npm package: @onlive.ai/flow
Description: > Web components for building multi-step interactive flows with forms, fields, actions, and stage navigation.
Latest version: 0.3.208

# Onlive Flow

> Web components for building multi-step interactive flows with forms, fields, actions, and stage navigation.

[![npm version](https://img.shields.io/npm/v/@onlive.ai/flow)](https://www.npmjs.com/package/@onlive.ai/flow)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.7-blue?logo=typescript)](https://www.typescriptlang.org/)
[![Lit](https://img.shields.io/badge/Lit-3.x-purple?logo=lit)](https://lit.dev/)
[![React](https://img.shields.io/badge/React-19.x-61DAFB?logo=react)](https://react.dev/)
[![License: Proprietary](https://img.shields.io/badge/License-Proprietary-red.svg)](https://onlive.site)

## Overview

The `@onlive.ai/flow` package provides a set of framework-agnostic web components for rendering [Onlive interactive flows](https://dev-docs.onlive.site/docs/onlive-flows/overview) — multi-step experiences with forms, field validation, stage navigation, and action handling. It integrates with the [Onlive Flow Client](https://dev-docs.onlive.site/docs/onlive-flows/custom-flow#installation) for data management and API communication.

## Installation

**Prerequisites**: Node.js 18+ and pnpm, npm, or yarn.

```bash
# pnpm (recommended)
pnpm add @onlive.ai/flow

# npm
npm install @onlive.ai/flow
```

### CDN

Use the components directly from the CDN with no build step:

```html
<!-- All components (IIFE bundle, global: OnliveFlow) -->
<script
  type="module"
  src="https://cdn.onlive.site/@onlive.ai/flow@latest/index.iife.js"
></script>

<!-- Individual component -->
<script
  type="module"
  src="https://cdn.onlive.site/@onlive.ai/flow@latest/components/flow/flow.element.js"
></script>
```

## Quick Start

```html
<!DOCTYPE html>
<html>
  <head>
    <title>Onlive Flow</title>
    <script
      type="module"
      src="https://cdn.onlive.site/@onlive.ai/flow@latest/index.iife.js"
    ></script>
  </head>
  <body>
    <ofl-flow id="flow"></ofl-flow>

    <script type="module">
      const flow = document.getElementById("flow");

      flow.context = {
        options: {
          baseUrl: "https://flow-api.onlive.site",
          organizationId: "your-organization-id",
          flowId: "your-flow-id",
        },
      };

      flow.addEventListener("ofl-close-panel", () => console.log("Flow closed"));
      flow.addEventListener("ofl-organization-call", (e) => console.log("Call requested", e.detail));
    </script>
  </body>
</html>
```

## Package Structure

```
packages/flow/
├── components/
│   ├── actions/     # Action buttons component (ofl-actions)
│   ├── error/       # Error display component (ofl-error)
│   ├── field/       # Individual field component (ofl-field)
│   ├── flow/        # Main flow container component (ofl-flow)
│   ├── form/        # Form container component (ofl-form)
│   └── stages/      # Stage progress component (ofl-stages)
├── react/           # React wrapper components
├── plugins/         # Build plugins (lit-css PostCSS plugin)
├── docs/            # Documentation assets
├── index.ts         # Main entry point
└── package.json
```

### Exports

```typescript
// Component classes
export { OflActions } from "@onlive.ai/flow";
export { OflError }   from "@onlive.ai/flow";
export { OflField }   from "@onlive.ai/flow";
export { OflFlow }    from "@onlive.ai/flow";
export { OflForm }    from "@onlive.ai/flow";
export { OflStages }  from "@onlive.ai/flow";

// Types
export type { PackageContext } from "@onlive.ai/flow";
export type { Field, FieldValue } from "@onlive.ai/flow";
```

### Build Formats

| Format | File | Use Case |
|--------|------|----------|
| ESM | `index.js` | Modern bundlers (Vite, Webpack, Rollup) |
| CommonJS | `index.cjs` | Node.js environments |
| IIFE | `index.iife.js` | Direct browser `<script>` tags (global: `OnliveFlow`) |
| TypeScript | `index.d.ts` | TypeScript type definitions |

## Usage

### With a Bundler

```typescript
// Import side-effectful — registers all custom elements
import "@onlive.ai/flow";

// Or import specific components
import "@onlive.ai/flow/components/flow/flow.element.js";
import "@onlive.ai/flow/components/form/form.element.js";

// Import types
import type { Field, FieldValue, PackageContext } from "@onlive.ai/flow";
```

### With React

```tsx
// Aggregated React wrapper entry
import { OflFlow, OflForm, OflField, OflStages, OflActions, OflError } from "@onlive.ai/flow/react";

// Or per-component
import { OflField } from "@onlive.ai/flow/react/components/field/Field";

function App() {
  return (
    <OflFlow
      context={{
        options: {
          baseUrl: "https://flow-api.onlive.site",
          organizationId: "your-organization-id",
          flowId: "your-flow-id",
        },
      }}
      onOflClosePanel={() => console.log("closed")}
      onOflOrganizationCall={(e) => console.log("call", e.detail)}
    />
  );
}
```

## API Reference

The following diagrams show the structural distribution of components within a flow:

![Flow components](https://cdn.onlive.site/@onlive.ai/flow@latest/docs/flow-components.png)
![Form components](https://cdn.onlive.site/@onlive.ai/flow@latest/docs/form-components.png)

---

### `ofl-flow`

The main container component. Manages the complete flow lifecycle: loading steps, handling navigation, collecting form values, and dispatching lifecycle events. Internally composes `ofl-stages`, `ofl-form`, and `ofl-actions`.

#### Import

```js
// ESM / Bundler
import "@onlive.ai/flow/components/flow/flow.element.js";

// CDN
<script type="module" src="https://cdn.onlive.site/@onlive.ai/flow@latest/components/flow/flow.element.js"></script>
```

#### Example

```html
<ofl-flow
  .context=${{
    options: {
      baseUrl: "https://flow-api.onlive.site",
      organizationId: "58b4b948-36d7-459b-adea-ca60412725a6",
      flowId: "683dbe2ea5ab95720a6b242f",
      lang: "en",
      theme: "light",
      navigation: { mode: "steps", position: "top" },
      inContainer: false,
    },
  }}
></ofl-flow>
```

#### Properties

| Name | Type | Reflects | Default | Description |
|------|------|----------|---------|-------------|
| `context` | `PackageContext` | `false` | `undefined` | Flow configuration. See [Context Configuration](#context-configuration) below. |

#### Public Methods

| Method | Description |
|--------|-------------|
| `close()` | Resets flow state and reloads the first step. |

#### Events

| Name | Detail Type | Description |
|------|-------------|-------------|
| `ofl-close-panel` | `{}` | Fired when a close-panel action is triggered. |
| `ofl-organization-call` | `{ params?: Record<string, unknown> }` | Fired when an organization call action is triggered. |
| `ofl-organization-chat` | `{ params?: Record<string, unknown> }` | Fired when an open-chat action is triggered. |
| `ofl-context-data` | `FlowContext` | Fired when the internal flow context data changes. |

#### Context Configuration

The `context` property accepts a `PackageContext` object:

```typescript
type PackageContext = {
  options?: FlowOptions;
  tracker?: Tracker;
  devMode?: boolean;
};

type FlowOptions = {
  baseUrl?: string;              // Base URL for the Flow API
  organizationId?: string;       // Organization identifier
  flowId?: string;               // Flow identifier to load
  stepId?: string;               // Jump directly to a specific step
  lang?: string;                 // Language code (e.g. "en", "es")
  theme?: "light" | "dark";      // Color scheme
  themeName?: string;            // Named theme override
  customStyles?: CSSStyleSheet;  // Custom styles applied to shadow DOM
  initialState?: Record<string, unknown>; // Pre-filled form state
  inContainer?: boolean;         // Whether rendered inside a container
  withTransparency?: boolean;    // Transparent background mode
  navigation?: {
    mode: "tabs" | "accordion" | "steps";
    position?: "top" | "middle" | "bottom";
  };
  tracking?: TrackingOptions<EventData>; // Analytics tracking configuration
  autoReposition?: {
    enabled: boolean;
    offset?: number;
  };
  loadingErrors?: {
    firstStep?: ErrorData;
    nextStep?: ErrorData;
  };
  currentModule?: "flow" | "chat" | "avatar" | "ievents" | "istore";
};
```

---

### `ofl-stages`

Displays stage progress in a multi-step flow. Renders responsively — a compact progress bar on small screens, a full stage list on larger ones.

#### Import

```js
// ESM / Bundler
import "@onlive.ai/flow/components/stages/stages.element.js";

// CDN
<script type="module" src="https://cdn.onlive.site/@onlive.ai/flow@latest/components/stages/stages.element.js"></script>
```

#### Example

```html
<ofl-stages
  active="stage-2"
  mode="steps"
  position="top"
  .stages=${[
    { id: "stage-1", name: "Personal Info" },
    { id: "stage-2", name: "Address" },
    { id: "stage-3", name: "Review" },
  ]}
></ofl-stages>
```

#### Properties

| Name | Type | Reflects | Default | Description |
|------|------|----------|---------|-------------|
| `context` | `PackageContext \| undefined` | `false` | `undefined` | Package context with custom styles. |
| `active` | `string` | `false` | `""` | ID of the currently active stage. |
| `stages` | `Array<{ id: string; name: string }>` | `false` | `[]` | Stage definitions. |
| `position` | `"top" \| "middle" \| "bottom"` | `false` | `"top"` | Vertical placement of the component within the layout. |
| `mode` | `"steps" \| "accordion" \| "tabs"` | `false` | `"tabs"` | Navigation display style. |

---

### `ofl-form`

Renders a list of fields and manages their collective values and validation state.

#### Import

```js
// ESM / Bundler
import "@onlive.ai/flow/components/form/form.element.js";

// CDN
<script type="module" src="https://cdn.onlive.site/@onlive.ai/flow@latest/components/form/form.element.js"></script>
```

#### Example

```html
<ofl-form
  .fields=${[
    { name: "fullName", label: "Full Name", type: "text", component: "input", required: true },
    { name: "email", label: "Email", type: "email", component: "input", required: true },
  ]}
></ofl-form>
```

#### Properties

| Name | Type | Reflects | Default | Description |
|------|------|----------|---------|-------------|
| `context` | `PackageContext \| undefined` | `false` | `undefined` | Package context with custom styles. |
| `fields` | `Array<Field>` | `false` | `[]` | Field definitions to render. |
| `readonly` | `boolean` | `false` | `false` | Puts all fields into read-only mode. |
| `errors` | `Array<{ name: string; error: string }>` | `false` | `[]` | External field-level validation errors. |

#### Events

| Name | Detail Type | Description |
|------|-------------|-------------|
| `ofl-change` | `{ values: Record<string, FieldValue \| FieldValue[] \| undefined>; valid: boolean }` | Fired when any field value or validation state changes. |
| `ofl-submit` | `{ action?: Partial<Pick<Action, "id" \| "type">> }` | Fired when a field triggers form submission. |

---

### `ofl-field`

A versatile single-field component that adapts to the field type. Handles value management, validation, and specialized input controllers (map, calendar, Stripe, carousel).

#### Import

```js
// ESM / Bundler
import "@onlive.ai/flow/components/field/field.element.js";

// CDN
<script type="module" src="https://cdn.onlive.site/@onlive.ai/flow@latest/components/field/field.element.js"></script>
```

#### Example

```html
<ofl-field
  .field=${{
    name: "email",
    label: "Email Address",
    type: "email",
    component: "input",
    required: true,
  }}
></ofl-field>
```

#### Properties

| Name | Type | Reflects | Default | Description |
|------|------|----------|---------|-------------|
| `context` | `PackageContext \| undefined` | `false` | `undefined` | Package context with custom styles. |
| `field` | `Field` | `false` | `undefined` | Field configuration object. |
| `name` | `string` | `true` | `undefined` | Field name identifier. |
| `errorMessage` | `string` | `false` | `""` | External error message to display. |
| `type` | `Field["type"]` | `true` | `undefined` | Input type (e.g. `"text"`, `"email"`, `"number"`). |
| `component` | `Field["component"]` | `true` | `undefined` | Component to render (e.g. `"input"`, `"select"`, `"checkbox"`). |

#### Supported Component Types

`button`, `calendar`, `carousel`, `checkbox`, `grid`, `input`, `label`, `map`, `phone-input`, `radio`, `rating`, `select`, `stripe`, `switch`, `textarea`

See the [Field Types reference](https://dev-docs.onlive.site/docs/onlive-flows/fields) for the complete list.

#### Events

| Name | Detail Type | Description |
|------|-------------|-------------|
| `ofl-change` | `{ value?: FieldValue \| FieldValue[]; valid: boolean }` | Fired when the field value changes. |
| `ofl-interaction` | `{ kind?: "initial" \| "final" }` | Fired when the user interacts with the field. |
| `ofl-submit` | `{ action?: Partial<Pick<Action, "id" \| "type">>; options?: FormSubmitOptions }` | Fired when the field triggers form submission. |

---

### `ofl-actions`

Renders a set of action buttons based on the provided configuration.

#### Import

```js
// ESM / Bundler
import "@onlive.ai/flow/components/actions/actions.element.js";

// CDN
<script type="module" src="https://cdn.onlive.site/@onlive.ai/flow@latest/components/actions/actions.element.js"></script>
```

#### Example

```html
<ofl-actions
  position="bottom"
  .actions=${[
    { id: "back",     label: "Back",     type: "back",   variant: "secondary" },
    { id: "continue", label: "Continue", type: "submit", variant: "primary" },
  ]}
></ofl-actions>
```

#### Properties

| Name | Type | Reflects | Default | Description |
|------|------|----------|---------|-------------|
| `context` | `PackageContext \| undefined` | `false` | `undefined` | Package context with custom styles. |
| `actions` | `Array<ActionButton>` | `false` | `[]` | Action button configurations. |
| `position` | `"top" \| "bottom"` | `true` | `undefined` | Vertical placement within the layout. |
| `extraClasses` | `string[]` | `false` | `[]` | Additional CSS classes for the container. |

#### Events

| Name | Detail Type | Description |
|------|-------------|-------------|
| `ofl-action-click` | `{ action: Action }` | Fired when an action button is clicked. |

---

### `ofl-error`

Displays a structured error state with optional action buttons, used when a flow step fails to load or an API error occurs.

#### Import

```js
// ESM / Bundler
import "@onlive.ai/flow/components/error/error.element.js";

// CDN
<script type="module" src="https://cdn.onlive.site/@onlive.ai/flow@latest/components/error/error.element.js"></script>
```

#### Properties

| Name | Type | Reflects | Default | Description |
|------|------|----------|---------|-------------|
| `context` | `PackageContext \| undefined` | `false` | `undefined` | Package context with custom styles. |
| `error` | `ErrorData \| undefined` | `false` | `undefined` | Error data to display. |

#### Events

| Name | Detail Type | Description |
|------|-------------|-------------|
| `ofl-error-action` | `{ action: Partial<Action>; source: "message" \| "actions" }` | Fired when the user clicks an action inside the error state. |

---

## React Wrappers

All components are available as React wrappers via `@lit/react`. Import from the dedicated entry point:

```tsx
import {
  OflFlow,
  OflForm,
  OflField,
  OflStages,
  OflActions,
  OflError,
} from "@onlive.ai/flow/react";
```

### React Event Props

| Component | React Prop | Native Event |
|-----------|------------|--------------|
| `OflFlow` | `onOflClosePanel` | `ofl-close-panel` |
| `OflFlow` | `onOflOrganizationCall` | `ofl-organization-call` |
| `OflActions` | `onOflActionClick` | `ofl-action-click` |
| `OflError` | `onOflErrorAction` | `ofl-error-action` |
| `OflField` | `onOflChange` | `ofl-change` |
| `OflField` | `onOflSubmit` | `ofl-submit` |
| `OflField` | `onOflInteraction` | `ofl-interaction` |
| `OflForm` | `onOflChange` | `ofl-change` |
| `OflForm` | `onOflSubmit` | `ofl-submit` |

## Theming

### Base Theming

`@onlive.ai/flow` uses [Onlive UI](https://ui.onlive.site/) for styling. Use the [UI theming guide](https://ui.onlive.site/getting-started/themes/) to customize the color palette and typography, and the individual [UI component docs](https://ui.onlive.site/components/button/#styling-buttons) for per-component overrides.

#### Color Palette Example

![Custom Buttons](https://cdn.onlive.site/@onlive.ai/flow@latest/docs/custom-buttons.png)

```css
:root {
  --ol-color-primary-50:  rgb(255 248 249);
  --ol-color-primary-100: rgb(254 231 236);
  --ol-color-primary-200: rgb(253 212 220);
  --ol-color-primary-300: rgb(252 190 203);
  --ol-color-primary-400: rgb(251 160 179);
  --ol-color-primary-500: rgb(249 117 145);
  --ol-color-primary-600: rgb(247  52  93);
  --ol-color-primary-700: rgb(217   4  49);
  --ol-color-primary-800: rgb(180   4  41);
  --ol-color-primary-900: rgb(131   3  30);
  --ol-color-primary-950: rgb( 85   2  19);
}

ol-button::part(base) {
  border-radius: var(--ol-border-radius-pill);
  border: 2px solid var(--ol-color-primary-600);
}

ol-button[variant="default"]::part(base) {
  color: var(--ol-color-primary-600);
  font-weight: var(--ol-font-weight-bold);
}
```

### Advanced Theming with Custom Styles

Pass a `CSSStyleSheet` via `options.customStyles` in the `context` to scope styles inside the shadow DOM. You can target internal layout classes for granular control.

#### Actions Layout Example

![Actions per row](https://cdn.onlive.site/@onlive.ai/flow@latest/docs/actions-per-row.png)

```css
/* Render 3 action buttons per row */
.ofl__actions {
  grid-template-columns: repeat(3, 1fr);
}

.ofl__actions .ofl__actions__button:last-child {
  grid-column: span 1;
}
```

## Dependencies

| Package | Purpose |
|---------|---------|
| `lit` | Web components framework |
| `@lit/context` | Context provider/consumer pattern |
| `@onlive.ai/flow-client` | Flow API client and state management |
| `@onlive.ai/ui` | UI component library |
| `@onlive.ai/common-121` | Shared utilities and types |
| `@onlive.ai/calendar` | Calendar components for date fields |
| `@onlive.ai/tracker` | Analytics event tracking |
| `@formkit/tempo` | Date/time formatting |
| `validator` | Input validation utilities |

**Peer dependency:** `react@^19.1.1` (only required when using React wrappers).

## Development

```bash
# Install dependencies
pnpm install

# Build all formats (ESM, CJS, IIFE, React wrappers)
pnpm run build:package

# Remove generated build artifacts
pnpm run clean
```

## Browser Support

Requires browser support for [Web Components](https://caniuse.com/custom-elementsv1):

| Browser | Minimum Version |
|---------|-----------------|
| Chrome | 54+ |
| Firefox | 63+ |
| Safari | 10.1+ |
| Edge | 79+ |

## Related Packages

| Package | Description |
|---------|-------------|
| [`@onlive.ai/flow-client`](https://www.npmjs.com/package/@onlive.ai/flow-client) | Flow management and API client |
| [`@onlive.ai/ui`](https://ui.onlive.site/) | UI component library |
| [`@onlive.ai/calendar`](https://www.npmjs.com/package/@onlive.ai/calendar) | Calendar components for date fields |

## Documentation

- [Onlive Flow Overview](https://dev-docs.onlive.site/docs/onlive-flows/overview)
- [Field Types Reference](https://dev-docs.onlive.site/docs/onlive-flows/fields)
- [Custom Flow Implementation](https://dev-docs.onlive.site/docs/onlive-flows/custom-flow)
- [Onlive UI Documentation](https://ui.onlive.site/)

## License

Proprietary software — © Onlive.ai. All rights reserved.

For support, visit the [Onlive documentation](https://dev-docs.onlive.site/) or contact the development team.