├── .babelrc ├── .eslintrc.js ├── .gitignore ├── .npmignore ├── .prettierrc ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── jest.config.js ├── package.json ├── rollup.config.js ├── setup.ts ├── src ├── next-qrcode.ts └── useQRCode.tsx ├── supports ├── create-next-app │ ├── .eslintrc.json │ ├── README.md │ ├── next-env.d.ts │ ├── next.config.js │ ├── package.json │ ├── src │ │ └── app │ │ │ ├── favicon.ico │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ └── tsconfig.json └── create-react-app │ ├── README.md │ ├── package.json │ ├── public │ └── index.html │ └── src │ ├── App.js │ ├── index.css │ ├── index.js │ ├── reportWebVitals.js │ └── setupTests.js ├── tsconfig.jest.json └── tsconfig.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env", 4 | "@babel/preset-react" 5 | ] // , 6 | // "plugins": ["@babel/plugin-proposal-class-properties"] 7 | } 8 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | extends: [ 4 | 'plugin:@typescript-eslint/recommended', 5 | 'plugin:react/recommended', 6 | ], 7 | parserOptions: { 8 | ecmaVersion: 2018, 9 | sourceType: 'module', 10 | }, 11 | plugins: ['react-hooks'], 12 | rules: { 13 | curly: 'error', 14 | '@typescript-eslint/indent': 'off', 15 | '@typescript-eslint/no-non-null-assertion': 'off', 16 | '@typescript-eslint/no-empty-function': 'off', 17 | '@typescript-eslint/ban-ts-comment': 'warn', 18 | '@typescript-eslint/no-explicit-any': 'off', 19 | '@typescript-eslint/explicit-function-return-type': 'off', 20 | '@typescript-eslint/no-empty-function': 'off', 21 | '@typescript-eslint/no-object-literal-type-assertion': 'off', 22 | 'react-hooks/rules-of-hooks': 'error', 23 | 'react-hooks/exhaustive-deps': 'error', 24 | 'react/display-name': 'warn', 25 | 'no-console': 'error', 26 | '@typescript-eslint/no-this-alias': [ 27 | 'error', 28 | { 29 | 'allowDestructuring': true, // Allow `const { props, state } = this`; false by default 30 | 'allowedNames': ['self'] // Allow `const self = this`; `[]` by default 31 | } 32 | ], 33 | '@typescript-eslint/explicit-module-boundary-types': 'off', 34 | '@typescript-eslint/no-var-requires': 'off', 35 | }, 36 | overrides: [ 37 | { 38 | files: ['*.spec.ts', '*.spec.tsx'], 39 | rules: { 40 | // Allow testing runtime errors to suppress TS errors 41 | '@typescript-eslint/ban-ts-comment': 'off', 42 | '@typescript-eslint/explicit-module-boundary-types': 'off', 43 | }, 44 | }, 45 | ], 46 | settings: { 47 | react: { 48 | pragma: 'React', 49 | version: 'detect', 50 | }, 51 | }, 52 | }; 53 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | 6 | # builds 7 | build 8 | dist 9 | 10 | # misc 11 | .DS_Store 12 | .env 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | package-lock.json 23 | 24 | /supports/create-react-app/node_modules 25 | /supports/create-react-app/package-lock.json 26 | 27 | /supports/create-next-app/node_modules 28 | /supports/create-next-app/.next 29 | /supports/create-next-app/package-lock.json 30 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # *** 2 | # * 3 | # * https://docs.npmjs.com/cli/v6/using-npm/developers 4 | # * 5 | # *** 6 | 7 | /src 8 | /supports 9 | /test 10 | .gitignore 11 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 14 4 | - 13 5 | - 12 6 | - 11 7 | - 10 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 2.5.1 (2023-08-01) 2 | 3 | ### ✨ Features 4 | 5 | * Upgrade QRCode options API 6 | 7 | Credits 8 | 9 | * [@Mehrdadx10](https://github.com/mehrdadx10) 10 | 11 | ## 2.5.0 (2023-07-05) 12 | 13 | ### ✨ Features 14 | 15 | * Upgrade dependencies 16 | 17 | Credits 18 | 19 | * [@Bunlong](https://github.com/Bunlong) 20 | 21 | ## 2.4.1 (2023-02-28) 22 | 23 | ### ✨ Features 24 | 25 | * Fix setting logo to center 26 | 27 | Credits 28 | 29 | * [@Bunlong](https://github.com/Bunlong) 30 | 31 | ## 2.4.0 (2022-11-29) 32 | 33 | ### ✨ Features 34 | 35 | * Add SVG 36 | 37 | Credits 38 | 39 | * [@Bunlong](https://github.com/Bunlong) 40 | 41 | ## 2.3.0 (2022-11-14) 42 | 43 | ### ✨ Features 44 | 45 | * Add logo to canvas 46 | 47 | Credits 48 | 49 | * [@Bunlong](https://github.com/Bunlong) 50 | 51 | ## 2.2.2 (2022-10-17) 52 | 53 | ### ✨ Features 54 | 55 | * Update dependencies 56 | 57 | Credits 58 | 59 | * [@Bunlong](https://github.com/Bunlong) 60 | 61 | ## 2.2.0 (2022-08-14) 62 | 63 | ### ✨ Features 64 | 65 | * Update dependencies 66 | 67 | Credits 68 | 69 | * [@Bunlong](https://github.com/Bunlong) 70 | 71 | ## 2.1.0 (2022-06-02) 72 | 73 | ### ✨ Features 74 | 75 | * Support React 18 76 | 77 | Credits 78 | 79 | * [@Bunlong](https://github.com/Bunlong) 80 | 81 | ## 2.0.0 (2022-02-02) 82 | 83 | ### ✨ Features 84 | 85 | * Improve code performance 86 | * Rewrite any existing hooks 87 | 88 | Credits 89 | 90 | * [@Bunlong](https://github.com/Bunlong) 91 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | Our open source projects are no exception. Trust, respect, collaboration and transparency are core values we believe should live and breathe within our projects. Our community welcomes participants from around the world with different experiences, unique perspectives, and great ideas to share. 4 | 5 | ## Our Pledge 6 | 7 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. 8 | 9 | ## Our Standards 10 | 11 | Examples of behavior that contributes to creating a positive environment include: 12 | 13 | * Using welcoming and inclusive language 14 | * Being respectful of differing viewpoints and experiences 15 | * Gracefully accepting constructive criticism 16 | * Attempting collaboration before conflict 17 | * Focusing on what is best for the community 18 | * Showing empathy towards other community members 19 | 20 | Examples of unacceptable behavior by participants include: 21 | 22 | * Violence, threats of violence, or inciting others to commit self-harm 23 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 24 | * Trolling, intentionally spreading misinformation, insulting/derogatory comments, and personal or political attacks 25 | * Public or private harassment 26 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 27 | * Abuse of the reporting process to intentionally harass or exclude others 28 | * Advocating for, or encouraging, any of the above behavior 29 | * Other conduct which could reasonably be considered inappropriate in a professional setting 30 | 31 | ## Our Responsibilities 32 | 33 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 34 | 35 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 36 | 37 | ## Scope 38 | 39 | This Code of Conduct applies within all project spaces, and it also applies when an individual is representing the project or its community in public spaces. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 40 | 41 | ## Enforcement 42 | 43 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at `bunlong.van@gmail.com`. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 44 | 45 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 46 | 47 | ## Attribution 48 | 49 | This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct/) 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Bunlong 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in 8 | all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 11 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 14 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 15 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 16 | THE SOFTWARE. 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # next-qrcode 2 | 3 | React hooks for generating QR code for your next React apps. 4 | 5 | [![downloads](https://img.shields.io/npm/dm/next-qrcode.svg?label=monthly%20downloads)](https://www.npmjs.com/package/next-qrcode) [![downloads](https://img.shields.io/npm/dt/next-qrcode.svg?label=total%20downloads)](https://www.npmjs.com/package/next-qrcode) 6 | 7 | [![NPM](https://img.shields.io/npm/v/next-qrcode.svg)](https://www.npmjs.com/package/next-qrcode) ![npm bundle size](https://img.shields.io/bundlephobia/min/next-qrcode) [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com) 8 | 9 | ## 🎁 Features 10 | 11 | * Render Canvas, SVG and Image 12 | * Support Numeric, Alphanumeric, Kanji and Byte mode 13 | * Support Japanese, Chinese, Greek and Cyrillic characters 14 | * Support multibyte characters (like emojis smile) 15 | 16 | [Live Demo](https://next-qrcode.js.org/demo) 17 | 18 | ## 🔧 Install 19 | 20 | next-qrcode is available on npm. It can be installed with the following command: 21 | 22 | ```js 23 | npm install next-qrcode --save 24 | ``` 25 | 26 | next-qrcode is available on yarn as well. It can be installed with the following command: 27 | 28 | ```js 29 | yarn add next-qrcode --save 30 | ``` 31 | 32 | ## 💡 Canvas 33 | 34 | ### Usage 35 | 36 | ```js 37 | import React from 'react'; 38 | import { useQRCode } from 'next-qrcode'; 39 | 40 | function App() { 41 | const { Canvas } = useQRCode(); 42 | 43 | return ( 44 | 57 | ); 58 | } 59 | 60 | export default App; 61 | ``` 62 | 63 | ### Canvas props 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 |
PropTypeRequireDescription
textstring✔️Text/URL to encode.
optionsoptionsQR code options.
logologoQR code logo.
95 | 96 | ### options 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 |
PropTypeDefaultRequireDescription
errorCorrectionLevelstringMCorrection level. Possible values are low, medium, quartile, high or L, M, Q, H.
marginnumber4Define how much wide the quiet zone should be.
scalenumber4Scale factor. A value of 1 means 1px per modules (black dots).
widthnumber4Forces a specific width for the output image. If width is too small to contain the qr symbol, this option will be ignored. Takes precedence over scale.
color.darkstring#000000ffColor of dark module. Value must be in hex format (RGBA). Note: dark color should always be darker than color.light.
color.lightstring#ffffffffColor of light module. Value must be in hex format (RGBA).
153 | 154 | ### logo 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 |
PropTypeRequireDescription
srcstring✔️The path to the image.
optionsoptionsLogo options.
180 | 181 | ### options 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 |
PropTypeDefaultRequireDescription
widthnumberLogo dimension.
xnumberIf none or undefined, will center.
ynumberIf none or undefined, will center.
217 | 218 | ## 💡 SVG 219 | 220 | ### Usage 221 | 222 | ```js 223 | import React from 'react'; 224 | import { useQRCode } from 'next-qrcode'; 225 | 226 | function App() { 227 | const { SVG } = useQRCode(); 228 | 229 | return ( 230 | 241 | ); 242 | } 243 | 244 | export default App; 245 | ``` 246 | 247 | ### SVG props 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 |
PropTypeRequireDescription
textstring✔️Text/URL to encode.
optionsoptionsQR code options.
273 | 274 | ### options 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 |
PropTypeDefaultRequireDescription
marginnumber4Define how much wide the quiet zone should be.
widthnumber4Forces a specific width for the output image. If width is too small to contain the qr symbol, this option will be ignored. Takes precedence over scale.
color.darkstring#000000ffColor of dark module. Value must be in hex format (RGBA). Note: dark color should always be darker than color.light.
color.lightstring#ffffffffColor of light module. Value must be in hex format (RGBA).
317 | 318 | ## 💡 Image 319 | 320 | ### Usage 321 | 322 | ```js 323 | import React from 'react'; 324 | import { useQRCode } from 'next-qrcode'; 325 | 326 | function App() { 327 | const { Image } = useQRCode(); 328 | 329 | return ( 330 | 345 | ); 346 | } 347 | 348 | export default App; 349 | ``` 350 | 351 | ### Image props 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 |
PropTypeRequireDescription
textstring✔️Text/URL to encode.
optionsobjectQR code options
377 | 378 | ### options 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 |
PropTypeDefaultRequireDescription
typestring (image/png, image/jpeg, image/webp)image/pngImage format.
qualitynumber0.92A Number between 0 and 1 indicating image quality if the type is image/jpeg or image/webp.
errorCorrectionLevelstringMCorrection level. Possible values are low, medium, quartile, high or L, M, Q, H.
marginnumber4Define how much wide the quiet zone should be.
scalenumber4Scale factor. A value of 1 means 1px per modules (black dots).
widthnumber4Forces a specific width for the output image. If width is too small to contain the qr symbol, this option will be ignored. Takes precedence over scale.
color.darkstring#000000ffColor of dark module. Value must be in hex format (RGBA). Note: dark color should always be darker than color.light.
color.lightstring#ffffffffColor of light module. Value must be in hex format (RGBA).
449 | 450 | ## 📜 Changelog 451 | 452 | Latest version 2.5.1 (2023-08-01): 453 | 454 | * Upgrade QRCode options API 455 | 456 | Details changes for each release are documented in the [CHANGELOG.md](https://github.com/Bunlong/next-qrcode/blob/master/CHANGELOG.md). 457 | 458 | ## ❗ Issues 459 | 460 | If you think any of the `next-qrcode` can be improved, please do open a PR with any updates and submit any issues. Also, I will continue to improve this, so you might want to watch/star this repository to revisit. 461 | 462 | ## 🌟 Contribution 463 | 464 | We'd love to have your helping hand on contributions to `next-qrcode` by forking and sending a pull request! 465 | 466 | Your contributions are heartily ♡ welcome, recognized and appreciated. (✿◠‿◠) 467 | 468 | How to contribute: 469 | 470 | - Open pull request with improvements 471 | - Discuss ideas in issues 472 | - Spread the word 473 | - Reach out with any feedback 474 | 475 | ## 🏆 Contributors 476 | 477 | 478 | 479 | 488 | 497 | 506 | 515 | 516 |
480 | 481 | Bunlong 482 |
483 | 484 | Bunlong 485 | 486 |
487 |
489 | 490 | Michael Desa 491 |
492 | 493 | Michael Desa 494 | 495 |
496 |
498 | 499 | Jared Scheib 500 |
501 | 502 | Jared Scheib 503 | 504 |
505 |
507 | 508 | Mehrdad MotaghiFar 509 |
510 | 511 | Mehrdad MotaghiFar 512 | 513 |
514 |
517 | 518 | ## 👨‍👩‍👦 Advertisement 519 | 520 | You maybe interested. 521 | 522 | * [React Patterns](https://github.com/reactpatterns/reactpatterns) – React patterns & techniques to use in development for React Developer. 523 | * [React Papaparse](https://github.com/Bunlong/react-papaparse) – The fastest in-browser CSV (or delimited text) parser for React. 524 | * [Next Share](https://github.com/Bunlong/next-share) – Social media share buttons for your next React apps. 525 | * [Next Time Ago](https://github.com/Bunlong/next-time-ago) – A lightweight tiny time-ago component for your next React apps. 526 | 527 | ## ⚖️ License 528 | 529 | The MIT License [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 530 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | roots: ['/test'], 3 | transform: { 4 | '^.+\\.tsx?$': 'ts-jest', 5 | }, 6 | globals: { 7 | 'ts-jest': { 8 | tsConfig: 'tsconfig.jest.json', 9 | }, 10 | }, 11 | testMatch: ['**/?(*.)+(spec|test).ts?(x)'], 12 | transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$'], 13 | setupFiles: ['/setup.ts'], 14 | moduleFileExtensions: ['ts', 'tsx', 'js'], 15 | }; 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next-qrcode", 3 | "version": "2.5.1", 4 | "description": "React hooks for generating QR code for your next React apps.", 5 | "author": "Bunlong ", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/Bunlong/next-qrcode.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/Bunlong/next-qrcode.git/issues" 13 | }, 14 | "keywords": [ 15 | "react", 16 | "reactjs", 17 | "qrcode", 18 | "next-qrcode", 19 | "next-plugin", 20 | "nextjs-plugin", 21 | "react-qrcode", 22 | "create-next-app", 23 | "create-react-app" 24 | ], 25 | "homepage": "https://next-qrcode.js.org", 26 | "main": "dist/next-qrcode.js", 27 | "module": "dist/next-qrcode.es.js", 28 | "jsnext:main": "dist/next-qrcode.es.js", 29 | "types": "dist/next-qrcode.d.ts", 30 | "@comment unpkg": "dist/next-qrcode.umd.js", 31 | "engines": { 32 | "node": ">=8", 33 | "npm": ">=5" 34 | }, 35 | "scripts": { 36 | "@test": "jest --runInBand", 37 | "build": "rollup -c", 38 | "prettier": "prettier --write './src/*.ts' './src/**/*.ts' './src/**/*.tsx' --config ./.prettierrc", 39 | "lint:check": "eslint ./src --ext .tsx,.ts --report-unused-disable-directives", 40 | "bundlesize": "npm run build && bundlesize", 41 | "dev": "rollup -c -w", 42 | "prepare": "npm run build", 43 | "predeploy": "cd docs && npm install && npm run build", 44 | "deploy": "gh-pages -d docs/build" 45 | }, 46 | "devDependencies": { 47 | "@babel/core": "^7.15.0", 48 | "@babel/plugin-proposal-class-properties": "^7.14.5", 49 | "@babel/preset-env": "^7.15.0", 50 | "@rollup/plugin-babel": "^5.3.0", 51 | "@rollup/plugin-commonjs": "^20.0.0", 52 | "@rollup/plugin-node-resolve": "^13.0.4", 53 | "@types/react": "^18.0.10", 54 | "@types/react-dom": "^18.0.5", 55 | "@types/react-test-renderer": "^18.0.0", 56 | "@typescript-eslint/eslint-plugin": "^4.29.3", 57 | "@typescript-eslint/parser": "^4.29.3", 58 | "bundlesize": "^0.18.1", 59 | "canvas": "^2.10.1", 60 | "eslint": "^7.32.0", 61 | "eslint-plugin-react": "^7.24.0", 62 | "eslint-plugin-react-hooks": "^4.2.0", 63 | "jest": "^27.1.0", 64 | "mutationobserver-shim": "^0.3.7", 65 | "prettier": "^2.3.2", 66 | "react": "^18.1.0", 67 | "react-dom": "^18.1.0", 68 | "react-scripts": "^5.0.1", 69 | "react-test-renderer": "^18.1.0", 70 | "rollup": "^2.56.3", 71 | "rollup-plugin-terser": "^7.0.2", 72 | "rollup-plugin-typescript2": "^0.35.0", 73 | "ts-jest": "^27.0.5", 74 | "tslib": "^2.3.1", 75 | "typescript": "^4.7.2" 76 | }, 77 | "files": [ 78 | "dist" 79 | ], 80 | "dependencies": { 81 | "qrcode": "^1.5.3" 82 | }, 83 | "bundlesize": [ 84 | { 85 | "path": "./dist/*.js", 86 | "maxSize": "21 kB" 87 | }, 88 | { 89 | "path": "./dist/**/*.js", 90 | "maxSize": "21 kB" 91 | }, 92 | { 93 | "path": "./dist/*.ts", 94 | "maxSize": "750 B" 95 | }, 96 | { 97 | "path": "./dist/**/*.ts", 98 | "maxSize": "770 B" 99 | } 100 | ], 101 | "peerDependencies": { 102 | "react": ">=17.0.0" 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import typescript from 'rollup-plugin-typescript2'; 2 | import babel from '@rollup/plugin-babel'; 3 | import commonjs from '@rollup/plugin-commonjs'; 4 | import { terser } from "rollup-plugin-terser"; 5 | 6 | // ======= FOR BUILDING NODE.JS PACKAGE ======= 7 | // import builtins from 'builtin-modules' 8 | // import resolve, { nodeResolve } from '@rollup/plugin-node-resolve'; 9 | // ============================================ 10 | 11 | import pkg from './package.json'; 12 | 13 | export default { 14 | input: 'src/next-qrcode.ts', 15 | output: [ 16 | { 17 | file: pkg.main, 18 | format: 'cjs', 19 | exports: 'named', 20 | }, 21 | { 22 | file: pkg.module, 23 | format: 'esm', 24 | exports: 'named', 25 | }, 26 | // { 27 | // file: `dist/${pkg.name}.min.es.js`, 28 | // format: 'es', 29 | // exports: 'named', 30 | // sourcemap: true 31 | // }, 32 | // { 33 | // name: 'next-qrcode', 34 | // file: `dist/${pkg.name}.umd.js`, 35 | // format: 'umd', 36 | // exports: 'named', 37 | // globals: { 38 | // react: 'React', 39 | // }, 40 | // }, 41 | ], 42 | // external: builtins, 43 | external: ['react', 'react-dom', 'qrcode'], 44 | plugins: [ 45 | typescript({ 46 | tsconfig: './tsconfig.json', 47 | clean: true, 48 | }), 49 | babel({ 50 | exclude: 'node_modules/**' 51 | }), 52 | // resolve({ 53 | // preferBuiltins: true 54 | // }), 55 | // nodeResolve(), 56 | commonjs({ 57 | extensions: ['.js', '.ts', '.tsx'] 58 | }), 59 | terser() 60 | ], 61 | }; 62 | -------------------------------------------------------------------------------- /setup.ts: -------------------------------------------------------------------------------- 1 | // require('mutationobserver-shim'); 2 | -------------------------------------------------------------------------------- /src/next-qrcode.ts: -------------------------------------------------------------------------------- 1 | export { useQRCode } from './useQRCode'; 2 | -------------------------------------------------------------------------------- /src/useQRCode.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | const QRCode = require('qrcode'); 3 | 4 | export interface Colors { 5 | dark?: string; 6 | light?: string; 7 | } 8 | 9 | export interface QRCodeOptions { 10 | type?: string; 11 | quality?: number; 12 | errorCorrectionLevel?: string; 13 | margin?: number; 14 | scale?: number; 15 | width?: number; 16 | color?: Colors; 17 | } 18 | 19 | export interface LogoOptions { 20 | width?: number; 21 | x?: number; 22 | y?: number; 23 | } 24 | 25 | export interface Logo { 26 | src: string; 27 | options?: LogoOptions; 28 | } 29 | 30 | export interface IQRCode { 31 | text: string; 32 | options?: QRCodeOptions; 33 | logo?: Logo; 34 | } 35 | 36 | function useImageComponent() { 37 | const ImageComponent = ({ 38 | text, 39 | options, 40 | }: IQRCode) => { 41 | const inputRef = React.useRef(null); 42 | 43 | React.useEffect( 44 | function () { 45 | if (inputRef && inputRef.current) { 46 | QRCode.toDataURL(text, options, function (error: any, url: string) { 47 | if (error) { 48 | throw error; 49 | } 50 | if (inputRef.current instanceof HTMLImageElement) { 51 | inputRef.current.src = url; 52 | } 53 | }); 54 | } 55 | }, 56 | [text, options, inputRef], 57 | ); 58 | 59 | return ; 60 | }; 61 | 62 | const Image = React.useMemo(() => ImageComponent, []); 63 | 64 | return Image; 65 | } 66 | 67 | function useCanvasComponent() { 68 | const CanvasComponent = ({ 69 | text, 70 | options, 71 | logo, 72 | }: IQRCode) => { 73 | const inputRef = React.useRef(null); 74 | 75 | React.useEffect( 76 | function () { 77 | if (inputRef && inputRef.current) { 78 | QRCode.toCanvas( 79 | inputRef.current, 80 | text, 81 | options, 82 | function (error: Error) { 83 | if (error) { 84 | throw error; 85 | } 86 | }, 87 | ); 88 | 89 | if (logo) { 90 | const crt = inputRef.current; 91 | const ctx = crt.getContext('2d'); 92 | if (ctx) { 93 | const img = new Image(); 94 | img.src = logo.src; 95 | const logoWidth = logo?.options?.width || 30; 96 | if ( 97 | logo?.options?.hasOwnProperty('x') && 98 | logo?.options?.hasOwnProperty('y') 99 | ) { 100 | const x = logo?.options?.x || 0; 101 | const y = logo?.options?.y || 0; 102 | img.onload = function () { 103 | ctx.drawImage(img, x, y, logoWidth, logoWidth); 104 | }; 105 | } 106 | if ( 107 | !logo?.options?.hasOwnProperty('x') || 108 | !logo?.options?.hasOwnProperty('y') || 109 | logo?.options?.x === undefined || 110 | logo?.options?.y === undefined 111 | ) { 112 | let margin = options?.margin; 113 | margin = !margin ? (margin === 0 ? 0 : 32) : margin * 8; 114 | const width = options?.width || 116 + margin; 115 | const center = (width - logoWidth) / 2; 116 | img.onload = function () { 117 | ctx.drawImage(img, center, center, logoWidth, logoWidth); 118 | }; 119 | } 120 | } 121 | } 122 | } 123 | }, 124 | [inputRef, text, options, logo], 125 | ); 126 | 127 | return ; 128 | }; 129 | 130 | const Canvas = React.useMemo(() => CanvasComponent, []); 131 | 132 | return Canvas; 133 | } 134 | 135 | function useSVGComponent() { 136 | const SVGComponent = ({ 137 | text, 138 | options, 139 | }: IQRCode) => { 140 | const inputRef = React.useRef(null); 141 | 142 | React.useEffect(() => { 143 | QRCode.toString(text, options, function (error: Error, svg: string) { 144 | if (error) { 145 | throw error; 146 | } 147 | if (inputRef.current instanceof HTMLDivElement) { 148 | inputRef.current.innerHTML = svg; 149 | } 150 | }); 151 | }, [text, options]); 152 | 153 | return
; 154 | }; 155 | 156 | const SVG = React.useMemo(() => SVGComponent, []); 157 | 158 | return SVG; 159 | } 160 | 161 | export function useQRCode() { 162 | const Image = useImageComponent(); 163 | const Canvas = useCanvasComponent(); 164 | const SVG = useSVGComponent(); 165 | 166 | return { 167 | Image, 168 | Canvas, 169 | SVG, 170 | }; 171 | } 172 | -------------------------------------------------------------------------------- /supports/create-next-app/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /supports/create-next-app/README.md: -------------------------------------------------------------------------------- 1 | ## Create Next App 2 | 3 | First, run the development server: 4 | 5 | ```bash 6 | npm run dev 7 | # or 8 | yarn dev 9 | # or 10 | pnpm dev 11 | ``` 12 | 13 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 14 | -------------------------------------------------------------------------------- /supports/create-next-app/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /supports/create-next-app/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {} 3 | 4 | module.exports = nextConfig 5 | -------------------------------------------------------------------------------- /supports/create-next-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-next-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@types/node": "20.4.5", 13 | "@types/react": "18.2.18", 14 | "@types/react-dom": "18.2.7", 15 | "eslint": "8.46.0", 16 | "eslint-config-next": "13.4.12", 17 | "next": "13.4.12", 18 | "next-qrcode": "file:../..", 19 | "react": "18.2.0", 20 | "react-dom": "18.2.0", 21 | "typescript": "5.1.6" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /supports/create-next-app/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bunlong/next-qrcode/a5c524d208c018baccc36cd3ab5050a5dd33086b/supports/create-next-app/src/app/favicon.ico -------------------------------------------------------------------------------- /supports/create-next-app/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from 'next' 2 | import { Inter } from 'next/font/google' 3 | 4 | const inter = Inter({ subsets: ['latin'] }) 5 | 6 | export const metadata: Metadata = { 7 | title: 'Create Next App', 8 | description: 'Generated by create next app', 9 | } 10 | 11 | export default function RootLayout({ 12 | children, 13 | }: { 14 | children: React.ReactNode 15 | }) { 16 | return ( 17 | 18 | {children} 19 | 20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /supports/create-next-app/src/app/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useQRCode } from 'next-qrcode' 4 | 5 | export default function Home() { 6 | const { 7 | Canvas, 8 | // Image, 9 | // SVG, 10 | } = useQRCode() 11 | 12 | return ( 13 |
14 | 37 | 38 | {/* */} 53 | 54 | {/* */} 65 |
66 | ) 67 | } 68 | -------------------------------------------------------------------------------- /supports/create-next-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "bundler", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true, 17 | "plugins": [ 18 | { 19 | "name": "next" 20 | } 21 | ], 22 | "paths": { 23 | "@/*": ["./src/*"] 24 | } 25 | }, 26 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 27 | "exclude": ["node_modules"] 28 | } 29 | -------------------------------------------------------------------------------- /supports/create-react-app/README.md: -------------------------------------------------------------------------------- 1 | # Create React App 2 | 3 | In the project directory, you can run: 4 | 5 | ### `npm start` 6 | 7 | Runs the app in the development mode.\ 8 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 9 | -------------------------------------------------------------------------------- /supports/create-react-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-react-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.17.0", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "next-qrcode": "file:../..", 10 | "react": "^18.2.0", 11 | "react-dom": "^18.2.0", 12 | "react-scripts": "5.0.1", 13 | "web-vitals": "^2.1.4" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": [ 23 | "react-app", 24 | "react-app/jest" 25 | ] 26 | }, 27 | "browserslist": { 28 | "production": [ 29 | ">0.2%", 30 | "not dead", 31 | "not op_mini all" 32 | ], 33 | "development": [ 34 | "last 1 chrome version", 35 | "last 1 firefox version", 36 | "last 1 safari version" 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /supports/create-react-app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /supports/create-react-app/src/App.js: -------------------------------------------------------------------------------- 1 | import { useQRCode } from 'next-qrcode'; 2 | 3 | function App() { 4 | const { SVG } = useQRCode(); 5 | 6 | return ( 7 |
8 | 23 |
24 | ); 25 | } 26 | 27 | export default App; 28 | -------------------------------------------------------------------------------- /supports/create-react-app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /supports/create-react-app/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const root = ReactDOM.createRoot(document.getElementById('root')); 8 | root.render( 9 | 10 | 11 | 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /supports/create-react-app/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /supports/create-react-app/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /tsconfig.jest.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "commonjs", 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | // "incremental": true, /* Enable incremental compilation */ 5 | "target": "es5", /* Specify ECMAScript target version: 'es3' (default), 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', or 'esnext'. */ 6 | "module": "es2015", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 7 | "lib": ["es2017", "es7", "es6", "es5", "dom"], /* Specify library files to be included in the compilation. */ 8 | "allowJs": false, /* Allow javascript files to be compiled. */ 9 | // "checkJs": true, /* Report errors in .js files. */ 10 | "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 11 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 12 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 13 | "sourceMap": true, /* Generates corresponding '.map' file. */ 14 | // "outFile": "./", /* Concatenate and emit output to single file. */ 15 | "outDir": "./dist", /* Redirect output structure to the directory. */ 16 | "rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 17 | // "composite": true, /* Enable project compilation */ 18 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 19 | // "removeComments": true, /* Do not emit comments to output. */ 20 | "noEmit": true, /* Do not emit outputs. */ 21 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 22 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 23 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 24 | 25 | /* Strict Type-Checking Options */ 26 | "strict": true, /* Enable all strict type-checking options. */ 27 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 28 | "strictNullChecks": true, /* Enable strict null checks. */ 29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 30 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 34 | 35 | /* Additional Checks */ 36 | "noUnusedLocals": true, /* Report errors on unused locals. */ 37 | "noUnusedParameters": true, /* Report errors on unused parameters. */ 38 | "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 39 | "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 40 | 41 | /* Module Resolution Options */ 42 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 43 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 44 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 45 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 46 | // "typeRoots": [], /* List of folders to include type definitions from. */ 47 | // "types": [], /* Type declaration files to be included in compilation. */ 48 | "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 49 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 50 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 51 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 52 | 53 | /* Source Map Options */ 54 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 55 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 56 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 57 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 58 | 59 | /* Experimental Options */ 60 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 61 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 62 | 63 | /* Advanced Options */ 64 | // "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 65 | }, 66 | "exclude": [ 67 | "node_modules", 68 | "test", 69 | "dist", 70 | "docs", 71 | "supports", 72 | "setup.ts", 73 | ] 74 | } 75 | --------------------------------------------------------------------------------