> For the complete documentation index, see [llms.txt](/llms.txt).
> The full corpus is at [llms-full.txt](/llms-full.txt).

# Behaviors

> How behaviors intercept and transform editor events to customize the Portable Text Editor's editing logic.

import {CardGrid, LinkCard} from '@astrojs/starlight/components'

Behaviors allow you to customize how users interact with the editor by hooking into events during the editing experience.

All behaviors follow this process:

1. Listen for an **event**.
2. Use a **guard** to decide if they should run or not.
3. Trigger a set of **actions** to perform on the editor.

This pattern is influenced by [Statecharts](https://statecharts.dev/).

Behaviors are defined with the `defineBehavior` helper. Here's an example event from the [behavior guide](/editor/guides/create-behavior/):

```tsx
defineBehavior({
  on: 'insert.text',
  guard: ({snapshot, event}) => event.text === 'a',
  actions: [
    ({snapshot, event}) => [
      {type: 'execute', event: {type: 'insert.text', text: 'A'}},
    ],
  ],
})
```

Revisiting the three step process above:

- `on` listens for the event.
- `guard` handles the conditional.
- `actions` sends, or invokes, the desired actions.

## Events

Whenever you enter text into the editor, activate a toolbar button, or anything else happens in the editor it sends an event.

There are three categories of Behavior Events:

- Native Events: Events that come from the browser or device directly.
- Synthetic Events: Editor-specific events that directly modify the editor state.
- Custom Events: Events that you create yourself.

<LinkCard
  title="Behavior API reference"
  description="Review the full list of native an synthetic events."
  href="/editor/reference/behavior-api/"
/>

The Behavior API uses events to trigger actions by listening for a specific event.

:::note
All events except native events can be executed or raised from within behaviors, but only synthetic events are guaranteed to resolve into a state change.
:::

## Guards

A guard is a condition that helps the behavior determine if it should perform the actions.

The `guard` key expects a response or `false`. The example above shows a simple _truthy_ guard. Here it is again:

```js
guard: ({snapshot, event}) => event.text === 'a'
```

Guards can also return parameters that you can access when firing an action.

```js
guard: ({snapshot, event}) => {
    if (event.text === 'a') {
        return {
            secret: 'secret text'
        }
    }
    return false
},
actions: [
    ({snapshot, event}, {secret}) => [
        /* ... */
    ]
]
```

Passing parameters allows you to reuse conditional behavior, such as selecting part of a string, without rewriting the logic.

Guards are optional. This means it's possible to create an unconditional behavior that always runs when an event occurs. The "soft return" behavior build into the PTE is one example:

```js
const softReturn = defineBehavior({
  on: 'insert.soft break',
  actions: [() => [execute({type: 'insert.text', text: '\n'})]],
})
```

This behavior listens for soft break events and uses the `insert.text` action to insert a `\n` instead to prevent splitting text blocks with `Shift+Enter`. These unconditional behaviors are rare and you'll mostly encounter conditional behaviors.

## Actions

Actions make things happen in the editor. This is where you change the standard behavior by modifying actions before they occur or by circumventing them completely. You've seen actions in some of the guard examples above.

The `actions` key expects an array of behavior action sets. As with guards, you have access to the `event` and `snapshot`.

So far we've only seen examples that invoke a single action, but you can send multiple actions or sets of actions from a single event.

### Raise events within actions

To send an event back into the editor, use the `raise` action type or the `raise` helper. This is useful for chaining behaviors and default events.

```tsx
// Approach A: With the type set to 'raise'
// Approach B: With the raise helper
import {defineBehavior, raise} from '@portabletext/editor/behaviors'

const raisedUppercaseA = defineBehavior({
  on: 'insert.text',
  guard: ({snapshot, event}) => event.text === 'a',
  actions: [
    ({snapshot, event}) => [
      {type: 'raise', event: {type: 'insert.text', text: 'A'}},
    ],
  ],
})

const raisedUppercaseA = defineBehavior({
  on: 'insert.text',
  guard: ({snapshot, event}) => event.text === 'a',
  actions: [({snapshot, event}) => [raise({type: 'insert.text', text: 'A'})]],
})
```

## Selectors

Selectors are pure functions that derive state from the editor snapshot (`snapshot` in the examples). A collection of selectors is included with the core library.

```tsx
// import all selectors
import * as selectors from '@portabletext/editor/selectors'
// or individual ones
import {getFocusSpan, getFocusTextBlock} from '@portabletext/editor/selectors'
```

The core selectors are useful helper functions for checking conditions of the editor, finding selected text, and more. You can manually do anything a selector can do by parsing the editor snapshot.

## Behavior examples

Browse the existing behaviors, or check out the Behavior Recipes documentation for examples of real-world behaviors.

<CardGrid>
  <LinkCard
    title="Behavior Recipes"
    description="Examples of useful behaviors."
    href="/editor/guides/behavior-cheat-sheet/"
  />
  <LinkCard
    title="Core Behaviors"
    description="Analyze the core behaviors included with the PTE."
    href="https://github.com/portabletext/editor/tree/main/packages/editor/src/behaviors"
  />
</CardGrid>