npm package: @stackbit/extensions
Description: A collection of utilities, actions, and other helpers for implementing common Stackbit patterns
Latest version: 0.1.0

# @stackbit/extensions

A collection of utilities, actions, and other helpers for implementing common Stackbit patterns.

## Requirements

This package is intended to be used in a [Stackbit](https://www.stackbit.com) project. In addition to [Stackbit requirements](https://docs.stackbit.com/#prerequisites), **this project requires that you're using TypeScript**.

## Installation

Add as a dependency to your project:

    npm install @stackbit/extensions

Note that if you aren't implementing in files used in the production application, this can be installed as a development dependency.

## Extension Usage

The following extensions are available:

- [`getFieldValue`](#getfieldvalue)
- [`ReactPreviewControls.PreviewUrl`](#reactpreviewcontrolspreviewurl)
- [`setRandomValue`](#setrandomvalue)
- [`updateFieldValue`](#updatefieldvalue)

### Utility Functions

Utility functions are typically used within another function.

#### `getFieldValue`

Extracts the value for a field from a document. This is useful for extracting the value of a field from a document, particularly when working with nested documents.

**Usage:**

```ts
getFieldValue(document: Document, fieldPath: Array<string | number>)
```

**Parameters:**

| Name        | Type                      | Description                                                        |
| ----------- | ------------------------- | ------------------------------------------------------------------ |
| `document`  | `Document`                | Parent document of the field                                       |
| `fieldPath` | `Array<string \| number>` | Path to the field of the parent document used to extract the value |

**Known Limitations:**

- Has only been tested in a limited capacity, alongside the `setRandomValue` action.
- Does not support localization.

#### `updateFieldValue`

Updates a value for a field from a document, and stores the result in the content source. This is particularly useful when working with nested documents.

**Usage:**

```ts
updateFieldValue(options: UpdateFieldOptions)
```

**Options:**

| Name         | Type                                      | Description                                                           |
| ------------ | ----------------------------------------- | --------------------------------------------------------------------- |
| `params`     | `Parameters<CustomActionField['run']>[0]` | Parameters sent to the action callback                                |
| `fieldPath`  | `Array<string \| number>`                 | Field path to update. If omitted, the current field path is used.     |
| `modelField` | `Field \| FieldListItems`                 | Field (from schema) to update. If omitted, the current field is used. |
| `value`      | `any`                                     | Value to set for the field.                                           |

**Known Limitations:**

- Has only been tested in a limited capacity, alongside the `setRandomValue` action.
- Does not support localization.

### Custom Actions

Custom actions enable editors to trigger events [within a specific context](https://docs.stackbit.com/features/custom-actions#types-of-actions).

#### `setRandomValue`

Sets a random value for a field from a document, and stores the result in the content source.

**Supported Contexts:**

- Field

**Usage:**

```ts
setRandomValue(options = {}): CustomActionField
```

**Options:**

| Name    | Required | Type     | Description                  |
| ------- | -------- | -------- | ---------------------------- |
| `label` | No       | `string` | Label for the trigger button |

**Field Action Example:**

```ts
import { setRandomValue } from '@stackbit/extensions';
import { ObjectModel } from '@stackbit/types';

export const ModelName: ObjectModel = {
  name: 'ModelName',
  type: 'object',
  fields: [{ type: 'string', name: 'title', actions: [setRandomValue()] }],
};
```

### Preview Controls

Preview controls provide a way to hook into the preview DOM from the Stackbit editor.

#### Supported Frameworks

Because preview controls are client-side implementations, they are available in specific framework contexts. Each control is provided as a property within an object that controls all available controls for a given framework.

**Supported Frameworks:**

| Framework | Object Name            |
| --------- | ---------------------- |
| React     | `ReactPreviewControls` |

#### Implementation

Preview controls are hooked into your application by importing from this application. They should be made available on any page you want to use them.

For example, in a Next.js application where you'd want a control available on every page, you'd likely want to implement in `pages/_app.tsx` (if using pages directory) or `app/layout.tsx` (if using app directory).

##### Next.js Configuration

Because the source code is written in TypeScript, Next.js typically requires an additional configuration to support TypeScript. Add this package to the `transpilePackages` option in your `next.config.js` file:

```js
/** @type {import('next').NextConfig} */

module.exports = {
  transpilePackages: ['@stackbit/extensions'],
  // ...
};
```

#### `PreviewUrl`

Shows a link to the preview URL for the current page.

**Supported Frameworks:**

- React

**Usage:**

```tsx
PreviewUrl(options: PreviewUrlOptions)
```

**Options:**

| Name             | Required | Type     | Description                                                                    |
| ---------------- | -------- | -------- | ------------------------------------------------------------------------------ |
| `previewBaseUrl` | Yes      | `string` | Base URL of the preview website. This gets prepended to the current page path. |
| `currentUrlPath` | Yes      | `string` | Current page path. This gets appended to the preview base URL.                 |

**React Example:**

```tsx
import { ReactPreviewControls } from '@stackbit/extensions';
import { AppProps } from 'next/app';
import { useRouter } from 'next/router';

export default function MyApp({ Component, pageProps }: AppProps) {
  ReactPreviewControls.PreviewUrl({
    currentUrlPath: useRouter().asPath,
    previewBaseUrl: 'https://www.example.com',
  });

  return (
    <>
      <Component {...pageProps} />
    </>
  );
}
```