@webstd-ui/router
v0.2.0
Published
A framework-agnostic client-side router built on @remix-run/fetch-router and @remix-run/events
Maintainers
Readme
@webstd-ui/router
A framework-agnostic client-side router built on @remix-run/fetch-router and @remix-run/events. This package provides a generic routing solution that works with any rendering library or framework.
Features
- Framework Agnostic: Works with any UI library (Remix, Preact, Solid, Lit, vanilla JS, etc.)
- Type-Safe: Full TypeScript support with comprehensive type definitions
- Event-Driven: Built on
@remix-run/eventsfor reactive updates - Navigation States: Track loading, submitting, and idle states
- Form Handling: Automatic interception of
<form>submissions - Link Interception: Handles
<a>clicks for seamless SPA navigation - Optimistic UI: Built-in support for optimistic updates
- Redirects: Server-style redirects with Response objects
- History Management: Integrated with browser History API for Safari and Firefox compatibility
Installation
pnpm add @webstd-ui/routerBasic Usage
import { Router } from "@webstd-ui/router";
import { route } from "@remix-run/fetch-router";
import { events } from "@remix-run/events";
// Create a router instance
const router = new Router();
// Define routes
const routes = route({
home: "/",
about: "/about",
contact: { method: "POST", pattern: "/contact" },
});
// Map routes to handlers
router.map(routes, {
async home() {
return `<h1>Home Page</h1>`;
},
async about() {
return `<h1>About Page</h1>`;
},
async contact({ formData }) {
// Handle form submission
const name = formData.get('name') as string;
return `<p>Thanks, ${name}!</p>`;
},
});
// Listen for updates
events(router, Router.update(() => {
// Re-render your UI
render(router.outlet);
}));
// Programmatic navigation
await router.navigate("/about");API Reference
Router Class
Properties
location: Current browser location after successful navigationnavigating: Navigation state object withtoandfrominformationoutlet: The rendered content from the matched route handlerstorage: Per-request storage shared across route handlers
Methods
map(routes, handlers): Register routes and their handlersnavigate(to, options): Programmatically navigate to a pathsubmit(target, options): Submit form data to a routeisActive(path, exact): Check if a path is currently activeisPending(path, exact): Check if a path is pending navigationoptimistic(handler, options): Wrap a handler with optimistic UI support
Events
Router.update: Fires whenever router state changes (navigation, loading, etc.)
Route Handlers
Route handlers receive a context object with:
// GET requests
{
params: Record<string, string>,
method: 'GET',
url: URL,
storage: AppStorage
}
// POST/PUT/DELETE requests
{
params: Record<string, string>,
method: FormMethod,
formData: FormData,
url: URL,
storage: AppStorage
}Handlers can return:
- Renderable content (HTML string, JSX, VNode, etc.)
Responseobject with redirects or JSONnullfor no content
Examples
See the examples directory for complete applications:
- Contacts - Contact management with CRUD operations
- Blog - Blog application
- Tasks - Task management with async operations
Development
To start the development server:
- Install Mise
- Run:
mise install
mise run :dev