From efc7709f66eba7814c7cf2ab017b69c5636e009b Mon Sep 17 00:00:00 2001 From: Amit Haridas Date: Sat, 6 Jun 2026 07:40:20 +0530 Subject: [PATCH] feat(renderer): AsciiGeneratorDialog (figlet text-to-ASCII-art) --- package-lock.json | 33 ++++++++ package.json | 2 + .../modals/AsciiGeneratorDialog.tsx | 77 +++++++++++++++++++ src/renderer/lib/figlet.ts | 14 ++++ .../modals/AsciiGeneratorDialog.test.tsx | 35 +++++++++ 5 files changed, 161 insertions(+) create mode 100644 src/renderer/components/modals/AsciiGeneratorDialog.tsx create mode 100644 src/renderer/lib/figlet.ts create mode 100644 tests/component/modals/AsciiGeneratorDialog.test.tsx diff --git a/package-lock.json b/package-lock.json index 575a627..857db3d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,6 +47,7 @@ "dompurify": "^3.3.1", "electron-store": "^10.1.0", "ffmpeg-static": "^5.3.0", + "figlet": "^1.11.0", "highlight.js": "^11.11.1", "html2pdf.js": "^0.14.0", "immer": "^11.1.8", @@ -76,6 +77,7 @@ "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", + "@types/figlet": "^1.7.0", "@types/node": "^25.9.1", "@types/react": "^19.2.16", "@types/react-dom": "^19.2.3", @@ -5737,6 +5739,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/figlet": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@types/figlet/-/figlet-1.7.0.tgz", + "integrity": "sha512-KwrT7p/8Eo3Op/HBSIwGXOsTZKYiM9NpWRBJ5sVjWP/SmlS+oxxRvJht/FNAtliJvja44N3ul1yATgohnVBV0Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/fs-extra": { "version": "9.0.13", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", @@ -10241,6 +10250,30 @@ "node": ">= 6" } }, + "node_modules/figlet": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.11.0.tgz", + "integrity": "sha512-EEx3OS/l2bFqcUNN2NM9FPJp8vAMrgbCxsbl2hbcJNNxOEwVe3mEzrhan7TbJQViZa8mMqhihlbCaqD+LyYKTQ==", + "license": "MIT", + "dependencies": { + "commander": "^14.0.0" + }, + "bin": { + "figlet": "bin/index.js" + }, + "engines": { + "node": ">= 17.0.0" + } + }, + "node_modules/figlet/node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", diff --git a/package.json b/package.json index a24270a..fbd562a 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", + "@types/figlet": "^1.7.0", "@types/node": "^25.9.1", "@types/react": "^19.2.16", "@types/react-dom": "^19.2.3", @@ -118,6 +119,7 @@ "dompurify": "^3.3.1", "electron-store": "^10.1.0", "ffmpeg-static": "^5.3.0", + "figlet": "^1.11.0", "highlight.js": "^11.11.1", "html2pdf.js": "^0.14.0", "immer": "^11.1.8", diff --git a/src/renderer/components/modals/AsciiGeneratorDialog.tsx b/src/renderer/components/modals/AsciiGeneratorDialog.tsx new file mode 100644 index 0000000..4938ea5 --- /dev/null +++ b/src/renderer/components/modals/AsciiGeneratorDialog.tsx @@ -0,0 +1,77 @@ +import { useState, useEffect } from 'react'; +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; +import { Button } from '@/components/ui/button'; +import { Label } from '@/components/ui/label'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; +import { Textarea } from '@/components/ui/textarea'; +import { useAppStore } from '@/stores/app-store'; +import { toast } from '@/lib/toast'; +import { figletText, FIGLET_FONTS, type FigletFont } from '@/lib/figlet'; + +export function AsciiGeneratorDialog() { + const closeModal = useAppStore((s) => s.closeModal); + const [text, setText] = useState('Hello'); + const [font, setFont] = useState('Standard'); + const [output, setOutput] = useState(''); + + useEffect(() => { + let cancelled = false; + figletText(text || ' ', font) + .then((result) => { if (!cancelled) setOutput(result); }) + .catch(() => { if (!cancelled) setOutput('(render error)'); }); + return () => { cancelled = true; }; + }, [text, font]); + + const handleCopy = async () => { + try { + await navigator.clipboard.writeText(output); + toast.success('Copied to clipboard'); + } catch { + toast.error('Failed to copy'); + } + }; + + return ( + !o && closeModal()}> + + + ASCII generator + Type text, pick a font, see ASCII art + +
+
+ +