wijjit.elements.input.datagrid.DataGrid

class wijjit.elements.input.datagrid.DataGrid(id=None, classes=None, tab_index=None, data=None, columns=None, width=60, height=15, show_row_numbers=True, editable=True, border_style='single', show_scrollbar=True, bind=True)[source]

Spreadsheet-like data entry grid with entry line editing.

This element provides a classic TUI spreadsheet experience with a separate entry line at the top for editing cell contents. Navigation uses arrow keys, Tab, and Enter, with visual highlighting of the active cell.

Parameters:
  • id (str, optional) – Element identifier

  • classes (str or list of str, optional) – CSS class names for styling

  • data (list of list, list of dict, or pandas DataFrame, optional) – Grid data in one of these formats: - List of lists: [[“Alice”, “30”], [“Bob”, “25”]] - List of dicts: [{“name”: “Alice”, “age”: 30}, …] - pandas DataFrame: pd.DataFrame({“name”: […], “age”: […]}) Columns are auto-inferred from dicts/DataFrame if not provided.

  • columns (list of str or list of dict, optional) – Column definitions. Can be simple strings (headers) or dicts with: - “key”: Column identifier - “label”: Display header text - “width”: Column width in characters (default: 10) If not provided and data is dict/DataFrame, columns are auto-inferred.

  • width (int, optional) – Total display width (default: 60)

  • height (int, optional) – Total display height including entry line and borders (default: 15)

  • show_row_numbers (bool, optional) – Show row numbers (1, 2, 3…) on left side (default: True)

  • editable (bool, optional) – Whether cells can be edited (default: True)

  • border_style (BorderStyle or str, optional) – Border style for the grid (default: “single”)

  • tab_index (int | None)

  • show_scrollbar (bool)

  • bind (bool | str)

Variables:
  • data (list of list of str) – Grid data as 2D list (normalized from any input format)

  • columns (list of dict) – Column definitions with “key”, “label”, “width”

  • cursor_row (int) – Currently selected row (0-indexed, data rows only)

  • cursor_col (int) – Currently selected column (0-indexed)

  • editing (bool) – Whether entry line is active for editing

  • edit_value (str) – Current value in entry line

  • edit_cursor_pos (int) – Cursor position within entry line

  • scroll_manager (ScrollManager) – Manages vertical scrolling of data rows

  • scroll_x (int) – Horizontal scroll offset (columns)

Notes

Editing Workflow: 1. Navigate with arrow keys to highlight a cell 2. Start typing -> content appears in entry line at top 3. Press Enter/Tab/arrow -> commits value to cell and moves cursor 4. Press Escape -> cancels edit, restores original value 5. Press F2 -> edit existing cell content

Layout Structure: - Entry line: 2 rows (border + content) - Header row: 1 row - Data rows: height - 4 (entry line + header + borders)

Data Format Conversion: - Use get_data() to get list of lists - Use get_data_as_dicts() to get list of dicts - Use get_data_as_dataframe() to get pandas DataFrame (requires pandas)

Examples

Create with list of lists:

>>> grid = DataGrid(
...     columns=["Name", "Age", "City"],
...     data=[["Alice", "30", "NYC"], ["Bob", "25", "LA"]]
... )

Create with list of dicts (columns auto-inferred):

>>> grid = DataGrid(data=[
...     {"name": "Alice", "age": 30, "city": "NYC"},
...     {"name": "Bob", "age": 25, "city": "LA"},
... ])

Create from pandas DataFrame:

>>> import pandas as pd
>>> df = pd.DataFrame({"name": ["Alice", "Bob"], "age": [30, 25]})
>>> grid = DataGrid(data=df)

Export back to DataFrame:

>>> df_out = grid.get_data_as_dataframe()
__init__(id=None, classes=None, tab_index=None, data=None, columns=None, width=60, height=15, show_row_numbers=True, editable=True, border_style='single', show_scrollbar=True, bind=True)[source]

Initialize scrollable element.

Parameters:
Return type:

None

Methods

__init__([id, classes, tab_index, data, ...])

Initialize scrollable element.

add_class(class_name)

Add a CSS class to this element.

add_column(header[, values])

Add column at end.

add_row([values])

Add row at end.

apply_props(props)

Apply props from a VNode, skipping ephemeral props.

can_scroll(direction)

Check if the grid can scroll in the given direction.

delete_column(index)

Delete column at index.

delete_row(index)

Delete row at index.

get_cell(row, col)

Get value at cell.

get_data()

Get all data as 2D list.

get_data_as_dataframe()

Get all data as a pandas DataFrame.

get_data_as_dicts()

Get all data as list of dictionaries.

get_ephemeral_state()

Get ephemeral state for reconciliation.

get_hardware_cursor_position()

Absolute screen cell where the hardware terminal cursor should park.

get_height_for_width(width)

Return the height this element needs when laid out at width.

get_intrinsic_size()

Get the intrinsic (preferred) size of the element.

handle_key(key)

Handle keyboard input.

handle_mouse(event)

Handle mouse input.

has_class(class_name)

Check if element has a CSS class.

insert_row(index[, values])

Insert row at index.

on_blur()

Called when element loses focus.

on_focus()

Called when element gains focus.

on_hover_enter()

Called when mouse enters element.

on_hover_exit()

Called when mouse exits element.

on_mount()

Called when element is first added to the element tree.

on_unmount()

Called when element is removed from the element tree.

on_update(changed_props)

Called when element props are updated during reconciliation.

remove_class(class_name)

Remove a CSS class from this element.

render_signature()

