CipherStreamWeb converted to use Vite

This commit is contained in:
2025-08-13 23:31:29 -04:00
parent 70f9adb930
commit c9bddfa74d
120 changed files with 13931 additions and 3 deletions

1
.env Normal file
View File

@@ -0,0 +1 @@
VITE_API_URL=https://api.cipherstream.mattrixwv.com

6
.gitignore vendored
View File

@@ -7,13 +7,17 @@ yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
#Node files
node_modules
dist
dist-ssr
*.local
#Router
.tanstack
#Editor directories and files
.vscode/*
.vscode
!.vscode/extensions.json
.idea
.DS_Store

54
README.md Normal file
View File

@@ -0,0 +1,54 @@
# React + TypeScript + Vite
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
Currently, two official plugins are available:
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
## Expanding the ESLint configuration
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
```js
export default tseslint.config({
extends: [
// Remove ...tseslint.configs.recommended and replace with this
...tseslint.configs.recommendedTypeChecked,
// Alternatively, use this for stricter rules
...tseslint.configs.strictTypeChecked,
// Optionally, add this for stylistic rules
...tseslint.configs.stylisticTypeChecked,
],
languageOptions: {
// other options...
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
},
})
```
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
```js
// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'
export default tseslint.config({
plugins: {
// Add the react-x and react-dom plugins
'react-x': reactX,
'react-dom': reactDom,
},
rules: {
// other rules...
// Enable its recommended typescript rules
...reactX.configs['recommended-typescript'].rules,
...reactDom.configs.recommended.rules,
},
})
```

42
eslint.config.js Normal file
View File

@@ -0,0 +1,42 @@
import js from "@eslint/js";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import globals from "globals";
import tseslint from "typescript-eslint";
export default tseslint.config(
{ ignores: ['dist'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommendedTypeChecked],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
project: ["./tsconfig.node.json", "./tsconfig.app.json"],
tsconfigRootDir: import.meta.dirname
}
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
react: react
},
rules: {
...react.configs.recommended.rules,
...react.configs["jsx-runtime"].rules,
...reactHooks.configs.recommended.rules,
"react-refresh/only-export-components": [
"warn",
{ allowConstantExport: true }
]
},
settings: {
react: {
version: "detect",
}
}
}
);

12
index.html Normal file
View File

@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

6911
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

44
package.json Normal file
View File

@@ -0,0 +1,44 @@
{
"name": "cipher-stream-web",
"private": true,
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"@headlessui/react": "^2.2.7",
"@tailwindcss/vite": "^4.1.11",
"@tanstack/react-query": "^5.85.0",
"@tanstack/react-router": "^1.131.10",
"@tanstack/react-router-devtools": "^1.131.10",
"axios": "^1.11.0",
"clsx": "^2.1.1",
"eslint-plugin-react": "^7.37.5",
"mattrixwv-components": "^0.0.7",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-icons": "^5.5.0",
"react-tooltip": "^5.29.1",
"tailwindcss": "^4.1.11",
"use-debounce": "^10.0.5"
},
"devDependencies": {
"@eslint/js": "^9.33.0",
"@tanstack/router-plugin": "^1.131.11",
"@types/node": "^24.2.1",
"@types/react": "^19.1.10",
"@types/react-dom": "^19.1.7",
"@vitejs/plugin-react": "^5.0.0",
"eslint": "^9.33.0",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.19",
"globals": "^16.3.0",
"typescript": "^5.9.2",
"typescript-eslint": "^8.39.1",
"vite": "^7.1.2"
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.1"
width="394"
height="500"
style="clip-rule:evenodd;fill-rule:evenodd;image-rendering:optimizeQuality;shape-rendering:geometricPrecision;text-rendering:geometricPrecision"
id="svg4"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs4"
/>
<g
id="g1"
>
<path
style="opacity:1"
fill="#aab8c2"
d="m 184.5,-0.5 c 8.333,0 16.667,0 25,0 9.962,1.74178 19.962,3.90845 30,6.5 64.584,22.3002 100.751,67.4668 108.5,135.5 0.5,18.997 0.667,37.997 0.5,57 -2.913,-0.741 -5.913,-1.241 -9,-1.5 -17.33,-0.5 -34.663,-0.667 -52,-0.5 0.167,-18.67 0,-37.336 -0.5,-56 C 280.798,102.627 259.631,77.1269 223.5,64 178.783,53.1241 143.616,66.6241 118,104.5 c -5.989,10.634 -9.989,21.967 -12,34 -0.5,19.33 -0.667,38.664 -0.5,58 -18.6696,-0.167 -37.3363,0 -56,0.5 -1.7475,0.352 -3.4142,0.852 -5,1.5 -0.1666,-19.669 0,-39.336 0.5,-59 1.3455,-14.035 4.3455,-27.701 9,-41 24.6984,-57.8741 68.198,-90.87408 130.5,-99 z"
id="path1"
/>
</g>
<g
id="g2"
>
<path
style="opacity:1"
fill="#feab33"
d="m 105.5,196.5 c 60.667,0 121.333,0 182,0 17.337,-0.167 34.67,0 52,0.5 3.087,0.259 6.087,0.759 9,1.5 24.416,7.747 39.416,24.08 45,49 0,66 0,132 0,198 -5.65,30.317 -23.65,48.317 -54,54 -95.333,0 -190.667,0 -286,0 -30.3262,-5.66 -48.32618,-23.66 -54,-54 0,-66.333 0,-132.667 0,-199 6.02196,-24.357 21.022,-40.357 45,-48 1.5858,-0.648 3.2525,-1.148 5,-1.5 18.6637,-0.5 37.3304,-0.667 56,-0.5 z"
id="path2"
/>
</g>
<path
d="m 172.69971,307.53657 q 0,3.74867 -3.71807,3.74867 h -12.74766 q -3.71806,0 -3.71806,-3.74867 v -12.58483 q -0.26558,-7.7651 -5.5771,-13.12035 -5.31153,-5.35524 -13.01323,-5.35524 H 74.702094 q -7.70171,0 -13.27881,5.62301 -5.311524,5.35524 -5.311524,13.12035 v 105.49833 q 0,7.76511 5.311524,13.38811 5.5771,5.35525 13.27881,5.35525 h 59.223496 q 7.7017,0 13.01323,-5.08748 5.31152,-5.35525 5.5771,-13.12035 v -12.8526 q 0,-1.3388 1.0623,-2.40985 1.0623,-1.33882 2.65576,-1.33882 h 12.74766 q 1.59346,0 2.65576,1.33882 1.06231,1.07105 1.06231,2.40985 v 12.8526 q 0,8.03286 -3.18692,14.99468 -3.18691,6.96182 -8.49843,12.31707 -5.04595,5.08748 -12.21651,8.30063 -6.90498,2.94538 -14.87226,2.94538 H 74.702094 q -7.967286,0 -15.137843,-2.94538 -6.90498,-3.21315 -12.216504,-8.30063 -5.045948,-5.35525 -8.232863,-12.58483 -2.921338,-7.22959 -2.921338,-15.26245 V 295.21951 q 0,-8.03287 2.921338,-14.99469 3.186915,-7.22958 8.232863,-12.58483 5.311524,-5.35524 12.216504,-8.30063 7.170557,-3.21315 15.137843,-3.21315 h 59.223496 q 7.96728,0 14.87226,3.21315 7.17056,2.94539 12.21651,8.30063 5.31152,5.08748 8.49843,12.31706 3.18692,6.96182 3.18692,14.99469 z m 48.335,93.18127 v -12.31707 q 0,-1.3388 1.06231,-2.40985 1.32788,-1.33882 2.65576,-1.33882 h 12.74766 q 1.59346,0 2.65577,1.33882 1.06229,1.07105 1.06229,2.40985 v 12.31707 q 0,7.76511 5.31153,13.38811 5.5771,5.35525 13.27881,5.35525 h 59.22349 q 7.7017,0 13.01323,-5.35525 5.5771,-5.623 5.5771,-13.38811 V 376.887 q 0,-7.76511 -5.5771,-13.12035 -5.31153,-5.62301 -13.01323,-5.62301 h -59.22349 q -7.96729,0 -15.13785,-2.94538 -6.90498,-3.21316 -12.2165,-8.30064 -5.31152,-5.35524 -8.49843,-12.58482 -2.92135,-7.22959 -2.92135,-15.26245 v -23.83084 q 0,-8.03287 2.92135,-14.99469 3.18691,-7.22958 8.49843,-12.58483 5.31152,-5.35524 12.2165,-8.30063 7.17056,-3.21315 15.13785,-3.21315 h 59.22349 q 7.96728,0 14.87226,3.21315 7.17056,2.94539 12.48209,8.30063 5.31152,5.35525 8.23286,12.58483 3.18691,6.96182 3.18691,14.99469 v 12.31706 q 0,3.74867 -3.71806,3.74867 h -12.74766 q -3.71807,0 -3.71807,-3.74867 v -12.31706 q 0,-7.76511 -5.5771,-13.12035 -5.31153,-5.62301 -13.01323,-5.62301 h -59.22349 q -7.70171,0 -13.27881,5.62301 -5.31153,5.35524 -5.31153,13.12035 v 23.83084 q 0,7.7651 5.31153,13.38811 5.5771,5.35524 13.27881,5.35524 h 59.22349 q 7.96728,0 14.87226,3.21315 7.17056,2.94539 12.48209,8.30063 5.31152,5.35525 8.23286,12.58483 3.18691,6.96182 3.18691,14.99469 v 23.83084 q 0,8.03286 -3.18691,15.26245 -2.92134,7.22958 -8.23286,12.58483 -5.31153,5.08748 -12.48209,8.30063 -6.90498,2.94538 -14.87226,2.94538 h -59.22349 q -7.96729,0 -15.13785,-2.94538 -6.90498,-3.21315 -12.2165,-8.30063 -5.31152,-5.35525 -8.49843,-12.58483 -2.92135,-7.22959 -2.92135,-15.26245 z"
id="text7"
style="font-size:266.667px;font-family:'Disket Mono';-inkscape-font-specification:'Disket Mono';stroke-width:0.990987"
aria-label="CS"
/>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -0,0 +1,25 @@
import { TertiaryButton, useToaster } from "mattrixwv-components";
export default function CopyOutputButton({
value
}:{
value: string;
}){
const { addSuccess } = useToaster();
const copyToClipboard = async () => {
await navigator.clipboard.writeText(value);
addSuccess("Output copied to clipboard", 5000);
}
return (
<TertiaryButton
onClick={() => void copyToClipboard()}
>
Copy Output
</TertiaryButton>
);
}

View File

@@ -0,0 +1,19 @@
import { ButtonSwitch } from "mattrixwv-components";
export default function EncodingDecodingButton({
encoding,
setEncoding
}:{
encoding: boolean,
setEncoding: (encoding: boolean) => void
}){
return (
<ButtonSwitch
checked={encoding}
onChange={setEncoding}
onNode={<div className="bg-blue-600 hover:bg-blue-700 active:bg-blue-800 rounded-lg px-4 py-2">Encoding</div>}
offNode={<div className="bg-green-600 hover:bg-green-700 active:bg-green-800 rounded-lg px-4 py-2">Decoding</div>}
/>
);
}

View File

@@ -0,0 +1,45 @@
import type { CipherInfo } from "@/models/CipherInfo";
import type { UseQueryResult } from "@tanstack/react-query";
import { DangerMessageBlock, RubberSpinner } from "mattrixwv-components";
import { CipherWrapper } from "./CipherWrapper";
export default function CipherLoader({
infoQuery,
children
}:{
infoQuery: UseQueryResult<CipherInfo, Error>;
children: React.ReactNode;
}){
return (
<>
{
infoQuery.isError &&
<div>
<DangerMessageBlock>
Error fetching cipher info.
</DangerMessageBlock>
</div>
}
{
infoQuery.isError &&
<div
className="w-32 h-32"
>
<RubberSpinner
className="stroke-blue-600"
trackClassName="fill-white/20"
/>
</div>
}
{
infoQuery.isSuccess &&
<CipherWrapper
cipherInfo={infoQuery.data}
>
{children}
</CipherWrapper>
}
</>
);
}

View File

@@ -0,0 +1,87 @@
import type { CipherInfo } from "@/models/CipherInfo";
export function CipherWrapper({
cipherInfo,
children
}:{
cipherInfo: CipherInfo;
children: React.ReactNode;
}){
return (
<div
className="flex flex-col items-center justify-center gap-y-16"
>
{/* Header */}
<div
className="flex flex-col items-center justify-center"
>
<h1
className="font-bold text-4xl"
>
{cipherInfo.name}
</h1>
<p
className="text-center"
>
{cipherInfo.description}
</p>
</div>
{/* Inputs */}
<div>
{children}
</div>
{/* Explanations */}
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<h3
className="text-2xl"
>
Explanation
</h3>
<div
className="flex flex-col items-center justify-center gap-y-2 w-full"
>
{
cipherInfo.explanation.map((line, index) => (
<p
key={index}
className="w-full text-justify"
>
{line}
</p>
))
}
</div>
<h3
className="text-2xl"
>
Facts
</h3>
<div
className="flex flex-col items-center justify-center gap-y-2 w-full"
>
{
cipherInfo.facts.map((fact, index) => (
<p
key={index}
className="w-full text-justify"
>
{fact}
</p>
))
}
{
cipherInfo.facts.length === 0 &&
<p
className="w-full text-justify"
>
No facts available.
</p>
}
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,142 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeADFGVX, useEncodeADFGVX } from "@/hooks/combination/ADFGVXHooks";
import { TextInput, useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function ADFGVXInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ squareKeyword, setSquareKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeADFGVXMutation = useEncodeADFGVX();
const decodeADFGVXMutation = useDecodeADFGVX();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < 2)){
setOutput("");
return;
}
if(encoding){
encodeADFGVXMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
squareKeyword,
inputString: input
});
}
else{
decodeADFGVXMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
squareKeyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, squareKeyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeADFGVXMutation.isSuccess){
setOutput(decodeADFGVXMutation.data.outputString ?? "");
decodeADFGVXMutation.reset();
}
if(encodeADFGVXMutation.isSuccess){
setOutput(encodeADFGVXMutation.data.outputString ?? "");
encodeADFGVXMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeADFGVXMutation.isSuccess, encodeADFGVXMutation.isSuccess, decodeADFGVXMutation.data, encodeADFGVXMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeADFGVXMutation.isError){
addDanger(decodeADFGVXMutation.error.message);
decodeADFGVXMutation.reset();
}
if(encodeADFGVXMutation.isError){
addDanger(encodeADFGVXMutation.error.message);
encodeADFGVXMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeADFGVXMutation.isError, encodeADFGVXMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<TextInput
placeholder="Square Keyword"
value={squareKeyword}
onChange={(e) => setSquareKeyword(e.target.value)}
labelClassName="bg-(--bg-color) text-(--text-color)"
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,142 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeADFGX, useEncodeADFGX } from "@/hooks/combination/ADFGXHooks";
import { TextInput, useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function ADFGXInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ squareKeyword, setSquareKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeADFGXMutation = useEncodeADFGX();
const decodeADFGXMutation = useDecodeADFGX();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < 2)){
setOutput("");
return;
}
if(encoding){
encodeADFGXMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
squareKeyword,
inputString: input
});
}
else{
decodeADFGXMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
squareKeyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, squareKeyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeADFGXMutation.isSuccess){
setOutput(decodeADFGXMutation.data.outputString ?? "");
decodeADFGXMutation.reset();
}
if(encodeADFGXMutation.isSuccess){
setOutput(encodeADFGXMutation.data.outputString ?? "");
encodeADFGXMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeADFGXMutation.isSuccess, encodeADFGXMutation.isSuccess, decodeADFGXMutation.data, encodeADFGXMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeADFGXMutation.isError){
addDanger(decodeADFGXMutation.error.message);
decodeADFGXMutation.reset();
}
if(encodeADFGXMutation.isError){
addDanger(encodeADFGXMutation.error.message);
encodeADFGXMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeADFGXMutation.isError, encodeADFGXMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<TextInput
value={squareKeyword}
onChange={(e) => setSquareKeyword(e.target.value)}
placeholder="Square Keyword"
labelClassName="bg-(--bg-color) text-(--text-color)"
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,150 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import NumberSelector from "@/components/input/NumberSelector";
import NumberSelectorArray from "@/components/input/NumberSelectorArray";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeAffine, useEncodeAffine } from "@/hooks/monosubstitution/AffineHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function AffineInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ key1, setKey1 ] = useState(1);
const [ key2, setKey2 ] = useState(0);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeAffineMutation = useEncodeAffine();
const decodeAffineMutation = useDecodeAffine();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeAffineMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
key1,
key2,
inputString: input
});
}
else{
decodeAffineMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
key1,
key2,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, key1, key2, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeAffineMutation.isSuccess){
setOutput(decodeAffineMutation.data.outputString ?? "");
decodeAffineMutation.reset();
}
if(encodeAffineMutation.isSuccess){
setOutput(encodeAffineMutation.data.outputString ?? "");
encodeAffineMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeAffineMutation.isSuccess, encodeAffineMutation.isSuccess, decodeAffineMutation.data, encodeAffineMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeAffineMutation.isError){
addDanger(decodeAffineMutation.error.message);
decodeAffineMutation.reset();
}
if(encodeAffineMutation.isError){
addDanger(encodeAffineMutation.error.message);
encodeAffineMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeAffineMutation.isError, encodeAffineMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<div
className="flex flex-col items-center justify-center gap-y-2"
>
<NumberSelectorArray
label="Key 1"
value={key1}
shiftArray={[1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25]}
onChange={setKey1}
/>
<NumberSelector
label="Key 2"
value={key2}
minValue={0}
maxValue={25}
onChange={setKey2}
/>
</div>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,125 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeAtbash, useEncodeAtbash } from "@/hooks/monosubstitution/AtbashHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function AtbashInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeAtbashMutation = useEncodeAtbash();
const decodeAtbashMutation = useDecodeAtbash();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeAtbashMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
inputString: input
});
}
else{
decodeAtbashMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeAtbashMutation.isSuccess){
setOutput(decodeAtbashMutation.data.outputString ?? "");
decodeAtbashMutation.reset();
}
if(encodeAtbashMutation.isSuccess){
setOutput(encodeAtbashMutation.data.outputString ?? "");
encodeAtbashMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeAtbashMutation.isSuccess, encodeAtbashMutation.isSuccess, decodeAtbashMutation.data, encodeAtbashMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeAtbashMutation.isError){
addDanger(decodeAtbashMutation.error.message);
decodeAtbashMutation.reset();
}
if(encodeAtbashMutation.isError){
addDanger(encodeAtbashMutation.error.message);
encodeAtbashMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeAtbashMutation, encodeAtbashMutation ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeAutokey, useEncodeAutokey } from "@/hooks/monosubstitution/AutokeyHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function AutokeyInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeAutokeyMutation = useEncodeAutokey();
const decodeAutokeyMutation = useDecodeAutokey();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < 2)){
setOutput("");
return;
}
if(encoding){
encodeAutokeyMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodeAutokeyMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, input, keyword, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeAutokeyMutation.isSuccess){
setOutput(decodeAutokeyMutation.data.outputString ?? "");
decodeAutokeyMutation.reset();
}
if(encodeAutokeyMutation.isSuccess){
setOutput(encodeAutokeyMutation.data.outputString ?? "");
encodeAutokeyMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeAutokeyMutation.isSuccess, encodeAutokeyMutation.isSuccess, decodeAutokeyMutation.data, encodeAutokeyMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeAutokeyMutation.isError){
addDanger(decodeAutokeyMutation.error.message);
decodeAutokeyMutation.reset();
}
if(encodeAutokeyMutation.isError){
addDanger(encodeAutokeyMutation.error.message);
encodeAutokeyMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeAutokeyMutation.isError, encodeAutokeyMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,115 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeBaconian, useEncodeBaconian } from "@/hooks/monosubstitution/BaconianHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function BaconianInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeBaconianMutation = useEncodeBaconian();
const decodeBaconianMutation = useDecodeBaconian();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeBaconianMutation.mutate({
encoding,
preserveCapitals: capitals,
inputString: input
});
}
else{
decodeBaconianMutation.mutate({
encoding,
preserveCapitals: capitals,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [ capitals, encoding, input, performCoding ]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeBaconianMutation.isSuccess){
setOutput(decodeBaconianMutation.data.outputString ?? "");
decodeBaconianMutation.reset();
}
if(encodeBaconianMutation.isSuccess){
setOutput(encodeBaconianMutation.data.outputString ?? "");
encodeBaconianMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBaconianMutation.isSuccess, encodeBaconianMutation.isSuccess, decodeBaconianMutation.data, encodeBaconianMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeBaconianMutation.isError){
addDanger(decodeBaconianMutation.error.message);
decodeBaconianMutation.reset();
}
if(encodeBaconianMutation.isError){
addDanger(encodeBaconianMutation.error.message);
encodeBaconianMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBaconianMutation.isError, encodeBaconianMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,118 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import NumberSelector from "@/components/input/NumberSelector";
import OutputMessage from "@/components/input/OutputMessage";
import { useDecodeBaseX, useEncodeBaseX } from "@/hooks/monosubstitution/BaseXHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function BaseXInputs(){
const [ encoding, setEncoding ] = useState(true);
const [ base, setBase ] = useState(2);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeBaseXMutation = useEncodeBaseX();
const decodeBaseXMutation = useDecodeBaseX();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeBaseXMutation.mutate({
encoding,
base,
inputString: input
});
}
else{
decodeBaseXMutation.mutate({
encoding,
base,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [base, encoding, input, performCoding]);
//When the mutations is successful set the new output
useEffect(() => {
if(decodeBaseXMutation.isSuccess){
setOutput(decodeBaseXMutation.data.outputString ?? "");
decodeBaseXMutation.reset();
}
if(encodeBaseXMutation.isSuccess){
setOutput(encodeBaseXMutation.data.outputString ?? "");
encodeBaseXMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBaseXMutation.isSuccess, encodeBaseXMutation.isSuccess, decodeBaseXMutation.data, encodeBaseXMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeBaseXMutation.isError){
addDanger(decodeBaseXMutation.error.message);
decodeBaseXMutation.reset();
}
if(encodeBaseXMutation.isError){
addDanger(encodeBaseXMutation.error.message);
encodeBaseXMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBaseXMutation.isError, encodeBaseXMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<div
className="flex flex-col items-center justify-center gap-y-2"
>
<NumberSelector
label="Base"
value={base}
onChange={setBase}
minValue={2}
maxValue={36}
/>
</div>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeBeaufort, useEncodeBeaufort } from "@/hooks/monosubstitution/BeaufortHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function BeaufortInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeBeaufortMutation = useEncodeBeaufort();
const decodeBeaufortMutation = useDecodeBeaufort();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < 2)){
setOutput("");
return;
}
if(encoding){
encodeBeaufortMutation.mutate({
encoding: encoding,
preserveCapitals: capitals,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
keyword: keyword,
inputString: input
});
}
else{
decodeBeaufortMutation.mutate({
encoding: encoding,
preserveCapitals: capitals,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
keyword: keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeBeaufortMutation.isSuccess){
setOutput(decodeBeaufortMutation.data.outputString ?? "");
decodeBeaufortMutation.reset();
}
if(encodeBeaufortMutation.isSuccess){
setOutput(encodeBeaufortMutation.data.outputString ?? "");
encodeBeaufortMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBeaufortMutation.isSuccess, encodeBeaufortMutation.isSuccess, decodeBeaufortMutation.data, encodeBeaufortMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeBeaufortMutation.isError){
addDanger(decodeBeaufortMutation.error.message);
decodeBeaufortMutation.reset();
}
if(encodeBeaufortMutation.isError){
addDanger(encodeBeaufortMutation.error.message);
encodeBeaufortMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBeaufortMutation.isError, encodeBeaufortMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,140 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import NumberSelector from "@/components/input/NumberSelector";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeCaesar, useEncodeCaesar } from "@/hooks/monosubstitution/CaesarHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function CaesarInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ shift, setShift ] = useState(0);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeCaesarMutation = useEncodeCaesar();
const decodeCaesarMutation = useDecodeCaesar();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeCaesarMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
shiftAmount: shift,
inputString: input
});
}
else{
decodeCaesarMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
shiftAmount: shift,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, input, performCoding, shift, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeCaesarMutation.isSuccess){
setOutput(decodeCaesarMutation.data.outputString ?? "");
decodeCaesarMutation.reset();
}
if(encodeCaesarMutation.isSuccess){
setOutput(encodeCaesarMutation.data.outputString ?? "");
encodeCaesarMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeCaesarMutation.isSuccess, encodeCaesarMutation.isSuccess, decodeCaesarMutation.data, encodeCaesarMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeCaesarMutation.isError){
addDanger(decodeCaesarMutation.error.message);
decodeCaesarMutation.reset();
}
if(encodeCaesarMutation.isError){
addDanger(encodeCaesarMutation.error.message);
encodeCaesarMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeCaesarMutation.isError, encodeCaesarMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<div
className="flex flex-col items-center justify-center gap-y-2"
>
<NumberSelector
label="Shift"
value={shift}
minValue={0}
maxValue={25}
onChange={setShift}
/>
</div>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordArea from "@/components/input/KeywordArea";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeOneTimePad, useEncodeOneTimePad } from "@/hooks/monosubstitution/OneTimePadHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function OneTimePadInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeOneTimePadMutation = useEncodeOneTimePad();
const decodeOneTimePadMutation = useDecodeOneTimePad();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < input.length)){
setOutput("");
return;
}
if(encoding){
encodeOneTimePadMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodeOneTimePadMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeOneTimePadMutation.isSuccess){
setOutput(decodeOneTimePadMutation.data.outputString ?? "");
decodeOneTimePadMutation.reset();
}
if(encodeOneTimePadMutation.isSuccess){
setOutput(encodeOneTimePadMutation.data.outputString ?? "");
encodeOneTimePadMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeOneTimePadMutation.isSuccess, encodeOneTimePadMutation.isSuccess, decodeOneTimePadMutation.data, encodeOneTimePadMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeOneTimePadMutation.isError){
addDanger(decodeOneTimePadMutation.error.message);
decodeOneTimePadMutation.reset();
}
if(encodeOneTimePadMutation.isError){
addDanger(encodeOneTimePadMutation.error.message);
encodeOneTimePadMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeOneTimePadMutation.isError, encodeOneTimePadMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordArea
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodePorta, useEncodePorta } from "@/hooks/monosubstitution/PortaHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function PortaInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodePortaMutation = useEncodePorta();
const decodePortaMutation = useDecodePorta();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < 2)){
setOutput("");
return;
}
if(encoding){
encodePortaMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodePortaMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodePortaMutation.isSuccess){
setOutput(decodePortaMutation.data.outputString ?? "");
decodePortaMutation.reset();
}
if(encodePortaMutation.isSuccess){
setOutput(encodePortaMutation.data.outputString ?? "");
encodePortaMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodePortaMutation.isSuccess, encodePortaMutation.isSuccess, decodePortaMutation.data, encodePortaMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodePortaMutation.isError){
addDanger(decodePortaMutation.error.message);
decodePortaMutation.reset();
}
if(encodePortaMutation.isError){
addDanger(encodePortaMutation.error.message);
encodePortaMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodePortaMutation.isError, encodePortaMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeSubstitution, useEncodeSubstitution } from "@/hooks/monosubstitution/SubstitutionHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function SubstitutionInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeSubstitutionMutation = useEncodeSubstitution();
const decodeSubstitutionMutation = useDecodeSubstitution();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || ((keyword.length !== 26) && (keyword.length !== 36))){
setOutput("");
return;
}
if(encoding){
encodeSubstitutionMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodeSubstitutionMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeSubstitutionMutation.isSuccess){
setOutput(decodeSubstitutionMutation.data.outputString ?? "");
decodeSubstitutionMutation.reset();
}
if(encodeSubstitutionMutation.isSuccess){
setOutput(encodeSubstitutionMutation.data.outputString ?? "");
encodeSubstitutionMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeSubstitutionMutation.isSuccess, encodeSubstitutionMutation.isSuccess, decodeSubstitutionMutation.data, encodeSubstitutionMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeSubstitutionMutation.isError){
addDanger(decodeSubstitutionMutation.error.message);
decodeSubstitutionMutation.reset();
}
if(encodeSubstitutionMutation.isError){
addDanger(encodeSubstitutionMutation.error.message);
encodeSubstitutionMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeSubstitutionMutation.isError, encodeSubstitutionMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeVigenere, useEncodeVigenere } from "@/hooks/monosubstitution/VigenereHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function VigenereInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeVigenereMutation = useEncodeVigenere();
const decodeVigenereMutation = useDecodeVigenere();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < 2)){
setOutput("");
return;
}
if(encoding){
encodeVigenereMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodeVigenereMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeVigenereMutation.isSuccess){
setOutput(decodeVigenereMutation.data.outputString ?? "");
decodeVigenereMutation.reset();
}
if(encodeVigenereMutation.isSuccess){
setOutput(encodeVigenereMutation.data.outputString ?? "");
encodeVigenereMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeVigenereMutation.isSuccess, encodeVigenereMutation.isSuccess, decodeVigenereMutation.data, encodeVigenereMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeVigenereMutation.isError){
addDanger(decodeVigenereMutation.error.message);
decodeVigenereMutation.reset();
}
if(encodeVigenereMutation.isError){
addDanger(encodeVigenereMutation.error.message);
encodeVigenereMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeVigenereMutation.isError, encodeVigenereMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeBifid, useEncodeBifid } from "@/hooks/polysubstitution/BifidHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function BifidInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeBifidMutation = useEncodeBifid();
const decodeBifidMutation = useDecodeBifid();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeBifidMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodeBifidMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeBifidMutation.isSuccess){
setOutput(decodeBifidMutation.data.outputString ?? "");
decodeBifidMutation.reset();
}
if(encodeBifidMutation.isSuccess){
setOutput(encodeBifidMutation.data.outputString ?? "");
encodeBifidMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBifidMutation.isSuccess, encodeBifidMutation.isSuccess, decodeBifidMutation.data, encodeBifidMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeBifidMutation.isError){
addDanger(decodeBifidMutation.error.message);
decodeBifidMutation.reset();
}
if(encodeBifidMutation.isError){
addDanger(encodeBifidMutation.error.message);
encodeBifidMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeBifidMutation.isError, encodeBifidMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeColumnar, useEncodeColumnar } from "@/hooks/polysubstitution/ColumnarHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function ColumnarInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeColumnarMutation = useEncodeColumnar();
const decodeColumnarMutation = useDecodeColumnar();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if((input === "") || (keyword.length < 2)){
setOutput("");
return;
}
if(encoding){
encodeColumnarMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodeColumnarMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeColumnarMutation.isSuccess){
setOutput(decodeColumnarMutation.data.outputString ?? "");
decodeColumnarMutation.reset();
}
if(encodeColumnarMutation.isSuccess){
setOutput(encodeColumnarMutation.data.outputString ?? "");
encodeColumnarMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeColumnarMutation.isSuccess, encodeColumnarMutation.isSuccess, decodeColumnarMutation.data, encodeColumnarMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeColumnarMutation.isError){
addDanger(decodeColumnarMutation.error.message);
decodeColumnarMutation.reset();
}
if(encodeColumnarMutation.isError){
addDanger(encodeColumnarMutation.error.message);
encodeColumnarMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeColumnarMutation.isError, encodeColumnarMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import SquareNumberArray from "@/components/input/SquareNumberArray";
import { useDecodeHill, useEncodeHill } from "@/hooks/polysubstitution/HillHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function HillInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ key, setKey ] = useState([[0, 0], [0, 0]]);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeHillMutation = useEncodeHill();
const decodeHillMutation = useDecodeHill();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeHillMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
key,
inputString: input
});
}
else{
decodeHillMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
key,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, key, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeHillMutation.isSuccess){
setOutput(decodeHillMutation.data.outputString ?? "");
decodeHillMutation.reset();
}
if(encodeHillMutation.isSuccess){
setOutput(encodeHillMutation.data.outputString ?? "");
encodeHillMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeHillMutation.isSuccess, encodeHillMutation.isSuccess, decodeHillMutation.data, encodeHillMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeHillMutation.isError){
addDanger(decodeHillMutation.error.message);
decodeHillMutation.reset();
}
if(encodeHillMutation.isError){
addDanger(encodeHillMutation.error.message);
encodeHillMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeHillMutation.isError, encodeHillMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<SquareNumberArray
value={key}
onChange={setKey}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,103 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import OutputMessage from "@/components/input/OutputMessage";
import { useDecodeMorse, useEncodeMorse } from "@/hooks/polysubstitution/MorseHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function MorseInputs(){
const [ encoding, setEncoding ] = useState(true);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeMorseMutation = useEncodeMorse();
const decodeMorseMutation = useDecodeMorse();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeMorseMutation.mutate({
encoding,
inputString: input
});
}
else{
decodeMorseMutation.mutate({
encoding,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [encoding, input, performCoding]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeMorseMutation.isSuccess){
setOutput(decodeMorseMutation.data.outputString ?? "");
decodeMorseMutation.reset();
}
if(encodeMorseMutation.isSuccess){
setOutput(encodeMorseMutation.data.outputString ?? "");
encodeMorseMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeMorseMutation.isSuccess, encodeMorseMutation.isSuccess, decodeMorseMutation.data, encodeMorseMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeMorseMutation.isError){
addDanger(decodeMorseMutation.error.message);
decodeMorseMutation.reset();
}
if(encodeMorseMutation.isError){
addDanger(encodeMorseMutation.error.message);
encodeMorseMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeMorseMutation.isError, encodeMorseMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,133 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodePlayfair, useEncodePlayfair } from "@/hooks/polysubstitution/PlayfairHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function PlayfairInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodePlayfairMutation = useEncodePlayfair();
const decodePlayfairMutation = useDecodePlayfair();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodePlayfairMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
else{
decodePlayfairMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodePlayfairMutation.isSuccess){
setOutput(decodePlayfairMutation.data.outputString ?? "");
decodePlayfairMutation.reset();
}
if(encodePlayfairMutation.isSuccess){
setOutput(encodePlayfairMutation.data.outputString ?? "");
encodePlayfairMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodePlayfairMutation.isSuccess, encodePlayfairMutation.isSuccess, decodePlayfairMutation.data, encodePlayfairMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodePlayfairMutation.isError){
addDanger(decodePlayfairMutation.error.message);
decodePlayfairMutation.reset();
}
if(encodePlayfairMutation.isError){
addDanger(encodePlayfairMutation.error.message);
encodePlayfairMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodePlayfairMutation.isError, encodePlayfairMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,128 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodePolybius, useEncodePolybius } from "@/hooks/polysubstitution/PolybiusHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function PolybiusInputs(){
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodePolybiusMutation = useEncodePolybius();
const decodePolybiusMutation = useDecodePolybius();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodePolybiusMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
keyword,
inputString: input
});
}
else{
decodePolybiusMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
keyword,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [encoding, keyword, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodePolybiusMutation.isSuccess){
setOutput(decodePolybiusMutation.data.outputString ?? "");
decodePolybiusMutation.reset();
}
if(encodePolybiusMutation.isSuccess){
setOutput(encodePolybiusMutation.data.outputString ?? "");
encodePolybiusMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodePolybiusMutation.isSuccess, encodePolybiusMutation.isSuccess, decodePolybiusMutation.data, encodePolybiusMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodePolybiusMutation.isError){
addDanger(decodePolybiusMutation.error.message);
decodePolybiusMutation.reset();
}
if(encodePolybiusMutation.isError){
addDanger(encodePolybiusMutation.error.message);
encodePolybiusMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodePolybiusMutation.isError, encodePolybiusMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,140 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import NumberSelector from "@/components/input/NumberSelector";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeRailFence, useEncodeRailFence } from "@/hooks/polysubstitution/RailFenceHooks";
import { useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function RaidFenceInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ rails, setRails ] = useState(2);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeRailFenceMutation = useEncodeRailFence();
const decodeRailFenceMutation = useDecodeRailFence();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeRailFenceMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
rails,
inputString: input
});
}
else{
decodeRailFenceMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
rails,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, rails, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeRailFenceMutation.isSuccess){
setOutput(decodeRailFenceMutation.data.outputString ?? "");
decodeRailFenceMutation.reset();
}
if(encodeRailFenceMutation.isSuccess){
setOutput(encodeRailFenceMutation.data.outputString ?? "");
encodeRailFenceMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeRailFenceMutation.isSuccess, encodeRailFenceMutation.isSuccess, decodeRailFenceMutation.data, encodeRailFenceMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeRailFenceMutation.isError){
addDanger(decodeRailFenceMutation.error.message);
decodeRailFenceMutation.reset();
}
if(encodeRailFenceMutation.isError){
addDanger(encodeRailFenceMutation.error.message);
encodeRailFenceMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeRailFenceMutation.isError, encodeRailFenceMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<div
className="flex flex-col items-center justify-center gap-y-2"
>
<NumberSelector
label="Rails"
value={rails}
onChange={setRails}
minValue={2}
maxValue={100}
/>
</div>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,157 @@
import CopyOutputButton from "@/components/button/CopyOutputButton";
import EncodingDecodingButton from "@/components/button/EncodingDecodingButton";
import InputMessage from "@/components/input/InputMessage";
import KeywordInput from "@/components/input/KeywordInput";
import NumberSelector from "@/components/input/NumberSelector";
import OutputMessage from "@/components/input/OutputMessage";
import PreservationSliders from "@/components/input/PreservationSliders";
import { useDecodeTrifid, useEncodeTrifid } from "@/hooks/polysubstitution/TrifidHooks";
import { TextInput, useToaster } from "mattrixwv-components";
import { useEffect, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
export default function TrifidInputs(){
const [ capitals, setCapitals ] = useState(true);
const [ symbols, setSymbols ] = useState(true);
const [ whitespace, setWhitespace ] = useState(true);
const [ encoding, setEncoding ] = useState(true);
const [ keyword, setKeyword ] = useState("");
const [ fill, setFill ] = useState("#");
const [ groupLength, setGroupLength ] = useState(1);
const [ input, setInput ] = useState("");
const [ output, setOutput ] = useState("");
const { addDanger } = useToaster();
const encodeTrifidMutation = useEncodeTrifid();
const decodeTrifidMutation = useDecodeTrifid();
//Do coding with a delay
const performCoding = useDebouncedCallback(() => {
if(input === ""){
setOutput("");
return;
}
if(encoding){
encodeTrifidMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
fill,
groupLength,
inputString: input
});
}
else{
decodeTrifidMutation.mutate({
encoding,
preserveSymbols: symbols,
preserveWhitespace: whitespace,
preserveCapitals: capitals,
keyword,
fill,
groupLength,
inputString: input
});
}
}, 1000);
//Code when input changes
useEffect(() => {
performCoding();
}, [capitals, encoding, keyword, fill, groupLength, input, performCoding, symbols, whitespace]);
//When the mutation is successful set the new output
useEffect(() => {
if(decodeTrifidMutation.isSuccess){
setOutput(decodeTrifidMutation.data.outputString ?? "");
decodeTrifidMutation.reset();
}
if(encodeTrifidMutation.isSuccess){
setOutput(encodeTrifidMutation.data.outputString ?? "");
encodeTrifidMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeTrifidMutation.isSuccess, encodeTrifidMutation.isSuccess, decodeTrifidMutation.data, encodeTrifidMutation.data ]);
//When the mutation has an error, display the message
useEffect(() => {
if(decodeTrifidMutation.isError){
addDanger(decodeTrifidMutation.error.message);
decodeTrifidMutation.reset();
}
if(encodeTrifidMutation.isError){
addDanger(encodeTrifidMutation.error.message);
encodeTrifidMutation.reset();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ decodeTrifidMutation.isError, encodeTrifidMutation.isError ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<PreservationSliders
capitals={capitals}
setCapitals={setCapitals}
symbols={symbols}
setSymbols={setSymbols}
whitespace={whitespace}
setWhitespace={setWhitespace}
/>
</div>
<div
className="flex flex-col items-center justify-center"
>
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
<div
className="flex flex-col items-center justify-center gap-y-8"
>
<div
className="flex flex-col items-center justify-center gap-y-2"
>
<NumberSelector
label="Group Size"
value={groupLength}
onChange={setGroupLength}
minValue={1}
maxValue={100}
/>
</div>
<TextInput
placeholder="Fill"
value={fill}
onChange={(e) => { if(e.target.value.length <= 1){ setFill(e.target.value); } }}
labelClassName="bg-(--bg-color) text-(--text-color)"
/>
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
<InputMessage
value={input}
onChange={setInput}
/>
<OutputMessage
value={output}
onChange={setOutput}
/>
<CopyOutputButton
value={output}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,24 @@
import { TextArea } from "mattrixwv-components";
export default function InputMessage({
value,
onChange
}:{
value: string;
onChange: (value: string) => void;
}){
return (
<div
className="w-160"
>
<TextArea
placeholder="Input Message"
value={value}
onChange={(e) => onChange(e.target.value)}
inputClassName="h-40 w-160 [resize:none]"
labelClassName="bg-(--bg-color) text-(--text-color) peer-focus:bg-(--bg-color) peer-focus:text-(--text-color)"
/>
</div>
);
}

View File

@@ -0,0 +1,23 @@
import { TextArea } from "mattrixwv-components";
export default function KeywordArea({
value,
onChange
}:{
value: string;
onChange: (value: string) => void;
}){
return (
<div
className="w-160"
>
<TextArea
placeholder="Keyword"
value={value}
onChange={(e) => onChange(e.target.value)}
inputClassName="h-40 w-160 [resize:none]"
labelClassName="bg-(--bg-color) text-(--text-color) peer-focus:bg-(--bg-color) peer-focus:text-(--text-color)"
/>
</div>
);
}

View File

@@ -0,0 +1,23 @@
import { TextInput } from "mattrixwv-components";
export default function KeywordInput({
value,
onChange
}:{
value: string;
onChange: (newValue: string) => void;
}){
return (
<div
className="w-160"
>
<TextInput
placeholder="Keyword"
value={value}
onChange={(e) => onChange(e.target.value)}
labelClassName="bg-(--bg-color) text-(--text-color) peer-focus:bg-(--bg-color) peer-focus:text-(--text-color)"
/>
</div>
);
}

View File

@@ -0,0 +1,31 @@
import { useMemo } from "react";
import NumberSelectorArray from "./NumberSelectorArray";
export default function NumberSelector({
value,
label,
minValue,
maxValue,
onChange
}:{
value: number;
label: string;
minValue: number;
maxValue: number;
onChange: (newShift: number) => void;
}){
const shiftArray: number[] = useMemo(() => (
Array.from({ length: maxValue - minValue + 1 }, (_, i) => i + minValue)
), [ minValue, maxValue ]);
//TODO: Perform a check for minValue <= value <= maxValue
return (
<NumberSelectorArray
value={value}
label={label}
shiftArray={shiftArray}
onChange={onChange}
/>
);
}

View File

@@ -0,0 +1,59 @@
import { PrimaryButton, SuccessButton } from "mattrixwv-components";
import { useCallback, useState } from "react";
import { BsChevronLeft, BsChevronRight } from "react-icons/bs";
export default function NumberSelectorArray({
label,
shiftArray,
value,
onChange
}:{
label: string;
shiftArray: number[];
value: number;
onChange: (value: number) => void;
}){
const [ arraySubscript, setArraySubscript ] = useState(shiftArray.indexOf(value) ?? 0);
//TODO: Check if the value exists
const decrementValue = useCallback(() => {
if(arraySubscript === 0){
setArraySubscript(shiftArray.length - 1);
onChange(shiftArray[shiftArray.length - 1]);
}
else{
setArraySubscript(arraySubscript - 1);
onChange(shiftArray[arraySubscript - 1]);
}
}, [arraySubscript, shiftArray, onChange]);
const incrementValue = useCallback(() => {
if(arraySubscript === shiftArray.length - 1){
setArraySubscript(0);
onChange(shiftArray[0]);
}
else{
setArraySubscript(arraySubscript + 1);
onChange(shiftArray[arraySubscript + 1]);
}
}, [arraySubscript, shiftArray, onChange]);
return (
<div
className="flex flex-col items-center justify-center text-2xl gap-y-2"
>
{/* Label */}
<div>{label}</div>
<div
className="flex flex-row items-center justify-center"
>
<SuccessButton size="sm" shape="square" onClick={decrementValue}><BsChevronLeft className="text-3xl text-white"/></SuccessButton>
<div className="w-16 text-center">{value}</div>
<PrimaryButton size="sm" shape="square" onClick={incrementValue}><BsChevronRight className="text-3xl text-white"/></PrimaryButton>
</div>
</div>
);
}

View File

@@ -0,0 +1,25 @@
import { TextArea } from "mattrixwv-components";
export default function OutputMessage({
value,
onChange
}:{
value: string;
onChange: (value: string) => void;
}){
return (
<div
className="w-160"
>
<TextArea
placeholder="Output Message"
value={value}
onChange={(e) => onChange(e.target.value)}
inputClassName="h-40 w-160 [resize:none]"
labelClassName="bg-(--bg-color) text-(--text-color) peer-focus:bg-(--bg-color) peer-focus:text-(--text-color)"
disabled={true}
/>
</div>
);
}

View File

@@ -0,0 +1,59 @@
import { PrimarySwitch } from "mattrixwv-components";
export default function PreservationSliders({
capitals,
setCapitals,
symbols,
setSymbols,
whitespace,
setWhitespace
}:{
capitals?: boolean;
setCapitals?: (value: boolean) => void;
symbols?: boolean;
setSymbols?: (value: boolean) => void;
whitespace?: boolean;
setWhitespace?: (value: boolean) => void;
}){
return (
<>
{
setCapitals &&
<div className="flex flex-row items-center justify-center">
<PrimarySwitch
checked={capitals}
onChange={setCapitals}
size="md"
>
<div className="pl-2">Preserve Capitals</div>
</PrimarySwitch>
</div>
}
{
setSymbols &&
<div className="flex flex-row items-center justify-center">
<PrimarySwitch
checked={symbols}
onChange={setSymbols}
size="md"
>
<div className="pl-2">Preserve Symbols</div>
</PrimarySwitch>
</div>
}
{
setWhitespace &&
<div className="flex flex-row items-center justify-center">
<PrimarySwitch
checked={whitespace}
onChange={setWhitespace}
size="md"
>
<div className="pl-2">Preserve Whitespace</div>
</PrimarySwitch>
</div>
}
</>
);
}

View File

@@ -0,0 +1,92 @@
import clsx from "clsx";
import { PrimaryButton, SuccessButton } from "mattrixwv-components";
import { useCallback } from "react";
import { BsDashLg, BsPlusLg } from "react-icons/bs";
export default function SquareNumberArray({
value,
onChange
}:{
value: number[][];
onChange: (value: number[][]) => void;
}){
//TODO: Check for a square array
const decreaseArraySize = useCallback(() => {
if(value.length <= 2){
throw new Error("Cannot decrease grid size below 2");
}
const newValue = value.slice(0, -1);
newValue.forEach((row) => {
row.pop();
});
onChange(newValue);
}, [ onChange, value ]);
const increaseArraySize = useCallback(() => {
if(value.length >= 10){
throw new Error("Cannot increase grid size above 10");
}
const newValue = [...value];
newValue.forEach((row) => {
row.push(0);
});
newValue.push(new Array(value.length + 1).fill(0) as number[]);
onChange(newValue);
}, [ onChange, value ]);
const updateValue = useCallback((rowIndex: number, cellIndex: number, newCellValue: number) => {
const newValue = [...value];
newValue[rowIndex][cellIndex] = newCellValue;
onChange(newValue);
}, [ onChange, value ]);
return (
<div
className="flex flex-col items-center justify-center gap-y-4"
>
<div
className="flex flex-row items-center justify-center gap-x-8"
>
<SuccessButton size="sm" shape="square" onClick={decreaseArraySize} disabled={value.length <= 2}><BsDashLg className="text-3xl text-white"/></SuccessButton>
<PrimaryButton size="sm" shape="square" onClick={increaseArraySize} disabled={value.length >= 10}><BsPlusLg className="text-3xl text-white"/></PrimaryButton>
</div>
<table>
<tbody>
{
value.map((row, rowIndex) => (
<tr
key={`squareNumberArrayRow${rowIndex}`}
className=""
>
{
row.map((cell, cellIndex) => (
<td
key={`squareNumberArrayCell${rowIndex}${cellIndex}`}
className="w-8 h-8 border"
>
<input
type="number"
className={clsx(
"text-center spinbox-hide text-xl w-12 h-10",
"[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
)}
value={cell}
onChange={(e) => updateValue(rowIndex, cellIndex, parseInt(e.target.value))}
/>
</td>
))
}
</tr>
))
}
</tbody>
</table>
</div>
);
}

View File

@@ -0,0 +1,53 @@
import { combinationLinks } from "@/util/LinksUtil";
import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react";
import { Link } from "@tanstack/react-router";
import clsx from "clsx";
import { IoMdArrowDropdown } from "react-icons/io";
export default function CombinationLinks(){
return (
<Popover>
<PopoverButton
className={clsx(
"navBarLink outline-none",
"peer flex flex-row items-center justify-center"
)}
>
Combination
<IoMdArrowDropdown
className="mt-1"
size={22}
/>
</PopoverButton>
<PopoverPanel
anchor={{to: "top"}}
className={clsx(
"absolute z-50 w-(--button-width) rounded-lg py-2",
"flex flex-col items-start justify-center",
"bg-gray-600 dark:bg-neutral-700",
"shadow-md shadow-gray-950"
)}
>
<Link
className="w-full px-4 py-2 text-start"
to="/combination"
>
Overview
</Link>
<hr className="bg-neutral-500 h-0.5 w-full"/>
{
combinationLinks.map((link) => (
<Link
key={link.to}
className="w-full px-4 py-2 text-start"
to={link.to}
>
{link.label}
</Link>
))
}
</PopoverPanel>
</Popover>
);
}

View File

@@ -0,0 +1,36 @@
import { useTheme } from "@/providers/ThemeProvider";
import { BsLightbulb, BsLightbulbFill } from "react-icons/bs";
export default function DarkModeToggle(){
const { theme, setTheme } = useTheme();
return (
<div className="cursor-pointer">
<input
id="darkModeCheckbox"
type="checkbox"
className="peer hidden"
onChange={() => setTheme(theme === "dark" ? "light" : "dark")}
defaultChecked={theme === "dark"}
/>
<label
htmlFor="darkModeCheckbox"
className="block peer-checked:hidden cursor-pointer"
>
<BsLightbulbFill
size={20}
/>
</label>
<label
htmlFor="darkModeCheckbox"
className="hidden peer-checked:block cursor-pointer"
>
<BsLightbulb
size={20}
/>
</label>
</div>
);
}

View File

@@ -0,0 +1,53 @@
import { monosubstitutionLinks } from "@/util/LinksUtil";
import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react";
import { Link } from "@tanstack/react-router";
import clsx from "clsx";
import { IoMdArrowDropdown } from "react-icons/io";
export default function MonoLinks(){
return (
<Popover>
<PopoverButton
className={clsx(
"navBarLink outline-none",
"peer flex flex-row items-center justify-center"
)}
>
Mono-Substitution
<IoMdArrowDropdown
className="mt-1"
size={22}
/>
</PopoverButton>
<PopoverPanel
anchor={{to: "top"}}
className={clsx(
"absolute z-50 w-(--button-width) rounded-lg py-1",
"flex flex-col items-start justify-center",
"bg-gray-600 dark:bg-neutral-700",
"shadow-md shadow-gray-950"
)}
>
<Link
className="w-full px-4 py-1 text-start"
to="/monosubstitution"
>
Overview
</Link>
<hr className="bg-neutral-500 h-0.5 my-1 w-full"/>
{
monosubstitutionLinks.map((link) => (
<Link
key={link.to}
className="w-full px-4 py-1 text-start"
to={link.to}
>
{link.label}
</Link>
))
}
</PopoverPanel>
</Popover>
);
}

View File

@@ -0,0 +1,69 @@
import cipherStreamIcon from "@/assets/cipherStreamIcon.svg";
import { PopoverGroup } from "@headlessui/react";
import { Link } from "@tanstack/react-router";
import clsx from "clsx";
import { BsList } from "react-icons/bs";
import CombinationLinks from "./CombinationLinks";
import DarkModeToggle from "./DarkModeToggle";
import MonoLinks from "./MonoLinks";
import PolyLinks from "./PolyLinks";
import TutorialLink from "./TutorialLink";
export default function NavBar(){
return (
<>
<nav
className={clsx(
"border-b-2 z-40",
"bg-gray-700 border-gray-600 text-white",
"dark:bg-zinc-900 dark:border-neutral-850"
)}
>
<div
className="navContents"
>
<Link
to="/"
className="flex items-center space-x-3 rtl:space-x-reverse"
>
<img
src={cipherStreamIcon}
alt="Cipher Stream Icon"
width={30}
height={30}
fetchPriority="high"
/>
<span
className="self-center text-2xl font-semibold whitespace-nowrap"
>
Cipher Stream
</span>
</Link>
<div
className="peer md:hidden text-3xl"
>
<BsList/>
</div>
<div
className={clsx(
"relative top-0 left-0 flex flex-row items-center rounded-lg gap-x-4",
"bg-gray-700 dark:bg-zinc-900"
)}
>
<PopoverGroup
className="flex flex-row items-center justify-center gap-x-4"
>
<MonoLinks/>
<PolyLinks/>
<CombinationLinks/>
</PopoverGroup>
<TutorialLink/>
<DarkModeToggle/>
</div>
</div>
<span className="bg-white"/>
</nav>
</>
);
}

View File

@@ -0,0 +1,53 @@
import { polysubstitutionLinks } from "@/util/LinksUtil";
import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react";
import { Link } from "@tanstack/react-router";
import clsx from "clsx";
import { IoMdArrowDropdown } from "react-icons/io";
export default function PolyLinks(){
return (
<Popover>
<PopoverButton
className={clsx(
"navBarLink outline-none",
"peer flex flex-row items-center justify-center"
)}
>
Poly-Substitution
<IoMdArrowDropdown
className="mt-1"
size={22}
/>
</PopoverButton>
<PopoverPanel
anchor={{to: "top"}}
className={clsx(
"absolute z-50 w-(--button-width) rounded-lg py-1",
"flex flex-col items-start justify-center",
"bg-gray-600 dark:bg-neutral-700",
"shadow-md shadow-gray-950"
)}
>
<Link
className="w-full px-4 py-1 text-start"
to="/polysubstitution"
>
Overview
</Link>
<hr className="bg-neutral-500 h-0.5 my-1 w-full"/>
{
polysubstitutionLinks.map((link) => (
<Link
key={link.to}
className="w-full px-4 py-1 text-start"
to={link.to}
>
{link.label}
</Link>
))
}
</PopoverPanel>
</Popover>
);
}

View File

@@ -0,0 +1,30 @@
import { useTheme } from "@/providers/ThemeProvider";
import { Link } from "@tanstack/react-router";
import { BsQuestion } from "react-icons/bs";
import { Tooltip } from "react-tooltip";
export default function TutorialLink(){
const { theme } = useTheme();
return (
<>
<Link
id="tutorialLink"
to="/tutorial"
aria-label="Learn how to use Cipher Stream"
>
<BsQuestion
size={32}
/>
</Link>
<Tooltip
anchorSelect="#tutorialLink"
place="bottom-end"
variant={theme === "dark" ? "light" : "dark"}
>
Learn how to use Cipher Stream
</Tooltip>
</>
);
}

View File

@@ -0,0 +1,26 @@
import { useState } from "react";
import EncodingDecodingButton from "../button/EncodingDecodingButton";
export default function EncodingTutorial(){
const [ encoding, setEncoding ] = useState(true);
return (
<div
className="flex flex-col items-center justify-center"
>
<h3 className="text-center text-2xl">Encoding/Decoding Button</h3>
<p>
Click this button to toggle between the input being encoded or decoded.
</p>
<div
className="mt-4">
<EncodingDecodingButton
encoding={encoding}
setEncoding={setEncoding}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,25 @@
import { useState } from "react";
import InputMessage from "../input/InputMessage";
export default function InputTutorial(){
const [ inputValue, setInputValue ] = useState("");
return (
<div
className="flex flex-col items-center justify-center"
>
<h3 className="text-center text-2xl">Input</h3>
<p>
Enter text here to be encoded or decoded, depending on the Coding Button selection.
</p>
<div className="mt-4">
<InputMessage
value={inputValue}
onChange={setInputValue}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,25 @@
import { useState } from "react";
import KeywordInput from "../input/KeywordInput";
export default function KeywordTutorial(){
const [ keyword, setKeyword ] = useState("");
return (
<div
className="flex flex-col items-center justify-center"
>
<h3 className="text-center text-2xl">Keyword</h3>
<p>
Enter a keyword used in the encryption.
</p>
<div className="mt-4">
<KeywordInput
value={keyword}
onChange={setKeyword}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,26 @@
import { useState } from "react";
import NumberSelector from "../input/NumberSelector";
export default function NumberSelectorTutorial(){
const [ value, setValue ] = useState(0);
return (
<div
className="flex flex-col items-center justify-center"
>
<h3 className="text-center text-2xl">Number Selector</h3>
<p>
Click the up and down arrows to select a number as a key.
</p>
<NumberSelector
label=""
value={value}
onChange={setValue}
minValue={0}
maxValue={100}
/>
</div>
);
}

View File

@@ -0,0 +1,25 @@
import { useState } from "react";
import OutputMessage from "../input/OutputMessage";
export default function OutputTutorial(){
const [ outputValue, setOutputValue ] = useState("");
return (
<div
className="flex flex-col items-center justify-center"
>
<h3 className="text-center text-2xl">Output</h3>
<p>
This is where the result of the encoding or decoding of the message will appear.
</p>
<div className="mt-4">
<OutputMessage
value={outputValue}
onChange={setOutputValue}
/>
</div>
</div>
);
}

View File

@@ -0,0 +1,22 @@
import { PrimarySwitch } from "mattrixwv-components";
export default function SwitchTutorial(){
return (
<div
className="flex flex-col justify-center items-center"
>
<h3 className="text-center text-2xl">Preserve Element Switch</h3>
<p>
These switches indicate what types of elements in the inputs message will be preserved through the coding process.
<br/>
They are normally listed as Capitals, Symbols (punctuation and other special characters), and Whitespace.
<br/>
Remember: The more elements you leave in the cipher text the easier it will be to crack!
</p>
<div className="flex flex-row items-center justify-center mt-4">
<PrimarySwitch defaultChecked={true} size="md"><div className="pl-2">Preserve Element</div></PrimarySwitch>
</div>
</div>
);
}

View File

@@ -0,0 +1,40 @@
import type { CipherInfo } from "@/models/CipherInfo";
import type { ADFGVXProps } from "@/models/CombinationProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetADFGVXInfo(){
return useQuery({
queryKey: [ "ADFGVX", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/adfgvx`);
return response.data as CipherInfo;
}
});
}
export function useEncodeADFGVX(){
return useMutation({
mutationKey: [ "ADFGVX", "Encode" ],
scope: { id: "ADFGVX Encode" },
mutationFn: async (props: ADFGVXProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/adfgvx/encode`, props);
return response.data as ADFGVXProps;
}
});
}
export function useDecodeADFGVX(){
return useMutation({
mutationKey: [ "ADFGVX", "Decode" ],
scope: { id: "ADFGVX Decode" },
mutationFn: async (props: ADFGVXProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/adfgvx/decode`, props);
return response.data as ADFGVXProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import type { CipherInfo } from "@/models/CipherInfo";
import type { ADFGXProps } from "@/models/CombinationProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetADFGXInfo(){
return useQuery({
queryKey: [ "ADFGX", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/adfgx`);
return response.data as CipherInfo;
}
});
}
export function useEncodeADFGX(){
return useMutation({
mutationKey: [ "ADFGX", "Encode" ],
scope: { id: "ADFGX Encode" },
mutationFn: async (props: ADFGXProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/adfgx/encode`, props);
return response.data as ADFGXProps;
}
});
}
export function useDecodeADFGX(){
return useMutation({
mutationKey: [ "ADFGX", "Decode" ],
scope: { id: "ADFGX Decode" },
mutationFn: async (props: ADFGXProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/adfgx/decode`, props);
return response.data as ADFGXProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { AffineProps } from "@/models/MonoSubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetAffineInfo(){
return useQuery({
queryKey: [ "Affine", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/affine`);
return response.data as CipherInfo;
}
});
}
export function useEncodeAffine(){
return useMutation({
mutationKey: [ "Affine", "Encode" ],
scope: { id: "Affine Encode" },
mutationFn: async (props: AffineProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/affine/encode`, props);
return response.data as AffineProps;
}
});
}
export function useDecodeAffine(){
return useMutation({
mutationKey: [ "Affine", "Decode" ],
scope: { id: "Affine Decode" },
mutationFn: async (props: AffineProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/affine/decode`, props);
return response.data as AffineProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import type { CipherInfo } from "@/models/CipherInfo";
import type { AtbashProps } from "@/models/MonoSubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetAtbashInfo(){
return useQuery({
queryKey: [ "Atbash", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/atbash`);
return response.data as CipherInfo;
}
});
}
export function useEncodeAtbash(){
return useMutation({
mutationKey: [ "Atbash", "Encode" ],
scope: { id: "Atbash Encode" },
mutationFn: async (props: AtbashProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/atbash/encode`, props);
return response.data as AtbashProps;
}
});
}
export function useDecodeAtbash(){
return useMutation({
mutationKey: [ "Atbash", "Decode" ],
scope: { id: "Atbash Decode" },
mutationFn: async (props: AtbashProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/atbash/decode`, props);
return response.data as AtbashProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import type { CipherInfo } from "@/models/CipherInfo";
import type { AutokeyProps } from "@/models/MonoSubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetAutokeyInfo(){
return useQuery({
queryKey: [ "Autokey", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/autokey`);
return response.data as CipherInfo;
}
});
}
export function useEncodeAutokey(){
return useMutation({
mutationKey: [ "Autokey", "Encode" ],
scope: { id: "Autokey Encode" },
mutationFn: async (props: AutokeyProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/autokey/encode`, props);
return response.data as AutokeyProps;
}
});
}
export function useDecodeAutokey(){
return useMutation({
mutationKey: [ "Autokey", "Decode" ],
scope: { id: "Autokey Decode" },
mutationFn: async (props: AutokeyProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/autokey/decode`, props);
return response.data as AutokeyProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { BaconianProps } from "@/models/MonoSubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetBaconianInfo(){
return useQuery({
queryKey: [ "Baconian", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/baconian`);
return response.data as CipherInfo;
}
});
}
export function useEncodeBaconian(){
return useMutation({
mutationKey: [ "Baconian", "Encode" ],
scope: { id: "Baconian Encode" },
mutationFn: async (props: BaconianProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/baconian/encode`, props);
return response.data as BaconianProps;
}
});
}
export function useDecodeBaconian(){
return useMutation({
mutationKey: [ "Baconian", "Decode" ],
scope: { id: "Baconian Decode" },
mutationFn: async (props: BaconianProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/baconian/decode`, props);
return response.data as BaconianProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { BaseXProps } from "@/models/MonoSubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetBaseXInfo(){
return useQuery({
queryKey: [ "BaseX", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/basex`);
return response.data as CipherInfo;
}
});
}
export function useEncodeBaseX(){
return useMutation({
mutationKey: [ "BaseX", "Encode" ],
scope: { id: "BaseX Encode" },
mutationFn: async (props: BaseXProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/basex/encode`, props);
return response.data as BaseXProps;
}
});
}
export function useDecodeBaseX(){
return useMutation({
mutationKey: [ "BaseX", "Decode" ],
scope: { id: "BaseX Decode" },
mutationFn: async (props: BaseXProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/basex/decode`, props);
return response.data as BaseXProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { BeaufortProps } from "@/models/MonoSubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetBeaufortInfo(){
return useQuery({
queryKey: [ "Beaufort", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/beaufort`);
return response.data as CipherInfo;
}
});
}
export function useEncodeBeaufort(){
return useMutation({
mutationKey: [ "Beaufort", "Encode" ],
scope: { id: "Beaufort Encode" },
mutationFn: async (props: BeaufortProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/beaufort/encode`, props);
return response.data as BeaufortProps;
}
});
}
export function useDecodeBeaufort(){
return useMutation({
mutationKey: [ "Beaufort", "Decode" ],
scope: { id: "Beaufort Decode" },
mutationFn: async (props: BeaufortProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/beaufort/decode`, props);
return response.data as BeaufortProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { CaesarProps } from "@/models/MonoSubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetCaesarInfo(){
return useQuery({
queryKey: [ "Caesar", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/caesar`);
return response.data as CipherInfo;
}
});
}
export function useEncodeCaesar(){
return useMutation({
mutationKey: [ "Caesar", "Encode" ],
scope: { id: "Caesar Encode" },
mutationFn: async (props: CaesarProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/caesar/encode`, props);
return response.data as CaesarProps;
}
});
}
export function useDecodeCaesar(){
return useMutation({
mutationKey: [ "Caesar", "Decode" ],
scope: { id: "Caesar Decode" },
mutationFn: async (props: CaesarProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/caesar/decode`, props);
return response.data as CaesarProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { OneTimePadProps } from "@/models/MonoSubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetOneTimePadInfo(){
return useQuery({
queryKey: [ "OneTimePad", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/oneTimePad`);
return response.data as CipherInfo;
}
});
}
export function useEncodeOneTimePad(){
return useMutation({
mutationKey: [ "OneTimePad", "Encode" ],
scope: { id: "OneTimePad Encode" },
mutationFn: async (props: OneTimePadProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/oneTimePad/encode`, props);
return response.data as OneTimePadProps;
}
});
}
export function useDecodeOneTimePad(){
return useMutation({
mutationKey: [ "OneTimePad", "Decode" ],
scope: { id: "OneTimePad Decode" },
mutationFn: async (props: OneTimePadProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/oneTimePad/decode`, props);
return response.data as OneTimePadProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { PortaProps } from "@/models/MonoSubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetPortaInfo(){
return useQuery({
queryKey: [ "Porta", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/porta`);
return response.data as CipherInfo;
}
});
}
export function useEncodePorta(){
return useMutation({
mutationKey: [ "Porta", "Encode" ],
scope: { id: "Porta Encode" },
mutationFn: async (props: PortaProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/porta/encode`, props);
return response.data as PortaProps;
}
});
}
export function useDecodePorta(){
return useMutation({
mutationKey: [ "Porta", "Decode" ],
scope: { id: "Porta Decode" },
mutationFn: async (props: PortaProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/porta/decode`, props);
return response.data as PortaProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { SubstitutionProps } from "@/models/MonoSubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetSubstitutionInfo(){
return useQuery({
queryKey: [ "Substitution", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/substitution`);
return response.data as CipherInfo;
}
});
}
export function useEncodeSubstitution(){
return useMutation({
mutationKey: [ "Substitution", "Encode" ],
scope: { id: "Substitution Encode" },
mutationFn: async (props: SubstitutionProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/substitution/encode`, props);
return response.data as SubstitutionProps;
}
});
}
export function useDecodeSubstitution(){
return useMutation({
mutationKey: [ "Substitution", "Decode" ],
scope: { id: "Substitution Decode" },
mutationFn: async (props: SubstitutionProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/substitution/decode`, props);
return response.data as SubstitutionProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { VigenereProps } from "@/models/MonoSubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetVigenereInfo(){
return useQuery({
queryKey: [ "Vigenere", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/vigenere`);
return response.data as CipherInfo;
}
});
}
export function useEncodeVigenere(){
return useMutation({
mutationKey: [ "Vigenere", "Encode" ],
scope: { id: "Vigenere Encode" },
mutationFn: async (props: VigenereProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/vigenere/encode`, props);
return response.data as VigenereProps;
}
});
}
export function useDecodeVigenere(){
return useMutation({
mutationKey: [ "Vigenere", "Decode" ],
scope: { id: "Vigenere Decode" },
mutationFn: async (props: VigenereProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/vigenere/decode`, props);
return response.data as VigenereProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { BifidProps } from "@/models/PolySubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetBifidInfo(){
return useQuery({
queryKey: [ "Bifid", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/bifid`);
return response.data as CipherInfo;
}
});
}
export function useEncodeBifid(){
return useMutation({
mutationKey: [ "Bifid", "Encode" ],
scope: { id: "Bifid Encode" },
mutationFn: async (props: BifidProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/bifid/encode`, props);
return response.data as BifidProps;
}
});
}
export function useDecodeBifid(){
return useMutation({
mutationKey: [ "Bifid", "Decode" ],
scope: { id: "Bifid Decode" },
mutationFn: async (props: BifidProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/bifid/decode`, props);
return response.data as BifidProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { ColumnarProps } from "@/models/PolySubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetColumnarInfo(){
return useQuery({
queryKey: [ "Columnar", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/columnar`);
return response.data as CipherInfo;
}
});
}
export function useEncodeColumnar(){
return useMutation({
mutationKey: [ "Columnar", "Encode" ],
scope: { id: "Columnar Encode" },
mutationFn: async (props: ColumnarProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/columnar/encode`, props);
return response.data as ColumnarProps;
}
});
}
export function useDecodeColumnar(){
return useMutation({
mutationKey: [ "Columnar", "Decode" ],
scope: { id: "Columnar Decode" },
mutationFn: async (props: ColumnarProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/columnar/decode`, props);
return response.data as ColumnarProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { HillProps } from "@/models/PolySubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetHillInfo(){
return useQuery({
queryKey: [ "Hill", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/hill`);
return response.data as CipherInfo;
}
});
}
export function useEncodeHill(){
return useMutation({
mutationKey: [ "Hill", "Encode" ],
scope: { id: "Hill Encode" },
mutationFn: async (props: HillProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/hill/encode`, props);
return response.data as HillProps;
}
});
}
export function useDecodeHill(){
return useMutation({
mutationKey: [ "Hill", "Decode" ],
scope: { id: "Hill Decode" },
mutationFn: async (props: HillProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/hill/decode`, props);
return response.data as HillProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { MorseProps } from "@/models/PolySubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetMorseInfo(){
return useQuery({
queryKey: [ "Morse", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/morse`);
return response.data as CipherInfo;
}
});
}
export function useEncodeMorse(){
return useMutation({
mutationKey: [ "Morse", "Encode" ],
scope: { id: "Morse Encode" },
mutationFn: async (props: MorseProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/morse/encode`, props);
return response.data as MorseProps;
}
});
}
export function useDecodeMorse(){
return useMutation({
mutationKey: [ "Morse", "Decode" ],
scope: { id: "Morse Decode" },
mutationFn: async (props: MorseProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/morse/decode`, props);
return response.data as MorseProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { PlayfairProps } from "@/models/PolySubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetPlayfairInfo(){
return useQuery({
queryKey: [ "Playfair", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/playfair`);
return response.data as CipherInfo;
}
});
}
export function useEncodePlayfair(){
return useMutation({
mutationKey: [ "Playfair", "Encode" ],
scope: { id: "Playfair Encode" },
mutationFn: async (props: PlayfairProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/playfair/encode`, props);
return response.data as PlayfairProps;
}
});
}
export function useDecodePlayfair(){
return useMutation({
mutationKey: [ "Playfair", "Decode" ],
scope: { id: "Playfair Decode" },
mutationFn: async (props: PlayfairProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/playfair/decode`, props);
return response.data as PlayfairProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { PolybiusProps } from "@/models/PolySubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetPolybiusInfo(){
return useQuery({
queryKey: [ "Polybius", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/polybius`);
return response.data as CipherInfo;
}
});
}
export function useEncodePolybius(){
return useMutation({
mutationKey: [ "Polybius", "Encode" ],
scope: { id: "Polybius Encode" },
mutationFn: async (props: PolybiusProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/polybius/encode`, props);
return response.data as PolybiusProps;
}
});
}
export function useDecodePolybius(){
return useMutation({
mutationKey: [ "Polybius", "Decode" ],
scope: { id: "Polybius Decode" },
mutationFn: async (props: PolybiusProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/polybius/decode`, props);
return response.data as PolybiusProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { RailFenceProps } from "@/models/PolySubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetRailFenceInfo(){
return useQuery({
queryKey: [ "RailFence", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/railFence`);
return response.data as CipherInfo;
}
});
}
export function useEncodeRailFence(){
return useMutation({
mutationKey: [ "RailFence", "Encode" ],
scope: { id: "RailFence Encode" },
mutationFn: async (props: RailFenceProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/railFence/encode`, props);
return response.data as RailFenceProps;
}
});
}
export function useDecodeRailFence(){
return useMutation({
mutationKey: [ "RailFence", "Decode" ],
scope: { id: "RailFence Decode" },
mutationFn: async (props: RailFenceProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/railFence/decode`, props);
return response.data as RailFenceProps;
}
});
}

View File

@@ -0,0 +1,40 @@
import { type CipherInfo } from "@/models/CipherInfo";
import type { TrifidProps } from "@/models/PolySubstitutionProps";
import api from "@/util/AxiosUtil";
import { useMutation, useQuery } from "@tanstack/react-query";
export function useGetTrifidInfo(){
return useQuery({
queryKey: [ "Trifid", "Info" ],
queryFn: async () => {
const response = await api.get(`${import.meta.env.VITE_API_URL}/trifid`);
return response.data as CipherInfo;
}
});
}
export function useEncodeTrifid(){
return useMutation({
mutationKey: [ "Trifid", "Encode" ],
scope: { id: "Trifid Encode" },
mutationFn: async (props: TrifidProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/trifid/encode`, props);
return response.data as TrifidProps;
}
});
}
export function useDecodeTrifid(){
return useMutation({
mutationKey: [ "Trifid", "Decode" ],
scope: { id: "Trifid Decode" },
mutationFn: async (props: TrifidProps) => {
const response = await api.post(`${import.meta.env.VITE_API_URL}/trifid/decode`, props);
return response.data as TrifidProps;
}
});
}

96
src/index.css Normal file
View File

@@ -0,0 +1,96 @@
@import "tailwindcss";
@custom-variant dark (&:where(.dark, .dark *));
@source "../node_modules/mattrixwv-components";
@theme {
--color-neutral-825: oklch(0.253 0 0);
--color-neutral-850: oklch(0.237 0 0);
}
:root.dark {
--text-color: #FFFFFFDE;
--bg-color: var(--color-neutral-825);
color-scheme: dark;
}
:root.light {
--text-color: #213547;
--bg-color: #FFFFFF;
}
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: var(--bg-color);
color: var(--text-color);
}
#root {
width: 100%;
}
a:hover{
color: var(--color-blue-300);
}
a.active {
color: var(--color-blue-400);
}
body {
place-items: center;
min-width: 320px;
min-height: 100vh;
max-width: var(--breakpoint-2xl);
margin-inline: auto;
padding-top: 90px;
padding-inline: 1rem;
text-align: center;
}
button {
cursor: pointer;
}
button:disabled {
cursor: default;
}
nav {
position: fixed;
top: 0;
left: 0;
width: 100%;
}
.navContents {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
justify-content: space-between;
max-width: var(--breakpoint-2xl);
margin-inline: auto;
padding: 1rem;
}
.navBarLink {
cursor: pointer;
}
.navBarLink:hover {
color: var(--color-blue-300);
}
.navBarLink:focus {
color: var(--color-blue-400);
}

38
src/main.tsx Normal file
View File

@@ -0,0 +1,38 @@
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { createRouter, RouterProvider } from "@tanstack/react-router";
import { ToasterProvider } from "mattrixwv-components";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import { ThemeProvider } from "./providers/components/ThemeProviderComponent.tsx";
import { routeTree } from "./routeTree.gen";
//Create a new router instance
const router = createRouter({ routeTree });
//Register the router instance for type safety
declare module "@tanstack/react-router" {
interface Register {
router: typeof router;
}
}
//Setup react-query
const queryClient = new QueryClient();
createRoot(document.getElementById('root')!).render(
<StrictMode>
<QueryClientProvider client={queryClient}>
<ThemeProvider
defaultTheme="dark"
storageKey="vite-ui-theme"
>
<ToasterProvider>
<RouterProvider router={router}/>
</ToasterProvider>
</ThemeProvider>
</QueryClientProvider>
</StrictMode>
);

6
src/models/CipherInfo.ts Normal file
View File

@@ -0,0 +1,6 @@
export interface CipherInfo{
name: string;
description: string;
explanation: string[];
facts: string[];
}

View File

@@ -0,0 +1,21 @@
export interface ADFGVXProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
keyword: string;
squareKeyword: string;
inputString: string;
outputString?: string;
}
export interface ADFGXProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
keyword: string;
squareKeyword: string;
inputString: string;
outputString?: string;
}

3
src/models/Errors.ts Normal file
View File

@@ -0,0 +1,3 @@
export interface ResponseError {
message: string;
}

View File

@@ -0,0 +1,103 @@
export interface AffineProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
key1: number;
key2: number;
inputString: string;
outputString?: string;
}
export interface AtbashProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
inputString: string;
outputString?: string;
}
export interface AutokeyProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
keyword: string;
inputString: string;
outputString?: string;
}
export interface BaconianProps {
encoding: boolean;
preserveCapitals: boolean;
inputString: string;
outputString?: string;
}
export interface BaseXProps {
encoding: boolean;
base: number;
inputString: string;
outputString?: string;
}
export interface BeaufortProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
keyword: string;
inputString: string;
outputString?: string;
}
export interface CaesarProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
shiftAmount: number;
inputString: string;
outputString?: string;
}
export interface OneTimePadProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
keyword: string;
inputString: string;
outputString?: string;
}
export interface PortaProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
keyword: string;
inputString: string;
outputString?: string;
}
export interface SubstitutionProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
keyword: string;
inputString: string;
outputString?: string;
}
export interface VigenereProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
keyword: string;
inputString: string;
outputString?: string;
}

View File

@@ -0,0 +1,76 @@
export interface BifidProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
keyword: string;
inputString: string;
outputString?: string;
}
export interface ColumnarProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
keyword: string;
inputString: string;
outputString?: string;
}
export interface HillProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
key: number[][];
inputString: string;
outputString?: string;
}
export interface MorseProps {
encoding: boolean;
inputString: string;
outputString?: string;
}
export interface PlayfairProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
keyword: string;
inputString: string;
outputString?: string;
}
export interface PolybiusProps {
encoding: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
keyword: string;
inputString: string;
outputString?: string;
}
export interface RailFenceProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
rails: number;
inputString: string;
outputString?: string;
}
export interface TrifidProps {
encoding: boolean;
preserveCapitals: boolean;
preserveWhitespace: boolean;
preserveSymbols: boolean;
keyword: string;
fill: string;
groupLength: number;
inputString: string;
outputString?: string;
}

View File

@@ -0,0 +1,34 @@
import type React from "react";
import { createContext, useContext } from "react";
export type Theme = "dark" | "light" | "system";
export type ThemeProviderProps = {
children: React.ReactNode;
defaultTheme?: Theme;
storageKey?: string;
}
type ThemeProviderState = {
theme: Theme;
setTheme: (theme: Theme) => void;
}
const initialState: ThemeProviderState = {
theme: "system",
setTheme: () => null
}
export const ThemeProviderContext = createContext<ThemeProviderState>(initialState);
export const useTheme = () => {
const context = useContext(ThemeProviderContext);
if(context === undefined){
throw new Error("useTHeme must be used within a ThemeProvider");
}
return context;
}

View File

@@ -0,0 +1,17 @@
import type { ErrorComponentProps } from "@tanstack/react-router";
export default function ErrorBoundary({
error,
info,
reset
}: ErrorComponentProps){
console.log("error", error, info, reset);
return(
<main>
Error Boundary
</main>
);
}

View File

@@ -0,0 +1,41 @@
import { useEffect, useMemo, useState } from "react";
import { ThemeProviderContext, type Theme, type ThemeProviderProps } from "../ThemeProvider";
export function ThemeProvider({
children,
defaultTheme = "system",
storageKey = "vite-ui-theme"
}: ThemeProviderProps){
const [ theme, setTheme ] = useState<Theme>(localStorage.getItem(storageKey) as Theme || defaultTheme);
useEffect(() => {
const root = window.document.documentElement;
root.classList.remove("light", "dark");
if(theme === "system"){
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
root.classList.add(systemTheme);
}
else{
root.classList.add(theme);
}
}, [ theme ]);
const currentTheme = useMemo(() => ({
theme,
setTheme: (theme: Theme) => {
localStorage.setItem(storageKey, theme);
setTheme(theme);
}
}), [ theme, storageKey ]);
return (
<ThemeProviderContext.Provider value={currentTheme}>
{children}
</ThemeProviderContext.Provider>
);
}

608
src/routeTree.gen.ts Normal file
View File

@@ -0,0 +1,608 @@
/* eslint-disable */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// This file was automatically generated by TanStack Router.
// You should NOT make any changes in this file as it will be overwritten.
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
import { Route as rootRouteImport } from './routes/__root'
import { Route as IndexRouteImport } from './routes/index'
import { Route as TutorialIndexRouteImport } from './routes/tutorial/index'
import { Route as PolysubstitutionIndexRouteImport } from './routes/polysubstitution/index'
import { Route as MonosubstitutionIndexRouteImport } from './routes/monosubstitution/index'
import { Route as CombinationIndexRouteImport } from './routes/combination/index'
import { Route as PolysubstitutionTrifidIndexRouteImport } from './routes/polysubstitution/trifid/index'
import { Route as PolysubstitutionRailfenceIndexRouteImport } from './routes/polysubstitution/railfence/index'
import { Route as PolysubstitutionPolybiusIndexRouteImport } from './routes/polysubstitution/polybius/index'
import { Route as PolysubstitutionPlayfairIndexRouteImport } from './routes/polysubstitution/playfair/index'
import { Route as PolysubstitutionMorseIndexRouteImport } from './routes/polysubstitution/morse/index'
import { Route as PolysubstitutionHillIndexRouteImport } from './routes/polysubstitution/hill/index'
import { Route as PolysubstitutionColumnarIndexRouteImport } from './routes/polysubstitution/columnar/index'
import { Route as PolysubstitutionBifidIndexRouteImport } from './routes/polysubstitution/bifid/index'
import { Route as MonosubstitutionVigenereIndexRouteImport } from './routes/monosubstitution/vigenere/index'
import { Route as MonosubstitutionSubstitutionIndexRouteImport } from './routes/monosubstitution/substitution/index'
import { Route as MonosubstitutionPortaIndexRouteImport } from './routes/monosubstitution/porta/index'
import { Route as MonosubstitutionOnetimepadIndexRouteImport } from './routes/monosubstitution/onetimepad/index'
import { Route as MonosubstitutionCaesarIndexRouteImport } from './routes/monosubstitution/caesar/index'
import { Route as MonosubstitutionBeaufortIndexRouteImport } from './routes/monosubstitution/beaufort/index'
import { Route as MonosubstitutionBasexIndexRouteImport } from './routes/monosubstitution/basex/index'
import { Route as MonosubstitutionBaconianIndexRouteImport } from './routes/monosubstitution/baconian/index'
import { Route as MonosubstitutionAutokeyIndexRouteImport } from './routes/monosubstitution/autokey/index'
import { Route as MonosubstitutionAtbashIndexRouteImport } from './routes/monosubstitution/atbash/index'
import { Route as MonosubstitutionAffineIndexRouteImport } from './routes/monosubstitution/affine/index'
import { Route as CombinationAdfgxIndexRouteImport } from './routes/combination/adfgx/index'
import { Route as CombinationAdfgvxIndexRouteImport } from './routes/combination/adfgvx/index'
const IndexRoute = IndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => rootRouteImport,
} as any)
const TutorialIndexRoute = TutorialIndexRouteImport.update({
id: '/tutorial/',
path: '/tutorial/',
getParentRoute: () => rootRouteImport,
} as any)
const PolysubstitutionIndexRoute = PolysubstitutionIndexRouteImport.update({
id: '/polysubstitution/',
path: '/polysubstitution/',
getParentRoute: () => rootRouteImport,
} as any)
const MonosubstitutionIndexRoute = MonosubstitutionIndexRouteImport.update({
id: '/monosubstitution/',
path: '/monosubstitution/',
getParentRoute: () => rootRouteImport,
} as any)
const CombinationIndexRoute = CombinationIndexRouteImport.update({
id: '/combination/',
path: '/combination/',
getParentRoute: () => rootRouteImport,
} as any)
const PolysubstitutionTrifidIndexRoute =
PolysubstitutionTrifidIndexRouteImport.update({
id: '/polysubstitution/trifid/',
path: '/polysubstitution/trifid/',
getParentRoute: () => rootRouteImport,
} as any)
const PolysubstitutionRailfenceIndexRoute =
PolysubstitutionRailfenceIndexRouteImport.update({
id: '/polysubstitution/railfence/',
path: '/polysubstitution/railfence/',
getParentRoute: () => rootRouteImport,
} as any)
const PolysubstitutionPolybiusIndexRoute =
PolysubstitutionPolybiusIndexRouteImport.update({
id: '/polysubstitution/polybius/',
path: '/polysubstitution/polybius/',
getParentRoute: () => rootRouteImport,
} as any)
const PolysubstitutionPlayfairIndexRoute =
PolysubstitutionPlayfairIndexRouteImport.update({
id: '/polysubstitution/playfair/',
path: '/polysubstitution/playfair/',
getParentRoute: () => rootRouteImport,
} as any)
const PolysubstitutionMorseIndexRoute =
PolysubstitutionMorseIndexRouteImport.update({
id: '/polysubstitution/morse/',
path: '/polysubstitution/morse/',
getParentRoute: () => rootRouteImport,
} as any)
const PolysubstitutionHillIndexRoute =
PolysubstitutionHillIndexRouteImport.update({
id: '/polysubstitution/hill/',
path: '/polysubstitution/hill/',
getParentRoute: () => rootRouteImport,
} as any)
const PolysubstitutionColumnarIndexRoute =
PolysubstitutionColumnarIndexRouteImport.update({
id: '/polysubstitution/columnar/',
path: '/polysubstitution/columnar/',
getParentRoute: () => rootRouteImport,
} as any)
const PolysubstitutionBifidIndexRoute =
PolysubstitutionBifidIndexRouteImport.update({
id: '/polysubstitution/bifid/',
path: '/polysubstitution/bifid/',
getParentRoute: () => rootRouteImport,
} as any)
const MonosubstitutionVigenereIndexRoute =
MonosubstitutionVigenereIndexRouteImport.update({
id: '/monosubstitution/vigenere/',
path: '/monosubstitution/vigenere/',
getParentRoute: () => rootRouteImport,
} as any)
const MonosubstitutionSubstitutionIndexRoute =
MonosubstitutionSubstitutionIndexRouteImport.update({
id: '/monosubstitution/substitution/',
path: '/monosubstitution/substitution/',
getParentRoute: () => rootRouteImport,
} as any)
const MonosubstitutionPortaIndexRoute =
MonosubstitutionPortaIndexRouteImport.update({
id: '/monosubstitution/porta/',
path: '/monosubstitution/porta/',
getParentRoute: () => rootRouteImport,
} as any)
const MonosubstitutionOnetimepadIndexRoute =
MonosubstitutionOnetimepadIndexRouteImport.update({
id: '/monosubstitution/onetimepad/',
path: '/monosubstitution/onetimepad/',
getParentRoute: () => rootRouteImport,
} as any)
const MonosubstitutionCaesarIndexRoute =
MonosubstitutionCaesarIndexRouteImport.update({
id: '/monosubstitution/caesar/',
path: '/monosubstitution/caesar/',
getParentRoute: () => rootRouteImport,
} as any)
const MonosubstitutionBeaufortIndexRoute =
MonosubstitutionBeaufortIndexRouteImport.update({
id: '/monosubstitution/beaufort/',
path: '/monosubstitution/beaufort/',
getParentRoute: () => rootRouteImport,
} as any)
const MonosubstitutionBasexIndexRoute =
MonosubstitutionBasexIndexRouteImport.update({
id: '/monosubstitution/basex/',
path: '/monosubstitution/basex/',
getParentRoute: () => rootRouteImport,
} as any)
const MonosubstitutionBaconianIndexRoute =
MonosubstitutionBaconianIndexRouteImport.update({
id: '/monosubstitution/baconian/',
path: '/monosubstitution/baconian/',
getParentRoute: () => rootRouteImport,
} as any)
const MonosubstitutionAutokeyIndexRoute =
MonosubstitutionAutokeyIndexRouteImport.update({
id: '/monosubstitution/autokey/',
path: '/monosubstitution/autokey/',
getParentRoute: () => rootRouteImport,
} as any)
const MonosubstitutionAtbashIndexRoute =
MonosubstitutionAtbashIndexRouteImport.update({
id: '/monosubstitution/atbash/',
path: '/monosubstitution/atbash/',
getParentRoute: () => rootRouteImport,
} as any)
const MonosubstitutionAffineIndexRoute =
MonosubstitutionAffineIndexRouteImport.update({
id: '/monosubstitution/affine/',
path: '/monosubstitution/affine/',
getParentRoute: () => rootRouteImport,
} as any)
const CombinationAdfgxIndexRoute = CombinationAdfgxIndexRouteImport.update({
id: '/combination/adfgx/',
path: '/combination/adfgx/',
getParentRoute: () => rootRouteImport,
} as any)
const CombinationAdfgvxIndexRoute = CombinationAdfgvxIndexRouteImport.update({
id: '/combination/adfgvx/',
path: '/combination/adfgvx/',
getParentRoute: () => rootRouteImport,
} as any)
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/combination': typeof CombinationIndexRoute
'/monosubstitution': typeof MonosubstitutionIndexRoute
'/polysubstitution': typeof PolysubstitutionIndexRoute
'/tutorial': typeof TutorialIndexRoute
'/combination/adfgvx': typeof CombinationAdfgvxIndexRoute
'/combination/adfgx': typeof CombinationAdfgxIndexRoute
'/monosubstitution/affine': typeof MonosubstitutionAffineIndexRoute
'/monosubstitution/atbash': typeof MonosubstitutionAtbashIndexRoute
'/monosubstitution/autokey': typeof MonosubstitutionAutokeyIndexRoute
'/monosubstitution/baconian': typeof MonosubstitutionBaconianIndexRoute
'/monosubstitution/basex': typeof MonosubstitutionBasexIndexRoute
'/monosubstitution/beaufort': typeof MonosubstitutionBeaufortIndexRoute
'/monosubstitution/caesar': typeof MonosubstitutionCaesarIndexRoute
'/monosubstitution/onetimepad': typeof MonosubstitutionOnetimepadIndexRoute
'/monosubstitution/porta': typeof MonosubstitutionPortaIndexRoute
'/monosubstitution/substitution': typeof MonosubstitutionSubstitutionIndexRoute
'/monosubstitution/vigenere': typeof MonosubstitutionVigenereIndexRoute
'/polysubstitution/bifid': typeof PolysubstitutionBifidIndexRoute
'/polysubstitution/columnar': typeof PolysubstitutionColumnarIndexRoute
'/polysubstitution/hill': typeof PolysubstitutionHillIndexRoute
'/polysubstitution/morse': typeof PolysubstitutionMorseIndexRoute
'/polysubstitution/playfair': typeof PolysubstitutionPlayfairIndexRoute
'/polysubstitution/polybius': typeof PolysubstitutionPolybiusIndexRoute
'/polysubstitution/railfence': typeof PolysubstitutionRailfenceIndexRoute
'/polysubstitution/trifid': typeof PolysubstitutionTrifidIndexRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
'/combination': typeof CombinationIndexRoute
'/monosubstitution': typeof MonosubstitutionIndexRoute
'/polysubstitution': typeof PolysubstitutionIndexRoute
'/tutorial': typeof TutorialIndexRoute
'/combination/adfgvx': typeof CombinationAdfgvxIndexRoute
'/combination/adfgx': typeof CombinationAdfgxIndexRoute
'/monosubstitution/affine': typeof MonosubstitutionAffineIndexRoute
'/monosubstitution/atbash': typeof MonosubstitutionAtbashIndexRoute
'/monosubstitution/autokey': typeof MonosubstitutionAutokeyIndexRoute
'/monosubstitution/baconian': typeof MonosubstitutionBaconianIndexRoute
'/monosubstitution/basex': typeof MonosubstitutionBasexIndexRoute
'/monosubstitution/beaufort': typeof MonosubstitutionBeaufortIndexRoute
'/monosubstitution/caesar': typeof MonosubstitutionCaesarIndexRoute
'/monosubstitution/onetimepad': typeof MonosubstitutionOnetimepadIndexRoute
'/monosubstitution/porta': typeof MonosubstitutionPortaIndexRoute
'/monosubstitution/substitution': typeof MonosubstitutionSubstitutionIndexRoute
'/monosubstitution/vigenere': typeof MonosubstitutionVigenereIndexRoute
'/polysubstitution/bifid': typeof PolysubstitutionBifidIndexRoute
'/polysubstitution/columnar': typeof PolysubstitutionColumnarIndexRoute
'/polysubstitution/hill': typeof PolysubstitutionHillIndexRoute
'/polysubstitution/morse': typeof PolysubstitutionMorseIndexRoute
'/polysubstitution/playfair': typeof PolysubstitutionPlayfairIndexRoute
'/polysubstitution/polybius': typeof PolysubstitutionPolybiusIndexRoute
'/polysubstitution/railfence': typeof PolysubstitutionRailfenceIndexRoute
'/polysubstitution/trifid': typeof PolysubstitutionTrifidIndexRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
'/combination/': typeof CombinationIndexRoute
'/monosubstitution/': typeof MonosubstitutionIndexRoute
'/polysubstitution/': typeof PolysubstitutionIndexRoute
'/tutorial/': typeof TutorialIndexRoute
'/combination/adfgvx/': typeof CombinationAdfgvxIndexRoute
'/combination/adfgx/': typeof CombinationAdfgxIndexRoute
'/monosubstitution/affine/': typeof MonosubstitutionAffineIndexRoute
'/monosubstitution/atbash/': typeof MonosubstitutionAtbashIndexRoute
'/monosubstitution/autokey/': typeof MonosubstitutionAutokeyIndexRoute
'/monosubstitution/baconian/': typeof MonosubstitutionBaconianIndexRoute
'/monosubstitution/basex/': typeof MonosubstitutionBasexIndexRoute
'/monosubstitution/beaufort/': typeof MonosubstitutionBeaufortIndexRoute
'/monosubstitution/caesar/': typeof MonosubstitutionCaesarIndexRoute
'/monosubstitution/onetimepad/': typeof MonosubstitutionOnetimepadIndexRoute
'/monosubstitution/porta/': typeof MonosubstitutionPortaIndexRoute
'/monosubstitution/substitution/': typeof MonosubstitutionSubstitutionIndexRoute
'/monosubstitution/vigenere/': typeof MonosubstitutionVigenereIndexRoute
'/polysubstitution/bifid/': typeof PolysubstitutionBifidIndexRoute
'/polysubstitution/columnar/': typeof PolysubstitutionColumnarIndexRoute
'/polysubstitution/hill/': typeof PolysubstitutionHillIndexRoute
'/polysubstitution/morse/': typeof PolysubstitutionMorseIndexRoute
'/polysubstitution/playfair/': typeof PolysubstitutionPlayfairIndexRoute
'/polysubstitution/polybius/': typeof PolysubstitutionPolybiusIndexRoute
'/polysubstitution/railfence/': typeof PolysubstitutionRailfenceIndexRoute
'/polysubstitution/trifid/': typeof PolysubstitutionTrifidIndexRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths:
| '/'
| '/combination'
| '/monosubstitution'
| '/polysubstitution'
| '/tutorial'
| '/combination/adfgvx'
| '/combination/adfgx'
| '/monosubstitution/affine'
| '/monosubstitution/atbash'
| '/monosubstitution/autokey'
| '/monosubstitution/baconian'
| '/monosubstitution/basex'
| '/monosubstitution/beaufort'
| '/monosubstitution/caesar'
| '/monosubstitution/onetimepad'
| '/monosubstitution/porta'
| '/monosubstitution/substitution'
| '/monosubstitution/vigenere'
| '/polysubstitution/bifid'
| '/polysubstitution/columnar'
| '/polysubstitution/hill'
| '/polysubstitution/morse'
| '/polysubstitution/playfair'
| '/polysubstitution/polybius'
| '/polysubstitution/railfence'
| '/polysubstitution/trifid'
fileRoutesByTo: FileRoutesByTo
to:
| '/'
| '/combination'
| '/monosubstitution'
| '/polysubstitution'
| '/tutorial'
| '/combination/adfgvx'
| '/combination/adfgx'
| '/monosubstitution/affine'
| '/monosubstitution/atbash'
| '/monosubstitution/autokey'
| '/monosubstitution/baconian'
| '/monosubstitution/basex'
| '/monosubstitution/beaufort'
| '/monosubstitution/caesar'
| '/monosubstitution/onetimepad'
| '/monosubstitution/porta'
| '/monosubstitution/substitution'
| '/monosubstitution/vigenere'
| '/polysubstitution/bifid'
| '/polysubstitution/columnar'
| '/polysubstitution/hill'
| '/polysubstitution/morse'
| '/polysubstitution/playfair'
| '/polysubstitution/polybius'
| '/polysubstitution/railfence'
| '/polysubstitution/trifid'
id:
| '__root__'
| '/'
| '/combination/'
| '/monosubstitution/'
| '/polysubstitution/'
| '/tutorial/'
| '/combination/adfgvx/'
| '/combination/adfgx/'
| '/monosubstitution/affine/'
| '/monosubstitution/atbash/'
| '/monosubstitution/autokey/'
| '/monosubstitution/baconian/'
| '/monosubstitution/basex/'
| '/monosubstitution/beaufort/'
| '/monosubstitution/caesar/'
| '/monosubstitution/onetimepad/'
| '/monosubstitution/porta/'
| '/monosubstitution/substitution/'
| '/monosubstitution/vigenere/'
| '/polysubstitution/bifid/'
| '/polysubstitution/columnar/'
| '/polysubstitution/hill/'
| '/polysubstitution/morse/'
| '/polysubstitution/playfair/'
| '/polysubstitution/polybius/'
| '/polysubstitution/railfence/'
| '/polysubstitution/trifid/'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
CombinationIndexRoute: typeof CombinationIndexRoute
MonosubstitutionIndexRoute: typeof MonosubstitutionIndexRoute
PolysubstitutionIndexRoute: typeof PolysubstitutionIndexRoute
TutorialIndexRoute: typeof TutorialIndexRoute
CombinationAdfgvxIndexRoute: typeof CombinationAdfgvxIndexRoute
CombinationAdfgxIndexRoute: typeof CombinationAdfgxIndexRoute
MonosubstitutionAffineIndexRoute: typeof MonosubstitutionAffineIndexRoute
MonosubstitutionAtbashIndexRoute: typeof MonosubstitutionAtbashIndexRoute
MonosubstitutionAutokeyIndexRoute: typeof MonosubstitutionAutokeyIndexRoute
MonosubstitutionBaconianIndexRoute: typeof MonosubstitutionBaconianIndexRoute
MonosubstitutionBasexIndexRoute: typeof MonosubstitutionBasexIndexRoute
MonosubstitutionBeaufortIndexRoute: typeof MonosubstitutionBeaufortIndexRoute
MonosubstitutionCaesarIndexRoute: typeof MonosubstitutionCaesarIndexRoute
MonosubstitutionOnetimepadIndexRoute: typeof MonosubstitutionOnetimepadIndexRoute
MonosubstitutionPortaIndexRoute: typeof MonosubstitutionPortaIndexRoute
MonosubstitutionSubstitutionIndexRoute: typeof MonosubstitutionSubstitutionIndexRoute
MonosubstitutionVigenereIndexRoute: typeof MonosubstitutionVigenereIndexRoute
PolysubstitutionBifidIndexRoute: typeof PolysubstitutionBifidIndexRoute
PolysubstitutionColumnarIndexRoute: typeof PolysubstitutionColumnarIndexRoute
PolysubstitutionHillIndexRoute: typeof PolysubstitutionHillIndexRoute
PolysubstitutionMorseIndexRoute: typeof PolysubstitutionMorseIndexRoute
PolysubstitutionPlayfairIndexRoute: typeof PolysubstitutionPlayfairIndexRoute
PolysubstitutionPolybiusIndexRoute: typeof PolysubstitutionPolybiusIndexRoute
PolysubstitutionRailfenceIndexRoute: typeof PolysubstitutionRailfenceIndexRoute
PolysubstitutionTrifidIndexRoute: typeof PolysubstitutionTrifidIndexRoute
}
declare module '@tanstack/react-router' {
interface FileRoutesByPath {
'/': {
id: '/'
path: '/'
fullPath: '/'
preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport
}
'/tutorial/': {
id: '/tutorial/'
path: '/tutorial'
fullPath: '/tutorial'
preLoaderRoute: typeof TutorialIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/polysubstitution/': {
id: '/polysubstitution/'
path: '/polysubstitution'
fullPath: '/polysubstitution'
preLoaderRoute: typeof PolysubstitutionIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/monosubstitution/': {
id: '/monosubstitution/'
path: '/monosubstitution'
fullPath: '/monosubstitution'
preLoaderRoute: typeof MonosubstitutionIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/combination/': {
id: '/combination/'
path: '/combination'
fullPath: '/combination'
preLoaderRoute: typeof CombinationIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/polysubstitution/trifid/': {
id: '/polysubstitution/trifid/'
path: '/polysubstitution/trifid'
fullPath: '/polysubstitution/trifid'
preLoaderRoute: typeof PolysubstitutionTrifidIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/polysubstitution/railfence/': {
id: '/polysubstitution/railfence/'
path: '/polysubstitution/railfence'
fullPath: '/polysubstitution/railfence'
preLoaderRoute: typeof PolysubstitutionRailfenceIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/polysubstitution/polybius/': {
id: '/polysubstitution/polybius/'
path: '/polysubstitution/polybius'
fullPath: '/polysubstitution/polybius'
preLoaderRoute: typeof PolysubstitutionPolybiusIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/polysubstitution/playfair/': {
id: '/polysubstitution/playfair/'
path: '/polysubstitution/playfair'
fullPath: '/polysubstitution/playfair'
preLoaderRoute: typeof PolysubstitutionPlayfairIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/polysubstitution/morse/': {
id: '/polysubstitution/morse/'
path: '/polysubstitution/morse'
fullPath: '/polysubstitution/morse'
preLoaderRoute: typeof PolysubstitutionMorseIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/polysubstitution/hill/': {
id: '/polysubstitution/hill/'
path: '/polysubstitution/hill'
fullPath: '/polysubstitution/hill'
preLoaderRoute: typeof PolysubstitutionHillIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/polysubstitution/columnar/': {
id: '/polysubstitution/columnar/'
path: '/polysubstitution/columnar'
fullPath: '/polysubstitution/columnar'
preLoaderRoute: typeof PolysubstitutionColumnarIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/polysubstitution/bifid/': {
id: '/polysubstitution/bifid/'
path: '/polysubstitution/bifid'
fullPath: '/polysubstitution/bifid'
preLoaderRoute: typeof PolysubstitutionBifidIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/monosubstitution/vigenere/': {
id: '/monosubstitution/vigenere/'
path: '/monosubstitution/vigenere'
fullPath: '/monosubstitution/vigenere'
preLoaderRoute: typeof MonosubstitutionVigenereIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/monosubstitution/substitution/': {
id: '/monosubstitution/substitution/'
path: '/monosubstitution/substitution'
fullPath: '/monosubstitution/substitution'
preLoaderRoute: typeof MonosubstitutionSubstitutionIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/monosubstitution/porta/': {
id: '/monosubstitution/porta/'
path: '/monosubstitution/porta'
fullPath: '/monosubstitution/porta'
preLoaderRoute: typeof MonosubstitutionPortaIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/monosubstitution/onetimepad/': {
id: '/monosubstitution/onetimepad/'
path: '/monosubstitution/onetimepad'
fullPath: '/monosubstitution/onetimepad'
preLoaderRoute: typeof MonosubstitutionOnetimepadIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/monosubstitution/caesar/': {
id: '/monosubstitution/caesar/'
path: '/monosubstitution/caesar'
fullPath: '/monosubstitution/caesar'
preLoaderRoute: typeof MonosubstitutionCaesarIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/monosubstitution/beaufort/': {
id: '/monosubstitution/beaufort/'
path: '/monosubstitution/beaufort'
fullPath: '/monosubstitution/beaufort'
preLoaderRoute: typeof MonosubstitutionBeaufortIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/monosubstitution/basex/': {
id: '/monosubstitution/basex/'
path: '/monosubstitution/basex'
fullPath: '/monosubstitution/basex'
preLoaderRoute: typeof MonosubstitutionBasexIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/monosubstitution/baconian/': {
id: '/monosubstitution/baconian/'
path: '/monosubstitution/baconian'
fullPath: '/monosubstitution/baconian'
preLoaderRoute: typeof MonosubstitutionBaconianIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/monosubstitution/autokey/': {
id: '/monosubstitution/autokey/'
path: '/monosubstitution/autokey'
fullPath: '/monosubstitution/autokey'
preLoaderRoute: typeof MonosubstitutionAutokeyIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/monosubstitution/atbash/': {
id: '/monosubstitution/atbash/'
path: '/monosubstitution/atbash'
fullPath: '/monosubstitution/atbash'
preLoaderRoute: typeof MonosubstitutionAtbashIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/monosubstitution/affine/': {
id: '/monosubstitution/affine/'
path: '/monosubstitution/affine'
fullPath: '/monosubstitution/affine'
preLoaderRoute: typeof MonosubstitutionAffineIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/combination/adfgx/': {
id: '/combination/adfgx/'
path: '/combination/adfgx'
fullPath: '/combination/adfgx'
preLoaderRoute: typeof CombinationAdfgxIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/combination/adfgvx/': {
id: '/combination/adfgvx/'
path: '/combination/adfgvx'
fullPath: '/combination/adfgvx'
preLoaderRoute: typeof CombinationAdfgvxIndexRouteImport
parentRoute: typeof rootRouteImport
}
}
}
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
CombinationIndexRoute: CombinationIndexRoute,
MonosubstitutionIndexRoute: MonosubstitutionIndexRoute,
PolysubstitutionIndexRoute: PolysubstitutionIndexRoute,
TutorialIndexRoute: TutorialIndexRoute,
CombinationAdfgvxIndexRoute: CombinationAdfgvxIndexRoute,
CombinationAdfgxIndexRoute: CombinationAdfgxIndexRoute,
MonosubstitutionAffineIndexRoute: MonosubstitutionAffineIndexRoute,
MonosubstitutionAtbashIndexRoute: MonosubstitutionAtbashIndexRoute,
MonosubstitutionAutokeyIndexRoute: MonosubstitutionAutokeyIndexRoute,
MonosubstitutionBaconianIndexRoute: MonosubstitutionBaconianIndexRoute,
MonosubstitutionBasexIndexRoute: MonosubstitutionBasexIndexRoute,
MonosubstitutionBeaufortIndexRoute: MonosubstitutionBeaufortIndexRoute,
MonosubstitutionCaesarIndexRoute: MonosubstitutionCaesarIndexRoute,
MonosubstitutionOnetimepadIndexRoute: MonosubstitutionOnetimepadIndexRoute,
MonosubstitutionPortaIndexRoute: MonosubstitutionPortaIndexRoute,
MonosubstitutionSubstitutionIndexRoute:
MonosubstitutionSubstitutionIndexRoute,
MonosubstitutionVigenereIndexRoute: MonosubstitutionVigenereIndexRoute,
PolysubstitutionBifidIndexRoute: PolysubstitutionBifidIndexRoute,
PolysubstitutionColumnarIndexRoute: PolysubstitutionColumnarIndexRoute,
PolysubstitutionHillIndexRoute: PolysubstitutionHillIndexRoute,
PolysubstitutionMorseIndexRoute: PolysubstitutionMorseIndexRoute,
PolysubstitutionPlayfairIndexRoute: PolysubstitutionPlayfairIndexRoute,
PolysubstitutionPolybiusIndexRoute: PolysubstitutionPolybiusIndexRoute,
PolysubstitutionRailfenceIndexRoute: PolysubstitutionRailfenceIndexRoute,
PolysubstitutionTrifidIndexRoute: PolysubstitutionTrifidIndexRoute,
}
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)
._addFileTypes<FileRouteTypes>()

16
src/routes/__root.tsx Normal file
View File

@@ -0,0 +1,16 @@
import NavBar from "@/components/nav/NavBar";
import ErrorBoundary from "@/providers/components/ErrorBoundary";
import { createRootRoute, Outlet } from "@tanstack/react-router";
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
export const Route = createRootRoute({
component: () => (
<>
<NavBar/>
<Outlet/>
<TanStackRouterDevtools/>
</>
),
errorComponent: ErrorBoundary
});

View File

@@ -0,0 +1,25 @@
import CipherLoader from '@/components/ciphers/CipherLoader';
import ADFGVXInputs from '@/components/ciphers/combination/adfgvx/ADFGVXInputs';
import { useGetADFGVXInfo } from '@/hooks/combination/ADFGVXHooks';
import { createFileRoute } from '@tanstack/react-router';
export const Route = createFileRoute('/combination/adfgvx/')({
component: ADFGVXPage
});
function ADFGVXPage(){
const adfgvxInfoQuery = useGetADFGVXInfo();
return (
<main
className="flex flex-col items-center justify-center"
>
<CipherLoader infoQuery={adfgvxInfoQuery}>
<ADFGVXInputs/>
</CipherLoader>
</main>
);
}

View File

@@ -0,0 +1,25 @@
import CipherLoader from '@/components/ciphers/CipherLoader';
import ADFGXInputs from '@/components/ciphers/combination/adfgx/ADFGXInputs';
import { useGetADFGXInfo } from '@/hooks/combination/ADFGXHooks';
import { createFileRoute } from '@tanstack/react-router';
export const Route = createFileRoute('/combination/adfgx/')({
component: ADFGXPage
});
function ADFGXPage(){
const adfgxInfoQuery = useGetADFGXInfo();
return (
<main
className="flex flex-col items-center justify-center"
>
<CipherLoader infoQuery={adfgxInfoQuery}>
<ADFGXInputs/>
</CipherLoader>
</main>
);
}

View File

@@ -0,0 +1,51 @@
import { combinationLinks } from '@/util/LinksUtil';
import { createFileRoute, Link } from '@tanstack/react-router';
export const Route = createFileRoute('/combination/')({
component: CombinationPage
});
function CombinationPage(){
return (
<main
className="flex flex-col items-center"
>
<h1
className="font-bold text-4xl my-8"
>
Combination Ciphers
</h1>
<p
className="text-center"
>
Combination ciphers encrypt text by combining two or more ciphers.
These ciphers are the most secure offered on the site because multiple layers of encryption must be broken in order to decrypt the text through brute force methods.
</p>
<div
className="mt-8"
>
<ul
className="grid grid-cols-2 gap-8"
>
{
combinationLinks.map(cipher => (
<li
key={cipher.label}
className="text-center"
>
<Link
className="cursor-pointer text-lg"
to={cipher.to}
>
{cipher.label}
</Link>
</li>
))
}
</ul>
</div>
</main>
);
}

56
src/routes/index.tsx Normal file
View File

@@ -0,0 +1,56 @@
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/")({
component: HomePage,
//TODO: Figure out how to get this metadata appearing in the app correctly
/*
head: () => ({
meta: [
{
title: "Cipher Stream",
name: "Cipher Stream Web Interface",
content: "Cipher Stream"
}
]
})
*/
/*
keywords: [
"ciphers",
"cipherstream",
"cipher stream",
"ciphers",
"encryption",
"decryption",
"Mattrixwv"
],
robots: "all"
*/
});
function HomePage(){
return (
<main>
<h1
className="text-4xl font-bold text-center"
>
Cipher Stream
</h1>
<p
className="text-center text-xl"
>
Dive into the fascinating realm of cryptography!
</p>
<div
className="text-center mt-4"
>
<p>
Encrypt your messages with classic and historical ciphers. Perfect for learning and entertainment. Our platform provides a way to delve into the historical origins of encryption.
While these ciphers do not provide security in a digital world, they do offer valuable insights into the history and evolution of cryptography.
</p>
</div>
</main>
);
}

View File

@@ -0,0 +1,33 @@
import CipherLoader from '@/components/ciphers/CipherLoader';
import AffineInputs from '@/components/ciphers/monosubstitution/affine/AffineInputs';
import { useGetAffineInfo } from '@/hooks/monosubstitution/AffineHooks';
import { createFileRoute } from '@tanstack/react-router';
/*
title: "Affine",
description: "",
keywords: [
"Affine"
]
*/
export const Route = createFileRoute('/monosubstitution/affine/')({
component: AffinePage
});
function AffinePage(){
const affineInfoQuery = useGetAffineInfo();
return (
<main
className="flex flex-col items-center justify-center"
>
<CipherLoader infoQuery={affineInfoQuery}>
<AffineInputs/>
</CipherLoader>
</main>
);
}

View File

@@ -0,0 +1,33 @@
import CipherLoader from '@/components/ciphers/CipherLoader';
import AtbashInputs from '@/components/ciphers/monosubstitution/atbash/AtbashInputs';
import { useGetAtbashInfo } from '@/hooks/monosubstitution/AtbashHooks';
import { createFileRoute } from '@tanstack/react-router';
/*
title: "Atbash",
description: "",
keywords: [
"Atbash"
]
*/
export const Route = createFileRoute('/monosubstitution/atbash/')({
component: AtbashPage
});
function AtbashPage(){
const atbashInfoQuery = useGetAtbashInfo();
return (
<main
className="flex flex-col items-center justify-center"
>
<CipherLoader infoQuery={atbashInfoQuery}>
<AtbashInputs/>
</CipherLoader>
</main>
);
}

View File

@@ -0,0 +1,35 @@
import CipherLoader from '@/components/ciphers/CipherLoader';
import AutokeyInputs from '@/components/ciphers/monosubstitution/autokey/AutokeyInputs';
import { useGetAutokeyInfo } from '@/hooks/monosubstitution/AutokeyHooks';
import { createFileRoute } from '@tanstack/react-router';
/*
{
title: "Autokey",
description: "",
keywords: [
"Autokey"
]
}
*/
export const Route = createFileRoute('/monosubstitution/autokey/')({
component: AutokeyPage
});
function AutokeyPage(){
const autokeyInfoQuery = useGetAutokeyInfo();
return (
<main
className="flex flex-col items-center justify-center"
>
<CipherLoader infoQuery={autokeyInfoQuery}>
<AutokeyInputs/>
</CipherLoader>
</main>
);
}

View File

@@ -0,0 +1,34 @@
import CipherLoader from '@/components/ciphers/CipherLoader';
import BaconianInputs from '@/components/ciphers/monosubstitution/baconian/BaconianInputs';
import { useGetBaconianInfo } from '@/hooks/monosubstitution/BaconianHooks';
import { createFileRoute } from '@tanstack/react-router';
/*
{
title: "Baconian",
description: "",
keywords: [
"Baconian"
]
}
*/
export const Route = createFileRoute('/monosubstitution/baconian/')({
component: BaconianPage
});
function BaconianPage(){
const baconianInfoQuery = useGetBaconianInfo();
return (
<main
className="flex flex-col items-center justify-center"
>
<CipherLoader infoQuery={baconianInfoQuery}>
<BaconianInputs/>
</CipherLoader>
</main>
);
}

View File

@@ -0,0 +1,40 @@
import CipherLoader from '@/components/ciphers/CipherLoader';
import BaseXInputs from '@/components/ciphers/monosubstitution/basex/BaseXInputs';
import { useGetBaseXInfo } from '@/hooks/monosubstitution/BaseXHooks';
import { createFileRoute } from '@tanstack/react-router';
/*
{
title: "Base X",
description: "",
keywords: [
"Base X", "base x", "BaseX", "basex",
"base 2", "base2", "binary",
"base 8", "base8", "octal",
"base 12", "base12",
"base 16", "base16", "hexadecimal"
]
}
*/
export const Route = createFileRoute('/monosubstitution/basex/')({
component: BaseXPage
});
function BaseXPage(){
const baseXInfoQuery = useGetBaseXInfo();
return (
<main
className="flex flex-col items-center justify-center"
>
<CipherLoader infoQuery={baseXInfoQuery}>
<BaseXInputs/>
</CipherLoader>
</main>
);
}

View File

@@ -0,0 +1,36 @@
import CipherLoader from '@/components/ciphers/CipherLoader';
import BeaufortInputs from '@/components/ciphers/monosubstitution/beaufort/BeaufortInputs';
import { useGetBeaufortInfo } from '@/hooks/monosubstitution/BeaufortHooks';
import { createFileRoute } from '@tanstack/react-router';
/*
{
title: "Beaufort",
description: "",
keywords: [
"Beaufort"
]
}
*/
export const Route = createFileRoute('/monosubstitution/beaufort/')({
component: BeaufortPage
});
function BeaufortPage(){
const beaufortInfoQuery = useGetBeaufortInfo();
return (
<main
className="flex flex-col items-center justify-center"
>
<CipherLoader infoQuery={beaufortInfoQuery}>
<BeaufortInputs/>
</CipherLoader>
</main>
);
}

View File

@@ -0,0 +1,36 @@
import CipherLoader from '@/components/ciphers/CipherLoader';
import CaesarInputs from '@/components/ciphers/monosubstitution/caesar/CaesarInputs';
import { useGetCaesarInfo } from '@/hooks/monosubstitution/CaesarHooks';
import { createFileRoute } from '@tanstack/react-router';
/*
{
title: "Caesar",
description: "",
keywords: [
"Caesar"
]
}
*/
export const Route = createFileRoute('/monosubstitution/caesar/')({
component: CaesarPage
});
function CaesarPage(){
const caesarInfoQuery = useGetCaesarInfo();
return (
<main
className="flex flex-col items-center justify-center"
>
<CipherLoader infoQuery={caesarInfoQuery}>
<CaesarInputs/>
</CipherLoader>
</main>
);
}

View File

@@ -0,0 +1,74 @@
import { monosubstitutionLinks } from "@/util/LinksUtil";
import { createFileRoute, Link } from "@tanstack/react-router";
/*
title: "Mono-Substitution",
description: "",
keywords: [
"Mono-Substitution",
"Affine",
"Atbash",
"Autokey",
"Baconian",
"Base X", "BaseX", "basex",
"Base 2", "base2", "binary",
"Base 8", "base8", "octal",
"Base 16", "base16", "hexadecimal",
"Beaufort",
"Caesar",
"One-Time Pad", "onetime pad", "onetimepad",
"Port",
"Substitution",
"Vigenere"
]
*/
export const Route = createFileRoute("/monosubstitution/")({
component: MonoPage
});
function MonoPage(){
return (
<main
className="flex flex-col items-center"
>
<h1
className="font-bold text-4xl my-8"
>
Mono-Substitution Ciphers
</h1>
<p
className="text-center"
>
Mono-Substitution ciphers encrypt text one character at a time.
These are generally the least secure ciphers because they are easy to break using brute force methods.
</p>
<div
className="mt-8"
>
<ul
className="grid grid-cols-4 gap-8"
>
{
monosubstitutionLinks.map(cipher => (
<li
key={cipher.label}
className="text-center"
>
<Link
className="cursor-pointer text-lg"
to={cipher.to}
>
{cipher.label}
</Link>
</li>
))
}
</ul>
</div>
</main>
);
}

View File

@@ -0,0 +1,39 @@
import CipherLoader from '@/components/ciphers/CipherLoader';
import OneTimePadInputs from '@/components/ciphers/monosubstitution/onetimepad/OneTimePadInputs';
import { useGetOneTimePadInfo } from '@/hooks/monosubstitution/OneTimePadHooks';
import { createFileRoute } from '@tanstack/react-router';
/*
{
title: "One-Time Pad",
description: "",
keywords: [
"One-Time Pad",
"one time pad",
"onetime pad",
"onetimepad"
]
}
*/
export const Route = createFileRoute('/monosubstitution/onetimepad/')({
component: OneTimePadPage
});
function OneTimePadPage(){
const oneTimePadInfoQuery = useGetOneTimePadInfo();
return (
<main
className="flex flex-col items-center justify-center"
>
<CipherLoader infoQuery={oneTimePadInfoQuery}>
<OneTimePadInputs/>
</CipherLoader>
</main>
);
}

Some files were not shown because too many files have changed in this diff Show More