graphix-package-gui 0.8.0

A dataflow language for UIs and network programming, GUI package
Documentation
type SortDirection = [`Ascending, `Descending];
type SortBy = { column: string, direction: SortDirection };

type ColumnType = [
    `Text({ on_edit: [fn(#path: string, #value: Any) -> Any, null] }),
    `Toggle({ on_edit: [fn(#path: string, #value: bool) -> Any, null] }),
    `Combo({
        choices: Array<{ id: string, label: string }>,
        on_edit: [fn(#path: string, #value: string) -> Any, null]
    }),
    `Spin({
        min: f64,
        max: f64,
        increment: f64,
        on_edit: [fn(#path: string, #value: f64) -> Any, null]
    }),
    `Progress,
    `Button({
        on_click: [fn(#path: string, #value: Any) -> Any, null]
    }),
    `Sparkline({
        history_seconds: f64,
        min: [f64, null],
        max: [f64, null]
    })
];

/// Where a column's per-cell values come from.
///
/// - `` `Netidx(fallback) ``: subscribe to `<row_path>/<column_name>`
///   for every absolute-path row. The fallback is the value rendered
///   for cells whose subscription is pending or `Unsubscribed`, AND
///   for virtual rows (non-absolute paths), which never subscribe.
///   It is one of:
///     - `null`: no fallback — cells render blank until the
///       subscription resolves, and virtual rows render blank.
///     - `string`: a uniform placeholder used for every cell.
///     - `Map<string, Any>`: per-row fallback keyed by row basename
///       — virtual rows pick up their map entry, and absolute rows
///       fall back to it before the subscription delivers a value.
/// - `string`: a uniform default — every cell renders this text. No
///   subscription. Useful for static fields and computed columns
///   where one value applies to all rows.
/// - `Map<string, Any>`: per-row defaults keyed by row basename. No
///   subscription on any row. Useful for purely "calculated"
///   columns whose values are derived in graphix and shouldn't
///   ever subscribe.
type Source = [`Netidx([null, string, Map<string, Any>]), string, Map<string, Any>];

type ColumnSpec = {
    name: string,
    typ: ColumnType,
    display_name: [string, null],
    source: &Source,
    on_resize: &[fn(width: f64) -> Any, null],
    width: &[f64, null]
};

/// The data table's content. Rows are netidx paths (absolute paths
/// drive subscriptions; non-absolute rows are virtual). Columns are
/// either bare strings (shorthand for a default Text column with
/// `` `Netidx `` source named after the string) or full `ColumnSpec`
/// structs with explicit type, source, width, etc. Bare strings let
/// `sys::net::Table` (which has `columns: Array<string>`) be passed
/// straight through; mixed arrays are fine.
///
/// Display order is exactly the order of entries in `columns` —
/// virtual and subscribed columns are not segregated.
type Table = {
    rows: Array<string>,
    columns: Array<[string, ColumnSpec]>
};

type DataTable = {
    on_activate: &[fn(#path: string) -> Any, null],
    on_header_click: &[fn(#column: string) -> Any, null],
    on_select: &[fn(#path: string) -> Any, null],
    on_update: &[fn(#path: string, #value: Primitive) -> Any, null],
    selection: &Array<string>,
    show_row_name: &bool,
    sort_by: &Array<SortBy>,
    table: &Table
};

/// A data table that displays rows and columns of data.
///
/// Rows that are absolute netidx paths trigger live subscriptions to
/// `<row_path>/<column_name>` for every column whose `source` is
/// `` `Netidx ``. Rows that are not absolute paths are virtual — they
/// never subscribe and render the column source's fallback value
/// (either the `Netidx` payload's per-row map / uniform string, or
/// the bare `string` / `Map<string, Any>` source).
///
/// The caller owns the shape of the Table: row order, column order,
/// hidden vs. shown, virtual vs. subscribed — all of that lives in
/// the `Table` value the caller passes in.
///
/// `sort_by` is a list of sort keys applied in order: the first key
/// is the primary sort, subsequent keys break ties. Empty list (the
/// default) preserves the Table's row order. Sort values come from
/// the column's source — a live subscription when source is
/// `` `Netidx ``, or the source's stored value otherwise.
val data_table: fn(
    ?#sort_by: &Array<SortBy>,
    ?#selection: &Array<string>,
    ?#show_row_name: &bool,
    ?#on_select: [fn(#path: string) -> Any, null],
    ?#on_activate: [fn(#path: string) -> Any, null],
    ?#on_header_click: [fn(#column: string) -> Any, null],
    ?#on_update: [fn(#path: string, #value: Primitive) -> Any, null],
    #table: &Table
) -> Widget;

/// Build a `Text` ColumnSpec. With no `on_edit` the cell is read-only.
val text_column: fn(
    #name: string,
    ?#on_edit: [fn(#path: string, #value: Any) -> Any, null],
    ?#display_name: [string, null],
    ?#source: &Source,
    ?#on_resize: &[fn(width: f64) -> Any, null],
    ?#width: &[f64, null]
) -> ColumnSpec;

/// Build a `Toggle` ColumnSpec for boolean cells.
val toggle_column: fn(
    #name: string,
    ?#on_edit: [fn(#path: string, #value: bool) -> Any, null],
    ?#display_name: [string, null],
    ?#source: &Source,
    ?#on_resize: &[fn(width: f64) -> Any, null],
    ?#width: &[f64, null]
) -> ColumnSpec;

/// Build a `Combo` ColumnSpec. `choices` is the picklist; each entry's
/// `id` is the value written and `label` is what the user sees.
val combo_column: fn(
    #name: string,
    #choices: Array<{ id: string, label: string }>,
    ?#on_edit: [fn(#path: string, #value: string) -> Any, null],
    ?#display_name: [string, null],
    ?#source: &Source,
    ?#on_resize: &[fn(width: f64) -> Any, null],
    ?#width: &[f64, null]
) -> ColumnSpec;

/// Build a `Spin` ColumnSpec for bounded numeric input.
val spin_column: fn(
    #name: string,
    #min: f64,
    #max: f64,
    #increment: f64,
    ?#on_edit: [fn(#path: string, #value: f64) -> Any, null],
    ?#display_name: [string, null],
    ?#source: &Source,
    ?#on_resize: &[fn(width: f64) -> Any, null],
    ?#width: &[f64, null]
) -> ColumnSpec;

/// Build a read-only `Progress` ColumnSpec. Cell values are clamped to [0, 1].
val progress_column: fn(
    #name: string,
    ?#display_name: [string, null],
    ?#source: &Source,
    ?#on_resize: &[fn(width: f64) -> Any, null],
    ?#width: &[f64, null]
) -> ColumnSpec;

/// Build a `Button` ColumnSpec. Each cell renders as a button; clicking
/// fires `on_click` with the cell's path and current value.
val button_column: fn(
    #name: string,
    ?#on_click: [fn(#path: string, #value: Any) -> Any, null],
    ?#display_name: [string, null],
    ?#source: &Source,
    ?#on_resize: &[fn(width: f64) -> Any, null],
    ?#width: &[f64, null]
) -> ColumnSpec;

/// Build a `Sparkline` ColumnSpec. Each cell accumulates values from its
/// subscription for `history_seconds` and renders them as a rolling
/// chart. By default the y-axis is shared across every cell in the
/// column (auto-scaled to the union of all rows' values), so cells can
/// be compared visually. Pass `#min`/`#max` to fix the axis to a
/// caller-defined range instead.
val sparkline_column: fn(
    #name: string,
    #history_seconds: f64,
    ?#min: [f64, null],
    ?#max: [f64, null],
    ?#display_name: [string, null],
    ?#source: &Source,
    ?#on_resize: &[fn(width: f64) -> Any, null],
    ?#width: &[f64, null]
) -> ColumnSpec;