@product7/feedback-sdk 1.6.3 → 1.6.5
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 +94 -14
- 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/core/FeedbackSDK.js +82 -12
- package/src/widgets/ButtonWidget.js +8 -1
- package/src/widgets/MessengerWidget.js +2 -0
- package/src/widgets/messenger/MessengerState.js +1 -0
- package/src/widgets/messenger/views/HomeView.js +1 -1
- package/types/index.d.ts +45 -3
package/package.json
CHANGED
package/src/core/FeedbackSDK.js
CHANGED
|
@@ -63,12 +63,15 @@ export class FeedbackSDK {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
const widgetId = generateId('widget');
|
|
66
|
+
const widgetConfig = this._getWidgetTypeConfig(type);
|
|
67
|
+
const explicitOptions = this._omitUndefined(options);
|
|
66
68
|
const widgetOptions = {
|
|
67
69
|
id: widgetId,
|
|
68
70
|
sdk: this,
|
|
69
71
|
apiService: this.apiService,
|
|
70
72
|
...this.config,
|
|
71
|
-
...
|
|
73
|
+
...widgetConfig,
|
|
74
|
+
...explicitOptions,
|
|
72
75
|
};
|
|
73
76
|
|
|
74
77
|
try {
|
|
@@ -180,13 +183,22 @@ export class FeedbackSDK {
|
|
|
180
183
|
}
|
|
181
184
|
|
|
182
185
|
const normalizedOptions = this._normalizeSurveyConfig(options);
|
|
186
|
+
const surveyConfigDefaults = this._getWidgetTypeConfig('survey');
|
|
183
187
|
|
|
184
188
|
const surveyWidget = this.createWidget('survey', {
|
|
185
189
|
surveyId: normalizedOptions.surveyId,
|
|
186
190
|
surveyType:
|
|
187
191
|
normalizedOptions.surveyType || normalizedOptions.type || 'nps',
|
|
188
|
-
position:
|
|
189
|
-
|
|
192
|
+
position:
|
|
193
|
+
normalizedOptions.position ??
|
|
194
|
+
surveyConfigDefaults.position ??
|
|
195
|
+
this.config.position ??
|
|
196
|
+
'bottom-right',
|
|
197
|
+
theme:
|
|
198
|
+
normalizedOptions.theme ??
|
|
199
|
+
surveyConfigDefaults.theme ??
|
|
200
|
+
this.config.theme ??
|
|
201
|
+
'light',
|
|
190
202
|
title: normalizedOptions.title,
|
|
191
203
|
description: normalizedOptions.description,
|
|
192
204
|
lowLabel: normalizedOptions.lowLabel,
|
|
@@ -389,6 +401,58 @@ export class FeedbackSDK {
|
|
|
389
401
|
return null;
|
|
390
402
|
}
|
|
391
403
|
|
|
404
|
+
_getWidgetTypeConfig(type) {
|
|
405
|
+
const widgetsConfig = this._isPlainObject(this.config?.widgets)
|
|
406
|
+
? this.config.widgets
|
|
407
|
+
: {};
|
|
408
|
+
|
|
409
|
+
const legacyTypeConfig = this._isPlainObject(this.config?.[type])
|
|
410
|
+
? this.config[type]
|
|
411
|
+
: {};
|
|
412
|
+
|
|
413
|
+
const namespacedTypeConfig = this._isPlainObject(widgetsConfig?.[type])
|
|
414
|
+
? widgetsConfig[type]
|
|
415
|
+
: {};
|
|
416
|
+
|
|
417
|
+
const mergedTypeConfig = deepMerge(legacyTypeConfig, namespacedTypeConfig);
|
|
418
|
+
return this._toCamelCaseObject(mergedTypeConfig);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
_isPlainObject(value) {
|
|
422
|
+
return Object.prototype.toString.call(value) === '[object Object]';
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
_toCamelCaseKey(key) {
|
|
426
|
+
return key.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
_toCamelCaseObject(value) {
|
|
430
|
+
if (Array.isArray(value)) {
|
|
431
|
+
return value.map((item) => this._toCamelCaseObject(item));
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
if (!this._isPlainObject(value)) {
|
|
435
|
+
return value;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
const normalized = {};
|
|
439
|
+
for (const [key, nestedValue] of Object.entries(value)) {
|
|
440
|
+
normalized[this._toCamelCaseKey(key)] =
|
|
441
|
+
this._toCamelCaseObject(nestedValue);
|
|
442
|
+
}
|
|
443
|
+
return normalized;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
_omitUndefined(value) {
|
|
447
|
+
if (!this._isPlainObject(value)) {
|
|
448
|
+
return value;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
return Object.fromEntries(
|
|
452
|
+
Object.entries(value).filter(([, nestedValue]) => nestedValue !== undefined)
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
|
|
392
456
|
showChangelog(options = {}) {
|
|
393
457
|
if (!this.initialized) {
|
|
394
458
|
throw new SDKError(
|
|
@@ -396,16 +460,22 @@ export class FeedbackSDK {
|
|
|
396
460
|
);
|
|
397
461
|
}
|
|
398
462
|
|
|
463
|
+
const defaults = {
|
|
464
|
+
position: this.config.position || 'bottom-right',
|
|
465
|
+
theme: this.config.theme || 'light',
|
|
466
|
+
title: "What's New",
|
|
467
|
+
triggerText: "What's New",
|
|
468
|
+
showBadge: true,
|
|
469
|
+
viewButtonText: 'View Update',
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
const configDefaults = this._getWidgetTypeConfig('changelog');
|
|
473
|
+
const explicitOptions = this._omitUndefined(options);
|
|
474
|
+
|
|
399
475
|
const changelogWidget = this.createWidget('changelog', {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
triggerText: options.triggerText || "What's New",
|
|
404
|
-
showBadge: options.showBadge !== false,
|
|
405
|
-
viewButtonText: options.viewButtonText || 'View Update',
|
|
406
|
-
changelogBaseUrl: options.changelogBaseUrl,
|
|
407
|
-
openInNewTab: options.openInNewTab,
|
|
408
|
-
onViewUpdate: options.onViewUpdate,
|
|
476
|
+
...defaults,
|
|
477
|
+
...configDefaults,
|
|
478
|
+
...explicitOptions,
|
|
409
479
|
});
|
|
410
480
|
|
|
411
481
|
changelogWidget.mount();
|
|
@@ -8,6 +8,13 @@ export class ButtonWidget extends BaseWidget {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
_render() {
|
|
11
|
+
const buttonText =
|
|
12
|
+
this.options.buttonText ||
|
|
13
|
+
this.options.triggerText ||
|
|
14
|
+
this.options.label ||
|
|
15
|
+
this.options.text ||
|
|
16
|
+
'Feedback';
|
|
17
|
+
|
|
11
18
|
const button = document.createElement('div');
|
|
12
19
|
button.className = `feedback-widget-button position-${this.options.position}`;
|
|
13
20
|
button.innerHTML = `
|
|
@@ -15,7 +22,7 @@ export class ButtonWidget extends BaseWidget {
|
|
|
15
22
|
<svg class="feedback-icon" width="20" height="20" viewBox="0 0 256 256" fill="currentColor">
|
|
16
23
|
<path d="M216,80H184V48a16,16,0,0,0-16-16H40A16,16,0,0,0,24,48V176a8,8,0,0,0,13,6.22L72,154V184a16,16,0,0,0,16,16h93.59L219,230.22a8,8,0,0,0,5,1.78,8,8,0,0,0,8-8V96A16,16,0,0,0,216,80ZM66.55,137.78,40,159.25V48H168v88H71.58A8,8,0,0,0,66.55,137.78ZM216,207.25l-26.55-21.47a8,8,0,0,0-5-1.78H88V152h80a16,16,0,0,0,16-16V96h32Z"/>
|
|
17
24
|
</svg>
|
|
18
|
-
<span class="feedback-text"
|
|
25
|
+
<span class="feedback-text">${buttonText}</span>
|
|
19
26
|
|
|
20
27
|
<div class="feedback-minimize-icon">
|
|
21
28
|
<svg viewBox="0 0 256 256">
|
|
@@ -27,6 +27,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
27
27
|
logoUrl: options.logoUrl || 'https://product7.io/p7logo.svg',
|
|
28
28
|
teamName: options.teamName || 'Support',
|
|
29
29
|
teamAvatars: options.teamAvatars || [],
|
|
30
|
+
greetingMessage: options.greetingMessage || 'Hi there 👋',
|
|
30
31
|
welcomeMessage: options.welcomeMessage || 'How can we help?',
|
|
31
32
|
enableHelp: options.enableHelp !== false,
|
|
32
33
|
enableChangelog: options.enableChangelog !== false,
|
|
@@ -44,6 +45,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
44
45
|
this.messengerState = new MessengerState({
|
|
45
46
|
teamName: this.messengerOptions.teamName,
|
|
46
47
|
teamAvatars: this.messengerOptions.teamAvatars,
|
|
48
|
+
greetingMessage: this.messengerOptions.greetingMessage,
|
|
47
49
|
welcomeMessage: this.messengerOptions.welcomeMessage,
|
|
48
50
|
enableHelp: this.messengerOptions.enableHelp,
|
|
49
51
|
enableChangelog: this.messengerOptions.enableChangelog,
|
|
@@ -16,6 +16,7 @@ export class MessengerState {
|
|
|
16
16
|
|
|
17
17
|
this.teamName = options.teamName || 'Support';
|
|
18
18
|
this.teamAvatars = options.teamAvatars || [];
|
|
19
|
+
this.greetingMessage = options.greetingMessage || 'Hi there 👋';
|
|
19
20
|
this.welcomeMessage = options.welcomeMessage || 'How can we help?';
|
|
20
21
|
|
|
21
22
|
this.userContext = options.userContext || null;
|
|
@@ -44,7 +44,7 @@ export class HomeView {
|
|
|
44
44
|
</button>
|
|
45
45
|
</div>
|
|
46
46
|
<div class="messenger-home-welcome">
|
|
47
|
-
<span class="messenger-home-greeting"
|
|
47
|
+
<span class="messenger-home-greeting">${this.state.greetingMessage}</span>
|
|
48
48
|
<span class="messenger-home-question">${this.state.welcomeMessage}</span>
|
|
49
49
|
</div>
|
|
50
50
|
</div>
|
package/types/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ declare module '@product7/feedback-sdk' {
|
|
|
8
8
|
theme?: 'light' | 'dark';
|
|
9
9
|
apiUrl?: string;
|
|
10
10
|
autoShow?: boolean;
|
|
11
|
+
widgets?: WidgetConfigMap;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export interface UserContext {
|
|
@@ -22,6 +23,33 @@ declare module '@product7/feedback-sdk' {
|
|
|
22
23
|
};
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
export interface ButtonWidgetOptions {
|
|
27
|
+
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
28
|
+
theme?: 'light' | 'dark';
|
|
29
|
+
boardId?: string;
|
|
30
|
+
displayMode?: 'panel' | 'modal';
|
|
31
|
+
size?: 'small' | 'medium' | 'large';
|
|
32
|
+
primaryColor?: string;
|
|
33
|
+
backgroundColor?: string;
|
|
34
|
+
textColor?: string;
|
|
35
|
+
autoShow?: boolean;
|
|
36
|
+
suppressAfterSubmission?: boolean;
|
|
37
|
+
suppressionDays?: number;
|
|
38
|
+
buttonText?: string;
|
|
39
|
+
triggerText?: string;
|
|
40
|
+
label?: string;
|
|
41
|
+
text?: string;
|
|
42
|
+
customStyles?: Record<string, string>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface WidgetConfigMap {
|
|
46
|
+
button?: Partial<ButtonWidgetOptions> | Record<string, any>;
|
|
47
|
+
survey?: Partial<SurveyWidgetOptions> | Record<string, any>;
|
|
48
|
+
messenger?: Partial<MessengerWidgetOptions> | Record<string, any>;
|
|
49
|
+
changelog?: Partial<ChangelogWidgetOptions> | Record<string, any>;
|
|
50
|
+
[key: string]: Record<string, any> | undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
25
53
|
export interface ButtonWidget {
|
|
26
54
|
id: string;
|
|
27
55
|
type: 'button';
|
|
@@ -29,8 +57,14 @@ declare module '@product7/feedback-sdk' {
|
|
|
29
57
|
destroy(): void;
|
|
30
58
|
show(): this;
|
|
31
59
|
hide(): this;
|
|
60
|
+
openPanel(): void;
|
|
61
|
+
closePanel(): void;
|
|
32
62
|
openModal(): void;
|
|
33
63
|
closeModal(): void;
|
|
64
|
+
updateText(text: string): void;
|
|
65
|
+
updatePosition(
|
|
66
|
+
position: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'
|
|
67
|
+
): void;
|
|
34
68
|
}
|
|
35
69
|
|
|
36
70
|
export class FeedbackSDK {
|
|
@@ -41,10 +75,17 @@ declare module '@product7/feedback-sdk' {
|
|
|
41
75
|
sessionToken?: string;
|
|
42
76
|
expiresIn?: number;
|
|
43
77
|
}>;
|
|
78
|
+
createWidget(type: 'button', options?: ButtonWidgetOptions): ButtonWidget;
|
|
79
|
+
createWidget(type: 'survey', options?: SurveyWidgetOptions): SurveyWidget;
|
|
80
|
+
createWidget(
|
|
81
|
+
type: 'messenger',
|
|
82
|
+
options?: MessengerWidgetOptions
|
|
83
|
+
): MessengerWidget;
|
|
44
84
|
createWidget(
|
|
45
|
-
type: '
|
|
46
|
-
options?:
|
|
47
|
-
):
|
|
85
|
+
type: 'changelog',
|
|
86
|
+
options?: ChangelogWidgetOptions
|
|
87
|
+
): ChangelogWidget;
|
|
88
|
+
createWidget(type: string, options?: Record<string, any>): any;
|
|
48
89
|
setUserContext(userContext: UserContext): void;
|
|
49
90
|
getUserContext(): UserContext | null;
|
|
50
91
|
destroy(): void;
|
|
@@ -213,6 +254,7 @@ declare module '@product7/feedback-sdk' {
|
|
|
213
254
|
theme?: 'light' | 'dark';
|
|
214
255
|
teamName?: string;
|
|
215
256
|
teamAvatars?: string[];
|
|
257
|
+
greetingMessage?: string;
|
|
216
258
|
welcomeMessage?: string;
|
|
217
259
|
enableHelp?: boolean;
|
|
218
260
|
enableChangelog?: boolean;
|