@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.mjs CHANGED
@@ -31,11 +31,11 @@ import {
31
31
  setViewTransitionName,
32
32
  supportsViewTransitions,
33
33
  waitForAnimations
34
- } from "./chunk-RLOQDT3I.mjs";
34
+ } from "./chunk-X3P7VCWP.mjs";
35
35
 
36
36
  // src/index.ts
37
37
  function initCapTransitions() {
38
- import("./components-6C46YYFQ.mjs");
38
+ import("./components-OPL2TMTE.mjs");
39
39
  }
40
40
  export {
41
41
  ANDROID_DURATION,
@@ -1242,9 +1242,26 @@ var CapRouterOutlet = class extends HTMLElement {
1242
1242
  skipNextHistoryBackTransition = false;
1243
1243
  swipeBackDepth = 0;
1244
1244
  lastNavigationHref = null;
1245
+ lastNavigationPosition = null;
1246
+ pendingHistoryDirection = null;
1247
+ navigationHrefs = [];
1245
1248
  swipeGestureEdgeWidth = 50;
1246
1249
  swipeGestureThreshold = 10;
1247
1250
  swipeGestureMinimumVelocity = 0.2;
1251
+ handleHistoryPopState = () => {
1252
+ const currentPosition = this.getCurrentNavigationPosition();
1253
+ if (currentPosition !== null && this.lastNavigationPosition !== null) {
1254
+ if (currentPosition < this.lastNavigationPosition) {
1255
+ this.pendingHistoryDirection = "back";
1256
+ return;
1257
+ }
1258
+ if (currentPosition > this.lastNavigationPosition) {
1259
+ this.pendingHistoryDirection = "forward";
1260
+ return;
1261
+ }
1262
+ }
1263
+ this.pendingHistoryDirection = "back";
1264
+ };
1248
1265
  static get observedAttributes() {
1249
1266
  return ["platform", "duration", "keep-in-dom", "max-cached", "swipe-gesture"];
1250
1267
  }
@@ -1264,6 +1281,8 @@ var CapRouterOutlet = class extends HTMLElement {
1264
1281
  this.style.height = "100%";
1265
1282
  this.style.overflow = "hidden";
1266
1283
  this.lastNavigationHref = this.getCurrentNavigationHref();
1284
+ this.lastNavigationPosition = this.getCurrentNavigationPosition();
1285
+ this.ownerDocument.defaultView?.addEventListener("popstate", this.handleHistoryPopState);
1267
1286
  this.observer = new MutationObserver((mutations) => {
1268
1287
  this.handleMutations(mutations);
1269
1288
  });
@@ -1279,10 +1298,14 @@ var CapRouterOutlet = class extends HTMLElement {
1279
1298
  }
1280
1299
  disconnectedCallback() {
1281
1300
  this.observer?.disconnect();
1301
+ this.ownerDocument.defaultView?.removeEventListener("popstate", this.handleHistoryPopState);
1282
1302
  this.removeSwipeGestureListeners();
1283
1303
  this.controller.clear();
1284
1304
  this.swipeBackDepth = 0;
1285
1305
  this.lastNavigationHref = null;
1306
+ this.lastNavigationPosition = null;
1307
+ this.pendingHistoryDirection = null;
1308
+ this.navigationHrefs = [];
1286
1309
  }
1287
1310
  attributeChangedCallback(name, _oldValue, newValue) {
1288
1311
  switch (name) {
@@ -1363,13 +1386,16 @@ var CapRouterOutlet = class extends HTMLElement {
1363
1386
  this.controller.pageStack.push(state);
1364
1387
  this.swipeBackDepth = 0;
1365
1388
  this.lastNavigationHref = this.getCurrentNavigationHref();
1389
+ this.lastNavigationPosition = this.getCurrentNavigationPosition();
1390
+ this.navigationHrefs = [this.lastNavigationHref];
1366
1391
  }
1367
1392
  /**
1368
1393
  * Handle a new page being added
1369
1394
  */
1370
1395
  async handleNewPage(page) {
1371
1396
  const outletDirection = this.dataset.direction;
1372
- const direction = page.dataset.direction || outletDirection || "forward";
1397
+ const explicitDirection = page.dataset.direction || outletDirection;
1398
+ const direction = this.resolveNavigationDirection(explicitDirection);
1373
1399
  if (outletDirection) {
1374
1400
  delete this.dataset.direction;
1375
1401
  }
@@ -1484,7 +1510,7 @@ var CapRouterOutlet = class extends HTMLElement {
1484
1510
  * Check if we can go back
1485
1511
  */
1486
1512
  get canGoBack() {
1487
- return this.controller.stack.length > 1 && this.swipeBackDepth > 0;
1513
+ return this.getSwipeBackDestination() !== null;
1488
1514
  }
1489
1515
  /**
1490
1516
  * Get whether edge swipe-back gesture is enabled.
@@ -1576,30 +1602,132 @@ var CapRouterOutlet = class extends HTMLElement {
1576
1602
  getCurrentNavigationHref() {
1577
1603
  return this.ownerDocument.defaultView?.location.href ?? null;
1578
1604
  }
1605
+ getCurrentNavigationPosition() {
1606
+ const win = this.ownerDocument.defaultView;
1607
+ if (!win) {
1608
+ return null;
1609
+ }
1610
+ const navigationIndex = win.navigation?.currentEntry?.index;
1611
+ if (typeof navigationIndex === "number" && Number.isFinite(navigationIndex)) {
1612
+ return navigationIndex;
1613
+ }
1614
+ const state = win.history.state;
1615
+ for (const key of ["idx", "position", "index"]) {
1616
+ const value = state?.[key];
1617
+ if (typeof value === "number" && Number.isFinite(value)) {
1618
+ return value;
1619
+ }
1620
+ }
1621
+ return null;
1622
+ }
1623
+ resolveNavigationDirection(explicitDirection) {
1624
+ if (explicitDirection) {
1625
+ this.pendingHistoryDirection = null;
1626
+ return explicitDirection;
1627
+ }
1628
+ const currentHref = this.getCurrentNavigationHref();
1629
+ const existingHrefIndex = this.findNavigationHrefIndex(currentHref, this.navigationHrefs.length - 2);
1630
+ if (existingHrefIndex !== -1) {
1631
+ this.pendingHistoryDirection = null;
1632
+ return "back";
1633
+ }
1634
+ if (currentHref !== null && currentHref === this.lastNavigationHref) {
1635
+ this.pendingHistoryDirection = null;
1636
+ return "none";
1637
+ }
1638
+ if (this.pendingHistoryDirection) {
1639
+ const direction = this.pendingHistoryDirection;
1640
+ this.pendingHistoryDirection = null;
1641
+ return direction;
1642
+ }
1643
+ const currentPosition = this.getCurrentNavigationPosition();
1644
+ if (currentPosition !== null && this.lastNavigationPosition !== null) {
1645
+ if (currentPosition < this.lastNavigationPosition) {
1646
+ return "back";
1647
+ }
1648
+ if (currentPosition === this.lastNavigationPosition) {
1649
+ return "none";
1650
+ }
1651
+ }
1652
+ return "forward";
1653
+ }
1579
1654
  recordCompletedNavigation(direction, options) {
1580
1655
  const currentHref = this.getCurrentNavigationHref();
1656
+ const currentPosition = this.getCurrentNavigationPosition();
1581
1657
  if (!options.hadPageBefore || direction === "root") {
1582
- this.swipeBackDepth = 0;
1583
- this.lastNavigationHref = currentHref;
1658
+ this.resetNavigationDepth(currentHref, currentPosition);
1584
1659
  return;
1585
1660
  }
1586
1661
  if (direction === "back") {
1587
- this.swipeBackDepth = Math.max(0, this.swipeBackDepth - 1);
1662
+ this.recordBackNavigation(currentHref);
1663
+ this.lastNavigationPosition = currentPosition;
1664
+ return;
1665
+ }
1666
+ if (direction === "none") {
1667
+ if (this.navigationHrefs.length === 0) {
1668
+ this.navigationHrefs = [currentHref];
1669
+ } else {
1670
+ this.navigationHrefs[this.navigationHrefs.length - 1] = currentHref;
1671
+ }
1672
+ this.syncSwipeBackDepth();
1588
1673
  this.lastNavigationHref = currentHref;
1674
+ this.lastNavigationPosition = currentPosition;
1589
1675
  return;
1590
1676
  }
1591
- if (direction === "forward" || direction === "none") {
1677
+ if (direction === "forward") {
1592
1678
  const hrefChanged = currentHref === null || this.lastNavigationHref === null || currentHref !== this.lastNavigationHref;
1593
1679
  if (options.forceForward || hrefChanged) {
1594
- this.swipeBackDepth += 1;
1680
+ this.navigationHrefs.push(currentHref);
1681
+ } else if (this.navigationHrefs.length === 0) {
1682
+ this.navigationHrefs = [currentHref];
1595
1683
  }
1684
+ this.syncSwipeBackDepth();
1596
1685
  this.lastNavigationHref = currentHref;
1686
+ this.lastNavigationPosition = currentPosition;
1597
1687
  return;
1598
1688
  }
1599
1689
  this.lastNavigationHref = currentHref;
1690
+ this.lastNavigationPosition = currentPosition;
1691
+ }
1692
+ resetNavigationDepth(currentHref, currentPosition) {
1693
+ this.navigationHrefs = [currentHref];
1694
+ this.swipeBackDepth = 0;
1695
+ this.lastNavigationHref = currentHref;
1696
+ this.lastNavigationPosition = currentPosition;
1697
+ }
1698
+ recordBackNavigation(currentHref) {
1699
+ const existingHrefIndex = this.findNavigationHrefIndex(currentHref, this.navigationHrefs.length - 2);
1700
+ if (existingHrefIndex !== -1) {
1701
+ this.navigationHrefs = this.navigationHrefs.slice(0, existingHrefIndex + 1);
1702
+ } else if (this.navigationHrefs.length > 1) {
1703
+ this.navigationHrefs.pop();
1704
+ this.navigationHrefs[this.navigationHrefs.length - 1] = currentHref;
1705
+ } else {
1706
+ this.navigationHrefs = [currentHref];
1707
+ }
1708
+ this.syncSwipeBackDepth();
1709
+ this.lastNavigationHref = currentHref;
1710
+ }
1711
+ findNavigationHrefIndex(href, fromIndex) {
1712
+ for (let index = Math.min(fromIndex, this.navigationHrefs.length - 1); index >= 0; index -= 1) {
1713
+ if (this.navigationHrefs[index] === href) {
1714
+ return index;
1715
+ }
1716
+ }
1717
+ return -1;
1718
+ }
1719
+ syncSwipeBackDepth() {
1720
+ this.swipeBackDepth = Math.max(0, this.navigationHrefs.length - 1);
1721
+ }
1722
+ getSwipeBackDestination() {
1723
+ const stack = this.controller.stack;
1724
+ if (this.swipeBackDepth <= 0 || stack.length <= 1) {
1725
+ return null;
1726
+ }
1727
+ return stack[stack.length - 2] ?? null;
1600
1728
  }
1601
1729
  canStartSwipeGesture(event) {
1602
- if (!this.isSwipeGestureEnabled() || this.controller.animating || this.pendingPage || !this.canGoBack) {
1730
+ if (!this.isSwipeGestureEnabled() || this.controller.animating || this.pendingPage || !this.getSwipeBackDestination()) {
1603
1731
  return false;
1604
1732
  }
1605
1733
  if (!event.isPrimary || event.pointerType === "mouse" && event.button !== 0) {
@@ -1686,6 +1814,10 @@ var CapRouterOutlet = class extends HTMLElement {
1686
1814
  return;
1687
1815
  }
1688
1816
  if (!pointer.dragging && deltaX > this.swipeGestureThreshold && absX > absY) {
1817
+ if (!this.getSwipeBackDestination()) {
1818
+ this.cancelSwipeGesturePointer(event.pointerId);
1819
+ return;
1820
+ }
1689
1821
  pointer.dragging = true;
1690
1822
  pointer.transitionStarted = this.controller.beginInteractiveBack({ direction: "back" });
1691
1823
  if (!pointer.transitionStarted) {
@@ -1694,6 +1826,10 @@ var CapRouterOutlet = class extends HTMLElement {
1694
1826
  }
1695
1827
  }
1696
1828
  if (pointer.dragging && pointer.transitionStarted) {
1829
+ if (!this.getSwipeBackDestination()) {
1830
+ this.cancelSwipeGesture(event.pointerId);
1831
+ return;
1832
+ }
1697
1833
  if (event.cancelable) event.preventDefault();
1698
1834
  const width = Math.max(this.getBoundingClientRect().width, 1);
1699
1835
  this.controller.stepInteractiveBack(deltaX / width);
@@ -1745,9 +1881,10 @@ var CapRouterOutlet = class extends HTMLElement {
1745
1881
  }
1746
1882
  }
1747
1883
  async finishSwipeGestureBack(shouldComplete, releaseDuration) {
1748
- const shouldUseHistory = shouldComplete && typeof window !== "undefined" && window.history.length > 1;
1749
- await this.controller.endInteractiveBack(shouldComplete, releaseDuration, !shouldUseHistory);
1750
- if (!shouldComplete) {
1884
+ const canComplete = shouldComplete && this.getSwipeBackDestination() !== null;
1885
+ const shouldUseHistory = canComplete && typeof window !== "undefined" && window.history.length > 1;
1886
+ await this.controller.endInteractiveBack(canComplete, canComplete ? releaseDuration : 0, !shouldUseHistory);
1887
+ if (!canComplete) {
1751
1888
  return;
1752
1889
  }
1753
1890
  if (shouldUseHistory) {