CipherStreamWeb converted to use Vite
This commit is contained in:
25
src/components/button/CopyOutputButton.tsx
Normal file
25
src/components/button/CopyOutputButton.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
19
src/components/button/EncodingDecodingButton.tsx
Normal file
19
src/components/button/EncodingDecodingButton.tsx
Normal 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>}
|
||||
/>
|
||||
);
|
||||
}
|
||||
45
src/components/ciphers/CipherLoader.tsx
Normal file
45
src/components/ciphers/CipherLoader.tsx
Normal 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>
|
||||
}
|
||||
</>
|
||||
);
|
||||
}
|
||||
87
src/components/ciphers/CipherWrapper.tsx
Normal file
87
src/components/ciphers/CipherWrapper.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
142
src/components/ciphers/combination/adfgvx/ADFGVXInputs.tsx
Normal file
142
src/components/ciphers/combination/adfgvx/ADFGVXInputs.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
142
src/components/ciphers/combination/adfgx/ADFGXInputs.tsx
Normal file
142
src/components/ciphers/combination/adfgx/ADFGXInputs.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
150
src/components/ciphers/monosubstitution/affine/AffineInputs.tsx
Normal file
150
src/components/ciphers/monosubstitution/affine/AffineInputs.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
125
src/components/ciphers/monosubstitution/atbash/AtbashInputs.tsx
Normal file
125
src/components/ciphers/monosubstitution/atbash/AtbashInputs.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
118
src/components/ciphers/monosubstitution/basex/BaseXInputs.tsx
Normal file
118
src/components/ciphers/monosubstitution/basex/BaseXInputs.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
140
src/components/ciphers/monosubstitution/caesar/CaesarInputs.tsx
Normal file
140
src/components/ciphers/monosubstitution/caesar/CaesarInputs.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
133
src/components/ciphers/monosubstitution/porta/PortaInputs.tsx
Normal file
133
src/components/ciphers/monosubstitution/porta/PortaInputs.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
133
src/components/ciphers/polysubstitution/bifid/BifidInputs.tsx
Normal file
133
src/components/ciphers/polysubstitution/bifid/BifidInputs.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
133
src/components/ciphers/polysubstitution/hill/HillInputs.tsx
Normal file
133
src/components/ciphers/polysubstitution/hill/HillInputs.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
103
src/components/ciphers/polysubstitution/morse/MorseInputs.tsx
Normal file
103
src/components/ciphers/polysubstitution/morse/MorseInputs.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
157
src/components/ciphers/polysubstitution/trifid/TrifidInputs.tsx
Normal file
157
src/components/ciphers/polysubstitution/trifid/TrifidInputs.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
24
src/components/input/InputMessage.tsx
Normal file
24
src/components/input/InputMessage.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
23
src/components/input/KeywordArea.tsx
Normal file
23
src/components/input/KeywordArea.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
23
src/components/input/KeywordInput.tsx
Normal file
23
src/components/input/KeywordInput.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
31
src/components/input/NumberSelector.tsx
Normal file
31
src/components/input/NumberSelector.tsx
Normal 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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
59
src/components/input/NumberSelectorArray.tsx
Normal file
59
src/components/input/NumberSelectorArray.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
25
src/components/input/OutputMessage.tsx
Normal file
25
src/components/input/OutputMessage.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
59
src/components/input/PreservationSliders.tsx
Normal file
59
src/components/input/PreservationSliders.tsx
Normal 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>
|
||||
}
|
||||
</>
|
||||
);
|
||||
}
|
||||
92
src/components/input/SquareNumberArray.tsx
Normal file
92
src/components/input/SquareNumberArray.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
53
src/components/nav/CombinationLinks.tsx
Normal file
53
src/components/nav/CombinationLinks.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
36
src/components/nav/DarkModeToggle.tsx
Normal file
36
src/components/nav/DarkModeToggle.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
53
src/components/nav/MonoLinks.tsx
Normal file
53
src/components/nav/MonoLinks.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
69
src/components/nav/NavBar.tsx
Normal file
69
src/components/nav/NavBar.tsx
Normal 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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
53
src/components/nav/PolyLinks.tsx
Normal file
53
src/components/nav/PolyLinks.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
30
src/components/nav/TutorialLink.tsx
Normal file
30
src/components/nav/TutorialLink.tsx
Normal 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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
26
src/components/tutorials/EncodingTutorial.tsx
Normal file
26
src/components/tutorials/EncodingTutorial.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
25
src/components/tutorials/InputTutorial.tsx
Normal file
25
src/components/tutorials/InputTutorial.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
25
src/components/tutorials/KeywordTutorial.tsx
Normal file
25
src/components/tutorials/KeywordTutorial.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
26
src/components/tutorials/NumberSelectorTutorial.tsx
Normal file
26
src/components/tutorials/NumberSelectorTutorial.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
25
src/components/tutorials/OutputTutorial.tsx
Normal file
25
src/components/tutorials/OutputTutorial.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
22
src/components/tutorials/SwitchTutorial.tsx
Normal file
22
src/components/tutorials/SwitchTutorial.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user