turbowrap-issue-widget 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 +116 -0
- package/dist/api/client.d.ts +10 -0
- package/dist/api/types.d.ts +51 -0
- package/dist/capture/screen-capture.d.ts +5 -0
- package/dist/index.d.ts +11 -0
- package/dist/issue-widget.es.js +5872 -0
- package/dist/issue-widget.es.js.map +1 -0
- package/dist/issue-widget.min.js +566 -0
- package/dist/issue-widget.min.js.map +1 -0
- package/dist/issue-widget.umd.js +566 -0
- package/dist/issue-widget.umd.js.map +1 -0
- package/dist/ui/icons.d.ts +10 -0
- package/dist/ui/styles.d.ts +1 -0
- package/dist/widget.d.ts +31 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# @turbowrap/issue-widget
|
|
2
|
+
|
|
3
|
+
Embeddable chatbot widget for collecting issues via TurboWrap.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### Script Tag (CDN)
|
|
8
|
+
|
|
9
|
+
```html
|
|
10
|
+
<script>
|
|
11
|
+
window.IssueWidgetConfig = {
|
|
12
|
+
apiUrl: 'https://your-api.turbowrap.io',
|
|
13
|
+
apiKey: 'your_api_key',
|
|
14
|
+
teamId: 'your-linear-team-uuid'
|
|
15
|
+
};
|
|
16
|
+
</script>
|
|
17
|
+
<script src="https://cdn.jsdelivr.net/npm/@turbowrap/issue-widget@latest/dist/issue-widget.min.js" async></script>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### npm
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @turbowrap/issue-widget
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
import { IssueWidget } from '@turbowrap/issue-widget';
|
|
28
|
+
|
|
29
|
+
const widget = new IssueWidget({
|
|
30
|
+
apiUrl: 'https://your-api.turbowrap.io',
|
|
31
|
+
apiKey: 'your_api_key',
|
|
32
|
+
teamId: 'your-linear-team-uuid'
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Configuration
|
|
37
|
+
|
|
38
|
+
| Option | Type | Required | Default | Description |
|
|
39
|
+
|--------|------|----------|---------|-------------|
|
|
40
|
+
| `apiUrl` | string | Yes | - | TurboWrap API URL |
|
|
41
|
+
| `apiKey` | string | Yes | - | Widget API key |
|
|
42
|
+
| `teamId` | string | Yes | - | Linear team UUID |
|
|
43
|
+
| `position` | string | No | `'bottom-right'` | Button position: `'bottom-right'` or `'bottom-left'` |
|
|
44
|
+
| `theme` | string | No | `'auto'` | Theme: `'light'`, `'dark'`, or `'auto'` |
|
|
45
|
+
| `buttonText` | string | No | `'Report Issue'` | Floating button text |
|
|
46
|
+
| `accentColor` | string | No | `'#6366f1'` | Primary accent color (hex) |
|
|
47
|
+
| `autoScreenshot` | boolean | No | `false` | Auto-capture on widget open |
|
|
48
|
+
| `screenshotMethod` | string | No | `'auto'` | `'display-media'`, `'html2canvas'`, or `'auto'` |
|
|
49
|
+
|
|
50
|
+
## Callbacks
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
window.IssueWidgetConfig = {
|
|
54
|
+
// ... required options ...
|
|
55
|
+
|
|
56
|
+
onOpen: () => {
|
|
57
|
+
console.log('Widget opened');
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
onClose: () => {
|
|
61
|
+
console.log('Widget closed');
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
onIssueCreated: (issue) => {
|
|
65
|
+
console.log('Issue created:', issue);
|
|
66
|
+
// issue: { id, identifier, url }
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
onError: (error) => {
|
|
70
|
+
console.error('Widget error:', error);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Features
|
|
76
|
+
|
|
77
|
+
- **Screen Capture**: Uses `getDisplayMedia` API with `html2canvas` fallback
|
|
78
|
+
- **AI Analysis**: Gemini Vision analyzes screenshots, Claude generates clarifying questions
|
|
79
|
+
- **Linear Integration**: Creates issues directly in your Linear workspace
|
|
80
|
+
- **Shadow DOM**: Styles are isolated, no conflicts with host site CSS
|
|
81
|
+
- **Responsive**: Works on mobile and desktop
|
|
82
|
+
- **Dark Mode**: Automatic theme detection
|
|
83
|
+
|
|
84
|
+
## Development
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Install dependencies
|
|
88
|
+
npm install
|
|
89
|
+
|
|
90
|
+
# Development server
|
|
91
|
+
npm run dev
|
|
92
|
+
|
|
93
|
+
# Build for production
|
|
94
|
+
npm run build
|
|
95
|
+
|
|
96
|
+
# Type check
|
|
97
|
+
npm run typecheck
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Backend Configuration
|
|
101
|
+
|
|
102
|
+
The widget requires CORS enabled on your TurboWrap backend. Set the environment variable:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
TURBOWRAP_SERVER_CORS_ORIGINS=["https://your-customer-site.com"]
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Or for development (allow all):
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
TURBOWRAP_SERVER_CORS_ORIGINS=["*"]
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
MIT
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { WidgetConfig, AnalyzeRequest, AnalyzeResult, FinalizeRequest, IssueCreatedResult } from './types';
|
|
2
|
+
export declare class IssueAPIClient {
|
|
3
|
+
private baseUrl;
|
|
4
|
+
private apiKey;
|
|
5
|
+
private teamId;
|
|
6
|
+
constructor(config: WidgetConfig);
|
|
7
|
+
analyzeIssue(data: AnalyzeRequest, onProgress: (msg: string) => void, onComplete: (result: AnalyzeResult) => void, onError: (error: string) => void): Promise<void>;
|
|
8
|
+
finalizeIssue(data: FinalizeRequest, onProgress: (msg: string) => void, onComplete: (result: IssueCreatedResult) => void, onError: (error: string) => void): Promise<void>;
|
|
9
|
+
private parseSSEStream;
|
|
10
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export interface WidgetConfig {
|
|
2
|
+
apiUrl: string;
|
|
3
|
+
apiKey: string;
|
|
4
|
+
teamId: string;
|
|
5
|
+
position?: 'bottom-right' | 'bottom-left';
|
|
6
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
7
|
+
buttonText?: string;
|
|
8
|
+
accentColor?: string;
|
|
9
|
+
autoScreenshot?: boolean;
|
|
10
|
+
screenshotMethod?: 'display-media' | 'html2canvas' | 'auto';
|
|
11
|
+
onOpen?: () => void;
|
|
12
|
+
onClose?: () => void;
|
|
13
|
+
onIssueCreated?: (issue: IssueCreatedResult) => void;
|
|
14
|
+
onError?: (error: Error) => void;
|
|
15
|
+
}
|
|
16
|
+
export interface AnalyzeRequest {
|
|
17
|
+
title: string;
|
|
18
|
+
description: string;
|
|
19
|
+
screenshots: Blob[];
|
|
20
|
+
figmaLink?: string;
|
|
21
|
+
websiteLink?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface Question {
|
|
24
|
+
id: number;
|
|
25
|
+
question: string;
|
|
26
|
+
why: string;
|
|
27
|
+
}
|
|
28
|
+
export interface AnalyzeResult {
|
|
29
|
+
questions: Question[];
|
|
30
|
+
geminiInsights: string;
|
|
31
|
+
tempSessionId: string;
|
|
32
|
+
}
|
|
33
|
+
export interface FinalizeRequest {
|
|
34
|
+
title: string;
|
|
35
|
+
description: string;
|
|
36
|
+
userAnswers: Record<number, string>;
|
|
37
|
+
geminiInsights: string;
|
|
38
|
+
teamId: string;
|
|
39
|
+
figmaLink?: string;
|
|
40
|
+
websiteLink?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface IssueCreatedResult {
|
|
43
|
+
id: string;
|
|
44
|
+
identifier: string;
|
|
45
|
+
url: string;
|
|
46
|
+
}
|
|
47
|
+
export type SSEEventType = 'progress' | 'log' | 'complete' | 'error';
|
|
48
|
+
export interface SSEEvent {
|
|
49
|
+
event: SSEEventType;
|
|
50
|
+
data: unknown;
|
|
51
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type CaptureMethod = 'display-media' | 'html2canvas' | 'auto';
|
|
2
|
+
export declare function captureScreen(method?: CaptureMethod): Promise<Blob>;
|
|
3
|
+
export declare function supportsDisplayMedia(): boolean;
|
|
4
|
+
export declare function compressImage(blob: Blob, maxWidth?: number): Promise<Blob>;
|
|
5
|
+
export declare function blobToDataUrl(blob: Blob): Promise<string>;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IssueWidget } from './widget';
|
|
2
|
+
import { WidgetConfig } from './api/types';
|
|
3
|
+
export { IssueWidget };
|
|
4
|
+
export type { WidgetConfig };
|
|
5
|
+
export type { AnalyzeRequest, AnalyzeResult, FinalizeRequest, IssueCreatedResult, Question, } from './api/types';
|
|
6
|
+
declare global {
|
|
7
|
+
interface Window {
|
|
8
|
+
IssueWidgetConfig?: WidgetConfig;
|
|
9
|
+
IssueWidget?: IssueWidget;
|
|
10
|
+
}
|
|
11
|
+
}
|