@hotwired/turbo 8.0.0-beta.3 → 8.0.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/dist/turbo.es2017-esm.js +151 -127
- package/dist/turbo.es2017-umd.js +151 -127
- package/package.json +2 -2
package/dist/turbo.es2017-esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
Turbo 8.0.0-
|
|
2
|
+
Turbo 8.0.0-rc.1
|
|
3
3
|
Copyright © 2024 37signals LLC
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
@@ -1469,7 +1469,12 @@ class View {
|
|
|
1469
1469
|
// Rendering
|
|
1470
1470
|
|
|
1471
1471
|
async render(renderer) {
|
|
1472
|
-
const { isPreview, shouldRender, newSnapshot: snapshot } = renderer;
|
|
1472
|
+
const { isPreview, shouldRender, willRender, newSnapshot: snapshot } = renderer;
|
|
1473
|
+
|
|
1474
|
+
// A workaround to ignore tracked element mismatch reloads when performing
|
|
1475
|
+
// a promoted Visit from a frame navigation
|
|
1476
|
+
const shouldInvalidate = willRender;
|
|
1477
|
+
|
|
1473
1478
|
if (shouldRender) {
|
|
1474
1479
|
try {
|
|
1475
1480
|
this.renderPromise = new Promise((resolve) => (this.#resolveRenderPromise = resolve));
|
|
@@ -1477,7 +1482,7 @@ class View {
|
|
|
1477
1482
|
await this.prepareToRenderSnapshot(renderer);
|
|
1478
1483
|
|
|
1479
1484
|
const renderInterception = new Promise((resolve) => (this.#resolveInterceptionPromise = resolve));
|
|
1480
|
-
const options = { resume: this.#resolveInterceptionPromise, render: this.renderer.renderElement };
|
|
1485
|
+
const options = { resume: this.#resolveInterceptionPromise, render: this.renderer.renderElement, renderMethod: this.renderer.renderMethod };
|
|
1481
1486
|
const immediateRender = this.delegate.allowsImmediateRender(snapshot, options);
|
|
1482
1487
|
if (!immediateRender) await renderInterception;
|
|
1483
1488
|
|
|
@@ -1490,7 +1495,7 @@ class View {
|
|
|
1490
1495
|
this.#resolveRenderPromise(undefined);
|
|
1491
1496
|
delete this.renderPromise;
|
|
1492
1497
|
}
|
|
1493
|
-
} else {
|
|
1498
|
+
} else if (shouldInvalidate) {
|
|
1494
1499
|
this.invalidate(renderer.reloadReason);
|
|
1495
1500
|
}
|
|
1496
1501
|
}
|
|
@@ -1937,8 +1942,6 @@ function readScrollBehavior(value, defaultValue) {
|
|
|
1937
1942
|
}
|
|
1938
1943
|
}
|
|
1939
1944
|
|
|
1940
|
-
const ProgressBarID = "turbo-progress-bar";
|
|
1941
|
-
|
|
1942
1945
|
class ProgressBar {
|
|
1943
1946
|
static animationDuration = 300 /*ms*/
|
|
1944
1947
|
|
|
@@ -2043,8 +2046,6 @@ class ProgressBar {
|
|
|
2043
2046
|
|
|
2044
2047
|
createStylesheetElement() {
|
|
2045
2048
|
const element = document.createElement("style");
|
|
2046
|
-
element.id = ProgressBarID;
|
|
2047
|
-
element.setAttribute("data-turbo-permanent", "");
|
|
2048
2049
|
element.type = "text/css";
|
|
2049
2050
|
element.textContent = ProgressBar.defaultCSS;
|
|
2050
2051
|
if (this.cspNonce) {
|
|
@@ -2364,6 +2365,7 @@ class Visit {
|
|
|
2364
2365
|
this.snapshotHTML = snapshotHTML;
|
|
2365
2366
|
this.response = response;
|
|
2366
2367
|
this.isSamePage = this.delegate.locationWithActionIsSamePage(this.location, this.action);
|
|
2368
|
+
this.isPageRefresh = this.view.isPageRefresh(this);
|
|
2367
2369
|
this.visitCachedSnapshot = visitCachedSnapshot;
|
|
2368
2370
|
this.willRender = willRender;
|
|
2369
2371
|
this.updateHistory = updateHistory;
|
|
@@ -2529,7 +2531,7 @@ class Visit {
|
|
|
2529
2531
|
const isPreview = this.shouldIssueRequest();
|
|
2530
2532
|
this.render(async () => {
|
|
2531
2533
|
this.cacheSnapshot();
|
|
2532
|
-
if (this.isSamePage) {
|
|
2534
|
+
if (this.isSamePage || this.isPageRefresh) {
|
|
2533
2535
|
this.adapter.visitRendered(this);
|
|
2534
2536
|
} else {
|
|
2535
2537
|
if (this.view.renderPromise) await this.view.renderPromise;
|
|
@@ -3171,20 +3173,17 @@ class LinkPrefetchObserver {
|
|
|
3171
3173
|
prepareRequest(request) {
|
|
3172
3174
|
const link = request.target;
|
|
3173
3175
|
|
|
3174
|
-
request.headers["Sec-Purpose"] = "prefetch";
|
|
3176
|
+
request.headers["X-Sec-Purpose"] = "prefetch";
|
|
3175
3177
|
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
} else if (link.dataset.turboFrame !== "_top") {
|
|
3179
|
-
const turboFrame = link.closest("turbo-frame");
|
|
3178
|
+
const turboFrame = link.closest("turbo-frame");
|
|
3179
|
+
const turboFrameTarget = link.getAttribute("data-turbo-frame") || turboFrame?.getAttribute("target") || turboFrame?.id;
|
|
3180
3180
|
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
}
|
|
3181
|
+
if (turboFrameTarget && turboFrameTarget !== "_top") {
|
|
3182
|
+
request.headers["Turbo-Frame"] = turboFrameTarget;
|
|
3184
3183
|
}
|
|
3185
3184
|
|
|
3186
3185
|
if (link.hasAttribute("data-turbo-stream")) {
|
|
3187
|
-
request.acceptResponseType(
|
|
3186
|
+
request.acceptResponseType(StreamMessage.contentType);
|
|
3188
3187
|
}
|
|
3189
3188
|
}
|
|
3190
3189
|
|
|
@@ -3209,7 +3208,7 @@ class LinkPrefetchObserver {
|
|
|
3209
3208
|
#isPrefetchable(link) {
|
|
3210
3209
|
const href = link.getAttribute("href");
|
|
3211
3210
|
|
|
3212
|
-
if (!href || href === "#" || link.
|
|
3211
|
+
if (!href || href === "#" || link.getAttribute("data-turbo") === "false" || link.getAttribute("data-turbo-prefetch") === "false") {
|
|
3213
3212
|
return false
|
|
3214
3213
|
}
|
|
3215
3214
|
|
|
@@ -3225,7 +3224,8 @@ class LinkPrefetchObserver {
|
|
|
3225
3224
|
return false
|
|
3226
3225
|
}
|
|
3227
3226
|
|
|
3228
|
-
|
|
3227
|
+
const turboMethod = link.getAttribute("data-turbo-method");
|
|
3228
|
+
if (turboMethod && turboMethod !== "get") {
|
|
3229
3229
|
return false
|
|
3230
3230
|
}
|
|
3231
3231
|
|
|
@@ -3233,13 +3233,9 @@ class LinkPrefetchObserver {
|
|
|
3233
3233
|
return false
|
|
3234
3234
|
}
|
|
3235
3235
|
|
|
3236
|
-
if (link.pathname + link.search === document.location.pathname + document.location.search) {
|
|
3237
|
-
return false
|
|
3238
|
-
}
|
|
3239
|
-
|
|
3240
3236
|
const turboPrefetchParent = findClosestRecursively(link, "[data-turbo-prefetch]");
|
|
3241
3237
|
|
|
3242
|
-
if (turboPrefetchParent && turboPrefetchParent.
|
|
3238
|
+
if (turboPrefetchParent && turboPrefetchParent.getAttribute("data-turbo-prefetch") === "false") {
|
|
3243
3239
|
return false
|
|
3244
3240
|
}
|
|
3245
3241
|
|
|
@@ -4554,92 +4550,6 @@ var Idiomorph = (function () {
|
|
|
4554
4550
|
}
|
|
4555
4551
|
})();
|
|
4556
4552
|
|
|
4557
|
-
class MorphRenderer extends Renderer {
|
|
4558
|
-
async render() {
|
|
4559
|
-
if (this.willRender) await this.#morphBody();
|
|
4560
|
-
}
|
|
4561
|
-
|
|
4562
|
-
get renderMethod() {
|
|
4563
|
-
return "morph"
|
|
4564
|
-
}
|
|
4565
|
-
|
|
4566
|
-
// Private
|
|
4567
|
-
|
|
4568
|
-
async #morphBody() {
|
|
4569
|
-
this.#morphElements(this.currentElement, this.newElement);
|
|
4570
|
-
this.#reloadRemoteFrames();
|
|
4571
|
-
|
|
4572
|
-
dispatch("turbo:morph", {
|
|
4573
|
-
detail: {
|
|
4574
|
-
currentElement: this.currentElement,
|
|
4575
|
-
newElement: this.newElement
|
|
4576
|
-
}
|
|
4577
|
-
});
|
|
4578
|
-
}
|
|
4579
|
-
|
|
4580
|
-
#morphElements(currentElement, newElement, morphStyle = "outerHTML") {
|
|
4581
|
-
this.isMorphingTurboFrame = this.#isFrameReloadedWithMorph(currentElement);
|
|
4582
|
-
|
|
4583
|
-
Idiomorph.morph(currentElement, newElement, {
|
|
4584
|
-
morphStyle: morphStyle,
|
|
4585
|
-
callbacks: {
|
|
4586
|
-
beforeNodeAdded: this.#shouldAddElement,
|
|
4587
|
-
beforeNodeMorphed: this.#shouldMorphElement,
|
|
4588
|
-
beforeNodeRemoved: this.#shouldRemoveElement
|
|
4589
|
-
}
|
|
4590
|
-
});
|
|
4591
|
-
}
|
|
4592
|
-
|
|
4593
|
-
#shouldAddElement = (node) => {
|
|
4594
|
-
return !(node.id && node.hasAttribute("data-turbo-permanent") && document.getElementById(node.id))
|
|
4595
|
-
}
|
|
4596
|
-
|
|
4597
|
-
#shouldMorphElement = (oldNode, newNode) => {
|
|
4598
|
-
if (oldNode instanceof HTMLElement) {
|
|
4599
|
-
return !oldNode.hasAttribute("data-turbo-permanent") && (this.isMorphingTurboFrame || !this.#isFrameReloadedWithMorph(oldNode))
|
|
4600
|
-
} else {
|
|
4601
|
-
return true
|
|
4602
|
-
}
|
|
4603
|
-
}
|
|
4604
|
-
|
|
4605
|
-
#shouldRemoveElement = (node) => {
|
|
4606
|
-
return this.#shouldMorphElement(node)
|
|
4607
|
-
}
|
|
4608
|
-
|
|
4609
|
-
#reloadRemoteFrames() {
|
|
4610
|
-
this.#remoteFrames().forEach((frame) => {
|
|
4611
|
-
if (this.#isFrameReloadedWithMorph(frame)) {
|
|
4612
|
-
this.#renderFrameWithMorph(frame);
|
|
4613
|
-
frame.reload();
|
|
4614
|
-
}
|
|
4615
|
-
});
|
|
4616
|
-
}
|
|
4617
|
-
|
|
4618
|
-
#renderFrameWithMorph(frame) {
|
|
4619
|
-
frame.addEventListener("turbo:before-frame-render", (event) => {
|
|
4620
|
-
event.detail.render = this.#morphFrameUpdate;
|
|
4621
|
-
}, { once: true });
|
|
4622
|
-
}
|
|
4623
|
-
|
|
4624
|
-
#morphFrameUpdate = (currentElement, newElement) => {
|
|
4625
|
-
dispatch("turbo:before-frame-morph", {
|
|
4626
|
-
target: currentElement,
|
|
4627
|
-
detail: { currentElement, newElement }
|
|
4628
|
-
});
|
|
4629
|
-
this.#morphElements(currentElement, newElement.children, "innerHTML");
|
|
4630
|
-
}
|
|
4631
|
-
|
|
4632
|
-
#isFrameReloadedWithMorph(element) {
|
|
4633
|
-
return element.src && element.refresh === "morph"
|
|
4634
|
-
}
|
|
4635
|
-
|
|
4636
|
-
#remoteFrames() {
|
|
4637
|
-
return Array.from(document.querySelectorAll('turbo-frame[src]')).filter(frame => {
|
|
4638
|
-
return !frame.closest('[data-turbo-permanent]')
|
|
4639
|
-
})
|
|
4640
|
-
}
|
|
4641
|
-
}
|
|
4642
|
-
|
|
4643
4553
|
class PageRenderer extends Renderer {
|
|
4644
4554
|
static renderElement(currentElement, newElement) {
|
|
4645
4555
|
if (document.body && newElement instanceof HTMLBodyElement) {
|
|
@@ -4717,7 +4627,7 @@ class PageRenderer extends Renderer {
|
|
|
4717
4627
|
await newStylesheetElements;
|
|
4718
4628
|
|
|
4719
4629
|
if (this.willRender) {
|
|
4720
|
-
this.
|
|
4630
|
+
this.removeUnusedDynamicStylesheetElements();
|
|
4721
4631
|
}
|
|
4722
4632
|
}
|
|
4723
4633
|
|
|
@@ -4750,8 +4660,8 @@ class PageRenderer extends Renderer {
|
|
|
4750
4660
|
}
|
|
4751
4661
|
}
|
|
4752
4662
|
|
|
4753
|
-
|
|
4754
|
-
for (const element of this.
|
|
4663
|
+
removeUnusedDynamicStylesheetElements() {
|
|
4664
|
+
for (const element of this.unusedDynamicStylesheetElements) {
|
|
4755
4665
|
document.head.removeChild(element);
|
|
4756
4666
|
}
|
|
4757
4667
|
}
|
|
@@ -4821,13 +4731,9 @@ class PageRenderer extends Renderer {
|
|
|
4821
4731
|
await this.renderElement(this.currentElement, this.newElement);
|
|
4822
4732
|
}
|
|
4823
4733
|
|
|
4824
|
-
get
|
|
4734
|
+
get unusedDynamicStylesheetElements() {
|
|
4825
4735
|
return this.oldHeadStylesheetElements.filter((element) => {
|
|
4826
|
-
return
|
|
4827
|
-
// Trix dynamically adds styles to the head that we want to keep around which have a
|
|
4828
|
-
// `data-tag-name` attribute. Long term we should moves those styles to Trix's CSS file
|
|
4829
|
-
// but for now we'll just skip removing them
|
|
4830
|
-
element.hasAttribute("data-tag-name"))
|
|
4736
|
+
return element.getAttribute("data-turbo-track") === "dynamic"
|
|
4831
4737
|
})
|
|
4832
4738
|
}
|
|
4833
4739
|
|
|
@@ -4856,6 +4762,122 @@ class PageRenderer extends Renderer {
|
|
|
4856
4762
|
}
|
|
4857
4763
|
}
|
|
4858
4764
|
|
|
4765
|
+
class MorphRenderer extends PageRenderer {
|
|
4766
|
+
async render() {
|
|
4767
|
+
if (this.willRender) await this.#morphBody();
|
|
4768
|
+
}
|
|
4769
|
+
|
|
4770
|
+
get renderMethod() {
|
|
4771
|
+
return "morph"
|
|
4772
|
+
}
|
|
4773
|
+
|
|
4774
|
+
// Private
|
|
4775
|
+
|
|
4776
|
+
async #morphBody() {
|
|
4777
|
+
this.#morphElements(this.currentElement, this.newElement);
|
|
4778
|
+
this.#reloadRemoteFrames();
|
|
4779
|
+
|
|
4780
|
+
dispatch("turbo:morph", {
|
|
4781
|
+
detail: {
|
|
4782
|
+
currentElement: this.currentElement,
|
|
4783
|
+
newElement: this.newElement
|
|
4784
|
+
}
|
|
4785
|
+
});
|
|
4786
|
+
}
|
|
4787
|
+
|
|
4788
|
+
#morphElements(currentElement, newElement, morphStyle = "outerHTML") {
|
|
4789
|
+
this.isMorphingTurboFrame = this.#isFrameReloadedWithMorph(currentElement);
|
|
4790
|
+
|
|
4791
|
+
Idiomorph.morph(currentElement, newElement, {
|
|
4792
|
+
ignoreActiveValue: true,
|
|
4793
|
+
morphStyle: morphStyle,
|
|
4794
|
+
callbacks: {
|
|
4795
|
+
beforeNodeAdded: this.#shouldAddElement,
|
|
4796
|
+
beforeNodeMorphed: this.#shouldMorphElement,
|
|
4797
|
+
beforeAttributeUpdated: this.#shouldUpdateAttribute,
|
|
4798
|
+
beforeNodeRemoved: this.#shouldRemoveElement,
|
|
4799
|
+
afterNodeMorphed: this.#didMorphElement
|
|
4800
|
+
}
|
|
4801
|
+
});
|
|
4802
|
+
}
|
|
4803
|
+
|
|
4804
|
+
#shouldAddElement = (node) => {
|
|
4805
|
+
return !(node.id && node.hasAttribute("data-turbo-permanent") && document.getElementById(node.id))
|
|
4806
|
+
}
|
|
4807
|
+
|
|
4808
|
+
#shouldMorphElement = (oldNode, newNode) => {
|
|
4809
|
+
if (oldNode instanceof HTMLElement) {
|
|
4810
|
+
if (!oldNode.hasAttribute("data-turbo-permanent") && (this.isMorphingTurboFrame || !this.#isFrameReloadedWithMorph(oldNode))) {
|
|
4811
|
+
const event = dispatch("turbo:before-morph-element", {
|
|
4812
|
+
cancelable: true,
|
|
4813
|
+
target: oldNode,
|
|
4814
|
+
detail: {
|
|
4815
|
+
newElement: newNode
|
|
4816
|
+
}
|
|
4817
|
+
});
|
|
4818
|
+
|
|
4819
|
+
return !event.defaultPrevented
|
|
4820
|
+
} else {
|
|
4821
|
+
return false
|
|
4822
|
+
}
|
|
4823
|
+
}
|
|
4824
|
+
}
|
|
4825
|
+
|
|
4826
|
+
#shouldUpdateAttribute = (attributeName, target, mutationType) => {
|
|
4827
|
+
const event = dispatch("turbo:before-morph-attribute", { cancelable: true, target, detail: { attributeName, mutationType } });
|
|
4828
|
+
|
|
4829
|
+
return !event.defaultPrevented
|
|
4830
|
+
}
|
|
4831
|
+
|
|
4832
|
+
#didMorphElement = (oldNode, newNode) => {
|
|
4833
|
+
if (newNode instanceof HTMLElement) {
|
|
4834
|
+
dispatch("turbo:morph-element", {
|
|
4835
|
+
target: oldNode,
|
|
4836
|
+
detail: {
|
|
4837
|
+
newElement: newNode
|
|
4838
|
+
}
|
|
4839
|
+
});
|
|
4840
|
+
}
|
|
4841
|
+
}
|
|
4842
|
+
|
|
4843
|
+
#shouldRemoveElement = (node) => {
|
|
4844
|
+
return this.#shouldMorphElement(node)
|
|
4845
|
+
}
|
|
4846
|
+
|
|
4847
|
+
#reloadRemoteFrames() {
|
|
4848
|
+
this.#remoteFrames().forEach((frame) => {
|
|
4849
|
+
if (this.#isFrameReloadedWithMorph(frame)) {
|
|
4850
|
+
this.#renderFrameWithMorph(frame);
|
|
4851
|
+
frame.reload();
|
|
4852
|
+
}
|
|
4853
|
+
});
|
|
4854
|
+
}
|
|
4855
|
+
|
|
4856
|
+
#renderFrameWithMorph(frame) {
|
|
4857
|
+
frame.addEventListener("turbo:before-frame-render", (event) => {
|
|
4858
|
+
event.detail.render = this.#morphFrameUpdate;
|
|
4859
|
+
}, { once: true });
|
|
4860
|
+
}
|
|
4861
|
+
|
|
4862
|
+
#morphFrameUpdate = (currentElement, newElement) => {
|
|
4863
|
+
dispatch("turbo:before-frame-morph", {
|
|
4864
|
+
target: currentElement,
|
|
4865
|
+
detail: { currentElement, newElement }
|
|
4866
|
+
});
|
|
4867
|
+
this.#morphElements(currentElement, newElement.children, "innerHTML");
|
|
4868
|
+
}
|
|
4869
|
+
|
|
4870
|
+
#isFrameReloadedWithMorph(element) {
|
|
4871
|
+
return element.src && element.refresh === "morph"
|
|
4872
|
+
}
|
|
4873
|
+
|
|
4874
|
+
#remoteFrames() {
|
|
4875
|
+
return Array.from(document.querySelectorAll('turbo-frame[src]')).filter(frame => {
|
|
4876
|
+
return !frame.closest('[data-turbo-permanent]')
|
|
4877
|
+
})
|
|
4878
|
+
}
|
|
4879
|
+
}
|
|
4880
|
+
|
|
4859
4881
|
class SnapshotCache {
|
|
4860
4882
|
keys = []
|
|
4861
4883
|
snapshots = {}
|
|
@@ -5015,7 +5037,7 @@ class Preloader {
|
|
|
5015
5037
|
// Fetch request delegate
|
|
5016
5038
|
|
|
5017
5039
|
prepareRequest(fetchRequest) {
|
|
5018
|
-
fetchRequest.headers["Sec-Purpose"] = "prefetch";
|
|
5040
|
+
fetchRequest.headers["X-Sec-Purpose"] = "prefetch";
|
|
5019
5041
|
}
|
|
5020
5042
|
|
|
5021
5043
|
async requestSucceededWithResponse(fetchRequest, fetchResponse) {
|
|
@@ -5149,8 +5171,10 @@ class Session {
|
|
|
5149
5171
|
const frameElement = options.frame ? document.getElementById(options.frame) : null;
|
|
5150
5172
|
|
|
5151
5173
|
if (frameElement instanceof FrameElement) {
|
|
5174
|
+
const action = options.action || getVisitAction(frameElement);
|
|
5175
|
+
|
|
5176
|
+
frameElement.delegate.proposeVisitIfNavigatedWithAction(frameElement, action);
|
|
5152
5177
|
frameElement.src = location.toString();
|
|
5153
|
-
frameElement.loaded;
|
|
5154
5178
|
} else {
|
|
5155
5179
|
this.navigator.proposeVisit(expandURL(location), options);
|
|
5156
5180
|
}
|
|
@@ -5791,7 +5815,7 @@ class FrameController {
|
|
|
5791
5815
|
// Appearance observer delegate
|
|
5792
5816
|
|
|
5793
5817
|
elementAppearedInViewport(element) {
|
|
5794
|
-
this.proposeVisitIfNavigatedWithAction(element, element);
|
|
5818
|
+
this.proposeVisitIfNavigatedWithAction(element, getVisitAction(element));
|
|
5795
5819
|
this.#loadSourceURL();
|
|
5796
5820
|
}
|
|
5797
5821
|
|
|
@@ -5879,7 +5903,7 @@ class FrameController {
|
|
|
5879
5903
|
formSubmissionSucceededWithResponse(formSubmission, response) {
|
|
5880
5904
|
const frame = this.#findFrameElement(formSubmission.formElement, formSubmission.submitter);
|
|
5881
5905
|
|
|
5882
|
-
frame.delegate.proposeVisitIfNavigatedWithAction(frame, formSubmission.
|
|
5906
|
+
frame.delegate.proposeVisitIfNavigatedWithAction(frame, getVisitAction(formSubmission.submitter, formSubmission.formElement, frame));
|
|
5883
5907
|
frame.delegate.loadResponse(response);
|
|
5884
5908
|
|
|
5885
5909
|
if (!formSubmission.isSafe) {
|
|
@@ -5984,15 +6008,15 @@ class FrameController {
|
|
|
5984
6008
|
#navigateFrame(element, url, submitter) {
|
|
5985
6009
|
const frame = this.#findFrameElement(element, submitter);
|
|
5986
6010
|
|
|
5987
|
-
frame.delegate.proposeVisitIfNavigatedWithAction(frame, element,
|
|
6011
|
+
frame.delegate.proposeVisitIfNavigatedWithAction(frame, getVisitAction(submitter, element, frame));
|
|
5988
6012
|
|
|
5989
6013
|
this.#withCurrentNavigationElement(element, () => {
|
|
5990
6014
|
frame.src = url;
|
|
5991
6015
|
});
|
|
5992
6016
|
}
|
|
5993
6017
|
|
|
5994
|
-
proposeVisitIfNavigatedWithAction(frame,
|
|
5995
|
-
this.action =
|
|
6018
|
+
proposeVisitIfNavigatedWithAction(frame, action = null) {
|
|
6019
|
+
this.action = action;
|
|
5996
6020
|
|
|
5997
6021
|
if (this.action) {
|
|
5998
6022
|
const pageSnapshot = PageSnapshot.fromElement(frame).clone();
|
package/dist/turbo.es2017-umd.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
Turbo 8.0.0-
|
|
2
|
+
Turbo 8.0.0-rc.1
|
|
3
3
|
Copyright © 2024 37signals LLC
|
|
4
4
|
*/
|
|
5
5
|
(function (global, factory) {
|
|
@@ -1475,7 +1475,12 @@ Copyright © 2024 37signals LLC
|
|
|
1475
1475
|
// Rendering
|
|
1476
1476
|
|
|
1477
1477
|
async render(renderer) {
|
|
1478
|
-
const { isPreview, shouldRender, newSnapshot: snapshot } = renderer;
|
|
1478
|
+
const { isPreview, shouldRender, willRender, newSnapshot: snapshot } = renderer;
|
|
1479
|
+
|
|
1480
|
+
// A workaround to ignore tracked element mismatch reloads when performing
|
|
1481
|
+
// a promoted Visit from a frame navigation
|
|
1482
|
+
const shouldInvalidate = willRender;
|
|
1483
|
+
|
|
1479
1484
|
if (shouldRender) {
|
|
1480
1485
|
try {
|
|
1481
1486
|
this.renderPromise = new Promise((resolve) => (this.#resolveRenderPromise = resolve));
|
|
@@ -1483,7 +1488,7 @@ Copyright © 2024 37signals LLC
|
|
|
1483
1488
|
await this.prepareToRenderSnapshot(renderer);
|
|
1484
1489
|
|
|
1485
1490
|
const renderInterception = new Promise((resolve) => (this.#resolveInterceptionPromise = resolve));
|
|
1486
|
-
const options = { resume: this.#resolveInterceptionPromise, render: this.renderer.renderElement };
|
|
1491
|
+
const options = { resume: this.#resolveInterceptionPromise, render: this.renderer.renderElement, renderMethod: this.renderer.renderMethod };
|
|
1487
1492
|
const immediateRender = this.delegate.allowsImmediateRender(snapshot, options);
|
|
1488
1493
|
if (!immediateRender) await renderInterception;
|
|
1489
1494
|
|
|
@@ -1496,7 +1501,7 @@ Copyright © 2024 37signals LLC
|
|
|
1496
1501
|
this.#resolveRenderPromise(undefined);
|
|
1497
1502
|
delete this.renderPromise;
|
|
1498
1503
|
}
|
|
1499
|
-
} else {
|
|
1504
|
+
} else if (shouldInvalidate) {
|
|
1500
1505
|
this.invalidate(renderer.reloadReason);
|
|
1501
1506
|
}
|
|
1502
1507
|
}
|
|
@@ -1943,8 +1948,6 @@ Copyright © 2024 37signals LLC
|
|
|
1943
1948
|
}
|
|
1944
1949
|
}
|
|
1945
1950
|
|
|
1946
|
-
const ProgressBarID = "turbo-progress-bar";
|
|
1947
|
-
|
|
1948
1951
|
class ProgressBar {
|
|
1949
1952
|
static animationDuration = 300 /*ms*/
|
|
1950
1953
|
|
|
@@ -2049,8 +2052,6 @@ Copyright © 2024 37signals LLC
|
|
|
2049
2052
|
|
|
2050
2053
|
createStylesheetElement() {
|
|
2051
2054
|
const element = document.createElement("style");
|
|
2052
|
-
element.id = ProgressBarID;
|
|
2053
|
-
element.setAttribute("data-turbo-permanent", "");
|
|
2054
2055
|
element.type = "text/css";
|
|
2055
2056
|
element.textContent = ProgressBar.defaultCSS;
|
|
2056
2057
|
if (this.cspNonce) {
|
|
@@ -2370,6 +2371,7 @@ Copyright © 2024 37signals LLC
|
|
|
2370
2371
|
this.snapshotHTML = snapshotHTML;
|
|
2371
2372
|
this.response = response;
|
|
2372
2373
|
this.isSamePage = this.delegate.locationWithActionIsSamePage(this.location, this.action);
|
|
2374
|
+
this.isPageRefresh = this.view.isPageRefresh(this);
|
|
2373
2375
|
this.visitCachedSnapshot = visitCachedSnapshot;
|
|
2374
2376
|
this.willRender = willRender;
|
|
2375
2377
|
this.updateHistory = updateHistory;
|
|
@@ -2535,7 +2537,7 @@ Copyright © 2024 37signals LLC
|
|
|
2535
2537
|
const isPreview = this.shouldIssueRequest();
|
|
2536
2538
|
this.render(async () => {
|
|
2537
2539
|
this.cacheSnapshot();
|
|
2538
|
-
if (this.isSamePage) {
|
|
2540
|
+
if (this.isSamePage || this.isPageRefresh) {
|
|
2539
2541
|
this.adapter.visitRendered(this);
|
|
2540
2542
|
} else {
|
|
2541
2543
|
if (this.view.renderPromise) await this.view.renderPromise;
|
|
@@ -3177,20 +3179,17 @@ Copyright © 2024 37signals LLC
|
|
|
3177
3179
|
prepareRequest(request) {
|
|
3178
3180
|
const link = request.target;
|
|
3179
3181
|
|
|
3180
|
-
request.headers["Sec-Purpose"] = "prefetch";
|
|
3182
|
+
request.headers["X-Sec-Purpose"] = "prefetch";
|
|
3181
3183
|
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
} else if (link.dataset.turboFrame !== "_top") {
|
|
3185
|
-
const turboFrame = link.closest("turbo-frame");
|
|
3184
|
+
const turboFrame = link.closest("turbo-frame");
|
|
3185
|
+
const turboFrameTarget = link.getAttribute("data-turbo-frame") || turboFrame?.getAttribute("target") || turboFrame?.id;
|
|
3186
3186
|
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
}
|
|
3187
|
+
if (turboFrameTarget && turboFrameTarget !== "_top") {
|
|
3188
|
+
request.headers["Turbo-Frame"] = turboFrameTarget;
|
|
3190
3189
|
}
|
|
3191
3190
|
|
|
3192
3191
|
if (link.hasAttribute("data-turbo-stream")) {
|
|
3193
|
-
request.acceptResponseType(
|
|
3192
|
+
request.acceptResponseType(StreamMessage.contentType);
|
|
3194
3193
|
}
|
|
3195
3194
|
}
|
|
3196
3195
|
|
|
@@ -3215,7 +3214,7 @@ Copyright © 2024 37signals LLC
|
|
|
3215
3214
|
#isPrefetchable(link) {
|
|
3216
3215
|
const href = link.getAttribute("href");
|
|
3217
3216
|
|
|
3218
|
-
if (!href || href === "#" || link.
|
|
3217
|
+
if (!href || href === "#" || link.getAttribute("data-turbo") === "false" || link.getAttribute("data-turbo-prefetch") === "false") {
|
|
3219
3218
|
return false
|
|
3220
3219
|
}
|
|
3221
3220
|
|
|
@@ -3231,7 +3230,8 @@ Copyright © 2024 37signals LLC
|
|
|
3231
3230
|
return false
|
|
3232
3231
|
}
|
|
3233
3232
|
|
|
3234
|
-
|
|
3233
|
+
const turboMethod = link.getAttribute("data-turbo-method");
|
|
3234
|
+
if (turboMethod && turboMethod !== "get") {
|
|
3235
3235
|
return false
|
|
3236
3236
|
}
|
|
3237
3237
|
|
|
@@ -3239,13 +3239,9 @@ Copyright © 2024 37signals LLC
|
|
|
3239
3239
|
return false
|
|
3240
3240
|
}
|
|
3241
3241
|
|
|
3242
|
-
if (link.pathname + link.search === document.location.pathname + document.location.search) {
|
|
3243
|
-
return false
|
|
3244
|
-
}
|
|
3245
|
-
|
|
3246
3242
|
const turboPrefetchParent = findClosestRecursively(link, "[data-turbo-prefetch]");
|
|
3247
3243
|
|
|
3248
|
-
if (turboPrefetchParent && turboPrefetchParent.
|
|
3244
|
+
if (turboPrefetchParent && turboPrefetchParent.getAttribute("data-turbo-prefetch") === "false") {
|
|
3249
3245
|
return false
|
|
3250
3246
|
}
|
|
3251
3247
|
|
|
@@ -4560,92 +4556,6 @@ Copyright © 2024 37signals LLC
|
|
|
4560
4556
|
}
|
|
4561
4557
|
})();
|
|
4562
4558
|
|
|
4563
|
-
class MorphRenderer extends Renderer {
|
|
4564
|
-
async render() {
|
|
4565
|
-
if (this.willRender) await this.#morphBody();
|
|
4566
|
-
}
|
|
4567
|
-
|
|
4568
|
-
get renderMethod() {
|
|
4569
|
-
return "morph"
|
|
4570
|
-
}
|
|
4571
|
-
|
|
4572
|
-
// Private
|
|
4573
|
-
|
|
4574
|
-
async #morphBody() {
|
|
4575
|
-
this.#morphElements(this.currentElement, this.newElement);
|
|
4576
|
-
this.#reloadRemoteFrames();
|
|
4577
|
-
|
|
4578
|
-
dispatch("turbo:morph", {
|
|
4579
|
-
detail: {
|
|
4580
|
-
currentElement: this.currentElement,
|
|
4581
|
-
newElement: this.newElement
|
|
4582
|
-
}
|
|
4583
|
-
});
|
|
4584
|
-
}
|
|
4585
|
-
|
|
4586
|
-
#morphElements(currentElement, newElement, morphStyle = "outerHTML") {
|
|
4587
|
-
this.isMorphingTurboFrame = this.#isFrameReloadedWithMorph(currentElement);
|
|
4588
|
-
|
|
4589
|
-
Idiomorph.morph(currentElement, newElement, {
|
|
4590
|
-
morphStyle: morphStyle,
|
|
4591
|
-
callbacks: {
|
|
4592
|
-
beforeNodeAdded: this.#shouldAddElement,
|
|
4593
|
-
beforeNodeMorphed: this.#shouldMorphElement,
|
|
4594
|
-
beforeNodeRemoved: this.#shouldRemoveElement
|
|
4595
|
-
}
|
|
4596
|
-
});
|
|
4597
|
-
}
|
|
4598
|
-
|
|
4599
|
-
#shouldAddElement = (node) => {
|
|
4600
|
-
return !(node.id && node.hasAttribute("data-turbo-permanent") && document.getElementById(node.id))
|
|
4601
|
-
}
|
|
4602
|
-
|
|
4603
|
-
#shouldMorphElement = (oldNode, newNode) => {
|
|
4604
|
-
if (oldNode instanceof HTMLElement) {
|
|
4605
|
-
return !oldNode.hasAttribute("data-turbo-permanent") && (this.isMorphingTurboFrame || !this.#isFrameReloadedWithMorph(oldNode))
|
|
4606
|
-
} else {
|
|
4607
|
-
return true
|
|
4608
|
-
}
|
|
4609
|
-
}
|
|
4610
|
-
|
|
4611
|
-
#shouldRemoveElement = (node) => {
|
|
4612
|
-
return this.#shouldMorphElement(node)
|
|
4613
|
-
}
|
|
4614
|
-
|
|
4615
|
-
#reloadRemoteFrames() {
|
|
4616
|
-
this.#remoteFrames().forEach((frame) => {
|
|
4617
|
-
if (this.#isFrameReloadedWithMorph(frame)) {
|
|
4618
|
-
this.#renderFrameWithMorph(frame);
|
|
4619
|
-
frame.reload();
|
|
4620
|
-
}
|
|
4621
|
-
});
|
|
4622
|
-
}
|
|
4623
|
-
|
|
4624
|
-
#renderFrameWithMorph(frame) {
|
|
4625
|
-
frame.addEventListener("turbo:before-frame-render", (event) => {
|
|
4626
|
-
event.detail.render = this.#morphFrameUpdate;
|
|
4627
|
-
}, { once: true });
|
|
4628
|
-
}
|
|
4629
|
-
|
|
4630
|
-
#morphFrameUpdate = (currentElement, newElement) => {
|
|
4631
|
-
dispatch("turbo:before-frame-morph", {
|
|
4632
|
-
target: currentElement,
|
|
4633
|
-
detail: { currentElement, newElement }
|
|
4634
|
-
});
|
|
4635
|
-
this.#morphElements(currentElement, newElement.children, "innerHTML");
|
|
4636
|
-
}
|
|
4637
|
-
|
|
4638
|
-
#isFrameReloadedWithMorph(element) {
|
|
4639
|
-
return element.src && element.refresh === "morph"
|
|
4640
|
-
}
|
|
4641
|
-
|
|
4642
|
-
#remoteFrames() {
|
|
4643
|
-
return Array.from(document.querySelectorAll('turbo-frame[src]')).filter(frame => {
|
|
4644
|
-
return !frame.closest('[data-turbo-permanent]')
|
|
4645
|
-
})
|
|
4646
|
-
}
|
|
4647
|
-
}
|
|
4648
|
-
|
|
4649
4559
|
class PageRenderer extends Renderer {
|
|
4650
4560
|
static renderElement(currentElement, newElement) {
|
|
4651
4561
|
if (document.body && newElement instanceof HTMLBodyElement) {
|
|
@@ -4723,7 +4633,7 @@ Copyright © 2024 37signals LLC
|
|
|
4723
4633
|
await newStylesheetElements;
|
|
4724
4634
|
|
|
4725
4635
|
if (this.willRender) {
|
|
4726
|
-
this.
|
|
4636
|
+
this.removeUnusedDynamicStylesheetElements();
|
|
4727
4637
|
}
|
|
4728
4638
|
}
|
|
4729
4639
|
|
|
@@ -4756,8 +4666,8 @@ Copyright © 2024 37signals LLC
|
|
|
4756
4666
|
}
|
|
4757
4667
|
}
|
|
4758
4668
|
|
|
4759
|
-
|
|
4760
|
-
for (const element of this.
|
|
4669
|
+
removeUnusedDynamicStylesheetElements() {
|
|
4670
|
+
for (const element of this.unusedDynamicStylesheetElements) {
|
|
4761
4671
|
document.head.removeChild(element);
|
|
4762
4672
|
}
|
|
4763
4673
|
}
|
|
@@ -4827,13 +4737,9 @@ Copyright © 2024 37signals LLC
|
|
|
4827
4737
|
await this.renderElement(this.currentElement, this.newElement);
|
|
4828
4738
|
}
|
|
4829
4739
|
|
|
4830
|
-
get
|
|
4740
|
+
get unusedDynamicStylesheetElements() {
|
|
4831
4741
|
return this.oldHeadStylesheetElements.filter((element) => {
|
|
4832
|
-
return
|
|
4833
|
-
// Trix dynamically adds styles to the head that we want to keep around which have a
|
|
4834
|
-
// `data-tag-name` attribute. Long term we should moves those styles to Trix's CSS file
|
|
4835
|
-
// but for now we'll just skip removing them
|
|
4836
|
-
element.hasAttribute("data-tag-name"))
|
|
4742
|
+
return element.getAttribute("data-turbo-track") === "dynamic"
|
|
4837
4743
|
})
|
|
4838
4744
|
}
|
|
4839
4745
|
|
|
@@ -4862,6 +4768,122 @@ Copyright © 2024 37signals LLC
|
|
|
4862
4768
|
}
|
|
4863
4769
|
}
|
|
4864
4770
|
|
|
4771
|
+
class MorphRenderer extends PageRenderer {
|
|
4772
|
+
async render() {
|
|
4773
|
+
if (this.willRender) await this.#morphBody();
|
|
4774
|
+
}
|
|
4775
|
+
|
|
4776
|
+
get renderMethod() {
|
|
4777
|
+
return "morph"
|
|
4778
|
+
}
|
|
4779
|
+
|
|
4780
|
+
// Private
|
|
4781
|
+
|
|
4782
|
+
async #morphBody() {
|
|
4783
|
+
this.#morphElements(this.currentElement, this.newElement);
|
|
4784
|
+
this.#reloadRemoteFrames();
|
|
4785
|
+
|
|
4786
|
+
dispatch("turbo:morph", {
|
|
4787
|
+
detail: {
|
|
4788
|
+
currentElement: this.currentElement,
|
|
4789
|
+
newElement: this.newElement
|
|
4790
|
+
}
|
|
4791
|
+
});
|
|
4792
|
+
}
|
|
4793
|
+
|
|
4794
|
+
#morphElements(currentElement, newElement, morphStyle = "outerHTML") {
|
|
4795
|
+
this.isMorphingTurboFrame = this.#isFrameReloadedWithMorph(currentElement);
|
|
4796
|
+
|
|
4797
|
+
Idiomorph.morph(currentElement, newElement, {
|
|
4798
|
+
ignoreActiveValue: true,
|
|
4799
|
+
morphStyle: morphStyle,
|
|
4800
|
+
callbacks: {
|
|
4801
|
+
beforeNodeAdded: this.#shouldAddElement,
|
|
4802
|
+
beforeNodeMorphed: this.#shouldMorphElement,
|
|
4803
|
+
beforeAttributeUpdated: this.#shouldUpdateAttribute,
|
|
4804
|
+
beforeNodeRemoved: this.#shouldRemoveElement,
|
|
4805
|
+
afterNodeMorphed: this.#didMorphElement
|
|
4806
|
+
}
|
|
4807
|
+
});
|
|
4808
|
+
}
|
|
4809
|
+
|
|
4810
|
+
#shouldAddElement = (node) => {
|
|
4811
|
+
return !(node.id && node.hasAttribute("data-turbo-permanent") && document.getElementById(node.id))
|
|
4812
|
+
}
|
|
4813
|
+
|
|
4814
|
+
#shouldMorphElement = (oldNode, newNode) => {
|
|
4815
|
+
if (oldNode instanceof HTMLElement) {
|
|
4816
|
+
if (!oldNode.hasAttribute("data-turbo-permanent") && (this.isMorphingTurboFrame || !this.#isFrameReloadedWithMorph(oldNode))) {
|
|
4817
|
+
const event = dispatch("turbo:before-morph-element", {
|
|
4818
|
+
cancelable: true,
|
|
4819
|
+
target: oldNode,
|
|
4820
|
+
detail: {
|
|
4821
|
+
newElement: newNode
|
|
4822
|
+
}
|
|
4823
|
+
});
|
|
4824
|
+
|
|
4825
|
+
return !event.defaultPrevented
|
|
4826
|
+
} else {
|
|
4827
|
+
return false
|
|
4828
|
+
}
|
|
4829
|
+
}
|
|
4830
|
+
}
|
|
4831
|
+
|
|
4832
|
+
#shouldUpdateAttribute = (attributeName, target, mutationType) => {
|
|
4833
|
+
const event = dispatch("turbo:before-morph-attribute", { cancelable: true, target, detail: { attributeName, mutationType } });
|
|
4834
|
+
|
|
4835
|
+
return !event.defaultPrevented
|
|
4836
|
+
}
|
|
4837
|
+
|
|
4838
|
+
#didMorphElement = (oldNode, newNode) => {
|
|
4839
|
+
if (newNode instanceof HTMLElement) {
|
|
4840
|
+
dispatch("turbo:morph-element", {
|
|
4841
|
+
target: oldNode,
|
|
4842
|
+
detail: {
|
|
4843
|
+
newElement: newNode
|
|
4844
|
+
}
|
|
4845
|
+
});
|
|
4846
|
+
}
|
|
4847
|
+
}
|
|
4848
|
+
|
|
4849
|
+
#shouldRemoveElement = (node) => {
|
|
4850
|
+
return this.#shouldMorphElement(node)
|
|
4851
|
+
}
|
|
4852
|
+
|
|
4853
|
+
#reloadRemoteFrames() {
|
|
4854
|
+
this.#remoteFrames().forEach((frame) => {
|
|
4855
|
+
if (this.#isFrameReloadedWithMorph(frame)) {
|
|
4856
|
+
this.#renderFrameWithMorph(frame);
|
|
4857
|
+
frame.reload();
|
|
4858
|
+
}
|
|
4859
|
+
});
|
|
4860
|
+
}
|
|
4861
|
+
|
|
4862
|
+
#renderFrameWithMorph(frame) {
|
|
4863
|
+
frame.addEventListener("turbo:before-frame-render", (event) => {
|
|
4864
|
+
event.detail.render = this.#morphFrameUpdate;
|
|
4865
|
+
}, { once: true });
|
|
4866
|
+
}
|
|
4867
|
+
|
|
4868
|
+
#morphFrameUpdate = (currentElement, newElement) => {
|
|
4869
|
+
dispatch("turbo:before-frame-morph", {
|
|
4870
|
+
target: currentElement,
|
|
4871
|
+
detail: { currentElement, newElement }
|
|
4872
|
+
});
|
|
4873
|
+
this.#morphElements(currentElement, newElement.children, "innerHTML");
|
|
4874
|
+
}
|
|
4875
|
+
|
|
4876
|
+
#isFrameReloadedWithMorph(element) {
|
|
4877
|
+
return element.src && element.refresh === "morph"
|
|
4878
|
+
}
|
|
4879
|
+
|
|
4880
|
+
#remoteFrames() {
|
|
4881
|
+
return Array.from(document.querySelectorAll('turbo-frame[src]')).filter(frame => {
|
|
4882
|
+
return !frame.closest('[data-turbo-permanent]')
|
|
4883
|
+
})
|
|
4884
|
+
}
|
|
4885
|
+
}
|
|
4886
|
+
|
|
4865
4887
|
class SnapshotCache {
|
|
4866
4888
|
keys = []
|
|
4867
4889
|
snapshots = {}
|
|
@@ -5021,7 +5043,7 @@ Copyright © 2024 37signals LLC
|
|
|
5021
5043
|
// Fetch request delegate
|
|
5022
5044
|
|
|
5023
5045
|
prepareRequest(fetchRequest) {
|
|
5024
|
-
fetchRequest.headers["Sec-Purpose"] = "prefetch";
|
|
5046
|
+
fetchRequest.headers["X-Sec-Purpose"] = "prefetch";
|
|
5025
5047
|
}
|
|
5026
5048
|
|
|
5027
5049
|
async requestSucceededWithResponse(fetchRequest, fetchResponse) {
|
|
@@ -5155,8 +5177,10 @@ Copyright © 2024 37signals LLC
|
|
|
5155
5177
|
const frameElement = options.frame ? document.getElementById(options.frame) : null;
|
|
5156
5178
|
|
|
5157
5179
|
if (frameElement instanceof FrameElement) {
|
|
5180
|
+
const action = options.action || getVisitAction(frameElement);
|
|
5181
|
+
|
|
5182
|
+
frameElement.delegate.proposeVisitIfNavigatedWithAction(frameElement, action);
|
|
5158
5183
|
frameElement.src = location.toString();
|
|
5159
|
-
frameElement.loaded;
|
|
5160
5184
|
} else {
|
|
5161
5185
|
this.navigator.proposeVisit(expandURL(location), options);
|
|
5162
5186
|
}
|
|
@@ -5797,7 +5821,7 @@ Copyright © 2024 37signals LLC
|
|
|
5797
5821
|
// Appearance observer delegate
|
|
5798
5822
|
|
|
5799
5823
|
elementAppearedInViewport(element) {
|
|
5800
|
-
this.proposeVisitIfNavigatedWithAction(element, element);
|
|
5824
|
+
this.proposeVisitIfNavigatedWithAction(element, getVisitAction(element));
|
|
5801
5825
|
this.#loadSourceURL();
|
|
5802
5826
|
}
|
|
5803
5827
|
|
|
@@ -5885,7 +5909,7 @@ Copyright © 2024 37signals LLC
|
|
|
5885
5909
|
formSubmissionSucceededWithResponse(formSubmission, response) {
|
|
5886
5910
|
const frame = this.#findFrameElement(formSubmission.formElement, formSubmission.submitter);
|
|
5887
5911
|
|
|
5888
|
-
frame.delegate.proposeVisitIfNavigatedWithAction(frame, formSubmission.
|
|
5912
|
+
frame.delegate.proposeVisitIfNavigatedWithAction(frame, getVisitAction(formSubmission.submitter, formSubmission.formElement, frame));
|
|
5889
5913
|
frame.delegate.loadResponse(response);
|
|
5890
5914
|
|
|
5891
5915
|
if (!formSubmission.isSafe) {
|
|
@@ -5990,15 +6014,15 @@ Copyright © 2024 37signals LLC
|
|
|
5990
6014
|
#navigateFrame(element, url, submitter) {
|
|
5991
6015
|
const frame = this.#findFrameElement(element, submitter);
|
|
5992
6016
|
|
|
5993
|
-
frame.delegate.proposeVisitIfNavigatedWithAction(frame, element,
|
|
6017
|
+
frame.delegate.proposeVisitIfNavigatedWithAction(frame, getVisitAction(submitter, element, frame));
|
|
5994
6018
|
|
|
5995
6019
|
this.#withCurrentNavigationElement(element, () => {
|
|
5996
6020
|
frame.src = url;
|
|
5997
6021
|
});
|
|
5998
6022
|
}
|
|
5999
6023
|
|
|
6000
|
-
proposeVisitIfNavigatedWithAction(frame,
|
|
6001
|
-
this.action =
|
|
6024
|
+
proposeVisitIfNavigatedWithAction(frame, action = null) {
|
|
6025
|
+
this.action = action;
|
|
6002
6026
|
|
|
6003
6027
|
if (this.action) {
|
|
6004
6028
|
const pageSnapshot = PageSnapshot.fromElement(frame).clone();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hotwired/turbo",
|
|
3
|
-
"version": "8.0.0-
|
|
3
|
+
"version": "8.0.0-rc.1",
|
|
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",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"chai": "~4.3.4",
|
|
45
45
|
"eslint": "^8.13.0",
|
|
46
46
|
"express": "^4.18.2",
|
|
47
|
-
"idiomorph": "
|
|
47
|
+
"idiomorph": "https://github.com/bigskysoftware/idiomorph.git",
|
|
48
48
|
"multer": "^1.4.2",
|
|
49
49
|
"rollup": "^2.35.1"
|
|
50
50
|
},
|