{"_id":"coolqr","_rev":"45-0b56c83bb3ad93e1b59767646d146926","name":"coolqr","dist-tags":{"latest":"2.1.0"},"versions":{"2.0.0":{"name":"coolqr","version":"2.0.0","keywords":["qr","qrcode","qr-code"],"author":{"name":"nazmirket"},"license":"ISC","_id":"coolqr@2.0.0","maintainers":[{"name":"nazmiyilmaz","email":"nazmi.yilmaz@agu.edu.tr"}],"dist":{"shasum":"d96e2f72bb4af895d597d40c6ec89e273ebc9b92","tarball":"https://registry.npmjs.org/coolqr/-/coolqr-2.0.0.tgz","fileCount":23,"integrity":"sha512-qqSGWQfLYmPxwD6cJZLvTWjEDlGnZfRJCtaZX2PTXm2m3spcUv7tSq5F/ImHelfBr9HqeFz9t9HLQiHG3DiL1A==","signatures":[{"sig":"MEUCIG/BhTs1tJaBT+SOvo3umClQba+PzK8f0balaeMBQPL8AiEA/qT87CRQzGzK+Lxraad77nVyxuPqkvU2MEO6V5TuFe0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":46006},"main":"dist/src/CoolQR.js","_from":"file:coolqr-2.0.0.tgz","types":"dist/src/CoolQR.d.ts","scripts":{"build":"rimraf dist && tsc"},"_npmUser":{"name":"nazmiyilmaz","email":"nazmi.yilmaz@agu.edu.tr"},"_resolved":"/private/var/folders/4z/v18wnt491wd53z5kctrk2rgc0000gn/T/a9a78e92541c05a096a791a49790c6d8/coolqr-2.0.0.tgz","_integrity":"sha512-qqSGWQfLYmPxwD6cJZLvTWjEDlGnZfRJCtaZX2PTXm2m3spcUv7tSq5F/ImHelfBr9HqeFz9t9HLQiHG3DiL1A==","_npmVersion":"10.2.4","description":"This is a custom QR code generator.","directories":{},"_nodeVersion":"20.11.1","dependencies":{"konva":"^9.2.0","qrcode":"^1.5.3"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^22.1.0","canvas":"^2.11.2","eslint":"^8.36.0","rimraf":"^5.0.0","ts-node":"^10.9.1","prettier":"^3.0.0","typescript":"^5.0.4","@types/node":"^18.16.3","@types/jsdom":"^21.1.2","@types/qrcode":"^1.5.1","eslint-plugin-n":"^15.6.1","@tsconfig/node18":"^2.0.0","eslint-config-prettier":"^8.8.0","eslint-plugin-prettier":"^4.2.1"},"_npmOperationalInternal":{"tmp":"tmp/coolqr_2.0.0_1752866745790_0.7187063294599094","host":"s3://npm-registry-packages-npm-production"}},"2.0.1":{"name":"coolqr","version":"2.0.1","keywords":["qr","qrcode","qr-code"],"author":{"name":"nazmirket"},"license":"ISC","_id":"coolqr@2.0.1","maintainers":[{"name":"nazmiyilmaz","email":"nazmi.yilmaz@agu.edu.tr"}],"dist":{"shasum":"241bc0791f8835c6731b2e0620203b225e4968e8","tarball":"https://registry.npmjs.org/coolqr/-/coolqr-2.0.1.tgz","fileCount":23,"integrity":"sha512-5ghoSm+cnOR2vZNQqWOXO9LzrL2UJ63DGcT9UAe5QjXN5CTlJj20mpH8xO8m6/AnH1Jtuc4Aq3/YOHxFMIQPlQ==","signatures":[{"sig":"MEUCIH7bQQCkXO4SaDRVR2lNw0VEXUKkAPAYetoX6uiahemMAiEA2mf1dkeMtnPDT94ZAU4xYaukS3KIeIyLSnxJ17nJbPE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":46212},"main":"dist/src/CoolQR.js","_from":"file:coolqr-2.0.1.tgz","types":"dist/src/CoolQR.d.ts","scripts":{"build":"rimraf dist && tsc"},"_npmUser":{"name":"nazmiyilmaz","email":"nazmi.yilmaz@agu.edu.tr"},"_resolved":"/private/var/folders/4z/v18wnt491wd53z5kctrk2rgc0000gn/T/cc6863923c5a0b9c501d021128e677a3/coolqr-2.0.1.tgz","_integrity":"sha512-5ghoSm+cnOR2vZNQqWOXO9LzrL2UJ63DGcT9UAe5QjXN5CTlJj20mpH8xO8m6/AnH1Jtuc4Aq3/YOHxFMIQPlQ==","_npmVersion":"10.2.4","description":"This is a custom QR code generator.","directories":{},"_nodeVersion":"20.11.1","dependencies":{"konva":"^9.2.0","qrcode":"^1.5.3"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^22.1.0","canvas":"^2.11.2","eslint":"^8.36.0","rimraf":"^5.0.0","ts-node":"^10.9.1","prettier":"^3.0.0","typescript":"^5.0.4","@types/node":"^18.16.3","@types/jsdom":"^21.1.2","@types/qrcode":"^1.5.1","eslint-plugin-n":"^15.6.1","@tsconfig/node18":"^2.0.0","eslint-config-prettier":"^8.8.0","eslint-plugin-prettier":"^4.2.1"},"_npmOperationalInternal":{"tmp":"tmp/coolqr_2.0.1_1752871750713_0.9952666383608109","host":"s3://npm-registry-packages-npm-production"}},"2.1.0":{"name":"coolqr","version":"2.1.0","author":{"name":"nazmirket"},"description":"This is a custom QR code generator.","main":"dist/CoolQR.js","types":"dist/CoolQR.d.ts","packageManager":"pnpm@10.33.0","scripts":{"build":"rimraf dist && tsc","lint":"eslint .","test":"npm run build && node --test tests/*.test.cjs && npm run test:types","test:types":"tsc -p tests/tsconfig.json","verify":"npm run lint && npm test","prepack":"npm run build","prepublishOnly":"npm run verify","release":"npm publish"},"keywords":["qr","qrcode","qr-code"],"license":"ISC","dependencies":{"konva":"^9.2.0","qrcode":"^1.5.3"},"devDependencies":{"@tsconfig/node18":"^2.0.0","@types/node":"^18.16.3","@types/qrcode":"^1.5.1","@typescript-eslint/eslint-plugin":"^6.21.0","@typescript-eslint/parser":"^6.21.0","eslint":"^8.57.1","eslint-config-prettier":"^9.1.2","eslint-plugin-n":"^16.6.2","eslint-plugin-prettier":"^5.5.4","prettier":"^3.6.2","rimraf":"^5.0.0","typescript":"^5.0.4"},"_id":"coolqr@2.1.0","_integrity":"sha512-vk8KTiRFpf0/h02FVdYocLDDRDNEsdxvJoQeiNEdYkNlukNxDykvbvPpWv9t4iZbzhSq9HpKVBeQ+LSa1pBufg==","_resolved":"/Users/nazmiyilmaz/Projects/coolqr/coolqr-2.1.0.tgz","_from":"file:coolqr-2.1.0.tgz","_nodeVersion":"20.19.5","_npmVersion":"11.6.3","dist":{"integrity":"sha512-vk8KTiRFpf0/h02FVdYocLDDRDNEsdxvJoQeiNEdYkNlukNxDykvbvPpWv9t4iZbzhSq9HpKVBeQ+LSa1pBufg==","shasum":"e66e446e4e7ba3b2f141c95c437bcb9ac16389b5","tarball":"https://registry.npmjs.org/coolqr/-/coolqr-2.1.0.tgz","fileCount":23,"unpackedSize":37477,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC1to2wUQJgZBzx/GPowzBsuW9UmZcICjxtloPeJPo62AIhAOCcXmzZgsTZRK0HycDKDkPLJIuwN6rOLaGo7rFD26Wp"}]},"_npmUser":{"name":"nazmiyilmaz","email":"nazmi.yilmaz@agu.edu.tr"},"directories":{},"maintainers":[{"name":"nazmiyilmaz","email":"nazmi.yilmaz@agu.edu.tr"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/coolqr_2.1.0_1785487660076_0.3348120332480067"},"_hasShrinkwrap":false}},"time":{"created":"2025-07-18T19:25:45.789Z","modified":"2026-07-31T08:47:40.397Z","1.0.0":"2023-07-17T18:29:25.089Z","1.0.1":"2023-07-17T18:55:10.510Z","1.0.2":"2023-07-17T18:55:55.505Z","1.0.3":"2023-07-17T18:56:30.576Z","1.0.4":"2023-07-17T18:57:02.220Z","1.1.0":"2023-07-18T19:45:24.373Z","1.1.1":"2023-07-18T19:57:34.771Z","1.1.2":"2023-07-20T09:33:18.697Z","1.1.3":"2023-07-23T09:19:25.463Z","1.2.0":"2023-07-23T09:45:03.879Z","1.2.1":"2023-07-23T09:47:59.705Z","1.2.2":"2023-07-23T09:51:54.436Z","1.2.5":"2023-07-23T09:55:49.010Z","1.3.0":"2023-07-23T14:09:48.528Z","1.3.1":"2023-07-23T19:12:51.882Z","1.3.2":"2023-07-23T19:37:50.591Z","1.3.3":"2023-07-23T19:48:42.964Z","1.3.4":"2023-07-23T19:51:25.848Z","1.3.5":"2023-07-23T19:59:36.876Z","1.3.6":"2023-07-23T20:00:22.803Z","1.3.7":"2023-07-23T20:03:38.512Z","1.3.8":"2023-08-14T23:18:31.008Z","1.4.0":"2023-09-03T09:31:40.970Z","1.5.0":"2023-09-03T09:36:25.841Z","1.6.0":"2023-09-03T09:46:17.342Z","1.7.0":"2023-09-03T09:52:24.948Z","1.8.0":"2023-09-03T11:08:31.990Z","1.8.1":"2023-09-03T11:12:31.990Z","1.8.2":"2023-09-03T11:12:54.452Z","1.8.3":"2023-09-03T11:24:34.390Z","1.8.4":"2023-09-03T11:27:55.480Z","1.8.5":"2023-09-03T12:29:01.728Z","1.8.6":"2023-09-03T12:30:34.298Z","1.8.7":"2023-09-09T13:21:54.106Z","1.8.8":"2023-09-09T13:24:55.292Z","1.8.9":"2023-09-09T13:26:40.154Z","1.9.0":"2023-09-17T06:56:43.855Z","1.9.1":"2023-09-17T07:03:43.652Z","1.9.2":"2023-09-17T07:07:05.048Z","2.0.0":"2025-07-18T19:25:45.997Z","2.0.1":"2025-07-18T20:49:10.909Z","2.1.0":"2026-07-31T08:47:40.218Z"},"author":{"name":"nazmirket"},"license":"ISC","keywords":["qr","qrcode","qr-code"],"description":"This is a custom QR code generator.","maintainers":[{"name":"nazmiyilmaz","email":"nazmi.yilmaz@agu.edu.tr"}],"readme":"# CoolQR\n\nCoolQR is a browser-side TypeScript library for rendering customizable QR codes with\nKonva. It supports styled finder eyes, multiple dot shapes, solid or gradient fills,\nand optional center images. Use it in browser applications or browser-targeted\nbundles; Node canvas rendering is outside the supported runtime.\n\n![Demo](https://i.imgur.com/QQiLsIy.png)\n\n[Live demo](https://qr.mirket.dev/)\n\n## Installation\n\n```bash\nnpm install coolqr\n```\n\n## Usage\n\n```typescript\nimport CoolQR, { type QROptions } from 'coolqr'\n\nconst options = {\n\tsize: 512,\n\tbackground: {\n\t\tfill: {\n\t\t\ttype: 'solid',\n\t\t\tcolor: '#ffffff',\n\t\t},\n\t},\n\teyes: {\n\t\touter: {\n\t\t\tshape: 'rounded',\n\t\t\tfill: {\n\t\t\t\ttype: 'solid',\n\t\t\t\tcolor: '#111827',\n\t\t\t},\n\t\t},\n\t\tinner: {\n\t\t\tshape: 'circle',\n\t\t\tfill: {\n\t\t\t\ttype: 'solid',\n\t\t\t\tcolor: '#111827',\n\t\t\t},\n\t\t},\n\t},\n\tdots: {\n\t\tshape: 'diamond',\n\t\tfill: {\n\t\t\ttype: 'gradient',\n\t\t\tcolor: '#111827',\n\t\t\tgradient: {\n\t\t\t\ttype: 'linear',\n\t\t\t\tcolors: ['#ef4444', '#2563eb'],\n\t\t\t},\n\t\t},\n\t},\n\timage: {\n\t\tsrc: '/logo.png',\n\t\tmargin: 12,\n\t\thideDots: true,\n\t},\n} satisfies QROptions\n\nconst container = document.getElementById('qr-container') as HTMLDivElement\nconst stage = await CoolQR.draw('https://example.com', container, options)\n```\n\n`size` is the exact width and height of the generated canvas in pixels. All modules\nand decorative geometry scale proportionally. When an optional image cannot load,\nCoolQR renders the QR code without the image and keeps the underlying dots visible.\n\nDestroy a stage when replacing it or unmounting its container:\n\n```typescript\nstage.destroy()\n```\n\n## API\n\n### `CoolQR.draw(data, container, options)`\n\nRenders the supplied data and resolves with a `Konva.Stage`.\n\n- `data`: String encoded into the QR code.\n- `container`: Browser `HTMLDivElement` that owns the stage.\n- `options`: A `QROptions` object.\n\nThe named `draw` export is also available.\n\n### `QROptions`\n\n- `size`: Positive output width and height in pixels.\n- `background.fill`: Canvas fill.\n- `eyes.outer.shape`: `square`, `circle`, `rounded`, `rounded2`, `rounded3`,\n  `rounded4`, `rounded5`, `rounded6`, or `squarecircle`.\n- `eyes.inner.shape` and `dots.shape`: `square`, `circle`, `diamond`, `rounded`,\n  `rounded2`, `rounded3`, `rounded4`, `sun`, `cross`, `hexagon`, or `octagon`.\n- `image.src`: Optional same-origin or CORS-enabled image URL.\n- `image.margin`: Non-negative image inset in pixels.\n- `image.hideDots`: Removes covered modules only after the image loads successfully.\n\n### `Fill`\n\nSolid fill:\n\n```typescript\nconst fill = {\n\ttype: 'solid',\n\tcolor: '#111827',\n} satisfies Fill\n```\n\nGradient fill:\n\n```typescript\nconst fill = {\n\ttype: 'gradient',\n\tcolor: '#111827',\n\tgradient: {\n\t\ttype: 'radial',\n\t\tcolors: ['#f43f5e', '#8b5cf6', '#2563eb'],\n\t},\n} satisfies Fill\n```\n\nGradient colors are distributed evenly and require at least two entries. `color`\nremains the fallback color for consumers that transform options before rendering.\n\n## Development\n\n```bash\npnpm install\npnpm verify\n\ncd demo\npnpm install\npnpm verify\n```\n\n`pnpm verify` runs linting, runtime tests, consumer declaration tests, and builds.\n\n## Docker Deployment\n\nThe production demo runs as an unprivileged, read-only container. Compose binds the\napplication only to loopback on port `9491`, allowing the host's Nginx service to\ncontinue handling TLS.\n\n```bash\ndocker compose build\ndocker compose up -d\ndocker compose ps\ncurl --fail http://127.0.0.1:9491/\n```\n\nUse `COOLQR_PORT` to select a different loopback port for validation:\n\n```bash\nCOOLQR_PORT=9492 docker compose -p coolqr-staging up -d --build\n```\n\n## Release\n\n```bash\npnpm verify\nnpm pack --dry-run\nnpm run release\n```\n\n`prepack` always rebuilds the package, and `prepublishOnly` runs the full verification\nsuite without recursively invoking `npm publish`.\n\n## License\n\nISC\n","readmeFilename":"README.MD"}