@nitra/zebra 7.0.0 → 7.1.0

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/dist/plugin.js CHANGED
@@ -17,6 +17,91 @@ var __exportAll = (all, no_symbols) => {
17
17
  return target;
18
18
  };
19
19
 
20
+ //#endregion
21
+ //#region ../node_modules/.bun/@capacitor+preferences@7.0.3+12459b436ab1bc92/node_modules/@capacitor/preferences/dist/esm/web.js
22
+ var web_exports$1 = /* @__PURE__ */ __exportAll({ PreferencesWeb: () => PreferencesWeb });
23
+ var PreferencesWeb;
24
+ var init_web$1 = __esmMin((() => {
25
+ PreferencesWeb = class extends WebPlugin {
26
+ constructor() {
27
+ super(...arguments);
28
+ this.group = "CapacitorStorage";
29
+ }
30
+ async configure({ group }) {
31
+ if (typeof group === "string") this.group = group;
32
+ }
33
+ async get(options) {
34
+ return { value: this.impl.getItem(this.applyPrefix(options.key)) };
35
+ }
36
+ async set(options) {
37
+ this.impl.setItem(this.applyPrefix(options.key), options.value);
38
+ }
39
+ async remove(options) {
40
+ this.impl.removeItem(this.applyPrefix(options.key));
41
+ }
42
+ async keys() {
43
+ return { keys: this.rawKeys().map((k) => k.substring(this.prefix.length)) };
44
+ }
45
+ async clear() {
46
+ for (const key of this.rawKeys()) this.impl.removeItem(key);
47
+ }
48
+ async migrate() {
49
+ var _a;
50
+ const migrated = [];
51
+ const existing = [];
52
+ const oldprefix = "_cap_";
53
+ const keys = Object.keys(this.impl).filter((k) => k.indexOf(oldprefix) === 0);
54
+ for (const oldkey of keys) {
55
+ const key = oldkey.substring(5);
56
+ const value = (_a = this.impl.getItem(oldkey)) !== null && _a !== void 0 ? _a : "";
57
+ const { value: currentValue } = await this.get({ key });
58
+ if (typeof currentValue === "string") existing.push(key);
59
+ else {
60
+ await this.set({
61
+ key,
62
+ value
63
+ });
64
+ migrated.push(key);
65
+ }
66
+ }
67
+ return {
68
+ migrated,
69
+ existing
70
+ };
71
+ }
72
+ async removeOld() {
73
+ const oldprefix = "_cap_";
74
+ const keys = Object.keys(this.impl).filter((k) => k.indexOf(oldprefix) === 0);
75
+ for (const oldkey of keys) this.impl.removeItem(oldkey);
76
+ }
77
+ get impl() {
78
+ return window.localStorage;
79
+ }
80
+ get prefix() {
81
+ return this.group === "NativeStorage" ? "" : `${this.group}.`;
82
+ }
83
+ rawKeys() {
84
+ return Object.keys(this.impl).filter((k) => k.indexOf(this.prefix) === 0);
85
+ }
86
+ applyPrefix(key) {
87
+ return this.prefix + key;
88
+ }
89
+ };
90
+ }));
91
+
92
+ //#endregion
93
+ //#region ../node_modules/.bun/@capacitor+preferences@7.0.3+12459b436ab1bc92/node_modules/@capacitor/preferences/dist/esm/index.js
94
+ const Preferences = registerPlugin("Preferences", { web: () => Promise.resolve().then(() => (init_web$1(), web_exports$1)).then((m) => new m.PreferencesWeb()) });
95
+
96
+ //#endregion
97
+ //#region src/utils/validate.js
98
+ function normalizePrintArg(zpl) {
99
+ if (typeof zpl !== "string") throw new TypeError("Expected \"zpl\" to be a string");
100
+ const command = zpl.trim();
101
+ if (!command) throw new Error("ZPL команда порожня");
102
+ return command;
103
+ }
104
+
20
105
  //#endregion
21
106
  //#region ../node_modules/.bun/consola@3.4.2/node_modules/consola/dist/core.mjs
