releasebird-javascript-sdk 1.0.87 → 1.0.89
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/build/index.js +1 -1
- package/package.json +3 -2
- package/published/1.0.87/index.js +1 -1
- package/published/1.0.88/index.js +1 -0
- package/published/1.0.89/index.js +1 -0
- package/published/latest/index.js +1 -1
- package/src/RbirdAutomationManager.js +416 -0
- package/src/RbirdFormManager.js +7 -2
- package/src/RbirdSurveyManager.js +720 -0
- package/src/RbirdWebsiteWidget.js +89 -8
- package/src/index.js +42 -0
|
@@ -54,6 +54,9 @@ export default class RbirdWebsiteWidget {
|
|
|
54
54
|
initialX = 0;
|
|
55
55
|
initialY = 0;
|
|
56
56
|
|
|
57
|
+
// Notification sound
|
|
58
|
+
audioContext = null;
|
|
59
|
+
|
|
57
60
|
static getInstance() {
|
|
58
61
|
if (!this.instance) {
|
|
59
62
|
this.instance = new RbirdWebsiteWidget();
|
|
@@ -369,8 +372,9 @@ export default class RbirdWebsiteWidget {
|
|
|
369
372
|
|
|
370
373
|
if (e.data === 'newMessageArrived') {
|
|
371
374
|
this.countNotifications();
|
|
372
|
-
//
|
|
375
|
+
// Play notification sound and refresh message bubbles when new message arrives
|
|
373
376
|
if (!RbirdUtils.hasClass(this.widgetContent, 'cta__modal--visible')) {
|
|
377
|
+
this.playNotificationSound();
|
|
374
378
|
this.fetchUnreadMessages();
|
|
375
379
|
if (this.iframe) {
|
|
376
380
|
this.iframe.contentWindow?.postMessage({
|
|
@@ -588,6 +592,43 @@ export default class RbirdWebsiteWidget {
|
|
|
588
592
|
this.messageBubblesContainer.style.right = 'unset';
|
|
589
593
|
}
|
|
590
594
|
|
|
595
|
+
/**
|
|
596
|
+
* Play a notification sound when new messages arrive
|
|
597
|
+
*/
|
|
598
|
+
playNotificationSound() {
|
|
599
|
+
try {
|
|
600
|
+
// Create AudioContext lazily (required for browser autoplay policies)
|
|
601
|
+
if (!this.audioContext) {
|
|
602
|
+
this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
const ctx = this.audioContext;
|
|
606
|
+
const now = ctx.currentTime;
|
|
607
|
+
|
|
608
|
+
// Create oscillator for the "plopp" sound
|
|
609
|
+
const oscillator = ctx.createOscillator();
|
|
610
|
+
const gainNode = ctx.createGain();
|
|
611
|
+
|
|
612
|
+
oscillator.connect(gainNode);
|
|
613
|
+
gainNode.connect(ctx.destination);
|
|
614
|
+
|
|
615
|
+
// Plopp sound: quick frequency drop with fast decay
|
|
616
|
+
oscillator.type = 'sine';
|
|
617
|
+
oscillator.frequency.setValueAtTime(800, now);
|
|
618
|
+
oscillator.frequency.exponentialRampToValueAtTime(300, now + 0.1);
|
|
619
|
+
|
|
620
|
+
// Quick attack and decay for the "plopp" effect
|
|
621
|
+
gainNode.gain.setValueAtTime(0, now);
|
|
622
|
+
gainNode.gain.linearRampToValueAtTime(0.3, now + 0.02);
|
|
623
|
+
gainNode.gain.exponentialRampToValueAtTime(0.01, now + 0.15);
|
|
624
|
+
|
|
625
|
+
oscillator.start(now);
|
|
626
|
+
oscillator.stop(now + 0.15);
|
|
627
|
+
} catch (e) {
|
|
628
|
+
// Silently fail if audio is not supported
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
591
632
|
/**
|
|
592
633
|
* Create a single message bubble element
|
|
593
634
|
* @param {Object} msg - Message object with chatId, text, senderName, senderAvatar, timestamp
|
|
@@ -763,6 +804,20 @@ export default class RbirdWebsiteWidget {
|
|
|
763
804
|
this.dragHandle.addEventListener('touchstart', (e) => this.startDrag(e), { passive: false });
|
|
764
805
|
document.addEventListener('touchmove', (e) => this.onDrag(e), { passive: false });
|
|
765
806
|
document.addEventListener('touchend', (e) => this.endDrag(e));
|
|
807
|
+
|
|
808
|
+
// Window resize listener to update position when viewport changes
|
|
809
|
+
window.addEventListener('resize', () => this.onWindowResize());
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* Handle window resize - update widget position to stay relative to viewport
|
|
814
|
+
*/
|
|
815
|
+
onWindowResize() {
|
|
816
|
+
const savedPosition = this.loadWidgetPosition();
|
|
817
|
+
if (savedPosition && this.widgetWrapper) {
|
|
818
|
+
this.updateWidgetPosition(savedPosition.x, savedPosition.y);
|
|
819
|
+
this.updateRelatedElementsPosition();
|
|
820
|
+
}
|
|
766
821
|
}
|
|
767
822
|
|
|
768
823
|
/**
|
|
@@ -863,11 +918,16 @@ export default class RbirdWebsiteWidget {
|
|
|
863
918
|
}
|
|
864
919
|
|
|
865
920
|
/**
|
|
866
|
-
* Save widget position to localStorage
|
|
921
|
+
* Save widget position to localStorage as percentage of viewport
|
|
867
922
|
*/
|
|
868
923
|
saveWidgetPosition(x, y) {
|
|
869
924
|
try {
|
|
870
|
-
|
|
925
|
+
// Store position as percentage of viewport for responsive behavior
|
|
926
|
+
const position = {
|
|
927
|
+
xPercent: x / window.innerWidth,
|
|
928
|
+
yPercent: y / window.innerHeight,
|
|
929
|
+
timestamp: Date.now()
|
|
930
|
+
};
|
|
871
931
|
window.localStorage.setItem('rbird_widget_position', JSON.stringify(position));
|
|
872
932
|
} catch (e) {
|
|
873
933
|
console.warn('[RbirdWidget] Could not save position to localStorage:', e);
|
|
@@ -875,17 +935,38 @@ export default class RbirdWebsiteWidget {
|
|
|
875
935
|
}
|
|
876
936
|
|
|
877
937
|
/**
|
|
878
|
-
* Load widget position from localStorage
|
|
938
|
+
* Load widget position from localStorage and convert to current viewport pixels
|
|
879
939
|
*/
|
|
880
940
|
loadWidgetPosition() {
|
|
881
941
|
try {
|
|
882
942
|
const saved = window.localStorage.getItem('rbird_widget_position');
|
|
883
943
|
if (saved) {
|
|
884
944
|
const position = JSON.parse(saved);
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
945
|
+
|
|
946
|
+
// Handle new percentage-based format
|
|
947
|
+
if (position.xPercent !== undefined && position.yPercent !== undefined) {
|
|
948
|
+
const x = position.xPercent * window.innerWidth;
|
|
949
|
+
const y = position.yPercent * window.innerHeight;
|
|
950
|
+
|
|
951
|
+
// Ensure position is within viewport bounds
|
|
952
|
+
const bubbleSize = 60; // approximate bubble size
|
|
953
|
+
const clampedX = Math.max(0, Math.min(x, window.innerWidth - bubbleSize));
|
|
954
|
+
const clampedY = Math.max(0, Math.min(y, window.innerHeight - bubbleSize));
|
|
955
|
+
|
|
956
|
+
return { x: clampedX, y: clampedY };
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// Handle legacy absolute pixel format - convert to percentage and save
|
|
960
|
+
if (position.x !== undefined && position.y !== undefined) {
|
|
961
|
+
// Clamp to current viewport
|
|
962
|
+
const bubbleSize = 60;
|
|
963
|
+
const clampedX = Math.max(0, Math.min(position.x, window.innerWidth - bubbleSize));
|
|
964
|
+
const clampedY = Math.max(0, Math.min(position.y, window.innerHeight - bubbleSize));
|
|
965
|
+
|
|
966
|
+
// Convert to percentage and save for future
|
|
967
|
+
this.saveWidgetPosition(clampedX, clampedY);
|
|
968
|
+
|
|
969
|
+
return { x: clampedX, y: clampedY };
|
|
889
970
|
}
|
|
890
971
|
}
|
|
891
972
|
} catch (e) {
|
package/src/index.js
CHANGED
|
@@ -4,6 +4,8 @@ import RbirdWebsiteWidget from "./RbirdWebsiteWidget";
|
|
|
4
4
|
import { ReleasebirdConsoleLogger } from "./ReleasebirdConsoleLogger";
|
|
5
5
|
import { RbirdBannerManager } from "./RbirdBannerManager";
|
|
6
6
|
import { RbirdFormManager } from "./RbirdFormManager";
|
|
7
|
+
import { RbirdSurveyManager } from "./RbirdSurveyManager";
|
|
8
|
+
import { RbirdAutomationManager } from "./RbirdAutomationManager";
|
|
7
9
|
|
|
8
10
|
class Rbird {
|
|
9
11
|
|
|
@@ -93,6 +95,15 @@ class Rbird {
|
|
|
93
95
|
// Initialize form manager
|
|
94
96
|
const formManager = RbirdFormManager.getInstance();
|
|
95
97
|
formManager.init(apiKey);
|
|
98
|
+
|
|
99
|
+
// Initialize survey manager
|
|
100
|
+
const surveyManager = RbirdSurveyManager.getInstance();
|
|
101
|
+
surveyManager.init(apiKey);
|
|
102
|
+
|
|
103
|
+
// Initialize automation manager
|
|
104
|
+
const automationManager = RbirdAutomationManager.getInstance();
|
|
105
|
+
automationManager.init(apiKey);
|
|
106
|
+
|
|
96
107
|
resolve();
|
|
97
108
|
});
|
|
98
109
|
});
|
|
@@ -161,6 +172,37 @@ class Rbird {
|
|
|
161
172
|
}
|
|
162
173
|
}
|
|
163
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Show a survey by its ID
|
|
177
|
+
* @param {string} surveyId - The ID of the survey to show
|
|
178
|
+
* @param {Object} options - Optional configuration
|
|
179
|
+
* @param {string} options.target - CSS selector for inline rendering (optional, shows as modal if not provided)
|
|
180
|
+
* @param {Function} options.onSubmit - Callback when survey is submitted
|
|
181
|
+
* @param {Function} options.onClose - Callback when survey is closed
|
|
182
|
+
*/
|
|
183
|
+
static showSurvey(surveyId, options = {}) {
|
|
184
|
+
if (typeof window === 'undefined') return;
|
|
185
|
+
try {
|
|
186
|
+
RbirdSurveyManager.getInstance().showSurvey(surveyId, options);
|
|
187
|
+
} catch (e) {
|
|
188
|
+
console.error(e);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Track a custom event for automations
|
|
194
|
+
* @param {string} eventName - The name of the event
|
|
195
|
+
* @param {Object} data - Additional event data
|
|
196
|
+
*/
|
|
197
|
+
static track(eventName, data = {}) {
|
|
198
|
+
if (typeof window === 'undefined') return;
|
|
199
|
+
try {
|
|
200
|
+
RbirdAutomationManager.getInstance().track(eventName, data);
|
|
201
|
+
} catch (e) {
|
|
202
|
+
console.error(e);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
164
206
|
}
|
|
165
207
|
|
|
166
208
|
export const runFunctionWhenDomIsReady = (callback) => {
|