npm package: @sonata-innovations/fiber-fbt
Description: Fiber Tool — drag-and-drop form builder UI that outputs structured Flow JSON
Latest version: 1.0.4

# @sonata-innovations/fiber-fbt

**Fiber Tool (FBT)** — A drag-and-drop form builder UI for creating structured Flow JSON. Part of the Fiber system alongside [FBRE](https://www.npmjs.com/package/@sonata-innovations/fiber-fbre) (render engine).

## Overview

FBT is a React library that provides a full-featured visual builder where non-technical users can design multi-screen data collection forms. It outputs structured Flow JSON that FBRE consumes to render the form at runtime.

### Key Features

- **Drag-and-drop** component placement with dnd-kit
- **29 component types** across six categories (Display, Text & Number, Selection, Date & Time, Interactive, Containers)
- **Multi-screen flows** with tabbed navigation
- **Live preview** via embedded FBRE (docked, floating, or fullscreen)
- **Undo/redo** history (100 states) powered by zundo
- **11 presets** (email, phone, URL, dollar amount, address block, contact info, etc.) and **4 templates** (contact form, sign-up, patient intake, feedback survey)
- **Custom presets and templates** via props
- **Repeater components** for iterable field groups (add/remove iterations)
- **Calculations engine** with MIN/MAX, IF/THEN/ELSE, and comparison operators for formula-based computed values
- **Condition system** with 20 operators and AND/OR logic
- **Detail rich text** field with WYSIWYG editing (bold, italic, link) and configurable label visibility via `showLabel`
- **Validation engine** with flow/screen/component-level checks
- **Flow import/export** (JSON)
- **Theme color** customization via prop
- **Group components** for nesting fields together
- **Composable API** for custom layouts

## Installation

```bash
npm install @sonata-innovations/fiber-fbt
```

Then import the CSS in your app entry point:

```ts
import "@sonata-innovations/fiber-fbt/styles";
```

Peer dependencies: `react` and `react-dom` (^18.0.0 || ^19.0.0).

## Usage

```tsx
import { FBT } from "@sonata-innovations/fiber-fbt";
import "@sonata-innovations/fiber-fbt/styles";

function App() {
  return (
    <FBT
      flow={existingFlow}           // optional — load an existing flow
      onFlowChange={(flow) => {     // optional — called on every change
        console.log(flow);
      }}
      themeColor="#1976d2"          // optional — accent color
      storeRef={storeRef}          // optional — expose store via ref
    />
  );
}
```

### Props

| Prop | Type | Description |
|------|------|-------------|
| `flow` | `Flow` | Initial flow to load into the builder |
| `onFlowChange` | `(flow: Flow) => void` | Callback fired on every flow change |
| `themeColor` | `string` | Theme accent color (default: `#1976d2`) |
| `storeRef` | `MutableRefObject<StoreApi<FBTStoreState> \| null>` | Ref to access the Zustand store externally |
| `customPresets` | `AnyPresetDefinition[]` | Custom preset definitions to add to the component palette |
| `customTemplates` | `AnyTemplateDefinition[]` | Custom template definitions to add to the template palette |

## Composable API

For custom layouts, use `FBTProvider` with individual sub-components instead of the all-in-one `<FBT />`:

```tsx
import {
  FBTProvider,
  FBTDndZone,
  FBTPool,
  FBTStage,
  FBTEditor,
  FBTScreenBar,
  FBTToolbar,
} from "@sonata-innovations/fiber-fbt";
import "@sonata-innovations/fiber-fbt/styles";

function CustomBuilder() {
  return (
    <FBTProvider flow={existingFlow} onFlowChange={handleChange}>
      <FBTDndZone>
        <div style={{ display: "flex" }}>
          <FBTPool />
          <div>
            <FBTScreenBar />
            <FBTToolbar />
            <FBTStage />
          </div>
          <FBTEditor />
        </div>
      </FBTDndZone>
    </FBTProvider>
  );
}
```

`FBTProvider` accepts the same props as `<FBT />` plus `children`. The built-in `<FBT />` component is equivalent to `<FBTProvider><FBTDefaultLayout /></FBTProvider>`.

### Composable Components

| Component | Description |
|-----------|-------------|
| `FBTProvider` | Context wrapper — required ancestor for all sub-components |
| `FBTDndZone` | Drag-and-drop wrapper — required ancestor for `FBTPool` and `FBTStage` |
| `FBTPool` | Component palette sidebar (drag source) |
| `FBTStage` | Canvas / drop zone where components are arranged |
| `FBTEditor` | Property editor panel for the selected component |
| `FBTScreenBar` | Screen tab navigation |
| `FBTToolbar` | Top toolbar (undo/redo, import/export, etc.) |
| `FBTPreviewPanel` | Docked FBRE preview panel |
| `FBTPreviewFloat` | Floating FBRE preview overlay |
| `FBTHelpModal` | Help / documentation modal |
| `FBTDefaultLayout` | The default layout used by `<FBT />` — renders all sub-components in the standard arrangement |

### Exports

```ts
// Components
import { FBT } from "@sonata-innovations/fiber-fbt";
import { FBTProvider } from "@sonata-innovations/fiber-fbt";
import {
  FBTDefaultLayout,
  FBTPool,
  FBTStage,
  FBTEditor,
  FBTScreenBar,
  FBTToolbar,
  FBTPreviewPanel,
  FBTPreviewFloat,
  FBTHelpModal,
  FBTDndZone,
} from "@sonata-innovations/fiber-fbt";

// Store hooks
import { useFBTStore, useFBTStoreApi } from "@sonata-innovations/fiber-fbt";

// Types
import type { FBTProviderProps, FBTStoreState } from "@sonata-innovations/fiber-fbt";
import type {
  CustomPresetDefinition,
  CustomTemplateDefinition,
  AnyPresetDefinition,
  AnyTemplateDefinition,
} from "@sonata-innovations/fiber-fbt";
import type { Flow, FlowScreen, Component, FlowMetadata, FlowConfiguration, ComponentProperties } from "@sonata-innovations/fiber-fbt";
```

## Architecture

### Layout

```
┌──────────────────────────────────────────────────────────┐
│  Pool (left)  │      Center          │  Right            │
│               │  ┌────────────────┐  │  ┌─────────────┐  │
│  Components   │  │  Screen Bar    │  │  │  Editor     │  │
│  Presets      │  ├────────────────┤  │  │  (property  │  │
│  Templates    │  │  Toolbar       │  │  │   panel)    │  │
│               │  ├────────────────┤  │  ├─────────────┤  │
│  (drag from   │  │  Stage         │  │  │  Preview    │  │
│   here)       │  │  (drop zone)   │  │  │  (FBRE)     │  │
│               │  └────────────────┘  │  └─────────────┘  │
└──────────────────────────────────────────────────────────┘
```

### Store (Zustand)

The store uses a **flattened architecture** — all components are stored in a single flat map with separate mappings for screen membership (`screenComponents`) and group nesting (`groupComponents`). This simplifies mutations and enables efficient undo/redo via `zundo` temporal middleware.

**Slices:** `flow` | `screens` | `components` | `selection` | `validation` | `calculations`

### Component Types

| Category | Types |
|----------|-------|
| Display | `header`, `text`, `divider`, `callout`, `table`, `computed` |
| Text & Number | `inputText`, `inputTextArea`, `inputNumber` |
| Selection | `dropDown`, `dropDownMulti`, `checkbox`, `radio`, `toggleSwitch`, `yesNo`, `cardSelect` |
| Date & Time | `date`, `time`, `dateTime`, `dateRange`, `timeRange`, `dateTimeRange` |
| Interactive | `fileUpload`, `rating`, `slider`, `colorPicker` |
| Containers | `group`, `repeater` |

### JSON Schema

```
Flow (uuid, metadata, config, screens)
  └─ Screen (uuid, label, components)
       └─ Component (uuid, type, properties, conditions?)
            └─ Group children (nested components)
```

## Styling

CSS modules with a `fbt-` class prefix. All styles bundle into a single `fiber-fbt.css` file. Theme customization is done through CSS custom properties:

| Variable | Default | Description |
|----------|---------|-------------|
| `--fbt-theme` | `#1976d2` | Primary accent color |
| `--fbt-bg` | `#fff` | Background |
| `--fbt-bg-surface` | `#f5f5f5` | Surface background |
| `--fbt-border` | `#ccc` | Border color |
| `--fbt-font-size` | `13px` | Base font size |

## Keyboard Shortcuts

| Shortcut | Action |
|----------|--------|
| `Ctrl+Z` | Undo |
| `Ctrl+Y` | Redo |
| `Delete` | Remove selected component |

## Scripts

```bash
npm run dev       # Start Vite dev server
npm run build     # Type-check + build library (ES + CJS)
npm run preview   # Preview production build
```

## Build Output

| File | Format | Description |
|------|--------|-------------|
| `dist/fiber-fbt.js` | ESM | Tree-shakeable ES module |
| `dist/fiber-fbt.cjs` | CJS | CommonJS module |
| `dist/fiber-fbt.css` | CSS | Bundled styles |
| `dist/index.d.ts` | TypeScript | Bundled type definitions |

## Dependencies

| Package | Purpose |
|---------|---------|
| `zustand` | State management |
| `zundo` | Undo/redo middleware |
| `@dnd-kit/core` + `@dnd-kit/sortable` | Drag-and-drop |
| `@dnd-kit/utilities` | dnd-kit utility helpers |
| `@sonata-innovations/fiber-types` | Shared type definitions |
| `@sonata-innovations/fiber-shared` | Shared validation/condition engines |
| `@sonata-innovations/fiber-fbre` | Live preview (render engine) |