Hashable/comparable capture of everything render_to() reads.

render_to(ctx)

Render the data grid to the paint context.

restore_ephemeral_state(state)

Restore ephemeral state after reconciliation.

set_bounds(bounds)

Set the element's screen bounds.

set_cell(row, col, value)

Set value at cell (triggers callback).

set_data(data[, update_columns])

Replace all data.

toggle_class(class_name)

Toggle a CSS class on this element.

Attributes

captures_tab

Whether this element wants the Tab key instead of focus movement.

cursor_state_key

Get the state key for cursor position.

data

The grid's rows, as a list of lists of strings.

parent_frame

Get the parent Frame if this element is inside a scrollable frame.

scroll_position

Get the current vertical scroll position.

scroll_state_key

Get the state key for vertical scroll position.

scroll_state_key_x

Get the state key for horizontal scroll position.

supports_dynamic_sizing

Whether this element supports dynamic sizing.

property data: list[list[str]]

The grid’s rows, as a list of lists of strings.

Returns:

The grid’s own working rows. Mutating them in place (as set_cell() does) is intentional and does not touch whatever the rows were assigned from.

Return type:

list of list of str

property cursor_state_key: str | None

Get the state key for cursor position.

Returns:

State key for cursor, or None if no id

Return type:

str or None

property scroll_position: int

Get the current vertical scroll position.

Returns:

Current scroll offset (0-based)

Return type:

int

can_scroll(direction)[source]

Check if the grid can scroll in the given direction.

Parameters:

direction (int) – Scroll direction: negative for up, positive for down

Returns:

True if scrolling in the given direction is possible

Return type:

bool

get_cell(row, col)[source]

Get value at cell.

Parameters:
  • row (int) – Row index (0-based)

  • col (int) – Column index (0-based)

Returns:

Cell value or empty string if out of bounds

Return type:

str

set_cell(row, col, value)[source]

Set value at cell (triggers callback).

Parameters:
  • row (int) – Row index (0-based)

  • col (int) – Column index (0-based)

  • value (str) – New cell value

Return type:

None

get_data()[source]

Get all data as 2D list.

Returns:

Copy of grid data

Return type:

list of list of str

get_data_as_dicts()[source]

Get all data as list of dictionaries.

Each row becomes a dict with column keys as keys. This is useful for converting grid data back to a format that can be used with pandas or other data processing tools.

Returns:

Data as list of dictionaries

Return type:

list of dict

Examples

>>> grid = DataGrid(
...     data=[["Alice", "30"], ["Bob", "25"]],
...     columns=[{"key": "name", "label": "Name"}, {"key": "age", "label": "Age"}]
... )
>>> grid.get_data_as_dicts()
[{'name': 'Alice', 'age': '30'}, {'name': 'Bob', 'age': '25'}]
get_data_as_dataframe()[source]

Get all data as a pandas DataFrame.

Requires pandas to be installed. If pandas is not available, raises ImportError with a helpful message.

Returns:

Data as DataFrame with column keys as column names

Return type:

pandas.DataFrame

Raises:

ImportError – If pandas is not installed

Examples

>>> import pandas as pd
>>> grid = DataGrid(
...     data=[["Alice", "30"], ["Bob", "25"]],
...     columns=[{"key": "name", "label": "Name"}, {"key": "age", "label": "Age"}]
... )
>>> df = grid.get_data_as_dataframe()
>>> isinstance(df, pd.DataFrame)
True
set_data(data, update_columns=False)[source]

Replace all data.

Accepts data in multiple formats (list of lists, list of dicts, or pandas DataFrame). Data is normalized to list of lists internally.

Parameters:
  • data (list of list, list of dict, or pandas DataFrame) – New grid data in any supported format

  • update_columns (bool, optional) – If True and data is dict/DataFrame format, also update columns from the new data. Default is False (preserve existing columns).

Return type:

None

add_row(values=None)[source]

Add row at end.

Parameters:

values (list of str, optional) – Row values (defaults to empty cells)

Return type:

None

insert_row(index, values=None)[source]

Insert row at index.

Parameters:
  • index (int) – Row index to insert at

  • values (list of str, optional) – Row values (defaults to empty cells)

Return type:

None

delete_row(index)[source]

Delete row at index.

Parameters:

index (int) – Row index to delete

Return type:

None

add_column(header, values=None)[source]

Add column at end.

Parameters:
  • header (str) – Column header label

  • values (list of str, optional) – Column values for each row (defaults to empty)

Return type:

None

delete_column(index)[source]

Delete column at index.

Parameters:

index (int) – Column index to delete

Return type:

None

handle_key(key)[source]

Handle keyboard input.

Parameters:

key (Key) – Key press to handle

Returns:

True if key was handled

Return type:

bool

async handle_mouse(event)[source]

Handle mouse input.

Parameters:

event (MouseEvent) – Mouse event to handle

Returns:

True if event was handled

Return type:

bool

get_intrinsic_size()[source]

Get the intrinsic (preferred) size of the element.

Returns:

(width, height) in characters/lines

Return type:

tuple of (int, int)

render_to(ctx)[source]

Render the data grid to the paint context.

Parameters:

ctx (PaintContext) – Paint context with buffer, style resolver, and bounds

Return type:

None

get_ephemeral_state()[source]

Get ephemeral state for reconciliation.

Returns:

State that should survive re-renders

Return type:

dict

restore_ephemeral_state(state)[source]

Restore ephemeral state after reconciliation.

Parameters:

state (dict) – State from get_ephemeral_state()

Return type:

None