v1.0
Primitive API / Page 04·01

FlexiBoard

The main container component of a board, managing the targets and widgets within it.

FlexiBoard (component)

Props
NameDescription
controller
Optional Bindable
FlexiBoardController | undefined

The controller managing this component's state and behaviour. Bind to it to access the component's imperative API.

onfirstcreate
Optional
((instance: FlexiBoardController) => void) | undefined

Fires when the component's controller is first created.

children
Required
Snippet

The child content of the board, which should contain the inner FlexiTarget and FlexiWidget components.

config
Optional
FlexiBoardConfiguration<ClassValue>

The configuration object for the board.

class
Optional
ClassValue

The class names to apply to the board's root element.

suspense
Optional
Snippet<[FlexiBoardSuspenseReason]>

Fallback content shown while the board's server-rendered layout is provisional: a stored layout not yet imported, or an unconfirmed responsive breakpoint guess. It is server-rendered alongside the board and toggled by generated CSS, so it applies from the first paint. It unmounts once the layout is confirmed at hydration.

<script lang="ts">
	import { FlexiBoard, FlexiTarget } from '@flexiboards/svelte';
</script>

<FlexiBoard class="flex gap-4" config={{ widgetDefaults: { draggability: 'full' } }}>
	<FlexiTarget key="main">
		<!-- widgets go here -->
	</FlexiTarget>
</FlexiBoard>

FlexiBoardController

You can access the controller via binding to the controller prop or using the onfirstcreate callback.

<script lang="ts">
	import { FlexiBoard, type FlexiBoardController } from '@flexiboards/svelte';

	let board: FlexiBoardController | undefined = $state();
</script>

<FlexiBoard bind:controller={board}>
	<!-- targets go here -->
</FlexiBoard>
Properties
NameDescription
style
string

The reactive styling to apply to the board's root element.

ref
HTMLElement | undefined

The reactive DOM reference to the board's root element.

breakpoint
Readonly
string

The breakpoint that the board corresponds to, if the board is responsive.

layoutPending
Readonly
boolean

Whether the board's rendered layout is provisional: a `loadLayout` (or `loadLayouts`) is configured but hasn't run yet. True throughout a server render and during hydration until the stored layout is imported. Adapters expose it in the markup (`data-flexi-pending="layout"`) so a skeleton or veil can cover the stand-in layout.

breakpointPending
Readonly
string | null

The breakpoint this render is assuming without confirmation, or null once it's real. Non-null only for a board under a ResponsiveFlexiBoard during a server render, where the rendered breakpoint is a guess. Adapters emit it as `data-flexi-pending="<key>"` (unless layoutPending takes priority) so a stylesheet can veil the board only when the viewport doesn't match the guess.

currentWidgetAction
Readonly
WidgetAction | null

The move or resize the user is in the middle of, or null when idle. Reactive: read it during render to react to a drag starting and ending.

Methods
NameDescription
moveWidget
(widget: FlexiWidgetController, from: FlexiTargetController | undefined, to: FlexiTargetController) => void

Moves an existing widget from one target to another.

importLayout
(layout: FlexiLayout | FlexiLayoutEnvelope) => void

Imports a widget layout into the board: a bare layout, or the `{ version, layout }` envelope that `exportLayoutEnvelope()` returns.

exportLayout
() => FlexiLayout

Exports the current widget layout of the board.

exportLayoutEnvelope
() => FlexiLayoutEnvelope

Exports the layout with its format version, the shape to persist so a later release can migrate it on import.

clear
() => void

Deletes every widget in every target of this board. Fires `onWidgetDelete` per widget and `onLayoutChange` once.

FlexiBoardConfiguration

FlexiBoard accepts these options through config. See Configuration reactivity for update behavior and initialization-only options.

For reactivity, give the config prop a reactive source (a proxy).

Properties
NameDescription
widgetDefaults
Optional
FlexiWidgetDefaults<ClassValue> | undefined

The default configuration for widgets within this board.

targetDefaults
Optional
FlexiTargetDefaults | undefined

The default configuration for targets within this board.

breakpoint
Optional
string | undefined

Optional breakpoint override. When this board is inside a ResponsiveFlexiBoard, the breakpoint is automatically inferred from the responsive controller's `currentBreakpoint`. You typically don't need to set this manually. If set outside of a ResponsiveFlexiBoard context, a warning will be logged.

registry
Optional
Record<string, FlexiRegistryEntry<ClassValue>> | undefined

A registry of widget types, mapping type keys to shared widget configuration. Widgets reference an entry via their `type`.

initialLayout
Optional
FlexiLayout | undefined

