@wroud/navigation

0.1.1 • Public • Published

@wroud/navigation

ESM-only package NPM version

@wroud/navigation is a flexible, pattern-matching navigation system for JavaScript applications. It provides a framework-agnostic routing solution with powerful pattern matching capabilities, browser integration, and navigation state management.

Features

  • Pattern-based Routing: Built-in support for static routes, parameter segments (/users/:id), and wildcard patterns (/files/:path*).
  • Framework Agnostic: Works with any JavaScript framework or vanilla JS.
  • Type Safety: Written in TypeScript with full type inference for route parameters.
  • Navigation History: Built-in navigation history management.
  • Browser Integration: Optional browser URL synchronization.
  • Extensible: Create custom navigation implementations for any environment.
  • Pure ESM package

Installation

Install via npm:

npm install @wroud/navigation

Install via yarn:

yarn add @wroud/navigation

Documentation

For detailed usage and API reference, visit the documentation site.

Examples

Basic Usage

import { Navigation, Router } from "@wroud/navigation";

// Create a router with default settings
const router = new Router();

// Add routes
router.addRoute({ id: "/" });
router.addRoute({ id: "/users" });
router.addRoute({ id: "/users/:id" });

// Create a navigation instance with the router
const navigation = new Navigation(router);

// Navigate to a route
await navigation.navigate({ id: "/users/:id", params: { id: "123" } });

// Get current route state
const currentState = navigation.getState();
console.log(currentState); // { id: "/users/:id", params: { id: "123" } }

// Go back to previous route
await navigation.goBack();

Using Pattern Matching

import { Navigation, Router, TriePatternMatching } from "@wroud/navigation";

// Create a router with pattern matching
const router = new Router({
  matcher: new TriePatternMatching({ trailingSlash: false })
});

// Add routes
router.addRoute({ id: "/" });
router.addRoute({ id: "/app" });
router.addRoute({ id: "/app/users" });
router.addRoute({ id: "/app/users/:id" });

// Create a navigation instance
const navigation = new Navigation(router);

// Match a URL to a route
const match = router.matchUrl("/app/users/123");
console.log(match); // { id: "/app/users/:id", params: { id: "123" } }

// Build a URL from a route and parameters
const url = router.buildUrl("/app/users/:id", { id: "456" });
console.log(url); // "/app/users/456"

// Navigate using the pattern matching
await navigation.navigate(router.matchUrl("/app/users/789"));

Browser Integration

import { Navigation, Router, TriePatternMatching } from "@wroud/navigation";
import { BrowserNavigation } from "@wroud/navigation/browser";

// Create a router with pattern matching
const router = new Router({
  matcher: new TriePatternMatching({
    trailingSlash: true,
    base: '/app' // Base path for the application
  })
});

// Add routes
router.addRoute({ id: "/" });
router.addRoute({ id: "/products" });
router.addRoute({ id: "/products/:id" });
router.addRoute({ id: "/blog/:year/:month/:slug" });

// Create a navigation instance
const navigation = new Navigation(router);

// Add a navigation listener for all navigation events
// including the initial navigation
const unsubscribe = navigation.addListener((type, from, to) => {
  if (type === "navigate" && !from) {
    console.log("Initial navigation:", to);
  } else {
    console.log(`Navigation: ${type}`, { from, to });
  }
});

// Create a browser navigation instance
const browserNavigation = new BrowserNavigation(navigation);

// Initialize browser navigation by registering routes
// This will sync with the browser's URL and history
await browserNavigation.registerRoutes();

// Navigate - this will update the browser URL
await navigation.navigate({ 
  id: "/products/:id", 
  params: { id: "123" } 
});

// Browser URL is now /app/products/123

// Later, remove the listener
unsubscribe();

Protected Routes with Navigation Guards

import { Navigation, Router } from "@wroud/navigation";

// Create a router
const router = new Router();

// Add routes with navigation guards
router.addRoute({ 
  id: "/", 
});

router.addRoute({ 
  id: "/dashboard", 
  // Check if user is authenticated before activating this route
  canActivate: (to, from) => {
    return isAuthenticated(); // Your authentication check
  }
});

router.addRoute({ 
  id: "/editor/:documentId", 
  // Check if user has permission to edit this document
  canActivate: async (to, from) => {
    if (!to.params.documentId) return false;
    return await hasEditPermission(to.params.documentId);
  },
  // Ask for confirmation before navigating away
  canDeactivate: (to, from) => {
    return confirm("Discard unsaved changes?");
  }
});

const navigation = new Navigation(router);

// This will fail if not authenticated
await navigation.navigate({ id: "/dashboard", params: {} });

Changelog

All notable changes to this project will be documented in the CHANGELOG file.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Package Sidebar

Install

npm i @wroud/navigation

Homepage

wroud.dev/

Weekly Downloads

72

Version

0.1.1

License

MIT

Unpacked Size

109 kB

Total Files

64

Last publish

Collaborators

  • wroud