npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@dvcol/svelte-simple-router

v1.1.2

Published

Simple svelte 5 client side router

Downloads

39

Readme

description here

Prerequisites

  • svelte >= 5.0.0

Install

pnpm add @dvcol/svelte-simple-router

Getting Started

The minimal setup requires a RouterView component and a list of routes.

The RouterView component will render the component associated with the current route in place.

You can find a complete example in the demo app.

<script lang="ts">
  import { RouterView } from '@dvcol/svelte-simple-router/components';

  import type { Route, RouterOptions } from '@dvcol/svelte-simple-router/models';
  
  import HelloComponent from '~/components/hello/HelloComponent.svelte';
  import GoodbyeComponent from '~/components/goodbye/GoodbyeComponent.svelte';

  const RouteName = {
    Hello: 'hello',
    Goodbye: 'goodbye',
    Home: 'home',
    Any: 'any',
  } as const;

  type RouteNames = (typeof RouteName)[keyof typeof RouteName];

  export const routes: Readonly<Route<RouteNames>[]> = [
    {
      name: RouteName.Home,
      path: '/',
      redirect: {
        name: RouteName.Hello,
      },
    },
    {
      name: RouteName.Hello,
      path: `/${RouteName.Hello}`,
      component: HelloComponent
    },
    {
      name: RouteName.Goodbye,
      path: `/${RouteName.Goodbye}`,
      component: GoodbyeComponent
    },
    {
      name: RouteName.Any,
      path: '*',
      redirect: {
        name: RouteName.Hello,
      },
    },
  ] as const;

  export const options: RouterOptions<RouteNames> = {
    routes,
  } as const;
  
</script>

<RouterView {options} />

Advanced Usage

Router Context

The RouterContext component injects the router instance into the component tree.

It can be used to share a router instance between RouterView components without the need to pass it down as a prop.

<script lang="ts">
  import { RouterContext } from '@dvcol/svelte-simple-router/components';
  import { RouterView } from '@dvcol/svelte-simple-router/components';
</script>

<RouterContext>
  <!--  children  -->
</RouterContext>

Route / Router debugger

The RouterDebugger and RouteDugger component will display the current route and router state.

It can be used to debug the router configuration and the current route.

It requires to be placed inside a RouterView or RouterContext component.

<script lang="ts">
  import { RouterDebugger, RouteDebugger } from '@dvcol/svelte-simple-router/components/debug';
  import { RouterView } from '@dvcol/svelte-simple-router/components';
</script>

<RouterView>
  <RouterDebugger />
  <RouteDebugger />
</RouterView>

Nested router / named Router

The RouterView component can be nested under another RouterView or RouterContext component.

Named RouterView components can be used to render different components on the same route.

Each RouterView grabs the router context from the nearest RouterContext or RouterView component.

Note: Sibling RouterView or RouterContext components will instantiate a new router instance.

<script lang="ts">
  import { RouterView } from '@dvcol/svelte-simple-router/components';
  import { RouterContext } from '@dvcol/svelte-simple-router/components';

  import type { Route, RouterOptions } from '@dvcol/svelte-simple-router/models';
  
  import ParentComponent from '~/components/hello/ParentComponent.svelte';
  import ChildComponent from '~/components/goodbye/ChildComponent.svelte';

  const RouteName = {
    Parent: 'parent',
    Child: 'child',
  } as const;

  type RouteNames = (typeof RouteName)[keyof typeof RouteName];

  export const routes: Readonly<Route<RouteNames>[]> = [
    {
      name: RouteName.Parent,
      path: `/${RouteName.Parent}`,
      component: ParentComponent
    },
    {
      name: RouteName.Nested,
      path: `/${RouteName.Parent}/${RouteName.Child}`,
      components: {
        default: ParentComponent,
        nested: ChildComponent,
      }
    },
  ] as const;

  export const options: RouterOptions<RouteNames> = {
    routes,
  } as const;

</script>

<RouterContext {options}>
  <RouterView>
    <!--  will render ParentComponent  -->
  </RouterView>
  
  <RouterView name="nested">
    <!--  will only render ChildComponent on /parent/child, and nothing on /parent -->
  </RouterView>
