@launchsecure/launch-beacon 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # @launchsecure/launch-beacon
2
+
3
+ Generic, vanilla, framework-agnostic Web Component for in-app user feedback. Captures a written description, severity, viewport screenshot with auto-numbered element pins, and per-pin element data (HTML, CSS selector, computed styles, framework component name when available).
4
+
5
+ Drop into any web app — React, Vue, Angular, Svelte, plain HTML, server-rendered. Works in any framework because it's a real Web Component, not a library wrapper.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @launchsecure/launch-beacon
11
+ # or
12
+ pnpm add @launchsecure/launch-beacon
13
+ ```
14
+
15
+ Or via `<script>` tag (UMD build):
16
+
17
+ ```html
18
+ <script src="https://cdn.jsdelivr.net/npm/@launchsecure/launch-beacon@0/dist/beacon.umd.js" defer></script>
19
+ ```
20
+
21
+ ## Quick start
22
+
23
+ ```html
24
+ <launchkit-beacon
25
+ endpoint="/api/feedback"
26
+ position="bottom-right"
27
+ ></launchkit-beacon>
28
+ ```
29
+
30
+ That's it. A floating "Feedback" button appears bottom-right. Clicking it opens the form.
31
+
32
+ ## Configuration
33
+
34
+ ### Declarative (HTML attributes)
35
+
36
+ | Attribute | Default | Notes |
37
+ |---|---|---|
38
+ | `endpoint` | required | URL to POST the feedback payload to |
39
+ | `position` | `bottom-right` | `bottom-right` \| `bottom-left` \| `hidden` (use `hidden` if providing your own trigger via slot) |
40
+ | `theme` | `auto` | `auto` \| `light` \| `dark` |
41
+ | `severities` | `bug,idea,ux,a11y` | Comma-separated list of severity options |
42
+
43
+ ### Programmatic (for dynamic config / auth headers)
44
+
45
+ ```js
46
+ const widget = document.querySelector('launchkit-beacon');
47
+ widget.config = {
48
+ endpoint: '/api/feedback',
49
+ headers: () => ({ Authorization: `Bearer ${getToken()}` }),
50
+ context: () => ({ orgSlug, projectSlug }),
51
+ };
52
+ ```
53
+
54
+ `headers` and `context` may be objects or functions (called at submit time).
55
+
56
+ ### Programmatic methods
57
+
58
+ ```js
59
+ widget.open(); // open form drawer
60
+ widget.openWithPicker(); // open and jump straight into element-pick mode
61
+ widget.close();
62
+ ```
63
+
64
+ ### Events (for wrappers / observers)
65
+
66
+ ```js
67
+ widget.addEventListener('beacon-before-submit', (e) => {
68
+ // mutate or enrich payload
69
+ e.detail.payload.context.sessionId = mySessionId;
70
+ // or cancel
71
+ // e.preventDefault();
72
+ });
73
+
74
+ widget.addEventListener('beacon-after-submit', (e) => {
75
+ console.log('submitted', e.detail.response);
76
+ });
77
+ ```
78
+
79
+ ### Slots
80
+
81
+ Override the default trigger button:
82
+
83
+ ```html
84
+ <launchkit-beacon endpoint="/api/feedback" position="hidden">
85
+ <button slot="trigger">Send feedback</button>
86
+ </launchkit-beacon>
87
+ ```
88
+
89
+ ### Theming
90
+
91
+ ```css
92
+ launchkit-beacon {
93
+ --beacon-accent: #0ea5e9;
94
+ --beacon-bg: #ffffff;
95
+ --beacon-fg: #0f172a;
96
+ --beacon-radius: 12px;
97
+ --beacon-z-index: 9999;
98
+ }
99
+ ```
100
+
101
+ ## Payload shape
102
+
103
+ Beacon POSTs JSON to your `endpoint`:
104
+
105
+ ```ts
106
+ type FeedbackPayload = {
107
+ description: string;
108
+ severity: 'bug' | 'idea' | 'ux' | 'a11y';
109
+ screenshot?: { dataUrl: string; mime: 'image/jpeg' };
110
+ metadata: {
111
+ url: string; referrer?: string;
112
+ userAgent: string;
113
+ uaData?: { brand: string; mobile: boolean; platform: string };
114
+ viewport: { w: number; h: number; dpr: number };
115
+ screen: { w: number; h: number };
116
+ timezone: string; locale: string; theme?: 'light' | 'dark';
117
+ capturedAt: string;
118
+ };
119
+ pins: Array<{
120
+ number: number;
121
+ note?: string;
122
+ selector: string;
123
+ tagName: string; id: string | null; classList: string[];
124
+ outerHTML: string; // truncated to 5KB
125
+ parentOuterHTML?: string; // truncated to 1KB
126
+ computedStyles: Record<string, string>; // ~30 useful properties
127
+ boundingRect: { x: number; y: number; w: number; h: number };
128
+ framework?: { lib: 'react'|'vue'|'angular'|'svelte'|null; name?: string };
129
+ }>;
130
+ context?: Record<string, unknown>;
131
+ };
132
+ ```
133
+
134
+ Your endpoint's response is forwarded into the `beacon-after-submit` event.
135
+
136
+ ## Honest limitations
137
+
138
+ - **Cross-origin iframes are opaque.** Same-Origin Policy hard-blocks DOM access into them. The picker can highlight the iframe boundary but not its contents.
139
+ - **Framework component names are best-effort.** In production builds with minification, names are usually stripped (`t.A` instead of `LoginButton`). We probe and include when available; you'll get `null` otherwise.
140
+ - **No source-file/line capture.** Would require source maps + a server-side resolver — out of scope for v1.
141
+ - **No "which CSS rule produced this property" data.** `getMatchedCSSRules()` was removed from all major browsers.
142
+ - **html-to-image quirks** apply: cross-origin `<img>` tags need `crossorigin="anonymous"`, custom `@font-face` fonts need same-origin URLs, video frames render blank, animated GIFs frozen at first frame.
143
+
144
+ For most in-app feedback use cases, what we capture is plenty: outerHTML, selector, computed styles, bounding rect, and an annotated viewport screenshot.
145
+
146
+ ## License
147
+
148
+ MIT