diff --git a/README.md b/README.md
index 1c32bac..0b7277d 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,7 @@
# Contection
+Contection is a state management library that extends React Context API with fine-grained subscriptions and computed values.
-A state management library that extends React Context API with fine-grained subscriptions and computed values. Built on React hooks and `useSyncExternalStore` to provide efficient, granular state updates.
-
-[npm](https://www.npmjs.com/package/contection) • [demo](https://www.contection.dev/)
-
-## Features
-
-- **React-Context-like API** - Extends the standard React Context pattern with hooks and components
-- **Granular Subscriptions** - Built on `useSyncExternalStore` for efficient, per-key subscription updates
-- **Selective Re-renders** - Subscribe to specific store keys to minimize component re-renders
-- **Computed Values** - Transform and derive state with mutation functions
-- **Additional Modules** - Extended functionality through specialized modules like [viewport management](https://github.com/alexdln/contection/tree/main/modules/viewport) and [top-layer management](https://github.com/alexdln/contection/tree/main/modules/top-layer)
-- **Storage adapters** - Automatic state persistence with optional validation and selective key persistence via [storage adapter](https://github.com/alexdln/contection/tree/main/adapters/storage) (localStorage/sessionStorage) and [next-cookie adapter](https://github.com/alexdln/contection/tree/main/adapters/next-cookie) (cookies with SSR support)
+[GitHub](https://github.com/alexdln/contection) • [NPM](https://www.npmjs.com/package/contection) • [Documentation](https://www.contection.dev/)
## Installation
@@ -23,6 +13,11 @@ yarn add contection
pnpm add contection
```
+## Getting Started
+
+1. [Getting Started](./docs/01-getting-started/README.md) - Installation and features
+2. [Quick Start](./docs/01-getting-started/quick-start.md) - Get up and running in minutes
+
## Quick Start
### 1. Create a Store
@@ -160,608 +155,12 @@ function UserProfile() {
}
```
-## Advanced Usage
-
-### Updating the Store
-
-Use `useStoreReducer` to get the store state and setStore function. Unlike `useStore`, the store returned from `useStoreReducer` does not trigger re-renders when it changes, making it useful for reading values without subscribing to updates:
-
-```tsx
-import { useStoreReducer } from "contection";
-
-function Counter() {
- const [store, setStore] = useStoreReducer(AppStore);
-
- return (
-
- alert(store.count)}>Show count
- setStore({ count: store.count + 1 })}>
- Increment
-
- setStore((prev) => ({ count: prev.count - 1 }))}>
- Decrement
-
-
- );
-}
-```
-
-### Selective Subscriptions
-
-Subscribe to specific store keys to limit re-render scope:
-
-```tsx
-// Component re-renders only when 'count' key changes
-const { count } = useStore(AppStore, { keys: ["count"] });
-
-// Component re-renders only when 'user' or 'theme' keys change
-const data = useStore(AppStore, { keys: ["user", "theme"] });
-```
-
-### Conditional Subscriptions
-
-Use the `enabled` option to conditionally enable or disable subscriptions. This is useful for tracking changes only under specific conditions, such as user roles, value ranges, or page contexts. When the `enabled` value changes, the hook will automatically resubscribe.
-
-The `enabled` option accepts:
-
-- `"always"` (default) - Subscription is always active
-- `"never"` - Subscription is never active
-- `"after-hydration"` - Subscription is active only after the component has mounted (useful for SSR/hydration scenarios)
-- A function `(store: Store) => boolean` - Dynamically determines if the subscription should be active based on the current store state
-
-```tsx
-// Track account changes only if user is an admin
-const { account } = useStore(AppStore, {
- keys: ["account"],
- enabled: (store) => store.user.role === "admin",
-});
-
-// Track numbers only when their values are less than 10
-const { count } = useStore(AppStore, {
- keys: ["count"],
- enabled: (store) => store.count < 10,
-});
-
-// Disable subscription completely
-const { notifications } = useStore(AppStore, {
- keys: ["notifications"],
- enabled: "never",
-});
-
-// Enable subscription only after hydration (useful for SSR)
-const { user } = useStore(AppStore, {
- keys: ["user"],
- enabled: "after-hydration",
-});
-```
-
-### Computed Values
-
-Derive computed state from store values using mutation functions:
-
-```tsx
-// Mutation calls only when 'user' key change
-// Component re-renders only when mutation result change
-const userInitials = useStore(AppStore, {
- keys: ["user"],
- mutation: (user) => {
- const names = user.name.split(" ");
- return names
- .map((n) => n[0])
- .join("")
- .toUpperCase();
- },
-});
-
-return userInitials; // JD
-```
-
-#### Mutation Function Parameters
-
-The mutation function receives three parameters:
-
-1. **`newStore`** - The current store state (or selected keys if `keys` option is used)
-2. **`prevStore`** - The previous store state (or selected keys). `undefined` on the first call
-3. **`prevMutatedStore`** - The previous result of the mutation function. `undefined` on the first call
-
-Use `prevStore` and `prevMutatedStore` to implement incremental updates, compare values, or optimize computations:
-
-```tsx
-// Track count changes and compute differences
-const countChange = useStore(AppStore, {
- keys: ["count"],
- mutation: (newStore, prevStore, prevMutatedStore) => {
- if (!prevStore) {
- return { current: newStore.count, change: 0 };
- }
- return {
- current: newStore.count,
- change: newStore.count - prevStore.count,
- };
- },
-});
-
-// Incremental list updates using previous computed value
-const filteredItems = useStore(AppStore, {
- keys: ["items", "filter"],
- mutation: (newStore, prevStore, prevMutatedStore) => {
- // Reuse previous result if filter hasn't changed
- if (prevMutatedStore && prevStore?.filter === newStore.filter) {
- return prevMutatedStore;
- }
- return newStore.items.filter((item) => item.includes(newStore.filter));
- },
-});
-```
-
-### Full Store Access
-
-Access the entire store when needed with full re-render cycle:
-
-```tsx
-const store = useStore(AppStore);
-
-// Or with Consumer
-
- {(store) => (
-
-
User: {store.user.name}
-
Count: {store.count}
-
Theme: {store.theme}
-
- )}
- ;
-```
-
-### Imperative Subscriptions
-
-Use `subscribe` and `unsubscribe` for imperative subscriptions outside React's render cycle. Useful for side effects, logging, or external system integrations:
-
-```tsx
-import { useStoreReducer } from "contection";
-import { useEffect } from "react";
-
-function AnalyticsTracker() {
- const [store, setStore, subscribe, unsubscribe] = useStoreReducer(AppStore);
-
- useEffect(() => {
- const unsubscribeUser = subscribe("user", (user) => {
- analytics.track("user_updated", { userId: user.email });
- });
-
- const unsubscribeTheme = subscribe("theme", (theme) => {
- document.documentElement.setAttribute("data-theme", theme);
- });
-
- // Cleanup subscriptions on unmount
- return () => {
- unsubscribeUser();
- unsubscribeTheme();
- };
- }, [subscribe]);
-
- return null;
-}
-```
-
-You can also use `subscribe` in a `ref` callback to set up subscriptions when you have direct access to a DOM node. This pattern is useful for imperative DOM manipulation that needs to react to store changes:
+## Documentation
-```tsx
-const Header = () => {
- const [store, , subscribe] = useStoreReducer(AppStore);
- return (
-
- {/* ... */}
-
- subscribe("device", (device) => {
- node?.setAttribute("aria-hidden", String(device === "desktop"));
- })
- }
- >
- {/* ... */}
-
-
- );
-};
-```
-
-### Lifecycle Hooks
-
-Lifecycle hooks allow you to perform initialization and cleanup operations at different stages of the store's lifecycle. They are passed as options to `createStore`:
-
-```tsx
-const AppStore = createStore(
- {
- user: { name: "", email: "" },
- count: 0,
- theme: "light",
- },
- {
- lifecycleHooks: {
- storeWillMount: (store, setStore, subscribe, unsubscribe) => {
- // Initialization logic
- // Return cleanup function if needed
- },
- storeDidMount: (store, setStore, subscribe, unsubscribe) => {
- // Post-mount logic
- // Return cleanup function if needed
- },
- storeWillUnmount: (store) => {
- // Synchronous cleanup before unmount
- },
- storeWillUnmountAsync: (store) => {
- // Asynchronous cleanup during unmount
- },
- },
- }
-);
-```
-
-You can also pass `options` to individual Provider instances to customize lifecycle hooks per instance. Provider options completely override options passed to `createStore`, allowing you to disable or customize settings for specific Provider instances. See [Provider-Level Lifecycle Hooks](#provider-level-lifecycle-hooks) for details.
-
-#### `storeWillMount`
-
-**Recommended for:** Single Page Applications (SPA), background key detection or subscriptions.
-
-Runs synchronously during render, **before** the store is fully initialized. This hook is ideal for:
-
-- Setting up background subscriptions that won't cause hydration errors
-- Initializing client-only state (e.g., localStorage, sessionStorage) in SPA
-- Detecting and subscribing to keys for custom logic
-
-**Important:** In React Strict Mode (development), `storeWillMount` is called **twice**. Return a cleanup function to properly handle subscriptions and prevent memory leaks:
-
-```tsx
-const AppStore = createStore(
- {
- user: { name: "", email: "" },
- count: 0,
- theme: "light",
- lastVisit: null as Date | null,
- },
- {
- lifecycleHooks: {
- storeWillMount: (store, setStore, subscribe) => {
- const savedTheme = localStorage.getItem("theme");
- if (savedTheme) {
- setStore({ theme: savedTheme as "light" | "dark" });
- }
- const unsubscribe = subscribe("count", (count) => {
- console.log("Count changed:", count);
- });
- return unsubscribe;
- },
- },
- }
-);
-```
-
-#### `storeDidMount`
-
-**Recommended for:** Fullstack solutions (Next.js, Remix, etc.) to avoid hydration errors.
-
-Runs asynchronously **after** the component mounts, making it safe for operations that might differ between server and client. This hook is ideal for:
-
-- Initializing state that depends on browser APIs
-- Fetching data that should only happen on the client
-- Setting up subscriptions that need to match server-rendered content
-
-```tsx
-const AppStore = createStore(
- {
- user: { name: "", email: "" },
- count: 0,
- theme: "light",
- windowWidth: 0,
- },
- {
- lifecycleHooks: {
- storeDidMount: (store, setStore, subscribe) => {
- setStore({ windowWidth: window.innerWidth });
-
- const handleResize = () => {
- setStore({ windowWidth: window.innerWidth });
- };
- window.addEventListener("resize", handleResize);
-
- // Return cleanup function
- return () => {
- window.removeEventListener("resize", handleResize);
- };
- },
- },
- }
-);
-```
-
-#### `storeWillUnmount`
-
-**Recommended for:** Synchronous cleanup operations that must complete before the component unmounts.
-
-Runs synchronously in `useLayoutEffect` cleanup, **before** the component unmounts. This hook is ideal for:
-
-- Synchronous cleanup that must happen before unmount
-- Cleanup operations that should block unmounting
-
-**Note:** This hook runs synchronously and should not perform heavy operations that could block the UI.
-
-```tsx
-const AppStore = createStore(
- {
- user: { name: "", email: "" },
- count: 0,
- theme: "light",
- },
- {
- lifecycleHooks: {
- storeWillUnmount: (store) => {
- if (store.count > 0) {
- localStorage.setItem("lastCount", String(store.count));
- }
- },
- },
- }
-);
-```
-
-#### `storeWillUnmountAsync`
-
-**Recommended for:** Asynchronous cleanup operations that can run during unmount.
-
-Runs asynchronously in `useEffect` cleanup, **during** component unmount. This hook is ideal for:
-
-- Asynchronous cleanup operations (API calls, timers, etc.)
-- Cleanup that doesn't need to block unmounting
-- Final data synchronization that can happen asynchronously
-
-**Execution Order:** This hook runs after `storeDidMount` cleanup (if provided) and after `storeWillMount` cleanup (if provided).
-
-```tsx
-const AppStore = createStore(
- {
- user: { name: "", email: "" },
- count: 0,
- theme: "light",
- },
- {
- lifecycleHooks: {
- storeDidMount: (store, setStore, subscribe, unsubscribe) => {
- const ws = new WebSocket("wss://example.com");
-
- return () => {
- ws.close();
- };
- },
- storeWillUnmountAsync: (store) => {
- fetch("https://example.com/api/sync-state", {
- method: "POST",
- body: JSON.stringify(store),
- }).catch(console.error);
- },
- },
- }
-);
-```
-
-### Lifecycle Execution Order
-
-1. **Mount Phase:**
-
-- `storeWillMount` (synchronous, during render) - called twice in React Strict Mode;
-- `storeDidMount` (asynchronous, after mount);
-
-2. **Unmount Phase:**
-
-- `storeWillUnmount` (synchronous, before unmount);
-- `storeWillMount` cleanup (if returned) - called an additional time in React Strict Mode between `storeWillMount` calls;
-- `storeDidMount` cleanup (if returned);
-- `storeWillUnmountAsync` (asynchronous, during unmount).
-
-### Provider-Level Lifecycle Hooks
-
-While lifecycle hooks can be passed to `createStore`, they are shared across all Provider instances and initialized outside React's scope. For per-instance customization, you can pass `options` directly to individual Provider components.
-
-**Provider options completely override options from `createStore`**, allowing you to:
-
-- Disable lifecycle hooks for specific instances
-- Customize hooks per Provider instance
-- Use React state/props in lifecycle hooks (since they're initialized within React scope)
-
-```tsx
-const sharedOptions = {
- lifecycleHooks: {
- storeDidMount: (store, setStore) => {
- console.log("Shared initialization");
- },
- },
-};
-
-const AppStore = createStore(
- {
- user: { name: "", email: "" },
- count: 0,
- theme: "light",
- },
- sharedOptions
-);
-
-function App() {
- return (
- <>
- {/* Uses shared options from createStore */}
-
-
-
- {/* Overrides with Provider-specific options */}
- {
- setStore({ count: 100 });
- },
- },
- }}
- >
-
-
- {/* Disables lifecycle hooks */}
-
-
-
- >
- );
-}
-```
-
-### Store Validation
-
-The `validate` option allows you to validate store data before it's applied. This is useful for ensuring data integrity and preventing invalid state updates.
-
-The validation function receives the store data (or partial update) and should return a truthy value if valid, or a falsy value if invalid:
-
-- **Invalid initial data** - Throws an error when the Provider is created
-- **Invalid updates** - Silently rejected (the update is not applied)
-
-```tsx
-import { createStore, useStoreReducer } from "contection";
-import { z } from "zod";
-
-const schema = z.object({
- user: z.object({
- name: z.string().min(1),
- email: z.string().email(),
- }),
- count: z.number().int().min(0),
-});
-
-const AppStore = createStore(
- {
- user: { name: "John", email: "john@example.com" },
- count: 0,
- },
- {
- validate: (data) => {
- const partialSchema = schema.pick(
- Object.fromEntries(Object.keys(data).map((k) => [k, true]))
- );
- const result = partialSchema.safeParse(data);
- return result.success ? result.data : false;
- },
- }
-);
-
-
- {/* Error: Invalid initial store data */}
- ;
-
-// Invalid updates are silently rejected
-function Counter() {
- const [store, setStore] = useStoreReducer(AppStore);
-
- // This update will be rejected silently
- setStore({ count: -1 });
-
- // This update will be applied
- setStore({ count: 1 });
-}
-```
-
-## API Reference
-
-### `createStore(initialData: Store, options?)`
-
-Creates a new store instance with Provider and Consumer components.
-
-**Parameters:**
-
-- `initialData: Store` - Initial state for the store
-- `options?: CreateStoreOptions` (optional):
- - `lifecycleHooks?: { storeWillMount?, storeDidMount?, storeWillUnmount?, storeWillUnmountAsync? }` - Lifecycle hooks for store initialization and cleanup
- - `validate?: (data: any) => boolean | null | never | undefined` - Validation function that validates store data. Returns a truthy value if valid, falsy if invalid. Invalid initial data throws an error, invalid updates are silently rejected.
-
-**Returns:**
-
-- `Provider` - React component to wrap scope
-- `Consumer` - React component for render props pattern
-- `_context` - The underlying React Context. In some cases, you can use it with the `use` hook to access the useStoreReducer data
-- `_initial` - The initial store data
-
-### `useStore(instance, options?)`
-
-Hook that subscribes to store state with optional key listening and computed value derivation.
-
-**Parameters:**
-
-- `instance` - Store instance returned from `createStore`
-- `options` (optional):
- - `keys?: string[]` - Array of store keys to subscribe to. If omitted, subscribes to all keys.
- - `mutation?: (newStore, prevStore?, prevMutatedStore?) => T` - Function to compute derived value from subscribed state. Receives:
- - `newStore` - Current store state (or selected keys if `keys` is provided)
- - `prevStore` - Previous store state (or selected keys). `undefined` on first call
- - `prevMutatedStore` - Previous result of the mutation function. `undefined` on first call
- - `enabled?: "always" | "never" | "after-hydration" | ((store: Store) => boolean)` - Condition to enable or disable the subscription. Accepts `"always"` (default), `"never"`, `"after-hydration"`, or a function `(store: Store) => boolean`. When this value changes, the hook will automatically resubscribe.
-
-**Returns:** Subscribed store data or computed value if mutation function is provided
-
-### `useStoreReducer(instance)`
-
-Hook that returns a tuple containing the store state and setStore functions.
-
-**Returns:** `[store, setStore, subscribe, unsubscribe]` tuple where:
-
-- `store` - Current store state object
-- `setStore` - Function to update store state: `(partial: Partial | (prev: Store) => Partial) => void`
-- `subscribe` - Function to subscribe to store key changes: `(key: K, listener: (value: Store[K]) => void) => () => void`. Returns an unsubscribe function.
-- `unsubscribe` - Function to unsubscribe from store key changes: `(key: K, listener: (value: Store[K]) => void) => void`
-
-### `Provider`
-
-Component that provides a scoped store instance to child components. Each Provider instance creates its own isolated store scope, similar to React Context.Provider. Components within a Provider can only access the store state from that Provider's scope.
-
-**Props:**
-
-- `children: React.ReactNode`
-- `value?: Store` - Optional initial value for this Provider's scope (defaults to store's initial data from `createStore`)
-- `options?: CreateStoreOptions` (optional):
- - `lifecycleHooks?: { storeWillMount?, storeDidMount?, storeWillUnmount?, storeWillUnmountAsync? }` - lifecycle hooks configuration. **Completely overrides** options passed to `createStore`, allowing per-instance customization. See [Lifecycle Hooks](#lifecycle-hooks) for available hooks.
- - `validate?: (data: any) => boolean | null | never | undefined` - Validation function that validates store data. Returns a truthy value if valid, falsy if invalid. Invalid initial data throws an error, invalid updates are silently rejected.
-
-**Scoping Behavior:**
-
-- `` (same as ``) instance creates a completely isolated store
-- Multiple Providers of the same store type do not share state
-- Nested Providers create nested scopes (inner Provider overrides outer Provider for its children)
-
-### `Consumer`
-
-Component that consumes the store using render props pattern.
-
-**Props:**
-
-- `children: (data) => React.ReactNode` - Render function
-- `options?: { keys?: string[], mutation?: Function, enabled?: boolean | Function }`:
- - `keys?: string[]` - Array of store keys to subscribe to. If omitted, subscribes to all keys.
- - `mutation?: (newStore, prevStore?, prevMutatedStore?) => T` - Function to compute derived value from subscribed state. Receives:
- - `newStore` - Current store state (or selected keys if `keys` is provided)
- - `prevStore` - Previous store state (or selected keys). `undefined` on first call
- - `prevMutatedStore` - Previous result of the mutation function. `undefined` on first call
- - `enabled?: "always" | "never" | "after-hydration" | ((store: Store) => boolean)` - Condition to enable or disable the subscription. Accepts `"always"` (default), `"never"`, `"after-hydration"`, or a function `(store: Store) => boolean`. When this value changes, the consumer will automatically resubscribe.
-
-## Contection modules
-
-### [contection-viewport](https://github.com/alexdln/contection/tree/main/modules/viewport)
-
-A performance-based viewport management module built on top of Contection. Provides efficient screen size tracking with granular subscriptions, memoization, and a single global resize listener.
-
-### [contection-top-layer](https://github.com/alexdln/contection/tree/main/modules/top-layer)
-
-A layer management module built on top of Contection. Provides efficient management of dialogs and upper layers with granular subscriptions, type safety, and support for isolated layers.
+- [Core Topics](./docs/02-core/README.md) - Stores, providers, hooks
+- [Advanced](./docs/03-advanced/README.md) - Lifecycle, validation, API reference, guides
+- [Modules and Adapters](./docs/04-modules/README.md) - Viewport, top-layer, storage, cookies
+- [Examples](./docs/05-examples/README.md) - Code examples and live demos
## Contection adapters
@@ -777,10 +176,8 @@ A cookie-based persistence adapter for Contection designed for Next.js applicati
The repository includes example applications demonstrating Contection's capabilities:
-- **[demo](examples/demo)** - Demonstrates fine-grained subscriptions with various optimization strategies, storage adapters for state persistence, and integration with `contection-viewport` and `contection-top-layer` modules. [Preview](https://www.contection.dev/)
-
+- **[demo](examples/demo)** - Demonstrates fine-grained subscriptions with various optimization strategies, storage adapters for state persistence, and integration with `contection-viewport` and `contection-top-layer` modules. [Preview](https://contection.dev/demo/)
- **[nextjs-bsky](examples/nextjs-bsky)** - Showcases performance improvements in Next.js applications using `cacheComponents` and a combined client-server architecture with next-cookie adapter and storage adapter for state persistence. [Preview](https://router-bsky.contection.dev/)
-
- **[react-routerjs-bsky](examples/react-routerjs-bsky)** - Showcases performance improvements in Next.js applications using `cacheComponents` and a combined client-server architecture with react-router-cookie adapter and storage adapter for state persistence. [Preview](https://router-bsky.contection.dev/)
## License
diff --git a/adapters/storage/README.md b/adapters/storage/README.md
index 64c65ea..1f40d46 100644
--- a/adapters/storage/README.md
+++ b/adapters/storage/README.md
@@ -2,7 +2,7 @@
A persistent storage adapter for [contection](https://github.com/alexdln/contection) that automatically saves and restores state to browser storage (localStorage or sessionStorage).
-[npm](https://www.npmjs.com/package/contection-storage-adapter) • [demo](https://www.contection.dev/)
+[npm](https://www.npmjs.com/package/contection-storage-adapter)
## Overview
@@ -150,8 +150,6 @@ The adapter automatically detects storage availability and gracefully degrades i
The repository includes example applications demonstrating storage adapter capabilities:
-- **[demo](examples/demo)** - Demonstrates fine-grained subscriptions with various optimization strategies, storage adapters for state persistence, and integration with `contection-viewport` and `contection-top-layer` modules.
-
- **[nextjs-bsky](examples/nextjs-bsky)** - Showcases performance improvements in Next.js applications using `cacheComponents` and a combined client-server architecture with next-cookie adapter and storage adapter for state persistence.
## License
diff --git a/docs/01-getting-started/README.md b/docs/01-getting-started/README.md
new file mode 100644
index 0000000..54d11c0
--- /dev/null
+++ b/docs/01-getting-started/README.md
@@ -0,0 +1,35 @@
+# Getting Started
+
+Contection extends React Context API with fine-grained subscriptions and computed values.
+
+## Installation
+
+```bash switcher tab="npm"
+npm install contection
+```
+
+```bash switcher tab="pnpm"
+pnpm add contection
+```
+
+```bash switcher tab="yarn"
+yarn add contection
+```
+
+```bash switcher tab="bun"
+bun add contection
+```
+
+**Requirements:** React 18+ (React 19 recommended), TypeScript 4.5+ (optional, types included)
+
+## Features
+
+- **Granular Subscriptions** - Subscribe to specific store keys
+- **Selective Re-renders** - Components update only when subscribed keys change
+- **Computed Values** - Derive state with mutation functions
+- **Type-Safe** - Full TypeScript support
+- **SSR Compatible** - Works with Next.js and other SSR frameworks
+
+## Next
+
+- [Quick Start](./quick-start.md) - Get up and running in minutes
diff --git a/docs/01-getting-started/quick-start.md b/docs/01-getting-started/quick-start.md
new file mode 100644
index 0000000..f7f60e9
--- /dev/null
+++ b/docs/01-getting-started/quick-start.md
@@ -0,0 +1,143 @@
+# Quick Start
+
+## Step 1: Create a Store
+
+```tsx filename="store.ts" switcher tab="TypeScript"
+import { createStore } from "contection";
+
+type AppStoreType = {
+ user: { name: string; email: string };
+ count: number;
+ theme: "light" | "dark";
+};
+
+const AppStore = createStore({
+ user: { name: "", email: "" },
+ count: 0,
+ theme: "light",
+});
+
+export { AppStore };
+export type { AppStoreType };
+```
+
+```js filename="store.js" switcher tab="JavaScript"
+import { createStore } from "contection";
+
+const AppStore = createStore({
+ user: { name: "", email: "" },
+ count: 0,
+ theme: "light",
+});
+
+export { AppStore };
+```
+
+## Step 2: Provide the Store
+
+```tsx filename="App.tsx" switcher tab="TypeScript"
+import { AppStore } from "./store";
+
+function App() {
+ return (
+
+
+
+ );
+}
+```
+
+```jsx filename="App.jsx" switcher tab="JavaScript"
+import { AppStore } from "./store";
+
+function App() {
+ return (
+
+
+
+ );
+}
+```
+
+Each Provider creates an isolated scope, similar to React Context.Provider.
+
+## Step 3: Use the Store
+
+### Subscribe to Specific Keys
+
+```tsx filename="Counter.tsx" switcher tab="TypeScript"
+import { useStore } from "contection";
+import { AppStore } from "./store";
+
+function Counter() {
+ // Component re-renders only when 'count' value changes
+ const { count } = useStore(AppStore, { keys: ["count"] });
+
+ return (
+
+ );
+}
+```
+
+```jsx filename="Counter.jsx" switcher tab="JavaScript"
+import { useStore } from "contection";
+import { AppStore } from "./store";
+
+function Counter() {
+ const { count } = useStore(AppStore, { keys: ["count"] });
+
+ return (
+
+ );
+}
+```
+
+### Access Nested Values
+
+```tsx filename="UserEmail.tsx" switcher tab="TypeScript"
+import { useStore } from "contection";
+import { AppStore } from "./store";
+
+function UserEmail() {
+ // Component re-renders only when 'user.email' changes
+ const email = useStore(AppStore, {
+ keys: ["user"],
+ mutation: (store) => store.user.email,
+ });
+
+ return E-mail: {email}
;
+}
+```
+
+### Update the Store
+
+```tsx filename="CounterControls.tsx" switcher tab="TypeScript"
+import { useStoreReducer } from "contection";
+import { AppStore } from "./store";
+
+function CounterControls() {
+ // useStoreReducer never triggers re-render
+ const [store, setStore] = useStoreReducer(AppStore);
+
+ return (
+
+ alert(store.count)}>Show count
+ setStore({ count: store.count + 1 })}>
+ Increment
+
+ setStore((prev) => ({ count: prev.count - 1 }))}>
+ Decrement
+
+
+ );
+}
+```
+
+## Next
+
+- [Stores and Providers](../02-core/stores-and-providers.md)
+- [Hooks](../02-core/hooks.md)
diff --git a/docs/02-core/README.md b/docs/02-core/README.md
new file mode 100644
index 0000000..cb6c442
--- /dev/null
+++ b/docs/02-core/README.md
@@ -0,0 +1,10 @@
+# Core Topics
+
+Contection provides two main primitives: **stores** for state containers and **hooks** for accessing them.
+
+Stores are created once and scoped via Providers. Unlike global state managers, each Provider maintains its own isolated state - components only see the nearest Provider's data.
+
+Hooks connect components to stores. `useStore` subscribes to specific keys and triggers re-renders; `useStoreReducer` provides state access and updates without re-renders.
+
+- [Stores and Providers](./stores-and-providers.md) - Create stores, scope with Providers, handle multiple instances
+- [Hooks](./hooks.md) - Subscribe with `useStore`, update with `useStoreReducer`, compute derived values
diff --git a/docs/02-core/hooks.md b/docs/02-core/hooks.md
new file mode 100644
index 0000000..b2a5606
--- /dev/null
+++ b/docs/02-core/hooks.md
@@ -0,0 +1,188 @@
+# Hooks
+
+## useStore
+
+Subscribes to store state and triggers re-renders when subscribed keys change.
+
+```tsx
+import { useStore } from "contection";
+
+function Counter() {
+ const { count } = useStore(AppStore, { keys: ["count"] });
+ return Count: {count}
;
+}
+```
+
+### Options
+
+#### `keys?: string[]`
+
+Keys to subscribe to. Omit for all keys.
+
+```tsx
+// Single key
+const { count } = useStore(AppStore, { keys: ["count"] });
+
+// Multiple keys - re-renders when 'user' OR 'theme' changes
+const { user, theme } = useStore(AppStore, { keys: ["user", "theme"] });
+
+// All keys - re-renders when ANY key changes
+const store = useStore(AppStore);
+```
+
+#### `mutation?: (newStore, prevStore?, prevMutatedStore?) => T`
+
+Compute derived values:
+
+```tsx
+const email = useStore(AppStore, {
+ keys: ["user"],
+ mutation: (store) => store.user.email,
+});
+
+const initials = useStore(AppStore, {
+ keys: ["user"],
+ mutation: (store) => store.user.name.split(" ").map((n) => n[0]).join("").toUpperCase(),
+});
+```
+
+**Memoization** - use previous values to avoid recomputation:
+
+```tsx
+const filtered = useStore(AppStore, {
+ keys: ["items", "filter"],
+ mutation: (newStore, prevStore, prevMutatedStore) => {
+ if (prevMutatedStore && prevStore?.filter === newStore.filter) {
+ return prevMutatedStore;
+ }
+ return newStore.items.filter((item) => item.includes(newStore.filter));
+ },
+});
+```
+
+#### `enabled?: "always" | "never" | "after-hydration" | (store) => boolean`
+
+Conditional subscription:
+
+```tsx
+// Role-based
+const { adminData } = useStore(AppStore, {
+ keys: ["adminData"],
+ enabled: (store) => store.user.role === "admin",
+});
+
+// SSR - active after mount
+const { clientData } = useStore(AppStore, {
+ keys: ["clientData"],
+ enabled: "after-hydration",
+});
+```
+
+## useStoreReducer
+
+Returns store state and update functions **without triggering re-renders**.
+
+```tsx
+import { useStoreReducer } from "contection";
+
+function Counter() {
+ const [store, setStore] = useStoreReducer(AppStore);
+
+ return (
+
+ alert(store.count)}>Show count
+ setStore({ count: store.count + 1 })}>
+ Increment
+
+
+ );
+}
+```
+
+### Return Value
+
+```tsx
+const [store, setStore, subscribe, unsubscribe] = useStoreReducer(AppStore);
+```
+
+- `store` - Current state (read-only, no re-renders)
+- `setStore` - Update function (object or function)
+- `subscribe` - Imperative subscription
+- `unsubscribe` - Remove subscription
+
+### Updating State
+
+```tsx
+// Object update
+setStore({ count: 10 });
+setStore({ count: 10, theme: "dark" });
+
+// Function update
+setStore((prev) => ({ count: prev.count + 1 }));
+```
+
+### Imperative Subscriptions
+
+Subscribe to key changes outside React's render cycle:
+
+```tsx
+const [, , subscribe] = useStoreReducer(AppStore);
+
+useEffect(() => {
+ const unsubscribe = subscribe("user", (user) => {
+ analytics.track("user_updated", { userId: user.email });
+ });
+ return unsubscribe;
+}, [subscribe]);
+```
+
+**Use cases:**
+
+```tsx
+// DOM manipulation
+subscribe("theme", (theme) => {
+ document.documentElement.setAttribute("data-theme", theme);
+});
+
+// WebSocket sync
+const ws = new WebSocket("wss://example.com");
+subscribe("data", (data) => ws.send(JSON.stringify(data)));
+```
+
+## Consumer Component
+
+Render props pattern with same options as `useStore`:
+
+```tsx
+
+ {({ user }) => (
+
+
{user.name}
+
{user.email}
+
+ )}
+
+
+// With mutation
+ store.user.email,
+ }}
+>
+ {(email) => E-mail: {email}
}
+
+```
+
+Prefer `useStore` for better TypeScript inference.
+
+## Comparison
+
+| Feature | `useStore` | `useStoreReducer` |
+|---------|-----------|-------------------|
+| Re-renders on changes | Yes | No |
+| Subscribe to keys | Yes | No |
+| Computed values | Yes | No |
+| Read state | Yes | Yes |
+| Update state | No | Yes |
+| Imperative subscriptions | No | Yes |
diff --git a/docs/02-core/stores-and-providers.md b/docs/02-core/stores-and-providers.md
new file mode 100644
index 0000000..f34c1ad
--- /dev/null
+++ b/docs/02-core/stores-and-providers.md
@@ -0,0 +1,170 @@
+# Stores and Providers
+
+## Creating a Store
+
+```tsx filename="store.ts" switcher tab="TypeScript"
+import { createStore } from "contection";
+
+type AppStoreType = {
+ user: { name: string; email: string };
+ count: number;
+ theme: "light" | "dark";
+};
+
+const AppStore = createStore({
+ user: { name: "", email: "" },
+ count: 0,
+ theme: "light",
+});
+
+export { AppStore };
+export type { AppStoreType };
+```
+
+```js filename="store.js" switcher tab="JavaScript"
+import { createStore } from "contection";
+
+const AppStore = createStore({
+ user: { name: "", email: "" },
+ count: 0,
+ theme: "light",
+});
+
+export { AppStore };
+```
+
+### Options
+
+```tsx
+const AppStore = createStore(
+ {
+ user: { name: "", email: "" },
+ count: 0,
+ theme: "light",
+ },
+ {
+ lifecycleHooks: {
+ storeDidMount: (store, setStore) => {
+ // Initialization logic
+ },
+ },
+ validate: (data) => {
+ // Validation logic
+ return true;
+ },
+ }
+);
+```
+
+## Provider Component
+
+```tsx
+function App() {
+ return (
+
+
+
+ );
+}
+
+// Or explicitly:
+function App() {
+ return (
+
+
+
+ );
+}
+```
+
+## Store Scoping
+
+Each Provider creates an isolated scope:
+
+```tsx
+function App() {
+ return (
+ <>
+ {/* First scope with initial data */}
+
+
+
+
+ {/* Second scope with different initial data - completely isolated */}
+
+
+
+ >
+ );
+}
+```
+
+Multiple Providers do not share state. Inner Providers override outer ones.
+
+## Multiple Stores
+
+```tsx
+const UserStore = createStore({
+ user: { name: "", email: "" },
+});
+
+const ThemeStore = createStore({
+ theme: "light",
+ accent: "blue",
+});
+
+const CounterStore = createStore({
+ count: 0,
+});
+
+function App() {
+ return (
+
+
+
+
+
+
+
+ );
+}
+```
+
+## Provider Props
+
+### `value`
+
+Optional initial value for this scope:
+
+```tsx
+
+
+
+```
+
+### `options`
+
+Provider-level options override `createStore` options. See [Advanced Topics](../03-advanced/README.md).
+
+## Nested Providers
+
+```tsx
+
+ {/* sees theme: "light" */}
+
+ {/* sees theme: "dark" */}
+
+
+```
diff --git a/docs/03-advanced/README.md b/docs/03-advanced/README.md
new file mode 100644
index 0000000..625cf8d
--- /dev/null
+++ b/docs/03-advanced/README.md
@@ -0,0 +1,17 @@
+# Advanced
+
+Beyond basic usage, Contection supports initialization logic, data validation, and per-Provider customization.
+
+**Lifecycle hooks** run code when stores mount/unmount - load from localStorage, set up event listeners, sync with external systems. **Validation** ensures data integrity before state updates. **Provider-level configuration** lets you override these behaviors per Provider instance.
+
+## Core
+
+- [Lifecycle and Validation](./lifecycle-and-validation.md) - `storeWillMount`, `storeDidMount`, `validate`, Provider overrides
+- [API Reference](./api.md) - Complete function signatures and options
+
+## Guides
+
+- [Performance](./performance.md) - Optimize re-renders, memoization patterns
+- [TypeScript](./typescript.md) - Type definitions, inference, generic stores
+- [Migration](./migration.md) - From Context, Zustand, Redux
+- [Troubleshooting](./troubleshooting.md) - Common issues and solutions
diff --git a/docs/03-advanced/api.md b/docs/03-advanced/api.md
new file mode 100644
index 0000000..9d95f84
--- /dev/null
+++ b/docs/03-advanced/api.md
@@ -0,0 +1,132 @@
+# API Reference
+
+Complete function signatures and options for all Contection exports.
+
+## createStore
+
+```tsx
+function createStore(
+ initialData: Store,
+ options?: CreateStoreOptions
+): StoreInstance
+```
+
+### Parameters
+
+- `initialData` - Initial state for the store
+- `options.lifecycleHooks` - Lifecycle callbacks (see [Lifecycle and Validation](./lifecycle-and-validation.md))
+- `options.validate` - Validation function `(data: Partial) => boolean`
+
+### Returns
+
+- `Provider` - Component wrapper
+- `Consumer` - Render props component
+- `_context` - Underlying React Context
+- `_initial` - Initial store data
+
+```tsx
+const AppStore = createStore(
+ { user: { name: "", email: "" }, count: 0 },
+ {
+ lifecycleHooks: {
+ storeDidMount: (store, setStore) => {
+ const saved = localStorage.getItem("theme");
+ if (saved) setStore({ theme: saved });
+ },
+ },
+ validate: (data) => !("count" in data && data.count < 0),
+ }
+);
+```
+
+---
+
+## useStore
+
+```tsx
+function useStore(
+ instance: StoreInstance,
+ options?: UseStoreOptions
+): T
+```
+
+### Options
+
+- `keys?: string[]` - Keys to subscribe to (omit for all)
+- `mutation?: (newStore, prevStore?, prevMutatedStore?) => T` - Compute derived value
+- `enabled?: "always" | "never" | "after-hydration" | (store) => boolean` - Conditional subscription
+
+### Returns
+
+Subscribed data or computed value. Re-renders when subscribed keys change.
+
+```tsx
+const { count } = useStore(AppStore, { keys: ["count"] });
+const email = useStore(AppStore, {
+ keys: ["user"],
+ mutation: (store) => store.user.email,
+});
+```
+
+---
+
+## useStoreReducer
+
+```tsx
+function useStoreReducer(
+ instance: StoreInstance
+): [store, setStore, subscribe, unsubscribe]
+```
+
+**Does not trigger re-renders.**
+
+### Returns
+
+- `store` - Current state (read-only)
+- `setStore` - Update function (object or function)
+- `subscribe` - Imperative subscription `(key, callback) => unsubscribe`
+- `unsubscribe` - Remove subscription `(key, callback) => void`
+
+```tsx
+const [store, setStore] = useStoreReducer(AppStore);
+setStore({ count: 10 });
+setStore((prev) => ({ count: prev.count + 1 }));
+```
+
+---
+
+## Provider
+
+```tsx
+>
+ {children}
+
+```
+
+Each Provider creates isolated scope.
+
+- `value` - Optional initial value (defaults to `createStore` initial data)
+- `options` - Overrides `createStore` options completely
+
+```tsx
+
+
+
+
+
+ true }}>
+```
+
+---
+
+## Consumer
+
+Render props pattern. Same options as `useStore`.
+
+```tsx
+
+ {({ count }) => {count}
}
+
+```
+
+Prefer `useStore` for better TypeScript inference.
diff --git a/docs/03-advanced/lifecycle-and-validation.md b/docs/03-advanced/lifecycle-and-validation.md
new file mode 100644
index 0000000..f828918
--- /dev/null
+++ b/docs/03-advanced/lifecycle-and-validation.md
@@ -0,0 +1,172 @@
+# Lifecycle and Validation
+
+Control store initialization, cleanup, and data integrity.
+
+## Lifecycle Hooks
+
+Run code when Providers mount/unmount - load persisted data, set up listeners, sync with external systems.
+
+```tsx
+const AppStore = createStore(
+ { user: { name: "", email: "" }, count: 0, theme: "light" },
+ {
+ lifecycleHooks: {
+ storeWillMount: (store, setStore, subscribe, unsubscribe) => {
+ // Sync init (SPA only) - return cleanup if needed
+ },
+ storeDidMount: (store, setStore, subscribe, unsubscribe) => {
+ // Async init (SSR-safe) - return cleanup if needed
+ },
+ storeWillUnmount: (store) => {
+ // Sync cleanup (useLayoutEffect)
+ },
+ storeWillUnmountAsync: (store) => {
+ // Async cleanup (useEffect)
+ },
+ },
+ }
+);
+```
+
+### storeWillMount
+
+Runs synchronously during render, **before** mount. Use for SPA client-only initialization.
+
+```tsx
+storeWillMount: (store, setStore, subscribe) => {
+ const saved = localStorage.getItem("theme");
+ if (saved) setStore({ theme: saved });
+
+ const unsubscribe = subscribe("count", (count) => console.log(count));
+ return unsubscribe; // Cleanup for Strict Mode
+}
+```
+
+### storeDidMount
+
+Runs asynchronously **after** mount. Use for SSR apps to avoid hydration errors.
+
+```tsx
+storeDidMount: (store, setStore) => {
+ setStore({ windowWidth: window.innerWidth });
+
+ const handleResize = () => setStore({ windowWidth: window.innerWidth });
+ window.addEventListener("resize", handleResize);
+ return () => window.removeEventListener("resize", handleResize);
+}
+```
+
+### storeWillUnmount / storeWillUnmountAsync
+
+```tsx
+storeWillUnmount: (store) => {
+ localStorage.setItem("lastCount", String(store.count)); // Sync
+}
+
+storeWillUnmountAsync: (store) => {
+ fetch("/api/sync", { method: "POST", body: JSON.stringify(store) }); // Async
+}
+```
+
+### Execution Order
+
+**Mount:** `storeWillMount` (sync) → `storeDidMount` (async)
+
+**Unmount:** `storeWillUnmount` (sync) → cleanups → `storeWillUnmountAsync` (async)
+
+---
+
+## Store Validation
+
+Validate store data before it's applied.
+
+```tsx
+const AppStore = createStore(
+ { count: 0 },
+ {
+ validate: (data) => {
+ if ("count" in data && data.count < 0) return false;
+ return true;
+ },
+ }
+);
+```
+
+- **Truthy** → Update applied
+- **Falsy** → Update rejected
+- **Invalid initial data** throws error
+- **Invalid updates** silently rejected
+
+### With Zod
+
+```tsx
+import { z } from "zod";
+
+const schema = z.object({
+ user: z.object({ name: z.string().min(1), email: z.string().email() }),
+ count: z.number().int().min(0),
+});
+
+const AppStore = createStore(
+ { user: { name: "John", email: "john@example.com" }, count: 0 },
+ {
+ validate: (data) => {
+ const partialSchema = schema.pick(
+ Object.fromEntries(Object.keys(data).map((k) => [k, true]))
+ );
+ const result = partialSchema.safeParse(data);
+ return result.success ? result.data : false;
+ },
+ }
+);
+```
+
+---
+
+## Provider-Level Configuration
+
+Provider `options` completely override `createStore` options.
+
+```tsx
+ {
+ // Provider-specific initialization
+ },
+ },
+ validate: (data) => true,
+ }}
+>
+
+
+```
+
+### With React Props
+
+Provider-level hooks can access React props:
+
+```tsx
+function App({ userId }: { userId: string }) {
+ return (
+ {
+ fetchUserData(userId).then((data) => setStore({ user: data }));
+ },
+ },
+ }}
+ >
+
+
+ );
+}
+```
+
+### Disable Features
+
+```tsx
+
+
+```
diff --git a/docs/03-advanced/migration.md b/docs/03-advanced/migration.md
new file mode 100644
index 0000000..8a1605a
--- /dev/null
+++ b/docs/03-advanced/migration.md
@@ -0,0 +1,120 @@
+# Migration Guide
+
+Contection replaces React Context, Zustand, and Redux with simpler patterns.
+
+## From React Context
+
+**Before:**
+```tsx
+const AppContext = createContext({ count: 0, setCount: () => {} });
+
+function Provider({ children }) {
+ const [count, setCount] = useState(0);
+ return (
+
+ {children}
+
+ );
+}
+
+function Counter() {
+ const { count, setCount } = useContext(AppContext);
+ return setCount(count + 1)}>{count} ;
+}
+```
+
+**After:**
+```tsx
+const AppStore = createStore({ count: 0 });
+
+function App() {
+ return (
+
+
+
+ );
+}
+
+function Counter() {
+ const { count } = useStore(AppStore, { keys: ["count"] });
+ const [, setStore] = useStoreReducer(AppStore);
+ return setStore({ count: count + 1 })}>{count} ;
+}
+```
+
+## From Zustand
+
+**Before:**
+```tsx
+const useStore = create((set) => ({
+ count: 0,
+ increment: () => set((state) => ({ count: state.count + 1 })),
+}));
+
+function Counter() {
+ const count = useStore((state) => state.count);
+ const increment = useStore((state) => state.increment);
+ return {count} ;
+}
+```
+
+**After:**
+```tsx
+const AppStore = createStore({ count: 0 });
+
+function Counter() {
+ const { count } = useStore(AppStore, { keys: ["count"] });
+ const [, setStore] = useStoreReducer(AppStore);
+ return setStore({ count: count + 1 })}>{count} ;
+}
+```
+
+## From Redux
+
+**Before:**
+```tsx
+// store.ts
+const counterSlice = createSlice({
+ name: "counter",
+ initialState: { count: 0 },
+ reducers: {
+ increment: (state) => { state.count += 1; },
+ },
+});
+
+// Counter.tsx
+function Counter() {
+ const count = useSelector((state) => state.counter.count);
+ const dispatch = useDispatch();
+ return dispatch(increment())}>{count} ;
+}
+```
+
+**After:**
+```tsx
+const AppStore = createStore({ count: 0 });
+
+function Counter() {
+ const { count } = useStore(AppStore, { keys: ["count"] });
+ const [, setStore] = useStoreReducer(AppStore);
+ return setStore({ count: count + 1 })}>{count} ;
+}
+```
+
+## Key Differences
+
+| Feature | Context | Zustand | Redux | Contection |
+|---------|---------|---------|-------|------------|
+| Granular subscriptions | Manual | Selector | Selector | Built-in `keys` |
+| State updates | setState | set() | dispatch | setStore |
+| Provider required | Yes | No | Yes | Yes |
+| Provider scoping | Yes | No | No | Yes |
+| Boilerplate | Medium | Low | High | Low |
+
+## Migration Steps
+
+1. **Create store** with `createStore()` using your existing state shape
+2. **Wrap with Provider** at the same level as your current provider
+3. **Replace hooks** - `useContext` → `useStore`, selectors → `keys` option
+4. **Replace updates** - setState/dispatch → `setStore` from `useStoreReducer`
+5. **Add granular subscriptions** - specify `keys` to optimize re-renders
diff --git a/docs/03-advanced/performance.md b/docs/03-advanced/performance.md
new file mode 100644
index 0000000..c3212a9
--- /dev/null
+++ b/docs/03-advanced/performance.md
@@ -0,0 +1,78 @@
+# Performance Optimization
+
+Contection's granular subscriptions already minimize re-renders, but these patterns help further.
+
+## Subscribe to Specific Keys
+
+Only subscribe to what you need - components won't re-render for unrelated state changes.
+
+```tsx
+// Only re-renders when count changes
+const { count } = useStore(AppStore, { keys: ["count"] });
+
+// Re-renders when user OR theme changes
+const { user, theme } = useStore(AppStore, { keys: ["user", "theme"] });
+```
+
+## Memoize Expensive Computations
+
+Use mutation's `prevMutatedStore` to skip recomputation when inputs haven't changed.
+
+```tsx
+const filteredItems = useStore(AppStore, {
+ keys: ["items", "filter"],
+ mutation: (newStore, prevStore, prevMutatedStore) => {
+ // Skip if filter hasn't changed
+ if (prevMutatedStore && prevStore?.filter === newStore.filter) {
+ return prevMutatedStore;
+ }
+ return newStore.items.filter((item) =>
+ item.name.includes(newStore.filter)
+ );
+ },
+});
+```
+
+## Use useStoreReducer for No Re-renders
+
+For event handlers that only read/write state without displaying it.
+
+```tsx
+function SaveButton() {
+ const [store, setStore] = useStoreReducer(AppStore);
+
+ const handleSave = () => {
+ // Read current state without subscribing
+ saveToServer(store.data);
+ setStore({ lastSaved: Date.now() });
+ };
+
+ return Save ;
+}
+```
+
+## Split Large Stores
+
+Instead of one monolithic store, split by domain:
+
+```tsx
+// Instead of one large store
+const AppStore = createStore({ user, theme, cart, notifications, ... });
+
+// Split into focused stores
+const UserStore = createStore({ user });
+const ThemeStore = createStore({ theme });
+const CartStore = createStore({ items, total });
+```
+
+## Avoid Subscribing to All Keys
+
+Omitting `keys` subscribes to everything - the component re-renders on any change.
+
+```tsx
+// Avoid: re-renders on ANY state change
+const store = useStore(AppStore);
+
+// Better: only re-renders when count changes
+const { count } = useStore(AppStore, { keys: ["count"] });
+```
diff --git a/docs/04-modules/README.md b/docs/04-modules/README.md
new file mode 100644
index 0000000..d52a0af
--- /dev/null
+++ b/docs/04-modules/README.md
@@ -0,0 +1,11 @@
+# Modules and Adapters
+
+Pre-built Contection stores and adapters for common use cases.
+
+**Modules** are ready-to-use stores with built-in logic:
+- [Viewport](./viewport.md) - Tracks window dimensions with a single resize listener shared across all subscribers
+- [Top Layer](./top-layer.md) - Manages stacked dialogs, modals, and overlays with proper z-index ordering
+
+**Adapters** persist store state to external storage:
+- [Storage Adapter](./storage-adapter.md) - Saves/restores state to localStorage or sessionStorage
+- [Next.js Cookie Adapter](./next-cookie-adapter.md) - Cookie persistence with SSR support - state available on both server and client
diff --git a/docs/04-modules/next-cookie-adapter.md b/docs/04-modules/next-cookie-adapter.md
new file mode 100644
index 0000000..7f67053
--- /dev/null
+++ b/docs/04-modules/next-cookie-adapter.md
@@ -0,0 +1,105 @@
+# Next.js Cookie Adapter
+
+[GitHub](https://github.com/alexdln/contection/tree/main/adapters/next-cookie) • [Demo](https://nextjs-bsky.contection.dev/)
+
+SSR-compatible state persistence using cookies. Unlike localStorage, cookies are available on both server and client, enabling true server-side rendering with pre-populated state.
+
+## Why Use This
+
+- **SSR support** - State available during server render, no hydration mismatch
+- **Automatic hydration** - Client automatically picks up server state
+- **Cookie options** - Full control over expiry, security, and scope
+- **Validation** - Validate cookie data before restoring
+
+## Installation
+
+```bash switcher tab="npm"
+npm install contection-next-cookie-adapter
+```
+
+```bash switcher tab="pnpm"
+pnpm add contection-next-cookie-adapter
+```
+
+```bash switcher tab="yarn"
+yarn add contection-next-cookie-adapter
+```
+
+## Usage
+
+```tsx
+import { createNextCookieAdapter } from "contection-next-cookie-adapter";
+
+const cookieAdapter = createNextCookieAdapter({
+ keys: ["theme", "user"],
+ cookieOptions: {
+ httpOnly: false,
+ secure: process.env.NODE_ENV === "production",
+ sameSite: "lax",
+ maxAge: 60 * 60 * 24 * 7, // 7 days
+ },
+});
+
+cookieAdapter.attach(AppStore);
+```
+
+### Options
+
+| Option | Type | Description |
+|--------|------|-------------|
+| `keys` | `string[]` | Store keys to persist |
+| `cookieOptions.httpOnly` | `boolean` | `false` for client access |
+| `cookieOptions.secure` | `boolean` | `true` for HTTPS only |
+| `cookieOptions.sameSite` | `string` | `"lax"`, `"strict"`, or `"none"` |
+| `cookieOptions.maxAge` | `number` | Expiry in seconds |
+| `validate` | `(data) => boolean` | Validate before restoring |
+
+### With Validation
+
+```tsx
+const cookieAdapter = createNextCookieAdapter({
+ keys: ["theme", "preferences"],
+ cookieOptions: {
+ httpOnly: false,
+ secure: true,
+ sameSite: "lax",
+ maxAge: 60 * 60 * 24 * 30, // 30 days
+ },
+ validate: (data) => {
+ if (data.theme && !["light", "dark", "system"].includes(data.theme)) {
+ return false;
+ }
+ return true;
+ },
+});
+```
+
+### Server Component Access
+
+```tsx
+// app/layout.tsx
+import { cookies } from "next/headers";
+
+export default function RootLayout({ children }) {
+ const theme = cookies().get("theme")?.value || "light";
+
+ return (
+
+
+
+ {children}
+
+
+
+ );
+}
+```
+
+## Comparison with Storage Adapter
+
+| Feature | Storage Adapter | Cookie Adapter |
+|---------|-----------------|----------------|
+| SSR support | No | Yes |
+| Server access | No | Yes |
+| Size limit | ~5MB | ~4KB |
+| Sent with requests | No | Yes |
diff --git a/docs/04-modules/storage-adapter.md b/docs/04-modules/storage-adapter.md
new file mode 100644
index 0000000..c4c536c
--- /dev/null
+++ b/docs/04-modules/storage-adapter.md
@@ -0,0 +1,78 @@
+# Storage Adapter
+
+[GitHub](https://github.com/alexdln/contection/tree/main/adapters/storage)
+
+Automatically persist and restore store state to browser storage. State survives page refreshes and browser sessions.
+
+## Why Use This
+
+- **Automatic sync** - Saves on every state change, restores on mount
+- **Selective persistence** - Choose which keys to persist
+- **Validation** - Validate stored data before restoring
+- **Storage choice** - Use localStorage (persistent) or sessionStorage (tab-scoped)
+
+## Installation
+
+```bash switcher tab="npm"
+npm install contection-storage-adapter
+```
+
+```bash switcher tab="pnpm"
+pnpm add contection-storage-adapter
+```
+
+```bash switcher tab="yarn"
+yarn add contection-storage-adapter
+```
+
+## Usage
+
+```tsx
+import { createStorageAdapter } from "contection-storage-adapter";
+
+const storageAdapter = createStorageAdapter({
+ storage: localStorage,
+ keys: ["theme", "user"],
+});
+
+storageAdapter.attach(AppStore);
+```
+
+### Options
+
+| Option | Type | Description |
+|--------|------|-------------|
+| `storage` | `Storage` | `localStorage` or `sessionStorage` |
+| `keys` | `string[]` | Store keys to persist |
+| `validate` | `(data) => boolean` | Validate before restoring |
+| `storageKey` | `string` | Custom storage key name |
+
+### With Validation
+
+```tsx
+const storageAdapter = createStorageAdapter({
+ storage: localStorage,
+ keys: ["theme", "settings"],
+ validate: (data) => {
+ if (data.theme && !["light", "dark"].includes(data.theme)) {
+ return false;
+ }
+ return true;
+ },
+});
+```
+
+### Session Storage
+
+```tsx
+// Data cleared when tab closes
+const sessionAdapter = createStorageAdapter({
+ storage: sessionStorage,
+ keys: ["formData"],
+});
+```
+
+## Examples
+
+- [nextjs-bsky](https://nextjs-bsky.contection.dev/) - Combined with cookie adapter
+- [react-routerjs-bsky](https://router-bsky.contection.dev/) - React Router integration
diff --git a/docs/04-modules/top-layer.md b/docs/04-modules/top-layer.md
new file mode 100644
index 0000000..69be606
--- /dev/null
+++ b/docs/04-modules/top-layer.md
@@ -0,0 +1,103 @@
+# Top Layer Module
+
+[GitHub](https://github.com/alexdln/contection/tree/main/modules/top-layer)
+
+Manage stacked UI layers like dialogs, modals, drawers, and tooltips. Handles z-index ordering, focus trapping, and escape key dismissal.
+
+## Why Use This
+
+- **Stack management** - Automatic z-index ordering for nested layers
+- **Focus handling** - Traps focus within active layer
+- **Keyboard support** - Escape key closes top layer
+- **Portal rendering** - Renders layers at document root
+
+## Installation
+
+```bash switcher tab="npm"
+npm install contection-top-layer
+```
+
+```bash switcher tab="pnpm"
+pnpm add contection-top-layer
+```
+
+```bash switcher tab="yarn"
+yarn add contection-top-layer
+```
+
+## Usage
+
+```tsx
+import { createTopLayerStore } from "contection-top-layer";
+import { useStore, useStoreReducer } from "contection";
+
+const TopLayerStore = createTopLayerStore();
+
+function App() {
+ return (
+
+
+
+
+ );
+}
+```
+
+### Open a Layer
+
+```tsx
+function DialogTrigger() {
+ const [, setStore] = useStoreReducer(TopLayerStore);
+
+ const openDialog = () => {
+ setStore((prev) => ({
+ layers: [...prev.layers, {
+ id: "dialog-1",
+ component: MyDialog,
+ props: { title: "Hello" }
+ }],
+ }));
+ };
+
+ return Open Dialog ;
+}
+```
+
+### Close a Layer
+
+```tsx
+function MyDialog({ id, title }) {
+ const [, setStore] = useStoreReducer(TopLayerStore);
+
+ const close = () => {
+ setStore((prev) => ({
+ layers: prev.layers.filter((l) => l.id !== id),
+ }));
+ };
+
+ return (
+
+
{title}
+ Close
+
+ );
+}
+```
+
+### Render Layers
+
+```tsx
+function LayerRenderer() {
+ const { layers } = useStore(TopLayerStore, { keys: ["layers"] });
+
+ return (
+ <>
+ {layers.map((layer, index) => (
+
+
+
+ ))}
+ >
+ );
+}
+```
diff --git a/docs/04-modules/viewport.md b/docs/04-modules/viewport.md
new file mode 100644
index 0000000..d273c11
--- /dev/null
+++ b/docs/04-modules/viewport.md
@@ -0,0 +1,74 @@
+# Viewport Module
+
+[GitHub](https://github.com/alexdln/contection/tree/main/modules/viewport)
+
+Reactive viewport dimensions with a single shared resize listener. Components subscribe to specific properties and only re-render when those values change.
+
+## Why Use This
+
+- **Single listener** - One `resize` event handler shared across all subscribers
+- **Granular updates** - Subscribe to `width`, `height`, or breakpoints independently
+- **SSR-safe** - Proper hydration handling for server-rendered apps
+
+## Installation
+
+```bash switcher tab="npm"
+npm install contection-viewport
+```
+
+```bash switcher tab="pnpm"
+pnpm add contection-viewport
+```
+
+```bash switcher tab="yarn"
+yarn add contection-viewport
+```
+
+## Usage
+
+```tsx
+import { createViewportStore } from "contection-viewport";
+import { useStore } from "contection";
+
+const ViewportStore = createViewportStore();
+
+function App() {
+ return (
+
+
+
+ );
+}
+```
+
+### Subscribe to Dimensions
+
+```tsx
+function WindowSize() {
+ const { width, height } = useStore(ViewportStore, {
+ keys: ["width", "height"],
+ });
+ return {width} x {height}
;
+}
+```
+
+### Subscribe to Breakpoints
+
+```tsx
+function ResponsiveComponent() {
+ const { isMobile } = useStore(ViewportStore, {
+ keys: ["isMobile"],
+ });
+ return isMobile ? : ;
+}
+```
+
+### Available Store Keys
+
+| Key | Type | Description |
+|-----|------|-------------|
+| `width` | `number` | Viewport width in pixels |
+| `height` | `number` | Viewport height in pixels |
+| `isMobile` | `boolean` | `true` if width < 768px |
+| `isTablet` | `boolean` | `true` if width >= 768px and < 1024px |
+| `isDesktop` | `boolean` | `true` if width >= 1024px |
diff --git a/docs/05-examples/README.md b/docs/05-examples/README.md
new file mode 100644
index 0000000..acad449
--- /dev/null
+++ b/docs/05-examples/README.md
@@ -0,0 +1,136 @@
+# Examples
+
+Working examples demonstrating Contection patterns and integrations.
+
+## Live Demos
+
+| Example | Description | Preview |
+|---------|-------------|---------|
+| **demo** | Fine-grained subscriptions, storage adapters, viewport/top-layer modules | [contection.dev](https://contection.dev/demo) |
+| **nextjs-bsky** | Next.js SSR with cookie adapter, combined server/client architecture | [nextjs-bsky.contection.dev](https://nextjs-bsky.contection.dev/) |
+| **react-routerjs-bsky** | React Router integration with storage persistence | [router-bsky.contection.dev](https://router-bsky.contection.dev/) |
+
+## Basic Patterns
+
+### Counter
+
+```tsx
+const CounterStore = createStore({ count: 0 });
+
+function Counter() {
+ const { count } = useStore(CounterStore, { keys: ["count"] });
+ const [, setStore] = useStoreReducer(CounterStore);
+
+ return (
+
+
Count: {count}
+
setStore({ count: count + 1 })}>+
+
setStore({ count: count - 1 })}>-
+
+ );
+}
+```
+
+### Theme Toggle
+
+```tsx
+const ThemeStore = createStore({ theme: "light" as "light" | "dark" });
+
+function ThemeToggle() {
+ const { theme } = useStore(ThemeStore, { keys: ["theme"] });
+ const [, setStore] = useStoreReducer(ThemeStore);
+
+ return (
+ setStore({ theme: theme === "light" ? "dark" : "light" })}>
+ {theme}
+
+ );
+}
+```
+
+---
+
+## Advanced Patterns
+
+### Form with Validation
+
+```tsx
+const FormStore = createStore({
+ fields: { name: "", email: "" },
+ errors: {} as Record,
+});
+
+const handleChange = (field: string, value: string) => {
+ const error = field === "email" && !value.includes("@") ? "Invalid email" : "";
+ setStore({
+ fields: { ...fields, [field]: value },
+ errors: { ...errors, [field]: error },
+ });
+};
+```
+
+### WebSocket Sync
+
+```tsx
+useEffect(() => {
+ const ws = new WebSocket("wss://example.com");
+ ws.onmessage = (e) => setStore({ data: JSON.parse(e.data) });
+
+ const unsubscribe = subscribe("data", (data) => {
+ if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify(data));
+ });
+
+ return () => { unsubscribe(); ws.close(); };
+}, []);
+```
+
+---
+
+## Framework Integration
+
+### Next.js
+
+```tsx
+// app/layout.tsx
+export default function RootLayout({ children }) {
+ return (
+
+ {children}
+
+ );
+}
+```
+
+### React Router
+
+```tsx
+function App() {
+ return (
+
+
+
+ } />
+
+
+
+ );
+}
+```
+
+### With Adapters
+
+```tsx
+// Storage adapter - persists to localStorage
+const storageAdapter = createStorageAdapter({
+ storage: localStorage,
+ keys: ["theme"],
+});
+storageAdapter.attach(AppStore);
+
+// Cookie adapter - SSR-compatible
+const cookieAdapter = createNextCookieAdapter({
+ keys: ["theme"],
+ cookieOptions: { httpOnly: false, secure: true },
+});
+cookieAdapter.attach(AppStore);
+```
diff --git a/examples/demo/.gitignore b/examples/demo/.gitignore
index 5940145..7ac8ea1 100644
--- a/examples/demo/.gitignore
+++ b/examples/demo/.gitignore
@@ -2,4 +2,3 @@ node_modules
dist
.DS_Store
*.log
-
diff --git a/examples/demo/src/components/demos/contection/store-controls.tsx b/examples/demo/src/components/demos/contection/store-controls.tsx
index 272d225..6d33946 100644
--- a/examples/demo/src/components/demos/contection/store-controls.tsx
+++ b/examples/demo/src/components/demos/contection/store-controls.tsx
@@ -20,7 +20,6 @@ export const StoreControls: React.FC = () => {
};
for (let i = 0; i < 200; i++) {
const nextTimezone = `UTC${Math.floor(i / 20)}`;
- await new Promise((resolve) => setTimeout(resolve, 20));
const random = Math.random();
if (random < 0.25) {
summary.counter++;
diff --git a/examples/demo/src/components/ui/layout/styles.scss b/examples/demo/src/components/ui/layout/styles.scss
index 1e4fbeb..0790d3f 100644
--- a/examples/demo/src/components/ui/layout/styles.scss
+++ b/examples/demo/src/components/ui/layout/styles.scss
@@ -37,5 +37,4 @@
@media (max-width: 768px) {
padding: 12px;
}
-}
-
+}
\ No newline at end of file
diff --git a/modules/top-layer/README.md b/modules/top-layer/README.md
index 94ab34b..e006d93 100644
--- a/modules/top-layer/README.md
+++ b/modules/top-layer/README.md
@@ -2,7 +2,7 @@
A layer management module built on top of [contection](https://github.com/alexdln/contection) - a performance-focused state management package. Provides efficient management of dialogs and upper layers with granular subscriptions, type safety, and support for isolated layers.
-[npm](https://www.npmjs.com/package/contection-top-layer) • [demo](https://www.contection.dev/?tab=top-layer)
+[npm](https://www.npmjs.com/package/contection-top-layer)
## Features
diff --git a/modules/viewport/README.md b/modules/viewport/README.md
index 573d0a5..7d97e73 100644
--- a/modules/viewport/README.md
+++ b/modules/viewport/README.md
@@ -2,7 +2,7 @@
A performance-based viewport management module built on top of [contection](https://github.com/alexdln/contection) - a performance-focused state management package. Provides efficient screen size tracking with granular subscriptions, memoization, and a single global resize subscribeer that triggers re-renders only where needed.
-[npm](https://www.npmjs.com/package/contection-viewport) • [demo](https://www.contection.dev/?tab=viewport)
+[npm](https://www.npmjs.com/package/contection-viewport)
## Features
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 356496d..a604b98 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -48,7 +48,7 @@ importers:
version: link:../../package
next:
specifier: ^16.0.4
- version: 16.0.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.93.3)
+ version: 16.0.4(react-dom@19.2.3(react@19.2.0))(react@19.2.0)(sass@1.97.2)
typescript:
specifier: 5.9.3
version: 5.9.3
@@ -67,7 +67,7 @@ importers:
version: link:../../package
react-router:
specifier: 7.9.6
- version: 7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ version: 7.9.6(react-dom@19.2.3(react@19.2.0))(react@19.2.0)
typescript:
specifier: 5.9.3
version: 5.9.3
@@ -120,7 +120,7 @@ importers:
version: 19.2.2(@types/react@19.2.2)
'@vitejs/plugin-react':
specifier: 5.1.1
- version: 5.1.1(vite@7.2.2(@types/node@22.19.1)(sass-embedded@1.93.3)(sass@1.93.3))
+ version: 5.1.1(vite@7.2.2(@types/node@22.19.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0))
sass-embedded:
specifier: ^1.93.3
version: 1.93.3
@@ -129,7 +129,7 @@ importers:
version: 5.9.3
vite:
specifier: 7.2.2
- version: 7.2.2(@types/node@22.19.1)(sass-embedded@1.93.3)(sass@1.93.3)
+ version: 7.2.2(@types/node@22.19.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)
examples/nextjs-bsky:
dependencies:
@@ -162,7 +162,7 @@ importers:
version: 11.2.2
next:
specifier: 16.0.7
- version: 16.0.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.93.3)
+ version: 16.0.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.97.2)
react:
specifier: 19.2.0
version: 19.2.0
@@ -242,7 +242,7 @@ importers:
devDependencies:
'@react-router/dev':
specifier: 7.9.6
- version: 7.9.6(@react-router/serve@7.9.6(react-router@7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@5.9.3))(@types/node@22.10.1)(@vitejs/plugin-rsc@0.5.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3)))(react-router@7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(sass-embedded@1.93.3)(sass@1.93.3)(typescript@5.9.3)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3))
+ version: 7.9.6(@react-router/serve@7.9.6(react-router@7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@5.9.3))(@types/node@22.10.1)(@vitejs/plugin-rsc@0.5.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)))(react-router@7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)(typescript@5.9.3)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0))
'@types/node':
specifier: 22.10.1
version: 22.10.1
@@ -254,19 +254,19 @@ importers:
version: 19.2.2(@types/react@19.2.2)
'@vitejs/plugin-rsc':
specifier: 0.5.2
- version: 0.5.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3))
+ version: 0.5.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0))
typescript:
specifier: 5.9.3
version: 5.9.3
vite:
specifier: 7.2.6
- version: 7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3)
+ version: 7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)
vite-plugin-devtools-json:
specifier: 1.0.0
- version: 1.0.0(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3))
+ version: 1.0.0(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0))
vite-tsconfig-paths:
specifier: 5.1.4
- version: 5.1.4(typescript@5.9.3)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3))
+ version: 5.1.4(typescript@5.9.3)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0))
modules/top-layer:
dependencies:
@@ -313,6 +313,49 @@ importers:
specifier: 5.9.3
version: 5.9.3
+ site:
+ dependencies:
+ '@robindoc/minisearch':
+ specifier: 3.7.2
+ version: 3.7.2(tsx@4.21.0)
+ '@robindoc/next':
+ specifier: 3.7.2
+ version: 3.7.2(next@16.1.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.2))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(robindoc@3.7.2(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))
+ contection:
+ specifier: latest
+ version: 2.3.0(react@19.2.3)
+ next:
+ specifier: 16.1.4
+ version: 16.1.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.2)
+ react:
+ specifier: 19.2.3
+ version: 19.2.3
+ react-dom:
+ specifier: 19.2.3
+ version: 19.2.3(react@19.2.3)
+ robindoc:
+ specifier: 3.7.2
+ version: 3.7.2(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ sass:
+ specifier: 1.97.2
+ version: 1.97.2
+ devDependencies:
+ '@types/node':
+ specifier: 25.0.8
+ version: 25.0.8
+ '@types/react':
+ specifier: 19.2.8
+ version: 19.2.8
+ '@types/react-dom':
+ specifier: 19.2.3
+ version: 19.2.3(@types/react@19.2.8)
+ tsx:
+ specifier: 4.21.0
+ version: 4.21.0
+ typescript:
+ specifier: 5.9.3
+ version: 5.9.3
+
tests:
dependencies:
contection:
@@ -1083,156 +1126,312 @@ packages:
cpu: [ppc64]
os: [aix]
+ '@esbuild/aix-ppc64@0.27.2':
+ resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
'@esbuild/android-arm64@0.25.12':
resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
+ '@esbuild/android-arm64@0.27.2':
+ resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
'@esbuild/android-arm@0.25.12':
resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
+ '@esbuild/android-arm@0.27.2':
+ resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
'@esbuild/android-x64@0.25.12':
resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
+ '@esbuild/android-x64@0.27.2':
+ resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
'@esbuild/darwin-arm64@0.25.12':
resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
+ '@esbuild/darwin-arm64@0.27.2':
+ resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
'@esbuild/darwin-x64@0.25.12':
resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
+ '@esbuild/darwin-x64@0.27.2':
+ resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
'@esbuild/freebsd-arm64@0.25.12':
resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
+ '@esbuild/freebsd-arm64@0.27.2':
+ resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
'@esbuild/freebsd-x64@0.25.12':
resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
+ '@esbuild/freebsd-x64@0.27.2':
+ resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
'@esbuild/linux-arm64@0.25.12':
resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
+ '@esbuild/linux-arm64@0.27.2':
+ resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
'@esbuild/linux-arm@0.25.12':
resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
+ '@esbuild/linux-arm@0.27.2':
+ resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
'@esbuild/linux-ia32@0.25.12':
resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
+ '@esbuild/linux-ia32@0.27.2':
+ resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
'@esbuild/linux-loong64@0.25.12':
resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
+ '@esbuild/linux-loong64@0.27.2':
+ resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
'@esbuild/linux-mips64el@0.25.12':
resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
+ '@esbuild/linux-mips64el@0.27.2':
+ resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
'@esbuild/linux-ppc64@0.25.12':
resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
+ '@esbuild/linux-ppc64@0.27.2':
+ resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
'@esbuild/linux-riscv64@0.25.12':
resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
+ '@esbuild/linux-riscv64@0.27.2':
+ resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
'@esbuild/linux-s390x@0.25.12':
resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
+ '@esbuild/linux-s390x@0.27.2':
+ resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
'@esbuild/linux-x64@0.25.12':
resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
+ '@esbuild/linux-x64@0.27.2':
+ resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
'@esbuild/netbsd-arm64@0.25.12':
resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
+ '@esbuild/netbsd-arm64@0.27.2':
+ resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
'@esbuild/netbsd-x64@0.25.12':
resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
+ '@esbuild/netbsd-x64@0.27.2':
+ resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
'@esbuild/openbsd-arm64@0.25.12':
resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
+ '@esbuild/openbsd-arm64@0.27.2':
+ resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
'@esbuild/openbsd-x64@0.25.12':
resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
+ '@esbuild/openbsd-x64@0.27.2':
+ resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
'@esbuild/openharmony-arm64@0.25.12':
resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openharmony]
+ '@esbuild/openharmony-arm64@0.27.2':
+ resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openharmony]
+
'@esbuild/sunos-x64@0.25.12':
resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
+ '@esbuild/sunos-x64@0.27.2':
+ resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
'@esbuild/win32-arm64@0.25.12':
resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
+ '@esbuild/win32-arm64@0.27.2':
+ resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
'@esbuild/win32-ia32@0.25.12':
resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
+ '@esbuild/win32-ia32@0.27.2':
+ resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
'@esbuild/win32-x64@0.25.12':
resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
+ '@esbuild/win32-x64@0.27.2':
+ resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
'@eslint-community/eslint-utils@4.9.0':
resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -1559,6 +1758,9 @@ packages:
'@next/env@16.0.7':
resolution: {integrity: sha512-gpaNgUh5nftFKRkRQGnVi5dpcYSKGcZZkQffZ172OrG/XkrnS7UBTQ648YY+8ME92cC4IojpI2LqTC8sTDhAaw==}
+ '@next/env@16.1.4':
+ resolution: {integrity: sha512-gkrXnZyxPUy0Gg6SrPQPccbNVLSP3vmW8LU5dwEttEEC1RwDivk8w4O+sZIjFvPrSICXyhQDCG+y3VmjlJf+9A==}
+
'@next/swc-darwin-arm64@16.0.4':
resolution: {integrity: sha512-TN0cfB4HT2YyEio9fLwZY33J+s+vMIgC84gQCOLZOYusW7ptgjIn8RwxQt0BUpoo9XRRVVWEHLld0uhyux1ZcA==}
engines: {node: '>= 10'}
@@ -1571,6 +1773,12 @@ packages:
cpu: [arm64]
os: [darwin]
+ '@next/swc-darwin-arm64@16.1.4':
+ resolution: {integrity: sha512-T8atLKuvk13XQUdVLCv1ZzMPgLPW0+DWWbHSQXs0/3TjPrKNxTmUIhOEaoEyl3Z82k8h/gEtqyuoZGv6+Ugawg==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
'@next/swc-darwin-x64@16.0.4':
resolution: {integrity: sha512-XsfI23jvimCaA7e+9f3yMCoVjrny2D11G6H8NCcgv+Ina/TQhKPXB9P4q0WjTuEoyZmcNvPdrZ+XtTh3uPfH7Q==}
engines: {node: '>= 10'}
@@ -1583,6 +1791,12 @@ packages:
cpu: [x64]
os: [darwin]
+ '@next/swc-darwin-x64@16.1.4':
+ resolution: {integrity: sha512-AKC/qVjUGUQDSPI6gESTx0xOnOPQ5gttogNS3o6bA83yiaSZJek0Am5yXy82F1KcZCx3DdOwdGPZpQCluonuxg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+
'@next/swc-linux-arm64-gnu@16.0.4':
resolution: {integrity: sha512-uo8X7qHDy4YdJUhaoJDMAbL8VT5Ed3lijip2DdBHIB4tfKAvB1XBih6INH2L4qIi4jA0Qq1J0ErxcOocBmUSwg==}
engines: {node: '>= 10'}
@@ -1595,6 +1809,12 @@ packages:
cpu: [arm64]
os: [linux]
+ '@next/swc-linux-arm64-gnu@16.1.4':
+ resolution: {integrity: sha512-POQ65+pnYOkZNdngWfMEt7r53bzWiKkVNbjpmCt1Zb3V6lxJNXSsjwRuTQ8P/kguxDC8LRkqaL3vvsFrce4dMQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
'@next/swc-linux-arm64-musl@16.0.4':
resolution: {integrity: sha512-pvR/AjNIAxsIz0PCNcZYpH+WmNIKNLcL4XYEfo+ArDi7GsxKWFO5BvVBLXbhti8Coyv3DE983NsitzUsGH5yTw==}
engines: {node: '>= 10'}
@@ -1607,6 +1827,12 @@ packages:
cpu: [arm64]
os: [linux]
+ '@next/swc-linux-arm64-musl@16.1.4':
+ resolution: {integrity: sha512-3Wm0zGYVCs6qDFAiSSDL+Z+r46EdtCv/2l+UlIdMbAq9hPJBvGu/rZOeuvCaIUjbArkmXac8HnTyQPJFzFWA0Q==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
'@next/swc-linux-x64-gnu@16.0.4':
resolution: {integrity: sha512-2hebpsd5MRRtgqmT7Jj/Wze+wG+ZEXUK2KFFL4IlZ0amEEFADo4ywsifJNeFTQGsamH3/aXkKWymDvgEi+pc2Q==}
engines: {node: '>= 10'}
@@ -1619,6 +1845,12 @@ packages:
cpu: [x64]
os: [linux]
+ '@next/swc-linux-x64-gnu@16.1.4':
+ resolution: {integrity: sha512-lWAYAezFinaJiD5Gv8HDidtsZdT3CDaCeqoPoJjeB57OqzvMajpIhlZFce5sCAH6VuX4mdkxCRqecCJFwfm2nQ==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
'@next/swc-linux-x64-musl@16.0.4':
resolution: {integrity: sha512-pzRXf0LZZ8zMljH78j8SeLncg9ifIOp3ugAFka+Bq8qMzw6hPXOc7wydY7ardIELlczzzreahyTpwsim/WL3Sg==}
engines: {node: '>= 10'}
@@ -1631,6 +1863,12 @@ packages:
cpu: [x64]
os: [linux]
+ '@next/swc-linux-x64-musl@16.1.4':
+ resolution: {integrity: sha512-fHaIpT7x4gA6VQbdEpYUXRGyge/YbRrkG6DXM60XiBqDM2g2NcrsQaIuj375egnGFkJow4RHacgBOEsHfGbiUw==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
'@next/swc-win32-arm64-msvc@16.0.4':
resolution: {integrity: sha512-7G/yJVzum52B5HOqqbQYX9bJHkN+c4YyZ2AIvEssMHQlbAWOn3iIJjD4sM6ihWsBxuljiTKJovEYlD1K8lCUHw==}
engines: {node: '>= 10'}
@@ -1643,6 +1881,12 @@ packages:
cpu: [arm64]
os: [win32]
+ '@next/swc-win32-arm64-msvc@16.1.4':
+ resolution: {integrity: sha512-MCrXxrTSE7jPN1NyXJr39E+aNFBrQZtO154LoCz7n99FuKqJDekgxipoodLNWdQP7/DZ5tKMc/efybx1l159hw==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [win32]
+
'@next/swc-win32-x64-msvc@16.0.4':
resolution: {integrity: sha512-0Vy4g8SSeVkuU89g2OFHqGKM4rxsQtihGfenjx2tRckPrge5+gtFnRWGAAwvGXr0ty3twQvcnYjEyOrLHJ4JWA==}
engines: {node: '>= 10'}
@@ -1655,6 +1899,12 @@ packages:
cpu: [x64]
os: [win32]
+ '@next/swc-win32-x64-msvc@16.1.4':
+ resolution: {integrity: sha512-JSVlm9MDhmTXw/sO2PE/MRj+G6XOSMZB+BcZ0a7d6KwVFZVpkHcb2okyoYFBaco6LeiL53BBklRlOrDDbOeE5w==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+
'@nimpl/cache-redis@0.4.0':
resolution: {integrity: sha512-+e/wWC5zfuyV++skOUE8Mk6t+LQzX1U6GOq0ei7YbZTqBOUmli+TaTkRVm911OvyXGE9SPrElA/VMimcFX9a7Q==}
@@ -1863,6 +2113,23 @@ packages:
'@remix-run/node-fetch-server@0.9.0':
resolution: {integrity: sha512-SoLMv7dbH+njWzXnOY6fI08dFMI5+/dQ+vY3n8RnnbdG7MdJEgiP28Xj/xWlnRnED/aB6SFw56Zop+LbmaaKqA==}
+ '@robindoc/minisearch@3.7.2':
+ resolution: {integrity: sha512-nzMtWIhjWU94RQUL8DFG98WtvQeC6iQCc+YCDVho1FftkWtIRBU/thMoPfoG8HxUF7Jqc9PXQvPFgYPoEYLvdg==}
+ hasBin: true
+ peerDependencies:
+ tsx: '>= 1.0.0'
+ peerDependenciesMeta:
+ tsx:
+ optional: true
+
+ '@robindoc/next@3.7.2':
+ resolution: {integrity: sha512-PhFYOAQX++cCzAvM74jf+g49Hp8cSTIDickcVKzDwQyaytmvY6XeGLO6o1o63jrGLnhGLMivl5nhKowUANemRA==}
+ peerDependencies:
+ next: '>= 14.0.0'
+ react: '>= 18.3.0'
+ react-dom: '>= 18.3.0'
+ robindoc: '>= 3.0.0'
+
'@rolldown/pluginutils@1.0.0-beta.47':
resolution: {integrity: sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw==}
@@ -1976,6 +2243,27 @@ packages:
cpu: [x64]
os: [win32]
+ '@shikijs/core@3.21.0':
+ resolution: {integrity: sha512-AXSQu/2n1UIQekY8euBJlvFYZIw0PHY63jUzGbrOma4wPxzznJXTXkri+QcHeBNaFxiiOljKxxJkVSoB3PjbyA==}
+
+ '@shikijs/engine-javascript@3.21.0':
+ resolution: {integrity: sha512-ATwv86xlbmfD9n9gKRiwuPpWgPENAWCLwYCGz9ugTJlsO2kOzhOkvoyV/UD+tJ0uT7YRyD530x6ugNSffmvIiQ==}
+
+ '@shikijs/engine-oniguruma@3.21.0':
+ resolution: {integrity: sha512-OYknTCct6qiwpQDqDdf3iedRdzj6hFlOPv5hMvI+hkWfCKs5mlJ4TXziBG9nyabLwGulrUjHiCq3xCspSzErYQ==}
+
+ '@shikijs/langs@3.21.0':
+ resolution: {integrity: sha512-g6mn5m+Y6GBJ4wxmBYqalK9Sp0CFkUqfNzUy2pJglUginz6ZpWbaWjDB4fbQ/8SHzFjYbtU6Ddlp1pc+PPNDVA==}
+
+ '@shikijs/themes@3.21.0':
+ resolution: {integrity: sha512-BAE4cr9EDiZyYzwIHEk7JTBJ9CzlPuM4PchfcA5ao1dWXb25nv6hYsoDiBq2aZK9E3dlt3WB78uI96UESD+8Mw==}
+
+ '@shikijs/types@3.21.0':
+ resolution: {integrity: sha512-zGrWOxZ0/+0ovPY7PvBU2gIS9tmhSUUt30jAcNV0Bq0gb2S98gwfjIs1vxlmH5zM7/4YxLamT6ChlqqAJmPPjA==}
+
+ '@shikijs/vscode-textmate@10.0.2':
+ resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
+
'@sinclair/typebox@0.34.41':
resolution: {integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==}
@@ -2040,6 +2328,9 @@ packages:
'@types/estree@1.0.8':
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+ '@types/hast@3.0.4':
+ resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
+
'@types/istanbul-lib-coverage@2.0.6':
resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
@@ -2058,6 +2349,9 @@ packages:
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+ '@types/mdast@4.0.4':
+ resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
+
'@types/node@22.10.1':
resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==}
@@ -2067,20 +2361,34 @@ packages:
'@types/node@24.10.0':
resolution: {integrity: sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==}
+ '@types/node@25.0.8':
+ resolution: {integrity: sha512-powIePYMmC3ibL0UJ2i2s0WIbq6cg6UyVFQxSCpaPxxzAaziRfimGivjdF943sSGV6RADVbk0Nvlm5P/FB44Zg==}
+
'@types/react-dom@19.2.2':
resolution: {integrity: sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==}
peerDependencies:
'@types/react': ^19.2.0
+ '@types/react-dom@19.2.3':
+ resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
+ peerDependencies:
+ '@types/react': ^19.2.0
+
'@types/react@19.2.2':
resolution: {integrity: sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==}
+ '@types/react@19.2.8':
+ resolution: {integrity: sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==}
+
'@types/stack-utils@2.0.3':
resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==}
'@types/tough-cookie@4.0.5':
resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==}
+ '@types/unist@3.0.3':
+ resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
+
'@types/yargs-parser@21.0.3':
resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
@@ -2445,6 +2753,9 @@ packages:
caniuse-lite@1.0.30001757:
resolution: {integrity: sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==}
+ ccount@2.0.1:
+ resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
+
chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
@@ -2453,6 +2764,12 @@ packages:
resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
engines: {node: '>=10'}
+ character-entities-html4@2.1.0:
+ resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
+
+ character-entities-legacy@3.0.0:
+ resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
+
chokidar@4.0.3:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
@@ -2471,6 +2788,10 @@ packages:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'}
+ clsx@2.1.1:
+ resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
+ engines: {node: '>=6'}
+
cluster-key-slot@1.1.2:
resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==}
engines: {node: '>=0.10.0'}
@@ -2492,6 +2813,9 @@ packages:
colorjs.io@0.5.2:
resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==}
+ comma-separated-tokens@2.0.3:
+ resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
+
compressible@2.0.18:
resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==}
engines: {node: '>= 0.6'}
@@ -2503,6 +2827,11 @@ packages:
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+ contection@2.3.0:
+ resolution: {integrity: sha512-SvgdLv4Ynb3Abpmf53a8WqYMlCSrG6JHwJvxA5FZqfKYaWSP2aGzFjQ/q8Tyvb/Hbbt8JT7bgl9cyhTGPNmH2w==}
+ peerDependencies:
+ react: '>= 19.0.0'
+
content-disposition@0.5.4:
resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
engines: {node: '>= 0.6'}
@@ -2615,12 +2944,32 @@ packages:
resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==}
engines: {node: '>=8'}
+ devlop@1.1.0:
+ resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
+
dom-accessibility-api@0.5.16:
resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==}
dom-accessibility-api@0.6.3:
resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==}
+ dom-serializer@2.0.0:
+ resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
+
+ domelementtype@2.3.0:
+ resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
+
+ domhandler@5.0.3:
+ resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
+ engines: {node: '>= 4'}
+
+ domutils@3.2.2:
+ resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
+
+ dot-prop@10.1.0:
+ resolution: {integrity: sha512-MVUtAugQMOff5RnBy2d9N31iG0lNwg1qAoAOn7pOK5wf94WIaE3My2p3uwTQuvS2AcqchkcR3bHByjaM0mmi7Q==}
+ engines: {node: '>=20'}
+
dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
@@ -2652,6 +3001,10 @@ packages:
resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
engines: {node: '>= 0.8'}
+ entities@4.5.0:
+ resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
+ engines: {node: '>=0.12'}
+
entities@6.0.1:
resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
engines: {node: '>=0.12'}
@@ -2682,6 +3035,11 @@ packages:
engines: {node: '>=18'}
hasBin: true
+ esbuild@0.27.2:
+ resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==}
+ engines: {node: '>=18'}
+ hasBin: true
+
escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
@@ -2791,6 +3149,10 @@ packages:
resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==}
engines: {node: '>= 0.10.0'}
+ extend-shallow@2.0.1:
+ resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==}
+ engines: {node: '>=0.10.0'}
+
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
@@ -2900,6 +3262,12 @@ packages:
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
engines: {node: '>=10'}
+ get-tsconfig@4.13.0:
+ resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==}
+
+ github-slugger@2.0.0:
+ resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==}
+
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
@@ -2933,6 +3301,10 @@ packages:
graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+ gray-matter@4.0.3:
+ resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==}
+ engines: {node: '>=6.0'}
+
has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
@@ -2945,10 +3317,19 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
+ hast-util-to-html@9.0.5:
+ resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==}
+
+ hast-util-whitespace@3.0.0:
+ resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
+
hosted-git-info@6.1.3:
resolution: {integrity: sha512-HVJyzUrLIL1c0QmviVh5E8VGyUS7xCFPS6yydaVd1UegW+ibV/CohqTH9MkOLDp5o+rb82DMo77PTuc9F/8GKw==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+ html-dom-parser@5.1.2:
+ resolution: {integrity: sha512-9nD3Rj3/FuQt83AgIa1Y3ruzspwFFA54AJbQnohXN+K6fL1/bhcDQJJY5Ne4L4A163ADQFVESd/0TLyNoV0mfg==}
+
html-encoding-sniffer@4.0.0:
resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==}
engines: {node: '>=18'}
@@ -2956,6 +3337,21 @@ packages:
html-escaper@2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
+ html-react-parser@5.2.11:
+ resolution: {integrity: sha512-WnSQVn/D1UTj64nSz5y8MriL+MrbsZH80Ytr1oqKqs8DGZnphWY1R1pl3t7TY3rpqTSu+FHA21P80lrsmrdNBA==}
+ peerDependencies:
+ '@types/react': 0.14 || 15 || 16 || 17 || 18 || 19
+ react: 0.14 || 15 || 16 || 17 || 18 || 19
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ html-void-elements@3.0.0:
+ resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
+
+ htmlparser2@10.0.0:
+ resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==}
+
http-errors@2.0.0:
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
engines: {node: '>= 0.8'}
@@ -3024,6 +3420,9 @@ packages:
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+ inline-style-parser@0.2.7:
+ resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
+
ioredis@5.8.2:
resolution: {integrity: sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q==}
engines: {node: '>=12.22.0'}
@@ -3039,6 +3438,10 @@ packages:
resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
engines: {node: '>= 0.4'}
+ is-extendable@0.1.1:
+ resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
+ engines: {node: '>=0.10.0'}
+
is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
@@ -3296,6 +3699,10 @@ packages:
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+ kind-of@6.0.3:
+ resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
+ engines: {node: '>=0.10.0'}
+
leven@3.1.0:
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
engines: {node: '>=6'}
@@ -3362,10 +3769,18 @@ packages:
makeerror@1.0.12:
resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==}
+ marked@17.0.1:
+ resolution: {integrity: sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==}
+ engines: {node: '>= 20'}
+ hasBin: true
+
math-intrinsics@1.1.0:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
+ mdast-util-to-hast@13.2.1:
+ resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==}
+
media-typer@0.3.0:
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
engines: {node: '>= 0.6'}
@@ -3384,6 +3799,21 @@ packages:
resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
engines: {node: '>= 0.6'}
+ micromark-util-character@2.1.1:
+ resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
+
+ micromark-util-encode@2.0.1:
+ resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
+
+ micromark-util-sanitize-uri@2.0.1:
+ resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
+
+ micromark-util-symbol@2.0.1:
+ resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
+
+ micromark-util-types@2.0.2:
+ resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==}
+
micromatch@4.0.8:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
@@ -3424,6 +3854,9 @@ packages:
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
engines: {node: '>=16 || 14 >=14.17'}
+ minisearch@7.2.0:
+ resolution: {integrity: sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==}
+
morgan@1.10.1:
resolution: {integrity: sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==}
engines: {node: '>= 0.8.0'}
@@ -3501,6 +3934,27 @@ packages:
sass:
optional: true
+ next@16.1.4:
+ resolution: {integrity: sha512-gKSecROqisnV7Buen5BfjmXAm7Xlpx9o2ueVQRo5DxQcjC8d330dOM1xiGWc2k3Dcnz0In3VybyRPOsudwgiqQ==}
+ engines: {node: '>=20.9.0'}
+ hasBin: true
+ peerDependencies:
+ '@opentelemetry/api': ^1.1.0
+ '@playwright/test': ^1.51.1
+ babel-plugin-react-compiler: '*'
+ react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
+ react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
+ sass: ^1.3.0
+ peerDependenciesMeta:
+ '@opentelemetry/api':
+ optional: true
+ '@playwright/test':
+ optional: true
+ babel-plugin-react-compiler:
+ optional: true
+ sass:
+ optional: true
+
node-addon-api@7.1.1:
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
@@ -3564,6 +4018,12 @@ packages:
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
engines: {node: '>=6'}
+ oniguruma-parser@0.12.1:
+ resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==}
+
+ oniguruma-to-es@4.3.4:
+ resolution: {integrity: sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA==}
+
optionator@0.9.4:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'}
@@ -3705,6 +4165,9 @@ packages:
resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==}
engines: {node: '>=10'}
+ property-information@7.1.0:
+ resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
+
proxy-addr@2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'}
@@ -3736,12 +4199,20 @@ packages:
peerDependencies:
react: ^19.2.0
+ react-dom@19.2.3:
+ resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==}
+ peerDependencies:
+ react: ^19.2.3
+
react-is@17.0.2:
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
react-is@18.3.1:
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
+ react-property@2.0.2:
+ resolution: {integrity: sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==}
+
react-refresh@0.14.2:
resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
engines: {node: '>=0.10.0'}
@@ -3764,6 +4235,10 @@ packages:
resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==}
engines: {node: '>=0.10.0'}
+ react@19.2.3:
+ resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==}
+ engines: {node: '>=0.10.0'}
+
readdirp@4.1.2:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
@@ -3791,6 +4266,15 @@ packages:
regenerate@1.4.2:
resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==}
+ regex-recursion@6.0.2:
+ resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==}
+
+ regex-utilities@2.3.0:
+ resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==}
+
+ regex@6.1.0:
+ resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==}
+
regexpu-core@6.4.0:
resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==}
engines: {node: '>=4'}
@@ -3818,6 +4302,9 @@ packages:
resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
engines: {node: '>=8'}
+ resolve-pkg-maps@1.0.0:
+ resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+
resolve@1.22.11:
resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==}
engines: {node: '>= 0.4'}
@@ -3831,6 +4318,12 @@ packages:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ robindoc@3.7.2:
+ resolution: {integrity: sha512-D2ZzYd7goA2ryXVIoH2r7re453naflxPFi5PYprPwAh350DoxTaohiQqrdyN3wSTObrSKNDX6M4/hCDc2Dya2w==}
+ peerDependencies:
+ react: '>= 18.3.0'
+ react-dom: '>= 18.3.0'
+
rollup@4.53.3:
resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@@ -3968,6 +4461,11 @@ packages:
engines: {node: '>=14.0.0'}
hasBin: true
+ sass@1.97.2:
+ resolution: {integrity: sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+
saxes@6.0.0:
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
engines: {node: '>=v12.22.7'}
@@ -3975,6 +4473,10 @@ packages:
scheduler@0.27.0:
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
+ section-matter@1.0.0:
+ resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
+ engines: {node: '>=4'}
+
semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
hasBin: true
@@ -4014,6 +4516,9 @@ packages:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'}
+ shiki@3.21.0:
+ resolution: {integrity: sha512-N65B/3bqL/TI2crrXr+4UivctrAGEjmsib5rPMMPpFp1xAx/w03v8WZ9RDDFYteXoEgY7qZ4HGgl5KBIu1153w==}
+
side-channel-list@1.0.0:
resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
engines: {node: '>= 0.4'}
@@ -4055,6 +4560,9 @@ packages:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
+ space-separated-tokens@2.0.2:
+ resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
+
spdx-correct@3.2.0:
resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
@@ -4097,6 +4605,9 @@ packages:
resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
engines: {node: '>=12'}
+ stringify-entities@4.0.4:
+ resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
+
strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
@@ -4105,6 +4616,10 @@ packages:
resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==}
engines: {node: '>=12'}
+ strip-bom-string@1.0.0:
+ resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==}
+ engines: {node: '>=0.10.0'}
+
strip-bom@4.0.0:
resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==}
engines: {node: '>=8'}
@@ -4124,6 +4639,12 @@ packages:
strip-literal@3.1.0:
resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==}
+ style-to-js@1.1.21:
+ resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==}
+
+ style-to-object@1.0.14:
+ resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==}
+
styled-jsx@5.1.6:
resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
engines: {node: '>= 12.0.0'}
@@ -4164,6 +4685,10 @@ packages:
resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==}
engines: {node: ^14.18.0 || >=16.0.0}
+ tagged-tag@1.0.0:
+ resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==}
+ engines: {node: '>=20'}
+
test-exclude@6.0.0:
resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==}
engines: {node: '>=8'}
@@ -4202,6 +4727,9 @@ packages:
resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==}
engines: {node: '>=18'}
+ trim-lines@3.0.1:
+ resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
+
ts-api-utils@2.1.0:
resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==}
engines: {node: '>=18.12'}
@@ -4221,6 +4749,11 @@ packages:
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+ tsx@4.21.0:
+ resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==}
+ engines: {node: '>=18.0.0'}
+ hasBin: true
+
turbo-stream@3.1.0:
resolution: {integrity: sha512-tVI25WEXl4fckNEmrq70xU1XumxUwEx/FZD5AgEcV8ri7Wvrg2o7GEq8U7htrNx3CajciGm+kDyhRf5JB6t7/A==}
@@ -4236,6 +4769,10 @@ packages:
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
engines: {node: '>=10'}
+ type-fest@5.4.1:
+ resolution: {integrity: sha512-xygQcmneDyzsEuKZrFbRMne5HDqMs++aFzefrJTgEIKjQ3rekM+RPfFCVq2Gp1VIDqddoYeppCj4Pcb+RZW0GQ==}
+ engines: {node: '>=20'}
+
type-is@1.6.18:
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
engines: {node: '>= 0.6'}
@@ -4283,6 +4820,21 @@ packages:
unicode-segmenter@0.14.0:
resolution: {integrity: sha512-AH4lhPCJANUnSLEKnM4byboctePJzltF4xj8b+NbNiYeAkAXGh7px2K/4NANFp7dnr6+zB3e6HLu8Jj8SKyvYg==}
+ unist-util-is@6.0.1:
+ resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
+
+ unist-util-position@5.0.0:
+ resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
+
+ unist-util-stringify-position@4.0.0:
+ resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
+
+ unist-util-visit-parents@6.0.2:
+ resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}
+
+ unist-util-visit@5.1.0:
+ resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==}
+
unpipe@1.0.0:
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
engines: {node: '>= 0.8'}
@@ -4333,6 +4885,12 @@ packages:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
+ vfile-message@4.0.3:
+ resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
+
+ vfile@6.0.3:
+ resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
+
vite-node@3.2.4:
resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
@@ -4535,6 +5093,9 @@ packages:
zod@3.25.76:
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
+ zwitch@2.0.4:
+ resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
+
snapshots:
'@adobe/css-tools@4.4.4': {}
@@ -5444,81 +6005,159 @@ snapshots:
'@esbuild/aix-ppc64@0.25.12':
optional: true
+ '@esbuild/aix-ppc64@0.27.2':
+ optional: true
+
'@esbuild/android-arm64@0.25.12':
optional: true
+ '@esbuild/android-arm64@0.27.2':
+ optional: true
+
'@esbuild/android-arm@0.25.12':
optional: true
+ '@esbuild/android-arm@0.27.2':
+ optional: true
+
'@esbuild/android-x64@0.25.12':
optional: true
+ '@esbuild/android-x64@0.27.2':
+ optional: true
+
'@esbuild/darwin-arm64@0.25.12':
optional: true
+ '@esbuild/darwin-arm64@0.27.2':
+ optional: true
+
'@esbuild/darwin-x64@0.25.12':
optional: true
+ '@esbuild/darwin-x64@0.27.2':
+ optional: true
+
'@esbuild/freebsd-arm64@0.25.12':
optional: true
+ '@esbuild/freebsd-arm64@0.27.2':
+ optional: true
+
'@esbuild/freebsd-x64@0.25.12':
optional: true
+ '@esbuild/freebsd-x64@0.27.2':
+ optional: true
+
'@esbuild/linux-arm64@0.25.12':
optional: true
+ '@esbuild/linux-arm64@0.27.2':
+ optional: true
+
'@esbuild/linux-arm@0.25.12':
optional: true
+ '@esbuild/linux-arm@0.27.2':
+ optional: true
+
'@esbuild/linux-ia32@0.25.12':
optional: true
+ '@esbuild/linux-ia32@0.27.2':
+ optional: true
+
'@esbuild/linux-loong64@0.25.12':
optional: true
+ '@esbuild/linux-loong64@0.27.2':
+ optional: true
+
'@esbuild/linux-mips64el@0.25.12':
optional: true
+ '@esbuild/linux-mips64el@0.27.2':
+ optional: true
+
'@esbuild/linux-ppc64@0.25.12':
optional: true
+ '@esbuild/linux-ppc64@0.27.2':
+ optional: true
+
'@esbuild/linux-riscv64@0.25.12':
optional: true
+ '@esbuild/linux-riscv64@0.27.2':
+ optional: true
+
'@esbuild/linux-s390x@0.25.12':
optional: true
+ '@esbuild/linux-s390x@0.27.2':
+ optional: true
+
'@esbuild/linux-x64@0.25.12':
optional: true
+ '@esbuild/linux-x64@0.27.2':
+ optional: true
+
'@esbuild/netbsd-arm64@0.25.12':
optional: true
+ '@esbuild/netbsd-arm64@0.27.2':
+ optional: true
+
'@esbuild/netbsd-x64@0.25.12':
optional: true
+ '@esbuild/netbsd-x64@0.27.2':
+ optional: true
+
'@esbuild/openbsd-arm64@0.25.12':
optional: true
+ '@esbuild/openbsd-arm64@0.27.2':
+ optional: true
+
'@esbuild/openbsd-x64@0.25.12':
optional: true
+ '@esbuild/openbsd-x64@0.27.2':
+ optional: true
+
'@esbuild/openharmony-arm64@0.25.12':
optional: true
+ '@esbuild/openharmony-arm64@0.27.2':
+ optional: true
+
'@esbuild/sunos-x64@0.25.12':
optional: true
+ '@esbuild/sunos-x64@0.27.2':
+ optional: true
+
'@esbuild/win32-arm64@0.25.12':
optional: true
+ '@esbuild/win32-arm64@0.27.2':
+ optional: true
+
'@esbuild/win32-ia32@0.25.12':
optional: true
+ '@esbuild/win32-ia32@0.27.2':
+ optional: true
+
'@esbuild/win32-x64@0.25.12':
optional: true
+ '@esbuild/win32-x64@0.27.2':
+ optional: true
+
'@eslint-community/eslint-utils@4.9.0(eslint@9.39.1)':
dependencies:
eslint: 9.39.1
@@ -5916,54 +6555,80 @@ snapshots:
'@next/env@16.0.7': {}
+ '@next/env@16.1.4': {}
+
'@next/swc-darwin-arm64@16.0.4':
optional: true
'@next/swc-darwin-arm64@16.0.7':
optional: true
+ '@next/swc-darwin-arm64@16.1.4':
+ optional: true
+
'@next/swc-darwin-x64@16.0.4':
optional: true
'@next/swc-darwin-x64@16.0.7':
optional: true
+ '@next/swc-darwin-x64@16.1.4':
+ optional: true
+
'@next/swc-linux-arm64-gnu@16.0.4':
optional: true
'@next/swc-linux-arm64-gnu@16.0.7':
optional: true
+ '@next/swc-linux-arm64-gnu@16.1.4':
+ optional: true
+
'@next/swc-linux-arm64-musl@16.0.4':
optional: true
'@next/swc-linux-arm64-musl@16.0.7':
optional: true
+ '@next/swc-linux-arm64-musl@16.1.4':
+ optional: true
+
'@next/swc-linux-x64-gnu@16.0.4':
optional: true
'@next/swc-linux-x64-gnu@16.0.7':
optional: true
+ '@next/swc-linux-x64-gnu@16.1.4':
+ optional: true
+
'@next/swc-linux-x64-musl@16.0.4':
optional: true
'@next/swc-linux-x64-musl@16.0.7':
optional: true
+ '@next/swc-linux-x64-musl@16.1.4':
+ optional: true
+
'@next/swc-win32-arm64-msvc@16.0.4':
optional: true
'@next/swc-win32-arm64-msvc@16.0.7':
optional: true
+ '@next/swc-win32-arm64-msvc@16.1.4':
+ optional: true
+
'@next/swc-win32-x64-msvc@16.0.4':
optional: true
'@next/swc-win32-x64-msvc@16.0.7':
optional: true
+ '@next/swc-win32-x64-msvc@16.1.4':
+ optional: true
+
'@nimpl/cache-redis@0.4.0':
dependencies:
chalk: 4.1.2
@@ -6085,7 +6750,7 @@ snapshots:
'@pkgr/core@0.2.9': {}
- '@react-router/dev@7.9.6(@react-router/serve@7.9.6(react-router@7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@5.9.3))(@types/node@22.10.1)(@vitejs/plugin-rsc@0.5.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3)))(react-router@7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(sass-embedded@1.93.3)(sass@1.93.3)(typescript@5.9.3)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3))':
+ '@react-router/dev@7.9.6(@react-router/serve@7.9.6(react-router@7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@5.9.3))(@types/node@22.10.1)(@vitejs/plugin-rsc@0.5.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)))(react-router@7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)(typescript@5.9.3)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0))':
dependencies:
'@babel/core': 7.28.5
'@babel/generator': 7.28.5
@@ -6115,11 +6780,11 @@ snapshots:
semver: 7.7.3
tinyglobby: 0.2.15
valibot: 1.2.0(typescript@5.9.3)
- vite: 7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3)
- vite-node: 3.2.4(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3)
+ vite: 7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)
+ vite-node: 3.2.4(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)
optionalDependencies:
'@react-router/serve': 7.9.6(react-router@7.9.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@5.9.3)
- '@vitejs/plugin-rsc': 0.5.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3))
+ '@vitejs/plugin-rsc': 0.5.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0))
typescript: 5.9.3
transitivePeerDependencies:
- '@types/node'
@@ -6191,6 +6856,21 @@ snapshots:
'@remix-run/node-fetch-server@0.9.0': {}
+ '@robindoc/minisearch@3.7.2(tsx@4.21.0)':
+ dependencies:
+ gray-matter: 4.0.3
+ marked: 17.0.1
+ minisearch: 7.2.0
+ optionalDependencies:
+ tsx: 4.21.0
+
+ '@robindoc/next@3.7.2(next@16.1.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.2))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(robindoc@3.7.2(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))':
+ dependencies:
+ next: 16.1.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.2)
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ robindoc: 3.7.2(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+
'@rolldown/pluginutils@1.0.0-beta.47': {}
'@rollup/rollup-android-arm-eabi@4.53.3':
@@ -6259,6 +6939,39 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.53.3':
optional: true
+ '@shikijs/core@3.21.0':
+ dependencies:
+ '@shikijs/types': 3.21.0
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.4
+ hast-util-to-html: 9.0.5
+
+ '@shikijs/engine-javascript@3.21.0':
+ dependencies:
+ '@shikijs/types': 3.21.0
+ '@shikijs/vscode-textmate': 10.0.2
+ oniguruma-to-es: 4.3.4
+
+ '@shikijs/engine-oniguruma@3.21.0':
+ dependencies:
+ '@shikijs/types': 3.21.0
+ '@shikijs/vscode-textmate': 10.0.2
+
+ '@shikijs/langs@3.21.0':
+ dependencies:
+ '@shikijs/types': 3.21.0
+
+ '@shikijs/themes@3.21.0':
+ dependencies:
+ '@shikijs/types': 3.21.0
+
+ '@shikijs/types@3.21.0':
+ dependencies:
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.4
+
+ '@shikijs/vscode-textmate@10.0.2': {}
+
'@sinclair/typebox@0.34.41': {}
'@sinonjs/commons@3.0.1':
@@ -6340,6 +7053,10 @@ snapshots:
'@types/estree@1.0.8': {}
+ '@types/hast@3.0.4':
+ dependencies:
+ '@types/unist': 3.0.3
+
'@types/istanbul-lib-coverage@2.0.6': {}
'@types/istanbul-lib-report@3.0.3':
@@ -6363,6 +7080,10 @@ snapshots:
'@types/json-schema@7.0.15': {}
+ '@types/mdast@4.0.4':
+ dependencies:
+ '@types/unist': 3.0.3
+
'@types/node@22.10.1':
dependencies:
undici-types: 6.20.0
@@ -6375,18 +7096,32 @@ snapshots:
dependencies:
undici-types: 7.16.0
+ '@types/node@25.0.8':
+ dependencies:
+ undici-types: 7.16.0
+
'@types/react-dom@19.2.2(@types/react@19.2.2)':
dependencies:
'@types/react': 19.2.2
+ '@types/react-dom@19.2.3(@types/react@19.2.8)':
+ dependencies:
+ '@types/react': 19.2.8
+
'@types/react@19.2.2':
dependencies:
csstype: 3.2.3
+ '@types/react@19.2.8':
+ dependencies:
+ csstype: 3.2.3
+
'@types/stack-utils@2.0.3': {}
'@types/tough-cookie@4.0.5': {}
+ '@types/unist@3.0.3': {}
+
'@types/yargs-parser@21.0.3': {}
'@types/yargs@17.0.35':
@@ -6547,7 +7282,7 @@ snapshots:
'@unrs/resolver-binding-win32-x64-msvc@1.11.1':
optional: true
- '@vitejs/plugin-react@5.1.1(vite@7.2.2(@types/node@22.19.1)(sass-embedded@1.93.3)(sass@1.93.3))':
+ '@vitejs/plugin-react@5.1.1(vite@7.2.2(@types/node@22.19.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0))':
dependencies:
'@babel/core': 7.28.5
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5)
@@ -6555,11 +7290,11 @@ snapshots:
'@rolldown/pluginutils': 1.0.0-beta.47
'@types/babel__core': 7.20.5
react-refresh: 0.18.0
- vite: 7.2.2(@types/node@22.19.1)(sass-embedded@1.93.3)(sass@1.93.3)
+ vite: 7.2.2(@types/node@22.19.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)
transitivePeerDependencies:
- supports-color
- '@vitejs/plugin-rsc@0.5.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3))':
+ '@vitejs/plugin-rsc@0.5.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0))':
dependencies:
'@remix-run/node-fetch-server': 0.12.0
es-module-lexer: 1.7.0
@@ -6570,8 +7305,8 @@ snapshots:
react-dom: 19.2.0(react@19.2.0)
strip-literal: 3.1.0
turbo-stream: 3.1.0
- vite: 7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3)
- vitefu: 1.1.1(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3))
+ vite: 7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)
+ vitefu: 1.1.1(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0))
accepts@1.3.8:
dependencies:
@@ -6793,6 +7528,8 @@ snapshots:
caniuse-lite@1.0.30001757: {}
+ ccount@2.0.1: {}
+
chalk@4.1.2:
dependencies:
ansi-styles: 4.3.0
@@ -6800,6 +7537,10 @@ snapshots:
char-regex@1.0.2: {}
+ character-entities-html4@2.1.0: {}
+
+ character-entities-legacy@3.0.0: {}
+
chokidar@4.0.3:
dependencies:
readdirp: 4.1.2
@@ -6816,6 +7557,8 @@ snapshots:
strip-ansi: 6.0.1
wrap-ansi: 7.0.0
+ clsx@2.1.1: {}
+
cluster-key-slot@1.1.2: {}
co@4.6.0: {}
@@ -6830,6 +7573,8 @@ snapshots:
colorjs.io@0.5.2: {}
+ comma-separated-tokens@2.0.3: {}
+
compressible@2.0.18:
dependencies:
mime-db: 1.54.0
@@ -6848,6 +7593,10 @@ snapshots:
concat-map@0.0.1: {}
+ contection@2.3.0(react@19.2.3):
+ dependencies:
+ react: 19.2.3
+
content-disposition@0.5.4:
dependencies:
safe-buffer: 5.2.1
@@ -6923,10 +7672,36 @@ snapshots:
detect-newline@3.1.0: {}
+ devlop@1.1.0:
+ dependencies:
+ dequal: 2.0.3
+
dom-accessibility-api@0.5.16: {}
dom-accessibility-api@0.6.3: {}
+ dom-serializer@2.0.0:
+ dependencies:
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+ entities: 4.5.0
+
+ domelementtype@2.3.0: {}
+
+ domhandler@5.0.3:
+ dependencies:
+ domelementtype: 2.3.0
+
+ domutils@3.2.2:
+ dependencies:
+ dom-serializer: 2.0.0
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+
+ dot-prop@10.1.0:
+ dependencies:
+ type-fest: 5.4.1
+
dunder-proto@1.0.1:
dependencies:
call-bind-apply-helpers: 1.0.2
@@ -6949,6 +7724,8 @@ snapshots:
encodeurl@2.0.0: {}
+ entities@4.5.0: {}
+
entities@6.0.1: {}
err-code@2.0.3: {}
@@ -6996,6 +7773,35 @@ snapshots:
'@esbuild/win32-ia32': 0.25.12
'@esbuild/win32-x64': 0.25.12
+ esbuild@0.27.2:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.27.2
+ '@esbuild/android-arm': 0.27.2
+ '@esbuild/android-arm64': 0.27.2
+ '@esbuild/android-x64': 0.27.2
+ '@esbuild/darwin-arm64': 0.27.2
+ '@esbuild/darwin-x64': 0.27.2
+ '@esbuild/freebsd-arm64': 0.27.2
+ '@esbuild/freebsd-x64': 0.27.2
+ '@esbuild/linux-arm': 0.27.2
+ '@esbuild/linux-arm64': 0.27.2
+ '@esbuild/linux-ia32': 0.27.2
+ '@esbuild/linux-loong64': 0.27.2
+ '@esbuild/linux-mips64el': 0.27.2
+ '@esbuild/linux-ppc64': 0.27.2
+ '@esbuild/linux-riscv64': 0.27.2
+ '@esbuild/linux-s390x': 0.27.2
+ '@esbuild/linux-x64': 0.27.2
+ '@esbuild/netbsd-arm64': 0.27.2
+ '@esbuild/netbsd-x64': 0.27.2
+ '@esbuild/openbsd-arm64': 0.27.2
+ '@esbuild/openbsd-x64': 0.27.2
+ '@esbuild/openharmony-arm64': 0.27.2
+ '@esbuild/sunos-x64': 0.27.2
+ '@esbuild/win32-arm64': 0.27.2
+ '@esbuild/win32-ia32': 0.27.2
+ '@esbuild/win32-x64': 0.27.2
+
escalade@3.2.0: {}
escape-html@1.0.3: {}
@@ -7152,6 +7958,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ extend-shallow@2.0.1:
+ dependencies:
+ is-extendable: 0.1.1
+
fast-deep-equal@3.1.3: {}
fast-diff@1.3.0: {}
@@ -7261,6 +8071,12 @@ snapshots:
get-stream@6.0.1: {}
+ get-tsconfig@4.13.0:
+ dependencies:
+ resolve-pkg-maps: 1.0.0
+
+ github-slugger@2.0.0: {}
+
glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
@@ -7297,6 +8113,13 @@ snapshots:
graphemer@1.4.0: {}
+ gray-matter@4.0.3:
+ dependencies:
+ js-yaml: 3.14.2
+ kind-of: 6.0.3
+ section-matter: 1.0.0
+ strip-bom-string: 1.0.0
+
has-flag@4.0.0: {}
has-symbols@1.1.0: {}
@@ -7305,16 +8128,58 @@ snapshots:
dependencies:
function-bind: 1.1.2
+ hast-util-to-html@9.0.5:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ ccount: 2.0.1
+ comma-separated-tokens: 2.0.3
+ hast-util-whitespace: 3.0.0
+ html-void-elements: 3.0.0
+ mdast-util-to-hast: 13.2.1
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
+ stringify-entities: 4.0.4
+ zwitch: 2.0.4
+
+ hast-util-whitespace@3.0.0:
+ dependencies:
+ '@types/hast': 3.0.4
+
hosted-git-info@6.1.3:
dependencies:
lru-cache: 7.18.3
+ html-dom-parser@5.1.2:
+ dependencies:
+ domhandler: 5.0.3
+ htmlparser2: 10.0.0
+
html-encoding-sniffer@4.0.0:
dependencies:
whatwg-encoding: 3.1.1
html-escaper@2.0.2: {}
+ html-react-parser@5.2.11(@types/react@19.2.8)(react@19.2.3):
+ dependencies:
+ domhandler: 5.0.3
+ html-dom-parser: 5.1.2
+ react: 19.2.3
+ react-property: 2.0.2
+ style-to-js: 1.1.21
+ optionalDependencies:
+ '@types/react': 19.2.8
+
+ html-void-elements@3.0.0: {}
+
+ htmlparser2@10.0.0:
+ dependencies:
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+ domutils: 3.2.2
+ entities: 6.0.1
+
http-errors@2.0.0:
dependencies:
depd: 2.0.0
@@ -7384,6 +8249,8 @@ snapshots:
inherits@2.0.4: {}
+ inline-style-parser@0.2.7: {}
+
ioredis@5.8.2:
dependencies:
'@ioredis/commands': 1.4.0
@@ -7406,6 +8273,8 @@ snapshots:
dependencies:
hasown: 2.0.2
+ is-extendable@0.1.1: {}
+
is-extglob@2.1.1: {}
is-fullwidth-code-point@3.0.0: {}
@@ -7884,6 +8753,8 @@ snapshots:
dependencies:
json-buffer: 3.0.1
+ kind-of@6.0.3: {}
+
leven@3.1.0: {}
levn@0.4.1:
@@ -7937,8 +8808,22 @@ snapshots:
dependencies:
tmpl: 1.0.5
+ marked@17.0.1: {}
+
math-intrinsics@1.1.0: {}
+ mdast-util-to-hast@13.2.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ '@ungap/structured-clone': 1.3.0
+ devlop: 1.1.0
+ micromark-util-sanitize-uri: 2.0.1
+ trim-lines: 3.0.1
+ unist-util-position: 5.0.0
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+
media-typer@0.3.0: {}
merge-descriptors@1.0.3: {}
@@ -7949,6 +8834,23 @@ snapshots:
methods@1.1.2: {}
+ micromark-util-character@2.1.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-encode@2.0.1: {}
+
+ micromark-util-sanitize-uri@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-encode: 2.0.1
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-symbol@2.0.1: {}
+
+ micromark-util-types@2.0.2: {}
+
micromatch@4.0.8:
dependencies:
braces: 3.0.3
@@ -7978,6 +8880,8 @@ snapshots:
minipass@7.1.2: {}
+ minisearch@7.2.0: {}
+
morgan@1.10.1:
dependencies:
basic-auth: 2.0.1
@@ -8004,14 +8908,14 @@ snapshots:
negotiator@0.6.4: {}
- next@16.0.4(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.93.3):
+ next@16.0.4(react-dom@19.2.3(react@19.2.0))(react@19.2.0)(sass@1.97.2):
dependencies:
'@next/env': 16.0.4
'@swc/helpers': 0.5.15
caniuse-lite: 1.0.30001757
postcss: 8.4.31
react: 19.2.0
- react-dom: 19.2.0(react@19.2.0)
+ react-dom: 19.2.3(react@19.2.0)
styled-jsx: 5.1.6(react@19.2.0)
optionalDependencies:
'@next/swc-darwin-arm64': 16.0.4
@@ -8022,13 +8926,13 @@ snapshots:
'@next/swc-linux-x64-musl': 16.0.4
'@next/swc-win32-arm64-msvc': 16.0.4
'@next/swc-win32-x64-msvc': 16.0.4
- sass: 1.93.3
+ sass: 1.97.2
sharp: 0.34.5
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
- next@16.0.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.93.3):
+ next@16.0.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sass@1.97.2):
dependencies:
'@next/env': 16.0.7
'@swc/helpers': 0.5.15
@@ -8046,7 +8950,32 @@ snapshots:
'@next/swc-linux-x64-musl': 16.0.7
'@next/swc-win32-arm64-msvc': 16.0.7
'@next/swc-win32-x64-msvc': 16.0.7
- sass: 1.93.3
+ sass: 1.97.2
+ sharp: 0.34.5
+ transitivePeerDependencies:
+ - '@babel/core'
+ - babel-plugin-macros
+
+ next@16.1.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(sass@1.97.2):
+ dependencies:
+ '@next/env': 16.1.4
+ '@swc/helpers': 0.5.15
+ baseline-browser-mapping: 2.8.31
+ caniuse-lite: 1.0.30001757
+ postcss: 8.4.31
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ styled-jsx: 5.1.6(react@19.2.3)
+ optionalDependencies:
+ '@next/swc-darwin-arm64': 16.1.4
+ '@next/swc-darwin-x64': 16.1.4
+ '@next/swc-linux-arm64-gnu': 16.1.4
+ '@next/swc-linux-arm64-musl': 16.1.4
+ '@next/swc-linux-x64-gnu': 16.1.4
+ '@next/swc-linux-x64-musl': 16.1.4
+ '@next/swc-win32-arm64-msvc': 16.1.4
+ '@next/swc-win32-x64-msvc': 16.1.4
+ sass: 1.97.2
sharp: 0.34.5
transitivePeerDependencies:
- '@babel/core'
@@ -8114,6 +9043,14 @@ snapshots:
dependencies:
mimic-fn: 2.1.0
+ oniguruma-parser@0.12.1: {}
+
+ oniguruma-to-es@4.3.4:
+ dependencies:
+ oniguruma-parser: 0.12.1
+ regex: 6.1.0
+ regex-recursion: 6.0.2
+
optionator@0.9.4:
dependencies:
deep-is: 0.1.4
@@ -8240,6 +9177,8 @@ snapshots:
err-code: 2.0.3
retry: 0.12.0
+ property-information@7.1.0: {}
+
proxy-addr@2.0.7:
dependencies:
forwarded: 0.2.0
@@ -8269,10 +9208,22 @@ snapshots:
react: 19.2.0
scheduler: 0.27.0
+ react-dom@19.2.3(react@19.2.0):
+ dependencies:
+ react: 19.2.0
+ scheduler: 0.27.0
+
+ react-dom@19.2.3(react@19.2.3):
+ dependencies:
+ react: 19.2.3
+ scheduler: 0.27.0
+
react-is@17.0.2: {}
react-is@18.3.1: {}
+ react-property@2.0.2: {}
+
react-refresh@0.14.2: {}
react-refresh@0.18.0: {}
@@ -8285,8 +9236,18 @@ snapshots:
optionalDependencies:
react-dom: 19.2.0(react@19.2.0)
+ react-router@7.9.6(react-dom@19.2.3(react@19.2.0))(react@19.2.0):
+ dependencies:
+ cookie: 1.1.1
+ react: 19.2.0
+ set-cookie-parser: 2.7.2
+ optionalDependencies:
+ react-dom: 19.2.3(react@19.2.0)
+
react@19.2.0: {}
+ react@19.2.3: {}
+
readdirp@4.1.2: {}
redent@3.0.0:
@@ -8314,6 +9275,16 @@ snapshots:
regenerate@1.4.2: {}
+ regex-recursion@6.0.2:
+ dependencies:
+ regex-utilities: 2.3.0
+
+ regex-utilities@2.3.0: {}
+
+ regex@6.1.0:
+ dependencies:
+ regex-utilities: 2.3.0
+
regexpu-core@6.4.0:
dependencies:
regenerate: 1.4.2
@@ -8339,6 +9310,8 @@ snapshots:
resolve-from@5.0.0: {}
+ resolve-pkg-maps@1.0.0: {}
+
resolve@1.22.11:
dependencies:
is-core-module: 2.16.1
@@ -8349,6 +9322,21 @@ snapshots:
reusify@1.1.0: {}
+ robindoc@3.7.2(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ dependencies:
+ clsx: 2.1.1
+ dot-prop: 10.1.0
+ github-slugger: 2.0.0
+ gray-matter: 4.0.3
+ html-react-parser: 5.2.11(@types/react@19.2.8)(react@19.2.3)
+ marked: 17.0.1
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ shiki: 3.21.0
+ tinyglobby: 0.2.15
+ transitivePeerDependencies:
+ - '@types/react'
+
rollup@4.53.3:
dependencies:
'@types/estree': 1.0.8
@@ -8490,12 +9478,25 @@ snapshots:
'@parcel/watcher': 2.5.1
optional: true
+ sass@1.97.2:
+ dependencies:
+ chokidar: 4.0.3
+ immutable: 5.1.4
+ source-map-js: 1.2.1
+ optionalDependencies:
+ '@parcel/watcher': 2.5.1
+
saxes@6.0.0:
dependencies:
xmlchars: 2.2.0
scheduler@0.27.0: {}
+ section-matter@1.0.0:
+ dependencies:
+ extend-shallow: 2.0.1
+ kind-of: 6.0.3
+
semver@6.3.1: {}
semver@7.7.3: {}
@@ -8587,6 +9588,17 @@ snapshots:
shebang-regex@3.0.0: {}
+ shiki@3.21.0:
+ dependencies:
+ '@shikijs/core': 3.21.0
+ '@shikijs/engine-javascript': 3.21.0
+ '@shikijs/engine-oniguruma': 3.21.0
+ '@shikijs/langs': 3.21.0
+ '@shikijs/themes': 3.21.0
+ '@shikijs/types': 3.21.0
+ '@shikijs/vscode-textmate': 10.0.2
+ '@types/hast': 3.0.4
+
side-channel-list@1.0.0:
dependencies:
es-errors: 1.3.0
@@ -8635,6 +9647,8 @@ snapshots:
source-map@0.6.1: {}
+ space-separated-tokens@2.0.2: {}
+
spdx-correct@3.2.0:
dependencies:
spdx-expression-parse: 3.0.1
@@ -8678,6 +9692,11 @@ snapshots:
emoji-regex: 9.2.2
strip-ansi: 7.1.2
+ stringify-entities@4.0.4:
+ dependencies:
+ character-entities-html4: 2.1.0
+ character-entities-legacy: 3.0.0
+
strip-ansi@6.0.1:
dependencies:
ansi-regex: 5.0.1
@@ -8686,6 +9705,8 @@ snapshots:
dependencies:
ansi-regex: 6.2.2
+ strip-bom-string@1.0.0: {}
+
strip-bom@4.0.0: {}
strip-final-newline@2.0.0: {}
@@ -8700,11 +9721,24 @@ snapshots:
dependencies:
js-tokens: 9.0.1
+ style-to-js@1.1.21:
+ dependencies:
+ style-to-object: 1.0.14
+
+ style-to-object@1.0.14:
+ dependencies:
+ inline-style-parser: 0.2.7
+
styled-jsx@5.1.6(react@19.2.0):
dependencies:
client-only: 0.0.1
react: 19.2.0
+ styled-jsx@5.1.6(react@19.2.3):
+ dependencies:
+ client-only: 0.0.1
+ react: 19.2.3
+
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
@@ -8727,6 +9761,8 @@ snapshots:
dependencies:
'@pkgr/core': 0.2.9
+ tagged-tag@1.0.0: {}
+
test-exclude@6.0.0:
dependencies:
'@istanbuljs/schema': 0.1.3
@@ -8762,6 +9798,8 @@ snapshots:
dependencies:
punycode: 2.3.1
+ trim-lines@3.0.1: {}
+
ts-api-utils@2.1.0(typescript@5.9.3):
dependencies:
typescript: 5.9.3
@@ -8772,6 +9810,13 @@ snapshots:
tslib@2.8.1: {}
+ tsx@4.21.0:
+ dependencies:
+ esbuild: 0.27.2
+ get-tsconfig: 4.13.0
+ optionalDependencies:
+ fsevents: 2.3.3
+
turbo-stream@3.1.0: {}
type-check@0.4.0:
@@ -8782,6 +9827,10 @@ snapshots:
type-fest@0.21.3: {}
+ type-fest@5.4.1:
+ dependencies:
+ tagged-tag: 1.0.0
+
type-is@1.6.18:
dependencies:
media-typer: 0.3.0
@@ -8823,6 +9872,29 @@ snapshots:
unicode-segmenter@0.14.0: {}
+ unist-util-is@6.0.1:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-position@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-stringify-position@4.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-visit-parents@6.0.2:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+
+ unist-util-visit@5.1.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+ unist-util-visit-parents: 6.0.2
+
unpipe@1.0.0: {}
unrs-resolver@1.11.1:
@@ -8884,13 +9956,23 @@ snapshots:
vary@1.1.2: {}
- vite-node@3.2.4(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3):
+ vfile-message@4.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-stringify-position: 4.0.0
+
+ vfile@6.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ vfile-message: 4.0.3
+
+ vite-node@3.2.4(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0):
dependencies:
cac: 6.7.14
debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 2.0.3
- vite: 7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3)
+ vite: 7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -8905,23 +9987,23 @@ snapshots:
- tsx
- yaml
- vite-plugin-devtools-json@1.0.0(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3)):
+ vite-plugin-devtools-json@1.0.0(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)):
dependencies:
uuid: 11.1.0
- vite: 7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3)
+ vite: 7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)
- vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3)):
+ vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)):
dependencies:
debug: 4.4.3
globrex: 0.1.2
tsconfck: 3.1.6(typescript@5.9.3)
optionalDependencies:
- vite: 7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3)
+ vite: 7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)
transitivePeerDependencies:
- supports-color
- typescript
- vite@7.2.2(@types/node@22.19.1)(sass-embedded@1.93.3)(sass@1.93.3):
+ vite@7.2.2(@types/node@22.19.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0):
dependencies:
esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.3)
@@ -8932,10 +10014,11 @@ snapshots:
optionalDependencies:
'@types/node': 22.19.1
fsevents: 2.3.3
- sass: 1.93.3
+ sass: 1.97.2
sass-embedded: 1.93.3
+ tsx: 4.21.0
- vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3):
+ vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0):
dependencies:
esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.3)
@@ -8946,12 +10029,13 @@ snapshots:
optionalDependencies:
'@types/node': 22.10.1
fsevents: 2.3.3
- sass: 1.93.3
+ sass: 1.97.2
sass-embedded: 1.93.3
+ tsx: 4.21.0
- vitefu@1.1.1(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3)):
+ vitefu@1.1.1(vite@7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)):
optionalDependencies:
- vite: 7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.93.3)
+ vite: 7.2.6(@types/node@22.10.1)(sass-embedded@1.93.3)(sass@1.97.2)(tsx@4.21.0)
w3c-xmlserializer@5.0.0:
dependencies:
@@ -9030,3 +10114,5 @@ snapshots:
zimmerframe@1.1.4: {}
zod@3.25.76: {}
+
+ zwitch@2.0.4: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 3959455..9f87b57 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,6 +1,7 @@
packages:
- "package"
- "tests"
+ - "site"
- "examples/*"
- "modules/*"
- "adapters/*"
diff --git a/site/.gitignore b/site/.gitignore
new file mode 100644
index 0000000..a408881
--- /dev/null
+++ b/site/.gitignore
@@ -0,0 +1,40 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+.yarn/install-state.gz
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+
+# generated
+/public/sitemap*
+/public/preview
+/public/search-index.json
diff --git a/site/next.config.mjs b/site/next.config.mjs
new file mode 100644
index 0000000..4205403
--- /dev/null
+++ b/site/next.config.mjs
@@ -0,0 +1,4 @@
+/** @type {import("next").NextConfig} */
+const nextConfig = {};
+
+export default nextConfig;
diff --git a/site/package.json b/site/package.json
new file mode 100644
index 0000000..29179b7
--- /dev/null
+++ b/site/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "robindoc-app",
+ "private": true,
+ "scripts": {
+ "dev": "pnpm run prebuild && next dev",
+ "prebuild": "robindoc-minisearch --template src/app/docs/robindoc.ts",
+ "build": "next build",
+ "start": "next start"
+ },
+ "dependencies": {
+ "next": "16.1.4",
+ "react": "19.2.3",
+ "react-dom": "19.2.3",
+ "robindoc": "3.7.2",
+ "@robindoc/minisearch": "3.7.2",
+ "@robindoc/next": "3.7.2",
+ "sass": "1.97.2",
+ "contection": "latest"
+ },
+ "devDependencies": {
+ "@types/node": "25.0.8",
+ "@types/react": "19.2.8",
+ "@types/react-dom": "19.2.3",
+ "typescript": "5.9.3",
+ "tsx": "4.21.0"
+ }
+}
\ No newline at end of file
diff --git a/site/src/app/demo/components/computed-subscriber/index.tsx b/site/src/app/demo/components/computed-subscriber/index.tsx
new file mode 100644
index 0000000..a5f8f98
--- /dev/null
+++ b/site/src/app/demo/components/computed-subscriber/index.tsx
@@ -0,0 +1,20 @@
+"use client";
+
+import { useStore } from "contection";
+
+import { DemoStore } from "../../store";
+import { RenderTracker } from "../render-tracker";
+
+export function ComputedSubscriber() {
+ const counterTens = useStore(DemoStore, {
+ keys: ["counter"],
+ mutation: (store) => Math.floor(store.counter / 10),
+ });
+
+ return (
+
+ Only when counter / 10 changes
+ {counterTens}
+
+ );
+}
diff --git a/site/src/app/demo/components/conditional-subscriber/index.tsx b/site/src/app/demo/components/conditional-subscriber/index.tsx
new file mode 100644
index 0000000..a9d0220
--- /dev/null
+++ b/site/src/app/demo/components/conditional-subscriber/index.tsx
@@ -0,0 +1,20 @@
+"use client";
+
+import { useStore } from "contection";
+
+import { DemoStore } from "../../store";
+import { RenderTracker } from "../render-tracker";
+
+export function ConditionalSubscriber() {
+ const { counter } = useStore(DemoStore, {
+ keys: ["counter"],
+ enabled: (store) => store.theme === "dark",
+ });
+
+ return (
+
+ Counter only when theme is dark
+ {counter}
+
+ );
+}
diff --git a/site/src/app/demo/components/consumer-demo/index.tsx b/site/src/app/demo/components/consumer-demo/index.tsx
new file mode 100644
index 0000000..b6ff324
--- /dev/null
+++ b/site/src/app/demo/components/consumer-demo/index.tsx
@@ -0,0 +1,20 @@
+"use client";
+
+import { DemoStore } from "../../store";
+import { RenderTracker } from "../render-tracker";
+
+export function ConsumerDemo() {
+ return (
+
+ Render-prop pattern
+
+ {({ counter, theme }) => (
+
+ counter: {counter}
+ theme: {theme}
+
+ )}
+
+
+ );
+}
diff --git a/site/src/app/demo/components/counter-subscriber/index.tsx b/site/src/app/demo/components/counter-subscriber/index.tsx
new file mode 100644
index 0000000..1c27d5e
--- /dev/null
+++ b/site/src/app/demo/components/counter-subscriber/index.tsx
@@ -0,0 +1,17 @@
+"use client";
+
+import { useStore } from "contection";
+
+import { DemoStore } from "../../store";
+import { RenderTracker } from "../render-tracker";
+
+export function CounterSubscriber() {
+ const { counter } = useStore(DemoStore, { keys: ["counter"] });
+
+ return (
+
+ Only when counter changes
+ {counter}
+
+ );
+}
diff --git a/site/src/app/demo/components/full-store-subscriber/index.tsx b/site/src/app/demo/components/full-store-subscriber/index.tsx
new file mode 100644
index 0000000..5b90748
--- /dev/null
+++ b/site/src/app/demo/components/full-store-subscriber/index.tsx
@@ -0,0 +1,21 @@
+"use client";
+
+import { useStore } from "contection";
+
+import { DemoStore } from "../../store";
+import { RenderTracker } from "../render-tracker";
+
+export function FullStoreSubscriber() {
+ const store = useStore(DemoStore);
+
+ return (
+
+ Re-renders on ANY change
+
+ counter: {store.counter}
+ theme: {store.theme}
+ user: {store.user.name}
+
+
+ );
+}
diff --git a/site/src/app/demo/components/index.tsx b/site/src/app/demo/components/index.tsx
new file mode 100644
index 0000000..d86e27f
--- /dev/null
+++ b/site/src/app/demo/components/index.tsx
@@ -0,0 +1,11 @@
+export { RenderTracker } from "./render-tracker";
+export { FullStoreSubscriber } from "./full-store-subscriber";
+export { CounterSubscriber } from "./counter-subscriber";
+export { UserSubscriber } from "./user-subscriber";
+export { ThemeSubscriber } from "./theme-subscriber";
+export { ComputedSubscriber } from "./computed-subscriber";
+export { ConditionalSubscriber } from "./conditional-subscriber";
+export { NoRenderControls } from "./no-render-controls";
+export { ConsumerDemo } from "./consumer-demo";
+export { StoreControls } from "./store-controls";
+export { Level1 } from "./nested-components";
diff --git a/site/src/app/demo/components/nested-components/index.tsx b/site/src/app/demo/components/nested-components/index.tsx
new file mode 100644
index 0000000..5f64823
--- /dev/null
+++ b/site/src/app/demo/components/nested-components/index.tsx
@@ -0,0 +1,41 @@
+"use client";
+
+import { useStore } from "contection";
+
+import { DemoStore } from "../../store";
+import { RenderTracker } from "../render-tracker";
+
+import "./styles.scss";
+
+function Level3() {
+ const { theme } = useStore(DemoStore, { keys: ["theme"] });
+ return (
+
+ {theme}
+
+ );
+}
+
+function Level2() {
+ const email = useStore(DemoStore, {
+ keys: ["user"],
+ mutation: (store) => store.user.email,
+ });
+ return (
+
+ {email}
+
+
+ );
+}
+
+export function Level1() {
+ return (
+
+
+ {({ counter }) => {counter} }
+
+
+
+ );
+}
diff --git a/site/src/app/demo/components/nested-components/styles.scss b/site/src/app/demo/components/nested-components/styles.scss
new file mode 100644
index 0000000..6cf5f6d
--- /dev/null
+++ b/site/src/app/demo/components/nested-components/styles.scss
@@ -0,0 +1,6 @@
+.nested-value {
+ display: block;
+ font-family: monospace;
+ color: var(--r-main-700);
+ margin-bottom: 12px;
+}
\ No newline at end of file
diff --git a/site/src/app/demo/components/no-render-controls/index.tsx b/site/src/app/demo/components/no-render-controls/index.tsx
new file mode 100644
index 0000000..0889215
--- /dev/null
+++ b/site/src/app/demo/components/no-render-controls/index.tsx
@@ -0,0 +1,30 @@
+"use client";
+
+import { useStoreReducer } from "contection";
+
+import { DemoStore } from "../../store";
+import { RenderTracker } from "../render-tracker";
+
+export function NoRenderControls() {
+ const [store, setStore] = useStoreReducer(DemoStore);
+
+ return (
+
+ Updates without re-rendering this component
+
+ setStore({ counter: store.counter + 100 })}>
+ +100
+
+ {
+ const newName = `User_${Math.random().toString(36).slice(2, 6)}`;
+ setStore((prev) => ({ user: { ...prev.user, name: newName } }));
+ }}
+ >
+ Random Name
+
+
+
+ );
+}
diff --git a/site/src/app/demo/components/render-tracker/index.tsx b/site/src/app/demo/components/render-tracker/index.tsx
new file mode 100644
index 0000000..eaa2796
--- /dev/null
+++ b/site/src/app/demo/components/render-tracker/index.tsx
@@ -0,0 +1,47 @@
+"use client";
+
+import { useRef, useEffect, type ReactNode } from "react";
+
+import "./styles.scss";
+
+interface RenderTrackerProps {
+ children: ReactNode;
+ label: string;
+ color: string;
+}
+
+export function RenderTracker({ children, label, color }: RenderTrackerProps) {
+ const ref = useRef(null);
+ const countRef = useRef(0);
+ const countDisplayRef = useRef(null);
+
+ useEffect(() => {
+ countRef.current += 1;
+ if (countDisplayRef.current) {
+ countDisplayRef.current.textContent = `${countRef.current}`;
+ }
+
+ if (ref.current) {
+ ref.current.style.boxShadow = `inset 0 0 0 2px ${color}`;
+
+ const timeout = setTimeout(() => {
+ if (ref.current) {
+ ref.current.style.boxShadow = "none";
+ }
+ }, 300);
+ return () => clearTimeout(timeout);
+ }
+ });
+
+ return (
+
+
+ {label}
+
+ {countRef.current}
+
+
+ {children}
+
+ );
+}
diff --git a/site/src/app/demo/components/render-tracker/styles.scss b/site/src/app/demo/components/render-tracker/styles.scss
new file mode 100644
index 0000000..7868987
--- /dev/null
+++ b/site/src/app/demo/components/render-tracker/styles.scss
@@ -0,0 +1,64 @@
+.card {
+ padding: 16px;
+ background: var(--r-main-100);
+ border: 1px solid var(--r-main-200);
+ border-radius: 8px;
+ transition: box-shadow 0.3s;
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 12px;
+}
+
+.card-label {
+ font-weight: 600;
+ color: var(--r-main-700);
+}
+
+.card-count {
+ min-width: 24px;
+ padding: 2px 8px;
+ font-weight: 700;
+ font-family: monospace;
+ font-size: 12px;
+ color: white;
+ text-align: center;
+ border-radius: 100px;
+}
+
+.card-desc {
+ color: var(--r-main-700);
+ margin: 0 0 12px;
+}
+
+.card-value {
+ font-weight: 600;
+ font-family: monospace;
+ text-align: center;
+ padding: 12px;
+ background: var(--r-main-200);
+ border-radius: 8px;
+}
+
+.card-values {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+
+ code {
+ font-family: monospace;
+ color: var(--r-main-700);
+ padding: 6px 10px;
+ background: var(--r-main-200);
+ border-radius: 4px;
+ }
+}
+
+.card-buttons {
+ display: flex;
+ gap: 6px;
+ margin-top: 12px;
+}
\ No newline at end of file
diff --git a/site/src/app/demo/components/store-controls/index.tsx b/site/src/app/demo/components/store-controls/index.tsx
new file mode 100644
index 0000000..b922f20
--- /dev/null
+++ b/site/src/app/demo/components/store-controls/index.tsx
@@ -0,0 +1,97 @@
+"use client";
+
+import { useStoreReducer } from "contection";
+
+import { DemoStore, initialState } from "../../store";
+
+import "./styles.scss";
+
+export function StoreControls() {
+ const [, setStore] = useStoreReducer(DemoStore);
+
+ const rapidUpdates = async (e: React.MouseEvent) => {
+ const node = e.currentTarget;
+ node.disabled = true;
+ for (let i = 0; i < 500; i++) {
+ await new Promise((r) => setTimeout(r, 0));
+ const random = Math.random();
+ if (random < 0.33) {
+ setStore((prev) => ({ counter: prev.counter + 1 }));
+ } else if (random < 0.66) {
+ setStore((prev) => ({
+ user: { ...prev.user, email: `${Math.random().toString(36).slice(2, 8)}@demo.com` },
+ }));
+ } else {
+ setStore((prev) => ({ theme: (prev.theme === "light" ? "dark" : "light") as "light" | "dark" }));
+ }
+ }
+ node.disabled = false;
+ };
+
+ return (
+
+
+
Counter
+
+ setStore((p) => ({ counter: p.counter - 1 }))}>
+ -1
+
+ setStore((p) => ({ counter: p.counter + 1 }))}>
+ +1
+
+
+
+
+
+
User
+
+
+ setStore((p) => ({
+ user: { ...p.user, name: `User_${Math.random().toString(36).slice(2, 6)}` },
+ }))
+ }
+ >
+ New Name
+
+
+ setStore((p) => ({
+ user: { ...p.user, email: `${Math.random().toString(36).slice(2, 8)}@demo.com` },
+ }))
+ }
+ >
+ New Email
+
+
+
+
+
+
Theme
+
+
+ setStore((p) => ({ theme: (p.theme === "light" ? "dark" : "light") as "light" | "dark" }))
+ }
+ >
+
+ {({ theme }) => (theme === "light" ? "Light" : "Dark")}
+
+
+
+
+
+
+
+ Rapid 500 Updates
+
+ setStore({ ...initialState })}>
+ Reset
+
+
+
+ );
+}
diff --git a/site/src/app/demo/components/store-controls/styles.scss b/site/src/app/demo/components/store-controls/styles.scss
new file mode 100644
index 0000000..9825504
--- /dev/null
+++ b/site/src/app/demo/components/store-controls/styles.scss
@@ -0,0 +1,81 @@
+.controls {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 24px;
+ padding: 20px;
+ background: var(--r-main-100);
+ border: 1px solid var(--r-main-200);
+ border-radius: 8px;
+
+ @media (max-width: 600px) {
+ flex-direction: column;
+ gap: 16px;
+ }
+}
+
+.control-group {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+}
+
+.control-group.actions {
+ margin-left: auto;
+
+ @media (max-width: 600px) {
+ margin-left: 0;
+ }
+}
+
+.control-label {
+ font-weight: 500;
+ color: var(--r-main-700);
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.control-buttons {
+ display: flex;
+ gap: 6px;
+}
+
+.btn {
+ padding: 8px 14px;
+ font-family: inherit;
+ font-size: inherit;
+ font-weight: 500;
+ border: 1px solid var(--r-main-200);
+ border-radius: 8px;
+ background: transparent;
+ color: var(--r-main-950);
+ cursor: pointer;
+ transition: all 0.15s;
+
+ &:hover:not(:disabled) {
+ border-color: var(--r-main-700);
+ }
+
+ &:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ }
+}
+
+.btn.primary {
+ background: var(--r-primary-500);
+ border-color: var(--r-primary-300);
+ color: white;
+
+ &:hover:not(:disabled) {
+ background: var(--r-primary-600);
+ border-color: var(--r-primary-400);
+ }
+}
+
+.btn.ghost {
+ color: var(--r-main-700);
+}
+
+.btn.sm {
+ padding: 6px 10px;
+}
\ No newline at end of file
diff --git a/site/src/app/demo/components/theme-subscriber/index.tsx b/site/src/app/demo/components/theme-subscriber/index.tsx
new file mode 100644
index 0000000..aa6bd33
--- /dev/null
+++ b/site/src/app/demo/components/theme-subscriber/index.tsx
@@ -0,0 +1,17 @@
+"use client";
+
+import { useStore } from "contection";
+
+import { DemoStore } from "../../store";
+import { RenderTracker } from "../render-tracker";
+
+export function ThemeSubscriber() {
+ const { theme } = useStore(DemoStore, { keys: ["theme"] });
+
+ return (
+
+ Only when theme changes
+ {theme}
+
+ );
+}
diff --git a/site/src/app/demo/components/user-subscriber/index.tsx b/site/src/app/demo/components/user-subscriber/index.tsx
new file mode 100644
index 0000000..a2c0b3d
--- /dev/null
+++ b/site/src/app/demo/components/user-subscriber/index.tsx
@@ -0,0 +1,20 @@
+"use client";
+
+import { useStore } from "contection";
+
+import { DemoStore } from "../../store";
+import { RenderTracker } from "../render-tracker";
+
+export function UserSubscriber() {
+ const { user } = useStore(DemoStore, { keys: ["user"] });
+
+ return (
+
+ Only when user changes
+
+ {user.name}
+ {user.email}
+
+
+ );
+}
diff --git a/site/src/app/demo/demo.scss b/site/src/app/demo/demo.scss
new file mode 100644
index 0000000..7f26d8d
--- /dev/null
+++ b/site/src/app/demo/demo.scss
@@ -0,0 +1,35 @@
+.main {
+ font-size: 16px;
+ padding: 24px;
+}
+
+.section {
+ margin-bottom: 48px;
+}
+
+.section-desc {
+ color: var(--r-main-700);
+ margin: -8px 0 16px;
+}
+
+.grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
+ gap: 16px;
+
+ @media (max-width: 600px) {
+ grid-template-columns: 1fr;
+ }
+}
+
+.nested {
+ padding: 16px;
+ background: var(--r-main-100);
+ border: 1px solid var(--r-main-200);
+ border-radius: 8px;
+
+ .card {
+ margin-top: 12px;
+ background: color-mix(in srgb, var(--r-main-200) 30%, transparent);
+ }
+}
\ No newline at end of file
diff --git a/site/src/app/demo/page.tsx b/site/src/app/demo/page.tsx
new file mode 100644
index 0000000..c395d17
--- /dev/null
+++ b/site/src/app/demo/page.tsx
@@ -0,0 +1,52 @@
+"use client";
+
+import { DemoStore, initialState } from "./store";
+import {
+ FullStoreSubscriber,
+ CounterSubscriber,
+ UserSubscriber,
+ ThemeSubscriber,
+ ComputedSubscriber,
+ ConditionalSubscriber,
+ NoRenderControls,
+ ConsumerDemo,
+ StoreControls,
+ Level1,
+} from "./components";
+
+import "./demo.scss";
+
+export default function DemoPage() {
+ return (
+
+
+
+
+
+ Subscription Patterns
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Nested Components
+ Each level subscribes independently
+
+
+
+
+
+
+ );
+}
diff --git a/site/src/app/demo/store.ts b/site/src/app/demo/store.ts
new file mode 100644
index 0000000..0e1600e
--- /dev/null
+++ b/site/src/app/demo/store.ts
@@ -0,0 +1,31 @@
+"use client";
+
+import { createStore } from "contection";
+
+export interface DemoStore {
+ counter: number;
+ user: {
+ name: string;
+ email: string;
+ };
+ theme: "light" | "dark";
+ settings: {
+ notifications: boolean;
+ language: string;
+ };
+}
+
+export const initialState: DemoStore = {
+ counter: 0,
+ user: {
+ name: "Alex",
+ email: "alex@example.com",
+ },
+ theme: "light",
+ settings: {
+ notifications: true,
+ language: "en",
+ },
+};
+
+export const DemoStore = createStore(initialState);
diff --git a/site/src/app/docs/[[...segments]]/page.tsx b/site/src/app/docs/[[...segments]]/page.tsx
new file mode 100644
index 0000000..2dee9a6
--- /dev/null
+++ b/site/src/app/docs/[[...segments]]/page.tsx
@@ -0,0 +1,29 @@
+import { Page, getMetadata, getStaticParams } from "../robindoc";
+
+export default async function Docs({ params }: { params: Promise<{ segments?: string[] }> }) {
+ const { segments } = await params;
+ const pathname = "/docs/" + (segments?.join("/") || "");
+
+ return (
+
+ );
+}
+
+export const generateMetadata = async ({ params }: { params: Promise<{ segments?: string[] }> }) => {
+ const { segments } = await params;
+ const pathname = "/docs/" + (segments?.join("/") || "");
+ const metadata = await getMetadata(pathname);
+
+ return metadata;
+};
+
+export const generateStaticParams = async () => {
+ const staticParams = await getStaticParams("/docs");
+
+ return staticParams;
+};
diff --git a/site/src/app/docs/layout.tsx b/site/src/app/docs/layout.tsx
new file mode 100644
index 0000000..6f80276
--- /dev/null
+++ b/site/src/app/docs/layout.tsx
@@ -0,0 +1,14 @@
+import type { ReactNode } from "react";
+import { DocsContainer, KeylinkToNavigation } from "robindoc";
+
+import { Sidebar } from "./robindoc";
+
+export default function DocsLayout({ children }: { children: ReactNode }) {
+ return (
+
+
+ {children}
+
+
+ );
+}
diff --git a/site/src/app/docs/robindoc.ts b/site/src/app/docs/robindoc.ts
new file mode 100644
index 0000000..f5424b5
--- /dev/null
+++ b/site/src/app/docs/robindoc.ts
@@ -0,0 +1,30 @@
+import { notFound } from "next/navigation";
+import { initializeRobindoc } from "robindoc";
+
+export const { Page, Sidebar, getPageData, getMetadata, getStaticParams, getPageInstruction } = initializeRobindoc(
+ {
+ configuration: {
+ sourceRoot: "../docs",
+ basePath: "/docs",
+ },
+ items: [
+ {
+ title: "Introduction",
+ type: "heading",
+ href: "/",
+ configuration: {
+ sourceRoot: "../README.md",
+ },
+ },
+ {
+ type: "separator",
+ },
+ "auto",
+ ],
+ },
+ {
+ processError: notFound,
+ matcher: ["/(?!.*\\..+).*"],
+ cache: true,
+ },
+);
diff --git a/site/src/app/globals.css b/site/src/app/globals.css
new file mode 100644
index 0000000..27bedc6
--- /dev/null
+++ b/site/src/app/globals.css
@@ -0,0 +1,12 @@
+html,
+body {
+ padding: 0;
+ margin: 0;
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
+}
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
diff --git a/site/src/app/home.scss b/site/src/app/home.scss
new file mode 100644
index 0000000..9c8dd80
--- /dev/null
+++ b/site/src/app/home.scss
@@ -0,0 +1,117 @@
+.home {
+ margin: 60px auto;
+}
+
+.hero {
+ text-align: center;
+ margin-bottom: 64px;
+}
+
+.hero h1 {
+ font-size: 3rem;
+ font-weight: 700;
+ margin: 0 0 12px;
+ letter-spacing: -0.02em;
+}
+
+.tagline {
+ font-size: 1.125rem;
+ color: var(--r-main-700);
+ margin: 0 0 32px;
+}
+
+.hero-actions {
+ display: flex;
+ gap: 12px;
+ justify-content: center;
+}
+
+.btn-primary,
+.btn-secondary {
+ padding: 10px 20px;
+ border-radius: 6px;
+ font-weight: 500;
+ text-decoration: none;
+ transition: opacity 0.15s;
+}
+
+.btn-primary {
+ background: var(--r-primary-500);
+ color: white;
+}
+
+.btn-secondary {
+ background: var(--r-main-200);
+ color: var(--r-main-900);
+}
+
+.btn-primary:hover,
+.btn-secondary:hover {
+ opacity: 0.85;
+}
+
+.features {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 24px;
+ margin: 80px 0;
+
+ @media (max-width: 600px) {
+ grid-template-columns: 1fr;
+ }
+}
+
+.feature {
+ padding: 16px;
+ border-radius: 8px;
+ border: 4px solid var(--r-main-100);
+}
+
+.feature h3 {
+ font-size: 1rem;
+ font-weight: 600;
+ margin: 0 0 6px;
+}
+
+.feature p {
+ font-size: 0.875rem;
+ color: var(--r-main-700);
+ margin: 0;
+ line-height: 1.5;
+}
+
+.example {
+ max-width: 600px;
+ margin: 60px auto;
+}
+
+.example pre {
+ border-radius: 8px;
+ border: 4px solid var(--r-main-100);
+ padding: 16px;
+ overflow-x: auto;
+ margin: 0;
+}
+
+.example code {
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
+ font-size: 0.875rem;
+ line-height: 1.6;
+ color: var(--r-main-900);
+}
+
+.links {
+ display: flex;
+ gap: 24px;
+ justify-content: center;
+}
+
+.links a {
+ color: var(--r-main-700);
+ text-decoration: none;
+}
+
+.links a:hover {
+ color: var(--r-main-900);
+ text-decoration: underline;
+}
\ No newline at end of file
diff --git a/site/src/app/layout.tsx b/site/src/app/layout.tsx
new file mode 100644
index 0000000..64ca8bf
--- /dev/null
+++ b/site/src/app/layout.tsx
@@ -0,0 +1,32 @@
+import { type ReactNode } from "react";
+import { RobinProvider, Header, Footer } from "robindoc";
+import { NavigationProvider } from "@robindoc/next";
+
+import { searchProvider } from "./search-provider";
+
+import "robindoc/lib/styles.css";
+import "./globals.css";
+
+export default function RootLayout({ children }: { children: ReactNode }) {
+ return (
+
+
+
+
+ Contection>}
+ links={[
+ { href: "/docs", title: "Docs" },
+ { href: "/demo", title: "Demo" },
+ ]}
+ git="https://github.com/alexdln/contection"
+ searcher={searchProvider}
+ />
+ {children}
+
+
+
+
+
+ );
+}
diff --git a/site/src/app/page.tsx b/site/src/app/page.tsx
new file mode 100644
index 0000000..10d4be8
--- /dev/null
+++ b/site/src/app/page.tsx
@@ -0,0 +1,63 @@
+import Link from "next/link";
+import { CodeBlock } from "robindoc/lib/components/ui/code-block";
+
+import "./home.scss";
+
+export default function Home() {
+ return (
+
+
+ Contection
+
+ React Context API extended with fine-grained subscriptions and computed values
+
+
+
+ Get Started
+
+
+ Live Demo
+
+
+
+
+
+
+
Granular Subscriptions
+
Subscribe to specific store keys — components re-render only when subscribed data changes
+
+
+
Computed Values
+
Derive state with mutation functions for transformed or filtered data
+
+
+
SSR Compatible
+
Works with Next.js and other SSR frameworks out of the box
+
+
+
+
+ {count};
+}`}
+ lang="typescript"
+ />
+
+
+
+
+ );
+}
diff --git a/site/src/app/search-provider.ts b/site/src/app/search-provider.ts
new file mode 100644
index 0000000..07a8579
--- /dev/null
+++ b/site/src/app/search-provider.ts
@@ -0,0 +1,5 @@
+"use client";
+
+import { createSearchProvider } from "@robindoc/minisearch/provider";
+
+export const searchProvider = createSearchProvider("/search-index.json");
diff --git a/site/tsconfig.json b/site/tsconfig.json
new file mode 100644
index 0000000..caff117
--- /dev/null
+++ b/site/tsconfig.json
@@ -0,0 +1,42 @@
+{
+ "compilerOptions": {
+ "target": "es2020",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": false,
+ "skipLibCheck": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "react-jsx",
+ "incremental": true,
+ "types": [
+ "node",
+ "react",
+ "react-dom"
+ ],
+ "esModuleInterop": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ]
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts",
+ ".next/dev/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/tests/jest.config.js b/tests/jest.config.js
index 5830ac8..b7233d8 100644
--- a/tests/jest.config.js
+++ b/tests/jest.config.js
@@ -29,4 +29,3 @@ module.exports = {
coverageReporters: ["text", "lcov", "html"],
testTimeout: 10000,
};
-