@mhmo91/schmancy 0.9.19 → 0.9.21

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.
Files changed (45) hide show
  1. package/dist/agent/{flow-CaPi2G8y.js.map → flow-CvG1fLW5.js.map} +1 -1
  2. package/dist/agent/{rolldown-runtime-DsMetpgY.js → rolldown-runtime-BIIoCavz.js} +9 -2
  3. package/dist/agent/schmancy.agent.js +3348 -3332
  4. package/dist/agent/schmancy.agent.js.map +1 -1
  5. package/dist/agent/{vendor-highlight-CHJZQQB7.js → vendor-highlight-Dow87ZL_.js} +90 -85
  6. package/dist/agent/{vendor-highlight-CHJZQQB7.js.map → vendor-highlight-Dow87ZL_.js.map} +1 -1
  7. package/dist/agent/{vendor-jsqr-r7GNh4P3.js → vendor-jsqr-Bl4iAtKC.js} +1 -1
  8. package/dist/agent/{vendor-jsqr-r7GNh4P3.js.map → vendor-jsqr-Bl4iAtKC.js.map} +1 -1
  9. package/dist/agent/{vendor-material-color-Be96dpGE.js.map → vendor-material-color-DcL7ZPxx.js.map} +1 -1
  10. package/dist/badge.cjs +1 -1
  11. package/dist/badge.js +1 -1
  12. package/dist/{code-highlight-zSYcSfCz.cjs → code-highlight-B_l8vDzn.cjs} +11 -11
  13. package/dist/code-highlight-B_l8vDzn.cjs.map +1 -0
  14. package/dist/{code-highlight-BgExKEto.js → code-highlight-CI_gqXYX.js} +30 -22
  15. package/dist/code-highlight-CI_gqXYX.js.map +1 -0
  16. package/dist/code-highlight.cjs +1 -1
  17. package/dist/code-highlight.js +1 -1
  18. package/dist/content-drawer.cjs +1 -1
  19. package/dist/content-drawer.js +1 -1
  20. package/dist/handover/agent-runtime-followups.md +1 -1
  21. package/dist/handover/agent-runtime-v1.md +3 -3
  22. package/dist/index.cjs +1 -1
  23. package/dist/index.js +2 -2
  24. package/dist/nav-drawer.cjs +1 -1
  25. package/dist/nav-drawer.js +1 -1
  26. package/dist/navigation-bar.cjs +1 -1
  27. package/dist/navigation-bar.js +1 -1
  28. package/dist/qr-scanner.cjs +5 -5
  29. package/dist/qr-scanner.cjs.map +1 -1
  30. package/dist/qr-scanner.js +10 -6
  31. package/dist/qr-scanner.js.map +1 -1
  32. package/dist/{src-BGj6ufWS.js → src-Dw-PjtMH.js} +1 -1
  33. package/dist/{src-BGj6ufWS.js.map → src-Dw-PjtMH.js.map} +1 -1
  34. package/dist/{src-BPKGdQdp.cjs → src-sG7Ihf0e.cjs} +1 -1
  35. package/dist/{src-BPKGdQdp.cjs.map → src-sG7Ihf0e.cjs.map} +1 -1
  36. package/dist/teleport.cjs +1 -1
  37. package/dist/teleport.js +1 -1
  38. package/package.json +1 -1
  39. package/src/code-highlight/code-highlight.ts +56 -24
  40. package/src/qr-scanner/qr-scanner.ts +27 -2
  41. package/types/src/code-highlight/code-highlight.d.ts +8 -1
  42. package/dist/code-highlight-BgExKEto.js.map +0 -1
  43. package/dist/code-highlight-zSYcSfCz.cjs.map +0 -1
  44. /package/dist/agent/{flow-CaPi2G8y.js → flow-CvG1fLW5.js} +0 -0
  45. /package/dist/agent/{vendor-material-color-Be96dpGE.js → vendor-material-color-DcL7ZPxx.js} +0 -0
@@ -5,8 +5,7 @@ import { distinctUntilChanged as a, filter as o, map as s, takeUntil as c, throt
5
5
  import { customElement as u, property as d, state as f } from "lit/decorators.js";
6
6
  import { css as p, html as m } from "lit";
7
7
  import { when as h } from "lit/directives/when.js";
8
- import g from "jsqr";
9
- var _ = class extends t(p`
8
+ var g = null, _ = null, v = class extends t(p`
10
9
  :host {
11
10
  display: block;
12
11
  width: 100%;
@@ -27,7 +26,10 @@ var _ = class extends t(p`
27
26
  width: { ideal: 1280 },
28
27
  height: { ideal: 720 }
29
28
  } };
30
- this.stream = await navigator.mediaDevices.getUserMedia(e), this.hasPermission = !0, this.error = "", await this.updateComplete, this.videoElement = this.shadowRoot?.querySelector("#video"), this.videoElement && (this.videoElement.srcObject = this.stream, await this.videoElement.play(), this.startScanning());
29
+ if (this.stream = await navigator.mediaDevices.getUserMedia(e), this.hasPermission = !0, this.error = "", await this.updateComplete, this.videoElement = this.shadowRoot?.querySelector("#video"), this.videoElement) {
30
+ if (this.videoElement.srcObject = this.stream, await this.videoElement.play(), await (_ ||= import("jsqr").then((e) => (g = e.default, e.default))), !this.isConnected) return;
31
+ this.startScanning();
32
+ }
31
33
  } catch {
32
34
  this.hasPermission = !1, this.error = "Camera access is required to scan QR codes. Please allow camera access and try again.";
33
35
  }
@@ -49,7 +51,9 @@ var _ = class extends t(p`
49
51
  let t = e.getContext("2d");
50
52
  if (!t) return null;
51
53
  t.drawImage(this.videoElement, 0, 0);
52
- let n = t.getImageData(0, 0, e.width, e.height), r = g(n.data, n.width, n.height);
54
+ let n = t.getImageData(0, 0, e.width, e.height);
55
+ if (!g) return null;
56
+ let r = g(n.data, n.width, n.height);
53
57
  if (r && r.data) return {
54
58
  data: r.data,
55
59
  timestamp: Date.now()
@@ -116,5 +120,5 @@ var _ = class extends t(p`
116
120
  `;
117
121
  }
118
122
  };
119
- e([d({ type: Boolean })], _.prototype, "continuous", void 0), e([f()], _.prototype, "hasPermission", void 0), e([f()], _.prototype, "error", void 0), e([f()], _.prototype, "showSuccess", void 0), _ = e([u("schmancy-qr-scanner")], _);
120
- export { _ as SchmancyQRScanner };
123
+ e([d({ type: Boolean })], v.prototype, "continuous", void 0), e([f()], v.prototype, "hasPermission", void 0), e([f()], v.prototype, "error", void 0), e([f()], v.prototype, "showSuccess", void 0), v = e([u("schmancy-qr-scanner")], v);
124
+ export { v as SchmancyQRScanner };
@@ -1 +1 @@
1
- {"version":3,"file":"qr-scanner.js","names":[],"sources":["../src/qr-scanner/qr-scanner.ts"],"sourcesContent":["import { $LitElement } from '@mixins/litElement.mixin'\nimport jsQR from 'jsqr'\nimport { css, html } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { when } from 'lit/directives/when.js'\nimport { animationFrames, Subject, timer } from 'rxjs'\nimport { distinctUntilChanged, filter, map, takeUntil, throttleTime } from 'rxjs/operators'\n\ninterface QRScanResult {\n\tdata: string\n\ttimestamp: number\n}\n\n@customElement('schmancy-qr-scanner')\nexport class SchmancyQRScanner extends $LitElement(css`\n\t:host {\n\t\tdisplay: block;\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tmin-height: 300px;\n\t}\n`) {\n\t@property({ type: Boolean }) continuous = true\n\n\t@state() private hasPermission = false\n\t@state() private error = ''\n\t@state() private showSuccess = false\n\n\tprivate stream: MediaStream | null = null\n\tprivate destroy$ = new Subject<void>()\n\tprivate videoElement: HTMLVideoElement | null = null\n\n\tconnectedCallback() {\n\t\tsuper.connectedCallback()\n\t\tthis.startCamera()\n\t}\n\n\tprivate async startCamera(): Promise<void> {\n\t\ttry {\n\t\t\tconst constraints: MediaStreamConstraints = {\n\t\t\t\tvideo: {\n\t\t\t\t\tfacingMode: 'environment',\n\t\t\t\t\twidth: { ideal: 1280 },\n\t\t\t\t\theight: { ideal: 720 },\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tthis.stream = await navigator.mediaDevices.getUserMedia(constraints)\n\t\t\tthis.hasPermission = true\n\t\t\tthis.error = ''\n\n\t\t\tawait this.updateComplete\n\n\t\t\tthis.videoElement = this.shadowRoot?.querySelector('#video') as HTMLVideoElement\n\t\t\tif (this.videoElement) {\n\t\t\t\tthis.videoElement.srcObject = this.stream\n\t\t\t\tawait this.videoElement.play()\n\t\t\t\tthis.startScanning()\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('Camera access denied:', error)\n\t\t\tthis.hasPermission = false\n\t\t\tthis.error = 'Camera access is required to scan QR codes. Please allow camera access and try again.'\n\t\t}\n\t}\n\n\tprivate stopCamera(): void {\n\t\tthis.destroy$.next()\n\n\t\tif (this.stream) {\n\t\t\tthis.stream.getTracks().forEach(track => track.stop())\n\t\t\tthis.stream = null\n\t\t}\n\n\t\tif (this.videoElement) {\n\t\t\tthis.videoElement.srcObject = null\n\t\t\tthis.videoElement = null\n\t\t}\n\n\t\tthis.hasPermission = false\n\t\tthis.error = ''\n\t\tthis.showSuccess = false\n\t}\n\n\tprivate startScanning(): void {\n\t\tif (!this.videoElement || !this.hasPermission) {\n\t\t\treturn\n\t\t}\n\n\t\tanimationFrames()\n\t\t\t.pipe(\n\t\t\t\tmap(() => this.scanFrame()),\n\t\t\t\tfilter((result): result is QRScanResult => result !== null),\n\t\t\t\tdistinctUntilChanged((prev, curr) => {\n\t\t\t\t\tif (prev.data !== curr.data) return false\n\t\t\t\t\treturn curr.timestamp - prev.timestamp < 2000\n\t\t\t\t}),\n\t\t\t\tthrottleTime(500),\n\t\t\t\ttakeUntil(this.destroy$),\n\t\t\t)\n\t\t\t.subscribe({\n\t\t\t\tnext: result => this.handleScanResult(result),\n\t\t\t\terror: error => {\n\t\t\t\t\tconsole.error('Scanning error:', error)\n\t\t\t\t},\n\t\t\t})\n\t}\n\n\tprivate scanFrame(): QRScanResult | null {\n\t\tif (!this.videoElement || this.videoElement.readyState !== HTMLMediaElement.HAVE_ENOUGH_DATA) {\n\t\t\treturn null\n\t\t}\n\n\t\ttry {\n\t\t\tconst canvas = document.createElement('canvas')\n\t\t\tcanvas.width = this.videoElement.videoWidth\n\t\t\tcanvas.height = this.videoElement.videoHeight\n\n\t\t\tconst ctx = canvas.getContext('2d')\n\t\t\tif (!ctx) return null\n\n\t\t\tctx.drawImage(this.videoElement, 0, 0)\n\t\t\tconst imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)\n\n\t\t\tconst code = jsQR(imageData.data, imageData.width, imageData.height)\n\n\t\t\tif (code && code.data) {\n\t\t\t\treturn {\n\t\t\t\t\tdata: code.data,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('Frame scan error:', error)\n\t\t}\n\n\t\treturn null\n\t}\n\n\tprivate handleScanResult(result: QRScanResult): void {\n\t\tthis.showSuccessFlash()\n\n\t\t// Haptic feedback if available\n\t\tif (navigator.vibrate) {\n\t\t\tnavigator.vibrate([100, 50, 100])\n\t\t}\n\n\t\t// Audio feedback\n\t\tthis.playSuccessSound()\n\n\t\t// Dispatch scan result\n\t\tthis.dispatchEvent(\n\t\t\tnew CustomEvent('scan-result', {\n\t\t\t\tdetail: { data: result.data, timestamp: result.timestamp },\n\t\t\t\tbubbles: true,\n\t\t\t\tcomposed: true,\n\t\t\t}),\n\t\t)\n\n\t}\n\n\tprivate showSuccessFlash(): void {\n\t\tthis.showSuccess = true\n\t\ttimer(500)\n\t\t\t.pipe(takeUntil(this.destroy$))\n\t\t\t.subscribe(() => {\n\t\t\t\tthis.showSuccess = false\n\t\t\t})\n\t}\n\n\tprivate playSuccessSound(): void {\n\t\ttry {\n\t\t\tconst AudioContextClass = window.AudioContext || (window as unknown as { webkitAudioContext: typeof AudioContext }).webkitAudioContext\n\t\t\tconst audioContext = new AudioContextClass()\n\t\t\tconst oscillator = audioContext.createOscillator()\n\t\t\tconst gainNode = audioContext.createGain()\n\n\t\t\toscillator.connect(gainNode)\n\t\t\tgainNode.connect(audioContext.destination)\n\n\t\t\toscillator.frequency.setValueAtTime(800, audioContext.currentTime)\n\t\t\toscillator.frequency.setValueAtTime(1000, audioContext.currentTime + 0.1)\n\n\t\t\tgainNode.gain.setValueAtTime(0.3, audioContext.currentTime)\n\t\t\tgainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.2)\n\n\t\t\toscillator.start(audioContext.currentTime)\n\t\t\toscillator.stop(audioContext.currentTime + 0.2)\n\t\t} catch {\n\t\t\t// Audio feedback failed silently\n\t\t}\n\t}\n\n\tdisconnectedCallback() {\n\t\tsuper.disconnectedCallback()\n\t\tthis.stopCamera()\n\t\tthis.destroy$.complete()\n\t}\n\n\trender() {\n\t\tif (this.error) {\n\t\t\treturn html`\n\t\t\t\t<div class=\"w-full h-full flex flex-col items-center justify-center bg-black text-white text-center p-5\">\n\t\t\t\t\t<schmancy-icon size=\"64\" class=\"mb-4\">camera_alt</schmancy-icon>\n\t\t\t\t\t<schmancy-typography type=\"headline\" token=\"md\" class=\"mb-4\">Camera Permission Required</schmancy-typography>\n\t\t\t\t\t<schmancy-typography type=\"body\" token=\"md\" class=\"mb-6 max-w-sm\">${this.error}</schmancy-typography>\n\t\t\t\t\t<schmancy-button variant=\"filled\" @click=${() => window.location.reload()}>Retry</schmancy-button>\n\t\t\t\t</div>\n\t\t\t`\n\t\t}\n\n\t\treturn html`\n\t\t\t<div class=\"relative w-full h-full bg-black overflow-hidden rounded-xl\">\n\t\t\t\t<!-- Video Stream -->\n\t\t\t\t<video id=\"video\" class=\"absolute inset-0 w-full h-full object-cover\" autoplay muted playsinline></video>\n\n\t\t\t\t<!-- Success Flash -->\n\t\t\t\t${when(this.showSuccess, () => html`<div class=\"absolute inset-0 bg-green-400/30 pointer-events-none\"></div>`)}\n\n\t\t\t\t<!-- Minimal corner brackets - Apple style -->\n\t\t\t\t<div class=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[250px] h-[250px] pointer-events-none animate-pulse\">\n\t\t\t\t\t<!-- Top-left corner -->\n\t\t\t\t\t<div class=\"absolute top-0 left-0 w-12 h-12 border-t-4 border-l-4 border-white rounded-tl-2xl\"></div>\n\t\t\t\t\t<!-- Top-right corner -->\n\t\t\t\t\t<div class=\"absolute top-0 right-0 w-12 h-12 border-t-4 border-r-4 border-white rounded-tr-2xl\"></div>\n\t\t\t\t\t<!-- Bottom-left corner -->\n\t\t\t\t\t<div class=\"absolute bottom-0 left-0 w-12 h-12 border-b-4 border-l-4 border-white rounded-bl-2xl\"></div>\n\t\t\t\t\t<!-- Bottom-right corner -->\n\t\t\t\t\t<div class=\"absolute bottom-0 right-0 w-12 h-12 border-b-4 border-r-4 border-white rounded-br-2xl\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-qr-scanner': SchmancyQRScanner\n\t}\n}\n"],"mappings":";;;;;;;;AAcO,IAAA,IAAA,cAAgC,EAAY,CAAG;;;;;;;;;kCAQX,GAAA,KAAA,gBAAA,CAET,GAAA,KAAA,QACR,IAAA,KAAA,cAAA,CACM,GAAA,KAAA,SAEM,MAAA,KAAA,WAClB,IAAI,GAAA,EAAA,KAAA,eACyB;;CAEhD,oBAAA;AACC,QAAM,mBAAA,EACN,KAAK,aAAA;;CAGN,MAAA,cAAc;AACb,MAAA;GACC,IAAM,IAAsC,EAC3C,OAAO;IACN,YAAY;IACZ,OAAO,EAAE,OAAO,MAAA;IAChB,QAAQ,EAAE,OAAO,KAAA;IAAA,EAAA;AAInB,QAAK,SAAA,MAAe,UAAU,aAAa,aAAa,EAAA,EACxD,KAAK,gBAAA,CAAgB,GACrB,KAAK,QAAQ,IAAA,MAEP,KAAK,gBAEX,KAAK,eAAe,KAAK,YAAY,cAAc,SAAA,EAC/C,KAAK,iBACR,KAAK,aAAa,YAAY,KAAK,QAAA,MAC7B,KAAK,aAAa,MAAA,EACxB,KAAK,eAAA;UAEE;AAER,QAAK,gBAAA,CAAgB,GACrB,KAAK,QAAQ;;;CAIf,aAAA;AACC,OAAK,SAAS,MAAA,EAEV,AAEH,KAAK,YADL,KAAK,OAAO,WAAA,CAAY,SAAQ,MAAS,EAAM,MAAA,CAAA,EACjC,OAGX,AAEH,KAAK,kBADL,KAAK,aAAa,YAAY,MACV,OAGrB,KAAK,gBAAA,CAAgB,GACrB,KAAK,QAAQ,IACb,KAAK,cAAA,CAAc;;CAGpB,gBAAA;AACM,OAAK,gBAAiB,KAAK,iBAIhC,GAAA,CACE,KACA,QAAU,KAAK,WAAA,CAAA,EACf,GAAQ,MAAmC,MAAW,KAAX,EAC3C,GAAsB,GAAM,MACvB,EAAK,SAAS,EAAK,QAChB,EAAK,YAAY,EAAK,YAAY,IAAA,EAE1C,EAAa,IAAA,EACb,EAAU,KAAK,SAAA,CAAA,CAEf,UAAU;GACV,OAAM,MAAU,KAAK,iBAAiB,EAAA;GACtC,QAAO,MAAA;GAAA,CAAA;;CAMV,YAAA;AACC,MAAA,CAAK,KAAK,gBAAgB,KAAK,aAAa,eAAe,iBAAiB,iBAC3E,QAAO;AAGR,MAAA;GACC,IAAM,IAAS,SAAS,cAAc,SAAA;AACtC,KAAO,QAAQ,KAAK,aAAa,YACjC,EAAO,SAAS,KAAK,aAAa;GAElC,IAAM,IAAM,EAAO,WAAW,KAAA;AAC9B,OAAA,CAAK,EAAK,QAAO;AAEjB,KAAI,UAAU,KAAK,cAAc,GAAG,EAAA;GACpC,IAAM,IAAY,EAAI,aAAa,GAAG,GAAG,EAAO,OAAO,EAAO,OAAA,EAExD,IAAO,EAAK,EAAU,MAAM,EAAU,OAAO,EAAU,OAAA;AAE7D,OAAI,KAAQ,EAAK,KAChB,QAAO;IACN,MAAM,EAAK;IACX,WAAW,KAAK,KAAA;IAAA;UAGV;AAIT,SAAO;;CAGR,iBAAyB,GAAA;AACxB,OAAK,kBAAA,EAGD,UAAU,WACb,UAAU,QAAQ;GAAC;GAAK;GAAI;GAAA,CAAA,EAI7B,KAAK,kBAAA,EAGL,KAAK,cACJ,IAAI,YAAY,eAAe;GAC9B,QAAQ;IAAE,MAAM,EAAO;IAAM,WAAW,EAAO;IAAA;GAC/C,SAAA,CAAS;GACT,UAAA,CAAU;GAAA,CAAA,CAAA;;CAMb,mBAAA;AACC,OAAK,cAAA,CAAc,GACnB,EAAM,IAAA,CACJ,KAAK,EAAU,KAAK,SAAA,CAAA,CACpB,gBAAA;AACA,QAAK,cAAA,CAAc;IAAA;;CAItB,mBAAA;AACC,MAAA;GAEC,IAAM,IAAe,KADK,OAAO,gBAAiB,OAAkE,qBAAA,EAE9G,IAAa,EAAa,kBAAA,EAC1B,IAAW,EAAa,YAAA;AAE9B,KAAW,QAAQ,EAAA,EACnB,EAAS,QAAQ,EAAa,YAAA,EAE9B,EAAW,UAAU,eAAe,KAAK,EAAa,YAAA,EACtD,EAAW,UAAU,eAAe,KAAM,EAAa,cAAc,GAAA,EAErE,EAAS,KAAK,eAAe,IAAK,EAAa,YAAA,EAC/C,EAAS,KAAK,6BAA6B,KAAM,EAAa,cAAc,GAAA,EAE5E,EAAW,MAAM,EAAa,YAAA,EAC9B,EAAW,KAAK,EAAa,cAAc,GAAA;UAAA;;CAM7C,uBAAA;AACC,QAAM,sBAAA,EACN,KAAK,YAAA,EACL,KAAK,SAAS,UAAA;;CAGf,SAAA;AACC,SAAI,KAAK,QACD,CAAI;;;;yEAI2D,KAAK,MAAA;sDACxB,OAAO,SAAS,QAAA,CAAA;;OAK7D,CAAI;;;;;;MAMP,EAAK,KAAK,mBAAmB,CAAI,2EAAA,CAAA;;;;;;;;;;;;;;;;;GAnMrC,EAAS,EAAE,MAAM,SAAA,CAAA,CAAA,EAAU,EAAA,WAAA,cAAA,KAAA,EAAA,EAAA,EAAA,CAE3B,GAAA,CAAA,EAAO,EAAA,WAAA,iBAAA,KAAA,EAAA,EAAA,EAAA,CACP,GAAA,CAAA,EAAO,EAAA,WAAA,SAAA,KAAA,EAAA,EAAA,EAAA,CACP,GAAA,CAAA,EAAO,EAAA,WAAA,eAAA,KAAA,EAAA,EAAA,IAAA,EAAA,CAbR,EAAc,sBAAA,CAAA,EAAsB,EAAA;AAAA,SAAA,KAAA"}
1
+ {"version":3,"file":"qr-scanner.js","names":[],"sources":["../src/qr-scanner/qr-scanner.ts"],"sourcesContent":["import { $LitElement } from '@mixins/litElement.mixin'\nimport { css, html } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { when } from 'lit/directives/when.js'\nimport { animationFrames, Subject, timer } from 'rxjs'\nimport { distinctUntilChanged, filter, map, takeUntil, throttleTime } from 'rxjs/operators'\n\n// jsQR (~53 KB gzipped) is loaded lazily the first time a camera stream\n// is attached — see ADR 0014. Until this resolves, scanFrame() returns\n// null and no decode happens, so the animationFrames loop spins harmlessly.\ntype JsQR = typeof import('jsqr').default\nlet jsQRFn: JsQR | null = null\nlet jsQRPromise: Promise<JsQR> | null = null\nfunction loadJsQR(): Promise<JsQR> {\n\tif (jsQRPromise) return jsQRPromise\n\tjsQRPromise = import('jsqr').then(m => {\n\t\tjsQRFn = m.default\n\t\treturn m.default\n\t})\n\treturn jsQRPromise\n}\n\ninterface QRScanResult {\n\tdata: string\n\ttimestamp: number\n}\n\n@customElement('schmancy-qr-scanner')\nexport class SchmancyQRScanner extends $LitElement(css`\n\t:host {\n\t\tdisplay: block;\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tmin-height: 300px;\n\t}\n`) {\n\t@property({ type: Boolean }) continuous = true\n\n\t@state() private hasPermission = false\n\t@state() private error = ''\n\t@state() private showSuccess = false\n\n\tprivate stream: MediaStream | null = null\n\tprivate destroy$ = new Subject<void>()\n\tprivate videoElement: HTMLVideoElement | null = null\n\n\tconnectedCallback() {\n\t\tsuper.connectedCallback()\n\t\tthis.startCamera()\n\t}\n\n\tprivate async startCamera(): Promise<void> {\n\t\ttry {\n\t\t\tconst constraints: MediaStreamConstraints = {\n\t\t\t\tvideo: {\n\t\t\t\t\tfacingMode: 'environment',\n\t\t\t\t\twidth: { ideal: 1280 },\n\t\t\t\t\theight: { ideal: 720 },\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tthis.stream = await navigator.mediaDevices.getUserMedia(constraints)\n\t\t\tthis.hasPermission = true\n\t\t\tthis.error = ''\n\n\t\t\tawait this.updateComplete\n\n\t\t\tthis.videoElement = this.shadowRoot?.querySelector('#video') as HTMLVideoElement\n\t\t\tif (this.videoElement) {\n\t\t\t\tthis.videoElement.srcObject = this.stream\n\t\t\t\tawait this.videoElement.play()\n\t\t\t\t// Preload jsQR before starting the animationFrames loop so the\n\t\t\t\t// first few frames have the decoder available. If the fetch\n\t\t\t\t// hasn't finished by the time a frame fires, scanFrame() just\n\t\t\t\t// returns null for that tick — no decode, no error.\n\t\t\t\tawait loadJsQR()\n\t\t\t\tif (!this.isConnected) return\n\t\t\t\tthis.startScanning()\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('Camera access denied:', error)\n\t\t\tthis.hasPermission = false\n\t\t\tthis.error = 'Camera access is required to scan QR codes. Please allow camera access and try again.'\n\t\t}\n\t}\n\n\tprivate stopCamera(): void {\n\t\tthis.destroy$.next()\n\n\t\tif (this.stream) {\n\t\t\tthis.stream.getTracks().forEach(track => track.stop())\n\t\t\tthis.stream = null\n\t\t}\n\n\t\tif (this.videoElement) {\n\t\t\tthis.videoElement.srcObject = null\n\t\t\tthis.videoElement = null\n\t\t}\n\n\t\tthis.hasPermission = false\n\t\tthis.error = ''\n\t\tthis.showSuccess = false\n\t}\n\n\tprivate startScanning(): void {\n\t\tif (!this.videoElement || !this.hasPermission) {\n\t\t\treturn\n\t\t}\n\n\t\tanimationFrames()\n\t\t\t.pipe(\n\t\t\t\tmap(() => this.scanFrame()),\n\t\t\t\tfilter((result): result is QRScanResult => result !== null),\n\t\t\t\tdistinctUntilChanged((prev, curr) => {\n\t\t\t\t\tif (prev.data !== curr.data) return false\n\t\t\t\t\treturn curr.timestamp - prev.timestamp < 2000\n\t\t\t\t}),\n\t\t\t\tthrottleTime(500),\n\t\t\t\ttakeUntil(this.destroy$),\n\t\t\t)\n\t\t\t.subscribe({\n\t\t\t\tnext: result => this.handleScanResult(result),\n\t\t\t\terror: error => {\n\t\t\t\t\tconsole.error('Scanning error:', error)\n\t\t\t\t},\n\t\t\t})\n\t}\n\n\tprivate scanFrame(): QRScanResult | null {\n\t\tif (!this.videoElement || this.videoElement.readyState !== HTMLMediaElement.HAVE_ENOUGH_DATA) {\n\t\t\treturn null\n\t\t}\n\n\t\ttry {\n\t\t\tconst canvas = document.createElement('canvas')\n\t\t\tcanvas.width = this.videoElement.videoWidth\n\t\t\tcanvas.height = this.videoElement.videoHeight\n\n\t\t\tconst ctx = canvas.getContext('2d')\n\t\t\tif (!ctx) return null\n\n\t\t\tctx.drawImage(this.videoElement, 0, 0)\n\t\t\tconst imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)\n\n\t\t\t// Skip this frame if jsQR hasn't resolved yet — startCamera awaits\n\t\t\t// loadJsQR() before this path runs, so in practice jsQRFn is\n\t\t\t// always set here. Keeping the guard for safety during racy\n\t\t\t// disconnects.\n\t\t\tif (!jsQRFn) return null\n\t\t\tconst code = jsQRFn(imageData.data, imageData.width, imageData.height)\n\n\t\t\tif (code && code.data) {\n\t\t\t\treturn {\n\t\t\t\t\tdata: code.data,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconsole.error('Frame scan error:', error)\n\t\t}\n\n\t\treturn null\n\t}\n\n\tprivate handleScanResult(result: QRScanResult): void {\n\t\tthis.showSuccessFlash()\n\n\t\t// Haptic feedback if available\n\t\tif (navigator.vibrate) {\n\t\t\tnavigator.vibrate([100, 50, 100])\n\t\t}\n\n\t\t// Audio feedback\n\t\tthis.playSuccessSound()\n\n\t\t// Dispatch scan result\n\t\tthis.dispatchEvent(\n\t\t\tnew CustomEvent('scan-result', {\n\t\t\t\tdetail: { data: result.data, timestamp: result.timestamp },\n\t\t\t\tbubbles: true,\n\t\t\t\tcomposed: true,\n\t\t\t}),\n\t\t)\n\n\t}\n\n\tprivate showSuccessFlash(): void {\n\t\tthis.showSuccess = true\n\t\ttimer(500)\n\t\t\t.pipe(takeUntil(this.destroy$))\n\t\t\t.subscribe(() => {\n\t\t\t\tthis.showSuccess = false\n\t\t\t})\n\t}\n\n\tprivate playSuccessSound(): void {\n\t\ttry {\n\t\t\tconst AudioContextClass = window.AudioContext || (window as unknown as { webkitAudioContext: typeof AudioContext }).webkitAudioContext\n\t\t\tconst audioContext = new AudioContextClass()\n\t\t\tconst oscillator = audioContext.createOscillator()\n\t\t\tconst gainNode = audioContext.createGain()\n\n\t\t\toscillator.connect(gainNode)\n\t\t\tgainNode.connect(audioContext.destination)\n\n\t\t\toscillator.frequency.setValueAtTime(800, audioContext.currentTime)\n\t\t\toscillator.frequency.setValueAtTime(1000, audioContext.currentTime + 0.1)\n\n\t\t\tgainNode.gain.setValueAtTime(0.3, audioContext.currentTime)\n\t\t\tgainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.2)\n\n\t\t\toscillator.start(audioContext.currentTime)\n\t\t\toscillator.stop(audioContext.currentTime + 0.2)\n\t\t} catch {\n\t\t\t// Audio feedback failed silently\n\t\t}\n\t}\n\n\tdisconnectedCallback() {\n\t\tsuper.disconnectedCallback()\n\t\tthis.stopCamera()\n\t\tthis.destroy$.complete()\n\t}\n\n\trender() {\n\t\tif (this.error) {\n\t\t\treturn html`\n\t\t\t\t<div class=\"w-full h-full flex flex-col items-center justify-center bg-black text-white text-center p-5\">\n\t\t\t\t\t<schmancy-icon size=\"64\" class=\"mb-4\">camera_alt</schmancy-icon>\n\t\t\t\t\t<schmancy-typography type=\"headline\" token=\"md\" class=\"mb-4\">Camera Permission Required</schmancy-typography>\n\t\t\t\t\t<schmancy-typography type=\"body\" token=\"md\" class=\"mb-6 max-w-sm\">${this.error}</schmancy-typography>\n\t\t\t\t\t<schmancy-button variant=\"filled\" @click=${() => window.location.reload()}>Retry</schmancy-button>\n\t\t\t\t</div>\n\t\t\t`\n\t\t}\n\n\t\treturn html`\n\t\t\t<div class=\"relative w-full h-full bg-black overflow-hidden rounded-xl\">\n\t\t\t\t<!-- Video Stream -->\n\t\t\t\t<video id=\"video\" class=\"absolute inset-0 w-full h-full object-cover\" autoplay muted playsinline></video>\n\n\t\t\t\t<!-- Success Flash -->\n\t\t\t\t${when(this.showSuccess, () => html`<div class=\"absolute inset-0 bg-green-400/30 pointer-events-none\"></div>`)}\n\n\t\t\t\t<!-- Minimal corner brackets - Apple style -->\n\t\t\t\t<div class=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[250px] h-[250px] pointer-events-none animate-pulse\">\n\t\t\t\t\t<!-- Top-left corner -->\n\t\t\t\t\t<div class=\"absolute top-0 left-0 w-12 h-12 border-t-4 border-l-4 border-white rounded-tl-2xl\"></div>\n\t\t\t\t\t<!-- Top-right corner -->\n\t\t\t\t\t<div class=\"absolute top-0 right-0 w-12 h-12 border-t-4 border-r-4 border-white rounded-tr-2xl\"></div>\n\t\t\t\t\t<!-- Bottom-left corner -->\n\t\t\t\t\t<div class=\"absolute bottom-0 left-0 w-12 h-12 border-b-4 border-l-4 border-white rounded-bl-2xl\"></div>\n\t\t\t\t\t<!-- Bottom-right corner -->\n\t\t\t\t\t<div class=\"absolute bottom-0 right-0 w-12 h-12 border-b-4 border-r-4 border-white rounded-br-2xl\"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-qr-scanner': SchmancyQRScanner\n\t}\n}\n"],"mappings":"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"}
@@ -16,7 +16,7 @@ import "./card-CEdgK9nb.js";
16
16
  import "./charts.js";
17
17
  import "./checkbox-Br84TiCs.js";
18
18
  import "./chips-BNYOweGm.js";
19
- import "./code-highlight-BgExKEto.js";
19
+ import "./code-highlight-CI_gqXYX.js";
20
20
  import "./components-DjKNS9R_.js";
21
21
  import "./connectivity.js";
22
22
  import "./date-range-sGkC0KF3.js";