npm package: @maks11060/svelte5-router
Description: A declarative Svelte routing library with SSR support
Author: MAKS11060
Latest version: 3.2.0

# Svelte5 Router

Forked from:

- [svelte5-router](https://github.com/jpcutshall/svelte5-router)
- [svelte-routing](https://github.com/EmilTholin/svelte-routing)

A declarative Svelte routing library with SSR support.

## Install

```bash
npm i -D @maks11060/svelte5-router
pnpm add @maks11060/svelte5-router
```

## Usage

```svelte
<!-- App.svelte -->
<script>
  import { Router, Link, Route } from "svelte5-router"
  import Home from "./routes/Home.svelte"
  import About from "./routes/About.svelte"
  import Blog from "./routes/Blog.svelte"

  export let url = $state("")
</script>

<Router {url}>
  <nav>
    <link href="/">Home</Link>
    <link href="/about">About</Link>
    <link href="/blog">Blog</Link>
  </nav>
  <div>
    <Route path="/blog/:id" component={BlogPost} />
    <Route path="/blog" component={Blog} />
    <Route path="/about" component={About} />
    <Route path="/"><Home /></Route>
  </div>
</Router>
```

```javascript
// main.js
import App from './App.svelte'
import {mount} from 'svelte'

const app = mount(App, {target: document.body})
```

## Examples

<details>
<summary>Load async component</summary>

```svelte
<script>
  import {dynamic, Link, Route, Router} from 'svelte5-router'
  import Blog from './routes/Blog.svelte'
  import Home from './routes/Home.svelte'

  const Blog = dynamic(import('./routes/Blog.svelte'))

  let url = $state('')
</script>

<Router {url}>
  <nav>
    <Link class="link" to="/">Home</Link>
    <Link class="link" to="/blog">Blog</Link>
  </nav>

  <div>
    <Route path="/">
      <Home />
    </Route>
    <Route path="/blog" component={Blog} />
  </div>
</Router>
```

</details>

<details>
<summary>Nested router</summary>

[Example code](tests/App.svelte)

</details>

## API

#### `Router`

The `Router` component supplies the `Link` and `Route` descendant components with routing information through context,
so you need at least one `Router` at the top of your application. It assigns a score to all its `Route` descendants and
picks the best match to render.

`Router` components can also be nested to allow for seamless merging of many smaller apps.

###### Properties

|     Property     | Required | Default Value | Description                                                                                                                                                                                                                                                                                                 |
| :--------------: | :------: | :-----------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|    `basepath`    |          |     `"/"`     | The `basepath` property will be added to all the `to` properties of `Link` descendants and to all `path` properties of `Route` descendants. This property can be ignored in most cases, but if you host your application on e.g. `https://example.com/my-site`, the `basepath` should be set to `/my-site`. |
|      `url`       |          |     `""`      | The `url` property is used in SSR to force the current URL of the application and will be used by all `Link` and `Route` descendants. A falsy value will be ignored by the `Router`, so it's enough to declare `let url = $state("")` for your topmost component and only give it a value in SSR.           |
| `viewtransition` |          |    `null`     | View Transition (Experimental)                                                                                                                                                                                                                                                                              |

#### `Link`

A component used to navigate around the application.

###### Properties

|     Property     | Required | Default Value | Description                                                                                                       |
| :--------------: | :------: | :-----------: | :---------------------------------------------------------------------------------------------------------------- |
|      `href`      |    ✔ ️    |     `"#"`     | URL the component should link to.                                                                                 |
|    `replace`     |          |    `false`    | When `true`, clicking the `Link` will replace the current entry in the history stack instead of adding a new one. |
|     `state`      |          |     `{}`      | An object that will be pushed to the history stack when the `Link` is clicked.                                    |
| `preserveScroll` |          |    `false`    | When `true`, clicking the `Link` will not scroll the page to the top.                                             |

#### `Route`

A component that will render its `component` property or children when its ancestor `Router` component decides it is the
best match.

All properties other than `path` and `component` given to the `Route` will be passed to the rendered `component`.

Potential path parameters will be passed to the rendered `component` as properties. A wildcard `*` can be given a name
with `*wildcardName` to pass the wildcard string as the `wildcardName` property instead of as the `*` property.

Potential path parameters are passed back to the parent using props, so they can be exposed to the children snippet.

```svelte
<Route path="/blog/:id">
  {#snippet children(params)}
    <BlogPost id={params.id} />
  {/snippet}
</Route>
```

The active status of link can be exposed to the children snippet.

```svelte
<link href="/browser">
{#snippet children(active)}
  <menuitem {active}>Browser</menuitem>
{/snippet}
</Link>
```

###### Properties

|    Property     | Required | Default Value | Description                                                                                                                                                              |
| :-------------: | :------: | :------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|     `path`      |          | `""`          | The path for when this component should be rendered. If no `path` is given the `Route` will act as the default that matches if no other `Route` in the `Router` matches. |
| ~~`component`~~ |          | `null`        | The component constructor that will be used for rendering when the `Route` matches. If `component` is not set, the children of `Route` will be rendered instead.         |
|   `children`    |   yes    |               | children passed inside the element. You can use the children snippet to access any url parameters `{#snippet children(params)}`                                          |

#### `navigate`

A function that allows you to imperatively navigate around the application for those use cases where a `Link` component
is not suitable, e.g. after submitting a form.

The first argument is a string denoting where to navigate to, and the second argument is an object with a `replace`,
`state` and `preserveScroll` properties equivalent to those in the `Link` component.

```svelte
<script>
  import {navigate} from '@maks11060/svelte5-router'

  function onSubmit() {
    login().then(() => {
      navigate('/success', {replace: true})
    })
  }
</script>
```

#### `listen`

A function that allows you to listen to path changes made from `navigate`, `Link` and browser back button.

The argument supplied must be a function that receives a Location object. Use the returned function to unsubscribe the
listener.

This function is meant to be used outside a Svelte component. The alternative function is `useLocation`, `useRouter` and
`useHistory` where it uses Svelte context to retrieve location, router or history object.

```js
import {listen as addListener} from '@maks11060/svelte5-router'

function init() {
  addListener(({location}) => {
    console.log(location.pathname)
  })
}
```

#### `link`

An action used on anchor tags to navigate around the application. You can add an attribute `replace` to replace the
current entry in the history stack instead of adding a new one and `preserveScroll` to not scroll the page to the top
when clicked.

```svelte
<script>
  import {link} from '@maks11060/svelte5-router'
</script>

<Router>
  <a href="/" use:link>Home</a>
  <a href="/replace" use:link replace>Replace this URL</a>
  <!-- ... -->
</Router>
```

#### `links`

An action used on a root element to make all relative anchor elements navigate around the application. You can add an
attribute `replace` on any anchor to replace the current entry in the history stack instead of adding a new one. You can
add an attribute `preserveScroll` on any anchor to not to scroll the page to the top when clicked. You can add an
attribute `noroute` for this action to skip over the anchor and allow it to use the native browser action.

```svelte
<!-- App.svelte -->
<script>
  import {links} from '@maks11060/svelte5-router'
</script>

<div use:links>
  <Router>
    <a href="/">Home</a>
    <a href="/replace" replace>Replace this URL</a>
    <a href="/native" noroute>Use the native action</a>
    <!-- ... -->
  </Router>
</div>
```

#### `viewtransition`

Viewtransition for navigation (Experimental).

_`builtin transition`_

```svelte
<script>
  import {fade} from 'svelte/transition'
  // ...
</script>

<Router viewtransition="{() => { fn: fade, duration: 500 }}">
  <Route path="/" component={Home} />
  <Route path="/contact" component={Contact} />
</Router>
```

_`custom transition`_

```svelte
<script>
  import {cubicin} from 'svelte/easing'
  // ...
</script>

<Router
  viewtransition="{() => { duration: 500, easing: cubicin, css: (t) => `scale:${t};transform-origin:center center;` }}"
>
  <Route path="/" component={Home} />
  <Route path="/contact" component={Contact} />
</Router>
```

# License

This project is licensed under the [**MIT**](LICENSE).

# Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for this project by you, shall be
licensed as **MIT**, without any additional terms or conditions. [**Code of Conduct**](CODE_OF_CONDUCT.md).