diff --git a/app/converters/json-yaml/page.tsx b/app/converters/json-yaml/page.tsx index 0e58ccd..b4ba77b 100644 --- a/app/converters/json-yaml/page.tsx +++ b/app/converters/json-yaml/page.tsx @@ -7,18 +7,8 @@ import { toolGroups } from "@/config/tools"; import { safeJsonParse } from "@/lib/json"; import { safeYamlParse } from "@/lib/yaml"; import { Editor, EditorProps } from "@/components/ui/editor"; -import { - Select, - SelectContent, - SelectItem, - SelectProps, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; -import { ClearButton } from "@/components/buttons/clear"; -import { CopyButton } from "@/components/buttons/copy"; -import { FileButton } from "@/components/buttons/file"; -import { PasteButton } from "@/components/buttons/paste"; +import * as Select from "@/components/ui/select"; +import * as Button from "@/components/buttons"; import { Configuration } from "@/components/configuration"; import { Configurations } from "@/components/configurations"; import { ControlMenu } from "@/components/control-menu"; @@ -38,41 +28,44 @@ export default function Page() { yaml: "foo: bar", }); - const setJsonReactively = useCallback((text: string) => { - const parsed = safeJsonParse(text); - + const setFormByJson = useCallback((text: string) => { setForm(prev => ({ ...prev, json: text, - yaml: parsed.isErr() - ? "" - : yaml.dump(parsed.value, { indent: prev.indentation.length, quotingType: '"' }), + yaml: safeJsonParse(text) + .map(x => yaml.dump(x, { indent: prev.indentation.length, quotingType: '"' })) + .unwrapOr(""), })); }, []); - const setYamlReactively = useCallback((text: string) => { - const parsed = safeYamlParse(text); - + const setFormByYaml = useCallback((text: string) => { setForm(prev => ({ ...prev, + json: safeYamlParse(text) + .map(x => JSON.stringify(x, null, prev.indentation)) + .unwrapOr(""), yaml: text, - json: parsed.isErr() ? "" : JSON.stringify(parsed.value, null, prev.indentation), })); }, []); const clearBoth = useCallback(() => { - setForm(prev => ({ ...prev, json: "", yaml: "" })); + setForm(prev => ({ + ...prev, + json: "", + yaml: "", + })); }, []); - const onIndentationChange: SelectProps["onValueChange"] = value => { - const parsed = safeJsonParse(form.json); - - const jsonYaml = parsed.isErr() - ? { json: "", yaml: "" } - : { - json: JSON.stringify(parsed.value, null, value), - yaml: yaml.dump(parsed.value, { indent: value.length, quotingType: '"' }), - }; + const onIndentationChange: Select.Props["onValueChange"] = value => { + const jsonYaml = safeJsonParse(form.json) + .map(x => ({ + json: JSON.stringify(x, null, value), + yaml: yaml.dump(x, { indent: value.length, quotingType: '"' }), + })) + .unwrapOr({ + json: "", + yaml: "", + }); setForm({ indentation: value, @@ -80,59 +73,55 @@ export default function Page() { }); }; - const onJsonChange: EditorProps["onChange"] = value => setJsonReactively(value ?? ""); - const onYamlChange: EditorProps["onChange"] = value => setYamlReactively(value ?? ""); + const onJsonChange: EditorProps["onChange"] = value => setFormByJson(value ?? ""); + const onYamlChange: EditorProps["onChange"] = value => setFormByYaml(value ?? ""); const indentationConfig = ( } title="Indentation" control={ - + + + + 2 spaces + 4 spaces + + } /> ); - const jsonPasteButton = ; - const yamlPasteButton = ; + const jsonPasteButton = ; + const yamlPasteButton = ; const jsonFileButton = ( - + ); const yamlFileButton = ( - ); - const jsonCopyButton = ; - const yamlCopyButton = ; + const jsonCopyButton = ; + const yamlCopyButton = ; - const clearButton = ; + const clearButton = ( + + ); const jsonControl = ( ); - const yamlControl = ( ); diff --git a/app/converters/number-base/page.tsx b/app/converters/number-base/page.tsx index b2df0c9..04be9a9 100644 --- a/app/converters/number-base/page.tsx +++ b/app/converters/number-base/page.tsx @@ -5,7 +5,7 @@ import { useCallback, useState } from "react"; import { toolGroups } from "@/config/tools"; import * as baselib from "@/lib/base"; import { Input, InputProps } from "@/components/ui/input"; -import { PasteButton } from "@/components/buttons/paste"; +import * as Button from "@/components/buttons"; import { Configuration } from "@/components/configuration"; import { Configurations } from "@/components/configurations"; import { ControlMenu } from "@/components/control-menu"; @@ -53,10 +53,10 @@ export default function Page() { const trySetOct = useCallback((value: string) => trySetInt(8)(value), []); const trySetBin = useCallback((value: string) => trySetInt(2)(value), []); - const onDecChange: InputProps["onChange"] = ({ currentTarget: { value } }) => trySetDec(value); - const onHexChange: InputProps["onChange"] = ({ currentTarget: { value } }) => trySetHex(value); - const onOctChange: InputProps["onChange"] = ({ currentTarget: { value } }) => trySetOct(value); - const onBinChange: InputProps["onChange"] = ({ currentTarget: { value } }) => trySetBin(value); + const onDecChange: InputProps["onChange"] = e => trySetDec(e.currentTarget.value); + const onHexChange: InputProps["onChange"] = e => trySetHex(e.currentTarget.value); + const onOctChange: InputProps["onChange"] = e => trySetOct(e.currentTarget.value); + const onBinChange: InputProps["onChange"] = e => trySetBin(e.currentTarget.value); const formatNumberConfig = ( ); - const decPasteButton = ; - const hexPasteButton = ; - const octPasteButton = ; - const binPasteButton = ; + const decPasteButton = ; + const hexPasteButton = ; + const octPasteButton = ; + const binPasteButton = ; const decControl = ; const hexControl = ; diff --git a/app/encoders-decoders/base64/page.tsx b/app/encoders-decoders/base64/page.tsx index 29db4fa..04d3376 100644 --- a/app/encoders-decoders/base64/page.tsx +++ b/app/encoders-decoders/base64/page.tsx @@ -5,10 +5,7 @@ import { decode, encode, isValid } from "js-base64"; import { toolGroups } from "@/config/tools"; import { Textarea, TextareaProps } from "@/components/ui/textarea"; -import { ClearButton } from "@/components/buttons/clear"; -import { CopyButton } from "@/components/buttons/copy"; -import { FileButton } from "@/components/buttons/file"; -import { PasteButton } from "@/components/buttons/paste"; +import * as Button from "@/components/buttons"; import { ControlMenu } from "@/components/control-menu"; import { PageRootSection } from "@/components/page-root-section"; import { PageSection } from "@/components/page-section"; @@ -19,19 +16,19 @@ export default function Page() { encoded: "8J+YgPCfmILwn6Sj", }); - const setDecodedReactively = useCallback((text: string) => { + const setFormByDecoded = useCallback((text: string) => { setForm({ decoded: text, encoded: encode(text), }); }, []); - const setEncodedReactively = useCallback((text: string) => { + const setFormByEncoded = useCallback((text: string) => { const newDecoded = decode(text); setForm({ - encoded: text, decoded: isValid(text) && !newDecoded.includes("�") ? newDecoded : "", + encoded: text, }); }, []); @@ -42,33 +39,29 @@ export default function Page() { }); }, []); - const onDecodedChange: TextareaProps["onChange"] = ({ currentTarget: { value } }) => - setDecodedReactively(value); + const onDecodedChange: TextareaProps["onChange"] = e => setFormByDecoded(e.currentTarget.value); + const onEncodedChange: TextareaProps["onChange"] = e => setFormByEncoded(e.currentTarget.value); - const onEncodedChange: TextareaProps["onChange"] = ({ currentTarget: { value } }) => - setEncodedReactively(value); - - const decodedPasteButton = ; - const encodedPasteButton = ; + const decodedPasteButton = ; + const encodedPasteButton = ; const decodedFileButton = ( - + ); const encodedFileButton = ( - + ); - const decodedCopyButton = ; - const encodedCopyButton = ; + const decodedCopyButton = ; + const encodedCopyButton = ; const clearButton = ( - + ); const decodedControl = ( ); - const encodedControl = ( ); diff --git a/app/encoders-decoders/html/page.tsx b/app/encoders-decoders/html/page.tsx index 977709f..c4defff 100644 --- a/app/encoders-decoders/html/page.tsx +++ b/app/encoders-decoders/html/page.tsx @@ -5,10 +5,7 @@ import { escape, unescape } from "html-escaper"; import { toolGroups } from "@/config/tools"; import { Textarea, TextareaProps } from "@/components/ui/textarea"; -import { ClearButton } from "@/components/buttons/clear"; -import { CopyButton } from "@/components/buttons/copy"; -import { FileButton } from "@/components/buttons/file"; -import { PasteButton } from "@/components/buttons/paste"; +import * as Button from "@/components/buttons"; import { ControlMenu } from "@/components/control-menu"; import { PageRootSection } from "@/components/page-root-section"; import { PageSection } from "@/components/page-section"; @@ -19,17 +16,17 @@ export default function Page() { encoded: "> It's "HTML escaping".", }); - const setDecodedReactively = useCallback((text: string) => { + const setFormByDecoded = useCallback((text: string) => { setForm({ decoded: text, encoded: escape(text), }); }, []); - const setEncodedReactively = useCallback((text: string) => { + const setFormByEncoded = useCallback((text: string) => { setForm({ - encoded: text, decoded: unescape(text), + encoded: text, }); }, []); @@ -40,33 +37,29 @@ export default function Page() { }); }, []); - const onDecodedChange: TextareaProps["onChange"] = ({ currentTarget: { value } }) => - setDecodedReactively(value); + const onDecodedChange: TextareaProps["onChange"] = e => setFormByDecoded(e.currentTarget.value); + const onEncodedChange: TextareaProps["onChange"] = e => setFormByEncoded(e.currentTarget.value); - const onEncodedChange: TextareaProps["onChange"] = ({ currentTarget: { value } }) => - setEncodedReactively(value); - - const decodedPasteButton = ; - const encodedPasteButton = ; + const decodedPasteButton = ; + const encodedPasteButton = ; const decodedFileButton = ( - + ); const encodedFileButton = ( - + ); - const decodedCopyButton = ; - const encodedCopyButton = ; + const decodedCopyButton = ; + const encodedCopyButton = ; const clearButton = ( - + ); const decodedControl = ( ); - const encodedControl = ( ); diff --git a/app/encoders-decoders/jwt/page.tsx b/app/encoders-decoders/jwt/page.tsx index cd88d42..014aba9 100644 --- a/app/encoders-decoders/jwt/page.tsx +++ b/app/encoders-decoders/jwt/page.tsx @@ -6,10 +6,7 @@ import { toolGroups } from "@/config/tools"; import { decode } from "@/lib/jwt"; import { Editor } from "@/components/ui/editor"; import { Textarea, TextareaProps } from "@/components/ui/textarea"; -import { ClearButton } from "@/components/buttons/clear"; -import { CopyButton } from "@/components/buttons/copy"; -import { FileButton } from "@/components/buttons/file"; -import { PasteButton } from "@/components/buttons/paste"; +import * as Button from "@/components/buttons"; import { ControlMenu } from "@/components/control-menu"; import { PageRootSection } from "@/components/page-root-section"; import { PageSection } from "@/components/page-section"; @@ -20,23 +17,23 @@ export default function Page() { ); const { header: h, payload: p } = decode(jwt); - const header = h.isErr() ? "" : JSON.stringify(h.value, null, 2); - const payload = p.isErr() ? "" : JSON.stringify(p.value, null, 2); + const header = h.map(x => JSON.stringify(x, null, 2)).unwrapOr(""); + const payload = p.map(x => JSON.stringify(x, null, 2)).unwrapOr(""); const clearJwt = useCallback(() => setJwt(""), []); - const onJwtChange: TextareaProps["onChange"] = ({ currentTarget: { value } }) => setJwt(value); + const onJwtChange: TextareaProps["onChange"] = e => setJwt(e.currentTarget.value); - const jwtTokenPasteButton = ; + const jwtTokenPasteButton = ; const jwtTokenFileButton = ( - + ); - const jwtTokenClearButton = ; + const jwtTokenClearButton = ; - const heaederCopyButton = ; - const payloadCopyButton = ; + const heaederCopyButton = ; + const payloadCopyButton = ; const jwtTokenControl = ( diff --git a/app/encoders-decoders/url/page.tsx b/app/encoders-decoders/url/page.tsx index 6fa8ca0..1fb2c38 100644 --- a/app/encoders-decoders/url/page.tsx +++ b/app/encoders-decoders/url/page.tsx @@ -5,10 +5,7 @@ import { useCallback, useState } from "react"; import { toolGroups } from "@/config/tools"; import { safeDecodeURIComponent, safeEncodeURIComponent } from "@/lib/uri"; import { Textarea, TextareaProps } from "@/components/ui/textarea"; -import { ClearButton } from "@/components/buttons/clear"; -import { CopyButton } from "@/components/buttons/copy"; -import { FileButton } from "@/components/buttons/file"; -import { PasteButton } from "@/components/buttons/paste"; +import * as Button from "@/components/buttons"; import { ControlMenu } from "@/components/control-menu"; import { PageRootSection } from "@/components/page-root-section"; import { PageSection } from "@/components/page-section"; @@ -19,17 +16,17 @@ export default function Page() { encoded: "%3E%20It's%20%22URL%20encoding%22%3F", }); - const setDecodedReactively = useCallback((text: string) => { + const setFormByDecoded = useCallback((text: string) => { setForm({ decoded: text, encoded: safeEncodeURIComponent(text).unwrapOr(""), }); }, []); - const setEncodedReactively = useCallback((text: string) => { + const setFormByEncoded = useCallback((text: string) => { setForm({ - encoded: text, decoded: safeDecodeURIComponent(text).unwrapOr(""), + encoded: text, }); }, []); @@ -40,33 +37,29 @@ export default function Page() { }); }, []); - const onDecodedChange: TextareaProps["onChange"] = ({ currentTarget: { value } }) => - setDecodedReactively(value); + const onDecodedChange: TextareaProps["onChange"] = e => setFormByDecoded(e.currentTarget.value); + const onEncodedChange: TextareaProps["onChange"] = e => setFormByEncoded(e.currentTarget.value); - const onEncodedChange: TextareaProps["onChange"] = ({ currentTarget: { value } }) => - setEncodedReactively(value); - - const decodedPasteButton = ; - const encodedPasteButton = ; + const decodedPasteButton = ; + const encodedPasteButton = ; const decodedFileButton = ( - + ); const encodedFileButton = ( - + ); - const decodedCopyButton = ; - const encodedCopyButton = ; + const decodedCopyButton = ; + const encodedCopyButton = ; const clearButton = ( - + ); const decodedControl = ( ); - const encodedControl = ( ); diff --git a/app/formatters/json/page.tsx b/app/formatters/json/page.tsx index 5d39291..e4d0d99 100644 --- a/app/formatters/json/page.tsx +++ b/app/formatters/json/page.tsx @@ -5,17 +5,8 @@ import { useCallback, useState } from "react"; import { toolGroups } from "@/config/tools"; import { safeJsonParse } from "@/lib/json"; import { Editor, EditorProps } from "@/components/ui/editor"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; -import { ClearButton } from "@/components/buttons/clear"; -import { CopyButton } from "@/components/buttons/copy"; -import { FileButton } from "@/components/buttons/file"; -import { PasteButton } from "@/components/buttons/paste"; +import * as Select from "@/components/ui/select"; +import * as Button from "@/components/buttons"; import { Configuration } from "@/components/configuration"; import { Configurations } from "@/components/configurations"; import { ControlMenu } from "@/components/control-menu"; @@ -35,7 +26,7 @@ export default function Page() { const [input, setInput] = useState('{\n"foo":"bar"\n}'); const parsed = safeJsonParse(input); - const output = parsed.isErr() ? "" : JSON.stringify(parsed.value, null, indentation); + const output = parsed.map(x => JSON.stringify(x, null, indentation)).unwrapOr(""); const clearInput = useCallback(() => setInput(""), []); @@ -46,33 +37,33 @@ export default function Page() { icon={} title="Indentation" control={ - + + + + 2 spaces + 4 spaces + 1 tab + minified + + } /> ); - const inputPasteButton = ; + const inputPasteButton = ; const inputFileButton = ( - + ); - const inputClearButton = ; + const inputClearButton = ; - const outputCopyButton = ; + const outputCopyButton = ; const inputControl = ; const outputControl = ; diff --git a/app/generators/hash/page.tsx b/app/generators/hash/page.tsx index ce2ce47..44bd38b 100644 --- a/app/generators/hash/page.tsx +++ b/app/generators/hash/page.tsx @@ -6,10 +6,7 @@ import createHash from "create-hash"; import { toolGroups } from "@/config/tools"; import { Input } from "@/components/ui/input"; import { Textarea, TextareaProps } from "@/components/ui/textarea"; -import { ClearButton } from "@/components/buttons/clear"; -import { CopyButton } from "@/components/buttons/copy"; -import { FileButton } from "@/components/buttons/file"; -import { PasteButton } from "@/components/buttons/paste"; +import * as Button from "@/components/buttons"; import { Configuration } from "@/components/configuration"; import { Configurations } from "@/components/configurations"; import { ControlMenu } from "@/components/control-menu"; @@ -34,8 +31,7 @@ export default function Page() { const clearInput = useCallback(() => setInput(""), []); - const onInputChange: TextareaProps["onChange"] = ({ currentTarget: { value } }) => - setInput(value); + const onInputChange: TextareaProps["onChange"] = e => setInput(e.currentTarget.value); const uppercaseConfig = ( ); - const inputPasteButton = ; - const inputFileButton = ; - const inputClearButton = ; + const inputPasteButton = ; + const inputFileButton = ; + const inputClearButton = ; const inputControl = ; - const md5CopyButton = ; - const sha1CopyButton = ; - const sha256CopyButton = ; - const sha512CopyButton = ; + const md5CopyButton = ; + const sha1CopyButton = ; + const sha256CopyButton = ( + + ); + const sha512CopyButton = ( + + ); return ( diff --git a/app/generators/uuid/page.tsx b/app/generators/uuid/page.tsx index a725a02..cec2c1a 100644 --- a/app/generators/uuid/page.tsx +++ b/app/generators/uuid/page.tsx @@ -9,17 +9,10 @@ import { uuid } from "@/lib/uuid"; import { useScrollFollow } from "@/hooks/useScrollFollow"; import { Button } from "@/components/ui/button"; import { Input, InputProps } from "@/components/ui/input"; -import { - Select, - SelectContent, - SelectItem, - SelectProps, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; +import * as Select from "@/components/ui/select"; import { Textarea } from "@/components/ui/textarea"; -import { ClearButton } from "@/components/buttons/clear"; -import { CopyButton } from "@/components/buttons/copy"; +import { Clear } from "@/components/buttons/clear"; +import { Copy } from "@/components/buttons/copy"; import { Configuration } from "@/components/configuration"; import { Configurations } from "@/components/configurations"; import { ControlMenu } from "@/components/control-menu"; @@ -48,22 +41,19 @@ export default function Page() { const clearUuids = useCallback(() => setUuids([]), []); - const onUuidVersionChange: NonNullable = useCallback(value => { + const onUuidVersionChange: NonNullable = useCallback(value => { if (uuidVersions.is(value)) { setUuidVersion(value); } }, []); - const onGeneratesChange: NonNullable = useCallback( - ({ currentTarget: { value } }) => { - const newGenerates = Number(value); + const onGeneratesChange: NonNullable = useCallback(e => { + const newGenerates = Number(e.currentTarget.value); - if (newGenerates >= 1 && newGenerates <= 1000) { - setGenerates(newGenerates); - } - }, - [] - ); + if (newGenerates >= 1 && newGenerates <= 1000) { + setGenerates(newGenerates); + } + }, []); const onGenerateClick = () => { const newUuids = range(1, generates).map(_ => uuid(uuidVersion, hyphens, uppercase)); @@ -108,24 +98,24 @@ export default function Page() { title="UUID version" description="Choose the version of UUID to generate" control={ - + + + + 1 + 4 (GUID) + + } /> ); - const uuidsCopyButton = ; - const uuidsClearButton = ; + const uuidsCopyButton = ; + const uuidsClearButton = ; const uuidsControl = ; diff --git a/app/settings/page.tsx b/app/settings/page.tsx index a9d3d77..71afcf0 100644 --- a/app/settings/page.tsx +++ b/app/settings/page.tsx @@ -3,13 +3,7 @@ import { useTheme } from "next-themes"; import { singleTools } from "@/config/tools"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; +import * as Select from "@/components/ui/select"; import { Configuration } from "@/components/configuration"; import { Configurations } from "@/components/configurations"; import { icons } from "@/components/icons"; @@ -25,19 +19,19 @@ export default function Page() { title="App theme" description="Select which app theme to display" control={ - + + + + Light + Dark + System + + } /> ); diff --git a/components/buttons/base.tsx b/components/buttons/base.tsx index fdfec9e..a1fb85d 100644 --- a/components/buttons/base.tsx +++ b/components/buttons/base.tsx @@ -1,13 +1,13 @@ import { Button, ButtonProps } from "@/components/ui/button"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; -export type BaseButtonProps = ButtonProps & { +export type BaseProps = ButtonProps & { icon: React.ReactNode; iconOnly?: true; labelText: string; }; -export function BaseButton({ icon, iconOnly, labelText, ...props }: BaseButtonProps) { +export function Base({ icon, iconOnly, labelText, ...props }: BaseProps) { const button = (