aumera-on-screen-widget 0.0.8 → 0.0.10
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/df-btn.js +141 -19
- package/package.json +1 -1
package/df-btn.js
CHANGED
|
@@ -34,7 +34,10 @@ if (!config.orgId) {
|
|
|
34
34
|
background-color: ${config.background || "#FEFFFF"};
|
|
35
35
|
border-radius: 24px;
|
|
36
36
|
cursor: pointer;
|
|
37
|
-
transition:
|
|
37
|
+
transition: none;
|
|
38
|
+
transform-origin: ${
|
|
39
|
+
config.position === "left" ? "bottom left" : "bottom right"
|
|
40
|
+
};
|
|
38
41
|
position: fixed;
|
|
39
42
|
bottom: 0px;
|
|
40
43
|
${config.position === "left" ? "left: 0px;" : "right: 0px;"}
|
|
@@ -130,7 +133,10 @@ if (!config.orgId) {
|
|
|
130
133
|
max-height: 75vh;
|
|
131
134
|
width: ${config.width || "414px"};
|
|
132
135
|
max-width: 414px;
|
|
133
|
-
transition:
|
|
136
|
+
transition: none;
|
|
137
|
+
transform-origin: ${
|
|
138
|
+
config.position === "left" ? "bottom left" : "bottom right"
|
|
139
|
+
};
|
|
134
140
|
${config.position === "left" ? "float: left;" : "float: right;"}
|
|
135
141
|
opacity: 1;
|
|
136
142
|
border-radius: 0 0 16px 16px;
|
|
@@ -160,24 +166,27 @@ if (!config.orgId) {
|
|
|
160
166
|
.df-btn.df-maximized {
|
|
161
167
|
width: 100vw !important;
|
|
162
168
|
height: 100vh !important;
|
|
169
|
+
height: 100dvh !important; /* Dynamic viewport height for mobile */
|
|
163
170
|
top: 0 !important;
|
|
164
|
-
left: 0 !important;
|
|
165
|
-
right: 0 !important;
|
|
171
|
+
${config.position === "left" ? "left: 0 !important;" : ""}
|
|
172
|
+
${config.position === "right" ? "right: 0 !important;" : ""}
|
|
166
173
|
bottom: 0 !important;
|
|
167
174
|
margin: 0 !important;
|
|
168
175
|
border-radius: 0 !important;
|
|
169
|
-
|
|
176
|
+
/* Handle safe areas on mobile devices */
|
|
177
|
+
padding-bottom: env(safe-area-inset-bottom, 0);
|
|
170
178
|
}
|
|
171
179
|
.df-btn.df-maximized .df-btn-content {
|
|
172
180
|
width: 100vw !important;
|
|
173
181
|
max-width: 100vw !important;
|
|
174
182
|
height: calc(100vh - 56px) !important;
|
|
183
|
+
height: calc(100dvh - env(safe-area-inset-bottom, 0px)) !important; /* Account for safe area */
|
|
175
184
|
max-height: calc(100vh - 56px) !important;
|
|
185
|
+
max-height: calc(100dvh - env(safe-area-inset-bottom, 0px)) !important;
|
|
176
186
|
opacity: 1 !important;
|
|
177
|
-
|
|
187
|
+
float: none !important;
|
|
178
188
|
display: block !important;
|
|
179
189
|
border-radius: 0 !important;
|
|
180
|
-
transition: all .45s cubic-bezier(.4, 0, .2, 1) !important;
|
|
181
190
|
}
|
|
182
191
|
.df-btn.df-closed .df-btn-content {
|
|
183
192
|
width: 0 !important;
|
|
@@ -194,6 +203,17 @@ if (!config.orgId) {
|
|
|
194
203
|
justify-content: center;
|
|
195
204
|
}
|
|
196
205
|
|
|
206
|
+
/* Animation classes for FLIP */
|
|
207
|
+
.df-animating {
|
|
208
|
+
transition: transform .45s cubic-bezier(.4, 0, .2, 1);
|
|
209
|
+
will-change: transform;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.df-content-animating {
|
|
213
|
+
transition: opacity .45s cubic-bezier(.4, 0, .2, 1);
|
|
214
|
+
will-change: opacity;
|
|
215
|
+
}
|
|
216
|
+
|
|
197
217
|
@media screen and (max-width: 720px){
|
|
198
218
|
.df-btn {
|
|
199
219
|
border-radius: 28px;
|
|
@@ -201,13 +221,16 @@ if (!config.orgId) {
|
|
|
201
221
|
|
|
202
222
|
.df-btn:not(.df-closed) {
|
|
203
223
|
margin: 0px;
|
|
204
|
-
border-radius: 0px
|
|
224
|
+
border-radius: 0px;
|
|
225
|
+
padding-bottom: env(safe-area-inset-bottom, 0);
|
|
205
226
|
}
|
|
206
227
|
|
|
207
228
|
.df-btn:not(.df-closed) > .df-btn-content {
|
|
208
229
|
width: 100vw;
|
|
209
230
|
max-height: 100vh;
|
|
231
|
+
max-height: 100dvh;
|
|
210
232
|
height: calc(100vh - 56px);
|
|
233
|
+
height: calc(100dvh - 56px - env(safe-area-inset-bottom, 0px));
|
|
211
234
|
padding-bottom: 0px
|
|
212
235
|
}
|
|
213
236
|
|
|
@@ -276,8 +299,7 @@ if (!config.orgId) {
|
|
|
276
299
|
// Get the detected language
|
|
277
300
|
const detectedLang = getLanguage();
|
|
278
301
|
|
|
279
|
-
// Check if mobile device
|
|
280
|
-
const isMobileDevice = window.innerWidth <= 768;
|
|
302
|
+
// Check if mobile device - removed unused variable
|
|
281
303
|
|
|
282
304
|
document.write(`
|
|
283
305
|
<button class="df-btn df-closed" onclick="dfToggle()">
|
|
@@ -289,7 +311,7 @@ if (!config.orgId) {
|
|
|
289
311
|
<div class="df-btn-header">
|
|
290
312
|
<div class="df-btn-text">${config.openText || "Chat"}</div>
|
|
291
313
|
</div>
|
|
292
|
-
<iframe class="df-btn-content" src="https://chat.aumera.ai/${detectedLang}/?orgId=${
|
|
314
|
+
<iframe class="df-btn-content" src="https://chat.dev.aumera.ai/${detectedLang}/?orgId=${
|
|
293
315
|
config.orgId
|
|
294
316
|
}" allow="microphone *"></iframe>
|
|
295
317
|
</button>
|
|
@@ -298,7 +320,6 @@ if (!config.orgId) {
|
|
|
298
320
|
let dfToggled = false;
|
|
299
321
|
let inactivityTimer = null;
|
|
300
322
|
let shakeInterval = null;
|
|
301
|
-
let maximized = false;
|
|
302
323
|
|
|
303
324
|
const startInactivityTimer = () => {
|
|
304
325
|
// Only start inactivity timer if button is closed
|
|
@@ -361,7 +382,6 @@ if (!config.orgId) {
|
|
|
361
382
|
btnText.style.paddingRight = "0";
|
|
362
383
|
|
|
363
384
|
// Only add maximize/minimize button on desktop
|
|
364
|
-
const isMobile = window.innerWidth <= 768;
|
|
365
385
|
|
|
366
386
|
// Add maximize/minimize button (right)
|
|
367
387
|
const maxBtn = document.createElement("div");
|
|
@@ -405,8 +425,56 @@ if (!config.orgId) {
|
|
|
405
425
|
function maximizeMinimize() {
|
|
406
426
|
const btn = document.querySelector(".df-btn");
|
|
407
427
|
if (!btn) return;
|
|
428
|
+
const content = btn.querySelector(".df-btn-content");
|
|
429
|
+
if (!content) return;
|
|
430
|
+
|
|
431
|
+
// FIRST: Capture current positions
|
|
432
|
+
const firstBtn = btn.getBoundingClientRect();
|
|
433
|
+
|
|
434
|
+
// Toggle the maximized state (instant layout change)
|
|
408
435
|
btn.classList.toggle("df-maximized");
|
|
409
|
-
|
|
436
|
+
|
|
437
|
+
// LAST: Capture new positions
|
|
438
|
+
const lastBtn = btn.getBoundingClientRect();
|
|
439
|
+
|
|
440
|
+
// INVERT: Calculate the delta and apply transform to invert to original position
|
|
441
|
+
const btnDeltaX = firstBtn.left - lastBtn.left;
|
|
442
|
+
const btnDeltaY = firstBtn.top - lastBtn.top;
|
|
443
|
+
const btnScaleX = firstBtn.width / Math.max(lastBtn.width, 0.0001);
|
|
444
|
+
const btnScaleY = firstBtn.height / Math.max(lastBtn.height, 0.0001);
|
|
445
|
+
|
|
446
|
+
// Apply inverted transform
|
|
447
|
+
btn.style.transform = `translate(${btnDeltaX}px, ${btnDeltaY}px) scale(${btnScaleX}, ${btnScaleY})`;
|
|
448
|
+
|
|
449
|
+
// Optional: Soften iframe reflow with opacity
|
|
450
|
+
content.classList.add("df-content-animating");
|
|
451
|
+
content.style.opacity = "0.95";
|
|
452
|
+
|
|
453
|
+
// Force reflow to ensure the inverted state is applied
|
|
454
|
+
btn.getBoundingClientRect();
|
|
455
|
+
|
|
456
|
+
// PLAY: Add animation class and clear transform to animate to identity
|
|
457
|
+
btn.classList.add("df-animating");
|
|
458
|
+
btn.style.transform = "";
|
|
459
|
+
|
|
460
|
+
// Cleanup after animation ends
|
|
461
|
+
const onTransitionEnd = (e) => {
|
|
462
|
+
if (e.target !== btn) return;
|
|
463
|
+
btn.classList.remove("df-animating");
|
|
464
|
+
content.classList.remove("df-content-animating");
|
|
465
|
+
content.style.opacity = "";
|
|
466
|
+
updateHeaderButtons();
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
btn.addEventListener("transitionend", onTransitionEnd, { once: true });
|
|
470
|
+
|
|
471
|
+
// Fallback cleanup in case transition doesn't fire
|
|
472
|
+
setTimeout(() => {
|
|
473
|
+
btn.classList.remove("df-animating");
|
|
474
|
+
content.classList.remove("df-content-animating");
|
|
475
|
+
content.style.opacity = "";
|
|
476
|
+
updateHeaderButtons();
|
|
477
|
+
}, 500);
|
|
410
478
|
}
|
|
411
479
|
|
|
412
480
|
function dfToggle() {
|
|
@@ -434,14 +502,68 @@ if (!config.orgId) {
|
|
|
434
502
|
// Check if mobile for later use
|
|
435
503
|
const isMobile = window.innerWidth <= 768;
|
|
436
504
|
|
|
437
|
-
btn.addEventListener("click", (
|
|
505
|
+
btn.addEventListener("click", () => {
|
|
438
506
|
// Only toggle if chat is closed (popover mode)
|
|
439
507
|
if (btn.classList.contains("df-closed")) {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
if (
|
|
508
|
+
const isMobile = window.innerWidth <= 768;
|
|
509
|
+
|
|
510
|
+
if (isMobile) {
|
|
511
|
+
// On mobile, apply FLIP animation for open+maximize
|
|
512
|
+
const content = btn.querySelector(".df-btn-content");
|
|
513
|
+
|
|
514
|
+
// FIRST: Capture current (closed) position
|
|
515
|
+
const firstBtn = btn.getBoundingClientRect();
|
|
516
|
+
|
|
517
|
+
// Open and maximize instantly
|
|
518
|
+
btn.classList.remove("df-closed");
|
|
443
519
|
btn.classList.add("df-maximized");
|
|
444
|
-
|
|
520
|
+
|
|
521
|
+
// LAST: Capture final position
|
|
522
|
+
const lastBtn = btn.getBoundingClientRect();
|
|
523
|
+
|
|
524
|
+
// INVERT
|
|
525
|
+
const btnDeltaX = firstBtn.left - lastBtn.left;
|
|
526
|
+
const btnDeltaY = firstBtn.top - lastBtn.top;
|
|
527
|
+
const btnScaleX = firstBtn.width / Math.max(lastBtn.width, 0.0001);
|
|
528
|
+
const btnScaleY = firstBtn.height / Math.max(lastBtn.height, 0.0001);
|
|
529
|
+
|
|
530
|
+
btn.style.transform = `translate(${btnDeltaX}px, ${btnDeltaY}px) scale(${btnScaleX}, ${btnScaleY})`;
|
|
531
|
+
|
|
532
|
+
if (content) {
|
|
533
|
+
content.classList.add("df-content-animating");
|
|
534
|
+
content.style.opacity = "0.95";
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// Force reflow
|
|
538
|
+
btn.getBoundingClientRect();
|
|
539
|
+
|
|
540
|
+
// PLAY
|
|
541
|
+
btn.classList.add("df-animating");
|
|
542
|
+
btn.style.transform = "";
|
|
543
|
+
|
|
544
|
+
// Cleanup
|
|
545
|
+
const onTransitionEnd = () => {
|
|
546
|
+
btn.classList.remove("df-animating");
|
|
547
|
+
if (content) {
|
|
548
|
+
content.classList.remove("df-content-animating");
|
|
549
|
+
content.style.opacity = "";
|
|
550
|
+
}
|
|
551
|
+
updateHeaderButtons();
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
btn.addEventListener("transitionend", onTransitionEnd, { once: true });
|
|
555
|
+
|
|
556
|
+
setTimeout(() => {
|
|
557
|
+
btn.classList.remove("df-animating");
|
|
558
|
+
if (content) {
|
|
559
|
+
content.classList.remove("df-content-animating");
|
|
560
|
+
content.style.opacity = "";
|
|
561
|
+
}
|
|
562
|
+
updateHeaderButtons();
|
|
563
|
+
}, 500);
|
|
564
|
+
} else {
|
|
565
|
+
// Desktop: just toggle open
|
|
566
|
+
dfToggle();
|
|
445
567
|
}
|
|
446
568
|
}
|
|
447
569
|
// If open, do nothing (let header buttons handle maximize/minimize/close)
|