ngx-dsxlibrary 2.21.41 → 2.21.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/ngx-dsxlibrary-src-lib-services.mjs +43 -0
- package/fesm2022/ngx-dsxlibrary-src-lib-services.mjs.map +1 -1
- package/fesm2022/ngx-dsxlibrary.mjs +263 -1
- package/fesm2022/ngx-dsxlibrary.mjs.map +1 -1
- package/ngx-dsxlibrary-2.21.42.tgz +0 -0
- package/package.json +6 -2
- package/types/ngx-dsxlibrary-src-lib-services.d.ts +12 -1
- package/types/ngx-dsxlibrary.d.ts +30 -2
- package/ngx-dsxlibrary-2.21.41.tgz +0 -0
|
@@ -1,4 +1,47 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Injectable } from '@angular/core';
|
|
3
|
+
import QRCode from 'qrcode';
|
|
4
|
+
|
|
5
|
+
class QrService {
|
|
6
|
+
/**
|
|
7
|
+
* Genera un código QR como Blob usando qrcode
|
|
8
|
+
* Sin necesidad de llamadas HTTP externas, evita problemas de CORS
|
|
9
|
+
*/
|
|
10
|
+
async getQrBlob(textToEncode) {
|
|
11
|
+
try {
|
|
12
|
+
// Genera el QR como Data URL
|
|
13
|
+
const dataUrl = await QRCode.toDataURL(textToEncode, {
|
|
14
|
+
errorCorrectionLevel: 'H',
|
|
15
|
+
type: 'image/png',
|
|
16
|
+
width: 300,
|
|
17
|
+
margin: 1,
|
|
18
|
+
color: {
|
|
19
|
+
dark: '#000000',
|
|
20
|
+
light: '#FFFFFF',
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
// Convierte Data URL a Blob
|
|
24
|
+
const response = await fetch(dataUrl);
|
|
25
|
+
return response.blob();
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
console.error('Error generando QR:', err);
|
|
29
|
+
throw err;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: QrService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
33
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: QrService, providedIn: 'root' });
|
|
34
|
+
}
|
|
35
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: QrService, decorators: [{
|
|
36
|
+
type: Injectable,
|
|
37
|
+
args: [{
|
|
38
|
+
providedIn: 'root',
|
|
39
|
+
}]
|
|
40
|
+
}] });
|
|
41
|
+
|
|
1
42
|
/**
|
|
2
43
|
* Generated bundle index. Do not edit.
|
|
3
44
|
*/
|
|
45
|
+
|
|
46
|
+
export { QrService };
|
|
4
47
|
//# sourceMappingURL=ngx-dsxlibrary-src-lib-services.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngx-dsxlibrary-src-lib-services.mjs","sources":["../../../projects/ngx-dsx/src/lib/services/ngx-dsxlibrary-src-lib-services.ts"],"sourcesContent":["/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ngx-dsxlibrary-src-lib-services.mjs","sources":["../../../projects/ngx-dsx/src/lib/services/src/qr.service.ts","../../../projects/ngx-dsx/src/lib/services/ngx-dsxlibrary-src-lib-services.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\nimport QRCode from 'qrcode';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class QrService {\r\n /**\r\n * Genera un código QR como Blob usando qrcode\r\n * Sin necesidad de llamadas HTTP externas, evita problemas de CORS\r\n */\r\n async getQrBlob(textToEncode: string): Promise<Blob> {\r\n try {\r\n // Genera el QR como Data URL\r\n const dataUrl = await QRCode.toDataURL(textToEncode, {\r\n errorCorrectionLevel: 'H',\r\n type: 'image/png',\r\n width: 300,\r\n margin: 1,\r\n color: {\r\n dark: '#000000',\r\n light: '#FFFFFF',\r\n },\r\n });\r\n\r\n // Convierte Data URL a Blob\r\n const response = await fetch(dataUrl);\r\n return response.blob();\r\n } catch (err) {\r\n console.error('Error generando QR:', err);\r\n throw err;\r\n }\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;MAMa,SAAS,CAAA;AACpB;;;AAGG;IACH,MAAM,SAAS,CAAC,YAAoB,EAAA;AAClC,QAAA,IAAI;;YAEF,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE;AACnD,gBAAA,oBAAoB,EAAE,GAAG;AACzB,gBAAA,IAAI,EAAE,WAAW;AACjB,gBAAA,KAAK,EAAE,GAAG;AACV,gBAAA,MAAM,EAAE,CAAC;AACT,gBAAA,KAAK,EAAE;AACL,oBAAA,IAAI,EAAE,SAAS;AACf,oBAAA,KAAK,EAAE,SAAS;AACjB,iBAAA;AACF,aAAA,CAAC;;AAGF,YAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC;AACrC,YAAA,OAAO,QAAQ,CAAC,IAAI,EAAE;QACxB;QAAE,OAAO,GAAG,EAAE;AACZ,YAAA,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,GAAG,CAAC;AACzC,YAAA,MAAM,GAAG;QACX;IACF;wGA1BW,SAAS,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAT,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,SAAS,cAFR,MAAM,EAAA,CAAA;;4FAEP,SAAS,EAAA,UAAA,EAAA,CAAA;kBAHrB,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE,MAAM;AACnB,iBAAA;;;ACLD;;AAEG;;;;"}
|
|
@@ -40,6 +40,7 @@ import * as i4 from 'primeng/menubar';
|
|
|
40
40
|
import { MenubarModule } from 'primeng/menubar';
|
|
41
41
|
import { JwtHelperService } from '@auth0/angular-jwt';
|
|
42
42
|
import { CookieService } from 'ngx-cookie-service';
|
|
43
|
+
import QRCode from 'qrcode';
|
|
43
44
|
import * as i6 from 'primeng/floatlabel';
|
|
44
45
|
import { FloatLabelModule } from 'primeng/floatlabel';
|
|
45
46
|
import * as i7 from 'primeng/password';
|
|
@@ -4877,6 +4878,267 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
4877
4878
|
], template: "<p-menubar>\r\n <ng-template #start>\r\n <p-image\r\n class=\"ms-15\"\r\n [src]=\"urlLogo()\"\r\n alt=\"Image\"\r\n [width]=\"logoWidth()\"\r\n />\r\n <span class=\"version-text\">{{ appVersion() }}</span>\r\n </ng-template>\r\n <ng-template #end>\r\n <div>\r\n <!-- Datos del usuario -->\r\n <div class=\"navbar-user-info\">\r\n <icon-dsx name=\"verified_user\" class=\"navbar-user-icon\"></icon-dsx>\r\n <div class=\"navbar-user-text\">\r\n <span class=\"navbar-user-name\">\r\n {{ _authorizeService.getTokenValues.userName }}\r\n </span>\r\n <span class=\"navbar-user-role\">\r\n {{ currentRole }}\r\n </span>\r\n </div>\r\n </div>\r\n\r\n <!-- Componente de estado de red -->\r\n <app-network-status></app-network-status>\r\n\r\n <!-- Actualizaci\u00F3n de permisos -->\r\n <p-button\r\n class=\"mr-2\"\r\n label=\"Permisos\"\r\n variant=\"text\"\r\n severity=\"info\"\r\n (click)=\"actualizarSeguridadIT()\"\r\n >\r\n <span class=\"material-symbols-outlined mr-1\">local_police</span>\r\n </p-button>\r\n\r\n <label class=\"ui-switch\">\r\n <input\r\n type=\"checkbox\"\r\n [(ngModel)]=\"checked\"\r\n (click)=\"onThemeChange(!checked ? true : false)\"\r\n />\r\n <div class=\"slider\">\r\n <div class=\"circle\"></div>\r\n </div>\r\n </label>\r\n <!-- <p-inputSwitch\r\n [(ngModel)]=\"checked\"\r\n (onChange)=\"onThemeChange($event.checked)\"\r\n ></p-inputSwitch> -->\r\n </div>\r\n </ng-template>\r\n</p-menubar>\r\n", styles: [":host ::ng-deep .p-menubar{display:flex;align-items:center!important;padding:.25rem 1.5rem!important;border-radius:999px;border:1px solid rgba(255,255,255,.2);background:#ffffff1f!important;backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);box-shadow:0 10px 30px #0f172a14;margin-left:4rem;margin-right:2.5rem}:host ::ng-deep .p-menubar-end>*{display:flex;align-items:center}.version-text{font-size:1.3rem;font-family:Montserrat,sans-serif!important;margin-left:.5rem;font-weight:600;background-image:linear-gradient(to right,#38bdf8,#630cb4);-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 2px 4px rgba(0,0,0,.1);padding:.2rem 0}.navbar-user-info{display:flex;align-items:center;gap:.35rem;padding:0 .75rem;border-radius:999px;background-color:#00000005}.navbar-user-icon{font-size:1.1rem;color:#374151}.navbar-user-name{font-size:.8rem;font-weight:500;color:#374151;white-space:nowrap}.navbar-user-text{display:flex;flex-direction:column;line-height:1.1}.navbar-user-role{font-size:.7rem;color:#6b7280;white-space:nowrap}.ui-switch{--switch-bg: rgb(135, 150, 165);--switch-width: 48px;--switch-height: 20px;--circle-diameter: 32px;--circle-bg: rgb(232, 89, 15);--circle-inset: calc((var(--circle-diameter) - var(--switch-height)) / 2)}.ui-switch input{display:none}.slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:var(--switch-width);height:var(--switch-height);background:var(--switch-bg);border-radius:999px;position:relative;cursor:pointer}.slider .circle{top:calc(var(--circle-inset) * -1);left:0;width:var(--circle-diameter);height:var(--circle-diameter);position:absolute;background:var(--circle-bg);border-radius:inherit;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjAiIHdpZHRoPSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj4KICAgIDxwYXRoIGZpbGw9IiNmZmYiCiAgICAgICAgZD0iTTkuMzA1IDEuNjY3VjMuNzVoMS4zODlWMS42NjdoLTEuMzl6bS00LjcwNyAxLjk1bC0uOTgyLjk4Mkw1LjA5IDYuMDcybC45ODItLjk4Mi0xLjQ3My0xLjQ3M3ptMTAuODAyIDBMMTMuOTI3IDUuMDlsLjk4Mi45ODIgMS40NzMtMS40NzMtLjk4Mi0uOTgyek0xMCA1LjEzOWE0Ljg3MiA0Ljg3MiAwIDAwLTQuODYyIDQuODZBNC44NzIgNC44NzIgMCAwMDEwIDE0Ljg2MiA0Ljg3MiA0Ljg3MiAwIDAwMTQuODYgMTAgNC44NzIgNC44NzIgMCAwMDEwIDUuMTM5em0wIDEuMzg5QTMuNDYyIDMuNDYyIDAgMDExMy40NzEgMTBhMy40NjIgMy40NjIgMCAwMS0zLjQ3MyAzLjQ3MkEzLjQ2MiAzLjQ2MiAwIDAxNi41MjcgMTAgMy40NjIgMy40NjIgMCAwMTEwIDYuNTI4ek0xLjY2NSA5LjMwNXYxLjM5aDIuMDgzdi0xLjM5SDEuNjY2em0xNC41ODMgMHYxLjM5aDIuMDg0di0xLjM5aC0yLjA4NHpNNS4wOSAxMy45MjhMMy42MTYgMTUuNGwuOTgyLjk4MiAxLjQ3My0xLjQ3My0uOTgyLS45ODJ6bTkuODIgMGwtLjk4Mi45ODIgMS40NzMgMS40NzMuOTgyLS45ODItMS40NzMtMS40NzN6TTkuMzA1IDE2LjI1djIuMDgzaDEuMzg5VjE2LjI1aC0xLjM5eiIgLz4KPC9zdmc+);background-repeat:no-repeat;background-position:center center;-webkit-transition:left .15s cubic-bezier(.4,0,.2,1) 0ms,-webkit-transform .15s cubic-bezier(.4,0,.2,1) 0ms;-o-transition:left .15s cubic-bezier(.4,0,.2,1) 0ms,transform .15s cubic-bezier(.4,0,.2,1) 0ms;transition:left .15s cubic-bezier(.4,0,.2,1) 0ms,transform .15s cubic-bezier(.4,0,.2,1) 0ms,-webkit-transform .15s cubic-bezier(.4,0,.2,1) 0ms;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;box-shadow:0 2px 1px -1px #0003,0 1px 1px #00000024,0 1px 3px #0000001f}.slider .circle:before{content:\"\";position:absolute;width:100%;height:100%;background:#ffffffbf;border-radius:inherit;-webkit-transition:all .5s;-o-transition:all .5s;transition:all .5s;opacity:0}.ui-switch input:checked+.slider .circle{left:calc(100% - var(--circle-diameter));background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjAiIHdpZHRoPSIyMCIgdmlld0JveD0iMCAwIDIwIDIwIj4KICAgIDxwYXRoIGZpbGw9IiNmZmYiCiAgICAgICAgZD0iTTQuMiAyLjVsLS43IDEuOC0xLjguNyAxLjguNy43IDEuOC42LTEuOEw2LjcgNWwtMS45LS43LS42LTEuOHptMTUgOC4zYTYuNyA2LjcgMCAxMS02LjYtNi42IDUuOCA1LjggMCAwMDYuNiA2LjZ6IiAvPgo8L3N2Zz4=);background-color:#003892}.ui-switch input:active+.slider .circle:before{-webkit-transition:0s;-o-transition:0s;transition:0s;opacity:1;width:0;height:0}\n"] }]
|
|
4878
4879
|
}], propDecorators: { appVersion: [{ type: i0.Input, args: [{ isSignal: true, alias: "appVersion", required: false }] }], logoWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "logoWidth", required: false }] }], urlLogo: [{ type: i0.Input, args: [{ isSignal: true, alias: "urlLogo", required: false }] }] } });
|
|
4879
4880
|
|
|
4881
|
+
class QrService {
|
|
4882
|
+
/**
|
|
4883
|
+
* Genera un código QR como Blob usando qrcode
|
|
4884
|
+
* Sin necesidad de llamadas HTTP externas, evita problemas de CORS
|
|
4885
|
+
*/
|
|
4886
|
+
async getQrBlob(textToEncode) {
|
|
4887
|
+
try {
|
|
4888
|
+
// Genera el QR como Data URL
|
|
4889
|
+
const dataUrl = await QRCode.toDataURL(textToEncode, {
|
|
4890
|
+
errorCorrectionLevel: 'H',
|
|
4891
|
+
type: 'image/png',
|
|
4892
|
+
width: 300,
|
|
4893
|
+
margin: 1,
|
|
4894
|
+
color: {
|
|
4895
|
+
dark: '#000000',
|
|
4896
|
+
light: '#FFFFFF',
|
|
4897
|
+
},
|
|
4898
|
+
});
|
|
4899
|
+
// Convierte Data URL a Blob
|
|
4900
|
+
const response = await fetch(dataUrl);
|
|
4901
|
+
return response.blob();
|
|
4902
|
+
}
|
|
4903
|
+
catch (err) {
|
|
4904
|
+
console.error('Error generando QR:', err);
|
|
4905
|
+
throw err;
|
|
4906
|
+
}
|
|
4907
|
+
}
|
|
4908
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: QrService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
4909
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: QrService, providedIn: 'root' });
|
|
4910
|
+
}
|
|
4911
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: QrService, decorators: [{
|
|
4912
|
+
type: Injectable,
|
|
4913
|
+
args: [{
|
|
4914
|
+
providedIn: 'root',
|
|
4915
|
+
}]
|
|
4916
|
+
}] });
|
|
4917
|
+
|
|
4918
|
+
class QrGenerator {
|
|
4919
|
+
qrService = inject(QrService);
|
|
4920
|
+
sanitizer = inject(DomSanitizer);
|
|
4921
|
+
// Inputs del padre
|
|
4922
|
+
codigoQr = input(null, ...(ngDevMode ? [{ debugName: "codigoQr" }] : /* istanbul ignore next */ [])); // Contenido a codificar en el QR
|
|
4923
|
+
labelQr = input('SCAN ME', ...(ngDevMode ? [{ debugName: "labelQr" }] : /* istanbul ignore next */ [])); // Texto del banner inferior
|
|
4924
|
+
// Señales internas (copias escribibles de los inputs)
|
|
4925
|
+
qrImageUrl = signal(null, ...(ngDevMode ? [{ debugName: "qrImageUrl" }] : /* istanbul ignore next */ []));
|
|
4926
|
+
labelText = signal('SCAN ME', ...(ngDevMode ? [{ debugName: "labelText" }] : /* istanbul ignore next */ []));
|
|
4927
|
+
textToEncode = signal('', ...(ngDevMode ? [{ debugName: "textToEncode" }] : /* istanbul ignore next */ []));
|
|
4928
|
+
constructor() {
|
|
4929
|
+
effect(() => {
|
|
4930
|
+
// Sincronizar labelQr → labelText
|
|
4931
|
+
this.labelText.set(this.labelQr());
|
|
4932
|
+
// Sincronizar codigoQr → textToEncode y generar el QR
|
|
4933
|
+
if (this.codigoQr()) {
|
|
4934
|
+
this.textToEncode.set(this.codigoQr());
|
|
4935
|
+
setTimeout(() => this.generateQrCode(), 100);
|
|
4936
|
+
}
|
|
4937
|
+
});
|
|
4938
|
+
}
|
|
4939
|
+
currentRawBlob = null;
|
|
4940
|
+
generateQrCode() {
|
|
4941
|
+
if (!this.textToEncode())
|
|
4942
|
+
return;
|
|
4943
|
+
this.qrService
|
|
4944
|
+
.getQrBlob(this.textToEncode())
|
|
4945
|
+
.then((blob) => {
|
|
4946
|
+
this.currentRawBlob = blob;
|
|
4947
|
+
this.generateDesignImage();
|
|
4948
|
+
})
|
|
4949
|
+
.catch((err) => console.error('Error generando QR:', err));
|
|
4950
|
+
}
|
|
4951
|
+
onLabelChange(value) {
|
|
4952
|
+
this.labelText.set(value);
|
|
4953
|
+
// Regenera la imagen de preview con la nueva etiqueta
|
|
4954
|
+
this.generateDesignImage();
|
|
4955
|
+
}
|
|
4956
|
+
generateDesignImage() {
|
|
4957
|
+
if (!this.currentRawBlob)
|
|
4958
|
+
return;
|
|
4959
|
+
const qrImage = new Image();
|
|
4960
|
+
const qrUrl = URL.createObjectURL(this.currentRawBlob);
|
|
4961
|
+
qrImage.src = qrUrl;
|
|
4962
|
+
qrImage.onload = () => {
|
|
4963
|
+
const qrSize = qrImage.width || 300;
|
|
4964
|
+
const padding = 40;
|
|
4965
|
+
const labelAreaHeight = 70;
|
|
4966
|
+
const canvas = document.createElement('canvas');
|
|
4967
|
+
canvas.width = qrSize + padding * 2;
|
|
4968
|
+
canvas.height = qrSize + labelAreaHeight + padding;
|
|
4969
|
+
const ctx = canvas.getContext('2d');
|
|
4970
|
+
if (!ctx)
|
|
4971
|
+
return;
|
|
4972
|
+
// Fondo blanco
|
|
4973
|
+
ctx.fillStyle = '#FFFFFF';
|
|
4974
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
4975
|
+
// DIBUJAR LAS ESQUINAS DE ENFOQUE
|
|
4976
|
+
ctx.strokeStyle = '#000000';
|
|
4977
|
+
ctx.lineWidth = 5;
|
|
4978
|
+
const lineLength = 25;
|
|
4979
|
+
const xMin = padding - 10;
|
|
4980
|
+
const yMin = padding - 10;
|
|
4981
|
+
const xMax = padding + qrSize + 10;
|
|
4982
|
+
const yMax = padding + qrSize + 10;
|
|
4983
|
+
// Esquinas
|
|
4984
|
+
ctx.beginPath();
|
|
4985
|
+
ctx.moveTo(xMin + lineLength, yMin);
|
|
4986
|
+
ctx.lineTo(xMin, yMin);
|
|
4987
|
+
ctx.lineTo(xMin, yMin + lineLength);
|
|
4988
|
+
ctx.stroke();
|
|
4989
|
+
ctx.beginPath();
|
|
4990
|
+
ctx.moveTo(xMax - lineLength, yMin);
|
|
4991
|
+
ctx.lineTo(xMax, yMin);
|
|
4992
|
+
ctx.lineTo(xMax, yMin + lineLength);
|
|
4993
|
+
ctx.stroke();
|
|
4994
|
+
ctx.beginPath();
|
|
4995
|
+
ctx.moveTo(xMin + lineLength, yMax);
|
|
4996
|
+
ctx.lineTo(xMin, yMax);
|
|
4997
|
+
ctx.lineTo(xMin, yMax - lineLength);
|
|
4998
|
+
ctx.stroke();
|
|
4999
|
+
ctx.beginPath();
|
|
5000
|
+
ctx.moveTo(xMax - lineLength, yMax);
|
|
5001
|
+
ctx.lineTo(xMax, yMax);
|
|
5002
|
+
ctx.lineTo(xMax, yMax - lineLength);
|
|
5003
|
+
ctx.stroke();
|
|
5004
|
+
// Dibujar el código QR
|
|
5005
|
+
ctx.drawImage(qrImage, padding, padding, qrSize, qrSize);
|
|
5006
|
+
// Configuración del banner
|
|
5007
|
+
const rectWidth = qrSize * 0.8;
|
|
5008
|
+
const rectHeight = 45;
|
|
5009
|
+
const rectX = padding + (qrSize - rectWidth) / 2;
|
|
5010
|
+
const rectY = yMax + 20;
|
|
5011
|
+
// Caja negra
|
|
5012
|
+
ctx.fillStyle = '#000000';
|
|
5013
|
+
ctx.fillRect(rectX, rectY, rectWidth, rectHeight);
|
|
5014
|
+
// Triángulo indicador
|
|
5015
|
+
ctx.beginPath();
|
|
5016
|
+
ctx.moveTo(canvas.width / 2, rectY - 8);
|
|
5017
|
+
ctx.lineTo(canvas.width / 2 - 10, rectY);
|
|
5018
|
+
ctx.lineTo(canvas.width / 2 + 10, rectY);
|
|
5019
|
+
ctx.closePath();
|
|
5020
|
+
ctx.fill();
|
|
5021
|
+
// Texto
|
|
5022
|
+
ctx.fillStyle = '#FFFFFF';
|
|
5023
|
+
ctx.font = 'bold 18px sans-serif';
|
|
5024
|
+
ctx.textAlign = 'center';
|
|
5025
|
+
ctx.textBaseline = 'middle';
|
|
5026
|
+
ctx.fillText(this.labelText().toUpperCase(), canvas.width / 2, rectY + rectHeight / 2);
|
|
5027
|
+
// Convertir a URL para mostrar en preview
|
|
5028
|
+
canvas.toBlob((blob) => {
|
|
5029
|
+
if (blob) {
|
|
5030
|
+
const previewUrl = URL.createObjectURL(blob);
|
|
5031
|
+
this.qrImageUrl.set(this.sanitizer.bypassSecurityTrustUrl(previewUrl));
|
|
5032
|
+
}
|
|
5033
|
+
}, 'image/png');
|
|
5034
|
+
};
|
|
5035
|
+
}
|
|
5036
|
+
downloadWithLabel() {
|
|
5037
|
+
if (!this.currentRawBlob)
|
|
5038
|
+
return;
|
|
5039
|
+
const qrImage = new Image();
|
|
5040
|
+
const qrUrl = URL.createObjectURL(this.currentRawBlob);
|
|
5041
|
+
qrImage.src = qrUrl;
|
|
5042
|
+
qrImage.onload = () => {
|
|
5043
|
+
const qrSize = qrImage.width || 300;
|
|
5044
|
+
const padding = 40; // Aumentamos el margen para las esquinas de enfoque
|
|
5045
|
+
const labelAreaHeight = 70;
|
|
5046
|
+
const canvas = document.createElement('canvas');
|
|
5047
|
+
canvas.width = qrSize + padding * 2;
|
|
5048
|
+
canvas.height = qrSize + labelAreaHeight + padding;
|
|
5049
|
+
const ctx = canvas.getContext('2d');
|
|
5050
|
+
if (!ctx)
|
|
5051
|
+
return;
|
|
5052
|
+
// Fondo blanco
|
|
5053
|
+
ctx.fillStyle = '#FFFFFF';
|
|
5054
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
5055
|
+
// DIBUJAR LAS ESQUINAS DE ENFOQUE (Estilo de tu imagen de referencia)
|
|
5056
|
+
ctx.strokeStyle = '#000000'; // Color negro para las líneas de enfoque
|
|
5057
|
+
ctx.lineWidth = 5; // Grosor de las esquinas
|
|
5058
|
+
const lineLength = 25; // Largo de cada segmento de la esquina
|
|
5059
|
+
// Área delimitadora donde se posicionará el QR
|
|
5060
|
+
const xMin = padding - 10;
|
|
5061
|
+
const yMin = padding - 10;
|
|
5062
|
+
const xMax = padding + qrSize + 10;
|
|
5063
|
+
const yMax = padding + qrSize + 10;
|
|
5064
|
+
// Esquina Superior Izquierda
|
|
5065
|
+
ctx.beginPath();
|
|
5066
|
+
ctx.moveTo(xMin + lineLength, yMin);
|
|
5067
|
+
ctx.lineTo(xMin, yMin);
|
|
5068
|
+
ctx.lineTo(xMin, yMin + lineLength);
|
|
5069
|
+
ctx.stroke();
|
|
5070
|
+
// Esquina Superior Derecha
|
|
5071
|
+
ctx.beginPath();
|
|
5072
|
+
ctx.moveTo(xMax - lineLength, yMin);
|
|
5073
|
+
ctx.lineTo(xMax, yMin);
|
|
5074
|
+
ctx.lineTo(xMax, yMin + lineLength);
|
|
5075
|
+
ctx.stroke();
|
|
5076
|
+
// Esquina Inferior Izquierda
|
|
5077
|
+
ctx.beginPath();
|
|
5078
|
+
ctx.moveTo(xMin + lineLength, yMax);
|
|
5079
|
+
ctx.lineTo(xMin, yMax);
|
|
5080
|
+
ctx.lineTo(xMin, yMax + lineLength);
|
|
5081
|
+
ctx.stroke();
|
|
5082
|
+
// Esquina Inferior Derecha
|
|
5083
|
+
ctx.beginPath();
|
|
5084
|
+
ctx.moveTo(xMax - lineLength, yMax);
|
|
5085
|
+
ctx.lineTo(xMax, yMax);
|
|
5086
|
+
ctx.lineTo(xMax, yMax + lineLength);
|
|
5087
|
+
ctx.stroke();
|
|
5088
|
+
// Dibujar el código QR original obtenido desde qrcoder.co.uk
|
|
5089
|
+
ctx.drawImage(qrImage, padding, padding, qrSize, qrSize);
|
|
5090
|
+
// Configuración geométrica de la etiqueta negra inferior
|
|
5091
|
+
const rectWidth = qrSize * 0.8;
|
|
5092
|
+
const rectHeight = 45;
|
|
5093
|
+
const rectX = padding + (qrSize - rectWidth) / 2;
|
|
5094
|
+
const rectY = yMax + 20; // Separado adecuadamente de la línea de enfoque inferior
|
|
5095
|
+
// Dibujar caja contenedora de texto
|
|
5096
|
+
ctx.fillStyle = '#000000';
|
|
5097
|
+
ctx.fillRect(rectX, rectY, rectWidth, rectHeight);
|
|
5098
|
+
// Pequeño triángulo indicador (Flecha superior de la caja)
|
|
5099
|
+
ctx.beginPath();
|
|
5100
|
+
ctx.moveTo(canvas.width / 2, rectY - 8);
|
|
5101
|
+
ctx.lineTo(canvas.width / 2 - 10, rectY);
|
|
5102
|
+
ctx.lineTo(canvas.width / 2 + 10, rectY);
|
|
5103
|
+
ctx.closePath();
|
|
5104
|
+
ctx.fill();
|
|
5105
|
+
// Renderizar Texto de Referencia
|
|
5106
|
+
ctx.fillStyle = '#FFFFFF';
|
|
5107
|
+
ctx.font = 'bold 18px sans-serif';
|
|
5108
|
+
ctx.textAlign = 'center';
|
|
5109
|
+
ctx.textBaseline = 'middle';
|
|
5110
|
+
ctx.fillText(this.labelText().toUpperCase(), canvas.width / 2, rectY + rectHeight / 2);
|
|
5111
|
+
// Conversión final y descarga en JPEG
|
|
5112
|
+
canvas.toBlob((finalBlob) => {
|
|
5113
|
+
if (finalBlob) {
|
|
5114
|
+
const downloadUrl = URL.createObjectURL(finalBlob);
|
|
5115
|
+
const link = document.createElement('a');
|
|
5116
|
+
link.href = downloadUrl;
|
|
5117
|
+
const now = new Date();
|
|
5118
|
+
const timestamp = now.getFullYear().toString() +
|
|
5119
|
+
(now.getMonth() + 1).toString().padStart(2, '0') +
|
|
5120
|
+
now.getDate().toString().padStart(2, '0') +
|
|
5121
|
+
now.getHours().toString().padStart(2, '0') +
|
|
5122
|
+
now.getMinutes().toString().padStart(2, '0') +
|
|
5123
|
+
now.getSeconds().toString().padStart(2, '0');
|
|
5124
|
+
link.download = `qr-${timestamp}.jpg`;
|
|
5125
|
+
document.body.appendChild(link);
|
|
5126
|
+
link.click();
|
|
5127
|
+
document.body.removeChild(link);
|
|
5128
|
+
URL.revokeObjectURL(downloadUrl);
|
|
5129
|
+
URL.revokeObjectURL(qrUrl);
|
|
5130
|
+
}
|
|
5131
|
+
}, 'image/jpeg', 0.95);
|
|
5132
|
+
};
|
|
5133
|
+
}
|
|
5134
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: QrGenerator, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5135
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: QrGenerator, isStandalone: true, selector: "dsx-qr-generator", inputs: { codigoQr: { classPropertyName: "codigoQr", publicName: "codigoQr", isSignal: true, isRequired: false, transformFunction: null }, labelQr: { classPropertyName: "labelQr", publicName: "labelQr", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"w-full max-w-xs mx-auto text-center\">\r\n <!-- Encabezado -->\r\n <h2 class=\"text-sm font-semibold text-gray-700 mb-2\">\r\n Generador de C\u00F3digo QR\r\n </h2>\r\n\r\n <!-- Valor recibido como validaci\u00F3n (solo lectura) -->\r\n <p class=\"text-xs text-gray-400 mb-3 truncate\">\r\n <span class=\"font-medium text-gray-500\">Contenido: </span>{{ textToEncode()\r\n }}\r\n </p>\r\n\r\n <!-- Preview del QR con dise\u00F1o -->\r\n @if (qrImageUrl()) {\r\n <div class=\"flex flex-col items-center gap-3\">\r\n <!-- Imagen generada con esquinas y banner -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-1 shadow-md inline-block\"\r\n >\r\n <img\r\n [src]=\"qrImageUrl()\"\r\n alt=\"C\u00F3digo QR\"\r\n class=\"w-44 h-auto block rounded\"\r\n />\r\n </div>\r\n\r\n <!-- Bot\u00F3n descarga -->\r\n <button\r\n style=\"\r\n background: #059669;\r\n color: #fff;\r\n font-size: 0.8rem;\r\n padding: 0.4rem 1rem;\r\n border-radius: 0.5rem;\r\n \"\r\n class=\"font-semibold hover:opacity-90 transition-opacity flex items-center justify-center gap-1\"\r\n (click)=\"downloadWithLabel()\"\r\n >\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n style=\"width: 1rem; height: 1rem; flex-shrink: 0\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n >\r\n <path\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n d=\"M4 16v2a2 2 0 002 2h12a2 2 0 002-2v-2M7 10l5 5 5-5M12 15V3\"\r\n />\r\n </svg>\r\n Descargar JPEG\r\n </button>\r\n </div>\r\n }\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }] });
|
|
5136
|
+
}
|
|
5137
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: QrGenerator, decorators: [{
|
|
5138
|
+
type: Component,
|
|
5139
|
+
args: [{ selector: 'dsx-qr-generator', imports: [FormsModule], template: "<div class=\"w-full max-w-xs mx-auto text-center\">\r\n <!-- Encabezado -->\r\n <h2 class=\"text-sm font-semibold text-gray-700 mb-2\">\r\n Generador de C\u00F3digo QR\r\n </h2>\r\n\r\n <!-- Valor recibido como validaci\u00F3n (solo lectura) -->\r\n <p class=\"text-xs text-gray-400 mb-3 truncate\">\r\n <span class=\"font-medium text-gray-500\">Contenido: </span>{{ textToEncode()\r\n }}\r\n </p>\r\n\r\n <!-- Preview del QR con dise\u00F1o -->\r\n @if (qrImageUrl()) {\r\n <div class=\"flex flex-col items-center gap-3\">\r\n <!-- Imagen generada con esquinas y banner -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-1 shadow-md inline-block\"\r\n >\r\n <img\r\n [src]=\"qrImageUrl()\"\r\n alt=\"C\u00F3digo QR\"\r\n class=\"w-44 h-auto block rounded\"\r\n />\r\n </div>\r\n\r\n <!-- Bot\u00F3n descarga -->\r\n <button\r\n style=\"\r\n background: #059669;\r\n color: #fff;\r\n font-size: 0.8rem;\r\n padding: 0.4rem 1rem;\r\n border-radius: 0.5rem;\r\n \"\r\n class=\"font-semibold hover:opacity-90 transition-opacity flex items-center justify-center gap-1\"\r\n (click)=\"downloadWithLabel()\"\r\n >\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n style=\"width: 1rem; height: 1rem; flex-shrink: 0\"\r\n fill=\"none\"\r\n viewBox=\"0 0 24 24\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n >\r\n <path\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n d=\"M4 16v2a2 2 0 002 2h12a2 2 0 002-2v-2M7 10l5 5 5-5M12 15V3\"\r\n />\r\n </svg>\r\n Descargar JPEG\r\n </button>\r\n </div>\r\n }\r\n</div>\r\n" }]
|
|
5140
|
+
}], ctorParameters: () => [], propDecorators: { codigoQr: [{ type: i0.Input, args: [{ isSignal: true, alias: "codigoQr", required: false }] }], labelQr: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelQr", required: false }] }] } });
|
|
5141
|
+
|
|
4880
5142
|
class TokenPurposeLogin {
|
|
4881
5143
|
fb = inject(FormBuilder);
|
|
4882
5144
|
_authorizeService = inject(AuthorizeService);
|
|
@@ -7039,5 +7301,5 @@ function minimumAgeValidator(minimumAge, referenceDate) {
|
|
|
7039
7301
|
* Generated bundle index. Do not edit.
|
|
7040
7302
|
*/
|
|
7041
7303
|
|
|
7042
|
-
export { ACTION_TYPES, AlertaService, AppMessageErrorComponent, ArrowNavigationDirective, AuthorizeService, BaseCRUDService, CACHE_KEYS, CacheService, CssV2Component, DSX_PALETTE, DateIndicator, DocxPreviewComponent, DsxAddToolsModule, DsxButtonComponent, DsxEnableDisable, DsxStatusToggle, DteService, ENVIRONMENT, EndpointService, ErrorHandlerService, FileComponent, GTQFormatter, HttpHelpersService, INITIAL_PARAMETERS, IconDsxComponent, JoinByPipe, JsonHighlightPipe, JsonValuesDebujComponent, JsonViewerComponent, KpicardComponent, LoadingComponent, LoadingLottieComponent, LogoDsxComponent, MasterDetailChangeService, NavbarDsxComponent, NetworkStatusComponent, OnlyRangoPatternDirective, ParameterValuesService, PdfPreviewComponent, PrimeNgModule, SWEET_ALERT_THEMES, SecurityService, SelectAllOnFocusDirective, SpinnerLoadingService, TemplateHighlight, TokenPurposeLogin, TruncatePipe, UtilityAddService, asyncExistsValidator, atLeastOneFieldRequiredValidator, chainControlGroups, createCurrencyFormatter, createInitialCache, createTypedCacheProvider, cuiValidator, dateMinMaxValidator, dateRangeValidator, dateRangeValidatorFromTo, developmentEnvironment, getZeroBasedRolIndex, guardTokenPurposeGuard, httpAuthorizeInterceptor, minimumAgeValidator, nitValidator, productionEnvironment, provideEnvironment, templateVariablesValidator, validateEnvironmentConfig };
|
|
7304
|
+
export { ACTION_TYPES, AlertaService, AppMessageErrorComponent, ArrowNavigationDirective, AuthorizeService, BaseCRUDService, CACHE_KEYS, CacheService, CssV2Component, DSX_PALETTE, DateIndicator, DocxPreviewComponent, DsxAddToolsModule, DsxButtonComponent, DsxEnableDisable, DsxStatusToggle, DteService, ENVIRONMENT, EndpointService, ErrorHandlerService, FileComponent, GTQFormatter, HttpHelpersService, INITIAL_PARAMETERS, IconDsxComponent, JoinByPipe, JsonHighlightPipe, JsonValuesDebujComponent, JsonViewerComponent, KpicardComponent, LoadingComponent, LoadingLottieComponent, LogoDsxComponent, MasterDetailChangeService, NavbarDsxComponent, NetworkStatusComponent, OnlyRangoPatternDirective, ParameterValuesService, PdfPreviewComponent, PrimeNgModule, QrGenerator, QrService, SWEET_ALERT_THEMES, SecurityService, SelectAllOnFocusDirective, SpinnerLoadingService, TemplateHighlight, TokenPurposeLogin, TruncatePipe, UtilityAddService, asyncExistsValidator, atLeastOneFieldRequiredValidator, chainControlGroups, createCurrencyFormatter, createInitialCache, createTypedCacheProvider, cuiValidator, dateMinMaxValidator, dateRangeValidator, dateRangeValidatorFromTo, developmentEnvironment, getZeroBasedRolIndex, guardTokenPurposeGuard, httpAuthorizeInterceptor, minimumAgeValidator, nitValidator, productionEnvironment, provideEnvironment, templateVariablesValidator, validateEnvironmentConfig };
|
|
7043
7305
|
//# sourceMappingURL=ngx-dsxlibrary.mjs.map
|