@product7/feedback-sdk 1.2.7 → 1.3.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/dist/feedback-sdk.js +1530 -1866
- package/dist/feedback-sdk.js.map +1 -1
- package/dist/feedback-sdk.min.js +1 -1
- package/dist/feedback-sdk.min.js.map +1 -1
- package/package.json +1 -1
- package/src/api/mock-data/index.js +202 -0
- package/src/api/services/ChangelogService.js +28 -0
- package/src/api/services/FeedbackService.js +44 -0
- package/src/api/services/HelpService.js +50 -0
- package/src/api/services/MessengerService.js +197 -0
- package/src/api/services/SurveyService.js +99 -0
- package/src/api/utils/helpers.js +30 -0
- package/src/core/APIService.js +40 -1142
- package/src/core/BaseAPIService.js +245 -0
- package/src/core/FeedbackSDK.js +0 -68
- package/src/styles/base.js +75 -0
- package/src/styles/changelog.js +698 -0
- package/src/styles/feedback.js +574 -0
- package/src/styles/styles.js +5 -1379
- package/src/widgets/ChangelogWidget.js +0 -5
- package/src/widgets/MessengerWidget.js +1 -2
- package/src/widgets/messenger/components/MessengerLauncher.js +7 -7
- package/src/widgets/messenger/components/NavigationTabs.js +16 -4
- package/src/widgets/messenger/views/ChangelogView.js +9 -9
- package/src/widgets/messenger/views/ChatView.js +9 -20
- package/src/widgets/messenger/views/ConversationsView.js +9 -13
- package/src/widgets/messenger/views/HelpView.js +15 -14
- package/src/widgets/messenger/views/HomeView.js +6 -15
package/dist/feedback-sdk.js
CHANGED
|
@@ -4,91 +4,6 @@
|
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.FeedbackSDK = {}));
|
|
5
5
|
})(this, (function (exports) { 'use strict';
|
|
6
6
|
|
|
7
|
-
class SDKError extends Error {
|
|
8
|
-
constructor(message, cause) {
|
|
9
|
-
super(message);
|
|
10
|
-
this.name = 'SDKError';
|
|
11
|
-
this.cause = cause;
|
|
12
|
-
|
|
13
|
-
if (Error.captureStackTrace) {
|
|
14
|
-
Error.captureStackTrace(this, SDKError);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
class APIError extends Error {
|
|
20
|
-
constructor(status, message, response) {
|
|
21
|
-
super(message);
|
|
22
|
-
this.name = 'APIError';
|
|
23
|
-
this.status = status;
|
|
24
|
-
this.response = response;
|
|
25
|
-
|
|
26
|
-
if (Error.captureStackTrace) {
|
|
27
|
-
Error.captureStackTrace(this, APIError);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
isNetworkError() {
|
|
32
|
-
return this.status === 0;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
isClientError() {
|
|
36
|
-
return this.status >= 400 && this.status < 500;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
isServerError() {
|
|
40
|
-
return this.status >= 500 && this.status < 600;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
class WidgetError extends Error {
|
|
45
|
-
constructor(message, widgetType, widgetId) {
|
|
46
|
-
super(message);
|
|
47
|
-
this.name = 'WidgetError';
|
|
48
|
-
this.widgetType = widgetType;
|
|
49
|
-
this.widgetId = widgetId;
|
|
50
|
-
|
|
51
|
-
if (Error.captureStackTrace) {
|
|
52
|
-
Error.captureStackTrace(this, WidgetError);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
class ConfigError extends Error {
|
|
58
|
-
constructor(message, configKey) {
|
|
59
|
-
super(message);
|
|
60
|
-
this.name = 'ConfigError';
|
|
61
|
-
this.configKey = configKey;
|
|
62
|
-
|
|
63
|
-
if (Error.captureStackTrace) {
|
|
64
|
-
Error.captureStackTrace(this, ConfigError);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
class ValidationError extends Error {
|
|
70
|
-
constructor(message, field, value) {
|
|
71
|
-
super(message);
|
|
72
|
-
this.name = 'ValidationError';
|
|
73
|
-
this.field = field;
|
|
74
|
-
this.value = value;
|
|
75
|
-
|
|
76
|
-
if (Error.captureStackTrace) {
|
|
77
|
-
Error.captureStackTrace(this, ValidationError);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const MOCK_CONFIG = {
|
|
83
|
-
primaryColor: '#21244A',
|
|
84
|
-
backgroundColor: '#ffffff',
|
|
85
|
-
textColor: '#1F2937',
|
|
86
|
-
boardId: 'feature-requests',
|
|
87
|
-
size: 'medium',
|
|
88
|
-
displayMode: 'modal',
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
// Mock changelogs for development
|
|
92
7
|
const MOCK_CHANGELOGS = [
|
|
93
8
|
{
|
|
94
9
|
id: 'changelog_1',
|
|
@@ -139,7 +54,6 @@
|
|
|
139
54
|
},
|
|
140
55
|
];
|
|
141
56
|
|
|
142
|
-
// Mock conversations for development
|
|
143
57
|
const MOCK_CONVERSATIONS = [
|
|
144
58
|
{
|
|
145
59
|
id: 'conv_1',
|
|
@@ -171,7 +85,6 @@
|
|
|
171
85
|
},
|
|
172
86
|
];
|
|
173
87
|
|
|
174
|
-
// Mock messages for development
|
|
175
88
|
const MOCK_MESSAGES = {
|
|
176
89
|
conv_1: [
|
|
177
90
|
{
|
|
@@ -218,7 +131,6 @@
|
|
|
218
131
|
],
|
|
219
132
|
};
|
|
220
133
|
|
|
221
|
-
// Mock help collections for development
|
|
222
134
|
const MOCK_HELP_COLLECTIONS = [
|
|
223
135
|
{
|
|
224
136
|
id: 'collection_1',
|
|
@@ -264,7 +176,6 @@
|
|
|
264
176
|
},
|
|
265
177
|
];
|
|
266
178
|
|
|
267
|
-
// Mock surveys for development
|
|
268
179
|
const MOCK_SURVEYS = [
|
|
269
180
|
{
|
|
270
181
|
id: 'mock_nps_survey',
|
|
@@ -296,110 +207,73 @@
|
|
|
296
207
|
},
|
|
297
208
|
];
|
|
298
209
|
|
|
299
|
-
|
|
300
|
-
const ENV_URLS = {
|
|
301
|
-
production: {
|
|
302
|
-
base: 'https://api.product7.io/api/v1',
|
|
303
|
-
withWorkspace: (workspace) => `https://${workspace}.api.product7.io/api/v1`,
|
|
304
|
-
},
|
|
305
|
-
staging: {
|
|
306
|
-
base: 'https://staging.api.product7.io/api/v1',
|
|
307
|
-
withWorkspace: (workspace) =>
|
|
308
|
-
`https://${workspace}.staging.api.product7.io/api/v1`,
|
|
309
|
-
},
|
|
310
|
-
};
|
|
210
|
+
const delay$1 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
311
211
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
this.sessionExpiry = null;
|
|
317
|
-
this.userContext = config.userContext || null;
|
|
318
|
-
this.mock = config.mock || false;
|
|
319
|
-
this.env = config.env || 'production';
|
|
212
|
+
function getDeviceInfo() {
|
|
213
|
+
if (typeof navigator === 'undefined') {
|
|
214
|
+
return { device: null, browser: null, os: null };
|
|
215
|
+
}
|
|
320
216
|
|
|
321
|
-
|
|
322
|
-
this.baseURL = config.apiUrl;
|
|
323
|
-
} else {
|
|
324
|
-
const envConfig = ENV_URLS[this.env] || ENV_URLS.production;
|
|
325
|
-
this.baseURL = this.workspace
|
|
326
|
-
? envConfig.withWorkspace(this.workspace)
|
|
327
|
-
: envConfig.base;
|
|
328
|
-
}
|
|
217
|
+
const ua = navigator.userAgent;
|
|
329
218
|
|
|
330
|
-
|
|
219
|
+
let device = 'desktop';
|
|
220
|
+
if (/Mobi|Android/i.test(ua)) {
|
|
221
|
+
device = /Tablet|iPad/i.test(ua) ? 'tablet' : 'mobile';
|
|
331
222
|
}
|
|
332
223
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
return { sessionToken: this.sessionToken };
|
|
340
|
-
}
|
|
224
|
+
let browser = 'unknown';
|
|
225
|
+
if (ua.includes('Firefox')) browser = 'firefox';
|
|
226
|
+
else if (ua.includes('Edg')) browser = 'edge';
|
|
227
|
+
else if (ua.includes('Chrome')) browser = 'chrome';
|
|
228
|
+
else if (ua.includes('Safari')) browser = 'safari';
|
|
229
|
+
else if (ua.includes('Opera') || ua.includes('OPR')) browser = 'opera';
|
|
341
230
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
231
|
+
let os = 'unknown';
|
|
232
|
+
if (ua.includes('Windows')) os = 'windows';
|
|
233
|
+
else if (ua.includes('Mac')) os = 'macos';
|
|
234
|
+
else if (ua.includes('Linux')) os = 'linux';
|
|
235
|
+
else if (ua.includes('Android')) os = 'android';
|
|
236
|
+
else if (ua.includes('iPhone') || ua.includes('iPad')) os = 'ios';
|
|
346
237
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
this.sessionToken = 'mock_session_' + Date.now();
|
|
350
|
-
this.sessionExpiry = new Date(Date.now() + 3600 * 1000);
|
|
351
|
-
this._storeSession();
|
|
352
|
-
return {
|
|
353
|
-
sessionToken: this.sessionToken,
|
|
354
|
-
config: MOCK_CONFIG,
|
|
355
|
-
expiresIn: 3600,
|
|
356
|
-
};
|
|
357
|
-
}
|
|
238
|
+
return { device, browser, os };
|
|
239
|
+
}
|
|
358
240
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
241
|
+
class ChangelogService {
|
|
242
|
+
constructor(baseAPI) {
|
|
243
|
+
this.api = baseAPI;
|
|
244
|
+
}
|
|
363
245
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
method: 'POST',
|
|
367
|
-
body: JSON.stringify(payload),
|
|
368
|
-
headers: {
|
|
369
|
-
'Content-Type': 'application/json',
|
|
370
|
-
},
|
|
371
|
-
});
|
|
246
|
+
async getChangelogs(options = {}) {
|
|
247
|
+
await this.api._ensureSession();
|
|
372
248
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
249
|
+
if (this.api.mock) {
|
|
250
|
+
await delay$1(300);
|
|
251
|
+
return { success: true, data: MOCK_CHANGELOGS };
|
|
252
|
+
}
|
|
376
253
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
};
|
|
382
|
-
} catch (error) {
|
|
383
|
-
throw new APIError(
|
|
384
|
-
error.status || 500,
|
|
385
|
-
`Failed to initialize widget: ${error.message}`,
|
|
386
|
-
error.response
|
|
254
|
+
return this.api._handleAuthRetry(async () => {
|
|
255
|
+
const endpoint = this.api._getEndpointWithParams(
|
|
256
|
+
'/widget/changelogs',
|
|
257
|
+
options
|
|
387
258
|
);
|
|
388
|
-
|
|
259
|
+
return await this.api._makeRequest(endpoint, {
|
|
260
|
+
method: 'GET',
|
|
261
|
+
headers: { Authorization: `Bearer ${this.api.sessionToken}` },
|
|
262
|
+
});
|
|
263
|
+
});
|
|
389
264
|
}
|
|
265
|
+
}
|
|
390
266
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
267
|
+
class FeedbackService {
|
|
268
|
+
constructor(baseAPI) {
|
|
269
|
+
this.api = baseAPI;
|
|
270
|
+
}
|
|
395
271
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
}
|
|
272
|
+
async submitFeedback(feedbackData) {
|
|
273
|
+
await this.api._ensureSession();
|
|
399
274
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
275
|
+
if (this.api.mock) {
|
|
276
|
+
await delay$1(500);
|
|
403
277
|
return {
|
|
404
278
|
success: true,
|
|
405
279
|
data: {
|
|
@@ -419,313 +293,98 @@
|
|
|
419
293
|
attachments: feedbackData.attachments || [],
|
|
420
294
|
};
|
|
421
295
|
|
|
422
|
-
|
|
423
|
-
const response = await this._makeRequest('/widget/feedback', {
|
|
296
|
+
return this.api._handleAuthRetry(async () => {
|
|
297
|
+
const response = await this.api._makeRequest('/widget/feedback', {
|
|
424
298
|
method: 'POST',
|
|
425
299
|
body: JSON.stringify(payload),
|
|
426
300
|
headers: {
|
|
427
301
|
'Content-Type': 'application/json',
|
|
428
|
-
Authorization: `Bearer ${this.sessionToken}`,
|
|
302
|
+
Authorization: `Bearer ${this.api.sessionToken}`,
|
|
429
303
|
},
|
|
430
304
|
});
|
|
431
|
-
|
|
432
305
|
return response;
|
|
433
|
-
}
|
|
434
|
-
if (error.status === 401) {
|
|
435
|
-
this.sessionToken = null;
|
|
436
|
-
this.sessionExpiry = null;
|
|
437
|
-
await this.init();
|
|
438
|
-
return this.submitFeedback(feedbackData);
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
throw new APIError(
|
|
442
|
-
error.status || 500,
|
|
443
|
-
`Failed to submit feedback: ${error.message}`,
|
|
444
|
-
error.response
|
|
445
|
-
);
|
|
446
|
-
}
|
|
306
|
+
});
|
|
447
307
|
}
|
|
308
|
+
}
|
|
448
309
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
* @param {Object} context.userProperties - Additional user properties
|
|
454
|
-
* @returns {Promise<Array>} Array of active surveys matching targeting rules
|
|
455
|
-
*/
|
|
456
|
-
async getActiveSurveys(context = {}) {
|
|
457
|
-
if (!this.isSessionValid()) {
|
|
458
|
-
await this.init();
|
|
459
|
-
}
|
|
310
|
+
class HelpService {
|
|
311
|
+
constructor(baseAPI) {
|
|
312
|
+
this.api = baseAPI;
|
|
313
|
+
}
|
|
460
314
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
}
|
|
315
|
+
async getHelpCollections(options = {}) {
|
|
316
|
+
await this.api._ensureSession();
|
|
464
317
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
return {
|
|
469
|
-
success: true,
|
|
470
|
-
data: MOCK_SURVEYS,
|
|
471
|
-
};
|
|
318
|
+
if (this.api.mock) {
|
|
319
|
+
await delay$1(200);
|
|
320
|
+
return { status: true, data: MOCK_HELP_COLLECTIONS };
|
|
472
321
|
}
|
|
473
322
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
queryParams.append('url', currentUrl);
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
// Auto-detect device info
|
|
486
|
-
const deviceInfo = this._getDeviceInfo();
|
|
487
|
-
if (deviceInfo.device) queryParams.append('device', deviceInfo.device);
|
|
488
|
-
if (deviceInfo.browser) queryParams.append('browser', deviceInfo.browser);
|
|
489
|
-
if (deviceInfo.os) queryParams.append('os', deviceInfo.os);
|
|
490
|
-
|
|
491
|
-
// Add user properties if provided
|
|
492
|
-
if (context.userProperties) {
|
|
493
|
-
queryParams.append(
|
|
494
|
-
'user_properties',
|
|
495
|
-
JSON.stringify(context.userProperties)
|
|
496
|
-
);
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
const endpoint = `/widget/surveys/active${queryParams.toString() ? '?' + queryParams.toString() : ''}`;
|
|
500
|
-
|
|
501
|
-
const response = await this._makeRequest(endpoint, {
|
|
502
|
-
method: 'GET',
|
|
503
|
-
headers: {
|
|
504
|
-
Authorization: `Bearer ${this.sessionToken}`,
|
|
505
|
-
},
|
|
506
|
-
});
|
|
507
|
-
|
|
508
|
-
return response;
|
|
509
|
-
} catch (error) {
|
|
510
|
-
if (error.status === 401) {
|
|
511
|
-
this.sessionToken = null;
|
|
512
|
-
this.sessionExpiry = null;
|
|
513
|
-
await this.init();
|
|
514
|
-
return this.getActiveSurveys(context);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
throw new APIError(
|
|
518
|
-
error.status || 500,
|
|
519
|
-
`Failed to get active surveys: ${error.message}`,
|
|
520
|
-
error.response
|
|
521
|
-
);
|
|
522
|
-
}
|
|
323
|
+
const endpoint = this.api._getEndpointWithParams(
|
|
324
|
+
'/widget/help/collections',
|
|
325
|
+
options
|
|
326
|
+
);
|
|
327
|
+
return this.api._makeRequest(endpoint, {
|
|
328
|
+
method: 'GET',
|
|
329
|
+
headers: { Authorization: `Bearer ${this.api.sessionToken}` },
|
|
330
|
+
});
|
|
523
331
|
}
|
|
524
332
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
* @returns {Object} Device info object
|
|
528
|
-
*/
|
|
529
|
-
_getDeviceInfo() {
|
|
530
|
-
if (typeof navigator === 'undefined') {
|
|
531
|
-
return { device: null, browser: null, os: null };
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
const ua = navigator.userAgent;
|
|
333
|
+
async searchHelpArticles(query, options = {}) {
|
|
334
|
+
await this.api._ensureSession();
|
|
535
335
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
336
|
+
if (this.api.mock) {
|
|
337
|
+
await delay$1(200);
|
|
338
|
+
const filtered = MOCK_HELP_COLLECTIONS.filter(
|
|
339
|
+
(c) =>
|
|
340
|
+
c.title.toLowerCase().includes(query.toLowerCase()) ||
|
|
341
|
+
c.description.toLowerCase().includes(query.toLowerCase())
|
|
342
|
+
);
|
|
343
|
+
return { status: true, data: filtered };
|
|
540
344
|
}
|
|
541
345
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
let os = 'unknown';
|
|
552
|
-
if (ua.includes('Windows')) os = 'windows';
|
|
553
|
-
else if (ua.includes('Mac')) os = 'macos';
|
|
554
|
-
else if (ua.includes('Linux')) os = 'linux';
|
|
555
|
-
else if (ua.includes('Android')) os = 'android';
|
|
556
|
-
else if (ua.includes('iPhone') || ua.includes('iPad')) os = 'ios';
|
|
557
|
-
|
|
558
|
-
return { device, browser, os };
|
|
346
|
+
const params = { q: query, ...options };
|
|
347
|
+
const endpoint = this.api._getEndpointWithParams(
|
|
348
|
+
'/widget/help/search',
|
|
349
|
+
params
|
|
350
|
+
);
|
|
351
|
+
return this.api._makeRequest(endpoint, {
|
|
352
|
+
method: 'GET',
|
|
353
|
+
headers: { Authorization: `Bearer ${this.api.sessionToken}` },
|
|
354
|
+
});
|
|
559
355
|
}
|
|
356
|
+
}
|
|
560
357
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
* @param {number|string} responseData.rating - The rating/score value
|
|
566
|
-
* @param {string} responseData.feedback - Optional text feedback
|
|
567
|
-
* @param {Object} responseData.answers - For custom surveys, key-value pairs
|
|
568
|
-
* @returns {Promise<Object>} Submission result
|
|
569
|
-
*/
|
|
570
|
-
async submitSurveyResponse(surveyId, responseData) {
|
|
571
|
-
if (!this.isSessionValid()) {
|
|
572
|
-
await this.init();
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
if (!this.sessionToken) {
|
|
576
|
-
throw new APIError(401, 'No valid session token available');
|
|
577
|
-
}
|
|
358
|
+
class MessengerService {
|
|
359
|
+
constructor(baseAPI) {
|
|
360
|
+
this.api = baseAPI;
|
|
361
|
+
}
|
|
578
362
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
}
|
|
363
|
+
async getMessengerSettings() {
|
|
364
|
+
await this.api._ensureSession();
|
|
582
365
|
|
|
583
|
-
|
|
584
|
-
if (this.mock) {
|
|
585
|
-
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
366
|
+
if (this.api.mock) {
|
|
586
367
|
return {
|
|
587
|
-
|
|
368
|
+
status: true,
|
|
588
369
|
data: {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
370
|
+
enabled: true,
|
|
371
|
+
greeting_message: 'Hi there! How can we help you today?',
|
|
372
|
+
team_name: 'Support Team',
|
|
373
|
+
response_time: 'Usually replies within a few minutes',
|
|
592
374
|
},
|
|
593
|
-
message: 'Survey response submitted successfully!',
|
|
594
375
|
};
|
|
595
376
|
}
|
|
596
377
|
|
|
597
|
-
|
|
598
|
-
rating: responseData.rating,
|
|
599
|
-
feedback: responseData.feedback || '',
|
|
600
|
-
answers: responseData.answers || {},
|
|
601
|
-
};
|
|
602
|
-
|
|
603
|
-
try {
|
|
604
|
-
const response = await this._makeRequest(
|
|
605
|
-
`/widget/surveys/${surveyId}/responses`,
|
|
606
|
-
{
|
|
607
|
-
method: 'POST',
|
|
608
|
-
body: JSON.stringify(payload),
|
|
609
|
-
headers: {
|
|
610
|
-
'Content-Type': 'application/json',
|
|
611
|
-
Authorization: `Bearer ${this.sessionToken}`,
|
|
612
|
-
},
|
|
613
|
-
}
|
|
614
|
-
);
|
|
615
|
-
|
|
616
|
-
return response;
|
|
617
|
-
} catch (error) {
|
|
618
|
-
if (error.status === 401) {
|
|
619
|
-
this.sessionToken = null;
|
|
620
|
-
this.sessionExpiry = null;
|
|
621
|
-
await this.init();
|
|
622
|
-
return this.submitSurveyResponse(surveyId, responseData);
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
throw new APIError(
|
|
626
|
-
error.status || 500,
|
|
627
|
-
`Failed to submit survey response: ${error.message}`,
|
|
628
|
-
error.response
|
|
629
|
-
);
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
/**
|
|
634
|
-
* Dismiss a survey (mark as seen but not completed)
|
|
635
|
-
* @param {string} surveyId - The survey ID to dismiss
|
|
636
|
-
* @returns {Promise<Object>} Dismissal result
|
|
637
|
-
*/
|
|
638
|
-
async dismissSurvey(surveyId) {
|
|
639
|
-
if (!this.isSessionValid()) {
|
|
640
|
-
await this.init();
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
if (!this.sessionToken) {
|
|
644
|
-
throw new APIError(401, 'No valid session token available');
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
if (!surveyId) {
|
|
648
|
-
throw new APIError(400, 'Survey ID is required');
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
// Mock mode - simulate success
|
|
652
|
-
if (this.mock) {
|
|
653
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
654
|
-
return {
|
|
655
|
-
success: true,
|
|
656
|
-
message: 'Survey dismissed successfully',
|
|
657
|
-
};
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
try {
|
|
661
|
-
const response = await this._makeRequest(
|
|
662
|
-
`/widget/surveys/${surveyId}/dismiss`,
|
|
663
|
-
{
|
|
664
|
-
method: 'POST',
|
|
665
|
-
headers: {
|
|
666
|
-
Authorization: `Bearer ${this.sessionToken}`,
|
|
667
|
-
},
|
|
668
|
-
}
|
|
669
|
-
);
|
|
670
|
-
|
|
671
|
-
return response;
|
|
672
|
-
} catch (error) {
|
|
673
|
-
if (error.status === 401) {
|
|
674
|
-
this.sessionToken = null;
|
|
675
|
-
this.sessionExpiry = null;
|
|
676
|
-
await this.init();
|
|
677
|
-
return this.dismissSurvey(surveyId);
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
throw new APIError(
|
|
681
|
-
error.status || 500,
|
|
682
|
-
`Failed to dismiss survey: ${error.message}`,
|
|
683
|
-
error.response
|
|
684
|
-
);
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
// ==========================================
|
|
689
|
-
// MESSENGER / CHAT ENDPOINTS
|
|
690
|
-
// ==========================================
|
|
691
|
-
|
|
692
|
-
/**
|
|
693
|
-
* Get messenger settings
|
|
694
|
-
* @returns {Promise<Object>} Messenger settings
|
|
695
|
-
*/
|
|
696
|
-
async getMessengerSettings() {
|
|
697
|
-
if (!this.isSessionValid()) {
|
|
698
|
-
await this.init();
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
if (this.mock) {
|
|
702
|
-
return {
|
|
703
|
-
status: true,
|
|
704
|
-
data: {
|
|
705
|
-
enabled: true,
|
|
706
|
-
greeting_message: 'Hi there! How can we help you today?',
|
|
707
|
-
team_name: 'Support Team',
|
|
708
|
-
response_time: 'Usually replies within a few minutes',
|
|
709
|
-
},
|
|
710
|
-
};
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
return this._makeRequest('/widget/messenger/settings', {
|
|
378
|
+
return this.api._makeRequest('/widget/messenger/settings', {
|
|
714
379
|
method: 'GET',
|
|
715
|
-
headers: { Authorization: `Bearer ${this.sessionToken}` },
|
|
380
|
+
headers: { Authorization: `Bearer ${this.api.sessionToken}` },
|
|
716
381
|
});
|
|
717
382
|
}
|
|
718
383
|
|
|
719
|
-
/**
|
|
720
|
-
* Check if agents are online
|
|
721
|
-
* @returns {Promise<Object>} Agent availability status
|
|
722
|
-
*/
|
|
723
384
|
async checkAgentsOnline() {
|
|
724
|
-
|
|
725
|
-
await this.init();
|
|
726
|
-
}
|
|
385
|
+
await this.api._ensureSession();
|
|
727
386
|
|
|
728
|
-
if (this.mock) {
|
|
387
|
+
if (this.api.mock) {
|
|
729
388
|
return {
|
|
730
389
|
status: true,
|
|
731
390
|
data: {
|
|
@@ -736,26 +395,17 @@
|
|
|
736
395
|
};
|
|
737
396
|
}
|
|
738
397
|
|
|
739
|
-
return this._makeRequest('/widget/messenger/agents/online', {
|
|
398
|
+
return this.api._makeRequest('/widget/messenger/agents/online', {
|
|
740
399
|
method: 'GET',
|
|
741
|
-
headers: { Authorization: `Bearer ${this.sessionToken}` },
|
|
400
|
+
headers: { Authorization: `Bearer ${this.api.sessionToken}` },
|
|
742
401
|
});
|
|
743
402
|
}
|
|
744
403
|
|
|
745
|
-
/**
|
|
746
|
-
* Get all conversations for the current contact
|
|
747
|
-
* @param {Object} options - Query options
|
|
748
|
-
* @param {number} options.page - Page number
|
|
749
|
-
* @param {number} options.limit - Items per page
|
|
750
|
-
* @returns {Promise<Object>} Conversations list
|
|
751
|
-
*/
|
|
752
404
|
async getConversations(options = {}) {
|
|
753
|
-
|
|
754
|
-
await this.init();
|
|
755
|
-
}
|
|
405
|
+
await this.api._ensureSession();
|
|
756
406
|
|
|
757
|
-
if (this.mock) {
|
|
758
|
-
await
|
|
407
|
+
if (this.api.mock) {
|
|
408
|
+
await delay$1(300);
|
|
759
409
|
return {
|
|
760
410
|
status: true,
|
|
761
411
|
data: MOCK_CONVERSATIONS,
|
|
@@ -763,92 +413,42 @@
|
|
|
763
413
|
};
|
|
764
414
|
}
|
|
765
415
|
|
|
766
|
-
const
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
return this._makeRequest(endpoint, {
|
|
416
|
+
const endpoint = this.api._getEndpointWithParams(
|
|
417
|
+
'/widget/messenger/conversations',
|
|
418
|
+
options
|
|
419
|
+
);
|
|
420
|
+
return this.api._makeRequest(endpoint, {
|
|
772
421
|
method: 'GET',
|
|
773
|
-
headers: { Authorization: `Bearer ${this.sessionToken}` },
|
|
422
|
+
headers: { Authorization: `Bearer ${this.api.sessionToken}` },
|
|
774
423
|
});
|
|
775
424
|
}
|
|
776
425
|
|
|
777
|
-
/**
|
|
778
|
-
* Get a single conversation with messages
|
|
779
|
-
* @param {string} conversationId - Conversation ID
|
|
780
|
-
* @returns {Promise<Object>} Conversation with messages
|
|
781
|
-
*/
|
|
782
426
|
async getConversation(conversationId) {
|
|
783
|
-
|
|
784
|
-
await this.init();
|
|
785
|
-
}
|
|
427
|
+
await this.api._ensureSession();
|
|
786
428
|
|
|
787
|
-
if (this.mock) {
|
|
788
|
-
await
|
|
429
|
+
if (this.api.mock) {
|
|
430
|
+
await delay$1(200);
|
|
789
431
|
const conv = MOCK_CONVERSATIONS.find((c) => c.id === conversationId);
|
|
790
432
|
return {
|
|
791
433
|
status: true,
|
|
792
|
-
data: {
|
|
793
|
-
...conv,
|
|
794
|
-
messages: MOCK_MESSAGES[conversationId] || [],
|
|
795
|
-
},
|
|
434
|
+
data: { ...conv, messages: MOCK_MESSAGES[conversationId] || [] },
|
|
796
435
|
};
|
|
797
436
|
}
|
|
798
437
|
|
|
799
|
-
return this._makeRequest(
|
|
438
|
+
return this.api._makeRequest(
|
|
800
439
|
`/widget/messenger/conversations/${conversationId}`,
|
|
801
440
|
{
|
|
802
441
|
method: 'GET',
|
|
803
|
-
headers: { Authorization: `Bearer ${this.sessionToken}` },
|
|
442
|
+
headers: { Authorization: `Bearer ${this.api.sessionToken}` },
|
|
804
443
|
}
|
|
805
444
|
);
|
|
806
445
|
}
|
|
807
446
|
|
|
808
|
-
/**
|
|
809
|
-
* Get messages for a conversation
|
|
810
|
-
* @param {string} conversationId - Conversation ID
|
|
811
|
-
* @param {Object} options - Query options
|
|
812
|
-
* @returns {Promise<Object>} Messages list
|
|
813
|
-
*/
|
|
814
|
-
async getMessages(conversationId, options = {}) {
|
|
815
|
-
if (!this.isSessionValid()) {
|
|
816
|
-
await this.init();
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
if (this.mock) {
|
|
820
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
821
|
-
return {
|
|
822
|
-
status: true,
|
|
823
|
-
data: MOCK_MESSAGES[conversationId] || [],
|
|
824
|
-
};
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
const params = new URLSearchParams();
|
|
828
|
-
if (options.page) params.append('page', options.page);
|
|
829
|
-
if (options.limit) params.append('limit', options.limit);
|
|
830
|
-
|
|
831
|
-
const endpoint = `/widget/messenger/conversations/${conversationId}/messages${params.toString() ? '?' + params.toString() : ''}`;
|
|
832
|
-
return this._makeRequest(endpoint, {
|
|
833
|
-
method: 'GET',
|
|
834
|
-
headers: { Authorization: `Bearer ${this.sessionToken}` },
|
|
835
|
-
});
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
/**
|
|
839
|
-
* Start a new conversation
|
|
840
|
-
* @param {Object} data - Conversation data
|
|
841
|
-
* @param {string} data.message - Initial message content
|
|
842
|
-
* @param {string} data.subject - Optional subject
|
|
843
|
-
* @returns {Promise<Object>} Created conversation
|
|
844
|
-
*/
|
|
845
447
|
async startConversation(data) {
|
|
846
|
-
|
|
847
|
-
await this.init();
|
|
848
|
-
}
|
|
448
|
+
await this.api._ensureSession();
|
|
849
449
|
|
|
850
|
-
if (this.mock) {
|
|
851
|
-
await
|
|
450
|
+
if (this.api.mock) {
|
|
451
|
+
await delay$1(300);
|
|
852
452
|
const newConv = {
|
|
853
453
|
id: 'conv_' + Date.now(),
|
|
854
454
|
subject: data.subject || 'New conversation',
|
|
@@ -869,11 +469,11 @@
|
|
|
869
469
|
return { status: true, data: newConv };
|
|
870
470
|
}
|
|
871
471
|
|
|
872
|
-
return this._makeRequest('/widget/messenger/conversations', {
|
|
472
|
+
return this.api._makeRequest('/widget/messenger/conversations', {
|
|
873
473
|
method: 'POST',
|
|
874
474
|
headers: {
|
|
875
475
|
'Content-Type': 'application/json',
|
|
876
|
-
Authorization: `Bearer ${this.sessionToken}`,
|
|
476
|
+
Authorization: `Bearer ${this.api.sessionToken}`,
|
|
877
477
|
},
|
|
878
478
|
body: JSON.stringify({
|
|
879
479
|
message: data.message,
|
|
@@ -882,20 +482,11 @@
|
|
|
882
482
|
});
|
|
883
483
|
}
|
|
884
484
|
|
|
885
|
-
/**
|
|
886
|
-
* Send a message in a conversation
|
|
887
|
-
* @param {string} conversationId - Conversation ID
|
|
888
|
-
* @param {Object} data - Message data
|
|
889
|
-
* @param {string} data.content - Message content
|
|
890
|
-
* @returns {Promise<Object>} Sent message
|
|
891
|
-
*/
|
|
892
485
|
async sendMessage(conversationId, data) {
|
|
893
|
-
|
|
894
|
-
await this.init();
|
|
895
|
-
}
|
|
486
|
+
await this.api._ensureSession();
|
|
896
487
|
|
|
897
|
-
if (this.mock) {
|
|
898
|
-
await
|
|
488
|
+
if (this.api.mock) {
|
|
489
|
+
await delay$1(200);
|
|
899
490
|
const newMessage = {
|
|
900
491
|
id: 'msg_' + Date.now(),
|
|
901
492
|
content: data.content,
|
|
@@ -909,80 +500,23 @@
|
|
|
909
500
|
return { status: true, data: newMessage };
|
|
910
501
|
}
|
|
911
502
|
|
|
912
|
-
return this._makeRequest(
|
|
503
|
+
return this.api._makeRequest(
|
|
913
504
|
`/widget/messenger/conversations/${conversationId}/messages`,
|
|
914
505
|
{
|
|
915
506
|
method: 'POST',
|
|
916
507
|
headers: {
|
|
917
508
|
'Content-Type': 'application/json',
|
|
918
|
-
Authorization: `Bearer ${this.sessionToken}`,
|
|
509
|
+
Authorization: `Bearer ${this.api.sessionToken}`,
|
|
919
510
|
},
|
|
920
511
|
body: JSON.stringify({ content: data.content }),
|
|
921
512
|
}
|
|
922
513
|
);
|
|
923
514
|
}
|
|
924
515
|
|
|
925
|
-
/**
|
|
926
|
-
* Send typing indicator
|
|
927
|
-
* @param {string} conversationId - Conversation ID
|
|
928
|
-
* @param {boolean} isTyping - Whether user is typing
|
|
929
|
-
* @returns {Promise<Object>} Response
|
|
930
|
-
*/
|
|
931
|
-
async sendTypingIndicator(conversationId, isTyping) {
|
|
932
|
-
if (!this.isSessionValid()) {
|
|
933
|
-
await this.init();
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
if (this.mock) {
|
|
937
|
-
return { status: true };
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
return this._makeRequest(
|
|
941
|
-
`/widget/messenger/conversations/${conversationId}/typing`,
|
|
942
|
-
{
|
|
943
|
-
method: 'POST',
|
|
944
|
-
headers: {
|
|
945
|
-
'Content-Type': 'application/json',
|
|
946
|
-
Authorization: `Bearer ${this.sessionToken}`,
|
|
947
|
-
},
|
|
948
|
-
body: JSON.stringify({ is_typing: isTyping }),
|
|
949
|
-
}
|
|
950
|
-
);
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
/**
|
|
954
|
-
* Mark conversation as read
|
|
955
|
-
* @param {string} conversationId - Conversation ID
|
|
956
|
-
* @returns {Promise<Object>} Response
|
|
957
|
-
*/
|
|
958
|
-
async markConversationAsRead(conversationId) {
|
|
959
|
-
if (!this.isSessionValid()) {
|
|
960
|
-
await this.init();
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
if (this.mock) {
|
|
964
|
-
return { status: true };
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
return this._makeRequest(
|
|
968
|
-
`/widget/messenger/conversations/${conversationId}/read`,
|
|
969
|
-
{
|
|
970
|
-
method: 'POST',
|
|
971
|
-
headers: { Authorization: `Bearer ${this.sessionToken}` },
|
|
972
|
-
}
|
|
973
|
-
);
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
/**
|
|
977
|
-
* Get unread count
|
|
978
|
-
* @returns {Promise<Object>} Unread count data
|
|
979
|
-
*/
|
|
980
516
|
async getUnreadCount() {
|
|
981
|
-
|
|
982
|
-
await this.init();
|
|
983
|
-
}
|
|
517
|
+
await this.api._ensureSession();
|
|
984
518
|
|
|
985
|
-
if (this.mock) {
|
|
519
|
+
if (this.api.mock) {
|
|
986
520
|
const count = MOCK_CONVERSATIONS.reduce(
|
|
987
521
|
(sum, c) => sum + (c.unread || 0),
|
|
988
522
|
0
|
|
@@ -993,187 +527,325 @@
|
|
|
993
527
|
};
|
|
994
528
|
}
|
|
995
529
|
|
|
996
|
-
return this._makeRequest('/widget/messenger/unread', {
|
|
530
|
+
return this.api._makeRequest('/widget/messenger/unread', {
|
|
997
531
|
method: 'GET',
|
|
998
|
-
headers: { Authorization: `Bearer ${this.sessionToken}` },
|
|
532
|
+
headers: { Authorization: `Bearer ${this.api.sessionToken}` },
|
|
999
533
|
});
|
|
1000
534
|
}
|
|
1001
535
|
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
* @param {string} conversationId - Conversation ID
|
|
1005
|
-
* @param {Object} data - Rating data
|
|
1006
|
-
* @param {number} data.rating - Rating (1-5 or thumbs up/down)
|
|
1007
|
-
* @param {string} data.comment - Optional comment
|
|
1008
|
-
* @returns {Promise<Object>} Response
|
|
1009
|
-
*/
|
|
1010
|
-
async submitRating(conversationId, data) {
|
|
1011
|
-
if (!this.isSessionValid()) {
|
|
1012
|
-
await this.init();
|
|
1013
|
-
}
|
|
536
|
+
async markConversationAsRead(conversationId) {
|
|
537
|
+
await this.api._ensureSession();
|
|
1014
538
|
|
|
1015
|
-
if (this.mock) {
|
|
1016
|
-
return { status: true
|
|
539
|
+
if (this.api.mock) {
|
|
540
|
+
return { status: true };
|
|
1017
541
|
}
|
|
1018
542
|
|
|
1019
|
-
return this._makeRequest(
|
|
1020
|
-
`/widget/messenger/conversations/${conversationId}/
|
|
543
|
+
return this.api._makeRequest(
|
|
544
|
+
`/widget/messenger/conversations/${conversationId}/read`,
|
|
1021
545
|
{
|
|
1022
546
|
method: 'POST',
|
|
1023
|
-
headers: {
|
|
1024
|
-
'Content-Type': 'application/json',
|
|
1025
|
-
Authorization: `Bearer ${this.sessionToken}`,
|
|
1026
|
-
},
|
|
1027
|
-
body: JSON.stringify({
|
|
1028
|
-
rating: data.rating,
|
|
1029
|
-
comment: data.comment || '',
|
|
1030
|
-
}),
|
|
547
|
+
headers: { Authorization: `Bearer ${this.api.sessionToken}` },
|
|
1031
548
|
}
|
|
1032
549
|
);
|
|
1033
550
|
}
|
|
551
|
+
}
|
|
1034
552
|
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
* @returns {Promise<Object>} Response
|
|
1041
|
-
*/
|
|
1042
|
-
async identifyContact(data) {
|
|
1043
|
-
if (!this.isSessionValid()) {
|
|
1044
|
-
await this.init();
|
|
1045
|
-
}
|
|
553
|
+
class SDKError extends Error {
|
|
554
|
+
constructor(message, cause) {
|
|
555
|
+
super(message);
|
|
556
|
+
this.name = 'SDKError';
|
|
557
|
+
this.cause = cause;
|
|
1046
558
|
|
|
1047
|
-
if (
|
|
1048
|
-
|
|
559
|
+
if (Error.captureStackTrace) {
|
|
560
|
+
Error.captureStackTrace(this, SDKError);
|
|
1049
561
|
}
|
|
1050
|
-
|
|
1051
|
-
return this._makeRequest('/widget/messenger/identify', {
|
|
1052
|
-
method: 'POST',
|
|
1053
|
-
headers: {
|
|
1054
|
-
'Content-Type': 'application/json',
|
|
1055
|
-
Authorization: `Bearer ${this.sessionToken}`,
|
|
1056
|
-
},
|
|
1057
|
-
body: JSON.stringify(data),
|
|
1058
|
-
});
|
|
1059
562
|
}
|
|
563
|
+
}
|
|
1060
564
|
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
565
|
+
class APIError extends Error {
|
|
566
|
+
constructor(status, message, response) {
|
|
567
|
+
super(message);
|
|
568
|
+
this.name = 'APIError';
|
|
569
|
+
this.status = status;
|
|
570
|
+
this.response = response;
|
|
1064
571
|
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
* @param {Object} options - Query options
|
|
1068
|
-
* @returns {Promise<Object>} Collections list
|
|
1069
|
-
*/
|
|
1070
|
-
async getHelpCollections(options = {}) {
|
|
1071
|
-
if (!this.isSessionValid()) {
|
|
1072
|
-
await this.init();
|
|
572
|
+
if (Error.captureStackTrace) {
|
|
573
|
+
Error.captureStackTrace(this, APIError);
|
|
1073
574
|
}
|
|
575
|
+
}
|
|
1074
576
|
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
}
|
|
577
|
+
isNetworkError() {
|
|
578
|
+
return this.status === 0;
|
|
579
|
+
}
|
|
1079
580
|
|
|
1080
|
-
|
|
1081
|
-
|
|
581
|
+
isClientError() {
|
|
582
|
+
return this.status >= 400 && this.status < 500;
|
|
583
|
+
}
|
|
1082
584
|
|
|
1083
|
-
|
|
1084
|
-
return this.
|
|
1085
|
-
method: 'GET',
|
|
1086
|
-
headers: { Authorization: `Bearer ${this.sessionToken}` },
|
|
1087
|
-
});
|
|
585
|
+
isServerError() {
|
|
586
|
+
return this.status >= 500 && this.status < 600;
|
|
1088
587
|
}
|
|
588
|
+
}
|
|
1089
589
|
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
if (
|
|
1098
|
-
|
|
590
|
+
class WidgetError extends Error {
|
|
591
|
+
constructor(message, widgetType, widgetId) {
|
|
592
|
+
super(message);
|
|
593
|
+
this.name = 'WidgetError';
|
|
594
|
+
this.widgetType = widgetType;
|
|
595
|
+
this.widgetId = widgetId;
|
|
596
|
+
|
|
597
|
+
if (Error.captureStackTrace) {
|
|
598
|
+
Error.captureStackTrace(this, WidgetError);
|
|
1099
599
|
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
1100
602
|
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
603
|
+
class ConfigError extends Error {
|
|
604
|
+
constructor(message, configKey) {
|
|
605
|
+
super(message);
|
|
606
|
+
this.name = 'ConfigError';
|
|
607
|
+
this.configKey = configKey;
|
|
608
|
+
|
|
609
|
+
if (Error.captureStackTrace) {
|
|
610
|
+
Error.captureStackTrace(this, ConfigError);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
class ValidationError extends Error {
|
|
616
|
+
constructor(message, field, value) {
|
|
617
|
+
super(message);
|
|
618
|
+
this.name = 'ValidationError';
|
|
619
|
+
this.field = field;
|
|
620
|
+
this.value = value;
|
|
621
|
+
|
|
622
|
+
if (Error.captureStackTrace) {
|
|
623
|
+
Error.captureStackTrace(this, ValidationError);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
class SurveyService {
|
|
629
|
+
constructor(baseAPI) {
|
|
630
|
+
this.api = baseAPI;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
async getActiveSurveys(context = {}) {
|
|
634
|
+
await this.api._ensureSession();
|
|
635
|
+
|
|
636
|
+
if (this.api.mock) {
|
|
637
|
+
await delay$1(200);
|
|
638
|
+
return { success: true, data: MOCK_SURVEYS };
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
const params = {
|
|
642
|
+
url:
|
|
643
|
+
context.url ||
|
|
644
|
+
(typeof window !== 'undefined' ? window.location.href : ''),
|
|
645
|
+
...getDeviceInfo(),
|
|
646
|
+
...(context.userProperties && {
|
|
647
|
+
user_properties: context.userProperties,
|
|
648
|
+
}),
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
return this.api._handleAuthRetry(async () => {
|
|
652
|
+
const endpoint = this.api._getEndpointWithParams(
|
|
653
|
+
'/widget/surveys/active',
|
|
654
|
+
params
|
|
1107
655
|
);
|
|
1108
|
-
return
|
|
656
|
+
return await this.api._makeRequest(endpoint, {
|
|
657
|
+
method: 'GET',
|
|
658
|
+
headers: { Authorization: `Bearer ${this.api.sessionToken}` },
|
|
659
|
+
});
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
async submitSurveyResponse(surveyId, responseData) {
|
|
664
|
+
if (!surveyId) throw new APIError(400, 'Survey ID is required');
|
|
665
|
+
|
|
666
|
+
await this.api._ensureSession();
|
|
667
|
+
|
|
668
|
+
if (this.api.mock) {
|
|
669
|
+
await delay$1(300);
|
|
670
|
+
return {
|
|
671
|
+
success: true,
|
|
672
|
+
data: {
|
|
673
|
+
id: 'mock_response_' + Date.now(),
|
|
674
|
+
survey_id: surveyId,
|
|
675
|
+
...responseData,
|
|
676
|
+
},
|
|
677
|
+
message: 'Survey response submitted successfully!',
|
|
678
|
+
};
|
|
1109
679
|
}
|
|
1110
680
|
|
|
1111
|
-
const
|
|
1112
|
-
|
|
681
|
+
const payload = {
|
|
682
|
+
rating: responseData.rating,
|
|
683
|
+
feedback: responseData.feedback || '',
|
|
684
|
+
answers: responseData.answers || {},
|
|
685
|
+
};
|
|
1113
686
|
|
|
1114
|
-
return this.
|
|
1115
|
-
|
|
1116
|
-
|
|
687
|
+
return this.api._handleAuthRetry(async () => {
|
|
688
|
+
return await this.api._makeRequest(
|
|
689
|
+
`/widget/surveys/${surveyId}/responses`,
|
|
690
|
+
{
|
|
691
|
+
method: 'POST',
|
|
692
|
+
body: JSON.stringify(payload),
|
|
693
|
+
headers: {
|
|
694
|
+
'Content-Type': 'application/json',
|
|
695
|
+
Authorization: `Bearer ${this.api.sessionToken}`,
|
|
696
|
+
},
|
|
697
|
+
}
|
|
698
|
+
);
|
|
1117
699
|
});
|
|
1118
700
|
}
|
|
1119
701
|
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
// ==========================================
|
|
702
|
+
async dismissSurvey(surveyId) {
|
|
703
|
+
if (!surveyId) throw new APIError(400, 'Survey ID is required');
|
|
1123
704
|
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
* @returns {Promise<Object>} Changelogs response
|
|
1130
|
-
*/
|
|
1131
|
-
async getChangelogs(options = {}) {
|
|
1132
|
-
if (!this.isSessionValid()) {
|
|
1133
|
-
await this.init();
|
|
705
|
+
await this.api._ensureSession();
|
|
706
|
+
|
|
707
|
+
if (this.api.mock) {
|
|
708
|
+
await delay$1(100);
|
|
709
|
+
return { success: true, message: 'Survey dismissed successfully' };
|
|
1134
710
|
}
|
|
1135
711
|
|
|
1136
|
-
|
|
1137
|
-
|
|
712
|
+
return this.api._handleAuthRetry(async () => {
|
|
713
|
+
return await this.api._makeRequest(
|
|
714
|
+
`/widget/surveys/${surveyId}/dismiss`,
|
|
715
|
+
{
|
|
716
|
+
method: 'POST',
|
|
717
|
+
headers: { Authorization: `Bearer ${this.api.sessionToken}` },
|
|
718
|
+
}
|
|
719
|
+
);
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
class BaseAPIService {
|
|
725
|
+
constructor(config = {}) {
|
|
726
|
+
this.workspace = config.workspace;
|
|
727
|
+
this.sessionToken = null;
|
|
728
|
+
this.sessionExpiry = null;
|
|
729
|
+
this.userContext = config.userContext || null;
|
|
730
|
+
this.mock = config.mock || false;
|
|
731
|
+
this.env = config.env || 'production';
|
|
732
|
+
this.baseURL = this._getBaseURL(config);
|
|
733
|
+
|
|
734
|
+
this._loadStoredSession();
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
_getBaseURL(config) {
|
|
738
|
+
if (config.apiUrl) return config.apiUrl;
|
|
739
|
+
|
|
740
|
+
const ENV_URLS = {
|
|
741
|
+
production: {
|
|
742
|
+
base: 'https://api.product7.io/api/v1',
|
|
743
|
+
withWorkspace: (ws) => `https://${ws}.api.product7.io/api/v1`,
|
|
744
|
+
},
|
|
745
|
+
staging: {
|
|
746
|
+
base: 'https://staging.api.product7.io/api/v1',
|
|
747
|
+
withWorkspace: (ws) => `https://${ws}.staging.api.product7.io/api/v1`,
|
|
748
|
+
},
|
|
749
|
+
};
|
|
750
|
+
|
|
751
|
+
const envConfig = ENV_URLS[this.env] || ENV_URLS.production;
|
|
752
|
+
return this.workspace
|
|
753
|
+
? envConfig.withWorkspace(this.workspace)
|
|
754
|
+
: envConfig.base;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
async init(userContext = null) {
|
|
758
|
+
if (userContext) {
|
|
759
|
+
this.userContext = userContext;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
if (this.isSessionValid()) {
|
|
763
|
+
return { sessionToken: this.sessionToken };
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
if (!this.workspace || !this.userContext) {
|
|
767
|
+
throw new APIError(
|
|
768
|
+
400,
|
|
769
|
+
`Missing ${!this.workspace ? 'workspace' : 'user context'} for initialization`
|
|
770
|
+
);
|
|
1138
771
|
}
|
|
1139
772
|
|
|
1140
|
-
// Mock mode - return mock changelogs
|
|
1141
773
|
if (this.mock) {
|
|
1142
|
-
|
|
1143
|
-
return {
|
|
1144
|
-
success: true,
|
|
1145
|
-
data: MOCK_CHANGELOGS,
|
|
1146
|
-
};
|
|
774
|
+
return this._initMockSession();
|
|
1147
775
|
}
|
|
1148
776
|
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
777
|
+
return this._initRealSession();
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
async _initMockSession() {
|
|
781
|
+
this.sessionToken = 'mock_session_' + Date.now();
|
|
782
|
+
this.sessionExpiry = new Date(Date.now() + 3600 * 1000);
|
|
783
|
+
this._storeSession();
|
|
784
|
+
return {
|
|
785
|
+
sessionToken: this.sessionToken,
|
|
786
|
+
config: {
|
|
787
|
+
primaryColor: '#21244A',
|
|
788
|
+
backgroundColor: '#ffffff',
|
|
789
|
+
textColor: '#1F2937',
|
|
790
|
+
boardId: 'feature-requests',
|
|
791
|
+
size: 'medium',
|
|
792
|
+
displayMode: 'modal',
|
|
793
|
+
},
|
|
794
|
+
expiresIn: 3600,
|
|
795
|
+
};
|
|
796
|
+
}
|
|
1153
797
|
|
|
1154
|
-
|
|
798
|
+
async _initRealSession() {
|
|
799
|
+
const payload = {
|
|
800
|
+
workspace: this.workspace,
|
|
801
|
+
user: this.userContext,
|
|
802
|
+
};
|
|
1155
803
|
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
},
|
|
804
|
+
try {
|
|
805
|
+
const response = await this._makeRequest('/widget/init', {
|
|
806
|
+
method: 'POST',
|
|
807
|
+
body: JSON.stringify(payload),
|
|
808
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1161
809
|
});
|
|
1162
810
|
|
|
1163
|
-
|
|
811
|
+
this.sessionToken = response.session_token;
|
|
812
|
+
this.sessionExpiry = new Date(Date.now() + response.expires_in * 1000);
|
|
813
|
+
this._storeSession();
|
|
814
|
+
|
|
815
|
+
return {
|
|
816
|
+
sessionToken: this.sessionToken,
|
|
817
|
+
config: response.config || {},
|
|
818
|
+
expiresIn: response.expires_in,
|
|
819
|
+
};
|
|
820
|
+
} catch (error) {
|
|
821
|
+
throw new APIError(
|
|
822
|
+
error.status || 500,
|
|
823
|
+
`Failed to initialize widget: ${error.message}`,
|
|
824
|
+
error.response
|
|
825
|
+
);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
async _ensureSession() {
|
|
830
|
+
if (!this.isSessionValid()) {
|
|
831
|
+
await this.init();
|
|
832
|
+
}
|
|
833
|
+
if (!this.sessionToken) {
|
|
834
|
+
throw new APIError(401, 'No valid session token available');
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
async _handleAuthRetry(method, ...args) {
|
|
839
|
+
try {
|
|
840
|
+
return await method.apply(this, args);
|
|
1164
841
|
} catch (error) {
|
|
1165
842
|
if (error.status === 401) {
|
|
1166
843
|
this.sessionToken = null;
|
|
1167
844
|
this.sessionExpiry = null;
|
|
1168
845
|
await this.init();
|
|
1169
|
-
return
|
|
846
|
+
return await method.apply(this, args);
|
|
1170
847
|
}
|
|
1171
|
-
|
|
1172
|
-
throw new APIError(
|
|
1173
|
-
error.status || 500,
|
|
1174
|
-
`Failed to get changelogs: ${error.message}`,
|
|
1175
|
-
error.response
|
|
1176
|
-
);
|
|
848
|
+
throw error;
|
|
1177
849
|
}
|
|
1178
850
|
}
|
|
1179
851
|
|
|
@@ -1185,12 +857,7 @@
|
|
|
1185
857
|
|
|
1186
858
|
setUserContext(userContext) {
|
|
1187
859
|
this.userContext = userContext;
|
|
1188
|
-
|
|
1189
|
-
localStorage.setItem(
|
|
1190
|
-
'feedbackSDK_userContext',
|
|
1191
|
-
JSON.stringify(userContext)
|
|
1192
|
-
);
|
|
1193
|
-
}
|
|
860
|
+
this._storeData('feedbackSDK_userContext', userContext);
|
|
1194
861
|
}
|
|
1195
862
|
|
|
1196
863
|
getUserContext() {
|
|
@@ -1200,30 +867,26 @@
|
|
|
1200
867
|
clearSession() {
|
|
1201
868
|
this.sessionToken = null;
|
|
1202
869
|
this.sessionExpiry = null;
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
localStorage.removeItem('feedbackSDK_userContext');
|
|
1206
|
-
}
|
|
870
|
+
this._removeData('feedbackSDK_session');
|
|
871
|
+
this._removeData('feedbackSDK_userContext');
|
|
1207
872
|
}
|
|
1208
873
|
|
|
1209
874
|
_storeSession() {
|
|
1210
875
|
if (typeof localStorage === 'undefined') return;
|
|
1211
|
-
|
|
1212
876
|
try {
|
|
1213
877
|
const sessionData = {
|
|
1214
878
|
token: this.sessionToken,
|
|
1215
879
|
expiry: this.sessionExpiry.toISOString(),
|
|
1216
880
|
workspace: this.workspace,
|
|
1217
881
|
};
|
|
1218
|
-
|
|
882
|
+
this._storeData('feedbackSDK_session', sessionData);
|
|
1219
883
|
} catch (error) {
|
|
1220
|
-
//
|
|
884
|
+
// Silent fail
|
|
1221
885
|
}
|
|
1222
886
|
}
|
|
1223
887
|
|
|
1224
888
|
_loadStoredSession() {
|
|
1225
889
|
if (typeof localStorage === 'undefined') return false;
|
|
1226
|
-
|
|
1227
890
|
try {
|
|
1228
891
|
const stored = localStorage.getItem('feedbackSDK_session');
|
|
1229
892
|
if (!stored) return false;
|
|
@@ -1238,6 +901,18 @@
|
|
|
1238
901
|
}
|
|
1239
902
|
}
|
|
1240
903
|
|
|
904
|
+
_storeData(key, value) {
|
|
905
|
+
if (typeof localStorage !== 'undefined') {
|
|
906
|
+
localStorage.setItem(key, JSON.stringify(value));
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
_removeData(key) {
|
|
911
|
+
if (typeof localStorage !== 'undefined') {
|
|
912
|
+
localStorage.removeItem(key);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
|
|
1241
916
|
async _makeRequest(endpoint, options = {}) {
|
|
1242
917
|
const url = `${this.baseURL}${endpoint}`;
|
|
1243
918
|
|
|
@@ -1266,68 +941,172 @@
|
|
|
1266
941
|
|
|
1267
942
|
return await response.text();
|
|
1268
943
|
} catch (error) {
|
|
1269
|
-
if (error instanceof APIError)
|
|
1270
|
-
throw error;
|
|
1271
|
-
}
|
|
944
|
+
if (error instanceof APIError) throw error;
|
|
1272
945
|
throw new APIError(0, error.message, null);
|
|
1273
946
|
}
|
|
1274
947
|
}
|
|
1275
|
-
}
|
|
1276
948
|
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
949
|
+
_buildQueryParams(params) {
|
|
950
|
+
const queryParams = new URLSearchParams();
|
|
951
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
952
|
+
if (value !== undefined && value !== null) {
|
|
953
|
+
queryParams.append(
|
|
954
|
+
key,
|
|
955
|
+
typeof value === 'object' ? JSON.stringify(value) : value
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
});
|
|
959
|
+
return queryParams.toString();
|
|
1280
960
|
}
|
|
1281
961
|
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
}
|
|
1286
|
-
this.events.get(event).push(callback);
|
|
1287
|
-
|
|
1288
|
-
return () => this.off(event, callback);
|
|
962
|
+
_getEndpointWithParams(endpoint, params) {
|
|
963
|
+
const queryString = this._buildQueryParams(params);
|
|
964
|
+
return `${endpoint}${queryString ? '?' + queryString : ''}`;
|
|
1289
965
|
}
|
|
966
|
+
}
|
|
1290
967
|
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
968
|
+
class APIService extends BaseAPIService {
|
|
969
|
+
constructor(config = {}) {
|
|
970
|
+
super(config);
|
|
971
|
+
|
|
972
|
+
this.feedback = new FeedbackService(this);
|
|
973
|
+
this.survey = new SurveyService(this);
|
|
974
|
+
this.messenger = new MessengerService(this);
|
|
975
|
+
this.help = new HelpService(this);
|
|
976
|
+
this.changelog = new ChangelogService(this);
|
|
1299
977
|
}
|
|
1300
978
|
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
if (callbacks) {
|
|
1304
|
-
callbacks.forEach((callback) => {
|
|
1305
|
-
try {
|
|
1306
|
-
callback(data);
|
|
1307
|
-
} catch (error) {
|
|
1308
|
-
console.error('[FeedbackSDK] Event callback error:', error);
|
|
1309
|
-
}
|
|
1310
|
-
});
|
|
1311
|
-
}
|
|
979
|
+
async submitFeedback(data) {
|
|
980
|
+
return this.feedback.submitFeedback(data);
|
|
1312
981
|
}
|
|
1313
982
|
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
callback(data);
|
|
1317
|
-
unsubscribe();
|
|
1318
|
-
});
|
|
1319
|
-
return unsubscribe;
|
|
983
|
+
async getActiveSurveys(context) {
|
|
984
|
+
return this.survey.getActiveSurveys(context);
|
|
1320
985
|
}
|
|
1321
986
|
|
|
1322
|
-
|
|
1323
|
-
this.
|
|
987
|
+
async submitSurveyResponse(surveyId, responseData) {
|
|
988
|
+
return this.survey.submitSurveyResponse(surveyId, responseData);
|
|
1324
989
|
}
|
|
1325
990
|
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
return callbacks ? callbacks.length : 0;
|
|
991
|
+
async dismissSurvey(surveyId) {
|
|
992
|
+
return this.survey.dismissSurvey(surveyId);
|
|
1329
993
|
}
|
|
1330
|
-
|
|
994
|
+
|
|
995
|
+
async getMessengerSettings() {
|
|
996
|
+
return this.messenger.getMessengerSettings();
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
async checkAgentsOnline() {
|
|
1000
|
+
return this.messenger.checkAgentsOnline();
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
async getConversations(options) {
|
|
1004
|
+
return this.messenger.getConversations(options);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
async getConversation(conversationId) {
|
|
1008
|
+
return this.messenger.getConversation(conversationId);
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
async getMessages(conversationId, options) {
|
|
1012
|
+
return this.messenger.getMessages(conversationId, options);
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
async startConversation(data) {
|
|
1016
|
+
return this.messenger.startConversation(data);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
async sendMessage(conversationId, data) {
|
|
1020
|
+
return this.messenger.sendMessage(conversationId, data);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
async sendTypingIndicator(conversationId, isTyping) {
|
|
1024
|
+
return this.messenger.sendTypingIndicator(conversationId, isTyping);
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
async markConversationAsRead(conversationId) {
|
|
1028
|
+
return this.messenger.markConversationAsRead(conversationId);
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
async getUnreadCount() {
|
|
1032
|
+
return this.messenger.getUnreadCount();
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
async submitRating(conversationId, data) {
|
|
1036
|
+
return this.messenger.submitRating(conversationId, data);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
async identifyContact(data) {
|
|
1040
|
+
return this.messenger.identifyContact(data);
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
async getHelpCollections(options) {
|
|
1044
|
+
return this.help.getHelpCollections(options);
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
async searchHelpArticles(query, options) {
|
|
1048
|
+
return this.help.searchHelpArticles(query, options);
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
async getChangelogs(options) {
|
|
1052
|
+
return this.changelog.getChangelogs(options);
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
class EventBus {
|
|
1057
|
+
constructor() {
|
|
1058
|
+
this.events = new Map();
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
on(event, callback) {
|
|
1062
|
+
if (!this.events.has(event)) {
|
|
1063
|
+
this.events.set(event, []);
|
|
1064
|
+
}
|
|
1065
|
+
this.events.get(event).push(callback);
|
|
1066
|
+
|
|
1067
|
+
return () => this.off(event, callback);
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
off(event, callback) {
|
|
1071
|
+
const callbacks = this.events.get(event);
|
|
1072
|
+
if (callbacks) {
|
|
1073
|
+
const index = callbacks.indexOf(callback);
|
|
1074
|
+
if (index > -1) {
|
|
1075
|
+
callbacks.splice(index, 1);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
emit(event, data) {
|
|
1081
|
+
const callbacks = this.events.get(event);
|
|
1082
|
+
if (callbacks) {
|
|
1083
|
+
callbacks.forEach((callback) => {
|
|
1084
|
+
try {
|
|
1085
|
+
callback(data);
|
|
1086
|
+
} catch (error) {
|
|
1087
|
+
console.error('[FeedbackSDK] Event callback error:', error);
|
|
1088
|
+
}
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
once(event, callback) {
|
|
1094
|
+
const unsubscribe = this.on(event, (data) => {
|
|
1095
|
+
callback(data);
|
|
1096
|
+
unsubscribe();
|
|
1097
|
+
});
|
|
1098
|
+
return unsubscribe;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
clear() {
|
|
1102
|
+
this.events.clear();
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
getListenerCount(event) {
|
|
1106
|
+
const callbacks = this.events.get(event);
|
|
1107
|
+
return callbacks ? callbacks.length : 0;
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1331
1110
|
|
|
1332
1111
|
function generateId(prefix = 'feedback') {
|
|
1333
1112
|
const timestamp = Date.now();
|
|
@@ -2630,11 +2409,6 @@
|
|
|
2630
2409
|
}
|
|
2631
2410
|
</div>
|
|
2632
2411
|
</div>
|
|
2633
|
-
<div class="changelog-list-item-arrow">
|
|
2634
|
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
2635
|
-
<path d="M9 18l6-6-6-6"/>
|
|
2636
|
-
</svg>
|
|
2637
|
-
</div>
|
|
2638
2412
|
</div>
|
|
2639
2413
|
`;
|
|
2640
2414
|
}
|
|
@@ -3508,15 +3282,12 @@
|
|
|
3508
3282
|
}
|
|
3509
3283
|
}
|
|
3510
3284
|
|
|
3511
|
-
/**
|
|
3512
|
-
* MessengerLauncher - Floating trigger button for messenger
|
|
3513
|
-
*/
|
|
3514
3285
|
class MessengerLauncher {
|
|
3515
3286
|
constructor(state, options = {}) {
|
|
3516
3287
|
this.state = state;
|
|
3517
3288
|
this.options = {
|
|
3518
3289
|
position: options.position || 'bottom-right',
|
|
3519
|
-
primaryColor: options.primaryColor || '#
|
|
3290
|
+
primaryColor: options.primaryColor || '#155eff',
|
|
3520
3291
|
...options,
|
|
3521
3292
|
};
|
|
3522
3293
|
this.element = null;
|
|
@@ -3530,7 +3301,6 @@
|
|
|
3530
3301
|
this._updateContent();
|
|
3531
3302
|
this._attachEvents();
|
|
3532
3303
|
|
|
3533
|
-
// Subscribe to state changes
|
|
3534
3304
|
this._unsubscribe = this.state.subscribe((type, data) => {
|
|
3535
3305
|
if (type === 'openChange') {
|
|
3536
3306
|
this._updateIcon();
|
|
@@ -3552,10 +3322,14 @@
|
|
|
3552
3322
|
this.element.innerHTML = `
|
|
3553
3323
|
<button class="messenger-launcher-btn" aria-label="Open messenger" style="background: ${this.options.primaryColor};">
|
|
3554
3324
|
<span class="messenger-launcher-icon messenger-launcher-icon-chat">
|
|
3555
|
-
<
|
|
3325
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#ffffff" viewBox="0 0 256 256">
|
|
3326
|
+
<path d="M144,140a12,12,0,1,1-12-12A12,12,0,0,1,144,140Zm44-12a12,12,0,1,0,12,12A12,12,0,0,0,188,128Zm51.34,83.47a16,16,0,0,1-19.87,19.87l-24.71-7.27A80,80,0,0,1,86.43,183.42a79,79,0,0,1-25.19-7.35l-24.71,7.27a16,16,0,0,1-19.87-19.87l7.27-24.71A80,80,0,1,1,169.58,72.59a80,80,0,0,1,62.49,114.17ZM81.3,166.3a79.94,79.94,0,0,1,70.38-93.87A64,64,0,0,0,39.55,134.19a8,8,0,0,1,.63,6L32,168l27.76-8.17a8,8,0,0,1,6,.63A63.45,63.45,0,0,0,81.3,166.3Zm135.15,15.89a64,64,0,1,0-26.26,26.26,8,8,0,0,1,6-.63L224,216l-8.17-27.76A8,8,0,0,1,216.45,182.19Z"></path>
|
|
3327
|
+
</svg>
|
|
3556
3328
|
</span>
|
|
3557
3329
|
<span class="messenger-launcher-icon messenger-launcher-icon-close" style="display: none;">
|
|
3558
|
-
<
|
|
3330
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#ffffff" viewBox="0 0 256 256">
|
|
3331
|
+
<path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
|
|
3332
|
+
</svg>
|
|
3559
3333
|
</span>
|
|
3560
3334
|
${badgeHtml}
|
|
3561
3335
|
</button>
|
|
@@ -3738,19 +3512,31 @@
|
|
|
3738
3512
|
}
|
|
3739
3513
|
|
|
3740
3514
|
_getHomeIcon() {
|
|
3741
|
-
return `<
|
|
3515
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#000000" viewBox="0 0 256 256">
|
|
3516
|
+
<path d="M216,115.54V208a8,8,0,0,1-8,8H160a8,8,0,0,1-8-8V160a8,8,0,0,0-8-8H112a8,8,0,0,0-8,8v48a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V115.54a8,8,0,0,1,2.62-5.92l80-75.54a8,8,0,0,1,10.77,0l80,75.54A8,8,0,0,1,216,115.54Z" opacity="0.2"></path>
|
|
3517
|
+
<path d="M218.83,103.77l-80-75.48a1.14,1.14,0,0,1-.11-.11,16,16,0,0,0-21.53,0l-.11.11L37.17,103.77A16,16,0,0,0,32,115.55V208a16,16,0,0,0,16,16H96a16,16,0,0,0,16-16V160h32v48a16,16,0,0,0,16,16h48a16,16,0,0,0,16-16V115.55A16,16,0,0,0,218.83,103.77ZM208,208H160V160a16,16,0,0,0-16-16H112a16,16,0,0,0-16,16v48H48V115.55l.11-.1L128,40l79.9,75.43.11.1Z"></path>
|
|
3518
|
+
</svg>`;
|
|
3742
3519
|
}
|
|
3743
3520
|
|
|
3744
3521
|
_getMessagesIcon() {
|
|
3745
|
-
return `<
|
|
3522
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#000000" viewBox="0 0 256 256">
|
|
3523
|
+
<path d="M224,64V192a8,8,0,0,1-8,8H82.5a8,8,0,0,0-5.15,1.88l-32.2,28.23A8,8,0,0,1,32,224V64a8,8,0,0,1,8-8H216A8,8,0,0,1,224,64Z" opacity="0.2"></path>
|
|
3524
|
+
<path d="M216,48H40A16,16,0,0,0,24,64V224a15.85,15.85,0,0,0,9.24,14.5A16.13,16.13,0,0,0,40,240a15.89,15.89,0,0,0,10.25-3.78.69.69,0,0,0,.13-.11L82.5,208H216a16,16,0,0,0,16-16V64A16,16,0,0,0,216,48ZM40,224h0ZM216,192H82.5a16,16,0,0,0-10.3,3.75l-.12.11L40,224V64H216Z"></path>
|
|
3525
|
+
</svg>`;
|
|
3746
3526
|
}
|
|
3747
3527
|
|
|
3748
3528
|
_getHelpIcon() {
|
|
3749
|
-
return `<
|
|
3529
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#000000" viewBox="0 0 256 256">
|
|
3530
|
+
<path d="M224,128a96,96,0,1,1-96-96A96,96,0,0,1,224,128Z" opacity="0.2"></path>
|
|
3531
|
+
<path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm16-40a8,8,0,0,1-8,8,16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40A8,8,0,0,1,144,176ZM112,84a12,12,0,1,1,12,12A12,12,0,0,1,112,84Z"></path>
|
|
3532
|
+
</svg>`;
|
|
3750
3533
|
}
|
|
3751
3534
|
|
|
3752
3535
|
_getChangelogIcon() {
|
|
3753
|
-
return `<
|
|
3536
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#000000" viewBox="0 0 256 256">
|
|
3537
|
+
<path d="M200,144a32,32,0,0,1-63.5,4.5L85.83,121.25a32.07,32.07,0,0,1-41.54-34l-24.15-21a8,8,0,0,1,10.25-12.29L54.55,75a32,32,0,0,1,59.16,2.5l50.63,27.25a31.88,31.88,0,0,1,35.66,7l26.46-23A8,8,0,1,1,236.71,101l-26.46,23A32,32,0,0,1,200,144Z" opacity="0.2"></path>
|
|
3538
|
+
<path d="M228.54,86.66l-26.46,23.07A40,40,0,0,0,168,72.13L120.89,46.5a40,40,0,0,0-75.44-4l-22-19.2a8,8,0,0,0-10.5,12L35.44,54.77a40,40,0,0,0,50,61.07l47.1,25.64a40,40,0,0,0,75.41,4.07l26.46-23.07a8,8,0,0,0-10.5-12ZM56,96A24,24,0,1,1,77.25,82.75,24,24,0,0,1,56,96Zm144,64a24,24,0,1,1,24-24A24,24,0,0,1,200,160Z"></path>
|
|
3539
|
+
</svg>`;
|
|
3754
3540
|
}
|
|
3755
3541
|
|
|
3756
3542
|
destroy() {
|
|
@@ -3893,9 +3679,6 @@
|
|
|
3893
3679
|
}
|
|
3894
3680
|
}
|
|
3895
3681
|
|
|
3896
|
-
/**
|
|
3897
|
-
* ChangelogView - Changelog and announcements
|
|
3898
|
-
*/
|
|
3899
3682
|
class ChangelogView {
|
|
3900
3683
|
constructor(state, options = {}) {
|
|
3901
3684
|
this.state = state;
|
|
@@ -3910,7 +3693,6 @@
|
|
|
3910
3693
|
|
|
3911
3694
|
this._updateContent();
|
|
3912
3695
|
|
|
3913
|
-
// Subscribe to state changes
|
|
3914
3696
|
this._unsubscribe = this.state.subscribe((type) => {
|
|
3915
3697
|
if (type === 'changelogUpdate') {
|
|
3916
3698
|
this._updateChangelogList();
|
|
@@ -3927,7 +3709,9 @@
|
|
|
3927
3709
|
<div class="messenger-changelog-header">
|
|
3928
3710
|
<h2>Changelog</h2>
|
|
3929
3711
|
<button class="messenger-close-btn" aria-label="Close">
|
|
3930
|
-
<
|
|
3712
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#000000" viewBox="0 0 256 256">
|
|
3713
|
+
<path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
|
|
3714
|
+
</svg>
|
|
3931
3715
|
</button>
|
|
3932
3716
|
</div>
|
|
3933
3717
|
|
|
@@ -3963,7 +3747,6 @@
|
|
|
3963
3747
|
.map((item) => this._renderChangelogCard(item))
|
|
3964
3748
|
.join('');
|
|
3965
3749
|
|
|
3966
|
-
// Attach click events
|
|
3967
3750
|
this._attachChangelogEvents();
|
|
3968
3751
|
}
|
|
3969
3752
|
|
|
@@ -3994,7 +3777,9 @@
|
|
|
3994
3777
|
${item.description ? `<p class="messenger-changelog-description">${this._truncateText(item.description, 100)}</p>` : ''}
|
|
3995
3778
|
<div class="messenger-changelog-meta">
|
|
3996
3779
|
<span class="messenger-changelog-date">${dateStr}</span>
|
|
3997
|
-
<
|
|
3780
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#000000" viewBox="0 0 256 256" class="messenger-changelog-arrow">
|
|
3781
|
+
<path d="M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z"></path>
|
|
3782
|
+
</svg>
|
|
3998
3783
|
</div>
|
|
3999
3784
|
</div>
|
|
4000
3785
|
</div>
|
|
@@ -4029,7 +3814,9 @@
|
|
|
4029
3814
|
return `
|
|
4030
3815
|
<div class="messenger-changelog-empty">
|
|
4031
3816
|
<div class="messenger-changelog-empty-icon">
|
|
4032
|
-
<
|
|
3817
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="#000000" viewBox="0 0 256 256">
|
|
3818
|
+
<path d="M228.54,86.66l-26.46,23.07A40,40,0,0,0,168,72.13L120.89,46.5a40,40,0,0,0-75.44-4l-22-19.2a8,8,0,0,0-10.5,12L35.44,54.77a40,40,0,0,0,50,61.07l47.1,25.64a40,40,0,0,0,75.41,4.07l26.46-23.07a8,8,0,0,0-10.5-12ZM56,96A24,24,0,1,1,77.25,82.75,24,24,0,0,1,56,96Zm144,64a24,24,0,1,1,24-24A24,24,0,0,1,200,160Z"></path>
|
|
3819
|
+
</svg>
|
|
4033
3820
|
</div>
|
|
4034
3821
|
<h3>No changelog yet</h3>
|
|
4035
3822
|
<p>Check back later for updates</p>
|
|
@@ -4054,7 +3841,6 @@
|
|
|
4054
3841
|
}
|
|
4055
3842
|
|
|
4056
3843
|
_attachEvents() {
|
|
4057
|
-
// Close button
|
|
4058
3844
|
this.element
|
|
4059
3845
|
.querySelector('.messenger-close-btn')
|
|
4060
3846
|
.addEventListener('click', () => {
|
|
@@ -4092,9 +3878,6 @@
|
|
|
4092
3878
|
}
|
|
4093
3879
|
}
|
|
4094
3880
|
|
|
4095
|
-
/**
|
|
4096
|
-
* ChatView - Individual conversation chat
|
|
4097
|
-
*/
|
|
4098
3881
|
class ChatView {
|
|
4099
3882
|
constructor(state, options = {}) {
|
|
4100
3883
|
this.state = state;
|
|
@@ -4112,7 +3895,6 @@
|
|
|
4112
3895
|
|
|
4113
3896
|
this._updateContent();
|
|
4114
3897
|
|
|
4115
|
-
// Subscribe to state changes
|
|
4116
3898
|
this._unsubscribe = this.state.subscribe((type, data) => {
|
|
4117
3899
|
if (
|
|
4118
3900
|
type === 'messageAdded' &&
|
|
@@ -4163,14 +3945,18 @@
|
|
|
4163
3945
|
this.element.innerHTML = `
|
|
4164
3946
|
<div class="messenger-chat-header">
|
|
4165
3947
|
<button class="messenger-back-btn" aria-label="Back">
|
|
4166
|
-
<
|
|
3948
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#000000" viewBox="0 0 256 256">
|
|
3949
|
+
<path d="M165.66,202.34a8,8,0,0,1-11.32,11.32l-80-80a8,8,0,0,1,0-11.32l80-80a8,8,0,0,1,11.32,11.32L91.31,128Z"></path>
|
|
3950
|
+
</svg>
|
|
4167
3951
|
</button>
|
|
4168
3952
|
<div class="messenger-chat-header-info">
|
|
4169
3953
|
${avatarHtml}
|
|
4170
3954
|
<span class="messenger-chat-title">${title}</span>
|
|
4171
3955
|
</div>
|
|
4172
3956
|
<button class="messenger-close-btn" aria-label="Close">
|
|
4173
|
-
<
|
|
3957
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#000000" viewBox="0 0 256 256">
|
|
3958
|
+
<path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
|
|
3959
|
+
</svg>
|
|
4174
3960
|
</button>
|
|
4175
3961
|
</div>
|
|
4176
3962
|
|
|
@@ -4189,7 +3975,9 @@
|
|
|
4189
3975
|
<textarea class="messenger-compose-input" placeholder="${placeholder}" rows="1"></textarea>
|
|
4190
3976
|
</div>
|
|
4191
3977
|
<button class="messenger-compose-send" aria-label="Send" disabled>
|
|
4192
|
-
<
|
|
3978
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#000000" viewBox="0 0 256 256">
|
|
3979
|
+
<path d="M227.32,28.68a16,16,0,0,0-15.66-4.08l-.15,0L19.57,82.84a16,16,0,0,0-2.49,29.8L102,154l41.3,84.87A15.86,15.86,0,0,0,157.74,248q.69,0,1.38-.06a15.88,15.88,0,0,0,14-11.51l58.2-191.94c0-.05,0-.1,0-.15A16,16,0,0,0,227.32,28.68ZM157.83,231.85l-.05.14L118.42,148.9l47.24-47.25a8,8,0,0,0-11.31-11.31L107.1,137.58,24,98.22l.14,0L216,40Z"></path>
|
|
3980
|
+
</svg>
|
|
4193
3981
|
</button>
|
|
4194
3982
|
</div>
|
|
4195
3983
|
`;
|
|
@@ -4309,7 +4097,6 @@
|
|
|
4309
4097
|
|
|
4310
4098
|
_formatMessageContent(content) {
|
|
4311
4099
|
if (!content) return '';
|
|
4312
|
-
// Basic HTML escaping and line breaks
|
|
4313
4100
|
return content
|
|
4314
4101
|
.replace(/&/g, '&')
|
|
4315
4102
|
.replace(/</g, '<')
|
|
@@ -4344,33 +4131,27 @@
|
|
|
4344
4131
|
}
|
|
4345
4132
|
|
|
4346
4133
|
_attachEvents() {
|
|
4347
|
-
// Back button
|
|
4348
4134
|
this.element
|
|
4349
4135
|
.querySelector('.messenger-back-btn')
|
|
4350
4136
|
.addEventListener('click', () => {
|
|
4351
4137
|
this.state.setView('messages');
|
|
4352
4138
|
});
|
|
4353
4139
|
|
|
4354
|
-
// Close button
|
|
4355
4140
|
this.element
|
|
4356
4141
|
.querySelector('.messenger-close-btn')
|
|
4357
4142
|
.addEventListener('click', () => {
|
|
4358
4143
|
this.state.setOpen(false);
|
|
4359
4144
|
});
|
|
4360
4145
|
|
|
4361
|
-
// Compose input
|
|
4362
4146
|
const input = this.element.querySelector('.messenger-compose-input');
|
|
4363
4147
|
const sendBtn = this.element.querySelector('.messenger-compose-send');
|
|
4364
4148
|
|
|
4365
4149
|
input.addEventListener('input', () => {
|
|
4366
|
-
// Auto-resize textarea
|
|
4367
4150
|
input.style.height = 'auto';
|
|
4368
4151
|
input.style.height = Math.min(input.scrollHeight, 120) + 'px';
|
|
4369
4152
|
|
|
4370
|
-
// Enable/disable send button
|
|
4371
4153
|
sendBtn.disabled = !input.value.trim();
|
|
4372
4154
|
|
|
4373
|
-
// Send typing indicator
|
|
4374
4155
|
if (input.value.trim()) {
|
|
4375
4156
|
this._startTyping();
|
|
4376
4157
|
}
|
|
@@ -4394,18 +4175,15 @@
|
|
|
4394
4175
|
|
|
4395
4176
|
if (!content) return;
|
|
4396
4177
|
|
|
4397
|
-
// Stop typing indicator
|
|
4398
4178
|
this._stopTyping();
|
|
4399
4179
|
|
|
4400
4180
|
const isNewConversation = !this.state.activeConversationId;
|
|
4401
4181
|
|
|
4402
4182
|
if (isNewConversation) {
|
|
4403
|
-
// Start a new conversation
|
|
4404
4183
|
if (this.options.onStartConversation) {
|
|
4405
4184
|
this.options.onStartConversation(content);
|
|
4406
4185
|
}
|
|
4407
4186
|
} else {
|
|
4408
|
-
// Add message to existing conversation
|
|
4409
4187
|
const message = {
|
|
4410
4188
|
id: 'msg_' + Date.now(),
|
|
4411
4189
|
content: content,
|
|
@@ -4415,13 +4193,11 @@
|
|
|
4415
4193
|
|
|
4416
4194
|
this.state.addMessage(this.state.activeConversationId, message);
|
|
4417
4195
|
|
|
4418
|
-
// Emit event for API integration
|
|
4419
4196
|
if (this.options.onSendMessage) {
|
|
4420
4197
|
this.options.onSendMessage(this.state.activeConversationId, message);
|
|
4421
4198
|
}
|
|
4422
4199
|
}
|
|
4423
4200
|
|
|
4424
|
-
// Clear input
|
|
4425
4201
|
input.value = '';
|
|
4426
4202
|
input.style.height = 'auto';
|
|
4427
4203
|
this.element.querySelector('.messenger-compose-send').disabled = true;
|
|
@@ -4435,7 +4211,6 @@
|
|
|
4435
4211
|
}
|
|
4436
4212
|
}
|
|
4437
4213
|
|
|
4438
|
-
// Reset typing timeout
|
|
4439
4214
|
if (this._typingTimeout) {
|
|
4440
4215
|
clearTimeout(this._typingTimeout);
|
|
4441
4216
|
}
|
|
@@ -4490,9 +4265,6 @@
|
|
|
4490
4265
|
}
|
|
4491
4266
|
}
|
|
4492
4267
|
|
|
4493
|
-
/**
|
|
4494
|
-
* ConversationsView - Message thread list
|
|
4495
|
-
*/
|
|
4496
4268
|
class ConversationsView {
|
|
4497
4269
|
constructor(state, options = {}) {
|
|
4498
4270
|
this.state = state;
|
|
@@ -4508,7 +4280,6 @@
|
|
|
4508
4280
|
this._updateContent();
|
|
4509
4281
|
this._attachEvents();
|
|
4510
4282
|
|
|
4511
|
-
// Subscribe to state changes
|
|
4512
4283
|
this._unsubscribe = this.state.subscribe((type) => {
|
|
4513
4284
|
if (
|
|
4514
4285
|
type === 'conversationsUpdate' ||
|
|
@@ -4531,7 +4302,9 @@
|
|
|
4531
4302
|
conversationsHtml = `
|
|
4532
4303
|
<div class="messenger-conversations-empty">
|
|
4533
4304
|
<div class="messenger-conversations-empty-icon">
|
|
4534
|
-
<
|
|
4305
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="#000000" viewBox="0 0 256 256">
|
|
4306
|
+
<path d="M216,48H40A16,16,0,0,0,24,64V224a15.85,15.85,0,0,0,9.24,14.5A16.13,16.13,0,0,0,40,240a15.89,15.89,0,0,0,10.25-3.78.69.69,0,0,0,.13-.11L82.5,208H216a16,16,0,0,0,16-16V64A16,16,0,0,0,216,48ZM40,224h0ZM216,192H82.5a16,16,0,0,0-10.3,3.75l-.12.11L40,224V64H216Z"></path>
|
|
4307
|
+
</svg>
|
|
4535
4308
|
</div>
|
|
4536
4309
|
<h3>No conversations yet</h3>
|
|
4537
4310
|
<p>Start a new conversation with our team</p>
|
|
@@ -4549,7 +4322,9 @@
|
|
|
4549
4322
|
<div class="messenger-conversations-header">
|
|
4550
4323
|
<h2>Messages</h2>
|
|
4551
4324
|
<button class="messenger-close-btn" aria-label="Close">
|
|
4552
|
-
<
|
|
4325
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#000000" viewBox="0 0 256 256">
|
|
4326
|
+
<path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
|
|
4327
|
+
</svg>
|
|
4553
4328
|
</button>
|
|
4554
4329
|
</div>
|
|
4555
4330
|
|
|
@@ -4561,7 +4336,9 @@
|
|
|
4561
4336
|
<button class="messenger-new-message-btn">
|
|
4562
4337
|
<div class="messenger-new-message-avatars">${avatarsHtml}</div>
|
|
4563
4338
|
<span>Send us a message</span>
|
|
4564
|
-
<
|
|
4339
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#000000" viewBox="0 0 256 256">
|
|
4340
|
+
<path d="M221.66,133.66l-72,72a8,8,0,0,1-11.32-11.32L196.69,136H40a8,8,0,0,1,0-16H196.69L138.34,61.66a8,8,0,0,1,11.32-11.32l72,72A8,8,0,0,1,221.66,133.66Z"></path>
|
|
4341
|
+
</svg>
|
|
4565
4342
|
</button>
|
|
4566
4343
|
</div>
|
|
4567
4344
|
`;
|
|
@@ -4660,7 +4437,6 @@
|
|
|
4660
4437
|
}
|
|
4661
4438
|
|
|
4662
4439
|
_attachEvents() {
|
|
4663
|
-
// Close button
|
|
4664
4440
|
const closeBtn = this.element.querySelector('.messenger-close-btn');
|
|
4665
4441
|
if (closeBtn) {
|
|
4666
4442
|
closeBtn.addEventListener('click', () => {
|
|
@@ -4668,7 +4444,6 @@
|
|
|
4668
4444
|
});
|
|
4669
4445
|
}
|
|
4670
4446
|
|
|
4671
|
-
// Conversation items
|
|
4672
4447
|
this.element
|
|
4673
4448
|
.querySelectorAll('.messenger-conversation-item')
|
|
4674
4449
|
.forEach((item) => {
|
|
@@ -4678,14 +4453,12 @@
|
|
|
4678
4453
|
this.state.markAsRead(convId);
|
|
4679
4454
|
this.state.setView('chat');
|
|
4680
4455
|
|
|
4681
|
-
// Notify widget to fetch messages
|
|
4682
4456
|
if (this.options.onSelectConversation) {
|
|
4683
4457
|
this.options.onSelectConversation(convId);
|
|
4684
4458
|
}
|
|
4685
4459
|
});
|
|
4686
4460
|
});
|
|
4687
4461
|
|
|
4688
|
-
// New message button
|
|
4689
4462
|
const newMsgBtn = this.element.querySelector('.messenger-new-message-btn');
|
|
4690
4463
|
if (newMsgBtn) {
|
|
4691
4464
|
newMsgBtn.addEventListener('click', () => {
|
|
@@ -4695,11 +4468,9 @@
|
|
|
4695
4468
|
}
|
|
4696
4469
|
|
|
4697
4470
|
_startNewConversation() {
|
|
4698
|
-
// Set view to chat with no active conversation (new conversation mode)
|
|
4699
4471
|
this.state.setActiveConversation(null);
|
|
4700
4472
|
this.state.setView('chat');
|
|
4701
4473
|
|
|
4702
|
-
// Notify widget to handle new conversation flow
|
|
4703
4474
|
if (this.options.onStartNewConversation) {
|
|
4704
4475
|
this.options.onStartNewConversation();
|
|
4705
4476
|
}
|
|
@@ -4715,9 +4486,6 @@
|
|
|
4715
4486
|
}
|
|
4716
4487
|
}
|
|
4717
4488
|
|
|
4718
|
-
/**
|
|
4719
|
-
* HelpView - Help collections browse with Intercom-style design
|
|
4720
|
-
*/
|
|
4721
4489
|
class HelpView {
|
|
4722
4490
|
constructor(state, options = {}) {
|
|
4723
4491
|
this.state = state;
|
|
@@ -4732,7 +4500,6 @@
|
|
|
4732
4500
|
|
|
4733
4501
|
this._updateContent();
|
|
4734
4502
|
|
|
4735
|
-
// Subscribe to state changes
|
|
4736
4503
|
this._unsubscribe = this.state.subscribe((type) => {
|
|
4737
4504
|
if (type === 'helpArticlesUpdate' || type === 'helpSearchChange') {
|
|
4738
4505
|
this._updateCollectionsList();
|
|
@@ -4751,7 +4518,9 @@
|
|
|
4751
4518
|
<div class="messenger-help-header">
|
|
4752
4519
|
<h2>Help</h2>
|
|
4753
4520
|
<button class="messenger-close-btn" aria-label="Close">
|
|
4754
|
-
<
|
|
4521
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#000000" viewBox="0 0 256 256">
|
|
4522
|
+
<path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
|
|
4523
|
+
</svg>
|
|
4755
4524
|
</button>
|
|
4756
4525
|
</div>
|
|
4757
4526
|
|
|
@@ -4763,7 +4532,9 @@
|
|
|
4763
4532
|
placeholder="Search for help"
|
|
4764
4533
|
value="${searchQuery}"
|
|
4765
4534
|
/>
|
|
4766
|
-
<
|
|
4535
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="#000000" viewBox="0 0 256 256" class="messenger-help-search-icon">
|
|
4536
|
+
<path d="M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z"></path>
|
|
4537
|
+
</svg>
|
|
4767
4538
|
</div>
|
|
4768
4539
|
</div>
|
|
4769
4540
|
|
|
@@ -4786,7 +4557,6 @@
|
|
|
4786
4557
|
const collections = this.state.helpArticles || [];
|
|
4787
4558
|
const searchQuery = (this.state.helpSearchQuery || '').toLowerCase();
|
|
4788
4559
|
|
|
4789
|
-
// Filter collections by search
|
|
4790
4560
|
const filteredCollections = searchQuery
|
|
4791
4561
|
? collections.filter(
|
|
4792
4562
|
(c) =>
|
|
@@ -4795,7 +4565,6 @@
|
|
|
4795
4565
|
)
|
|
4796
4566
|
: collections;
|
|
4797
4567
|
|
|
4798
|
-
// Update collection count
|
|
4799
4568
|
const headerEl = this.element.querySelector(
|
|
4800
4569
|
'.messenger-help-collections-header'
|
|
4801
4570
|
);
|
|
@@ -4812,7 +4581,6 @@
|
|
|
4812
4581
|
.map((collection) => this._renderCollectionItem(collection))
|
|
4813
4582
|
.join('');
|
|
4814
4583
|
|
|
4815
|
-
// Attach click events
|
|
4816
4584
|
this._attachCollectionEvents();
|
|
4817
4585
|
}
|
|
4818
4586
|
|
|
@@ -4825,7 +4593,9 @@
|
|
|
4825
4593
|
<p class="messenger-help-collection-desc">${collection.description || ''}</p>
|
|
4826
4594
|
<span class="messenger-help-collection-count">${articleCount} articles</span>
|
|
4827
4595
|
</div>
|
|
4828
|
-
<
|
|
4596
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#000000" viewBox="0 0 256 256" class="messenger-help-collection-arrow">
|
|
4597
|
+
<path d="M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z"></path>
|
|
4598
|
+
</svg>
|
|
4829
4599
|
</div>
|
|
4830
4600
|
`;
|
|
4831
4601
|
}
|
|
@@ -4837,7 +4607,9 @@
|
|
|
4837
4607
|
return `
|
|
4838
4608
|
<div class="messenger-help-empty">
|
|
4839
4609
|
<div class="messenger-help-empty-icon">
|
|
4840
|
-
<
|
|
4610
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="#000000" viewBox="0 0 256 256">
|
|
4611
|
+
<path d="M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z"></path>
|
|
4612
|
+
</svg>
|
|
4841
4613
|
</div>
|
|
4842
4614
|
<h3>No results found</h3>
|
|
4843
4615
|
<p>Try a different search term</p>
|
|
@@ -4848,7 +4620,9 @@
|
|
|
4848
4620
|
return `
|
|
4849
4621
|
<div class="messenger-help-empty">
|
|
4850
4622
|
<div class="messenger-help-empty-icon">
|
|
4851
|
-
<
|
|
4623
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="#000000" viewBox="0 0 256 256">
|
|
4624
|
+
<path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm16-40a8,8,0,0,1-8,8,16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40A8,8,0,0,1,144,176ZM112,84a12,12,0,1,1,12,12A12,12,0,0,1,112,84Z"></path>
|
|
4625
|
+
</svg>
|
|
4852
4626
|
</div>
|
|
4853
4627
|
<h3>Help collections</h3>
|
|
4854
4628
|
<p>No collections available yet</p>
|
|
@@ -4857,14 +4631,12 @@
|
|
|
4857
4631
|
}
|
|
4858
4632
|
|
|
4859
4633
|
_attachEvents() {
|
|
4860
|
-
// Close button
|
|
4861
4634
|
this.element
|
|
4862
4635
|
.querySelector('.messenger-close-btn')
|
|
4863
4636
|
.addEventListener('click', () => {
|
|
4864
4637
|
this.state.setOpen(false);
|
|
4865
4638
|
});
|
|
4866
4639
|
|
|
4867
|
-
// Search input
|
|
4868
4640
|
const searchInput = this.element.querySelector(
|
|
4869
4641
|
'.messenger-help-search-input'
|
|
4870
4642
|
);
|
|
@@ -4907,9 +4679,6 @@
|
|
|
4907
4679
|
}
|
|
4908
4680
|
}
|
|
4909
4681
|
|
|
4910
|
-
/**
|
|
4911
|
-
* HomeView - Welcome screen with team info and quick actions
|
|
4912
|
-
*/
|
|
4913
4682
|
class HomeView {
|
|
4914
4683
|
constructor(state, options = {}) {
|
|
4915
4684
|
this.state = state;
|
|
@@ -4924,7 +4693,6 @@
|
|
|
4924
4693
|
|
|
4925
4694
|
this._updateContent();
|
|
4926
4695
|
|
|
4927
|
-
// Subscribe to state changes to re-render when data loads
|
|
4928
4696
|
this._unsubscribe = this.state.subscribe((type) => {
|
|
4929
4697
|
if (
|
|
4930
4698
|
type === 'homeChangelogUpdate' ||
|
|
@@ -4950,7 +4718,9 @@
|
|
|
4950
4718
|
</div>
|
|
4951
4719
|
<div class="messenger-home-avatars">${avatarsHtml}</div>
|
|
4952
4720
|
<button class="messenger-close-btn" aria-label="Close">
|
|
4953
|
-
<
|
|
4721
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#000000" viewBox="0 0 256 256">
|
|
4722
|
+
<path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
|
|
4723
|
+
</svg>
|
|
4954
4724
|
</button>
|
|
4955
4725
|
</div>
|
|
4956
4726
|
<div class="messenger-home-welcome">
|
|
@@ -4963,7 +4733,9 @@
|
|
|
4963
4733
|
<div class="messenger-home-body">
|
|
4964
4734
|
<button class="messenger-home-message-btn">
|
|
4965
4735
|
<span>Send us a message</span>
|
|
4966
|
-
<
|
|
4736
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#000000" viewBox="0 0 256 256">
|
|
4737
|
+
<path d="M221.66,133.66l-72,72a8,8,0,0,1-11.32-11.32L196.69,136H40a8,8,0,0,1,0-16H196.69L138.34,61.66a8,8,0,0,1,11.32-11.32l72,72A8,8,0,0,1,221.66,133.66Z"></path>
|
|
4738
|
+
</svg>
|
|
4967
4739
|
</button>
|
|
4968
4740
|
|
|
4969
4741
|
${this._renderFeaturedCard()}
|
|
@@ -4978,7 +4750,6 @@
|
|
|
4978
4750
|
_renderAvatarStack() {
|
|
4979
4751
|
const avatars = this.state.teamAvatars;
|
|
4980
4752
|
if (!avatars || avatars.length === 0) {
|
|
4981
|
-
// Default avatars with initials
|
|
4982
4753
|
return `
|
|
4983
4754
|
<div class="messenger-avatar-stack">
|
|
4984
4755
|
<div class="messenger-avatar" style="background: #5856d6;">S</div>
|
|
@@ -5028,7 +4799,6 @@
|
|
|
5028
4799
|
}
|
|
5029
4800
|
|
|
5030
4801
|
_renderFeaturedCard() {
|
|
5031
|
-
// Only show if there's featured content configured
|
|
5032
4802
|
if (!this.options.featuredContent) {
|
|
5033
4803
|
return '';
|
|
5034
4804
|
}
|
|
@@ -5049,7 +4819,6 @@
|
|
|
5049
4819
|
}
|
|
5050
4820
|
|
|
5051
4821
|
_renderRecentChangelog() {
|
|
5052
|
-
// Show recent changelog preview as cards with images
|
|
5053
4822
|
const changelogItems = this.state.homeChangelogItems;
|
|
5054
4823
|
if (changelogItems.length === 0) {
|
|
5055
4824
|
return '';
|
|
@@ -5098,31 +4867,26 @@
|
|
|
5098
4867
|
}
|
|
5099
4868
|
|
|
5100
4869
|
_attachEvents() {
|
|
5101
|
-
// Close button
|
|
5102
4870
|
this.element
|
|
5103
4871
|
.querySelector('.messenger-close-btn')
|
|
5104
4872
|
.addEventListener('click', () => {
|
|
5105
4873
|
this.state.setOpen(false);
|
|
5106
4874
|
});
|
|
5107
4875
|
|
|
5108
|
-
// Send message button
|
|
5109
4876
|
this.element
|
|
5110
4877
|
.querySelector('.messenger-home-message-btn')
|
|
5111
4878
|
.addEventListener('click', () => {
|
|
5112
4879
|
this.state.setView('messages');
|
|
5113
4880
|
});
|
|
5114
4881
|
|
|
5115
|
-
// Changelog items
|
|
5116
4882
|
this.element
|
|
5117
4883
|
.querySelectorAll('.messenger-home-changelog-item')
|
|
5118
4884
|
.forEach((item) => {
|
|
5119
4885
|
item.addEventListener('click', () => {
|
|
5120
|
-
// Navigate to changelog view with specific item selected
|
|
5121
4886
|
this.state.setView('changelog');
|
|
5122
4887
|
});
|
|
5123
4888
|
});
|
|
5124
4889
|
|
|
5125
|
-
// See all changelog
|
|
5126
4890
|
const seeAllBtn = this.element.querySelector(
|
|
5127
4891
|
'.messenger-home-changelog-all'
|
|
5128
4892
|
);
|
|
@@ -5132,7 +4896,6 @@
|
|
|
5132
4896
|
});
|
|
5133
4897
|
}
|
|
5134
4898
|
|
|
5135
|
-
// Featured card action
|
|
5136
4899
|
const featuredBtn = this.element.querySelector(
|
|
5137
4900
|
'.messenger-home-featured-btn'
|
|
5138
4901
|
);
|
|
@@ -5175,7 +4938,7 @@
|
|
|
5175
4938
|
welcomeMessage: options.welcomeMessage || 'How can we help?',
|
|
5176
4939
|
enableHelp: options.enableHelp !== false,
|
|
5177
4940
|
enableChangelog: options.enableChangelog !== false,
|
|
5178
|
-
logoUrl: options.logoUrl || 'https://
|
|
4941
|
+
logoUrl: options.logoUrl || 'https://product7.io/p7logo.svg',
|
|
5179
4942
|
featuredContent: options.featuredContent || null,
|
|
5180
4943
|
primaryColor: options.primaryColor || '#1c1c1e',
|
|
5181
4944
|
// Callbacks
|
|
@@ -5740,7 +5503,6 @@
|
|
|
5740
5503
|
}
|
|
5741
5504
|
|
|
5742
5505
|
async _fetchChangelog() {
|
|
5743
|
-
// Mock data for now - simulating changelog API response
|
|
5744
5506
|
if (this.apiService?.mock) {
|
|
5745
5507
|
return {
|
|
5746
5508
|
homeItems: [
|
|
@@ -6658,7 +6420,6 @@
|
|
|
6658
6420
|
try {
|
|
6659
6421
|
const initData = await this.apiService.init(this.config.userContext);
|
|
6660
6422
|
|
|
6661
|
-
// Merge backend config as base, local config overrides
|
|
6662
6423
|
if (initData.config) {
|
|
6663
6424
|
this.config = deepMerge(initData.config, this.config);
|
|
6664
6425
|
}
|
|
@@ -6711,13 +6472,6 @@
|
|
|
6711
6472
|
return this.widgets.get(id);
|
|
6712
6473
|
}
|
|
6713
6474
|
|
|
6714
|
-
/**
|
|
6715
|
-
* Fetch active surveys from the backend
|
|
6716
|
-
* @param {Object} context - Optional context for targeting
|
|
6717
|
-
* @param {string} context.page - Current page/route
|
|
6718
|
-
* @param {string} context.event - Event trigger name
|
|
6719
|
-
* @returns {Promise<Array>} Array of active survey configurations
|
|
6720
|
-
*/
|
|
6721
6475
|
async getActiveSurveys(context = {}) {
|
|
6722
6476
|
if (!this.initialized) {
|
|
6723
6477
|
throw new SDKError(
|
|
@@ -6737,17 +6491,6 @@
|
|
|
6737
6491
|
}
|
|
6738
6492
|
}
|
|
6739
6493
|
|
|
6740
|
-
/**
|
|
6741
|
-
* Show a survey by its backend ID
|
|
6742
|
-
* Fetches survey configuration from the backend and displays it
|
|
6743
|
-
* @param {string} surveyId - The backend survey ID
|
|
6744
|
-
* @param {Object} options - Additional display options
|
|
6745
|
-
* @param {string} options.position - Position override
|
|
6746
|
-
* @param {string} options.theme - Theme override
|
|
6747
|
-
* @param {Function} options.onSubmit - Callback when survey is submitted
|
|
6748
|
-
* @param {Function} options.onDismiss - Callback when survey is dismissed
|
|
6749
|
-
* @returns {Promise<SurveyWidget>} The survey widget instance
|
|
6750
|
-
*/
|
|
6751
6494
|
async showSurveyById(surveyId, options = {}) {
|
|
6752
6495
|
if (!this.initialized) {
|
|
6753
6496
|
throw new SDKError(
|
|
@@ -6755,7 +6498,6 @@
|
|
|
6755
6498
|
);
|
|
6756
6499
|
}
|
|
6757
6500
|
|
|
6758
|
-
// Fetch active surveys to find the one with matching ID
|
|
6759
6501
|
const surveys = await this.getActiveSurveys();
|
|
6760
6502
|
const surveyConfig = surveys.find((s) => s.id === surveyId);
|
|
6761
6503
|
|
|
@@ -6777,22 +6519,6 @@
|
|
|
6777
6519
|
});
|
|
6778
6520
|
}
|
|
6779
6521
|
|
|
6780
|
-
/**
|
|
6781
|
-
* Show a survey widget (local/manual mode)
|
|
6782
|
-
* For backend-driven surveys, use showSurveyById() instead
|
|
6783
|
-
* @param {Object} options - Survey options
|
|
6784
|
-
* @param {string} options.surveyId - Backend survey ID (for API tracking)
|
|
6785
|
-
* @param {string} options.surveyType - Type of survey: 'nps', 'csat', 'ces', 'custom'
|
|
6786
|
-
* @param {string} options.position - Position: 'bottom-right', 'bottom-left', 'center', 'bottom'
|
|
6787
|
-
* @param {string} options.theme - Theme: 'light', 'dark'
|
|
6788
|
-
* @param {string} options.title - Custom title
|
|
6789
|
-
* @param {string} options.description - Custom description
|
|
6790
|
-
* @param {string} options.lowLabel - Low end label
|
|
6791
|
-
* @param {string} options.highLabel - High end label
|
|
6792
|
-
* @param {Function} options.onSubmit - Callback when survey is submitted
|
|
6793
|
-
* @param {Function} options.onDismiss - Callback when survey is dismissed
|
|
6794
|
-
* @returns {SurveyWidget} The survey widget instance
|
|
6795
|
-
*/
|
|
6796
6522
|
showSurvey(options = {}) {
|
|
6797
6523
|
if (!this.initialized) {
|
|
6798
6524
|
throw new SDKError(
|
|
@@ -6820,20 +6546,6 @@
|
|
|
6820
6546
|
return surveyWidget;
|
|
6821
6547
|
}
|
|
6822
6548
|
|
|
6823
|
-
/**
|
|
6824
|
-
* Show a changelog widget with sidebar
|
|
6825
|
-
* @param {Object} options - Changelog widget options
|
|
6826
|
-
* @param {string} options.position - Position: 'bottom-right', 'bottom-left', 'top-right', 'top-left'
|
|
6827
|
-
* @param {string} options.theme - Theme: 'light', 'dark'
|
|
6828
|
-
* @param {string} options.title - Sidebar title
|
|
6829
|
-
* @param {string} options.triggerText - Text on the trigger button
|
|
6830
|
-
* @param {boolean} options.showBadge - Show notification badge
|
|
6831
|
-
* @param {string} options.viewButtonText - Text for the view update button
|
|
6832
|
-
* @param {string} options.changelogBaseUrl - Base URL for changelog links
|
|
6833
|
-
* @param {boolean} options.openInNewTab - Open changelog links in new tab (default: true)
|
|
6834
|
-
* @param {Function} options.onViewUpdate - Callback when user clicks view update
|
|
6835
|
-
* @returns {ChangelogWidget} The changelog widget instance
|
|
6836
|
-
*/
|
|
6837
6549
|
showChangelog(options = {}) {
|
|
6838
6550
|
if (!this.initialized) {
|
|
6839
6551
|
throw new SDKError(
|
|
@@ -6859,13 +6571,6 @@
|
|
|
6859
6571
|
return changelogWidget;
|
|
6860
6572
|
}
|
|
6861
6573
|
|
|
6862
|
-
/**
|
|
6863
|
-
* Get changelogs from the backend
|
|
6864
|
-
* @param {Object} options - Optional query parameters
|
|
6865
|
-
* @param {number} options.limit - Number of changelogs to fetch
|
|
6866
|
-
* @param {number} options.offset - Offset for pagination
|
|
6867
|
-
* @returns {Promise<Array>} Array of changelog entries
|
|
6868
|
-
*/
|
|
6869
6574
|
async getChangelogs(options = {}) {
|
|
6870
6575
|
if (!this.initialized) {
|
|
6871
6576
|
throw new SDKError(
|
|
@@ -6973,17 +6678,10 @@
|
|
|
6973
6678
|
this.eventBus.emit('sdk:destroyed');
|
|
6974
6679
|
}
|
|
6975
6680
|
|
|
6976
|
-
/**
|
|
6977
|
-
* Check if feedback was recently submitted for this workspace
|
|
6978
|
-
* Uses backend tracking (preferred) with localStorage as fallback
|
|
6979
|
-
* @param {number} cooldownDays - Days to consider as "recently" (default: 30)
|
|
6980
|
-
* @returns {boolean} true if feedback was submitted within the cooldown period
|
|
6981
|
-
*/
|
|
6982
6681
|
hasFeedbackBeenSubmitted(cooldownDays = 30) {
|
|
6983
6682
|
const cooldownMs = cooldownDays * 24 * 60 * 60 * 1000;
|
|
6984
6683
|
const now = Date.now();
|
|
6985
6684
|
|
|
6986
|
-
// Check backend tracking first (from init response)
|
|
6987
6685
|
if (this.config.last_feedback_at) {
|
|
6988
6686
|
try {
|
|
6989
6687
|
const backendTimestamp = new Date(
|
|
@@ -6997,7 +6695,6 @@
|
|
|
6997
6695
|
}
|
|
6998
6696
|
}
|
|
6999
6697
|
|
|
7000
|
-
// Fallback to localStorage
|
|
7001
6698
|
try {
|
|
7002
6699
|
const storageKey = `feedback_submitted_${this.config.workspace}`;
|
|
7003
6700
|
const stored = localStorage.getItem(storageKey);
|
|
@@ -7010,9 +6707,6 @@
|
|
|
7010
6707
|
}
|
|
7011
6708
|
}
|
|
7012
6709
|
|
|
7013
|
-
/**
|
|
7014
|
-
* Clear the feedback submission tracking (allow showing widgets again)
|
|
7015
|
-
*/
|
|
7016
6710
|
clearFeedbackSubmissionTracking() {
|
|
7017
6711
|
try {
|
|
7018
6712
|
const storageKey = `feedback_submitted_${this.config.workspace}`;
|
|
@@ -8898,7 +8592,7 @@
|
|
|
8898
8592
|
}
|
|
8899
8593
|
`;
|
|
8900
8594
|
|
|
8901
|
-
const
|
|
8595
|
+
const baseStyles = `
|
|
8902
8596
|
.feedback-widget {
|
|
8903
8597
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
8904
8598
|
font-size: 14px;
|
|
@@ -8913,32 +8607,94 @@
|
|
|
8913
8607
|
box-sizing: border-box;
|
|
8914
8608
|
}
|
|
8915
8609
|
|
|
8916
|
-
|
|
8610
|
+
/* Animations */
|
|
8611
|
+
@keyframes fadeIn {
|
|
8612
|
+
from { opacity: 0; }
|
|
8613
|
+
to { opacity: 1; }
|
|
8614
|
+
}
|
|
8615
|
+
|
|
8616
|
+
@keyframes slideInRight {
|
|
8617
|
+
from {
|
|
8618
|
+
transform: translateX(400px);
|
|
8619
|
+
opacity: 0;
|
|
8620
|
+
}
|
|
8621
|
+
to {
|
|
8622
|
+
transform: translateX(0);
|
|
8623
|
+
opacity: 1;
|
|
8624
|
+
}
|
|
8625
|
+
}
|
|
8626
|
+
|
|
8627
|
+
@keyframes confettiFall {
|
|
8628
|
+
0% {
|
|
8629
|
+
opacity: 1;
|
|
8630
|
+
transform: translateY(0) rotate(0deg) scale(1);
|
|
8631
|
+
}
|
|
8632
|
+
10% {
|
|
8633
|
+
opacity: 1;
|
|
8634
|
+
}
|
|
8635
|
+
100% {
|
|
8636
|
+
opacity: 0;
|
|
8637
|
+
transform: translateY(100vh) rotate(720deg) scale(0.5);
|
|
8638
|
+
}
|
|
8639
|
+
}
|
|
8640
|
+
|
|
8641
|
+
@keyframes changelogSpin {
|
|
8642
|
+
to {
|
|
8643
|
+
transform: rotate(360deg);
|
|
8644
|
+
}
|
|
8645
|
+
}
|
|
8646
|
+
|
|
8647
|
+
/* Accessibility */
|
|
8648
|
+
@media (prefers-reduced-motion: reduce) {
|
|
8649
|
+
* {
|
|
8650
|
+
transition: none !important;
|
|
8651
|
+
animation: none !important;
|
|
8652
|
+
}
|
|
8653
|
+
}
|
|
8654
|
+
|
|
8655
|
+
/* Print */
|
|
8656
|
+
@media print {
|
|
8657
|
+
.feedback-widget,
|
|
8658
|
+
.feedback-panel,
|
|
8659
|
+
.feedback-panel-backdrop,
|
|
8660
|
+
.feedback-success-notification,
|
|
8661
|
+
.changelog-widget,
|
|
8662
|
+
.changelog-modal,
|
|
8663
|
+
.changelog-modal-backdrop,
|
|
8664
|
+
.changelog-list-modal,
|
|
8665
|
+
.changelog-list-modal-backdrop {
|
|
8666
|
+
display: none !important;
|
|
8667
|
+
}
|
|
8668
|
+
}
|
|
8669
|
+
`;
|
|
8670
|
+
|
|
8671
|
+
const changelogStyles = `
|
|
8672
|
+
.changelog-widget {
|
|
8917
8673
|
position: fixed;
|
|
8918
8674
|
z-index: 999999;
|
|
8919
8675
|
}
|
|
8920
8676
|
|
|
8921
|
-
.
|
|
8677
|
+
.changelog-widget.position-bottom-right {
|
|
8922
8678
|
bottom: 20px;
|
|
8923
8679
|
right: 20px;
|
|
8924
8680
|
}
|
|
8925
8681
|
|
|
8926
|
-
.
|
|
8682
|
+
.changelog-widget.position-bottom-left {
|
|
8927
8683
|
bottom: 20px;
|
|
8928
8684
|
left: 20px;
|
|
8929
8685
|
}
|
|
8930
8686
|
|
|
8931
|
-
.
|
|
8687
|
+
.changelog-widget.position-top-right {
|
|
8932
8688
|
top: 20px;
|
|
8933
8689
|
right: 20px;
|
|
8934
8690
|
}
|
|
8935
8691
|
|
|
8936
|
-
.
|
|
8692
|
+
.changelog-widget.position-top-left {
|
|
8937
8693
|
top: 20px;
|
|
8938
8694
|
left: 20px;
|
|
8939
8695
|
}
|
|
8940
8696
|
|
|
8941
|
-
.
|
|
8697
|
+
.changelog-trigger-btn {
|
|
8942
8698
|
position: relative;
|
|
8943
8699
|
display: flex;
|
|
8944
8700
|
align-items: center;
|
|
@@ -8960,1326 +8716,1234 @@
|
|
|
8960
8716
|
width: fit-content;
|
|
8961
8717
|
}
|
|
8962
8718
|
|
|
8963
|
-
.
|
|
8719
|
+
.changelog-trigger-btn:hover {
|
|
8964
8720
|
transform: translateY(-2px);
|
|
8965
8721
|
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
|
|
8966
8722
|
}
|
|
8967
8723
|
|
|
8968
|
-
.
|
|
8969
|
-
opacity: 0.7;
|
|
8970
|
-
cursor: not-allowed;
|
|
8971
|
-
}
|
|
8972
|
-
|
|
8973
|
-
.feedback-trigger-btn:focus-visible {
|
|
8724
|
+
.changelog-trigger-btn:focus-visible {
|
|
8974
8725
|
outline: 2px solid #155EEF;
|
|
8975
8726
|
outline-offset: 2px;
|
|
8976
8727
|
}
|
|
8977
8728
|
|
|
8978
|
-
.
|
|
8729
|
+
.changelog-icon {
|
|
8979
8730
|
flex-shrink: 0;
|
|
8980
8731
|
}
|
|
8981
8732
|
|
|
8982
|
-
.
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
top: -6px;
|
|
8986
|
-
right: -6px;
|
|
8987
|
-
width: 24px;
|
|
8988
|
-
height: 24px;
|
|
8989
|
-
padding: 4px;
|
|
8990
|
-
display: flex;
|
|
8991
|
-
align-items: center;
|
|
8992
|
-
justify-content: center;
|
|
8993
|
-
background: white;
|
|
8994
|
-
border-radius: 50%;
|
|
8995
|
-
opacity: 0;
|
|
8996
|
-
transition: opacity 0.2s ease;
|
|
8997
|
-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
8998
|
-
cursor: pointer;
|
|
8999
|
-
display: flex;
|
|
9000
|
-
align-items: center;
|
|
9001
|
-
justify-content: center;
|
|
8733
|
+
.changelog-confetti-emoji {
|
|
8734
|
+
font-size: 14px;
|
|
8735
|
+
margin-left: 2px;
|
|
9002
8736
|
}
|
|
9003
8737
|
|
|
9004
|
-
.
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
.feedback-widget-button:not(.minimized) .feedback-trigger-btn:hover .feedback-minimize-icon {
|
|
9014
|
-
opacity: 1;
|
|
9015
|
-
}
|
|
9016
|
-
|
|
9017
|
-
/* Minimized state - just icon */
|
|
9018
|
-
.feedback-widget-button.minimized .feedback-trigger-btn {
|
|
9019
|
-
padding: 12px;
|
|
9020
|
-
width: 48px;
|
|
9021
|
-
height: 48px;
|
|
9022
|
-
justify-content: center;
|
|
9023
|
-
}
|
|
9024
|
-
|
|
9025
|
-
.feedback-widget-button.minimized .feedback-text {
|
|
9026
|
-
display: none;
|
|
9027
|
-
}
|
|
9028
|
-
|
|
9029
|
-
.feedback-widget-button.minimized .feedback-minimize-icon {
|
|
9030
|
-
display: none;
|
|
9031
|
-
}
|
|
9032
|
-
|
|
9033
|
-
/* Show expand icon on hover when minimized */
|
|
9034
|
-
.feedback-widget-button.minimized .feedback-trigger-btn:hover .feedback-expand-icon {
|
|
9035
|
-
opacity: 1;
|
|
8738
|
+
.changelog-badge {
|
|
8739
|
+
position: absolute;
|
|
8740
|
+
top: -4px;
|
|
8741
|
+
right: -4px;
|
|
8742
|
+
width: 12px;
|
|
8743
|
+
height: 12px;
|
|
8744
|
+
background: #EF4444;
|
|
8745
|
+
border-radius: 50%;
|
|
8746
|
+
border: 2px solid white;
|
|
9036
8747
|
}
|
|
9037
8748
|
|
|
9038
|
-
|
|
9039
|
-
.feedback-panel {
|
|
8749
|
+
.changelog-confetti-container {
|
|
9040
8750
|
position: fixed;
|
|
9041
|
-
|
|
9042
|
-
|
|
9043
|
-
width:
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
font-family: inherit;
|
|
8751
|
+
top: 0;
|
|
8752
|
+
left: 0;
|
|
8753
|
+
width: 100%;
|
|
8754
|
+
height: 100%;
|
|
8755
|
+
pointer-events: none;
|
|
8756
|
+
z-index: 1000001;
|
|
8757
|
+
overflow: hidden;
|
|
9049
8758
|
}
|
|
9050
8759
|
|
|
9051
|
-
.
|
|
9052
|
-
|
|
8760
|
+
.changelog-confetti {
|
|
8761
|
+
position: absolute;
|
|
8762
|
+
top: -20px;
|
|
8763
|
+
opacity: 0;
|
|
8764
|
+
animation: confettiFall 2s ease-out forwards;
|
|
9053
8765
|
}
|
|
9054
8766
|
|
|
9055
|
-
.
|
|
8767
|
+
.changelog-modal-backdrop {
|
|
9056
8768
|
position: fixed;
|
|
9057
8769
|
top: 0;
|
|
9058
8770
|
left: 0;
|
|
9059
8771
|
right: 0;
|
|
9060
8772
|
bottom: 0;
|
|
9061
|
-
background: rgba(0, 0, 0, 0.
|
|
8773
|
+
background: rgba(0, 0, 0, 0.5);
|
|
9062
8774
|
opacity: 0;
|
|
9063
8775
|
transition: opacity 0.3s ease;
|
|
9064
8776
|
pointer-events: none;
|
|
9065
|
-
z-index:
|
|
8777
|
+
z-index: 999998;
|
|
8778
|
+
display: flex;
|
|
8779
|
+
align-items: center;
|
|
8780
|
+
justify-content: center;
|
|
9066
8781
|
}
|
|
9067
8782
|
|
|
9068
|
-
.
|
|
8783
|
+
.changelog-modal-backdrop.show {
|
|
9069
8784
|
opacity: 1;
|
|
9070
8785
|
pointer-events: auto;
|
|
9071
8786
|
}
|
|
9072
8787
|
|
|
9073
|
-
.
|
|
9074
|
-
|
|
9075
|
-
|
|
8788
|
+
.changelog-modal {
|
|
8789
|
+
position: fixed;
|
|
8790
|
+
top: 0;
|
|
8791
|
+
left: 0;
|
|
8792
|
+
right: 0;
|
|
8793
|
+
bottom: 0;
|
|
8794
|
+
z-index: 999999;
|
|
9076
8795
|
display: flex;
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
}
|
|
9083
|
-
|
|
9084
|
-
.feedback-panel.theme-dark .feedback-panel-content {
|
|
9085
|
-
background: #1F2937;
|
|
9086
|
-
color: white;
|
|
8796
|
+
align-items: center;
|
|
8797
|
+
justify-content: center;
|
|
8798
|
+
padding: 20px;
|
|
8799
|
+
pointer-events: none;
|
|
8800
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
9087
8801
|
}
|
|
9088
8802
|
|
|
9089
|
-
.
|
|
9090
|
-
|
|
9091
|
-
align-items: center;
|
|
9092
|
-
justify-content: space-between;
|
|
9093
|
-
padding: 24px;
|
|
9094
|
-
border-bottom: 1px solid #E5E7EB;
|
|
9095
|
-
flex-shrink: 0;
|
|
8803
|
+
.changelog-modal.open {
|
|
8804
|
+
pointer-events: auto;
|
|
9096
8805
|
}
|
|
9097
8806
|
|
|
9098
|
-
.
|
|
9099
|
-
|
|
8807
|
+
.changelog-modal-container {
|
|
8808
|
+
position: relative;
|
|
8809
|
+
width: 100%;
|
|
8810
|
+
max-width: 580px;
|
|
8811
|
+
max-height: 90vh;
|
|
8812
|
+
background: #DBEAFE;
|
|
8813
|
+
border-radius: 24px;
|
|
8814
|
+
overflow: hidden;
|
|
8815
|
+
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
8816
|
+
transform: scale(0.9) translateY(20px);
|
|
8817
|
+
opacity: 0;
|
|
8818
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
9100
8819
|
}
|
|
9101
8820
|
|
|
9102
|
-
.
|
|
9103
|
-
|
|
9104
|
-
|
|
9105
|
-
font-weight: 600;
|
|
9106
|
-
color: #111827;
|
|
8821
|
+
.changelog-modal.open .changelog-modal-container {
|
|
8822
|
+
transform: scale(1) translateY(0);
|
|
8823
|
+
opacity: 1;
|
|
9107
8824
|
}
|
|
9108
8825
|
|
|
9109
|
-
.
|
|
9110
|
-
|
|
8826
|
+
.changelog-modal.theme-dark .changelog-modal-container {
|
|
8827
|
+
background: #1E3A5F;
|
|
9111
8828
|
}
|
|
9112
8829
|
|
|
9113
|
-
.
|
|
9114
|
-
|
|
8830
|
+
.changelog-modal-close {
|
|
8831
|
+
position: absolute;
|
|
8832
|
+
top: 16px;
|
|
8833
|
+
right: 16px;
|
|
8834
|
+
background: rgba(255, 255, 255, 0.9);
|
|
9115
8835
|
border: none;
|
|
9116
8836
|
font-size: 24px;
|
|
9117
8837
|
cursor: pointer;
|
|
9118
8838
|
color: #6B7280;
|
|
9119
|
-
padding:
|
|
9120
|
-
width:
|
|
9121
|
-
height:
|
|
8839
|
+
padding: 0;
|
|
8840
|
+
width: 36px;
|
|
8841
|
+
height: 36px;
|
|
9122
8842
|
display: flex;
|
|
9123
8843
|
align-items: center;
|
|
9124
8844
|
justify-content: center;
|
|
9125
|
-
border-radius:
|
|
8845
|
+
border-radius: 50%;
|
|
9126
8846
|
transition: all 0.2s ease;
|
|
8847
|
+
line-height: 1;
|
|
8848
|
+
z-index: 10;
|
|
8849
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
9127
8850
|
}
|
|
9128
8851
|
|
|
9129
|
-
.
|
|
9130
|
-
background:
|
|
8852
|
+
.changelog-modal-close:hover {
|
|
8853
|
+
background: white;
|
|
9131
8854
|
color: #111827;
|
|
8855
|
+
transform: scale(1.05);
|
|
9132
8856
|
}
|
|
9133
8857
|
|
|
9134
|
-
.
|
|
9135
|
-
|
|
9136
|
-
|
|
9137
|
-
}
|
|
9138
|
-
|
|
9139
|
-
.feedback-panel.theme-dark .feedback-panel-close {
|
|
9140
|
-
color: #9CA3AF;
|
|
8858
|
+
.changelog-modal.theme-dark .changelog-modal-close {
|
|
8859
|
+
background: rgba(55, 65, 81, 0.9);
|
|
8860
|
+
color: #D1D5DB;
|
|
9141
8861
|
}
|
|
9142
8862
|
|
|
9143
|
-
.
|
|
8863
|
+
.changelog-modal.theme-dark .changelog-modal-close:hover {
|
|
9144
8864
|
background: #374151;
|
|
9145
8865
|
color: white;
|
|
9146
8866
|
}
|
|
9147
8867
|
|
|
9148
|
-
.
|
|
9149
|
-
flex: 1;
|
|
8868
|
+
.changelog-modal-content {
|
|
9150
8869
|
overflow-y: auto;
|
|
9151
|
-
|
|
8870
|
+
max-height: 90vh;
|
|
9152
8871
|
}
|
|
9153
8872
|
|
|
9154
|
-
.
|
|
8873
|
+
.changelog-loading {
|
|
9155
8874
|
display: flex;
|
|
9156
|
-
|
|
9157
|
-
|
|
8875
|
+
align-items: center;
|
|
8876
|
+
justify-content: center;
|
|
8877
|
+
padding: 80px 20px;
|
|
9158
8878
|
}
|
|
9159
8879
|
|
|
9160
|
-
.
|
|
8880
|
+
.changelog-loading-spinner {
|
|
8881
|
+
width: 32px;
|
|
8882
|
+
height: 32px;
|
|
8883
|
+
border: 3px solid #E5E7EB;
|
|
8884
|
+
border-top-color: #155EEF;
|
|
8885
|
+
border-radius: 50%;
|
|
8886
|
+
animation: changelogSpin 0.8s linear infinite;
|
|
8887
|
+
}
|
|
8888
|
+
|
|
8889
|
+
.changelog-empty {
|
|
9161
8890
|
display: flex;
|
|
9162
8891
|
flex-direction: column;
|
|
9163
|
-
|
|
9164
|
-
|
|
8892
|
+
align-items: center;
|
|
8893
|
+
justify-content: center;
|
|
8894
|
+
padding: 80px 20px;
|
|
8895
|
+
text-align: center;
|
|
8896
|
+
color: #9CA3AF;
|
|
9165
8897
|
}
|
|
9166
8898
|
|
|
9167
|
-
.
|
|
9168
|
-
margin-bottom:
|
|
8899
|
+
.changelog-empty svg {
|
|
8900
|
+
margin-bottom: 16px;
|
|
8901
|
+
stroke: #D1D5DB;
|
|
9169
8902
|
}
|
|
9170
8903
|
|
|
9171
|
-
.
|
|
9172
|
-
|
|
9173
|
-
font-
|
|
9174
|
-
line-height: 1.25;
|
|
9175
|
-
color: #374151;
|
|
8904
|
+
.changelog-empty p {
|
|
8905
|
+
margin: 0;
|
|
8906
|
+
font-size: 15px;
|
|
9176
8907
|
}
|
|
9177
8908
|
|
|
9178
|
-
.
|
|
9179
|
-
|
|
8909
|
+
.changelog-popup-item {
|
|
8910
|
+
display: flex;
|
|
8911
|
+
flex-direction: column;
|
|
9180
8912
|
}
|
|
9181
8913
|
|
|
9182
|
-
.
|
|
9183
|
-
height: 44px;
|
|
8914
|
+
.changelog-popup-image {
|
|
9184
8915
|
width: 100%;
|
|
9185
|
-
|
|
9186
|
-
border: 1px solid #D1D5DB;
|
|
9187
|
-
padding: 10px 14px;
|
|
9188
|
-
font-size: 15px;
|
|
9189
|
-
font-weight: 400;
|
|
9190
|
-
line-height: 1.5;
|
|
9191
|
-
color: #1F2937;
|
|
9192
|
-
font-family: inherit;
|
|
9193
|
-
outline: none;
|
|
9194
|
-
transition: all 0.2s ease;
|
|
8916
|
+
padding: 24px 24px 0;
|
|
9195
8917
|
}
|
|
9196
8918
|
|
|
9197
|
-
.
|
|
9198
|
-
|
|
9199
|
-
|
|
8919
|
+
.changelog-popup-image img {
|
|
8920
|
+
width: 100%;
|
|
8921
|
+
height: auto;
|
|
8922
|
+
display: block;
|
|
8923
|
+
object-fit: cover;
|
|
8924
|
+
border-radius: 12px;
|
|
8925
|
+
border: 2px solid #155EEF;
|
|
8926
|
+
box-shadow: 0 4px 20px rgba(21, 94, 239, 0.2);
|
|
9200
8927
|
}
|
|
9201
8928
|
|
|
9202
|
-
.
|
|
9203
|
-
|
|
9204
|
-
|
|
8929
|
+
.changelog-popup-body {
|
|
8930
|
+
padding: 24px 32px 32px;
|
|
8931
|
+
text-align: center;
|
|
9205
8932
|
}
|
|
9206
8933
|
|
|
9207
|
-
.
|
|
9208
|
-
|
|
8934
|
+
.changelog-popup-title {
|
|
8935
|
+
margin: 0 0 16px;
|
|
8936
|
+
font-size: 18px;
|
|
8937
|
+
font-weight: 600;
|
|
8938
|
+
line-height: 1.3;
|
|
8939
|
+
color: #111827;
|
|
9209
8940
|
}
|
|
9210
8941
|
|
|
9211
|
-
.
|
|
9212
|
-
|
|
9213
|
-
width: 100%;
|
|
9214
|
-
resize: vertical;
|
|
9215
|
-
border-radius: 8px;
|
|
9216
|
-
border: 1px solid #D1D5DB;
|
|
9217
|
-
padding: 10px 14px;
|
|
9218
|
-
font-size: 15px;
|
|
9219
|
-
font-weight: 400;
|
|
9220
|
-
line-height: 1.5;
|
|
9221
|
-
color: #1F2937;
|
|
9222
|
-
font-family: inherit;
|
|
9223
|
-
outline: none;
|
|
9224
|
-
transition: all 0.2s ease;
|
|
9225
|
-
}
|
|
9226
|
-
|
|
9227
|
-
.feedback-form-group textarea::placeholder {
|
|
9228
|
-
font-size: 15px;
|
|
9229
|
-
color: #9CA3AF;
|
|
9230
|
-
}
|
|
9231
|
-
|
|
9232
|
-
.feedback-form-group textarea:focus {
|
|
9233
|
-
border-color: #155EEF;
|
|
9234
|
-
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
|
|
9235
|
-
}
|
|
9236
|
-
|
|
9237
|
-
.feedback-form-group textarea:focus-visible {
|
|
9238
|
-
outline: none;
|
|
8942
|
+
.changelog-modal.theme-dark .changelog-popup-title {
|
|
8943
|
+
color: white;
|
|
9239
8944
|
}
|
|
9240
8945
|
|
|
9241
|
-
.
|
|
9242
|
-
|
|
9243
|
-
|
|
9244
|
-
|
|
9245
|
-
color:
|
|
8946
|
+
.changelog-popup-description {
|
|
8947
|
+
margin: 0 0 24px;
|
|
8948
|
+
font-size: 17px;
|
|
8949
|
+
line-height: 1.6;
|
|
8950
|
+
color: #4B5563;
|
|
9246
8951
|
}
|
|
9247
8952
|
|
|
9248
|
-
.
|
|
9249
|
-
|
|
9250
|
-
color: #6B7280;
|
|
8953
|
+
.changelog-modal.theme-dark .changelog-popup-description {
|
|
8954
|
+
color: #D1D5DB;
|
|
9251
8955
|
}
|
|
9252
8956
|
|
|
9253
|
-
.
|
|
9254
|
-
position: relative;
|
|
8957
|
+
.changelog-popup-btn {
|
|
9255
8958
|
display: inline-flex;
|
|
9256
8959
|
align-items: center;
|
|
9257
8960
|
justify-content: center;
|
|
9258
|
-
|
|
9259
|
-
|
|
8961
|
+
padding: 14px 32px;
|
|
8962
|
+
font-size: 16px;
|
|
8963
|
+
font-weight: 600;
|
|
8964
|
+
color: white;
|
|
8965
|
+
background: #155EEF;
|
|
9260
8966
|
border: none;
|
|
9261
|
-
|
|
9262
|
-
padding: 10px 18px;
|
|
9263
|
-
font-size: 15px;
|
|
9264
|
-
font-weight: 500;
|
|
9265
|
-
font-family: inherit;
|
|
8967
|
+
border-radius: 10px;
|
|
9266
8968
|
cursor: pointer;
|
|
9267
8969
|
transition: all 0.2s ease;
|
|
9268
8970
|
}
|
|
9269
8971
|
|
|
9270
|
-
.
|
|
9271
|
-
|
|
9272
|
-
|
|
8972
|
+
.changelog-popup-btn:hover {
|
|
8973
|
+
background: #1249CA;
|
|
8974
|
+
transform: translateY(-2px);
|
|
8975
|
+
box-shadow: 0 4px 12px rgba(21, 94, 239, 0.3);
|
|
9273
8976
|
}
|
|
9274
8977
|
|
|
9275
|
-
.
|
|
8978
|
+
.changelog-popup-btn:focus-visible {
|
|
9276
8979
|
outline: 2px solid #155EEF;
|
|
9277
8980
|
outline-offset: 2px;
|
|
9278
8981
|
}
|
|
9279
8982
|
|
|
9280
|
-
.
|
|
9281
|
-
|
|
9282
|
-
|
|
9283
|
-
|
|
8983
|
+
.changelog-popup-footer {
|
|
8984
|
+
padding: 0 32px 24px;
|
|
8985
|
+
display: flex;
|
|
8986
|
+
flex-direction: column;
|
|
8987
|
+
align-items: center;
|
|
8988
|
+
gap: 16px;
|
|
9284
8989
|
}
|
|
9285
8990
|
|
|
9286
|
-
.
|
|
9287
|
-
|
|
8991
|
+
.changelog-popup-dots {
|
|
8992
|
+
display: flex;
|
|
8993
|
+
gap: 8px;
|
|
9288
8994
|
}
|
|
9289
8995
|
|
|
9290
|
-
.
|
|
9291
|
-
|
|
8996
|
+
.changelog-dot {
|
|
8997
|
+
width: 10px;
|
|
8998
|
+
height: 10px;
|
|
8999
|
+
border-radius: 50%;
|
|
9000
|
+
background: rgba(21, 94, 239, 0.3);
|
|
9001
|
+
cursor: pointer;
|
|
9002
|
+
transition: all 0.2s ease;
|
|
9292
9003
|
}
|
|
9293
9004
|
|
|
9294
|
-
.
|
|
9295
|
-
background:
|
|
9296
|
-
color: #6B7280;
|
|
9297
|
-
border: 1px solid #D1D5DB;
|
|
9005
|
+
.changelog-dot:hover {
|
|
9006
|
+
background: rgba(21, 94, 239, 0.5);
|
|
9298
9007
|
}
|
|
9299
9008
|
|
|
9300
|
-
.
|
|
9301
|
-
background: #
|
|
9302
|
-
|
|
9303
|
-
color: #374151;
|
|
9009
|
+
.changelog-dot.active {
|
|
9010
|
+
background: #155EEF;
|
|
9011
|
+
transform: scale(1.2);
|
|
9304
9012
|
}
|
|
9305
9013
|
|
|
9306
|
-
.
|
|
9307
|
-
|
|
9308
|
-
|
|
9014
|
+
.changelog-view-all-btn {
|
|
9015
|
+
display: inline-flex;
|
|
9016
|
+
align-items: center;
|
|
9017
|
+
gap: 6px;
|
|
9018
|
+
background: none;
|
|
9019
|
+
border: none;
|
|
9020
|
+
color: #155EEF;
|
|
9021
|
+
font-size: 14px;
|
|
9022
|
+
font-weight: 500;
|
|
9023
|
+
cursor: pointer;
|
|
9024
|
+
padding: 8px 12px;
|
|
9025
|
+
border-radius: 6px;
|
|
9026
|
+
transition: all 0.2s ease;
|
|
9309
9027
|
}
|
|
9310
9028
|
|
|
9311
|
-
.
|
|
9312
|
-
background:
|
|
9029
|
+
.changelog-view-all-btn:hover {
|
|
9030
|
+
background: rgba(21, 94, 239, 0.1);
|
|
9313
9031
|
}
|
|
9314
9032
|
|
|
9315
|
-
.
|
|
9316
|
-
|
|
9317
|
-
flex-direction: column;
|
|
9318
|
-
gap: 12px;
|
|
9319
|
-
margin-top: auto;
|
|
9320
|
-
padding-top: 24px;
|
|
9033
|
+
.changelog-view-all-btn svg {
|
|
9034
|
+
transition: transform 0.2s ease;
|
|
9321
9035
|
}
|
|
9322
9036
|
|
|
9323
|
-
.
|
|
9324
|
-
|
|
9325
|
-
font-size: 14px;
|
|
9326
|
-
font-weight: 400;
|
|
9327
|
-
margin-top: 8px;
|
|
9328
|
-
padding: 12px;
|
|
9329
|
-
background: #FEE2E2;
|
|
9330
|
-
border: 1px solid #FECACA;
|
|
9331
|
-
border-radius: 8px;
|
|
9332
|
-
display: none;
|
|
9037
|
+
.changelog-view-all-btn:hover svg {
|
|
9038
|
+
transform: translateX(3px);
|
|
9333
9039
|
}
|
|
9334
9040
|
|
|
9335
|
-
.
|
|
9336
|
-
|
|
9041
|
+
.changelog-modal.theme-dark .changelog-view-all-btn {
|
|
9042
|
+
color: #60A5FA;
|
|
9337
9043
|
}
|
|
9338
9044
|
|
|
9339
|
-
.
|
|
9340
|
-
background:
|
|
9341
|
-
border-color: #991B1B;
|
|
9342
|
-
color: #FCA5A5;
|
|
9045
|
+
.changelog-modal.theme-dark .changelog-view-all-btn:hover {
|
|
9046
|
+
background: rgba(96, 165, 250, 0.1);
|
|
9343
9047
|
}
|
|
9344
9048
|
|
|
9345
|
-
.
|
|
9049
|
+
.changelog-list-modal-backdrop {
|
|
9346
9050
|
position: fixed;
|
|
9347
|
-
top:
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9051
|
+
top: 0;
|
|
9052
|
+
left: 0;
|
|
9053
|
+
right: 0;
|
|
9054
|
+
bottom: 0;
|
|
9055
|
+
background: rgba(0, 0, 0, 0.5);
|
|
9056
|
+
opacity: 0;
|
|
9057
|
+
transition: opacity 0.3s ease;
|
|
9058
|
+
pointer-events: none;
|
|
9059
|
+
z-index: 999998;
|
|
9356
9060
|
}
|
|
9357
9061
|
|
|
9358
|
-
.
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
padding: 16px 20px;
|
|
9362
|
-
gap: 12px;
|
|
9062
|
+
.changelog-list-modal-backdrop.show {
|
|
9063
|
+
opacity: 1;
|
|
9064
|
+
pointer-events: auto;
|
|
9363
9065
|
}
|
|
9364
9066
|
|
|
9365
|
-
.
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9067
|
+
.changelog-list-modal {
|
|
9068
|
+
position: fixed;
|
|
9069
|
+
top: 0;
|
|
9070
|
+
left: 0;
|
|
9071
|
+
right: 0;
|
|
9072
|
+
bottom: 0;
|
|
9073
|
+
z-index: 999999;
|
|
9371
9074
|
display: flex;
|
|
9372
9075
|
align-items: center;
|
|
9373
9076
|
justify-content: center;
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9077
|
+
padding: 20px;
|
|
9078
|
+
pointer-events: none;
|
|
9079
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
9377
9080
|
}
|
|
9378
9081
|
|
|
9379
|
-
.
|
|
9380
|
-
|
|
9381
|
-
font-weight: 500;
|
|
9382
|
-
font-size: 14px;
|
|
9383
|
-
flex: 1;
|
|
9082
|
+
.changelog-list-modal.open {
|
|
9083
|
+
pointer-events: auto;
|
|
9384
9084
|
}
|
|
9385
9085
|
|
|
9386
|
-
.
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
|
|
9086
|
+
.changelog-list-modal-container {
|
|
9087
|
+
position: relative;
|
|
9088
|
+
width: 100%;
|
|
9089
|
+
max-width: 460px;
|
|
9090
|
+
max-height: 85vh;
|
|
9091
|
+
background: white;
|
|
9092
|
+
border-radius: 20px;
|
|
9093
|
+
overflow: hidden;
|
|
9094
|
+
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
9095
|
+
transform: scale(0.9) translateY(20px);
|
|
9096
|
+
opacity: 0;
|
|
9097
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
9395
9098
|
display: flex;
|
|
9396
|
-
|
|
9397
|
-
justify-content: center;
|
|
9398
|
-
transition: all 0.2s ease;
|
|
9399
|
-
border-radius: 4px;
|
|
9400
|
-
flex-shrink: 0;
|
|
9099
|
+
flex-direction: column;
|
|
9401
9100
|
}
|
|
9402
9101
|
|
|
9403
|
-
.
|
|
9404
|
-
|
|
9405
|
-
|
|
9102
|
+
.changelog-list-modal.open .changelog-list-modal-container {
|
|
9103
|
+
transform: scale(1) translateY(0);
|
|
9104
|
+
opacity: 1;
|
|
9406
9105
|
}
|
|
9407
9106
|
|
|
9408
|
-
.
|
|
9409
|
-
|
|
9410
|
-
|
|
9107
|
+
.changelog-list-modal.theme-dark .changelog-list-modal-container {
|
|
9108
|
+
background: #1F2937;
|
|
9109
|
+
color: white;
|
|
9411
9110
|
}
|
|
9412
9111
|
|
|
9413
|
-
|
|
9414
|
-
|
|
9415
|
-
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9421
|
-
}
|
|
9422
|
-
}
|
|
9423
|
-
|
|
9424
|
-
@keyframes fadeIn {
|
|
9425
|
-
from { opacity: 0; }
|
|
9426
|
-
to { opacity: 1; }
|
|
9112
|
+
.changelog-list-modal-header {
|
|
9113
|
+
display: flex;
|
|
9114
|
+
align-items: center;
|
|
9115
|
+
justify-content: space-between;
|
|
9116
|
+
padding: 14px 20px;
|
|
9117
|
+
border-bottom: 1px solid #E5E7EB;
|
|
9118
|
+
flex-shrink: 0;
|
|
9119
|
+
background: white;
|
|
9427
9120
|
}
|
|
9428
9121
|
|
|
9429
|
-
.
|
|
9430
|
-
|
|
9122
|
+
.changelog-list-modal.theme-dark .changelog-list-modal-header {
|
|
9123
|
+
border-bottom-color: #374151;
|
|
9124
|
+
background: #1F2937;
|
|
9431
9125
|
}
|
|
9432
9126
|
|
|
9433
|
-
|
|
9434
|
-
|
|
9435
|
-
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
right: 0;
|
|
9439
|
-
left: 0;
|
|
9440
|
-
height: 85vh;
|
|
9441
|
-
max-height: 85vh;
|
|
9442
|
-
transform: translateY(100%);
|
|
9443
|
-
border-radius: 20px 20px 0 0;
|
|
9444
|
-
}
|
|
9445
|
-
|
|
9446
|
-
.feedback-panel.open {
|
|
9447
|
-
transform: translateY(0);
|
|
9448
|
-
}
|
|
9449
|
-
|
|
9450
|
-
.feedback-panel-content {
|
|
9451
|
-
border-radius: 20px 20px 0 0;
|
|
9452
|
-
}
|
|
9453
|
-
|
|
9454
|
-
.feedback-panel-header {
|
|
9455
|
-
padding: 20px;
|
|
9456
|
-
position: relative;
|
|
9457
|
-
}
|
|
9458
|
-
|
|
9459
|
-
.feedback-panel-header::before {
|
|
9460
|
-
content: '';
|
|
9461
|
-
position: absolute;
|
|
9462
|
-
top: 8px;
|
|
9463
|
-
left: 50%;
|
|
9464
|
-
transform: translateX(-50%);
|
|
9465
|
-
width: 40px;
|
|
9466
|
-
height: 4px;
|
|
9467
|
-
background: #D1D5DB;
|
|
9468
|
-
border-radius: 2px;
|
|
9469
|
-
}
|
|
9470
|
-
|
|
9471
|
-
.feedback-panel.theme-dark .feedback-panel-header::before {
|
|
9472
|
-
background: #4B5563;
|
|
9473
|
-
}
|
|
9474
|
-
|
|
9475
|
-
.feedback-panel-body {
|
|
9476
|
-
padding: 20px;
|
|
9477
|
-
}
|
|
9478
|
-
|
|
9479
|
-
.feedback-form-group textarea {
|
|
9480
|
-
min-height: 150px;
|
|
9481
|
-
}
|
|
9482
|
-
|
|
9483
|
-
.feedback-widget-button {
|
|
9484
|
-
bottom: 16px;
|
|
9485
|
-
right: 16px;
|
|
9486
|
-
}
|
|
9487
|
-
|
|
9488
|
-
.feedback-widget-button.position-bottom-left {
|
|
9489
|
-
left: 16px;
|
|
9490
|
-
}
|
|
9491
|
-
|
|
9492
|
-
.feedback-success-notification {
|
|
9493
|
-
top: 16px;
|
|
9494
|
-
right: 16px;
|
|
9495
|
-
left: 16px;
|
|
9496
|
-
min-width: auto;
|
|
9497
|
-
}
|
|
9498
|
-
|
|
9499
|
-
.feedback-minimize-icon,
|
|
9500
|
-
.feedback-expand-icon {
|
|
9501
|
-
top: -4px;
|
|
9502
|
-
right: -4px;
|
|
9503
|
-
width: 20px;
|
|
9504
|
-
height: 20px;
|
|
9505
|
-
}
|
|
9506
|
-
|
|
9507
|
-
.feedback-minimize-icon svg,
|
|
9508
|
-
.feedback-expand-icon svg {
|
|
9509
|
-
width: 14px;
|
|
9510
|
-
height: 14px;
|
|
9511
|
-
}
|
|
9127
|
+
.changelog-list-modal-header h2 {
|
|
9128
|
+
margin: 0;
|
|
9129
|
+
font-size: 16px;
|
|
9130
|
+
font-weight: 600;
|
|
9131
|
+
color: #111827;
|
|
9512
9132
|
}
|
|
9513
9133
|
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
.feedback-btn,
|
|
9517
|
-
.feedback-panel,
|
|
9518
|
-
.feedback-panel-backdrop,
|
|
9519
|
-
.feedback-success-notification,
|
|
9520
|
-
.feedback-minimize-icon,
|
|
9521
|
-
.feedback-expand-icon {
|
|
9522
|
-
transition: none;
|
|
9523
|
-
animation: none;
|
|
9524
|
-
}
|
|
9134
|
+
.changelog-list-modal.theme-dark .changelog-list-modal-header h2 {
|
|
9135
|
+
color: white;
|
|
9525
9136
|
}
|
|
9526
9137
|
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
|
|
9531
|
-
|
|
9532
|
-
|
|
9533
|
-
|
|
9138
|
+
.changelog-list-modal-close {
|
|
9139
|
+
background: none;
|
|
9140
|
+
border: none;
|
|
9141
|
+
font-size: 22px;
|
|
9142
|
+
cursor: pointer;
|
|
9143
|
+
color: #6B7280;
|
|
9144
|
+
padding: 4px;
|
|
9145
|
+
width: 28px;
|
|
9146
|
+
height: 28px;
|
|
9147
|
+
display: flex;
|
|
9148
|
+
align-items: center;
|
|
9149
|
+
justify-content: center;
|
|
9150
|
+
border-radius: 6px;
|
|
9151
|
+
transition: all 0.2s ease;
|
|
9152
|
+
line-height: 1;
|
|
9534
9153
|
}
|
|
9535
9154
|
|
|
9536
|
-
|
|
9537
|
-
|
|
9538
|
-
|
|
9539
|
-
z-index: 999999;
|
|
9155
|
+
.changelog-list-modal-close:hover {
|
|
9156
|
+
background: #F3F4F6;
|
|
9157
|
+
color: #111827;
|
|
9540
9158
|
}
|
|
9541
9159
|
|
|
9542
|
-
.changelog-
|
|
9543
|
-
|
|
9544
|
-
right: 20px;
|
|
9160
|
+
.changelog-list-modal.theme-dark .changelog-list-modal-close {
|
|
9161
|
+
color: #9CA3AF;
|
|
9545
9162
|
}
|
|
9546
9163
|
|
|
9547
|
-
.changelog-
|
|
9548
|
-
|
|
9549
|
-
|
|
9164
|
+
.changelog-list-modal.theme-dark .changelog-list-modal-close:hover {
|
|
9165
|
+
background: #374151;
|
|
9166
|
+
color: white;
|
|
9550
9167
|
}
|
|
9551
9168
|
|
|
9552
|
-
.changelog-
|
|
9553
|
-
|
|
9554
|
-
|
|
9169
|
+
.changelog-list-modal-body {
|
|
9170
|
+
flex: 1;
|
|
9171
|
+
overflow-y: auto;
|
|
9555
9172
|
}
|
|
9556
9173
|
|
|
9557
|
-
.changelog-
|
|
9558
|
-
|
|
9559
|
-
|
|
9174
|
+
.changelog-list {
|
|
9175
|
+
display: flex;
|
|
9176
|
+
flex-direction: column;
|
|
9560
9177
|
}
|
|
9561
9178
|
|
|
9562
|
-
.changelog-
|
|
9563
|
-
position: relative;
|
|
9179
|
+
.changelog-list-item {
|
|
9564
9180
|
display: flex;
|
|
9181
|
+
flex-direction: row;
|
|
9565
9182
|
align-items: center;
|
|
9566
|
-
|
|
9567
|
-
|
|
9568
|
-
height: 48px;
|
|
9569
|
-
overflow: visible;
|
|
9570
|
-
border-radius: 9999px;
|
|
9571
|
-
border: none;
|
|
9572
|
-
padding: 12px 20px;
|
|
9573
|
-
font-size: 14px;
|
|
9574
|
-
font-weight: 500;
|
|
9575
|
-
font-family: inherit;
|
|
9183
|
+
padding: 12px 16px;
|
|
9184
|
+
border-bottom: 1px solid #E5E7EB;
|
|
9576
9185
|
cursor: pointer;
|
|
9577
|
-
transition:
|
|
9578
|
-
|
|
9579
|
-
background: #155EEF;
|
|
9580
|
-
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
9581
|
-
width: fit-content;
|
|
9582
|
-
}
|
|
9583
|
-
|
|
9584
|
-
.changelog-trigger-btn:hover {
|
|
9585
|
-
transform: translateY(-2px);
|
|
9586
|
-
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
|
|
9186
|
+
transition: background-color 0.2s ease;
|
|
9187
|
+
position: relative;
|
|
9587
9188
|
}
|
|
9588
9189
|
|
|
9589
|
-
.changelog-
|
|
9590
|
-
|
|
9591
|
-
outline-offset: 2px;
|
|
9190
|
+
.changelog-list-item:hover {
|
|
9191
|
+
background: #F9FAFB;
|
|
9592
9192
|
}
|
|
9593
9193
|
|
|
9594
|
-
.changelog-
|
|
9595
|
-
|
|
9194
|
+
.changelog-list-item:last-child {
|
|
9195
|
+
border-bottom: none;
|
|
9596
9196
|
}
|
|
9597
9197
|
|
|
9598
|
-
.changelog-
|
|
9599
|
-
|
|
9600
|
-
margin-left: 2px;
|
|
9198
|
+
.changelog-list-modal.theme-dark .changelog-list-item {
|
|
9199
|
+
border-bottom-color: #374151;
|
|
9601
9200
|
}
|
|
9602
9201
|
|
|
9603
|
-
.changelog-
|
|
9604
|
-
|
|
9605
|
-
top: -4px;
|
|
9606
|
-
right: -4px;
|
|
9607
|
-
width: 12px;
|
|
9608
|
-
height: 12px;
|
|
9609
|
-
background: #EF4444;
|
|
9610
|
-
border-radius: 50%;
|
|
9611
|
-
border: 2px solid white;
|
|
9202
|
+
.changelog-list-modal.theme-dark .changelog-list-item:hover {
|
|
9203
|
+
background: #374151;
|
|
9612
9204
|
}
|
|
9613
9205
|
|
|
9614
|
-
|
|
9615
|
-
.changelog-confetti-container {
|
|
9616
|
-
position: fixed;
|
|
9617
|
-
top: 0;
|
|
9618
|
-
left: 0;
|
|
9206
|
+
.changelog-list-item-image {
|
|
9619
9207
|
width: 100%;
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
z-index: 1000001;
|
|
9208
|
+
margin-bottom: 8px;
|
|
9209
|
+
border-radius: 6px;
|
|
9623
9210
|
overflow: hidden;
|
|
9211
|
+
border: 1px solid #E5E7EB;
|
|
9624
9212
|
}
|
|
9625
9213
|
|
|
9626
|
-
.changelog-
|
|
9627
|
-
|
|
9628
|
-
|
|
9629
|
-
|
|
9630
|
-
|
|
9631
|
-
}
|
|
9632
|
-
|
|
9633
|
-
@keyframes confettiFall {
|
|
9634
|
-
0% {
|
|
9635
|
-
opacity: 1;
|
|
9636
|
-
transform: translateY(0) rotate(0deg) scale(1);
|
|
9637
|
-
}
|
|
9638
|
-
10% {
|
|
9639
|
-
opacity: 1;
|
|
9640
|
-
}
|
|
9641
|
-
100% {
|
|
9642
|
-
opacity: 0;
|
|
9643
|
-
transform: translateY(100vh) rotate(720deg) scale(0.5);
|
|
9644
|
-
}
|
|
9645
|
-
}
|
|
9646
|
-
|
|
9647
|
-
/* Changelog Modal */
|
|
9648
|
-
.changelog-modal-backdrop {
|
|
9649
|
-
position: fixed;
|
|
9650
|
-
top: 0;
|
|
9651
|
-
left: 0;
|
|
9652
|
-
right: 0;
|
|
9653
|
-
bottom: 0;
|
|
9654
|
-
background: rgba(0, 0, 0, 0.5);
|
|
9655
|
-
opacity: 0;
|
|
9656
|
-
transition: opacity 0.3s ease;
|
|
9657
|
-
pointer-events: none;
|
|
9658
|
-
z-index: 999998;
|
|
9659
|
-
display: flex;
|
|
9660
|
-
align-items: center;
|
|
9661
|
-
justify-content: center;
|
|
9214
|
+
.changelog-list-item-image img {
|
|
9215
|
+
width: 100%;
|
|
9216
|
+
height: 100px;
|
|
9217
|
+
display: block;
|
|
9218
|
+
object-fit: cover;
|
|
9662
9219
|
}
|
|
9663
9220
|
|
|
9664
|
-
.changelog-
|
|
9665
|
-
|
|
9666
|
-
|
|
9221
|
+
.changelog-list-item-main {
|
|
9222
|
+
flex: 1;
|
|
9223
|
+
min-width: 0;
|
|
9667
9224
|
}
|
|
9668
9225
|
|
|
9669
|
-
.changelog-
|
|
9670
|
-
position: fixed;
|
|
9671
|
-
top: 0;
|
|
9672
|
-
left: 0;
|
|
9673
|
-
right: 0;
|
|
9674
|
-
bottom: 0;
|
|
9675
|
-
z-index: 999999;
|
|
9226
|
+
.changelog-list-item-content {
|
|
9676
9227
|
display: flex;
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
padding: 20px;
|
|
9680
|
-
pointer-events: none;
|
|
9681
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
9682
|
-
}
|
|
9683
|
-
|
|
9684
|
-
.changelog-modal.open {
|
|
9685
|
-
pointer-events: auto;
|
|
9686
|
-
}
|
|
9687
|
-
|
|
9688
|
-
.changelog-modal-container {
|
|
9689
|
-
position: relative;
|
|
9690
|
-
width: 100%;
|
|
9691
|
-
max-width: 580px;
|
|
9692
|
-
max-height: 90vh;
|
|
9693
|
-
background: #DBEAFE;
|
|
9694
|
-
border-radius: 24px;
|
|
9695
|
-
overflow: hidden;
|
|
9696
|
-
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
9697
|
-
transform: scale(0.9) translateY(20px);
|
|
9698
|
-
opacity: 0;
|
|
9699
|
-
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
9228
|
+
flex-direction: column;
|
|
9229
|
+
gap: 3px;
|
|
9700
9230
|
}
|
|
9701
9231
|
|
|
9702
|
-
.changelog-
|
|
9703
|
-
|
|
9704
|
-
|
|
9232
|
+
.changelog-list-item-date {
|
|
9233
|
+
font-size: 11px;
|
|
9234
|
+
color: #6B7280;
|
|
9235
|
+
font-weight: 500;
|
|
9705
9236
|
}
|
|
9706
9237
|
|
|
9707
|
-
.changelog-modal.theme-dark .changelog-
|
|
9708
|
-
|
|
9238
|
+
.changelog-list-modal.theme-dark .changelog-list-item-date {
|
|
9239
|
+
color: #9CA3AF;
|
|
9709
9240
|
}
|
|
9710
9241
|
|
|
9711
|
-
.changelog-
|
|
9712
|
-
position: absolute;
|
|
9713
|
-
top: 16px;
|
|
9714
|
-
right: 16px;
|
|
9715
|
-
background: rgba(255, 255, 255, 0.9);
|
|
9716
|
-
border: none;
|
|
9717
|
-
font-size: 24px;
|
|
9718
|
-
cursor: pointer;
|
|
9719
|
-
color: #6B7280;
|
|
9720
|
-
padding: 0;
|
|
9721
|
-
width: 36px;
|
|
9722
|
-
height: 36px;
|
|
9242
|
+
.changelog-list-item-labels {
|
|
9723
9243
|
display: flex;
|
|
9724
|
-
|
|
9725
|
-
|
|
9726
|
-
|
|
9727
|
-
transition: all 0.2s ease;
|
|
9728
|
-
line-height: 1;
|
|
9729
|
-
z-index: 10;
|
|
9730
|
-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
9244
|
+
flex-wrap: wrap;
|
|
9245
|
+
gap: 4px;
|
|
9246
|
+
margin-bottom: 1px;
|
|
9731
9247
|
}
|
|
9732
9248
|
|
|
9733
|
-
.changelog-
|
|
9734
|
-
|
|
9249
|
+
.changelog-list-item-title {
|
|
9250
|
+
margin: 0;
|
|
9251
|
+
font-size: 14px;
|
|
9252
|
+
font-weight: 600;
|
|
9253
|
+
line-height: 1.3;
|
|
9735
9254
|
color: #111827;
|
|
9736
|
-
transform: scale(1.05);
|
|
9737
9255
|
}
|
|
9738
9256
|
|
|
9739
|
-
.changelog-modal.theme-dark .changelog-
|
|
9740
|
-
background: rgba(55, 65, 81, 0.9);
|
|
9741
|
-
color: #D1D5DB;
|
|
9742
|
-
}
|
|
9743
|
-
|
|
9744
|
-
.changelog-modal.theme-dark .changelog-modal-close:hover {
|
|
9745
|
-
background: #374151;
|
|
9257
|
+
.changelog-list-modal.theme-dark .changelog-list-item-title {
|
|
9746
9258
|
color: white;
|
|
9747
9259
|
}
|
|
9748
9260
|
|
|
9749
|
-
.changelog-
|
|
9750
|
-
|
|
9751
|
-
|
|
9752
|
-
|
|
9753
|
-
|
|
9754
|
-
|
|
9755
|
-
|
|
9756
|
-
|
|
9757
|
-
|
|
9758
|
-
justify-content: center;
|
|
9759
|
-
padding: 80px 20px;
|
|
9760
|
-
}
|
|
9761
|
-
|
|
9762
|
-
.changelog-loading-spinner {
|
|
9763
|
-
width: 32px;
|
|
9764
|
-
height: 32px;
|
|
9765
|
-
border: 3px solid #E5E7EB;
|
|
9766
|
-
border-top-color: #155EEF;
|
|
9767
|
-
border-radius: 50%;
|
|
9768
|
-
animation: changelogSpin 0.8s linear infinite;
|
|
9769
|
-
}
|
|
9770
|
-
|
|
9771
|
-
@keyframes changelogSpin {
|
|
9772
|
-
to {
|
|
9773
|
-
transform: rotate(360deg);
|
|
9774
|
-
}
|
|
9261
|
+
.changelog-list-item-description {
|
|
9262
|
+
margin: 0;
|
|
9263
|
+
font-size: 12px;
|
|
9264
|
+
line-height: 1.4;
|
|
9265
|
+
color: #6B7280;
|
|
9266
|
+
display: -webkit-box;
|
|
9267
|
+
-webkit-line-clamp: 2;
|
|
9268
|
+
-webkit-box-orient: vertical;
|
|
9269
|
+
overflow: hidden;
|
|
9775
9270
|
}
|
|
9776
9271
|
|
|
9777
|
-
|
|
9778
|
-
.changelog-empty {
|
|
9779
|
-
display: flex;
|
|
9780
|
-
flex-direction: column;
|
|
9781
|
-
align-items: center;
|
|
9782
|
-
justify-content: center;
|
|
9783
|
-
padding: 80px 20px;
|
|
9784
|
-
text-align: center;
|
|
9272
|
+
.changelog-list-modal.theme-dark .changelog-list-item-description {
|
|
9785
9273
|
color: #9CA3AF;
|
|
9786
9274
|
}
|
|
9787
9275
|
|
|
9788
|
-
.changelog-
|
|
9789
|
-
|
|
9790
|
-
|
|
9276
|
+
.changelog-list-item-arrow {
|
|
9277
|
+
flex-shrink: 0;
|
|
9278
|
+
margin-left: 12px;
|
|
9279
|
+
color: #9CA3AF;
|
|
9280
|
+
transition: all 0.2s ease;
|
|
9791
9281
|
}
|
|
9792
9282
|
|
|
9793
|
-
.changelog-
|
|
9794
|
-
|
|
9795
|
-
|
|
9283
|
+
.changelog-list-item:hover .changelog-list-item-arrow {
|
|
9284
|
+
color: #155EEF;
|
|
9285
|
+
transform: translateX(3px);
|
|
9796
9286
|
}
|
|
9797
9287
|
|
|
9798
|
-
|
|
9799
|
-
|
|
9800
|
-
display: flex;
|
|
9801
|
-
flex-direction: column;
|
|
9288
|
+
.changelog-list-modal.theme-dark .changelog-list-item-arrow {
|
|
9289
|
+
color: #6B7280;
|
|
9802
9290
|
}
|
|
9803
9291
|
|
|
9804
|
-
.changelog-
|
|
9805
|
-
|
|
9806
|
-
padding: 24px 24px 0;
|
|
9292
|
+
.changelog-list-modal.theme-dark .changelog-list-item:hover .changelog-list-item-arrow {
|
|
9293
|
+
color: #60A5FA;
|
|
9807
9294
|
}
|
|
9808
9295
|
|
|
9809
|
-
|
|
9810
|
-
|
|
9811
|
-
|
|
9812
|
-
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
|
|
9816
|
-
|
|
9296
|
+
/* ==================== MOBILE RESPONSIVE ==================== */
|
|
9297
|
+
@media (max-width: 768px) {
|
|
9298
|
+
.changelog-widget {
|
|
9299
|
+
bottom: 16px;
|
|
9300
|
+
right: 16px;
|
|
9301
|
+
}
|
|
9302
|
+
|
|
9303
|
+
.changelog-widget.position-bottom-left {
|
|
9304
|
+
left: 16px;
|
|
9305
|
+
}
|
|
9306
|
+
|
|
9307
|
+
.changelog-modal {
|
|
9308
|
+
padding: 16px;
|
|
9309
|
+
}
|
|
9310
|
+
|
|
9311
|
+
.changelog-modal-container {
|
|
9312
|
+
max-width: 100%;
|
|
9313
|
+
border-radius: 20px;
|
|
9314
|
+
}
|
|
9315
|
+
|
|
9316
|
+
.changelog-popup-image {
|
|
9317
|
+
padding: 20px 20px 0;
|
|
9318
|
+
}
|
|
9319
|
+
|
|
9320
|
+
.changelog-popup-body {
|
|
9321
|
+
padding: 20px 24px 24px;
|
|
9322
|
+
}
|
|
9323
|
+
|
|
9324
|
+
.changelog-popup-title {
|
|
9325
|
+
font-size: 22px;
|
|
9326
|
+
}
|
|
9327
|
+
|
|
9328
|
+
.changelog-popup-description {
|
|
9329
|
+
font-size: 15px;
|
|
9330
|
+
}
|
|
9331
|
+
|
|
9332
|
+
.changelog-popup-btn {
|
|
9333
|
+
padding: 12px 28px;
|
|
9334
|
+
font-size: 15px;
|
|
9335
|
+
width: 100%;
|
|
9336
|
+
}
|
|
9337
|
+
|
|
9338
|
+
.changelog-popup-footer {
|
|
9339
|
+
padding: 0 24px 20px;
|
|
9340
|
+
}
|
|
9341
|
+
|
|
9342
|
+
.changelog-list-modal {
|
|
9343
|
+
padding: 16px;
|
|
9344
|
+
}
|
|
9345
|
+
|
|
9346
|
+
.changelog-list-modal-container {
|
|
9347
|
+
max-width: 100%;
|
|
9348
|
+
max-height: 90vh;
|
|
9349
|
+
border-radius: 16px;
|
|
9350
|
+
}
|
|
9351
|
+
|
|
9352
|
+
.changelog-list-item {
|
|
9353
|
+
padding: 10px 14px;
|
|
9354
|
+
}
|
|
9355
|
+
|
|
9356
|
+
.changelog-list-item-image img {
|
|
9357
|
+
height: 80px;
|
|
9358
|
+
}
|
|
9359
|
+
|
|
9360
|
+
.changelog-list-item-title {
|
|
9361
|
+
font-size: 13px;
|
|
9362
|
+
}
|
|
9363
|
+
|
|
9364
|
+
.changelog-list-item-description {
|
|
9365
|
+
font-size: 11px;
|
|
9366
|
+
}
|
|
9817
9367
|
}
|
|
9368
|
+
`;
|
|
9818
9369
|
|
|
9819
|
-
|
|
9820
|
-
|
|
9821
|
-
|
|
9370
|
+
const feedbackStyles = `
|
|
9371
|
+
.feedback-widget-button {
|
|
9372
|
+
position: fixed;
|
|
9373
|
+
z-index: 999999;
|
|
9822
9374
|
}
|
|
9823
9375
|
|
|
9824
|
-
.
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
font-weight: 600;
|
|
9828
|
-
line-height: 1.3;
|
|
9829
|
-
color: #111827;
|
|
9376
|
+
.feedback-widget-button.position-bottom-right {
|
|
9377
|
+
bottom: 20px;
|
|
9378
|
+
right: 20px;
|
|
9830
9379
|
}
|
|
9831
9380
|
|
|
9832
|
-
.
|
|
9833
|
-
|
|
9381
|
+
.feedback-widget-button.position-bottom-left {
|
|
9382
|
+
bottom: 20px;
|
|
9383
|
+
left: 20px;
|
|
9834
9384
|
}
|
|
9835
9385
|
|
|
9836
|
-
.
|
|
9837
|
-
|
|
9838
|
-
|
|
9839
|
-
line-height: 1.6;
|
|
9840
|
-
color: #4B5563;
|
|
9386
|
+
.feedback-widget-button.position-top-right {
|
|
9387
|
+
top: 20px;
|
|
9388
|
+
right: 20px;
|
|
9841
9389
|
}
|
|
9842
9390
|
|
|
9843
|
-
.
|
|
9844
|
-
|
|
9391
|
+
.feedback-widget-button.position-top-left {
|
|
9392
|
+
top: 20px;
|
|
9393
|
+
left: 20px;
|
|
9845
9394
|
}
|
|
9846
9395
|
|
|
9847
|
-
.
|
|
9848
|
-
|
|
9396
|
+
.feedback-trigger-btn {
|
|
9397
|
+
position: relative;
|
|
9398
|
+
display: flex;
|
|
9849
9399
|
align-items: center;
|
|
9850
9400
|
justify-content: center;
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
|
|
9854
|
-
|
|
9855
|
-
background: #155EEF;
|
|
9401
|
+
gap: 8px;
|
|
9402
|
+
height: 48px;
|
|
9403
|
+
overflow: visible;
|
|
9404
|
+
border-radius: 9999px;
|
|
9856
9405
|
border: none;
|
|
9857
|
-
|
|
9406
|
+
padding: 12px 20px;
|
|
9407
|
+
font-size: 14px;
|
|
9408
|
+
font-weight: 500;
|
|
9409
|
+
font-family: inherit;
|
|
9858
9410
|
cursor: pointer;
|
|
9859
|
-
transition: all 0.
|
|
9411
|
+
transition: all 0.3s ease;
|
|
9412
|
+
color: white;
|
|
9413
|
+
background: #155EEF;
|
|
9414
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
9415
|
+
width: fit-content;
|
|
9860
9416
|
}
|
|
9861
9417
|
|
|
9862
|
-
.
|
|
9863
|
-
background: #1249CA;
|
|
9418
|
+
.feedback-trigger-btn:hover:not(:disabled) {
|
|
9864
9419
|
transform: translateY(-2px);
|
|
9865
|
-
box-shadow: 0
|
|
9420
|
+
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
|
|
9866
9421
|
}
|
|
9867
9422
|
|
|
9868
|
-
.
|
|
9423
|
+
.feedback-trigger-btn:disabled {
|
|
9424
|
+
opacity: 0.7;
|
|
9425
|
+
cursor: not-allowed;
|
|
9426
|
+
}
|
|
9427
|
+
|
|
9428
|
+
.feedback-trigger-btn:focus-visible {
|
|
9869
9429
|
outline: 2px solid #155EEF;
|
|
9870
9430
|
outline-offset: 2px;
|
|
9871
9431
|
}
|
|
9872
9432
|
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
padding: 0 32px 24px;
|
|
9876
|
-
display: flex;
|
|
9877
|
-
flex-direction: column;
|
|
9878
|
-
align-items: center;
|
|
9879
|
-
gap: 16px;
|
|
9433
|
+
.feedback-icon {
|
|
9434
|
+
flex-shrink: 0;
|
|
9880
9435
|
}
|
|
9881
9436
|
|
|
9882
|
-
.
|
|
9437
|
+
.feedback-minimize-icon,
|
|
9438
|
+
.feedback-expand-icon {
|
|
9439
|
+
position: absolute;
|
|
9440
|
+
top: -6px;
|
|
9441
|
+
right: -6px;
|
|
9442
|
+
width: 24px;
|
|
9443
|
+
height: 24px;
|
|
9444
|
+
padding: 4px;
|
|
9883
9445
|
display: flex;
|
|
9884
|
-
|
|
9885
|
-
|
|
9886
|
-
|
|
9887
|
-
.changelog-dot {
|
|
9888
|
-
width: 10px;
|
|
9889
|
-
height: 10px;
|
|
9446
|
+
align-items: center;
|
|
9447
|
+
justify-content: center;
|
|
9448
|
+
background: white;
|
|
9890
9449
|
border-radius: 50%;
|
|
9891
|
-
|
|
9450
|
+
opacity: 0;
|
|
9451
|
+
transition: opacity 0.2s ease;
|
|
9452
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
9892
9453
|
cursor: pointer;
|
|
9893
|
-
transition: all 0.2s ease;
|
|
9894
9454
|
}
|
|
9895
9455
|
|
|
9896
|
-
.
|
|
9897
|
-
|
|
9456
|
+
.feedback-minimize-icon svg,
|
|
9457
|
+
.feedback-expand-icon svg {
|
|
9458
|
+
width: 16px;
|
|
9459
|
+
height: 16px;
|
|
9460
|
+
display: block;
|
|
9461
|
+
fill: #155EEF;
|
|
9898
9462
|
}
|
|
9899
9463
|
|
|
9900
|
-
.
|
|
9901
|
-
|
|
9902
|
-
transform: scale(1.2);
|
|
9464
|
+
.feedback-widget-button:not(.minimized) .feedback-trigger-btn:hover .feedback-minimize-icon {
|
|
9465
|
+
opacity: 1;
|
|
9903
9466
|
}
|
|
9904
9467
|
|
|
9905
|
-
.
|
|
9906
|
-
|
|
9907
|
-
|
|
9908
|
-
|
|
9909
|
-
|
|
9910
|
-
border: none;
|
|
9911
|
-
color: #155EEF;
|
|
9912
|
-
font-size: 14px;
|
|
9913
|
-
font-weight: 500;
|
|
9914
|
-
cursor: pointer;
|
|
9915
|
-
padding: 8px 12px;
|
|
9916
|
-
border-radius: 6px;
|
|
9917
|
-
transition: all 0.2s ease;
|
|
9468
|
+
.feedback-widget-button.minimized .feedback-trigger-btn {
|
|
9469
|
+
padding: 12px;
|
|
9470
|
+
width: 48px;
|
|
9471
|
+
height: 48px;
|
|
9472
|
+
justify-content: center;
|
|
9918
9473
|
}
|
|
9919
9474
|
|
|
9920
|
-
.
|
|
9921
|
-
|
|
9475
|
+
.feedback-widget-button.minimized .feedback-text {
|
|
9476
|
+
display: none;
|
|
9922
9477
|
}
|
|
9923
9478
|
|
|
9924
|
-
.
|
|
9925
|
-
|
|
9479
|
+
.feedback-widget-button.minimized .feedback-minimize-icon {
|
|
9480
|
+
display: none;
|
|
9926
9481
|
}
|
|
9927
9482
|
|
|
9928
|
-
.
|
|
9929
|
-
|
|
9483
|
+
.feedback-widget-button.minimized .feedback-trigger-btn:hover .feedback-expand-icon {
|
|
9484
|
+
opacity: 1;
|
|
9930
9485
|
}
|
|
9931
9486
|
|
|
9932
|
-
.
|
|
9933
|
-
|
|
9487
|
+
.feedback-panel {
|
|
9488
|
+
position: fixed;
|
|
9489
|
+
bottom: 80px;
|
|
9490
|
+
right: 24px;
|
|
9491
|
+
width: 420px;
|
|
9492
|
+
max-height: 500px;
|
|
9493
|
+
z-index: 1000000;
|
|
9494
|
+
transform: translateX(calc(100% + 24px));
|
|
9495
|
+
transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
|
|
9496
|
+
font-family: inherit;
|
|
9934
9497
|
}
|
|
9935
9498
|
|
|
9936
|
-
.
|
|
9937
|
-
|
|
9499
|
+
.feedback-panel.open {
|
|
9500
|
+
transform: translateX(0);
|
|
9938
9501
|
}
|
|
9939
9502
|
|
|
9940
|
-
|
|
9941
|
-
.changelog-list-modal-backdrop {
|
|
9503
|
+
.feedback-panel-backdrop {
|
|
9942
9504
|
position: fixed;
|
|
9943
9505
|
top: 0;
|
|
9944
9506
|
left: 0;
|
|
9945
9507
|
right: 0;
|
|
9946
9508
|
bottom: 0;
|
|
9947
|
-
background: rgba(0, 0, 0, 0.
|
|
9509
|
+
background: rgba(0, 0, 0, 0.1);
|
|
9948
9510
|
opacity: 0;
|
|
9949
9511
|
transition: opacity 0.3s ease;
|
|
9950
9512
|
pointer-events: none;
|
|
9951
|
-
z-index: 999998;
|
|
9952
|
-
}
|
|
9953
|
-
|
|
9954
|
-
.changelog-list-modal-backdrop.show {
|
|
9955
|
-
opacity: 1;
|
|
9956
|
-
pointer-events: auto;
|
|
9957
|
-
}
|
|
9958
|
-
|
|
9959
|
-
.changelog-list-modal {
|
|
9960
|
-
position: fixed;
|
|
9961
|
-
top: 0;
|
|
9962
|
-
left: 0;
|
|
9963
|
-
right: 0;
|
|
9964
|
-
bottom: 0;
|
|
9965
9513
|
z-index: 999999;
|
|
9966
|
-
|
|
9967
|
-
align-items: center;
|
|
9968
|
-
justify-content: center;
|
|
9969
|
-
padding: 20px;
|
|
9970
|
-
pointer-events: none;
|
|
9971
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
9514
|
+
animation: fadeIn 0.3s ease;
|
|
9972
9515
|
}
|
|
9973
9516
|
|
|
9974
|
-
.
|
|
9517
|
+
.feedback-panel-backdrop.show {
|
|
9518
|
+
opacity: 1;
|
|
9975
9519
|
pointer-events: auto;
|
|
9976
9520
|
}
|
|
9977
9521
|
|
|
9978
|
-
.
|
|
9979
|
-
position: relative;
|
|
9980
|
-
width: 100%;
|
|
9981
|
-
max-width: 460px;
|
|
9982
|
-
max-height: 85vh;
|
|
9522
|
+
.feedback-panel-content {
|
|
9983
9523
|
background: white;
|
|
9984
|
-
|
|
9985
|
-
overflow: hidden;
|
|
9986
|
-
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
9987
|
-
transform: scale(0.9) translateY(20px);
|
|
9988
|
-
opacity: 0;
|
|
9989
|
-
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
9524
|
+
height: 100%;
|
|
9990
9525
|
display: flex;
|
|
9991
9526
|
flex-direction: column;
|
|
9527
|
+
border-radius: 16px;
|
|
9528
|
+
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1),
|
|
9529
|
+
0 10px 10px -5px rgba(0, 0, 0, 0.04),
|
|
9530
|
+
0 0 0 1px rgba(0, 0, 0, 0.05);
|
|
9992
9531
|
}
|
|
9993
9532
|
|
|
9994
|
-
.
|
|
9995
|
-
transform: scale(1) translateY(0);
|
|
9996
|
-
opacity: 1;
|
|
9997
|
-
}
|
|
9998
|
-
|
|
9999
|
-
.changelog-list-modal.theme-dark .changelog-list-modal-container {
|
|
9533
|
+
.feedback-panel.theme-dark .feedback-panel-content {
|
|
10000
9534
|
background: #1F2937;
|
|
10001
9535
|
color: white;
|
|
10002
9536
|
}
|
|
10003
9537
|
|
|
10004
|
-
.
|
|
9538
|
+
.feedback-panel-header {
|
|
10005
9539
|
display: flex;
|
|
10006
9540
|
align-items: center;
|
|
10007
9541
|
justify-content: space-between;
|
|
10008
|
-
padding:
|
|
9542
|
+
padding: 24px;
|
|
10009
9543
|
border-bottom: 1px solid #E5E7EB;
|
|
10010
9544
|
flex-shrink: 0;
|
|
10011
|
-
background: white;
|
|
10012
9545
|
}
|
|
10013
9546
|
|
|
10014
|
-
.
|
|
9547
|
+
.feedback-panel.theme-dark .feedback-panel-header {
|
|
10015
9548
|
border-bottom-color: #374151;
|
|
10016
|
-
background: #1F2937;
|
|
10017
9549
|
}
|
|
10018
9550
|
|
|
10019
|
-
.
|
|
9551
|
+
.feedback-panel-header h3 {
|
|
10020
9552
|
margin: 0;
|
|
10021
|
-
font-size:
|
|
9553
|
+
font-size: 18px;
|
|
10022
9554
|
font-weight: 600;
|
|
10023
9555
|
color: #111827;
|
|
10024
9556
|
}
|
|
10025
9557
|
|
|
10026
|
-
.
|
|
9558
|
+
.feedback-panel.theme-dark .feedback-panel-header h3 {
|
|
10027
9559
|
color: white;
|
|
10028
9560
|
}
|
|
10029
9561
|
|
|
10030
|
-
.
|
|
9562
|
+
.feedback-panel-close {
|
|
10031
9563
|
background: none;
|
|
10032
9564
|
border: none;
|
|
10033
|
-
font-size:
|
|
9565
|
+
font-size: 24px;
|
|
10034
9566
|
cursor: pointer;
|
|
10035
9567
|
color: #6B7280;
|
|
10036
9568
|
padding: 4px;
|
|
10037
|
-
width:
|
|
10038
|
-
height:
|
|
9569
|
+
width: 32px;
|
|
9570
|
+
height: 32px;
|
|
10039
9571
|
display: flex;
|
|
10040
9572
|
align-items: center;
|
|
10041
9573
|
justify-content: center;
|
|
10042
9574
|
border-radius: 6px;
|
|
10043
9575
|
transition: all 0.2s ease;
|
|
10044
|
-
line-height: 1;
|
|
10045
9576
|
}
|
|
10046
9577
|
|
|
10047
|
-
.
|
|
9578
|
+
.feedback-panel-close:hover {
|
|
10048
9579
|
background: #F3F4F6;
|
|
10049
9580
|
color: #111827;
|
|
10050
9581
|
}
|
|
10051
9582
|
|
|
10052
|
-
.
|
|
9583
|
+
.feedback-panel-close:focus-visible {
|
|
9584
|
+
outline: 2px solid #155EEF;
|
|
9585
|
+
outline-offset: 2px;
|
|
9586
|
+
}
|
|
9587
|
+
|
|
9588
|
+
.feedback-panel.theme-dark .feedback-panel-close {
|
|
10053
9589
|
color: #9CA3AF;
|
|
10054
9590
|
}
|
|
10055
9591
|
|
|
10056
|
-
.
|
|
9592
|
+
.feedback-panel.theme-dark .feedback-panel-close:hover {
|
|
10057
9593
|
background: #374151;
|
|
10058
9594
|
color: white;
|
|
10059
9595
|
}
|
|
10060
9596
|
|
|
10061
|
-
.
|
|
9597
|
+
.feedback-panel-body {
|
|
10062
9598
|
flex: 1;
|
|
10063
9599
|
overflow-y: auto;
|
|
9600
|
+
padding: 24px;
|
|
10064
9601
|
}
|
|
10065
9602
|
|
|
10066
|
-
|
|
10067
|
-
.changelog-list {
|
|
9603
|
+
.feedback-form {
|
|
10068
9604
|
display: flex;
|
|
10069
9605
|
flex-direction: column;
|
|
9606
|
+
height: 100%;
|
|
10070
9607
|
}
|
|
10071
9608
|
|
|
10072
|
-
.
|
|
9609
|
+
.feedback-form-group {
|
|
10073
9610
|
display: flex;
|
|
10074
|
-
flex-direction:
|
|
10075
|
-
|
|
10076
|
-
|
|
10077
|
-
border-bottom: 1px solid #E5E7EB;
|
|
10078
|
-
cursor: pointer;
|
|
10079
|
-
transition: background-color 0.2s ease;
|
|
10080
|
-
position: relative;
|
|
9611
|
+
flex-direction: column;
|
|
9612
|
+
gap: 8px;
|
|
9613
|
+
margin-bottom: 20px;
|
|
10081
9614
|
}
|
|
10082
9615
|
|
|
10083
|
-
.
|
|
10084
|
-
|
|
9616
|
+
.feedback-form-group:last-child {
|
|
9617
|
+
margin-bottom: 0;
|
|
10085
9618
|
}
|
|
10086
9619
|
|
|
10087
|
-
.
|
|
10088
|
-
|
|
9620
|
+
.feedback-form-group label {
|
|
9621
|
+
font-size: 14px;
|
|
9622
|
+
font-weight: 500;
|
|
9623
|
+
line-height: 1.25;
|
|
9624
|
+
color: #374151;
|
|
10089
9625
|
}
|
|
10090
9626
|
|
|
10091
|
-
.
|
|
10092
|
-
|
|
9627
|
+
.feedback-panel.theme-dark .feedback-form-group label {
|
|
9628
|
+
color: #D1D5DB;
|
|
10093
9629
|
}
|
|
10094
9630
|
|
|
10095
|
-
.
|
|
10096
|
-
|
|
9631
|
+
.feedback-form-group input {
|
|
9632
|
+
height: 44px;
|
|
9633
|
+
width: 100%;
|
|
9634
|
+
border-radius: 8px;
|
|
9635
|
+
border: 1px solid #D1D5DB;
|
|
9636
|
+
padding: 10px 14px;
|
|
9637
|
+
font-size: 15px;
|
|
9638
|
+
font-weight: 400;
|
|
9639
|
+
line-height: 1.5;
|
|
9640
|
+
color: #1F2937;
|
|
9641
|
+
font-family: inherit;
|
|
9642
|
+
outline: none;
|
|
9643
|
+
transition: all 0.2s ease;
|
|
10097
9644
|
}
|
|
10098
9645
|
|
|
10099
|
-
.
|
|
9646
|
+
.feedback-form-group input::placeholder {
|
|
9647
|
+
font-size: 15px;
|
|
9648
|
+
color: #9CA3AF;
|
|
9649
|
+
}
|
|
9650
|
+
|
|
9651
|
+
.feedback-form-group input:focus {
|
|
9652
|
+
border-color: #155EEF;
|
|
9653
|
+
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
|
|
9654
|
+
}
|
|
9655
|
+
|
|
9656
|
+
.feedback-form-group input:focus-visible {
|
|
9657
|
+
outline: none;
|
|
9658
|
+
}
|
|
9659
|
+
|
|
9660
|
+
.feedback-form-group textarea {
|
|
9661
|
+
min-height: 200px;
|
|
10100
9662
|
width: 100%;
|
|
10101
|
-
|
|
10102
|
-
border-radius:
|
|
9663
|
+
resize: vertical;
|
|
9664
|
+
border-radius: 8px;
|
|
9665
|
+
border: 1px solid #D1D5DB;
|
|
9666
|
+
padding: 10px 14px;
|
|
9667
|
+
font-size: 15px;
|
|
9668
|
+
font-weight: 400;
|
|
9669
|
+
line-height: 1.5;
|
|
9670
|
+
color: #1F2937;
|
|
9671
|
+
font-family: inherit;
|
|
9672
|
+
outline: none;
|
|
9673
|
+
transition: all 0.2s ease;
|
|
9674
|
+
}
|
|
9675
|
+
|
|
9676
|
+
.feedback-form-group textarea::placeholder {
|
|
9677
|
+
font-size: 15px;
|
|
9678
|
+
color: #9CA3AF;
|
|
9679
|
+
}
|
|
9680
|
+
|
|
9681
|
+
.feedback-form-group textarea:focus {
|
|
9682
|
+
border-color: #155EEF;
|
|
9683
|
+
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
|
|
9684
|
+
}
|
|
9685
|
+
|
|
9686
|
+
.feedback-form-group textarea:focus-visible {
|
|
9687
|
+
outline: none;
|
|
9688
|
+
}
|
|
9689
|
+
|
|
9690
|
+
.feedback-panel.theme-dark .feedback-form-group input,
|
|
9691
|
+
.feedback-panel.theme-dark .feedback-form-group textarea {
|
|
9692
|
+
background: #374151;
|
|
9693
|
+
border-color: #4B5563;
|
|
9694
|
+
color: white;
|
|
9695
|
+
}
|
|
9696
|
+
|
|
9697
|
+
.feedback-panel.theme-dark .feedback-form-group input::placeholder,
|
|
9698
|
+
.feedback-panel.theme-dark .feedback-form-group textarea::placeholder {
|
|
9699
|
+
color: #6B7280;
|
|
9700
|
+
}
|
|
9701
|
+
|
|
9702
|
+
.feedback-btn {
|
|
9703
|
+
position: relative;
|
|
9704
|
+
display: inline-flex;
|
|
9705
|
+
align-items: center;
|
|
9706
|
+
justify-content: center;
|
|
10103
9707
|
overflow: hidden;
|
|
10104
|
-
border:
|
|
9708
|
+
border-radius: 8px;
|
|
9709
|
+
border: none;
|
|
9710
|
+
height: 44px;
|
|
9711
|
+
padding: 10px 18px;
|
|
9712
|
+
font-size: 15px;
|
|
9713
|
+
font-weight: 500;
|
|
9714
|
+
font-family: inherit;
|
|
9715
|
+
cursor: pointer;
|
|
9716
|
+
transition: all 0.2s ease;
|
|
10105
9717
|
}
|
|
10106
9718
|
|
|
10107
|
-
.
|
|
9719
|
+
.feedback-btn:disabled {
|
|
9720
|
+
opacity: 0.6;
|
|
9721
|
+
cursor: not-allowed;
|
|
9722
|
+
}
|
|
9723
|
+
|
|
9724
|
+
.feedback-btn:focus-visible {
|
|
9725
|
+
outline: 2px solid #155EEF;
|
|
9726
|
+
outline-offset: 2px;
|
|
9727
|
+
}
|
|
9728
|
+
|
|
9729
|
+
.feedback-btn-submit {
|
|
9730
|
+
background: #155EEF;
|
|
9731
|
+
color: white;
|
|
10108
9732
|
width: 100%;
|
|
10109
|
-
height: 100px;
|
|
10110
|
-
display: block;
|
|
10111
|
-
object-fit: cover;
|
|
10112
9733
|
}
|
|
10113
9734
|
|
|
10114
|
-
.
|
|
10115
|
-
|
|
10116
|
-
|
|
9735
|
+
.feedback-btn-submit:hover:not(:disabled) {
|
|
9736
|
+
background: #4338ca;
|
|
9737
|
+
}
|
|
9738
|
+
|
|
9739
|
+
.feedback-btn-submit:active:not(:disabled) {
|
|
9740
|
+
background: #3730a3;
|
|
10117
9741
|
}
|
|
10118
9742
|
|
|
10119
|
-
.
|
|
10120
|
-
|
|
10121
|
-
|
|
10122
|
-
|
|
9743
|
+
.feedback-btn-cancel {
|
|
9744
|
+
background: transparent;
|
|
9745
|
+
color: #6B7280;
|
|
9746
|
+
border: 1px solid #D1D5DB;
|
|
10123
9747
|
}
|
|
10124
9748
|
|
|
10125
|
-
.
|
|
10126
|
-
|
|
10127
|
-
color: #
|
|
10128
|
-
|
|
9749
|
+
.feedback-btn-cancel:hover:not(:disabled) {
|
|
9750
|
+
background: #F9FAFB;
|
|
9751
|
+
border-color: #9CA3AF;
|
|
9752
|
+
color: #374151;
|
|
10129
9753
|
}
|
|
10130
9754
|
|
|
10131
|
-
.
|
|
10132
|
-
color: #
|
|
9755
|
+
.feedback-panel.theme-dark .feedback-btn-cancel {
|
|
9756
|
+
color: #D1D5DB;
|
|
9757
|
+
border-color: #4B5563;
|
|
10133
9758
|
}
|
|
10134
9759
|
|
|
10135
|
-
.
|
|
9760
|
+
.feedback-panel.theme-dark .feedback-btn-cancel:hover:not(:disabled) {
|
|
9761
|
+
background: #374151;
|
|
9762
|
+
}
|
|
9763
|
+
|
|
9764
|
+
.feedback-form-actions {
|
|
10136
9765
|
display: flex;
|
|
10137
|
-
flex-
|
|
10138
|
-
gap:
|
|
10139
|
-
margin-
|
|
9766
|
+
flex-direction: column;
|
|
9767
|
+
gap: 12px;
|
|
9768
|
+
margin-top: auto;
|
|
9769
|
+
padding-top: 24px;
|
|
10140
9770
|
}
|
|
10141
9771
|
|
|
10142
|
-
.
|
|
10143
|
-
|
|
9772
|
+
.feedback-error {
|
|
9773
|
+
color: #DC2626;
|
|
10144
9774
|
font-size: 14px;
|
|
10145
|
-
font-weight:
|
|
10146
|
-
|
|
10147
|
-
|
|
9775
|
+
font-weight: 400;
|
|
9776
|
+
margin-top: 8px;
|
|
9777
|
+
padding: 12px;
|
|
9778
|
+
background: #FEE2E2;
|
|
9779
|
+
border: 1px solid #FECACA;
|
|
9780
|
+
border-radius: 8px;
|
|
9781
|
+
display: none;
|
|
10148
9782
|
}
|
|
10149
9783
|
|
|
10150
|
-
.
|
|
10151
|
-
|
|
9784
|
+
.feedback-error.show {
|
|
9785
|
+
display: block;
|
|
10152
9786
|
}
|
|
10153
9787
|
|
|
10154
|
-
.
|
|
10155
|
-
|
|
10156
|
-
|
|
10157
|
-
|
|
10158
|
-
color: #6B7280;
|
|
10159
|
-
display: -webkit-box;
|
|
10160
|
-
-webkit-line-clamp: 2;
|
|
10161
|
-
-webkit-box-orient: vertical;
|
|
10162
|
-
overflow: hidden;
|
|
9788
|
+
.feedback-panel.theme-dark .feedback-error {
|
|
9789
|
+
background: #7F1D1D;
|
|
9790
|
+
border-color: #991B1B;
|
|
9791
|
+
color: #FCA5A5;
|
|
10163
9792
|
}
|
|
10164
9793
|
|
|
10165
|
-
|
|
10166
|
-
|
|
9794
|
+
/* ==================== SUCCESS NOTIFICATION ==================== */
|
|
9795
|
+
.feedback-success-notification {
|
|
9796
|
+
position: fixed;
|
|
9797
|
+
top: 24px;
|
|
9798
|
+
right: 24px;
|
|
9799
|
+
z-index: 1000002;
|
|
9800
|
+
background: white;
|
|
9801
|
+
border: 1px solid #D1FAE5;
|
|
9802
|
+
border-radius: 12px;
|
|
9803
|
+
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
9804
|
+
animation: slideInRight 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
9805
|
+
min-width: 320px;
|
|
10167
9806
|
}
|
|
10168
9807
|
|
|
10169
|
-
.
|
|
9808
|
+
.feedback-success-content {
|
|
9809
|
+
display: flex;
|
|
9810
|
+
align-items: center;
|
|
9811
|
+
padding: 16px 20px;
|
|
9812
|
+
gap: 12px;
|
|
9813
|
+
}
|
|
9814
|
+
|
|
9815
|
+
.feedback-success-icon {
|
|
9816
|
+
width: 20px;
|
|
9817
|
+
height: 20px;
|
|
9818
|
+
border-radius: 50%;
|
|
9819
|
+
background: #10B981;
|
|
9820
|
+
color: white;
|
|
9821
|
+
display: flex;
|
|
9822
|
+
align-items: center;
|
|
9823
|
+
justify-content: center;
|
|
9824
|
+
font-size: 12px;
|
|
9825
|
+
font-weight: 600;
|
|
10170
9826
|
flex-shrink: 0;
|
|
10171
|
-
margin-left: 12px;
|
|
10172
|
-
color: #9CA3AF;
|
|
10173
|
-
transition: all 0.2s ease;
|
|
10174
9827
|
}
|
|
10175
9828
|
|
|
10176
|
-
.
|
|
10177
|
-
color: #
|
|
10178
|
-
|
|
9829
|
+
.feedback-success-content span {
|
|
9830
|
+
color: #065F46;
|
|
9831
|
+
font-weight: 500;
|
|
9832
|
+
font-size: 14px;
|
|
9833
|
+
flex: 1;
|
|
10179
9834
|
}
|
|
10180
9835
|
|
|
10181
|
-
.
|
|
9836
|
+
.feedback-success-close {
|
|
9837
|
+
background: none;
|
|
9838
|
+
border: none;
|
|
10182
9839
|
color: #6B7280;
|
|
9840
|
+
cursor: pointer;
|
|
9841
|
+
font-size: 20px;
|
|
9842
|
+
padding: 0;
|
|
9843
|
+
width: 24px;
|
|
9844
|
+
height: 24px;
|
|
9845
|
+
display: flex;
|
|
9846
|
+
align-items: center;
|
|
9847
|
+
justify-content: center;
|
|
9848
|
+
transition: all 0.2s ease;
|
|
9849
|
+
border-radius: 4px;
|
|
9850
|
+
flex-shrink: 0;
|
|
10183
9851
|
}
|
|
10184
9852
|
|
|
10185
|
-
.
|
|
10186
|
-
|
|
9853
|
+
.feedback-success-close:hover {
|
|
9854
|
+
background: #F3F4F6;
|
|
9855
|
+
color: #374151;
|
|
10187
9856
|
}
|
|
10188
9857
|
|
|
10189
|
-
|
|
10190
|
-
|
|
10191
|
-
|
|
10192
|
-
|
|
10193
|
-
}
|
|
10194
|
-
|
|
10195
|
-
.changelog-modal-container {
|
|
10196
|
-
max-width: 100%;
|
|
10197
|
-
border-radius: 20px;
|
|
10198
|
-
}
|
|
9858
|
+
.feedback-success-close:focus-visible {
|
|
9859
|
+
outline: 2px solid #155EEF;
|
|
9860
|
+
outline-offset: 2px;
|
|
9861
|
+
}
|
|
10199
9862
|
|
|
10200
|
-
|
|
9863
|
+
@media (max-width: 768px) {
|
|
9864
|
+
.feedback-widget-button {
|
|
10201
9865
|
bottom: 16px;
|
|
10202
9866
|
right: 16px;
|
|
10203
9867
|
}
|
|
10204
|
-
|
|
10205
|
-
.
|
|
9868
|
+
|
|
9869
|
+
.feedback-widget-button.position-bottom-left {
|
|
10206
9870
|
left: 16px;
|
|
10207
9871
|
}
|
|
10208
|
-
|
|
10209
|
-
.
|
|
10210
|
-
|
|
10211
|
-
|
|
10212
|
-
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
}
|
|
10216
|
-
|
|
10217
|
-
.changelog-popup-title {
|
|
10218
|
-
font-size: 22px;
|
|
9872
|
+
|
|
9873
|
+
.feedback-minimize-icon,
|
|
9874
|
+
.feedback-expand-icon {
|
|
9875
|
+
top: -4px;
|
|
9876
|
+
right: -4px;
|
|
9877
|
+
width: 20px;
|
|
9878
|
+
height: 20px;
|
|
10219
9879
|
}
|
|
10220
|
-
|
|
10221
|
-
.
|
|
10222
|
-
|
|
9880
|
+
|
|
9881
|
+
.feedback-minimize-icon svg,
|
|
9882
|
+
.feedback-expand-icon svg {
|
|
9883
|
+
width: 14px;
|
|
9884
|
+
height: 14px;
|
|
10223
9885
|
}
|
|
10224
9886
|
|
|
10225
|
-
.
|
|
10226
|
-
padding: 12px 28px;
|
|
10227
|
-
font-size: 15px;
|
|
9887
|
+
.feedback-panel {
|
|
10228
9888
|
width: 100%;
|
|
9889
|
+
top: auto;
|
|
9890
|
+
bottom: 0;
|
|
9891
|
+
right: 0;
|
|
9892
|
+
left: 0;
|
|
9893
|
+
height: 85vh;
|
|
9894
|
+
max-height: 85vh;
|
|
9895
|
+
transform: translateY(100%);
|
|
9896
|
+
border-radius: 20px 20px 0 0;
|
|
10229
9897
|
}
|
|
10230
|
-
|
|
10231
|
-
.
|
|
10232
|
-
|
|
9898
|
+
|
|
9899
|
+
.feedback-panel.open {
|
|
9900
|
+
transform: translateY(0);
|
|
10233
9901
|
}
|
|
10234
|
-
|
|
10235
|
-
|
|
10236
|
-
|
|
10237
|
-
padding: 16px;
|
|
9902
|
+
|
|
9903
|
+
.feedback-panel-content {
|
|
9904
|
+
border-radius: 20px 20px 0 0;
|
|
10238
9905
|
}
|
|
10239
|
-
|
|
10240
|
-
.
|
|
10241
|
-
|
|
10242
|
-
|
|
10243
|
-
border-radius: 16px;
|
|
9906
|
+
|
|
9907
|
+
.feedback-panel-header {
|
|
9908
|
+
padding: 20px;
|
|
9909
|
+
position: relative;
|
|
10244
9910
|
}
|
|
10245
|
-
|
|
10246
|
-
.
|
|
10247
|
-
|
|
9911
|
+
|
|
9912
|
+
.feedback-panel-header::before {
|
|
9913
|
+
content: '';
|
|
9914
|
+
position: absolute;
|
|
9915
|
+
top: 8px;
|
|
9916
|
+
left: 50%;
|
|
9917
|
+
transform: translateX(-50%);
|
|
9918
|
+
width: 40px;
|
|
9919
|
+
height: 4px;
|
|
9920
|
+
background: #D1D5DB;
|
|
9921
|
+
border-radius: 2px;
|
|
10248
9922
|
}
|
|
10249
|
-
|
|
10250
|
-
.
|
|
10251
|
-
|
|
9923
|
+
|
|
9924
|
+
.feedback-panel.theme-dark .feedback-panel-header::before {
|
|
9925
|
+
background: #4B5563;
|
|
10252
9926
|
}
|
|
10253
|
-
|
|
10254
|
-
.
|
|
10255
|
-
|
|
9927
|
+
|
|
9928
|
+
.feedback-panel-body {
|
|
9929
|
+
padding: 20px;
|
|
10256
9930
|
}
|
|
10257
|
-
|
|
10258
|
-
.
|
|
10259
|
-
|
|
9931
|
+
|
|
9932
|
+
.feedback-form-group textarea {
|
|
9933
|
+
min-height: 150px;
|
|
10260
9934
|
}
|
|
10261
|
-
}
|
|
10262
9935
|
|
|
10263
|
-
|
|
10264
|
-
|
|
10265
|
-
|
|
10266
|
-
|
|
10267
|
-
|
|
10268
|
-
.changelog-list-modal-container,
|
|
10269
|
-
.changelog-list-modal-backdrop,
|
|
10270
|
-
.changelog-trigger-btn,
|
|
10271
|
-
.changelog-popup-btn,
|
|
10272
|
-
.changelog-view-all-btn,
|
|
10273
|
-
.changelog-loading-spinner,
|
|
10274
|
-
.changelog-dot,
|
|
10275
|
-
.changelog-list-item,
|
|
10276
|
-
.changelog-list-item-arrow {
|
|
10277
|
-
transition: none;
|
|
10278
|
-
animation: none;
|
|
9936
|
+
.feedback-success-notification {
|
|
9937
|
+
top: 16px;
|
|
9938
|
+
right: 16px;
|
|
9939
|
+
left: 16px;
|
|
9940
|
+
min-width: auto;
|
|
10279
9941
|
}
|
|
10280
9942
|
}
|
|
10281
9943
|
`;
|
|
10282
9944
|
|
|
9945
|
+
const CSS_STYLES = baseStyles + feedbackStyles + changelogStyles;
|
|
9946
|
+
|
|
10283
9947
|
function injectStyles() {
|
|
10284
9948
|
if (
|
|
10285
9949
|
typeof document !== 'undefined' &&
|