@launchsecure/launch-kit 0.0.29 → 0.0.31

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 (202) hide show
  1. package/dist/beacon/beacon.mjs +2825 -1243
  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/internal/screenshot.d.ts +26 -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/chart-client/assets/{index-CJ4mgRRF.css → index-CDIhdgWg.css} +1 -1
  71. package/dist/chart-client/index.html +2 -2
  72. package/dist/client/assets/{index-DI5qSR_w.css → index-CfW4n40I.css} +1 -1
  73. package/dist/client/index.html +2 -2
  74. package/dist/council-client/assets/{index-C_-vAM9L.css → index-CZim6x1u.css} +1 -1
  75. package/dist/council-client/index.html +2 -2
  76. package/dist/deck-client/assets/{_baseUniq-W2JQDmje.js → _baseUniq-DdHaBFYO.js} +1 -1
  77. package/dist/deck-client/assets/{arc-DIBWAId9.js → arc-D98e_18X.js} +1 -1
  78. package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-CAIRMvJK.js → architectureDiagram-Q4EWVU46-DNFZzh-4.js} +1 -1
  79. package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-BeNaNiOi.js → blockDiagram-DXYQGD6D-DeQvGUdX.js} +1 -1
  80. package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-B9Ozi62h.js → c4Diagram-AHTNJAMY-B6ekZf1n.js} +1 -1
  81. package/dist/deck-client/assets/channel-DmR7Tyyt.js +1 -0
  82. package/dist/deck-client/assets/{chunk-4BX2VUAB-D7AZ47dt.js → chunk-4BX2VUAB-9aDWymq2.js} +1 -1
  83. package/dist/deck-client/assets/{chunk-4TB4RGXK-DnVnNPcI.js → chunk-4TB4RGXK-DtKQqaI7.js} +1 -1
  84. package/dist/deck-client/assets/{chunk-55IACEB6-UKYs-YNd.js → chunk-55IACEB6-COy9hEae.js} +1 -1
  85. package/dist/deck-client/assets/{chunk-EDXVE4YY-D43b-SKn.js → chunk-EDXVE4YY-D_f861An.js} +1 -1
  86. package/dist/deck-client/assets/{chunk-FMBD7UC4-QzBAoyyW.js → chunk-FMBD7UC4-CmuA5UKn.js} +1 -1
  87. package/dist/deck-client/assets/{chunk-OYMX7WX6-Cjif4r6W.js → chunk-OYMX7WX6-vT8z8D-0.js} +1 -1
  88. package/dist/deck-client/assets/{chunk-QZHKN3VN-CqLDirEI.js → chunk-QZHKN3VN-CTlwwg-R.js} +1 -1
  89. package/dist/deck-client/assets/{chunk-YZCP3GAM-_FQvmMs4.js → chunk-YZCP3GAM-C44yr620.js} +1 -1
  90. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-Bl4ozQWs.js +1 -0
  91. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-Bl4ozQWs.js +1 -0
  92. package/dist/deck-client/assets/clone-BAy58j24.js +1 -0
  93. package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-rfrocesE.js → cose-bilkent-S5V4N54A-DBB2J2nL.js} +1 -1
  94. package/dist/deck-client/assets/{dagre-KV5264BT-Bv_7DJat.js → dagre-KV5264BT-DxDTYbKl.js} +1 -1
  95. package/dist/deck-client/assets/{diagram-5BDNPKRD-4F1414G5.js → diagram-5BDNPKRD-DByWrWd1.js} +1 -1
  96. package/dist/deck-client/assets/{diagram-G4DWMVQ6-C4-Pszqm.js → diagram-G4DWMVQ6-B8B6ddMq.js} +1 -1
  97. package/dist/deck-client/assets/{diagram-MMDJMWI5-B647TIx9.js → diagram-MMDJMWI5-BMUZ2PWK.js} +1 -1
  98. package/dist/deck-client/assets/{diagram-TYMM5635-BFAqpezd.js → diagram-TYMM5635-Bk9e8BB-.js} +1 -1
  99. package/dist/deck-client/assets/{erDiagram-SMLLAGMA-BfBfrJOC.js → erDiagram-SMLLAGMA-DcOSwSol.js} +1 -1
  100. package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-DX9YAYes.js → flowDiagram-DWJPFMVM-DI-4BR0F.js} +1 -1
  101. package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-DCuiy7wF.js → ganttDiagram-T4ZO3ILL-BeZuXBoU.js} +1 -1
  102. package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-CGp1IXUh.js → gitGraphDiagram-UUTBAWPF-Bcki__f-.js} +1 -1
  103. package/dist/deck-client/assets/{graph-B7g8aoxv.js → graph-CifKx6G1.js} +1 -1
  104. package/dist/deck-client/assets/index-6sdqbm2o.js +2 -0
  105. package/dist/deck-client/assets/{index-DsIZ3LqL.css → index-BlTlhxFW.css} +1 -1
  106. package/dist/deck-client/assets/index-CB-qlwRT.js +1195 -0
  107. package/dist/deck-client/assets/{infoDiagram-42DDH7IO-L3fahMkF.js → infoDiagram-42DDH7IO-CReN1nFN.js} +1 -1
  108. package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-aS_EjWBZ.js → ishikawaDiagram-UXIWVN3A-CDF_VLN_.js} +1 -1
  109. package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-djTSQZF9.js → journeyDiagram-VCZTEJTY-DwgGrNVB.js} +1 -1
  110. package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-CcTHo4CM.js → kanban-definition-6JOO6SKY-DB_zohh5.js} +1 -1
  111. package/dist/deck-client/assets/{layout-mEJiadb7.js → layout-DFfX1O3z.js} +1 -1
  112. package/dist/deck-client/assets/{linear-XgTKqyRu.js → linear-CtKb4EXj.js} +1 -1
  113. package/dist/deck-client/assets/{min-Ct9jZdpd.js → min-DCRRwUZv.js} +1 -1
  114. package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-BaFxCGNU.js → mindmap-definition-QFDTVHPH-D0QBOiFe.js} +1 -1
  115. package/dist/deck-client/assets/{pieDiagram-DEJITSTG-CIbYYjtw.js → pieDiagram-DEJITSTG-CD-EV5WB.js} +1 -1
  116. package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-D9EtCOvh.js → quadrantDiagram-34T5L4WZ-B-JXZ8xI.js} +1 -1
  117. package/dist/deck-client/assets/{requirementDiagram-MS252O5E-xeni9eVG.js → requirementDiagram-MS252O5E-D2_OK5Dp.js} +1 -1
  118. package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-LYeknz9h.js → sankeyDiagram-XADWPNL6-BbBJqVSC.js} +1 -1
  119. package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-RDbsKFZf.js → sequenceDiagram-FGHM5R23-Db8A-Rkk.js} +1 -1
  120. package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-BH1Zjglk.js → stateDiagram-FHFEXIEX-DGJnanjS.js} +1 -1
  121. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-CR7riiab.js +1 -0
  122. package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-IFXxKptt.js → timeline-definition-GMOUNBTQ-BRkr6T4w.js} +1 -1
  123. package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-D-sLkQs9.js → vennDiagram-DHZGUBPP-d0rsTqFo.js} +1 -1
  124. package/dist/deck-client/assets/{wardley-RL74JXVD-C010F8l4.js → wardley-RL74JXVD-2t7cMqdS.js} +1 -1
  125. package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-BTjjuDU3.js → wardleyDiagram-NUSXRM2D-DzboAsHh.js} +1 -1
  126. package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-AYbv92n-.js → xychartDiagram-5P7HB3ND-CgTP9u2V.js} +1 -1
  127. package/dist/deck-client/index.html +2 -2
  128. package/dist/server/beacon-monitor-entry.js +548 -6
  129. package/dist/server/chart-serve.js +917 -248
  130. package/dist/server/cli.js +2033 -385
  131. package/dist/server/deck-mcp-entry.js +141 -21
  132. package/dist/server/deck-serve.js +141 -21
  133. package/dist/server/graph-mcp-entry.js +1991 -333
  134. package/dist/server/init-entry.js +24 -13
  135. package/dist/server/orbit-entry.js +135 -7
  136. package/dist/server/parse-worker-entry.js +918 -247
  137. package/package.json +4 -2
  138. package/scaffolds/ls-marketplace/plugins/kit/skills/analyse/SKILL.md +180 -0
  139. package/scaffolds/ls-marketplace/plugins/kit/skills/beacon-array/SKILL.md +107 -0
  140. package/scaffolds/ls-marketplace/plugins/kit/skills/beacon-clear/SKILL.md +94 -0
  141. package/scaffolds/ls-marketplace/plugins/kit/skills/beacon-pulse/SKILL.md +82 -0
  142. package/scaffolds/ls-marketplace/plugins/kit/skills/beacon-scan/SKILL.md +66 -0
  143. package/scaffolds/ls-marketplace/plugins/kit/skills/blast-radius/SKILL.md +117 -0
  144. package/scaffolds/ls-marketplace/plugins/kit/skills/brief/SKILL.md +112 -0
  145. package/scaffolds/ls-marketplace/plugins/kit/skills/course/SKILL.md +84 -0
  146. package/scaffolds/ls-marketplace/plugins/kit/skills/debug/SKILL.md +85 -0
  147. package/scaffolds/ls-marketplace/plugins/kit/skills/deploy-check/SKILL.md +160 -0
  148. package/scaffolds/ls-marketplace/plugins/kit/skills/diagram/SKILL.md +152 -0
  149. package/scaffolds/ls-marketplace/plugins/kit/skills/orbit/SKILL.md +87 -0
  150. package/scaffolds/ls-marketplace/plugins/kit/skills/prototype/SKILL.md +110 -0
  151. package/scaffolds/ls-marketplace/plugins/kit/skills/recovery/SKILL.md +95 -0
  152. package/scaffolds/ls-marketplace/plugins/kit/{commands/show-mcp-status.md → skills/show-mcp-status/SKILL.md} +4 -4
  153. package/scaffolds/ls-marketplace/plugins/kit/skills/wireframe/SKILL.md +90 -0
  154. package/scaffolds/statusline/statusline-mcp.sh +21 -9
  155. package/dist/beacon/types/capture/element.d.ts +0 -3
  156. package/dist/beacon/types/capture/element.d.ts.map +0 -1
  157. package/dist/beacon/types/capture/events.d.ts +0 -20
  158. package/dist/beacon/types/capture/events.d.ts.map +0 -1
  159. package/dist/beacon/types/capture/framework.d.ts +0 -3
  160. package/dist/beacon/types/capture/framework.d.ts.map +0 -1
  161. package/dist/beacon/types/capture/metadata.d.ts +0 -3
  162. package/dist/beacon/types/capture/metadata.d.ts.map +0 -1
  163. package/dist/beacon/types/capture/overlay.d.ts +0 -7
  164. package/dist/beacon/types/capture/overlay.d.ts.map +0 -1
  165. package/dist/beacon/types/capture/picker.d.ts.map +0 -1
  166. package/dist/beacon/types/capture/screenshot.d.ts +0 -7
  167. package/dist/beacon/types/capture/screenshot.d.ts.map +0 -1
  168. package/dist/beacon/types/capture/selector.d.ts.map +0 -1
  169. package/dist/beacon/types/monitor/dom.d.ts +0 -13
  170. package/dist/beacon/types/monitor/dom.d.ts.map +0 -1
  171. package/dist/beacon/types/monitor/index.d.ts +0 -19
  172. package/dist/beacon/types/monitor/index.d.ts.map +0 -1
  173. package/dist/beacon/types/monitor/network.d.ts +0 -12
  174. package/dist/beacon/types/monitor/network.d.ts.map +0 -1
  175. package/dist/beacon/types/monitor/transport.d.ts.map +0 -1
  176. package/dist/beacon/types/monitor/types.d.ts.map +0 -1
  177. package/dist/beacon/types/transport/submit.d.ts +0 -3
  178. package/dist/beacon/types/transport/submit.d.ts.map +0 -1
  179. package/dist/beacon/types/ui/button.d.ts +0 -2
  180. package/dist/beacon/types/ui/button.d.ts.map +0 -1
  181. package/dist/beacon/types/ui/drawer.d.ts +0 -33
  182. package/dist/beacon/types/ui/drawer.d.ts.map +0 -1
  183. package/dist/beacon/types/ui/icons.d.ts +0 -9
  184. package/dist/beacon/types/ui/icons.d.ts.map +0 -1
  185. package/dist/beacon/types/ui/monitor-panel.d.ts +0 -19
  186. package/dist/beacon/types/ui/monitor-panel.d.ts.map +0 -1
  187. package/dist/beacon/types/ui/pick-mode-overlay.d.ts.map +0 -1
  188. package/dist/beacon/types/ui/pin-popover.d.ts.map +0 -1
  189. package/dist/deck-client/assets/channel-CRdozqbp.js +0 -1
  190. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-lIZMp57W.js +0 -1
  191. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-lIZMp57W.js +0 -1
  192. package/dist/deck-client/assets/clone-BtWeSTyJ.js +0 -1
  193. package/dist/deck-client/assets/index-Dg1r-WSN.js +0 -476
  194. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-BrV78NDR.js +0 -1
  195. package/scaffolds/ls-marketplace/plugins/kit/commands/beacon-array.md +0 -92
  196. package/scaffolds/ls-marketplace/plugins/kit/commands/beacon-clear.md +0 -68
  197. package/scaffolds/ls-marketplace/plugins/kit/commands/beacon-pulse.md +0 -80
  198. package/scaffolds/ls-marketplace/plugins/kit/commands/beacon-scan.md +0 -62
  199. /package/dist/beacon/types/{capture → internal}/selector.d.ts +0 -0
  200. /package/dist/chart-client/assets/{index-Ccy-DpI-.js → index-B__ARB8k.js} +0 -0
  201. /package/dist/client/assets/{index-Dp0_okva.js → index-h8kMzVtG.js} +0 -0
  202. /package/dist/council-client/assets/{index-Dt4zWKSj.js → index-CWaDcsFR.js} +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 Me = 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 Xe() {
698
+ if (typeof document > "u" || !document.head || document.getElementById(se)) return;
699
+ const e = document.createElement("style");
700
+ e.id = se, e.textContent = Me, 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 z = "launch-kit-beacon", Ge = typeof HTMLElement < "u" ? HTMLElement : class {
712
+ };
713
+ class Je extends Ge {
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 = Me, 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 a of o)
731
+ a.addEventListener("click", () => {
732
+ var r;
733
+ return (r = this.onTriggerClick) == null ? void 0 : r.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;
324
- }
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`;
328
- }
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;
340
- }
341
- }
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
- });
748
+ }
749
+ function Ie() {
750
+ typeof window > "u" || typeof customElements > "u" || customElements.get(z) || customElements.define(z, Je);
751
+ }
752
+ function Ze(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 Qe extends Error {
769
+ constructor(t) {
770
+ super(`Duplicate plugin name: "${t}"`), this.name = "DuplicatePluginNameError";
349
771
  }
350
- let x = null;
351
- function v() {
352
- x === null && (x = requestAnimationFrame(() => {
353
- x = null, w();
354
- }));
772
+ }
773
+ function et(e) {
774
+ const t = /* @__PURE__ */ new Set();
775
+ for (const o of e) {
776
+ if (t.has(o.name)) throw new Qe(o.name);
777
+ t.add(o.name);
355
778
  }
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
- },
361
- setLoading(h) {
362
- h ? r.innerHTML = l + a(h) : r.textContent = K;
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, a) {
788
+ for (const r of n)
789
+ if (r.ctx = o(r.plugin.name), !!r.plugin.setupOnce)
790
+ try {
791
+ const i = r.plugin.setupOnce(r.ctx);
792
+ typeof i == "function" && (r.teardown = i);
793
+ } catch (i) {
794
+ const s = i instanceof Error ? i : new Error(String(i));
795
+ r.status = {
796
+ state: "failed",
797
+ failures: r.status.failures + 1,
798
+ error: { message: s.message, ...s.stack ? { stack: s.stack } : {}, at: "setupOnce" }
799
+ }, a({ plugin: r.plugin.name, error: s, at: "setupOnce" });
800
+ }
363
801
  },
364
802
  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();
803
+ var o;
804
+ for (const a of n) {
805
+ try {
806
+ (o = a.teardown) == null || o.call(a);
807
+ } catch {
808
+ }
809
+ a.teardown = void 0;
810
+ }
811
+ },
812
+ async capture(o, a) {
813
+ const r = {};
814
+ for (const i of n)
815
+ if (i.plugin.capture)
816
+ try {
817
+ const s = await i.plugin.capture(i.ctx), c = tt(s, i.plugin.version);
818
+ c !== null && (r[i.plugin.name] = c);
819
+ } catch (s) {
820
+ const c = s instanceof Error ? s : new Error(String(s));
821
+ r[i.plugin.name] = nt(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
+ }, a({ plugin: i.plugin.name, error: c, at: "capture" });
826
+ }
827
+ return r;
828
+ },
829
+ status() {
830
+ const o = {};
831
+ for (const a of n)
832
+ o[a.plugin.name] = a.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 tt(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 nt(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 ot(e, t, n, o, a = "omit") {
849
+ const r = await rt(n), i = await fetch(e, {
850
+ method: "POST",
851
+ credentials: a,
852
+ headers: { "Content-Type": "application/json", ...r },
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 rt(e) {
859
+ return e ? typeof e == "function" ? await e() ?? {} : e : {};
860
+ }
861
+ function at(e, t, n) {
862
+ for (const o of t) {
863
+ const a = document.createElement("div");
864
+ if (a.className = "beacon-field", o.label) {
865
+ const i = document.createElement("label");
866
+ i.className = "beacon-label", i.textContent = o.label, a.appendChild(i);
867
+ }
868
+ if (o.description) {
869
+ const i = document.createElement("div");
870
+ i.className = "beacon-description", i.textContent = o.description, a.appendChild(i);
871
+ }
872
+ const r = it(o, n);
873
+ a.appendChild(r), e.appendChild(a);
874
+ }
875
+ }
876
+ function it(e, t) {
877
+ var o, a;
878
+ const n = t.get(e.name);
879
+ switch (e.type) {
880
+ case "toggle": {
881
+ const r = document.createElement("label");
882
+ r.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)), r.appendChild(i), t.set(e.name, i.checked), r;
885
+ }
886
+ case "text": {
887
+ const r = document.createElement("input");
888
+ r.type = "text", r.className = "beacon-input";
889
+ const i = n ?? e.defaultValue ?? "";
890
+ return r.value = i, e.placeholder && (r.placeholder = e.placeholder), r.addEventListener("input", () => t.set(e.name, r.value)), t.set(e.name, i), r;
891
+ }
892
+ case "textarea": {
893
+ const r = document.createElement("textarea");
894
+ r.className = "beacon-textarea";
895
+ const i = n ?? e.defaultValue ?? "";
896
+ return r.value = i, e.placeholder && (r.placeholder = e.placeholder), e.rows && (r.rows = e.rows), r.addEventListener("input", () => t.set(e.name, r.value)), t.set(e.name, i), r;
897
+ }
898
+ case "select": {
899
+ const r = document.createElement("select");
900
+ r.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), r.appendChild(c);
905
+ }
906
+ return r.addEventListener("change", () => t.set(e.name, r.value)), t.set(e.name, i), r;
907
+ }
908
+ case "radio": {
909
+ const r = document.createElement("div");
910
+ r.className = "beacon-radio-group";
911
+ const i = n ?? e.defaultValue ?? ((a = e.options[0]) == null ? void 0 : a.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), r.appendChild(c);
919
+ }
920
+ return t.set(e.name, i), r;
921
+ }
922
+ case "number": {
923
+ const r = document.createElement("input");
924
+ r.type = "number", r.className = "beacon-input";
925
+ const i = n ?? e.defaultValue;
926
+ return i !== void 0 && (r.value = String(i)), e.min !== void 0 && (r.min = String(e.min)), e.max !== void 0 && (r.max = String(e.max)), e.step !== void 0 && (r.step = String(e.step)), r.addEventListener("input", () => {
927
+ const s = r.value === "" ? void 0 : Number(r.value);
928
+ t.set(e.name, s);
929
+ }), i !== void 0 && t.set(e.name, i), r;
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 st() {
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 ct {
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 a = document.createElement("div");
946
+ a.className = "beacon-drawer-header";
947
+ const r = document.createElement("div");
948
+ r.className = "beacon-drawer-title", r.textContent = t.drawerTitle, a.appendChild(r);
949
+ const i = document.createElement("button");
950
+ i.type = "button", i.className = "beacon-icon-btn", i.setAttribute("aria-label", t.closeButton), i.appendChild(st()), i.addEventListener("click", () => this.userCloseAttempt()), a.appendChild(i), this.inner.appendChild(a), this.root.addEventListener("cancel", (g) => {
951
+ this.submitSucceeded || this.hasUnsavedInput() && (g.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 m = document.createElement("label");
962
+ m.className = "beacon-label", m.textContent = t.severityLabel, this.severitiesContainer = document.createElement("div"), this.severitiesContainer.className = "beacon-severity";
963
+ for (const g of n) {
964
+ const u = document.createElement("label");
965
+ u.className = "beacon-severity-opt", u.dataset.sev = g;
966
+ const v = document.createElement("input");
967
+ v.type = "radio", v.name = "beacon-severity", v.value = g, g === this.severitySelected && (v.checked = !0, u.classList.add("selected")), v.addEventListener("change", () => this.setSeverity(g)), u.appendChild(v), u.appendChild(document.createTextNode(this.severityLabel(g))), this.severitiesContainer.appendChild(u);
968
+ }
969
+ l.appendChild(m), 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 p = document.createElement("div");
971
+ p.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()), p.appendChild(this.submitBtn), s.appendChild(p), 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
+ };
425
986
  }
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`;
987
+ applyMode(t, n) {
988
+ var o, a;
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(), (a = (o = this.lastActive) == null ? void 0 : o.focus) == null || a.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 r = this.inner.querySelector(".beacon-drawer-body");
1000
+ r && (r.style.display = n ? "none" : "");
1001
+ break;
1002
+ }
1003
+ }
433
1004
  }
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));
1005
+ // ── Public surface ──────────────────────────────────────────
1006
+ open() {
1007
+ this.root.open || this.tryShowModal();
437
1008
  }
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);
1009
+ close(t = "user") {
1010
+ this.root.open && this.root.close(), t === "submitted" && (this.statusEl.textContent = "");
443
1011
  }
