telega/dialog/widget
Built-in managed keyboard widgets for dialogs.
A widget renders extra button rows for a window and handles their events
itself (see KeyboardWidget in telega/dialog/types): the dialog engine
appends widget rows after the window’s own buttons and routes widget
button presses (w:<widget_id>:<cmd> action ids) to the widget, bypassing
the window’s on_action. Widget state lives in a per-widget WidgetStore
persisted with the dialog instance, so selections and page positions
survive restarts.
Built-ins:
pager— page navigation row (‹ 2/5 ›); read the page withcurrent_pageto slice content in the window’s render.select— one-shot choice: a press callson_selected(usually aGoto).radio— single choice kept in the store, marked withlabels.checked; read withradio_value.multiselect— a set of choices with checkboxes and adonebutton shown only while the selection count is withinmin/max; read withmultiselect_values.paged_select—selectandpagercombined: items are sliced by the widget itself.
Reading widget state from window handlers (on_action, on_text,
on_done) and renders goes through dialog.widget_store:
let zone =
dialog.widget_store(ctx, window_id: "prefs", widget_id: "zone")
|> widget.radio_value
|> option.unwrap("hall")
All user-facing symbols (‹, ›, ●, ☑, “done”) come from the
dialog’s Labels — override them with dialog.with_labels for i18n.
Types
An item offered by select/radio/multiselect/paged_select. The id
travels in callback data — keep it short (the 64-byte limit is validated
on every render) and without : at the edges of your scheme (an id may
contain :, it is re-joined on parse).
pub type SelectItem {
SelectItem(id: String, label: String)
}
Constructors
-
SelectItem(id: String, label: String)
Values
pub fn current_page(store store: types.WidgetStore) -> Int
The current 0-based page kept by a pager/paged_select store.
pub fn multiselect(
id id: String,
items items: fn(
state,
bot.Context(session, error, dependencies),
) -> List(SelectItem),
min min: Int,
max max: Int,
done done: String,
) -> types.KeyboardWidget(state, session, error, dependencies)
A set of choices with checkbox marks. Toggling above max is ignored;
the labels.done button renders only while the count is within
min/max and emits Goto(done, state) when pressed. done must be an
existing window id — validated by dialog.build().
pub fn multiselect_values(
store store: types.WidgetStore,
) -> List(String)
The item ids currently selected in a multiselect store, in pick order.
pub fn paged_select(
id id: String,
items items: fn(
state,
bot.Context(session, error, dependencies),
) -> List(SelectItem),
page_size page_size: Int,
columns columns: Int,
on_selected on_selected: fn(
state,
String,
bot.Context(session, error, dependencies),
) -> Result(types.DialogAction(state), error),
) -> types.KeyboardWidget(state, session, error, dependencies)
select and pager in one widget: items are sliced to the current page
by the widget itself (page_size counts items, not rows), the pager row
appears only when there is more than one page.
pub fn pager(
id id: String,
page_size page_size: Int,
total total: fn(
state,
bot.Context(session, error, dependencies),
) -> Int,
) -> types.KeyboardWidget(state, session, error, dependencies)
Page navigation: the store keeps the current page, the row renders as
‹ 2/5 › (the counter is a no-op button). total returns the number of
items; the row disappears when everything fits on one page. Slice your
content in the window’s render with current_page.
pub fn radio(
id id: String,
items items: fn(
state,
bot.Context(session, error, dependencies),
) -> List(SelectItem),
default default: option.Option(String),
) -> types.KeyboardWidget(state, session, error, dependencies)
Single choice kept in the widget store: the selected item is marked with
labels.checked, the rest with labels.unchecked. default is only a
visual pre-selection — radio_value stays None until the user actually
picks, so apply the same default when reading.
pub fn radio_value(
store store: types.WidgetStore,
) -> option.Option(String)
The item id picked in a radio store, None until the first press.
pub fn seed_store(
window_id window_id: String,
widget_id widget_id: String,
store store: types.WidgetStore,
) -> Nil
Seed a widget store for pure render tests — the runtime equivalent is the engine’s automatic stash before user code. Merges into the current stash.
pub fn select(
id id: String,
items items: fn(
state,
bot.Context(session, error, dependencies),
) -> List(SelectItem),
columns columns: Int,
on_selected on_selected: fn(
state,
String,
bot.Context(session, error, dependencies),
) -> Result(types.DialogAction(state), error),
) -> types.KeyboardWidget(state, session, error, dependencies)
One-shot choice: each item is a button, a press calls on_selected with
the item id and the resulting DialogAction is applied (usually a
Goto). Nothing is stored. columns lays the buttons out in a grid
(1 = one item per row).
pub fn widget_store(
ctx: bot.Context(session, error, dependencies),
window_id window_id: String,
widget_id widget_id: String,
) -> types.WidgetStore
Read a widget’s store from inside a window render or handler. Returns an
empty store when the widget has no state yet. Prefer the typed readers on
top: radio_value, multiselect_values, current_page.