diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index fb61f29..02eecf5 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,14 +4,12 @@
-
-
-
-
+
-
+
+
@@ -28,7 +26,7 @@
@@ -229,7 +227,7 @@
"Vitest.replaceText function (regexp mode).should return the original text when passed an invalid regexp.executor": "Run",
"Vitest.replaceText function.executor": "Run",
"Vitest.timeBetweenDates.executor": "Run",
- "git-widget-placeholder": "main",
+ "git-widget-placeholder": "qr-code",
"ignore.virus.scanning.warn.message": "true",
"kotlin-language-version-configured": "true",
"last_opened_file_path": "C:/Users/Ibrahima/IdeaProjects/omni-tools/src",
@@ -469,14 +467,6 @@
-
-
- 1741487735223
-
-
-
- 1741487735223
-
1741492688761
@@ -861,7 +851,15 @@
1748881153433
-
+
+
+ 1749147227565
+
+
+
+ 1749147227565
+
+
@@ -908,7 +906,6 @@
-
@@ -933,7 +930,8 @@
-
+
+
diff --git a/package-lock.json b/package-lock.json
index 49caad8..e501cc8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -41,7 +41,7 @@
"pdf-lib": "^1.17.1",
"pdfjs-dist": "^5.2.133",
"playwright": "^1.45.0",
- "qrcode.react": "^4.2.0",
+ "qrcode": "^1.5.4",
"rc-slider": "^11.1.8",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -62,6 +62,7 @@
"@types/color": "^3.0.6",
"@types/color-rgba": "^2.1.2",
"@types/node": "^20.12.12",
+ "@types/qrcode": "^1.5.5",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/react-helmet": "^6.1.11",
@@ -3370,6 +3371,16 @@
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
},
+ "node_modules/@types/qrcode": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.5.tgz",
+ "integrity": "sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/react": {
"version": "18.3.3",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz",
@@ -3868,7 +3879,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -3877,7 +3887,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -4376,6 +4385,15 @@
"node": ">=6"
}
},
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/camelcase-css": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
@@ -4922,6 +4940,15 @@
}
}
},
+ "node_modules/decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/deep-eql": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz",
@@ -5046,6 +5073,12 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
+ "node_modules/dijkstrajs": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
+ "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==",
+ "license": "MIT"
+ },
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -6106,7 +6139,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true,
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
@@ -6849,7 +6881,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -8479,6 +8510,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/package-json-from-dist": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
@@ -8547,7 +8587,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
"engines": {
"node": ">=8"
}
@@ -9130,13 +9169,168 @@
"node": ">=6"
}
},
- "node_modules/qrcode.react": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-4.2.0.tgz",
- "integrity": "sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA==",
+ "node_modules/qrcode": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz",
+ "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
+ "license": "MIT",
+ "dependencies": {
+ "dijkstrajs": "^1.0.1",
+ "pngjs": "^5.0.0",
+ "yargs": "^15.3.1"
+ },
+ "bin": {
+ "qrcode": "bin/qrcode"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/qrcode/node_modules/cliui": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
"license": "ISC",
- "peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "node_modules/qrcode/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/qrcode/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/qrcode/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/pngjs": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
+ "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/qrcode/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/y18n": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+ "license": "ISC"
+ },
+ "node_modules/qrcode/node_modules/yargs": {
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^6.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^4.2.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=6"
}
},
"node_modules/queue-microtask": {
@@ -9422,7 +9616,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -9436,6 +9629,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "license": "ISC"
+ },
"node_modules/resolve": {
"version": "2.0.0-next.5",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
@@ -9676,6 +9875,12 @@
"node": ">=10"
}
},
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+ "license": "ISC"
+ },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@@ -10207,7 +10412,6 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -11213,6 +11417,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/which-module": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
+ "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
+ "license": "ISC"
+ },
"node_modules/which-typed-array": {
"version": "1.1.15",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz",
diff --git a/package.json b/package.json
index 7d97d6e..ed7ebcf 100644
--- a/package.json
+++ b/package.json
@@ -58,7 +58,7 @@
"pdf-lib": "^1.17.1",
"pdfjs-dist": "^5.2.133",
"playwright": "^1.45.0",
- "qrcode.react": "^4.2.0",
+ "qrcode": "^1.5.4",
"rc-slider": "^11.1.8",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -79,6 +79,7 @@
"@types/color": "^3.0.6",
"@types/color-rgba": "^2.1.2",
"@types/node": "^20.12.12",
+ "@types/qrcode": "^1.5.5",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/react-helmet": "^6.1.11",
diff --git a/src/components/options/ColorSelector.tsx b/src/components/options/ColorSelector.tsx
index a89ea1d..a24cf40 100644
--- a/src/components/options/ColorSelector.tsx
+++ b/src/components/options/ColorSelector.tsx
@@ -39,7 +39,7 @@ const ColorSelector: React.FC = ({
('');
- const [currentValues, setCurrentValues] =
- useState(initialValues);
-
- // Update QR code value when form values change
- useEffect(() => {
- setQRValue(formatQRCodeData(currentValues));
- }, [currentValues]);
-
+ const [result, setResult] = useState(null);
const getGroups: GetGroupsType = ({
values,
updateField
}) => {
- // Update current values for QR code preview
- setCurrentValues(values);
-
return [
{
title: 'QR Code Type',
@@ -437,32 +428,29 @@ export default function QRCodeGenerator({ title }: ToolComponentProps) {
];
};
- // Save QR code as image
- const saveQRCode = () => {
- const svg = document.getElementById('qr-code-svg');
- if (!svg) return;
-
- const svgData = new XMLSerializer().serializeToString(svg);
+ const compute = async (options: InitialValuesType) => {
+ const qrValue = formatQRCodeData(options);
+ if (!qrValue) return;
const canvas = document.createElement('canvas');
- const ctx = canvas.getContext('2d');
- const img = new Image();
-
- img.onload = () => {
- canvas.width = img.width;
- canvas.height = img.height;
- ctx?.drawImage(img, 0, 0);
- const pngFile = canvas.toDataURL('image/png');
-
- const downloadLink = document.createElement('a');
- downloadLink.download = 'qrcode.png';
- downloadLink.href = pngFile;
- downloadLink.click();
- };
-
- img.src =
- 'data:image/svg+xml;base64,' +
- btoa(unescape(encodeURIComponent(svgData)));
+ QRCode.toDataURL(
+ canvas,
+ qrValue,
+ {
+ color: {
+ dark: options.fgColor,
+ light: options.bgColor
+ },
+ width: Number(options.size) || 200
+ },
+ async (error, url) => {
+ const res = await fetch(url);
+ const blob = await res.blob();
+ const file = new File([blob], 'Qr code.png', { type: 'image/png' });
+ setResult(file);
+ }
+ );
};
+ const debouncedCompute = useCallback(debounce(compute, 1000), []);
return (
{}}
- inputComponent={
-
- QR Code Preview
-
- {qrValue && (
-
- )}
-
-
-
+ compute={debouncedCompute}
+ resultComponent={
+
}
- resultComponent={null}
toolInfo={{
title: 'QR Code Generator',
description: