@launchsecure/launch-kit 0.0.28 → 0.0.30

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 (195) hide show
  1. package/dist/beacon/beacon.mjs +2759 -1246
  2. package/dist/beacon/beacon.mjs.map +1 -1
  3. package/dist/beacon/beacon.umd.js +710 -95
  4. package/dist/beacon/beacon.umd.js.map +1 -1
  5. package/dist/beacon/types/core.d.ts +14 -0
  6. package/dist/beacon/types/core.d.ts.map +1 -0
  7. package/dist/beacon/types/ctx.d.ts +14 -0
  8. package/dist/beacon/types/ctx.d.ts.map +1 -0
  9. package/dist/beacon/types/element.d.ts +16 -48
  10. package/dist/beacon/types/element.d.ts.map +1 -1
  11. package/dist/beacon/types/index.d.ts +5 -4
  12. package/dist/beacon/types/index.d.ts.map +1 -1
  13. package/dist/beacon/types/internal/annotation-cache.d.ts +10 -0
  14. package/dist/beacon/types/internal/annotation-cache.d.ts.map +1 -0
  15. package/dist/beacon/types/internal/element-capture.d.ts +19 -0
  16. package/dist/beacon/types/internal/element-capture.d.ts.map +1 -0
  17. package/dist/beacon/types/internal/event-buffer.d.ts +16 -0
  18. package/dist/beacon/types/internal/event-buffer.d.ts.map +1 -0
  19. package/dist/beacon/types/internal/framework-detect.d.ts +6 -0
  20. package/dist/beacon/types/internal/framework-detect.d.ts.map +1 -0
  21. package/dist/beacon/types/internal/markers.d.ts +17 -0
  22. package/dist/beacon/types/internal/markers.d.ts.map +1 -0
  23. package/dist/beacon/types/internal/monitor/capture-dom.d.ts +14 -0
  24. package/dist/beacon/types/internal/monitor/capture-dom.d.ts.map +1 -0
  25. package/dist/beacon/types/internal/monitor/capture-network.d.ts +12 -0
  26. package/dist/beacon/types/internal/monitor/capture-network.d.ts.map +1 -0
  27. package/dist/beacon/types/internal/monitor/overlay.d.ts +16 -0
  28. package/dist/beacon/types/internal/monitor/overlay.d.ts.map +1 -0
  29. package/dist/beacon/types/internal/monitor/session.d.ts +41 -0
  30. package/dist/beacon/types/internal/monitor/session.d.ts.map +1 -0
  31. package/dist/beacon/types/{monitor → internal/monitor}/transport.d.ts +3 -3
  32. package/dist/beacon/types/internal/monitor/transport.d.ts.map +1 -0
  33. package/dist/beacon/types/{monitor/types.d.ts → internal/monitor/wire.d.ts} +69 -27
  34. package/dist/beacon/types/internal/monitor/wire.d.ts.map +1 -0
  35. package/dist/beacon/types/{ui → internal}/pick-mode-overlay.d.ts +4 -5
  36. package/dist/beacon/types/internal/pick-mode-overlay.d.ts.map +1 -0
  37. package/dist/beacon/types/{capture → internal}/picker.d.ts +0 -1
  38. package/dist/beacon/types/internal/picker.d.ts.map +1 -0
  39. package/dist/beacon/types/{ui → internal}/pin-popover.d.ts +1 -1
  40. package/dist/beacon/types/internal/pin-popover.d.ts.map +1 -0
  41. package/dist/beacon/types/{capture → internal}/screenshot.d.ts +1 -0
  42. package/dist/beacon/types/internal/screenshot.d.ts.map +1 -0
  43. package/dist/beacon/types/internal/selector.d.ts.map +1 -0
  44. package/dist/beacon/types/plugins/domEle.d.ts +14 -0
  45. package/dist/beacon/types/plugins/domEle.d.ts.map +1 -0
  46. package/dist/beacon/types/plugins/domSS.d.ts +8 -0
  47. package/dist/beacon/types/plugins/domSS.d.ts.map +1 -0
  48. package/dist/beacon/types/plugins/errors.d.ts +3 -0
  49. package/dist/beacon/types/plugins/errors.d.ts.map +1 -0
  50. package/dist/beacon/types/plugins/index.d.ts +8 -0
  51. package/dist/beacon/types/plugins/index.d.ts.map +1 -0
  52. package/dist/beacon/types/plugins/liveMonitor.d.ts +14 -0
  53. package/dist/beacon/types/plugins/liveMonitor.d.ts.map +1 -0
  54. package/dist/beacon/types/plugins/metadata.d.ts +3 -0
  55. package/dist/beacon/types/plugins/metadata.d.ts.map +1 -0
  56. package/dist/beacon/types/registry.d.ts +33 -0
  57. package/dist/beacon/types/registry.d.ts.map +1 -0
  58. package/dist/beacon/types/styles.d.ts +8 -0
  59. package/dist/beacon/types/styles.d.ts.map +1 -0
  60. package/dist/beacon/types/transport.d.ts +3 -0
  61. package/dist/beacon/types/transport.d.ts.map +1 -0
  62. package/dist/beacon/types/types.d.ts +152 -68
  63. package/dist/beacon/types/types.d.ts.map +1 -1
  64. package/dist/beacon/types/ui/dialog.d.ts +53 -0
  65. package/dist/beacon/types/ui/dialog.d.ts.map +1 -0
  66. package/dist/beacon/types/ui/form.d.ts +7 -0
  67. package/dist/beacon/types/ui/form.d.ts.map +1 -0
  68. package/dist/beacon/types/ui/overlay.d.ts +6 -0
  69. package/dist/beacon/types/ui/overlay.d.ts.map +1 -0
  70. package/dist/deck-client/assets/{_baseUniq-W2JQDmje.js → _baseUniq-DCt2IMRR.js} +1 -1
  71. package/dist/deck-client/assets/{arc-DIBWAId9.js → arc-h-ifqmNR.js} +1 -1
  72. package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-CAIRMvJK.js → architectureDiagram-Q4EWVU46-C9dITSPv.js} +1 -1
  73. package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-BeNaNiOi.js → blockDiagram-DXYQGD6D-BHuJT34t.js} +1 -1
  74. package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-B9Ozi62h.js → c4Diagram-AHTNJAMY-CpvMGtDG.js} +1 -1
  75. package/dist/deck-client/assets/channel-2PZVMiXf.js +1 -0
  76. package/dist/deck-client/assets/{chunk-4BX2VUAB-D7AZ47dt.js → chunk-4BX2VUAB-B6md1VIm.js} +1 -1
  77. package/dist/deck-client/assets/{chunk-4TB4RGXK-DnVnNPcI.js → chunk-4TB4RGXK-BmEnX8ik.js} +1 -1
  78. package/dist/deck-client/assets/{chunk-55IACEB6-UKYs-YNd.js → chunk-55IACEB6-BZPUyZAZ.js} +1 -1
  79. package/dist/deck-client/assets/{chunk-EDXVE4YY-D43b-SKn.js → chunk-EDXVE4YY-BWwNUK-l.js} +1 -1
  80. package/dist/deck-client/assets/{chunk-FMBD7UC4-QzBAoyyW.js → chunk-FMBD7UC4-o7gSppGI.js} +1 -1
  81. package/dist/deck-client/assets/{chunk-OYMX7WX6-Cjif4r6W.js → chunk-OYMX7WX6-C4KoTL5p.js} +1 -1
  82. package/dist/deck-client/assets/{chunk-QZHKN3VN-CqLDirEI.js → chunk-QZHKN3VN-jkf68sDs.js} +1 -1
  83. package/dist/deck-client/assets/{chunk-YZCP3GAM-_FQvmMs4.js → chunk-YZCP3GAM-Cd4yBE7o.js} +1 -1
  84. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-Bt8xBAof.js +1 -0
  85. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-Bt8xBAof.js +1 -0
  86. package/dist/deck-client/assets/clone-BHQryoDl.js +1 -0
  87. package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-rfrocesE.js → cose-bilkent-S5V4N54A-DeGFUgAV.js} +1 -1
  88. package/dist/deck-client/assets/{dagre-KV5264BT-Bv_7DJat.js → dagre-KV5264BT-ekcYJuUV.js} +1 -1
  89. package/dist/deck-client/assets/{diagram-5BDNPKRD-4F1414G5.js → diagram-5BDNPKRD-YHPk4rV2.js} +1 -1
  90. package/dist/deck-client/assets/{diagram-G4DWMVQ6-C4-Pszqm.js → diagram-G4DWMVQ6-DM-JCd_B.js} +1 -1
  91. package/dist/deck-client/assets/{diagram-MMDJMWI5-B647TIx9.js → diagram-MMDJMWI5-l5FK1ybk.js} +1 -1
  92. package/dist/deck-client/assets/{diagram-TYMM5635-BFAqpezd.js → diagram-TYMM5635-CIN4_1-j.js} +1 -1
  93. package/dist/deck-client/assets/{erDiagram-SMLLAGMA-BfBfrJOC.js → erDiagram-SMLLAGMA-MyinSkEl.js} +1 -1
  94. package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-DX9YAYes.js → flowDiagram-DWJPFMVM-Dk8nn42x.js} +1 -1
  95. package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-DCuiy7wF.js → ganttDiagram-T4ZO3ILL-BU1ihicu.js} +1 -1
  96. package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-CGp1IXUh.js → gitGraphDiagram-UUTBAWPF-BjsTL13C.js} +1 -1
  97. package/dist/deck-client/assets/{graph-B7g8aoxv.js → graph-DJmh-xi7.js} +1 -1
  98. package/dist/deck-client/assets/{index-Dg1r-WSN.js → index-KsShfCV-.js} +3 -3
  99. package/dist/deck-client/assets/{infoDiagram-42DDH7IO-L3fahMkF.js → infoDiagram-42DDH7IO-Dxvy_RB4.js} +1 -1
  100. package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-aS_EjWBZ.js → ishikawaDiagram-UXIWVN3A-DPOaNF1l.js} +1 -1
  101. package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-djTSQZF9.js → journeyDiagram-VCZTEJTY-DMew3K5c.js} +1 -1
  102. package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-CcTHo4CM.js → kanban-definition-6JOO6SKY-csciJFuk.js} +1 -1
  103. package/dist/deck-client/assets/{layout-mEJiadb7.js → layout-Dg4yyms2.js} +1 -1
  104. package/dist/deck-client/assets/{linear-XgTKqyRu.js → linear-BA3zU6gq.js} +1 -1
  105. package/dist/deck-client/assets/{min-Ct9jZdpd.js → min-lz-Ird-p.js} +1 -1
  106. package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-BaFxCGNU.js → mindmap-definition-QFDTVHPH-CCEN8OQV.js} +1 -1
  107. package/dist/deck-client/assets/{pieDiagram-DEJITSTG-CIbYYjtw.js → pieDiagram-DEJITSTG-DM6n1HY7.js} +1 -1
  108. package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-D9EtCOvh.js → quadrantDiagram-34T5L4WZ-_ULoR66n.js} +1 -1
  109. package/dist/deck-client/assets/{requirementDiagram-MS252O5E-xeni9eVG.js → requirementDiagram-MS252O5E-BuwJs7Tn.js} +1 -1
  110. package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-LYeknz9h.js → sankeyDiagram-XADWPNL6-BEsuzkW4.js} +1 -1
  111. package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-RDbsKFZf.js → sequenceDiagram-FGHM5R23-CP2H0YWf.js} +1 -1
  112. package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-BH1Zjglk.js → stateDiagram-FHFEXIEX-B5Gw_NNL.js} +1 -1
  113. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-4T4wMDXr.js +1 -0
  114. package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-IFXxKptt.js → timeline-definition-GMOUNBTQ-DsoYydQa.js} +1 -1
  115. package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-D-sLkQs9.js → vennDiagram-DHZGUBPP-Dz8JT_ob.js} +1 -1
  116. package/dist/deck-client/assets/wardley-RL74JXVD-DGHQ_Ijv.js +162 -0
  117. package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-BTjjuDU3.js → wardleyDiagram-NUSXRM2D-DN1LJMB1.js} +1 -1
  118. package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-AYbv92n-.js → xychartDiagram-5P7HB3ND-nb0oSfrQ.js} +1 -1
  119. package/dist/deck-client/index.html +1 -1
  120. package/dist/server/beacon-monitor-entry.js +548 -6
  121. package/dist/server/chart-serve.js +920 -249
  122. package/dist/server/cli.js +1599 -595
  123. package/dist/server/course-entry.js +3 -3
  124. package/dist/server/graph-mcp-entry.js +1361 -394
  125. package/dist/server/init-entry.js +799 -195
  126. package/dist/server/orbit-entry.js +135 -7
  127. package/dist/server/parse-worker-entry.js +918 -247
  128. package/package.json +3 -2
  129. package/scaffolds/ls-marketplace/.claude-plugin/marketplace.json +4 -4
  130. package/scaffolds/ls-marketplace/plugins/{ls → kit}/.claude-plugin/plugin.json +1 -10
  131. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/activate-beacon.md +2 -2
  132. package/scaffolds/ls-marketplace/plugins/kit/commands/activate-statusline.md +46 -0
  133. package/scaffolds/ls-marketplace/plugins/kit/commands/deactivate-statusline.md +34 -0
  134. package/scaffolds/ls-marketplace/plugins/{ls → kit}/commands/standup.md +52 -38
  135. package/scaffolds/ls-marketplace/plugins/kit/skills/beacon-array.md +107 -0
  136. package/scaffolds/ls-marketplace/plugins/kit/skills/beacon-clear.md +94 -0
  137. package/scaffolds/ls-marketplace/plugins/kit/skills/beacon-pulse.md +82 -0
  138. package/scaffolds/ls-marketplace/plugins/kit/skills/beacon-scan.md +66 -0
  139. package/scaffolds/ls-marketplace/plugins/kit/skills/blast-radius.md +101 -0
  140. package/scaffolds/ls-marketplace/plugins/kit/skills/brief.md +112 -0
  141. package/scaffolds/ls-marketplace/plugins/kit/skills/course.md +84 -0
  142. package/scaffolds/ls-marketplace/plugins/kit/skills/debug.md +92 -0
  143. package/scaffolds/ls-marketplace/plugins/kit/skills/deploy-check.md +160 -0
  144. package/scaffolds/ls-marketplace/plugins/kit/skills/diagram.md +134 -0
  145. package/scaffolds/ls-marketplace/plugins/kit/skills/orbit.md +87 -0
  146. package/scaffolds/ls-marketplace/plugins/kit/skills/prototype.md +90 -0
  147. package/scaffolds/ls-marketplace/plugins/kit/skills/recall.md +83 -0
  148. package/scaffolds/ls-marketplace/plugins/{ls/commands → kit/skills}/show-mcp-status.md +8 -8
  149. package/scaffolds/ls-marketplace/plugins/kit/skills/wireframe.md +70 -0
  150. package/scaffolds/statusline/statusline-mcp.sh +204 -0
  151. package/scaffolds/statusline/statusline-wrapper.sh +50 -0
  152. package/dist/beacon/types/capture/element.d.ts +0 -3
  153. package/dist/beacon/types/capture/element.d.ts.map +0 -1
  154. package/dist/beacon/types/capture/events.d.ts +0 -20
  155. package/dist/beacon/types/capture/events.d.ts.map +0 -1
  156. package/dist/beacon/types/capture/framework.d.ts +0 -3
  157. package/dist/beacon/types/capture/framework.d.ts.map +0 -1
  158. package/dist/beacon/types/capture/metadata.d.ts +0 -3
  159. package/dist/beacon/types/capture/metadata.d.ts.map +0 -1
  160. package/dist/beacon/types/capture/overlay.d.ts +0 -7
  161. package/dist/beacon/types/capture/overlay.d.ts.map +0 -1
  162. package/dist/beacon/types/capture/picker.d.ts.map +0 -1
  163. package/dist/beacon/types/capture/screenshot.d.ts.map +0 -1
  164. package/dist/beacon/types/capture/selector.d.ts.map +0 -1
  165. package/dist/beacon/types/monitor/dom.d.ts +0 -13
  166. package/dist/beacon/types/monitor/dom.d.ts.map +0 -1
  167. package/dist/beacon/types/monitor/index.d.ts +0 -19
  168. package/dist/beacon/types/monitor/index.d.ts.map +0 -1
  169. package/dist/beacon/types/monitor/network.d.ts +0 -12
  170. package/dist/beacon/types/monitor/network.d.ts.map +0 -1
  171. package/dist/beacon/types/monitor/transport.d.ts.map +0 -1
  172. package/dist/beacon/types/monitor/types.d.ts.map +0 -1
  173. package/dist/beacon/types/transport/submit.d.ts +0 -3
  174. package/dist/beacon/types/transport/submit.d.ts.map +0 -1
  175. package/dist/beacon/types/ui/button.d.ts +0 -2
  176. package/dist/beacon/types/ui/button.d.ts.map +0 -1
  177. package/dist/beacon/types/ui/drawer.d.ts +0 -33
  178. package/dist/beacon/types/ui/drawer.d.ts.map +0 -1
  179. package/dist/beacon/types/ui/icons.d.ts +0 -9
  180. package/dist/beacon/types/ui/icons.d.ts.map +0 -1
  181. package/dist/beacon/types/ui/monitor-panel.d.ts +0 -19
  182. package/dist/beacon/types/ui/monitor-panel.d.ts.map +0 -1
  183. package/dist/beacon/types/ui/pick-mode-overlay.d.ts.map +0 -1
  184. package/dist/beacon/types/ui/pin-popover.d.ts.map +0 -1
  185. package/dist/deck-client/assets/channel-CRdozqbp.js +0 -1
  186. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-lIZMp57W.js +0 -1
  187. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-lIZMp57W.js +0 -1
  188. package/dist/deck-client/assets/clone-BtWeSTyJ.js +0 -1
  189. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-BrV78NDR.js +0 -1
  190. package/dist/deck-client/assets/wardley-RL74JXVD-C010F8l4.js +0 -162
  191. package/scaffolds/ls-marketplace/plugins/ls/commands/beacon-array.md +0 -92
  192. package/scaffolds/ls-marketplace/plugins/ls/commands/beacon-clear.md +0 -68
  193. package/scaffolds/ls-marketplace/plugins/ls/commands/beacon-pulse.md +0 -80
  194. package/scaffolds/ls-marketplace/plugins/ls/commands/beacon-scan.md +0 -62
  195. /package/dist/beacon/types/{capture → internal}/selector.d.ts +0 -0
@@ -1,535 +1,1364 @@
1
- const V = '.beacon-drawer,.beacon-pin-popover{--beacon-accent: #0ea5e9;--beacon-bg: #ffffff;--beacon-fg: #0f172a;--beacon-muted: #64748b;--beacon-border: #e2e8f0;--beacon-radius: 10px;--beacon-shadow: 0 10px 30px rgba(0, 0, 0, .15), 0 2px 6px rgba(0, 0, 0, .08);--beacon-z-index: 2147483647;--beacon-bug: #ef4444;--beacon-idea: #22c55e;--beacon-ux: #a855f7;--beacon-a11y: #06b6d4}.beacon-drawer.beacon-theme-dark,.beacon-pin-popover.beacon-theme-dark{--beacon-bg: #0f172a;--beacon-fg: #f1f5f9;--beacon-muted: #94a3b8;--beacon-border: #334155}@media (prefers-color-scheme: dark){.beacon-drawer.beacon-theme-auto,.beacon-pin-popover.beacon-theme-auto{--beacon-bg: #0f172a;--beacon-fg: #f1f5f9;--beacon-muted: #94a3b8;--beacon-border: #334155}}:host{--beacon-accent: #0ea5e9;--beacon-bg: #ffffff;--beacon-fg: #0f172a;--beacon-muted: #64748b;--beacon-border: #e2e8f0;--beacon-radius: 10px;--beacon-z-index: 2147483645;--beacon-shadow: 0 10px 30px rgba(0, 0, 0, .15), 0 2px 6px rgba(0, 0, 0, .08);--beacon-bug: #ef4444;--beacon-idea: #22c55e;--beacon-ux: #a855f7;--beacon-a11y: #06b6d4;position:fixed;z-index:var(--beacon-z-index);font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:14px;color:var(--beacon-fg);line-height:1.5}:host([theme="dark"]){--beacon-bg: #0f172a;--beacon-fg: #f1f5f9;--beacon-muted: #94a3b8;--beacon-border: #334155}@media (prefers-color-scheme: dark){:host([theme="auto"]){--beacon-bg: #0f172a;--beacon-fg: #f1f5f9;--beacon-muted: #94a3b8;--beacon-border: #334155}}:host([position="bottom-right"]){right:20px;bottom:20px;left:auto;top:auto}:host([position="bottom-left"]){left:20px;bottom:20px;right:auto;top:auto}:host([position="hidden"]){position:static;display:contents}:host([position="hidden"]) .beacon-default-trigger{display:none}.beacon-default-trigger{display:inline-flex;align-items:center;gap:6px;background:var(--beacon-accent);color:#fff;border:0;border-radius:999px;padding:10px 16px;font:inherit;font-weight:500;cursor:pointer;box-shadow:var(--beacon-shadow);transition:transform .15s ease,box-shadow .15s ease}.beacon-default-trigger:hover{transform:translateY(-1px);box-shadow:0 14px 36px #0003}.beacon-default-trigger svg{width:18px;height:18px}.beacon-drawer{position:fixed;right:20px;bottom:20px;width:380px;max-width:calc(100vw - 24px);max-height:calc(100vh - 24px);background:var(--beacon-bg);color:var(--beacon-fg);border:1px solid var(--beacon-border);border-radius:var(--beacon-radius);box-shadow:var(--beacon-shadow);display:none;flex-direction:column;overflow:hidden;z-index:var(--beacon-z-index)}:host([position="bottom-left"]) .beacon-drawer{left:20px;right:auto}.beacon-drawer.open{display:flex}.beacon-drawer.minimized{display:none}.beacon-drawer-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--beacon-border)}.beacon-drawer-title{font-weight:600}.beacon-icon-btn{background:transparent;border:0;color:var(--beacon-muted);cursor:pointer;padding:4px;border-radius:4px;display:inline-flex}.beacon-icon-btn:hover{background:var(--beacon-border);color:var(--beacon-fg)}.beacon-icon-btn svg{width:16px;height:16px}.beacon-drawer-body{padding:16px;overflow-y:auto;display:flex;flex-direction:column;gap:14px}.beacon-field{display:flex;flex-direction:column;gap:6px}.beacon-label{font-size:12px;color:var(--beacon-muted);font-weight:500}.beacon-textarea{width:100%;min-height:80px;padding:8px 10px;background:var(--beacon-bg);color:var(--beacon-fg);border:1px solid var(--beacon-border);border-radius:6px;font:inherit;resize:vertical;box-sizing:border-box}.beacon-textarea:focus{outline:2px solid var(--beacon-accent);outline-offset:-1px;border-color:var(--beacon-accent)}.beacon-severity{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}.beacon-severity-opt{position:relative;display:flex;align-items:center;justify-content:center;padding:6px 4px;background:transparent;border:1px solid var(--beacon-border);border-radius:6px;cursor:pointer;font-size:12px;font-weight:500;color:var(--beacon-fg);text-transform:capitalize}.beacon-severity-opt input{position:absolute;opacity:0;pointer-events:none}.beacon-severity-opt:hover{background:var(--beacon-border)}.beacon-severity-opt.selected[data-sev=bug]{border-color:var(--beacon-bug);color:var(--beacon-bug)}.beacon-severity-opt.selected[data-sev=idea]{border-color:var(--beacon-idea);color:var(--beacon-idea)}.beacon-severity-opt.selected[data-sev=ux]{border-color:var(--beacon-ux);color:var(--beacon-ux)}.beacon-severity-opt.selected[data-sev=a11y]{border-color:var(--beacon-a11y);color:var(--beacon-a11y)}.beacon-actions{display:flex;gap:8px;align-items:center}.beacon-btn{display:inline-flex;align-items:center;gap:6px;padding:8px 14px;border-radius:6px;border:0;cursor:pointer;font:inherit;font-weight:500;font-size:13px;transition:opacity .15s ease}.beacon-btn[disabled]{opacity:.5;cursor:not-allowed}.beacon-btn svg{width:14px;height:14px}.beacon-btn.primary{background:var(--beacon-accent);color:#fff}.beacon-btn.secondary{background:transparent;color:var(--beacon-fg);border:1px solid var(--beacon-border)}.beacon-btn.secondary:hover{background:var(--beacon-border)}.beacon-pin-list{display:flex;flex-direction:column;gap:6px;max-height:200px;overflow-y:auto}.beacon-pin-item{display:flex;align-items:flex-start;gap:8px;padding:8px;background:var(--beacon-border);border-radius:6px}.beacon-pin-num{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;background:var(--beacon-accent);color:#fff;font-size:11px;font-weight:600;flex-shrink:0}.beacon-pin-meta{flex:1;min-width:0}.beacon-pin-selector{font:11px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--beacon-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.beacon-pin-note{margin-top:4px;font-size:12px;color:var(--beacon-fg)}.beacon-pin-note-input{margin-top:4px;width:100%;padding:4px 6px;background:var(--beacon-bg);color:var(--beacon-fg);border:1px solid var(--beacon-border);border-radius:4px;font:inherit;font-size:12px;box-sizing:border-box}.beacon-thumb{width:100%;border:1px solid var(--beacon-border);border-radius:6px;display:block}.beacon-status{font-size:12px;color:var(--beacon-muted);text-align:center;padding:4px}.beacon-status.error{color:var(--beacon-bug)}.beacon-status.success{color:var(--beacon-idea)}.beacon-events{font-size:12px;border:1px solid var(--beacon-border);border-radius:6px;padding:6px 8px}.beacon-events-summary{cursor:pointer;list-style:none;display:flex;align-items:center;gap:6px;color:var(--beacon-muted);-webkit-user-select:none;-moz-user-select:none;user-select:none}.beacon-events-summary::-webkit-details-marker{display:none}.beacon-events-dot{color:var(--beacon-bug);font-size:10px;line-height:1}.beacon-events-list{list-style:none;margin:8px 0 0;padding:0;display:flex;flex-direction:column;gap:4px;max-height:160px;overflow-y:auto}.beacon-events-item{display:flex;align-items:flex-start;gap:6px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;line-height:1.4}.beacon-events-kind{flex-shrink:0;padding:1px 5px;border-radius:3px;font-size:10px;text-transform:uppercase;letter-spacing:.04em}.beacon-events-kind.error{background:#eb141426;color:var(--beacon-bug)}.beacon-events-kind.rejection{background:#f59f0a26;color:#f59f0a}.beacon-events-msg{word-break:break-word;color:var(--beacon-fg)}.beacon-pin-popover{position:fixed;z-index:2147483647;width:240px;background:var(--beacon-bg);color:var(--beacon-fg);border:1px solid var(--beacon-border);border-radius:6px;box-shadow:var(--beacon-shadow);padding:10px;display:none;flex-direction:column;gap:8px}.beacon-pin-popover.open{display:flex}.beacon-pin-popover-header{display:flex;align-items:center;justify-content:space-between;gap:6px}.beacon-pin-popover-actions{display:flex;gap:6px;justify-content:flex-end}', k = {
2
- feedback: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>',
3
- pin: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 17v5"/><path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z"/></svg>',
4
- close: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>',
5
- trash: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>',
6
- send: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m22 2-7 20-4-9-9-4Z"/><path d="M22 2 11 13"/></svg>',
7
- check: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"/></svg>'
8
- };
9
- function ke(t = "Feedback") {
10
- const e = document.createElement("button");
11
- return e.type = "button", e.className = "beacon-default-trigger", e.setAttribute("aria-label", t), e.innerHTML = `${k.feedback}<span>${t}</span>`, e;
12
- }
13
- const Ae = ["bug", "idea", "ux", "a11y"];
14
- class Ce {
15
- constructor(e, n) {
16
- this.state = {
17
- description: "",
18
- severity: "bug",
19
- pins: [],
20
- events: [],
21
- annotatedScreenshot: void 0,
22
- submitting: !1,
23
- status: "",
24
- statusKind: ""
25
- }, this.severities = e.length > 0 ? e : Ae, this.callbacks = n, this.root = document.createElement("div"), this.root.className = "beacon-drawer", this.root.innerHTML = `
26
- <div class="beacon-drawer-header">
27
- <div class="beacon-drawer-title">Send feedback</div>
28
- <button type="button" class="beacon-icon-btn" data-action="close" aria-label="Close">${k.close}</button>
29
- </div>
30
- <div class="beacon-drawer-body"></div>
31
- `, this.bodyEl = this.root.querySelector(".beacon-drawer-body"), this.root.querySelector('[data-action="close"]').addEventListener("click", () => this.callbacks.onClose()), this.render();
32
- }
33
- open() {
34
- this.root.classList.remove("minimized"), this.root.classList.add("open");
35
- }
36
- close() {
37
- this.root.classList.remove("open");
38
- }
39
- minimize() {
40
- this.root.classList.add("minimized"), this.root.classList.remove("open");
41
- }
42
- setPins(e, n) {
43
- this.state.pins = e, n !== void 0 && (this.state.annotatedScreenshot = n), this.render();
44
- }
45
- // Push the latest events buffer into the drawer. element.ts calls this both
46
- // on open() (initial snapshot) AND from a subscriber so the chip ticks up
47
- // live as errors fire. We partial-update the chip element only — a full
48
- // re-render of bodyEl would blow away the textarea's focus + cursor while
49
- // the user is typing, which is much worse than the chip never animating.
50
- setEvents(e) {
51
- this.state.events = e, this.updateEventsChip();
52
- }
53
- updateEventsChip() {
54
- const e = this.bodyEl.querySelector(".beacon-events");
55
- if (!e) {
56
- this.render();
57
- return;
58
- }
59
- const n = this.state.events.length;
60
- if (n === 0) {
61
- e.hidden = !0;
62
- return;
63
- }
64
- e.hidden = !1, e.dataset.count = String(n);
65
- const o = e.querySelector(".beacon-events-label");
66
- o && (o.textContent = `${n} runtime ${n === 1 ? "error" : "errors"} will be included`);
67
- const s = e.querySelector(".beacon-events-list");
68
- s && (s.innerHTML = this.state.events.map((i) => `
69
- <li class="beacon-events-item">
70
- <span class="beacon-events-kind ${i.kind === "unhandledrejection" ? "rejection" : "error"}">${i.kind === "unhandledrejection" ? "rejection" : "error"}</span>
71
- <span class="beacon-events-msg">${S(i.message)}</span>
72
- </li>
73
- `).join(""));
74
- }
75
- getAnnotatedScreenshot() {
76
- return this.state.annotatedScreenshot;
77
- }
78
- setAnnotatedScreenshot(e) {
79
- this.state.annotatedScreenshot = e, this.render();
80
- }
81
- setSubmitting(e) {
82
- this.state.submitting = e, this.render();
83
- }
84
- setStatus(e, n = "") {
85
- this.state.status = e, this.state.statusKind = n, this.render();
86
- }
87
- reset() {
88
- this.state = {
89
- description: "",
90
- severity: "bug",
91
- pins: [],
92
- events: [],
93
- annotatedScreenshot: void 0,
94
- submitting: !1,
95
- status: "",
96
- statusKind: ""
97
- }, this.render();
98
- }
99
- getDescription() {
100
- return this.state.description;
1
+ const Te = String.raw`
2
+ :host {
3
+ --beacon-accent: #0ea5e9;
4
+ --beacon-bg: #ffffff;
5
+ --beacon-fg: #0f172a;
6
+ --beacon-muted: #64748b;
7
+ --beacon-border: #e2e8f0;
8
+ --beacon-radius: 10px;
9
+ --beacon-z-index: 2147483645;
10
+ --beacon-shadow: 0 10px 30px hsl(0 0% 0% / 0.15), 0 2px 6px hsl(0 0% 0% / 0.08);
11
+ --beacon-font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
12
+ --beacon-color-scheme: light dark;
13
+
14
+ --beacon-bug: #ef4444;
15
+ --beacon-idea: #22c55e;
16
+ --beacon-ux: #a855f7;
17
+ --beacon-a11y: #06b6d4;
18
+
19
+ position: fixed;
20
+ z-index: var(--beacon-z-index);
21
+ font-family: var(--beacon-font-family);
22
+ font-size: 14px;
23
+ color: var(--beacon-fg);
24
+ line-height: 1.5;
25
+ color-scheme: var(--beacon-color-scheme);
26
+ }
27
+
28
+ :host([theme='dark']) {
29
+ --beacon-bg: #0f172a;
30
+ --beacon-fg: #f1f5f9;
31
+ --beacon-muted: #94a3b8;
32
+ --beacon-border: #334155;
33
+ --beacon-color-scheme: dark;
34
+ }
35
+
36
+ @media (prefers-color-scheme: dark) {
37
+ :host([theme='auto']) {
38
+ --beacon-bg: #0f172a;
39
+ --beacon-fg: #f1f5f9;
40
+ --beacon-muted: #94a3b8;
41
+ --beacon-border: #334155;
101
42
  }
102
- getSeverity() {
103
- return this.state.severity;
104
- }
105
- render() {
106
- var o, s;
107
- const e = this.state.description.trim().length > 0 && !this.state.submitting;
108
- this.bodyEl.innerHTML = `
109
- <div class="beacon-field">
110
- <label class="beacon-label" for="beacon-desc">What's the issue?</label>
111
- <textarea id="beacon-desc" class="beacon-textarea" placeholder="Describe what you saw, what you expected, anything that helps reproduce…">${S(this.state.description)}</textarea>
112
- </div>
43
+ }
113
44
 
114
- <div class="beacon-field">
115
- <span class="beacon-label">Severity</span>
116
- <div class="beacon-severity" role="radiogroup">
117
- ${this.severities.map((i) => `
118
- <label class="beacon-severity-opt ${i === this.state.severity ? "selected" : ""}" data-sev="${i}">
119
- <input type="radio" name="beacon-severity" value="${i}" ${i === this.state.severity ? "checked" : ""}>
120
- ${i}
121
- </label>
122
- `).join("")}
123
- </div>
124
- </div>
45
+ :host([position='bottom-right']) { right: 20px; bottom: 20px; left: auto; top: auto; }
46
+ :host([position='bottom-left']) { left: 20px; bottom: 20px; right: auto; top: auto; }
125
47
 
126
- ${this.state.annotatedScreenshot ? `
127
- <div class="beacon-field">
128
- <span class="beacon-label">Annotated screenshot</span>
129
- <img src="${this.state.annotatedScreenshot}" class="beacon-thumb" alt="Annotated screenshot preview">
130
- </div>
131
- ` : ""}
48
+ :host([position='hidden']) {
49
+ position: static;
50
+ display: contents;
51
+ }
52
+ :host([position='hidden']) .beacon-default-trigger { display: none; }
132
53
 
133
- ${this.state.pins.length > 0 ? `
134
- <div class="beacon-field">
135
- <span class="beacon-label">Pins (${this.state.pins.length})</span>
136
- <div class="beacon-pin-list">
137
- ${this.state.pins.map((i) => `
138
- <div class="beacon-pin-item" data-pin="${i.number}">
139
- <span class="beacon-pin-num">${i.number}</span>
140
- <div class="beacon-pin-meta">
141
- <div class="beacon-pin-selector" title="${S(i.selector)}">${S(i.selector)}</div>
142
- <input type="text" class="beacon-pin-note-input" placeholder="Add a note (optional)" value="${S(i.note ?? "")}">
143
- </div>
144
- <button type="button" class="beacon-icon-btn" data-pin-delete="${i.number}" aria-label="Remove pin ${i.number}">${k.trash}</button>
145
- </div>
146
- `).join("")}
147
- </div>
148
- </div>
149
- ` : ""}
54
+ .beacon-default-trigger {
55
+ display: inline-flex;
56
+ align-items: center;
57
+ gap: 6px;
58
+ background: var(--beacon-accent);
59
+ color: white;
60
+ border: 0;
61
+ border-radius: 999px;
62
+ padding: 10px 16px;
63
+ font: inherit;
64
+ font-weight: 500;
65
+ cursor: pointer;
66
+ box-shadow: var(--beacon-shadow);
67
+ transition: transform 0.15s ease, box-shadow 0.15s ease;
68
+ }
69
+ .beacon-default-trigger:hover { transform: translateY(-1px); }
70
+ .beacon-default-trigger svg { width: 18px; height: 18px; }
150
71
 
151
- <details class="beacon-events" data-count="${this.state.events.length}" ${this.state.events.length === 0 ? "hidden" : ""}>
152
- <summary class="beacon-events-summary">
153
- <span class="beacon-events-dot" aria-hidden="true">●</span>
154
- <span class="beacon-events-label">${this.state.events.length} runtime ${this.state.events.length === 1 ? "error" : "errors"} will be included</span>
155
- </summary>
156
- <ul class="beacon-events-list">
157
- ${this.state.events.map((i) => `
158
- <li class="beacon-events-item">
159
- <span class="beacon-events-kind ${i.kind === "unhandledrejection" ? "rejection" : "error"}">${i.kind === "unhandledrejection" ? "rejection" : "error"}</span>
160
- <span class="beacon-events-msg">${S(i.message)}</span>
161
- </li>
162
- `).join("")}
163
- </ul>
164
- </details>
72
+ .beacon-health-dot {
73
+ display: none;
74
+ width: 8px;
75
+ height: 8px;
76
+ border-radius: 50%;
77
+ background: var(--beacon-bug);
78
+ margin-left: 2px;
79
+ }
80
+ .beacon-health-dot.visible { display: inline-block; }
165
81
 
166
- <div class="beacon-actions">
167
- <button type="button" class="beacon-btn secondary" data-action="annotate" ${this.state.submitting ? "disabled" : ""}>
168
- ${k.pin} ${this.state.pins.length > 0 ? "Add another pin" : "Annotate elements"}
169
- </button>
170
- <span style="flex:1"></span>
171
- <button type="button" class="beacon-btn primary" data-action="submit" ${e ? "" : "disabled"}>
172
- ${k.send} ${this.state.submitting ? "Sending…" : "Send"}
173
- </button>
174
- </div>
82
+ dialog.beacon-dialog {
83
+ width: 380px;
84
+ max-width: calc(100vw - 24px);
85
+ max-height: calc(100vh - 24px);
86
+ padding: 0;
87
+ background: var(--beacon-bg);
88
+ color: var(--beacon-fg);
89
+ border: 1px solid var(--beacon-border);
90
+ border-radius: var(--beacon-radius);
91
+ box-shadow: var(--beacon-shadow);
92
+ font-family: var(--beacon-font-family);
93
+ font-size: 14px;
94
+ line-height: 1.5;
95
+ }
96
+ dialog.beacon-dialog::backdrop {
97
+ background: hsl(0 0% 0% / 0.8);
98
+ }
175
99
 
176
- ${this.state.status ? `<div class="beacon-status ${this.state.statusKind}">${S(this.state.status)}</div>` : ""}
177
- `;
178
- const n = this.bodyEl.querySelector("#beacon-desc");
179
- n.addEventListener("input", () => {
180
- this.state.description = n.value, this.callbacks.onDescriptionChange(n.value);
181
- const i = this.bodyEl.querySelector('[data-action="submit"]');
182
- i && (i.disabled = !(n.value.trim().length > 0) || this.state.submitting);
183
- }), this.bodyEl.querySelectorAll('input[name="beacon-severity"]').forEach((i) => {
184
- i.addEventListener("change", () => {
185
- i.checked && (this.state.severity = i.value, this.callbacks.onSeverityChange(this.state.severity), this.render());
186
- });
187
- }), (o = this.bodyEl.querySelector('[data-action="annotate"]')) == null || o.addEventListener("click", () => this.callbacks.onAnnotate()), (s = this.bodyEl.querySelector('[data-action="submit"]')) == null || s.addEventListener("click", () => this.callbacks.onSubmit()), this.bodyEl.querySelectorAll("[data-pin-delete]").forEach((i) => {
188
- i.addEventListener("click", () => {
189
- const r = Number(i.getAttribute("data-pin-delete"));
190
- this.callbacks.onPinDelete(r);
191
- });
192
- }), this.bodyEl.querySelectorAll(".beacon-pin-note-input").forEach((i) => {
193
- const r = i.closest("[data-pin]"), l = Number((r == null ? void 0 : r.getAttribute("data-pin")) ?? 0);
194
- i.addEventListener("input", () => this.callbacks.onPinNoteChange(l, i.value));
195
- });
100
+ .beacon-dialog-inner {
101
+ display: flex;
102
+ flex-direction: column;
103
+ max-height: calc(100vh - 24px);
104
+ }
105
+
106
+ .beacon-drawer-header {
107
+ display: flex;
108
+ align-items: center;
109
+ justify-content: space-between;
110
+ padding: 12px 16px;
111
+ border-bottom: 1px solid var(--beacon-border);
112
+ }
113
+ .beacon-drawer-title { font-weight: 600; }
114
+ .beacon-icon-btn {
115
+ background: transparent;
116
+ border: 0;
117
+ color: var(--beacon-muted);
118
+ cursor: pointer;
119
+ padding: 4px;
120
+ border-radius: 4px;
121
+ display: inline-flex;
122
+ }
123
+ .beacon-icon-btn:hover { background: var(--beacon-border); color: var(--beacon-fg); }
124
+ .beacon-icon-btn svg { width: 16px; height: 16px; }
125
+
126
+ .beacon-drawer-body {
127
+ padding: 16px;
128
+ overflow-y: auto;
129
+ display: flex;
130
+ flex-direction: column;
131
+ gap: 14px;
132
+ }
133
+
134
+ /* Plugin panels share the same vertical rhythm as the drawer body so sibling
135
+ panels (annotate, monitor, etc.) don't visually collide. Without this, every
136
+ plugin panel renders flush against the previous one. */
137
+ .beacon-plugin-panels {
138
+ display: flex;
139
+ flex-direction: column;
140
+ gap: 14px;
141
+ }
142
+
143
+ .beacon-field { display: flex; flex-direction: column; gap: 6px; }
144
+ .beacon-label { font-size: 12px; color: var(--beacon-muted); font-weight: 500; }
145
+ .beacon-description { font-size: 12px; color: var(--beacon-muted); }
146
+
147
+ .beacon-input,
148
+ .beacon-textarea,
149
+ .beacon-select {
150
+ width: 100%;
151
+ padding: 8px 10px;
152
+ background: var(--beacon-bg);
153
+ color: var(--beacon-fg);
154
+ border: 1px solid var(--beacon-border);
155
+ border-radius: 6px;
156
+ font: inherit;
157
+ box-sizing: border-box;
158
+ }
159
+ .beacon-textarea { min-height: 80px; resize: vertical; }
160
+ .beacon-input:focus,
161
+ .beacon-textarea:focus,
162
+ .beacon-select:focus { outline: 2px solid var(--beacon-accent); outline-offset: -1px; border-color: var(--beacon-accent); }
163
+
164
+ .beacon-toggle {
165
+ display: inline-flex;
166
+ align-items: center;
167
+ gap: 8px;
168
+ cursor: pointer;
169
+ user-select: none;
170
+ }
171
+ .beacon-toggle input { margin: 0; }
172
+
173
+ .beacon-radio-group { display: flex; flex-direction: column; gap: 4px; }
174
+ .beacon-radio-opt { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }
175
+
176
+ .beacon-severity {
177
+ display: grid;
178
+ grid-template-columns: repeat(4, 1fr);
179
+ gap: 6px;
180
+ }
181
+ .beacon-severity-opt {
182
+ position: relative;
183
+ display: flex;
184
+ align-items: center;
185
+ justify-content: center;
186
+ padding: 6px 4px;
187
+ background: transparent;
188
+ border: 1px solid var(--beacon-border);
189
+ border-radius: 6px;
190
+ cursor: pointer;
191
+ font-size: 12px;
192
+ font-weight: 500;
193
+ color: var(--beacon-fg);
194
+ text-transform: capitalize;
195
+ }
196
+ .beacon-severity-opt input { position: absolute; opacity: 0; pointer-events: none; }
197
+ .beacon-severity-opt:hover { background: var(--beacon-border); }
198
+ .beacon-severity-opt.selected[data-sev='bug'] { border-color: var(--beacon-bug); color: var(--beacon-bug); }
199
+ .beacon-severity-opt.selected[data-sev='idea'] { border-color: var(--beacon-idea); color: var(--beacon-idea); }
200
+ .beacon-severity-opt.selected[data-sev='ux'] { border-color: var(--beacon-ux); color: var(--beacon-ux); }
201
+ .beacon-severity-opt.selected[data-sev='a11y'] { border-color: var(--beacon-a11y); color: var(--beacon-a11y); }
202
+
203
+ .beacon-actions {
204
+ display: flex;
205
+ gap: 8px;
206
+ align-items: center;
207
+ }
208
+ .beacon-btn {
209
+ display: inline-flex;
210
+ align-items: center;
211
+ gap: 6px;
212
+ padding: 8px 14px;
213
+ border-radius: 6px;
214
+ border: 0;
215
+ cursor: pointer;
216
+ font: inherit;
217
+ font-weight: 500;
218
+ font-size: 13px;
219
+ transition: opacity 0.15s ease;
220
+ }
221
+ .beacon-btn[disabled] { opacity: 0.5; cursor: not-allowed; }
222
+ .beacon-btn svg { width: 14px; height: 14px; }
223
+ .beacon-btn.primary { background: var(--beacon-accent); color: white; }
224
+ .beacon-btn.secondary {
225
+ background: transparent;
226
+ color: var(--beacon-fg);
227
+ border: 1px solid var(--beacon-border);
228
+ }
229
+ .beacon-btn.secondary:hover { background: var(--beacon-border); }
230
+
231
+ .beacon-status {
232
+ font-size: 12px;
233
+ color: var(--beacon-muted);
234
+ text-align: center;
235
+ padding: 4px;
236
+ }
237
+ .beacon-status.error { color: var(--beacon-bug); }
238
+ .beacon-status.success { color: var(--beacon-idea); }
239
+
240
+ .beacon-plugin-panel {
241
+ display: flex;
242
+ flex-direction: column;
243
+ gap: 10px;
244
+ padding: 12px;
245
+ border: 1px solid var(--beacon-border);
246
+ border-radius: 6px;
247
+ }
248
+ .beacon-plugin-panel-title {
249
+ font-size: 12px;
250
+ text-transform: uppercase;
251
+ letter-spacing: 0.04em;
252
+ color: var(--beacon-muted);
253
+ font-weight: 600;
254
+ }
255
+
256
+ /* ── Pin list (domEle plugin) ─────────────────────────────── */
257
+ .beacon-pin-list-header {
258
+ font-size: 12px;
259
+ color: var(--beacon-muted);
260
+ font-weight: 500;
261
+ }
262
+ .beacon-pin-list {
263
+ display: flex;
264
+ flex-direction: column;
265
+ gap: 6px;
266
+ max-height: 200px;
267
+ overflow-y: auto;
268
+ }
269
+ .beacon-pin-item {
270
+ display: flex;
271
+ align-items: flex-start;
272
+ gap: 8px;
273
+ padding: 8px;
274
+ background: var(--beacon-border);
275
+ border-radius: 6px;
276
+ }
277
+ .beacon-pin-num {
278
+ display: inline-flex;
279
+ align-items: center;
280
+ justify-content: center;
281
+ width: 20px;
282
+ height: 20px;
283
+ border-radius: 50%;
284
+ background: var(--beacon-accent);
285
+ color: white;
286
+ font-size: 11px;
287
+ font-weight: 600;
288
+ flex-shrink: 0;
289
+ }
290
+ .beacon-pin-meta { flex: 1; min-width: 0; }
291
+ .beacon-pin-selector {
292
+ font: 11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace;
293
+ color: var(--beacon-muted);
294
+ white-space: nowrap;
295
+ overflow: hidden;
296
+ text-overflow: ellipsis;
297
+ }
298
+ .beacon-pin-note-input {
299
+ margin-top: 4px;
300
+ width: 100%;
301
+ padding: 4px 6px;
302
+ background: var(--beacon-bg);
303
+ color: var(--beacon-fg);
304
+ border: 1px solid var(--beacon-border);
305
+ border-radius: 4px;
306
+ font: inherit;
307
+ font-size: 12px;
308
+ box-sizing: border-box;
309
+ }
310
+ .beacon-pin-annotate { align-self: flex-start; }
311
+ .beacon-thumb {
312
+ width: 100%;
313
+ border: 1px solid var(--beacon-border);
314
+ border-radius: 6px;
315
+ display: block;
316
+ }
317
+
318
+ /* ── Captured runtime events chip (errors plugin form panel) ─── */
319
+ .beacon-events {
320
+ font-size: 12px;
321
+ border: 1px solid var(--beacon-border);
322
+ border-radius: 6px;
323
+ padding: 6px 8px;
324
+ }
325
+ .beacon-events-summary {
326
+ cursor: pointer;
327
+ list-style: none;
328
+ display: flex;
329
+ align-items: center;
330
+ gap: 6px;
331
+ color: var(--beacon-muted);
332
+ user-select: none;
333
+ }
334
+ .beacon-events-summary::-webkit-details-marker { display: none; }
335
+ .beacon-events-dot {
336
+ color: var(--beacon-bug);
337
+ font-size: 10px;
338
+ line-height: 1;
339
+ }
340
+ .beacon-events-list {
341
+ list-style: none;
342
+ margin: 8px 0 0;
343
+ padding: 0;
344
+ display: flex;
345
+ flex-direction: column;
346
+ gap: 4px;
347
+ max-height: 160px;
348
+ overflow-y: auto;
349
+ }
350
+ .beacon-events-item {
351
+ display: flex;
352
+ align-items: flex-start;
353
+ gap: 6px;
354
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
355
+ font-size: 11px;
356
+ line-height: 1.4;
357
+ }
358
+ .beacon-events-kind {
359
+ flex-shrink: 0;
360
+ padding: 1px 5px;
361
+ border-radius: 3px;
362
+ font-size: 10px;
363
+ text-transform: uppercase;
364
+ letter-spacing: 0.04em;
365
+ }
366
+ .beacon-events-kind.error { background: hsl(0 84% 50% / 0.15); color: var(--beacon-bug); }
367
+ .beacon-events-kind.rejection { background: hsl(38 92% 50% / 0.15); color: hsl(38 92% 50%); }
368
+ .beacon-events-msg {
369
+ word-break: break-word;
370
+ color: var(--beacon-fg);
371
+ }
372
+
373
+ /* ── liveMonitor plugin panel ─────────────────────────────── */
374
+ .beacon-monitor {
375
+ padding: 0 0 4px;
376
+ font-size: 12px;
377
+ color: var(--beacon-fg);
378
+ display: flex;
379
+ flex-direction: column;
380
+ gap: 6px;
381
+ }
382
+ .beacon-monitor-title {
383
+ display: flex;
384
+ align-items: center;
385
+ gap: 8px;
386
+ font-weight: 600;
387
+ text-transform: uppercase;
388
+ letter-spacing: 0.04em;
389
+ color: var(--beacon-muted);
390
+ font-size: 11px;
391
+ }
392
+ .beacon-monitor-rec {
393
+ width: 8px;
394
+ height: 8px;
395
+ border-radius: 50%;
396
+ background: var(--beacon-bug);
397
+ animation: beacon-rec-pulse 1.4s ease-in-out infinite;
398
+ }
399
+ @keyframes beacon-rec-pulse {
400
+ 0%, 100% { opacity: 1; }
401
+ 50% { opacity: 0.35; }
402
+ }
403
+ .beacon-monitor-row {
404
+ display: flex;
405
+ gap: 6px;
406
+ align-items: center;
407
+ }
408
+ .beacon-monitor-input {
409
+ flex: 1;
410
+ font: inherit;
411
+ padding: 6px 8px;
412
+ background: var(--beacon-bg);
413
+ color: var(--beacon-fg);
414
+ border: 1px solid var(--beacon-border);
415
+ border-radius: 6px;
416
+ min-width: 0;
417
+ box-sizing: border-box;
418
+ }
419
+ .beacon-monitor-input::placeholder { color: var(--beacon-muted); opacity: 0.7; }
420
+ .beacon-monitor-input:focus {
421
+ outline: 2px solid var(--beacon-accent);
422
+ outline-offset: -1px;
423
+ border-color: var(--beacon-accent);
424
+ }
425
+ .beacon-monitor-btn {
426
+ font: inherit;
427
+ padding: 6px 10px;
428
+ border-radius: 6px;
429
+ border: 1px solid var(--beacon-accent);
430
+ background: var(--beacon-accent);
431
+ color: white;
432
+ cursor: pointer;
433
+ font-weight: 500;
434
+ }
435
+ .beacon-monitor-btn:disabled { opacity: 0.4; cursor: not-allowed; }
436
+ .beacon-monitor-btn.stop {
437
+ background: transparent;
438
+ color: var(--beacon-accent);
439
+ }
440
+ .beacon-monitor-help {
441
+ color: var(--beacon-muted);
442
+ font-size: 11px;
443
+ }
444
+ .beacon-monitor-active-url {
445
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
446
+ font-size: 11px;
447
+ color: var(--beacon-muted);
448
+ word-break: break-all;
449
+ background: hsl(0 0% 0% / 0.18);
450
+ border-radius: 4px;
451
+ padding: 4px 6px;
452
+ }
453
+ .beacon-monitor-verbose {
454
+ display: inline-flex;
455
+ align-items: center;
456
+ gap: 6px;
457
+ color: var(--beacon-muted);
458
+ font-size: 11px;
459
+ cursor: pointer;
460
+ user-select: none;
461
+ }
462
+
463
+ .beacon-overlay-layer {
464
+ position: fixed;
465
+ inset: 0;
466
+ pointer-events: none;
467
+ z-index: calc(var(--beacon-z-index) + 1);
468
+ }
469
+ .beacon-overlay-layer > * { pointer-events: auto; }
470
+
471
+ /* ── Body-mounted UI ──────────────────────────────────────
472
+ Pin-popover and other overlays mount on document.body to escape transformed
473
+ ancestors. Shadow DOM :host vars don't reach them, so we re-declare the
474
+ variables here on each body-mounted root. */
475
+
476
+ .beacon-pin-popover {
477
+ --beacon-accent: #0ea5e9;
478
+ --beacon-bg: #ffffff;
479
+ --beacon-fg: #0f172a;
480
+ --beacon-muted: #64748b;
481
+ --beacon-border: #e2e8f0;
482
+ --beacon-radius: 10px;
483
+ --beacon-shadow: 0 10px 30px hsl(0 0% 0% / 0.15), 0 2px 6px hsl(0 0% 0% / 0.08);
484
+ --beacon-bug: #ef4444;
485
+ --beacon-idea: #22c55e;
486
+ --beacon-ux: #a855f7;
487
+ --beacon-a11y: #06b6d4;
488
+
489
+ position: fixed;
490
+ z-index: 2147483647;
491
+ width: 240px;
492
+ background: var(--beacon-bg);
493
+ color: var(--beacon-fg);
494
+ border: 1px solid var(--beacon-border);
495
+ border-radius: 6px;
496
+ box-shadow: var(--beacon-shadow);
497
+ padding: 10px;
498
+ display: none;
499
+ flex-direction: column;
500
+ gap: 8px;
501
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
502
+ font-size: 14px;
503
+ line-height: 1.5;
504
+ }
505
+ .beacon-pin-popover.open { display: flex; }
506
+ .beacon-pin-popover.beacon-theme-dark {
507
+ --beacon-bg: #0f172a;
508
+ --beacon-fg: #f1f5f9;
509
+ --beacon-muted: #94a3b8;
510
+ --beacon-border: #334155;
511
+ }
512
+ @media (prefers-color-scheme: dark) {
513
+ .beacon-pin-popover.beacon-theme-auto {
514
+ --beacon-bg: #0f172a;
515
+ --beacon-fg: #f1f5f9;
516
+ --beacon-muted: #94a3b8;
517
+ --beacon-border: #334155;
196
518
  }
197
519
  }
198
- function S(t) {
199
- return t.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
520
+
521
+ .beacon-pin-popover .beacon-pin-popover-header {
522
+ display: flex;
523
+ align-items: center;
524
+ justify-content: space-between;
525
+ gap: 6px;
526
+ }
527
+ .beacon-pin-popover .beacon-pin-popover-actions {
528
+ display: flex;
529
+ gap: 6px;
530
+ justify-content: flex-end;
531
+ }
532
+ .beacon-pin-popover .beacon-pin-num {
533
+ display: inline-flex;
534
+ align-items: center;
535
+ justify-content: center;
536
+ width: 20px;
537
+ height: 20px;
538
+ border-radius: 50%;
539
+ background: var(--beacon-accent);
540
+ color: white;
541
+ font-size: 11px;
542
+ font-weight: 600;
543
+ flex-shrink: 0;
544
+ }
545
+ .beacon-pin-popover .beacon-icon-btn {
546
+ background: transparent;
547
+ border: 0;
548
+ color: var(--beacon-muted);
549
+ cursor: pointer;
550
+ padding: 4px;
551
+ border-radius: 4px;
552
+ display: inline-flex;
553
+ }
554
+ .beacon-pin-popover .beacon-icon-btn:hover { background: var(--beacon-border); color: var(--beacon-fg); }
555
+ .beacon-pin-popover .beacon-icon-btn svg { width: 16px; height: 16px; }
556
+ .beacon-pin-popover .beacon-textarea {
557
+ width: 100%;
558
+ min-height: 48px;
559
+ padding: 6px 8px;
560
+ background: var(--beacon-bg);
561
+ color: var(--beacon-fg);
562
+ border: 1px solid var(--beacon-border);
563
+ border-radius: 6px;
564
+ font: inherit;
565
+ resize: vertical;
566
+ box-sizing: border-box;
567
+ }
568
+ .beacon-pin-popover .beacon-textarea:focus {
569
+ outline: 2px solid var(--beacon-accent);
570
+ outline-offset: -1px;
571
+ border-color: var(--beacon-accent);
572
+ }
573
+ .beacon-pin-popover .beacon-btn {
574
+ display: inline-flex;
575
+ align-items: center;
576
+ gap: 6px;
577
+ padding: 6px 12px;
578
+ border-radius: 6px;
579
+ border: 0;
580
+ cursor: pointer;
581
+ font: inherit;
582
+ font-weight: 500;
583
+ font-size: 13px;
584
+ }
585
+ .beacon-pin-popover .beacon-btn.primary { background: var(--beacon-accent); color: white; }
586
+ .beacon-pin-popover .beacon-btn svg { width: 14px; height: 14px; }
587
+
588
+ /* ── liveMonitor body-portal overlay ───────────────────────
589
+ Dashed viewport frame + draggable status chip. Body-mounted (same reason as
590
+ pick-mode-overlay), so the CSS var --beacon-monitor-accent is set inline on
591
+ the frame and chip elements by the plugin — the shadow root's :host vars
592
+ don't reach here. */
593
+
594
+ @keyframes beacon-monitor-frame-pulse {
595
+ 0%, 100% { opacity: 0.55; }
596
+ 50% { opacity: 1; }
200
597
  }
201
- function Le(t) {
202
- return new Promise((e) => {
203
- const n = document.createElement("div");
204
- n.className = "beacon-pin-popover open beacon-no-capture beacon-theme-auto", n.innerHTML = `
205
- <div class="beacon-pin-popover-header">
206
- <div style="display:flex;align-items:center;gap:6px;font-weight:600;font-size:13px;">
207
- <span class="beacon-pin-num">${t.pinNumber}</span>
208
- <span>Note for this pin</span>
209
- </div>
210
- <button type="button" class="beacon-icon-btn" data-action="cancel" aria-label="Discard this pin">${k.close}</button>
211
- </div>
212
- <textarea class="beacon-textarea" rows="2" placeholder="Optional — describe what's wrong here…" style="min-height:48px;"></textarea>
213
- <div class="beacon-pin-popover-actions">
214
- <button type="button" class="beacon-btn primary" data-action="save">${k.check} Save</button>
215
- </div>
216
- `;
217
- const o = 240, s = 160, i = Math.min(Math.max(8, t.anchor.x), window.innerWidth - o - 8), r = Math.min(Math.max(8, t.anchor.y + 12), window.innerHeight - s - 8);
218
- n.style.left = `${i}px`, n.style.top = `${r}px`, document.body.appendChild(n);
219
- const l = n.querySelector("textarea");
220
- l.focus();
221
- function a(d) {
222
- document.removeEventListener("keydown", c, !0), n.remove(), e(d);
223
- }
224
- function c(d) {
225
- d.key === "Escape" && (d.preventDefault(), d.stopPropagation(), a({ cancelled: "all" }));
226
- }
227
- document.addEventListener("keydown", c, !0), n.addEventListener("click", (d) => {
228
- var y;
229
- const g = (y = d.target.closest("[data-action]")) == null ? void 0 : y.getAttribute("data-action");
230
- if (g === "cancel" && a({ cancelled: "pin" }), g === "save") {
231
- const w = l.value.trim();
232
- a({ ...w ? { note: w } : {}, cancelled: !1 });
233
- }
234
- }), l.addEventListener("keydown", (d) => {
235
- if (d.key === "Enter" && (d.metaKey || d.ctrlKey)) {
236
- d.preventDefault();
237
- const u = l.value.trim();
238
- a({ ...u ? { note: u } : {}, cancelled: !1 });
239
- }
240
- });
241
- });
598
+
599
+ .beacon-monitor-overlay-frame {
600
+ --beacon-monitor-accent: #10b981;
601
+ position: fixed;
602
+ inset: 0;
603
+ pointer-events: none;
604
+ z-index: 2147483646;
605
+ border: 2px dashed var(--beacon-monitor-accent);
606
+ border-radius: 4px;
607
+ box-shadow: inset 0 0 56px color-mix(in srgb, var(--beacon-monitor-accent) 18%, transparent);
608
+ box-sizing: border-box;
609
+ animation: beacon-monitor-frame-pulse 2.4s ease-in-out infinite;
242
610
  }
243
- const A = "beacon-no-capture", Te = "#0ea5e9", K = "Click any element to pin it · Press Esc to finish";
244
- function X(t, e) {
245
- return /^#[0-9a-fA-F]{6}$/.test(t) ? `${t}${e}` : t;
611
+
612
+ .beacon-monitor-overlay-chip {
613
+ --beacon-monitor-accent: #10b981;
614
+ position: fixed;
615
+ z-index: 2147483647;
616
+ pointer-events: auto;
617
+ cursor: grab;
618
+ user-select: none;
619
+ background: #0f172a;
620
+ color: #f1f5f9;
621
+ border: 1px solid color-mix(in srgb, var(--beacon-monitor-accent) 50%, transparent);
622
+ border-radius: 999px;
623
+ padding: 6px 6px 6px 12px;
624
+ box-shadow: 0 6px 20px hsl(0 0% 0% / 0.3);
625
+ font: 500 12px/1.2 system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
626
+ letter-spacing: 0.01em;
627
+ display: flex;
628
+ flex-direction: column;
629
+ gap: 4px;
630
+ min-width: 140px;
631
+ max-width: min(360px, calc(100vw - 32px));
632
+ touch-action: none;
633
+ }
634
+ .beacon-monitor-overlay-chip[data-dragging] { cursor: grabbing; }
635
+
636
+ .beacon-monitor-overlay-chip-row {
637
+ display: flex;
638
+ align-items: center;
639
+ gap: 6px;
246
640
  }
247
- function Me(t = {}) {
248
- const e = t.accent ?? Te, n = X(e, "b3"), o = X(e, "2e"), s = document.createElement("style");
249
- s.className = A, s.textContent = "@keyframes beacon-spin { to { transform: rotate(360deg); } }", document.head.appendChild(s);
250
- const i = document.createElement("div");
251
- i.className = A, i.setAttribute("aria-hidden", "true"), i.style.cssText = [
252
- "position: fixed",
253
- "inset: 0",
254
- "pointer-events: none",
255
- "z-index: 2147483646",
256
- `border: 2px dashed ${n}`,
257
- "border-radius: 4px",
258
- `box-shadow: inset 0 0 56px ${o}`,
259
- "box-sizing: border-box"
260
- ].join("; ");
261
- const r = document.createElement("div");
262
- r.className = A, r.setAttribute("role", "status"), r.style.cssText = [
263
- "position: fixed",
264
- "top: 16px",
265
- "left: 50%",
266
- "transform: translateX(-50%)",
267
- `background: ${e}`,
268
- "color: #fff",
269
- "padding: 6px 14px",
270
- "border-radius: 999px",
271
- "font: 500 12px/1.4 system-ui, -apple-system, sans-serif",
272
- "letter-spacing: 0.01em",
273
- "box-shadow: 0 4px 12px #0000004d",
274
- "pointer-events: none",
275
- "white-space: nowrap",
276
- "z-index: 2147483646"
277
- ].join("; "), r.textContent = K;
278
- const l = `<span style="
279
- display: inline-block;
280
- width: 12px;
281
- height: 12px;
282
- border: 2px solid #fff;
283
- border-top-color: transparent;
284
- border-radius: 50%;
285
- animation: beacon-spin 800ms linear infinite;
286
- vertical-align: middle;
287
- margin-right: 8px;
288
- "></span>`;
289
- function a(h) {
290
- return h.replace(/[<>&]/g, (f) => ({ "<": "&lt;", ">": "&gt;", "&": "&amp;" })[f]);
641
+
642
+ .beacon-monitor-overlay-rec-dot {
643
+ width: 8px;
644
+ height: 8px;
645
+ border-radius: 50%;
646
+ background: #ef4444;
647
+ flex-shrink: 0;
648
+ animation: beacon-rec-pulse 1.4s ease-in-out infinite;
649
+ }
650
+
651
+ .beacon-monitor-overlay-rec-label {
652
+ font-weight: 700;
653
+ letter-spacing: 0.06em;
654
+ color: #ef4444;
655
+ font-size: 11px;
656
+ }
657
+
658
+ .beacon-monitor-overlay-sep {
659
+ color: #64748b;
660
+ }
661
+
662
+ .beacon-monitor-overlay-timer {
663
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
664
+ font-variant-numeric: tabular-nums;
665
+ font-size: 12px;
666
+ flex: 1;
667
+ min-width: 48px;
668
+ }
669
+
670
+ .beacon-monitor-overlay-stop {
671
+ font: inherit;
672
+ font-weight: 500;
673
+ font-size: 11px;
674
+ padding: 3px 10px;
675
+ border-radius: 999px;
676
+ background: var(--beacon-monitor-accent);
677
+ color: #ffffff;
678
+ border: 0;
679
+ cursor: pointer;
680
+ flex-shrink: 0;
681
+ }
682
+ .beacon-monitor-overlay-stop:hover {
683
+ background: color-mix(in srgb, var(--beacon-monitor-accent) 85%, white);
684
+ }
685
+
686
+ .beacon-monitor-overlay-url {
687
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
688
+ font-size: 10px;
689
+ color: #94a3b8;
690
+ padding: 0 6px;
691
+ white-space: nowrap;
692
+ overflow: hidden;
693
+ text-overflow: ellipsis;
694
+ max-width: 100%;
695
+ }
696
+ `, se = "launch-kit-beacon-portal-styles";
697
+ function Ye() {
698
+ if (typeof document > "u" || !document.head || document.getElementById(se)) return;
699
+ const e = document.createElement("style");
700
+ e.id = se, e.textContent = Te, document.head.appendChild(e);
701
+ }
702
+ const V = "http://www.w3.org/2000/svg";
703
+ function Ke() {
704
+ const e = document.createElementNS(V, "svg");
705
+ e.setAttribute("viewBox", "0 0 24 24"), e.setAttribute("fill", "none"), e.setAttribute("stroke", "currentColor"), e.setAttribute("stroke-width", "2"), e.setAttribute("stroke-linecap", "round"), e.setAttribute("stroke-linejoin", "round");
706
+ const t = document.createElementNS(V, "path");
707
+ t.setAttribute("d", "M3 11l18-5v12L3 14v-3z");
708
+ const n = document.createElementNS(V, "path");
709
+ return n.setAttribute("d", "M11.6 16.8a3 3 0 1 1-5.8-1.6"), e.appendChild(t), e.appendChild(n), e;
710
+ }
711
+ const B = "launch-kit-beacon", Xe = typeof HTMLElement < "u" ? HTMLElement : class {
712
+ };
713
+ class Ge extends Xe {
714
+ constructor() {
715
+ super(...arguments), this.onTriggerClick = null;
291
716
  }
292
- document.body.appendChild(i), document.body.appendChild(r);
293
- const c = /* @__PURE__ */ new Map();
294
- function d(h) {
295
- const f = document.createElement("div");
296
- return f.className = A, f.setAttribute("aria-hidden", "true"), f.style.cssText = [
297
- "position: fixed",
298
- "width: 24px",
299
- "height: 24px",
300
- "border-radius: 999px",
301
- `background: ${e}`,
302
- "color: #fff",
303
- "display: flex",
304
- "align-items: center",
305
- "justify-content: center",
306
- "font: 700 12px/1 system-ui, -apple-system, sans-serif",
307
- "border: 2px solid #fff",
308
- "box-shadow: 0 2px 8px #00000066",
309
- "pointer-events: none",
310
- "z-index: 2147483646"
311
- ].join("; "), f.textContent = String(h), document.body.appendChild(f), f;
717
+ connectedCallback() {
718
+ if (this.shadow) return;
719
+ this.shadow = this.attachShadow({ mode: "open" });
720
+ const t = document.createElement("style");
721
+ t.textContent = Te, this.shadow.appendChild(t), this.triggerSlot = document.createElement("slot"), this.triggerSlot.name = "trigger", this.shadow.appendChild(this.triggerSlot), this.defaultTrigger = document.createElement("button"), this.defaultTrigger.type = "button", this.defaultTrigger.className = "beacon-default-trigger", this.defaultTrigger.appendChild(Ke());
722
+ const n = document.createElement("span");
723
+ n.textContent = "Feedback", this.defaultTrigger.appendChild(n), this.healthDot = document.createElement("span"), this.healthDot.className = "beacon-health-dot", this.defaultTrigger.appendChild(this.healthDot), this.shadow.appendChild(this.defaultTrigger), this.defaultTrigger.addEventListener("click", () => {
724
+ var o;
725
+ return (o = this.onTriggerClick) == null ? void 0 : o.call(this);
726
+ }), this.triggerSlot.addEventListener("slotchange", () => {
727
+ const o = this.triggerSlot.assignedElements();
728
+ if (o.length > 0) {
729
+ this.defaultTrigger.style.display = "none";
730
+ for (const r of o)
731
+ r.addEventListener("click", () => {
732
+ var a;
733
+ return (a = this.onTriggerClick) == null ? void 0 : a.call(this);
734
+ });
735
+ } else
736
+ this.defaultTrigger.style.display = "";
737
+ }), this.hasAttribute("position") || this.setAttribute("position", "bottom-right"), this.hasAttribute("theme") || this.setAttribute("theme", "auto");
738
+ }
739
+ setTriggerLabel(t) {
740
+ if (!this.defaultTrigger) return;
741
+ const n = this.defaultTrigger.querySelector("span");
742
+ n && (n.textContent = t);
743
+ }
744
+ setHealthIndicator(t) {
745
+ var n;
746
+ (n = this.healthDot) == null || n.classList.toggle("visible", t);
312
747
  }
313
- function u() {
314
- const h = document.createElement("div");
315
- return h.className = A, h.setAttribute("aria-hidden", "true"), h.style.cssText = [
316
- "position: fixed",
317
- "pointer-events: none",
318
- `border: 2px solid ${e}`,
319
- "border-radius: 2px",
320
- "box-sizing: border-box",
321
- // Slightly below marker z so the marker visually "sits on" the outline corner.
322
- "z-index: 2147483645"
323
- ].join("; "), document.body.appendChild(h), h;
748
+ }
749
+ function Me() {
750
+ typeof window > "u" || typeof customElements > "u" || customElements.get(B) || customElements.define(B, Ge);
751
+ }
752
+ function Je(e, t) {
753
+ return {
754
+ pluginName: e,
755
+ captured: (n) => t.getCaptured(n),
756
+ get formValues() {
757
+ return t.getFormValues(e);
758
+ },
759
+ requestMode: (n) => t.requestMode(n),
760
+ overlay: (n) => t.overlay(n),
761
+ on: (n, o) => t.onLifecycle(n, o),
762
+ get signal() {
763
+ return t.getInitSignal();
764
+ },
765
+ captureSignal: () => t.getCaptureSignal()
766
+ };
767
+ }
768
+ class Ze extends Error {
769
+ constructor(t) {
770
+ super(`Duplicate plugin name: "${t}"`), this.name = "DuplicatePluginNameError";
324
771
  }
325
- function g(h, f, p) {
326
- const b = p ? "0.5" : "1";
327
- h.outline.style.display = "block", h.outline.style.opacity = b, h.outline.style.left = `${f.x}px`, h.outline.style.top = `${f.y}px`, h.outline.style.width = `${f.w}px`, h.outline.style.height = `${f.h}px`, h.marker.style.display = "flex", h.marker.style.opacity = b, h.marker.style.left = `${f.x + f.w - 12}px`, h.marker.style.top = `${Math.max(2, f.y - 12)}px`;
772
+ }
773
+ function Qe(e) {
774
+ const t = /* @__PURE__ */ new Set();
775
+ for (const o of e) {
776
+ if (t.has(o.name)) throw new Ze(o.name);
777
+ t.add(o.name);
328
778
  }
329
- function y(h) {
330
- h.marker.style.display = "none", h.outline.style.display = "none";
331
- }
332
- function w() {
333
- c.forEach((h) => {
334
- let f = h.anchor.target;
335
- if (document.contains(f) || (f = null), !f && h.anchor.selector && (f = document.querySelector(h.anchor.selector), f && (h.anchor.target = f)), f) {
336
- const b = f.getBoundingClientRect();
337
- if (b.width > 0 || b.height > 0) {
338
- g(h, { x: b.left, y: b.top, w: b.width, h: b.height }, !1);
339
- return;
779
+ const n = e.map((o) => ({
780
+ plugin: o,
781
+ // Placeholder; install() rebinds with the real ctx factory.
782
+ ctx: null,
783
+ status: { state: "active", failures: 0 }
784
+ }));
785
+ return {
786
+ entries: n,
787
+ install(o, r) {
788
+ for (const a of n)
789
+ if (a.ctx = o(a.plugin.name), !!a.plugin.setupOnce)
790
+ try {
791
+ const i = a.plugin.setupOnce(a.ctx);
792
+ typeof i == "function" && (a.teardown = i);
793
+ } catch (i) {
794
+ const s = i instanceof Error ? i : new Error(String(i));
795
+ a.status = {
796
+ state: "failed",
797
+ failures: a.status.failures + 1,
798
+ error: { message: s.message, ...s.stack ? { stack: s.stack } : {}, at: "setupOnce" }
799
+ }, r({ plugin: a.plugin.name, error: s, at: "setupOnce" });
800
+ }
801
+ },
802
+ destroy() {
803
+ var o;
804
+ for (const r of n) {
805
+ try {
806
+ (o = r.teardown) == null || o.call(r);
807
+ } catch {
340
808
  }
809
+ r.teardown = void 0;
341
810
  }
342
- const p = h.anchor.fallbackRect;
343
- if (p && (p.w > 0 || p.h > 0)) {
344
- g(h, p, !0);
345
- return;
346
- }
347
- y(h);
348
- });
349
- }
350
- let x = null;
351
- function v() {
352
- x === null && (x = requestAnimationFrame(() => {
353
- x = null, w();
354
- }));
355
- }
356
- return window.addEventListener("scroll", v, !0), window.addEventListener("resize", v), {
357
- addPin(h, f) {
358
- const p = d(h), b = u();
359
- c.set(h, { anchor: f, marker: p, outline: b }), w();
360
811
  },
361
- setLoading(h) {
362
- h ? r.innerHTML = l + a(h) : r.textContent = K;
812
+ async capture(o, r) {
813
+ const a = {};
814
+ for (const i of n)
815
+ if (i.plugin.capture)
816
+ try {
817
+ const s = await i.plugin.capture(i.ctx), c = et(s, i.plugin.version);
818
+ c !== null && (a[i.plugin.name] = c);
819
+ } catch (s) {
820
+ const c = s instanceof Error ? s : new Error(String(s));
821
+ a[i.plugin.name] = tt(c), i.status = {
822
+ state: "failed",
823
+ failures: i.status.failures + 1,
824
+ error: { message: c.message, ...c.stack ? { stack: c.stack } : {}, at: "capture" }
825
+ }, r({ plugin: i.plugin.name, error: c, at: "capture" });
826
+ }
827
+ return a;
363
828
  },
364
- destroy() {
365
- window.removeEventListener("scroll", v, !0), window.removeEventListener("resize", v), x !== null && cancelAnimationFrame(x), i.remove(), r.remove(), s.remove(), c.forEach(({ marker: h, outline: f }) => {
366
- h.remove(), f.remove();
367
- }), c.clear();
829
+ status() {
830
+ const o = {};
831
+ for (const r of n)
832
+ o[r.plugin.name] = r.status;
833
+ return o;
368
834
  }
369
835
  };
370
836
  }
371
- const Ie = "#0ea5e9";
372
- function _e(t, e) {
373
- return /^#[0-9a-fA-F]{6}$/.test(t) ? `${t}${e}` : t;
837
+ function et(e, t) {
838
+ if (e == null) return null;
839
+ const n = t ?? 1;
840
+ return Array.isArray(e) || typeof e != "object" ? { v: n, value: e } : { ...e, v: n };
374
841
  }
375
- function $e(t) {
376
- const { shadowRoot: e, onHover: n } = t, o = t.accent ?? Ie, s = _e(o, "14"), i = document.createElement("div");
377
- i.style.cssText = [
378
- "position: fixed",
379
- "pointer-events: none",
380
- "z-index: 2147483646",
381
- `border: 2px solid ${o}`,
382
- `background: ${s}`,
383
- "transition: all 60ms ease-out",
384
- "box-sizing: border-box",
385
- "border-radius: 2px"
386
- ].join("; "), document.body.appendChild(i);
387
- const r = document.createElement("div");
388
- r.style.cssText = [
389
- "position: fixed",
390
- "pointer-events: none",
391
- "z-index: 2147483647",
392
- "background: #0f172a",
393
- "color: #fff",
394
- "font: 11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace",
395
- "padding: 3px 6px",
396
- "border-radius: 3px",
397
- "max-width: 280px",
398
- "overflow: hidden",
399
- "text-overflow: ellipsis",
400
- "white-space: nowrap"
401
- ].join("; "), document.body.appendChild(r);
402
- const l = document.body.style.cursor;
403
- document.body.style.cursor = "crosshair";
404
- let a = !1, c = () => {
842
+ function tt(e) {
843
+ return {
844
+ error: e.message,
845
+ ...e.stack ? { stack: e.stack } : {}
405
846
  };
406
- const d = new Promise((p) => {
407
- c = p;
408
- });
409
- function u(p) {
410
- if (!p || !(p instanceof Node)) return !1;
411
- let b = p;
412
- for (; b; ) {
413
- if (b === e || b === e.host) return !0;
414
- b = b.parentNode ?? b.host ?? null;
847
+ }
848
+ async function nt(e, t, n, o, r = "omit") {
849
+ const a = await ot(n), i = await fetch(e, {
850
+ method: "POST",
851
+ credentials: r,
852
+ headers: { "Content-Type": "application/json", ...a },
853
+ body: JSON.stringify(t),
854
+ signal: o
855
+ }), c = (i.headers.get("content-type") ?? "").includes("application/json") ? await i.json().catch(() => null) : await i.text();
856
+ return { ok: i.ok, status: i.status, body: c };
857
+ }
858
+ async function ot(e) {
859
+ return e ? typeof e == "function" ? await e() ?? {} : e : {};
860
+ }
861
+ function rt(e, t, n) {
862
+ for (const o of t) {
863
+ const r = document.createElement("div");
864
+ if (r.className = "beacon-field", o.label) {
865
+ const i = document.createElement("label");
866
+ i.className = "beacon-label", i.textContent = o.label, r.appendChild(i);
867
+ }
868
+ if (o.description) {
869
+ const i = document.createElement("div");
870
+ i.className = "beacon-description", i.textContent = o.description, r.appendChild(i);
871
+ }
872
+ const a = at(o, n);
873
+ r.appendChild(a), e.appendChild(r);
874
+ }
875
+ }
876
+ function at(e, t) {
877
+ var o, r;
878
+ const n = t.get(e.name);
879
+ switch (e.type) {
880
+ case "toggle": {
881
+ const a = document.createElement("label");
882
+ a.className = "beacon-toggle";
883
+ const i = document.createElement("input");
884
+ return i.type = "checkbox", i.checked = n ?? e.defaultValue ?? !1, i.addEventListener("change", () => t.set(e.name, i.checked)), a.appendChild(i), t.set(e.name, i.checked), a;
885
+ }
886
+ case "text": {
887
+ const a = document.createElement("input");
888
+ a.type = "text", a.className = "beacon-input";
889
+ const i = n ?? e.defaultValue ?? "";
890
+ return a.value = i, e.placeholder && (a.placeholder = e.placeholder), a.addEventListener("input", () => t.set(e.name, a.value)), t.set(e.name, i), a;
891
+ }
892
+ case "textarea": {
893
+ const a = document.createElement("textarea");
894
+ a.className = "beacon-textarea";
895
+ const i = n ?? e.defaultValue ?? "";
896
+ return a.value = i, e.placeholder && (a.placeholder = e.placeholder), e.rows && (a.rows = e.rows), a.addEventListener("input", () => t.set(e.name, a.value)), t.set(e.name, i), a;
897
+ }
898
+ case "select": {
899
+ const a = document.createElement("select");
900
+ a.className = "beacon-select";
901
+ const i = n ?? e.defaultValue ?? ((o = e.options[0]) == null ? void 0 : o.value) ?? "";
902
+ for (const s of e.options) {
903
+ const c = document.createElement("option");
904
+ c.value = s.value, c.textContent = s.label ?? s.value, s.value === i && (c.selected = !0), a.appendChild(c);
905
+ }
906
+ return a.addEventListener("change", () => t.set(e.name, a.value)), t.set(e.name, i), a;
907
+ }
908
+ case "radio": {
909
+ const a = document.createElement("div");
910
+ a.className = "beacon-radio-group";
911
+ const i = n ?? e.defaultValue ?? ((r = e.options[0]) == null ? void 0 : r.value) ?? "";
912
+ for (const s of e.options) {
913
+ const c = document.createElement("label");
914
+ c.className = "beacon-radio-opt";
915
+ const d = document.createElement("input");
916
+ d.type = "radio", d.name = e.name, d.value = s.value, s.value === i && (d.checked = !0), d.addEventListener("change", () => t.set(e.name, s.value));
917
+ const l = document.createElement("span");
918
+ l.textContent = s.label ?? s.value, c.appendChild(d), c.appendChild(l), a.appendChild(c);
919
+ }
920
+ return t.set(e.name, i), a;
921
+ }
922
+ case "number": {
923
+ const a = document.createElement("input");
924
+ a.type = "number", a.className = "beacon-input";
925
+ const i = n ?? e.defaultValue;
926
+ return i !== void 0 && (a.value = String(i)), e.min !== void 0 && (a.min = String(e.min)), e.max !== void 0 && (a.max = String(e.max)), e.step !== void 0 && (a.step = String(e.step)), a.addEventListener("input", () => {
927
+ const s = a.value === "" ? void 0 : Number(a.value);
928
+ t.set(e.name, s);
929
+ }), i !== void 0 && t.set(e.name, i), a;
415
930
  }
416
- return !1;
417
931
  }
418
- function g(p, b) {
419
- i.style.display = "none", r.style.display = "none";
420
- const N = document.elementsFromPoint(p, b);
421
- i.style.display = "block", r.style.display = "block";
422
- for (const I of N)
423
- if (!u(I)) return I;
424
- return null;
932
+ }
933
+ const W = "http://www.w3.org/2000/svg";
934
+ function it() {
935
+ const e = document.createElementNS(W, "svg");
936
+ e.setAttribute("viewBox", "0 0 24 24"), e.setAttribute("fill", "none"), e.setAttribute("stroke", "currentColor"), e.setAttribute("stroke-width", "2"), e.setAttribute("stroke-linecap", "round"), e.setAttribute("stroke-linejoin", "round");
937
+ const t = document.createElementNS(W, "line");
938
+ t.setAttribute("x1", "18"), t.setAttribute("y1", "6"), t.setAttribute("x2", "6"), t.setAttribute("y2", "18");
939
+ const n = document.createElementNS(W, "line");
940
+ return n.setAttribute("x1", "6"), n.setAttribute("y1", "6"), n.setAttribute("x2", "18"), n.setAttribute("y2", "18"), e.appendChild(t), e.appendChild(n), e;
941
+ }
942
+ class st {
943
+ constructor(t, n, o) {
944
+ this.labels = t, this.severities = n, this.callbacks = o, this.severitySelected = "bug", this.modeCounts = { minimize: 0, hide: 0, pickElement: 0 }, this.pluginCleanups = [], this.lastActive = null, this.submitSucceeded = !1, this.expectedSuppressedCloses = 0, this.root = document.createElement("dialog"), this.root.className = "beacon-dialog", this.inner = document.createElement("div"), this.inner.className = "beacon-dialog-inner", this.root.appendChild(this.inner);
945
+ const r = document.createElement("div");
946
+ r.className = "beacon-drawer-header";
947
+ const a = document.createElement("div");
948
+ a.className = "beacon-drawer-title", a.textContent = t.drawerTitle, r.appendChild(a);
949
+ const i = document.createElement("button");
950
+ i.type = "button", i.className = "beacon-icon-btn", i.setAttribute("aria-label", t.closeButton), i.appendChild(it()), i.addEventListener("click", () => this.userCloseAttempt()), r.appendChild(i), this.inner.appendChild(r), this.root.addEventListener("cancel", (b) => {
951
+ this.submitSucceeded || this.hasUnsavedInput() && (b.preventDefault(), window.confirm("You have unsaved feedback. Discard?") && this.root.close());
952
+ });
953
+ const s = document.createElement("div");
954
+ s.className = "beacon-drawer-body", this.inner.appendChild(s);
955
+ const c = document.createElement("div");
956
+ c.className = "beacon-field";
957
+ const d = document.createElement("label");
958
+ d.className = "beacon-label", d.textContent = t.descriptionLabel, this.descTextarea = document.createElement("textarea"), this.descTextarea.className = "beacon-textarea", this.descTextarea.placeholder = t.descriptionPlaceholder, this.descTextarea.rows = 4, c.appendChild(d), c.appendChild(this.descTextarea), s.appendChild(c);
959
+ const l = document.createElement("div");
960
+ l.className = "beacon-field";
961
+ const p = document.createElement("label");
962
+ p.className = "beacon-label", p.textContent = t.severityLabel, this.severitiesContainer = document.createElement("div"), this.severitiesContainer.className = "beacon-severity";
963
+ for (const b of n) {
964
+ const m = document.createElement("label");
965
+ m.className = "beacon-severity-opt", m.dataset.sev = b;
966
+ const x = document.createElement("input");
967
+ x.type = "radio", x.name = "beacon-severity", x.value = b, b === this.severitySelected && (x.checked = !0, m.classList.add("selected")), x.addEventListener("change", () => this.setSeverity(b)), m.appendChild(x), m.appendChild(document.createTextNode(this.severityLabel(b))), this.severitiesContainer.appendChild(m);
968
+ }
969
+ l.appendChild(p), l.appendChild(this.severitiesContainer), s.appendChild(l), this.pluginSlot = document.createElement("div"), this.pluginSlot.className = "beacon-plugin-panels", s.appendChild(this.pluginSlot), this.statusEl = document.createElement("div"), this.statusEl.className = "beacon-status", s.appendChild(this.statusEl);
970
+ const f = document.createElement("div");
971
+ f.className = "beacon-actions", this.submitBtn = document.createElement("button"), this.submitBtn.type = "button", this.submitBtn.className = "beacon-btn primary", this.submitBtn.textContent = t.send, this.submitBtn.addEventListener("click", () => this.callbacks.onSubmit()), f.appendChild(this.submitBtn), s.appendChild(f), this.root.addEventListener("close", () => {
972
+ if (this.expectedSuppressedCloses > 0) {
973
+ this.expectedSuppressedCloses -= 1;
974
+ return;
975
+ }
976
+ this.callbacks.onClose("user");
977
+ });
978
+ }
979
+ // ── Mode handling (§5) ──────────────────────────────────────────
980
+ async requestMode(t) {
981
+ this.modeCounts[t] += 1, this.modeCounts[t] === 1 && this.applyMode(t, !0);
982
+ let n = !1;
983
+ return () => {
984
+ n || (n = !0, this.modeCounts[t] -= 1, this.modeCounts[t] === 0 && this.applyMode(t, !1));
985
+ };
986
+ }
987
+ applyMode(t, n) {
988
+ var o, r;
989
+ switch (t) {
990
+ case "pickElement": {
991
+ n ? (this.lastActive = document.activeElement instanceof HTMLElement ? document.activeElement : null, this.root.open && (this.expectedSuppressedCloses += 1, this.root.close())) : (this.root.open || this.tryShowModal(), (r = (o = this.lastActive) == null ? void 0 : o.focus) == null || r.call(o));
992
+ break;
993
+ }
994
+ case "hide": {
995
+ this.inner.style.visibility = n ? "hidden" : "", this.root.style.opacity = n ? "0" : "";
996
+ break;
997
+ }
998
+ case "minimize": {
999
+ const a = this.inner.querySelector(".beacon-drawer-body");
1000
+ a && (a.style.display = n ? "none" : "");
1001
+ break;
1002
+ }
1003
+ }
1004
+ }
1005
+ // ── Public surface ──────────────────────────────────────────
1006
+ open() {
1007
+ this.root.open || this.tryShowModal();
425
1008
  }
426
- function y(p) {
427
- const b = p.getBoundingClientRect();
428
- i.style.left = `${b.left}px`, i.style.top = `${b.top}px`, i.style.width = `${b.width}px`, i.style.height = `${b.height}px`;
429
- const N = p.tagName.toLowerCase(), I = p.classList.length > 0 ? "." + Array.from(p.classList).slice(0, 2).join(".") : "";
430
- r.textContent = N + I;
431
- const W = b.top - 22;
432
- r.style.left = `${b.left}px`, r.style.top = `${W >= 0 ? W : b.bottom + 4}px`;
1009
+ close(t = "user") {
1010
+ this.root.open && this.root.close(), t === "submitted" && (this.statusEl.textContent = "");
433
1011
  }
434
- function w(p) {
435
- const b = g(p.clientX, p.clientY);
436
- b ? (y(b), n == null || n(b)) : (i.style.display = "none", r.style.display = "none", n == null || n(null));
1012
+ userCloseAttempt() {
1013
+ !this.submitSucceeded && this.hasUnsavedInput() && !window.confirm("You have unsaved feedback. Discard?") || this.root.open && this.root.close();
437
1014
  }
438
- function x(p) {
439
- if (p.button !== 0) return;
440
- p.preventDefault(), p.stopPropagation();
441
- const b = g(p.clientX, p.clientY);
442
- b && f(b);
1015
+ hasUnsavedInput() {
1016
+ return this.descTextarea.value.trim().length > 0;
443
1017
  }
444
- function v(p) {
445
- p.preventDefault(), p.stopPropagation();
1018
+ setSubmitSucceeded(t) {
1019
+ this.submitSucceeded = t;
1020
+ }
1021
+ getDescription() {
1022
+ return this.descTextarea.value;
1023
+ }
1024
+ setDescription(t) {
1025
+ this.descTextarea.value = t;
1026
+ }
1027
+ getSeverity() {
1028
+ return this.severitySelected;
1029
+ }
1030
+ setSeverity(t) {
1031
+ this.severitySelected = t;
1032
+ for (const n of Array.from(this.severitiesContainer.children)) {
1033
+ n.classList.toggle("selected", n.dataset.sev === t);
1034
+ const o = n.querySelector("input");
1035
+ o && (o.checked = n.dataset.sev === t);
1036
+ }
1037
+ }
1038
+ setStatus(t, n = "idle") {
1039
+ this.statusEl.textContent = t, this.statusEl.classList.remove("error", "success"), n !== "idle" && this.statusEl.classList.add(n);
1040
+ }
1041
+ setSubmitting(t) {
1042
+ this.submitBtn.disabled = t, this.submitBtn.textContent = t ? this.labels.sending : this.labels.send;
1043
+ }
1044
+ // Reset drawer state after a successful submit so the next open() starts fresh.
1045
+ resetState() {
1046
+ this.descTextarea.value = "", this.setStatus("", "idle"), this.setSubmitting(!1), this.submitSucceeded = !1, this.severities[0] && this.setSeverity(this.severities[0]);
1047
+ }
1048
+ // ── Plugin panel management ──────────────────────────────────────
1049
+ installPluginPanels(t, n) {
1050
+ this.clearPluginPanels();
1051
+ for (const o of t) {
1052
+ const r = document.createElement("div");
1053
+ if (r.className = "beacon-plugin-panel", o.form.title) {
1054
+ const a = document.createElement("div");
1055
+ a.className = "beacon-plugin-panel-title", a.textContent = o.form.title, r.appendChild(a);
1056
+ }
1057
+ if ("fields" in o.form)
1058
+ rt(r, o.form.fields, {
1059
+ get: (a) => n.get(o.name, a),
1060
+ set: (a, i) => n.set(o.name, a, i)
1061
+ });
1062
+ else {
1063
+ const a = o.form.render(r, o.ctx);
1064
+ typeof a == "function" && this.pluginCleanups.push(a);
1065
+ }
1066
+ this.pluginSlot.appendChild(r);
1067
+ }
446
1068
  }
447
- function h(p) {
448
- p.key === "Escape" && (p.preventDefault(), f(null));
1069
+ clearPluginPanels() {
1070
+ for (const t of this.pluginCleanups)
1071
+ try {
1072
+ t();
1073
+ } catch {
1074
+ }
1075
+ this.pluginCleanups = [], this.pluginSlot.innerHTML = "";
1076
+ }
1077
+ severityLabel(t) {
1078
+ switch (t) {
1079
+ case "bug":
1080
+ return this.labels.severityBug;
1081
+ case "idea":
1082
+ return this.labels.severityIdea;
1083
+ case "ux":
1084
+ return this.labels.severityUx;
1085
+ case "a11y":
1086
+ return this.labels.severityA11y;
1087
+ }
449
1088
  }
450
- function f(p) {
451
- a || (a = !0, document.removeEventListener("mousemove", w, !0), document.removeEventListener("pointerdown", x, !0), document.removeEventListener("click", v, !0), document.removeEventListener("mouseup", v, !0), document.removeEventListener("keydown", h, !0), i.remove(), r.remove(), document.body.style.cursor = l, c(p));
1089
+ tryShowModal() {
1090
+ try {
1091
+ this.root.showModal();
1092
+ } catch {
1093
+ this.root.show();
1094
+ }
452
1095
  }
453
- return document.addEventListener("mousemove", w, !0), document.addEventListener("pointerdown", x, !0), document.addEventListener("click", v, !0), document.addEventListener("mouseup", v, !0), document.addEventListener("keydown", h, !0), {
454
- cancel: () => f(null),
455
- promise: d
1096
+ }
1097
+ function ct() {
1098
+ return {
1099
+ triggerButton: "Feedback",
1100
+ drawerTitle: "Send feedback",
1101
+ closeButton: "Close",
1102
+ send: "Send",
1103
+ sending: "Sending…",
1104
+ sentSuccess: "Sent — thanks!",
1105
+ descriptionLabel: "Description",
1106
+ descriptionPlaceholder: "What happened?",
1107
+ severityLabel: "Severity",
1108
+ severityBug: "bug",
1109
+ severityIdea: "idea",
1110
+ severityUx: "ux",
1111
+ severityA11y: "a11y"
456
1112
  };
457
1113
  }
458
- const Ne = 8;
459
- function Y(t, e = document) {
460
- if (!t) return !1;
1114
+ function lt(e) {
1115
+ const t = document.createElement("div");
1116
+ return t.className = "beacon-overlay-layer", e.appendChild(t), { layer: t };
1117
+ }
1118
+ function dt(e, t) {
1119
+ const n = document.createElement("div");
1120
+ e.layer.appendChild(n);
1121
+ let o;
461
1122
  try {
462
- return e.querySelectorAll(`#${CSS.escape(t)}`).length === 1;
1123
+ o = t(n);
1124
+ } catch (r) {
1125
+ throw n.remove(), r;
1126
+ }
1127
+ return () => {
1128
+ try {
1129
+ o == null || o();
1130
+ } catch {
1131
+ }
1132
+ n.parentNode && n.parentNode.removeChild(n);
1133
+ };
1134
+ }
1135
+ function ut() {
1136
+ var n, o;
1137
+ const e = navigator;
1138
+ return e.userAgentData ? {
1139
+ brand: ((n = e.userAgentData.brands.find((r) => !/Not[.\-]?A.?Brand/i.test(r.brand))) == null ? void 0 : n.brand) ?? ((o = e.userAgentData.brands[0]) == null ? void 0 : o.brand) ?? "unknown",
1140
+ mobile: e.userAgentData.mobile,
1141
+ platform: e.userAgentData.platform
1142
+ } : void 0;
1143
+ }
1144
+ function pt() {
1145
+ return {
1146
+ name: "metadata",
1147
+ capture() {
1148
+ const e = ut();
1149
+ return e ? { uaData: e } : null;
1150
+ }
1151
+ };
1152
+ }
1153
+ const ft = 30, K = 500, ce = 2e3, mt = 500, ht = 5e3, bt = /launch-kit-beacon|beacon\.(?:es|umd|mjs)|\/beacon\//i;
1154
+ function R(e, t) {
1155
+ if (e)
1156
+ return e.length > t ? e.slice(0, t) : e;
1157
+ }
1158
+ function gt(e, t) {
1159
+ const n = (t == null ? void 0 : t.split(`
1160
+ `).slice(0, 3).join("|")) ?? "";
1161
+ return `${e}::${n}`;
1162
+ }
1163
+ function yt(e) {
1164
+ return !!e && bt.test(e);
1165
+ }
1166
+ function vt(e) {
1167
+ try {
1168
+ return JSON.stringify(e).slice(0, K);
1169
+ } catch {
1170
+ return String(e);
1171
+ }
1172
+ }
1173
+ function Ie() {
1174
+ const e = [], t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Set();
1175
+ let o = !1, r, a;
1176
+ function i(s) {
1177
+ if (yt(s.stack) || s.kind === "unhandledrejection" && /AbortError/i.test(s.message)) return;
1178
+ const c = gt(s.message, s.stack), d = t.get(c);
1179
+ if (d !== void 0 && s.ts - d < ht) {
1180
+ t.set(c, s.ts);
1181
+ return;
1182
+ }
1183
+ t.set(c, s.ts), e.push(s), e.length > ft && e.shift();
1184
+ for (const l of n)
1185
+ try {
1186
+ l();
1187
+ } catch {
1188
+ }
1189
+ }
1190
+ return {
1191
+ install() {
1192
+ return o ? () => {
1193
+ } : typeof window > "u" ? () => {
1194
+ } : (o = !0, r = (s) => {
1195
+ try {
1196
+ const c = s.error instanceof Error ? s.error.message : void 0, d = s.error instanceof Error ? s.error.stack : void 0;
1197
+ i({
1198
+ ts: Date.now(),
1199
+ kind: "error",
1200
+ message: R(s.message || c || "Unknown error", K) ?? "Unknown error",
1201
+ ...d ? { stack: R(d, ce) } : {},
1202
+ ...s.filename ? { source: R(s.filename, mt) } : {},
1203
+ ...Number.isFinite(s.lineno) ? { line: s.lineno } : {},
1204
+ ...Number.isFinite(s.colno) ? { col: s.colno } : {}
1205
+ });
1206
+ } catch {
1207
+ }
1208
+ }, a = (s) => {
1209
+ try {
1210
+ const c = s.reason, d = c instanceof Error ? c.message : typeof c == "string" ? c : vt(c), l = c instanceof Error ? c.stack : void 0;
1211
+ i({
1212
+ ts: Date.now(),
1213
+ kind: "unhandledrejection",
1214
+ message: R(d || "Unknown rejection", K) ?? "Unknown rejection",
1215
+ ...l ? { stack: R(l, ce) } : {}
1216
+ });
1217
+ } catch {
1218
+ }
1219
+ }, window.addEventListener("error", r), window.addEventListener("unhandledrejection", a), () => {
1220
+ r && window.removeEventListener("error", r), a && window.removeEventListener("unhandledrejection", a), o = !1, n.clear();
1221
+ });
1222
+ },
1223
+ snapshot() {
1224
+ return e.slice();
1225
+ },
1226
+ subscribe(s) {
1227
+ return n.add(s), () => {
1228
+ n.delete(s);
1229
+ };
1230
+ }
1231
+ };
1232
+ }
1233
+ function xt() {
1234
+ let e = null;
1235
+ return {
1236
+ name: "errors",
1237
+ setupOnce(t) {
1238
+ e = Ie();
1239
+ const n = e.install();
1240
+ return t.signal.addEventListener("abort", n, { once: !0 }), n;
1241
+ },
1242
+ form() {
1243
+ return {
1244
+ render: (t) => {
1245
+ const n = document.createElement("details");
1246
+ n.className = "beacon-events";
1247
+ const o = document.createElement("summary");
1248
+ o.className = "beacon-events-summary";
1249
+ const r = document.createElement("span");
1250
+ r.className = "beacon-events-dot", r.textContent = "●";
1251
+ const a = document.createElement("span");
1252
+ a.className = "beacon-events-label", o.appendChild(r), o.appendChild(a), n.appendChild(o);
1253
+ const i = document.createElement("ul");
1254
+ i.className = "beacon-events-list", n.appendChild(i), t.appendChild(n);
1255
+ function s() {
1256
+ const d = (e == null ? void 0 : e.snapshot()) ?? [], l = d.length;
1257
+ if (l === 0) {
1258
+ t.style.display = "none";
1259
+ return;
1260
+ }
1261
+ t.style.display = "", a.textContent = `${l} runtime error${l !== 1 ? "s" : ""} captured`, i.innerHTML = "";
1262
+ for (const p of d) {
1263
+ const f = document.createElement("li");
1264
+ f.className = "beacon-events-item";
1265
+ const b = document.createElement("span");
1266
+ b.className = `beacon-events-kind ${p.kind === "unhandledrejection" ? "rejection" : "error"}`, b.textContent = p.kind === "unhandledrejection" ? "REJ" : "ERR";
1267
+ const m = document.createElement("span");
1268
+ m.className = "beacon-events-msg", m.textContent = p.message, f.appendChild(b), f.appendChild(m), i.appendChild(f);
1269
+ }
1270
+ }
1271
+ s();
1272
+ const c = e == null ? void 0 : e.subscribe(s);
1273
+ return () => {
1274
+ c == null || c();
1275
+ };
1276
+ }
1277
+ };
1278
+ },
1279
+ capture() {
1280
+ const t = (e == null ? void 0 : e.snapshot()) ?? [];
1281
+ return t.length === 0 ? null : { events: t };
1282
+ }
1283
+ };
1284
+ }
1285
+ const wt = 8;
1286
+ function le(e, t = document) {
1287
+ if (!e) return !1;
1288
+ try {
1289
+ return t.querySelectorAll(`#${CSS.escape(e)}`).length === 1;
463
1290
  } catch {
464
1291
  return !1;
465
1292
  }
466
1293
  }
467
- function Re(t) {
468
- const e = t.tagName.toLowerCase(), n = Array.from(t.classList).filter((o) => o.length > 0 && o.length < 40).slice(0, 3).map((o) => `.${CSS.escape(o)}`).join("");
469
- return e + n;
470
- }
471
- function Pe(t) {
472
- const e = t.parentElement;
473
- return e ? Array.from(e.children).filter((o) => o.tagName === t.tagName).indexOf(t) + 1 : 1;
474
- }
475
- function De(t) {
476
- if (!t || t.nodeType !== Node.ELEMENT_NODE) return "";
477
- if (t.id && Y(t.id))
478
- return `#${CSS.escape(t.id)}`;
479
- const e = [];
480
- let n = t, o = 0;
481
- for (; n && n.tagName.toLowerCase() !== "body" && o < Ne; ) {
482
- const s = n;
483
- if (s.id && Y(s.id)) {
484
- e.unshift(`#${CSS.escape(s.id)}`);
1294
+ function Et(e) {
1295
+ const t = e.tagName.toLowerCase(), n = Array.from(e.classList).filter((o) => o.length > 0 && o.length < 40).slice(0, 3).map((o) => `.${CSS.escape(o)}`).join("");
1296
+ return t + n;
1297
+ }
1298
+ function St(e) {
1299
+ const t = e.parentElement;
1300
+ return t ? Array.from(t.children).filter((o) => o.tagName === e.tagName).indexOf(e) + 1 : 1;
1301
+ }
1302
+ function Ct(e) {
1303
+ if (!e || e.nodeType !== Node.ELEMENT_NODE) return "";
1304
+ if (e.id && le(e.id))
1305
+ return `#${CSS.escape(e.id)}`;
1306
+ const t = [];
1307
+ let n = e, o = 0;
1308
+ for (; n && n.tagName.toLowerCase() !== "body" && o < wt; ) {
1309
+ const r = n;
1310
+ if (r.id && le(r.id)) {
1311
+ t.unshift(`#${CSS.escape(r.id)}`);
485
1312
  break;
486
1313
  }
487
- const i = Re(s), r = s.parentElement;
488
- let l = i;
489
- if (r)
1314
+ const a = Et(r), i = r.parentElement;
1315
+ let s = a;
1316
+ if (i)
490
1317
  try {
491
- const a = Array.from(s.classList).join(" ");
492
- Array.from(r.children).filter(
493
- (d) => d.tagName === s.tagName && Array.from(d.classList).join(" ") === a
494
- ).length > 1 && (l = `${s.tagName.toLowerCase()}:nth-of-type(${Pe(s)})`);
1318
+ const c = Array.from(r.classList).join(" ");
1319
+ Array.from(i.children).filter(
1320
+ (l) => l.tagName === r.tagName && Array.from(l.classList).join(" ") === c
1321
+ ).length > 1 && (s = `${r.tagName.toLowerCase()}:nth-of-type(${St(r)})`);
495
1322
  } catch {
496
1323
  }
497
- e.unshift(l), n = r, o++;
1324
+ t.unshift(s), n = i, o++;
498
1325
  }
499
- return e.join(" > ");
1326
+ return t.join(" > ");
500
1327
  }
501
- function Be(t) {
502
- const e = Object.keys(t).filter((o) => o.startsWith("__reactFiber$") || o.startsWith("__reactInternalInstance$"));
503
- if (e.length === 0) return null;
504
- let n = t[e[0]];
1328
+ function kt(e) {
1329
+ const t = Object.keys(e).filter(
1330
+ (o) => o.startsWith("__reactFiber$") || o.startsWith("__reactInternalInstance$")
1331
+ );
1332
+ if (t.length === 0) return null;
1333
+ let n = e[t[0]];
505
1334
  for (let o = 0; o < 10 && n; o++) {
506
- const s = n, i = s.type;
507
- if (typeof i == "function") {
508
- const r = i.displayName ?? i.name;
509
- if (r && r !== "_default") return { lib: "react", name: r };
1335
+ const r = n, a = r.type;
1336
+ if (typeof a == "function") {
1337
+ const i = a.displayName ?? a.name;
1338
+ if (i && i !== "_default") return { lib: "react", name: i };
510
1339
  }
511
- if (typeof i == "object" && i !== null) {
512
- const r = i.displayName ?? i.name;
513
- if (r) return { lib: "react", name: r };
1340
+ if (typeof a == "object" && a !== null) {
1341
+ const i = a.displayName ?? a.name;
1342
+ if (i) return { lib: "react", name: i };
514
1343
  }
515
- n = s.return;
1344
+ n = r.return;
516
1345
  }
517
1346
  return { lib: "react" };
518
1347
  }
519
- function je(t) {
520
- var o, s;
521
- const e = t, n = e.__vueParentComponent;
1348
+ function At(e) {
1349
+ var o, r;
1350
+ const t = e, n = t.__vueParentComponent;
522
1351
  if (n) {
523
- const i = ((o = n.type) == null ? void 0 : o.name) ?? ((s = n.type) == null ? void 0 : s.__name);
524
- return { lib: "vue", ...i ? { name: i } : {} };
1352
+ const a = ((o = n.type) == null ? void 0 : o.name) ?? ((r = n.type) == null ? void 0 : r.__name);
1353
+ return { lib: "vue", ...a ? { name: a } : {} };
525
1354
  }
526
- return e.__vue__ ? { lib: "vue" } : null;
1355
+ return t.__vue__ ? { lib: "vue" } : null;
527
1356
  }
528
- function Oe(t) {
529
- const e = window.ng;
530
- if (!(e != null && e.getComponent)) return null;
1357
+ function Lt(e) {
1358
+ const t = window.ng;
1359
+ if (!(t != null && t.getComponent)) return null;
531
1360
  try {
532
- const n = e.getComponent(t);
1361
+ const n = t.getComponent(e);
533
1362
  if (!n) return null;
534
1363
  const o = n.constructor;
535
1364
  return { lib: "angular", ...o != null && o.name ? { name: o.name } : {} };
@@ -537,13 +1366,13 @@ function Oe(t) {
537
1366
  return null;
538
1367
  }
539
1368
  }
540
- function ze(t) {
541
- return "__svelte_meta" in t ? { lib: "svelte" } : null;
1369
+ function Nt(e) {
1370
+ return "__svelte_meta" in e ? { lib: "svelte" } : null;
542
1371
  }
543
- function G(t) {
544
- return Be(t) ?? je(t) ?? Oe(t) ?? ze(t) ?? void 0;
1372
+ function Tt(e) {
1373
+ return kt(e) ?? At(e) ?? Lt(e) ?? Nt(e) ?? void 0;
545
1374
  }
546
- const Ue = 5e3, He = 1e3, J = 1e3, Z = 200, qe = 50, Q = 200, Fe = 500, We = [
1375
+ const Mt = 5e3, It = 1e3, de = 1e3, ue = 200, Rt = 50, pe = 200, _t = 500, Pt = [
547
1376
  "display",
548
1377
  "position",
549
1378
  "top",
@@ -582,666 +1411,823 @@ const Ue = 5e3, He = 1e3, J = 1e3, Z = 200, qe = 50, Q = 200, Fe = 500, We = [
582
1411
  "grid-template-columns",
583
1412
  "grid-template-rows"
584
1413
  ];
585
- function ee(t, e) {
586
- return t.length <= e ? t : t.slice(0, e) + `
1414
+ function fe(e, t) {
1415
+ return e.length <= t ? e : e.slice(0, t) + `
587
1416
 
588
- /* … truncated, original was ${t.length} chars */`;
1417
+ /* … truncated, original was ${e.length} chars */`;
589
1418
  }
590
- function Ve(t) {
591
- const e = getComputedStyle(t), n = {};
592
- for (const o of We) {
593
- const s = e.getPropertyValue(o);
594
- s && s !== "normal" && s !== "none" && s !== "auto" && s !== "0px" && (n[o] = s.trim().slice(0, Fe));
1419
+ function Dt(e) {
1420
+ const t = getComputedStyle(e), n = {};
1421
+ for (const o of Pt) {
1422
+ const r = t.getPropertyValue(o);
1423
+ r && r !== "normal" && r !== "none" && r !== "auto" && r !== "0px" && (n[o] = r.trim().slice(0, _t));
595
1424
  }
596
1425
  return n;
597
1426
  }
598
- function Ke(t) {
599
- return Array.from(t.classList).slice(0, qe).map((n) => n.length > Q ? n.slice(0, Q) : n);
1427
+ function $t(e) {
1428
+ return Array.from(e.classList).slice(0, Rt).map((t) => t.length > pe ? t.slice(0, pe) : t);
600
1429
  }
601
- function Xe(t) {
602
- const e = t.getBoundingClientRect(), n = De(t), o = t.id || null;
1430
+ function Bt(e) {
1431
+ const t = e.getBoundingClientRect(), n = Ct(e), o = e.id || null, r = Tt(e);
603
1432
  return {
604
- selector: n.length > J ? n.slice(0, J) : n,
605
- tagName: t.tagName.toLowerCase(),
606
- id: o && o.length > Z ? o.slice(0, Z) : o,
607
- classList: Ke(t),
608
- outerHTML: ee(t.outerHTML, Ue),
609
- ...t.parentElement ? { parentOuterHTML: ee(t.parentElement.outerHTML, He) } : {},
610
- computedStyles: Ve(t),
1433
+ selector: n.length > de ? n.slice(0, de) : n,
1434
+ tagName: e.tagName.toLowerCase(),
1435
+ id: o && o.length > ue ? o.slice(0, ue) : o,
1436
+ classList: $t(e),
1437
+ outerHTML: fe(e.outerHTML, Mt),
1438
+ ...e.parentElement ? { parentOuterHTML: fe(e.parentElement.outerHTML, It) } : {},
1439
+ computedStyles: Dt(e),
611
1440
  boundingRect: {
612
- x: Math.round(e.x),
613
- y: Math.round(e.y),
614
- w: Math.round(e.width),
615
- h: Math.round(e.height)
1441
+ x: Math.round(t.x),
1442
+ y: Math.round(t.y),
1443
+ w: Math.round(t.width),
1444
+ h: Math.round(t.height)
616
1445
  },
617
- ...G(t) ? { framework: G(t) } : {}
1446
+ ...r ? { framework: r } : {}
618
1447
  };
619
1448
  }
620
- function te() {
621
- var n, o;
622
- const t = navigator;
623
- return t.userAgentData ? {
624
- brand: ((n = t.userAgentData.brands.find((s) => !/Not[.\-]?A.?Brand/i.test(s.brand))) == null ? void 0 : n.brand) ?? ((o = t.userAgentData.brands[0]) == null ? void 0 : o.brand) ?? "unknown",
625
- mobile: t.userAgentData.mobile,
626
- platform: t.userAgentData.platform
627
- } : void 0;
1449
+ const zt = 14, Ot = "#ffffff", Ht = "#ffffff", qt = 3, Ut = "#0ea5e9";
1450
+ async function Re(e, t, n, o = Ut) {
1451
+ const r = await jt(e), a = document.createElement("canvas");
1452
+ a.width = r.naturalWidth, a.height = r.naturalHeight;
1453
+ const i = a.getContext("2d");
1454
+ if (!i) throw new Error("Could not get 2D canvas context");
1455
+ i.drawImage(r, 0, 0);
1456
+ const s = a.width / n.w, c = a.height / n.h;
1457
+ for (const d of t) {
1458
+ const l = Ft(d);
1459
+ if (!l) continue;
1460
+ const p = l.x * s, f = l.y * c, b = l.w * s, m = l.h * c;
1461
+ i.lineWidth = qt, i.strokeStyle = o, i.strokeRect(p, f, b, m);
1462
+ const x = p + b, g = f;
1463
+ i.beginPath(), i.fillStyle = o, i.arc(x, g, zt, 0, Math.PI * 2), i.fill(), i.lineWidth = 3, i.strokeStyle = Ot, i.stroke(), i.fillStyle = Ht, i.font = "bold 16px system-ui, -apple-system, sans-serif", i.textAlign = "center", i.textBaseline = "middle", i.fillText(String(d.number), x, g + 1);
1464
+ }
1465
+ return a.toDataURL("image/jpeg", 0.85);
1466
+ }
1467
+ function Ft(e) {
1468
+ if (e.liveElement && document.contains(e.liveElement)) {
1469
+ const t = e.liveElement.getBoundingClientRect();
1470
+ if (t.width > 0 || t.height > 0)
1471
+ return { x: t.left, y: t.top, w: t.width, h: t.height };
1472
+ }
1473
+ if (e.selector)
1474
+ try {
1475
+ const t = document.querySelector(e.selector);
1476
+ if (t) {
1477
+ const n = t.getBoundingClientRect();
1478
+ if (n.width > 0 || n.height > 0)
1479
+ return { x: n.left, y: n.top, w: n.width, h: n.height };
1480
+ }
1481
+ } catch {
1482
+ }
1483
+ return e.boundingRect;
628
1484
  }
629
- function ne() {
630
- if (window.matchMedia("(prefers-color-scheme: dark)").matches) return "dark";
631
- if (window.matchMedia("(prefers-color-scheme: light)").matches) return "light";
1485
+ function jt(e) {
1486
+ return new Promise((t, n) => {
1487
+ const o = new Image();
1488
+ o.onload = () => t(o), o.onerror = (r) => n(r), o.src = e;
1489
+ });
632
1490
  }
633
- function oe() {
634
- return {
635
- url: window.location.href,
636
- ...document.referrer ? { referrer: document.referrer } : {},
637
- userAgent: navigator.userAgent,
638
- ...te() ? { uaData: te() } : {},
639
- viewport: {
640
- w: window.innerWidth,
641
- h: window.innerHeight,
642
- dpr: window.devicePixelRatio || 1
1491
+ const _ = "beacon-no-capture", Vt = "#0ea5e9", me = "Click any element to pin it · Press Esc to finish";
1492
+ function he(e, t) {
1493
+ return /^#[0-9a-fA-F]{6}$/.test(e) ? `${e}${t}` : e;
1494
+ }
1495
+ function Wt(e = {}) {
1496
+ const t = e.accent ?? Vt, n = he(t, "b3"), o = he(t, "2e"), r = document.createElement("style");
1497
+ r.className = _, r.textContent = "@keyframes beacon-spin { to { transform: rotate(360deg); } }", document.head.appendChild(r);
1498
+ const a = document.createElement("div");
1499
+ a.className = _, a.setAttribute("aria-hidden", "true"), a.style.cssText = [
1500
+ "position: fixed",
1501
+ "inset: 0",
1502
+ "pointer-events: none",
1503
+ "z-index: 2147483646",
1504
+ `border: 2px dashed ${n}`,
1505
+ "border-radius: 4px",
1506
+ `box-shadow: inset 0 0 56px ${o}`,
1507
+ "box-sizing: border-box"
1508
+ ].join("; ");
1509
+ const i = document.createElement("div");
1510
+ i.className = _, i.setAttribute("role", "status"), i.style.cssText = [
1511
+ "position: fixed",
1512
+ "top: 16px",
1513
+ "left: 50%",
1514
+ "transform: translateX(-50%)",
1515
+ `background: ${t}`,
1516
+ "color: #fff",
1517
+ "padding: 6px 14px",
1518
+ "border-radius: 999px",
1519
+ "font: 500 12px/1.4 system-ui, -apple-system, sans-serif",
1520
+ "letter-spacing: 0.01em",
1521
+ "box-shadow: 0 4px 12px hsl(0 0% 0% / 0.3)",
1522
+ "pointer-events: none",
1523
+ "white-space: nowrap",
1524
+ "z-index: 2147483646"
1525
+ ].join("; "), i.textContent = me;
1526
+ const s = `<span style="
1527
+ display: inline-block;
1528
+ width: 12px;
1529
+ height: 12px;
1530
+ border: 2px solid #fff;
1531
+ border-top-color: transparent;
1532
+ border-radius: 50%;
1533
+ animation: beacon-spin 800ms linear infinite;
1534
+ vertical-align: middle;
1535
+ margin-right: 8px;
1536
+ "></span>`;
1537
+ function c(u) {
1538
+ return u.replace(/[<>&]/g, (y) => ({ "<": "&lt;", ">": "&gt;", "&": "&amp;" })[y]);
1539
+ }
1540
+ document.body.appendChild(a), document.body.appendChild(i);
1541
+ const d = /* @__PURE__ */ new Map();
1542
+ function l(u) {
1543
+ const y = document.createElement("div");
1544
+ return y.className = _, y.setAttribute("aria-hidden", "true"), y.style.cssText = [
1545
+ "position: fixed",
1546
+ "width: 24px",
1547
+ "height: 24px",
1548
+ "border-radius: 999px",
1549
+ `background: ${t}`,
1550
+ "color: #fff",
1551
+ "display: flex",
1552
+ "align-items: center",
1553
+ "justify-content: center",
1554
+ "font: 700 12px/1 system-ui, -apple-system, sans-serif",
1555
+ "border: 2px solid #fff",
1556
+ "box-shadow: 0 2px 8px hsl(0 0% 0% / 0.4)",
1557
+ "pointer-events: none",
1558
+ "z-index: 2147483646"
1559
+ ].join("; "), y.textContent = String(u), document.body.appendChild(y), y;
1560
+ }
1561
+ function p() {
1562
+ const u = document.createElement("div");
1563
+ return u.className = _, u.setAttribute("aria-hidden", "true"), u.style.cssText = [
1564
+ "position: fixed",
1565
+ "pointer-events: none",
1566
+ `border: 2px solid ${t}`,
1567
+ "border-radius: 2px",
1568
+ "box-sizing: border-box",
1569
+ "z-index: 2147483645"
1570
+ ].join("; "), document.body.appendChild(u), u;
1571
+ }
1572
+ function f(u, y, h) {
1573
+ const v = h ? "0.5" : "1";
1574
+ u.outline.style.display = "block", u.outline.style.opacity = v, u.outline.style.left = `${y.x}px`, u.outline.style.top = `${y.y}px`, u.outline.style.width = `${y.w}px`, u.outline.style.height = `${y.h}px`, u.marker.style.display = "flex", u.marker.style.opacity = v, u.marker.style.left = `${y.x + y.w - 12}px`, u.marker.style.top = `${Math.max(2, y.y - 12)}px`;
1575
+ }
1576
+ function b(u) {
1577
+ u.marker.style.display = "none", u.outline.style.display = "none";
1578
+ }
1579
+ function m() {
1580
+ d.forEach((u) => {
1581
+ let y = u.anchor.target;
1582
+ if (document.contains(y) || (y = null), !y && u.anchor.selector && (y = document.querySelector(u.anchor.selector), y && (u.anchor.target = y)), y) {
1583
+ const v = y.getBoundingClientRect();
1584
+ if (v.width > 0 || v.height > 0) {
1585
+ f(u, { x: v.left, y: v.top, w: v.width, h: v.height }, !1);
1586
+ return;
1587
+ }
1588
+ }
1589
+ const h = u.anchor.fallbackRect;
1590
+ if (h && (h.w > 0 || h.h > 0)) {
1591
+ f(u, h, !0);
1592
+ return;
1593
+ }
1594
+ b(u);
1595
+ });
1596
+ }
1597
+ let x = null;
1598
+ function g() {
1599
+ x === null && (x = requestAnimationFrame(() => {
1600
+ x = null, m();
1601
+ }));
1602
+ }
1603
+ return window.addEventListener("scroll", g, !0), window.addEventListener("resize", g), {
1604
+ addPin(u, y) {
1605
+ const h = l(u), v = p();
1606
+ d.set(u, { anchor: y, marker: h, outline: v }), m();
643
1607
  },
644
- screen: {
645
- w: window.screen.width,
646
- h: window.screen.height
1608
+ setLoading(u) {
1609
+ u ? i.innerHTML = s + c(u) : i.textContent = me;
647
1610
  },
648
- timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
649
- locale: navigator.language,
650
- ...ne() ? { theme: ne() } : {},
651
- capturedAt: (/* @__PURE__ */ new Date()).toISOString()
1611
+ destroy() {
1612
+ window.removeEventListener("scroll", g, !0), window.removeEventListener("resize", g), x !== null && cancelAnimationFrame(x), a.remove(), i.remove(), r.remove(), d.forEach(({ marker: u, outline: y }) => {
1613
+ u.remove(), y.remove();
1614
+ }), d.clear();
1615
+ }
1616
+ };
1617
+ }
1618
+ const Yt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>', Kt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>';
1619
+ function Xt(e) {
1620
+ return new Promise((t) => {
1621
+ const n = document.createElement("div");
1622
+ n.className = "beacon-pin-popover open beacon-no-capture beacon-theme-auto", n.innerHTML = `
1623
+ <div class="beacon-pin-popover-header">
1624
+ <div style="display:flex;align-items:center;gap:6px;font-weight:600;font-size:13px;">
1625
+ <span class="beacon-pin-num">${e.pinNumber}</span>
1626
+ <span>Note for this pin</span>
1627
+ </div>
1628
+ <button type="button" class="beacon-icon-btn" data-action="cancel" aria-label="Discard this pin">${Yt}</button>
1629
+ </div>
1630
+ <textarea class="beacon-textarea" rows="2" placeholder="Optional — describe what's wrong here…" style="min-height:48px;"></textarea>
1631
+ <div class="beacon-pin-popover-actions">
1632
+ <button type="button" class="beacon-btn primary" data-action="save">${Kt} Save</button>
1633
+ </div>
1634
+ `;
1635
+ const o = 240, r = 160, a = Math.min(Math.max(8, e.anchor.x), window.innerWidth - o - 8), i = Math.min(Math.max(8, e.anchor.y + 12), window.innerHeight - r - 8);
1636
+ n.style.left = `${a}px`, n.style.top = `${i}px`, document.body.appendChild(n);
1637
+ const s = n.querySelector("textarea");
1638
+ s.focus();
1639
+ function c(l) {
1640
+ document.removeEventListener("keydown", d, !0), n.remove(), t(l);
1641
+ }
1642
+ function d(l) {
1643
+ l.key === "Escape" && (l.preventDefault(), l.stopPropagation(), c({ cancelled: "all" }));
1644
+ }
1645
+ document.addEventListener("keydown", d, !0), n.addEventListener("click", (l) => {
1646
+ var b;
1647
+ const f = (b = l.target.closest("[data-action]")) == null ? void 0 : b.getAttribute("data-action");
1648
+ if (f === "cancel" && c({ cancelled: "pin" }), f === "save") {
1649
+ const m = s.value.trim();
1650
+ c({ ...m ? { note: m } : {}, cancelled: !1 });
1651
+ }
1652
+ }), s.addEventListener("keydown", (l) => {
1653
+ if (l.key === "Enter" && (l.metaKey || l.ctrlKey)) {
1654
+ l.preventDefault();
1655
+ const p = s.value.trim();
1656
+ c({ ...p ? { note: p } : {}, cancelled: !1 });
1657
+ }
1658
+ });
1659
+ });
1660
+ }
1661
+ const Gt = "#0ea5e9";
1662
+ function Jt(e, t) {
1663
+ return /^#[0-9a-fA-F]{6}$/.test(e) ? `${e}${t}` : e;
1664
+ }
1665
+ function Zt(e) {
1666
+ const { shadowRoot: t, onHover: n } = e, o = e.accent ?? Gt, r = Jt(o, "14"), a = document.createElement("div");
1667
+ a.style.cssText = [
1668
+ "position: fixed",
1669
+ "pointer-events: none",
1670
+ "z-index: 2147483646",
1671
+ `border: 2px solid ${o}`,
1672
+ `background: ${r}`,
1673
+ "transition: all 60ms ease-out",
1674
+ "box-sizing: border-box",
1675
+ "border-radius: 2px"
1676
+ ].join("; "), document.body.appendChild(a);
1677
+ const i = document.createElement("div");
1678
+ i.style.cssText = [
1679
+ "position: fixed",
1680
+ "pointer-events: none",
1681
+ "z-index: 2147483647",
1682
+ "background: #0f172a",
1683
+ "color: #fff",
1684
+ "font: 11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace",
1685
+ "padding: 3px 6px",
1686
+ "border-radius: 3px",
1687
+ "max-width: 280px",
1688
+ "overflow: hidden",
1689
+ "text-overflow: ellipsis",
1690
+ "white-space: nowrap"
1691
+ ].join("; "), document.body.appendChild(i);
1692
+ const s = document.body.style.cursor;
1693
+ document.body.style.cursor = "crosshair";
1694
+ let c = !1, d = () => {
1695
+ };
1696
+ const l = new Promise((h) => {
1697
+ d = h;
1698
+ });
1699
+ function p(h) {
1700
+ if (!h || !(h instanceof Node)) return !1;
1701
+ let v = h;
1702
+ for (; v; ) {
1703
+ if (v === t || v === t.host) return !0;
1704
+ v = v.parentNode ?? v.host ?? null;
1705
+ }
1706
+ return !1;
1707
+ }
1708
+ function f(h, v) {
1709
+ a.style.display = "none", i.style.display = "none";
1710
+ const C = document.elementsFromPoint(h, v);
1711
+ a.style.display = "block", i.style.display = "block";
1712
+ for (const S of C)
1713
+ if (!p(S)) return S;
1714
+ return null;
1715
+ }
1716
+ function b(h) {
1717
+ const v = h.getBoundingClientRect();
1718
+ a.style.left = `${v.left}px`, a.style.top = `${v.top}px`, a.style.width = `${v.width}px`, a.style.height = `${v.height}px`;
1719
+ const C = h.tagName.toLowerCase(), S = h.classList.length > 0 ? "." + Array.from(h.classList).slice(0, 2).join(".") : "";
1720
+ i.textContent = C + S;
1721
+ const L = v.top - 22;
1722
+ i.style.left = `${v.left}px`, i.style.top = `${L >= 0 ? L : v.bottom + 4}px`;
1723
+ }
1724
+ function m(h) {
1725
+ const v = f(h.clientX, h.clientY);
1726
+ v ? (b(v), n == null || n(v)) : (a.style.display = "none", i.style.display = "none", n == null || n(null));
1727
+ }
1728
+ function x(h) {
1729
+ if (h.button !== 0) return;
1730
+ h.preventDefault(), h.stopPropagation();
1731
+ const v = f(h.clientX, h.clientY);
1732
+ v && y(v);
1733
+ }
1734
+ function g(h) {
1735
+ h.preventDefault(), h.stopPropagation();
1736
+ }
1737
+ function u(h) {
1738
+ h.key === "Escape" && (h.preventDefault(), y(null));
1739
+ }
1740
+ function y(h) {
1741
+ c || (c = !0, document.removeEventListener("mousemove", m, !0), document.removeEventListener("pointerdown", x, !0), document.removeEventListener("click", g, !0), document.removeEventListener("mouseup", g, !0), document.removeEventListener("keydown", u, !0), a.remove(), i.remove(), document.body.style.cursor = s, d(h));
1742
+ }
1743
+ return document.addEventListener("mousemove", m, !0), document.addEventListener("pointerdown", x, !0), document.addEventListener("click", g, !0), document.addEventListener("mouseup", g, !0), document.addEventListener("keydown", u, !0), {
1744
+ cancel: () => y(null),
1745
+ promise: l
652
1746
  };
653
1747
  }
654
- let R = null;
655
- async function Ye() {
656
- return R || (R = await import("./index-DAIDnjfR.mjs")), R;
1748
+ let Y = null;
1749
+ async function Qt() {
1750
+ return Y || (Y = await import("./index-DAIDnjfR.mjs")), Y;
657
1751
  }
658
- const _ = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkAAIAAAoAAv/lxKUAAAAASUVORK5CYII=";
659
- function se(t, e) {
660
- if (!t || t.startsWith("data:") || t.startsWith("blob:") || t.startsWith("/") || t.startsWith("#")) return !0;
1752
+ const q = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkAAIAAAoAAv/lxKUAAAAASUVORK5CYII=";
1753
+ function be(e, t) {
1754
+ if (!e || e.startsWith("data:") || e.startsWith("blob:") || e.startsWith("/") || e.startsWith("#")) return !0;
661
1755
  try {
662
- if (new URL(t, window.location.href).origin === window.location.origin) return !0;
1756
+ if (new URL(e, window.location.href).origin === window.location.origin) return !0;
663
1757
  } catch {
664
1758
  return !1;
665
1759
  }
666
- return e === "anonymous" || e === "use-credentials";
1760
+ return t === "anonymous" || t === "use-credentials";
667
1761
  }
668
- function Ge() {
669
- const t = [], e = [];
1762
+ function en() {
1763
+ const e = [], t = [];
670
1764
  return document.querySelectorAll("img").forEach((n) => {
671
- se(n.src, n.crossOrigin) || (t.push({ el: n, src: n.src }), n.src = _);
1765
+ be(n.src, n.crossOrigin) || (e.push({ el: n, src: n.src }), n.src = q);
672
1766
  }), document.querySelectorAll("image").forEach((n) => {
673
- const o = n, s = o.getAttribute("href"), i = o.getAttributeNS("http://www.w3.org/1999/xlink", "href"), r = s || i || "";
674
- r && !se(r) && (e.push({ el: o, href: s, xlink: i }), s !== null && o.setAttribute("href", _), i !== null && o.setAttributeNS("http://www.w3.org/1999/xlink", "href", _));
1767
+ const o = n, r = o.getAttribute("href"), a = o.getAttributeNS("http://www.w3.org/1999/xlink", "href"), i = r || a || "";
1768
+ i && !be(i) && (t.push({ el: o, href: r, xlink: a }), r !== null && o.setAttribute("href", q), a !== null && o.setAttributeNS("http://www.w3.org/1999/xlink", "href", q));
675
1769
  }), () => {
676
- for (const { el: n, src: o } of t)
677
- n.src = o;
678
- for (const { el: n, href: o, xlink: s } of e)
679
- o !== null && n.setAttribute("href", o), s !== null && n.setAttributeNS("http://www.w3.org/1999/xlink", "href", s);
1770
+ for (const { el: n, src: o } of e) n.src = o;
1771
+ for (const { el: n, href: o, xlink: r } of t)
1772
+ o !== null && n.setAttribute("href", o), r !== null && n.setAttributeNS("http://www.w3.org/1999/xlink", "href", r);
680
1773
  };
681
1774
  }
682
- async function ie(t = {}) {
683
- const { quality: e = 0.7, pixelRatio: n = Math.min(window.devicePixelRatio || 1, 2), excludeShadowRoot: o } = t, s = await Ye(), i = o ? (l) => {
684
- let a = l;
685
- for (; a; ) {
686
- if (a === o.host || a instanceof Element && a.classList.contains("beacon-no-capture")) return !1;
687
- a = a.parentNode;
1775
+ async function _e(e = {}) {
1776
+ const {
1777
+ quality: t = 0.7,
1778
+ pixelRatio: n = Math.min(window.devicePixelRatio || 1, 2),
1779
+ excludeShadowRoot: o,
1780
+ excludeHosts: r
1781
+ } = e, a = await Qt(), i = o || r != null && r.length ? (c) => {
1782
+ let d = c;
1783
+ for (; d; ) {
1784
+ if (o && d === o.host || r && d instanceof Element && r.includes(d) || d instanceof Element && d.classList.contains("beacon-no-capture")) return !1;
1785
+ d = d.parentNode;
688
1786
  }
689
1787
  return !0;
690
- } : void 0, r = Ge();
1788
+ } : void 0, s = en();
691
1789
  try {
692
- return await s.toJpeg(document.documentElement, {
693
- quality: e,
1790
+ return await a.toJpeg(document.documentElement, {
1791
+ quality: t,
694
1792
  pixelRatio: n,
695
1793
  cacheBust: !0,
696
1794
  ...i ? { filter: i } : {},
697
- imagePlaceholder: _,
698
- // Cap dimensions to viewport so we don't accidentally capture full document height.
1795
+ imagePlaceholder: q,
699
1796
  width: window.innerWidth,
700
1797
  height: window.innerHeight,
701
- style: {
702
- // Avoid scrolling artifacts.
703
- transform: "none"
704
- }
1798
+ style: { transform: "none" }
705
1799
  });
706
1800
  } finally {
707
- r();
708
- }
709
- }
710
- const Je = 14, Ze = "#ffffff", Qe = "#ffffff", et = 3, tt = "#0ea5e9";
711
- async function re(t, e, n, o, s = tt) {
712
- const i = s, r = s, l = await ot(t), a = document.createElement("canvas");
713
- a.width = l.naturalWidth, a.height = l.naturalHeight;
714
- const c = a.getContext("2d");
715
- if (!c) throw new Error("Could not get 2D canvas context");
716
- c.drawImage(l, 0, 0);
717
- const d = a.width / n.w, u = a.height / n.h;
718
- for (const g of e) {
719
- const y = nt(g, o);
720
- if (!y) continue;
721
- const w = y.x * d, x = y.y * u, v = y.w * d, h = y.h * u;
722
- c.lineWidth = et, c.strokeStyle = r, c.strokeRect(w, x, v, h);
723
- const f = w + v, p = x;
724
- c.beginPath(), c.fillStyle = i, c.arc(f, p, Je, 0, Math.PI * 2), c.fill(), c.lineWidth = 3, c.strokeStyle = Ze, c.stroke(), c.fillStyle = Qe, c.font = "bold 16px system-ui, -apple-system, sans-serif", c.textAlign = "center", c.textBaseline = "middle", c.fillText(String(g.number), f, p + 1);
725
- }
726
- return a.toDataURL("image/jpeg", 0.85);
727
- }
728
- function nt(t, e) {
729
- const n = e == null ? void 0 : e.get(t);
730
- if (n && document.contains(n)) {
731
- const o = n.getBoundingClientRect();
732
- if (o.width > 0 || o.height > 0)
733
- return { x: o.left, y: o.top, w: o.width, h: o.height };
734
- }
735
- if (t.selector)
1801
+ s();
1802
+ }
1803
+ }
1804
+ let Q = null;
1805
+ function tn(e) {
1806
+ Q = e;
1807
+ }
1808
+ function nn() {
1809
+ return Q;
1810
+ }
1811
+ function D() {
1812
+ Q = null;
1813
+ }
1814
+ const ge = "http://www.w3.org/2000/svg";
1815
+ function on() {
1816
+ const e = document.createElementNS(ge, "svg");
1817
+ e.setAttribute("viewBox", "0 0 24 24"), e.setAttribute("fill", "none"), e.setAttribute("stroke", "currentColor"), e.setAttribute("stroke-width", "2"), e.setAttribute("stroke-linecap", "round"), e.setAttribute("stroke-linejoin", "round"), e.setAttribute("aria-hidden", "true");
1818
+ const t = [
1819
+ "M3 6h18",
1820
+ "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",
1821
+ "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"
1822
+ ];
1823
+ for (const n of t) {
1824
+ const o = document.createElementNS(ge, "path");
1825
+ o.setAttribute("d", n), e.appendChild(o);
1826
+ }
1827
+ return e;
1828
+ }
1829
+ function rn(e = {}) {
1830
+ const t = e.maxPins ?? 20;
1831
+ let n = [], o = /* @__PURE__ */ new WeakMap(), r = null, a = null, i = null, s = null, c = null;
1832
+ function d() {
1833
+ n = [], o = /* @__PURE__ */ new WeakMap(), r = null, D(), m(), x();
1834
+ }
1835
+ function l() {
1836
+ const g = document.querySelector("launch-kit-beacon");
1837
+ return (g == null ? void 0 : g.shadowRoot) ?? null;
1838
+ }
1839
+ function p() {
1840
+ if (typeof window > "u") return e.accent ?? "#0ea5e9";
1841
+ if (e.accent) return e.accent;
1842
+ const g = document.querySelector("launch-kit-beacon");
1843
+ return g && getComputedStyle(g).getPropertyValue("--beacon-accent").trim() || "#0ea5e9";
1844
+ }
1845
+ async function f(g) {
1846
+ const u = l();
1847
+ if (!u) return;
1848
+ const y = p(), h = await g.requestMode("pickElement"), v = Wt({ accent: y });
1849
+ for (const C of n) {
1850
+ const S = o.get(C);
1851
+ S && v.addPin(C.number, {
1852
+ target: S,
1853
+ selector: C.selector,
1854
+ fallbackRect: C.boundingRect
1855
+ });
1856
+ }
736
1857
  try {
737
- const o = document.querySelector(t.selector);
738
- if (o) {
739
- const s = o.getBoundingClientRect();
740
- if (s.width > 0 || s.height > 0)
741
- return { x: s.left, y: s.top, w: s.width, h: s.height };
1858
+ let C = !0;
1859
+ for (; C && !(n.length >= t); ) {
1860
+ const L = await Zt({ shadowRoot: u, accent: y }).promise;
1861
+ if (!L) break;
1862
+ const T = L.getBoundingClientRect(), N = await Xt({
1863
+ anchor: { x: T.left, y: T.bottom },
1864
+ pinNumber: n.length + 1
1865
+ });
1866
+ if (N.cancelled === "all") {
1867
+ C = !1;
1868
+ break;
1869
+ }
1870
+ if (N.cancelled === "pin") continue;
1871
+ const w = Bt(L), k = {
1872
+ number: n.length + 1,
1873
+ ...w,
1874
+ ...N.note ? { note: N.note } : {}
1875
+ };
1876
+ n.push(k), o.set(k, L), v.addPin(k.number, {
1877
+ target: L,
1878
+ selector: w.selector,
1879
+ fallbackRect: w.boundingRect
1880
+ });
1881
+ }
1882
+ if (n.length > 0) {
1883
+ v.setLoading("Capturing screenshot…"), await new Promise((S) => requestAnimationFrame(() => S()));
1884
+ try {
1885
+ const S = Array.from(document.querySelectorAll("launch-kit-beacon")), L = await _e({ excludeHosts: S }), T = n.map((k) => ({
1886
+ number: k.number,
1887
+ selector: k.selector,
1888
+ boundingRect: k.boundingRect,
1889
+ ...o.get(k) ? { liveElement: o.get(k) } : {}
1890
+ })), N = {
1891
+ w: window.innerWidth,
1892
+ h: window.innerHeight,
1893
+ dpr: window.devicePixelRatio || 1
1894
+ }, w = await Re(L, T, N, y);
1895
+ r = w, tn({ dataUrl: w, mime: "image/jpeg" });
1896
+ } catch {
1897
+ r = null, D();
1898
+ }
1899
+ } else
1900
+ r = null, D();
1901
+ } finally {
1902
+ v.destroy(), h();
1903
+ }
1904
+ m(), x();
1905
+ }
1906
+ function b(g) {
1907
+ const u = n.findIndex((y) => y.number === g);
1908
+ u !== -1 && (n.splice(u, 1), n.forEach((y, h) => {
1909
+ y.number = h + 1;
1910
+ }), r = null, D(), m(), x());
1911
+ }
1912
+ function m() {
1913
+ if (a && (a.textContent = `Pins (${n.length})`, a.style.display = n.length === 0 ? "none" : ""), c && (c.textContent = n.length === 0 ? "Annotate elements" : "Add another pin"), !!i) {
1914
+ i.innerHTML = "", i.style.display = n.length === 0 ? "none" : "";
1915
+ for (const g of n) {
1916
+ const u = document.createElement("div");
1917
+ u.className = "beacon-pin-item", u.dataset.pin = String(g.number);
1918
+ const y = document.createElement("span");
1919
+ y.className = "beacon-pin-num", y.textContent = String(g.number);
1920
+ const h = document.createElement("div");
1921
+ h.className = "beacon-pin-meta";
1922
+ const v = document.createElement("div");
1923
+ v.className = "beacon-pin-selector", v.title = g.selector, v.textContent = g.selector || g.tagName;
1924
+ const C = document.createElement("input");
1925
+ C.type = "text", C.className = "beacon-pin-note-input", C.placeholder = "Add a note (optional)", C.value = g.note ?? "", C.addEventListener("input", () => {
1926
+ C.value.trim() ? g.note = C.value : delete g.note;
1927
+ }), h.appendChild(v), h.appendChild(C);
1928
+ const S = document.createElement("button");
1929
+ S.type = "button", S.className = "beacon-icon-btn", S.setAttribute("aria-label", `Remove pin ${g.number}`), S.appendChild(on()), S.addEventListener("click", () => b(g.number)), u.appendChild(y), u.appendChild(h), u.appendChild(S), i.appendChild(u);
742
1930
  }
743
- } catch {
744
1931
  }
745
- return t.boundingRect;
746
- }
747
- function ot(t) {
748
- return new Promise((e, n) => {
749
- const o = new Image();
750
- o.onload = () => e(o), o.onerror = (s) => n(s), o.src = t;
751
- });
752
- }
753
- const st = 30, D = 500, ae = 2e3, it = 500, rt = 5e3, at = /launch-kit-beacon|beacon-client|beacon\.(?:es|umd|mjs)/i, $ = [], P = /* @__PURE__ */ new Map(), B = /* @__PURE__ */ new Set();
754
- let ce = !1;
755
- function C(t, e) {
756
- if (t)
757
- return t.length > e ? t.slice(0, e) : t;
758
- }
759
- function ct(t, e) {
760
- const n = (e == null ? void 0 : e.split(`
761
- `).slice(0, 3).join("|")) ?? "";
762
- return `${t}::${n}`;
763
- }
764
- function lt(t) {
765
- return !!t && at.test(t);
766
- }
767
- function dt(t) {
768
- try {
769
- return JSON.stringify(t).slice(0, D);
770
- } catch {
771
- return String(t);
772
1932
  }
773
- }
774
- function le(t) {
775
- if (lt(t.stack) || t.kind === "unhandledrejection" && /AbortError/i.test(t.message)) return;
776
- const e = ct(t.message, t.stack), n = P.get(e);
777
- if (n !== void 0 && t.ts - n < rt) {
778
- P.set(e, t.ts);
779
- return;
1933
+ function x() {
1934
+ s && (r ? (s.src = r, s.style.display = "block") : (s.removeAttribute("src"), s.style.display = "none"));
780
1935
  }
781
- P.set(e, t.ts), $.push(t), $.length > st && $.shift();
782
- for (const o of B)
783
- try {
784
- o();
785
- } catch {
786
- }
787
- }
788
- function ut() {
789
- ce || typeof window > "u" || (ce = !0, window.addEventListener("error", (t) => {
790
- try {
791
- const e = t.error instanceof Error ? t.error.message : void 0, n = t.error instanceof Error ? t.error.stack : void 0;
792
- le({
793
- ts: Date.now(),
794
- kind: "error",
795
- message: C(t.message || e || "Unknown error", D) ?? "Unknown error",
796
- ...n ? { stack: C(n, ae) } : {},
797
- ...t.filename ? { source: C(t.filename, it) } : {},
798
- ...Number.isFinite(t.lineno) ? { line: t.lineno } : {},
799
- ...Number.isFinite(t.colno) ? { col: t.colno } : {}
800
- });
801
- } catch {
802
- }
803
- }), window.addEventListener("unhandledrejection", (t) => {
804
- try {
805
- const e = t.reason, n = e instanceof Error ? e.message : typeof e == "string" ? e : dt(e), o = e instanceof Error ? e.stack : void 0;
806
- le({
807
- ts: Date.now(),
808
- kind: "unhandledrejection",
809
- message: C(n || "Unknown rejection", D) ?? "Unknown rejection",
810
- ...o ? { stack: C(o, ae) } : {}
811
- });
812
- } catch {
1936
+ return {
1937
+ name: "domEle",
1938
+ setupOnce(g) {
1939
+ return g.on("close", () => d());
1940
+ },
1941
+ form(g) {
1942
+ return {
1943
+ render: (u) => (a = document.createElement("div"), a.className = "beacon-pin-list-header", u.appendChild(a), i = document.createElement("div"), i.className = "beacon-pin-list", u.appendChild(i), c = document.createElement("button"), c.type = "button", c.className = "beacon-btn secondary beacon-pin-annotate", c.addEventListener("click", () => {
1944
+ f(g);
1945
+ }), u.appendChild(c), s = document.createElement("img"), s.className = "beacon-thumb", s.alt = "Annotated screenshot preview", s.style.display = "none", u.appendChild(s), m(), x(), () => {
1946
+ a = null, i = null, s = null, c = null;
1947
+ })
1948
+ };
1949
+ },
1950
+ capture() {
1951
+ return n.length === 0 ? null : { pins: n };
813
1952
  }
814
- }));
1953
+ };
815
1954
  }
816
- function M() {
817
- return $.slice();
1955
+ function an(e) {
1956
+ return !!e && typeof e == "object" && !("v" in e) && "error" in e;
818
1957
  }
819
- function ge(t) {
820
- return B.add(t), () => {
821
- B.delete(t);
1958
+ function sn(e = {}) {
1959
+ return {
1960
+ name: "domSS",
1961
+ async capture(t) {
1962
+ const n = nn();
1963
+ if (n)
1964
+ return { dataUrl: n.dataUrl, mime: n.mime };
1965
+ const o = await t.requestMode("hide");
1966
+ try {
1967
+ await new Promise((p) => requestAnimationFrame(() => p()));
1968
+ const r = Array.from(document.querySelectorAll("launch-kit-beacon")), a = await _e({
1969
+ quality: e.quality,
1970
+ pixelRatio: e.pixelRatio,
1971
+ excludeHosts: r
1972
+ }), i = t.captured("domEle"), s = cn(i), c = {
1973
+ w: window.innerWidth,
1974
+ h: window.innerHeight,
1975
+ dpr: window.devicePixelRatio || 1
1976
+ }, d = e.accent ?? ln();
1977
+ return { dataUrl: s.length > 0 ? await Re(a, s, c, d) : a, mime: "image/jpeg" };
1978
+ } finally {
1979
+ o();
1980
+ }
1981
+ }
822
1982
  };
823
1983
  }
824
- async function ht(t, e, n) {
825
- const o = await fetch(t, {
826
- method: "POST",
827
- credentials: "include",
828
- headers: {
829
- "Content-Type": "application/json",
830
- ...n ?? {}
831
- },
832
- body: JSON.stringify(e)
833
- });
834
- let s = null;
835
- if ((o.headers.get("Content-Type") ?? "").includes("application/json"))
836
- try {
837
- s = await o.json();
838
- } catch {
839
- s = null;
840
- }
841
- else
1984
+ function cn(e) {
1985
+ if (!e || an(e)) return [];
1986
+ const t = e.pins;
1987
+ return Array.isArray(t) ? t.filter((n) => !!n && typeof n == "object").map((n) => ({
1988
+ number: Number(n.number) || 0,
1989
+ selector: typeof n.selector == "string" ? n.selector : void 0,
1990
+ boundingRect: n.boundingRect ?? { x: 0, y: 0, w: 0, h: 0 }
1991
+ })) : [];
1992
+ }
1993
+ function ln() {
1994
+ if (typeof window > "u") return "#0ea5e9";
1995
+ const e = document.querySelector("launch-kit-beacon");
1996
+ return e && getComputedStyle(e).getPropertyValue("--beacon-accent").trim() || "#0ea5e9";
1997
+ }
1998
+ const ye = "beacon-no-capture", ve = "__lsBeaconMonitorChipPos", dn = "#10b981";
1999
+ function un(e) {
2000
+ const t = e.accent ?? dn, n = e.startedAt ?? Date.now(), o = document.createElement("div");
2001
+ o.className = `${ye} beacon-monitor-overlay-frame`, o.setAttribute("aria-hidden", "true"), o.style.setProperty("--beacon-monitor-accent", t), document.body.appendChild(o);
2002
+ const r = document.createElement("div");
2003
+ r.className = `${ye} beacon-monitor-overlay-chip`, r.setAttribute("role", "status"), r.setAttribute("aria-label", "Recording — drag to move"), r.style.setProperty("--beacon-monitor-accent", t);
2004
+ const a = document.createElement("div");
2005
+ a.className = "beacon-monitor-overlay-chip-row";
2006
+ const i = document.createElement("span");
2007
+ i.className = "beacon-monitor-overlay-rec-dot", i.setAttribute("aria-hidden", "true");
2008
+ const s = document.createElement("span");
2009
+ s.className = "beacon-monitor-overlay-rec-label", s.textContent = "REC";
2010
+ const c = document.createElement("span");
2011
+ c.className = "beacon-monitor-overlay-sep", c.setAttribute("aria-hidden", "true"), c.textContent = "·";
2012
+ const d = document.createElement("span");
2013
+ d.className = "beacon-monitor-overlay-timer", d.textContent = "00:00";
2014
+ const l = document.createElement("button");
2015
+ l.type = "button", l.className = "beacon-monitor-overlay-stop", l.textContent = "Stop", l.setAttribute("aria-label", "Stop monitoring"), a.appendChild(i), a.appendChild(s), a.appendChild(c), a.appendChild(d), a.appendChild(l), r.appendChild(a);
2016
+ const p = document.createElement("div");
2017
+ p.className = "beacon-monitor-overlay-url", e.url ? (p.textContent = e.url, p.title = e.url) : p.style.display = "none", r.appendChild(p), document.body.appendChild(r);
2018
+ const f = b() ?? m();
2019
+ g(x(f));
2020
+ function b() {
842
2021
  try {
843
- s = await o.text();
2022
+ const w = localStorage.getItem(ve);
2023
+ if (!w) return null;
2024
+ const k = JSON.parse(w), I = typeof k.x == "number" ? k.x : NaN, z = typeof k.y == "number" ? k.y : NaN;
2025
+ return !Number.isFinite(I) || !Number.isFinite(z) ? null : { x: I, y: z };
844
2026
  } catch {
845
- s = null;
2027
+ return null;
846
2028
  }
847
- return {
848
- ok: o.ok,
849
- status: o.status,
850
- body: s
851
- };
852
- }
853
- const pt = ["endpoint", "position", "theme", "severities"], de = "launch-kit-beacon-portal-styles";
854
- function ft(t) {
855
- if (document.getElementById(de)) return;
856
- const e = document.createElement("style");
857
- e.id = de, e.textContent = t, document.head.appendChild(e);
858
- }
859
- const bt = [
860
- "--beacon-accent",
861
- "--beacon-bg",
862
- "--beacon-fg",
863
- "--beacon-muted",
864
- "--beacon-border",
865
- "--beacon-radius",
866
- "--beacon-shadow",
867
- "--beacon-z-index",
868
- "--beacon-bug",
869
- "--beacon-idea",
870
- "--beacon-ux",
871
- "--beacon-a11y"
872
- ], ue = "#0ea5e9";
873
- class mt extends HTMLElement {
874
- constructor() {
875
- super(...arguments), this._config = null, this.pins = [], this.pinElements = /* @__PURE__ */ new WeakMap(), this.description = "", this.severity = "bug", this.submitSucceeded = !1;
876
2029
  }
877
- static get observedAttributes() {
878
- return pt;
2030
+ function m() {
2031
+ const k = r.getBoundingClientRect().width || 200;
2032
+ return { x: Math.max(8, Math.floor((window.innerWidth - k) / 2)), y: 16 };
879
2033
  }
880
- /** Public — wrappers can set `widget.config = {...}` for dynamic endpoint/headers/context. */
881
- set config(e) {
882
- this._config = e;
2034
+ function x(w) {
2035
+ const I = r.getBoundingClientRect(), z = I.width || 200, je = I.height || 40, Ve = Math.max(8, window.innerWidth - z - 8), We = Math.max(8, window.innerHeight - je - 8);
2036
+ return {
2037
+ x: Math.min(Math.max(8, w.x), Ve),
2038
+ y: Math.min(Math.max(8, w.y), We)
2039
+ };
883
2040
  }
884
- get config() {
885
- if (this._config) return this._config;
886
- const e = this.getAttribute("endpoint");
887
- return e ? { endpoint: e } : null;
2041
+ function g(w) {
2042
+ r.style.left = `${w.x}px`, r.style.top = `${w.y}px`;
888
2043
  }
889
- connectedCallback() {
890
- if (!this.shadow) {
891
- this.shadow = this.attachShadow({ mode: "open" });
892
- const e = document.createElement("style");
893
- e.textContent = V, this.shadow.appendChild(e), this.slotEl = document.createElement("slot"), this.slotEl.name = "trigger", this.shadow.appendChild(this.slotEl), this.trigger = ke(), this.shadow.appendChild(this.trigger), this.trigger.addEventListener("click", () => this.open()), this.slotEl.addEventListener("slotchange", () => {
894
- const n = this.slotEl.assignedElements();
895
- n.length > 0 && (this.trigger && (this.trigger.style.display = "none"), n.forEach((o) => o.addEventListener("click", () => this.open())));
896
- }), this.drawer = new Ce(this.parseSeverities(), {
897
- onClose: () => this.close(),
898
- onAnnotate: () => this.startAnnotate(),
899
- onSubmit: () => this.handleSubmit(),
900
- onPinNoteChange: (n, o) => this.updatePinNote(n, o),
901
- onPinDelete: (n) => this.deletePin(n),
902
- onDescriptionChange: (n) => {
903
- this.description = n;
904
- },
905
- onSeverityChange: (n) => {
906
- this.severity = n;
907
- }
908
- }), ft(V), this.drawer.root.classList.add("beacon-no-capture"), this.drawer.root.classList.add(`beacon-theme-${this.getAttribute("theme") ?? "auto"}`), document.body.appendChild(this.drawer.root), this.eventsUnsubscribe = ge(() => {
909
- var n;
910
- (n = this.drawer) == null || n.setEvents(M());
911
- });
2044
+ let u = !1, y = null, h = { x: 0, y: 0 };
2045
+ function v(w) {
2046
+ if (w.target instanceof Element && w.target.closest(".beacon-monitor-overlay-stop")) return;
2047
+ w.preventDefault(), u = !0, y = w.pointerId;
2048
+ try {
2049
+ r.setPointerCapture(w.pointerId);
2050
+ } catch {
912
2051
  }
913
- this.hasAttribute("position") || this.setAttribute("position", "bottom-right"), this.hasAttribute("theme") || this.setAttribute("theme", "auto");
2052
+ r.setAttribute("data-dragging", "true");
2053
+ const k = r.getBoundingClientRect();
2054
+ h = { x: w.clientX - k.left, y: w.clientY - k.top };
914
2055
  }
915
- attributeChangedCallback(e, n, o) {
916
- e === "severities" && this.drawer && console.warn("[launch-kit-beacon] severities attribute changed after mount; not yet hot-reloaded."), e === "theme" && this.drawer && n !== o && (this.drawer.root.classList.remove(`beacon-theme-${n ?? "auto"}`), this.drawer.root.classList.add(`beacon-theme-${o ?? "auto"}`));
2056
+ function C(w) {
2057
+ !u || w.pointerId !== y || g(x({ x: w.clientX - h.x, y: w.clientY - h.y }));
917
2058
  }
918
- // ── Public API ──────────────────────────────────────────
919
- open() {
920
- var e;
921
- if (this.drawer) {
922
- if (this.getAttribute("position") === "hidden") {
923
- const n = (e = this.slotEl) == null ? void 0 : e.assignedElements()[0];
924
- n && wt(this.drawer.root, n);
925
- }
926
- this.submitSucceeded = !1, this.drawer.setEvents(M()), this.syncCustomProperties(), this.installClickBlocker(), this.drawer.open();
927
- }
928
- }
929
- close() {
930
- this.drawer && (!this.submitSucceeded && this.hasUnsavedData() && !window.confirm("You have unsaved feedback. Close and discard it?") || this.forceClose());
931
- }
932
- disconnectedCallback() {
933
- var e;
934
- this.uninstallClickBlocker(), (e = this.eventsUnsubscribe) == null || e.call(this), this.eventsUnsubscribe = void 0, this.drawer && this.drawer.root.parentNode && this.drawer.root.parentNode.removeChild(this.drawer.root);
935
- }
936
- async openWithPicker() {
937
- this.open(), setTimeout(() => this.startAnnotate(), 0);
938
- }
939
- // ── Annotate flow ──────────────────────────────────────────
940
- async startAnnotate() {
941
- if (!this.drawer) return;
942
- this.drawer.minimize();
943
- const e = this.getAccentColor(), n = Me({ accent: e });
944
- for (const o of this.pins) {
945
- const s = this.pinElements.get(o);
946
- s && n.addPin(o.number, {
947
- target: s,
948
- selector: o.selector,
949
- fallbackRect: o.boundingRect
950
- });
951
- }
2059
+ function S(w) {
2060
+ if (!u || w.pointerId !== y) return;
2061
+ u = !1, y = null, r.removeAttribute("data-dragging");
952
2062
  try {
953
- let o = !0;
954
- for (; o; ) {
955
- const i = await $e({ shadowRoot: this.shadow, accent: e }).promise;
956
- if (!i) break;
957
- const r = i.getBoundingClientRect(), l = await Le({
958
- shadowRoot: this.shadow,
959
- anchor: { x: r.left, y: r.bottom },
960
- pinNumber: this.pins.length + 1
961
- });
962
- if (l.cancelled === "all") break;
963
- if (l.cancelled === "pin") continue;
964
- const a = Xe(i), c = {
965
- number: this.pins.length + 1,
966
- ...a,
967
- ...l.note ? { note: l.note } : {}
968
- };
969
- this.pins.push(c), this.pinElements.set(c, i), n.addPin(c.number, {
970
- target: i,
971
- selector: a.selector,
972
- fallbackRect: a.boundingRect
973
- });
974
- }
975
- if (this.pins.length > 0) {
976
- n.setLoading("Capturing screenshot…"), await new Promise((s) => requestAnimationFrame(() => s()));
977
- try {
978
- const s = oe(), i = await ie({ excludeShadowRoot: this.shadow }), r = await re(i, this.pins, s.viewport, this.pinElements, e);
979
- this.drawer.setPins(this.pins, r);
980
- } catch (s) {
981
- const i = s instanceof Error ? s.message : String(s);
982
- console.error("[launch-kit-beacon] screenshot capture failed:", s), this.drawer.setPins(this.pins), this.drawer.setStatus(`Screenshot capture failed: ${i}`, "error");
983
- }
984
- }
985
- } finally {
986
- n.destroy();
987
- }
988
- this.drawer.open();
989
- }
990
- updatePinNote(e, n) {
991
- const o = this.pins.find((s) => s.number === e);
992
- o && (n.trim() ? o.note = n : delete o.note);
993
- }
994
- deletePin(e) {
995
- var n, o;
996
- this.pins = this.pins.filter((s) => s.number !== e), this.pins.forEach((s, i) => {
997
- s.number = i + 1;
998
- }), (n = this.drawer) == null || n.setAnnotatedScreenshot(void 0), (o = this.drawer) == null || o.setPins(this.pins);
999
- }
1000
- // ── Submit flow ──────────────────────────────────────────
1001
- async handleSubmit() {
1002
- if (!this.drawer) return;
1003
- const e = this.config;
1004
- if (!(e != null && e.endpoint)) {
1005
- this.drawer.setStatus("Missing endpoint configuration", "error");
1006
- return;
1007
- }
1008
- const n = this.drawer.getDescription().trim(), o = this.drawer.getSeverity();
1009
- if (!n) {
1010
- this.drawer.setStatus("Description is required", "error");
1011
- return;
1012
- }
1013
- this.drawer.setSubmitting(!0);
1014
- let s = this.drawer.getAnnotatedScreenshot();
1015
- const i = !s && this.pins.length > 0;
1016
- this.drawer.setStatus(i ? "Capturing screenshot…" : "Sending…"), await new Promise((u) => requestAnimationFrame(() => u()));
1017
- const r = oe();
1018
- if (i)
1019
- try {
1020
- const u = await ie({ excludeShadowRoot: this.shadow });
1021
- s = await re(u, this.pins, r.viewport, this.pinElements, this.getAccentColor());
1022
- } catch (u) {
1023
- console.error("[launch-kit-beacon] screenshot capture failed at submit:", u);
1024
- }
1025
- const l = M(), a = {
1026
- description: n,
1027
- severity: o,
1028
- ...s ? { screenshot: { dataUrl: s, mime: "image/jpeg" } } : {},
1029
- metadata: r,
1030
- pins: this.pins,
1031
- ...l.length > 0 ? { events: l } : {},
1032
- ...this.resolveContext() ? { context: this.resolveContext() } : {}
1033
- }, c = new CustomEvent("beacon-before-submit", {
1034
- detail: { payload: a },
1035
- cancelable: !0,
1036
- bubbles: !0,
1037
- composed: !0
1038
- });
1039
- if (!this.dispatchEvent(c)) {
1040
- this.drawer.setSubmitting(!1), this.drawer.setStatus("Submission cancelled", "error");
1041
- return;
2063
+ r.releasePointerCapture(w.pointerId);
2064
+ } catch {
1042
2065
  }
1043
- this.drawer.setStatus("Sending…");
2066
+ const k = r.getBoundingClientRect();
1044
2067
  try {
1045
- const u = this.resolveHeaders(), g = await ht(e.endpoint, a, u);
1046
- this.drawer.setSubmitting(!1), g.ok ? (this.submitSucceeded = !0, this.drawer.setStatus("Sent — thanks!", "success"), this.dispatchEvent(new CustomEvent("beacon-after-submit", {
1047
- detail: { response: g },
1048
- bubbles: !0,
1049
- composed: !0
1050
- })), setTimeout(() => {
1051
- this.forceClose();
1052
- }, 1500)) : this.drawer.setStatus(`Failed: ${g.status}`, "error");
1053
- } catch (u) {
1054
- this.drawer.setSubmitting(!1);
1055
- const g = u instanceof Error ? u.message : "Network error";
1056
- this.drawer.setStatus(`Failed: ${g}`, "error");
1057
- }
1058
- }
1059
- // ── Helpers ──────────────────────────────────────────
1060
- /**
1061
- * Resolved accent color — reads --beacon-accent from the host's computed style
1062
- * (which picks up any inline `style="--beacon-accent: …"` or stylesheet override
1063
- * targeting the host). Falls back to the default sky-blue if unset.
1064
- */
1065
- getAccentColor() {
1066
- return typeof window > "u" ? ue : getComputedStyle(this).getPropertyValue("--beacon-accent").trim() || ue;
1067
- }
1068
- /**
1069
- * Mirror every customizable --beacon-* var from the host onto the body-mounted
1070
- * drawer. CSS inheritance stops at the body boundary, so we copy the host's
1071
- * resolved values forward. Called on open() so changes mid-session are picked up.
1072
- */
1073
- syncCustomProperties() {
1074
- if (!this.drawer) return;
1075
- const e = getComputedStyle(this);
1076
- for (const n of bt) {
1077
- const o = e.getPropertyValue(n).trim();
1078
- o && this.drawer.root.style.setProperty(n, o);
1079
- }
1080
- }
1081
- hasUnsavedData() {
1082
- var n;
1083
- return this.pins.length > 0 ? !0 : (((n = this.drawer) == null ? void 0 : n.getDescription()) ?? "").trim().length > 0;
1084
- }
1085
- resetState() {
1086
- var e;
1087
- this.pins = [], this.description = "", this.severity = "bug", this.pinElements = /* @__PURE__ */ new WeakMap(), (e = this.drawer) == null || e.reset();
1088
- }
1089
- forceClose() {
1090
- var e;
1091
- this.uninstallClickBlocker(), this.resetState(), this.submitSucceeded = !1, (e = this.drawer) == null || e.close();
1092
- }
1093
- installClickBlocker() {
1094
- this.documentClickBlocker || (this.documentClickBlocker = (e) => {
1095
- const n = e.composedPath();
1096
- if (!n.includes(this.shadow.host)) {
1097
- for (const o of n)
1098
- if (o instanceof Element && o.classList.contains("beacon-no-capture")) return;
1099
- e.preventDefault(), e.stopPropagation();
1100
- }
1101
- }, document.addEventListener("click", this.documentClickBlocker, !0));
2068
+ localStorage.setItem(ve, JSON.stringify({ x: k.left, y: k.top }));
2069
+ } catch {
2070
+ }
1102
2071
  }
1103
- uninstallClickBlocker() {
1104
- this.documentClickBlocker && (document.removeEventListener("click", this.documentClickBlocker, !0), this.documentClickBlocker = void 0);
2072
+ r.addEventListener("pointerdown", v), r.addEventListener("pointermove", C), r.addEventListener("pointerup", S), r.addEventListener("pointercancel", S), l.addEventListener("click", (w) => {
2073
+ w.stopPropagation(), e.onStop();
2074
+ });
2075
+ function L() {
2076
+ const w = r.getBoundingClientRect();
2077
+ g(x({ x: w.left, y: w.top }));
1105
2078
  }
1106
- resolveHeaders() {
1107
- var n;
1108
- const e = (n = this.config) == null ? void 0 : n.headers;
1109
- if (e)
1110
- return typeof e == "function" ? e() : e;
2079
+ window.addEventListener("resize", L);
2080
+ function T() {
2081
+ const w = Math.max(0, Math.floor((Date.now() - n) / 1e3));
2082
+ d.textContent = pn(w);
1111
2083
  }
1112
- resolveContext() {
1113
- var n;
1114
- const e = (n = this.config) == null ? void 0 : n.context;
1115
- if (e)
1116
- return typeof e == "function" ? e() : e;
1117
- }
1118
- parseSeverities() {
1119
- const e = this.getAttribute("severities");
1120
- return e ? e.split(",").map((n) => n.trim()).filter(Boolean) : ["bug", "idea", "ux", "a11y"];
1121
- }
1122
- }
1123
- function gt(t = "launch-kit-beacon") {
1124
- typeof window > "u" || customElements.get(t) || customElements.define(t, mt);
1125
- }
1126
- const he = 380, E = 8, yt = 520;
1127
- function wt(t, e) {
1128
- const n = e.getBoundingClientRect(), o = window.innerWidth, s = window.innerHeight;
1129
- let i = Math.max(E, o - n.right);
1130
- o - i - he < E && (i = Math.max(E, o - he - E));
1131
- const l = s - n.bottom - E, a = n.top - E;
1132
- t.style.left = "auto", t.style.right = `${i}px`, l >= yt || l >= a ? (t.style.top = `${n.bottom + E}px`, t.style.bottom = "auto") : (t.style.top = "auto", t.style.bottom = `${s - n.top + E}px`);
1133
- }
1134
- const vt = 1024, xt = 5;
1135
- function Et(t, e) {
1136
- return t.length > e ? t.slice(0, e) : t;
1137
- }
1138
- function ye(t) {
1139
- if (t.id) return `#${CSS.escape(t.id)}`;
1140
- const e = [];
1141
- let n = t;
1142
- for (let o = 0; o < 3 && n; o++) {
1143
- const s = n.tagName.toLowerCase(), i = n.id ? `#${CSS.escape(n.id)}` : "", r = n.classList.length > 0 ? "." + Array.from(n.classList).slice(0, 3).map(CSS.escape).join(".") : "";
1144
- if (e.unshift(`${s}${i}${r}`), i) break;
2084
+ T();
2085
+ const N = window.setInterval(T, 1e3);
2086
+ return {
2087
+ updateUrl(w) {
2088
+ w ? (p.textContent = w, p.title = w, p.style.display = "") : p.style.display = "none";
2089
+ },
2090
+ destroy() {
2091
+ window.clearInterval(N), window.removeEventListener("resize", L), r.removeEventListener("pointerdown", v), r.removeEventListener("pointermove", C), r.removeEventListener("pointerup", S), r.removeEventListener("pointercancel", S), o.remove(), r.remove();
2092
+ }
2093
+ };
2094
+ }
2095
+ function pn(e) {
2096
+ const t = Math.floor(e / 3600), n = Math.floor(e % 3600 / 60), o = e % 60;
2097
+ return t > 0 ? `${P(t)}:${P(n)}:${P(o)}` : `${P(n)}:${P(o)}`;
2098
+ }
2099
+ function P(e) {
2100
+ return e < 10 ? `0${e}` : String(e);
2101
+ }
2102
+ const O = 80, fn = 'button, a, input[type="submit"], input[type="button"], [role="button"], [role="link"], [role="menuitem"], [role="tab"], [role="option"]', mn = 1024, hn = 5;
2103
+ function bn(e, t) {
2104
+ return e.length > t ? e.slice(0, t) : e;
2105
+ }
2106
+ function ee(e) {
2107
+ if (e.id) return `#${CSS.escape(e.id)}`;
2108
+ const t = [];
2109
+ let n = e;
2110
+ for (let o = 0; o < 5 && n; o++) {
2111
+ const r = n.tagName.toLowerCase(), a = n.id ? `#${CSS.escape(n.id)}` : "", i = n.classList.length > 0 ? "." + Array.from(n.classList).slice(0, 3).map(CSS.escape).join(".") : "";
2112
+ if (t.unshift(`${r}${a}${i}`), a) break;
1145
2113
  n = n.parentElement;
1146
2114
  }
1147
- return e.join(" > ");
2115
+ return t.join(" > ");
1148
2116
  }
1149
- function pe(t) {
2117
+ function H(e, t) {
2118
+ if (!e) return;
2119
+ const n = e.replace(/\s+/g, " ").trim();
2120
+ if (n)
2121
+ return n.length > t ? n.slice(0, t) : n;
2122
+ }
2123
+ function xe(e) {
2124
+ const t = H(e.textContent, O), n = H(e.getAttribute("aria-label"), O), o = e.getAttribute("data-testid") || void 0, r = e.getAttribute("name") || void 0;
2125
+ let a = n || t;
2126
+ if (!a) {
2127
+ const i = e.closest(fn);
2128
+ i && i !== e && (a = H(i.getAttribute("aria-label"), O) || H(i.textContent, O));
2129
+ }
1150
2130
  return {
1151
- tag: t.tagName.toLowerCase(),
1152
- id: t.id || null,
1153
- classes: Array.from(t.classList).slice(0, 10),
1154
- role: t.getAttribute("role"),
1155
- selector: ye(t)
2131
+ tag: e.tagName.toLowerCase(),
2132
+ id: e.id || null,
2133
+ classes: Array.from(e.classList).slice(0, 10),
2134
+ role: e.getAttribute("role"),
2135
+ selector: ee(e),
2136
+ ...t ? { text: t } : {},
2137
+ ...n ? { ariaLabel: n } : {},
2138
+ ...o ? { testid: o } : {},
2139
+ ...r ? { name: r } : {},
2140
+ // Only include label when it adds something beyond `text` (avoids dup).
2141
+ ...a && a !== t ? { label: a } : {}
1156
2142
  };
1157
2143
  }
1158
- function St(t, e) {
2144
+ function gn(e, t) {
1159
2145
  const n = [], o = document.querySelectorAll("body *");
1160
- for (const s of Array.from(o)) {
1161
- const i = getComputedStyle(s);
1162
- if (i.position !== "fixed" && i.position !== "sticky") continue;
1163
- const r = s.getBoundingClientRect();
1164
- if (t < r.left || t > r.right || e < r.top || e > r.bottom) continue;
1165
- const l = parseInt(i.zIndex, 10);
1166
- !Number.isFinite(l) && i.zIndex !== "auto" || n.push({
1167
- tag: s.tagName.toLowerCase(),
1168
- zIndex: Number.isFinite(l) ? l : 0,
1169
- pointerEvents: i.pointerEvents,
1170
- classes: Array.from(s.classList).slice(0, 5).join(" ")
2146
+ for (const r of Array.from(o)) {
2147
+ const a = getComputedStyle(r);
2148
+ if (a.position !== "fixed" && a.position !== "sticky") continue;
2149
+ const i = r.getBoundingClientRect();
2150
+ if (e < i.left || e > i.right || t < i.top || t > i.bottom) continue;
2151
+ const s = parseInt(a.zIndex, 10);
2152
+ !Number.isFinite(s) && a.zIndex !== "auto" || n.push({
2153
+ tag: r.tagName.toLowerCase(),
2154
+ zIndex: Number.isFinite(s) ? s : 0,
2155
+ pointerEvents: a.pointerEvents,
2156
+ classes: Array.from(r.classList).slice(0, 5).join(" ")
1171
2157
  });
1172
2158
  }
1173
- return n.sort((s, i) => i.zIndex - s.zIndex).slice(0, xt);
1174
- }
1175
- function kt(t) {
1176
- const e = (s) => (i) => {
1177
- const r = i, l = r.target;
1178
- if (!(l instanceof Element)) return;
1179
- const a = r.clientX, c = r.clientY, d = document.elementFromPoint(a, c), u = d === l || (d ? l.contains(d) || d.contains(l) : !1), g = document.querySelectorAll('[role="dialog"][data-state="open"]').length, y = getComputedStyle(document.body).pointerEvents, w = St(a, c);
1180
- t.emitClick({
1181
- kind: s,
1182
- target: pe(l),
1183
- hitMatchesTarget: u,
1184
- ...!u && d instanceof Element ? { hitTarget: pe(d) } : {},
1185
- coords: { x: a, y: c },
1186
- openDialogs: g,
1187
- bodyPointerEvents: y,
1188
- ...w.length > 0 ? { overlaysAtPoint: w } : {}
2159
+ return n.sort((r, a) => a.zIndex - r.zIndex).slice(0, hn);
2160
+ }
2161
+ function yn(e) {
2162
+ const t = (r) => (a) => {
2163
+ const i = a, s = i.target;
2164
+ if (!(s instanceof Element)) return;
2165
+ const c = i.clientX, d = i.clientY, l = document.elementFromPoint(c, d), p = l === s || (l ? s.contains(l) || l.contains(s) : !1), f = document.querySelectorAll('[role="dialog"][data-state="open"]').length, b = getComputedStyle(document.body).pointerEvents, m = p ? [] : gn(c, d);
2166
+ e.emitClick({
2167
+ kind: r,
2168
+ target: xe(s),
2169
+ hitMatchesTarget: p,
2170
+ ...!p && l instanceof Element ? { hitTarget: xe(l) } : {},
2171
+ coords: { x: c, y: d },
2172
+ openDialogs: f,
2173
+ bodyPointerEvents: b,
2174
+ ...m.length > 0 ? { overlaysAtPoint: m } : {}
1189
2175
  });
1190
- }, n = e("click"), o = e("mousedown");
2176
+ }, n = t("click"), o = t("mousedown");
1191
2177
  return document.addEventListener("click", n, { capture: !0, passive: !0 }), document.addEventListener("mousedown", o, { capture: !0, passive: !0 }), () => {
1192
2178
  document.removeEventListener("click", n, { capture: !0 }), document.removeEventListener("mousedown", o, { capture: !0 });
1193
2179
  };
1194
2180
  }
1195
- function At(t) {
1196
- const e = history.pushState, n = history.replaceState;
2181
+ function vn(e) {
2182
+ const t = history.pushState, n = history.replaceState;
1197
2183
  let o = window.location.href;
1198
- const s = (l) => {
1199
- const a = window.location.href;
1200
- if (a === o) return;
1201
- const c = o;
1202
- o = a, t.emitRoute({ kind: "route", from: c, to: a, via: l });
2184
+ const r = (s) => {
2185
+ const c = window.location.href;
2186
+ if (c === o) return;
2187
+ const d = o;
2188
+ o = c, e.emitRoute({ kind: "route", from: d, to: c, via: s });
1203
2189
  };
1204
- history.pushState = function(...a) {
1205
- const c = e.apply(this, a);
1206
- return s("pushState"), c;
1207
- }, history.replaceState = function(...a) {
1208
- const c = n.apply(this, a);
1209
- return s("replaceState"), c;
2190
+ history.pushState = function(...c) {
2191
+ const d = t.apply(this, c);
2192
+ return r("pushState"), d;
2193
+ }, history.replaceState = function(...c) {
2194
+ const d = n.apply(this, c);
2195
+ return r("replaceState"), d;
1210
2196
  };
1211
- const i = () => s("popstate"), r = () => s("hashchange");
1212
- return window.addEventListener("popstate", i), window.addEventListener("hashchange", r), () => {
1213
- history.pushState = e, history.replaceState = n, window.removeEventListener("popstate", i), window.removeEventListener("hashchange", r);
2197
+ const a = () => r("popstate"), i = () => r("hashchange");
2198
+ return window.addEventListener("popstate", a), window.addEventListener("hashchange", i), () => {
2199
+ history.pushState = t, history.replaceState = n, window.removeEventListener("popstate", a), window.removeEventListener("hashchange", i);
1214
2200
  };
1215
2201
  }
1216
- function Ct(t) {
1217
- const e = /* @__PURE__ */ new WeakSet(), n = (s, i) => {
1218
- const r = ye(s);
1219
- t.emitDialog({
2202
+ function xn(e) {
2203
+ const t = /* @__PURE__ */ new WeakSet(), n = (r, a) => {
2204
+ const i = ee(r);
2205
+ e.emitDialog({
1220
2206
  kind: "dialog",
1221
- action: i,
1222
- selector: r,
1223
- state: s.getAttribute("data-state"),
1224
- ...i === "mount" ? { outerHTML: Et(s.outerHTML, vt) } : {}
2207
+ action: a,
2208
+ selector: i,
2209
+ state: r.getAttribute("data-state"),
2210
+ ...a === "mount" ? { outerHTML: bn(r.outerHTML, mn) } : {}
1225
2211
  });
1226
2212
  };
1227
- for (const s of Array.from(document.querySelectorAll('[role="dialog"]')))
1228
- e.add(s);
1229
- const o = new MutationObserver((s) => {
1230
- var i, r, l, a;
1231
- for (const c of s) {
1232
- for (const d of Array.from(c.addedNodes)) {
1233
- if (!(d instanceof Element)) continue;
1234
- const u = (i = d.matches) != null && i.call(d, '[role="dialog"]') ? [d] : Array.from(((r = d.querySelectorAll) == null ? void 0 : r.call(d, '[role="dialog"]')) ?? []);
1235
- for (const g of u)
1236
- e.has(g) || (e.add(g), n(g, "mount"));
2213
+ for (const r of Array.from(document.querySelectorAll('[role="dialog"]')))
2214
+ t.add(r);
2215
+ const o = new MutationObserver((r) => {
2216
+ var a, i, s, c;
2217
+ for (const d of r) {
2218
+ for (const l of Array.from(d.addedNodes)) {
2219
+ if (!(l instanceof Element)) continue;
2220
+ const p = (a = l.matches) != null && a.call(l, '[role="dialog"]') ? [l] : Array.from(((i = l.querySelectorAll) == null ? void 0 : i.call(l, '[role="dialog"]')) ?? []);
2221
+ for (const f of p)
2222
+ t.has(f) || (t.add(f), n(f, "mount"));
1237
2223
  }
1238
- for (const d of Array.from(c.removedNodes)) {
1239
- if (!(d instanceof Element)) continue;
1240
- const u = (l = d.matches) != null && l.call(d, '[role="dialog"]') ? [d] : Array.from(((a = d.querySelectorAll) == null ? void 0 : a.call(d, '[role="dialog"]')) ?? []);
1241
- for (const g of u)
1242
- e.has(g) && (e.delete(g), n(g, "unmount"));
2224
+ for (const l of Array.from(d.removedNodes)) {
2225
+ if (!(l instanceof Element)) continue;
2226
+ const p = (s = l.matches) != null && s.call(l, '[role="dialog"]') ? [l] : Array.from(((c = l.querySelectorAll) == null ? void 0 : c.call(l, '[role="dialog"]')) ?? []);
2227
+ for (const f of p)
2228
+ t.has(f) && (t.delete(f), n(f, "unmount"));
1243
2229
  }
1244
- c.type === "attributes" && c.attributeName === "data-state" && c.target instanceof Element && c.target.getAttribute("role") === "dialog" && n(c.target, "state");
2230
+ d.type === "attributes" && d.attributeName === "data-state" && d.target instanceof Element && d.target.getAttribute("role") === "dialog" && n(d.target, "state");
1245
2231
  }
1246
2232
  });
1247
2233
  return o.observe(document.body, {
@@ -1251,132 +2237,278 @@ function Ct(t) {
1251
2237
  attributeFilter: ["data-state"]
1252
2238
  }), () => o.disconnect();
1253
2239
  }
1254
- function Lt(t) {
1255
- const e = kt(t), n = At(t), o = Ct(t);
2240
+ function wn(e) {
2241
+ const t = (n) => {
2242
+ const o = n.target;
2243
+ if (!(o instanceof HTMLFormElement)) return;
2244
+ const r = [];
2245
+ for (const a of Array.from(o.elements)) {
2246
+ if (!(a instanceof HTMLInputElement || a instanceof HTMLTextAreaElement || a instanceof HTMLSelectElement)) continue;
2247
+ const i = a.getAttribute("name") || "<unnamed>", s = a instanceof HTMLInputElement ? a.type : a.tagName.toLowerCase();
2248
+ let c;
2249
+ a instanceof HTMLInputElement && (a.type === "checkbox" || a.type === "radio") ? c = a.checked : c = !!a.value, r.push({ name: i, type: s, hasValue: c });
2250
+ }
2251
+ e.emitSubmit({
2252
+ kind: "submit",
2253
+ form: {
2254
+ id: o.id || null,
2255
+ action: o.getAttribute("action") || null,
2256
+ method: (o.getAttribute("method") || "GET").toUpperCase(),
2257
+ selector: ee(o),
2258
+ fields: r
2259
+ }
2260
+ });
2261
+ };
2262
+ return document.addEventListener("submit", t, { capture: !0 }), () => document.removeEventListener("submit", t, { capture: !0 });
2263
+ }
2264
+ function En(e) {
2265
+ const t = yn(e), n = vn(e), o = xn(e), r = wn(e);
1256
2266
  return {
1257
2267
  uninstall() {
1258
- e(), n(), o();
2268
+ t(), n(), o(), r();
1259
2269
  }
1260
2270
  };
1261
2271
  }
1262
- const j = 1e3;
1263
- function O(t, e) {
1264
- return t.length > e ? t.slice(0, e) : t;
2272
+ const X = 1e3, we = 10 * 1024, Pe = "[REDACTED]", De = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]), Sn = [
2273
+ /Bearer\s+[A-Za-z0-9._\-+/=]+/gi,
2274
+ /\bls_pat_[A-Za-z0-9_]+/g,
2275
+ // JWT: three dot-separated base64url segments starting with eyJ (the b64
2276
+ // encoding of the JSON {"). Matches Auth0/Clerk/most providers' tokens.
2277
+ /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g
2278
+ ], Cn = /^(password|passwd|secret|token|api[_-]?key|auth|access[_-]?token|refresh[_-]?token|client[_-]?secret|private[_-]?key)$/i;
2279
+ function G(e, t) {
2280
+ return e.length > t ? e.slice(0, t) : e;
2281
+ }
2282
+ function $e(e) {
2283
+ let t = e;
2284
+ for (const n of Sn)
2285
+ t = t.replace(n, Pe);
2286
+ return t;
2287
+ }
2288
+ function J(e) {
2289
+ if (e === null || typeof e != "object")
2290
+ return typeof e == "string" ? $e(e) : e;
2291
+ if (Array.isArray(e)) return e.map(J);
2292
+ const t = {};
2293
+ for (const [n, o] of Object.entries(e))
2294
+ t[n] = Cn.test(n) ? Pe : J(o);
2295
+ return t;
2296
+ }
2297
+ function Ee(e, t) {
2298
+ if (t && t.includes("application/json"))
2299
+ try {
2300
+ const n = JSON.parse(e);
2301
+ return JSON.stringify(J(n));
2302
+ } catch {
2303
+ }
2304
+ return $e(e);
2305
+ }
2306
+ function U(e, t) {
2307
+ const n = e.length, o = { bodySize: n };
2308
+ return n > we ? (o.body = Ee(e.slice(0, we), t), o.bodyTruncated = !0) : o.body = Ee(e, t), t && (o.contentType = t), o;
2309
+ }
2310
+ function kn(e, t) {
2311
+ const n = t == null ? void 0 : t.body;
2312
+ if (n != null) {
2313
+ if (typeof n == "string") return n;
2314
+ if (n instanceof URLSearchParams) return n.toString();
2315
+ if (n instanceof FormData) {
2316
+ const o = [];
2317
+ return n.forEach((r, a) => {
2318
+ o.push(`${a}=${typeof r == "string" ? `[${r.length}b]` : "[file]"}`);
2319
+ }), `[FormData] ${o.join("&")}`;
2320
+ }
2321
+ return n instanceof Blob ? `[Blob ${n.size}b ${n.type || "unknown"}]` : n instanceof ArrayBuffer ? `[binary ${n.byteLength}b]` : ArrayBuffer.isView(n) ? `[binary ${n.byteLength}b]` : null;
2322
+ }
2323
+ return e instanceof Request, null;
2324
+ }
2325
+ function An(e, t) {
2326
+ return !!(((o) => o ? o instanceof Headers ? o.has("authorization") : Array.isArray(o) ? o.some(([r]) => r.toLowerCase() === "authorization") : typeof o == "object" ? Object.keys(o).some((r) => r.toLowerCase() === "authorization") : !1 : !1)(t == null ? void 0 : t.headers) || e instanceof Request && e.headers.has("authorization"));
1265
2327
  }
1266
- function Tt(t) {
1267
- const e = window.fetch;
1268
- if (typeof e != "function") return () => {
2328
+ function Ln(e, t) {
2329
+ return ((o) => {
2330
+ if (o) {
2331
+ if (o instanceof Headers) return o.get("content-type") || void 0;
2332
+ if (Array.isArray(o)) {
2333
+ const r = o.find(([a]) => a.toLowerCase() === "content-type");
2334
+ return r ? r[1] : void 0;
2335
+ }
2336
+ if (typeof o == "object") {
2337
+ for (const [r, a] of Object.entries(o))
2338
+ if (r.toLowerCase() === "content-type") return a;
2339
+ }
2340
+ }
2341
+ })(t == null ? void 0 : t.headers) ?? (e instanceof Request && e.headers.get("content-type") || void 0);
2342
+ }
2343
+ function Nn(e, t, n) {
2344
+ if (!De.has(n)) return;
2345
+ const o = An(e, t), r = kn(e, t);
2346
+ if (r == null && !o) return;
2347
+ const a = Ln(e, t), i = r != null ? U(r, a) : {};
2348
+ return o && (i.hasAuth = !0), i;
2349
+ }
2350
+ function Tn(e) {
2351
+ const t = window.fetch;
2352
+ if (typeof t != "function") return () => {
1269
2353
  };
1270
- const n = async (o, s) => {
1271
- const i = performance.now(), r = ((s == null ? void 0 : s.method) ?? (o instanceof Request ? o.method : "GET")).toUpperCase(), l = typeof o == "string" ? o : o instanceof URL ? o.toString() : o.url;
2354
+ const n = async (o, r) => {
2355
+ const a = performance.now(), i = ((r == null ? void 0 : r.method) ?? (o instanceof Request ? o.method : "GET")).toUpperCase(), s = typeof o == "string" ? o : o instanceof URL ? o.toString() : o.url, c = Nn(o, r, i);
1272
2356
  try {
1273
- const a = await e.call(window, o, s), c = Math.round(performance.now() - i), d = a.status >= 400;
1274
- return (d || t.verbose) && t.emit({
2357
+ const d = await t.call(window, o, r), l = Math.round(performance.now() - a), p = d.status >= 400;
2358
+ let f;
2359
+ if (p || e.verbose)
2360
+ try {
2361
+ const b = await d.clone().text(), m = d.headers.get("content-type") || void 0;
2362
+ f = U(b, m);
2363
+ } catch {
2364
+ }
2365
+ return (p || e.verbose) && e.emit({
1275
2366
  kind: "fetch",
1276
- url: O(l, j),
1277
- method: r,
1278
- status: a.status,
1279
- durationMs: c,
1280
- failed: d
1281
- }), a;
1282
- } catch (a) {
1283
- const c = Math.round(performance.now() - i);
1284
- throw t.emit({
2367
+ url: G(s, X),
2368
+ method: i,
2369
+ status: d.status,
2370
+ durationMs: l,
2371
+ failed: p,
2372
+ ...c ? { request: c } : {},
2373
+ ...f ? { response: f } : {}
2374
+ }), d;
2375
+ } catch (d) {
2376
+ const l = Math.round(performance.now() - a);
2377
+ throw e.emit({
1285
2378
  kind: "fetch",
1286
- url: O(l, j),
1287
- method: r,
2379
+ url: G(s, X),
2380
+ method: i,
1288
2381
  status: 0,
1289
- durationMs: c,
2382
+ durationMs: l,
1290
2383
  failed: !0,
1291
- error: a instanceof Error ? a.message : String(a)
1292
- }), a;
2384
+ error: d instanceof Error ? d.message : String(d),
2385
+ ...c ? { request: c } : {}
2386
+ }), d;
1293
2387
  }
1294
2388
  };
1295
2389
  return n.__lsBeaconWrapped = !0, window.fetch = n, () => {
1296
- window.fetch.__lsBeaconWrapped && (window.fetch = e);
2390
+ window.fetch.__lsBeaconWrapped && (window.fetch = t);
1297
2391
  };
1298
2392
  }
1299
- function Mt(t) {
1300
- const e = XMLHttpRequest.prototype, n = e.open, o = e.send, s = /* @__PURE__ */ new WeakMap();
1301
- return e.open = function(r, l, ...a) {
1302
- return s.set(this, {
1303
- method: r.toUpperCase(),
1304
- url: typeof l == "string" ? l : l.toString(),
1305
- start: 0
1306
- }), n.call(this, r, l, ...a);
1307
- }, e.send = function(r) {
1308
- const l = s.get(this);
1309
- l && (l.start = performance.now());
1310
- const a = () => {
1311
- this.removeEventListener("loadend", a);
1312
- const c = s.get(this);
1313
- if (!c) return;
1314
- const d = Math.round(performance.now() - c.start), u = this.status === 0 || this.status >= 400;
1315
- (u || t.verbose) && t.emit({
2393
+ function Mn(e) {
2394
+ if (e == null) return null;
2395
+ if (typeof e == "string") return e;
2396
+ if (e instanceof URLSearchParams) return e.toString();
2397
+ if (e instanceof FormData) {
2398
+ const t = [];
2399
+ return e.forEach((n, o) => {
2400
+ t.push(`${o}=${typeof n == "string" ? `[${n.length}b]` : "[file]"}`);
2401
+ }), `[FormData] ${t.join("&")}`;
2402
+ }
2403
+ return e instanceof Blob ? `[Blob ${e.size}b ${e.type || "unknown"}]` : e instanceof ArrayBuffer ? `[binary ${e.byteLength}b]` : ArrayBuffer.isView(e) ? `[binary ${e.byteLength}b]` : null;
2404
+ }
2405
+ function In(e) {
2406
+ const t = XMLHttpRequest.prototype, n = t.open, o = t.send, r = t.setRequestHeader, a = /* @__PURE__ */ new WeakMap();
2407
+ return t.open = function(s, c, ...d) {
2408
+ return a.set(this, {
2409
+ method: s.toUpperCase(),
2410
+ url: typeof c == "string" ? c : c.toString(),
2411
+ start: 0,
2412
+ hasAuth: !1
2413
+ }), n.call(this, s, c, ...d);
2414
+ }, t.setRequestHeader = function(s, c) {
2415
+ const d = a.get(this);
2416
+ if (d) {
2417
+ const l = s.toLowerCase();
2418
+ l === "authorization" ? d.hasAuth = !0 : l === "content-type" && (d.requestContentType = c);
2419
+ }
2420
+ return r.call(this, s, c);
2421
+ }, t.send = function(s) {
2422
+ const c = a.get(this);
2423
+ if (c)
2424
+ if (c.start = performance.now(), De.has(c.method)) {
2425
+ const l = Mn(s);
2426
+ l != null ? c.request = U(l, c.requestContentType) : c.request = {}, c.hasAuth && (c.request.hasAuth = !0);
2427
+ } else c.hasAuth && (c.request = { hasAuth: !0 });
2428
+ const d = () => {
2429
+ this.removeEventListener("loadend", d);
2430
+ const l = a.get(this);
2431
+ if (!l) return;
2432
+ const p = Math.round(performance.now() - l.start), f = this.status === 0 || this.status >= 400;
2433
+ let b;
2434
+ if ((f || e.verbose) && this.status > 0)
2435
+ try {
2436
+ const m = this.responseType === "" || this.responseType === "text" ? this.responseText : "";
2437
+ if (m) {
2438
+ const x = this.getResponseHeader("content-type") || void 0;
2439
+ b = U(m, x);
2440
+ }
2441
+ } catch {
2442
+ }
2443
+ (f || e.verbose) && e.emit({
1316
2444
  kind: "xhr",
1317
- url: O(c.url, j),
1318
- method: c.method,
2445
+ url: G(l.url, X),
2446
+ method: l.method,
1319
2447
  status: this.status,
1320
- durationMs: d,
1321
- failed: u
1322
- }), s.delete(this);
2448
+ durationMs: p,
2449
+ failed: f,
2450
+ ...l.request ? { request: l.request } : {},
2451
+ ...b ? { response: b } : {}
2452
+ }), a.delete(this);
1323
2453
  };
1324
- return this.addEventListener("loadend", a), o.call(this, r);
2454
+ return this.addEventListener("loadend", d), o.call(this, s);
1325
2455
  }, () => {
1326
- e.open = n, e.send = o;
2456
+ t.open = n, t.send = o, t.setRequestHeader = r;
1327
2457
  };
1328
2458
  }
1329
- function It(t) {
1330
- const e = Tt(t), n = Mt(t);
2459
+ function Rn(e) {
2460
+ const t = Tn(e), n = In(e);
1331
2461
  return {
1332
2462
  uninstall() {
1333
- e(), n();
2463
+ t(), n();
1334
2464
  }
1335
2465
  };
1336
2466
  }
1337
- const _t = 1e3, fe = 50, $t = 500;
1338
- class Nt {
1339
- constructor(e) {
2467
+ const _n = 1e3, Se = 50, Pn = 500;
2468
+ class Dn {
2469
+ constructor(t) {
1340
2470
  this.buffer = [], this.inflight = !1, this.timer = null, this.destroyed = !1, this.handleVisibilityChange = () => {
1341
2471
  document.visibilityState === "hidden" && this.flushSync();
1342
- }, this.url = e.url, this.sessionId = e.sessionId, this.onError = e.onError, this.timer = setInterval(() => this.flush(), _t), this.pagehideHandler = () => this.flushSync(), window.addEventListener("pagehide", this.pagehideHandler), document.addEventListener("visibilitychange", this.handleVisibilityChange);
2472
+ }, this.url = t.url, this.sessionId = t.sessionId, this.onError = t.onError, this.timer = setInterval(() => {
2473
+ this.flush();
2474
+ }, _n), this.pagehideHandler = () => this.flushSync(), window.addEventListener("pagehide", this.pagehideHandler), document.addEventListener("visibilitychange", this.handleVisibilityChange);
1343
2475
  }
1344
- enqueue(e) {
1345
- this.destroyed || (this.buffer.push(e), this.buffer.length >= $t && this.buffer.shift(), this.buffer.length >= fe && this.flush());
2476
+ enqueue(t) {
2477
+ this.destroyed || (this.buffer.push(t), this.buffer.length > Pn && this.buffer.shift(), this.buffer.length >= Se && this.flush());
1346
2478
  }
1347
2479
  /** Async flush via fetch. No-op when in-flight or empty. */
1348
2480
  async flush() {
1349
- var o, s;
2481
+ var o, r;
1350
2482
  if (this.destroyed || this.inflight || this.buffer.length === 0) return;
1351
- const e = this.buffer.splice(0, fe), n = this.makeBatch(e);
2483
+ const t = this.buffer.splice(0, Se), n = this.makeBatch(t);
1352
2484
  this.inflight = !0;
1353
2485
  try {
1354
- const i = await fetch(this.url, {
2486
+ const a = await fetch(this.url, {
1355
2487
  method: "POST",
1356
- // No credentials — this is going to the developer's local server,
1357
- // not the app's own backend. Avoid leaking session cookies.
2488
+ // credentials:'omit' — going to the dev's local server, not the app
2489
+ // backend; avoid leaking session cookies cross-origin.
1358
2490
  credentials: "omit",
1359
2491
  headers: { "Content-Type": "application/json" },
1360
2492
  body: JSON.stringify(n),
1361
2493
  // keepalive lets the request survive a same-tick navigation when
1362
- // we missed pagehide (e.g. a window.location.assign from script).
2494
+ // pagehide didn't fire (e.g. a window.location.assign from script).
1363
2495
  keepalive: !0
1364
2496
  });
1365
- i.ok || (o = this.onError) == null || o.call(this, new Error(`monitor flush: HTTP ${i.status}`));
1366
- } catch (i) {
1367
- (s = this.onError) == null || s.call(this, i instanceof Error ? i : new Error(String(i)));
2497
+ a.ok || (o = this.onError) == null || o.call(this, new Error(`monitor flush: HTTP ${a.status}`));
2498
+ } catch (a) {
2499
+ (r = this.onError) == null || r.call(this, a instanceof Error ? a : new Error(String(a)));
1368
2500
  } finally {
1369
2501
  this.inflight = !1;
1370
2502
  }
1371
2503
  }
1372
- /** Synchronous flush via sendBeacon, used on pagehide. */
2504
+ /** Synchronous flush via sendBeacon, used on pagehide / visibility:hidden. */
1373
2505
  flushSync() {
1374
2506
  if (this.destroyed || this.buffer.length === 0) return;
1375
2507
  if (!navigator.sendBeacon) {
1376
2508
  this.flush();
1377
2509
  return;
1378
2510
  }
1379
- const e = this.buffer.splice(0), n = this.makeBatch(e), o = new Blob([JSON.stringify(n)], { type: "application/json" });
2511
+ const t = this.buffer.splice(0), n = this.makeBatch(t), o = new Blob([JSON.stringify(n)], { type: "application/json" });
1380
2512
  try {
1381
2513
  navigator.sendBeacon(this.url, o);
1382
2514
  } catch {
@@ -1385,10 +2517,10 @@ class Nt {
1385
2517
  destroy() {
1386
2518
  this.destroyed || (this.destroyed = !0, this.timer && clearInterval(this.timer), this.pagehideHandler && window.removeEventListener("pagehide", this.pagehideHandler), document.removeEventListener("visibilitychange", this.handleVisibilityChange), this.flushSync());
1387
2519
  }
1388
- makeBatch(e) {
2520
+ makeBatch(t) {
1389
2521
  return {
1390
2522
  sessionId: this.sessionId,
1391
- events: e,
2523
+ events: t,
1392
2524
  meta: {
1393
2525
  url: window.location.href,
1394
2526
  userAgent: navigator.userAgent,
@@ -1402,178 +2534,559 @@ class Nt {
1402
2534
  };
1403
2535
  }
1404
2536
  }
1405
- const U = "__lsBeaconMonitorUrl", H = "__lsBeaconMonitorSession", q = "__lsBeaconMonitorVerbose", F = "__lsBeaconMonitorDeadline", we = 30 * 6e4, be = 4096;
1406
- let m = null;
1407
- const Rt = /* @__PURE__ */ new Set();
1408
- let L = 0;
1409
- function ve() {
2537
+ const te = "__lsBeaconMonitorUrl", Be = "__lsBeaconMonitorSession", ne = "__lsBeaconMonitorVerbose", oe = "__lsBeaconMonitorDeadline", ze = 30 * 6e4, Ce = 4096;
2538
+ let E = null;
2539
+ const Z = /* @__PURE__ */ new Set();
2540
+ function $n() {
1410
2541
  return typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID().slice(0, 8) : Math.random().toString(36).slice(2, 10);
1411
2542
  }
1412
- function Pt(t) {
1413
- const e = /* @__PURE__ */ new WeakSet(), n = (o) => {
2543
+ function Bn(e) {
2544
+ const t = /* @__PURE__ */ new WeakSet(), n = (o) => {
1414
2545
  if (o === null || typeof o != "object")
1415
- return typeof o == "string" && o.length > be ? o.slice(0, be) : o;
1416
- if (e.has(o)) return "[cyclic]";
1417
- if (e.add(o), Array.isArray(o)) return o.map(n);
1418
- const s = {};
1419
- for (const i of Object.keys(o).slice(0, 50))
2546
+ return typeof o == "string" && o.length > Ce ? o.slice(0, Ce) : o;
2547
+ if (t.has(o)) return "[cyclic]";
2548
+ if (t.add(o), Array.isArray(o)) return o.map(n);
2549
+ const r = {};
2550
+ for (const a of Object.keys(o).slice(0, 50))
1420
2551
  try {
1421
- s[i] = n(o[i]);
2552
+ r[a] = n(o[a]);
1422
2553
  } catch {
1423
- s[i] = "[unreadable]";
2554
+ r[a] = "[unreadable]";
1424
2555
  }
1425
- return s;
2556
+ return r;
1426
2557
  };
1427
2558
  try {
1428
- return n(t);
2559
+ return n(e);
1429
2560
  } catch {
1430
2561
  return "[unserialisable]";
1431
2562
  }
1432
2563
  }
1433
- function xe() {
1434
- for (const t of Rt)
2564
+ function re() {
2565
+ for (const e of Z)
1435
2566
  try {
1436
- t(m !== null, (m == null ? void 0 : m.url) ?? null);
2567
+ e(E !== null, (E == null ? void 0 : E.url) ?? null);
1437
2568
  } catch {
1438
2569
  }
1439
2570
  }
1440
- function Dt(t) {
1441
- return m ? (m.seq += 1, {
1442
- ...t,
2571
+ function zn(e) {
2572
+ return E ? (E.seq += 1, {
2573
+ ...e,
1443
2574
  ts: Date.now(),
1444
- sessionId: m.sessionId,
1445
- seq: m.seq
2575
+ sessionId: E.sessionId,
2576
+ seq: E.seq
1446
2577
  }) : {
1447
- ...t,
2578
+ ...e,
1448
2579
  ts: Date.now(),
1449
2580
  sessionId: "",
1450
2581
  seq: 0
1451
2582
  };
1452
2583
  }
1453
- function T(t) {
1454
- if (!m) return;
1455
- const e = Dt(t);
1456
- m.transport.enqueue(e);
2584
+ function M(e) {
2585
+ if (!E) return;
2586
+ const t = zn(e);
2587
+ E.transport.enqueue(t);
1457
2588
  }
1458
- function Bt() {
1459
- if (m)
2589
+ function On() {
2590
+ if (E)
1460
2591
  try {
1461
- sessionStorage.setItem(U, m.url), sessionStorage.setItem(H, m.sessionId), sessionStorage.setItem(q, m.verbose ? "1" : "0"), sessionStorage.setItem(F, String(m.deadlineMs));
2592
+ sessionStorage.setItem(te, E.url), sessionStorage.setItem(Be, E.sessionId), sessionStorage.setItem(ne, E.verbose ? "1" : "0"), sessionStorage.setItem(oe, String(E.deadlineMs));
1462
2593
  } catch {
1463
2594
  }
1464
2595
  }
1465
- function Ee() {
2596
+ function Oe() {
1466
2597
  try {
1467
- sessionStorage.removeItem(U), sessionStorage.removeItem(H), sessionStorage.removeItem(q), sessionStorage.removeItem(F);
2598
+ sessionStorage.removeItem(te), sessionStorage.removeItem(Be), sessionStorage.removeItem(ne), sessionStorage.removeItem(oe);
1468
2599
  } catch {
1469
2600
  }
1470
2601
  }
1471
- function jt() {
2602
+ function Hn() {
1472
2603
  try {
1473
- const t = sessionStorage.getItem(U);
1474
- if (!t) return null;
1475
- const e = sessionStorage.getItem(H) ?? ve(), n = sessionStorage.getItem(q) === "1", o = sessionStorage.getItem(F), s = o ? Number(o) : Date.now() + we;
1476
- return Number.isFinite(s) && s <= Date.now() ? (Ee(), null) : { url: t, sessionId: e, verbose: n, deadlineMs: s };
2604
+ const e = sessionStorage.getItem(te);
2605
+ if (!e) return null;
2606
+ const t = sessionStorage.getItem(ne) === "1", n = sessionStorage.getItem(oe), o = n ? Number(n) : Date.now() + ze;
2607
+ return Number.isFinite(o) && o <= Date.now() ? (Oe(), null) : { url: e, verbose: t, deadlineMs: o };
1477
2608
  } catch {
1478
2609
  return null;
1479
2610
  }
1480
2611
  }
1481
- function Se(t) {
1482
- if (m && z(), !t.url) return;
1483
- const e = t.maxSessionMs ?? we, n = Date.now() + e, o = ve(), s = !!t.verbose, i = new Nt({
1484
- url: t.url,
2612
+ function ke(e) {
2613
+ E && (E.seq += 1, E.transport.enqueue({
2614
+ kind: e.kind,
2615
+ ts: e.ts,
2616
+ sessionId: E.sessionId,
2617
+ seq: E.seq,
2618
+ message: e.message,
2619
+ ...e.stack ? { stack: e.stack } : {},
2620
+ ...e.source ? { source: e.source } : {},
2621
+ ...typeof e.line == "number" ? { line: e.line } : {},
2622
+ ...typeof e.col == "number" ? { col: e.col } : {}
2623
+ }));
2624
+ }
2625
+ function He(e) {
2626
+ if (E && F(), !e.url) return;
2627
+ const t = e.maxSessionMs ?? ze, n = Date.now() + t, o = $n(), r = !!e.verbose, a = new Dn({
2628
+ url: e.url,
1485
2629
  sessionId: o,
1486
- onError: (u) => {
1487
- console.warn("[launch-kit-beacon] monitor transport error:", u.message);
1488
- }
1489
- }), r = M();
1490
- L = r.length;
1491
- for (const u of r) me(u, i, o);
1492
- const l = ge(() => {
1493
- const u = M();
1494
- for (; L < u.length; ) {
1495
- const g = u[L];
1496
- g && me(g, i, o), L += 1;
1497
- }
1498
- }), a = It({
1499
- emit: (u) => T(u),
1500
- verbose: s
1501
- }), c = Lt({
1502
- emitClick: (u) => T(u),
1503
- emitRoute: (u) => T(u),
1504
- emitDialog: (u) => T(u)
1505
- }), d = setTimeout(() => {
1506
- console.info("[launch-kit-beacon] monitor session expired (max duration reached)"), z();
2630
+ onError: (m) => {
2631
+ console.warn("[launch-kit-beacon] monitor transport error:", m.message);
2632
+ }
2633
+ }), i = Ie(), s = i.install(), c = i.snapshot();
2634
+ for (const m of c) ke(m);
2635
+ let d = c.length;
2636
+ const l = i.subscribe(() => {
2637
+ if (!E) return;
2638
+ const m = E.errorsBuffer.snapshot();
2639
+ for (; E.drainedThrough < m.length; ) {
2640
+ const x = m[E.drainedThrough];
2641
+ x && ke(x), E.drainedThrough += 1;
2642
+ }
2643
+ }), p = Rn({
2644
+ emit: (m) => M(m),
2645
+ verbose: r
2646
+ }), f = En({
2647
+ emitClick: (m) => M(m),
2648
+ emitRoute: (m) => M(m),
2649
+ emitDialog: (m) => M(m),
2650
+ emitSubmit: (m) => M(m)
2651
+ }), b = setTimeout(() => {
2652
+ console.info("[launch-kit-beacon] monitor session expired (max duration reached)"), F();
1507
2653
  }, Math.max(0, n - Date.now()));
1508
- m = {
1509
- url: t.url,
2654
+ E = {
2655
+ url: e.url,
1510
2656
  sessionId: o,
1511
- verbose: s,
2657
+ verbose: r,
1512
2658
  deadlineMs: n,
1513
2659
  seq: 0,
1514
- transport: i,
1515
- uninstallNetwork: a.uninstall,
1516
- uninstallDom: c.uninstall,
1517
- uninstallErrors: l,
1518
- deadlineTimer: d
1519
- }, Bt(), xe();
1520
- }
1521
- function me(t, e, n) {
1522
- m && (m.seq += 1, e.enqueue({
1523
- kind: t.kind,
1524
- ts: t.ts,
1525
- sessionId: n,
1526
- seq: m.seq,
1527
- message: t.message,
1528
- ...t.stack ? { stack: t.stack } : {},
1529
- ...t.source ? { source: t.source } : {},
1530
- ...typeof t.line == "number" ? { line: t.line } : {},
1531
- ...typeof t.col == "number" ? { col: t.col } : {}
1532
- }));
1533
- }
1534
- function z() {
1535
- m && (clearTimeout(m.deadlineTimer), m.uninstallNetwork(), m.uninstallDom(), m.uninstallErrors(), m.transport.destroy(), m = null, L = 0, Ee(), xe());
1536
- }
1537
- function Ot(t, e) {
1538
- m && T({
2660
+ transport: a,
2661
+ errorsBuffer: i,
2662
+ uninstallNetwork: p.uninstall,
2663
+ uninstallDom: f.uninstall,
2664
+ uninstallErrors: s,
2665
+ errorsUnsub: l,
2666
+ deadlineTimer: b,
2667
+ drainedThrough: d
2668
+ }, On(), re();
2669
+ }
2670
+ function F() {
2671
+ qe(), Oe(), re();
2672
+ }
2673
+ function qn() {
2674
+ E && (qe(), re());
2675
+ }
2676
+ function qe() {
2677
+ E && (clearTimeout(E.deadlineTimer), E.errorsUnsub(), E.uninstallErrors(), E.uninstallNetwork(), E.uninstallDom(), E.transport.destroy(), E = null);
2678
+ }
2679
+ function Qn(e, t) {
2680
+ E && M({
1539
2681
  kind: "probe",
1540
- label: t.slice(0, 200),
1541
- data: Pt(e)
2682
+ label: e.slice(0, 200),
2683
+ data: Bn(t)
1542
2684
  });
1543
2685
  }
1544
- function zt() {
1545
- return m !== null;
2686
+ function Ae() {
2687
+ return E !== null;
1546
2688
  }
1547
- function Ut() {
1548
- return (m == null ? void 0 : m.url) ?? null;
2689
+ function Le() {
2690
+ return (E == null ? void 0 : E.url) ?? null;
1549
2691
  }
1550
- const Ht = {
1551
- start: Se,
1552
- stop: z,
1553
- probe: Ot,
1554
- isActive: zt,
1555
- currentUrl: Ut
1556
- };
1557
- function qt() {
1558
- if (m) return;
1559
- const t = jt();
1560
- t && Se({
1561
- url: t.url,
1562
- verbose: t.verbose,
1563
- maxSessionMs: Math.max(6e4, t.deadlineMs - Date.now())
2692
+ function Ne(e) {
2693
+ return Z.add(e), () => {
2694
+ Z.delete(e);
2695
+ };
2696
+ }
2697
+ function Un() {
2698
+ if (E || typeof window > "u") return;
2699
+ const e = Hn();
2700
+ e && He({
2701
+ url: e.url,
2702
+ verbose: e.verbose,
2703
+ maxSessionMs: Math.max(6e4, e.deadlineMs - Date.now())
1564
2704
  });
1565
2705
  }
1566
- function Ft() {
2706
+ function eo(e = {}) {
2707
+ let t = null, n = null, o = "", r = null;
2708
+ function a() {
2709
+ r || (r = un({
2710
+ onStop: () => F(),
2711
+ url: Le()
2712
+ }));
2713
+ }
2714
+ function i() {
2715
+ if (r) {
2716
+ try {
2717
+ r.destroy();
2718
+ } catch {
2719
+ }
2720
+ r = null;
2721
+ }
2722
+ }
2723
+ function s() {
2724
+ if (!t) return;
2725
+ t.innerHTML = "";
2726
+ const l = document.createElement("div");
2727
+ l.className = "beacon-monitor-title", l.textContent = "Monitor — paste a stream URL", t.appendChild(l);
2728
+ const p = document.createElement("div");
2729
+ p.className = "beacon-monitor-row";
2730
+ const f = document.createElement("input");
2731
+ f.type = "url", f.className = "beacon-monitor-input", f.placeholder = "http://localhost:9876/m/…", f.value = o, f.autocomplete = "off", f.spellcheck = !1, p.appendChild(f);
2732
+ const b = document.createElement("button");
2733
+ b.type = "button", b.className = "beacon-monitor-btn", b.textContent = "Start", b.disabled = !o.trim(), p.appendChild(b), t.appendChild(p);
2734
+ const m = document.createElement("label");
2735
+ m.className = "beacon-monitor-verbose";
2736
+ const x = document.createElement("input");
2737
+ x.type = "checkbox", x.dataset.role = "verbose", m.appendChild(x), m.appendChild(document.createTextNode(" verbose (capture successful network too)")), t.appendChild(m);
2738
+ const g = document.createElement("div");
2739
+ g.className = "beacon-monitor-help", g.textContent = "Streams clicks, failed network, errors, route + dialog changes.", t.appendChild(g), f.addEventListener("input", () => {
2740
+ o = f.value, b.disabled = !f.value.trim();
2741
+ }), b.addEventListener("click", () => {
2742
+ const u = f.value.trim();
2743
+ if (u) {
2744
+ try {
2745
+ new URL(u);
2746
+ } catch {
2747
+ f.setCustomValidity("Enter a valid URL (e.g. http://localhost:9876/m/abc)"), f.reportValidity();
2748
+ return;
2749
+ }
2750
+ f.setCustomValidity(""), He({
2751
+ url: u,
2752
+ verbose: x.checked,
2753
+ ...e.maxSessionMs !== void 0 ? { maxSessionMs: e.maxSessionMs } : {}
2754
+ });
2755
+ }
2756
+ });
2757
+ }
2758
+ function c() {
2759
+ if (!t) return;
2760
+ t.innerHTML = "";
2761
+ const l = Le() ?? "", p = document.createElement("div");
2762
+ p.className = "beacon-monitor-title";
2763
+ const f = document.createElement("span");
2764
+ f.className = "beacon-monitor-rec", f.setAttribute("aria-hidden", "true"), p.appendChild(f), p.appendChild(document.createTextNode(" Monitor — recording")), t.appendChild(p);
2765
+ const b = document.createElement("div");
2766
+ b.className = "beacon-monitor-active-url", b.title = l, b.textContent = l, t.appendChild(b);
2767
+ const m = document.createElement("div");
2768
+ m.className = "beacon-monitor-row";
2769
+ const x = document.createElement("button");
2770
+ x.type = "button", x.className = "beacon-monitor-btn stop", x.textContent = "Stop monitoring", x.addEventListener("click", () => F()), m.appendChild(x), t.appendChild(m);
2771
+ const g = document.createElement("div");
2772
+ g.className = "beacon-monitor-help", g.textContent = "Events stream to the URL above. Auto-stops after 30 min.", t.appendChild(g);
2773
+ }
2774
+ function d() {
2775
+ Ae() ? c() : s();
2776
+ }
2777
+ return {
2778
+ name: "liveMonitor",
2779
+ setupOnce(l) {
2780
+ Un(), Ae() && a();
2781
+ const p = Ne((b, m) => {
2782
+ b ? (a(), r == null || r.updateUrl(m)) : i();
2783
+ }), f = () => {
2784
+ i(), p();
2785
+ try {
2786
+ qn();
2787
+ } catch {
2788
+ }
2789
+ };
2790
+ l.signal.addEventListener("abort", f, { once: !0 });
2791
+ },
2792
+ form() {
2793
+ return {
2794
+ render: (l) => (t = document.createElement("div"), t.className = "beacon-monitor", l.appendChild(t), d(), n = Ne(() => d()), () => {
2795
+ n == null || n(), n = null, t = null;
2796
+ })
2797
+ };
2798
+ }
2799
+ // No capture(): liveMonitor is a side-channel, not a feedback payload contributor.
2800
+ };
2801
+ }
2802
+ let A = null;
2803
+ const ae = {
2804
+ "plugin:error": /* @__PURE__ */ new Set(),
2805
+ "submit:success": /* @__PURE__ */ new Set(),
2806
+ "submit:error": /* @__PURE__ */ new Set(),
2807
+ ready: /* @__PURE__ */ new Set()
2808
+ };
2809
+ function to(e) {
1567
2810
  if (typeof window > "u") return;
1568
- const t = window;
1569
- t.__lsBeacon || (t.__lsBeacon = Ht);
2811
+ if (!e.endpoint) throw new Error("init: endpoint is required");
2812
+ Me(), jn();
2813
+ const t = { ...ct(), ...e.labels ?? {} }, n = new AbortController(), o = Yn(e), r = e.position ?? "bottom-right", a = e.theme ?? "auto";
2814
+ Ye(), Wn(e, r, a);
2815
+ const i = document.querySelector(B);
2816
+ if (!i)
2817
+ throw new Error("init: failed to acquire <launch-kit-beacon> host");
2818
+ if (!i.shadow)
2819
+ throw new Error("init: host element shadow root not initialized");
2820
+ const s = lt(i.shadow), c = new st(
2821
+ t,
2822
+ ["bug", "idea", "ux", "a11y"],
2823
+ {
2824
+ onSubmit: () => {
2825
+ Gn();
2826
+ },
2827
+ onClose: (p) => {
2828
+ j("close", {}), p === "user" && Fe();
2829
+ }
2830
+ }
2831
+ );
2832
+ i.shadow.appendChild(c.root), i.classList.add("beacon-no-capture");
2833
+ const d = Qe(o), l = {
2834
+ endpoint: e.endpoint,
2835
+ headers: e.headers,
2836
+ context: e.context,
2837
+ credentials: e.credentials ?? "omit",
2838
+ plugins: o,
2839
+ registry: d,
2840
+ dialog: c,
2841
+ overlayHost: s,
2842
+ hostElement: i,
2843
+ initAbort: n,
2844
+ labels: t,
2845
+ debug: !!e.debug || Xn(),
2846
+ healthIndicator: e.healthIndicator ?? "never",
2847
+ position: r,
2848
+ theme: a,
2849
+ currentSubmit: null,
2850
+ capturedEntries: {},
2851
+ formValues: {},
2852
+ lifecycleHandlers: {
2853
+ open: /* @__PURE__ */ new Set(),
2854
+ close: /* @__PURE__ */ new Set(),
2855
+ beforeSubmit: /* @__PURE__ */ new Set(),
2856
+ afterSubmit: /* @__PURE__ */ new Set()
2857
+ },
2858
+ panelSources: []
2859
+ };
2860
+ A = l, i.onTriggerClick = () => Fn(), d.install(
2861
+ (p) => Ue(p),
2862
+ (p) => ie(p)
2863
+ ), $("ready", { ready: !0 }), l.debug && console.info("[beacon] ready", l.endpoint);
2864
+ }
2865
+ function Fn() {
2866
+ const e = A;
2867
+ e && (e.currentSubmit || (e.panelSources = e.plugins.map((t) => {
2868
+ if (!t.form) return null;
2869
+ const n = Ue(t.name);
2870
+ let o;
2871
+ try {
2872
+ o = t.form(n);
2873
+ } catch (r) {
2874
+ return ie({
2875
+ plugin: t.name,
2876
+ error: r instanceof Error ? r : new Error(String(r)),
2877
+ at: "form"
2878
+ }), null;
2879
+ }
2880
+ return { name: t.name, form: o, ctx: n };
2881
+ }).filter((t) => t !== null), e.dialog.installPluginPanels(e.panelSources, {
2882
+ get: (t, n) => {
2883
+ var o;
2884
+ return (o = e.formValues[t]) == null ? void 0 : o[n];
2885
+ },
2886
+ set: (t, n, o) => {
2887
+ var a;
2888
+ const r = (a = e.formValues)[t] ?? (a[t] = {});
2889
+ r[n] = o;
2890
+ }
2891
+ }), e.dialog.open(), j("open", {})));
2892
+ }
2893
+ function no() {
2894
+ const e = A;
2895
+ e && e.dialog.close("user");
2896
+ }
2897
+ function jn() {
2898
+ var t;
2899
+ const e = A;
2900
+ if (e) {
2901
+ e.initAbort.abort(), (t = e.currentSubmit) == null || t.abort(), e.registry.destroy(), D();
2902
+ try {
2903
+ e.dialog.root.remove(), e.overlayHost.layer.remove();
2904
+ } catch {
2905
+ }
2906
+ e.hostElement.onTriggerClick = null, A = null;
2907
+ }
2908
+ }
2909
+ function oo() {
2910
+ const e = A;
2911
+ return e ? {
2912
+ ready: !0,
2913
+ transport: "idle",
2914
+ plugins: e.registry.status()
2915
+ } : { ready: !1, transport: "idle", plugins: {} };
2916
+ }
2917
+ function ro(e, t) {
2918
+ return ae[e].add(t), () => Vn(e, t);
2919
+ }
2920
+ function Vn(e, t) {
2921
+ ae[e].delete(t);
2922
+ }
2923
+ function Wn(e, t, n) {
2924
+ let o = document.querySelector(B);
2925
+ if (!o) {
2926
+ o = document.createElement(B), o.setAttribute("position", t), o.setAttribute("theme", n), t === "hidden" && (o.style.position = "absolute", o.style.left = "-9999px"), (document.body ?? document.documentElement).appendChild(o);
2927
+ return;
2928
+ }
2929
+ e.position !== void 0 && o.setAttribute("position", t), e.theme !== void 0 && o.setAttribute("theme", n);
2930
+ }
2931
+ function Yn(e) {
2932
+ return e.plugins ? e.plugins : e.defaultPlugins === !1 ? [] : Kn();
2933
+ }
2934
+ function Kn() {
2935
+ return [pt(), xt(), rn(), sn()];
2936
+ }
2937
+ function Xn() {
2938
+ if (typeof window > "u") return !1;
2939
+ try {
2940
+ return new URLSearchParams(window.location.search).has("lsbeacon-debug");
2941
+ } catch {
2942
+ return !1;
2943
+ }
2944
+ }
2945
+ function Ue(e) {
2946
+ const t = A;
2947
+ return Je(e, {
2948
+ getCaptured: (o) => t == null ? void 0 : t.capturedEntries[o],
2949
+ getFormValues: (o) => {
2950
+ var r;
2951
+ return t ? (r = t.formValues)[o] ?? (r[o] = {}) : {};
2952
+ },
2953
+ getCaptureSignal: () => {
2954
+ var o;
2955
+ return (o = t == null ? void 0 : t.currentSubmit) == null ? void 0 : o.signal;
2956
+ },
2957
+ getInitSignal: () => t.initAbort.signal,
2958
+ requestMode: async (o) => t ? t.dialog.requestMode(o) : () => {
2959
+ },
2960
+ overlay: (o) => t ? dt(t.overlayHost, o.render) : () => {
2961
+ },
2962
+ onLifecycle: (o, r) => {
2963
+ if (!t) return () => {
2964
+ };
2965
+ const a = t.lifecycleHandlers[o];
2966
+ return a.add(r), () => a.delete(r);
2967
+ }
2968
+ });
2969
+ }
2970
+ function j(e, t) {
2971
+ const n = A;
2972
+ if (n)
2973
+ for (const o of n.lifecycleHandlers[e])
2974
+ try {
2975
+ o(t);
2976
+ } catch (r) {
2977
+ n.debug && console.error("[beacon] lifecycle handler threw:", r);
2978
+ }
2979
+ }
2980
+ function $(e, t) {
2981
+ for (const n of ae[e])
2982
+ try {
2983
+ n(t);
2984
+ } catch (o) {
2985
+ A != null && A.debug && console.error("[beacon] system handler threw:", o);
2986
+ }
2987
+ }
2988
+ function ie(e) {
2989
+ $("plugin:error", { plugin: e.plugin, error: e.error, at: e.at });
2990
+ const t = A;
2991
+ t && ((t.healthIndicator === "always" || t.healthIndicator === "dev" && t.debug) && t.hostElement.setHealthIndicator(!0), t.debug && console.warn(`[beacon] plugin "${e.plugin}" ${e.at} failed:`, e.error));
2992
+ }
2993
+ function Fe() {
2994
+ const e = A;
2995
+ e && (e.dialog.resetState(), e.dialog.clearPluginPanels(), e.formValues = {});
2996
+ }
2997
+ async function Gn() {
2998
+ const e = A;
2999
+ if (!e || e.currentSubmit) return;
3000
+ const t = e.dialog.getDescription().trim();
3001
+ if (!t) {
3002
+ e.dialog.setStatus("Description is required", "error");
3003
+ return;
3004
+ }
3005
+ e.currentSubmit = new AbortController(), e.capturedEntries = {}, e.dialog.setSubmitting(!0), e.dialog.setStatus("Capturing…");
3006
+ let n = null;
3007
+ try {
3008
+ const o = await e.registry.capture(
3009
+ (s) => e.capturedEntries[s],
3010
+ (s) => ie(s)
3011
+ );
3012
+ e.capturedEntries = o, n = Jn(e, t, o);
3013
+ let r = null;
3014
+ if (j("beforeSubmit", { payload: n, cancel: (s) => {
3015
+ r === null && (r = s);
3016
+ } }), r !== null) {
3017
+ e.dialog.setSubmitting(!1), e.dialog.setStatus(`Cancelled: ${r}`, "error");
3018
+ return;
3019
+ }
3020
+ e.dialog.setStatus("Sending…");
3021
+ const i = await nt(
3022
+ e.endpoint,
3023
+ n,
3024
+ e.headers,
3025
+ e.currentSubmit.signal,
3026
+ e.credentials
3027
+ );
3028
+ j("afterSubmit", { payload: n, response: i }), e.dialog.setSubmitting(!1), i.ok ? ($("submit:success", { payload: n, response: i }), e.dialog.setSubmitSucceeded(!0), e.dialog.setStatus(e.labels.sentSuccess, "success"), window.setTimeout(() => {
3029
+ A === e && e.dialog.close("submitted"), Fe();
3030
+ }, 1500)) : ($("submit:error", { payload: n, error: new Error(`HTTP ${i.status}`) }), e.dialog.setStatus(`Failed (${i.status})`, "error"));
3031
+ } catch (o) {
3032
+ e.dialog.setSubmitting(!1);
3033
+ const r = o instanceof Error ? o : new Error(String(o));
3034
+ n && $("submit:error", { payload: n, error: r }), e.dialog.setStatus(`Failed: ${r.message}`, "error");
3035
+ } finally {
3036
+ e.currentSubmit = null;
3037
+ }
3038
+ }
3039
+ function Jn(e, t, n) {
3040
+ var a;
3041
+ const o = Zn(), r = (a = e.context) == null ? void 0 : a.call(e);
3042
+ return {
3043
+ description: t,
3044
+ severity: e.dialog.getSeverity(),
3045
+ metadata: o,
3046
+ ...r ? { context: r } : {},
3047
+ plugins: n
3048
+ };
3049
+ }
3050
+ function Zn() {
3051
+ const e = window.location.href, t = document.referrer, n = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
3052
+ return {
3053
+ url: e,
3054
+ ...t ? { referrer: t } : {},
3055
+ userAgent: navigator.userAgent,
3056
+ viewport: {
3057
+ w: window.innerWidth,
3058
+ h: window.innerHeight,
3059
+ dpr: window.devicePixelRatio || 1
3060
+ },
3061
+ screen: {
3062
+ w: window.screen.width,
3063
+ h: window.screen.height
3064
+ },
3065
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
3066
+ locale: navigator.language,
3067
+ theme: n,
3068
+ capturedAt: (/* @__PURE__ */ new Date()).toISOString()
3069
+ };
1570
3070
  }
1571
- gt();
1572
- ut();
1573
- Ft();
1574
- qt();
3071
+ Me();
1575
3072
  export {
1576
- mt as LaunchKitBeacon,
1577
- gt as defineBeacon
3073
+ Le as currentMonitorUrl,
3074
+ jn as destroy,
3075
+ rn as domEle,
3076
+ sn as domSS,
3077
+ xt as errors,
3078
+ no as hide,
3079
+ to as init,
3080
+ Ae as isMonitorActive,
3081
+ an as isPluginFailure,
3082
+ eo as liveMonitor,
3083
+ pt as metadata,
3084
+ Vn as off,
3085
+ ro as on,
3086
+ Qn as probe,
3087
+ Fn as show,
3088
+ He as startMonitor,
3089
+ oo as status,
3090
+ F as stopMonitor
1578
3091
  };
1579
3092
  //# sourceMappingURL=beacon.mjs.map