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

super-svelte-router

v1.6.1

Published

A powerful, easy to use Router for svelte

Downloads

5

Readme

super-svelte-router

this project follows semver

a small, simple router for svelte

Table of contents

Usage

<script>
  import { Router } from "super-svelte-router";

  const routes = [
    {
      path: "**",
      component: NotFound,
    },
    {
      path: "/",
      component: Main,
    },
    {
      path: "/about",
      component: Main,
    },
    {
      path: "/product/:id",
      component: Product,
    },
    {
      path: "/lazy",
      component: () => import("./Lazy.svelte"),
      loading: Loading,
      lazyLoad: true,
    },
    {
      path: "/protected",
      authenticator: () => {
        // some authentication logic
        return true;
        // or if fails
        return false;
      },
      // or
      authenticator: async () => {
        // some async authentication logic
        return true;
        // or if fails
        return false;
      },
      authComponent: authComponent,
      component: Protected,
    },
  ];
</script>

<Router {routes}></Router>

API

routerStore

routerStore is a custom svelte store that contain the status of the router

Also the Router will pass every property on $routerStore as props

for example you could do this:

<script>
  export let params;

  console.log(params);
</script>

instead of:

<script>
  import { routerStore } from "super-svelte-router";

  console.log($routerStore.params);
</script>

To prevent that pass noProp prop to the Router

noProps

<script>
  import { Router } from "super-svelte-router";

  const routes = [...];
</script>

<Router {routes} noProps="{true}"></Router>

redirect method

routerStore.redirect is used for redirecting

example:

import { routerStore } from "super-svelte-router";

routerStore.redirect("/hello");
// to replace instead of push
routerStore.redirect("/hello", true);

Not found routes

DO NOT put more than one 404 route in routes

to use 404 route you set path to ** like below

[
  ...
  {
    path: "**",
    component: NotFound
  }
  ...
]

example for 404 component

<h1>404 Not Found</h1>

Static routes

DO NOT use : in static routes

example:

[
  ...
  {
    path: "/static",
    component: Static
  }
  ...
]

example for static component

<h1>I'm static</h1>

Dynamic routes

to use a dynamic route put : before the dynamic part(s) of url you could have as many dynamic parts as you like

for example:

/foo/:id

in this example :id could be replaced with anything including :id

example for pathname(s) that matches this example

/foo/100 /foo/random-id /foo/:id /foo/ <-- be careful with this one

use routerStore to access params

example:

[
  ...
  {
    path: "/foo/:id",
    component: Params
  }
  ...
]

example for params component

<script>
  import { routerStore } from "super-svelte-router";

  console.log($routerStore.params); // => { id: "100" }
</script>

<h1>id is {$routerStore.params.id}</h1>

Lazy loaded routes

to use a lazy route you set lazyLoad.component to a function that returns a dynamic import for component

you muse setup rollup first see Setting up rollup for code splitting

if you use this module before v1.5.0 see this note

example:

[
  ...
  {
    path: "/lazy",
    // or lazy with params
    path: "/lazy/:id",
    component: () => import("./lazy.svelte"),
    lazyLoad: true
  }
  ...
]

loading

loading is an option to display a component while the lazy-loaded component is loading or failed loading

if you want to set a default loading component see defaultLoading

routerStore value will have these properties:

  • loadingStatus a string that represents the status of loading if pending component is still loading if error loading failed
  • error (optional) represents an error happened while loading component
  • params Loading component have access to params

example:

[
  ...
  {
    path: "/lazy",
    component: () => import("./lazy.svelte"),
    loading: Loading,
    lazyLoad: true
  }
  ...
]

example for Loading component

<script>
  import { routerStore } from "super-svelte-router";
</script>

<h1>
  {#if $routerStore.loadingStatus === "pending"} Loading... {:else if
  $routerStore.loadingStatus === "error"} Error {/if}
</h1>

