@hotwired/turbo 7.0.0-rc.2 → 7.0.0

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.0.0-rc.2
2
+ Turbo 7.0.0
3
3
  Copyright © 2021 Basecamp, LLC
4
4
  */
5
5
  (function () {
@@ -35,6 +35,8 @@ function clickCaptured(event) {
35
35
  (function () {
36
36
  if ("SubmitEvent" in window)
37
37
  return;
38
+ if ("submitter" in Event.prototype)
39
+ return;
38
40
  addEventListener("click", clickCaptured, true);
39
41
  Object.defineProperty(Event.prototype, "submitter", {
40
42
  get() {
@@ -222,11 +224,11 @@ class FetchResponse {
222
224
  return this.header("Content-Type");
223
225
  }
224
226
  get responseText() {
225
- return this.response.text();
227
+ return this.response.clone().text();
226
228
  }
227
229
  get responseHTML() {
228
230
  if (this.isHTML) {
229
- return this.response.text();
231
+ return this.response.clone().text();
230
232
  }
231
233
  else {
232
234
  return Promise.resolve(undefined);
@@ -239,7 +241,12 @@ class FetchResponse {
239
241
 
240
242
  function dispatch(eventName, { target, cancelable, detail } = {}) {
241
243
  const event = new CustomEvent(eventName, { cancelable, bubbles: true, detail });
242
- void (target || document.documentElement).dispatchEvent(event);
244
+ if (target && target.isConnected) {
245
+ target.dispatchEvent(event);
246
+ }
247
+ else {
248
+ document.documentElement.dispatchEvent(event);
249
+ }
243
250
  return event;
244
251
  }
245
252
  function nextAnimationFrame() {
@@ -301,7 +308,7 @@ function fetchMethodFromString(method) {
301
308
  }
302
309
  }
303
310
  class FetchRequest {
304
- constructor(delegate, method, location, body = new URLSearchParams) {
311
+ constructor(delegate, method, location, body = new URLSearchParams, target = null) {
305
312
  this.abortController = new AbortController;
306
313
  this.resolveRequestPromise = (value) => { };
307
314
  this.delegate = delegate;
@@ -314,6 +321,7 @@ class FetchRequest {
314
321
  this.body = body;
315
322
  this.url = location;
316
323
  }
324
+ this.target = target;
317
325
  }
318
326
  get location() {
319
327
  return this.url;
@@ -349,7 +357,7 @@ class FetchRequest {
349
357
  }
350
358
  async receive(response) {
351
359
  const fetchResponse = new FetchResponse(response);
352
- const event = dispatch("turbo:before-fetch-response", { cancelable: true, detail: { fetchResponse } });
360
+ const event = dispatch("turbo:before-fetch-response", { cancelable: true, detail: { fetchResponse }, target: this.target });
353
361
  if (event.defaultPrevented) {
354
362
  this.delegate.requestPreventedHandlingResponse(this, fetchResponse);
355
363
  }
@@ -386,7 +394,15 @@ class FetchRequest {
386
394
  }
387
395
  async allowRequestToBeIntercepted(fetchOptions) {
388
396
  const requestInterception = new Promise(resolve => this.resolveRequestPromise = resolve);
389
- const event = dispatch("turbo:before-fetch-request", { cancelable: true, detail: { fetchOptions, url: this.url.href, resume: this.resolveRequestPromise } });
397
+ const event = dispatch("turbo:before-fetch-request", {
398
+ cancelable: true,
399
+ detail: {
400
+ fetchOptions,
401
+ url: this.url.href,
402
+ resume: this.resolveRequestPromise
403
+ },
404
+ target: this.target
405
+ });
390
406
  if (event.defaultPrevented)
391
407
  await requestInterception;
392
408
  }
@@ -499,7 +515,7 @@ class FormSubmission {
499
515
  this.formElement = formElement;
500
516
  this.submitter = submitter;
501
517
  this.formData = buildFormData(formElement, submitter);
502
- this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body);
518
+ this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body, this.formElement);
503
519
  this.mustRedirect = mustRedirect;
504
520
  }
505
521
  get method() {
@@ -1112,6 +1128,7 @@ class HeadSnapshot extends Snapshot {
1112
1128
  super(...arguments);
1113
1129
  this.detailsByOuterHTML = this.children
1114
1130
  .filter((element) => !elementIsNoscript(element))
1131
+ .map((element) => elementWithoutNonce(element))
1115
1132
  .reduce((result, element) => {
1116
1133
  const { outerHTML } = element;
1117
1134
  const details = outerHTML in result
@@ -1196,6 +1213,12 @@ function elementIsMetaElementWithName(element, name) {
1196
1213
  const tagName = element.tagName.toLowerCase();
1197
1214
  return tagName == "meta" && element.getAttribute("name") == name;
1198
1215
  }
1216
+ function elementWithoutNonce(element) {
1217
+ if (element.hasAttribute("nonce")) {
1218
+ element.setAttribute("nonce", "");
1219
+ }
1220
+ return element;
1221
+ }
1199
1222
 
1200
1223
  class PageSnapshot extends Snapshot {
1201
1224
  constructor(element, headSnapshot) {
@@ -1581,7 +1604,7 @@ class BrowserAdapter {
1581
1604
  visitRequestStarted(visit) {
1582
1605
  this.progressBar.setValue(0);
1583
1606
  if (visit.hasCachedSnapshot() || visit.action != "restore") {
1584
- this.showProgressBarAfterDelay();
1607
+ this.showVisitProgressBarAfterDelay();
1585
1608
  }
1586
1609
  else {
1587
1610
  this.showProgressBar();
@@ -1602,7 +1625,7 @@ class BrowserAdapter {
1602
1625
  }
1603
1626
  visitRequestFinished(visit) {
1604
1627
  this.progressBar.setValue(1);
1605
- this.hideProgressBar();
1628
+ this.hideVisitProgressBar();
1606
1629
  }
1607
1630
  visitCompleted(visit) {
1608
1631
  }
@@ -1615,20 +1638,32 @@ class BrowserAdapter {
1615
1638
  }
1616
1639
  formSubmissionStarted(formSubmission) {
1617
1640
  this.progressBar.setValue(0);
1618
- this.showProgressBarAfterDelay();
1641
+ this.showFormProgressBarAfterDelay();
1619
1642
  }
1620
1643
  formSubmissionFinished(formSubmission) {
1621
1644
  this.progressBar.setValue(1);
1622
- this.hideProgressBar();
1645
+ this.hideFormProgressBar();
1646
+ }
1647
+ showVisitProgressBarAfterDelay() {
1648
+ this.visitProgressBarTimeout = window.setTimeout(this.showProgressBar, this.session.progressBarDelay);
1649
+ }
1650
+ hideVisitProgressBar() {
1651
+ this.progressBar.hide();
1652
+ if (this.visitProgressBarTimeout != null) {
1653
+ window.clearTimeout(this.visitProgressBarTimeout);
1654
+ delete this.visitProgressBarTimeout;
1655
+ }
1623
1656
  }
1624
- showProgressBarAfterDelay() {
1625
- this.progressBarTimeout = window.setTimeout(this.showProgressBar, this.session.progressBarDelay);
1657
+ showFormProgressBarAfterDelay() {
1658
+ if (this.formProgressBarTimeout == null) {
1659
+ this.formProgressBarTimeout = window.setTimeout(this.showProgressBar, this.session.progressBarDelay);
1660
+ }
1626
1661
  }
1627
- hideProgressBar() {
1662
+ hideFormProgressBar() {
1628
1663
  this.progressBar.hide();
1629
- if (this.progressBarTimeout != null) {
1630
- window.clearTimeout(this.progressBarTimeout);
1631
- delete this.progressBarTimeout;
1664
+ if (this.formProgressBarTimeout != null) {
1665
+ window.clearTimeout(this.formProgressBarTimeout);
1666
+ delete this.formProgressBarTimeout;
1632
1667
  }
1633
1668
  }
1634
1669
  reload() {
@@ -1719,6 +1754,7 @@ class FrameRedirector {
1719
1754
  linkClickIntercepted(element, url) {
1720
1755
  const frame = this.findFrameElement(element);
1721
1756
  if (frame) {
1757
+ frame.setAttribute("reloadable", "");
1722
1758
  frame.src = url;
1723
1759
  }
1724
1760
  }
@@ -1726,17 +1762,18 @@ class FrameRedirector {
1726
1762
  return this.shouldRedirect(element, submitter);
1727
1763
  }
1728
1764
  formSubmissionIntercepted(element, submitter) {
1729
- const frame = this.findFrameElement(element);
1765
+ const frame = this.findFrameElement(element, submitter);
1730
1766
  if (frame) {
1767
+ frame.removeAttribute("reloadable");
1731
1768
  frame.delegate.formSubmissionIntercepted(element, submitter);
1732
1769
  }
1733
1770
  }
1734
1771
  shouldRedirect(element, submitter) {
1735
- const frame = this.findFrameElement(element);
1772
+ const frame = this.findFrameElement(element, submitter);
1736
1773
  return frame ? frame != element.closest("turbo-frame") : false;
1737
1774
  }
1738
- findFrameElement(element) {
1739
- const id = element.getAttribute("data-turbo-frame");
1775
+ findFrameElement(element, submitter) {
1776
+ const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame");
1740
1777
  if (id && id != "_top") {
1741
1778
  const frame = this.element.querySelector(`#${id}:not([disabled])`);
1742
1779
  if (frame instanceof FrameElement) {
@@ -2448,12 +2485,14 @@ class Session {
2448
2485
  this.convertLinkWithMethodClickToFormSubmission(link) || this.visit(location.href, { action });
2449
2486
  }
2450
2487
  convertLinkWithMethodClickToFormSubmission(link) {
2488
+ var _a;
2451
2489
  const linkMethod = link.getAttribute("data-turbo-method");
2452
2490
  if (linkMethod) {
2453
2491
  const form = document.createElement("form");
2454
2492
  form.method = linkMethod;
2455
2493
  form.action = link.getAttribute("href") || "undefined";
2456
- document.body.appendChild(form);
2494
+ form.hidden = true;
2495
+ (_a = link.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(form, link);
2457
2496
  return dispatch("submit", { cancelable: true, target: form });
2458
2497
  }
2459
2498
  else {
@@ -2762,7 +2801,7 @@ class FrameController {
2762
2801
  this.reloadable = false;
2763
2802
  this.formSubmission = new FormSubmission(this, element, submitter);
2764
2803
  if (this.formSubmission.fetchRequest.isIdempotent) {
2765
- this.navigateFrame(element, this.formSubmission.fetchRequest.url.href);
2804
+ this.navigateFrame(element, this.formSubmission.fetchRequest.url.href, submitter);
2766
2805
  }
2767
2806
  else {
2768
2807
  const { fetchRequest } = this.formSubmission;
@@ -2799,7 +2838,7 @@ class FrameController {
2799
2838
  frame.setAttribute("busy", "");
2800
2839
  }
2801
2840
  formSubmissionSucceededWithResponse(formSubmission, response) {
2802
- const frame = this.findFrameElement(formSubmission.formElement);
2841
+ const frame = this.findFrameElement(formSubmission.formElement, formSubmission.submitter);
2803
2842
  frame.delegate.loadResponse(response);
2804
2843
  }
2805
2844
  formSubmissionFailedWithResponse(formSubmission, fetchResponse) {
@@ -2820,7 +2859,7 @@ class FrameController {
2820
2859
  viewInvalidated() {
2821
2860
  }
2822
2861
  async visit(url) {
2823
- const request = new FetchRequest(this, FetchMethod.get, expandURL(url));
2862
+ const request = new FetchRequest(this, FetchMethod.get, expandURL(url), undefined, this.element);
2824
2863
  return new Promise(resolve => {
2825
2864
  this.resolveVisitPromise = () => {
2826
2865
  this.resolveVisitPromise = () => { };
@@ -2829,13 +2868,14 @@ class FrameController {
2829
2868
  request.perform();
2830
2869
  });
2831
2870
  }
2832
- navigateFrame(element, url) {
2833
- const frame = this.findFrameElement(element);
2871
+ navigateFrame(element, url, submitter) {
2872
+ const frame = this.findFrameElement(element, submitter);
2873
+ frame.setAttribute("reloadable", "");
2834
2874
  frame.src = url;
2835
2875
  }
2836
- findFrameElement(element) {
2876
+ findFrameElement(element, submitter) {
2837
2877
  var _a;
2838
- const id = element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
2878
+ const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
2839
2879
  return (_a = getFrameElementById(id)) !== null && _a !== void 0 ? _a : this.element;
2840
2880
  }
2841
2881
  async extractForeignFrameElement(container) {
@@ -2857,7 +2897,7 @@ class FrameController {
2857
2897
  return new FrameElement();
2858
2898
  }
2859
2899
  shouldInterceptNavigation(element, submitter) {
2860
- const id = element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
2900
+ const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
2861
2901
  if (!this.enabled || id == "_top") {
2862
2902
  return false;
2863
2903
  }
@@ -3105,4 +3145,3 @@ window.Turbo = Turbo;
3105
3145
  start();
3106
3146
 
3107
3147
  export { PageRenderer, PageSnapshot, clearCache, connectStreamSource, disconnectStreamSource, navigator, registerAdapter, renderStreamMessage, session, setProgressBarDelay, start, visit };
3108
- //# sourceMappingURL=turbo.es2017-esm.js.map