@bworlds/launchkit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,172 @@
1
+ # @bworlds/launchkit
2
+
3
+ Launch kit for builders - demo recording, feedback tools, and more for BWorlds.
4
+
5
+ ## Features
6
+
7
+ - **Session Recording** - Captures user interactions using rrweb
8
+ - **Automatic Screenshots** - Takes snapshots on page load, navigation, form submit, modal open, and scroll
9
+ - **Privacy-First** - Automatically masks passwords and credit card inputs
10
+ - **Lightweight UI** - Minimal toolbar (~3KB) with start/pause/stop controls
11
+ - **Auto-Stop** - Recordings automatically stop after 15 minutes
12
+ - **Zero Config** - Just add the URL parameter to start recording
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @bworlds/launchkit
18
+ # or
19
+ pnpm add @bworlds/launchkit
20
+ # or
21
+ yarn add @bworlds/launchkit
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ### Auto-Activation (Recommended)
27
+
28
+ Import the package anywhere in your app - it auto-activates when the URL contains `?_bw_record=<api_key>`:
29
+
30
+ ```typescript
31
+ // In your app entry point or layout
32
+ import '@bworlds/launchkit';
33
+ ```
34
+
35
+ Then visit your app with the recording parameter:
36
+
37
+ ```
38
+ https://yourapp.com?_bw_record=your_api_key
39
+ ```
40
+
41
+ A toolbar will appear in the bottom-right corner.
42
+
43
+ ### Manual Control
44
+
45
+ For programmatic control over recording:
46
+
47
+ ```typescript
48
+ import { DemoRecorder } from '@bworlds/launchkit';
49
+
50
+ const recorder = new DemoRecorder({
51
+ apiKey: 'your_api_key',
52
+ maxDuration: 10 * 60 * 1000, // 10 minutes (default: 15)
53
+ maskInputs: true, // default: true
54
+ toolbar: {
55
+ position: 'bottom-right', // or 'bottom-left', 'top-right', 'top-left'
56
+ enabled: true,
57
+ },
58
+ onComplete: (result) => {
59
+ console.log('Recording URL:', result.playbackUrl);
60
+ },
61
+ });
62
+
63
+ // Initialize toolbar
64
+ recorder.init();
65
+
66
+ // Control recording programmatically
67
+ await recorder.start();
68
+ recorder.pause();
69
+ recorder.resume();
70
+ await recorder.stop();
71
+
72
+ // Take manual screenshot
73
+ await recorder.screenshot();
74
+ ```
75
+
76
+ ### Script Tag (CDN)
77
+
78
+ For non-bundled applications:
79
+
80
+ ```html
81
+ <script src="https://cdn.bworlds.com/recorder.umd.js"></script>
82
+ ```
83
+
84
+ Then visit with `?_bw_record=your_api_key` to activate.
85
+
86
+ ## Next.js / React Setup
87
+
88
+ Create a client component:
89
+
90
+ ```tsx
91
+ // components/DemoRecorder.tsx
92
+ 'use client';
93
+
94
+ import { useEffect } from 'react';
95
+
96
+ export function DemoRecorder() {
97
+ useEffect(() => {
98
+ import('@bworlds/launchkit');
99
+ }, []);
100
+
101
+ return null;
102
+ }
103
+ ```
104
+
105
+ Add to your layout:
106
+
107
+ ```tsx
108
+ // app/layout.tsx
109
+ import { DemoRecorder } from '@/components/DemoRecorder';
110
+
111
+ export default function RootLayout({ children }) {
112
+ return (
113
+ <html>
114
+ <body>
115
+ <DemoRecorder />
116
+ {children}
117
+ </body>
118
+ </html>
119
+ );
120
+ }
121
+ ```
122
+
123
+ ## Configuration
124
+
125
+ | Option | Type | Default | Description |
126
+ |--------|------|---------|-------------|
127
+ | `apiKey` | `string` | required | Your BWorlds API key |
128
+ | `apiEndpoint` | `string` | `https://api.bworlds.com` | API endpoint URL |
129
+ | `maxDuration` | `number` | `900000` (15 min) | Max recording duration in ms |
130
+ | `maskInputs` | `boolean` | `true` | Mask sensitive inputs |
131
+ | `toolbar.position` | `string` | `bottom-right` | Toolbar position |
132
+ | `toolbar.enabled` | `boolean` | `true` | Show/hide toolbar |
133
+ | `onComplete` | `function` | - | Called when recording finishes |
134
+ | `onStateChange` | `function` | - | Called on state changes |
135
+ | `onError` | `function` | - | Called on errors |
136
+
137
+ ## Automatic Screenshots
138
+
139
+ Screenshots are captured automatically on:
140
+
141
+ - **Page Load** - After initial render
142
+ - **Navigation** - On route changes (SPA or browser)
143
+ - **Form Submit** - Before form submission
144
+ - **Modal Open** - When dialogs/modals appear
145
+ - **Scroll** - After scrolling >50% of viewport
146
+
147
+ You can also take manual screenshots via the camera button or `recorder.screenshot()`.
148
+
149
+ ## Privacy
150
+
151
+ The SDK automatically masks:
152
+
153
+ - Password inputs (`type="password"`)
154
+ - Credit card fields (`autocomplete="cc-*"`)
155
+ - Fields with `data-private` or `data-sensitive` attributes
156
+
157
+ To exclude an element from recording entirely:
158
+
159
+ ```html
160
+ <div data-recorder-block>This won't be recorded</div>
161
+ ```
162
+
163
+ ## Browser Support
164
+
165
+ - Chrome 80+
166
+ - Firefox 75+
167
+ - Safari 13+
168
+ - Edge 80+
169
+
170
+ ## License
171
+
172
+ MIT
@@ -0,0 +1,57 @@
1
+ import type { eventWithTime } from 'rrweb';
2
+ import type { ScreenshotCapture } from './screenshot';
3
+ /**
4
+ * Event detection for automatic screenshots
5
+ */
6
+ export declare class EventDetector {
7
+ private screenshotCapture;
8
+ private lastScrollY;
9
+ private viewportHeight;
10
+ private observers;
11
+ private isRecording;
12
+ private hasInitialScreenshot;
13
+ constructor(screenshotCapture: ScreenshotCapture);
14
+ /**
15
+ * Start event detection
16
+ */
17
+ start(): void;
18
+ /**
19
+ * Stop event detection
20
+ */
21
+ stop(): void;
22
+ /**
23
+ * Handle rrweb event for additional detection
24
+ */
25
+ handleRrwebEvent(event: eventWithTime): void;
26
+ /**
27
+ * Trigger a screenshot with event type
28
+ */
29
+ private triggerScreenshot;
30
+ /**
31
+ * Set up modal/dialog detection using MutationObserver
32
+ */
33
+ private setupModalDetection;
34
+ /**
35
+ * Check if an element is a modal/dialog
36
+ */
37
+ private isModal;
38
+ /**
39
+ * Set up scroll detection
40
+ */
41
+ private setupScrollDetection;
42
+ private handleScroll;
43
+ /**
44
+ * Set up form submission detection
45
+ */
46
+ private setupFormDetection;
47
+ private handleFormSubmit;
48
+ /**
49
+ * Set up navigation detection
50
+ */
51
+ private setupNavigationDetection;
52
+ private handleNavigation;
53
+ /**
54
+ * Clean up all listeners
55
+ */
56
+ destroy(): void;
57
+ }
@@ -0,0 +1,61 @@
1
+ import { InviteDialogController } from './ui/InviteDialog';
2
+ import type { RecorderConfig, RecorderState, RecordingResult } from './types';
3
+ export { InviteDialogController };
4
+ export type { RecorderConfig, RecorderState, RecordingResult, ToolbarPosition, ScreenshotMarker, ScreenshotEventType, } from './types';
5
+ /**
6
+ * Main DemoRecorder class - orchestrates all components
7
+ */
8
+ export declare class DemoRecorder {
9
+ private config;
10
+ private recorder;
11
+ private screenshotMarker;
12
+ private eventDetector;
13
+ private toolbar;
14
+ private isInitialized;
15
+ constructor(config: RecorderConfig);
16
+ /**
17
+ * Initialize the recorder (mount toolbar)
18
+ */
19
+ init(): void;
20
+ /**
21
+ * Start recording
22
+ */
23
+ start(): Promise<void>;
24
+ /**
25
+ * Pause recording
26
+ */
27
+ pause(): void;
28
+ /**
29
+ * Resume recording
30
+ */
31
+ resume(): void;
32
+ /**
33
+ * Stop recording
34
+ */
35
+ stop(): Promise<RecordingResult | undefined>;
36
+ /**
37
+ * Add a manual screenshot marker
38
+ */
39
+ screenshot(): void;
40
+ /**
41
+ * Restart - reset everything for a new recording
42
+ */
43
+ restart(): void;
44
+ /**
45
+ * Get current state
46
+ */
47
+ getState(): RecorderState;
48
+ /**
49
+ * Get elapsed time
50
+ */
51
+ getElapsedTime(): number;
52
+ /**
53
+ * Destroy the recorder
54
+ */
55
+ destroy(): void;
56
+ /**
57
+ * Handle state changes
58
+ */
59
+ private handleStateChange;
60
+ }
61
+ export default DemoRecorder;