{#if $routerStore.loadingStatus === -1}
<div>error {$routerStore.error}</div>
{/if}

Protected routes

to use a protected route you set authenticator to a function that either returns a boolean or a promise that returns a boolean

the router will display the protected component only if:

  • authenticator returned a truthy value
  • authenticator returned a promise that returned a truthy value

otherwise authentication failed and it will hide the component

example:

[
  ...
  {
    path: "/protected",
    // or protected with params
    path: "/protected/:id"
    authenticator: () => {
      // some authentication logic...
      return true;
    },
    // or
    authenticator: async () => {
      // some authentication logic...
      return true;
    },
    component: Protected
  }
  ...
]

authRedirect

authRedirect is an option to redirect the user to a different route (/login for example) if authentication fails

example

[
  {
    path: "/login",
    component: Login,
  },
  {
    path: "/user-info",
    component: UserInfo,
    authenticator: () => {
      /* some authentication logic... */
    },
    // redirects the user to "/login" if he is not logged in
    authRedirect: "/login",
  },
];

authComponent

authComponent is an an option to display a component if authentication failed or pending

if you want to set a default authComponent see defaultAuthComponent

the router will pass the following props:

  • authStatus a string that represents the status of authentication if pending authenticator returned a promise and it's pending if fail authentication failed if error authenticator returned a promise and it reject
  • error (optional) represents an error if authenticator returned a promise and it reject
  • params Auth component have access to params

example

<script>
  import { routerStore } from "super-svelte-router";
</script>

<h1>
  {#if $routerStore.authStatus === "pending"} Checking if you authenticated
  {:else if $routerStore.authStatus === "fail"} Sorry, you are NOT authenticated
  {:else if $routerStore.authStatus === "error"} Sorry, Unknown error happened
  {/if}
</h1>

Layout routes

layout routes is to create a layouts that wraps some other routes

layout

layout could be a number or true if number that means the layout should be applied for the next layout value of routes

if true that layout will be applied for the routes next it unless another layout overwrite it

example

[
  {
    layout: 1,
    component: Layout1
  },
  {
    // Layout1 WILL be applied here
    path: "/example1",
    component: SomeComponent
  },
  {
    // Layout1 WILL NOT be applied here
    // 'cause it only convert it's 1 next item(s)
    path: "/example2",
    component: SomeComponent
  },
  {
    layout: true,
    component: Layout2
  },
  {
    // Layout2 WILL be applied here
    path: "/example3",
    component: SomeComponent
  },
  {
    // Layout2 WILL be applied here
    // 'cause it will continue to convert routes until another layout overwrites it
    path: "/example4",
    component: SomeComponent
  },
  {
    layout: true,
    component: Layout3
  }
  {
    // Layout3 WILL be applied here
    // and Layout2 WILL NOT
    // 'cause Layout3 overwrited Layout2
    path: "/example5",
    component: SomeComponent
  },
  {
    layout: 1,
    component: Layout4
  },
  {
    // Layout3 WILL NOT be applied here
    // 'cause Layout4 overwrited Layout3
    path: "/example6",
    component: SomeComponent
  },
]

writing Layouts

example

<script>
  // all the other $routerStore properties is still accessible via props
  export let params;
</script>

<h1>I'm Layout</h1>
<div>
  <slot />
</div>

<style>
  div {
    border: 2px solid black;
    padding: 20px;
  }
</style>

Metadata

metadata is an object that contains some metadata for the router

[
  {
    metadata: true,
    defaultLoading: loading,
    defaultAuthComponent: Auth,
  },
];

defaultLoading

if loading is not set the routes will use it as a replacement

defaultAuthComponent

if authComponent is not set will use it as a replacement

Component

if you want to have a component being in App.svelte instead of having a hole file for it use Component

Component takes a prop called name to identify it

to use a Component set component to the Component's name

you could also set authComponent and loading to the Component's name

you could access every thing on routerStore via slot props

example:

<script>
  import { Router, Component } from "super-svelte-router";

  const routes = [
    {
      path: "/",
      component: "main",
    },
    {
      path: "/article/:id",
      component: "article",
    },
  ];
</script>

<Router {routes}>
  <Component name="main">
    <h1>This is the main page</h1>
  </Component>
  <Component name="article" let:params>
    <h1>This is article {params.id}</h1>
  </Component>
</Router>

isActive

if you want to check if a route is use isActive

isActive is a derived store the it's value is the function

that you pass the pathname of route you want to check if it's active

example:

<script>
  import { isActive } from "super-svelte-router";
</script>

<h1 class:red={$isActive("/")}>I'm Red if route is /</h1>

<style>
  .red { color: red }
</style>

redirect

use routerStore.redirect instead

redirect is function to redirect programmatically

NOTE: do not use full urls this function only works with pathname(s)

import { redirect } from "super-svelte-router";

redirect("/endpoint");
// replace instead of push
redirect("/endpoint", true);

link

link is an action for redirecting

<script>
  import { link } from "super-svelte-router";
</script>

<a href="/hello" use:link>/hello</a>

<!-- or (not recommended) -->

<a use:link="/hello">/hello</a>

linkHandler

use link instead

linkHandler is a function that handles clicking on a link (a tag)

<script>
  import { linkHandler } from "super-svelte-router";

  function handler(e) {
    linkHandler(e);
    // your code...
  }
</script>

<!-- if what you is only redirecting -->
<a href="/hello" on:click="{linkHandler}">/hello</a>
<!-- or -->
<a href="/hello" on:click="{handler}">/hello</a>

Notes

lazy-loaded routes deprecated format

since v1.5.0 lazy-loaded routes format changed and it will still be supported until v2.0.0

deprecated (old) format:

// deprecated
[
  {
    path: "<path>",
    lazyLoad: {
      component: () => import("<component-path>"),
      loading: LoadingComponent, // (optional)
    },
  },
];

current format:

[
  {
    path: "<path>",
    component: () => import("<component-path>"),
    loading: LoadingComponent, // (optional)
    lazyLoad: true,
  },
];

Setting up rollup for code splitting

you should set up code splitting if will use lazy loading

in rollup.config.js

export default {
  ...
  output: {
    sourcemap: true,
    // change format from iffe to es
    format: "es",
    name: "app",
    dir: "public/build",
  },
  ...
}

in public/index.html

<html>
  <head>
    ...
    <!-- add type="module" to script tag -->
    <script src="build/main.js" type="module"></script>
    ...
  </head>
  ...
</html>