diff --git a/.changeset/mighty-pigs-kiss.md b/.changeset/mighty-pigs-kiss.md new file mode 100644 index 0000000..1e18b75 --- /dev/null +++ b/.changeset/mighty-pigs-kiss.md @@ -0,0 +1,5 @@ +--- +'sveltekit-view-transition': patch +--- + +fix typing for action and move jsdoc to return value diff --git a/README.md b/README.md index 46e4596..ee23377 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,27 @@ Simplified `view-transition-api` for Sveltekit. ## Before we begin: what is a view transition? -I could go in thousands of details on what `view-transitions` are but what a better way of understanding them that from the words of Jake Archibald, the main mind behind them? Here's a [wonderful article](https://developer.chrome.com/docs/web-platform/view-transitions/) from him that explains what they are and how to use them in Vanilla JS. +Svelte has kinda spoiled us: we have built in animations and transitions so that we can add a little bit of micro-interactions to our websites and apps. Do you need to animate a list reordering? `flip` comes to the rescue. Is a div moving and morphing from one list to another? `crossfade` is your friend. The web platform must have seen how much svelte developers love those kind of things and has provided us with a brand new, fully progressive enhance-able api: **[the view transition API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API)**. This api not only allows you to animate between two states of your application regardless of the fact that two elements are actually the same or not (something that before was only possible with third party libraries or very complex code) but allows you to animate elements that are **on different pages**! + +SvelteKit provides a way to hook into the navigation to allow the developer to start a view transition before the navigation and they do so with a very low level primitive. Here's how you can enable view transitions in SvelteKit + +```ts +onNavigate((navigation) => { + if (!document.startViewTransition) return; + return new Promise((resolve) => { + document.startViewTransition(async () => { + resolve(); + await navigation.complete; + }); + }); +}); +``` + +While not very complex, writing this snippets everywhere you need it can get quite tedious and sometimes based on how the `view-transition-api` works you might need to do other things like add classes or change the style of an element. + +`sveltekit-view-transition` aim to ease the experience of writing easy and complex transitions in SvelteKit! + +Before going in the details of how this library works and how to make use of it i want to leave here a [wonderful article](https://developer.chrome.com/docs/web-platform/view-transitions/) that explains what they are and how to use them in Vanilla JS from Jake Archibald, the main mind behind them. ## Installation diff --git a/src/lib/sveltekit-view-transition.ts b/src/lib/sveltekit-view-transition.ts index e3ca229..5e5c58a 100644 --- a/src/lib/sveltekit-view-transition.ts +++ b/src/lib/sveltekit-view-transition.ts @@ -96,14 +96,6 @@ function run_all_events( } } -/** - * This function is used to deregister from an event. A function that - * deregister from an event is also returned from the on function. - * @param event the event name you want to deregister from - * @param callback the callback reference you want to deregister - * @param autoWrap by default the off function is wrapped in afterNavigate so that you can - * avoid unnecessarily wrap it every time. If you need to avoid this behavior you can pass false. - */ function off( event: T, callback: (props: SveltekitViewTransitionEventsMap[T]) => void | Promise, @@ -142,19 +134,6 @@ function off( } } -/** - * Function used to register a callback run during the onNavigate - * @param event the event name you want to register a callback for - * @param callback The callback you want to run - * @param options The options for the add listener - * @param options.registerDuringTransition if you want to register this callback even if a transition is running (if false - * it will still be registered as soon as the transition finishes) - * @param options.avoidWrapping by default the on function is wrapped in afterNavigate so that you can - * avoid unnecessarily wrap it every time. If you need to avoid this behavior you can pass true. - * @param options.autoClean wether the listener clean automatically after has been applied or it requires manual cleaning. - * it defaults to true - * @returns A function to deregister the callback - */ function on( event: T, callback: (props: SveltekitViewTransitionEventsMap[T]) => void, @@ -199,18 +178,6 @@ function on( return return_value; } -/** - * Function to call during component initialization to add a class or a series of classes - * during the navigation. This is useful to run a different types of transition when you are going - * back to a specific page. - * - * The classes will be automatically removed at the end of the transition. - * - * @param to_add either a list of class that will always be applied or a function that returns an array - * of strings. The function will get a navigation props as input to allow you to check the to, from, route id etc. - * @param autoWrap by default the classes function is wrapped in afterNavigate so that you can - * avoid unnecessarily wrap it every time. If you need to avoid this behavior you can pass false. - */ function classes( to_add: | string[] @@ -249,30 +216,7 @@ function classes( ); } -/** - * The action to specify a transition name on a specific element. You can use it on an element - * passing a string to directly assign that specific string as view transition name. - * - * If you pass an object instead you can specify a series of options: - * - * - name: required, it's the transition name that will be applied it can be either a string or a function that return a string. The function takes a navigation - * object as input. This is useful if you need to apply different transition names depending on where the navigation is going. - * - classes: either an array of strings or a function that returns an array of string that will be applied - * during the transition. The function will take a navigation object - * - applyImmediately: by default when you specify a transition name it will only be applied when it's actually navigating - * following the suggestion from Jake Archibald himself (the creator of the view transition api) https://twitter.com/jaffathecake/status/1697541871847748098?s=20 - * that you should not add transition names to everything but only to the elements involved in the transition. Sometimes tho you want to - * add a transition name immediately (for example when you are coming back from a detail page and you want to animate back an image in the list). - * applyImmediately is either a boolean or a function that take the navigation object (please note that this is the navigation object) from - * the previous page so the `from` will be the page that is navigating to this page and the `to` will be this page) and returns a boolean. - * - shouldApply: as mentioned above this can be either a boolean or a function that takes a navigation object (this time the `from` is - * this page and the `to` is the page you are navigating to) and return a boolean. If the boolean is true the transition name will be applied. - * This is useful when you want to navigate from a list to a detail. - * - * @param node The element to apply the action to - * @param props either a string for a simple view transition name or a set of options - */ -function transition(node: HTMLElement, props: string | TransitionAction) { +function transition(node: HTMLElement | SVGElement, props: string | TransitionAction) { if (typeof props === 'string') { node.style.setProperty('view-transition-name', props); return; @@ -434,9 +378,65 @@ export function setupViewTransition() { } return { + /** + * Function used to register a callback run during the onNavigate + * @param event the event name you want to register a callback for + * @param callback The callback you want to run + * @param options The options for the add listener + * @param options.registerDuringTransition if you want to register this callback even if a transition is running (if false + * it will still be registered as soon as the transition finishes) + * @param options.avoidWrapping by default the on function is wrapped in afterNavigate so that you can + * avoid unnecessarily wrap it every time. If you need to avoid this behavior you can pass true. + * @param options.autoClean wether the listener clean automatically after has been applied or it requires manual cleaning. + * it defaults to true + * @returns A function to deregister the callback + */ on, + /** + * This function is used to deregister from an event. A function that + * deregister from an event is also returned from the on function. + * @param event the event name you want to deregister from + * @param callback the callback reference you want to deregister + * @param autoWrap by default the off function is wrapped in afterNavigate so that you can + * avoid unnecessarily wrap it every time. If you need to avoid this behavior you can pass false. + */ off, + /** + * The action to specify a transition name on a specific element. You can use it on an element + * passing a string to directly assign that specific string as view transition name. + * + * If you pass an object instead you can specify a series of options: + * + * - name: required, it's the transition name that will be applied it can be either a string or a function that return a string. The function takes a navigation + * object as input. This is useful if you need to apply different transition names depending on where the navigation is going. + * - classes: either an array of strings or a function that returns an array of string that will be applied + * during the transition. The function will take a navigation object + * - applyImmediately: by default when you specify a transition name it will only be applied when it's actually navigating + * following the suggestion from Jake Archibald himself (the creator of the view transition api) https://twitter.com/jaffathecake/status/1697541871847748098?s=20 + * that you should not add transition names to everything but only to the elements involved in the transition. Sometimes tho you want to + * add a transition name immediately (for example when you are coming back from a detail page and you want to animate back an image in the list). + * applyImmediately is either a boolean or a function that take the navigation object (please note that this is the navigation object) from + * the previous page so the `from` will be the page that is navigating to this page and the `to` will be this page) and returns a boolean. + * - shouldApply: as mentioned above this can be either a boolean or a function that takes a navigation object (this time the `from` is + * this page and the `to` is the page you are navigating to) and return a boolean. If the boolean is true the transition name will be applied. + * This is useful when you want to navigate from a list to a detail. + * + * @param node The element to apply the action to + * @param props either a string for a simple view transition name or a set of options + */ transition, + /** + * Function to call during component initialization to add a class or a series of classes + * during the navigation. This is useful to run a different types of transition when you are going + * back to a specific page. + * + * The classes will be automatically removed at the end of the transition. + * + * @param to_add either a list of class that will always be applied or a function that returns an array + * of strings. The function will get a navigation props as input to allow you to check the to, from, route id etc. + * @param autoWrap by default the classes function is wrapped in afterNavigate so that you can + * avoid unnecessarily wrap it every time. If you need to avoid this behavior you can pass false. + */ classes, }; } diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 3d4322e..89d4cca 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -66,10 +66,37 @@ +

+ sveltekit-view-transition +

+

+ Made with 🧡 by paoloricciuti +

{:else}
-
+

`sveltekit-view-transition`

+

Getting started

diff --git a/src/routes/docs/+page.svelte b/src/routes/docs/+page.svelte index e068fbf..252e9b5 100644 --- a/src/routes/docs/+page.svelte +++ b/src/routes/docs/+page.svelte @@ -5,9 +5,23 @@ const { transition } = setupViewTransition(); -

+

`sveltekit-view-transition`

+
-
+