Merge branch 'main' into tools-filtering

This commit is contained in:
AshAnand34
2025-07-18 14:45:15 -07:00
336 changed files with 21767 additions and 2122 deletions

View File

@@ -11,6 +11,7 @@ import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import SimpleRadio from '@components/options/SimpleRadio';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import * as Yup from 'yup';
import { useTranslation } from 'react-i18next';
interface InitialValuesType {
splitOperatorType: SplitOperatorType;
@@ -101,6 +102,7 @@ const exampleCards: CardExampleType<InitialValuesType>[] = [
];
export default function Duplicate({ title }: ToolComponentProps) {
const { t } = useTranslation('list');
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
@@ -121,9 +123,9 @@ export default function Duplicate({ title }: ToolComponentProps) {
);
} catch (error) {
if (error instanceof Error) {
setResult(`Error: ${error.message}`);
setResult(`${t('duplicate.error')}: ${error.message}`);
} else {
setResult('An unknown error occurred');
setResult(t('duplicate.unknownError'));
}
}
}
@@ -134,55 +136,53 @@ export default function Duplicate({ title }: ToolComponentProps) {
updateField
}) => [
{
title: 'Split Options',
title: t('duplicate.splitOptions'),
component: (
<Box>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'symbol')}
checked={values.splitOperatorType === 'symbol'}
title={'Split by Symbol'}
title={t('duplicate.splitBySymbol')}
/>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'regex')}
checked={values.splitOperatorType === 'regex'}
title={'Split by Regular Expression'}
title={t('duplicate.splitByRegex')}
/>
<TextFieldWithDesc
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
description={'Separator to split the list'}
description={t('duplicate.splitSeparatorDescription')}
/>
<TextFieldWithDesc
value={values.joinSeparator}
onOwnChange={(val) => updateField('joinSeparator', val)}
description={'Separator to join the duplicated list'}
description={t('duplicate.joinSeparatorDescription')}
/>
</Box>
)
},
{
title: 'Duplication Options',
title: t('duplicate.duplicationOptions'),
component: (
<Box>
<TextFieldWithDesc
value={values.copy}
onOwnChange={(val) => updateField('copy', val)}
description={'Number of copies (can be fractional)'}
description={t('duplicate.copyDescription')}
type="number"
/>
<CheckboxWithDesc
title={'Concatenate'}
title={t('duplicate.concatenate')}
checked={values.concatenate}
onChange={(checked) => updateField('concatenate', checked)}
description={
'Concatenate copies (if unchecked, items will be interweaved)'
}
description={t('duplicate.concatenateDescription')}
/>
<CheckboxWithDesc
title={'Reverse'}
title={t('duplicate.reverse')}
checked={values.reverse}
onChange={(checked) => updateField('reverse', checked)}
description={'Reverse the duplicated items'}
description={t('duplicate.reverseDescription')}
/>
</Box>
)
@@ -193,18 +193,21 @@ export default function Duplicate({ title }: ToolComponentProps) {
<ToolContent
title={title}
inputComponent={
<ToolTextInput title="Input List" value={input} onChange={setInput} />
<ToolTextInput
title={t('duplicate.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult title="Duplicated List" value={result} />
<ToolTextResult title={t('duplicate.resultTitle')} 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."
title: t('duplicate.toolInfo.title'),
description: t('duplicate.toolInfo.description')
}}
exampleCards={exampleCards}
input={input}

View File

@@ -3,13 +3,15 @@ import { lazy } from 'react';
// import image from '@assets/text.png';
export const tool = defineTool('list', {
name: 'Duplicate',
path: 'duplicate',
icon: 'mdi:content-duplicate',
description:
'A tool to duplicate each item in a list a specified number of times. Perfect for creating repeated patterns, test data, or expanding datasets.',
shortDescription: 'Repeat items in a list multiple times.',
icon: 'material-symbols-light:content-copy',
keywords: ['duplicate'],
userTypes: ['General Users', 'Students', 'Developers'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list:duplicate.title',
description: 'list:duplicate.description',
shortDescription: 'list:duplicate.shortDescription',
userTypes: ['General Users', 'Students', 'Developers']
}
});

View File

@@ -1,5 +1,6 @@
import { Box } from '@mui/material';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import {
@@ -14,6 +15,7 @@ import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import SelectWithDesc from '@components/options/SelectWithDesc';
import ToolContent from '@components/ToolContent';
import { ToolComponentProps } from '@tools/defineTool';
import { ParseKeys } from 'i18next';
const initialValues = {
splitSeparatorType: 'symbol' as SplitOperatorType,
@@ -25,23 +27,24 @@ const initialValues = {
trimItems: false
};
const splitOperators: {
title: string;
description: string;
title: ParseKeys<'list'>;
description: ParseKeys<'list'>;
type: SplitOperatorType;
}[] = [
{
title: 'Use a Symbol for Splitting',
description: 'Delimit input list items with a character.',
title: 'findMostPopular.splitOperators.symbol.title',
description: 'findMostPopular.splitOperators.symbol.description',
type: 'symbol'
},
{
title: 'Use a Regex for Splitting',
title: 'findMostPopular.splitOperators.regex.title',
type: 'regex',
description: 'Delimit input list items with a regular expression.'
description: 'findMostPopular.splitOperators.regex.description'
}
];
export default function FindMostPopular({ title }: ToolComponentProps) {
const { t } = useTranslation('list');
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: typeof initialValues, input: any) => {
@@ -74,28 +77,35 @@ export default function FindMostPopular({ title }: ToolComponentProps) {
title={title}
input={input}
inputComponent={
<ToolTextInput title={'Input list'} value={input} onChange={setInput} />
<ToolTextInput
title={t('findMostPopular.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult title={'Most popular items'} value={result} />
<ToolTextResult
title={t('findMostPopular.resultTitle')}
value={result}
/>
}
initialValues={initialValues}
getGroups={({ values, updateField }) => [
{
title: 'How to Extract List Items?',
title: t('findMostPopular.extractListItems'),
component: (
<Box>
{splitOperators.map(({ title, description, type }) => (
<SimpleRadio
key={type}
onClick={() => updateField('splitSeparatorType', type)}
title={title}
description={description}
title={t(title)}
description={t(description)}
checked={values.splitSeparatorType === type}
/>
))}
<TextFieldWithDesc
description={'Set a delimiting symbol or regular expression.'}
description={t('findMostPopular.splitSeparatorDescription')}
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
/>
@@ -103,26 +113,24 @@ export default function FindMostPopular({ title }: ToolComponentProps) {
)
},
{
title: 'Item comparison',
title: t('findMostPopular.itemComparison'),
component: (
<Box>
<CheckboxWithDesc
title={'Remove empty items'}
description={'Ignore empty items from comparison.'}
title={t('findMostPopular.removeEmptyItems')}
description={t('findMostPopular.removeEmptyItemsDescription')}
checked={values.deleteEmptyItems}
onChange={(value) => updateField('deleteEmptyItems', value)}
/>
<CheckboxWithDesc
title={'Trim top list items'}
description={
'Remove leading and trailing spaces before comparing items'
}
title={t('findMostPopular.trimItems')}
description={t('findMostPopular.trimItemsDescription')}
checked={values.trimItems}
onChange={(value) => updateField('trimItems', value)}
/>
<CheckboxWithDesc
title={'Ignore Item Case'}
description={'Compare all list items in lowercase.'}
title={t('findMostPopular.ignoreItemCase')}
description={t('findMostPopular.ignoreItemCaseDescription')}
checked={values.ignoreItemCase}
onChange={(value) => updateField('ignoreItemCase', value)}
/>
@@ -130,27 +138,42 @@ export default function FindMostPopular({ title }: ToolComponentProps) {
)
},
{
title: 'Top item output format',
title: t('findMostPopular.outputFormat'),
component: (
<Box>
<SelectWithDesc
selected={values.displayFormat}
options={[
{ label: 'Show item percentage', value: 'percentage' },
{ label: 'Show item count', value: 'count' },
{ label: 'Show item total', value: 'total' }
{
label: t('findMostPopular.displayOptions.percentage'),
value: 'percentage'
},
{
label: t('findMostPopular.displayOptions.count'),
value: 'count'
},
{
label: t('findMostPopular.displayOptions.total'),
value: 'total'
}
]}
onChange={(value) => updateField('displayFormat', value)}
description={'How to display the most popular list items?'}
description={t('findMostPopular.displayFormatDescription')}
/>
<SelectWithDesc
selected={values.sortingMethod}
options={[
{ label: 'Sort Alphabetically', value: 'alphabetic' },
{ label: 'Sort by count', value: 'count' }
{
label: t('findMostPopular.sortOptions.alphabetic'),
value: 'alphabetic'
},
{
label: t('findMostPopular.sortOptions.count'),
value: 'count'
}
]}
onChange={(value) => updateField('sortingMethod', value)}
description={'Select a sorting method.'}
description={t('findMostPopular.sortingMethodDescription')}
/>
</Box>
)

View File

@@ -3,13 +3,15 @@ import { lazy } from 'react';
// import image from '@assets/text.png';
export const tool = defineTool('list', {
name: 'Find most popular',
path: 'find-most-popular',
icon: 'material-symbols-light:query-stats',
description:
'A tool to identify and count the most frequently occurring items in a list. Useful for data analysis, finding trends, or identifying common elements.',
shortDescription: 'Find most common items in a list.',
icon: 'material-symbols-light:trending-up',
keywords: ['find', 'most', 'popular'],
userTypes: ['General Users', 'Students', 'Developers'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list:findMostPopular.title',
description: 'list:findMostPopular.description',
shortDescription: 'list:findMostPopular.shortDescription',
userTypes: ['General Users', 'Students', 'Developers']
}
});

View File

@@ -7,6 +7,7 @@ import { findUniqueCompute, SplitOperatorType } from './service';
import SimpleRadio from '@components/options/SimpleRadio';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import { useTranslation } from 'react-i18next';
const initialValues = {
splitOperatorType: 'symbol' as SplitOperatorType,
@@ -35,6 +36,7 @@ const splitOperators: {
];
export default function FindUnique() {
const { t } = useTranslation('list');
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: typeof initialValues, input: any) => {
@@ -64,18 +66,24 @@ export default function FindUnique() {
return (
<ToolContent
title="Find Unique"
title={t('findUnique.title')}
initialValues={initialValues}
compute={compute}
input={input}
setInput={setInput}
inputComponent={
<ToolTextInput title={'Input list'} value={input} onChange={setInput} />
<ToolTextInput
title={t('findUnique.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult title={t('findUnique.resultTitle')} value={result} />
}
resultComponent={<ToolTextResult title={'Unique items'} value={result} />}
getGroups={({ values, updateField }) => [
{
title: 'Input List Delimiter',
title: t('findUnique.inputListDelimiter'),
component: (
<Box>
{splitOperators.map(({ title, description, type }) => (
@@ -88,7 +96,7 @@ export default function FindUnique() {
/>
))}
<TextFieldWithDesc
description={'Set a delimiting symbol or regular expression.'}
description={t('findUnique.delimiterDescription')}
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
/>
@@ -96,7 +104,7 @@ export default function FindUnique() {
)
},
{
title: 'Output List Delimiter',
title: t('findUnique.outputListDelimiter'),
component: (
<Box>
<TextFieldWithDesc
@@ -104,18 +112,14 @@ export default function FindUnique() {
onOwnChange={(value) => updateField('joinSeparator', value)}
/>
<CheckboxWithDesc
title={'Trim top list items'}
description={
'Remove leading and trailing spaces before comparing items'
}
title={t('findUnique.trimItems')}
description={t('findUnique.trimItemsDescription')}
checked={values.trimItems}
onChange={(value) => updateField('trimItems', value)}
/>
<CheckboxWithDesc
title={'Skip empty items'}
description={
"Don't include the empty list items in the output."
}
title={t('findUnique.skipEmptyItems')}
description={t('findUnique.skipEmptyItemsDescription')}
checked={values.deleteEmptyItems}
onChange={(value) => updateField('deleteEmptyItems', value)}
/>
@@ -123,22 +127,20 @@ export default function FindUnique() {
)
},
{
title: 'Unique Item Options',
title: t('findUnique.uniqueItemOptions'),
component: (
<Box>
<CheckboxWithDesc
title={'Find Absolutely Unique Items'}
description={
'Display only those items of the list that exist in a single copy.'
}
title={t('findUnique.findAbsolutelyUniqueItems')}
description={t(
'findUnique.findAbsolutelyUniqueItemsDescription'
)}
checked={values.absolutelyUnique}
onChange={(value) => updateField('absolutelyUnique', value)}
/>
<CheckboxWithDesc
title={'Case Sensitive Items'}
description={
'Output items with different case as unique elements in the list.'
}
title={t('findUnique.caseSensitiveItems')}
description={t('findUnique.caseSensitiveItemsDescription')}
checked={values.caseSensitive}
onChange={(value) => updateField('caseSensitive', value)}
/>

View File

@@ -2,13 +2,15 @@ import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('list', {
name: 'Find unique',
path: 'find-unique',
icon: 'mynaui:one',
description:
"World's simplest browser-based utility for finding unique items in a list. Just input your list with any separator, and it will automatically identify and extract unique items. Perfect for removing duplicates, finding distinct values, or analyzing data uniqueness. You can customize the input/output separators and choose whether to preserve the original order.",
shortDescription: 'Find unique items in a list',
icon: 'material-symbols-light:search',
keywords: ['find', 'unique'],
userTypes: ['General Users', 'Students', 'Developers'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list:findUnique.title',
description: 'list:findUnique.description',
shortDescription: 'list:findUnique.shortDescription',
userTypes: ['General Users', 'Students', 'Developers']
}
});

View File

@@ -9,6 +9,7 @@ import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import { formatNumber } from '../../../../utils/number';
import ToolContent from '@components/ToolContent';
import { ToolComponentProps } from '@tools/defineTool';
import { useTranslation } from 'react-i18next';
const initialValues = {
splitOperatorType: 'symbol' as SplitOperatorType,
@@ -40,6 +41,7 @@ const splitOperators: {
];
export default function FindUnique({ title }: ToolComponentProps) {
const { t } = useTranslation('list');
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: typeof initialValues, input: any) => {
@@ -78,28 +80,32 @@ export default function FindUnique({ title }: ToolComponentProps) {
title={title}
input={input}
inputComponent={
<ToolTextInput title={'Input list'} value={input} onChange={setInput} />
<ToolTextInput
title={t('group.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult title={'Grouped items'} value={result} />
<ToolTextResult title={t('group.resultTitle')} value={result} />
}
initialValues={initialValues}
getGroups={({ values, updateField }) => [
{
title: 'Input Item Separator',
title: t('group.inputItemSeparator'),
component: (
<Box>
{splitOperators.map(({ title, description, type }) => (
<SimpleRadio
key={type}
onClick={() => updateField('splitOperatorType', type)}
title={title}
description={description}
title={t(`group.splitOperators.${type}.title`)}
description={t(`group.splitOperators.${type}.description`)}
checked={values.splitOperatorType === type}
/>
))}
<TextFieldWithDesc
description={'Set a delimiting symbol or regular expression.'}
description={t('group.splitSeparatorDescription')}
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
/>
@@ -107,12 +113,12 @@ export default function FindUnique({ title }: ToolComponentProps) {
)
},
{
title: 'Group Size and Separators',
title: t('group.groupSizeAndSeparators'),
component: (
<Box>
<TextFieldWithDesc
value={values.groupNumber}
description={'Number of items in a group'}
description={t('group.groupNumberDescription')}
type={'number'}
onOwnChange={(value) =>
updateField('groupNumber', formatNumber(value, 1))
@@ -120,52 +126,46 @@ export default function FindUnique({ title }: ToolComponentProps) {
/>
<TextFieldWithDesc
value={values.itemSeparator}
description={'Item separator character'}
description={t('group.itemSeparatorDescription')}
onOwnChange={(value) => updateField('itemSeparator', value)}
/>
<TextFieldWithDesc
value={values.groupSeparator}
description={'Group separator character'}
description={t('group.groupSeparatorDescription')}
onOwnChange={(value) => updateField('groupSeparator', value)}
/>
<TextFieldWithDesc
value={values.leftWrap}
description={"Group's left wrap symbol."}
description={t('group.leftWrapDescription')}
onOwnChange={(value) => updateField('leftWrap', value)}
/>
<TextFieldWithDesc
value={values.rightWrap}
description={"Group's right wrap symbol."}
description={t('group.rightWrapDescription')}
onOwnChange={(value) => updateField('rightWrap', value)}
/>
</Box>
)
},
{
title: 'Empty Items and Padding',
title: t('group.emptyItemsAndPadding'),
component: (
<Box>
<CheckboxWithDesc
title={'Delete Empty Items'}
description={
"Ignore empty items and don't include them in the groups."
}
title={t('group.deleteEmptyItems')}
description={t('group.deleteEmptyItemsDescription')}
checked={values.deleteEmptyItems}
onChange={(value) => updateField('deleteEmptyItems', value)}
/>
<CheckboxWithDesc
title={'Pad Non-full Groups'}
description={
'Fill non-full groups with a custom item (enter below).'
}
title={t('group.padNonFullGroups')}
description={t('group.padNonFullGroupsDescription')}
checked={values.padNonFullGroup}
onChange={(value) => updateField('padNonFullGroup', value)}
/>
<TextFieldWithDesc
value={values.paddingChar}
description={
'Use this character or item to pad non-full groups.'
}
description={t('group.paddingCharDescription')}
onOwnChange={(value) => updateField('paddingChar', value)}
/>
</Box>

View File

@@ -2,13 +2,15 @@ import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('list', {
name: 'Group Items',
path: 'group',
icon: 'pajamas:group',
description:
"World's simplest browser-based utility for grouping list items. Input your list and specify grouping criteria to organize items into logical groups. Perfect for categorizing data, organizing information, or creating structured lists. Supports custom separators and various grouping options.",
shortDescription: 'Group list items by common properties',
keywords: ['group'],
userTypes: ['General Users', 'Students', 'Developers'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list:group.title',
description: 'list:group.description',
shortDescription: 'list:group.shortDescription',
userTypes: ['General Users', 'Students', 'Developers']
}
});

View File

@@ -9,6 +9,7 @@ import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import ToolContent from '@components/ToolContent';
import { useTranslation } from 'react-i18next';
const initialValues = {
splitOperatorType: 'symbol' as SplitOperatorType,
@@ -111,6 +112,7 @@ argument`,
];
export default function Reverse({ title }: ToolComponentProps) {
const { t } = useTranslation('list');
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
@@ -119,15 +121,15 @@ export default function Reverse({ title }: ToolComponentProps) {
updateField
}) => [
{
title: 'Splitter Mode',
title: t('reverse.splitterMode'),
component: (
<Box>
{splitOperators.map(({ title, description, type }) => (
<SimpleRadio
key={type}
onClick={() => updateField('splitOperatorType', type)}
title={title}
description={description}
title={t(`reverse.splitOperators.${type}.title`)}
description={t(`reverse.splitOperators.${type}.description`)}
checked={values.splitOperatorType === type}
/>
))}
@@ -135,11 +137,11 @@ export default function Reverse({ title }: ToolComponentProps) {
)
},
{
title: 'Item Separator',
title: t('reverse.itemSeparator'),
component: (
<Box>
<TextFieldWithDesc
description={'Set a delimiting symbol or regular expression.'}
description={t('reverse.itemSeparatorDescription')}
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
/>
@@ -147,11 +149,11 @@ export default function Reverse({ title }: ToolComponentProps) {
)
},
{
title: 'Output List Options',
title: t('reverse.outputListOptions'),
component: (
<Box>
<TextFieldWithDesc
description={'Output list item separator.'}
description={t('reverse.outputSeparatorDescription')}
value={values.joinSeparator}
onOwnChange={(val) => updateField('joinSeparator', val)}
/>
@@ -176,15 +178,18 @@ export default function Reverse({ title }: ToolComponentProps) {
input={input}
setInput={setInput}
inputComponent={
<ToolTextInput title={'Input list'} value={input} onChange={setInput} />
<ToolTextInput
title={t('reverse.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult title={'Reversed list'} value={result} />
<ToolTextResult title={t('reverse.resultTitle')} value={result} />
}
toolInfo={{
title: 'What Is a List Reverser?',
description:
'With this utility, you can reverse the order of items in a list. The utility first splits the input list into individual items and then iterates through them from the last item to the first item, printing each item to the output during the iteration. The input list may contain anything that can be represented as textual data, which includes digits, numbers, strings, words, sentences, etc. The input item separator can also be a regular expression. For example, the regex /[;,]/ will allow you to use items that are either comma- or semicolon-separated. The input and output list items delimiters can be customized in the options. By default, both input and output lists are comma-separated. Listabulous!'
title: t('reverse.toolInfo.title'),
description: t('reverse.toolInfo.description')
}}
exampleCards={exampleCards}
/>

View File

@@ -3,13 +3,14 @@ import { lazy } from 'react';
// import image from '@assets/text.png';
export const tool = defineTool('list', {
name: 'Reverse list',
path: 'reverse',
icon: 'proicons:reverse',
description:
'This is a super simple browser-based application prints all list items in reverse. The input items can be separated by any symbol and you can also change the separator of the reversed list items.',
shortDescription: 'Quickly reverse a list',
keywords: ['reverse'],
userTypes: ['General Users', 'Students'],
i18n: {
name: 'list:reverse.title',
description: 'list:reverse.description',
shortDescription: 'list:reverse.shortDescription',
userTypes: ['General Users', 'Students']
},
component: lazy(() => import('./index'))
});

View File

@@ -3,13 +3,15 @@ import { lazy } from 'react';
// import image from '@assets/text.png';
export const tool = defineTool('list', {
name: 'Rotate list',
path: 'rotate',
icon: 'material-symbols-light:rotate-right',
description:
'A tool to rotate items in a list by a specified number of positions. Shift elements left or right while maintaining their relative order.',
shortDescription: 'Shift list items by position.',
keywords: ['rotate'],
userTypes: ['General Users', 'Students'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list:rotate.title',
description: 'list:rotate.description',
shortDescription: 'list:rotate.shortDescription',
userTypes: ['General Users', 'Students']
}
});

View File

@@ -7,6 +7,7 @@ import { shuffleList, SplitOperatorType } from './service';
import SimpleRadio from '@components/options/SimpleRadio';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import { isNumber } from '@utils/string';
import { useTranslation } from 'react-i18next';
const initialValues = {
splitOperatorType: 'symbol' as SplitOperatorType,
@@ -32,6 +33,7 @@ const splitOperators: {
];
export default function Shuffle() {
const { t } = useTranslation('list');
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: typeof initialValues, input: any) => {
@@ -51,20 +53,24 @@ export default function Shuffle() {
return (
<ToolContent
title="Shuffle"
title={t('shuffle.title')}
initialValues={initialValues}
compute={compute}
input={input}
setInput={setInput}
inputComponent={
<ToolTextInput title={'Input list'} value={input} onChange={setInput} />
<ToolTextInput
title={t('shuffle.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult title={'Shuffled list'} value={result} />
<ToolTextResult title={t('shuffle.resultTitle')} value={result} />
}
getGroups={({ values, updateField }) => [
{
title: 'Input list separator',
title: t('shuffle.inputListSeparator'),
component: (
<Box>
{splitOperators.map(({ title, description, type }) => (
@@ -77,7 +83,7 @@ export default function Shuffle() {
/>
))}
<TextFieldWithDesc
description={'Set a delimiting symbol or regular expression.'}
description={t('shuffle.delimiterDescription')}
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
/>
@@ -85,11 +91,11 @@ export default function Shuffle() {
)
},
{
title: 'Shuffled List Length',
title: t('shuffle.shuffledListLength'),
component: (
<Box>
<TextFieldWithDesc
description={'Output this many random items'}
description={t('shuffle.outputLengthDescription')}
value={values.length}
onOwnChange={(val) => updateField('length', val)}
/>
@@ -97,13 +103,13 @@ export default function Shuffle() {
)
},
{
title: 'Shuffled List Separator',
title: t('shuffle.shuffledListSeparator'),
component: (
<Box>
<TextFieldWithDesc
value={values.joinSeparator}
onOwnChange={(value) => updateField('joinSeparator', value)}
description={'Use this separator in the randomized list.'}
description={t('shuffle.joinSeparatorDescription')}
/>
</Box>
)

View File

@@ -3,13 +3,15 @@ import { lazy } from 'react';
// import image from '@assets/text.png';
export const tool = defineTool('list', {
name: 'Shuffle list',
path: 'shuffle',
icon: 'material-symbols-light:shuffle',
description:
'A tool to randomly reorder items in a list. Perfect for randomizing data, creating random selections, or generating random sequences.',
shortDescription: 'Randomly reorder list items.',
keywords: ['shuffle'],
userTypes: ['General Users', 'Students'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list:shuffle.title',
description: 'list:shuffle.description',
shortDescription: 'list:shuffle.shortDescription',
userTypes: ['General Users', 'Students']
}
});

View File

@@ -9,6 +9,7 @@ import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import SelectWithDesc from '@components/options/SelectWithDesc';
import ToolContent from '@components/ToolContent';
import { ToolComponentProps } from '@tools/defineTool';
import { useTranslation } from 'react-i18next';
const initialValues = {
splitSeparatorType: 'symbol' as SplitOperatorType,
@@ -36,7 +37,8 @@ const splitOperators: {
}
];
export default function SplitText({ title }: ToolComponentProps) {
export default function SortList({ title }: ToolComponentProps) {
const { t } = useTranslation('list');
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: typeof initialValues, input: any) => {
@@ -69,26 +71,32 @@ export default function SplitText({ title }: ToolComponentProps) {
title={title}
input={input}
inputComponent={
<ToolTextInput title={'Input list'} value={input} onChange={setInput} />
<ToolTextInput
title={t('sort.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult title={t('sort.resultTitle')} value={result} />
}
resultComponent={<ToolTextResult title={'Sorted list'} value={result} />}
initialValues={initialValues}
getGroups={({ values, updateField }) => [
{
title: 'Input item separator',
title: t('sort.inputItemSeparator'),
component: (
<Box>
{splitOperators.map(({ title, description, type }) => (
<SimpleRadio
key={type}
onClick={() => updateField('splitSeparatorType', type)}
title={title}
description={description}
title={t(`sort.splitOperators.${type}.title`)}
description={t(`sort.splitOperators.${type}.description`)}
checked={values.splitSeparatorType === type}
/>
))}
<TextFieldWithDesc
description={'Set a delimiting symbol or regular expression.'}
description={t('sort.splitSeparatorDescription')}
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
/>
@@ -96,35 +104,45 @@ export default function SplitText({ title }: ToolComponentProps) {
)
},
{
title: 'Sort method',
title: t('sort.sortMethod'),
component: (
<Box>
<SelectWithDesc
selected={values.sortingMethod}
options={[
{ label: 'Sort Alphabetically', value: 'alphabetic' },
{ label: 'Sort Numerically', value: 'numeric' },
{ label: 'Sort by Length', value: 'length' }
{
label: t('sort.sortOptions.alphabetic'),
value: 'alphabetic'
},
{
label: t('sort.sortOptions.numeric'),
value: 'numeric'
},
{ label: t('sort.sortOptions.length'), value: 'length' }
]}
onChange={(value) => updateField('sortingMethod', value)}
description={'Select a sorting method.'}
description={t('sort.sortMethodDescription')}
/>
<SelectWithDesc
selected={values.increasing}
options={[
{ label: 'Increasing order', value: true },
{ label: 'Decreasing order', value: false }
{
label: t('sort.orderOptions.increasing'),
value: true
},
{
label: t('sort.orderOptions.decreasing'),
value: false
}
]}
onChange={(value) => {
updateField('increasing', value);
}}
description={'Select a sorting order.'}
description={t('sort.orderDescription')}
/>
<CheckboxWithDesc
title={'Case Sensitive Sort'}
description={
'Sort uppercase and lowercase items separately. Capital letters precede lowercase letters in an ascending list. (Works only in alphabetical sorting mode.)'
}
title={t('sort.caseSensitive')}
description={t('sort.caseSensitiveDescription')}
checked={values.caseSensitive}
onChange={(val) => updateField('caseSensitive', val)}
/>
@@ -132,19 +150,17 @@ export default function SplitText({ title }: ToolComponentProps) {
)
},
{
title: 'Sorted item properties',
title: t('sort.sortedItemProperties'),
component: (
<Box>
<TextFieldWithDesc
description={
'Use this symbol as a joiner between items in a sorted list.'
}
description={t('sort.joinSeparatorDescription')}
value={values.joinSeparator}
onOwnChange={(val) => updateField('joinSeparator', val)}
/>
<CheckboxWithDesc
title={'Remove duplicates'}
description={'Delete duplicate list items.'}
title={t('sort.removeDuplicates')}
description={t('sort.removeDuplicatesDescription')}
checked={values.removeDuplicated}
onChange={(val) => updateField('removeDuplicated', val)}
/>

View File

@@ -3,13 +3,15 @@ import { lazy } from 'react';
// import image from '@assets/text.png';
export const tool = defineTool('list', {
name: 'Sort list',
path: 'sort',
icon: 'basil:sort-outline',
description:
'This is a super simple browser-based application that sorts items in a list and arranges them in increasing or decreasing order. You can sort the items alphabetically, numerically, or by their length. You can also remove duplicate and empty items, as well as trim individual items that have whitespace around them. You can use any separator character to separate the input list items or alternatively use a regular expression to separate them. Additionally, you can create a new delimiter for the sorted output list.',
shortDescription: 'Quickly sort a list',
icon: 'material-symbols-light:sort',
keywords: ['sort'],
userTypes: ['General Users', 'Students', 'Developers'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list:sort.title',
description: 'list:sort.description',
shortDescription: 'list:sort.shortDescription',
userTypes: ['General Users', 'Students', 'Developers']
}
});

View File

@@ -2,13 +2,15 @@ import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('list', {
name: 'Truncate list',
path: 'truncate',
shortDescription: 'Truncate a list to a specified number of items',
icon: 'material-symbols-light:short-text',
description:
'Truncate a list to keep only the first N items or remove items beyond a certain limit.',
keywords: ['truncate', 'list', 'limit', 'cut'],
userTypes: ['General Users', 'Students'],
component: lazy(() => import('./index'))
icon: 'material-symbols-light:content-cut',
keywords: ['truncate'],
component: lazy(() => import('./index')),
i18n: {
name: 'list:truncate.title',
description: 'list:truncate.description',
shortDescription: 'list:truncate.shortDescription',
userTypes: ['General Users', 'Students']
}
});

View File

@@ -3,13 +3,15 @@ import { lazy } from 'react';
// import image from '@assets/text.png';
export const tool = defineTool('list', {
name: 'Unwrap items',
path: 'unwrap',
shortDescription: 'Remove wrapping text from items in a list',
icon: 'material-symbols-light:format-clear',
description:
'Remove custom wrapping text from items in a list, such as quotes, brackets, or any other prefix and suffix.',
keywords: ['unwrap', 'list', 'remove', 'format'],
userTypes: ['General Users', 'Students', 'Developers'],
component: lazy(() => import('./index'))
icon: 'material-symbols-light:unfold-more',
keywords: ['unwrap'],
component: lazy(() => import('./index')),
i18n: {
name: 'list:unwrap.title',
description: 'list:unwrap.description',
shortDescription: 'list:unwrap.shortDescription',
userTypes: ['General Users', 'Students', 'Developers']
}
});

View File

@@ -11,6 +11,7 @@ import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import SimpleRadio from '@components/options/SimpleRadio';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import * as Yup from 'yup';
import { useTranslation } from 'react-i18next';
interface InitialValuesType {
splitOperatorType: SplitOperatorType;
@@ -85,6 +86,7 @@ const exampleCards: CardExampleType<InitialValuesType>[] = [
];
export default function Wrap({ title }: ToolComponentProps) {
const { t } = useTranslation('list');
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
@@ -117,50 +119,50 @@ export default function Wrap({ title }: ToolComponentProps) {
updateField
}) => [
{
title: 'Split Options',
title: t('wrap.splitOptions'),
component: (
<Box>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'symbol')}
checked={values.splitOperatorType === 'symbol'}
title={'Split by Symbol'}
title={t('wrap.splitBySymbol')}
/>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'regex')}
checked={values.splitOperatorType === 'regex'}
title={'Split by Regular Expression'}
title={t('wrap.splitByRegex')}
/>
<TextFieldWithDesc
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
description={'Separator to split the list'}
description={t('wrap.splitSeparatorDescription')}
/>
<TextFieldWithDesc
value={values.joinSeparator}
onOwnChange={(val) => updateField('joinSeparator', val)}
description={'Separator to join the wrapped list'}
description={t('wrap.joinSeparatorDescription')}
/>
<CheckboxWithDesc
checked={values.deleteEmptyItems}
onChange={(checked) => updateField('deleteEmptyItems', checked)}
title={'Remove empty items'}
title={t('wrap.removeEmptyItems')}
/>
</Box>
)
},
{
title: 'Wrap Options',
title: t('wrap.wrapOptions'),
component: (
<Box>
<TextFieldWithDesc
value={values.left}
onOwnChange={(val) => updateField('left', val)}
description={'Text to add before each item'}
description={t('wrap.leftTextDescription')}
/>
<TextFieldWithDesc
value={values.right}
onOwnChange={(val) => updateField('right', val)}
description={'Text to add after each item'}
description={t('wrap.rightTextDescription')}
/>
</Box>
)
@@ -171,16 +173,21 @@ export default function Wrap({ title }: ToolComponentProps) {
<ToolContent
title={title}
inputComponent={
<ToolTextInput title="Input List" value={input} onChange={setInput} />
<ToolTextInput
title={t('wrap.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult title={t('wrap.resultTitle')} value={result} />
}
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."
title: t('wrap.toolInfo.title'),
description: t('wrap.toolInfo.description')
}}
exampleCards={exampleCards}
input={input}

View File

@@ -3,13 +3,15 @@ import { lazy } from 'react';
// import image from '@assets/text.png';
export const tool = defineTool('list', {
name: 'Wrap items',
path: 'wrap',
shortDescription: 'Wrap items in a list with custom text',
icon: 'material-symbols-light:format-quote',
description:
'Wrap each item in a list with custom text, such as quotes, brackets, or any other prefix and suffix.',
keywords: ['wrap', 'list', 'format', 'text'],
userTypes: ['General Users', 'Students', 'Developers'],
component: lazy(() => import('./index'))
icon: 'material-symbols-light:wrap-text',
keywords: ['wrap'],
component: lazy(() => import('./index')),
i18n: {
name: 'list:wrap.title',
description: 'list:wrap.description',
shortDescription: 'list:wrap.shortDescription',
userTypes: ['General Users', 'Students', 'Developers']
}
});