ngx-kjua
Version:
Angular QR-Code generator component.
1,043 lines (1,029 loc) • 32.2 kB
JavaScript
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