@hotwired/turbo 7.2.0-rc.1 → 7.2.0-rc.3

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.
@@ -1,5 +1,5 @@
1
1
  /*
2
- Turbo 7.2.0-rc.1
2
+ Turbo 7.2.0-rc.3
3
3
  Copyright © 2022 Basecamp, LLC
4
4
  */
5
5
  (function () {
@@ -448,9 +448,6 @@ function getVisitAction(...elements) {
448
448
  const action = getAttribute("data-turbo-action", ...elements);
449
449
  return isAction(action) ? action : null;
450
450
  }
451
- function getBodyElementId() {
452
- return getMetaContent("turbo-body");
453
- }
454
451
  function getMetaElement(name) {
455
452
  return document.querySelector(`meta[name="${name}"]`);
456
453
  }
@@ -526,7 +523,9 @@ class FetchRequest {
526
523
  }
527
524
  catch (error) {
528
525
  if (error.name !== "AbortError") {
529
- this.delegate.requestErrored(this, error);
526
+ if (this.willDelegateErrorHandling(error)) {
527
+ this.delegate.requestErrored(this, error);
528
+ }
530
529
  throw error;
531
530
  }
532
531
  }
@@ -592,6 +591,14 @@ class FetchRequest {
592
591
  if (event.defaultPrevented)
593
592
  await requestInterception;
594
593
  }
594
+ willDelegateErrorHandling(error) {
595
+ const event = dispatch("turbo:fetch-request-error", {
596
+ target: this.target,
597
+ cancelable: true,
598
+ detail: { request: this, error: error },
599
+ });
600
+ return !event.defaultPrevented;
601
+ }
595
602
  }
596
603
 
597
604
  class AppearanceObserver {
@@ -789,10 +796,6 @@ class FormSubmission {
789
796
  }
790
797
  requestErrored(request, error) {
791
798
  this.result = { success: false, error };
792
- dispatch("turbo:fetch-request-error", {
793
- target: this.formElement,
794
- detail: { request, error },
795
- });
796
799
  this.delegate.formSubmissionErrored(this, error);
797
800
  }
798
801
  requestFinished(_request) {
@@ -1622,7 +1625,6 @@ const defaultOptions = {
1622
1625
  updateHistory: true,
1623
1626
  shouldCacheSnapshot: true,
1624
1627
  acceptsStreamResponse: false,
1625
- initiator: document.documentElement,
1626
1628
  };
1627
1629
  var SystemStatusCode;
1628
1630
  (function (SystemStatusCode) {
@@ -1632,6 +1634,7 @@ var SystemStatusCode;
1632
1634
  })(SystemStatusCode || (SystemStatusCode = {}));
1633
1635
  class Visit {
1634
1636
  constructor(delegate, location, restorationIdentifier, options = {}) {
1637
+ this.identifier = uuid();
1635
1638
  this.timingMetrics = {};
1636
1639
  this.followedRedirect = false;
1637
1640
  this.historyChanged = false;
@@ -1643,8 +1646,7 @@ class Visit {
1643
1646
  this.delegate = delegate;
1644
1647
  this.location = location;
1645
1648
  this.restorationIdentifier = restorationIdentifier || uuid();
1646
- this.promise = new Promise((resolve, reject) => (this.resolvingFunctions = { resolve, reject }));
1647
- const { action, historyChanged, referrer, snapshotHTML, response, visitCachedSnapshot, willRender, updateHistory, shouldCacheSnapshot, acceptsStreamResponse, initiator, } = Object.assign(Object.assign({}, defaultOptions), options);
1649
+ const { action, historyChanged, referrer, snapshotHTML, response, visitCachedSnapshot, willRender, updateHistory, shouldCacheSnapshot, acceptsStreamResponse, } = Object.assign(Object.assign({}, defaultOptions), options);
1648
1650
  this.action = action;
1649
1651
  this.historyChanged = historyChanged;
1650
1652
  this.referrer = referrer;
@@ -1657,7 +1659,6 @@ class Visit {
1657
1659
  this.scrolled = !willRender;
1658
1660
  this.shouldCacheSnapshot = shouldCacheSnapshot;
1659
1661
  this.acceptsStreamResponse = acceptsStreamResponse;
1660
- this.initiator = initiator;
1661
1662
  }
1662
1663
  get adapter() {
1663
1664
  return this.delegate.adapter;
@@ -1689,7 +1690,6 @@ class Visit {
1689
1690
  }
1690
1691
  this.cancelRender();
1691
1692
  this.state = VisitState.canceled;
1692
- this.resolvingFunctions.reject();
1693
1693
  }
1694
1694
  }
1695
1695
  complete() {
@@ -1701,14 +1701,12 @@ class Visit {
1701
1701
  this.adapter.visitCompleted(this);
1702
1702
  this.delegate.visitCompleted(this);
1703
1703
  }
1704
- this.resolvingFunctions.resolve();
1705
1704
  }
1706
1705
  }
1707
1706
  fail() {
1708
1707
  if (this.state == VisitState.started) {
1709
1708
  this.state = VisitState.failed;
1710
1709
  this.adapter.visitFailed(this);
1711
- this.resolvingFunctions.reject();
1712
1710
  }
1713
1711
  }
1714
1712
  changeHistory() {
@@ -1725,7 +1723,7 @@ class Visit {
1725
1723
  this.simulateRequest();
1726
1724
  }
1727
1725
  else if (this.shouldIssueRequest() && !this.request) {
1728
- this.request = new FetchRequest(this, FetchMethod.get, this.location, undefined, this.initiator);
1726
+ this.request = new FetchRequest(this, FetchMethod.get, this.location);
1729
1727
  this.request.perform();
1730
1728
  }
1731
1729
  }
@@ -1971,7 +1969,7 @@ class BrowserAdapter {
1971
1969
  this.session = session;
1972
1970
  }
1973
1971
  visitProposedToLocation(location, options) {
1974
- return this.navigator.startVisit(location, (options === null || options === void 0 ? void 0 : options.restorationIdentifier) || uuid(), options);
1972
+ this.navigator.startVisit(location, (options === null || options === void 0 ? void 0 : options.restorationIdentifier) || uuid(), options);
1975
1973
  }
1976
1974
  visitStarted(visit) {
1977
1975
  this.location = visit.location;
@@ -2230,25 +2228,20 @@ class Navigator {
2230
2228
  this.delegate = delegate;
2231
2229
  }
2232
2230
  proposeVisit(location, options = {}) {
2233
- if (this.delegate.allowsVisitingLocation(location, options)) {
2231
+ if (this.delegate.allowsVisitingLocationWithAction(location, options.action)) {
2234
2232
  if (locationIsVisitable(location, this.view.snapshot.rootLocation)) {
2235
- return this.delegate.visitProposedToLocation(location, options);
2233
+ this.delegate.visitProposedToLocation(location, options);
2236
2234
  }
2237
2235
  else {
2238
2236
  window.location.href = location.toString();
2239
- return Promise.resolve();
2240
2237
  }
2241
2238
  }
2242
- else {
2243
- return Promise.reject();
2244
- }
2245
2239
  }
2246
2240
  startVisit(locatable, restorationIdentifier, options = {}) {
2247
2241
  this.lastVisit = this.currentVisit;
2248
2242
  this.stop();
2249
2243
  this.currentVisit = new Visit(this, expandURL(locatable), restorationIdentifier, Object.assign({ referrer: this.location }, options));
2250
2244
  this.currentVisit.start();
2251
- return this.currentVisit.promise;
2252
2245
  }
2253
2246
  submitForm(form, submitter) {
2254
2247
  this.stop();
@@ -2562,19 +2555,16 @@ class ErrorRenderer extends Renderer {
2562
2555
  }
2563
2556
 
2564
2557
  class PageRenderer extends Renderer {
2565
- static async renderElement(currentElement, newElement) {
2566
- await nextEventLoopTick();
2558
+ static renderElement(currentElement, newElement) {
2567
2559
  if (document.body && newElement instanceof HTMLBodyElement) {
2568
- const currentBody = PageRenderer.getBodyElement(currentElement);
2569
- const newBody = PageRenderer.getBodyElement(newElement);
2570
- currentBody.replaceWith(newBody);
2560
+ document.body.replaceWith(newElement);
2571
2561
  }
2572
2562
  else {
2573
2563
  document.documentElement.appendChild(newElement);
2574
2564
  }
2575
2565
  }
2576
2566
  get shouldRender() {
2577
- return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical && this.bodyElementMatches;
2567
+ return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical;
2578
2568
  }
2579
2569
  get reloadReason() {
2580
2570
  if (!this.newSnapshot.isVisitable) {
@@ -2587,11 +2577,6 @@ class PageRenderer extends Renderer {
2587
2577
  reason: "tracked_element_mismatch",
2588
2578
  };
2589
2579
  }
2590
- if (!this.bodyElementMatches) {
2591
- return {
2592
- reason: "body_element_mismatch",
2593
- };
2594
- }
2595
2580
  }
2596
2581
  async prepareToRender() {
2597
2582
  await this.mergeHead();
@@ -2632,16 +2617,6 @@ class PageRenderer extends Renderer {
2632
2617
  get trackedElementsAreIdentical() {
2633
2618
  return this.currentHeadSnapshot.trackedElementSignature == this.newHeadSnapshot.trackedElementSignature;
2634
2619
  }
2635
- get bodyElementMatches() {
2636
- return PageRenderer.getBodyElement(this.newElement) !== null;
2637
- }
2638
- static get bodySelector() {
2639
- const bodyId = getBodyElementId();
2640
- return bodyId ? `#${bodyId}` : "body";
2641
- }
2642
- static getBodyElement(element) {
2643
- return element.querySelector(this.bodySelector) || element;
2644
- }
2645
2620
  async copyNewHeadStylesheetElements() {
2646
2621
  const loadingElements = [];
2647
2622
  for (const element of this.newHeadStylesheetElements) {
@@ -2887,10 +2862,10 @@ class Session {
2887
2862
  const frameElement = options.frame ? document.getElementById(options.frame) : null;
2888
2863
  if (frameElement instanceof FrameElement) {
2889
2864
  frameElement.src = location.toString();
2890
- return frameElement.loaded;
2865
+ frameElement.loaded;
2891
2866
  }
2892
2867
  else {
2893
- return this.navigator.proposeVisit(expandURL(location), options);
2868
+ this.navigator.proposeVisit(expandURL(location), options);
2894
2869
  }
2895
2870
  }
2896
2871
  connectStreamSource(source) {
@@ -2945,15 +2920,14 @@ class Session {
2945
2920
  followedLinkToLocation(link, location) {
2946
2921
  const action = this.getActionForLink(link);
2947
2922
  const acceptsStreamResponse = link.hasAttribute("data-turbo-stream");
2948
- this.visit(location.href, { action, acceptsStreamResponse, initiator: link });
2923
+ this.visit(location.href, { action, acceptsStreamResponse });
2949
2924
  }
2950
- allowsVisitingLocation(location, options = {}) {
2951
- return (this.locationWithActionIsSamePage(location, options.action) ||
2952
- this.applicationAllowsVisitingLocation(location, options));
2925
+ allowsVisitingLocationWithAction(location, action) {
2926
+ return this.locationWithActionIsSamePage(location, action) || this.applicationAllowsVisitingLocation(location);
2953
2927
  }
2954
2928
  visitProposedToLocation(location, options) {
2955
2929
  extendURLWithDeprecatedProperties(location);
2956
- return this.adapter.visitProposedToLocation(location, options);
2930
+ this.adapter.visitProposedToLocation(location, options);
2957
2931
  }
2958
2932
  visitStarted(visit) {
2959
2933
  if (!visit.acceptsStreamResponse) {
@@ -2961,7 +2935,7 @@ class Session {
2961
2935
  }
2962
2936
  extendURLWithDeprecatedProperties(visit.location);
2963
2937
  if (!visit.silent) {
2964
- this.notifyApplicationAfterVisitingLocation(visit.location, visit.action, visit.initiator);
2938
+ this.notifyApplicationAfterVisitingLocation(visit.location, visit.action);
2965
2939
  }
2966
2940
  }
2967
2941
  visitCompleted(visit) {
@@ -3029,8 +3003,8 @@ class Session {
3029
3003
  const event = this.notifyApplicationAfterClickingLinkToLocation(link, location, ev);
3030
3004
  return !event.defaultPrevented;
3031
3005
  }
3032
- applicationAllowsVisitingLocation(location, options = {}) {
3033
- const event = this.notifyApplicationBeforeVisitingLocation(location, options.initiator);
3006
+ applicationAllowsVisitingLocation(location) {
3007
+ const event = this.notifyApplicationBeforeVisitingLocation(location);
3034
3008
  return !event.defaultPrevented;
3035
3009
  }
3036
3010
  notifyApplicationAfterClickingLinkToLocation(link, location, event) {
@@ -3040,18 +3014,14 @@ class Session {
3040
3014
  cancelable: true,
3041
3015
  });
3042
3016
  }
3043
- notifyApplicationBeforeVisitingLocation(location, element) {
3017
+ notifyApplicationBeforeVisitingLocation(location) {
3044
3018
  return dispatch("turbo:before-visit", {
3045
- target: element,
3046
3019
  detail: { url: location.href },
3047
3020
  cancelable: true,
3048
3021
  });
3049
3022
  }
3050
- notifyApplicationAfterVisitingLocation(location, action, element) {
3051
- return dispatch("turbo:visit", {
3052
- target: element,
3053
- detail: { url: location.href, action },
3054
- });
3023
+ notifyApplicationAfterVisitingLocation(location, action) {
3024
+ return dispatch("turbo:visit", { detail: { url: location.href, action } });
3055
3025
  }
3056
3026
  notifyApplicationBeforeCachingSnapshot() {
3057
3027
  return dispatch("turbo:before-cache");
@@ -3196,7 +3166,7 @@ function registerAdapter(adapter) {
3196
3166
  session.registerAdapter(adapter);
3197
3167
  }
3198
3168
  function visit(location, options) {
3199
- return session.visit(location, options);
3169
+ session.visit(location, options);
3200
3170
  }
3201
3171
  function connectStreamSource(source) {
3202
3172
  session.connectStreamSource(source);
@@ -3414,10 +3384,6 @@ class FrameController {
3414
3384
  }
3415
3385
  requestErrored(request, error) {
3416
3386
  console.error(error);
3417
- dispatch("turbo:fetch-request-error", {
3418
- target: this.element,
3419
- detail: { request, error },
3420
- });
3421
3387
  this.resolveVisitPromise();
3422
3388
  }
3423
3389
  requestFinished(_request) {
@@ -1,5 +1,5 @@
1
1
  /*
2
- Turbo 7.2.0-rc.1
2
+ Turbo 7.2.0-rc.3
3
3
  Copyright © 2022 Basecamp, LLC
4
4
  */
5
5
  (function (global, factory) {
@@ -454,9 +454,6 @@ Copyright © 2022 Basecamp, LLC
454
454
  const action = getAttribute("data-turbo-action", ...elements);
455
455
  return isAction(action) ? action : null;
456
456
  }
457
- function getBodyElementId() {
458
- return getMetaContent("turbo-body");
459
- }
460
457
  function getMetaElement(name) {
461
458
  return document.querySelector(`meta[name="${name}"]`);
462
459
  }
@@ -532,7 +529,9 @@ Copyright © 2022 Basecamp, LLC
532
529
  }
533
530
  catch (error) {
534
531
  if (error.name !== "AbortError") {
535
- this.delegate.requestErrored(this, error);
532
+ if (this.willDelegateErrorHandling(error)) {
533
+ this.delegate.requestErrored(this, error);
534
+ }
536
535
  throw error;
537
536
  }
538
537
  }
@@ -598,6 +597,14 @@ Copyright © 2022 Basecamp, LLC
598
597
  if (event.defaultPrevented)
599
598
  await requestInterception;
600
599
  }
600
+ willDelegateErrorHandling(error) {
601
+ const event = dispatch("turbo:fetch-request-error", {
602
+ target: this.target,
603
+ cancelable: true,
604
+ detail: { request: this, error: error },
605
+ });
606
+ return !event.defaultPrevented;
607
+ }
601
608
  }
602
609
 
603
610
  class AppearanceObserver {
@@ -795,10 +802,6 @@ Copyright © 2022 Basecamp, LLC
795
802
  }
796
803
  requestErrored(request, error) {
797
804
  this.result = { success: false, error };
798
- dispatch("turbo:fetch-request-error", {
799
- target: this.formElement,
800
- detail: { request, error },
801
- });
802
805
  this.delegate.formSubmissionErrored(this, error);
803
806
  }
804
807
  requestFinished(_request) {
@@ -1628,7 +1631,6 @@ Copyright © 2022 Basecamp, LLC
1628
1631
  updateHistory: true,
1629
1632
  shouldCacheSnapshot: true,
1630
1633
  acceptsStreamResponse: false,
1631
- initiator: document.documentElement,
1632
1634
  };
1633
1635
  var SystemStatusCode;
1634
1636
  (function (SystemStatusCode) {
@@ -1638,6 +1640,7 @@ Copyright © 2022 Basecamp, LLC
1638
1640
  })(SystemStatusCode || (SystemStatusCode = {}));
1639
1641
  class Visit {
1640
1642
  constructor(delegate, location, restorationIdentifier, options = {}) {
1643
+ this.identifier = uuid();
1641
1644
  this.timingMetrics = {};
1642
1645
  this.followedRedirect = false;
1643
1646
  this.historyChanged = false;
@@ -1649,8 +1652,7 @@ Copyright © 2022 Basecamp, LLC
1649
1652
  this.delegate = delegate;
1650
1653
  this.location = location;
1651
1654
  this.restorationIdentifier = restorationIdentifier || uuid();
1652
- this.promise = new Promise((resolve, reject) => (this.resolvingFunctions = { resolve, reject }));
1653
- const { action, historyChanged, referrer, snapshotHTML, response, visitCachedSnapshot, willRender, updateHistory, shouldCacheSnapshot, acceptsStreamResponse, initiator, } = Object.assign(Object.assign({}, defaultOptions), options);
1655
+ const { action, historyChanged, referrer, snapshotHTML, response, visitCachedSnapshot, willRender, updateHistory, shouldCacheSnapshot, acceptsStreamResponse, } = Object.assign(Object.assign({}, defaultOptions), options);
1654
1656
  this.action = action;
1655
1657
  this.historyChanged = historyChanged;
1656
1658
  this.referrer = referrer;
@@ -1663,7 +1665,6 @@ Copyright © 2022 Basecamp, LLC
1663
1665
  this.scrolled = !willRender;
1664
1666
  this.shouldCacheSnapshot = shouldCacheSnapshot;
1665
1667
  this.acceptsStreamResponse = acceptsStreamResponse;
1666
- this.initiator = initiator;
1667
1668
  }
1668
1669
  get adapter() {
1669
1670
  return this.delegate.adapter;
@@ -1695,7 +1696,6 @@ Copyright © 2022 Basecamp, LLC
1695
1696
  }
1696
1697
  this.cancelRender();
1697
1698
  this.state = VisitState.canceled;
1698
- this.resolvingFunctions.reject();
1699
1699
  }
1700
1700
  }
1701
1701
  complete() {
@@ -1707,14 +1707,12 @@ Copyright © 2022 Basecamp, LLC
1707
1707
  this.adapter.visitCompleted(this);
1708
1708
  this.delegate.visitCompleted(this);
1709
1709
  }
1710
- this.resolvingFunctions.resolve();
1711
1710
  }
1712
1711
  }
1713
1712
  fail() {
1714
1713
  if (this.state == VisitState.started) {
1715
1714
  this.state = VisitState.failed;
1716
1715
  this.adapter.visitFailed(this);
1717
- this.resolvingFunctions.reject();
1718
1716
  }
1719
1717
  }
1720
1718
  changeHistory() {
@@ -1731,7 +1729,7 @@ Copyright © 2022 Basecamp, LLC
1731
1729
  this.simulateRequest();
1732
1730
  }
1733
1731
  else if (this.shouldIssueRequest() && !this.request) {
1734
- this.request = new FetchRequest(this, FetchMethod.get, this.location, undefined, this.initiator);
1732
+ this.request = new FetchRequest(this, FetchMethod.get, this.location);
1735
1733
  this.request.perform();
1736
1734
  }
1737
1735
  }
@@ -1977,7 +1975,7 @@ Copyright © 2022 Basecamp, LLC
1977
1975
  this.session = session;
1978
1976
  }
1979
1977
  visitProposedToLocation(location, options) {
1980
- return this.navigator.startVisit(location, (options === null || options === void 0 ? void 0 : options.restorationIdentifier) || uuid(), options);
1978
+ this.navigator.startVisit(location, (options === null || options === void 0 ? void 0 : options.restorationIdentifier) || uuid(), options);
1981
1979
  }
1982
1980
  visitStarted(visit) {
1983
1981
  this.location = visit.location;
@@ -2236,25 +2234,20 @@ Copyright © 2022 Basecamp, LLC
2236
2234
  this.delegate = delegate;
2237
2235
  }
2238
2236
  proposeVisit(location, options = {}) {
2239
- if (this.delegate.allowsVisitingLocation(location, options)) {
2237
+ if (this.delegate.allowsVisitingLocationWithAction(location, options.action)) {
2240
2238
  if (locationIsVisitable(location, this.view.snapshot.rootLocation)) {
2241
- return this.delegate.visitProposedToLocation(location, options);
2239
+ this.delegate.visitProposedToLocation(location, options);
2242
2240
  }
2243
2241
  else {
2244
2242
  window.location.href = location.toString();
2245
- return Promise.resolve();
2246
2243
  }
2247
2244
  }
2248
- else {
2249
- return Promise.reject();
2250
- }
2251
2245
  }
2252
2246
  startVisit(locatable, restorationIdentifier, options = {}) {
2253
2247
  this.lastVisit = this.currentVisit;
2254
2248
  this.stop();
2255
2249
  this.currentVisit = new Visit(this, expandURL(locatable), restorationIdentifier, Object.assign({ referrer: this.location }, options));
2256
2250
  this.currentVisit.start();
2257
- return this.currentVisit.promise;
2258
2251
  }
2259
2252
  submitForm(form, submitter) {
2260
2253
  this.stop();
@@ -2568,19 +2561,16 @@ Copyright © 2022 Basecamp, LLC
2568
2561
  }
2569
2562
 
2570
2563
  class PageRenderer extends Renderer {
2571
- static async renderElement(currentElement, newElement) {
2572
- await nextEventLoopTick();
2564
+ static renderElement(currentElement, newElement) {
2573
2565
  if (document.body && newElement instanceof HTMLBodyElement) {
2574
- const currentBody = PageRenderer.getBodyElement(currentElement);
2575
- const newBody = PageRenderer.getBodyElement(newElement);
2576
- currentBody.replaceWith(newBody);
2566
+ document.body.replaceWith(newElement);
2577
2567
  }
2578
2568
  else {
2579
2569
  document.documentElement.appendChild(newElement);
2580
2570
  }
2581
2571
  }
2582
2572
  get shouldRender() {
2583
- return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical && this.bodyElementMatches;
2573
+ return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical;
2584
2574
  }
2585
2575
  get reloadReason() {
2586
2576
  if (!this.newSnapshot.isVisitable) {
@@ -2593,11 +2583,6 @@ Copyright © 2022 Basecamp, LLC
2593
2583
  reason: "tracked_element_mismatch",
2594
2584
  };
2595
2585
  }
2596
- if (!this.bodyElementMatches) {
2597
- return {
2598
- reason: "body_element_mismatch",
2599
- };
2600
- }
2601
2586
  }
2602
2587
  async prepareToRender() {
2603
2588
  await this.mergeHead();
@@ -2638,16 +2623,6 @@ Copyright © 2022 Basecamp, LLC
2638
2623
  get trackedElementsAreIdentical() {
2639
2624
  return this.currentHeadSnapshot.trackedElementSignature == this.newHeadSnapshot.trackedElementSignature;
2640
2625
  }
2641
- get bodyElementMatches() {
2642
- return PageRenderer.getBodyElement(this.newElement) !== null;
2643
- }
2644
- static get bodySelector() {
2645
- const bodyId = getBodyElementId();
2646
- return bodyId ? `#${bodyId}` : "body";
2647
- }
2648
- static getBodyElement(element) {
2649
- return element.querySelector(this.bodySelector) || element;
2650
- }
2651
2626
  async copyNewHeadStylesheetElements() {
2652
2627
  const loadingElements = [];
2653
2628
  for (const element of this.newHeadStylesheetElements) {
@@ -2893,10 +2868,10 @@ Copyright © 2022 Basecamp, LLC
2893
2868
  const frameElement = options.frame ? document.getElementById(options.frame) : null;
2894
2869
  if (frameElement instanceof FrameElement) {
2895
2870
  frameElement.src = location.toString();
2896
- return frameElement.loaded;
2871
+ frameElement.loaded;
2897
2872
  }
2898
2873
  else {
2899
- return this.navigator.proposeVisit(expandURL(location), options);
2874
+ this.navigator.proposeVisit(expandURL(location), options);
2900
2875
  }
2901
2876
  }
2902
2877
  connectStreamSource(source) {
@@ -2951,15 +2926,14 @@ Copyright © 2022 Basecamp, LLC
2951
2926
  followedLinkToLocation(link, location) {
2952
2927
  const action = this.getActionForLink(link);
2953
2928
  const acceptsStreamResponse = link.hasAttribute("data-turbo-stream");
2954
- this.visit(location.href, { action, acceptsStreamResponse, initiator: link });
2929
+ this.visit(location.href, { action, acceptsStreamResponse });
2955
2930
  }
2956
- allowsVisitingLocation(location, options = {}) {
2957
- return (this.locationWithActionIsSamePage(location, options.action) ||
2958
- this.applicationAllowsVisitingLocation(location, options));
2931
+ allowsVisitingLocationWithAction(location, action) {
2932
+ return this.locationWithActionIsSamePage(location, action) || this.applicationAllowsVisitingLocation(location);
2959
2933
  }
2960
2934
  visitProposedToLocation(location, options) {
2961
2935
  extendURLWithDeprecatedProperties(location);
2962
- return this.adapter.visitProposedToLocation(location, options);
2936
+ this.adapter.visitProposedToLocation(location, options);
2963
2937
  }
2964
2938
  visitStarted(visit) {
2965
2939
  if (!visit.acceptsStreamResponse) {
@@ -2967,7 +2941,7 @@ Copyright © 2022 Basecamp, LLC
2967
2941
  }
2968
2942
  extendURLWithDeprecatedProperties(visit.location);
2969
2943
  if (!visit.silent) {
2970
- this.notifyApplicationAfterVisitingLocation(visit.location, visit.action, visit.initiator);
2944
+ this.notifyApplicationAfterVisitingLocation(visit.location, visit.action);
2971
2945
  }
2972
2946
  }
2973
2947
  visitCompleted(visit) {
@@ -3035,8 +3009,8 @@ Copyright © 2022 Basecamp, LLC
3035
3009
  const event = this.notifyApplicationAfterClickingLinkToLocation(link, location, ev);
3036
3010
  return !event.defaultPrevented;
3037
3011
  }
3038
- applicationAllowsVisitingLocation(location, options = {}) {
3039
- const event = this.notifyApplicationBeforeVisitingLocation(location, options.initiator);
3012
+ applicationAllowsVisitingLocation(location) {
3013
+ const event = this.notifyApplicationBeforeVisitingLocation(location);
3040
3014
  return !event.defaultPrevented;
3041
3015
  }
3042
3016
  notifyApplicationAfterClickingLinkToLocation(link, location, event) {
@@ -3046,18 +3020,14 @@ Copyright © 2022 Basecamp, LLC
3046
3020
  cancelable: true,
3047
3021
  });
3048
3022
  }
3049
- notifyApplicationBeforeVisitingLocation(location, element) {
3023
+ notifyApplicationBeforeVisitingLocation(location) {
3050
3024
  return dispatch("turbo:before-visit", {
3051
- target: element,
3052
3025
  detail: { url: location.href },
3053
3026
  cancelable: true,
3054
3027
  });
3055
3028
  }
3056
- notifyApplicationAfterVisitingLocation(location, action, element) {
3057
- return dispatch("turbo:visit", {
3058
- target: element,
3059
- detail: { url: location.href, action },
3060
- });
3029
+ notifyApplicationAfterVisitingLocation(location, action) {
3030
+ return dispatch("turbo:visit", { detail: { url: location.href, action } });
3061
3031
  }
3062
3032
  notifyApplicationBeforeCachingSnapshot() {
3063
3033
  return dispatch("turbo:before-cache");
@@ -3202,7 +3172,7 @@ Copyright © 2022 Basecamp, LLC
3202
3172
  session.registerAdapter(adapter);
3203
3173
  }
3204
3174
  function visit(location, options) {
3205
- return session.visit(location, options);
3175
+ session.visit(location, options);
3206
3176
  }
3207
3177
  function connectStreamSource(source) {
3208
3178
  session.connectStreamSource(source);
@@ -3420,10 +3390,6 @@ Copyright © 2022 Basecamp, LLC
3420
3390
  }
3421
3391
  requestErrored(request, error) {
3422
3392
  console.error(error);
3423
- dispatch("turbo:fetch-request-error", {
3424
- target: this.element,
3425
- detail: { request, error },
3426
- });
3427
3393
  this.resolveVisitPromise();
3428
3394
  }
3429
3395
  requestFinished(_request) {
@@ -4,8 +4,8 @@ import { FormSubmission } from "./form_submission";
4
4
  import { Locatable } from "../url";
5
5
  import { Visit, VisitDelegate, VisitOptions } from "./visit";
6
6
  export declare type NavigatorDelegate = VisitDelegate & {
7
- allowsVisitingLocation(location: URL, options: Partial<VisitOptions>): boolean;
8
- visitProposedToLocation(location: URL, options: Partial<VisitOptions>): Promise<void>;
7
+ allowsVisitingLocationWithAction(location: URL, action?: Action): boolean;
8
+ visitProposedToLocation(location: URL, options: Partial<VisitOptions>): void;
9
9
  notifyApplicationAfterVisitingSamePageLocation(oldURL: URL, newURL: URL): void;
10
10
  };
11
11
  export declare class Navigator {
@@ -14,8 +14,8 @@ export declare class Navigator {
14
14
  currentVisit?: Visit;
15
15
  lastVisit?: Visit;
16
16
  constructor(delegate: NavigatorDelegate);
17
- proposeVisit(location: URL, options?: Partial<VisitOptions>): Promise<void>;
18
- startVisit(locatable: Locatable, restorationIdentifier: string, options?: Partial<VisitOptions>): Promise<void>;
17
+ proposeVisit(location: URL, options?: Partial<VisitOptions>): void;
18
+ startVisit(locatable: Locatable, restorationIdentifier: string, options?: Partial<VisitOptions>): void;
19
19
  submitForm(form: HTMLFormElement, submitter?: HTMLElement): void;
20
20
  stop(): void;
21
21
  get adapter(): import("../native/adapter").Adapter;
@@ -2,7 +2,7 @@ import { Renderer } from "../renderer";
2
2
  import { PageSnapshot } from "./page_snapshot";
3
3
  import { ReloadReason } from "../native/browser_adapter";
4
4
  export declare class PageRenderer extends Renderer<HTMLBodyElement, PageSnapshot> {
5
- static renderElement(currentElement: HTMLBodyElement, newElement: HTMLBodyElement): Promise<void>;
5
+ static renderElement(currentElement: HTMLBodyElement, newElement: HTMLBodyElement): void;
6
6
  get shouldRender(): boolean;
7
7
  get reloadReason(): ReloadReason;
8
8
  prepareToRender(): Promise<void>;
@@ -14,9 +14,6 @@ export declare class PageRenderer extends Renderer<HTMLBodyElement, PageSnapshot
14
14
  mergeHead(): Promise<void>;
15
15
  replaceBody(): void;
16
16
  get trackedElementsAreIdentical(): boolean;
17
- get bodyElementMatches(): boolean;
18
- static get bodySelector(): string;
19
- static getBodyElement(element: HTMLElement): HTMLElement;
20
17
  copyNewHeadStylesheetElements(): Promise<void>;
21
18
  copyNewHeadScriptElements(): void;
22
19
  removeCurrentHeadProvisionalElements(): void;
@@ -44,7 +44,6 @@ export declare type VisitOptions = {
44
44
  shouldCacheSnapshot: boolean;
45
45
  frame?: string;
46
46
  acceptsStreamResponse: boolean;
47
- initiator: Element;
48
47
  };
49
48
  export declare type VisitResponse = {
50
49
  statusCode: number;
@@ -58,6 +57,7 @@ export declare enum SystemStatusCode {
58
57
  }
59
58
  export declare class Visit implements FetchRequestDelegate {
60
59
  readonly delegate: VisitDelegate;
60
+ readonly identifier: string;
61
61
  readonly restorationIdentifier: string;
62
62
  readonly action: Action;
63
63
  readonly referrer?: URL;
@@ -65,9 +65,6 @@ export declare class Visit implements FetchRequestDelegate {
65
65
  readonly visitCachedSnapshot: (snapshot: Snapshot) => void;
66
66
  readonly willRender: boolean;
67
67
  readonly updateHistory: boolean;
68
- readonly promise: Promise<void>;
69
- readonly initiator: Element;
70
- private resolvingFunctions;
71
68
  followedRedirect: boolean;
72
69
  frame?: number;
73
70
  historyChanged: boolean;
@@ -12,13 +12,13 @@ declare const session: Session;
12
12
  declare const cache: Cache;
13
13
  declare const navigator: import("./drive/navigator").Navigator;
14
14
  export { navigator, session, cache, PageRenderer, PageSnapshot, FrameRenderer };
15
- export { TurboBeforeCacheEvent, TurboBeforeRenderEvent, TurboBeforeVisitEvent, TurboClickEvent, TurboFetchRequestErrorEvent, TurboFrameLoadEvent, TurboFrameRenderEvent, TurboLoadEvent, TurboRenderEvent, TurboVisitEvent, } from "./session";
15
+ export { TurboBeforeCacheEvent, TurboBeforeRenderEvent, TurboBeforeVisitEvent, TurboClickEvent, TurboBeforeFrameRenderEvent, TurboFrameLoadEvent, TurboFrameRenderEvent, TurboLoadEvent, TurboRenderEvent, TurboVisitEvent, } from "./session";
16
16
  export { TurboSubmitStartEvent, TurboSubmitEndEvent } from "./drive/form_submission";
17
17
  export { TurboFrameMissingEvent } from "./frames/frame_controller";
18
18
  export { StreamActions, TurboStreamAction, TurboStreamActions } from "./streams/stream_actions";
19
19
  export declare function start(): void;
20
20
  export declare function registerAdapter(adapter: Adapter): void;
21
- export declare function visit(location: Locatable, options?: Partial<VisitOptions>): Promise<void>;
21
+ export declare function visit(location: Locatable, options?: Partial<VisitOptions>): void;
22
22
  export declare function connectStreamSource(source: StreamSource): void;
23
23
  export declare function disconnectStreamSource(source: StreamSource): void;
24
24
  export declare function renderStreamMessage(message: StreamMessage | string): void;
@@ -2,7 +2,7 @@ import { Visit, VisitOptions } from "../drive/visit";
2
2
  import { FormSubmission } from "../drive/form_submission";
3
3
  import { ReloadReason } from "./browser_adapter";
4
4
  export interface Adapter {
5
- visitProposedToLocation(location: URL, options?: Partial<VisitOptions>): Promise<void>;
5
+ visitProposedToLocation(location: URL, options?: Partial<VisitOptions>): void;
6
6
  visitStarted(visit: Visit): void;
7
7
  visitCompleted(visit: Visit): void;
8
8
  visitFailed(visit: Visit): void;
@@ -17,7 +17,7 @@ export declare class BrowserAdapter implements Adapter {
17
17
  formProgressBarTimeout?: number;
18
18
  location?: URL;
19
19
  constructor(session: Session);
20
- visitProposedToLocation(location: URL, options?: Partial<VisitOptions>): Promise<void>;
20
+ visitProposedToLocation(location: URL, options?: Partial<VisitOptions>): void;
21
21
  visitStarted(visit: Visit): void;
22
22
  visitRequestStarted(visit: Visit): void;
23
23
  visitRequestCompleted(visit: Visit): void;
@@ -21,7 +21,6 @@ import { FrameElement } from "../elements/frame_element";
21
21
  import { FrameViewRenderOptions } from "./frames/frame_view";
22
22
  import { FetchResponse } from "../http/fetch_response";
23
23
  import { Preloader, PreloaderDelegate } from "./drive/preloader";
24
- import { FetchRequest } from "../http/fetch_request";
25
24
  export declare type FormMode = "on" | "off" | "optin";
26
25
  export declare type TimingData = unknown;
27
26
  export declare type TurboBeforeCacheEvent = CustomEvent;
@@ -39,10 +38,6 @@ export declare type TurboFrameLoadEvent = CustomEvent;
39
38
  export declare type TurboBeforeFrameRenderEvent = CustomEvent<{
40
39
  newFrame: FrameElement;
41
40
  } & FrameViewRenderOptions>;
42
- export declare type TurboFetchRequestErrorEvent = CustomEvent<{
43
- request: FetchRequest;
44
- error: Error;
45
- }>;
46
41
  export declare type TurboFrameRenderEvent = CustomEvent<{
47
42
  fetchResponse: FetchResponse;
48
43
  }>;
@@ -79,7 +74,7 @@ export declare class Session implements FormSubmitObserverDelegate, HistoryDeleg
79
74
  disable(): void;
80
75
  stop(): void;
81
76
  registerAdapter(adapter: Adapter): void;
82
- visit(location: Locatable, options?: Partial<VisitOptions>): Promise<void>;
77
+ visit(location: Locatable, options?: Partial<VisitOptions>): void;
83
78
  connectStreamSource(source: StreamSource): void;
84
79
  disconnectStreamSource(source: StreamSource): void;
85
80
  renderStreamMessage(message: StreamMessage | string): void;
@@ -94,8 +89,8 @@ export declare class Session implements FormSubmitObserverDelegate, HistoryDeleg
94
89
  submittedFormLinkToLocation(): void;
95
90
  willFollowLinkToLocation(link: Element, location: URL, event: MouseEvent): boolean;
96
91
  followedLinkToLocation(link: Element, location: URL): void;
97
- allowsVisitingLocation(location: URL, options?: Partial<VisitOptions>): boolean;
98
- visitProposedToLocation(location: URL, options: Partial<VisitOptions>): Promise<void>;
92
+ allowsVisitingLocationWithAction(location: URL, action?: Action): boolean;
93
+ visitProposedToLocation(location: URL, options: Partial<VisitOptions>): void;
99
94
  visitStarted(visit: Visit): void;
100
95
  visitCompleted(visit: Visit): void;
101
96
  locationWithActionIsSamePage(location: URL, action?: Action): boolean;
@@ -114,15 +109,15 @@ export declare class Session implements FormSubmitObserverDelegate, HistoryDeleg
114
109
  frameLoaded(frame: FrameElement): void;
115
110
  frameRendered(fetchResponse: FetchResponse, frame: FrameElement): void;
116
111
  applicationAllowsFollowingLinkToLocation(link: Element, location: URL, ev: MouseEvent): boolean;
117
- applicationAllowsVisitingLocation(location: URL, options?: Partial<VisitOptions>): boolean;
112
+ applicationAllowsVisitingLocation(location: URL): boolean;
118
113
  notifyApplicationAfterClickingLinkToLocation(link: Element, location: URL, event: MouseEvent): CustomEvent<{
119
114
  url: string;
120
115
  originalEvent: MouseEvent;
121
116
  }>;
122
- notifyApplicationBeforeVisitingLocation(location: URL, element?: Element): CustomEvent<{
117
+ notifyApplicationBeforeVisitingLocation(location: URL): CustomEvent<{
123
118
  url: string;
124
119
  }>;
125
- notifyApplicationAfterVisitingLocation(location: URL, action: Action, element?: Element): CustomEvent<{
120
+ notifyApplicationAfterVisitingLocation(location: URL, action: Action): CustomEvent<{
126
121
  url: string;
127
122
  action: Action;
128
123
  }>;
@@ -8,7 +8,3 @@ export declare type StreamSource = {
8
8
  addEventListener(type: "message", listener: (event: MessageEvent) => void, options?: boolean | AddEventListenerOptions): void;
9
9
  removeEventListener(type: "message", listener: (event: MessageEvent) => void, options?: boolean | EventListenerOptions): void;
10
10
  };
11
- export declare type ResolvingFunctions<T = unknown> = {
12
- resolve(value: T | PromiseLike<T>): void;
13
- reject(reason?: any): void;
14
- };
@@ -1,4 +1,5 @@
1
1
  import { FetchResponse } from "./fetch_response";
2
+ import { FrameElement } from "../elements/frame_element";
2
3
  export declare type TurboBeforeFetchRequestEvent = CustomEvent<{
3
4
  fetchOptions: RequestInit;
4
5
  url: URL;
@@ -7,6 +8,10 @@ export declare type TurboBeforeFetchRequestEvent = CustomEvent<{
7
8
  export declare type TurboBeforeFetchResponseEvent = CustomEvent<{
8
9
  fetchResponse: FetchResponse;
9
10
  }>;
11
+ export declare type TurboFetchRequestErrorEvent = CustomEvent<{
12
+ request: FetchRequest;
13
+ error: Error;
14
+ }>;
10
15
  export interface FetchRequestDelegate {
11
16
  referrer?: URL;
12
17
  prepareHeadersForRequest?(headers: FetchRequestHeaders, request: FetchRequest): void;
@@ -40,10 +45,10 @@ export declare class FetchRequest {
40
45
  readonly headers: FetchRequestHeaders;
41
46
  readonly url: URL;
42
47
  readonly body?: FetchRequestBody;
43
- readonly target?: Element | null;
48
+ readonly target?: FrameElement | HTMLFormElement | null;
44
49
  readonly abortController: AbortController;
45
50
  private resolveRequestPromise;
46
- constructor(delegate: FetchRequestDelegate, method: FetchMethod, location: URL, body?: FetchRequestBody, target?: Element | null);
51
+ constructor(delegate: FetchRequestDelegate, method: FetchMethod, location: URL, body?: FetchRequestBody, target?: FrameElement | HTMLFormElement | null);
47
52
  get location(): URL;
48
53
  get params(): URLSearchParams;
49
54
  get entries(): [string, FormDataEntryValue][];
@@ -58,4 +63,5 @@ export declare class FetchRequest {
58
63
  get abortSignal(): AbortSignal;
59
64
  acceptResponseType(mimeType: string): void;
60
65
  private allowRequestToBeIntercepted;
66
+ private willDelegateErrorHandling;
61
67
  }
@@ -1 +1 @@
1
- export { TurboBeforeFetchRequestEvent, TurboBeforeFetchResponseEvent } from "./fetch_request";
1
+ export { TurboBeforeFetchRequestEvent, TurboBeforeFetchResponseEvent, TurboFetchRequestErrorEvent, } from "./fetch_request";
@@ -9,7 +9,7 @@ export declare class DeprecatedAdapterSupportTest extends DOMTestCase implements
9
9
  teardown(): Promise<void>;
10
10
  "test visit proposal location includes deprecated absoluteURL property"(): Promise<void>;
11
11
  "test visit start location includes deprecated absoluteURL property"(): Promise<void>;
12
- visitProposedToLocation(location: URL, _options?: Partial<VisitOptions>): Promise<void>;
12
+ visitProposedToLocation(location: URL, _options?: Partial<VisitOptions>): void;
13
13
  visitStarted(visit: Visit): void;
14
14
  visitCompleted(_visit: Visit): void;
15
15
  visitFailed(_visit: Visit): void;
@@ -0,0 +1,5 @@
1
+ import { DOMTestCase } from "../helpers/dom_test_case";
2
+ export { PageRenderer, PageSnapshot, FrameRenderer, FrameElement, StreamActions, StreamElement, StreamSourceElement, TurboBeforeCacheEvent, TurboBeforeFetchRequestEvent, TurboBeforeFetchResponseEvent, TurboBeforeFrameRenderEvent, TurboBeforeRenderEvent, TurboBeforeStreamRenderEvent, TurboBeforeVisitEvent, TurboClickEvent, TurboFetchRequestErrorEvent, TurboFrameLoadEvent, TurboFrameMissingEvent, TurboFrameRenderEvent, TurboLoadEvent, TurboRenderEvent, TurboStreamAction, TurboStreamActions, TurboSubmitEndEvent, TurboSubmitStartEvent, TurboVisitEvent, } from "../../index";
3
+ export declare class ExportTests extends DOMTestCase {
4
+ "test Turbo interface"(): Promise<void>;
5
+ }
@@ -1,2 +1,3 @@
1
+ export * from "./export_tests";
1
2
  export * from "./deprecated_adapter_support_test";
2
3
  export * from "./stream_element_tests";
@@ -20,7 +20,6 @@ export declare function clearBusyState(...elements: Element[]): void;
20
20
  export declare function waitForLoad(element: HTMLLinkElement, timeoutInMilliseconds?: number): Promise<void>;
21
21
  export declare function getHistoryMethodForAction(action: Action): (data: any, unused: string, url?: string | URL | null | undefined) => void;
22
22
  export declare function getVisitAction(...elements: (Element | undefined)[]): Action | null;
23
- export declare function getBodyElementId(): string | null;
24
23
  export declare function getMetaElement(name: string): HTMLMetaElement | null;
25
24
  export declare function getMetaContent(name: string): string | null;
26
25
  export declare function setMetaContent(name: string, content: string): HTMLMetaElement;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotwired/turbo",
3
- "version": "7.2.0-rc.1",
3
+ "version": "7.2.0-rc.3",
4
4
  "description": "The speed of a single-page web application without having to write any JavaScript",
5
5
  "module": "dist/turbo.es2017-esm.js",
6
6
  "main": "dist/turbo.es2017-umd.js",