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 elementcontainer_class: CSS classes to apply to the container (e.g., grid layout classes)item_class: CSS class for individual sortable itemsdragging_class: CSS class applied to the item being draggeddrag_over_class: CSS class applied to the item being dragged overghost_class: CSS class for the drag ghost/placeholderaccept_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 progressDragging: Desktop drag in progress with source container, index, and optional targetTouchDragging: 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 containerdrag_state: Current drag state (should be managed in your application state)items: List of sortable items to renderrender_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 reorderfrom_index: The current index of the item to moveto_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 processdrag_state: The current drag stateconfig: The sortable configuration (needed to check accept_from)
Returns
A tuple containing:
- The new
DragStateafter processing the message Option(ReorderAction)- Information about reorder/transfer action,Noneotherwise
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())
}
}
}