npm package: @sirou/react
Description: React adapter for Sirou — type-safe routing hooks, components, and DevTools
Author: Sirou Contributors
Latest version: 1.1.3

# @sirou/react

The React adapter for Sirou. Provides a context provider, hooks, components, and DevTools for building type-safe, data-driven React applications.

## Installation

```bash
npm install @sirou/react @sirou/core react-router-dom
```

---

## Setup

Wrap your app with `SirouRouterProvider` inside a `BrowserRouter`:

```tsx
// src/main.tsx
import { BrowserRouter } from "react-router-dom";
import { SirouRouterProvider } from "@sirou/react";
import { routes } from "./routes";

function App() {
  return (
    <BrowserRouter>
      <SirouRouterProvider config={routes}>
        <YourApp />
      </SirouRouterProvider>
    </BrowserRouter>
  );
}
```

---

## API Reference

### `SirouRouterProvider`

The context provider that initializes the Sirou router and makes it available to all child components.

**Props:**

| Prop       | Type          | Description                             |
| ---------- | ------------- | --------------------------------------- |
| `config`   | `RouteConfig` | Your route schema from `defineRoutes()` |
| `children` | `ReactNode`   | Your application tree                   |

---

### Hooks

#### `useSirouRouter<T>()`

Returns the fully typed router instance. Pass `typeof routes` as the generic to get type-safe navigation.

```tsx
import { useSirouRouter } from "@sirou/react";
import { routes } from "./routes";

const router = useSirouRouter<typeof routes>();

// TypeScript knows 'user' requires { id: string }
router.go("user", { id: "abc" });

// Build a URL without navigating
const url = router.build("user", { id: "abc" }); // => '/user/abc'
```

---

#### `useRouteParams<T>(routeName)`

Returns the typed params for the specified route. Throws if called outside the correct route context.

```tsx
import { useRouteParams } from "@sirou/react";
import { routes } from "./routes";

// Inside a component rendered at /user/:id
const { id } = useRouteParams<typeof routes>("user");
// id is typed as `string`
```

---

#### `useRouteData<T>()`

Returns the pre-fetched data from the current route's `loader`. Returns `undefined` while loading.

```tsx
import { useRouteData } from "@sirou/react";

type Product = { name: string; price: string };

function ProductPage() {
  const product = useRouteData<Product>();

  if (!product) return <p>Loading...</p>;
  return (
    <h1>
      {product.name} — {product.price}
    </h1>
  );
}
```

---

#### `useSirouRoute()`

Returns the `RouteInfo` object for the currently active route, updating reactively on navigation.

```tsx
import { useSirouRoute } from "@sirou/react";

const route = useSirouRoute();
console.log(route?.name); // e.g., 'products.details'
console.log(route?.params); // e.g., { productId: 'abc' }
console.log(route?.meta); // e.g., { title: 'Product Details' }
```

---

#### `useRouteTitle(fallback?)`

Automatically syncs `document.title` with the `meta.title` of the current route.

```tsx
// In your root layout
useRouteTitle("My App"); // Fallback if route has no title
```

---

#### `useRouteAnalytics(callback, deps?)`

Fires a callback on every route change. Perfect for analytics integrations.

```tsx
useRouteAnalytics((routeInfo) => {
  window.gtag("event", "page_view", {
    page_title: routeInfo.meta.title,
    page_path: routeInfo.path,
  });
});
```

---

#### `useBreadcrumbs()`

Returns an array of breadcrumb objects for the current path.

```tsx
const crumbs = useBreadcrumbs();
// => [{ label: 'Products', path: '/products' }, { label: 'Details', path: '/products/abc' }]

return (
  <nav>
    {crumbs.map((c) => (
      <a key={c.path} href={c.path}>
        {c.label}
      </a>
    ))}
  </nav>
);
```

---

### Components

#### `SirouLink`

A type-safe link component. TypeScript will error if you pass incorrect params.

```tsx
import { SirouLink } from "@sirou/react";

<SirouLink to="user" params={{ id: "abc" }}>
  View Profile
</SirouLink>;
```

---

#### `SirouGuard`

A component that checks guards before rendering its children via `<Outlet />`. Use it in your route configuration.

```tsx
import { SirouGuard } from '@sirou/react';

// In your React Router route config:
{
  path: '/dashboard',
  element: <SirouGuard routeName="dashboard" />,
  children: [
    { index: true, element: <DashboardPage /> },
  ],
}
```

---

#### `SirouDevTools`

A floating panel for real-time debugging of route state. Add it once at the root of your app.

```tsx
import { SirouDevTools } from "@sirou/react";

function App() {
  return (
    <>
      <YourApp />
      {process.env.NODE_ENV === "development" && <SirouDevTools />}
    </>
  );
}
```

**Features:**

- **Overview tab**: Current route name and path
- **History tab**: Full navigation history
- **Params tab**: Current route params and query
- **Meta tab**: Route metadata object

---

## License

MIT