@feedvalue/core 0.1.14 → 0.1.15

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/index.d.cts CHANGED
@@ -573,6 +573,7 @@ declare class FeedValue implements FeedValueInstance {
573
573
  private modal;
574
574
  private overlay;
575
575
  private stylesInjected;
576
+ private viewportResizeCleanup;
576
577
  private autoCloseTimeout;
577
578
  private isDestroyed;
578
579
  /**
@@ -714,8 +715,15 @@ declare class FeedValue implements FeedValueInstance {
714
715
  */
715
716
  private getModalPositionStyles;
716
717
  /**
717
- * SVG icons for trigger button (matching widget-bundle exactly)
718
+ * Smooth viewport resize compensation for mobile browser toolbar show/hide.
719
+ *
720
+ * When Chrome/Safari's bottom toolbar appears or disappears, the layout viewport
721
+ * resizes and position:fixed elements jump. This detects toolbar-sized height
722
+ * changes and applies an inverse CSS translate to cancel the jump, then animates
723
+ * back to the natural position. Uses the `translate` CSS property (separate from
724
+ * `transform`) to avoid conflicting with the hover transform on the trigger.
718
725
  */
726
+ private setupViewportCompensation;
719
727
  /**
720
728
  * SVG icons for trigger button - must match Lucide icons used in frontend-web
721
729
  * chat = MessageCircle, message = MessageSquare, feedback = MessagesSquare,
package/dist/index.d.ts CHANGED
@@ -573,6 +573,7 @@ declare class FeedValue implements FeedValueInstance {
573
573
  private modal;
574
574
  private overlay;
575
575
  private stylesInjected;
576
+ private viewportResizeCleanup;
576
577
  private autoCloseTimeout;
577
578
  private isDestroyed;
578
579
  /**
@@ -714,8 +715,15 @@ declare class FeedValue implements FeedValueInstance {
714
715
  */
715
716
  private getModalPositionStyles;
716
717
  /**
717
- * SVG icons for trigger button (matching widget-bundle exactly)
718
+ * Smooth viewport resize compensation for mobile browser toolbar show/hide.
719
+ *
720
+ * When Chrome/Safari's bottom toolbar appears or disappears, the layout viewport
721
+ * resizes and position:fixed elements jump. This detects toolbar-sized height
722
+ * changes and applies an inverse CSS translate to cancel the jump, then animates
723
+ * back to the natural position. Uses the `translate` CSS property (separate from
724
+ * `transform`) to avoid conflicting with the hover transform on the trigger.
718
725
  */
726
+ private setupViewportCompensation;
719
727
  /**
720
728
  * SVG icons for trigger button - must match Lucide icons used in frontend-web
721
729
  * chat = MessageCircle, message = MessageSquare, feedback = MessagesSquare,
package/dist/index.js CHANGED
@@ -615,6 +615,8 @@ var _FeedValue = class _FeedValue {
615
615
  __publicField(this, "modal", null);
616
616
  __publicField(this, "overlay", null);
617
617
  __publicField(this, "stylesInjected", false);
618
+ // Viewport resize compensation cleanup
619
+ __publicField(this, "viewportResizeCleanup", null);
618
620
  // Auto-close timeout reference (for cleanup on destroy)
619
621
  __publicField(this, "autoCloseTimeout", null);
620
622
  // Destroyed flag - guards async continuations (fixes React StrictMode race condition)
@@ -753,6 +755,8 @@ var _FeedValue = class _FeedValue {
753
755
  clearTimeout(this.autoCloseTimeout);
754
756
  this.autoCloseTimeout = null;
755
757
  }
758
+ this.viewportResizeCleanup?.();
759
+ this.viewportResizeCleanup = null;
756
760
  this.triggerButton?.remove();
757
761
  this.modal?.remove();
758
762
  this.overlay?.remove();
@@ -1176,6 +1180,7 @@ var _FeedValue = class _FeedValue {
1176
1180
  }
1177
1181
  this.renderTrigger();
1178
1182
  this.renderModal();
1183
+ this.setupViewportCompensation();
1179
1184
  }
1180
1185
  /**
1181
1186
  * Sanitize CSS to block potentially dangerous patterns
@@ -1388,7 +1393,7 @@ var _FeedValue = class _FeedValue {
1388
1393
  getPositionStyles(position) {
1389
1394
  switch (position) {
1390
1395
  case "bottom-left":
1391
- return "bottom: 20px; left: 20px;";
1396
+ return "bottom: calc(20px + env(safe-area-inset-bottom, 0px)); left: 20px;";
1392
1397
  case "top-right":
1393
1398
  return "top: 20px; right: 20px;";
1394
1399
  case "top-left":
@@ -1397,7 +1402,7 @@ var _FeedValue = class _FeedValue {
1397
1402
  return "top: 50%; left: 50%; transform: translate(-50%, -50%);";
1398
1403
  case "bottom-right":
1399
1404
  default:
1400
- return "bottom: 20px; right: 20px;";
1405
+ return "bottom: calc(20px + env(safe-area-inset-bottom, 0px)); right: 20px;";
1401
1406
  }
1402
1407
  }
1403
1408
  /**
@@ -1406,9 +1411,9 @@ var _FeedValue = class _FeedValue {
1406
1411
  getModalPositionStyles(position) {
1407
1412
  switch (position) {
1408
1413
  case "bottom-left":
1409
- return "bottom: 20px; left: 20px;";
1414
+ return "bottom: calc(20px + env(safe-area-inset-bottom, 0px)); left: 20px;";
1410
1415
  case "bottom-right":
1411
- return "bottom: 20px; right: 20px;";
1416
+ return "bottom: calc(20px + env(safe-area-inset-bottom, 0px)); right: 20px;";
1412
1417
  case "top-right":
1413
1418
  return "top: 20px; right: 20px;";
1414
1419
  case "top-left":
@@ -1418,6 +1423,37 @@ var _FeedValue = class _FeedValue {
1418
1423
  return "top: 50%; left: 50%; transform: translate(-50%, -50%);";
1419
1424
  }
1420
1425
  }
1426
+ /**
1427
+ * Smooth viewport resize compensation for mobile browser toolbar show/hide.
1428
+ *
1429
+ * When Chrome/Safari's bottom toolbar appears or disappears, the layout viewport
1430
+ * resizes and position:fixed elements jump. This detects toolbar-sized height
1431
+ * changes and applies an inverse CSS translate to cancel the jump, then animates
1432
+ * back to the natural position. Uses the `translate` CSS property (separate from
1433
+ * `transform`) to avoid conflicting with the hover transform on the trigger.
1434
+ */
1435
+ setupViewportCompensation() {
1436
+ if (typeof window === "undefined") return;
1437
+ let lastHeight = window.innerHeight;
1438
+ const handleResize = () => {
1439
+ const newHeight = window.innerHeight;
1440
+ const delta = newHeight - lastHeight;
1441
+ lastHeight = newHeight;
1442
+ if (Math.abs(delta) <= 5 || Math.abs(delta) >= 120) return;
1443
+ const elements = [this.triggerButton, this.modal].filter(Boolean);
1444
+ for (const el of elements) {
1445
+ el.style.transition = "none";
1446
+ el.style.translate = `0 ${delta}px`;
1447
+ void el.offsetHeight;
1448
+ el.style.transition = "translate 0.3s ease-out";
1449
+ el.style.translate = "0 0";
1450
+ }
1451
+ };
1452
+ window.addEventListener("resize", handleResize, { passive: true });
1453
+ this.viewportResizeCleanup = () => {
1454
+ window.removeEventListener("resize", handleResize);
1455
+ };
1456
+ }
1421
1457
  /**
1422
1458
  * Parse SVG string to DOM element safely using DOMParser
1423
1459
  */
@@ -1618,9 +1654,6 @@ var _FeedValue = class _FeedValue {
1618
1654
  }
1619
1655
  }
1620
1656
  };
1621
- /**
1622
- * SVG icons for trigger button (matching widget-bundle exactly)
1623
- */
1624
1657
  /**
1625
1658
  * SVG icons for trigger button - must match Lucide icons used in frontend-web
1626
1659
  * chat = MessageCircle, message = MessageSquare, feedback = MessagesSquare,