@hotwired/turbo 7.2.0-beta.2 → 7.2.0-rc.1
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/README.md +4 -0
- package/dist/turbo.es2017-esm.js +150 -56
- package/dist/turbo.es2017-umd.js +160 -63
- package/dist/types/core/drive/form_submission.d.ts +1 -3
- package/dist/types/core/drive/navigator.d.ts +1 -1
- package/dist/types/core/drive/page_renderer.d.ts +4 -1
- package/dist/types/core/drive/visit.d.ts +2 -1
- package/dist/types/core/frames/frame_controller.d.ts +9 -3
- package/dist/types/core/index.d.ts +2 -4
- package/dist/types/core/session.d.ts +6 -5
- package/dist/types/core/snapshot.d.ts +3 -1
- package/dist/types/core/streams/stream_actions.d.ts +4 -2
- package/dist/types/core/streams/stream_message_renderer.d.ts +7 -0
- package/dist/types/elements/index.d.ts +1 -0
- package/dist/types/elements/stream_element.d.ts +5 -1
- package/dist/types/http/fetch_request.d.ts +2 -3
- package/dist/types/http/index.d.ts +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/tests/functional/drive_custom_body_tests.d.ts +1 -0
- package/dist/types/tests/helpers/page.d.ts +8 -2
- package/dist/types/util.d.ts +2 -0
- package/package.json +4 -4
package/dist/turbo.es2017-umd.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Turbo 7.2.0-
|
|
2
|
+
Turbo 7.2.0-rc.1
|
|
3
3
|
Copyright © 2022 Basecamp, LLC
|
|
4
4
|
*/
|
|
5
5
|
(function (global, factory) {
|
|
@@ -113,11 +113,11 @@ Copyright © 2022 Basecamp, LLC
|
|
|
113
113
|
});
|
|
114
114
|
})();
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
exports.FrameLoadingStyle = void 0;
|
|
117
117
|
(function (FrameLoadingStyle) {
|
|
118
118
|
FrameLoadingStyle["eager"] = "eager";
|
|
119
119
|
FrameLoadingStyle["lazy"] = "lazy";
|
|
120
|
-
})(FrameLoadingStyle || (FrameLoadingStyle = {}));
|
|
120
|
+
})(exports.FrameLoadingStyle || (exports.FrameLoadingStyle = {}));
|
|
121
121
|
class FrameElement extends HTMLElement {
|
|
122
122
|
constructor() {
|
|
123
123
|
super();
|
|
@@ -212,9 +212,9 @@ Copyright © 2022 Basecamp, LLC
|
|
|
212
212
|
function frameLoadingStyleFromString(style) {
|
|
213
213
|
switch (style.toLowerCase()) {
|
|
214
214
|
case "lazy":
|
|
215
|
-
return FrameLoadingStyle.lazy;
|
|
215
|
+
return exports.FrameLoadingStyle.lazy;
|
|
216
216
|
default:
|
|
217
|
-
return FrameLoadingStyle.eager;
|
|
217
|
+
return exports.FrameLoadingStyle.eager;
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
220
|
|
|
@@ -410,6 +410,9 @@ Copyright © 2022 Basecamp, LLC
|
|
|
410
410
|
}
|
|
411
411
|
return null;
|
|
412
412
|
}
|
|
413
|
+
function hasAttribute(attributeName, ...elements) {
|
|
414
|
+
return elements.some((element) => element && element.hasAttribute(attributeName));
|
|
415
|
+
}
|
|
413
416
|
function markAsBusy(...elements) {
|
|
414
417
|
for (const element of elements) {
|
|
415
418
|
if (element.localName == "turbo-frame") {
|
|
@@ -451,6 +454,9 @@ Copyright © 2022 Basecamp, LLC
|
|
|
451
454
|
const action = getAttribute("data-turbo-action", ...elements);
|
|
452
455
|
return isAction(action) ? action : null;
|
|
453
456
|
}
|
|
457
|
+
function getBodyElementId() {
|
|
458
|
+
return getMetaContent("turbo-body");
|
|
459
|
+
}
|
|
454
460
|
function getMetaElement(name) {
|
|
455
461
|
return document.querySelector(`meta[name="${name}"]`);
|
|
456
462
|
}
|
|
@@ -685,7 +691,7 @@ Copyright © 2022 Basecamp, LLC
|
|
|
685
691
|
this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body, this.formElement);
|
|
686
692
|
this.mustRedirect = mustRedirect;
|
|
687
693
|
}
|
|
688
|
-
static confirmMethod(message, _element) {
|
|
694
|
+
static confirmMethod(message, _element, _submitter) {
|
|
689
695
|
return Promise.resolve(confirm(message));
|
|
690
696
|
}
|
|
691
697
|
get method() {
|
|
@@ -723,17 +729,11 @@ Copyright © 2022 Basecamp, LLC
|
|
|
723
729
|
return entries.concat(typeof value == "string" ? [[name, value]] : []);
|
|
724
730
|
}, []);
|
|
725
731
|
}
|
|
726
|
-
get confirmationMessage() {
|
|
727
|
-
var _a;
|
|
728
|
-
return ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("data-turbo-confirm")) || this.formElement.getAttribute("data-turbo-confirm");
|
|
729
|
-
}
|
|
730
|
-
get needsConfirmation() {
|
|
731
|
-
return this.confirmationMessage !== null;
|
|
732
|
-
}
|
|
733
732
|
async start() {
|
|
734
733
|
const { initialized, requesting } = FormSubmissionState;
|
|
735
|
-
|
|
736
|
-
|
|
734
|
+
const confirmationMessage = getAttribute("data-turbo-confirm", this.submitter, this.formElement);
|
|
735
|
+
if (typeof confirmationMessage === "string") {
|
|
736
|
+
const answer = await FormSubmission.confirmMethod(confirmationMessage, this.formElement, this.submitter);
|
|
737
737
|
if (!answer) {
|
|
738
738
|
return;
|
|
739
739
|
}
|
|
@@ -815,7 +815,7 @@ Copyright © 2022 Basecamp, LLC
|
|
|
815
815
|
return !request.isIdempotent && this.mustRedirect;
|
|
816
816
|
}
|
|
817
817
|
requestAcceptsTurboStreamResponse(request) {
|
|
818
|
-
return !request.isIdempotent ||
|
|
818
|
+
return !request.isIdempotent || hasAttribute("data-turbo-stream", this.submitter, this.formElement);
|
|
819
819
|
}
|
|
820
820
|
}
|
|
821
821
|
function buildFormData(formElement, submitter) {
|
|
@@ -881,10 +881,10 @@ Copyright © 2022 Basecamp, LLC
|
|
|
881
881
|
return null;
|
|
882
882
|
}
|
|
883
883
|
get permanentElements() {
|
|
884
|
-
return
|
|
884
|
+
return queryPermanentElementsAll(this.element);
|
|
885
885
|
}
|
|
886
886
|
getPermanentElementById(id) {
|
|
887
|
-
return this.element
|
|
887
|
+
return getPermanentElementById(this.element, id);
|
|
888
888
|
}
|
|
889
889
|
getPermanentElementMapForSnapshot(snapshot) {
|
|
890
890
|
const permanentElementMap = {};
|
|
@@ -898,6 +898,12 @@ Copyright © 2022 Basecamp, LLC
|
|
|
898
898
|
return permanentElementMap;
|
|
899
899
|
}
|
|
900
900
|
}
|
|
901
|
+
function getPermanentElementById(node, id) {
|
|
902
|
+
return node.querySelector(`#${id}[data-turbo-permanent]`);
|
|
903
|
+
}
|
|
904
|
+
function queryPermanentElementsAll(node) {
|
|
905
|
+
return node.querySelectorAll("[id][data-turbo-permanent]");
|
|
906
|
+
}
|
|
901
907
|
|
|
902
908
|
class FormSubmitObserver {
|
|
903
909
|
constructor(delegate, eventTarget) {
|
|
@@ -1139,6 +1145,9 @@ Copyright © 2022 Basecamp, LLC
|
|
|
1139
1145
|
const turboFrame = link.getAttribute("data-turbo-frame");
|
|
1140
1146
|
if (turboFrame)
|
|
1141
1147
|
form.setAttribute("data-turbo-frame", turboFrame);
|
|
1148
|
+
const turboAction = link.getAttribute("data-turbo-action");
|
|
1149
|
+
if (turboAction)
|
|
1150
|
+
form.setAttribute("data-turbo-action", turboAction);
|
|
1142
1151
|
const turboConfirm = link.getAttribute("data-turbo-confirm");
|
|
1143
1152
|
if (turboConfirm)
|
|
1144
1153
|
form.setAttribute("data-turbo-confirm", turboConfirm);
|
|
@@ -1147,8 +1156,8 @@ Copyright © 2022 Basecamp, LLC
|
|
|
1147
1156
|
form.setAttribute("data-turbo-stream", "");
|
|
1148
1157
|
this.delegate.submittedFormLinkToLocation(link, location, form);
|
|
1149
1158
|
document.body.appendChild(form);
|
|
1150
|
-
form.
|
|
1151
|
-
form.
|
|
1159
|
+
form.addEventListener("turbo:submit-end", () => form.remove(), { once: true });
|
|
1160
|
+
requestAnimationFrame(() => form.requestSubmit());
|
|
1152
1161
|
}
|
|
1153
1162
|
}
|
|
1154
1163
|
|
|
@@ -1519,19 +1528,19 @@ Copyright © 2022 Basecamp, LLC
|
|
|
1519
1528
|
return element.getAttribute("data-turbo-track") == "reload";
|
|
1520
1529
|
}
|
|
1521
1530
|
function elementIsScript(element) {
|
|
1522
|
-
const tagName = element.
|
|
1531
|
+
const tagName = element.localName;
|
|
1523
1532
|
return tagName == "script";
|
|
1524
1533
|
}
|
|
1525
1534
|
function elementIsNoscript(element) {
|
|
1526
|
-
const tagName = element.
|
|
1535
|
+
const tagName = element.localName;
|
|
1527
1536
|
return tagName == "noscript";
|
|
1528
1537
|
}
|
|
1529
1538
|
function elementIsStylesheet(element) {
|
|
1530
|
-
const tagName = element.
|
|
1539
|
+
const tagName = element.localName;
|
|
1531
1540
|
return tagName == "style" || (tagName == "link" && element.getAttribute("rel") == "stylesheet");
|
|
1532
1541
|
}
|
|
1533
1542
|
function elementIsMetaElementWithName(element, name) {
|
|
1534
|
-
const tagName = element.
|
|
1543
|
+
const tagName = element.localName;
|
|
1535
1544
|
return tagName == "meta" && element.getAttribute("name") == name;
|
|
1536
1545
|
}
|
|
1537
1546
|
function elementWithoutNonce(element) {
|
|
@@ -1556,7 +1565,20 @@ Copyright © 2022 Basecamp, LLC
|
|
|
1556
1565
|
return new this(body, new HeadSnapshot(head));
|
|
1557
1566
|
}
|
|
1558
1567
|
clone() {
|
|
1559
|
-
|
|
1568
|
+
const clonedElement = this.element.cloneNode(true);
|
|
1569
|
+
const selectElements = this.element.querySelectorAll("select");
|
|
1570
|
+
const clonedSelectElements = clonedElement.querySelectorAll("select");
|
|
1571
|
+
for (const [index, source] of selectElements.entries()) {
|
|
1572
|
+
const clone = clonedSelectElements[index];
|
|
1573
|
+
for (const option of clone.selectedOptions)
|
|
1574
|
+
option.selected = false;
|
|
1575
|
+
for (const option of source.selectedOptions)
|
|
1576
|
+
clone.options[option.index].selected = true;
|
|
1577
|
+
}
|
|
1578
|
+
for (const clonedPasswordInput of clonedElement.querySelectorAll('input[type="password"]')) {
|
|
1579
|
+
clonedPasswordInput.value = "";
|
|
1580
|
+
}
|
|
1581
|
+
return new PageSnapshot(clonedElement, this.headSnapshot);
|
|
1560
1582
|
}
|
|
1561
1583
|
get headElement() {
|
|
1562
1584
|
return this.headSnapshot.element;
|
|
@@ -1606,6 +1628,7 @@ Copyright © 2022 Basecamp, LLC
|
|
|
1606
1628
|
updateHistory: true,
|
|
1607
1629
|
shouldCacheSnapshot: true,
|
|
1608
1630
|
acceptsStreamResponse: false,
|
|
1631
|
+
initiator: document.documentElement,
|
|
1609
1632
|
};
|
|
1610
1633
|
var SystemStatusCode;
|
|
1611
1634
|
(function (SystemStatusCode) {
|
|
@@ -1615,7 +1638,6 @@ Copyright © 2022 Basecamp, LLC
|
|
|
1615
1638
|
})(SystemStatusCode || (SystemStatusCode = {}));
|
|
1616
1639
|
class Visit {
|
|
1617
1640
|
constructor(delegate, location, restorationIdentifier, options = {}) {
|
|
1618
|
-
this.identifier = uuid();
|
|
1619
1641
|
this.timingMetrics = {};
|
|
1620
1642
|
this.followedRedirect = false;
|
|
1621
1643
|
this.historyChanged = false;
|
|
@@ -1628,7 +1650,7 @@ Copyright © 2022 Basecamp, LLC
|
|
|
1628
1650
|
this.location = location;
|
|
1629
1651
|
this.restorationIdentifier = restorationIdentifier || uuid();
|
|
1630
1652
|
this.promise = new Promise((resolve, reject) => (this.resolvingFunctions = { resolve, reject }));
|
|
1631
|
-
const { action, historyChanged, referrer, snapshotHTML, response, visitCachedSnapshot, willRender, updateHistory, shouldCacheSnapshot, acceptsStreamResponse, } = Object.assign(Object.assign({}, defaultOptions), options);
|
|
1653
|
+
const { action, historyChanged, referrer, snapshotHTML, response, visitCachedSnapshot, willRender, updateHistory, shouldCacheSnapshot, acceptsStreamResponse, initiator, } = Object.assign(Object.assign({}, defaultOptions), options);
|
|
1632
1654
|
this.action = action;
|
|
1633
1655
|
this.historyChanged = historyChanged;
|
|
1634
1656
|
this.referrer = referrer;
|
|
@@ -1641,6 +1663,7 @@ Copyright © 2022 Basecamp, LLC
|
|
|
1641
1663
|
this.scrolled = !willRender;
|
|
1642
1664
|
this.shouldCacheSnapshot = shouldCacheSnapshot;
|
|
1643
1665
|
this.acceptsStreamResponse = acceptsStreamResponse;
|
|
1666
|
+
this.initiator = initiator;
|
|
1644
1667
|
}
|
|
1645
1668
|
get adapter() {
|
|
1646
1669
|
return this.delegate.adapter;
|
|
@@ -1708,7 +1731,7 @@ Copyright © 2022 Basecamp, LLC
|
|
|
1708
1731
|
this.simulateRequest();
|
|
1709
1732
|
}
|
|
1710
1733
|
else if (this.shouldIssueRequest() && !this.request) {
|
|
1711
|
-
this.request = new FetchRequest(this, FetchMethod.get, this.location);
|
|
1734
|
+
this.request = new FetchRequest(this, FetchMethod.get, this.location, undefined, this.initiator);
|
|
1712
1735
|
this.request.perform();
|
|
1713
1736
|
}
|
|
1714
1737
|
}
|
|
@@ -1804,7 +1827,6 @@ Copyright © 2022 Basecamp, LLC
|
|
|
1804
1827
|
if (this.redirectedToLocation && !this.followedRedirect && ((_a = this.response) === null || _a === void 0 ? void 0 : _a.redirected)) {
|
|
1805
1828
|
this.adapter.visitProposedToLocation(this.redirectedToLocation, {
|
|
1806
1829
|
action: "replace",
|
|
1807
|
-
willRender: false,
|
|
1808
1830
|
response: this.response,
|
|
1809
1831
|
});
|
|
1810
1832
|
this.followedRedirect = true;
|
|
@@ -2214,7 +2236,7 @@ Copyright © 2022 Basecamp, LLC
|
|
|
2214
2236
|
this.delegate = delegate;
|
|
2215
2237
|
}
|
|
2216
2238
|
proposeVisit(location, options = {}) {
|
|
2217
|
-
if (this.delegate.
|
|
2239
|
+
if (this.delegate.allowsVisitingLocation(location, options)) {
|
|
2218
2240
|
if (locationIsVisitable(location, this.view.snapshot.rootLocation)) {
|
|
2219
2241
|
return this.delegate.visitProposedToLocation(location, options);
|
|
2220
2242
|
}
|
|
@@ -2422,6 +2444,30 @@ Copyright © 2022 Basecamp, LLC
|
|
|
2422
2444
|
}
|
|
2423
2445
|
}
|
|
2424
2446
|
|
|
2447
|
+
class StreamMessageRenderer {
|
|
2448
|
+
render({ fragment }) {
|
|
2449
|
+
Bardo.preservingPermanentElements(this, getPermanentElementMapForFragment(fragment), () => document.documentElement.appendChild(fragment));
|
|
2450
|
+
}
|
|
2451
|
+
enteringBardo(currentPermanentElement, newPermanentElement) {
|
|
2452
|
+
newPermanentElement.replaceWith(currentPermanentElement.cloneNode(true));
|
|
2453
|
+
}
|
|
2454
|
+
leavingBardo() { }
|
|
2455
|
+
}
|
|
2456
|
+
function getPermanentElementMapForFragment(fragment) {
|
|
2457
|
+
const permanentElementsInDocument = queryPermanentElementsAll(document.documentElement);
|
|
2458
|
+
const permanentElementMap = {};
|
|
2459
|
+
for (const permanentElementInDocument of permanentElementsInDocument) {
|
|
2460
|
+
const { id } = permanentElementInDocument;
|
|
2461
|
+
for (const streamElement of fragment.querySelectorAll("turbo-stream")) {
|
|
2462
|
+
const elementInStream = getPermanentElementById(streamElement.templateElement.content, id);
|
|
2463
|
+
if (elementInStream) {
|
|
2464
|
+
permanentElementMap[id] = [permanentElementInDocument, elementInStream];
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
return permanentElementMap;
|
|
2469
|
+
}
|
|
2470
|
+
|
|
2425
2471
|
class StreamObserver {
|
|
2426
2472
|
constructor(delegate) {
|
|
2427
2473
|
this.sources = new Set();
|
|
@@ -2522,16 +2568,19 @@ Copyright © 2022 Basecamp, LLC
|
|
|
2522
2568
|
}
|
|
2523
2569
|
|
|
2524
2570
|
class PageRenderer extends Renderer {
|
|
2525
|
-
static renderElement(currentElement, newElement) {
|
|
2571
|
+
static async renderElement(currentElement, newElement) {
|
|
2572
|
+
await nextEventLoopTick();
|
|
2526
2573
|
if (document.body && newElement instanceof HTMLBodyElement) {
|
|
2527
|
-
|
|
2574
|
+
const currentBody = PageRenderer.getBodyElement(currentElement);
|
|
2575
|
+
const newBody = PageRenderer.getBodyElement(newElement);
|
|
2576
|
+
currentBody.replaceWith(newBody);
|
|
2528
2577
|
}
|
|
2529
2578
|
else {
|
|
2530
2579
|
document.documentElement.appendChild(newElement);
|
|
2531
2580
|
}
|
|
2532
2581
|
}
|
|
2533
2582
|
get shouldRender() {
|
|
2534
|
-
return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical;
|
|
2583
|
+
return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical && this.bodyElementMatches;
|
|
2535
2584
|
}
|
|
2536
2585
|
get reloadReason() {
|
|
2537
2586
|
if (!this.newSnapshot.isVisitable) {
|
|
@@ -2544,6 +2593,11 @@ Copyright © 2022 Basecamp, LLC
|
|
|
2544
2593
|
reason: "tracked_element_mismatch",
|
|
2545
2594
|
};
|
|
2546
2595
|
}
|
|
2596
|
+
if (!this.bodyElementMatches) {
|
|
2597
|
+
return {
|
|
2598
|
+
reason: "body_element_mismatch",
|
|
2599
|
+
};
|
|
2600
|
+
}
|
|
2547
2601
|
}
|
|
2548
2602
|
async prepareToRender() {
|
|
2549
2603
|
await this.mergeHead();
|
|
@@ -2584,6 +2638,16 @@ Copyright © 2022 Basecamp, LLC
|
|
|
2584
2638
|
get trackedElementsAreIdentical() {
|
|
2585
2639
|
return this.currentHeadSnapshot.trackedElementSignature == this.newHeadSnapshot.trackedElementSignature;
|
|
2586
2640
|
}
|
|
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
|
+
}
|
|
2587
2651
|
async copyNewHeadStylesheetElements() {
|
|
2588
2652
|
const loadingElements = [];
|
|
2589
2653
|
for (const element of this.newHeadStylesheetElements) {
|
|
@@ -2782,6 +2846,7 @@ Copyright © 2022 Basecamp, LLC
|
|
|
2782
2846
|
this.streamObserver = new StreamObserver(this);
|
|
2783
2847
|
this.formLinkClickObserver = new FormLinkClickObserver(this, document.documentElement);
|
|
2784
2848
|
this.frameRedirector = new FrameRedirector(this, document.documentElement);
|
|
2849
|
+
this.streamMessageRenderer = new StreamMessageRenderer();
|
|
2785
2850
|
this.drive = true;
|
|
2786
2851
|
this.enabled = true;
|
|
2787
2852
|
this.progressBarDelay = 500;
|
|
@@ -2825,7 +2890,7 @@ Copyright © 2022 Basecamp, LLC
|
|
|
2825
2890
|
this.adapter = adapter;
|
|
2826
2891
|
}
|
|
2827
2892
|
visit(location, options = {}) {
|
|
2828
|
-
const frameElement = document.getElementById(options.frame
|
|
2893
|
+
const frameElement = options.frame ? document.getElementById(options.frame) : null;
|
|
2829
2894
|
if (frameElement instanceof FrameElement) {
|
|
2830
2895
|
frameElement.src = location.toString();
|
|
2831
2896
|
return frameElement.loaded;
|
|
@@ -2841,7 +2906,7 @@ Copyright © 2022 Basecamp, LLC
|
|
|
2841
2906
|
this.streamObserver.disconnectStreamSource(source);
|
|
2842
2907
|
}
|
|
2843
2908
|
renderStreamMessage(message) {
|
|
2844
|
-
|
|
2909
|
+
this.streamMessageRenderer.render(StreamMessage.wrap(message));
|
|
2845
2910
|
}
|
|
2846
2911
|
clearCache() {
|
|
2847
2912
|
this.view.clearSnapshotCache();
|
|
@@ -2886,22 +2951,27 @@ Copyright © 2022 Basecamp, LLC
|
|
|
2886
2951
|
followedLinkToLocation(link, location) {
|
|
2887
2952
|
const action = this.getActionForLink(link);
|
|
2888
2953
|
const acceptsStreamResponse = link.hasAttribute("data-turbo-stream");
|
|
2889
|
-
this.visit(location.href, { action, acceptsStreamResponse });
|
|
2954
|
+
this.visit(location.href, { action, acceptsStreamResponse, initiator: link });
|
|
2890
2955
|
}
|
|
2891
|
-
|
|
2892
|
-
return this.locationWithActionIsSamePage(location, action) ||
|
|
2956
|
+
allowsVisitingLocation(location, options = {}) {
|
|
2957
|
+
return (this.locationWithActionIsSamePage(location, options.action) ||
|
|
2958
|
+
this.applicationAllowsVisitingLocation(location, options));
|
|
2893
2959
|
}
|
|
2894
2960
|
visitProposedToLocation(location, options) {
|
|
2895
2961
|
extendURLWithDeprecatedProperties(location);
|
|
2896
2962
|
return this.adapter.visitProposedToLocation(location, options);
|
|
2897
2963
|
}
|
|
2898
2964
|
visitStarted(visit) {
|
|
2965
|
+
if (!visit.acceptsStreamResponse) {
|
|
2966
|
+
markAsBusy(document.documentElement);
|
|
2967
|
+
}
|
|
2899
2968
|
extendURLWithDeprecatedProperties(visit.location);
|
|
2900
2969
|
if (!visit.silent) {
|
|
2901
|
-
this.notifyApplicationAfterVisitingLocation(visit.location, visit.action);
|
|
2970
|
+
this.notifyApplicationAfterVisitingLocation(visit.location, visit.action, visit.initiator);
|
|
2902
2971
|
}
|
|
2903
2972
|
}
|
|
2904
2973
|
visitCompleted(visit) {
|
|
2974
|
+
clearBusyState(document.documentElement);
|
|
2905
2975
|
this.notifyApplicationAfterPageLoad(visit.getTimingMetrics());
|
|
2906
2976
|
}
|
|
2907
2977
|
locationWithActionIsSamePage(location, action) {
|
|
@@ -2961,16 +3031,12 @@ Copyright © 2022 Basecamp, LLC
|
|
|
2961
3031
|
frameRendered(fetchResponse, frame) {
|
|
2962
3032
|
this.notifyApplicationAfterFrameRender(fetchResponse, frame);
|
|
2963
3033
|
}
|
|
2964
|
-
frameMissing(frame, fetchResponse) {
|
|
2965
|
-
console.warn(`Completing full-page visit as matching frame for #${frame.id} was missing from the response`);
|
|
2966
|
-
return this.visit(fetchResponse.location);
|
|
2967
|
-
}
|
|
2968
3034
|
applicationAllowsFollowingLinkToLocation(link, location, ev) {
|
|
2969
3035
|
const event = this.notifyApplicationAfterClickingLinkToLocation(link, location, ev);
|
|
2970
3036
|
return !event.defaultPrevented;
|
|
2971
3037
|
}
|
|
2972
|
-
applicationAllowsVisitingLocation(location) {
|
|
2973
|
-
const event = this.notifyApplicationBeforeVisitingLocation(location);
|
|
3038
|
+
applicationAllowsVisitingLocation(location, options = {}) {
|
|
3039
|
+
const event = this.notifyApplicationBeforeVisitingLocation(location, options.initiator);
|
|
2974
3040
|
return !event.defaultPrevented;
|
|
2975
3041
|
}
|
|
2976
3042
|
notifyApplicationAfterClickingLinkToLocation(link, location, event) {
|
|
@@ -2980,15 +3046,18 @@ Copyright © 2022 Basecamp, LLC
|
|
|
2980
3046
|
cancelable: true,
|
|
2981
3047
|
});
|
|
2982
3048
|
}
|
|
2983
|
-
notifyApplicationBeforeVisitingLocation(location) {
|
|
3049
|
+
notifyApplicationBeforeVisitingLocation(location, element) {
|
|
2984
3050
|
return dispatch("turbo:before-visit", {
|
|
3051
|
+
target: element,
|
|
2985
3052
|
detail: { url: location.href },
|
|
2986
3053
|
cancelable: true,
|
|
2987
3054
|
});
|
|
2988
3055
|
}
|
|
2989
|
-
notifyApplicationAfterVisitingLocation(location, action) {
|
|
2990
|
-
|
|
2991
|
-
|
|
3056
|
+
notifyApplicationAfterVisitingLocation(location, action, element) {
|
|
3057
|
+
return dispatch("turbo:visit", {
|
|
3058
|
+
target: element,
|
|
3059
|
+
detail: { url: location.href, action },
|
|
3060
|
+
});
|
|
2992
3061
|
}
|
|
2993
3062
|
notifyApplicationBeforeCachingSnapshot() {
|
|
2994
3063
|
return dispatch("turbo:before-cache");
|
|
@@ -3003,7 +3072,6 @@ Copyright © 2022 Basecamp, LLC
|
|
|
3003
3072
|
return dispatch("turbo:render");
|
|
3004
3073
|
}
|
|
3005
3074
|
notifyApplicationAfterPageLoad(timing = {}) {
|
|
3006
|
-
clearBusyState(document.documentElement);
|
|
3007
3075
|
return dispatch("turbo:load", {
|
|
3008
3076
|
detail: { url: this.location.href, timing },
|
|
3009
3077
|
});
|
|
@@ -3207,7 +3275,7 @@ Copyright © 2022 Basecamp, LLC
|
|
|
3207
3275
|
connect() {
|
|
3208
3276
|
if (!this.connected) {
|
|
3209
3277
|
this.connected = true;
|
|
3210
|
-
if (this.loadingStyle == FrameLoadingStyle.lazy) {
|
|
3278
|
+
if (this.loadingStyle == exports.FrameLoadingStyle.lazy) {
|
|
3211
3279
|
this.appearanceObserver.start();
|
|
3212
3280
|
}
|
|
3213
3281
|
else {
|
|
@@ -3228,7 +3296,7 @@ Copyright © 2022 Basecamp, LLC
|
|
|
3228
3296
|
}
|
|
3229
3297
|
}
|
|
3230
3298
|
disabledChanged() {
|
|
3231
|
-
if (this.loadingStyle == FrameLoadingStyle.eager) {
|
|
3299
|
+
if (this.loadingStyle == exports.FrameLoadingStyle.eager) {
|
|
3232
3300
|
this.loadSourceURL();
|
|
3233
3301
|
}
|
|
3234
3302
|
}
|
|
@@ -3238,7 +3306,7 @@ Copyright © 2022 Basecamp, LLC
|
|
|
3238
3306
|
if (this.element.isConnected) {
|
|
3239
3307
|
this.complete = false;
|
|
3240
3308
|
}
|
|
3241
|
-
if (this.loadingStyle == FrameLoadingStyle.eager || this.hasBeenLoaded) {
|
|
3309
|
+
if (this.loadingStyle == exports.FrameLoadingStyle.eager || this.hasBeenLoaded) {
|
|
3242
3310
|
this.loadSourceURL();
|
|
3243
3311
|
}
|
|
3244
3312
|
}
|
|
@@ -3248,7 +3316,7 @@ Copyright © 2022 Basecamp, LLC
|
|
|
3248
3316
|
this.loadSourceURL();
|
|
3249
3317
|
}
|
|
3250
3318
|
loadingStyleChanged() {
|
|
3251
|
-
if (this.loadingStyle == FrameLoadingStyle.lazy) {
|
|
3319
|
+
if (this.loadingStyle == exports.FrameLoadingStyle.lazy) {
|
|
3252
3320
|
this.appearanceObserver.start();
|
|
3253
3321
|
}
|
|
3254
3322
|
else {
|
|
@@ -3285,8 +3353,9 @@ Copyright © 2022 Basecamp, LLC
|
|
|
3285
3353
|
session.frameLoaded(this.element);
|
|
3286
3354
|
this.fetchResponseLoaded(fetchResponse);
|
|
3287
3355
|
}
|
|
3288
|
-
else if (this.
|
|
3289
|
-
|
|
3356
|
+
else if (this.willHandleFrameMissingFromResponse(fetchResponse)) {
|
|
3357
|
+
console.warn(`A matching frame for #${this.element.id} was missing from the response, transforming into full-page Visit.`);
|
|
3358
|
+
this.visitResponse(fetchResponse.response);
|
|
3290
3359
|
}
|
|
3291
3360
|
}
|
|
3292
3361
|
}
|
|
@@ -3344,8 +3413,9 @@ Copyright © 2022 Basecamp, LLC
|
|
|
3344
3413
|
await this.loadResponse(response);
|
|
3345
3414
|
this.resolveVisitPromise();
|
|
3346
3415
|
}
|
|
3347
|
-
requestFailedWithResponse(request, response) {
|
|
3416
|
+
async requestFailedWithResponse(request, response) {
|
|
3348
3417
|
console.error(response);
|
|
3418
|
+
await this.loadResponse(response);
|
|
3349
3419
|
this.resolveVisitPromise();
|
|
3350
3420
|
}
|
|
3351
3421
|
requestErrored(request, error) {
|
|
@@ -3447,15 +3517,30 @@ Copyright © 2022 Basecamp, LLC
|
|
|
3447
3517
|
session.history.update(method, expandURL(this.frame.src || ""), this.restorationIdentifier);
|
|
3448
3518
|
}
|
|
3449
3519
|
}
|
|
3450
|
-
|
|
3520
|
+
willHandleFrameMissingFromResponse(fetchResponse) {
|
|
3451
3521
|
this.element.setAttribute("complete", "");
|
|
3522
|
+
const response = fetchResponse.response;
|
|
3523
|
+
const visit = async (url, options = {}) => {
|
|
3524
|
+
if (url instanceof Response) {
|
|
3525
|
+
this.visitResponse(url);
|
|
3526
|
+
}
|
|
3527
|
+
else {
|
|
3528
|
+
session.visit(url, options);
|
|
3529
|
+
}
|
|
3530
|
+
};
|
|
3452
3531
|
const event = dispatch("turbo:frame-missing", {
|
|
3453
3532
|
target: this.element,
|
|
3454
|
-
detail: {
|
|
3533
|
+
detail: { response, visit },
|
|
3455
3534
|
cancelable: true,
|
|
3456
3535
|
});
|
|
3457
3536
|
return !event.defaultPrevented;
|
|
3458
3537
|
}
|
|
3538
|
+
async visitResponse(response) {
|
|
3539
|
+
const wrapped = new FetchResponse(response);
|
|
3540
|
+
const responseHTML = await wrapped.responseHTML;
|
|
3541
|
+
const { location, redirected, statusCode } = wrapped;
|
|
3542
|
+
return session.visit(location, { response: { redirected, statusCode, responseHTML } });
|
|
3543
|
+
}
|
|
3459
3544
|
findFrameElement(element, submitter) {
|
|
3460
3545
|
var _a;
|
|
3461
3546
|
const id = getAttribute("data-turbo-frame", submitter, element) || this.element.getAttribute("target");
|
|
@@ -3591,6 +3676,9 @@ Copyright © 2022 Basecamp, LLC
|
|
|
3591
3676
|
}
|
|
3592
3677
|
|
|
3593
3678
|
class StreamElement extends HTMLElement {
|
|
3679
|
+
static async renderElement(newElement) {
|
|
3680
|
+
await newElement.performAction();
|
|
3681
|
+
}
|
|
3594
3682
|
async connectedCallback() {
|
|
3595
3683
|
try {
|
|
3596
3684
|
await this.render();
|
|
@@ -3605,9 +3693,10 @@ Copyright © 2022 Basecamp, LLC
|
|
|
3605
3693
|
async render() {
|
|
3606
3694
|
var _a;
|
|
3607
3695
|
return ((_a = this.renderPromise) !== null && _a !== void 0 ? _a : (this.renderPromise = (async () => {
|
|
3608
|
-
|
|
3696
|
+
const event = this.beforeRenderEvent;
|
|
3697
|
+
if (this.dispatchEvent(event)) {
|
|
3609
3698
|
await nextAnimationFrame();
|
|
3610
|
-
|
|
3699
|
+
await event.detail.render(this);
|
|
3611
3700
|
}
|
|
3612
3701
|
})()));
|
|
3613
3702
|
}
|
|
@@ -3651,7 +3740,12 @@ Copyright © 2022 Basecamp, LLC
|
|
|
3651
3740
|
return this.templateElement.content.cloneNode(true);
|
|
3652
3741
|
}
|
|
3653
3742
|
get templateElement() {
|
|
3654
|
-
if (this.firstElementChild
|
|
3743
|
+
if (this.firstElementChild === null) {
|
|
3744
|
+
const template = this.ownerDocument.createElement("template");
|
|
3745
|
+
this.appendChild(template);
|
|
3746
|
+
return template;
|
|
3747
|
+
}
|
|
3748
|
+
else if (this.firstElementChild instanceof HTMLTemplateElement) {
|
|
3655
3749
|
return this.firstElementChild;
|
|
3656
3750
|
}
|
|
3657
3751
|
this.raise("first child element must be a <template> element");
|
|
@@ -3676,7 +3770,7 @@ Copyright © 2022 Basecamp, LLC
|
|
|
3676
3770
|
return new CustomEvent("turbo:before-stream-render", {
|
|
3677
3771
|
bubbles: true,
|
|
3678
3772
|
cancelable: true,
|
|
3679
|
-
detail: { newStream: this },
|
|
3773
|
+
detail: { newStream: this, render: StreamElement.renderElement },
|
|
3680
3774
|
});
|
|
3681
3775
|
}
|
|
3682
3776
|
get targetElementsById() {
|
|
@@ -3758,10 +3852,13 @@ Copyright © 2022 Basecamp, LLC
|
|
|
3758
3852
|
window.Turbo = Turbo;
|
|
3759
3853
|
start();
|
|
3760
3854
|
|
|
3855
|
+
exports.FrameElement = FrameElement;
|
|
3761
3856
|
exports.FrameRenderer = FrameRenderer;
|
|
3762
3857
|
exports.PageRenderer = PageRenderer;
|
|
3763
3858
|
exports.PageSnapshot = PageSnapshot;
|
|
3764
3859
|
exports.StreamActions = StreamActions;
|
|
3860
|
+
exports.StreamElement = StreamElement;
|
|
3861
|
+
exports.StreamSourceElement = StreamSourceElement;
|
|
3765
3862
|
exports.cache = cache;
|
|
3766
3863
|
exports.clearCache = clearCache;
|
|
3767
3864
|
exports.connectStreamSource = connectStreamSource;
|
|
@@ -45,7 +45,7 @@ export declare class FormSubmission {
|
|
|
45
45
|
readonly mustRedirect: boolean;
|
|
46
46
|
state: FormSubmissionState;
|
|
47
47
|
result?: FormSubmissionResult;
|
|
48
|
-
static confirmMethod(message: string, _element: HTMLFormElement): Promise<boolean>;
|
|
48
|
+
static confirmMethod(message: string, _element: HTMLFormElement, _submitter: HTMLElement | undefined): Promise<boolean>;
|
|
49
49
|
constructor(delegate: FormSubmissionDelegate, formElement: HTMLFormElement, submitter?: HTMLElement, mustRedirect?: boolean);
|
|
50
50
|
get method(): FetchMethod;
|
|
51
51
|
get action(): string;
|
|
@@ -53,8 +53,6 @@ export declare class FormSubmission {
|
|
|
53
53
|
get enctype(): FormEnctype;
|
|
54
54
|
get isIdempotent(): boolean;
|
|
55
55
|
get stringFormData(): [string, string][];
|
|
56
|
-
get confirmationMessage(): string | null;
|
|
57
|
-
get needsConfirmation(): boolean;
|
|
58
56
|
start(): Promise<void | FetchResponse>;
|
|
59
57
|
stop(): true | undefined;
|
|
60
58
|
prepareHeadersForRequest(headers: FetchRequestHeaders, request: FetchRequest): void;
|
|
@@ -4,7 +4,7 @@ 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
|
-
|
|
7
|
+
allowsVisitingLocation(location: URL, options: Partial<VisitOptions>): boolean;
|
|
8
8
|
visitProposedToLocation(location: URL, options: Partial<VisitOptions>): Promise<void>;
|
|
9
9
|
notifyApplicationAfterVisitingSamePageLocation(oldURL: URL, newURL: URL): void;
|
|
10
10
|
};
|
|
@@ -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): void
|
|
5
|
+
static renderElement(currentElement: HTMLBodyElement, newElement: HTMLBodyElement): Promise<void>;
|
|
6
6
|
get shouldRender(): boolean;
|
|
7
7
|
get reloadReason(): ReloadReason;
|
|
8
8
|
prepareToRender(): Promise<void>;
|
|
@@ -14,6 +14,9 @@ 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;
|
|
17
20
|
copyNewHeadStylesheetElements(): Promise<void>;
|
|
18
21
|
copyNewHeadScriptElements(): void;
|
|
19
22
|
removeCurrentHeadProvisionalElements(): void;
|
|
@@ -44,6 +44,7 @@ export declare type VisitOptions = {
|
|
|
44
44
|
shouldCacheSnapshot: boolean;
|
|
45
45
|
frame?: string;
|
|
46
46
|
acceptsStreamResponse: boolean;
|
|
47
|
+
initiator: Element;
|
|
47
48
|
};
|
|
48
49
|
export declare type VisitResponse = {
|
|
49
50
|
statusCode: number;
|
|
@@ -57,7 +58,6 @@ export declare enum SystemStatusCode {
|
|
|
57
58
|
}
|
|
58
59
|
export declare class Visit implements FetchRequestDelegate {
|
|
59
60
|
readonly delegate: VisitDelegate;
|
|
60
|
-
readonly identifier: string;
|
|
61
61
|
readonly restorationIdentifier: string;
|
|
62
62
|
readonly action: Action;
|
|
63
63
|
readonly referrer?: URL;
|
|
@@ -66,6 +66,7 @@ export declare class Visit implements FetchRequestDelegate {
|
|
|
66
66
|
readonly willRender: boolean;
|
|
67
67
|
readonly updateHistory: boolean;
|
|
68
68
|
readonly promise: Promise<void>;
|
|
69
|
+
readonly initiator: Element;
|
|
69
70
|
private resolvingFunctions;
|
|
70
71
|
followedRedirect: boolean;
|
|
71
72
|
frame?: number;
|