</RouterContext>

Router transition

The RouterView component can take a transition prop to animate the route transition.

It wraps the route component in a div with optionals in and out transitions.

A default fade/scale transition is provided, but you can pass your own transitions.

Note: By default the first enter transition is ignored, you can change this behavior by setting the skipFirst option to false.

<script lang="ts">
  import { RouterView } from '@dvcol/svelte-simple-router/components';
  import { transition } from '@dvcol/svelte-simple-router/utils';
  
  ...
</script>

<RouterView {transition} {options} />

Dom actions

Link action

The link action intercepts click events on dom elements and triggers a router navigation instead.

The link action will prevent the default behavior and use the router only if the following conditions are met:

  • The element is within a router context
  • The event is a left click or enter key
  • The event does not have a modifier key
  • The target is not an external link (for anchor elements)
  • The target is not a new tab or window (for anchor elements)

Additionally:

  • The action merge data-attributes with the options passed as argument.
  • Passed options have precedence over data-attributes.
  • If attribute expects a JSON object, it will be parsed.
  • If a name or path parameter are provided, they will be used to navigate and href will be ignored.
  • Name takes precedence over path.
  • If the host is not an anchor element, the role and tabindex attributes will be set.

Note: The action requires the router context to be present in the component tree.

<script lang="ts">
  import { link } from '@dvcol/svelte-simple-router/router';
</script>

<a href="/path/:param?query=value" use:link>simple link</a>
<a href='goodbye' name use:link>named link</a>
<a href='/path/:param' data-query='{"query":"value"}' use:link>link with query</a>
<a href='/path/:param' use:link="{ params: { param: 'value' } }">link with params</a>
<div href='/path/:param' use:link="{ params: { param: 'value' } }">div link</div>
<button href='/path/:param' use:link="{ params: { param: 'value' } }">button link</button>

Active action

The active action adds an active state (class, style or attribute) to an element when the route matches.

Additionally:

  • If attached to an anchor element, it will attempt to match the href attribute.
  • If path or name options are provided, they will take precedence over the element attributes.
  • Name always takes precedence over path.
  • When the route un-matches, the original style will be restored.

Note: The action requires the router context to be present in the component tree.

<script lang="ts">
  import { active } from '@dvcol/svelte-simple-router/router';
</script>

<a href="/path" use:active>simple link</a>
<a href="/path" data-name="route-name" use:active>named link</a>
<button :use:active="{ path: '/path' }">button link</button>
<div :use:active="{ name: 'route-name' }">div link</div>

Programmatic navigation

To navigate without a dom link, you can grab the router instance from the context and call the push or replace methods.

See the router model for more information.


<script lang="ts">
  import { RouterContext } from '@dvcol/svelte-simple-router/components';
  import { RouterView } from '@dvcol/svelte-simple-router/components';
  import { useRouter } from '@dvcol/svelte-simple-router/router';
  
  const router = useRouter();
  
  const onPush = () => {
    router.push({ path: "/route-path" });
  };
  
  const onReplace = () => {
    router.replace({ name: "route-name" });
  };
</script>

If you need to access the router instance outside of a component, you can instantiate a router instance and pass it to the RouterContext or RouterView component.

import { Router } from '@dvcol/svelte-simple-router/router';

export const router = new Router();
<script lang="ts">
  import { RouterView } from '@dvcol/svelte-simple-router/components';
  
  import { router } from './router';
</script>

<RouterView {router} />

Router navigation support several options:

  • name or path to navigate to a named or path route.
  • params to pass route parameters.
  • query to pass query parameters.
  • state to pass an history state object.
  • stripQuery to remove current query parameters from the url.
  • stripHash to remove the hash from the url (only in path mode).
  • stripTrailingHash to remove the trailing hash from the url (only in hash mode).

