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

nav-spa

v1.0.1

Published

Give you SPA normal URL-based state navigation

Downloads

4

Readme

nav-spa

NPM version

This code makes URL navigation in your SPA look just like classic HATEOAS websites, where the URL tells people what's going on. Every state (if you want) can be bookmarked, shared, and even edited by hand in the address bar. We put things in the query string by default, but if you provide parse+unparse functions, state can also be encoded using the path and/or hash.

Alternatives include more established options like react-router-redux, or using architectures like service-workers to get SPA performance, without actually being a SPA. This seemed simpler to me.


walkthru of one example

There are currently some examples, running on github pages. The simplest ('colors') is something like:

const nav = require('nav-spa')

nav.on('change-color', ({key, oldValue, newValue}) => {
  console.log('Nav-state property %o changed value from %o to %o',
              key, oldValue, newValue)
  
  if (!newValue) newValue = 'white'
  document.getElementById('test').style.backgroundColor = newValue
  document.title = `Hello in ${newValue}`
})

The state-changing navigation in this case is set-up by HTML like this:

      <a data-link-to-state="{color: 'green'}">green</a>
      <a data-link-to-state="{color: 'yellow'}">yellow</a>

This module looks for data-link-to-state attributes and adds the right href to get us to that state. The state is a JS expression which is eval'd to produce a state overlay object. And properties not mentioned in the overlay remain unchanged; set them to null or '' to remove them. They're always strings, so for our purposes '' === null == undefined. (Actually, you can provide a non-string and we'll JSON.stringify it for you, but it's always handed back to you as a string.) If your expression evals to function, it's called, passing it the current state, and letting it return the new state.

You can get that URL manually with nav.link(...) or go ahead and jump there, perhaps in an onclick handler, with nav.jump(...). The .jump function has an option to skip putting it in browser history.

The module also sets some CSS classes on the links, so you can show users which of the states they are currently in. It shouldn't matter how they got to that state.

The "motion" example shows you can even change the url state at the browser frame rate. Seems to work okay, about as fast as that animation done without this library (see cheating.html in the same directory to compare.). For that example, we don't put the state in the browser history. (Imagine clicking back through your history, one animation frame at a time!)

Custom Paths

By default we store all the state in query parameters. You can (and probable should) provide functions to map some state properties into the pathname (and/or hash).

If you store state in the pathname, your web server will have to serve up this SPA for all those URLs (but still let your CSS and JS files through). You also need to include a link.rel=start to the one that's the starting empty state.

Example "path" shows this in action, modifying "colors" by adding this code:

nav.customPath = { parse, unparse }

function parse (path) {
  path = path.slice(1) // skip the leading slash
  if (path === '') return { }
  if (/^\w+$/.test(path)) return { color: path }
  return 'NotFound'
}

function unparse (state) {
  if (state.color) return '/' + state.color
  return '/'
}

Your parse function takes a path and returns an object like { prop: value, prop2: value2, ... } with whatever state it gleaned. It returns the magic string 'NotFound' if it can't deal with this. In practice that NotFound flag is used to limit what URLs we intercept clicks on.

Your unparse function takes a state object, like what parse produced, and returns string which encodes some or all of that state.

This module automatically detects when state is encoded in a string and then skips encoding it in the query parameters. (It does this by calling your parse function on the string to see what will be able to extracted. It gives errors on the console if it detects a situation where parse and unparse are not acting as inverse functions of each other.)