@product7/feedback-sdk 1.6.4 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@product7/feedback-sdk",
3
- "version": "1.6.4",
3
+ "version": "1.6.5",
4
4
  "description": "JavaScript SDK for integrating Product7 feedback widgets into any website",
5
5
  "main": "dist/feedback-sdk.js",
6
6
  "module": "src/index.js",
@@ -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
- ...options,
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: normalizedOptions.position || 'bottom-right',
189
- theme: normalizedOptions.theme || this.config.theme || 'light',
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
- position: options.position || 'bottom-right',
401
- theme: options.theme || this.config.theme || 'light',
402
- title: options.title || "What's New",
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">Feedback</span>
25
+ <span class="feedback-text">${buttonText}</span>
19
26
 
20
27
  <div class="feedback-minimize-icon">
21
28
  <svg viewBox="0 0 256 256">
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: 'button',
46
- options?: Partial<FeedbackConfig>
47
- ): ButtonWidget;
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;