444
- function v(p) {
445
- p.preventDefault(), p.stopPropagation();
1012
+ userCloseAttempt() {
1013
+ !this.submitSucceeded && this.hasUnsavedInput() && !window.confirm("You have unsaved feedback. Discard?") || this.root.open && this.root.close();
446
1014
  }
447
- function h(p) {
448
- p.key === "Escape" && (p.preventDefault(), f(null));
1015
+ hasUnsavedInput() {
1016
+ return this.descTextarea.value.trim().length > 0;
449
1017
  }
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));
1018
+ setSubmitSucceeded(t) {
1019
+ this.submitSucceeded = t;
452
1020
  }
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
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 a = document.createElement("div");
1053
+ if (a.className = "beacon-plugin-panel", o.form.title) {
1054
+ const r = document.createElement("div");
1055
+ r.className = "beacon-plugin-panel-title", r.textContent = o.form.title, a.appendChild(r);
1056
+ }
1057
+ if ("fields" in o.form)
1058
+ at(a, o.form.fields, {
1059
+ get: (r) => n.get(o.name, r),
1060
+ set: (r, i) => n.set(o.name, r, i)
1061
+ });
1062
+ else {
1063
+ const r = o.form.render(a, o.ctx);
1064
+ typeof r == "function" && this.pluginCleanups.push(r);
1065
+ }
1066
+ this.pluginSlot.appendChild(a);
1067
+ }
1068
+ }
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
+ }
1088
+ }
1089
+ tryShowModal() {
1090
+ try {
1091
+ this.root.showModal();
1092
+ } catch {
1093
+ this.root.show();
1094
+ }
1095
+ }
1096
+ }
1097
+ function lt() {
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 dt(e) {
1115
+ const t = document.createElement("div");
1116
+ return t.className = "beacon-overlay-layer", e.appendChild(t), { layer: t };
1117
+ }
1118
+ function ut(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 (a) {
1125
+ throw n.remove(), a;
1126
+ }
1127
+ return () => {
1128
+ try {
1129
+ o == null || o();
1130
+ } catch {
1131
+ }
1132
+ n.parentNode && n.parentNode.removeChild(n);
1133
+ };
1134
+ }
1135
+ function pt() {
1136
+ var n, o;
1137
+ const e = navigator;
1138
+ return e.userAgentData ? {
1139
+ brand: ((n = e.userAgentData.brands.find((a) => !/Not[.\-]?A.?Brand/i.test(a.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 ft() {
1145
+ return {
1146
+ name: "metadata",
1147
+ capture() {
1148
+ const e = pt();
1149
+ return e ? { uaData: e } : null;
1150
+ }
1151
+ };
1152
+ }
1153
+ const mt = 30, X = 500, ce = 2e3, ht = 500, bt = 5e3, gt = /launch-kit-beacon|beacon\.(?:es|umd|mjs)|\/beacon\//i;
1154
+ function _(e, t) {
1155
+ if (e)
1156
+ return e.length > t ? e.slice(0, t) : e;
1157
+ }
1158
+ function yt(e, t) {
1159
+ const n = (t == null ? void 0 : t.split(`
1160
+ `).slice(0, 3).join("|")) ?? "";
1161
+ return `${e}::${n}`;
1162
+ }
1163
+ function vt(e) {
1164
+ return !!e && gt.test(e);
1165
+ }
1166
+ function xt(e) {
1167
+ try {
1168
+ return JSON.stringify(e).slice(0, X);
463
1169
  } catch {
464
- return !1;
1170
+ return String(e);
1171
+ }
1172
+ }
1173
+ function Re() {
1174
+ const e = [], t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Set();
1175
+ let o = !1, a, r;
1176
+ function i(s) {
1177
+ if (vt(s.stack) || s.kind === "unhandledrejection" && /AbortError/i.test(s.message)) return;
1178
+ const c = yt(s.message, s.stack), d = t.get(c);
1179
+ if (d !== void 0 && s.ts - d < bt) {
1180
+ t.set(c, s.ts);
1181
+ return;
1182
+ }
1183
+ t.set(c, s.ts), e.push(s), e.length > mt && e.shift();
1184
+ for (const l of n)
1185
+ try {
1186
+ l();
1187
+ } catch {
1188
+ }
465
1189
  }
1190
+ return {
1191
+ install() {
1192
+ return o ? () => {
1193
+ } : typeof window > "u" ? () => {
1194
+ } : (o = !0, a = (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: _(s.message || c || "Unknown error", X) ?? "Unknown error",
1201
+ ...d ? { stack: _(d, ce) } : {},
1202
+ ...s.filename ? { source: _(s.filename, ht) } : {},
1203
+ ...Number.isFinite(s.lineno) ? { line: s.lineno } : {},
1204
+ ...Number.isFinite(s.colno) ? { col: s.colno } : {}
1205
+ });
1206
+ } catch {
1207
+ }
1208
+ }, r = (s) => {
1209
+ try {
1210
+ const c = s.reason, d = c instanceof Error ? c.message : typeof c == "string" ? c : xt(c), l = c instanceof Error ? c.stack : void 0;
1211
+ i({
1212
+ ts: Date.now(),
1213
+ kind: "unhandledrejection",
1214
+ message: _(d || "Unknown rejection", X) ?? "Unknown rejection",
1215
+ ...l ? { stack: _(l, ce) } : {}
1216
+ });
1217
+ } catch {
1218
+ }
1219
+ }, window.addEventListener("error", a), window.addEventListener("unhandledrejection", r), () => {
1220
+ a && window.removeEventListener("error", a), r && window.removeEventListener("unhandledrejection", r), 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
+ };
466
1232
  }
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;
1233
+ function wt() {
1234
+ let e = null;
1235
+ return {
1236
+ name: "errors",
1237
+ setupOnce(t) {
1238
+ e = Re();
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 a = document.createElement("span");
1250
+ a.className = "beacon-events-dot", a.textContent = "●";
1251
+ const r = document.createElement("span");
1252
+ r.className = "beacon-events-label", o.appendChild(a), o.appendChild(r), 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 = "", r.textContent = `${l} runtime error${l !== 1 ? "s" : ""} captured`, i.innerHTML = "";
1262
+ for (const m of d) {
1263
+ const p = document.createElement("li");
1264
+ p.className = "beacon-events-item";
1265
+ const g = document.createElement("span");
1266
+ g.className = `beacon-events-kind ${m.kind === "unhandledrejection" ? "rejection" : "error"}`, g.textContent = m.kind === "unhandledrejection" ? "REJ" : "ERR";
1267
+ const u = document.createElement("span");
1268
+ u.className = "beacon-events-msg", u.textContent = m.message, p.appendChild(g), p.appendChild(u), i.appendChild(p);
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
+ };
470
1284
  }
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;
1285
+ const Et = 8;
1286
+ function le(e, t = document) {
1287
+ if (!e) return !1;
1288
+ try {
1289
+ return t.querySelectorAll(`#${CSS.escape(e)}`).length === 1;
1290
+ } catch {
1291
+ return !1;
1292
+ }
474
1293
  }
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 St(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 Ct(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 kt(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 < Et; ) {
1309
+ const a = n;
1310
+ if (a.id && le(a.id)) {
1311
+ t.unshift(`#${CSS.escape(a.id)}`);
485
1312
  break;
486
1313
  }
487
- const i = Re(s), r = s.parentElement;
488
- let l = i;
489
- if (r)
1314
+ const r = St(a), i = a.parentElement;
1315
+ let s = r;
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(a.classList).join(" ");
1319
+ Array.from(i.children).filter(
1320
+ (l) => l.tagName === a.tagName && Array.from(l.classList).join(" ") === c
1321
+ ).length > 1 && (s = `${a.tagName.toLowerCase()}:nth-of-type(${Ct(a)})`);
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 At(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 a = n, r = a.type;
1336
+ if (typeof r == "function") {
1337
+ const i = r.displayName ?? r.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 r == "object" && r !== null) {
1341
+ const i = r.displayName ?? r.name;
1342
+ if (i) return { lib: "react", name: i };
514
1343
  }
515
- n = s.return;
1344
+ n = a.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 Lt(e) {
1349
+ var o, a;
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 r = ((o = n.type) == null ? void 0 : o.name) ?? ((a = n.type) == null ? void 0 : a.__name);
1353
+ return { lib: "vue", ...r ? { name: r } : {} };
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 Tt(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 Mt(e) {
1373
+ return At(e) ?? Lt(e) ?? Tt(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 It = 5e3, Rt = 1e3, de = 1e3, ue = 200, Pt = 50, pe = 200, _t = 500, Dt = [
547
1376
  "display",
548
1377
  "position",
549
1378
  "top",
@@ -582,666 +1411,892 @@ 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 $t(e) {
1420
+ const t = getComputedStyle(e), n = {};
1421
+ for (const o of Dt) {
1422
+ const a = t.getPropertyValue(o);
1423
+ a && a !== "normal" && a !== "none" && a !== "auto" && a !== "0px" && (n[o] = a.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 Bt(e) {
1428
+ return Array.from(e.classList).slice(0, Pt).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 zt(e) {
1431
+ const t = e.getBoundingClientRect(), n = kt(e), o = e.id || null, a = Mt(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: Bt(e),
1437
+ outerHTML: fe(e.outerHTML, It),
1438
+ ...e.parentElement ? { parentOuterHTML: fe(e.parentElement.outerHTML, Rt) } : {},
1439
+ computedStyles: $t(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
+ ...a ? { framework: a } : {}
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 Ot = 14, Ht = "#ffffff", Ut = "#ffffff", qt = 3, Ft = "#0ea5e9";
1450
+ async function Pe(e, t, n, o = Ft) {
1451
+ const a = await Vt(e), r = document.createElement("canvas");
1452
+ r.width = a.naturalWidth, r.height = a.naturalHeight;
1453
+ const i = r.getContext("2d");
1454
+ if (!i) throw new Error("Could not get 2D canvas context");
1455
+ i.drawImage(a, 0, 0);
1456
+ const s = r.width / n.w, c = r.height / n.h;
1457
+ for (const d of t) {
1458
+ const l = jt(d);
1459
+ if (!l) continue;
1460
+ const m = l.x * s, p = l.y * c, g = l.w * s, u = l.h * c;
1461
+ i.lineWidth = qt, i.strokeStyle = o, i.strokeRect(m, p, g, u);
1462
+ const v = m + g, E = p;
1463
+ i.beginPath(), i.fillStyle = o, i.arc(v, E, Ot, 0, Math.PI * 2), i.fill(), i.lineWidth = 3, i.strokeStyle = Ht, i.stroke(), i.fillStyle = Ut, i.font = "bold 16px system-ui, -apple-system, sans-serif", i.textAlign = "center", i.textBaseline = "middle", i.fillText(String(d.number), v, E + 1);
1464
+ }
1465
+ return r.toDataURL("image/jpeg", 0.85);
1466
+ }
1467
+ function jt(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 Vt(e) {
1486
+ return new Promise((t, n) => {
1487
+ const o = new Image();
1488
+ o.onload = () => t(o), o.onerror = (a) => n(a), 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 D = "beacon-no-capture", Wt = "#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 Yt(e = {}) {
1496
+ const t = e.accent ?? Wt, n = he(t, "b3"), o = he(t, "2e"), a = document.createElement("style");
1497
+ a.className = D, a.textContent = "@keyframes beacon-spin { to { transform: rotate(360deg); } }", document.head.appendChild(a);
1498
+ const r = document.createElement("div");
1499
+ r.className = D, r.setAttribute("aria-hidden", "true"), r.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 = D, 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(b) {
1538
+ return b.replace(/[<>&]/g, (f) => ({ "<": "&lt;", ">": "&gt;", "&": "&amp;" })[f]);
1539
+ }
1540
+ document.body.appendChild(r), document.body.appendChild(i);
1541
+ const d = /* @__PURE__ */ new Map();
1542
+ function l(b) {
1543
+ const f = document.createElement("div");
1544
+ return f.className = D, f.setAttribute("aria-hidden", "true"), f.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("; "), f.textContent = String(b), document.body.appendChild(f), f;
1560
+ }
1561
+ function m() {
1562
+ const b = document.createElement("div");
1563
+ return b.className = D, b.setAttribute("aria-hidden", "true"), b.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(b), b;
1571
+ }
1572
+ function p(b, f, h) {
1573
+ const y = h ? "0.5" : "1";
1574
+ b.outline.style.display = "block", b.outline.style.opacity = y, b.outline.style.left = `${f.x}px`, b.outline.style.top = `${f.y}px`, b.outline.style.width = `${f.w}px`, b.outline.style.height = `${f.h}px`, b.marker.style.display = "flex", b.marker.style.opacity = y, b.marker.style.left = `${f.x + f.w - 12}px`, b.marker.style.top = `${Math.max(2, f.y - 12)}px`;
1575
+ }
1576
+ function g(b) {
1577
+ b.marker.style.display = "none", b.outline.style.display = "none";
1578
+ }
1579
+ function u() {
1580
+ d.forEach((b) => {
1581
+ let f = b.anchor.target;
1582
+ if (document.contains(f) || (f = null), !f && b.anchor.selector && (f = document.querySelector(b.anchor.selector), f && (b.anchor.target = f)), f) {
1583
+ const y = f.getBoundingClientRect();
1584
+ if (y.width > 0 || y.height > 0) {
1585
+ p(b, { x: y.left, y: y.top, w: y.width, h: y.height }, !1);
1586
+ return;
1587
+ }
1588
+ }
1589
+ const h = b.anchor.fallbackRect;
1590
+ if (h && (h.w > 0 || h.h > 0)) {
1591
+ p(b, h, !0);
1592
+ return;
1593
+ }
1594
+ g(b);
1595
+ });
1596
+ }
1597
+ let v = null;
1598
+ function E() {
1599
+ v === null && (v = requestAnimationFrame(() => {
1600
+ v = null, u();
1601
+ }));
1602
+ }
1603
+ return window.addEventListener("scroll", E, !0), window.addEventListener("resize", E), {
1604
+ addPin(b, f) {
1605
+ const h = l(b), y = m();
1606
+ d.set(b, { anchor: f, marker: h, outline: y }), u();
643
1607
  },
644
- screen: {
645
- w: window.screen.width,
646
- h: window.screen.height
1608
+ setLoading(b) {
1609
+ b ? i.innerHTML = s + c(b) : 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", E, !0), window.removeEventListener("resize", E), v !== null && cancelAnimationFrame(v), r.remove(), i.remove(), a.remove(), d.forEach(({ marker: b, outline: f }) => {
1613
+ b.remove(), f.remove();
1614
+ }), d.clear();
1615
+ }
1616
+ };
1617
+ }
1618
+ const Xt = '<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 Gt(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">${Xt}</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, a = 160, r = Math.min(Math.max(8, e.anchor.x), window.innerWidth - o - 8), i = Math.min(Math.max(8, e.anchor.y + 12), window.innerHeight - a - 8);
1636
+ n.style.left = `${r}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 g;
1647
+ const p = (g = l.target.closest("[data-action]")) == null ? void 0 : g.getAttribute("data-action");
1648
+ if (p === "cancel" && c({ cancelled: "pin" }), p === "save") {
1649
+ const u = s.value.trim();
1650
+ c({ ...u ? { note: u } : {}, cancelled: !1 });
1651
+ }
1652
+ }), s.addEventListener("keydown", (l) => {
1653
+ if (l.key === "Enter" && (l.metaKey || l.ctrlKey)) {
1654
+ l.preventDefault();
1655
+ const m = s.value.trim();
1656
+ c({ ...m ? { note: m } : {}, cancelled: !1 });
1657
+ }
1658
+ });
1659
+ });
1660
+ }
1661
+ const Jt = "#0ea5e9";
1662
+ function Zt(e, t) {
1663
+ return /^#[0-9a-fA-F]{6}$/.test(e) ? `${e}${t}` : e;
1664
+ }
1665
+ function Qt(e) {
1666
+ const { shadowRoot: t, onHover: n } = e, o = e.accent ?? Jt, a = Zt(o, "14"), r = document.createElement("div");
1667
+ r.style.cssText = [
1668
+ "position: fixed",
1669
+ "pointer-events: none",
1670
+ "z-index: 2147483646",
1671
+ `border: 2px solid ${o}`,
1672
+ `background: ${a}`,
1673
+ "transition: all 60ms ease-out",
1674
+ "box-sizing: border-box",
1675
+ "border-radius: 2px"
1676
+ ].join("; "), document.body.appendChild(r);
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 m(h) {
1700
+ if (!h || !(h instanceof Node)) return !1;
1701
+ let y = h;
1702
+ for (; y; ) {
1703
+ if (y === t || y === t.host) return !0;
1704
+ y = y.parentNode ?? y.host ?? null;
1705
+ }
1706
+ return !1;
1707
+ }
1708
+ function p(h, y) {
1709
+ r.style.display = "none", i.style.display = "none";
1710
+ const C = document.elementsFromPoint(h, y);
1711
+ r.style.display = "block", i.style.display = "block";
1712
+ for (const k of C)
1713
+ if (!m(k)) return k;
1714
+ return null;
1715
+ }
1716
+ function g(h) {
1717
+ const y = h.getBoundingClientRect();
1718
+ r.style.left = `${y.left}px`, r.style.top = `${y.top}px`, r.style.width = `${y.width}px`, r.style.height = `${y.height}px`;
1719
+ const C = h.tagName.toLowerCase(), k = h.classList.length > 0 ? "." + Array.from(h.classList).slice(0, 2).join(".") : "";
1720
+ i.textContent = C + k;
1721
+ const S = y.top - 22;
1722
+ i.style.left = `${y.left}px`, i.style.top = `${S >= 0 ? S : y.bottom + 4}px`;
1723
+ }
1724
+ function u(h) {
1725
+ const y = p(h.clientX, h.clientY);
1726
+ y ? (g(y), n == null || n(y)) : (r.style.display = "none", i.style.display = "none", n == null || n(null));
1727
+ }
1728
+ function v(h) {
1729
+ if (h.button !== 0) return;
1730
+ h.preventDefault(), h.stopPropagation();
1731
+ const y = p(h.clientX, h.clientY);
1732
+ y && f(y);
1733
+ }
1734
+ function E(h) {
1735
+ h.preventDefault(), h.stopPropagation();
1736
+ }
1737
+ function b(h) {
1738
+ h.key === "Escape" && (h.preventDefault(), f(null));
1739
+ }
1740
+ function f(h) {
1741
+ c || (c = !0, document.removeEventListener("mousemove", u, !0), document.removeEventListener("pointerdown", v, !0), document.removeEventListener("click", E, !0), document.removeEventListener("mouseup", E, !0), document.removeEventListener("keydown", b, !0), r.remove(), i.remove(), document.body.style.cursor = s, d(h));
1742
+ }
1743
+ return document.addEventListener("mousemove", u, !0), document.addEventListener("pointerdown", v, !0), document.addEventListener("click", E, !0), document.addEventListener("mouseup", E, !0), document.addEventListener("keydown", b, !0), {
1744
+ cancel: () => f(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 en() {
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 U = "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 tn() {
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 = U);
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, a = o.getAttribute("href"), r = o.getAttributeNS("http://www.w3.org/1999/xlink", "href"), i = a || r || "";
1768
+ i && !be(i) && (t.push({ el: o, href: a, xlink: r }), a !== null && o.setAttribute("href", U), r !== null && o.setAttributeNS("http://www.w3.org/1999/xlink", "href", U));
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: a } of t)
1772
+ o !== null && n.setAttribute("href", o), a !== null && n.setAttributeNS("http://www.w3.org/1999/xlink", "href", a);
1773
+ };
1774
+ }
1775
+ function nn() {
1776
+ const e = [];
1777
+ document.querySelectorAll("*").forEach((r) => {
1778
+ const i = getComputedStyle(r), s = (i.overflowY === "auto" || i.overflowY === "scroll") && r.scrollHeight > r.clientHeight, c = (i.overflowX === "auto" || i.overflowX === "scroll") && r.scrollWidth > r.clientWidth;
1779
+ (s || c) && e.push(r);
1780
+ });
1781
+ const t = window.scrollX, n = window.scrollY, o = e.map((r) => ({
1782
+ el: r,
1783
+ scrollLeft: r.scrollLeft,
1784
+ scrollTop: r.scrollTop
1785
+ })), a = /* @__PURE__ */ new Map();
1786
+ for (const r of e) {
1787
+ let i = r;
1788
+ for (; i && i !== document.documentElement.parentElement; )
1789
+ a.has(i) || a.set(i, i.style.cssText), i = i.parentElement;
1790
+ }
1791
+ for (const r of a.keys())
1792
+ r.style.setProperty("overflow", "visible", "important"), r.style.setProperty("overflow-x", "visible", "important"), r.style.setProperty("overflow-y", "visible", "important"), r.style.setProperty("max-height", "none", "important"), r.style.setProperty("height", "auto", "important"), r.style.setProperty("min-height", "0", "important");
1793
+ return () => {
1794
+ for (const [r, i] of a)
1795
+ r.style.cssText = i;
1796
+ for (const { el: r, scrollLeft: i, scrollTop: s } of o)
1797
+ r.scrollLeft = i, r.scrollTop = s;
1798
+ window.scrollTo(t, n);
680
1799
  };
681
1800
  }
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;
1801
+ let ge = Promise.resolve();
1802
+ async function _e(e = {}) {
1803
+ const t = ge;
1804
+ let n;
1805
+ ge = new Promise((o) => {
1806
+ n = o;
1807
+ });
1808
+ try {
1809
+ return await t, await on(e, n);
1810
+ } catch (o) {
1811
+ throw n(), o;
1812
+ }
1813
+ }
1814
+ async function on(e, t) {
1815
+ const {
1816
+ quality: n = 0.7,
1817
+ pixelRatio: o = Math.min(window.devicePixelRatio || 1, 2),
1818
+ excludeShadowRoot: a,
1819
+ excludeHosts: r,
1820
+ fullPage: i = !0
1821
+ } = e, s = await en(), c = a || r != null && r.length ? (g) => {
1822
+ let u = g;
1823
+ for (; u; ) {
1824
+ if (a && u === a.host || r && u instanceof Element && r.includes(u) || u instanceof Element && u.classList.contains("beacon-no-capture")) return !1;
1825
+ u = u.parentNode;
688
1826
  }
689
1827
  return !0;
690
- } : void 0, r = Ge();
1828
+ } : void 0, d = tn(), l = i ? nn() : () => {
1829
+ };
1830
+ let m = !1;
1831
+ const p = () => {
1832
+ if (!m) {
1833
+ m = !0;
1834
+ try {
1835
+ l();
1836
+ } finally {
1837
+ try {
1838
+ d();
1839
+ } finally {
1840
+ t();
1841
+ }
1842
+ }
1843
+ }
1844
+ };
691
1845
  try {
692
- return await s.toJpeg(document.documentElement, {
693
- quality: e,
694
- pixelRatio: n,
1846
+ i && await new Promise((b) => requestAnimationFrame(() => b()));
1847
+ const g = document.documentElement, u = i ? Math.max(g.scrollWidth, window.innerWidth) : window.innerWidth, v = i ? Math.max(g.scrollHeight, window.innerHeight) : window.innerHeight;
1848
+ return { dataUrl: await s.toJpeg(g, {
1849
+ quality: n,
1850
+ pixelRatio: o,
695
1851
  cacheBust: !0,
696
- ...i ? { filter: i } : {},
697
- imagePlaceholder: _,
698
- // Cap dimensions to viewport so we don't accidentally capture full document height.
699
- width: window.innerWidth,
700
- height: window.innerHeight,
701
- style: {
702
- // Avoid scrolling artifacts.
703
- transform: "none"
704
- }
705
- });
706
- } 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)
1852
+ ...c ? { filter: c } : {},
1853
+ imagePlaceholder: U,
1854
+ width: u,
1855
+ height: v,
1856
+ style: { transform: "none" }
1857
+ }), width: u, height: v, pixelRatio: o, dispose: p };
1858
+ } catch (g) {
1859
+ throw p(), g;
1860
+ }
1861
+ }
1862
+ let Q = null;
1863
+ function rn(e) {
1864
+ Q = e;
1865
+ }
1866
+ function an() {
1867
+ return Q;
1868
+ }
1869
+ function R() {
1870
+ Q = null;
1871
+ }
1872
+ const ye = "http://www.w3.org/2000/svg";
1873
+ function sn() {
1874
+ const e = document.createElementNS(ye, "svg");
1875
+ 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");
1876
+ const t = [
1877
+ "M3 6h18",
1878
+ "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",
1879
+ "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"
1880
+ ];
1881
+ for (const n of t) {
1882
+ const o = document.createElementNS(ye, "path");
1883
+ o.setAttribute("d", n), e.appendChild(o);
1884
+ }
1885
+ return e;
1886
+ }
1887
+ function cn(e = {}) {
1888
+ const t = e.maxPins ?? 20;
1889
+ let n = [], o = /* @__PURE__ */ new WeakMap(), a = null, r = 0, i = null, s = null, c = null, d = null;
1890
+ function l() {
1891
+ n = [], o = /* @__PURE__ */ new WeakMap(), a = null, r += 1, R(), E(), b();
1892
+ }
1893
+ function m() {
1894
+ const f = document.querySelector("launch-kit-beacon");
1895
+ return (f == null ? void 0 : f.shadowRoot) ?? null;
1896
+ }
1897
+ function p() {
1898
+ if (typeof window > "u") return e.accent ?? "#0ea5e9";
1899
+ if (e.accent) return e.accent;
1900
+ const f = document.querySelector("launch-kit-beacon");
1901
+ return f && getComputedStyle(f).getPropertyValue("--beacon-accent").trim() || "#0ea5e9";
1902
+ }
1903
+ async function g(f) {
1904
+ const h = m();
1905
+ if (!h) return;
1906
+ const y = p(), C = await f.requestMode("pickElement"), k = Yt({ accent: y });
1907
+ for (const S of n) {
1908
+ const A = o.get(S);
1909
+ A && k.addPin(S.number, {
1910
+ target: A,
1911
+ selector: S.selector,
1912
+ fallbackRect: S.boundingRect
1913
+ });
1914
+ }
736
1915
  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 };
1916
+ let S = !0;
1917
+ for (; S && !(n.length >= t); ) {
1918
+ const N = await Qt({ shadowRoot: h, accent: y }).promise;
1919
+ if (!N) break;
1920
+ const w = N.getBoundingClientRect(), L = await Gt({
1921
+ anchor: { x: w.left, y: w.bottom },
1922
+ pinNumber: n.length + 1
1923
+ });
1924
+ if (L.cancelled === "all") {
1925
+ S = !1;
1926
+ break;
1927
+ }
1928
+ if (L.cancelled === "pin") continue;
1929
+ const M = zt(N), I = {
1930
+ number: n.length + 1,
1931
+ ...M,
1932
+ ...L.note ? { note: L.note } : {}
1933
+ };
1934
+ n.push(I), o.set(I, N), k.addPin(I.number, {
1935
+ target: N,
1936
+ selector: M.selector,
1937
+ fallbackRect: M.boundingRect
1938
+ });
742
1939
  }
743
- } catch {
1940
+ n.length > 0 ? (k.setLoading("Capturing screenshot…"), await new Promise((A) => requestAnimationFrame(() => A())), await u()) : (a = null, R());
1941
+ } finally {
1942
+ k.destroy(), C();
744
1943
  }
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);
1944
+ E(), b();
772
1945
  }
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;
780
- }
781
- P.set(e, t.ts), $.push(t), $.length > st && $.shift();
782
- for (const o of B)
783
- try {
784
- o();
785
- } catch {
1946
+ async function u() {
1947
+ const f = ++r;
1948
+ if (n.length === 0) {
1949
+ a = null, R(), b();
1950
+ return;
786
1951
  }
787
- }
788
- function ut() {
789
- ce || typeof window > "u" || (ce = !0, window.addEventListener("error", (t) => {
1952
+ const h = p();
790
1953
  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
- });
1954
+ const y = Array.from(document.querySelectorAll("launch-kit-beacon")), C = await _e({ excludeHosts: y });
1955
+ try {
1956
+ if (f !== r) return;
1957
+ const k = n.map((N) => ({
1958
+ number: N.number,
1959
+ selector: N.selector,
1960
+ boundingRect: N.boundingRect,
1961
+ ...o.get(N) ? { liveElement: o.get(N) } : {}
1962
+ })), S = { w: C.width, h: C.height, dpr: C.pixelRatio }, A = await Pe(C.dataUrl, k, S, h);
1963
+ if (f !== r) return;
1964
+ a = A, rn({ dataUrl: A, mime: "image/jpeg" });
1965
+ } finally {
1966
+ C.dispose();
1967
+ }
801
1968
  } catch {
1969
+ if (f !== r) return;
1970
+ a = null, R();
802
1971
  }
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 {
1972
+ f === r && b();
1973
+ }
1974
+ function v(f) {
1975
+ const h = n.findIndex((y) => y.number === f);
1976
+ h !== -1 && (n.splice(h, 1), n.forEach((y, C) => {
1977
+ y.number = C + 1;
1978
+ }), a = null, R(), E(), b(), u());
1979
+ }
1980
+ function E() {
1981
+ if (i && (i.textContent = `Pins (${n.length})`, i.style.display = n.length === 0 ? "none" : ""), d && (d.textContent = n.length === 0 ? "Annotate elements" : "Add another pin"), !!s) {
1982
+ s.innerHTML = "", s.style.display = n.length === 0 ? "none" : "";
1983
+ for (const f of n) {
1984
+ const h = document.createElement("div");
1985
+ h.className = "beacon-pin-item", h.dataset.pin = String(f.number);
1986
+ const y = document.createElement("span");
1987
+ y.className = "beacon-pin-num", y.textContent = String(f.number);
1988
+ const C = document.createElement("div");
1989
+ C.className = "beacon-pin-meta";
1990
+ const k = document.createElement("div");
1991
+ k.className = "beacon-pin-selector", k.title = f.selector, k.textContent = f.selector || f.tagName;
1992
+ const S = document.createElement("input");
1993
+ S.type = "text", S.className = "beacon-pin-note-input", S.placeholder = "Add a note (optional)", S.value = f.note ?? "", S.addEventListener("input", () => {
1994
+ S.value.trim() ? f.note = S.value : delete f.note;
1995
+ }), C.appendChild(k), C.appendChild(S);
1996
+ const A = document.createElement("button");
1997
+ A.type = "button", A.className = "beacon-icon-btn", A.setAttribute("aria-label", `Remove pin ${f.number}`), A.appendChild(sn()), A.addEventListener("click", () => v(f.number)), h.appendChild(y), h.appendChild(C), h.appendChild(A), s.appendChild(h);
1998
+ }
813
1999
  }
814
- }));
2000
+ }
2001
+ function b() {
2002
+ c && (a ? (c.src = a, c.style.display = "block") : (c.removeAttribute("src"), c.style.display = "none"));
2003
+ }
2004
+ return {
2005
+ name: "domEle",
2006
+ setupOnce(f) {
2007
+ return f.on("close", () => l());
2008
+ },
2009
+ form(f) {
2010
+ return {
2011
+ render: (h) => (i = document.createElement("div"), i.className = "beacon-pin-list-header", h.appendChild(i), s = document.createElement("div"), s.className = "beacon-pin-list", h.appendChild(s), d = document.createElement("button"), d.type = "button", d.className = "beacon-btn secondary beacon-pin-annotate", d.addEventListener("click", () => {
2012
+ g(f);
2013
+ }), h.appendChild(d), c = document.createElement("img"), c.className = "beacon-thumb", c.alt = "Annotated screenshot preview", c.style.display = "none", h.appendChild(c), E(), b(), () => {
2014
+ i = null, s = null, c = null, d = null;
2015
+ })
2016
+ };
2017
+ },
2018
+ capture() {
2019
+ return n.length === 0 ? null : { pins: n };
2020
+ }
2021
+ };
815
2022
  }
816
- function M() {
817
- return $.slice();
2023
+ function ln(e) {
2024
+ return !!e && typeof e == "object" && !("v" in e) && "error" in e;
818
2025
  }
819
- function ge(t) {
820
- return B.add(t), () => {
821
- B.delete(t);
2026
+ function dn(e = {}) {
2027
+ return {
2028
+ name: "domSS",
2029
+ async capture(t) {
2030
+ const n = an();
2031
+ if (n)
2032
+ return { dataUrl: n.dataUrl, mime: n.mime };
2033
+ const o = await t.requestMode("hide");
2034
+ try {
2035
+ await new Promise((i) => requestAnimationFrame(() => i()));
2036
+ const a = Array.from(document.querySelectorAll("launch-kit-beacon")), r = await _e({
2037
+ quality: e.quality,
2038
+ pixelRatio: e.pixelRatio,
2039
+ excludeHosts: a
2040
+ });
2041
+ try {
2042
+ const i = t.captured("domEle"), s = un(i), c = { w: r.width, h: r.height, dpr: r.pixelRatio }, d = e.accent ?? pn();
2043
+ return { dataUrl: s.length > 0 ? await Pe(r.dataUrl, s, c, d) : r.dataUrl, mime: "image/jpeg" };
2044
+ } finally {
2045
+ r.dispose();
2046
+ }
2047
+ } finally {
2048
+ o();
2049
+ }
2050
+ }
822
2051
  };
823
2052
  }
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
2053
+ function un(e) {
2054
+ if (!e || ln(e)) return [];
2055
+ const t = e.pins;
2056
+ return Array.isArray(t) ? t.filter((n) => !!n && typeof n == "object").map((n) => ({
2057
+ number: Number(n.number) || 0,
2058
+ selector: typeof n.selector == "string" ? n.selector : void 0,
2059
+ boundingRect: n.boundingRect ?? { x: 0, y: 0, w: 0, h: 0 }
2060
+ })) : [];
2061
+ }
2062
+ function pn() {
2063
+ if (typeof window > "u") return "#0ea5e9";
2064
+ const e = document.querySelector("launch-kit-beacon");
2065
+ return e && getComputedStyle(e).getPropertyValue("--beacon-accent").trim() || "#0ea5e9";
2066
+ }
2067
+ const ve = "beacon-no-capture", xe = "__lsBeaconMonitorChipPos", fn = "#10b981";
2068
+ function mn(e) {
2069
+ const t = e.accent ?? fn, n = e.startedAt ?? Date.now(), o = document.createElement("div");
2070
+ o.className = `${ve} beacon-monitor-overlay-frame`, o.setAttribute("aria-hidden", "true"), o.style.setProperty("--beacon-monitor-accent", t), document.body.appendChild(o);
2071
+ const a = document.createElement("div");
2072
+ a.className = `${ve} beacon-monitor-overlay-chip`, a.setAttribute("role", "status"), a.setAttribute("aria-label", "Recording — drag to move"), a.style.setProperty("--beacon-monitor-accent", t);
2073
+ const r = document.createElement("div");
2074
+ r.className = "beacon-monitor-overlay-chip-row";
2075
+ const i = document.createElement("span");
2076
+ i.className = "beacon-monitor-overlay-rec-dot", i.setAttribute("aria-hidden", "true");
2077
+ const s = document.createElement("span");
2078
+ s.className = "beacon-monitor-overlay-rec-label", s.textContent = "REC";
2079
+ const c = document.createElement("span");
2080
+ c.className = "beacon-monitor-overlay-sep", c.setAttribute("aria-hidden", "true"), c.textContent = "·";
2081
+ const d = document.createElement("span");
2082
+ d.className = "beacon-monitor-overlay-timer", d.textContent = "00:00";
2083
+ const l = document.createElement("button");
2084
+ l.type = "button", l.className = "beacon-monitor-overlay-stop", l.textContent = "Stop", l.setAttribute("aria-label", "Stop monitoring"), r.appendChild(i), r.appendChild(s), r.appendChild(c), r.appendChild(d), r.appendChild(l), a.appendChild(r);
2085
+ const m = document.createElement("div");
2086
+ m.className = "beacon-monitor-overlay-url", e.url ? (m.textContent = e.url, m.title = e.url) : m.style.display = "none", a.appendChild(m), document.body.appendChild(a);
2087
+ const p = g() ?? u();
2088
+ E(v(p));
2089
+ function g() {
842
2090
  try {
843
- s = await o.text();
2091
+ const w = localStorage.getItem(xe);
2092
+ if (!w) return null;
2093
+ const L = JSON.parse(w), M = typeof L.x == "number" ? L.x : NaN, I = typeof L.y == "number" ? L.y : NaN;
2094
+ return !Number.isFinite(M) || !Number.isFinite(I) ? null : { x: M, y: I };
844
2095
  } catch {
845
- s = null;
2096
+ return null;
846
2097
  }
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
2098
  }
877
- static get observedAttributes() {
878
- return pt;
2099
+ function u() {
2100
+ const L = a.getBoundingClientRect().width || 200;
2101
+ return { x: Math.max(8, Math.floor((window.innerWidth - L) / 2)), y: 16 };
879
2102
  }
880
- /** Public — wrappers can set `widget.config = {...}` for dynamic endpoint/headers/context. */
881
- set config(e) {
882
- this._config = e;
2103
+ function v(w) {
2104
+ const M = a.getBoundingClientRect(), I = M.width || 200, Ve = M.height || 40, We = Math.max(8, window.innerWidth - I - 8), Ye = Math.max(8, window.innerHeight - Ve - 8);
2105
+ return {
2106
+ x: Math.min(Math.max(8, w.x), We),
2107
+ y: Math.min(Math.max(8, w.y), Ye)
2108
+ };
883
2109
  }
884
- get config() {
885
- if (this._config) return this._config;
886
- const e = this.getAttribute("endpoint");
887
- return e ? { endpoint: e } : null;
2110
+ function E(w) {
2111
+ a.style.left = `${w.x}px`, a.style.top = `${w.y}px`;
888
2112
  }
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
- });
2113
+ let b = !1, f = null, h = { x: 0, y: 0 };
2114
+ function y(w) {
2115
+ if (w.target instanceof Element && w.target.closest(".beacon-monitor-overlay-stop")) return;
2116
+ w.preventDefault(), b = !0, f = w.pointerId;
2117
+ try {
2118
+ a.setPointerCapture(w.pointerId);
2119
+ } catch {
912
2120
  }
913
- this.hasAttribute("position") || this.setAttribute("position", "bottom-right"), this.hasAttribute("theme") || this.setAttribute("theme", "auto");
2121
+ a.setAttribute("data-dragging", "true");
2122
+ const L = a.getBoundingClientRect();
2123
+ h = { x: w.clientX - L.left, y: w.clientY - L.top };
914
2124
  }
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"}`));
2125
+ function C(w) {
2126
+ !b || w.pointerId !== f || E(v({ x: w.clientX - h.x, y: w.clientY - h.y }));
917
2127
  }
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
- }
2128
+ function k(w) {
2129
+ if (!b || w.pointerId !== f) return;
2130
+ b = !1, f = null, a.removeAttribute("data-dragging");
952
2131
  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;
2132
+ a.releasePointerCapture(w.pointerId);
2133
+ } catch {
1042
2134
  }
1043
- this.drawer.setStatus("Sending…");
2135
+ const L = a.getBoundingClientRect();
1044
2136
  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));
1102
- }
1103
- uninstallClickBlocker() {
1104
- this.documentClickBlocker && (document.removeEventListener("click", this.documentClickBlocker, !0), this.documentClickBlocker = void 0);
1105
- }
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;
2137
+ localStorage.setItem(xe, JSON.stringify({ x: L.left, y: L.top }));
2138
+ } catch {
2139
+ }
1111
2140
  }
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;
2141
+ a.addEventListener("pointerdown", y), a.addEventListener("pointermove", C), a.addEventListener("pointerup", k), a.addEventListener("pointercancel", k), l.addEventListener("click", (w) => {
2142
+ w.stopPropagation(), e.onStop();
2143
+ });
2144
+ function S() {
2145
+ const w = a.getBoundingClientRect();
2146
+ E(v({ x: w.left, y: w.top }));
1117
2147
  }
1118
- parseSeverities() {
1119
- const e = this.getAttribute("severities");
1120
- return e ? e.split(",").map((n) => n.trim()).filter(Boolean) : ["bug", "idea", "ux", "a11y"];
2148
+ window.addEventListener("resize", S);
2149
+ function A() {
2150
+ const w = Math.max(0, Math.floor((Date.now() - n) / 1e3));
2151
+ d.textContent = hn(w);
1121
2152
  }
2153
+ A();
2154
+ const N = window.setInterval(A, 1e3);
2155
+ return {
2156
+ updateUrl(w) {
2157
+ w ? (m.textContent = w, m.title = w, m.style.display = "") : m.style.display = "none";
2158
+ },
2159
+ destroy() {
2160
+ window.clearInterval(N), window.removeEventListener("resize", S), a.removeEventListener("pointerdown", y), a.removeEventListener("pointermove", C), a.removeEventListener("pointerup", k), a.removeEventListener("pointercancel", k), o.remove(), a.remove();
2161
+ }
2162
+ };
1122
2163
  }
1123
- function gt(t = "launch-kit-beacon") {
1124
- typeof window > "u" || customElements.get(t) || customElements.define(t, mt);
2164
+ function hn(e) {
2165
+ const t = Math.floor(e / 3600), n = Math.floor(e % 3600 / 60), o = e % 60;
2166
+ return t > 0 ? `${$(t)}:${$(n)}:${$(o)}` : `${$(n)}:${$(o)}`;
1125
2167
  }
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`);
2168
+ function $(e) {
2169
+ return e < 10 ? `0${e}` : String(e);
1133
2170
  }
1134
- const vt = 1024, xt = 5;
1135
- function Et(t, e) {
1136
- return t.length > e ? t.slice(0, e) : t;
2171
+ const O = 80, bn = 'button, a, input[type="submit"], input[type="button"], [role="button"], [role="link"], [role="menuitem"], [role="tab"], [role="option"]', gn = 1024, yn = 5;
2172
+ function vn(e, t) {
2173
+ return e.length > t ? e.slice(0, t) : e;
1137
2174
  }
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;
2175
+ function ee(e) {
2176
+ if (e.id) return `#${CSS.escape(e.id)}`;
2177
+ const t = [];
2178
+ let n = e;
2179
+ for (let o = 0; o < 5 && n; o++) {
2180
+ const a = n.tagName.toLowerCase(), r = n.id ? `#${CSS.escape(n.id)}` : "", i = n.classList.length > 0 ? "." + Array.from(n.classList).slice(0, 3).map(CSS.escape).join(".") : "";
2181
+ if (t.unshift(`${a}${r}${i}`), r) break;
1145
2182
  n = n.parentElement;
1146
2183
  }
1147
- return e.join(" > ");
2184
+ return t.join(" > ");
2185
+ }
2186
+ function H(e, t) {
2187
+ if (!e) return;
2188
+ const n = e.replace(/\s+/g, " ").trim();
2189
+ if (n)
2190
+ return n.length > t ? n.slice(0, t) : n;
1148
2191
  }
1149
- function pe(t) {
2192
+ function we(e) {
2193
+ const t = H(e.textContent, O), n = H(e.getAttribute("aria-label"), O), o = e.getAttribute("data-testid") || void 0, a = e.getAttribute("name") || void 0;
2194
+ let r = n || t;
2195
+ if (!r) {
2196
+ const i = e.closest(bn);
2197
+ i && i !== e && (r = H(i.getAttribute("aria-label"), O) || H(i.textContent, O));
2198
+ }
1150
2199
  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)
2200
+ tag: e.tagName.toLowerCase(),
2201
+ id: e.id || null,
2202
+ classes: Array.from(e.classList).slice(0, 10),
2203
+ role: e.getAttribute("role"),
2204
+ selector: ee(e),
2205
+ ...t ? { text: t } : {},
2206
+ ...n ? { ariaLabel: n } : {},
2207
+ ...o ? { testid: o } : {},
2208
+ ...a ? { name: a } : {},
2209
+ // Only include label when it adds something beyond `text` (avoids dup).
2210
+ ...r && r !== t ? { label: r } : {}
1156
2211
  };
1157
2212
  }
1158
- function St(t, e) {
2213
+ function xn(e, t) {
1159
2214
  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(" ")
2215
+ for (const a of Array.from(o)) {
2216
+ const r = getComputedStyle(a);
2217
+ if (r.position !== "fixed" && r.position !== "sticky") continue;
2218
+ const i = a.getBoundingClientRect();
2219
+ if (e < i.left || e > i.right || t < i.top || t > i.bottom) continue;
2220
+ const s = parseInt(r.zIndex, 10);
2221
+ !Number.isFinite(s) && r.zIndex !== "auto" || n.push({
2222
+ tag: a.tagName.toLowerCase(),
2223
+ zIndex: Number.isFinite(s) ? s : 0,
2224
+ pointerEvents: r.pointerEvents,
2225
+ classes: Array.from(a.classList).slice(0, 5).join(" ")
1171
2226
  });
1172
2227
  }
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 } : {}
2228
+ return n.sort((a, r) => r.zIndex - a.zIndex).slice(0, yn);
2229
+ }
2230
+ function wn(e) {
2231
+ const t = (a) => (r) => {
2232
+ const i = r, s = i.target;
2233
+ if (!(s instanceof Element)) return;
2234
+ const c = i.clientX, d = i.clientY, l = document.elementFromPoint(c, d), m = l === s || (l ? s.contains(l) || l.contains(s) : !1), p = document.querySelectorAll('[role="dialog"][data-state="open"]').length, g = getComputedStyle(document.body).pointerEvents, u = m ? [] : xn(c, d);
2235
+ e.emitClick({
2236
+ kind: a,
2237
+ target: we(s),
2238
+ hitMatchesTarget: m,
2239
+ ...!m && l instanceof Element ? { hitTarget: we(l) } : {},
2240
+ coords: { x: c, y: d },
2241
+ openDialogs: p,
2242
+ bodyPointerEvents: g,
2243
+ ...u.length > 0 ? { overlaysAtPoint: u } : {}
1189
2244
  });
1190
- }, n = e("click"), o = e("mousedown");
2245
+ }, n = t("click"), o = t("mousedown");
1191
2246
  return document.addEventListener("click", n, { capture: !0, passive: !0 }), document.addEventListener("mousedown", o, { capture: !0, passive: !0 }), () => {
1192
2247
  document.removeEventListener("click", n, { capture: !0 }), document.removeEventListener("mousedown", o, { capture: !0 });
1193
2248
  };
1194
2249
  }
1195
- function At(t) {
1196
- const e = history.pushState, n = history.replaceState;
2250
+ function En(e) {
2251
+ const t = history.pushState, n = history.replaceState;
1197
2252
  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 });
2253
+ const a = (s) => {
2254
+ const c = window.location.href;
2255
+ if (c === o) return;
2256
+ const d = o;
2257
+ o = c, e.emitRoute({ kind: "route", from: d, to: c, via: s });
1203
2258
  };
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;
2259
+ history.pushState = function(...c) {
2260
+ const d = t.apply(this, c);
2261
+ return a("pushState"), d;
2262
+ }, history.replaceState = function(...c) {
2263
+ const d = n.apply(this, c);
2264
+ return a("replaceState"), d;
1210
2265
  };
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);
2266
+ const r = () => a("popstate"), i = () => a("hashchange");
2267
+ return window.addEventListener("popstate", r), window.addEventListener("hashchange", i), () => {
2268
+ history.pushState = t, history.replaceState = n, window.removeEventListener("popstate", r), window.removeEventListener("hashchange", i);
1214
2269
  };
1215
2270
  }
1216
- function Ct(t) {
1217
- const e = /* @__PURE__ */ new WeakSet(), n = (s, i) => {
1218
- const r = ye(s);
1219
- t.emitDialog({
2271
+ function Sn(e) {
2272
+ const t = /* @__PURE__ */ new WeakSet(), n = (a, r) => {
2273
+ const i = ee(a);
2274
+ e.emitDialog({
1220
2275
  kind: "dialog",
1221
- action: i,
1222
- selector: r,
1223
- state: s.getAttribute("data-state"),
1224
- ...i === "mount" ? { outerHTML: Et(s.outerHTML, vt) } : {}
2276
+ action: r,
2277
+ selector: i,
2278
+ state: a.getAttribute("data-state"),
2279
+ ...r === "mount" ? { outerHTML: vn(a.outerHTML, gn) } : {}
1225
2280
  });
1226
2281
  };
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"));
2282
+ for (const a of Array.from(document.querySelectorAll('[role="dialog"]')))
2283
+ t.add(a);
2284
+ const o = new MutationObserver((a) => {
2285
+ var r, i, s, c;
2286
+ for (const d of a) {
2287
+ for (const l of Array.from(d.addedNodes)) {
2288
+ if (!(l instanceof Element)) continue;
2289
+ const m = (r = l.matches) != null && r.call(l, '[role="dialog"]') ? [l] : Array.from(((i = l.querySelectorAll) == null ? void 0 : i.call(l, '[role="dialog"]')) ?? []);
2290
+ for (const p of m)
2291
+ t.has(p) || (t.add(p), n(p, "mount"));
1237
2292
  }
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"));
2293
+ for (const l of Array.from(d.removedNodes)) {
2294
+ if (!(l instanceof Element)) continue;
2295
+ const m = (s = l.matches) != null && s.call(l, '[role="dialog"]') ? [l] : Array.from(((c = l.querySelectorAll) == null ? void 0 : c.call(l, '[role="dialog"]')) ?? []);
2296
+ for (const p of m)
2297
+ t.has(p) && (t.delete(p), n(p, "unmount"));
1243
2298
  }
1244
- c.type === "attributes" && c.attributeName === "data-state" && c.target instanceof Element && c.target.getAttribute("role") === "dialog" && n(c.target, "state");
2299
+ d.type === "attributes" && d.attributeName === "data-state" && d.target instanceof Element && d.target.getAttribute("role") === "dialog" && n(d.target, "state");
1245
2300
  }
1246
2301
  });
1247
2302
  return o.observe(document.body, {
@@ -1251,132 +2306,278 @@ function Ct(t) {
1251
2306
  attributeFilter: ["data-state"]
1252
2307
  }), () => o.disconnect();
1253
2308
  }
1254
- function Lt(t) {
1255
- const e = kt(t), n = At(t), o = Ct(t);
2309
+ function Cn(e) {
2310
+ const t = (n) => {
2311
+ const o = n.target;
2312
+ if (!(o instanceof HTMLFormElement)) return;
2313
+ const a = [];
2314
+ for (const r of Array.from(o.elements)) {
2315
+ if (!(r instanceof HTMLInputElement || r instanceof HTMLTextAreaElement || r instanceof HTMLSelectElement)) continue;
2316
+ const i = r.getAttribute("name") || "<unnamed>", s = r instanceof HTMLInputElement ? r.type : r.tagName.toLowerCase();
2317
+ let c;
2318
+ r instanceof HTMLInputElement && (r.type === "checkbox" || r.type === "radio") ? c = r.checked : c = !!r.value, a.push({ name: i, type: s, hasValue: c });
2319
+ }
2320
+ e.emitSubmit({
2321
+ kind: "submit",
2322
+ form: {
2323
+ id: o.id || null,
2324
+ action: o.getAttribute("action") || null,
2325
+ method: (o.getAttribute("method") || "GET").toUpperCase(),
2326
+ selector: ee(o),
2327
+ fields: a
2328
+ }
2329
+ });
2330
+ };
2331
+ return document.addEventListener("submit", t, { capture: !0 }), () => document.removeEventListener("submit", t, { capture: !0 });
2332
+ }
2333
+ function kn(e) {
2334
+ const t = wn(e), n = En(e), o = Sn(e), a = Cn(e);
1256
2335
  return {
1257
2336
  uninstall() {
1258
- e(), n(), o();
2337
+ t(), n(), o(), a();
1259
2338
  }
1260
2339
  };
1261
2340
  }
1262
- const j = 1e3;
1263
- function O(t, e) {
1264
- return t.length > e ? t.slice(0, e) : t;
2341
+ const K = 1e3, Ee = 10 * 1024, De = "[REDACTED]", $e = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]), An = [
2342
+ /Bearer\s+[A-Za-z0-9._\-+/=]+/gi,
2343
+ /\bls_pat_[A-Za-z0-9_]+/g,
2344
+ // JWT: three dot-separated base64url segments starting with eyJ (the b64
2345
+ // encoding of the JSON {"). Matches Auth0/Clerk/most providers' tokens.
2346
+ /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g
2347
+ ], Ln = /^(password|passwd|secret|token|api[_-]?key|auth|access[_-]?token|refresh[_-]?token|client[_-]?secret|private[_-]?key)$/i;
2348
+ function G(e, t) {
2349
+ return e.length > t ? e.slice(0, t) : e;
2350
+ }
2351
+ function Be(e) {
2352
+ let t = e;
2353
+ for (const n of An)
2354
+ t = t.replace(n, De);
2355
+ return t;
2356
+ }
2357
+ function J(e) {
2358
+ if (e === null || typeof e != "object")
2359
+ return typeof e == "string" ? Be(e) : e;
2360
+ if (Array.isArray(e)) return e.map(J);
2361
+ const t = {};
2362
+ for (const [n, o] of Object.entries(e))
2363
+ t[n] = Ln.test(n) ? De : J(o);
2364
+ return t;
2365
+ }
2366
+ function Se(e, t) {
2367
+ if (t && t.includes("application/json"))
2368
+ try {
2369
+ const n = JSON.parse(e);
2370
+ return JSON.stringify(J(n));
2371
+ } catch {
2372
+ }
2373
+ return Be(e);
2374
+ }
2375
+ function q(e, t) {
2376
+ const n = e.length, o = { bodySize: n };
2377
+ return n > Ee ? (o.body = Se(e.slice(0, Ee), t), o.bodyTruncated = !0) : o.body = Se(e, t), t && (o.contentType = t), o;
2378
+ }
2379
+ function Tn(e, t) {
2380
+ const n = t == null ? void 0 : t.body;
2381
+ if (n != null) {
2382
+ if (typeof n == "string") return n;
2383
+ if (n instanceof URLSearchParams) return n.toString();
2384
+ if (n instanceof FormData) {
2385
+ const o = [];
2386
+ return n.forEach((a, r) => {
2387
+ o.push(`${r}=${typeof a == "string" ? `[${a.length}b]` : "[file]"}`);
2388
+ }), `[FormData] ${o.join("&")}`;
2389
+ }
2390
+ 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;
2391
+ }
2392
+ return e instanceof Request, null;
2393
+ }
2394
+ function Nn(e, t) {
2395
+ return !!(((o) => o ? o instanceof Headers ? o.has("authorization") : Array.isArray(o) ? o.some(([a]) => a.toLowerCase() === "authorization") : typeof o == "object" ? Object.keys(o).some((a) => a.toLowerCase() === "authorization") : !1 : !1)(t == null ? void 0 : t.headers) || e instanceof Request && e.headers.has("authorization"));
1265
2396
  }
1266
- function Tt(t) {
1267
- const e = window.fetch;
1268
- if (typeof e != "function") return () => {
2397
+ function Mn(e, t) {
2398
+ return ((o) => {
2399
+ if (o) {
2400
+ if (o instanceof Headers) return o.get("content-type") || void 0;
2401
+ if (Array.isArray(o)) {
2402
+ const a = o.find(([r]) => r.toLowerCase() === "content-type");
2403
+ return a ? a[1] : void 0;
2404
+ }
2405
+ if (typeof o == "object") {
2406
+ for (const [a, r] of Object.entries(o))
2407
+ if (a.toLowerCase() === "content-type") return r;
2408
+ }
2409
+ }
2410
+ })(t == null ? void 0 : t.headers) ?? (e instanceof Request && e.headers.get("content-type") || void 0);
2411
+ }
2412
+ function In(e, t, n) {
2413
+ if (!$e.has(n)) return;
2414
+ const o = Nn(e, t), a = Tn(e, t);
2415
+ if (a == null && !o) return;
2416
+ const r = Mn(e, t), i = a != null ? q(a, r) : {};
2417
+ return o && (i.hasAuth = !0), i;
2418
+ }
2419
+ function Rn(e) {
2420
+ const t = window.fetch;
2421
+ if (typeof t != "function") return () => {
1269
2422
  };
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;
2423
+ const n = async (o, a) => {
2424
+ const r = performance.now(), i = ((a == null ? void 0 : a.method) ?? (o instanceof Request ? o.method : "GET")).toUpperCase(), s = typeof o == "string" ? o : o instanceof URL ? o.toString() : o.url, c = In(o, a, i);
1272
2425
  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({
2426
+ const d = await t.call(window, o, a), l = Math.round(performance.now() - r), m = d.status >= 400;
2427
+ let p;
2428
+ if (m || e.verbose)
2429
+ try {
2430
+ const g = await d.clone().text(), u = d.headers.get("content-type") || void 0;
2431
+ p = q(g, u);
2432
+ } catch {
2433
+ }
2434
+ return (m || e.verbose) && e.emit({
1275
2435
  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({
2436
+ url: G(s, K),
2437
+ method: i,
2438
+ status: d.status,
2439
+ durationMs: l,
2440
+ failed: m,
2441
+ ...c ? { request: c } : {},
2442
+ ...p ? { response: p } : {}
2443
+ }), d;
2444
+ } catch (d) {
2445
+ const l = Math.round(performance.now() - r);
2446
+ throw e.emit({
1285
2447
  kind: "fetch",
1286
- url: O(l, j),
1287
- method: r,
2448
+ url: G(s, K),
2449
+ method: i,
1288
2450
  status: 0,
1289
- durationMs: c,
2451
+ durationMs: l,
1290
2452
  failed: !0,
1291
- error: a instanceof Error ? a.message : String(a)
1292
- }), a;
2453
+ error: d instanceof Error ? d.message : String(d),
2454
+ ...c ? { request: c } : {}
2455
+ }), d;
1293
2456
  }
1294
2457
  };
1295
2458
  return n.__lsBeaconWrapped = !0, window.fetch = n, () => {
1296
- window.fetch.__lsBeaconWrapped && (window.fetch = e);
2459
+ window.fetch.__lsBeaconWrapped && (window.fetch = t);
1297
2460
  };
1298
2461
  }
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({
2462
+ function Pn(e) {
2463
+ if (e == null) return null;
2464
+ if (typeof e == "string") return e;
2465
+ if (e instanceof URLSearchParams) return e.toString();
2466
+ if (e instanceof FormData) {
2467
+ const t = [];
2468
+ return e.forEach((n, o) => {
2469
+ t.push(`${o}=${typeof n == "string" ? `[${n.length}b]` : "[file]"}`);
2470
+ }), `[FormData] ${t.join("&")}`;
2471
+ }
2472
+ 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;
2473
+ }
2474
+ function _n(e) {
2475
+ const t = XMLHttpRequest.prototype, n = t.open, o = t.send, a = t.setRequestHeader, r = /* @__PURE__ */ new WeakMap();
2476
+ return t.open = function(s, c, ...d) {
2477
+ return r.set(this, {
2478
+ method: s.toUpperCase(),
2479
+ url: typeof c == "string" ? c : c.toString(),
2480
+ start: 0,
2481
+ hasAuth: !1
2482
+ }), n.call(this, s, c, ...d);
2483
+ }, t.setRequestHeader = function(s, c) {
2484
+ const d = r.get(this);
2485
+ if (d) {
2486
+ const l = s.toLowerCase();
2487
+ l === "authorization" ? d.hasAuth = !0 : l === "content-type" && (d.requestContentType = c);
2488
+ }
2489
+ return a.call(this, s, c);
2490
+ }, t.send = function(s) {
2491
+ const c = r.get(this);
2492
+ if (c)
2493
+ if (c.start = performance.now(), $e.has(c.method)) {
2494
+ const l = Pn(s);
2495
+ l != null ? c.request = q(l, c.requestContentType) : c.request = {}, c.hasAuth && (c.request.hasAuth = !0);
2496
+ } else c.hasAuth && (c.request = { hasAuth: !0 });
2497
+ const d = () => {
2498
+ this.removeEventListener("loadend", d);
2499
+ const l = r.get(this);
2500
+ if (!l) return;
2501
+ const m = Math.round(performance.now() - l.start), p = this.status === 0 || this.status >= 400;
2502
+ let g;
2503
+ if ((p || e.verbose) && this.status > 0)
2504
+ try {
2505
+ const u = this.responseType === "" || this.responseType === "text" ? this.responseText : "";
2506
+ if (u) {
2507
+ const v = this.getResponseHeader("content-type") || void 0;
2508
+ g = q(u, v);
2509
+ }
2510
+ } catch {
2511
+ }
2512
+ (p || e.verbose) && e.emit({
1316
2513
  kind: "xhr",
1317
- url: O(c.url, j),
1318
- method: c.method,
2514
+ url: G(l.url, K),
2515
+ method: l.method,
1319
2516
  status: this.status,
1320
- durationMs: d,
1321
- failed: u
1322
- }), s.delete(this);
2517
+ durationMs: m,
2518
+ failed: p,
2519
+ ...l.request ? { request: l.request } : {},
2520
+ ...g ? { response: g } : {}
2521
+ }), r.delete(this);
1323
2522
  };
1324
- return this.addEventListener("loadend", a), o.call(this, r);
2523
+ return this.addEventListener("loadend", d), o.call(this, s);
1325
2524
  }, () => {
1326
- e.open = n, e.send = o;
2525
+ t.open = n, t.send = o, t.setRequestHeader = a;
1327
2526
  };
1328
2527
  }
1329
- function It(t) {
1330
- const e = Tt(t), n = Mt(t);
2528
+ function Dn(e) {
2529
+ const t = Rn(e), n = _n(e);
1331
2530
  return {
1332
2531
  uninstall() {
1333
- e(), n();
2532
+ t(), n();
1334
2533
  }
1335
2534
  };
1336
2535
  }
1337
- const _t = 1e3, fe = 50, $t = 500;
1338
- class Nt {
1339
- constructor(e) {
2536
+ const $n = 1e3, Ce = 50, Bn = 500;
2537
+ class zn {
2538
+ constructor(t) {
1340
2539
  this.buffer = [], this.inflight = !1, this.timer = null, this.destroyed = !1, this.handleVisibilityChange = () => {
1341
2540
  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);
2541
+ }, this.url = t.url, this.sessionId = t.sessionId, this.onError = t.onError, this.timer = setInterval(() => {
2542
+ this.flush();
2543
+ }, $n), this.pagehideHandler = () => this.flushSync(), window.addEventListener("pagehide", this.pagehideHandler), document.addEventListener("visibilitychange", this.handleVisibilityChange);
1343
2544
  }
1344
- enqueue(e) {
1345
- this.destroyed || (this.buffer.push(e), this.buffer.length >= $t && this.buffer.shift(), this.buffer.length >= fe && this.flush());
2545
+ enqueue(t) {
2546
+ this.destroyed || (this.buffer.push(t), this.buffer.length > Bn && this.buffer.shift(), this.buffer.length >= Ce && this.flush());
1346
2547
  }
1347
2548
  /** Async flush via fetch. No-op when in-flight or empty. */
1348
2549
  async flush() {
1349
- var o, s;
2550
+ var o, a;
1350
2551
  if (this.destroyed || this.inflight || this.buffer.length === 0) return;
1351
- const e = this.buffer.splice(0, fe), n = this.makeBatch(e);
2552
+ const t = this.buffer.splice(0, Ce), n = this.makeBatch(t);
1352
2553
  this.inflight = !0;
1353
2554
  try {
1354
- const i = await fetch(this.url, {
2555
+ const r = await fetch(this.url, {
1355
2556
  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.
2557
+ // credentials:'omit' — going to the dev's local server, not the app
2558
+ // backend; avoid leaking session cookies cross-origin.
1358
2559
  credentials: "omit",
1359
2560
  headers: { "Content-Type": "application/json" },
1360
2561
  body: JSON.stringify(n),
1361
2562
  // keepalive lets the request survive a same-tick navigation when
1362
- // we missed pagehide (e.g. a window.location.assign from script).
2563
+ // pagehide didn't fire (e.g. a window.location.assign from script).
1363
2564
  keepalive: !0
1364
2565
  });
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)));
2566
+ r.ok || (o = this.onError) == null || o.call(this, new Error(`monitor flush: HTTP ${r.status}`));
2567
+ } catch (r) {
2568
+ (a = this.onError) == null || a.call(this, r instanceof Error ? r : new Error(String(r)));
1368
2569
  } finally {
1369
2570
  this.inflight = !1;
1370
2571
  }
1371
2572
  }
1372
- /** Synchronous flush via sendBeacon, used on pagehide. */
2573
+ /** Synchronous flush via sendBeacon, used on pagehide / visibility:hidden. */
1373
2574
  flushSync() {
1374
2575
  if (this.destroyed || this.buffer.length === 0) return;
1375
2576
  if (!navigator.sendBeacon) {
1376
2577
  this.flush();
1377
2578
  return;
1378
2579
  }
1379
- const e = this.buffer.splice(0), n = this.makeBatch(e), o = new Blob([JSON.stringify(n)], { type: "application/json" });
2580
+ const t = this.buffer.splice(0), n = this.makeBatch(t), o = new Blob([JSON.stringify(n)], { type: "application/json" });
1380
2581
  try {
1381
2582
  navigator.sendBeacon(this.url, o);
1382
2583
  } catch {
@@ -1385,10 +2586,10 @@ class Nt {
1385
2586
  destroy() {
1386
2587
  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
2588
  }
1388
- makeBatch(e) {
2589
+ makeBatch(t) {
1389
2590
  return {
1390
2591
  sessionId: this.sessionId,
1391
- events: e,
2592
+ events: t,
1392
2593
  meta: {
1393
2594
  url: window.location.href,
1394
2595
  userAgent: navigator.userAgent,
@@ -1402,178 +2603,559 @@ class Nt {
1402
2603
  };
1403
2604
  }
1404
2605
  }
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() {
2606
+ const te = "__lsBeaconMonitorUrl", ze = "__lsBeaconMonitorSession", ne = "__lsBeaconMonitorVerbose", oe = "__lsBeaconMonitorDeadline", Oe = 30 * 6e4, ke = 4096;
2607
+ let x = null;
2608
+ const Z = /* @__PURE__ */ new Set();
2609
+ function On() {
1410
2610
  return typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID().slice(0, 8) : Math.random().toString(36).slice(2, 10);
1411
2611
  }
1412
- function Pt(t) {
1413
- const e = /* @__PURE__ */ new WeakSet(), n = (o) => {
2612
+ function Hn(e) {
2613
+ const t = /* @__PURE__ */ new WeakSet(), n = (o) => {
1414
2614
  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))
2615
+ return typeof o == "string" && o.length > ke ? o.slice(0, ke) : o;
2616
+ if (t.has(o)) return "[cyclic]";
2617
+ if (t.add(o), Array.isArray(o)) return o.map(n);
2618
+ const a = {};
2619
+ for (const r of Object.keys(o).slice(0, 50))
1420
2620
  try {
1421
- s[i] = n(o[i]);
2621
+ a[r] = n(o[r]);
1422
2622
  } catch {
1423
- s[i] = "[unreadable]";
2623
+ a[r] = "[unreadable]";
1424
2624
  }
1425
- return s;
2625
+ return a;
1426
2626
  };
1427
2627
  try {
1428
- return n(t);
2628
+ return n(e);
1429
2629
  } catch {
1430
2630
  return "[unserialisable]";
1431
2631
  }
1432
2632
  }
1433
- function xe() {
1434
- for (const t of Rt)
2633
+ function re() {
2634
+ for (const e of Z)
1435
2635
  try {
1436
- t(m !== null, (m == null ? void 0 : m.url) ?? null);
2636
+ e(x !== null, (x == null ? void 0 : x.url) ?? null);
1437
2637
  } catch {
1438
2638
  }
1439
2639
  }
1440
- function Dt(t) {
1441
- return m ? (m.seq += 1, {
1442
- ...t,
2640
+ function Un(e) {
2641
+ return x ? (x.seq += 1, {
2642
+ ...e,
1443
2643
  ts: Date.now(),
1444
- sessionId: m.sessionId,
1445
- seq: m.seq
2644
+ sessionId: x.sessionId,
2645
+ seq: x.seq
1446
2646
  }) : {
1447
- ...t,
2647
+ ...e,
1448
2648
  ts: Date.now(),
1449
2649
  sessionId: "",
1450
2650
  seq: 0
1451
2651
  };
1452
2652
  }
1453
- function T(t) {
1454
- if (!m) return;
1455
- const e = Dt(t);
1456
- m.transport.enqueue(e);
2653
+ function P(e) {
2654
+ if (!x) return;
2655
+ const t = Un(e);
2656
+ x.transport.enqueue(t);
1457
2657
  }
1458
- function Bt() {
1459
- if (m)
2658
+ function qn() {
2659
+ if (x)
1460
2660
  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));
2661
+ sessionStorage.setItem(te, x.url), sessionStorage.setItem(ze, x.sessionId), sessionStorage.setItem(ne, x.verbose ? "1" : "0"), sessionStorage.setItem(oe, String(x.deadlineMs));
1462
2662
  } catch {
1463
2663
  }
1464
2664
  }
1465
- function Ee() {
2665
+ function He() {
1466
2666
  try {
1467
- sessionStorage.removeItem(U), sessionStorage.removeItem(H), sessionStorage.removeItem(q), sessionStorage.removeItem(F);
2667
+ sessionStorage.removeItem(te), sessionStorage.removeItem(ze), sessionStorage.removeItem(ne), sessionStorage.removeItem(oe);
1468
2668
  } catch {
1469
2669
  }
1470
2670
  }
1471
- function jt() {
2671
+ function Fn() {
1472
2672
  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 };
2673
+ const e = sessionStorage.getItem(te);
2674
+ if (!e) return null;
2675
+ const t = sessionStorage.getItem(ne) === "1", n = sessionStorage.getItem(oe), o = n ? Number(n) : Date.now() + Oe;
2676
+ return Number.isFinite(o) && o <= Date.now() ? (He(), null) : { url: e, verbose: t, deadlineMs: o };
1477
2677
  } catch {
1478
2678
  return null;
1479
2679
  }
1480
2680
  }
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,
2681
+ function Ae(e) {
2682
+ x && (x.seq += 1, x.transport.enqueue({
2683
+ kind: e.kind,
2684
+ ts: e.ts,
2685
+ sessionId: x.sessionId,
2686
+ seq: x.seq,
2687
+ message: e.message,
2688
+ ...e.stack ? { stack: e.stack } : {},
2689
+ ...e.source ? { source: e.source } : {},
2690
+ ...typeof e.line == "number" ? { line: e.line } : {},
2691
+ ...typeof e.col == "number" ? { col: e.col } : {}
2692
+ }));
2693
+ }
2694
+ function Ue(e) {
2695
+ if (x && F(), !e.url) return;
2696
+ const t = e.maxSessionMs ?? Oe, n = Date.now() + t, o = On(), a = !!e.verbose, r = new zn({
2697
+ url: e.url,
1485
2698
  sessionId: o,
1486
2699
  onError: (u) => {
1487
2700
  console.warn("[launch-kit-beacon] monitor transport error:", u.message);
1488
2701
  }
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();
2702
+ }), i = Re(), s = i.install(), c = i.snapshot();
2703
+ for (const u of c) Ae(u);
2704
+ let d = c.length;
2705
+ const l = i.subscribe(() => {
2706
+ if (!x) return;
2707
+ const u = x.errorsBuffer.snapshot();
2708
+ for (; x.drainedThrough < u.length; ) {
2709
+ const v = u[x.drainedThrough];
2710
+ v && Ae(v), x.drainedThrough += 1;
2711
+ }
2712
+ }), m = Dn({
2713
+ emit: (u) => P(u),
2714
+ verbose: a
2715
+ }), p = kn({
2716
+ emitClick: (u) => P(u),
2717
+ emitRoute: (u) => P(u),
2718
+ emitDialog: (u) => P(u),
2719
+ emitSubmit: (u) => P(u)
2720
+ }), g = setTimeout(() => {
2721
+ console.info("[launch-kit-beacon] monitor session expired (max duration reached)"), F();
1507
2722
  }, Math.max(0, n - Date.now()));
1508
- m = {
1509
- url: t.url,
2723
+ x = {
2724
+ url: e.url,
1510
2725
  sessionId: o,
1511
- verbose: s,
2726
+ verbose: a,
1512
2727
  deadlineMs: n,
1513
2728
  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({
2729
+ transport: r,
2730
+ errorsBuffer: i,
2731
+ uninstallNetwork: m.uninstall,
2732
+ uninstallDom: p.uninstall,
2733
+ uninstallErrors: s,
2734
+ errorsUnsub: l,
2735
+ deadlineTimer: g,
2736
+ drainedThrough: d
2737
+ }, qn(), re();
2738
+ }
2739
+ function F() {
2740
+ qe(), He(), re();
2741
+ }
2742
+ function jn() {
2743
+ x && (qe(), re());
2744
+ }
2745
+ function qe() {
2746
+ x && (clearTimeout(x.deadlineTimer), x.errorsUnsub(), x.uninstallErrors(), x.uninstallNetwork(), x.uninstallDom(), x.transport.destroy(), x = null);
2747
+ }
2748
+ function no(e, t) {
2749
+ x && P({
1539
2750
  kind: "probe",
1540
- label: t.slice(0, 200),
1541
- data: Pt(e)
2751
+ label: e.slice(0, 200),
2752
+ data: Hn(t)
1542
2753
  });
1543
2754
  }
1544
- function zt() {
1545
- return m !== null;
2755
+ function Le() {
2756
+ return x !== null;
1546
2757
  }
1547
- function Ut() {
1548
- return (m == null ? void 0 : m.url) ?? null;
2758
+ function Te() {
2759
+ return (x == null ? void 0 : x.url) ?? null;
1549
2760
  }
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())
2761
+ function Ne(e) {
2762
+ return Z.add(e), () => {
2763
+ Z.delete(e);
2764
+ };
2765
+ }
2766
+ function Vn() {
2767
+ if (x || typeof window > "u") return;
2768
+ const e = Fn();
2769
+ e && Ue({
2770
+ url: e.url,
2771
+ verbose: e.verbose,
2772
+ maxSessionMs: Math.max(6e4, e.deadlineMs - Date.now())
1564
2773
  });
1565
2774
  }
1566
- function Ft() {
2775
+ function oo(e = {}) {
2776
+ let t = null, n = null, o = "", a = null;
2777
+ function r() {
2778
+ a || (a = mn({
2779
+ onStop: () => F(),
2780
+ url: Te()
2781
+ }));
2782
+ }
2783
+ function i() {
2784
+ if (a) {
2785
+ try {
2786
+ a.destroy();
2787
+ } catch {
2788
+ }
2789
+ a = null;
2790
+ }
2791
+ }
2792
+ function s() {
2793
+ if (!t) return;
2794
+ t.innerHTML = "";
2795
+ const l = document.createElement("div");
2796
+ l.className = "beacon-monitor-title", l.textContent = "Monitor — paste a stream URL", t.appendChild(l);
2797
+ const m = document.createElement("div");
2798
+ m.className = "beacon-monitor-row";
2799
+ const p = document.createElement("input");
2800
+ p.type = "url", p.className = "beacon-monitor-input", p.placeholder = "http://localhost:9876/m/…", p.value = o, p.autocomplete = "off", p.spellcheck = !1, m.appendChild(p);
2801
+ const g = document.createElement("button");
2802
+ g.type = "button", g.className = "beacon-monitor-btn", g.textContent = "Start", g.disabled = !o.trim(), m.appendChild(g), t.appendChild(m);
2803
+ const u = document.createElement("label");
2804
+ u.className = "beacon-monitor-verbose";
2805
+ const v = document.createElement("input");
2806
+ v.type = "checkbox", v.dataset.role = "verbose", u.appendChild(v), u.appendChild(document.createTextNode(" verbose (capture successful network too)")), t.appendChild(u);
2807
+ const E = document.createElement("div");
2808
+ E.className = "beacon-monitor-help", E.textContent = "Streams clicks, failed network, errors, route + dialog changes.", t.appendChild(E), p.addEventListener("input", () => {
2809
+ o = p.value, g.disabled = !p.value.trim();
2810
+ }), g.addEventListener("click", () => {
2811
+ const b = p.value.trim();
2812
+ if (b) {
2813
+ try {
2814
+ new URL(b);
2815
+ } catch {
2816
+ p.setCustomValidity("Enter a valid URL (e.g. http://localhost:9876/m/abc)"), p.reportValidity();
2817
+ return;
2818
+ }
2819
+ p.setCustomValidity(""), Ue({
2820
+ url: b,
2821
+ verbose: v.checked,
2822
+ ...e.maxSessionMs !== void 0 ? { maxSessionMs: e.maxSessionMs } : {}
2823
+ });
2824
+ }
2825
+ });
2826
+ }
2827
+ function c() {
2828
+ if (!t) return;
2829
+ t.innerHTML = "";
2830
+ const l = Te() ?? "", m = document.createElement("div");
2831
+ m.className = "beacon-monitor-title";
2832
+ const p = document.createElement("span");
2833
+ p.className = "beacon-monitor-rec", p.setAttribute("aria-hidden", "true"), m.appendChild(p), m.appendChild(document.createTextNode(" Monitor — recording")), t.appendChild(m);
2834
+ const g = document.createElement("div");
2835
+ g.className = "beacon-monitor-active-url", g.title = l, g.textContent = l, t.appendChild(g);
2836
+ const u = document.createElement("div");
2837
+ u.className = "beacon-monitor-row";
2838
+ const v = document.createElement("button");
2839
+ v.type = "button", v.className = "beacon-monitor-btn stop", v.textContent = "Stop monitoring", v.addEventListener("click", () => F()), u.appendChild(v), t.appendChild(u);
2840
+ const E = document.createElement("div");
2841
+ E.className = "beacon-monitor-help", E.textContent = "Events stream to the URL above. Auto-stops after 30 min.", t.appendChild(E);
2842
+ }
2843
+ function d() {
2844
+ Le() ? c() : s();
2845
+ }
2846
+ return {
2847
+ name: "liveMonitor",
2848
+ setupOnce(l) {
2849
+ Vn(), Le() && r();
2850
+ const m = Ne((g, u) => {
2851
+ g ? (r(), a == null || a.updateUrl(u)) : i();
2852
+ }), p = () => {
2853
+ i(), m();
2854
+ try {
2855
+ jn();
2856
+ } catch {
2857
+ }
2858
+ };
2859
+ l.signal.addEventListener("abort", p, { once: !0 });
2860
+ },
2861
+ form() {
2862
+ return {
2863
+ render: (l) => (t = document.createElement("div"), t.className = "beacon-monitor", l.appendChild(t), d(), n = Ne(() => d()), () => {
2864
+ n == null || n(), n = null, t = null;
2865
+ })
2866
+ };
2867
+ }
2868
+ // No capture(): liveMonitor is a side-channel, not a feedback payload contributor.
2869
+ };
2870
+ }
2871
+ let T = null;
2872
+ const ae = {
2873
+ "plugin:error": /* @__PURE__ */ new Set(),
2874
+ "submit:success": /* @__PURE__ */ new Set(),
2875
+ "submit:error": /* @__PURE__ */ new Set(),
2876
+ ready: /* @__PURE__ */ new Set()
2877
+ };
2878
+ function ro(e) {
1567
2879
  if (typeof window > "u") return;
1568
- const t = window;
1569
- t.__lsBeacon || (t.__lsBeacon = Ht);
2880
+ if (!e.endpoint) throw new Error("init: endpoint is required");
2881
+ Ie(), Yn();
2882
+ const t = { ...lt(), ...e.labels ?? {} }, n = new AbortController(), o = Gn(e), a = e.position ?? "bottom-right", r = e.theme ?? "auto";
2883
+ Xe(), Kn(e, a, r);
2884
+ const i = document.querySelector(z);
2885
+ if (!i)
2886
+ throw new Error("init: failed to acquire <launch-kit-beacon> host");
2887
+ if (!i.shadow)
2888
+ throw new Error("init: host element shadow root not initialized");
2889
+ const s = dt(i.shadow), c = new ct(
2890
+ t,
2891
+ ["bug", "idea", "ux", "a11y"],
2892
+ {
2893
+ onSubmit: () => {
2894
+ Qn();
2895
+ },
2896
+ onClose: (m) => {
2897
+ j("close", {}), m === "user" && je();
2898
+ }
2899
+ }
2900
+ );
2901
+ i.shadow.appendChild(c.root), i.classList.add("beacon-no-capture");
2902
+ const d = et(o), l = {
2903
+ endpoint: e.endpoint,
2904
+ headers: e.headers,
2905
+ context: e.context,
2906
+ credentials: e.credentials ?? "omit",
2907
+ plugins: o,
2908
+ registry: d,
2909
+ dialog: c,
2910
+ overlayHost: s,
2911
+ hostElement: i,
2912
+ initAbort: n,
2913
+ labels: t,
2914
+ debug: !!e.debug || Zn(),
2915
+ healthIndicator: e.healthIndicator ?? "never",
2916
+ position: a,
2917
+ theme: r,
2918
+ currentSubmit: null,
2919
+ capturedEntries: {},
2920
+ formValues: {},
2921
+ lifecycleHandlers: {
2922
+ open: /* @__PURE__ */ new Set(),
2923
+ close: /* @__PURE__ */ new Set(),
2924
+ beforeSubmit: /* @__PURE__ */ new Set(),
2925
+ afterSubmit: /* @__PURE__ */ new Set()
2926
+ },
2927
+ panelSources: []
2928
+ };
2929
+ T = l, i.onTriggerClick = () => Wn(), d.install(
2930
+ (m) => Fe(m),
2931
+ (m) => ie(m)
2932
+ ), B("ready", { ready: !0 }), l.debug && console.info("[beacon] ready", l.endpoint);
2933
+ }
2934
+ function Wn() {
2935
+ const e = T;
2936
+ e && (e.currentSubmit || (e.panelSources = e.plugins.map((t) => {
2937
+ if (!t.form) return null;
2938
+ const n = Fe(t.name);
2939
+ let o;
2940
+ try {
2941
+ o = t.form(n);
2942
+ } catch (a) {
2943
+ return ie({
2944
+ plugin: t.name,
2945
+ error: a instanceof Error ? a : new Error(String(a)),
2946
+ at: "form"
2947
+ }), null;
2948
+ }
2949
+ return { name: t.name, form: o, ctx: n };
2950
+ }).filter((t) => t !== null), e.dialog.installPluginPanels(e.panelSources, {
2951
+ get: (t, n) => {
2952
+ var o;
2953
+ return (o = e.formValues[t]) == null ? void 0 : o[n];
2954
+ },
2955
+ set: (t, n, o) => {
2956
+ var r;
2957
+ const a = (r = e.formValues)[t] ?? (r[t] = {});
2958
+ a[n] = o;
2959
+ }
2960
+ }), e.dialog.open(), j("open", {})));
2961
+ }
2962
+ function ao() {
2963
+ const e = T;
2964
+ e && e.dialog.close("user");
2965
+ }
2966
+ function Yn() {
2967
+ var t;
2968
+ const e = T;
2969
+ if (e) {
2970
+ e.initAbort.abort(), (t = e.currentSubmit) == null || t.abort(), e.registry.destroy(), R();
2971
+ try {
2972
+ e.dialog.root.remove(), e.overlayHost.layer.remove();
2973
+ } catch {
2974
+ }
2975
+ e.hostElement.onTriggerClick = null, T = null;
2976
+ }
2977
+ }
2978
+ function io() {
2979
+ const e = T;
2980
+ return e ? {
2981
+ ready: !0,
2982
+ transport: "idle",
2983
+ plugins: e.registry.status()
2984
+ } : { ready: !1, transport: "idle", plugins: {} };
2985
+ }
2986
+ function so(e, t) {
2987
+ return ae[e].add(t), () => Xn(e, t);
2988
+ }
2989
+ function Xn(e, t) {
2990
+ ae[e].delete(t);
2991
+ }
2992
+ function Kn(e, t, n) {
2993
+ let o = document.querySelector(z);
2994
+ if (!o) {
2995
+ o = document.createElement(z), o.setAttribute("position", t), o.setAttribute("theme", n), t === "hidden" && (o.style.position = "absolute", o.style.left = "-9999px"), (document.body ?? document.documentElement).appendChild(o);
2996
+ return;
2997
+ }
2998
+ e.position !== void 0 && o.setAttribute("position", t), e.theme !== void 0 && o.setAttribute("theme", n);
2999
+ }
3000
+ function Gn(e) {
3001
+ return e.plugins ? e.plugins : e.defaultPlugins === !1 ? [] : Jn();
3002
+ }
3003
+ function Jn() {
3004
+ return [ft(), wt(), cn(), dn()];
3005
+ }
3006
+ function Zn() {
3007
+ if (typeof window > "u") return !1;
3008
+ try {
3009
+ return new URLSearchParams(window.location.search).has("lsbeacon-debug");
3010
+ } catch {
3011
+ return !1;
3012
+ }
3013
+ }
3014
+ function Fe(e) {
3015
+ const t = T;
3016
+ return Ze(e, {
3017
+ getCaptured: (o) => t == null ? void 0 : t.capturedEntries[o],
3018
+ getFormValues: (o) => {
3019
+ var a;
3020
+ return t ? (a = t.formValues)[o] ?? (a[o] = {}) : {};
3021
+ },
3022
+ getCaptureSignal: () => {
3023
+ var o;
3024
+ return (o = t == null ? void 0 : t.currentSubmit) == null ? void 0 : o.signal;
3025
+ },
3026
+ getInitSignal: () => t.initAbort.signal,
3027
+ requestMode: async (o) => t ? t.dialog.requestMode(o) : () => {
3028
+ },
3029
+ overlay: (o) => t ? ut(t.overlayHost, o.render) : () => {
3030
+ },
3031
+ onLifecycle: (o, a) => {
3032
+ if (!t) return () => {
3033
+ };
3034
+ const r = t.lifecycleHandlers[o];
3035
+ return r.add(a), () => r.delete(a);
3036
+ }
3037
+ });
3038
+ }
3039
+ function j(e, t) {
3040
+ const n = T;
3041
+ if (n)
3042
+ for (const o of n.lifecycleHandlers[e])
3043
+ try {
3044
+ o(t);
3045
+ } catch (a) {
3046
+ n.debug && console.error("[beacon] lifecycle handler threw:", a);
3047
+ }
3048
+ }
3049
+ function B(e, t) {
3050
+ for (const n of ae[e])
3051
+ try {
3052
+ n(t);
3053
+ } catch (o) {
3054
+ T != null && T.debug && console.error("[beacon] system handler threw:", o);
3055
+ }
3056
+ }
3057
+ function ie(e) {
3058
+ B("plugin:error", { plugin: e.plugin, error: e.error, at: e.at });
3059
+ const t = T;
3060
+ 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));
3061
+ }
3062
+ function je() {
3063
+ const e = T;
3064
+ e && (e.dialog.resetState(), e.dialog.clearPluginPanels(), e.formValues = {});
3065
+ }
3066
+ async function Qn() {
3067
+ const e = T;
3068
+ if (!e || e.currentSubmit) return;
3069
+ const t = e.dialog.getDescription().trim();
3070
+ if (!t) {
3071
+ e.dialog.setStatus("Description is required", "error");
3072
+ return;
3073
+ }
3074
+ e.currentSubmit = new AbortController(), e.capturedEntries = {}, e.dialog.setSubmitting(!0), e.dialog.setStatus("Capturing…");
3075
+ let n = null;
3076
+ try {
3077
+ const o = await e.registry.capture(
3078
+ (s) => e.capturedEntries[s],
3079
+ (s) => ie(s)
3080
+ );
3081
+ e.capturedEntries = o, n = eo(e, t, o);
3082
+ let a = null;
3083
+ if (j("beforeSubmit", { payload: n, cancel: (s) => {
3084
+ a === null && (a = s);
3085
+ } }), a !== null) {
3086
+ e.dialog.setSubmitting(!1), e.dialog.setStatus(`Cancelled: ${a}`, "error");
3087
+ return;
3088
+ }
3089
+ e.dialog.setStatus("Sending…");
3090
+ const i = await ot(
3091
+ e.endpoint,
3092
+ n,
3093
+ e.headers,
3094
+ e.currentSubmit.signal,
3095
+ e.credentials
3096
+ );
3097
+ j("afterSubmit", { payload: n, response: i }), e.dialog.setSubmitting(!1), i.ok ? (B("submit:success", { payload: n, response: i }), e.dialog.setSubmitSucceeded(!0), e.dialog.setStatus(e.labels.sentSuccess, "success"), window.setTimeout(() => {
3098
+ T === e && e.dialog.close("submitted"), je();
3099
+ }, 1500)) : (B("submit:error", { payload: n, error: new Error(`HTTP ${i.status}`) }), e.dialog.setStatus(`Failed (${i.status})`, "error"));
3100
+ } catch (o) {
3101
+ e.dialog.setSubmitting(!1);
3102
+ const a = o instanceof Error ? o : new Error(String(o));
3103
+ n && B("submit:error", { payload: n, error: a }), e.dialog.setStatus(`Failed: ${a.message}`, "error");
3104
+ } finally {
3105
+ e.currentSubmit = null;
3106
+ }
3107
+ }
3108
+ function eo(e, t, n) {
3109
+ var r;
3110
+ const o = to(), a = (r = e.context) == null ? void 0 : r.call(e);
3111
+ return {
3112
+ description: t,
3113
+ severity: e.dialog.getSeverity(),
3114
+ metadata: o,
3115
+ ...a ? { context: a } : {},
3116
+ plugins: n
3117
+ };
3118
+ }
3119
+ function to() {
3120
+ const e = window.location.href, t = document.referrer, n = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
3121
+ return {
3122
+ url: e,
3123
+ ...t ? { referrer: t } : {},
3124
+ userAgent: navigator.userAgent,
3125
+ viewport: {
3126
+ w: window.innerWidth,
3127
+ h: window.innerHeight,
3128
+ dpr: window.devicePixelRatio || 1
3129
+ },
3130
+ screen: {
3131
+ w: window.screen.width,
3132
+ h: window.screen.height
3133
+ },
3134
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
3135
+ locale: navigator.language,
3136
+ theme: n,
3137
+ capturedAt: (/* @__PURE__ */ new Date()).toISOString()
3138
+ };
1570
3139
  }
1571
- gt();
1572
- ut();
1573
- Ft();
1574
- qt();
3140
+ Ie();
1575
3141
  export {
1576
- mt as LaunchKitBeacon,
1577
- gt as defineBeacon
3142
+ Te as currentMonitorUrl,
3143
+ Yn as destroy,
3144
+ cn as domEle,
3145
+ dn as domSS,
3146
+ wt as errors,
3147
+ ao as hide,
3148
+ ro as init,
3149
+ Le as isMonitorActive,
3150
+ ln as isPluginFailure,
3151
+ oo as liveMonitor,
3152
+ ft as metadata,
3153
+ Xn as off,
3154
+ so as on,
3155
+ no as probe,
3156
+ Wn as show,
3157
+ Ue as startMonitor,
3158
+ io as status,
3159
+ F as stopMonitor
1578
3160
  };
1579
3161
  //# sourceMappingURL=beacon.mjs.map