@capgo/capacitor-transitions 8.0.1 → 8.0.2

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.ts CHANGED
@@ -321,9 +321,13 @@ declare class CapRouterOutlet extends HTMLElement {
321
321
  private skipNextHistoryBackTransition;
322
322
  private swipeBackDepth;
323
323
  private lastNavigationHref;
324
+ private lastNavigationPosition;
325
+ private pendingHistoryDirection;
326
+ private navigationHrefs;
324
327
  private readonly swipeGestureEdgeWidth;
325
328
  private readonly swipeGestureThreshold;
326
329
  private readonly swipeGestureMinimumVelocity;
330
+ private readonly handleHistoryPopState;
327
331
  static get observedAttributes(): string[];
328
332
  constructor();
329
333
  connectedCallback(): void;
@@ -395,7 +399,14 @@ declare class CapRouterOutlet extends HTMLElement {
395
399
  private removeSwipeGestureListeners;
396
400
  private isSwipeGestureEnabled;
397
401
  private getCurrentNavigationHref;
402
+ private getCurrentNavigationPosition;
403
+ private resolveNavigationDirection;
398
404
  private recordCompletedNavigation;
405
+ private resetNavigationDepth;
406
+ private recordBackNavigation;
407
+ private findNavigationHrefIndex;
408
+ private syncSwipeBackDepth;
409
+ private getSwipeBackDestination;
399
410
  private canStartSwipeGesture;
400
411
  private isRTL;
401
412
  private getSwipeGestureDeltaX;
package/dist/index.js CHANGED
@@ -1338,9 +1338,26 @@ var init_cap_router_outlet = __esm({
1338
1338
  skipNextHistoryBackTransition = false;
1339
1339
  swipeBackDepth = 0;
1340
1340
  lastNavigationHref = null;
1341
+ lastNavigationPosition = null;
1342
+ pendingHistoryDirection = null;
1343
+ navigationHrefs = [];
1341
1344
  swipeGestureEdgeWidth = 50;
1342
1345
  swipeGestureThreshold = 10;
1343
1346
  swipeGestureMinimumVelocity = 0.2;
1347
+ handleHistoryPopState = () => {
1348
+ const currentPosition = this.getCurrentNavigationPosition();
1349
+ if (currentPosition !== null && this.lastNavigationPosition !== null) {
1350
+ if (currentPosition < this.lastNavigationPosition) {
1351
+ this.pendingHistoryDirection = "back";
1352
+ return;
1353
+ }
1354
+ if (currentPosition > this.lastNavigationPosition) {
1355
+ this.pendingHistoryDirection = "forward";
1356
+ return;
1357
+ }
1358
+ }
1359
+ this.pendingHistoryDirection = "back";
1360
+ };
1344
1361
  static get observedAttributes() {
1345
1362
  return ["platform", "duration", "keep-in-dom", "max-cached", "swipe-gesture"];
1346
1363
  }
@@ -1360,6 +1377,8 @@ var init_cap_router_outlet = __esm({
1360
1377
  this.style.height = "100%";
1361
1378
  this.style.overflow = "hidden";
1362
1379
  this.lastNavigationHref = this.getCurrentNavigationHref();
1380
+ this.lastNavigationPosition = this.getCurrentNavigationPosition();
1381
+ this.ownerDocument.defaultView?.addEventListener("popstate", this.handleHistoryPopState);
1363
1382
  this.observer = new MutationObserver((mutations) => {
1364
1383
  this.handleMutations(mutations);
1365
1384
  });
@@ -1375,10 +1394,14 @@ var init_cap_router_outlet = __esm({
1375
1394
  }
1376
1395
  disconnectedCallback() {
1377
1396
  this.observer?.disconnect();
1397
+ this.ownerDocument.defaultView?.removeEventListener("popstate", this.handleHistoryPopState);
1378
1398
  this.removeSwipeGestureListeners();
1379
1399
  this.controller.clear();
1380
1400
  this.swipeBackDepth = 0;
1381
1401
  this.lastNavigationHref = null;
1402
+ this.lastNavigationPosition = null;
1403
+ this.pendingHistoryDirection = null;
1404
+ this.navigationHrefs = [];
1382
1405
  }
1383
1406
  attributeChangedCallback(name, _oldValue, newValue) {
1384
1407
  switch (name) {
@@ -1459,13 +1482,16 @@ var init_cap_router_outlet = __esm({
1459
1482
  this.controller.pageStack.push(state);
1460
1483
  this.swipeBackDepth = 0;
1461
1484
  this.lastNavigationHref = this.getCurrentNavigationHref();
1485
+ this.lastNavigationPosition = this.getCurrentNavigationPosition();
1486
+ this.navigationHrefs = [this.lastNavigationHref];
1462
1487
  }
1463
1488
  /**
1464
1489
  * Handle a new page being added
1465
1490
  */
1466
1491
  async handleNewPage(page) {
1467
1492
  const outletDirection = this.dataset.direction;
1468
- const direction = page.dataset.direction || outletDirection || "forward";
1493
+ const explicitDirection = page.dataset.direction || outletDirection;
1494
+ const direction = this.resolveNavigationDirection(explicitDirection);
1469
1495
  if (outletDirection) {
1470
1496
  delete this.dataset.direction;
1471
1497
  }
@@ -1580,7 +1606,7 @@ var init_cap_router_outlet = __esm({
1580
1606
  * Check if we can go back
1581
1607
  */
1582
1608
  get canGoBack() {
1583
- return this.controller.stack.length > 1 && this.swipeBackDepth > 0;
1609
+ return this.getSwipeBackDestination() !== null;
1584
1610
  }
1585
1611
  /**
1586
1612
  * Get whether edge swipe-back gesture is enabled.
@@ -1672,30 +1698,132 @@ var init_cap_router_outlet = __esm({
1672
1698
  getCurrentNavigationHref() {
1673
1699
  return this.ownerDocument.defaultView?.location.href ?? null;
1674
1700
  }
1701
+ getCurrentNavigationPosition() {
1702
+ const win = this.ownerDocument.defaultView;
1703
+ if (!win) {
1704
+ return null;
1705
+ }
1706
+ const navigationIndex = win.navigation?.currentEntry?.index;
1707
+ if (typeof navigationIndex === "number" && Number.isFinite(navigationIndex)) {
1708
+ return navigationIndex;
1709
+ }
1710
+ const state = win.history.state;
1711
+ for (const key of ["idx", "position", "index"]) {
1712
+ const value = state?.[key];
1713
+ if (typeof value === "number" && Number.isFinite(value)) {
1714
+ return value;
1715
+ }
1716
+ }
1717
+ return null;
1718
+ }
1719
+ resolveNavigationDirection(explicitDirection) {
1720
+ if (explicitDirection) {
1721
+ this.pendingHistoryDirection = null;
1722
+ return explicitDirection;
1723
+ }
1724
+ const currentHref = this.getCurrentNavigationHref();
1725
+ const existingHrefIndex = this.findNavigationHrefIndex(currentHref, this.navigationHrefs.length - 2);
1726
+ if (existingHrefIndex !== -1) {
1727
+ this.pendingHistoryDirection = null;
1728
+ return "back";
1729
+ }
1730
+ if (currentHref !== null && currentHref === this.lastNavigationHref) {
1731
+ this.pendingHistoryDirection = null;
1732
+ return "none";
1733
+ }
1734
+ if (this.pendingHistoryDirection) {
1735
+ const direction = this.pendingHistoryDirection;
1736
+ this.pendingHistoryDirection = null;
1737
+ return direction;
1738
+ }
1739
+ const currentPosition = this.getCurrentNavigationPosition();
1740
+ if (currentPosition !== null && this.lastNavigationPosition !== null) {
1741
+ if (currentPosition < this.lastNavigationPosition) {
1742
+ return "back";
1743
+ }
1744
+ if (currentPosition === this.lastNavigationPosition) {
1745
+ return "none";
1746
+ }
1747
+ }
1748
+ return "forward";
1749
+ }
1675
1750
  recordCompletedNavigation(direction, options) {
1676
1751
  const currentHref = this.getCurrentNavigationHref();
1752
+ const currentPosition = this.getCurrentNavigationPosition();
1677
1753
  if (!options.hadPageBefore || direction === "root") {
1678
- this.swipeBackDepth = 0;
1679
- this.lastNavigationHref = currentHref;
1754
+ this.resetNavigationDepth(currentHref, currentPosition);
1680
1755
  return;
1681
1756
  }
1682
1757
  if (direction === "back") {
1683
- this.swipeBackDepth = Math.max(0, this.swipeBackDepth - 1);
1758
+ this.recordBackNavigation(currentHref);
1759
+ this.lastNavigationPosition = currentPosition;
1760
+ return;
1761
+ }
1762
+ if (direction === "none") {
1763
+ if (this.navigationHrefs.length === 0) {
1764
+ this.navigationHrefs = [currentHref];
1765
+ } else {
1766
+ this.navigationHrefs[this.navigationHrefs.length - 1] = currentHref;
1767
+ }
1768
+ this.syncSwipeBackDepth();
1684
1769
  this.lastNavigationHref = currentHref;
1770
+ this.lastNavigationPosition = currentPosition;
1685
1771
  return;
1686
1772
  }
1687
- if (direction === "forward" || direction === "none") {
1773
+ if (direction === "forward") {
1688
1774
  const hrefChanged = currentHref === null || this.lastNavigationHref === null || currentHref !== this.lastNavigationHref;
1689
1775
  if (options.forceForward || hrefChanged) {
1690
- this.swipeBackDepth += 1;
1776
+ this.navigationHrefs.push(currentHref);
1777
+ } else if (this.navigationHrefs.length === 0) {
1778
+ this.navigationHrefs = [currentHref];
1691
1779
  }
1780
+ this.syncSwipeBackDepth();
1692
1781
  this.lastNavigationHref = currentHref;
1782
+ this.lastNavigationPosition = currentPosition;
1693
1783
  return;
1694
1784
  }
1695
1785
  this.lastNavigationHref = currentHref;
1786
+ this.lastNavigationPosition = currentPosition;
1787
+ }
1788
+ resetNavigationDepth(currentHref, currentPosition) {
1789
+ this.navigationHrefs = [currentHref];
1790
+ this.swipeBackDepth = 0;
1791
+ this.lastNavigationHref = currentHref;
1792
+ this.lastNavigationPosition = currentPosition;
1793
+ }
1794
+ recordBackNavigation(currentHref) {
1795
+ const existingHrefIndex = this.findNavigationHrefIndex(currentHref, this.navigationHrefs.length - 2);
1796
+ if (existingHrefIndex !== -1) {
1797
+ this.navigationHrefs = this.navigationHrefs.slice(0, existingHrefIndex + 1);
1798
+ } else if (this.navigationHrefs.length > 1) {
1799
+ this.navigationHrefs.pop();
1800
+ this.navigationHrefs[this.navigationHrefs.length - 1] = currentHref;
1801
+ } else {
1802
+ this.navigationHrefs = [currentHref];
1803
+ }
1804
+ this.syncSwipeBackDepth();
1805
+ this.lastNavigationHref = currentHref;
1806
+ }
1807
+ findNavigationHrefIndex(href, fromIndex) {
1808
+ for (let index = Math.min(fromIndex, this.navigationHrefs.length - 1); index >= 0; index -= 1) {
1809
+ if (this.navigationHrefs[index] === href) {
1810
+ return index;
1811
+ }
1812
+ }
1813
+ return -1;
1814
+ }
1815
+ syncSwipeBackDepth() {
1816
+ this.swipeBackDepth = Math.max(0, this.navigationHrefs.length - 1);
1817
+ }
1818
+ getSwipeBackDestination() {
1819
+ const stack = this.controller.stack;
1820
+ if (this.swipeBackDepth <= 0 || stack.length <= 1) {
1821
+ return null;
1822
+ }
1823
+ return stack[stack.length - 2] ?? null;
1696
1824
  }
1697
1825
  canStartSwipeGesture(event) {
1698
- if (!this.isSwipeGestureEnabled() || this.controller.animating || this.pendingPage || !this.canGoBack) {
1826
+ if (!this.isSwipeGestureEnabled() || this.controller.animating || this.pendingPage || !this.getSwipeBackDestination()) {
1699
1827
  return false;
1700
1828
  }
1701
1829
  if (!event.isPrimary || event.pointerType === "mouse" && event.button !== 0) {
@@ -1782,6 +1910,10 @@ var init_cap_router_outlet = __esm({
1782
1910
  return;
1783
1911
  }
1784
1912
  if (!pointer.dragging && deltaX > this.swipeGestureThreshold && absX > absY) {
1913
+ if (!this.getSwipeBackDestination()) {
1914
+ this.cancelSwipeGesturePointer(event.pointerId);
1915
+ return;
1916
+ }
1785
1917
  pointer.dragging = true;
1786
1918
  pointer.transitionStarted = this.controller.beginInteractiveBack({ direction: "back" });
1787
1919
  if (!pointer.transitionStarted) {
@@ -1790,6 +1922,10 @@ var init_cap_router_outlet = __esm({
1790
1922
  }
1791
1923
  }
1792
1924
  if (pointer.dragging && pointer.transitionStarted) {
1925
+ if (!this.getSwipeBackDestination()) {
1926
+ this.cancelSwipeGesture(event.pointerId);
1927
+ return;
1928
+ }
1793
1929
  if (event.cancelable) event.preventDefault();
1794
1930
  const width = Math.max(this.getBoundingClientRect().width, 1);
1795
1931
  this.controller.stepInteractiveBack(deltaX / width);
@@ -1841,9 +1977,10 @@ var init_cap_router_outlet = __esm({
1841
1977
  }
1842
1978
  }
1843
1979
  async finishSwipeGestureBack(shouldComplete, releaseDuration) {
1844
- const shouldUseHistory = shouldComplete && typeof window !== "undefined" && window.history.length > 1;
1845
- await this.controller.endInteractiveBack(shouldComplete, releaseDuration, !shouldUseHistory);
1846
- if (!shouldComplete) {
1980
+ const canComplete = shouldComplete && this.getSwipeBackDestination() !== null;
1981
+ const shouldUseHistory = canComplete && typeof window !== "undefined" && window.history.length > 1;
1982
+ await this.controller.endInteractiveBack(canComplete, canComplete ? releaseDuration : 0, !shouldUseHistory);
1983
+ if (!canComplete) {
1847
1984
  return;
1848
1985
  }
1849
1986
  if (shouldUseHistory) {