

Use `useUrlOpen` for dialogs, sheets, alert dialogs, and popovers that should reflect URL state without storing open state internally.

The hook is route-agnostic and always serializes open-state values as strings.

## Usage [#usage]

```tsx
import { useUrlOpen } from "@tilt-legal/cubitt-components/utilities/hooks";

export function Dialog() {
  const { isOpen, open, close } = useUrlOpen({
    paramName: "dialog",
  });

  return (
    <YourDialog
      open={isOpen}
      onOpenChange={(value) => (value ? void open() : void close())}
    />
  );
}
```

## Router registration [#router-registration]

When your app registers its TanStack Router, `paramName` narrows to known search keys from the route tree. Without registration, it falls back to loose `string` typing but still works at runtime.

## API [#api]

| Option                | Type       | Description                                                                      | Default |
| --------------------- | ---------- | -------------------------------------------------------------------------------- | ------- |
| `paramName`           | `string`   | URL parameter name. Narrows to known search keys when your router is registered. | -       |
| `paramMatchValue`     | `string`   | Open only when the URL value matches this string                                 | -       |
| `onUrlValueChange`    | `function` | Callback when the URL value changes                                              | -       |
| `paramClearOnDefault` | `boolean`  | Remove the parameter when closed                                                 | `true`  |
| `paramThrottle`       | `number`   | Throttle URL writes in milliseconds                                              | -       |
| `paramDebounce`       | `number`   | Debounce URL writes in milliseconds                                              | -       |
| `open`                | `boolean`  | Controlled open state (passthrough to component)                                 | -       |
| `defaultOpen`         | `boolean`  | Default open state for uncontrolled usage                                        | `false` |