A layout to render from instead of the widgets declared in markup, as a plain value keyed by target. Applied during the initial render pass on both the server and the client, so a layout fetched in a server request handler (e.g. from a database) server-renders at its final positions with no pending window. Requires a `registry` to resolve each entry's `type`. Targets without an entry here fall back to their declared widgets. A configured `loadLayout` still runs on the client and overrides this.

loadLayout
Optional
(() => | FlexiLayout | FlexiLayoutEnvelope | FlexiWidgetLayoutEntry[] | undefined) | undefined

Function to load an initial layout on mount. Called once when the board is ready. Not invoked during server rendering. Use `initialLayout` for layouts the server already has.

onLayoutChange
Optional
((layout: FlexiLayout) => void) | undefined

Callback fired when the board's layout changes (widget moved, resized, added, or removed), whether by the user or through the controller API. Receives the committed layout in a microtask, before drop animations settle. Synchronous changes are batched into one notification.

onWidgetGrab
Optional
((event: FlexiWidgetEvent) => void) | undefined

Called when the user picks a widget up (by pointer or keyboard).

onWidgetDrop
Optional
((event: FlexiWidgetDropEvent) => void) | undefined

Called when a widget the user was moving or resizing lands in a target. Fires after the placement is committed, so the widget's `x`, `y`, `width`, `height` and `target` are already final.

onWidgetCancel
Optional
((event: FlexiWidgetEvent) => void) | undefined

Called when the user cancels a move or resize (Escape, or releasing where nothing accepts the widget); the widget is back where it started.

onWidgetDelete
Optional
((event: FlexiWidgetEvent) => void) | undefined

Called when a widget is deleted, by dropping it on a FlexiDelete or by calling `widget.delete()`.

onWidgetResize
Optional
((event: FlexiWidgetEvent) => void) | undefined

Called when a resize the user was making commits. The widget's `width` and `height` are already final.

onWidgetEnterTarget
Optional
((event: FlexiWidgetEvent) => void) | undefined

Called when a widget being moved is carried over a target, which then shows a drop preview for it.

onWidgetLeaveTarget
Optional
((event: FlexiWidgetEvent) => void) | undefined

Called when a widget being moved leaves the target it was over.

canDrop
Optional
((check: FlexiDropCheck) => boolean) | undefined

Decides whether a widget may be placed at a position. Called while the user hovers (so the drop preview can show a rejection) and again on release. Return false to refuse: the widget stays where it was. Placement rules the grid already enforces (bounds, collisions) run regardless.

portalDropFlights
Optional
boolean | undefined

Hosts drop flights in the fixed, viewport-level portal instead of flying them inside the board. Reach for this when drops are released outside the board's box and must fly in across its edge without clipping under the board's overflow lock (e.g. a small hero board mid-page). Leave it off for scrollable boards: a portalled flight escapes the scroll container's clip and paints above surrounding chrome for its duration.

Default: false

autoScroll
Optional
boolean | undefined

Scrolls the board's scrollable ancestors (the page included) while a drag or resize hovers within 48px of their visible edge. Turn it off for boards that sit on a page where a drag should never move the viewport (e.g. a marketing hero). An unexpected page scroll mid-drag reads as the board jumping.

Default: true

FlexiTargetDefaults

The default configuration for targets.

Properties
NameDescription
rowSizing
Optional
(string | (({ target, grid }: { target: FlexiTargetController; grid: FlexiGrid }) => string))

The value inside the target's `grid-template-rows` `repeat()` function.

columnSizing
Optional
(string | (({ target, grid }: { target: FlexiTargetController; grid: FlexiGrid }) => string))

The value inside the target's `grid-template-columns` `repeat()` function.

layout
Optional
TargetLayout

The layout algorithm and parameters to use for the target grid.

Interaction callbacks

onWidgetGrab, onWidgetDrop, onWidgetResize, onWidgetCancel, onWidgetDelete, onWidgetEnterTarget and onWidgetLeaveTarget receive these events. canDrop receives a FlexiDropCheck and returns whether the placement is allowed; see Reacting to interactions for when each fires.

FlexiWidgetEvent

Properties
NameDescription
widget
Required
FlexiWidgetController
target
Optional
FlexiTargetController

The target the widget is in or over. Undefined when it is over none (e.g. a cancelled adder drag).

FlexiWidgetDropEvent

Properties
NameDescription
widget
Required
FlexiWidgetController
sourceTarget
Optional
FlexiTargetController

The target the widget was picked up from. Undefined for a widget added through an adder.

target
Required
FlexiTargetController

The target the widget landed in.

