@product7/feedback-sdk 1.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.
@@ -0,0 +1,264 @@
1
+ # Installation Guide
2
+
3
+ This guide covers all the ways to install and set up the Feedback Widget SDK in your project.
4
+
5
+ ---
6
+
7
+ ## 📦 Installation Methods
8
+
9
+ ### 1. CDN (Recommended for Quick Setup)
10
+
11
+ Load the SDK from our CDN:
12
+
13
+ ```html
14
+ <!-- Latest version (not pinned, not recommended for production) -->
15
+ <script src="https://cdn.jsdelivr.net/npm/@product7/feedback-sdk@1/dist/feedback-sdk.min.js"></script>
16
+
17
+ <!-- Specific version (recommended for production) -->
18
+ <script src="https://cdn.jsdelivr.net/npm/@product7/feedback-sdk@1.0.0/dist/feedback-sdk.min.js"></script>
19
+ ```
20
+
21
+ #### Basic Example
22
+
23
+ ```html
24
+ <!DOCTYPE html>
25
+ <html>
26
+ <head>
27
+ <title>My App</title>
28
+ </head>
29
+ <body>
30
+ <h1>Welcome to my app!</h1>
31
+
32
+ <!-- Load the SDK -->
33
+ <script src="https://cdn.jsdelivr.net/npm/@product7/feedback-sdk@1/dist/feedback-sdk.min.js"></script>
34
+
35
+ <script>
36
+ const feedback = new FeedbackSDK({
37
+ workspace: 'your-workspace-name',
38
+ boardId: 'your-board-id',
39
+ });
40
+
41
+ feedback.init().then(() => {
42
+ const widget = feedback.createWidget('button');
43
+ widget.mount();
44
+ });
45
+ </script>
46
+ </body>
47
+ </html>
48
+ ```
49
+
50
+ ---
51
+
52
+ ### 2. NPM/Yarn
53
+
54
+ For projects using a build system:
55
+
56
+ ```bash
57
+ # NPM
58
+ npm install @product7/feedback-sdk
59
+
60
+ # Yarn
61
+ yarn add @product7/feedback-sdk
62
+
63
+ # PNPM
64
+ pnpm add @product7/feedback-sdk
65
+ ```
66
+
67
+ #### ES Modules
68
+
69
+ ```javascript
70
+ import { FeedbackSDK } from '@product7/feedback-sdk';
71
+
72
+ const feedback = new FeedbackSDK({ workspace: 'your-workspace' });
73
+ await feedback.init();
74
+ ```
75
+
76
+ #### CommonJS
77
+
78
+ ```javascript
79
+ const { FeedbackSDK } = require('@product7/feedback-sdk');
80
+
81
+ const feedback = new FeedbackSDK({ workspace: 'your-workspace' });
82
+ feedback.init().then(() => {
83
+ // SDK ready
84
+ });
85
+ ```
86
+
87
+ ---
88
+
89
+ ### 3. Direct Download
90
+
91
+ Download from [GitHub Releases](https://github.com/product7/feedback-sdk/releases):
92
+
93
+ ```html
94
+ <script src="path/to/feedback-sdk.min.js"></script>
95
+ ```
96
+
97
+ ---
98
+
99
+ ## 🔧 Build Tools Integration
100
+
101
+ The SDK works out of the box with modern bundlers (Webpack, Rollup, Vite, Parcel):
102
+
103
+ ```javascript
104
+ import { FeedbackSDK } from '@product7/feedback-sdk';
105
+ // or
106
+ const { FeedbackSDK } = require('@product7/feedback-sdk');
107
+ ```
108
+
109
+ ---
110
+
111
+ ## ⚙️ Configuration Setup
112
+
113
+ ### Basic
114
+
115
+ ```javascript
116
+ const feedback = new FeedbackSDK({
117
+ workspace: 'your-workspace', // Required
118
+ boardId: 'your-board-id', // Optional
119
+ theme: 'light',
120
+ debug: false,
121
+ });
122
+ ```
123
+
124
+ ### Advanced
125
+
126
+ ```javascript
127
+ const feedback = new FeedbackSDK({
128
+ workspace: 'your-workspace',
129
+ apiKey: 'your-api-key',
130
+ baseUrl: 'https://custom-api.com',
131
+ theme: 'dark',
132
+ position: 'bottom-left',
133
+ language: 'en',
134
+ debug: process.env.NODE_ENV === 'development',
135
+ });
136
+ ```
137
+
138
+ ### Environment Variables
139
+
140
+ ```javascript
141
+ const feedback = new FeedbackSDK({
142
+ workspace: process.env.FEEDBACK_WORKSPACE,
143
+ boardId: process.env.FEEDBACK_BOARD_ID,
144
+ apiKey: process.env.FEEDBACK_API_KEY,
145
+ debug: process.env.NODE_ENV === 'development',
146
+ });
147
+ ```
148
+
149
+ ---
150
+
151
+ ## 🚀 Auto-Initialization
152
+
153
+ ```html
154
+ <script>
155
+ window.FeedbackSDKConfig = {
156
+ workspace: 'your-workspace',
157
+ boardId: 'your-board-id',
158
+ theme: 'light',
159
+ autoCreate: {
160
+ type: 'button',
161
+ position: 'bottom-right',
162
+ },
163
+ // Or multiple:
164
+ // autoCreate: [
165
+ // { type: 'button', position: 'bottom-right' },
166
+ // { type: 'inline', container: '#feedback-section' }
167
+ // ]
168
+ };
169
+ </script>
170
+ <script src="https://cdn.jsdelivr.net/npm/@product7/feedback-sdk@1/dist/feedback-sdk.min.js"></script>
171
+ ```
172
+
173
+ ---
174
+
175
+ ## 📋 Requirements
176
+
177
+ **Browsers**
178
+
179
+ - Chrome 60+, Firefox 55+, Safari 12+, Edge 79+
180
+ - iOS Safari 12+, Android Chrome 60+
181
+ - ES5 support required
182
+ - No jQuery needed
183
+
184
+ **API**
185
+
186
+ - Valid Product7 workspace
187
+ - Network access to your workspace API
188
+ - API key optional (for authenticated requests)
189
+
190
+ ---
191
+
192
+ ## 🔒 Content Security Policy (CSP)
193
+
194
+ The SDK is CSP-friendly (no `eval()`). Add directives:
195
+
196
+ ```
197
+ script-src 'self' https://cdn.jsdelivr.net;
198
+ connect-src 'self' https://*.api.staging.product7.io;
199
+ style-src 'self' 'unsafe-inline';
200
+ ```
201
+
202
+ ---
203
+
204
+ ## 🧪 Testing Your Installation
205
+
206
+ ```html
207
+ <script>
208
+ const feedback = new FeedbackSDK({
209
+ workspace: 'test-workspace',
210
+ debug: true,
211
+ });
212
+
213
+ feedback
214
+ .init()
215
+ .then(() => {
216
+ console.log('✅ SDK initialized');
217
+ const widget = feedback.createWidget('button');
218
+ widget.mount();
219
+ })
220
+ .catch((error) => {
221
+ console.error('❌ Initialization failed:', error);
222
+ });
223
+ </script>
224
+ ```
225
+
226
+ Verify by:
227
+
228
+ 1. Opening browser dev tools
229
+ 2. Checking for initialization logs
230
+ 3. Confirming widget renders
231
+ 4. Clicking widget to open modal
232
+
233
+ ---
234
+
235
+ ## 🚨 Troubleshooting
236
+
237
+ | Issue | Fix |
238
+ | ------------------------ | -------------------------------------------------------------------- |
239
+ | `SDK not defined` | Load script after DOM or wrap in `DOMContentLoaded` |
240
+ | Workspace not found | Check workspace name spelling |
241
+ | CSP Violations | Ensure directives match [CSP section](#-content-security-policy-csp) |
242
+ | `Module not found` (NPM) | Clear npm cache and reinstall |
243
+
244
+ Enable debug mode for detailed logs:
245
+
246
+ ```javascript
247
+ const feedback = new FeedbackSDK({ workspace: 'your-workspace', debug: true });
248
+ ```
249
+
250
+ If problems persist:
251
+
252
+ - Check browser console logs
253
+ - Review the [FAQ](faq.md)
254
+ - Search [GitHub Issues](https://github.com/product7/feedback-sdk/issues)
255
+ - Open a [new issue](https://github.com/product7/feedback-sdk/issues/new) with steps to reproduce
256
+
257
+ ---
258
+
259
+ ## ⏭️ Next Steps
260
+
261
+ - [Widget Types](widgets.md)
262
+ - [Configuration](configuration.md)
263
+ - [Theming](theming.md)
264
+ - [Examples](examples.md)
package/src/index.js ADDED
@@ -0,0 +1,281 @@
1
+ import { APIService } from './core/APIService.js';
2
+ import { EventBus } from './core/EventBus.js';
3
+ import { FeedbackSDK } from './core/FeedbackSDK.js';
4
+ import { CSS_STYLES } from './styles/styles.js';
5
+ import {
6
+ APIError,
7
+ ConfigError,
8
+ SDKError,
9
+ ValidationError,
10
+ WidgetError,
11
+ } from './utils/errors.js';
12
+ import * as helpers from './utils/helpers.js';
13
+ import { BaseWidget } from './widgets/BaseWidget.js';
14
+ import { ButtonWidget } from './widgets/ButtonWidget.js';
15
+ import { InlineWidget } from './widgets/InlineWidget.js';
16
+ import { TabWidget } from './widgets/TabWidget.js';
17
+ import { WidgetFactory } from './widgets/WidgetFactory.js';
18
+
19
+ function injectStyles() {
20
+ console.log('injectStyles called');
21
+ console.log('document exists:', typeof document !== 'undefined');
22
+ console.log('CSS_STYLES exists:', !!CSS_STYLES);
23
+
24
+ if (
25
+ typeof document !== 'undefined' &&
26
+ !document.querySelector('#feedback-sdk-styles')
27
+ ) {
28
+ console.log('Injecting CSS...');
29
+ const style = document.createElement('style');
30
+ style.id = 'feedback-sdk-styles';
31
+ style.textContent = CSS_STYLES;
32
+ document.head.appendChild(style);
33
+ console.log(
34
+ 'CSS injected, style element created:',
35
+ !!document.querySelector('#feedback-sdk-styles')
36
+ );
37
+ } else {
38
+ console.log('CSS already exists or document not ready');
39
+ }
40
+ }
41
+
42
+ function autoInit() {
43
+ if (typeof window !== 'undefined' && window.FeedbackSDKConfig) {
44
+ injectStyles();
45
+
46
+ const config = { ...window.FeedbackSDKConfig };
47
+
48
+ if (!config.userContext) {
49
+ config.userContext = getUserContextFromEnvironment();
50
+ }
51
+
52
+ const sdk = new FeedbackSDK(config);
53
+
54
+ sdk
55
+ .init()
56
+ .then((initData) => {
57
+ window.FeedbackSDK.instance = sdk;
58
+
59
+ if (window.FeedbackSDKConfig.autoCreate) {
60
+ const widgets = Array.isArray(window.FeedbackSDKConfig.autoCreate)
61
+ ? window.FeedbackSDKConfig.autoCreate
62
+ : [window.FeedbackSDKConfig.autoCreate];
63
+
64
+ widgets.forEach((widgetConfig) => {
65
+ try {
66
+ const widget = sdk.createWidget(
67
+ widgetConfig.type || 'button',
68
+ widgetConfig
69
+ );
70
+ widget.mount(widgetConfig.container);
71
+ } catch (error) {
72
+ console.error('[FeedbackSDK] Failed to create widget:', error);
73
+ }
74
+ });
75
+ }
76
+
77
+ if (typeof CustomEvent !== 'undefined') {
78
+ const event = new CustomEvent('FeedbackSDKReady', {
79
+ detail: {
80
+ sdk,
81
+ config: config,
82
+ initData: initData,
83
+ },
84
+ });
85
+ window.dispatchEvent(event);
86
+ }
87
+
88
+ console.log(
89
+ '[FeedbackSDK] Successfully initialized with session:',
90
+ initData.sessionToken ? 'Yes' : 'No'
91
+ );
92
+ })
93
+ .catch((error) => {
94
+ console.error('[FeedbackSDK] Auto-initialization failed:', error);
95
+
96
+ if (typeof CustomEvent !== 'undefined') {
97
+ const event = new CustomEvent('FeedbackSDKError', {
98
+ detail: {
99
+ error,
100
+ config: config,
101
+ phase: 'initialization',
102
+ },
103
+ });
104
+ window.dispatchEvent(event);
105
+ }
106
+ });
107
+ }
108
+ }
109
+
110
+ function getUserContextFromEnvironment() {
111
+ if (typeof window === 'undefined') return null;
112
+
113
+ if (window.FeedbackSDKUserContext) {
114
+ return window.FeedbackSDKUserContext;
115
+ }
116
+
117
+ const authSources = [
118
+ () => window.auth0?.user,
119
+ () => window.firebase?.auth()?.currentUser,
120
+ () => window.amplify?.Auth?.currentAuthenticatedUser(),
121
+
122
+ () => window.currentUser,
123
+ () => window.user,
124
+ () => window.userData,
125
+
126
+ () => window.app?.user,
127
+ () => window.store?.getState?.()?.user,
128
+ () => window.App?.currentUser,
129
+ ];
130
+
131
+ for (const getAuth of authSources) {
132
+ try {
133
+ const authData = getAuth();
134
+ if (authData) {
135
+ const userContext = FeedbackSDK.extractUserContextFromAuth(authData);
136
+ if (userContext && (userContext.user_id || userContext.email)) {
137
+ console.log(
138
+ '[FeedbackSDK] Auto-detected user context from',
139
+ getAuth.name || 'unknown source'
140
+ );
141
+ return userContext;
142
+ }
143
+ }
144
+ } catch (error) {
145
+ continue;
146
+ }
147
+ }
148
+
149
+ try {
150
+ const storedAuth =
151
+ localStorage.getItem('auth') ||
152
+ localStorage.getItem('user') ||
153
+ localStorage.getItem('session');
154
+ if (storedAuth) {
155
+ const authData = JSON.parse(storedAuth);
156
+ const userContext = FeedbackSDK.extractUserContextFromAuth(authData);
157
+ if (userContext && (userContext.user_id || userContext.email)) {
158
+ console.log(
159
+ '[FeedbackSDK] Auto-detected user context from localStorage'
160
+ );
161
+ return userContext;
162
+ }
163
+ }
164
+ } catch (error) {
165
+ // Continue
166
+ }
167
+
168
+ console.warn(
169
+ '[FeedbackSDK] No user context found. Widget initialization may require manual user context setting.'
170
+ );
171
+ return null;
172
+ }
173
+
174
+ function handleDOMReady() {
175
+ if (typeof document !== 'undefined') {
176
+ if (document.readyState === 'loading') {
177
+ document.addEventListener('DOMContentLoaded', autoInit);
178
+ } else {
179
+ setTimeout(autoInit, 0);
180
+ }
181
+ }
182
+ }
183
+
184
+ const FeedbackSDKExport = {
185
+ FeedbackSDK,
186
+ BaseWidget,
187
+ ButtonWidget,
188
+ TabWidget,
189
+ InlineWidget,
190
+ WidgetFactory,
191
+ EventBus,
192
+ APIService,
193
+ SDKError,
194
+ APIError,
195
+ WidgetError,
196
+ ConfigError,
197
+ ValidationError,
198
+ helpers,
199
+ create: (config) => {
200
+ injectStyles();
201
+ return new FeedbackSDK(config);
202
+ },
203
+ version: '1.0.0',
204
+ instance: null,
205
+
206
+ isReady: () => Boolean(FeedbackSDKExport.instance),
207
+ getInstance: () => FeedbackSDKExport.instance,
208
+
209
+ setUserContext: (userContext) => {
210
+ if (FeedbackSDKExport.instance) {
211
+ FeedbackSDKExport.instance.setUserContext(userContext);
212
+ } else {
213
+ if (typeof window !== 'undefined') {
214
+ window.FeedbackSDKUserContext = userContext;
215
+ }
216
+ }
217
+ },
218
+
219
+ initWithUser: async (config, userContext) => {
220
+ injectStyles();
221
+ const fullConfig = { ...config, userContext };
222
+ const sdk = new FeedbackSDK(fullConfig);
223
+ await sdk.init();
224
+
225
+ if (typeof window !== 'undefined') {
226
+ window.FeedbackSDK.instance = sdk;
227
+ }
228
+
229
+ return sdk;
230
+ },
231
+
232
+ onReady: (callback) => {
233
+ if (typeof window !== 'undefined') {
234
+ if (FeedbackSDKExport.isReady()) {
235
+ callback(FeedbackSDKExport.instance);
236
+ } else {
237
+ window.addEventListener(
238
+ 'FeedbackSDKReady',
239
+ (event) => {
240
+ callback(event.detail.sdk, event.detail);
241
+ },
242
+ { once: true }
243
+ );
244
+ }
245
+ }
246
+ },
247
+
248
+ onError: (callback) => {
249
+ if (typeof window !== 'undefined') {
250
+ window.addEventListener('FeedbackSDKError', (event) => {
251
+ callback(event.detail.error, event.detail);
252
+ });
253
+ }
254
+ },
255
+
256
+ extractUserContext: FeedbackSDK.extractUserContextFromAuth,
257
+ };
258
+
259
+ if (typeof window !== 'undefined') {
260
+ window.FeedbackSDK = FeedbackSDKExport;
261
+ handleDOMReady();
262
+ }
263
+
264
+ export default FeedbackSDKExport;
265
+
266
+ export {
267
+ APIError,
268
+ APIService,
269
+ BaseWidget,
270
+ ButtonWidget,
271
+ ConfigError,
272
+ EventBus,
273
+ FeedbackSDK,
274
+ helpers,
275
+ InlineWidget,
276
+ SDKError,
277
+ TabWidget,
278
+ ValidationError,
279
+ WidgetError,
280
+ WidgetFactory,
281
+ };