This commit is contained in:
Carson Gross 2023-03-28 14:15:00 -06:00
parent 36780c034f
commit fd87ffd516
5 changed files with 111 additions and 5 deletions

View File

@ -70,6 +70,7 @@ return (function () {
scrollBehavior: 'smooth',
defaultFocusScroll: false,
getCacheBusterParam: false,
globalViewTransitions: false,
},
parseInterval:parseInterval,
_:internalEval,
@ -2396,6 +2397,9 @@ return (function () {
if (modifier.indexOf("settle:") === 0) {
swapSpec["settleDelay"] = parseInterval(modifier.substr(7));
}
if (modifier.indexOf("transition:") === 0) {
swapSpec["transition"] = modifier.substr(11) === "true";
}
if (modifier.indexOf("scroll:") === 0) {
var scrollSpec = modifier.substr(7);
var splitSpec = scrollSpec.split(":");
@ -3127,9 +3131,13 @@ return (function () {
var swapSpec = getSwapSpecification(elt, swapOverride);
target.classList.add(htmx.config.swappingClass);
// optional transition API promise callbacks
var settleResolve = null;
var settleReject = null;
var doSwap = function () {
try {
var activeElt = document.activeElement;
var selectionInfo = {};
try {
@ -3228,6 +3236,7 @@ return (function () {
}
handleTrigger(xhr, "HX-Trigger-After-Settle", finalElt);
}
maybeCall(settleResolve);
}
if (swapSpec.settleDelay > 0) {
@ -3237,10 +3246,34 @@ return (function () {
}
} catch (e) {
triggerErrorEvent(elt, 'htmx:swapError', responseInfo);
maybeCall(settleReject);
throw e;
}
};
var shouldTransition = htmx.config.globalViewTransitions
if(swapSpec.hasOwnProperty('transition')){
shouldTransition = swapSpec.transition;
}
if(shouldTransition &&
triggerEvent(elt, 'htmx:beforeTransition', responseInfo) &&
typeof Promise !== "undefined" && document.startViewTransition){
var settlePromise = new Promise(function (_resolve, _reject) {
settleResolve = _resolve;
settleReject = _reject;
});
// wrap the original doSwap() in a call to startViewTransition()
var innerDoSwap = doSwap;
doSwap = function() {
document.startViewTransition(function () {
innerDoSwap();
return settlePromise;
});
}
}
if (swapSpec.swapDelay > 0) {
setTimeout(doSwap, swapSpec.swapDelay)
} else {

View File

@ -14,6 +14,36 @@
}
</style>
<style>
@keyframes fade-in {
from { opacity: 0; }
}
@keyframes fade-out {
to { opacity: 0; }
}
@keyframes slide-from-right {
from { transform: translateX(30px); }
}
@keyframes slide-to-left {
to { transform: translateX(-30px); }
}
::view-transition-old(root) {
animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}
::view-transition-new(root) {
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}
</style>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
</head>
@ -48,6 +78,7 @@
</script>
<h2>Server Options</h2>
<button onclick="server.respond()">Server Respond</button>
<br/>
@ -62,12 +93,17 @@ Autorespond: <input id="autorespond" type="checkbox" onclick="toggleAutoRespond(
</div>
<script>
this.server.respondWith("GET", "/demo", 'demo response...');
let requestCount = 0;
this.server.respondWith("GET", "/demo", function(xhr){
let randomStr = (Math.random() + 1).toString(36).substring(7);
xhr.respond(200, {}, "Request #" + requestCount++ + " : " + randomStr)
});
</script>
<button>First</button>
<input hx-get="/demo" hx-target="next output" hx-trigger="keyup changed" hx-on-before-request="alert('foo')"/>
<output>--</output>
<button hx-get="/demo"
hx-target="next h1"
hx-swap="innerHTML transition:true">Issue Request</button>
<h1 id="h1">--</h1>
</body>
</html>

View File

@ -35,6 +35,12 @@ The `div` will issue a request to `/example` and append the returned content aft
The `hx-swap` attributes supports modifiers for changing the behavior of the swap. They are outlined below.
#### Transition: `transition`
If you want to use the new (View Transitions)[https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API] API
when a swap occurs, you can use the `transition:true` option for your swap. You can also enable this feature globally by
setting the `htmx.config.globalViewTransitions` config setting to `true`.
#### Timing: `swap` & `settle`
You can modify the amount of time that htmx will wait after receiving a response to swap the content

View File

@ -417,6 +417,22 @@ The following extensions are available for morph-style swaps:
* [Idiomorph](https://github.com/bigskysoftware/idiomorph#htmx) - A newer morphing algorithm developed by us, the creators
of htmx. Idiomorph will be available out of the box in htmx 2.0.
#### <a name="view-transitions"></a> [View Transitions](#view-transitions)
The new, experimental [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API)
gives developers a way to create an animated transition between different DOM states. It is still in active development
and is not available in all browsers, but htmx provides a way to work with this new API that falls back to the non-transition
mechanism if the API is not available in a given browser.
You can experiment with this new API using the following approaches:
* Set the `htmx.config.globalViewTransitions` config variable to `true` to use transitions for all swaps
* Use the `transition:true` option in the `hx-swap` attribute
* If an element swap is going to be transitioned due to either of the above configurations, you may catch the
`htmx:beforeTransition` event and call `preventDefault()` on it to cancel the transition.
View Transitions can be configured using CSS, as outlined in [the Chrome documentation for the feature](https://developer.chrome.com/docs/web-platform/view-transitions/#simple-customization).
### <a name="synchronization"></a> [Synchronization](#synchronization)
Often you want to coordinate the requests between two elements. For example, you may want a request from one element
@ -1402,6 +1418,7 @@ listed below:
| `htmx.config.timeout` | defaults to 0 in milliseconds |
| `htmx.config.defaultFocusScroll` | if the focused element should be scrolled into view, defaults to false and can be overridden using the [focus-scroll](/attributes/hx-swap/#focus-scroll) swap modifier. |
| `htmx.config.getCacheBusterParam` | defaults to false, if set to true htmx will include a cache-busting parameter in `GET` requests to avoid caching partial responses by the browser |
| `htmx.config.globalViewTransitions` | if set to `true`, htmx will use the [View Transition](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) API when swapping in new content. |
</div>

View File

@ -134,6 +134,20 @@ the documentation on [configuring swapping](/docs#modifying_swapping_behavior_wi
* `detail.shouldSwap` - if the content will be swapped (defaults to `false` for non-200 response codes)
* `detail.target` - the target of the swap
### <a name="htmx:beforeTransition"></a> Event - [`htmx:beforeTransition`](#htmx:beforeTransition)
This event is triggered before a [View Transition](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API)
wrapped swap occurs. If the event is cancelled, the View Transition will not occur and the normal swapping logic will
happen instead.
##### Details
* `detail.elt` - the element that dispatched the request
* `detail.xhr` - the `XMLHttpRequest`
* `detail.requestConfig` - the configuration of the AJAX request
* `detail.shouldSwap` - if the content will be swapped (defaults to `false` for non-200 response codes)
* `detail.target` - the target of the swap
### <a name="htmx:configRequest"></a> Event - [`htmx:configRequest`](#htmx:configRequest)
This event is triggered after htmx has collected parameters for inclusion in the request. It can be