wijjit.elements.input.text.TextInput

class wijjit.elements.input.text.TextInput(id=None, classes=None, tab_index=None, placeholder='', value='', width=20, max_length=None, style=InputStyle.BRACKETS, completer=None, autocomplete=None, action=None, bind=True, password=False, mask_char='*')[source]

Text input field element.

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

  • placeholder (str, optional) – Placeholder text when empty

  • value (str, optional) – Initial value

  • width (int, optional) – Display width for content (default: 20), excludes borders

  • max_length (int, optional) – Maximum input length

  • style (InputStyle, optional) – Visual style for input rendering (default: BRACKETS)

  • completer (Completer, optional) – Autocomplete completer for suggestions

  • password (bool, optional) – If True, render each character as mask_char instead of the literal text (default: False). The real text is still stored in value and returned by state bindings and callbacks; only the display is masked.

  • mask_char (str, optional) – Character used to mask each character when password is True (default: "*").

  • classes (str | list[str] | set[str] | None)

  • tab_index (int | None)

  • autocomplete (list[str] | str | bool | Completer | None)

  • action (str | None)

  • bind (bool | str)

Variables:
  • value (str) – Current input value

  • placeholder (str) – Placeholder text

  • cursor_pos (int) – Cursor position in the text

  • width (int) – Display width for content (excludes borders)

  • max_length (int or None) – Maximum input length

  • style (InputStyle) – Visual style for rendering

Examples

Create a basic text input:

>>> inp = TextInput(placeholder="Enter name...")

Create input with different styles:

>>> inp = TextInput(placeholder="Email", style=InputStyle.BOX, width=30)
>>> inp = TextInput(value="Default", style=InputStyle.UNDERLINE)
__init__(id=None, classes=None, tab_index=None, placeholder='', value='', width=20, max_length=None, style=InputStyle.BRACKETS, completer=None, autocomplete=None, action=None, bind=True, password=False, mask_char='*')[source]
Parameters:
Return type:

None

Methods

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

add_class(class_name)

Add a CSS class to this element.

apply_props(props)

Apply props from a VNode, skipping ephemeral props.

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 size of the text input.

handle_key(key)

Handle keyboard input.

handle_mouse(event)

Handle mouse input.

has_class(class_name)

Check if element has a CSS class.

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()

Paint memo for the skip-unchanged fast path.

render_to(ctx)

Render text input using cell-based rendering (NEW API).

restore_ephemeral_state(state)

Restore ephemeral state, clamping the cursor into range.

set_bounds(bounds)

Stretch the field to the assigned width (e.g. width="fill").

toggle_class(class_name)

Toggle a CSS class on this element.

Attributes

autocomplete_is_open

Check if the autocomplete popup is currently open.

captures_tab

Whether Tab should reach this input instead of moving focus.

completer

parent_frame

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

supports_dynamic_sizing

Whether this element supports dynamic sizing.

value

cursor_pos

bounds

property captures_tab: bool

Whether Tab should reach this input instead of moving focus.

Returns:

True only while an autocomplete popup is open and configured to accept the highlighted suggestion on Tab.

Return type:

bool

Notes

Claimed conditionally rather than always: a text input in a form must keep Tab-to-next-field. The moment the popup closes, Tab goes back to moving focus - which is also what makes the completer’s select_on_tab reachable at all, since the app’s focus handler would otherwise cancel Tab before any element saw it.

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.

On click events, positions the cursor at the clicked character position. Focus management is handled separately by the MouseEventRouter before this method is called (see mouse_router.py:_handle_focus_on_click).

Parameters:

event (MouseEvent) – Mouse event to handle

Returns:

True if event was handled (click/double-click consumed)

Return type:

bool

Notes

The MouseEventRouter sets focus on focusable elements before calling handle_mouse(). This method handles cursor positioning within the text. Returning True indicates the event was consumed, preventing propagation to parent containers.

render_signature()[source]

Paint memo for the skip-unchanged fast path.

Captures value, placeholder, cursor position, masking, width, visual style, and style-affecting state. The scroll offset and caret rendering are derived deterministically from these, so they need not be listed separately. See Element.render_signature().

Return type:

Any

render_to(ctx)[source]

Render text input using cell-based rendering (NEW API).

Parameters:

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

Return type:

None

Notes

This is the reference implementation for text input cell-based rendering. It demonstrates how to: 1. Handle text that exceeds display width (scrolling) 2. Render cursor position with proper styling 3. Show placeholder text when empty 4. Apply different border styles 5. Resolve styles based on focus state

The input renders as a single line with decorative borders and cursor indication when focused.

get_intrinsic_size()[source]

Get the intrinsic size of the text input.

Returns the total width including border characters based on style.

Returns:

(width, height) tuple where width includes borders

Return type:

tuple[int, int]

set_bounds(bounds)[source]

Stretch the field to the assigned width (e.g. width="fill").

The field is painted from self.width (content columns, excluding the bracket/box border glyphs), which under a "fill" spec holds the tag’s numeric default rather than the width the layout engine assigned. Fixed-width inputs already budget the border into the layout node, so bounds match the props and this sync is a no-op.

Parameters:

bounds (Bounds) – New bounds for the element.

Return type:

None

get_ephemeral_state()[source]

Get ephemeral state for reconciliation.

Returns:

Cursor position that should survive re-renders

Return type:

dict

restore_ephemeral_state(state)[source]

Restore ephemeral state, clamping the cursor into range.

Parameters:

state (dict) – State from get_ephemeral_state().

Return type:

None

Notes

Called by the reconciler after prop changes are applied, so self.value already holds the new value. A programmatic value change (e.g. a shrinking state binding) can leave the preserved cursor position past the end of the text; clamping here prevents out-of-range insert/delete.