@hotwired/turbo 7.2.4 → 7.2.5
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/turbo.es2017-esm.js +104 -54
- package/dist/turbo.es2017-umd.js +104 -54
- package/dist/types/core/bardo.d.ts +1 -1
- package/dist/types/core/drive/form_submission.d.ts +2 -2
- package/dist/types/core/drive/navigator.d.ts +1 -1
- package/dist/types/core/drive/page_renderer.d.ts +4 -2
- package/dist/types/core/drive/visit.d.ts +2 -2
- package/dist/types/core/frames/frame_controller.d.ts +5 -7
- package/dist/types/core/renderer.d.ts +2 -2
- package/dist/types/core/types.d.ts +0 -1
- package/dist/types/http/fetch_request.d.ts +1 -1
- package/dist/types/observers/appearance_observer.d.ts +6 -6
- package/dist/types/observers/link_click_observer.d.ts +1 -1
- package/dist/types/tests/functional/frame_tests.d.ts +7 -0
- package/dist/types/tests/helpers/intern_test_case.d.ts +0 -1
- package/dist/types/tests/helpers/page.d.ts +7 -0
- package/dist/types/tests/{functional → integration}/ujs_tests.d.ts +0 -0
- package/dist/types/util.d.ts +2 -0
- package/package.json +2 -2
package/dist/turbo.es2017-esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Turbo 7.2.
|
|
3
|
-
Copyright ©
|
|
2
|
+
Turbo 7.2.5
|
|
3
|
+
Copyright © 2023 37signals LLC
|
|
4
4
|
*/
|
|
5
5
|
(function () {
|
|
6
6
|
if (window.Reflect === undefined ||
|
|
@@ -307,10 +307,6 @@ class FetchResponse {
|
|
|
307
307
|
}
|
|
308
308
|
}
|
|
309
309
|
|
|
310
|
-
function isAction(action) {
|
|
311
|
-
return action == "advance" || action == "replace" || action == "restore";
|
|
312
|
-
}
|
|
313
|
-
|
|
314
310
|
function activateScriptElement(element) {
|
|
315
311
|
if (element.getAttribute("data-turbo-eval") == "false") {
|
|
316
312
|
return element;
|
|
@@ -341,6 +337,7 @@ function dispatch(eventName, { target, cancelable, detail } = {}) {
|
|
|
341
337
|
const event = new CustomEvent(eventName, {
|
|
342
338
|
cancelable,
|
|
343
339
|
bubbles: true,
|
|
340
|
+
composed: true,
|
|
344
341
|
detail,
|
|
345
342
|
});
|
|
346
343
|
if (target && target.isConnected) {
|
|
@@ -440,6 +437,9 @@ function getHistoryMethodForAction(action) {
|
|
|
440
437
|
return history.pushState;
|
|
441
438
|
}
|
|
442
439
|
}
|
|
440
|
+
function isAction(action) {
|
|
441
|
+
return action == "advance" || action == "replace" || action == "restore";
|
|
442
|
+
}
|
|
443
443
|
function getVisitAction(...elements) {
|
|
444
444
|
const action = getAttribute("data-turbo-action", ...elements);
|
|
445
445
|
return isAction(action) ? action : null;
|
|
@@ -461,6 +461,13 @@ function setMetaContent(name, content) {
|
|
|
461
461
|
element.setAttribute("content", content);
|
|
462
462
|
return element;
|
|
463
463
|
}
|
|
464
|
+
function findClosestRecursively(element, selector) {
|
|
465
|
+
var _a;
|
|
466
|
+
if (element instanceof Element) {
|
|
467
|
+
return (element.closest(selector) ||
|
|
468
|
+
findClosestRecursively(element.assignedSlot || ((_a = element.getRootNode()) === null || _a === void 0 ? void 0 : _a.host), selector));
|
|
469
|
+
}
|
|
470
|
+
}
|
|
464
471
|
|
|
465
472
|
var FetchMethod;
|
|
466
473
|
(function (FetchMethod) {
|
|
@@ -508,9 +515,8 @@ class FetchRequest {
|
|
|
508
515
|
this.abortController.abort();
|
|
509
516
|
}
|
|
510
517
|
async perform() {
|
|
511
|
-
var _a, _b;
|
|
512
518
|
const { fetchOptions } = this;
|
|
513
|
-
|
|
519
|
+
this.delegate.prepareRequest(this);
|
|
514
520
|
await this.allowRequestToBeIntercepted(fetchOptions);
|
|
515
521
|
try {
|
|
516
522
|
this.delegate.requestStarted(this);
|
|
@@ -748,11 +754,11 @@ class FormSubmission {
|
|
|
748
754
|
return true;
|
|
749
755
|
}
|
|
750
756
|
}
|
|
751
|
-
|
|
757
|
+
prepareRequest(request) {
|
|
752
758
|
if (!request.isIdempotent) {
|
|
753
759
|
const token = getCookieValue(getMetaContent("csrf-param")) || getMetaContent("csrf-token");
|
|
754
760
|
if (token) {
|
|
755
|
-
headers["X-CSRF-Token"] = token;
|
|
761
|
+
request.headers["X-CSRF-Token"] = token;
|
|
756
762
|
}
|
|
757
763
|
}
|
|
758
764
|
if (this.requestAcceptsTurboStreamResponse(request)) {
|
|
@@ -940,12 +946,17 @@ function submissionDoesNotDismissDialog(form, submitter) {
|
|
|
940
946
|
return method != "dialog";
|
|
941
947
|
}
|
|
942
948
|
function submissionDoesNotTargetIFrame(form, submitter) {
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
949
|
+
if ((submitter === null || submitter === void 0 ? void 0 : submitter.hasAttribute("formtarget")) || form.hasAttribute("target")) {
|
|
950
|
+
const target = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formtarget")) || form.target;
|
|
951
|
+
for (const element of document.getElementsByName(target)) {
|
|
952
|
+
if (element instanceof HTMLIFrameElement)
|
|
953
|
+
return false;
|
|
954
|
+
}
|
|
955
|
+
return true;
|
|
956
|
+
}
|
|
957
|
+
else {
|
|
958
|
+
return true;
|
|
947
959
|
}
|
|
948
|
-
return true;
|
|
949
960
|
}
|
|
950
961
|
|
|
951
962
|
class View {
|
|
@@ -1138,20 +1149,23 @@ class LinkClickObserver {
|
|
|
1138
1149
|
event.shiftKey);
|
|
1139
1150
|
}
|
|
1140
1151
|
findLinkFromClickTarget(target) {
|
|
1141
|
-
|
|
1142
|
-
return target.closest("a[href]:not([target^=_]):not([download])");
|
|
1143
|
-
}
|
|
1152
|
+
return findClosestRecursively(target, "a[href]:not([target^=_]):not([download])");
|
|
1144
1153
|
}
|
|
1145
1154
|
getLocationForLink(link) {
|
|
1146
1155
|
return expandURL(link.getAttribute("href") || "");
|
|
1147
1156
|
}
|
|
1148
1157
|
}
|
|
1149
1158
|
function doesNotTargetIFrame(anchor) {
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1159
|
+
if (anchor.hasAttribute("target")) {
|
|
1160
|
+
for (const element of document.getElementsByName(anchor.target)) {
|
|
1161
|
+
if (element instanceof HTMLIFrameElement)
|
|
1162
|
+
return false;
|
|
1163
|
+
}
|
|
1164
|
+
return true;
|
|
1165
|
+
}
|
|
1166
|
+
else {
|
|
1167
|
+
return true;
|
|
1153
1168
|
}
|
|
1154
|
-
return true;
|
|
1155
1169
|
}
|
|
1156
1170
|
|
|
1157
1171
|
class FormLinkClickObserver {
|
|
@@ -1170,10 +1184,14 @@ class FormLinkClickObserver {
|
|
|
1170
1184
|
link.hasAttribute("data-turbo-method"));
|
|
1171
1185
|
}
|
|
1172
1186
|
followedLinkToLocation(link, location) {
|
|
1173
|
-
const action = location.href;
|
|
1174
1187
|
const form = document.createElement("form");
|
|
1188
|
+
const type = "hidden";
|
|
1189
|
+
for (const [name, value] of location.searchParams) {
|
|
1190
|
+
form.append(Object.assign(document.createElement("input"), { type, name, value }));
|
|
1191
|
+
}
|
|
1192
|
+
const action = Object.assign(location, { search: "" });
|
|
1175
1193
|
form.setAttribute("data-turbo", "true");
|
|
1176
|
-
form.setAttribute("action", action);
|
|
1194
|
+
form.setAttribute("action", action.href);
|
|
1177
1195
|
form.setAttribute("hidden", "");
|
|
1178
1196
|
const method = link.getAttribute("data-turbo-method");
|
|
1179
1197
|
if (method)
|
|
@@ -1181,7 +1199,7 @@ class FormLinkClickObserver {
|
|
|
1181
1199
|
const turboFrame = link.getAttribute("data-turbo-frame");
|
|
1182
1200
|
if (turboFrame)
|
|
1183
1201
|
form.setAttribute("data-turbo-frame", turboFrame);
|
|
1184
|
-
const turboAction = link
|
|
1202
|
+
const turboAction = getVisitAction(link);
|
|
1185
1203
|
if (turboAction)
|
|
1186
1204
|
form.setAttribute("data-turbo-action", turboAction);
|
|
1187
1205
|
const turboConfirm = link.getAttribute("data-turbo-confirm");
|
|
@@ -1202,10 +1220,10 @@ class Bardo {
|
|
|
1202
1220
|
this.delegate = delegate;
|
|
1203
1221
|
this.permanentElementMap = permanentElementMap;
|
|
1204
1222
|
}
|
|
1205
|
-
static preservingPermanentElements(delegate, permanentElementMap, callback) {
|
|
1223
|
+
static async preservingPermanentElements(delegate, permanentElementMap, callback) {
|
|
1206
1224
|
const bardo = new this(delegate, permanentElementMap);
|
|
1207
1225
|
bardo.enter();
|
|
1208
|
-
callback();
|
|
1226
|
+
await callback();
|
|
1209
1227
|
bardo.leave();
|
|
1210
1228
|
}
|
|
1211
1229
|
enter() {
|
|
@@ -1274,8 +1292,8 @@ class Renderer {
|
|
|
1274
1292
|
delete this.resolvingFunctions;
|
|
1275
1293
|
}
|
|
1276
1294
|
}
|
|
1277
|
-
preservingPermanentElements(callback) {
|
|
1278
|
-
Bardo.preservingPermanentElements(this, this.permanentElementMap, callback);
|
|
1295
|
+
async preservingPermanentElements(callback) {
|
|
1296
|
+
await Bardo.preservingPermanentElements(this, this.permanentElementMap, callback);
|
|
1279
1297
|
}
|
|
1280
1298
|
focusFirstAutofocusableElement() {
|
|
1281
1299
|
const element = this.connectedSnapshot.firstAutofocusableElement;
|
|
@@ -1860,6 +1878,8 @@ class Visit {
|
|
|
1860
1878
|
this.adapter.visitProposedToLocation(this.redirectedToLocation, {
|
|
1861
1879
|
action: "replace",
|
|
1862
1880
|
response: this.response,
|
|
1881
|
+
shouldCacheSnapshot: false,
|
|
1882
|
+
willRender: false,
|
|
1863
1883
|
});
|
|
1864
1884
|
this.followedRedirect = true;
|
|
1865
1885
|
}
|
|
@@ -1874,7 +1894,7 @@ class Visit {
|
|
|
1874
1894
|
});
|
|
1875
1895
|
}
|
|
1876
1896
|
}
|
|
1877
|
-
|
|
1897
|
+
prepareRequest(request) {
|
|
1878
1898
|
if (this.acceptsStreamResponse) {
|
|
1879
1899
|
request.acceptResponseType(StreamMessage.contentType);
|
|
1880
1900
|
}
|
|
@@ -2375,10 +2395,8 @@ class Navigator {
|
|
|
2375
2395
|
get restorationIdentifier() {
|
|
2376
2396
|
return this.history.restorationIdentifier;
|
|
2377
2397
|
}
|
|
2378
|
-
getActionForFormSubmission(
|
|
2379
|
-
|
|
2380
|
-
const action = getAttribute("data-turbo-action", submitter, formElement);
|
|
2381
|
-
return isAction(action) ? action : "advance";
|
|
2398
|
+
getActionForFormSubmission({ submitter, formElement }) {
|
|
2399
|
+
return getVisitAction(submitter, formElement) || "advance";
|
|
2382
2400
|
}
|
|
2383
2401
|
}
|
|
2384
2402
|
|
|
@@ -2620,7 +2638,7 @@ class PageRenderer extends Renderer {
|
|
|
2620
2638
|
}
|
|
2621
2639
|
async render() {
|
|
2622
2640
|
if (this.willRender) {
|
|
2623
|
-
this.replaceBody();
|
|
2641
|
+
await this.replaceBody();
|
|
2624
2642
|
}
|
|
2625
2643
|
}
|
|
2626
2644
|
finishRendering() {
|
|
@@ -2639,16 +2657,16 @@ class PageRenderer extends Renderer {
|
|
|
2639
2657
|
return this.newSnapshot.element;
|
|
2640
2658
|
}
|
|
2641
2659
|
async mergeHead() {
|
|
2660
|
+
const mergedHeadElements = this.mergeProvisionalElements();
|
|
2642
2661
|
const newStylesheetElements = this.copyNewHeadStylesheetElements();
|
|
2643
2662
|
this.copyNewHeadScriptElements();
|
|
2644
|
-
|
|
2645
|
-
this.copyNewHeadProvisionalElements();
|
|
2663
|
+
await mergedHeadElements;
|
|
2646
2664
|
await newStylesheetElements;
|
|
2647
2665
|
}
|
|
2648
|
-
replaceBody() {
|
|
2649
|
-
this.preservingPermanentElements(() => {
|
|
2666
|
+
async replaceBody() {
|
|
2667
|
+
await this.preservingPermanentElements(async () => {
|
|
2650
2668
|
this.activateNewBody();
|
|
2651
|
-
this.assignNewBody();
|
|
2669
|
+
await this.assignNewBody();
|
|
2652
2670
|
});
|
|
2653
2671
|
}
|
|
2654
2672
|
get trackedElementsAreIdentical() {
|
|
@@ -2667,6 +2685,35 @@ class PageRenderer extends Renderer {
|
|
|
2667
2685
|
document.head.appendChild(activateScriptElement(element));
|
|
2668
2686
|
}
|
|
2669
2687
|
}
|
|
2688
|
+
async mergeProvisionalElements() {
|
|
2689
|
+
const newHeadElements = [...this.newHeadProvisionalElements];
|
|
2690
|
+
for (const element of this.currentHeadProvisionalElements) {
|
|
2691
|
+
if (!this.isCurrentElementInElementList(element, newHeadElements)) {
|
|
2692
|
+
document.head.removeChild(element);
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
for (const element of newHeadElements) {
|
|
2696
|
+
document.head.appendChild(element);
|
|
2697
|
+
}
|
|
2698
|
+
}
|
|
2699
|
+
isCurrentElementInElementList(element, elementList) {
|
|
2700
|
+
for (const [index, newElement] of elementList.entries()) {
|
|
2701
|
+
if (element.tagName == "TITLE") {
|
|
2702
|
+
if (newElement.tagName != "TITLE") {
|
|
2703
|
+
continue;
|
|
2704
|
+
}
|
|
2705
|
+
if (element.innerHTML == newElement.innerHTML) {
|
|
2706
|
+
elementList.splice(index, 1);
|
|
2707
|
+
return true;
|
|
2708
|
+
}
|
|
2709
|
+
}
|
|
2710
|
+
if (newElement.isEqualNode(element)) {
|
|
2711
|
+
elementList.splice(index, 1);
|
|
2712
|
+
return true;
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
return false;
|
|
2716
|
+
}
|
|
2670
2717
|
removeCurrentHeadProvisionalElements() {
|
|
2671
2718
|
for (const element of this.currentHeadProvisionalElements) {
|
|
2672
2719
|
document.head.removeChild(element);
|
|
@@ -2687,8 +2734,8 @@ class PageRenderer extends Renderer {
|
|
|
2687
2734
|
inertScriptElement.replaceWith(activatedScriptElement);
|
|
2688
2735
|
}
|
|
2689
2736
|
}
|
|
2690
|
-
assignNewBody() {
|
|
2691
|
-
this.renderElement(this.currentElement, this.newElement);
|
|
2737
|
+
async assignNewBody() {
|
|
2738
|
+
await this.renderElement(this.currentElement, this.newElement);
|
|
2692
2739
|
}
|
|
2693
2740
|
get newHeadStylesheetElements() {
|
|
2694
2741
|
return this.newHeadSnapshot.getStylesheetElementsNotInSnapshot(this.currentHeadSnapshot);
|
|
@@ -3105,8 +3152,8 @@ class Session {
|
|
|
3105
3152
|
}
|
|
3106
3153
|
}
|
|
3107
3154
|
elementIsNavigatable(element) {
|
|
3108
|
-
const container = element
|
|
3109
|
-
const withinFrame = element
|
|
3155
|
+
const container = findClosestRecursively(element, "[data-turbo]");
|
|
3156
|
+
const withinFrame = findClosestRecursively(element, "turbo-frame");
|
|
3110
3157
|
if (this.drive || withinFrame) {
|
|
3111
3158
|
if (container) {
|
|
3112
3159
|
return container.getAttribute("data-turbo") != "false";
|
|
@@ -3125,8 +3172,7 @@ class Session {
|
|
|
3125
3172
|
}
|
|
3126
3173
|
}
|
|
3127
3174
|
getActionForLink(link) {
|
|
3128
|
-
|
|
3129
|
-
return isAction(action) ? action : "advance";
|
|
3175
|
+
return getVisitAction(link) || "advance";
|
|
3130
3176
|
}
|
|
3131
3177
|
get snapshot() {
|
|
3132
3178
|
return this.view.snapshot;
|
|
@@ -3186,7 +3232,10 @@ const StreamActions = {
|
|
|
3186
3232
|
this.targetElements.forEach((e) => e.replaceWith(this.templateContent));
|
|
3187
3233
|
},
|
|
3188
3234
|
update() {
|
|
3189
|
-
this.targetElements.forEach((
|
|
3235
|
+
this.targetElements.forEach((targetElement) => {
|
|
3236
|
+
targetElement.innerHTML = "";
|
|
3237
|
+
targetElement.append(this.templateContent);
|
|
3238
|
+
});
|
|
3190
3239
|
},
|
|
3191
3240
|
};
|
|
3192
3241
|
|
|
@@ -3374,7 +3423,8 @@ class FrameController {
|
|
|
3374
3423
|
this.fetchResponseLoaded = () => { };
|
|
3375
3424
|
}
|
|
3376
3425
|
}
|
|
3377
|
-
elementAppearedInViewport(
|
|
3426
|
+
elementAppearedInViewport(element) {
|
|
3427
|
+
this.proposeVisitIfNavigatedWithAction(element, element);
|
|
3378
3428
|
this.loadSourceURL();
|
|
3379
3429
|
}
|
|
3380
3430
|
willSubmitFormLinkToLocation(link) {
|
|
@@ -3400,12 +3450,12 @@ class FrameController {
|
|
|
3400
3450
|
}
|
|
3401
3451
|
this.formSubmission = new FormSubmission(this, element, submitter);
|
|
3402
3452
|
const { fetchRequest } = this.formSubmission;
|
|
3403
|
-
this.
|
|
3453
|
+
this.prepareRequest(fetchRequest);
|
|
3404
3454
|
this.formSubmission.start();
|
|
3405
3455
|
}
|
|
3406
|
-
|
|
3456
|
+
prepareRequest(request) {
|
|
3407
3457
|
var _a;
|
|
3408
|
-
headers["Turbo-Frame"] = this.id;
|
|
3458
|
+
request.headers["Turbo-Frame"] = this.id;
|
|
3409
3459
|
if ((_a = this.currentNavigationElement) === null || _a === void 0 ? void 0 : _a.hasAttribute("data-turbo-stream")) {
|
|
3410
3460
|
request.acceptResponseType(StreamMessage.contentType);
|
|
3411
3461
|
}
|
|
@@ -3485,7 +3535,6 @@ class FrameController {
|
|
|
3485
3535
|
}
|
|
3486
3536
|
navigateFrame(element, url, submitter) {
|
|
3487
3537
|
const frame = this.findFrameElement(element, submitter);
|
|
3488
|
-
this.pageSnapshot = PageSnapshot.fromElement(frame).clone();
|
|
3489
3538
|
frame.delegate.proposeVisitIfNavigatedWithAction(frame, element, submitter);
|
|
3490
3539
|
this.withCurrentNavigationElement(element, () => {
|
|
3491
3540
|
frame.src = url;
|
|
@@ -3493,7 +3542,8 @@ class FrameController {
|
|
|
3493
3542
|
}
|
|
3494
3543
|
proposeVisitIfNavigatedWithAction(frame, element, submitter) {
|
|
3495
3544
|
this.action = getVisitAction(submitter, element, frame);
|
|
3496
|
-
if (
|
|
3545
|
+
if (this.action) {
|
|
3546
|
+
const pageSnapshot = PageSnapshot.fromElement(frame).clone();
|
|
3497
3547
|
const { visitCachedSnapshot } = frame.delegate;
|
|
3498
3548
|
frame.delegate.fetchResponseLoaded = (fetchResponse) => {
|
|
3499
3549
|
if (frame.src) {
|
|
@@ -3506,7 +3556,7 @@ class FrameController {
|
|
|
3506
3556
|
willRender: false,
|
|
3507
3557
|
updateHistory: false,
|
|
3508
3558
|
restorationIdentifier: this.restorationIdentifier,
|
|
3509
|
-
snapshot:
|
|
3559
|
+
snapshot: pageSnapshot,
|
|
3510
3560
|
};
|
|
3511
3561
|
if (this.action)
|
|
3512
3562
|
options.action = this.action;
|
package/dist/turbo.es2017-umd.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Turbo 7.2.
|
|
3
|
-
Copyright ©
|
|
2
|
+
Turbo 7.2.5
|
|
3
|
+
Copyright © 2023 37signals LLC
|
|
4
4
|
*/
|
|
5
5
|
(function (global, factory) {
|
|
6
6
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
@@ -313,10 +313,6 @@ Copyright © 2022 37signals LLC
|
|
|
313
313
|
}
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
-
function isAction(action) {
|
|
317
|
-
return action == "advance" || action == "replace" || action == "restore";
|
|
318
|
-
}
|
|
319
|
-
|
|
320
316
|
function activateScriptElement(element) {
|
|
321
317
|
if (element.getAttribute("data-turbo-eval") == "false") {
|
|
322
318
|
return element;
|
|
@@ -347,6 +343,7 @@ Copyright © 2022 37signals LLC
|
|
|
347
343
|
const event = new CustomEvent(eventName, {
|
|
348
344
|
cancelable,
|
|
349
345
|
bubbles: true,
|
|
346
|
+
composed: true,
|
|
350
347
|
detail,
|
|
351
348
|
});
|
|
352
349
|
if (target && target.isConnected) {
|
|
@@ -446,6 +443,9 @@ Copyright © 2022 37signals LLC
|
|
|
446
443
|
return history.pushState;
|
|
447
444
|
}
|
|
448
445
|
}
|
|
446
|
+
function isAction(action) {
|
|
447
|
+
return action == "advance" || action == "replace" || action == "restore";
|
|
448
|
+
}
|
|
449
449
|
function getVisitAction(...elements) {
|
|
450
450
|
const action = getAttribute("data-turbo-action", ...elements);
|
|
451
451
|
return isAction(action) ? action : null;
|
|
@@ -467,6 +467,13 @@ Copyright © 2022 37signals LLC
|
|
|
467
467
|
element.setAttribute("content", content);
|
|
468
468
|
return element;
|
|
469
469
|
}
|
|
470
|
+
function findClosestRecursively(element, selector) {
|
|
471
|
+
var _a;
|
|
472
|
+
if (element instanceof Element) {
|
|
473
|
+
return (element.closest(selector) ||
|
|
474
|
+
findClosestRecursively(element.assignedSlot || ((_a = element.getRootNode()) === null || _a === void 0 ? void 0 : _a.host), selector));
|
|
475
|
+
}
|
|
476
|
+
}
|
|
470
477
|
|
|
471
478
|
var FetchMethod;
|
|
472
479
|
(function (FetchMethod) {
|
|
@@ -514,9 +521,8 @@ Copyright © 2022 37signals LLC
|
|
|
514
521
|
this.abortController.abort();
|
|
515
522
|
}
|
|
516
523
|
async perform() {
|
|
517
|
-
var _a, _b;
|
|
518
524
|
const { fetchOptions } = this;
|
|
519
|
-
|
|
525
|
+
this.delegate.prepareRequest(this);
|
|
520
526
|
await this.allowRequestToBeIntercepted(fetchOptions);
|
|
521
527
|
try {
|
|
522
528
|
this.delegate.requestStarted(this);
|
|
@@ -754,11 +760,11 @@ Copyright © 2022 37signals LLC
|
|
|
754
760
|
return true;
|
|
755
761
|
}
|
|
756
762
|
}
|
|
757
|
-
|
|
763
|
+
prepareRequest(request) {
|
|
758
764
|
if (!request.isIdempotent) {
|
|
759
765
|
const token = getCookieValue(getMetaContent("csrf-param")) || getMetaContent("csrf-token");
|
|
760
766
|
if (token) {
|
|
761
|
-
headers["X-CSRF-Token"] = token;
|
|
767
|
+
request.headers["X-CSRF-Token"] = token;
|
|
762
768
|
}
|
|
763
769
|
}
|
|
764
770
|
if (this.requestAcceptsTurboStreamResponse(request)) {
|
|
@@ -946,12 +952,17 @@ Copyright © 2022 37signals LLC
|
|
|
946
952
|
return method != "dialog";
|
|
947
953
|
}
|
|
948
954
|
function submissionDoesNotTargetIFrame(form, submitter) {
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
955
|
+
if ((submitter === null || submitter === void 0 ? void 0 : submitter.hasAttribute("formtarget")) || form.hasAttribute("target")) {
|
|
956
|
+
const target = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formtarget")) || form.target;
|
|
957
|
+
for (const element of document.getElementsByName(target)) {
|
|
958
|
+
if (element instanceof HTMLIFrameElement)
|
|
959
|
+
return false;
|
|
960
|
+
}
|
|
961
|
+
return true;
|
|
962
|
+
}
|
|
963
|
+
else {
|
|
964
|
+
return true;
|
|
953
965
|
}
|
|
954
|
-
return true;
|
|
955
966
|
}
|
|
956
967
|
|
|
957
968
|
class View {
|
|
@@ -1144,20 +1155,23 @@ Copyright © 2022 37signals LLC
|
|
|
1144
1155
|
event.shiftKey);
|
|
1145
1156
|
}
|
|
1146
1157
|
findLinkFromClickTarget(target) {
|
|
1147
|
-
|
|
1148
|
-
return target.closest("a[href]:not([target^=_]):not([download])");
|
|
1149
|
-
}
|
|
1158
|
+
return findClosestRecursively(target, "a[href]:not([target^=_]):not([download])");
|
|
1150
1159
|
}
|
|
1151
1160
|
getLocationForLink(link) {
|
|
1152
1161
|
return expandURL(link.getAttribute("href") || "");
|
|
1153
1162
|
}
|
|
1154
1163
|
}
|
|
1155
1164
|
function doesNotTargetIFrame(anchor) {
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1165
|
+
if (anchor.hasAttribute("target")) {
|
|
1166
|
+
for (const element of document.getElementsByName(anchor.target)) {
|
|
1167
|
+
if (element instanceof HTMLIFrameElement)
|
|
1168
|
+
return false;
|
|
1169
|
+
}
|
|
1170
|
+
return true;
|
|
1171
|
+
}
|
|
1172
|
+
else {
|
|
1173
|
+
return true;
|
|
1159
1174
|
}
|
|
1160
|
-
return true;
|
|
1161
1175
|
}
|
|
1162
1176
|
|
|
1163
1177
|
class FormLinkClickObserver {
|
|
@@ -1176,10 +1190,14 @@ Copyright © 2022 37signals LLC
|
|
|
1176
1190
|
link.hasAttribute("data-turbo-method"));
|
|
1177
1191
|
}
|
|
1178
1192
|
followedLinkToLocation(link, location) {
|
|
1179
|
-
const action = location.href;
|
|
1180
1193
|
const form = document.createElement("form");
|
|
1194
|
+
const type = "hidden";
|
|
1195
|
+
for (const [name, value] of location.searchParams) {
|
|
1196
|
+
form.append(Object.assign(document.createElement("input"), { type, name, value }));
|
|
1197
|
+
}
|
|
1198
|
+
const action = Object.assign(location, { search: "" });
|
|
1181
1199
|
form.setAttribute("data-turbo", "true");
|
|
1182
|
-
form.setAttribute("action", action);
|
|
1200
|
+
form.setAttribute("action", action.href);
|
|
1183
1201
|
form.setAttribute("hidden", "");
|
|
1184
1202
|
const method = link.getAttribute("data-turbo-method");
|
|
1185
1203
|
if (method)
|
|
@@ -1187,7 +1205,7 @@ Copyright © 2022 37signals LLC
|
|
|
1187
1205
|
const turboFrame = link.getAttribute("data-turbo-frame");
|
|
1188
1206
|
if (turboFrame)
|
|
1189
1207
|
form.setAttribute("data-turbo-frame", turboFrame);
|
|
1190
|
-
const turboAction = link
|
|
1208
|
+
const turboAction = getVisitAction(link);
|
|
1191
1209
|
if (turboAction)
|
|
1192
1210
|
form.setAttribute("data-turbo-action", turboAction);
|
|
1193
1211
|
const turboConfirm = link.getAttribute("data-turbo-confirm");
|
|
@@ -1208,10 +1226,10 @@ Copyright © 2022 37signals LLC
|
|
|
1208
1226
|
this.delegate = delegate;
|
|
1209
1227
|
this.permanentElementMap = permanentElementMap;
|
|
1210
1228
|
}
|
|
1211
|
-
static preservingPermanentElements(delegate, permanentElementMap, callback) {
|
|
1229
|
+
static async preservingPermanentElements(delegate, permanentElementMap, callback) {
|
|
1212
1230
|
const bardo = new this(delegate, permanentElementMap);
|
|
1213
1231
|
bardo.enter();
|
|
1214
|
-
callback();
|
|
1232
|
+
await callback();
|
|
1215
1233
|
bardo.leave();
|
|
1216
1234
|
}
|
|
1217
1235
|
enter() {
|
|
@@ -1280,8 +1298,8 @@ Copyright © 2022 37signals LLC
|
|
|
1280
1298
|
delete this.resolvingFunctions;
|
|
1281
1299
|
}
|
|
1282
1300
|
}
|
|
1283
|
-
preservingPermanentElements(callback) {
|
|
1284
|
-
Bardo.preservingPermanentElements(this, this.permanentElementMap, callback);
|
|
1301
|
+
async preservingPermanentElements(callback) {
|
|
1302
|
+
await Bardo.preservingPermanentElements(this, this.permanentElementMap, callback);
|
|
1285
1303
|
}
|
|
1286
1304
|
focusFirstAutofocusableElement() {
|
|
1287
1305
|
const element = this.connectedSnapshot.firstAutofocusableElement;
|
|
@@ -1866,6 +1884,8 @@ Copyright © 2022 37signals LLC
|
|
|
1866
1884
|
this.adapter.visitProposedToLocation(this.redirectedToLocation, {
|
|
1867
1885
|
action: "replace",
|
|
1868
1886
|
response: this.response,
|
|
1887
|
+
shouldCacheSnapshot: false,
|
|
1888
|
+
willRender: false,
|
|
1869
1889
|
});
|
|
1870
1890
|
this.followedRedirect = true;
|
|
1871
1891
|
}
|
|
@@ -1880,7 +1900,7 @@ Copyright © 2022 37signals LLC
|
|
|
1880
1900
|
});
|
|
1881
1901
|
}
|
|
1882
1902
|
}
|
|
1883
|
-
|
|
1903
|
+
prepareRequest(request) {
|
|
1884
1904
|
if (this.acceptsStreamResponse) {
|
|
1885
1905
|
request.acceptResponseType(StreamMessage.contentType);
|
|
1886
1906
|
}
|
|
@@ -2381,10 +2401,8 @@ Copyright © 2022 37signals LLC
|
|
|
2381
2401
|
get restorationIdentifier() {
|
|
2382
2402
|
return this.history.restorationIdentifier;
|
|
2383
2403
|
}
|
|
2384
|
-
getActionForFormSubmission(
|
|
2385
|
-
|
|
2386
|
-
const action = getAttribute("data-turbo-action", submitter, formElement);
|
|
2387
|
-
return isAction(action) ? action : "advance";
|
|
2404
|
+
getActionForFormSubmission({ submitter, formElement }) {
|
|
2405
|
+
return getVisitAction(submitter, formElement) || "advance";
|
|
2388
2406
|
}
|
|
2389
2407
|
}
|
|
2390
2408
|
|
|
@@ -2626,7 +2644,7 @@ Copyright © 2022 37signals LLC
|
|
|
2626
2644
|
}
|
|
2627
2645
|
async render() {
|
|
2628
2646
|
if (this.willRender) {
|
|
2629
|
-
this.replaceBody();
|
|
2647
|
+
await this.replaceBody();
|
|
2630
2648
|
}
|
|
2631
2649
|
}
|
|
2632
2650
|
finishRendering() {
|
|
@@ -2645,16 +2663,16 @@ Copyright © 2022 37signals LLC
|
|
|
2645
2663
|
return this.newSnapshot.element;
|
|
2646
2664
|
}
|
|
2647
2665
|
async mergeHead() {
|
|
2666
|
+
const mergedHeadElements = this.mergeProvisionalElements();
|
|
2648
2667
|
const newStylesheetElements = this.copyNewHeadStylesheetElements();
|
|
2649
2668
|
this.copyNewHeadScriptElements();
|
|
2650
|
-
|
|
2651
|
-
this.copyNewHeadProvisionalElements();
|
|
2669
|
+
await mergedHeadElements;
|
|
2652
2670
|
await newStylesheetElements;
|
|
2653
2671
|
}
|
|
2654
|
-
replaceBody() {
|
|
2655
|
-
this.preservingPermanentElements(() => {
|
|
2672
|
+
async replaceBody() {
|
|
2673
|
+
await this.preservingPermanentElements(async () => {
|
|
2656
2674
|
this.activateNewBody();
|
|
2657
|
-
this.assignNewBody();
|
|
2675
|
+
await this.assignNewBody();
|
|
2658
2676
|
});
|
|
2659
2677
|
}
|
|
2660
2678
|
get trackedElementsAreIdentical() {
|
|
@@ -2673,6 +2691,35 @@ Copyright © 2022 37signals LLC
|
|
|
2673
2691
|
document.head.appendChild(activateScriptElement(element));
|
|
2674
2692
|
}
|
|
2675
2693
|
}
|
|
2694
|
+
async mergeProvisionalElements() {
|
|
2695
|
+
const newHeadElements = [...this.newHeadProvisionalElements];
|
|
2696
|
+
for (const element of this.currentHeadProvisionalElements) {
|
|
2697
|
+
if (!this.isCurrentElementInElementList(element, newHeadElements)) {
|
|
2698
|
+
document.head.removeChild(element);
|
|
2699
|
+
}
|
|
2700
|
+
}
|
|
2701
|
+
for (const element of newHeadElements) {
|
|
2702
|
+
document.head.appendChild(element);
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
isCurrentElementInElementList(element, elementList) {
|
|
2706
|
+
for (const [index, newElement] of elementList.entries()) {
|
|
2707
|
+
if (element.tagName == "TITLE") {
|
|
2708
|
+
if (newElement.tagName != "TITLE") {
|
|
2709
|
+
continue;
|
|
2710
|
+
}
|
|
2711
|
+
if (element.innerHTML == newElement.innerHTML) {
|
|
2712
|
+
elementList.splice(index, 1);
|
|
2713
|
+
return true;
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
if (newElement.isEqualNode(element)) {
|
|
2717
|
+
elementList.splice(index, 1);
|
|
2718
|
+
return true;
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
2721
|
+
return false;
|
|
2722
|
+
}
|
|
2676
2723
|
removeCurrentHeadProvisionalElements() {
|
|
2677
2724
|
for (const element of this.currentHeadProvisionalElements) {
|
|
2678
2725
|
document.head.removeChild(element);
|
|
@@ -2693,8 +2740,8 @@ Copyright © 2022 37signals LLC
|
|
|
2693
2740
|
inertScriptElement.replaceWith(activatedScriptElement);
|
|
2694
2741
|
}
|
|
2695
2742
|
}
|
|
2696
|
-
assignNewBody() {
|
|
2697
|
-
this.renderElement(this.currentElement, this.newElement);
|
|
2743
|
+
async assignNewBody() {
|
|
2744
|
+
await this.renderElement(this.currentElement, this.newElement);
|
|
2698
2745
|
}
|
|
2699
2746
|
get newHeadStylesheetElements() {
|
|
2700
2747
|
return this.newHeadSnapshot.getStylesheetElementsNotInSnapshot(this.currentHeadSnapshot);
|
|
@@ -3111,8 +3158,8 @@ Copyright © 2022 37signals LLC
|
|
|
3111
3158
|
}
|
|
3112
3159
|
}
|
|
3113
3160
|
elementIsNavigatable(element) {
|
|
3114
|
-
const container = element
|
|
3115
|
-
const withinFrame = element
|
|
3161
|
+
const container = findClosestRecursively(element, "[data-turbo]");
|
|
3162
|
+
const withinFrame = findClosestRecursively(element, "turbo-frame");
|
|
3116
3163
|
if (this.drive || withinFrame) {
|
|
3117
3164
|
if (container) {
|
|
3118
3165
|
return container.getAttribute("data-turbo") != "false";
|
|
@@ -3131,8 +3178,7 @@ Copyright © 2022 37signals LLC
|
|
|
3131
3178
|
}
|
|
3132
3179
|
}
|
|
3133
3180
|
getActionForLink(link) {
|
|
3134
|
-
|
|
3135
|
-
return isAction(action) ? action : "advance";
|
|
3181
|
+
return getVisitAction(link) || "advance";
|
|
3136
3182
|
}
|
|
3137
3183
|
get snapshot() {
|
|
3138
3184
|
return this.view.snapshot;
|
|
@@ -3192,7 +3238,10 @@ Copyright © 2022 37signals LLC
|
|
|
3192
3238
|
this.targetElements.forEach((e) => e.replaceWith(this.templateContent));
|
|
3193
3239
|
},
|
|
3194
3240
|
update() {
|
|
3195
|
-
this.targetElements.forEach((
|
|
3241
|
+
this.targetElements.forEach((targetElement) => {
|
|
3242
|
+
targetElement.innerHTML = "";
|
|
3243
|
+
targetElement.append(this.templateContent);
|
|
3244
|
+
});
|
|
3196
3245
|
},
|
|
3197
3246
|
};
|
|
3198
3247
|
|
|
@@ -3380,7 +3429,8 @@ Copyright © 2022 37signals LLC
|
|
|
3380
3429
|
this.fetchResponseLoaded = () => { };
|
|
3381
3430
|
}
|
|
3382
3431
|
}
|
|
3383
|
-
elementAppearedInViewport(
|
|
3432
|
+
elementAppearedInViewport(element) {
|
|
3433
|
+
this.proposeVisitIfNavigatedWithAction(element, element);
|
|
3384
3434
|
this.loadSourceURL();
|
|
3385
3435
|
}
|
|
3386
3436
|
willSubmitFormLinkToLocation(link) {
|
|
@@ -3406,12 +3456,12 @@ Copyright © 2022 37signals LLC
|
|
|
3406
3456
|
}
|
|
3407
3457
|
this.formSubmission = new FormSubmission(this, element, submitter);
|
|
3408
3458
|
const { fetchRequest } = this.formSubmission;
|
|
3409
|
-
this.
|
|
3459
|
+
this.prepareRequest(fetchRequest);
|
|
3410
3460
|
this.formSubmission.start();
|
|
3411
3461
|
}
|
|
3412
|
-
|
|
3462
|
+
prepareRequest(request) {
|
|
3413
3463
|
var _a;
|
|
3414
|
-
headers["Turbo-Frame"] = this.id;
|
|
3464
|
+
request.headers["Turbo-Frame"] = this.id;
|
|
3415
3465
|
if ((_a = this.currentNavigationElement) === null || _a === void 0 ? void 0 : _a.hasAttribute("data-turbo-stream")) {
|
|
3416
3466
|
request.acceptResponseType(StreamMessage.contentType);
|
|
3417
3467
|
}
|
|
@@ -3491,7 +3541,6 @@ Copyright © 2022 37signals LLC
|
|
|
3491
3541
|
}
|
|
3492
3542
|
navigateFrame(element, url, submitter) {
|
|
3493
3543
|
const frame = this.findFrameElement(element, submitter);
|
|
3494
|
-
this.pageSnapshot = PageSnapshot.fromElement(frame).clone();
|
|
3495
3544
|
frame.delegate.proposeVisitIfNavigatedWithAction(frame, element, submitter);
|
|
3496
3545
|
this.withCurrentNavigationElement(element, () => {
|
|
3497
3546
|
frame.src = url;
|
|
@@ -3499,7 +3548,8 @@ Copyright © 2022 37signals LLC
|
|
|
3499
3548
|
}
|
|
3500
3549
|
proposeVisitIfNavigatedWithAction(frame, element, submitter) {
|
|
3501
3550
|
this.action = getVisitAction(submitter, element, frame);
|
|
3502
|
-
if (
|
|
3551
|
+
if (this.action) {
|
|
3552
|
+
const pageSnapshot = PageSnapshot.fromElement(frame).clone();
|
|
3503
3553
|
const { visitCachedSnapshot } = frame.delegate;
|
|
3504
3554
|
frame.delegate.fetchResponseLoaded = (fetchResponse) => {
|
|
3505
3555
|
if (frame.src) {
|
|
@@ -3512,7 +3562,7 @@ Copyright © 2022 37signals LLC
|
|
|
3512
3562
|
willRender: false,
|
|
3513
3563
|
updateHistory: false,
|
|
3514
3564
|
restorationIdentifier: this.restorationIdentifier,
|
|
3515
|
-
snapshot:
|
|
3565
|
+
snapshot: pageSnapshot,
|
|
3516
3566
|
};
|
|
3517
3567
|
if (this.action)
|
|
3518
3568
|
options.action = this.action;
|
|
@@ -6,7 +6,7 @@ export interface BardoDelegate {
|
|
|
6
6
|
export declare class Bardo {
|
|
7
7
|
readonly permanentElementMap: PermanentElementMap;
|
|
8
8
|
readonly delegate: BardoDelegate;
|
|
9
|
-
static preservingPermanentElements(delegate: BardoDelegate, permanentElementMap: PermanentElementMap, callback: () => void): void
|
|
9
|
+
static preservingPermanentElements(delegate: BardoDelegate, permanentElementMap: PermanentElementMap, callback: () => void): Promise<void>;
|
|
10
10
|
constructor(delegate: BardoDelegate, permanentElementMap: PermanentElementMap);
|
|
11
11
|
enter(): void;
|
|
12
12
|
leave(): void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FetchRequest, FetchMethod
|
|
1
|
+
import { FetchRequest, FetchMethod } from "../../http/fetch_request";
|
|
2
2
|
import { FetchResponse } from "../../http/fetch_response";
|
|
3
3
|
export interface FormSubmissionDelegate {
|
|
4
4
|
formSubmissionStarted(formSubmission: FormSubmission): void;
|
|
@@ -55,7 +55,7 @@ export declare class FormSubmission {
|
|
|
55
55
|
get stringFormData(): [string, string][];
|
|
56
56
|
start(): Promise<void | FetchResponse>;
|
|
57
57
|
stop(): true | undefined;
|
|
58
|
-
|
|
58
|
+
prepareRequest(request: FetchRequest): void;
|
|
59
59
|
requestStarted(_request: FetchRequest): void;
|
|
60
60
|
requestPreventedHandlingResponse(request: FetchRequest, response: FetchResponse): void;
|
|
61
61
|
requestSucceededWithResponse(request: FetchRequest, response: FetchResponse): void;
|
|
@@ -31,5 +31,5 @@ export declare class Navigator {
|
|
|
31
31
|
visitScrolledToSamePageLocation(oldURL: URL, newURL: URL): void;
|
|
32
32
|
get location(): URL;
|
|
33
33
|
get restorationIdentifier(): string;
|
|
34
|
-
getActionForFormSubmission(
|
|
34
|
+
getActionForFormSubmission({ submitter, formElement }: FormSubmission): Action;
|
|
35
35
|
}
|
|
@@ -12,15 +12,17 @@ export declare class PageRenderer extends Renderer<HTMLBodyElement, PageSnapshot
|
|
|
12
12
|
get newHeadSnapshot(): import("./head_snapshot").HeadSnapshot;
|
|
13
13
|
get newElement(): HTMLBodyElement;
|
|
14
14
|
mergeHead(): Promise<void>;
|
|
15
|
-
replaceBody(): void
|
|
15
|
+
replaceBody(): Promise<void>;
|
|
16
16
|
get trackedElementsAreIdentical(): boolean;
|
|
17
17
|
copyNewHeadStylesheetElements(): Promise<void>;
|
|
18
18
|
copyNewHeadScriptElements(): void;
|
|
19
|
+
mergeProvisionalElements(): Promise<void>;
|
|
20
|
+
isCurrentElementInElementList(element: Element, elementList: Element[]): boolean;
|
|
19
21
|
removeCurrentHeadProvisionalElements(): void;
|
|
20
22
|
copyNewHeadProvisionalElements(): void;
|
|
21
23
|
activateNewBody(): void;
|
|
22
24
|
activateNewBodyScriptElements(): void;
|
|
23
|
-
assignNewBody(): void
|
|
25
|
+
assignNewBody(): Promise<void>;
|
|
24
26
|
get newHeadStylesheetElements(): HTMLLinkElement[];
|
|
25
27
|
get newHeadScriptElements(): HTMLScriptElement[];
|
|
26
28
|
get currentHeadProvisionalElements(): Element[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Adapter } from "../native/adapter";
|
|
2
|
-
import { FetchRequest, FetchRequestDelegate
|
|
2
|
+
import { FetchRequest, FetchRequestDelegate } from "../../http/fetch_request";
|
|
3
3
|
import { FetchResponse } from "../../http/fetch_response";
|
|
4
4
|
import { History } from "./history";
|
|
5
5
|
import { Snapshot } from "../snapshot";
|
|
@@ -104,7 +104,7 @@ export declare class Visit implements FetchRequestDelegate {
|
|
|
104
104
|
loadCachedSnapshot(): void;
|
|
105
105
|
followRedirect(): void;
|
|
106
106
|
goToSamePageAnchor(): void;
|
|
107
|
-
|
|
107
|
+
prepareRequest(request: FetchRequest): void;
|
|
108
108
|
requestStarted(): void;
|
|
109
109
|
requestPreventedHandlingResponse(_request: FetchRequest, _response: FetchResponse): void;
|
|
110
110
|
requestSucceededWithResponse(request: FetchRequest, response: FetchResponse): Promise<void>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FrameElement, FrameElementDelegate, FrameLoadingStyle } from "../../elements/frame_element";
|
|
2
|
-
import { FetchRequest, FetchRequestDelegate
|
|
2
|
+
import { FetchRequest, FetchRequestDelegate } from "../../http/fetch_request";
|
|
3
3
|
import { FetchResponse } from "../../http/fetch_response";
|
|
4
4
|
import { AppearanceObserver, AppearanceObserverDelegate } from "../../observers/appearance_observer";
|
|
5
5
|
import { FormSubmission, FormSubmissionDelegate } from "../drive/form_submission";
|
|
@@ -11,16 +11,15 @@ import { FrameView } from "./frame_view";
|
|
|
11
11
|
import { LinkInterceptor, LinkInterceptorDelegate } from "./link_interceptor";
|
|
12
12
|
import { FormLinkClickObserver, FormLinkClickObserverDelegate } from "../../observers/form_link_click_observer";
|
|
13
13
|
import { VisitOptions } from "../drive/visit";
|
|
14
|
-
import { PageSnapshot } from "../drive/page_snapshot";
|
|
15
14
|
declare type VisitFallback = (location: Response | Locatable, options: Partial<VisitOptions>) => Promise<void>;
|
|
16
15
|
export declare type TurboFrameMissingEvent = CustomEvent<{
|
|
17
16
|
response: Response;
|
|
18
17
|
visit: VisitFallback;
|
|
19
18
|
}>;
|
|
20
|
-
export declare class FrameController implements AppearanceObserverDelegate
|
|
19
|
+
export declare class FrameController implements AppearanceObserverDelegate<FrameElement>, FetchRequestDelegate, FormSubmitObserverDelegate, FormSubmissionDelegate, FrameElementDelegate, FormLinkClickObserverDelegate, LinkInterceptorDelegate, ViewDelegate<FrameElement, Snapshot<FrameElement>> {
|
|
21
20
|
readonly element: FrameElement;
|
|
22
21
|
readonly view: FrameView;
|
|
23
|
-
readonly appearanceObserver: AppearanceObserver
|
|
22
|
+
readonly appearanceObserver: AppearanceObserver<FrameElement>;
|
|
24
23
|
readonly formLinkClickObserver: FormLinkClickObserver;
|
|
25
24
|
readonly linkInterceptor: LinkInterceptor;
|
|
26
25
|
readonly formSubmitObserver: FormSubmitObserver;
|
|
@@ -35,7 +34,6 @@ export declare class FrameController implements AppearanceObserverDelegate, Fetc
|
|
|
35
34
|
readonly restorationIdentifier: string;
|
|
36
35
|
private previousFrameElement?;
|
|
37
36
|
private currentNavigationElement?;
|
|
38
|
-
pageSnapshot?: PageSnapshot;
|
|
39
37
|
constructor(element: FrameElement);
|
|
40
38
|
connect(): void;
|
|
41
39
|
disconnect(): void;
|
|
@@ -46,14 +44,14 @@ export declare class FrameController implements AppearanceObserverDelegate, Fetc
|
|
|
46
44
|
loadingStyleChanged(): void;
|
|
47
45
|
private loadSourceURL;
|
|
48
46
|
loadResponse(fetchResponse: FetchResponse): Promise<void>;
|
|
49
|
-
elementAppearedInViewport(
|
|
47
|
+
elementAppearedInViewport(element: FrameElement): void;
|
|
50
48
|
willSubmitFormLinkToLocation(link: Element): boolean;
|
|
51
49
|
submittedFormLinkToLocation(link: Element, _location: URL, form: HTMLFormElement): void;
|
|
52
50
|
shouldInterceptLinkClick(element: Element, _location: string, _event: MouseEvent): boolean;
|
|
53
51
|
linkClickIntercepted(element: Element, location: string): void;
|
|
54
52
|
willSubmitForm(element: HTMLFormElement, submitter?: HTMLElement): boolean;
|
|
55
53
|
formSubmitted(element: HTMLFormElement, submitter?: HTMLElement): void;
|
|
56
|
-
|
|
54
|
+
prepareRequest(request: FetchRequest): void;
|
|
57
55
|
requestStarted(_request: FetchRequest): void;
|
|
58
56
|
requestPreventedHandlingResponse(_request: FetchRequest, _response: FetchResponse): void;
|
|
59
57
|
requestSucceededWithResponse(request: FetchRequest, response: FetchResponse): Promise<void>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BardoDelegate } from "./bardo";
|
|
2
2
|
import { Snapshot } from "./snapshot";
|
|
3
3
|
import { ReloadReason } from "./native/browser_adapter";
|
|
4
|
-
export declare type Render<E> = (
|
|
4
|
+
export declare type Render<E> = (currentElement: E, newElement: E) => void;
|
|
5
5
|
export declare abstract class Renderer<E extends Element, S extends Snapshot<E> = Snapshot<E>> implements BardoDelegate {
|
|
6
6
|
readonly currentSnapshot: S;
|
|
7
7
|
readonly newSnapshot: S;
|
|
@@ -17,7 +17,7 @@ export declare abstract class Renderer<E extends Element, S extends Snapshot<E>
|
|
|
17
17
|
prepareToRender(): void;
|
|
18
18
|
abstract render(): Promise<void>;
|
|
19
19
|
finishRendering(): void;
|
|
20
|
-
preservingPermanentElements(callback: () => void): void
|
|
20
|
+
preservingPermanentElements(callback: () => void): Promise<void>;
|
|
21
21
|
focusFirstAutofocusableElement(): void;
|
|
22
22
|
enteringBardo(currentPermanentElement: Element): void;
|
|
23
23
|
leavingBardo(currentPermanentElement: Element): void;
|
|
@@ -14,7 +14,7 @@ export declare type TurboFetchRequestErrorEvent = CustomEvent<{
|
|
|
14
14
|
}>;
|
|
15
15
|
export interface FetchRequestDelegate {
|
|
16
16
|
referrer?: URL;
|
|
17
|
-
|
|
17
|
+
prepareRequest(request: FetchRequest): void;
|
|
18
18
|
requestStarted(request: FetchRequest): void;
|
|
19
19
|
requestPreventedHandlingResponse(request: FetchRequest, response: FetchResponse): void;
|
|
20
20
|
requestSucceededWithResponse(request: FetchRequest, response: FetchResponse): void;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
export interface AppearanceObserverDelegate {
|
|
2
|
-
elementAppearedInViewport(element:
|
|
1
|
+
export interface AppearanceObserverDelegate<T extends Element> {
|
|
2
|
+
elementAppearedInViewport(element: T): void;
|
|
3
3
|
}
|
|
4
|
-
export declare class AppearanceObserver {
|
|
5
|
-
readonly delegate: AppearanceObserverDelegate
|
|
6
|
-
readonly element:
|
|
4
|
+
export declare class AppearanceObserver<T extends Element> {
|
|
5
|
+
readonly delegate: AppearanceObserverDelegate<T>;
|
|
6
|
+
readonly element: T;
|
|
7
7
|
readonly intersectionObserver: IntersectionObserver;
|
|
8
8
|
started: boolean;
|
|
9
|
-
constructor(delegate: AppearanceObserverDelegate
|
|
9
|
+
constructor(delegate: AppearanceObserverDelegate<T>, element: T);
|
|
10
10
|
start(): void;
|
|
11
11
|
stop(): void;
|
|
12
12
|
intersect: IntersectionObserverCallback;
|
|
@@ -12,6 +12,6 @@ export declare class LinkClickObserver {
|
|
|
12
12
|
clickCaptured: () => void;
|
|
13
13
|
clickBubbled: (event: Event) => void;
|
|
14
14
|
clickEventIsSignificant(event: MouseEvent): boolean;
|
|
15
|
-
findLinkFromClickTarget(target: EventTarget | null): HTMLAnchorElement |
|
|
15
|
+
findLinkFromClickTarget(target: EventTarget | null): HTMLAnchorElement | undefined;
|
|
16
16
|
getLocationForLink(link: Element): URL;
|
|
17
17
|
}
|
|
@@ -6,6 +6,8 @@ declare type EventLog = [EventType, EventDetail, Target];
|
|
|
6
6
|
declare type MutationAttributeName = string;
|
|
7
7
|
declare type MutationAttributeValue = string | null;
|
|
8
8
|
declare type MutationLog = [MutationAttributeName, Target, MutationAttributeValue];
|
|
9
|
+
declare type BodyHTML = string;
|
|
10
|
+
declare type BodyMutationLog = [BodyHTML];
|
|
9
11
|
export declare function attributeForSelector(page: Page, selector: string, attributeName: string): Promise<string | null>;
|
|
10
12
|
declare type CancellableEvent = "turbo:click" | "turbo:before-visit";
|
|
11
13
|
export declare function cancelNextEvent(page: Page, eventName: CancellableEvent): Promise<void>;
|
|
@@ -23,13 +25,17 @@ export declare function nextBody(_page: Page, timeout?: number): Promise<void>;
|
|
|
23
25
|
export declare function nextEventNamed(page: Page, eventName: string): Promise<any>;
|
|
24
26
|
export declare function nextEventOnTarget(page: Page, elementId: string, eventName: string): Promise<any>;
|
|
25
27
|
export declare function listenForEventOnTarget(page: Page, elementId: string, eventName: string): Promise<void>;
|
|
28
|
+
export declare function nextBodyMutation(page: Page): Promise<string | null>;
|
|
29
|
+
export declare function noNextBodyMutation(page: Page): Promise<boolean>;
|
|
26
30
|
export declare function nextAttributeMutationNamed(page: Page, elementId: string, attributeName: string): Promise<string | null>;
|
|
27
31
|
export declare function noNextAttributeMutationNamed(page: Page, elementId: string, attributeName: string): Promise<boolean>;
|
|
28
32
|
export declare function noNextEventNamed(page: Page, eventName: string): Promise<boolean>;
|
|
29
33
|
export declare function noNextEventOnTarget(page: Page, elementId: string, eventName: string): Promise<boolean>;
|
|
30
34
|
export declare function outerHTMLForSelector(page: Page, selector: string): Promise<string>;
|
|
31
35
|
export declare function pathname(url: string): string;
|
|
36
|
+
export declare function pathnameForIFrame(page: Page, name: string): Promise<string>;
|
|
32
37
|
export declare function propertyForSelector(page: Page, selector: string, propertyName: string): Promise<any>;
|
|
38
|
+
export declare function readBodyMutationLogs(page: Page, length?: number): Promise<BodyMutationLog[]>;
|
|
33
39
|
export declare function readEventLogs(page: Page, length?: number): Promise<EventLog[]>;
|
|
34
40
|
export declare function readMutationLogs(page: Page, length?: number): Promise<MutationLog[]>;
|
|
35
41
|
export declare function search(url: string): string;
|
|
@@ -47,6 +53,7 @@ export declare function strictElementEquals(left: Locator, right: Locator): Prom
|
|
|
47
53
|
export declare function textContent(page: Page, html: string): Promise<string | null>;
|
|
48
54
|
export declare function visitAction(page: Page): Promise<string>;
|
|
49
55
|
export declare function waitForPathname(page: Page, pathname: string): Promise<void>;
|
|
56
|
+
export declare function waitUntilText(page: Page, text: string, state?: "visible" | "attached"): Promise<import("playwright-core").ElementHandle<HTMLElement | SVGElement>>;
|
|
50
57
|
export declare function waitUntilSelector(page: Page, selector: string, state?: "visible" | "attached"): Promise<import("playwright-core").ElementHandle<HTMLElement | SVGElement>>;
|
|
51
58
|
export declare function waitUntilNoSelector(page: Page, selector: string, state?: "hidden" | "detached"): Promise<import("playwright-core").ElementHandle<HTMLElement | SVGElement> | null>;
|
|
52
59
|
export declare function willChangeBody(page: Page, callback: () => Promise<void>): Promise<boolean>;
|
|
File without changes
|
package/dist/types/util.d.ts
CHANGED
|
@@ -19,7 +19,9 @@ export declare function markAsBusy(...elements: Element[]): void;
|
|
|
19
19
|
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
|
+
export declare function isAction(action: any): action is Action;
|
|
22
23
|
export declare function getVisitAction(...elements: (Element | undefined)[]): Action | null;
|
|
23
24
|
export declare function getMetaElement(name: string): HTMLMetaElement | null;
|
|
24
25
|
export declare function getMetaContent(name: string): string | null;
|
|
25
26
|
export declare function setMetaContent(name: string, content: string): HTMLMetaElement;
|
|
27
|
+
export declare function findClosestRecursively<E extends Element>(element: Element | null, selector: string): E | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hotwired/turbo",
|
|
3
|
-
"version": "7.2.
|
|
3
|
+
"version": "7.2.5",
|
|
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",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"access": "public"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@playwright/test": "^1.
|
|
38
|
+
"@playwright/test": "^1.28.0",
|
|
39
39
|
"@rollup/plugin-node-resolve": "13.1.3",
|
|
40
40
|
"@rollup/plugin-typescript": "^8.5.0",
|
|
41
41
|
"@types/multer": "^1.4.5",
|