ensaimada

Types

Configuration for a sortable container.

  • on_reorder: Callback function called when items are reordered with (from_index, to_index)
  • container_id: HTML id attribute for the container element
  • container_class: CSS classes to apply to the container (e.g., grid layout classes)
  • item_class: CSS class for individual sortable items
  • dragging_class: CSS class applied to the item being dragged
  • drag_over_class: CSS class applied to the item being dragged over
  • ghost_class: CSS class for the drag ghost/placeholder
  • accept_from: List of container IDs that can drop items into this container (empty list = only same container)
pub type Config(msg) {
  Config(
    on_reorder: fn(Int, Int) -> msg,
    container_id: String,
    container_class: String,
    item_class: String,
    dragging_class: String,
    drag_over_class: String,
    ghost_class: String,
    accept_from: List(String),
  )
}

Constructors

  • Config(
      on_reorder: fn(Int, Int) -> msg,
      container_id: String,
      container_class: String,
      item_class: String,
      dragging_class: String,
      drag_over_class: String,
      ghost_class: String,
      accept_from: List(String),
    )

Represents the current drag state of the sortable container.

  • NoDrag: No drag operation in progress
  • Dragging: Desktop drag in progress with source container, index, and optional target
  • TouchDragging: Mobile touch drag in progress with source container, index, and optional target
pub type DragState {
  NoDrag
  Dragging(
    source_container: String,
    source_index: Int,
    over_container: option.Option(String),
    over_index: option.Option(Int),
  )
  TouchDragging(
    source_container: String,
    source_index: Int,
    over_container: option.Option(String),
    over_index: option.Option(Int),
  )
}

Constructors

  • NoDrag
  • Dragging(
      source_container: String,
      source_index: Int,
      over_container: option.Option(String),
      over_index: option.Option(Int),
    )
  • TouchDragging(
      source_container: String,
      source_index: Int,
      over_container: option.Option(String),
      over_index: option.Option(Int),
    )

A wrapper for items in a sortable list. The type is opaque to ensure proper encapsulation of the item data and metadata.

Use ensaimada.item() to create instances and accessor functions to retrieve data.

pub opaque type Item(a)

Messages emitted by the sortable container during drag and drop interactions. These should be handled in your application’s update function.

pub type Msg(msg) {
  StartDrag(container_id: String, index: Int)
  DragOver(Int)
  DragEnter(container_id: String, index: Int)
  DragLeave
  Drop(container_id: String, index: Int)
  DragEnd
  TouchStart(container_id: String, index: Int)
  TouchMove
  TouchEnd
  TouchEnter(container_id: String, index: Int)
  UserMsg(msg)
}

Constructors

  • StartDrag(container_id: String, index: Int)
  • DragOver(Int)
  • DragEnter(container_id: String, index: Int)
  • DragLeave
  • Drop(container_id: String, index: Int)
  • DragEnd
  • TouchStart(container_id: String, index: Int)
  • TouchMove
  • TouchEnd
  • TouchEnter(container_id: String, index: Int)
  • UserMsg(msg)

Represents different types of reorder actions

pub type ReorderAction {
  SameContainer(from_index: Int, to_index: Int)
  CrossContainer(
    from_container: String,
    from_index: Int,
    to_container: String,
    to_index: Int,
  )
}

Constructors

  • SameContainer(from_index: Int, to_index: Int)

    Reordering within the same container

  • CrossContainer(
      from_container: String,
      from_index: Int,
      to_container: String,
      to_index: Int,
    )

    Moving item from one container to another

Values

pub fn container(
  config: Config(msg),
  drag_state: DragState,
  items: List(Item(a)),
  render_item: fn(Item(a), Int, DragState) -> element.Element(msg),
) -> element.Element(Msg(msg))

Creates a sortable container element that handles drag and drop interactions.

Arguments

  • config: Configuration for the sortable container
  • drag_state: Current drag state (should be managed in your application state)
  • items: List of sortable items to render
  • render_item: Function to render individual items, receives (item, index, drag_state)

Returns

A Lustre Element that handles drag and drop events and renders the sortable items. The element emits Msg events that should be handled in your update function.

Example

ensaimada.container(
  config,
  model.drag_state,
  model.items |> list.index_map(fn(item, i) {
    ensaimada.item("item-" <> int.to_string(i), item)
  }),
  fn(item, index, drag_state) { render_my_item(item, index, drag_state) }
)
pub fn default_config(
  on_reorder: fn(Int, Int) -> msg,
  container_id: String,
) -> Config(msg)

Creates a default sortable configuration with standard CSS classes.

Arguments

  • on_reorder: Function called when items are reordered, receives (from_index, to_index)
  • container_id: HTML id for the sortable container element

Returns

A Config with default CSS classes:

  • Container: “sortable-container”
  • Item: “sortable-item”
  • Dragging: “sortable-dragging”
  • Drag over: “sortable-drag-over”
  • Ghost: “sortable-ghost”

Example

let config = ensaimada.default_config(
  fn(from, to) { ReorderImages(from, to) },
  "image-grid"
)
pub fn item(id: String, data: a) -> Item(a)

Creates a new sortable item with the given id and data.

let item = ensaimada.item("image-1", my_image_data)
pub fn item_data(item: Item(a)) -> a

Extracts the data from a sortable item.

Arguments

  • item: The sortable item to extract data from

Returns

The original data that was stored in the item.

Example

let data = ensaimada.item_data(item)
pub fn item_id(item: Item(a)) -> String

Gets the unique identifier of a sortable item.

Arguments

  • item: The sortable item to get the id from

Returns

The string id that was assigned to the item.

Example

let id = ensaimada.item_id(item)
pub fn reorder(
  items: List(a),
  from_index: Int,
  to_index: Int,
) -> List(a)

Reorders a list by moving an item from one index to another.

Arguments

  • items: The list to reorder
  • from_index: The current index of the item to move
  • to_index: The new index where the item should be placed

Returns

A new list with the item moved to the new position. If indices are invalid or the same, returns the original list unchanged.

Example

let items = [1, 2, 3, 4, 5]
let reordered = ensaimada.reorder(items, 1, 3)
// Result: [1, 3, 4, 2, 5] (moved item at index 1 to index 3)
pub fn update(
  sortable_msg: Msg(msg),
  drag_state: DragState,
  config: Config(msg),
) -> #(DragState, option.Option(ReorderAction))

Updates the drag state based on sortable messages and returns reorder information.

This function should be called from your application’s update function when handling Msg events. It manages the drag state and returns information about when items should be reordered or moved between containers.

Arguments

  • sortable_msg: The sortable message to process
  • drag_state: The current drag state
  • config: The sortable configuration (needed to check accept_from)

Returns

A tuple containing:

  1. The new DragState after processing the message
  2. Option(ReorderAction) - Information about reorder/transfer action, None otherwise

Example

// In your update function
MyMsg(sortable_msg) -> {
  let #(new_drag_state, maybe_action) =
    ensaimada.update(sortable_msg, model.drag_state, config)

  case maybe_action {
    Some(ensaimada.SameContainer(from, to)) -> {
      let new_items = ensaimada.reorder(model.items, from, to)
      #(Model(..model, items: new_items, drag_state: new_drag_state), effect.none())
    }
    Some(ensaimada.CrossContainer(from_cont, from_idx, to_cont, to_idx)) -> {
      // Handle cross-container transfer
      ...
    }
    None -> {
      #(Model(..model, drag_state: new_drag_state), effect.none())
    }
  }
}
Search Document