Skip to content

TheFreeform

The main container component that manages all drag & drop state.

Basic Usage

vue
<TheFreeform v-model="items" @drop-into="onDropInto">
  <FreeformItem v-for="item in items" :key="item.id" :item="item" />
  <FreeformPlaceholder />
</TheFreeform>

Props

PropTypeDefaultDescription
modelValueFreeformItemData[]requiredItems array (v-model)
disabledbooleanfalseDisable all interactions
manualReorderbooleanfalseDon't auto-reorder, handle @reorder manually

Events

EventPayloadDescription
update:modelValueitems[]Items array changed (reorder)
selectitems[]Selection changed
drag-startitems[]Drag operation started
drag-moveitems[], positionDragging (with cursor position)
drag-enditems[]Drag operation ended
drop-intoitems[], container, acceptedItems dropped into a container
reorderfromIndex, toIndexItems reordered

Slots

Default Slot

Receives state information:

vue
<TheFreeform v-model="items">
  <template #default="{ items, selected, isDragging, dragItems, dropIndex }">
    <!-- Your content -->
  </template>
</TheFreeform>
PropTypeDescription
itemsarrayCurrent items
selectedarrayCurrently selected items
isDraggingbooleanDrag in progress
dragItemsarrayItems being dragged
dropIndexnumberWhere items will drop

drag-ghost

Custom ghost displayed while dragging:

vue
<template #drag-ghost="{ items, count, position }">
  <div class="my-ghost">
    {{ items[0]?.name }}
    <span v-if="count > 1">+{{ count - 1 }}</span>
  </div>
</template>

CSS Variables

Set these on the container to customize colors:

css
.my-freeform {
  --freeform-color-primary: #3b82f6;
  --freeform-color-primary-light: #dbeafe;
  --freeform-color-success: #22c55e;
  --freeform-color-success-light: #dcfce7;
  --freeform-color-danger: #ef4444;
  --freeform-color-danger-light: #fee2e2;
  --freeform-color-neutral: #f3f4f6;
  --freeform-color-text: #374151;
}

Manual Reorder

Set manualReorder to handle reordering yourself:

vue
<TheFreeform
  v-model="items"
  :manual-reorder="true"
  @reorder="handleReorder"
>
ts
function handleReorder(fromIndex: number, toIndex: number) {
  // Custom reorder logic
  const item = items.value.splice(fromIndex, 1)[0]
  items.value.splice(toIndex, 0, item)
}

MIT Licensed