npm package: @gearbox-built/sanity-path-input
Description: A custom input component that syncs the slug to the path
Author: Gearbox Built
Latest version: 1.0.0

# @gearbox-built/sanity-path-input

> This is a **Sanity Studio v3 & v4** plugin with **React 18 & 19** support.

## Compatibility

- **React**: 18.3+ or 19.x
- **Sanity Studio**: v3.x or v4.x
- **Node.js**: 18+ (Node.js 20+ required for Sanity v4)
- **TypeScript**: 5.5+ with full type safety

## What it does

This plugin automatically syncs your document's `slug` field to a `path` field, with support for custom path generation logic. Perfect for generating URLs with parent paths, custom routing, or complex path structures.

## Installation

```sh
npm install @gearbox-built/sanity-path-input
```

or

```sh
yarn add @gearbox-built/sanity-path-input
```

## Important: Field Visibility

**The `path` field MUST be visible whenever the `slug` field is visible.** This is critical because the path input component only watches for slug changes when it's mounted. In Sanity Studio, React components only mount when they're visible in the UI.

If you organize fields using tabs or conditional fieldsets:
- ✅ **Correct**: Place `slug` and `path` in the same tab/fieldset
- ❌ **Incorrect**: Place `slug` and `path` in different tabs

When fields are in different tabs, changing the slug won't update the path until the user navigates to the path field's tab.

## Usage

Add it as a plugin in `sanity.config.ts` (or .js):

```ts
import {defineConfig} from 'sanity'
import PathInputPlugin from '@gearbox-built/sanity-path-input'
import generatePath from '@/utils/generatePath' // Custom async function you provide to fetch parent paths and custom routing need

export default defineConfig({
  //...
  plugins: [
    PathInputPlugin({
      generatePath, // defaults to `/${document.slug.current}`
    }),
  ],
})
```

## Schema

```ts
import {defineField} from 'sanity'


defineField({
  type: 'path',
  name: 'path',
  title: 'Path',
}),
```

## Schema With just the input

```ts
import {defineField} from 'sanity'
import {PathInput} from '@gearbox-built/sanity-path-input'


defineField({
  type: 'string',
  name: 'path',
  title: 'Path',
  components: {
    input: PathInput
  }
}),
```

## generatePath (Optional)

By default, paths are generated as `/${document.slug.current}`. You can customize this by providing a `generatePath` function to handle complex routing logic.

### Simple routing by type

```ts
import type {SanityClient} from 'sanity'

export const generatePath = async ({document, client}: {document: any, client: SanityClient}) => {
  switch (document._type) {
    case 'post':
      return `/blog/${document.slug.current}`
    default:
      return `/${document.slug.current}`
  }
}
```

### Complex logic with parent paths

```ts
export const generatePath = async ({document, client}: {document: any, client: SanityClient}) => {
  switch (document._type) {
    case 'post':
    case 'page':
      // Custom logic to fetch parent paths recursively
      return getRecursiveFetchingOfParentPaths(document, client)
    default:
      return `/${document.slug.current}`
  }
}
```

## Requirements

- Your document schema **must include a `slug` field** (type: `slug`) for the path input to function
- The slug field must be present and visible when using the path input

## How it works

The path field automatically updates when the slug changes, with a 250ms debounce to prevent excessive calls to your `generatePath` function. This means:
- Path updates happen shortly after you finish typing the slug
- Your `generatePath` function won't be called on every keystroke
- The field is read-only to prevent manual editing (it's auto-generated)

## License

[MIT](LICENSE) © Gearbox Built

## Testing

This plugin includes a comprehensive test suite using Vitest:

```sh
# Run all tests
yarn test

# Run tests in watch mode
yarn test:watch

# Run tests with coverage
yarn test:coverage

# Run tests with UI
yarn test:ui

# Type-check without building
yarn type-check
```

## Develop & test

This plugin uses [@sanity/plugin-kit](https://github.com/sanity-io/plugin-kit)
with default configuration for build & watch scripts.

See [Testing a plugin in Sanity Studio](https://github.com/sanity-io/plugin-kit#testing-a-plugin-in-sanity-studio)
on how to run this plugin with hotreload in the studio.

### Development Commands

```sh
# Build the plugin
yarn build

# Build in watch mode
yarn watch

# Link and watch for testing in a Sanity Studio
yarn link-watch
```