mirror of
https://github.com/iib0011/omni-tools.git
synced 2025-09-04 06:46:33 +02:00
feat: tools normalized
This commit is contained in:
@@ -26,12 +26,7 @@
|
|||||||
"ecmaVersion": 11,
|
"ecmaVersion": 11,
|
||||||
"sourceType": "module"
|
"sourceType": "module"
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": ["react", "react-hooks", "@typescript-eslint", "tailwindcss"],
|
||||||
"react",
|
|
||||||
"react-hooks",
|
|
||||||
"@typescript-eslint",
|
|
||||||
"tailwindcss"
|
|
||||||
],
|
|
||||||
"rules": {
|
"rules": {
|
||||||
"react-hooks/rules-of-hooks": "error",
|
"react-hooks/rules-of-hooks": "error",
|
||||||
"react-hooks/exhaustive-deps": "warn",
|
"react-hooks/exhaustive-deps": "warn",
|
||||||
|
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
@@ -3,7 +3,7 @@ name: CI
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main # or the branch you want to trigger the workflow on
|
- main # or the branch you want to trigger the workflow on
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
@@ -19,7 +19,7 @@ jobs:
|
|||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: '18' # Specify the Node.js version you want to use
|
node-version: '18' # Specify the Node.js version you want to use
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm install
|
run: npm install
|
||||||
@@ -42,4 +42,3 @@ jobs:
|
|||||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
||||||
timeout-minutes: 1
|
timeout-minutes: 1
|
||||||
|
|
||||||
|
113
.idea/workspace.xml
generated
113
.idea/workspace.xml
generated
@@ -4,15 +4,43 @@
|
|||||||
<option name="autoReloadType" value="SELECTIVE" />
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="chore: idea config">
|
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="feat: react helmet">
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/pages/images/imageTools.ts" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/pages/images/png/change-colors-in-png/meta.ts" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/pages/images/png/pngTools.ts" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/pages/string/split/meta.ts" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/pages/string/stringTools.ts" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/tools/defineTool.tsx" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/tools/index.ts" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/.eslintrc" beforeDir="false" afterPath="$PROJECT_DIR$/.eslintrc" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/.github/workflows/ci.yml" beforeDir="false" afterPath="$PROJECT_DIR$/.github/workflows/ci.yml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.github/workflows/ci.yml" beforeDir="false" afterPath="$PROJECT_DIR$/.github/workflows/ci.yml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/omni-tools.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/omni-tools.iml" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/Readme.md" beforeDir="false" afterPath="$PROJECT_DIR$/Readme.md" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.vitest/setup.ts" beforeDir="false" afterPath="$PROJECT_DIR$/.vitest/setup.ts" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/package-lock.json" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/index.html" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/pnpm-lock.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/pnpm-lock.yaml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/components/ToolLayout.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/ToolLayout.tsx" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/postcss.config.mjs" beforeDir="false" afterPath="$PROJECT_DIR$/postcss.config.mjs" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/App.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/App.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/Loading.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/Loading.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/Navbar/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/Navbar/index.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/ToolHeader.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/ToolHeader.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/input/ToolTextInput.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/input/ToolTextInput.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/config/routesConfig.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/config/routesConfig.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/hooks/useDebounce.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/hooks/useDebounce.ts" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/hooks/usePrevious.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/hooks/usePrevious.ts" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/hooks/useTimeout.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/hooks/useTimeout.ts" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/hooks/useUpdateEffect.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/hooks/useUpdateEffect.ts" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/index.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/pages/home/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/home/index.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/pages/images/ImagesConfig.tsx" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/pages/images/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/images/index.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/pages/images/png/PngConfig.tsx" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/pages/images/png/change-colors-in-png/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/images/png/change-colors-in-png/index.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/pages/images/png/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/images/png/index.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/pages/string/StringConfig.tsx" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/pages/string/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/string/index.tsx" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/pages/string/split/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/string/split/index.tsx" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/pages/string/split/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/string/split/index.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/utils/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/utils/index.ts" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/tailwind.config.mjs" beforeDir="false" afterPath="$PROJECT_DIR$/tailwind.config.mjs" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
@@ -41,32 +69,32 @@
|
|||||||
<option name="hideEmptyMiddlePackages" value="true" />
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
<option name="showLibraryContents" value="true" />
|
<option name="showLibraryContents" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent">{
|
<component name="PropertiesComponent"><![CDATA[{
|
||||||
"keyToString": {
|
"keyToString": {
|
||||||
"ASKED_ADD_EXTERNAL_FILES": "true",
|
"ASKED_ADD_EXTERNAL_FILES": "true",
|
||||||
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
"git-widget-placeholder": "main",
|
"git-widget-placeholder": "main",
|
||||||
"ignore.virus.scanning.warn.message": "true",
|
"ignore.virus.scanning.warn.message": "true",
|
||||||
"kotlin-language-version-configured": "true",
|
"kotlin-language-version-configured": "true",
|
||||||
"last_opened_file_path": "C:/Users/HP/IdeaProjects/omni-tools/public",
|
"last_opened_file_path": "C:/Users/HP/IdeaProjects/omni-tools/src/pages/string/split",
|
||||||
"node.js.detected.package.eslint": "true",
|
"node.js.detected.package.eslint": "true",
|
||||||
"node.js.detected.package.tslint": "true",
|
"node.js.detected.package.tslint": "true",
|
||||||
"node.js.selected.package.eslint": "(autodetect)",
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
"node.js.selected.package.tslint": "(autodetect)",
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
"nodejs_package_manager_path": "npm",
|
"nodejs_package_manager_path": "npm",
|
||||||
"npm.dev.executor": "Run",
|
"npm.dev.executor": "Run",
|
||||||
"npm.prebuild.executor": "Run",
|
"npm.prebuild.executor": "Run",
|
||||||
"prettierjs.PrettierConfiguration.Package": "C:\\Users\\HP\\IdeaProjects\\omni-tools\\node_modules\\prettier",
|
"prettierjs.PrettierConfiguration.Package": "C:\\Users\\HP\\IdeaProjects\\omni-tools\\node_modules\\prettier",
|
||||||
"project.structure.last.edited": "Problems",
|
"project.structure.last.edited": "Problems",
|
||||||
"project.structure.proportion": "0.0",
|
"project.structure.proportion": "0.0",
|
||||||
"project.structure.side.proportion": "0.2",
|
"project.structure.side.proportion": "0.2",
|
||||||
"settings.editor.selected.configurable": "settings.typescriptcompiler",
|
"settings.editor.selected.configurable": "settings.typescriptcompiler",
|
||||||
"ts.external.directory.path": "C:\\Users\\HP\\IdeaProjects\\omni-tools\\node_modules\\typescript\\lib",
|
"ts.external.directory.path": "C:\\Users\\HP\\IdeaProjects\\omni-tools\\node_modules\\typescript\\lib",
|
||||||
"vue.rearranger.settings.migration": "true"
|
"vue.rearranger.settings.migration": "true"
|
||||||
}
|
}
|
||||||
}</component>
|
}]]></component>
|
||||||
<component name="ReactDesignerToolWindowState">
|
<component name="ReactDesignerToolWindowState">
|
||||||
<option name="myId2Visible">
|
<option name="myId2Visible">
|
||||||
<map>
|
<map>
|
||||||
@@ -78,11 +106,15 @@
|
|||||||
</component>
|
</component>
|
||||||
<component name="RecentsManager">
|
<component name="RecentsManager">
|
||||||
<key name="CopyFile.RECENT_KEYS">
|
<key name="CopyFile.RECENT_KEYS">
|
||||||
|
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\pages\string\split" />
|
||||||
|
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\pages\images" />
|
||||||
<recent name="C:\Users\HP\IdeaProjects\omni-tools\public" />
|
<recent name="C:\Users\HP\IdeaProjects\omni-tools\public" />
|
||||||
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\assets" />
|
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\assets" />
|
||||||
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src" />
|
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src" />
|
||||||
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\pages\string" />
|
</key>
|
||||||
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\pages\images" />
|
<key name="MoveFile.RECENT_KEYS">
|
||||||
|
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\pages\images\png\change-colors-in-png" />
|
||||||
|
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\tools" />
|
||||||
</key>
|
</key>
|
||||||
</component>
|
</component>
|
||||||
<component name="RunManager" selected="npm.dev">
|
<component name="RunManager" selected="npm.dev">
|
||||||
@@ -129,7 +161,7 @@
|
|||||||
<workItem from="1719006887776" duration="7000" />
|
<workItem from="1719006887776" duration="7000" />
|
||||||
<workItem from="1719006951159" duration="2377000" />
|
<workItem from="1719006951159" duration="2377000" />
|
||||||
<workItem from="1719021128819" duration="3239000" />
|
<workItem from="1719021128819" duration="3239000" />
|
||||||
<workItem from="1719083989394" duration="1047000" />
|
<workItem from="1719083989394" duration="6308000" />
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00001" summary="feat: use vite and ts">
|
<task id="LOCAL-00001" summary="feat: use vite and ts">
|
||||||
<option name="closed" value="true" />
|
<option name="closed" value="true" />
|
||||||
@@ -299,7 +331,15 @@
|
|||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1719024346455</updated>
|
<updated>1719024346455</updated>
|
||||||
</task>
|
</task>
|
||||||
<option name="localTasksCounter" value="22" />
|
<task id="LOCAL-00022" summary="feat: react helmet">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1719085085537</created>
|
||||||
|
<option name="number" value="00022" />
|
||||||
|
<option name="presentableId" value="LOCAL-00022" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1719085085537</updated>
|
||||||
|
</task>
|
||||||
|
<option name="localTasksCounter" value="23" />
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TypeScriptGeneratedFilesManager">
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
@@ -338,7 +378,8 @@
|
|||||||
<MESSAGE value="test: init" />
|
<MESSAGE value="test: init" />
|
||||||
<MESSAGE value="chore: remove prebuild" />
|
<MESSAGE value="chore: remove prebuild" />
|
||||||
<MESSAGE value="chore: idea config" />
|
<MESSAGE value="chore: idea config" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value="chore: idea config" />
|
<MESSAGE value="feat: react helmet" />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="feat: react helmet" />
|
||||||
</component>
|
</component>
|
||||||
<component name="XSLT-Support.FileAssociations.UIState">
|
<component name="XSLT-Support.FileAssociations.UIState">
|
||||||
<expand />
|
<expand />
|
||||||
|
@@ -1 +1 @@
|
|||||||
import '@testing-library/jest-dom/vitest'
|
import '@testing-library/jest-dom/vitest';
|
||||||
|
22
index.html
22
index.html
@@ -1,13 +1,13 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg"/>
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Omni Tools</title>
|
<title>Omni Tools</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script type="module" src="/src/index.tsx"></script>
|
<script type="module" src="/src/index.tsx"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
3083
pnpm-lock.yaml
generated
3083
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -3,4 +3,4 @@ export default {
|
|||||||
tailwindcss: {},
|
tailwindcss: {},
|
||||||
autoprefixer: {}
|
autoprefixer: {}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
@@ -7,9 +7,14 @@ import { ThemeProvider } from '@mui/material';
|
|||||||
import theme from '../config/muiConfig';
|
import theme from '../config/muiConfig';
|
||||||
import { CustomSnackBarProvider } from '../contexts/CustomSnackBarContext';
|
import { CustomSnackBarProvider } from '../contexts/CustomSnackBarContext';
|
||||||
import { SnackbarProvider } from 'notistack';
|
import { SnackbarProvider } from 'notistack';
|
||||||
|
import { tools } from '../tools';
|
||||||
|
|
||||||
const AppRoutes = () => {
|
const AppRoutes = () => {
|
||||||
return useRoutes(routesConfig);
|
const updatedRoutesConfig = [...routesConfig];
|
||||||
|
tools.forEach((tool) => {
|
||||||
|
updatedRoutesConfig.push({ path: tool.path, element: tool.component() });
|
||||||
|
});
|
||||||
|
return useRoutes(updatedRoutesConfig);
|
||||||
};
|
};
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import Typography from '@mui/material/Typography'
|
import Typography from '@mui/material/Typography';
|
||||||
import { useState } from 'react'
|
import { useState } from 'react';
|
||||||
import Box from '@mui/material/Box'
|
import Box from '@mui/material/Box';
|
||||||
import { useTimeout } from '../hooks'
|
import { useTimeout } from '../hooks';
|
||||||
|
|
||||||
export type FuseLoadingProps = {
|
export type FuseLoadingProps = {
|
||||||
delay?: number;
|
delay?: number;
|
||||||
@@ -12,16 +12,15 @@ export type FuseLoadingProps = {
|
|||||||
* FuseLoading displays a loading state with an optional delay
|
* FuseLoading displays a loading state with an optional delay
|
||||||
*/
|
*/
|
||||||
function FuseLoading(props: FuseLoadingProps) {
|
function FuseLoading(props: FuseLoadingProps) {
|
||||||
const { delay = 0, className } = props
|
const { delay = 0, className } = props;
|
||||||
const [showLoading, setShowLoading] = useState(!delay)
|
const [showLoading, setShowLoading] = useState(!delay);
|
||||||
|
|
||||||
useTimeout(() => {
|
useTimeout(() => {
|
||||||
setShowLoading(true)
|
setShowLoading(true);
|
||||||
}, delay)
|
}, delay);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div>
|
||||||
>
|
|
||||||
<Typography
|
<Typography
|
||||||
className="-mb-16 text-13 font-medium sm:text-20"
|
className="-mb-16 text-13 font-medium sm:text-20"
|
||||||
color="text.secondary"
|
color="text.secondary"
|
||||||
@@ -41,7 +40,7 @@ function FuseLoading(props: FuseLoadingProps) {
|
|||||||
<div className="bounce3" />
|
<div className="bounce3" />
|
||||||
</Box>
|
</Box>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FuseLoading
|
export default FuseLoading;
|
||||||
|
@@ -4,22 +4,41 @@ import Toolbar from '@mui/material/Toolbar';
|
|||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
import {Link, useNavigate} from 'react-router-dom';
|
import { Link, useNavigate } from 'react-router-dom';
|
||||||
import githubIcon from '../../assets/github-mark.png'; // Adjust the path to your GitHub icon
|
import githubIcon from '../../assets/github-mark.png'; // Adjust the path to your GitHub icon
|
||||||
|
|
||||||
const Navbar: React.FC = () => {
|
const Navbar: React.FC = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
return (
|
return (
|
||||||
<AppBar position="static" style={{backgroundColor: 'white', color: 'black'}}>
|
<AppBar
|
||||||
|
position="static"
|
||||||
|
style={{ backgroundColor: 'white', color: 'black' }}
|
||||||
|
>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<Typography onClick={() => navigate('/')} fontSize={20}
|
<Typography
|
||||||
sx={{flexGrow: 1, cursor: 'pointer'}} color={'primary'}>OmniTools</Typography>
|
onClick={() => navigate('/')}
|
||||||
|
fontSize={20}
|
||||||
|
sx={{ flexGrow: 1, cursor: 'pointer' }}
|
||||||
|
color={'primary'}
|
||||||
|
>
|
||||||
|
OmniTools
|
||||||
|
</Typography>
|
||||||
|
|
||||||
<Button color="inherit">
|
<Button color="inherit">
|
||||||
<Link to="/features" style={{textDecoration: 'none', color: 'inherit'}}>Features</Link>
|
<Link
|
||||||
|
to="/features"
|
||||||
|
style={{ textDecoration: 'none', color: 'inherit' }}
|
||||||
|
>
|
||||||
|
Features
|
||||||
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
<Button color="inherit">
|
<Button color="inherit">
|
||||||
<Link to="/about-us" style={{textDecoration: 'none', color: 'inherit'}}>About Us</Link>
|
<Link
|
||||||
|
to="/about-us"
|
||||||
|
style={{ textDecoration: 'none', color: 'inherit' }}
|
||||||
|
>
|
||||||
|
About Us
|
||||||
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
@@ -28,7 +47,11 @@ const Navbar: React.FC = () => {
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
<img src={githubIcon} alt="GitHub" style={{height: '24px', marginRight: '8px'}}/>
|
<img
|
||||||
|
src={githubIcon}
|
||||||
|
alt="GitHub"
|
||||||
|
style={{ height: '24px', marginRight: '8px' }}
|
||||||
|
/>
|
||||||
<Typography variant="button">Star us</Typography>
|
<Typography variant="button">Star us</Typography>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
|
@@ -1,18 +1,22 @@
|
|||||||
import {Box, Stack} from "@mui/material";
|
import { Box, Stack } from '@mui/material';
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from '@mui/material/Typography';
|
||||||
import textImage from '../assets/text.png'
|
import textImage from '../assets/text.png';
|
||||||
|
|
||||||
interface ToolHeaderProps {
|
interface ToolHeaderProps {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ToolHeader({title, description}: ToolHeaderProps) {
|
export default function ToolHeader({ title, description }: ToolHeaderProps) {
|
||||||
return (<Stack direction={'row'} alignItems={'center'} spacing={2} mt={4}>
|
return (
|
||||||
<Box>
|
<Stack direction={'row'} alignItems={'center'} spacing={2} mt={4}>
|
||||||
<Typography mb={2} fontSize={30} color={'primary'}>{title}</Typography>
|
<Box>
|
||||||
<Typography fontSize={20}>{description}</Typography>
|
<Typography mb={2} fontSize={30} color={'primary'}>
|
||||||
</Box>
|
{title}
|
||||||
<img width={'20%'} src={textImage}/>
|
</Typography>
|
||||||
</Stack>)
|
<Typography fontSize={20}>{description}</Typography>
|
||||||
|
</Box>
|
||||||
|
<img width={'20%'} src={textImage} />
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +1,18 @@
|
|||||||
import { Box, Stack, TextField } from '@mui/material'
|
import { Box, Stack, TextField } from '@mui/material';
|
||||||
import Typography from '@mui/material/Typography'
|
import Typography from '@mui/material/Typography';
|
||||||
import Button from '@mui/material/Button'
|
import Button from '@mui/material/Button';
|
||||||
import PublishIcon from '@mui/icons-material/Publish'
|
import PublishIcon from '@mui/icons-material/Publish';
|
||||||
import ContentPasteIcon from '@mui/icons-material/ContentPaste'
|
import ContentPasteIcon from '@mui/icons-material/ContentPaste';
|
||||||
import React from 'react'
|
import React from 'react';
|
||||||
|
|
||||||
export default function ToolTextInput({ value, onChange, title = 'Input text' }: {
|
export default function ToolTextInput({
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
title = 'Input text'
|
||||||
|
}: {
|
||||||
title?: string;
|
title?: string;
|
||||||
value: string
|
value: string;
|
||||||
onChange: (value: string) => void
|
onChange: (value: string) => void;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
@@ -27,5 +31,5 @@ export default function ToolTextInput({ value, onChange, title = 'Input text' }:
|
|||||||
<Button startIcon={<ContentPasteIcon />}>Copy to clipboard</Button>
|
<Button startIcon={<ContentPasteIcon />}>Copy to clipboard</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
@@ -1,29 +1,18 @@
|
|||||||
import {RouteObject} from "react-router-dom";
|
import { RouteObject } from 'react-router-dom';
|
||||||
import {Navigate} from "react-router-dom";
|
import { Navigate } from 'react-router-dom';
|
||||||
import {ImagesConfig} from "../pages/images/ImagesConfig";
|
import { lazy } from 'react';
|
||||||
import {lazy} from "react";
|
|
||||||
import {StringConfig} from "../pages/string/StringConfig";
|
|
||||||
|
|
||||||
const Home = lazy(() => import("../pages/home"));
|
const Home = lazy(() => import('../pages/home'));
|
||||||
|
|
||||||
const routes: RouteObject[] = [
|
const routes: RouteObject[] = [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: '/',
|
||||||
element: <Home/>,
|
element: <Home />
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "images",
|
path: '*',
|
||||||
children: ImagesConfig
|
element: <Navigate to="404" />
|
||||||
},
|
}
|
||||||
{
|
|
||||||
path: "string",
|
|
||||||
children: StringConfig
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "*",
|
|
||||||
element: <Navigate to="404"/>,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export default routes;
|
export default routes;
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import {useCallback, useEffect, useRef} from "react";
|
import { useCallback, useEffect, useRef } from 'react';
|
||||||
import _ from "lodash";
|
import _ from 'lodash';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Debounce hook.
|
* Debounce hook.
|
||||||
@@ -9,7 +9,7 @@ import _ from "lodash";
|
|||||||
*/
|
*/
|
||||||
function useDebounce<T extends (...args: never[]) => void>(
|
function useDebounce<T extends (...args: never[]) => void>(
|
||||||
callback: T,
|
callback: T,
|
||||||
delay: number,
|
delay: number
|
||||||
): T {
|
): T {
|
||||||
const callbackRef = useRef<T>(callback);
|
const callbackRef = useRef<T>(callback);
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ function useDebounce<T extends (...args: never[]) => void>(
|
|||||||
_.debounce((...args: never[]) => {
|
_.debounce((...args: never[]) => {
|
||||||
callbackRef.current(...args);
|
callbackRef.current(...args);
|
||||||
}, delay),
|
}, delay),
|
||||||
[delay],
|
[delay]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from 'react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The usePrevious function is a custom hook that returns the previous value of a variable.
|
* The usePrevious function is a custom hook that returns the previous value of a variable.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from 'react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The useTimeout function is a custom hook that sets a timeout for a given callback function.
|
* The useTimeout function is a custom hook that sets a timeout for a given callback function.
|
||||||
@@ -15,7 +15,7 @@ function useTimeout(callback: () => void, delay: number) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let timer: NodeJS.Timeout | undefined;
|
let timer: NodeJS.Timeout | undefined;
|
||||||
|
|
||||||
if (delay !== null && callback && typeof callback === "function") {
|
if (delay !== null && callback && typeof callback === 'function') {
|
||||||
timer = setTimeout(callbackRef.current, delay);
|
timer = setTimeout(callbackRef.current, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { DependencyList, EffectCallback, useEffect, useRef } from "react";
|
import { DependencyList, EffectCallback, useEffect, useRef } from 'react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The useUpdateEffect function is a custom hook that behaves like useEffect, but only runs on updates and not on initial mount.
|
* The useUpdateEffect function is a custom hook that behaves like useEffect, but only runs on updates and not on initial mount.
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
import { createRoot } from 'react-dom/client'
|
import { createRoot } from 'react-dom/client';
|
||||||
import 'tailwindcss/tailwind.css'
|
import 'tailwindcss/tailwind.css';
|
||||||
import App from 'components/App'
|
import App from 'components/App';
|
||||||
|
|
||||||
const container = document.getElementById('root') as HTMLDivElement
|
const container = document.getElementById('root') as HTMLDivElement;
|
||||||
const root = createRoot(container)
|
const root = createRoot(container);
|
||||||
|
|
||||||
root.render(<App />)
|
root.render(<App />);
|
||||||
|
@@ -1,62 +1,83 @@
|
|||||||
import {Box, Icon, Input, Stack, TextField} from "@mui/material";
|
import { Box, Stack, TextField } from '@mui/material';
|
||||||
import Grid from "@mui/material/Grid";
|
import Grid from '@mui/material/Grid';
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from '@mui/material/Typography';
|
||||||
import SearchIcon from '@mui/icons-material/Search';
|
import SearchIcon from '@mui/icons-material/Search';
|
||||||
import {useNavigate} from "react-router-dom";
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
const exampleTools: { label: string; url: string }[] = [{
|
const exampleTools: { label: string; url: string }[] = [
|
||||||
label: 'Create a transparent image',
|
{
|
||||||
url: ''
|
label: 'Create a transparent image',
|
||||||
},
|
url: ''
|
||||||
{label: 'Convert text to morse code', url: ''},
|
},
|
||||||
{label: 'Change GIF speed', url: ''},
|
{ label: 'Convert text to morse code', url: '' },
|
||||||
{label: 'Pick a random item', url: ''},
|
{ label: 'Change GIF speed', url: '' },
|
||||||
{label: 'Find and replace text', url: ''},
|
{ label: 'Pick a random item', url: '' },
|
||||||
{label: 'Convert emoji to image', url: ''},
|
{ label: 'Find and replace text', url: '' },
|
||||||
{label: 'Split a string', url: '/string/split'},
|
{ label: 'Convert emoji to image', url: '' },
|
||||||
{label: 'Calculate number sum', url: ''},
|
{ label: 'Split a string', url: '/string/split' },
|
||||||
{label: 'Pixelate an image', url: ''},
|
{ label: 'Calculate number sum', url: '' },
|
||||||
]
|
{ label: 'Pixelate an image', url: '' }
|
||||||
|
];
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (<Box padding={5} display={'flex'} flexDirection={'column'} alignItems={'center'} justifyContent={'center'}
|
return (
|
||||||
width={'100%'}>
|
<Box
|
||||||
<Box width={"60%"}>
|
padding={5}
|
||||||
<Stack mb={1} direction={'row'} spacing={1}> <Typography fontSize={30}>Transform Your Workflow
|
display={'flex'}
|
||||||
with </Typography><Typography
|
flexDirection={'column'}
|
||||||
fontSize={30}
|
alignItems={'center'}
|
||||||
color={'primary'}>Omni
|
justifyContent={'center'}
|
||||||
Tools</Typography></Stack>
|
width={'100%'}
|
||||||
<Typography fontSize={20} mb={2}>
|
>
|
||||||
Boost your productivity with Omni Tools, the ultimate toolkit for getting things done quickly! Access thousands
|
<Box width={'60%'}>
|
||||||
of
|
<Stack mb={1} direction={'row'} spacing={1}>
|
||||||
user-friendly utilities for editing images, text, lists, and data, all directly from your browser.
|
{' '}
|
||||||
</Typography>
|
<Typography fontSize={30}>Transform Your Workflow with </Typography>
|
||||||
|
<Typography fontSize={30} color={'primary'}>
|
||||||
|
Omni Tools
|
||||||
|
</Typography>
|
||||||
|
</Stack>
|
||||||
|
<Typography fontSize={20} mb={2}>
|
||||||
|
Boost your productivity with Omni Tools, the ultimate toolkit for
|
||||||
|
getting things done quickly! Access thousands of user-friendly
|
||||||
|
utilities for editing images, text, lists, and data, all directly from
|
||||||
|
your browser.
|
||||||
|
</Typography>
|
||||||
|
|
||||||
<TextField fullWidth placeholder={'Search all tools'} sx={{borderRadius: 2}} InputProps={{
|
<TextField
|
||||||
endAdornment: (
|
fullWidth
|
||||||
<SearchIcon/>
|
placeholder={'Search all tools'}
|
||||||
),
|
sx={{ borderRadius: 2 }}
|
||||||
}}/>
|
InputProps={{
|
||||||
<Grid container spacing={1} mt={2}>
|
endAdornment: <SearchIcon />
|
||||||
{exampleTools.map((tool) => (
|
}}
|
||||||
<Grid
|
/>
|
||||||
onClick={() => navigate(tool.url)}
|
<Grid container spacing={1} mt={2}>
|
||||||
item
|
{exampleTools.map((tool) => (
|
||||||
xs={4}
|
<Grid
|
||||||
key={tool.label}
|
onClick={() => navigate(tool.url)}
|
||||||
display="flex"
|
item
|
||||||
flexDirection="row"
|
xs={4}
|
||||||
justifyContent="center"
|
key={tool.label}
|
||||||
alignItems="center"
|
display="flex"
|
||||||
padding={2}
|
flexDirection="row"
|
||||||
sx={{borderWidth: 1, borderRadius: 3, borderColor: 'grey', borderStyle: 'solid', cursor: 'pointer'}}
|
justifyContent="center"
|
||||||
>
|
alignItems="center"
|
||||||
<Typography>{tool.label}</Typography>
|
padding={2}
|
||||||
</Grid>
|
sx={{
|
||||||
))}
|
borderWidth: 1,
|
||||||
</Grid>
|
borderRadius: 3,
|
||||||
|
borderColor: 'grey',
|
||||||
|
borderStyle: 'solid',
|
||||||
|
cursor: 'pointer'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography>{tool.label}</Typography>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>)
|
);
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +0,0 @@
|
|||||||
import {RouteObject} from "react-router-dom";
|
|
||||||
import {lazy} from "react";
|
|
||||||
import {PngConfig} from "./png/PngConfig";
|
|
||||||
|
|
||||||
const PngHome = lazy(() => import("./index"));
|
|
||||||
|
|
||||||
export const ImagesConfig: RouteObject[] = [
|
|
||||||
{path: '', element: <PngHome/>},
|
|
||||||
{path: 'png', children: PngConfig},
|
|
||||||
]
|
|
3
src/pages/images/imageTools.ts
Normal file
3
src/pages/images/imageTools.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { pngTools } from './png/pngTools';
|
||||||
|
|
||||||
|
export const imageTools = [...pngTools];
|
@@ -1,5 +1,5 @@
|
|||||||
import {Box} from "@mui/material";
|
import { Box } from '@mui/material';
|
||||||
|
|
||||||
export default function ImageHome() {
|
export default function ImageHome() {
|
||||||
return (<Box></Box>)
|
return <Box></Box>;
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +0,0 @@
|
|||||||
import {RouteObject} from "react-router-dom";
|
|
||||||
import {lazy} from "react";
|
|
||||||
|
|
||||||
const ChangeColorsInPng = lazy(() => import("./change-colors-in-png"));
|
|
||||||
const PngHome = lazy(() => import("./"));
|
|
||||||
|
|
||||||
export const PngConfig: RouteObject[] = [
|
|
||||||
{path: '', element: <PngHome/>},
|
|
||||||
{path: 'change-colors-in-png', element: <ChangeColorsInPng/>}
|
|
||||||
]
|
|
@@ -1,4 +1,4 @@
|
|||||||
import { Box } from "@mui/material";
|
import { Box } from '@mui/material';
|
||||||
|
|
||||||
export default function ChangeColorsInPng() {
|
export default function ChangeColorsInPng() {
|
||||||
return <Box></Box>;
|
return <Box></Box>;
|
||||||
|
11
src/pages/images/png/change-colors-in-png/meta.ts
Normal file
11
src/pages/images/png/change-colors-in-png/meta.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { defineTool } from '../../../../tools/defineTool';
|
||||||
|
import { lazy } from 'react';
|
||||||
|
|
||||||
|
export const tool = defineTool('png', {
|
||||||
|
path: 'change-colors',
|
||||||
|
name: 'Change colors in PNG',
|
||||||
|
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.",
|
||||||
|
keywords: ['png', 'split'],
|
||||||
|
component: lazy(() => import('./index'))
|
||||||
|
});
|
@@ -1,5 +1,5 @@
|
|||||||
import {Box} from "@mui/material";
|
import { Box } from '@mui/material';
|
||||||
|
|
||||||
export default function PngHome() {
|
export default function PngHome() {
|
||||||
return (<Box></Box>)
|
return <Box></Box>;
|
||||||
}
|
}
|
||||||
|
3
src/pages/images/png/pngTools.ts
Normal file
3
src/pages/images/png/pngTools.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { tool as changeColorsInPng } from './change-colors-in-png/meta';
|
||||||
|
|
||||||
|
export const pngTools = [changeColorsInPng];
|
@@ -1,10 +0,0 @@
|
|||||||
import {RouteObject} from "react-router-dom";
|
|
||||||
import {lazy} from "react";
|
|
||||||
|
|
||||||
const StringHome = lazy(() => import("./index"));
|
|
||||||
const StringSplit = lazy(() => import("./split"));
|
|
||||||
|
|
||||||
export const StringConfig: RouteObject[] = [
|
|
||||||
{path: '', element: <StringHome/>},
|
|
||||||
{path: 'split', element: <StringSplit/>},
|
|
||||||
]
|
|
@@ -1,5 +1,5 @@
|
|||||||
import {Box} from "@mui/material";
|
import { Box } from '@mui/material';
|
||||||
|
|
||||||
export default function StringHome() {
|
export default function StringHome() {
|
||||||
return (<Box></Box>)
|
return <Box></Box>;
|
||||||
}
|
}
|
||||||
|
@@ -186,12 +186,7 @@ export default function SplitText() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ToolLayout
|
<Box>
|
||||||
title={'Text Splitter'}
|
|
||||||
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."
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid item xs={6}>
|
<Grid item xs={6}>
|
||||||
<ToolTextInput value={input} onChange={setInput} />
|
<ToolTextInput value={input} onChange={setInput} />
|
||||||
@@ -242,6 +237,6 @@ export default function SplitText() {
|
|||||||
)}
|
)}
|
||||||
</Formik>
|
</Formik>
|
||||||
</ToolOptions>
|
</ToolOptions>
|
||||||
</ToolLayout>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
11
src/pages/string/split/meta.ts
Normal file
11
src/pages/string/split/meta.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { defineTool } from '../../../tools/defineTool';
|
||||||
|
import { lazy } from 'react';
|
||||||
|
|
||||||
|
export const tool = defineTool('string', {
|
||||||
|
path: 'split',
|
||||||
|
name: 'Text splitter',
|
||||||
|
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.",
|
||||||
|
keywords: ['text', 'split'],
|
||||||
|
component: lazy(() => import('./index'))
|
||||||
|
});
|
3
src/pages/string/stringTools.ts
Normal file
3
src/pages/string/stringTools.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { tool as stringSplit } from './split/meta';
|
||||||
|
|
||||||
|
export const stringTools = [stringSplit];
|
39
src/tools/defineTool.tsx
Normal file
39
src/tools/defineTool.tsx
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import ToolLayout from '../components/ToolLayout';
|
||||||
|
import React, { LazyExoticComponent, JSXElementConstructor } from 'react';
|
||||||
|
|
||||||
|
interface ToolOptions {
|
||||||
|
path: string;
|
||||||
|
component: LazyExoticComponent<JSXElementConstructor<NonNullable<unknown>>>;
|
||||||
|
keywords: string[];
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DefinedTool {
|
||||||
|
path: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
keywords: string[];
|
||||||
|
component: () => JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const defineTool = (
|
||||||
|
basePath: string,
|
||||||
|
options: ToolOptions
|
||||||
|
): DefinedTool => {
|
||||||
|
const { path, name, description, keywords, component } = options;
|
||||||
|
const Component = component;
|
||||||
|
return {
|
||||||
|
path: `${basePath}/${path}`,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
keywords,
|
||||||
|
component: () => {
|
||||||
|
return (
|
||||||
|
<ToolLayout title={name} description={description}>
|
||||||
|
<Component />
|
||||||
|
</ToolLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
4
src/tools/index.ts
Normal file
4
src/tools/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { stringTools } from '../pages/string/stringTools';
|
||||||
|
import { imageTools } from '../pages/images/imageTools';
|
||||||
|
|
||||||
|
export const tools = [...stringTools, ...imageTools];
|
@@ -1,3 +1,3 @@
|
|||||||
export function classNames(...classes: unknown[]): string {
|
export function classNames(...classes: unknown[]): string {
|
||||||
return classes.filter(Boolean).join(' ')
|
return classes.filter(Boolean).join(' ');
|
||||||
}
|
}
|
||||||
|
@@ -6,4 +6,4 @@ export default {
|
|||||||
extend: {}
|
extend: {}
|
||||||
},
|
},
|
||||||
plugins: []
|
plugins: []
|
||||||
}
|
};
|
||||||
|
Reference in New Issue
Block a user