UNPKG

@larscom/ng-qrcode-svg

Version:

Simple QR code generator (SVG only) for Angular

102 lines 11.1 kB
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; import { Ecc, QrCode } from './qrcode-generator'; import * as i0 from "@angular/core"; const VALID_COLOR_REGEX = /^#(?:[0-9a-fA-F]{3,4}){1,2}$/; export class QrcodeSvgComponent { constructor() { this.ecl = 'medium'; this.borderSize = 2; this.size = 250; this.backgroundColor = '#FFFFFF'; this.foregroundColor = '#000000'; } ngOnChanges(changes) { this.validateInputs(); if (this.skipUpdate(changes)) return; this.qr = QrCode.encodeText(this.value, Ecc[this.ecl]); const s = this.qr.size + this.borderSize * 2; this.viewBox = `0 0 ${s} ${s}`; this.d = this.createD(this.borderSize); } validateInputs() { if (!this.value) throw Error('[@larscom/ng-qrcode-svg] You must provide a value!'); if (!VALID_COLOR_REGEX.test(this.backgroundColor)) throw Error('[@larscom/ng-qrcode-svg] You must provide a valid backgroundColor (HEX RGB) eg: #FFFFFF'); if (!VALID_COLOR_REGEX.test(this.foregroundColor)) throw Error('[@larscom/ng-qrcode-svg] You must provide a valid foregroundColor (HEX RGB) eg: #000000'); } skipUpdate({ backgroundColor, foregroundColor, size }) { const bgColorChanged = backgroundColor?.currentValue && !backgroundColor?.firstChange; const fgColorChanged = foregroundColor?.currentValue && !foregroundColor.firstChange; const sizeChanged = size?.currentValue && !size.firstChange; return bgColorChanged || fgColorChanged || sizeChanged; } createD(borderSize) { const parts = []; for (let y = 0; y < this.qr.size; y++) { for (let x = 0; x < this.qr.size; x++) { if (this.qr.getModule(x, y)) parts.push(`M${x + borderSize},${y + borderSize}h1v1h-1z`); } } return parts.join(' '); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: QrcodeSvgComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: QrcodeSvgComponent, isStandalone: true, selector: "qrcode-svg", inputs: { value: "value", ecl: "ecl", borderSize: "borderSize", size: "size", backgroundColor: "backgroundColor", foregroundColor: "foregroundColor", alt: "alt", ariaLabel: "ariaLabel" }, usesOnChanges: true, ngImport: i0, template: ` <svg xmlns="http://www.w3.org/2000/svg" version="1.1" stroke="none" [attr.alt]="alt" [attr.aria-label]="ariaLabel" [attr.width]="size" [attr.height]="size" [attr.viewBox]="viewBox" > <rect width="100%" height="100%" [attr.fill]="backgroundColor" /> <path [attr.d]="d" [attr.fill]="foregroundColor" /> </svg> `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: QrcodeSvgComponent, decorators: [{ type: Component, args: [{ selector: 'qrcode-svg', standalone: true, template: ` <svg xmlns="http://www.w3.org/2000/svg" version="1.1" stroke="none" [attr.alt]="alt" [attr.aria-label]="ariaLabel" [attr.width]="size" [attr.height]="size" [attr.viewBox]="viewBox" > <rect width="100%" height="100%" [attr.fill]="backgroundColor" /> <path [attr.d]="d" [attr.fill]="foregroundColor" /> </svg> `, changeDetection: ChangeDetectionStrategy.OnPush }] }], propDecorators: { value: [{ type: Input }], ecl: [{ type: Input }], borderSize: [{ type: Input }], size: [{ type: Input }], backgroundColor: [{ type: Input }], foregroundColor: [{ type: Input }], alt: [{ type: Input }], ariaLabel: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXJjb2RlLXN2Zy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy1xcmNvZGUtc3ZnL3NyYy9saWIvcXJjb2RlLXN2Zy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQTRCLE1BQU0sZUFBZSxDQUFBO0FBQ25HLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sb0JBQW9CLENBQUE7O0FBRWhELE1BQU0saUJBQWlCLEdBQUcsOEJBQThCLENBQUE7QUFzQnhELE1BQU0sT0FBTyxrQkFBa0I7SUFwQi9CO1FBc0JXLFFBQUcsR0FBMkMsUUFBUSxDQUFBO1FBQ3RELGVBQVUsR0FBRyxDQUFDLENBQUE7UUFFZCxTQUFJLEdBQW9CLEdBQUcsQ0FBQTtRQUMzQixvQkFBZSxHQUFHLFNBQVMsQ0FBQTtRQUMzQixvQkFBZSxHQUFHLFNBQVMsQ0FBQTtLQWdEckM7SUF0Q0MsV0FBVyxDQUFDLE9BQXNCO1FBQ2hDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQTtRQUVyQixJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDO1lBQUUsT0FBTTtRQUVwQyxJQUFJLENBQUMsRUFBRSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7UUFDdEQsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUE7UUFDNUMsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQTtRQUM5QixJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFBO0lBQ3hDLENBQUM7SUFFTyxjQUFjO1FBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSztZQUFFLE1BQU0sS0FBSyxDQUFDLG9EQUFvRCxDQUFDLENBQUE7UUFFbEYsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDO1lBQy9DLE1BQU0sS0FBSyxDQUFDLHlGQUF5RixDQUFDLENBQUE7UUFFeEcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDO1lBQy9DLE1BQU0sS0FBSyxDQUFDLHlGQUF5RixDQUFDLENBQUE7SUFDMUcsQ0FBQztJQUVPLFVBQVUsQ0FBQyxFQUFFLGVBQWUsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFpQjtRQUMxRSxNQUFNLGNBQWMsR0FBRyxlQUFlLEVBQUUsWUFBWSxJQUFJLENBQUMsZUFBZSxFQUFFLFdBQVcsQ0FBQTtRQUNyRixNQUFNLGNBQWMsR0FBRyxlQUFlLEVBQUUsWUFBWSxJQUFJLENBQUMsZUFBZSxDQUFDLFdBQVcsQ0FBQTtRQUNwRixNQUFNLFdBQVcsR0FBRyxJQUFJLEVBQUUsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQTtRQUUzRCxPQUFPLGNBQWMsSUFBSSxjQUFjLElBQUksV0FBVyxDQUFBO0lBQ3hELENBQUM7SUFFTyxPQUFPLENBQUMsVUFBa0I7UUFDaEMsTUFBTSxLQUFLLEdBQWEsRUFBRSxDQUFBO1FBQzFCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3RDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUN0QyxJQUFJLElBQUksQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7b0JBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxVQUFVLElBQUksQ0FBQyxHQUFHLFVBQVUsVUFBVSxDQUFDLENBQUE7WUFDekYsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUE7SUFDeEIsQ0FBQzsrR0F0RFUsa0JBQWtCO21HQUFsQixrQkFBa0IsdVJBakJuQjs7Ozs7Ozs7Ozs7Ozs7R0FjVDs7NEZBR1Usa0JBQWtCO2tCQXBCOUIsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsWUFBWTtvQkFDdEIsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7R0FjVDtvQkFDRCxlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTtpQkFDaEQ7OEJBRVUsS0FBSztzQkFBYixLQUFLO2dCQUNHLEdBQUc7c0JBQVgsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUVHLElBQUk7c0JBQVosS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUNHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBRUcsR0FBRztzQkFBWCxLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBJbnB1dCwgT25DaGFuZ2VzLCBTaW1wbGVDaGFuZ2VzIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSdcbmltcG9ydCB7IEVjYywgUXJDb2RlIH0gZnJvbSAnLi9xcmNvZGUtZ2VuZXJhdG9yJ1xuXG5jb25zdCBWQUxJRF9DT0xPUl9SRUdFWCA9IC9eIyg/OlswLTlhLWZBLUZdezMsNH0pezEsMn0kL1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdxcmNvZGUtc3ZnJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8c3ZnXG4gICAgICB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCJcbiAgICAgIHZlcnNpb249XCIxLjFcIlxuICAgICAgc3Ryb2tlPVwibm9uZVwiXG4gICAgICBbYXR0ci5hbHRdPVwiYWx0XCJcbiAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiYXJpYUxhYmVsXCJcbiAgICAgIFthdHRyLndpZHRoXT1cInNpemVcIlxuICAgICAgW2F0dHIuaGVpZ2h0XT1cInNpemVcIlxuICAgICAgW2F0dHIudmlld0JveF09XCJ2aWV3Qm94XCJcbiAgICA+XG4gICAgICA8cmVjdCB3aWR0aD1cIjEwMCVcIiBoZWlnaHQ9XCIxMDAlXCIgW2F0dHIuZmlsbF09XCJiYWNrZ3JvdW5kQ29sb3JcIiAvPlxuICAgICAgPHBhdGggW2F0dHIuZF09XCJkXCIgW2F0dHIuZmlsbF09XCJmb3JlZ3JvdW5kQ29sb3JcIiAvPlxuICAgIDwvc3ZnPlxuICBgLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaFxufSlcbmV4cG9ydCBjbGFzcyBRcmNvZGVTdmdDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuICBASW5wdXQoKSB2YWx1ZSE6IHN0cmluZ1xuICBASW5wdXQoKSBlY2w6ICdsb3cnIHwgJ21lZGl1bScgfCAncXVhcnRpbGUnIHwgJ2hpZ2gnID0gJ21lZGl1bSdcbiAgQElucHV0KCkgYm9yZGVyU2l6ZSA9IDJcblxuICBASW5wdXQoKSBzaXplOiBzdHJpbmcgfCBudW1iZXIgPSAyNTBcbiAgQElucHV0KCkgYmFja2dyb3VuZENvbG9yID0gJyNGRkZGRkYnXG4gIEBJbnB1dCgpIGZvcmVncm91bmRDb2xvciA9ICcjMDAwMDAwJ1xuXG4gIEBJbnB1dCgpIGFsdDogc3RyaW5nIHwgdW5kZWZpbmVkXG4gIEBJbnB1dCgpIGFyaWFMYWJlbDogc3RyaW5nIHwgdW5kZWZpbmVkXG5cbiAgcHJpdmF0ZSBxciE6IFFyQ29kZVxuXG4gIHZpZXdCb3ghOiBzdHJpbmdcbiAgZCE6IHN0cmluZ1xuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICB0aGlzLnZhbGlkYXRlSW5wdXRzKClcblxuICAgIGlmICh0aGlzLnNraXBVcGRhdGUoY2hhbmdlcykpIHJldHVyblxuXG4gICAgdGhpcy5xciA9IFFyQ29kZS5lbmNvZGVUZXh0KHRoaXMudmFsdWUsIEVjY1t0aGlzLmVjbF0pXG4gICAgY29uc3QgcyA9IHRoaXMucXIuc2l6ZSArIHRoaXMuYm9yZGVyU2l6ZSAqIDJcbiAgICB0aGlzLnZpZXdCb3ggPSBgMCAwICR7c30gJHtzfWBcbiAgICB0aGlzLmQgPSB0aGlzLmNyZWF0ZUQodGhpcy5ib3JkZXJTaXplKVxuICB9XG5cbiAgcHJpdmF0ZSB2YWxpZGF0ZUlucHV0cygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMudmFsdWUpIHRocm93IEVycm9yKCdbQGxhcnNjb20vbmctcXJjb2RlLXN2Z10gWW91IG11c3QgcHJvdmlkZSBhIHZhbHVlIScpXG5cbiAgICBpZiAoIVZBTElEX0NPTE9SX1JFR0VYLnRlc3QodGhpcy5iYWNrZ3JvdW5kQ29sb3IpKVxuICAgICAgdGhyb3cgRXJyb3IoJ1tAbGFyc2NvbS9uZy1xcmNvZGUtc3ZnXSBZb3UgbXVzdCBwcm92aWRlIGEgdmFsaWQgYmFja2dyb3VuZENvbG9yIChIRVggUkdCKSBlZzogI0ZGRkZGRicpXG5cbiAgICBpZiAoIVZBTElEX0NPTE9SX1JFR0VYLnRlc3QodGhpcy5mb3JlZ3JvdW5kQ29sb3IpKVxuICAgICAgdGhyb3cgRXJyb3IoJ1tAbGFyc2NvbS9uZy1xcmNvZGUtc3ZnXSBZb3UgbXVzdCBwcm92aWRlIGEgdmFsaWQgZm9yZWdyb3VuZENvbG9yIChIRVggUkdCKSBlZzogIzAwMDAwMCcpXG4gIH1cblxuICBwcml2YXRlIHNraXBVcGRhdGUoeyBiYWNrZ3JvdW5kQ29sb3IsIGZvcmVncm91bmRDb2xvciwgc2l6ZSB9OiBTaW1wbGVDaGFuZ2VzKTogYm9vbGVhbiB7XG4gICAgY29uc3QgYmdDb2xvckNoYW5nZWQgPSBiYWNrZ3JvdW5kQ29sb3I/LmN1cnJlbnRWYWx1ZSAmJiAhYmFja2dyb3VuZENvbG9yPy5maXJzdENoYW5nZVxuICAgIGNvbnN0IGZnQ29sb3JDaGFuZ2VkID0gZm9yZWdyb3VuZENvbG9yPy5jdXJyZW50VmFsdWUgJiYgIWZvcmVncm91bmRDb2xvci5maXJzdENoYW5nZVxuICAgIGNvbnN0IHNpemVDaGFuZ2VkID0gc2l6ZT8uY3VycmVudFZhbHVlICYmICFzaXplLmZpcnN0Q2hhbmdlXG5cbiAgICByZXR1cm4gYmdDb2xvckNoYW5nZWQgfHwgZmdDb2xvckNoYW5nZWQgfHwgc2l6ZUNoYW5nZWRcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlRChib3JkZXJTaXplOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGNvbnN0IHBhcnRzOiBzdHJpbmdbXSA9IFtdXG4gICAgZm9yIChsZXQgeSA9IDA7IHkgPCB0aGlzLnFyLnNpemU7IHkrKykge1xuICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCB0aGlzLnFyLnNpemU7IHgrKykge1xuICAgICAgICBpZiAodGhpcy5xci5nZXRNb2R1bGUoeCwgeSkpIHBhcnRzLnB1c2goYE0ke3ggKyBib3JkZXJTaXplfSwke3kgKyBib3JkZXJTaXplfWgxdjFoLTF6YClcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHBhcnRzLmpvaW4oJyAnKVxuICB9XG59XG4iXX0=