@sonata-innovations/fiber-fbt
v1.0.4
Published
Fiber Tool — drag-and-drop form builder UI that outputs structured Flow JSON
Maintainers
Readme
@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 (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
npm install @sonata-innovations/fiber-fbtThen import the CSS in your app entry point:
import "@sonata-innovations/fiber-fbt/styles";Peer dependencies: react and react-dom (^18.0.0 || ^19.0.0).
Usage
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 />:
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
// 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
npm run dev # Start Vite dev server
npm run build # Type-check + build library (ES + CJS)
npm run preview # Preview production buildBuild 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) |
