UNPKG

ngx-kjua

Version:

Angular QR-Code generator component.

1,043 lines (1,029 loc) 32.2 kB
import * as i0 from '@angular/core'; import { EventEmitter, booleanAttribute, ViewChild, Output, Input, ChangeDetectionStrategy, Component } from '@angular/core'; import qrcode from 'qrcode-generator'; const win = window; // eslint-disable-line no-undef const doc = win.document; const dpr = win.devicePixelRatio || 1; const SVG_NS = "http://www.w3.org/2000/svg"; const get_attr = (el, key) => el.getAttribute(key); const set_attrs = (el, obj) => { Object.keys(obj || {}).forEach((key) => { el.setAttribute(key, obj[key]); }); return el; }; const create_el = (name, obj) => set_attrs(doc.createElement(name), obj); const create_svg_el = (name, obj) => set_attrs(doc.createElementNS(SVG_NS, name), obj); const create_canvas = (size, ratio) => { const canvas = create_el("canvas", { width: size * ratio, height: size * ratio, }); canvas.style.width = `${size}px`; canvas.style.height = `${size}px`; return canvas; }; const canvas_to_img = (canvas, elementId) => { const img = create_el("img", { crossOrigin: "anonymous", src: canvas.toDataURL("image/png"), width: get_attr(canvas, "width"), height: get_attr(canvas, "height"), id: elementId, }); img.style.width = canvas.style.width; img.style.height = canvas.style.height; return img; }; const calc_image_pos = (settings) => { let mSize = settings.mSize; let mPosX = settings.mPosX; let mPosY = settings.mPosY; let arrayPos = 0; if (settings.mode === "labelimage") { arrayPos = 1; } if (Array.isArray(settings.mSize)) { mSize = settings.mSize[arrayPos]; } if (Array.isArray(settings.mPosX)) { mPosX = settings.mPosX[arrayPos]; } if (Array.isArray(settings.mPosY)) { mPosY = settings.mPosY[arrayPos]; } const size = settings.size; const w = settings.image.naturalWidth || 1; const h = settings.image.naturalHeight || 1; const sh = mSize * 0.01; const sw = (sh * w) / h; const sl = (1 - sw) * mPosX * 0.01; const st = (1 - sh) * mPosY * 0.01; const x = sl * size; const y = st * size; const iw = sw * size; const ih = sh * size; return { x, y, iw, ih }; }; const draw_label = (ctx, settings) => { let mSize = settings.mSize; let mPosX = settings.mPosX; let mPosY = settings.mPosY; let arrayPos = 0; if (settings.mode === "imagelabel") { arrayPos = 1; } if (Array.isArray(settings.mSize)) { mSize = settings.mSize[arrayPos]; } if (Array.isArray(settings.mPosX)) { mPosX = settings.mPosX[arrayPos]; } if (Array.isArray(settings.mPosY)) { mPosY = settings.mPosY[arrayPos]; } const size = settings.size; const font = "bold " + mSize * 0.01 * size + "px " + settings.fontname; ctx.strokeStyle = settings.back; ctx.lineWidth = mSize * 0.01 * size * 0.1; ctx.fillStyle = settings.fontcolor; ctx.font = font; const w = ctx.measureText(settings.label).width; const sh = mSize * 0.01; const sw = w / size; const sl = (1 - sw) * mPosX * 0.01; const st = (1 - sh) * mPosY * 0.01; const x = sl * size; const y = st * size + 0.75 * mSize * 0.01 * size; ctx.strokeText(settings.label, x, y); ctx.fillText(settings.label, x, y); }; const draw_image = (ctx, settings) => { const imagePos = calc_image_pos(settings); if (settings.imageAsCode) { ctx.drawImage(settings.image, 0, 0, settings.size, settings.size); } else { ctx.drawImage(settings.image, imagePos.x, imagePos.y, imagePos.iw, imagePos.ih); } }; const draw_mode = (ctx, settings) => { const mode = settings.mode; if (mode === "label") { draw_label(ctx, settings); } else if (mode === "image") { draw_image(ctx, settings); } else if (mode === "labelimage") { draw_label(ctx, settings); draw_image(ctx, settings); } else if (mode === "imagelabel") { draw_image(ctx, settings); draw_label(ctx, settings); } else if (mode === "clearimage") { // We set the mode to "labelimage" here. this will change to behavior of calc_image_pos() to use // the arrayposition 1 (that means, the second position in the pos-array is used for drawing the image. // the first position in the pos-array is used for clearing the background via "destination-out"). // We can't just change the calc_image_pos() to use arrayposition 1 in the case of clearimage as we // call this function as well to calculate the area to be cleared draw_image(ctx, { ...settings, mode: "labelimage" }); } }; const create_draw_ctx$1 = (ctx) => { return { m(x, y) { ctx.moveTo(x, y); return this; }, l(x, y) { ctx.lineTo(x, y); return this; }, a(...args) { ctx.arcTo(...args); return this; }, }; }; const draw_dark$1 = (ctx, l, t, r, b, rad, nw, ne, se, sw) => { if (nw) { ctx.m(l + rad, t); } else { ctx.m(l, t); } if (ne) { ctx.l(r - rad, t).a(r, t, r, b, rad); } else { ctx.l(r, t); } if (se) { ctx.l(r, b - rad).a(r, b, l, b, rad); } else { ctx.l(r, b); } if (sw) { ctx.l(l + rad, b).a(l, b, l, t, rad); } else { ctx.l(l, b); } if (nw) { ctx.l(l, t + rad).a(l, t, r, t, rad); } else { ctx.l(l, t); } }; const draw_light$1 = (ctx, l, t, r, b, rad, nw, ne, se, sw) => { if (nw) { ctx .m(l + rad, t) .l(l, t) .l(l, t + rad) .a(l, t, l + rad, t, rad); } if (ne) { ctx .m(r - rad, t) .l(r, t) .l(r, t + rad) .a(r, t, r - rad, t, rad); } if (se) { ctx .m(r - rad, b) .l(r, b) .l(r, b - rad) .a(r, b, r - rad, b, rad); } if (sw) { ctx .m(l + rad, b) .l(l, b) .l(l, b - rad) .a(l, b, l + rad, b, rad); } }; const draw_module_rounded = (qr, ctx, settings, width, row, col) => { const left = col * width; const top = row * width; const right = left + width; const bottom = top + width; const radius = settings.rounded * 0.005 * width; const is_dark = qr.is_dark; const row_n = row - 1; const row_s = row + 1; const col_w = col - 1; const col_e = col + 1; const dark_center = is_dark(row, col); const dark_nw = is_dark(row_n, col_w); const dark_n = is_dark(row_n, col); const dark_ne = is_dark(row_n, col_e); const dark_e = is_dark(row, col_e); const dark_se = is_dark(row_s, col_e); const dark_s = is_dark(row_s, col); const dark_sw = is_dark(row_s, col_w); const dark_w = is_dark(row, col_w); const draw_ctx = create_draw_ctx$1(ctx); if (dark_center) { draw_dark$1(draw_ctx, left, top, right, bottom, radius, !dark_n && !dark_w, !dark_n && !dark_e, !dark_s && !dark_e, !dark_s && !dark_w); } else { draw_light$1(draw_ctx, left, top, right, bottom, radius, dark_n && dark_w && dark_nw, dark_n && dark_e && dark_ne, dark_s && dark_e && dark_se, dark_s && dark_w && dark_sw); } }; const draw_background = (ctx, settings) => { if (settings.back) { ctx.fillStyle = settings.back; ctx.fillRect(0, 0, settings.size, settings.size); } }; const draw_module_default = (qr, ctx, settings, width, row, col) => { if (qr.is_dark(row, col)) { ctx.rect(col * width, row * width, width, width); } }; const draw_modules = (qr, ctx, settings) => { if (!qr) { return; } const draw_module = settings.rounded > 0 && settings.rounded <= 100 ? draw_module_rounded : draw_module_default; const mod_count = qr.module_count; let mod_size = settings.size / mod_count; let offset = 0; if (settings.crisp) { mod_size = Math.floor(mod_size); offset = Math.floor((settings.size - mod_size * mod_count) / 2); } ctx.translate(offset, offset); ctx.beginPath(); for (let row = 0; row < mod_count; row += 1) { for (let col = 0; col < mod_count; col += 1) { draw_module(qr, ctx, settings, mod_size, row, col); } } ctx.fillStyle = settings.fill; ctx.fill(); ctx.translate(-offset, -offset); }; const draw = (qr, ctx, settings) => { draw_background(ctx, settings); draw_modules(qr, ctx, settings); if (settings.mode !== "clearimage") { // we do this later manually draw_mode(ctx, settings); } }; const create_canvas_qrcode = (qr, settings, as_image) => { const ratio = settings.ratio || dpr; const canvas = create_canvas(settings.size, ratio); const context = canvas.getContext("2d"); if (settings.imageAsCode) { const canvas = create_canvas(settings.size, ratio); const ctx2 = canvas.getContext("2d"); draw_modules(qr, ctx2, settings); const imagePos = calc_image_pos(settings); ctx2.globalCompositeOperation = "source-in"; ctx2.drawImage(settings.image, imagePos.x, imagePos.y, imagePos.iw, imagePos.ih); settings = Object.assign({}, settings, { image: ctx2.canvas }); } context.scale(ratio, ratio); draw(qr, context, settings); if (settings.mode === "clearimage") { // draw_modules(qr, ctx2, settings); const imagePos = calc_image_pos(settings); context.globalCompositeOperation = "destination-out"; context.fillStyle = "deeppink"; // any color works context.fillRect(imagePos.x, imagePos.y, imagePos.iw, imagePos.ih); context.globalCompositeOperation = "source-over"; draw_mode(context, settings); } return as_image ? canvas_to_img(canvas, settings.elementId) : canvas; }; const create_draw_ctx = (ctx) => { const rnd = (x) => Math.round(x * 10) / 10; const rndo = (x) => Math.round(x * 10) / 10 + ctx.o; return { m(x, y) { ctx.p += `M ${rndo(x)} ${rndo(y)} `; return this; }, l(x, y) { ctx.p += `L ${rndo(x)} ${rndo(y)} `; return this; }, a(x, y, rad) { ctx.p += `A ${rnd(rad)} ${rnd(rad)} 0 0 1 ${rndo(x)} ${rndo(y)} `; return this; }, }; }; const draw_dark = (ctx, l, t, r, b, rad, nw, ne, se, sw) => { if (nw) { ctx.m(l + rad, t); } else { ctx.m(l, t); } if (ne) { ctx.l(r - rad, t).a(r, t + rad, rad); } else { ctx.l(r, t); } if (se) { ctx.l(r, b - rad).a(r - rad, b, rad); } else { ctx.l(r, b); } if (sw) { ctx.l(l + rad, b).a(l, b - rad, rad); } else { ctx.l(l, b); } if (nw) { ctx.l(l, t + rad).a(l + rad, t, rad); } else { ctx.l(l, t); } }; const draw_light = (ctx, l, t, r, b, rad, nw, ne, se, sw) => { if (nw) { ctx .m(l + rad, t) .l(l, t) .l(l, t + rad) .a(l + rad, t, rad); } if (ne) { ctx .m(r, t + rad) .l(r, t) .l(r - rad, t) .a(r, t + rad, rad); } if (se) { ctx .m(r - rad, b) .l(r, b) .l(r, b - rad) .a(r - rad, b, rad); } if (sw) { ctx .m(l, b - rad) .l(l, b) .l(l + rad, b) .a(l, b - rad, rad); } }; const draw_mod = (qr, ctx, settings, width, row, col) => { const left = col * width; const top = row * width; const right = left + width; const bottom = top + width; const radius = settings.rounded * 0.005 * width; const is_dark = qr.is_dark; const row_n = row - 1; const row_s = row + 1; const col_w = col - 1; const col_e = col + 1; const dark_center = is_dark(row, col); const dark_nw = is_dark(row_n, col_w); const dark_n = is_dark(row_n, col); const dark_ne = is_dark(row_n, col_e); const dark_e = is_dark(row, col_e); const dark_se = is_dark(row_s, col_e); const dark_s = is_dark(row_s, col); const dark_sw = is_dark(row_s, col_w); const dark_w = is_dark(row, col_w); if (dark_center) { draw_dark(ctx, left, top, right, bottom, radius, !dark_n && !dark_w, !dark_n && !dark_e, !dark_s && !dark_e, !dark_s && !dark_w); } else { draw_light(ctx, left, top, right, bottom, radius, dark_n && dark_w && dark_nw, dark_n && dark_e && dark_ne, dark_s && dark_e && dark_se, dark_s && dark_w && dark_sw); } }; const create_path = (qr, settings) => { if (!qr) { return ""; } const ctx = { p: "", o: 0 }; const mod_count = qr.module_count; let mod_size = settings.size / mod_count; if (settings.crisp) { mod_size = Math.floor(mod_size); ctx.o = Math.floor((settings.size - mod_size * mod_count) / 2); } const draw_ctx = create_draw_ctx(ctx); for (let row = 0; row < mod_count; row += 1) { for (let col = 0; col < mod_count; col += 1) { draw_mod(qr, draw_ctx, settings, mod_size, row, col); } } return ctx.p; }; const add_label = (el, settings) => { let mSize = settings.mSize; let mPosX = settings.mPosX; let mPosY = settings.mPosY; let arrayPos = 0; if (settings.mode === "imagelabel") { arrayPos = 1; } if (Array.isArray(settings.mSize)) { mSize = settings.mSize[arrayPos]; } if (Array.isArray(settings.mPosX)) { mPosX = settings.mPosX[arrayPos]; } if (Array.isArray(settings.mPosY)) { mPosY = settings.mPosY[arrayPos]; } const size = settings.size; const font = "bold " + mSize * 0.01 * size + "px " + settings.fontname; const ratio = settings.ratio || dpr; const ctx = create_canvas(size, ratio).getContext("2d"); ctx.strokeStyle = settings.back; ctx.lineWidth = mSize * 0.01 * size * 0.1; ctx.fillStyle = settings.fontcolor; ctx.font = font; const w = ctx.measureText(settings.label).width; const sh = mSize * 0.01; const sw = w / size; const sl = (1 - sw) * mPosX * 0.01; const st = (1 - sh) * mPosY * 0.01; const x = sl * size; const y = st * size + 0.75 * mSize * 0.01 * size; const text_el = create_svg_el("text", { x, y, }); Object.assign(text_el.style, { font, fill: settings.fontcolor, "paint-order": "stroke", stroke: settings.back, "stroke-width": ctx.lineWidth, }); text_el.textContent = settings.label; el.appendChild(text_el); }; const add_image = (el, settings) => { let img_el; if (settings.imageAsCode) { img_el = create_svg_el("image", { href: settings.image, x: 0, y: 0, width: settings.size, height: settings.size, }); } else { const imagePos = calc_image_pos(settings); img_el = create_svg_el("image", { href: settings.image, x: imagePos.x, y: imagePos.y, width: imagePos.iw, height: imagePos.ih, }); } el.appendChild(img_el); }; const create_svg_qrcode = (qr, settings) => { const size = settings.size; const mode = settings.mode; const svg_el = create_svg_el("svg", { xmlns: SVG_NS, width: size, height: size, viewBox: `0 0 ${size} ${size}`, }); svg_el.style.width = `${size}px`; svg_el.style.height = `${size}px`; svg_el.setAttribute("title", settings.text); if (!!settings.elementId) { svg_el.setAttribute("id", settings.elementId); } if (settings.back) { svg_el.appendChild(create_svg_el("rect", { x: 0, y: 0, width: size, height: size, fill: settings.back, })); } svg_el.appendChild(create_svg_el("path", { d: create_path(qr, settings), fill: settings.fill, })); if (settings.image) { if (settings.imageAsCode) { const ratio = settings.ratio || dpr; const canvas = create_canvas(settings.size, ratio); const ctx2 = canvas.getContext("2d"); draw_modules(qr, ctx2, settings); const imagePos = calc_image_pos(settings); ctx2.globalCompositeOperation = "source-in"; ctx2.drawImage(settings.image, imagePos.x, imagePos.y, imagePos.iw, imagePos.ih); settings = Object.assign({}, settings, { image: ctx2.canvas.toDataURL(), }); } else { settings = Object.assign({}, settings, { image: get_attr(settings.image, "src"), }); } if (settings.mode === "clearimage") { const ratio = settings.ratio || dpr; const canvas = create_canvas(settings.size, ratio); const ctx2 = canvas.getContext("2d"); const imagePos = calc_image_pos(settings); ctx2.globalCompositeOperation = "destination-in"; ctx2.fillStyle = "deeppink"; ctx2.fillRect(imagePos.x, imagePos.y, imagePos.iw, imagePos.ih); } } if (mode === "label") { add_label(svg_el, settings); } else if (mode === "image") { add_image(svg_el, settings); } else if (mode === "labelimage") { add_label(svg_el, settings); add_image(svg_el, settings); } else if (mode === "imagelabel") { add_image(svg_el, settings); add_label(svg_el, settings); } else if (mode === "clearimage") { // We set the mode to "labelimage" here. this will change to behavior of calc_image_pos() to use // the arrayposition 1 (that means, the second position in the pos-array is used for drawing the image. // the first position in the pos-array is used for clearing the background via "destination-out"). // We can't just change the calc_image_pos() to use arrayposition 1 in the case of clearimage as we // call this function as well to calculate the area to be cleared add_image(svg_el, { ...settings, mode: "labelimage" }); } return svg_el; }; const defaults = { // render method: 'canvas' or 'image' or 'svg' render: "svg", // render pixel-perfect lines crisp: true, // minimum version: 1..40 minVersion: 1, // error correction level: 'L', 'M', 'Q' or 'H' ecLevel: "L", // size in pixel size: 200, // pixel-ratio, null for devicePixelRatio ratio: null, // code color fill: "#333", // background color back: "#fff", // content text: "", // rounded corners in pc: 0..100 rounded: 0, // quiet zone in modules quiet: 0, // modes: 'plain', 'label', 'image', 'imagelabel' or 'labelimage' mode: "plain", // label/image size and pos in pc: 0..100 mSize: 30, mPosX: 50, mPosY: 50, // label label: "", fontname: "sans", fontcolor: "#333", fontoutline: true, // image element image: null, // draw the image as part of the code imageAsCode: false, elementId: null, }; const RE_CODE_LENGTH_OVERFLOW = /code length overflow/i; qrcode.stringToBytes = qrcode.stringToBytesFuncs["UTF-8"]; const min_qrcode = (text, level, min_ver = 1) => { min_ver = Math.max(1, min_ver); for (let version = min_ver; version <= 40; version += 1) { try { const qr = qrcode(version, level); qr.addData(text); qr.make(); const module_count = qr.getModuleCount(); const is_dark = (row, col) => { return (row >= 0 && row < module_count && col >= 0 && col < module_count && qr.isDark(row, col)); }; return { text, level, version, module_count, is_dark }; } catch (err) { if (!(version < 40 && RE_CODE_LENGTH_OVERFLOW.test(err))) { throw new Error(err); } } } return null; }; const quiet_qrcode = (text = "", level = "L", min_ver = 1, quiet = 0) => { const qr = min_qrcode(text, level, min_ver); if (qr) { const prev_is_dark = qr.is_dark; qr.module_count += 2 * quiet; qr.is_dark = (row, col) => prev_is_dark(row - quiet, col - quiet); } return qr; }; const kjua = (options) => { const settings = Object.assign({}, defaults, options); const qr = quiet_qrcode(settings.text, settings.ecLevel, settings.minVersion, settings.quiet); if (typeof settings.image === "string") { const image = new Image(); image.src = "data:image/png;base64," + settings.image; image.crossOrigin = "anonymous"; settings.image = image; } if (settings.render === "svg") { return create_svg_qrcode(qr, settings); } return create_canvas_qrcode(qr, settings, settings.render === "image"); }; class NgxKjuaComponent { /** * render method */ render = "svg"; /** * render pixel-perfect lines */ crisp = true; /** * minimum version= 1..40 */ minVersion = 1; /** * error correction level */ ecLevel = "L"; /** * size in pixel */ size = 200; /** * pixel-ratio; undefined for devicePixelRatio */ ratio = undefined; /** * code color */ fill = "#333"; /** * background color */ back = "#fff"; /** * content */ _text = ""; set text(value) { if (String(value)) this._text = value; else if (Number(value)) this._text = value.toString(); else this._text = ""; } /** * rounded corners in pc= 0..100 */ rounded = 0; /** * quiet zone in modules */ quiet = 0; /** * modes */ mode = "plain"; /** * label/image size and pos in pc= 0..100 */ mSize = 30; mPosX = 50; mPosY = 50; image = undefined; imageAsCode = false; /** * label */ label = ""; fontname = "sans-serif"; fontcolor = "#333"; fontoutline = true; /** * If true, rendering is done inside "requestAnimationFrame"-call. * Use this if you want to generate more than one code (e.g. batch) */ renderAsync = false; /** * If set, this css-class will be appended to the div-container that contains * the qr-code (which is either an img or a canvas) */ cssClass; /** * an optional HTML-ID-attribute for the element (works only with render-mode SVG and image) */ elementId; codeFinished = new EventEmitter(); div; viewInitialized = false; constructor() { } ngAfterViewInit() { this.viewInitialized = true; this.updateView(); } ngOnChanges(_changes) { if (this.viewInitialized) { this.updateView(); } } get template() { const settings = { render: this.render, crisp: this.crisp, minVersion: this.minVersion, ecLevel: this.ecLevel, size: +this.size, ratio: this.ratio, fill: this.fill, back: this.back, text: this._text, rounded: this.rounded, quiet: this.quiet, mode: this.mode, mSize: this.mSize, mPosX: this.mPosX, mPosY: this.mPosY, label: this.label, fontname: this.fontname, fontcolor: this.fontcolor, image: this.image, fontoutline: this.fontoutline, imageAsCode: this.imageAsCode, elementId: this.elementId, }; return kjua(settings); } renderCode() { this.div.nativeElement.innerHTML = ""; const node = this.template; this.div.nativeElement.appendChild(node); this.codeFinished.next(node); } updateView() { this.div.nativeElement.style.width = this.size.toString() + "px"; this.div.nativeElement.style.height = this.size.toString() + "px"; if (typeof this.image === "string") { const img = new Image(); img.crossOrigin = "anonymous"; img.onload = () => { if (this.renderAsync) { requestAnimationFrame(() => this.renderCode()); } else { this.renderCode(); } }; img.src = "data:image/png;base64," + this.image; } else { if (this.renderAsync) { requestAnimationFrame(() => this.renderCode()); } else { this.renderCode(); } } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxKjuaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "20.0.3", type: NgxKjuaComponent, isStandalone: true, selector: "ngx-kjua", inputs: { render: "render", crisp: "crisp", minVersion: "minVersion", ecLevel: "ecLevel", size: "size", ratio: "ratio", fill: "fill", back: "back", text: "text", rounded: "rounded", quiet: "quiet", mode: "mode", mSize: "mSize", mPosX: "mPosX", mPosY: "mPosY", image: "image", imageAsCode: ["imageAsCode", "imageAsCode", booleanAttribute], label: "label", fontname: "fontname", fontcolor: "fontcolor", fontoutline: "fontoutline", renderAsync: ["renderAsync", "renderAsync", booleanAttribute], cssClass: "cssClass", elementId: "elementId" }, outputs: { codeFinished: "codeFinished" }, viewQueries: [{ propertyName: "div", first: true, predicate: ["elem"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: `<div [class]="cssClass" #elem></div>`, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: NgxKjuaComponent, decorators: [{ type: Component, args: [{ standalone: true, selector: "ngx-kjua", template: `<div [class]="cssClass" #elem></div>`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}\n"] }] }], ctorParameters: () => [], propDecorators: { render: [{ type: Input }], crisp: [{ type: Input }], minVersion: [{ type: Input }], ecLevel: [{ type: Input }], size: [{ type: Input }], ratio: [{ type: Input }], fill: [{ type: Input }], back: [{ type: Input }], text: [{ type: Input }], rounded: [{ type: Input }], quiet: [{ type: Input }], mode: [{ type: Input }], mSize: [{ type: Input }], mPosX: [{ type: Input }], mPosY: [{ type: Input }], image: [{ type: Input }], imageAsCode: [{ type: Input, args: [{ transform: booleanAttribute }] }], label: [{ type: Input }], fontname: [{ type: Input }], fontcolor: [{ type: Input }], fontoutline: [{ type: Input }], renderAsync: [{ type: Input, args: [{ transform: booleanAttribute }] }], cssClass: [{ type: Input }], elementId: [{ type: Input }], codeFinished: [{ type: Output }], div: [{ type: ViewChild, args: ["elem", { static: true }] }] } }); class QrCodeHelper { /** * Make the code for creating an SMS. * Number can be provided as number or string (useful for international format e.g. +1 for USA) * * @paramnumber * @param text */ static makeSMS(number, text) { if (text) { if (text.length > 160) { return `SMSTO:${number}:${text.substr(0, 160)}`; } else { return `SMSTO:${number}:${text}`; } } else { return `SMSTO:${number}`; } } /** * Make the code for making a phone call * Number can be provided as number or string (useful for international format e.g. +1 for USA) * * @param number */ static makeCall(number) { return `tel:${number}`; } /** * Make the code for encoding a location * * @param lat * @param lon * @param meters */ static makeGeo(lat, lon, meters = 400) { return `geo:${lat},${lon},${meters}`; } /** * Make the code for encoding an event in iCal format * You have to do the encoding for the begin and end by yourself (use moment.js!) * * @param description * @param begin * @param end */ static makeEvent(description, begin, end) { return `BEGIN:VEVENT SUMMARY:${description} DTSTART:${begin} DTEND:${end} END:VEVENT`; } /** * Make the code for an Email * * @param recipient * @param subject * @param text */ static makeEmail(recipient, subject, text) { let retVal = `MATMSG:TO:${recipient};`; if (subject) { retVal += `SUB:${subject}`; } retVal += `;`; if (text) { retVal += `BODY:${text}`; } retVal += `;;`; return retVal; } /** * Make the code that lets user login to a WiFi * If no pass is provided, the WiFi is considered as not encrypted (no WPA) * * @param ssid * @param pass * @param hidden */ static makeWifi(ssid, pass, hidden = false) { let retVal = `WIFI:${!!pass ? "T:WPA" : "T:nopass"};S:${ssid};`; if (pass) { retVal += `P:${pass}`; } retVal += `;`; if (hidden) { retVal += `H:true`; } retVal += `;`; return retVal; } /** * Make the code that encodes contact information. * Numbers can be provided as number or string (useful for international format e.g. +1 for USA) * Encoding is done with MECARD-format and NOT VCard! VCard gives a longer string and therefore a * bigger code which has a negative impact on readability for scanners. You can, of course, create * a VCard string as well but the format is more complex. * * @param name * @param telNumbers * @param address, values separated with comma * @param email * @param url */ static makeContactMeCard(name, telNumbers, address, email, url) { let retVal = `MECARD:N:${name};`; if (address) { retVal += `ADR:${address};`; } if (telNumbers && telNumbers.length > 0) { for (let i = 0; i < telNumbers.length; i++) { retVal += `TEL:${telNumbers[i]};`; } } if (email) { retVal += `EMAIL:${email};`; } if (url) { retVal += `URL:${url};`; } retVal += `;`; return retVal; } } /* * Public API Surface of ngx-kjua */ /** * Generated bundle index. Do not edit. */ export { NgxKjuaComponent, QrCodeHelper, kjua }; //# sourceMappingURL=ngx-kjua.mjs.map