FlexiDropCheck

Properties
NameDescription
widget
Required
FlexiWidgetController
target
Required
FlexiTargetController
x
Required
number
y
Required
number
width
Required
number
height
Required
number

FlexiWidgetDefaults

The default configuration for widgets.

Properties
NameDescription
draggability
Optional
'none' | 'movable' | 'full' | undefined

The draggability of the widget.

Default: full

resizability
Optional
'none' | 'horizontal' | 'vertical' | 'both' | undefined

The resizability of the widget.

Default: none

snippet
Optional
(Snippet<[{ widget: FlexiWidgetController }]>)

The render function used for this widget's content.

component
Optional
(Component)

The component that is rendered by this widget.

componentProps
Optional
Record<string, any> | undefined

The props applied to the component rendered, if it has one.

className
Optional
(ClassValue | ((widget: FlexiWidgetController) => ClassValue)) | undefined

The class names to apply to this widget.

transition
Optional
FlexiWidgetTransitionConfiguration | undefined

The transition configuration for this widget.

grabTrigger
Optional
FlexiWidgetTriggerConfiguration | undefined

The configuration for how pointer events should trigger a grab event on the widget. E.g. a long press.

resizeTrigger
Optional
FlexiWidgetTriggerConfiguration | undefined

The configuration for how pointer events should trigger a resize event on the widget. E.g. a long press.

minWidth
Optional
number | undefined

The minimum width of the widget in units. Defaults to 1, cannot be less than 1.

minHeight
Optional
number | undefined

The minimum height of the widget in units. Defaults to 1, cannot be less than 1.

maxWidth
Optional
number | undefined

The maximum width of the widget in units. Defaults to Infinity, cannot be less than 1.

maxHeight
Optional
number | undefined

The maximum height of the widget in units. Defaults to Infinity, cannot be less than 1.

FlexiLayout

The value returned by exportLayout() and accepted by importLayout(), initialLayout, and loadLayout. It maps each target’s key to an array of entries. See Exporting & Importing.

FlexiWidgetLayoutEntry

Properties
NameDescription
id
Optional
string

A stable identifier for this widget. Always present in an export: the id you gave the widget, or a generated one. Round-trips through import.

type
Optional
string

The registry key that says how to render this widget. Exported even when absent, so no widget's position is lost; on import, entries without a type are skipped, since nothing says how to render them.

x
Required
number

The column the widget starts at, zero-indexed.

y
Required
number

The row the widget starts at, zero-indexed.

width
Required
number

The width of the widget in grid units.

height
Required
number

The height of the widget in grid units.

metadata
Optional
Record<string, any>

Custom serialisable data attached to the widget, preserved through export and import.

FlexiRegistryEntry

An entry in the board’s registry, keyed by widget type. Its properties are widget defaults applied to every widget of that type.

Properties
NameDescription
draggability
Optional
'none' | 'movable' | 'full' | undefined

The draggability of the widget.

Default: full

resizability
Optional
'none' | 'horizontal' | 'vertical' | 'both' | undefined

The resizability of the widget.

Default: none

snippet
Optional
(Snippet<[{ widget: FlexiWidgetController }]>)

The render function used for this widget's content.

component
Optional
(Component)

The component that is rendered by this widget.

componentProps
Optional
Record<string, any> | undefined

The props applied to the component rendered, if it has one.

className
Optional
(ClassValue | ((widget: FlexiWidgetController) => ClassValue)) | undefined

The class names to apply to this widget.

transition
Optional
FlexiWidgetTransitionConfiguration | undefined

The transition configuration for this widget.

grabTrigger
Optional
FlexiWidgetTriggerConfiguration | undefined

The configuration for how pointer events should trigger a grab event on the widget. E.g. a long press.

resizeTrigger
Optional
FlexiWidgetTriggerConfiguration | undefined

The configuration for how pointer events should trigger a resize event on the widget. E.g. a long press.

minWidth
Optional
number | undefined

The minimum width of the widget in units. Defaults to 1, cannot be less than 1.

minHeight
Optional
number | undefined

The minimum height of the widget in units. Defaults to 1, cannot be less than 1.

maxWidth
Optional
number | undefined

The maximum width of the widget in units. Defaults to Infinity, cannot be less than 1.

maxHeight
Optional
number | undefined

The maximum height of the widget in units. Defaults to Infinity, cannot be less than 1.

Accessibility

The board renders as role="application", described by a visually hidden instructions element, and carries aria-busy while a layout is pending. It also hosts the aria-live announcer that reports grabs, resizes, releases, and rejected drops. See Accessibility.