You can also override the router's navigation options:

  • base to set the base path for the router.
  • hash to enable hash routing.
  • strict to enable strictly match routes (i.e. /path will not match /path/child).
  • force to force navigation even if the route is the same.
  • caseSensitive to enable case sensitive route names.
  • failOnNotFound to throw an error when a route is not found.
  • metaAsState to pass the route meta as state when navigating.
  • nameAsTitle to set the document title to the route name.
  • followGuardRedirects to follow guard redirects.

Dynamic routes

You can dynamically add or remove routes from the router instance.

Note that although the inner route map are reactive, adding or removing routes will not trigger a re-synchronization of the router state.

To force a re-synchronization, you can call the sync method on the router instance.

Guards and listeners

The route and router` supports several navigation guards and listeners:

Guards trigger after url change and before the route component is rendered.

If a guard returns false, and object of instance Error or throws, the navigation will be aborted and the error will be thrown.

If a guard returns an object with a path or name property, the navigation will be redirected to the provided route, if any is found and followGuardRedirects is enabled.

The router (dynamically or through options) and RouterView also support several event listeners:

  • onStart - executed when the navigation is triggered but before the route is resolved (fires on start and redirects).
  • onEnd - executed when the navigation is triggered and the route is resolved (fires on successful and failed navigation, but not on cancelled/redirected).
  • onError - executed when the navigation is triggered but an error occurs.

Lazy routing

The Route object supports lazy loading of the route component.

When the component property is a lazy import, the router will resolve the matched component before rendering it.

While the component is being resolved, the loading component will be rendered if any, the loading snippet if any, or nothing.

Similarly, if an error occurs during the component resolution, the error component will be rendered if any, the error snippet if any, or nothing.

<script lang="ts">
    import { RouterView } from '@dvcol/svelte-simple-router/components';
    import type { Route, RouterOptions } from '@dvcol/svelte-simple-router/models';
    
    const routes: Readonly<Route[]> = [
        {
            name: 'lazy',
            path: '/lazy',
            component: () => import('./LazyComponent.svelte'),
            loading: () => import('./LoadingComponent.svelte'),
            error: () => import('./ErrorComponent.svelte'),
        },
        {
            name: 'lazy-snippet',
            path: '/lazy-snippet',
            components: () => import('./LazyComponent.svelte')
        }
    ] as const;
</script>

<RouterView {routes}>
  {#snippet loading()}
    <h1>Default Loading...</h1>
  {/snippet}

  {#snippet error(err)}
    <h1>Default Error: {err}</h1>
  {/snippet}
</RouterView>

Routes

  • Route path supports parameters. Parameters are defined by a colon followed by the parameter name.
/path/:param
  • Parameters can be optional by adding a question mark.
/path/:param?

Parameters can also have a type constraint by adding :{string} or :{number} before the parameter name.

The router will only match the route if the parameter matches the type constraint.

/path/:{string}:param?

Will match /path/param but not /path/1.

/path/:{number}:param

Will match /path/1 but not /path/param.

  • Route support wildcards. The * character will match any path segment.
/path/*

Will match /path/param and /path/param/param.

/path/*/:{number}:param/*

Will match /path/any/12 and /path/other/12/path/end.

  • Route can have a redirect property to redirect to another route (by path or name).
  • Route can have components, loadings or errors properties to render the route component, loading component or error component respectively (see lazy-routing).
  • Route can have a meta property to store additional information attached to the route.
  • Route can have a title property to set the document title when the route is active (if nameAsTitle is enabled).
  • Route can have default query or params to be used when navigating to the route.
  • Route can have guard properties to run before the route is resolved (see guards and listeners).
  • Route can provide their own matcher object to resolve the active route.
  • Route can have children routes that will be parsed by the router instance.

Router

In addition to default navigation options (see programmatic navigation), the router instance supports several options:

  • history to set the history instance the router will use (defaults to window.history).
  • listen to listen to popstate or navigation events and trigger synchronization.
  • priority to set the priority when multiple routes match the current path.
  • caseSensitive to enable case sensitive route names.
  • And various guards and listeners.

Author

Show your support

Give a ⭐️ if this project helped you!

📝 License

This project is MIT licensed.


This README was generated with ❤️ by readme-md-generator