22
107
  function isPlainObject$1(value) {
@@ -461,87 +546,276 @@ var init_browser$1 = __esmMin((() => {
461
546
  }));
462
547
 
463
548
  //#endregion
464
- //#region ../node_modules/.bun/@nitra+consola@2.3.0/node_modules/@nitra/consola/src/browser.js
465
- var options, CanvasPopupReporter, isPopupDebugEnabled, canvasPopupReporter, defaultConsola;
549
+ //#region ../node_modules/.bun/@nitra+consola@2.4.1/node_modules/@nitra/consola/src/otel-reporter.js
550
+ var getViteEnvVar$1, OpenTelemetryReporter;
551
+ var init_otel_reporter = __esmMin((() => {
552
+ getViteEnvVar$1 = (name) => {
553
+ try {
554
+ const viteName = `VITE_${name}`;
555
+ return import.meta?.env?.[viteName];
556
+ } catch {
557
+ return null;
558
+ }
559
+ };
560
+ OpenTelemetryReporter = class {
561
+ constructor(options = {}) {
562
+ this.endpoint = options.endpoint || getViteEnvVar$1("OTEL_EXPORTER_OTLP_LOGS_ENDPOINT") || "http://localhost:4318/v1/logs";
563
+ this.serviceName = options.serviceName || getViteEnvVar$1("OTEL_SERVICE_NAME") || "consola-service";
564
+ this.serviceVersion = options.serviceVersion || getViteEnvVar$1("OTEL_SERVICE_VERSION") || "1.0.0";
565
+ this.batchSize = options.batchSize || parseInt(getViteEnvVar$1("OTEL_BATCH_SIZE") || "10", 10);
566
+ this.flushInterval = options.flushInterval || parseInt(getViteEnvVar$1("OTEL_FLUSH_INTERVAL") || "5000", 10);
567
+ this.buffer = [];
568
+ this.flushTimer = null;
569
+ this.headers = {
570
+ "Content-Type": "application/json",
571
+ ...options.headers
572
+ };
573
+ if (this.flushInterval > 0) this.startFlushTimer();
574
+ }
575
+ formatMessage(logObj) {
576
+ const args = logObj.args || [];
577
+ if (args.length === 0) return "";
578
+ return args.map((arg) => {
579
+ if (arg instanceof Error) {
580
+ let msg = `${arg.name || "Error"}: ${arg.message || ""}`;
581
+ if (arg.stack && arg.stack !== arg.message) msg += "\n" + arg.stack;
582
+ return msg;
583
+ }
584
+ if (arg === null) return "null";
585
+ if (arg === void 0) return "undefined";
586
+ if (typeof arg === "object") try {
587
+ return JSON.stringify(arg, null, 2);
588
+ } catch {
589
+ return String(arg);
590
+ }
591
+ return String(arg);
592
+ }).join(" ");
593
+ }
594
+ getSeverityNumber(type) {
595
+ return {
596
+ trace: 1,
597
+ debug: 5,
598
+ info: 9,
599
+ log: 9,
600
+ warn: 13,
601
+ error: 17,
602
+ fatal: 21,
603
+ success: 9,
604
+ start: 9,
605
+ ready: 9,
606
+ fail: 17
607
+ }[type] || 9;
608
+ }
609
+ getSeverityText(type) {
610
+ return {
611
+ trace: "TRACE",
612
+ debug: "DEBUG",
613
+ info: "INFO",
614
+ log: "INFO",
615
+ warn: "WARN",
616
+ error: "ERROR",
617
+ fatal: "FATAL",
618
+ success: "INFO",
619
+ start: "INFO",
620
+ ready: "INFO",
621
+ fail: "ERROR"
622
+ }[type] || "INFO";
623
+ }
624
+ getFileInfo() {
625
+ try {
626
+ const stack = (/* @__PURE__ */ new Error("Stack trace")).stack;
627
+ if (!stack) return null;
628
+ const skipPatterns = [
629
+ "OpenTelemetryReporter",
630
+ "otel-reporter.js",
631
+ "browser.js",
632
+ "consola",
633
+ "createLogger"
634
+ ];
635
+ const lines = stack.split("\n").slice(4, 15);
636
+ for (const line of lines) {
637
+ const trimmed = line.trim();
638
+ if (!skipPatterns.some((pattern) => trimmed.includes(pattern))) {
639
+ const match = trimmed.match(/\(?([^()]+):(\d+):(\d+)\)?/) || trimmed.match(/at\s+[^(]*\(?([^:]+):(\d+):(\d+)\)?/);
640
+ if (match) {
641
+ let file = match[1].trim();
642
+ const lineNum = match[2];
643
+ if (file.includes("://")) file = file.slice(file.indexOf("://") + 3).slice(file.indexOf("/"));
644
+ if (file.includes("/src/")) file = file.slice(file.indexOf("/src/") + 5);
645
+ const queryIndex = file.indexOf("?");
646
+ if (queryIndex > 0) file = file.slice(0, queryIndex);
647
+ const hashIndex = file.indexOf("#");
648
+ if (hashIndex > 0) file = file.slice(0, hashIndex);
649
+ if (file.startsWith("/")) file = file.slice(1);
650
+ if (file && lineNum) return {
651
+ file,
652
+ line: parseInt(lineNum, 10),
653
+ column: parseInt(match[3], 10)
654
+ };
655
+ }
656
+ }
657
+ }
658
+ } catch {}
659
+ return null;
660
+ }
661
+ createLogRecord(logObj) {
662
+ const type = logObj.type || "log";
663
+ const message = this.formatMessage(logObj);
664
+ const fileInfo = this.getFileInfo();
665
+ const logRecord = {
666
+ timeUnixNano: (Date.now() * 1e6).toString(),
667
+ severityNumber: this.getSeverityNumber(type),
668
+ severityText: this.getSeverityText(type),
669
+ body: { stringValue: message },
670
+ attributes: [{
671
+ key: "log.type",
672
+ value: { stringValue: type }
673
+ }]
674
+ };
675
+ if (fileInfo) {
676
+ logRecord.attributes.push({
677
+ key: "code.filepath",
678
+ value: { stringValue: fileInfo.file }
679
+ }, {
680
+ key: "code.lineno",
681
+ value: { intValue: fileInfo.line }
682
+ });
683
+ if (fileInfo.column) logRecord.attributes.push({
684
+ key: "code.colno",
685
+ value: { intValue: fileInfo.column }
686
+ });
687
+ }
688
+ if (logObj.extra && typeof logObj.extra === "object") for (const [key, value] of Object.entries(logObj.extra)) logRecord.attributes.push({
689
+ key: `extra.${key}`,
690
+ value: { stringValue: String(value) }
691
+ });
692
+ return logRecord;
693
+ }
694
+ async sendLogs(logs) {
695
+ if (logs.length === 0) return;
696
+ const payload = { resourceLogs: [{
697
+ resource: { attributes: [{
698
+ key: "service.name",
699
+ value: { stringValue: this.serviceName }
700
+ }, {
701
+ key: "service.version",
702
+ value: { stringValue: this.serviceVersion }
703
+ }] },
704
+ scopeLogs: [{
705
+ scope: {
706
+ name: "consola",
707
+ version: "1.0.0"
708
+ },
709
+ logRecords: logs
710
+ }]
711
+ }] };
712
+ try {
713
+ const response = await fetch(this.endpoint, {
714
+ method: "POST",
715
+ mode: "cors",
716
+ headers: this.headers,
717
+ body: JSON.stringify(payload)
718
+ });
719
+ if (!response.ok) console.warn(`OpenTelemetry export failed: ${response.status} ${response.statusText}`);
720
+ } catch (error) {
721
+ console.warn("OpenTelemetry export error:", error?.message || String(error));
722
+ }
723
+ }
724
+ async flush() {
725
+ if (this.buffer.length === 0) return;
726
+ const logsToSend = [...this.buffer];
727
+ this.buffer = [];
728
+ await this.sendLogs(logsToSend);
729
+ }
730
+ startFlushTimer() {
731
+ if (this.flushTimer) clearInterval(this.flushTimer);
732
+ this.flushTimer = setInterval(() => {
733
+ this.flush().catch((error) => {
734
+ console.warn("OpenTelemetry flush error:", error?.message || String(error));
735
+ });
736
+ }, this.flushInterval);
737
+ }
738
+ log(logObj) {
739
+ try {
740
+ const logRecord = this.createLogRecord(logObj);
741
+ this.buffer.push(logRecord);
742
+ if (this.buffer.length >= this.batchSize) this.flush().catch((error) => {
743
+ console.warn("OpenTelemetry flush error:", error?.message || String(error));
744
+ });
745
+ } catch (error) {
746
+ console.warn("OpenTelemetry log processing error:", error?.message || String(error));
747
+ }
748
+ }
749
+ destroy() {
750
+ if (this.flushTimer) {
751
+ clearInterval(this.flushTimer);
752
+ this.flushTimer = null;
753
+ }
754
+ return this.flush();
755
+ }
756
+ };
757
+ }));
758
+
759
+ //#endregion
760
+ //#region ../node_modules/.bun/@nitra+consola@2.4.1/node_modules/@nitra/consola/src/browser.js
761
+ var options, POPUP_PADDING, POPUP_LABEL_PADDING, POPUP_LINE_HEIGHT, POPUP_BUTTON_SIZE, POPUP_BUTTON_PADDING, POPUP_MIN_HEIGHT, POPUP_MAX_MESSAGE_LENGTH, POPUP_STYLES, HtmlPopupReporter, getViteEnvVar, isPopupDebugEnabled, htmlPopupReporter, defaultConsola, openTelemetryReporter;
466
762
  var init_browser = __esmMin((() => {
467
763
  init_browser$1();
764
+ init_otel_reporter();
468
765
  options = {};
469
766
  if (typeof __CONSOLA_LEVEL_DEBUG__ !== "undefined") options.level = 4;
470
767
  else if (typeof location !== "undefined" && location.protocol === "http:") options.level = 4;
471
768
  else if (typeof process !== "undefined" && (process.env.DEV || process.env.CONSOLA_LEVEL_DEBUG)) options.level = 4;
472
- CanvasPopupReporter = class CanvasPopupReporter {
473
- static PADDING = 12;
474
- static LABEL_PADDING = 8;
475
- static LINE_HEIGHT = 20;
476
- static BUTTON_SIZE = 18;
477
- static BUTTON_PADDING = 6;
478
- static MIN_HEIGHT = 36;
479
- static MAX_MESSAGE_LENGTH = 500;
480
- static FONT_TEXT = "13px -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif";
481
- static FONT_MONO = "11px monospace";
769
+ POPUP_PADDING = 12;
770
+ POPUP_LABEL_PADDING = 8;
771
+ POPUP_LINE_HEIGHT = 20;
772
+ POPUP_BUTTON_SIZE = 18;
773
+ POPUP_BUTTON_PADDING = 6;
774
+ POPUP_MIN_HEIGHT = 36;
775
+ POPUP_MAX_MESSAGE_LENGTH = 500;
776
+ POPUP_STYLES = `
777
+ #consola-popup-container { position: fixed; inset: 0; pointer-events: none; z-index: 999999; }
778
+ .consola-popup { pointer-events: auto; position: fixed; left: 20px; max-width: calc(100vw - 40px); min-height: ${POPUP_MIN_HEIGHT}px;
779
+ display: flex; align-items: stretch; background: #fff; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e0e0e0;
780
+ font: 13px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; }
781
+ .consola-popup-label { flex-shrink: 0; padding: 0 ${POPUP_LABEL_PADDING}px; display: flex; align-items: center; justify-content: center;
782
+ color: #fff; font: 11px monospace; font-weight: bold; text-transform: lowercase; }
783
+ .consola-popup-content { flex: 1; min-width: 0; padding: ${POPUP_PADDING}px; display: flex; flex-wrap: wrap; align-items: flex-start; gap: 4px 8px; }
784
+ .consola-popup-text { flex: 1 1 auto; min-width: 0; color: #212121; line-height: ${POPUP_LINE_HEIGHT}px; white-space: pre-wrap; word-break: break-word; }
785
+ .consola-popup-filelink { flex: 0 0 auto; color: #1976D2; font: 11px monospace; text-decoration: underline; cursor: pointer; }
786
+ .consola-popup-filelink:hover { text-decoration: underline; }
787
+ .consola-popup-close { flex-shrink: 0; width: ${POPUP_BUTTON_SIZE}px; height: ${POPUP_BUTTON_SIZE}px; margin: ${POPUP_BUTTON_PADDING}px; padding: 0; border: none; background: transparent;
788
+ color: #999; font-size: 16px; line-height: 1; cursor: pointer; display: flex; align-items: center; justify-content: center; border-radius: 2px; }
789
+ .consola-popup-close:hover { background: rgba(0,0,0,0.06); color: #666; }
790
+ `;
791
+ HtmlPopupReporter = class {
482
792
  constructor() {
483
- this.canvas = null;
484
- this.ctx = null;
793
+ this.container = null;
485
794
  this.messages = [];
486
795
  this.messageId = 0;
487
- this.initCanvas();
796
+ this.init();
488
797
  }
489
- initCanvas() {
798
+ init() {
490
799
  if (typeof document === "undefined") return;
491
- const init = () => {
800
+ const doInit = () => {
492
801
  if (!document.body) {
493
- setTimeout(init, 10);
802
+ setTimeout(doInit, 10);
494
803
  return;
495
804
  }
496
- let canvas = document.querySelector("#consola-popup-canvas");
497
- if (!canvas) {
498
- canvas = document.createElement("canvas");
499
- canvas.id = "consola-popup-canvas";
500
- canvas.style.position = "fixed";
501
- canvas.style.top = "0";
502
- canvas.style.left = "0";
503
- canvas.style.width = "100%";
504
- canvas.style.height = "100%";
505
- canvas.style.pointerEvents = "auto";
506
- canvas.style.zIndex = "999999";
507
- document.body.append(canvas);
508
- canvas.addEventListener("click", (e) => this.handleClick(e));
805
+ let container = document.querySelector("#consola-popup-container");
806
+ if (!container) {
807
+ const style = document.createElement("style");
808
+ style.textContent = POPUP_STYLES;
809
+ document.head.append(style);
810
+ container = document.createElement("div");
811
+ container.id = "consola-popup-container";
812
+ document.body.append(container);
509
813
  }
510
- this.canvas = canvas;
511
- this.resizeCanvas();
512
- window.addEventListener("resize", () => this.resizeCanvas());
814
+ this.container = container;
513
815
  this.animate();
514
816
  };
515
- if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", init);
516
- else init();
517
- }
518
- handleClick(event) {
519
- if (!this.canvas || !this.ctx) return;
520
- const rect = this.canvas.getBoundingClientRect();
521
- const x = event.clientX - rect.left;
522
- const y = event.clientY - rect.top;
523
- for (let i = this.messages.length - 1; i >= 0; i--) {
524
- const msg = this.messages[i];
525
- if (msg.fileInfo && msg.fileLinkX && msg.fileLinkY && msg.fileLinkWidth) {
526
- if (x >= msg.fileLinkX - msg.fileLinkWidth && x <= msg.fileLinkX && y >= msg.fileLinkY && y <= msg.fileLinkY + 14) {
527
- console.log(`%c${msg.fileInfo.file}:${msg.fileInfo.line}`, "color: #1976D2; text-decoration: underline;");
528
- return;
529
- }
530
- }
531
- const buttonX = msg.x + (msg.width || 200) - CanvasPopupReporter.BUTTON_SIZE - CanvasPopupReporter.BUTTON_PADDING;
532
- const buttonY = msg.y + CanvasPopupReporter.BUTTON_PADDING;
533
- if (x >= buttonX && x <= buttonX + CanvasPopupReporter.BUTTON_SIZE && y >= buttonY && y <= buttonY + CanvasPopupReporter.BUTTON_SIZE) {
534
- const index = this.messages.findIndex((m) => m.id === msg.id);
535
- if (index !== -1) this.messages.splice(index, 1);
536
- return;
537
- }
538
- }
539
- }
540
- resizeCanvas() {
541
- if (!this.canvas) return;
542
- this.canvas.width = window.innerWidth;
543
- this.canvas.height = window.innerHeight;
544
- this.ctx = this.canvas.getContext("2d");
817
+ if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", doInit);
818
+ else doInit();
545
819
  }
546
820
  getColorForType(type) {
547
821
  const colors = {
@@ -568,6 +842,7 @@ var init_browser = __esmMin((() => {
568
842
  const stack = (/* @__PURE__ */ new Error("Stack trace")).stack;
569
843
  if (!stack) return null;
570
844
  const skipPatterns = [
845
+ "HtmlPopupReporter",
571
846
  "CanvasPopupReporter",
572
847
  "browser.js",
573
848
  "consola",
@@ -620,172 +895,93 @@ var init_browser = __esmMin((() => {
620
895
  }
621
896
  return String(arg);
622
897
  }).join(" ");
623
- return message.length > CanvasPopupReporter.MAX_MESSAGE_LENGTH ? message.slice(0, CanvasPopupReporter.MAX_MESSAGE_LENGTH) + "..." : message;
624
- }
625
- calculateMessageHeight(message, maxWidth) {
626
- if (!this.ctx) return CanvasPopupReporter.MIN_HEIGHT;
627
- this.ctx.save();
628
- this.ctx.font = CanvasPopupReporter.FONT_TEXT;
629
- const words = message.split(" ");
630
- const lines = [];
631
- let currentLine = "";
632
- for (const word of words) {
633
- const testLine = currentLine ? `${currentLine} ${word}` : word;
634
- if (this.ctx.measureText(testLine).width > maxWidth && currentLine) {
635
- lines.push(currentLine);
636
- currentLine = word;
637
- } else currentLine = testLine;
638
- }
639
- if (currentLine) lines.push(currentLine);
640
- this.ctx.restore();
641
- return Math.max(CanvasPopupReporter.MIN_HEIGHT, lines.length * CanvasPopupReporter.LINE_HEIGHT + CanvasPopupReporter.PADDING * 2);
898
+ return message.length > POPUP_MAX_MESSAGE_LENGTH ? message.slice(0, POPUP_MAX_MESSAGE_LENGTH) + "..." : message;
642
899
  }
643
900
  log(logObj) {
644
- if (!this.canvas || !this.ctx) return;
645
- const message = this.formatMessage(logObj);
646
- if (!message) return;
901
+ if (!this.container) return;
902
+ const text = this.formatMessage(logObj);
903
+ if (!text) return;
647
904
  const type = logObj.type || "log";
648
905
  const color = this.getColorForType(type);
649
906
  const typeLabel = this.getTypeLabel(type);
650
907
  const id = this.messageId++;
651
908
  const fileInfo = this.getFileInfo();
652
- this.ctx.save();
653
- this.ctx.font = CanvasPopupReporter.FONT_MONO;
654
- const labelWidth = this.ctx.measureText(typeLabel).width + 16;
655
- let fileLinkWidth = 0;
909
+ const popup = document.createElement("div");
910
+ popup.className = "consola-popup";
911
+ popup.dataset.id = String(id);
912
+ popup.style.bottom = `${window.innerHeight}px`;
913
+ popup.style.backgroundColor = "#fff";
914
+ const label = document.createElement("span");
915
+ label.className = "consola-popup-label";
916
+ label.style.backgroundColor = color;
917
+ label.textContent = typeLabel;
918
+ const content = document.createElement("div");
919
+ content.className = "consola-popup-content";
920
+ const textEl = document.createElement("div");
921
+ textEl.className = "consola-popup-text";
922
+ textEl.textContent = text;
923
+ content.append(textEl);
656
924
  if (fileInfo) {
657
- const fileLinkText = `${fileInfo.file}:${fileInfo.line}`;
658
- fileLinkWidth = this.ctx.measureText(fileLinkText).width + 12;
925
+ const fileLink = document.createElement("span");
926
+ fileLink.className = "consola-popup-filelink";
927
+ fileLink.textContent = `${fileInfo.file}:${fileInfo.line}`;
928
+ fileLink.role = "button";
929
+ fileLink.tabIndex = 0;
930
+ fileLink.addEventListener("click", (e) => {
931
+ e.preventDefault();
932
+ console.log(`%c${fileInfo.file}:${fileInfo.line}`, "color: #1976D2; text-decoration: underline;");
933
+ });
934
+ content.append(fileLink);
659
935
  }
660
- this.ctx.restore();
661
- const textMaxWidth = this.canvas.width - 40 - labelWidth - CanvasPopupReporter.PADDING * 2 - CanvasPopupReporter.BUTTON_SIZE - CanvasPopupReporter.BUTTON_PADDING - fileLinkWidth;
662
- const boxHeight = this.calculateMessageHeight(message, textMaxWidth);
936
+ const closeBtn = document.createElement("button");
937
+ closeBtn.type = "button";
938
+ closeBtn.className = "consola-popup-close";
939
+ closeBtn.setAttribute("aria-label", "Close");
940
+ closeBtn.textContent = "×";
941
+ closeBtn.addEventListener("click", () => {
942
+ const idx = this.messages.findIndex((m) => m.id === id);
943
+ if (idx !== -1) {
944
+ const entry = this.messages[idx];
945
+ if (entry.el && entry.el.parentNode) entry.el.remove();
946
+ this.messages.splice(idx, 1);
947
+ }
948
+ });
949
+ popup.append(label, content, closeBtn);
950
+ this.container.append(popup);
951
+ const height = popup.offsetHeight;
663
952
  this.messages.push({
664
953
  id,
665
- text: message,
666
- color,
667
- type,
668
- typeLabel,
669
- fileInfo,
670
- timestamp: Date.now(),
671
- y: this.canvas.height,
672
- opacity: 1,
673
- x: 20,
674
- height: boxHeight,
675
- width: 0
954
+ el: popup,
955
+ targetBottom: 20,
956
+ currentBottom: window.innerHeight,
957
+ height
676
958
  });
677
959
  }
678
960
  animate() {
679
- if (!this.canvas || !this.ctx) return;
680
- this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
681
- let currentY = this.canvas.height - 20;
961
+ if (!this.container) return;
962
+ let offset = 20;
682
963
  for (let i = this.messages.length - 1; i >= 0; i--) {
683
964
  const msg = this.messages[i];
684
- const msgHeight = msg.height || 60;
685
- const targetY = currentY - msgHeight;
686
- msg.y += (targetY - msg.y) * .1;
687
- currentY = targetY - 10;
688
- this.ctx.save();
689
- this.ctx.globalAlpha = msg.opacity;
690
- this.ctx.font = "13px -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif";
691
- this.ctx.textBaseline = "top";
692
- const padding = CanvasPopupReporter.PADDING;
693
- const labelPadding = CanvasPopupReporter.LABEL_PADDING;
694
- const maxWidth = this.canvas.width - 40;
695
- const lineHeight = CanvasPopupReporter.LINE_HEIGHT;
696
- this.ctx.font = CanvasPopupReporter.FONT_MONO;
697
- const labelWidth = this.ctx.measureText(msg.typeLabel || "log").width + labelPadding * 2;
698
- const buttonSize = CanvasPopupReporter.BUTTON_SIZE;
699
- const buttonPadding = CanvasPopupReporter.BUTTON_PADDING;
700
- let fileLinkWidth = 0;
701
- let fileLinkText = "";
702
- if (msg.fileInfo) {
703
- fileLinkText = `${msg.fileInfo.file}:${msg.fileInfo.line}`;
704
- this.ctx.font = CanvasPopupReporter.FONT_MONO;
705
- fileLinkWidth = this.ctx.measureText(fileLinkText).width + 12;
706
- }
707
- this.ctx.font = CanvasPopupReporter.FONT_TEXT;
708
- const textMaxWidthForHeight = maxWidth - labelWidth - padding * 2 - fileLinkWidth - buttonSize - buttonPadding;
709
- const calculatedHeight = this.calculateMessageHeight(msg.text, textMaxWidthForHeight);
710
- if (msg.height !== calculatedHeight) msg.height = calculatedHeight;
711
- const words = msg.text.split(" ");
712
- const lines = [];
713
- let currentLine = "";
714
- const textMaxWidth = textMaxWidthForHeight;
715
- for (const word of words) {
716
- const testLine = currentLine ? currentLine + " " + word : word;
717
- if (this.ctx.measureText(testLine).width > textMaxWidth && currentLine) {
718
- lines.push(currentLine);
719
- currentLine = word;
720
- } else currentLine = testLine;
965
+ if (msg.el && msg.el.parentNode) {
966
+ const h = msg.el.offsetHeight;
967
+ msg.height = h;
968
+ msg.targetBottom = offset;
969
+ msg.currentBottom += (msg.targetBottom - msg.currentBottom) * .1;
970
+ msg.el.style.bottom = `${Math.round(msg.currentBottom)}px`;
971
+ offset += h + 10;
721
972
  }
722
- if (currentLine) lines.push(currentLine);
723
- const maxTextWidth = lines.length > 0 ? Math.max(...lines.map((line) => this.ctx.measureText(line).width)) : 0;
724
- const boxWidth = Math.min(labelWidth + padding * 2 + maxTextWidth + fileLinkWidth + buttonSize + buttonPadding, maxWidth);
725
- const boxHeight = Math.max(msg.height || calculatedHeight, CanvasPopupReporter.MIN_HEIGHT);
726
- msg.fileLinkX = msg.x + labelWidth + padding * 2 + maxTextWidth;
727
- msg.fileLinkY = msg.y + padding;
728
- msg.fileLinkWidth = fileLinkWidth;
729
- msg.width = boxWidth;
730
- this.ctx.fillStyle = "#ffffff";
731
- this.ctx.fillRect(msg.x, msg.y, boxWidth, boxHeight);
732
- this.ctx.shadowColor = "rgba(0, 0, 0, 0.1)";
733
- this.ctx.shadowBlur = 8;
734
- this.ctx.shadowOffsetX = 0;
735
- this.ctx.shadowOffsetY = 2;
736
- this.ctx.fillRect(msg.x, msg.y, boxWidth, boxHeight);
737
- this.ctx.shadowBlur = 0;
738
- this.ctx.shadowOffsetX = 0;
739
- this.ctx.shadowOffsetY = 0;
740
- this.ctx.strokeStyle = "#e0e0e0";
741
- this.ctx.lineWidth = 1;
742
- this.ctx.strokeRect(msg.x, msg.y, boxWidth, boxHeight);
743
- this.ctx.fillStyle = msg.color;
744
- this.ctx.fillRect(msg.x, msg.y, labelWidth, boxHeight);
745
- this.ctx.fillStyle = "#ffffff";
746
- this.ctx.font = CanvasPopupReporter.FONT_MONO;
747
- this.ctx.fontWeight = "bold";
748
- const labelTextY = msg.y + boxHeight / 2 - 6;
749
- this.ctx.textAlign = "center";
750
- this.ctx.fillText(msg.typeLabel, msg.x + labelWidth / 2, labelTextY);
751
- this.ctx.textAlign = "left";
752
- this.ctx.fillStyle = "#212121";
753
- this.ctx.font = CanvasPopupReporter.FONT_TEXT;
754
- const textStartX = msg.x + labelWidth + padding;
755
- for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) this.ctx.fillText(lines[lineIndex], textStartX, msg.y + padding + lineIndex * lineHeight, maxTextWidth);
756
- if (msg.fileInfo && fileLinkText) {
757
- this.ctx.fillStyle = "#1976D2";
758
- this.ctx.font = CanvasPopupReporter.FONT_MONO;
759
- this.ctx.textAlign = "right";
760
- const fileLinkX = msg.x + boxWidth - buttonSize - buttonPadding - 6;
761
- const fileLinkY = msg.y + padding + 2;
762
- this.ctx.fillText(fileLinkText, fileLinkX, fileLinkY);
763
- this.ctx.textAlign = "left";
764
- this.ctx.strokeStyle = "#1976D2";
765
- this.ctx.lineWidth = 1;
766
- const textMetrics = this.ctx.measureText(fileLinkText);
767
- this.ctx.beginPath();
768
- this.ctx.moveTo(fileLinkX - textMetrics.width, fileLinkY + 11);
769
- this.ctx.lineTo(fileLinkX, fileLinkY + 11);
770
- this.ctx.stroke();
771
- }
772
- const buttonX = msg.x + boxWidth - buttonSize - buttonPadding;
773
- const buttonY = msg.y + buttonPadding;
774
- this.ctx.strokeStyle = "#999999";
775
- this.ctx.lineWidth = 1.5;
776
- this.ctx.lineCap = "round";
777
- const crossPadding = 4;
778
- this.ctx.beginPath();
779
- this.ctx.moveTo(buttonX + crossPadding, buttonY + crossPadding);
780
- this.ctx.lineTo(buttonX + buttonSize - crossPadding, buttonY + buttonSize - crossPadding);
781
- this.ctx.moveTo(buttonX + buttonSize - crossPadding, buttonY + crossPadding);
782
- this.ctx.lineTo(buttonX + crossPadding, buttonY + buttonSize - crossPadding);
783
- this.ctx.stroke();
784
- this.ctx.restore();
785
973
  }
786
974
  requestAnimationFrame(() => this.animate());
787
975
  }
788
976
  };
977
+ getViteEnvVar = (name) => {
978
+ try {
979
+ const viteName = `VITE_${name}`;
980
+ return import.meta?.env?.[viteName];
981
+ } catch {
982
+ return null;
983
+ }
984
+ };
789
985
  isPopupDebugEnabled = false;
790
986
  if (typeof document !== "undefined") try {
791
987
  const envValue = import.meta.env?.VITE_CONSOLA_POPUP_DEBUG;
@@ -795,10 +991,15 @@ var init_browser = __esmMin((() => {
795
991
  const processValue = process.env.VITE_CONSOLA_POPUP_DEBUG;
796
992
  if (processValue) isPopupDebugEnabled = String(processValue).toLowerCase() === "true";
797
993
  }
798
- canvasPopupReporter = null;
799
- if (isPopupDebugEnabled && typeof document !== "undefined") canvasPopupReporter = new CanvasPopupReporter();
994
+ htmlPopupReporter = null;
995
+ if (isPopupDebugEnabled && typeof document !== "undefined") htmlPopupReporter = new HtmlPopupReporter();
800
996
  defaultConsola = consola.create(options);
801
- if (isPopupDebugEnabled && typeof document !== "undefined" && canvasPopupReporter) defaultConsola.addReporter(canvasPopupReporter);
997
+ if (isPopupDebugEnabled && typeof document !== "undefined" && htmlPopupReporter) defaultConsola.addReporter(htmlPopupReporter);
998
+ openTelemetryReporter = null;
999
+ if (getViteEnvVar("OTEL_EXPORTER_OTLP_LOGS_ENDPOINT")) {
1000
+ openTelemetryReporter = new OpenTelemetryReporter();
1001
+ defaultConsola.addReporter(openTelemetryReporter);
1002
+ }
802
1003
  }));
803
1004
 
804
1005
  //#endregion
@@ -808,10 +1009,12 @@ var ZebraWeb;
808
1009
  var init_web = __esmMin((() => {
809
1010
  init_browser();
810
1011
  ZebraWeb = class extends WebPlugin {
811
- async print(zpl) {
1012
+ async print({ zpl }) {
812
1013
  try {
813
1014
  defaultConsola.debug("Запит на підключення до принтера...", "info");
814
- const port = await navigator.serial.requestPort();
1015
+ const serial = navigator.serial;
1016
+ if (!serial) throw new Error("Web Serial API не підтримується в цьому браузері");
1017
+ const port = await serial.requestPort();
815
1018
  defaultConsola.debug("Порт вибрано, відкриваємо з'єднання...", "info");
816
1019
  await port.open({
817
1020
  baudRate: 9600,
@@ -821,22 +1024,65 @@ var init_web = __esmMin((() => {
821
1024
  flowControl: "none"
822
1025
  });
823
1026
  defaultConsola.debug("З'єднання відкрито!", "success");
824
- port.writable.getWriter();
825
- isConnected.value = true;
1027
+ const writer = port.writable.getWriter();
826
1028
  defaultConsola.debug("Принтер готовий до друку", "success");
1029
+ if (!port || !writer) {
1030
+ defaultConsola.debug("Помилка: Принтер не підключено", "error");
1031
+ return;
1032
+ }
1033
+ defaultConsola.debug(`Відправка ZPL команди: ${zpl.slice(0, 50)}...`, "info");
1034
+ const data = new TextEncoder().encode(zpl);
1035
+ await writer.write(data);
1036
+ defaultConsola.debug(`✓ Команда відправлена (${data.length} байт)`, "success");
1037
+ defaultConsola.debug("print from web capacitor plugin", zpl);
1038
+ return { success: true };
827
1039
  } catch (error) {
828
- defaultConsola.debug(`Помилка підключення: ${error.message}`, "error");
829
- isConnected.value = false;
1040
+ const message = error instanceof Error ? error.message : String(error);
1041
+ defaultConsola.debug(`Помилка підключення: ${message}`, "error");
1042
+ throw error;
830
1043
  }
831
- console.consola.debug("print from web capacitor plugin", zpl);
832
- return true;
1044
+ }
1045
+ getPairedDevices() {
1046
+ return { devices: [{
1047
+ address: "00:00:00:00:00:00",
1048
+ name: "Virtual Printer"
1049
+ }, {
1050
+ address: "11:11:11:11:11:11",
1051
+ name: "Virtual Headphone"
1052
+ }] };
833
1053
  }
834
1054
  };
835
1055
  }));
836
1056
 
837
1057
  //#endregion
838
1058
  //#region src/index.js
839
- const Zebra = registerPlugin("Zebra", { web: () => Promise.resolve().then(() => (init_web(), web_exports)).then((m) => new m.ZebraWeb()) });
1059
+ const ZebraPlugin = registerPlugin("Zebra", { web: () => Promise.resolve().then(() => (init_web(), web_exports)).then((m) => new m.ZebraWeb()) });
1060
+ const Zebra = {
1061
+ async print(zpl) {
1062
+ const zplNormalized = normalizePrintArg(zpl);
1063
+ const { value: address } = await Preferences.get({ key: "printer_address" });
1064
+ const addressTrimmed = typeof address === "string" ? address.trim() : "";
1065
+ if (!addressTrimmed) {
1066
+ const { devices } = await ZebraPlugin.getPairedDevices();
1067
+ if (devices?.length > 0) return {
1068
+ success: false,
1069
+ message: "device list",
1070
+ devices
1071
+ };
1072
+ return {
1073
+ success: false,
1074
+ message: "No paired devices found"
1075
+ };
1076
+ }
1077
+ return ZebraPlugin.print({
1078
+ zpl: zplNormalized,
1079
+ address: addressTrimmed
1080
+ });
1081
+ },
1082
+ getPairedDevices() {
1083
+ return ZebraPlugin.getPairedDevices();
1084
+ }
1085
+ };
840
1086
 
841
1087
  //#endregion
842
1088
  export { Zebra };