Skip to content

xnano.grids

xnano.grids

xnano.grids


Build declarative layouts from named Field values. Grids can nest, share state, react to hooks, and use the same layout on terminal and web.

Classes:

  • GridSettings

    Rendering, layout, and frame settings for a BaseGrid subclass.

  • BaseGrid

    Declarative layout container for a terminal-based UI.

GridSettings

Bases: TypedDict

Rendering, layout, and frame settings for a BaseGrid subclass.

Attributes:

foreground instance-attribute

foreground: NotRequired[ColorLike]

The foreground color of the grid's content.

background instance-attribute

background: NotRequired[ColorLike]

The background color of the grid's frame area.

direction instance-attribute

direction: NotRequired[Direction]

The direction in which content within this grid should be laid out.

gap instance-attribute

The gap between fields in this grid.

border instance-attribute

The border style to be applied onto the outer frame of the grid.

border_sides instance-attribute

border_sides: NotRequired[list[Side]]

The sides of the border to be applied onto the outer frame of the grid.

border_color instance-attribute

border_color: NotRequired[ColorLike]

The color of the border.

title instance-attribute

title: NotRequired[str]

The title to be displayed around the outer frame of the grid.

title_position instance-attribute

The position of the title within the outer frame of the grid.

padding instance-attribute

The padding to be applied around the content area of the grid.

bold instance-attribute

Whether the grid should be rendered in bold.

dim instance-attribute

Whether the grid should be rendered in dim.

italic instance-attribute

italic: NotRequired[bool]

Whether the grid should be rendered in italic.

underline instance-attribute

underline: NotRequired[bool]

Whether the grid should be rendered in underline.

slow_blink: NotRequired[bool]

Whether the grid should be rendered in slow blink.

rapid_blink: NotRequired[bool]

Whether the grid should be rendered in rapid blink.

reversed instance-attribute

reversed: NotRequired[bool]

Whether the grid should be rendered in reversed color.

strict instance-attribute

strict: NotRequired[bool]

When True (the default), all field values are validated against their type annotations during grid construction.

BaseGrid

BaseGrid()

Bases: AbstractInterface

Declarative layout container for a terminal-based UI.

BaseGrid-scoped settings may be declared on the class header (class Dashboard(BaseGrid, direction="horizontal", gap=1): ...), in a class-level grid_settings dict, or both — values in grid_settings override matching header kwargs.

Attributes:

  • grid_settings (GridSettings) –

    Class-level layout and frame configuration.

  • visible (bool) –

    Whether the grid is rendered.

  • z (int) –

    Layering order for overlapping grids.

  • columns (int) –

    Columns available during the current frame.

  • rows (int) –

    Rows available during the current frame.

Examples:

Layout fields render content; state=True fields hold app data. Nested BaseGrid subclasses compose larger layouts:

from xnano import BaseGrid, Field, Terminal

class Sidebar(BaseGrid, direction="vertical"):
    nav: str = Field(default="Home", border="rounded", height="1fr")

class App(BaseGrid, direction="horizontal", gap=1):
    sidebar: Sidebar = Field(default_factory=Sidebar, width="25%")
    content: str = Field(default="Main area", width="1fr")

    selected: int = Field(default=0, state=True)

Terminal().run(App())

Event hooks register handlers on the grid class. Use @on_click to scope mouse handlers to a layout field's region:

from xnano import BaseGrid, Context, Field, Terminal, hooks

class Counter(BaseGrid, direction="vertical", gap=1):
    label: str = Field(default="Count: 0", height=1)
    body: str = Field(default="Click me", height="1fr")

    count: int = Field(default=0, state=True)

    @hooks.on_keyboard("up")
    def increment(self) -> None:
        self.count += 1
        self.label = f"Count: {self.count}"

    @hooks.on_keyboard("down")
    def decrement(self) -> None:
        self.count -= 1
        self.label = f"Count: {self.count}"

    @hooks.on_click("body")
    def on_body(self, ctx: Context) -> None:
        self.body = "Clicked!"

    @hooks.on_tick(1000)
    def reset_body(self) -> None:
        self.body = "Click me"

Terminal().run(Counter())

Methods:

Source code in xnano/grids.py
def __init__(self) -> None:
    self._grid_init_field_states()
    self.__post_init__()

grid_settings class-attribute

grid_settings: GridSettings = {}

Class-level grid configuration, like Pydantic's model_config.

__xnano_grid__ class-attribute

__xnano_grid__: bool = True

Marks this class as a grid, for cheap identity checks.

Faster and clearer than duck-typing _grid_fields, and usable from layers that must not import BaseGrid — see is_grid.

visible class-attribute instance-attribute

visible: bool = True

Whether this grid is rendered in the live session.

z class-attribute instance-attribute

z: int = 0

Z-index used when layering overlapping grids.

columns class-attribute instance-attribute

columns: int = 0

Terminal columns available to this grid — set by the session each frame.

rows class-attribute instance-attribute

rows: int = 0

Terminal rows available to this grid — set by the session each frame.

grid_focused property

grid_focused: bool

Whether any of this grid's fields currently holds field focus.

Live alongside per-component focused: derived from the same per-frame focus flags, so self.grid_focused in a hook and @on_field("focused") both read the current state.

grid_state property

grid_state: Any

Return the active terminal's shared state, or None.

focused property

focused: bool

Deprecated alias for grid_focused.

state property

state: Any

Deprecated alias for grid_state.

__post_init__

__post_init__() -> None

Called at the end of the generated __init__. Override to run post-construction logic.

Source code in xnano/grids.py
def __post_init__(self) -> None:
    """Called at the end of the generated ``__init__``. Override to run post-construction logic."""

grid_post_init

grid_post_init() -> None

Called exactly once, when this grid is first attached to a live terminal — after its own hooks are bound, before its first paint.

Unlike __post_init__ (construction time, no terminal attached yet), ctx/ctx.state are live here. Override with either signature — the extra parameter is optional, matching every other @on_* hook, dispatched by arity at runtime (see _call_hook):

def grid_post_init(self) -> None: ...
def grid_post_init(self, ctx: Context[MyState]) -> None: ...

A static type checker sees the one-parameter form as an invalid override (this base declares zero); that's a known false positive for this flexible-arity hook pattern — add # ty: ignore[invalid-method-override] on the override line.

Source code in xnano/grids.py
def grid_post_init(self) -> None:
    """Called exactly once, when this grid is first attached to a live
    terminal — after its own hooks are bound, before its first paint.

    Unlike ``__post_init__`` (construction time, no terminal attached
    yet), ``ctx``/``ctx.state`` are live here. Override with either
    signature — the extra parameter is optional, matching every other
    ``@on_*`` hook, dispatched by arity at runtime (see ``_call_hook``):

        def grid_post_init(self) -> None: ...
        def grid_post_init(self, ctx: Context[MyState]) -> None: ...

    A static type checker sees the one-parameter form as an invalid
    override (this base declares zero); that's a known false positive
    for this flexible-arity hook pattern — add
    ``# ty: ignore[invalid-method-override]`` on the override line.
    """

grid_render

grid_render() -> None

Called each frame before layout.

Override to refresh field values every frame. Initial values can be set with Field(default=...), default_factory, or __post_init__.

Override with either signature — the extra Context parameter is optional, dispatched by arity like grid_post_init:

def grid_render(self) -> None: ...
def grid_render(self, ctx: Context[MyState]) -> None: ...

A static type checker sees the one-parameter form as an invalid override; add # ty: ignore[invalid-method-override] on the override line.

Source code in xnano/grids.py
def grid_render(self) -> None:
    """Called each frame before layout.

    Override to refresh field values every frame. Initial values can be set
    with ``Field(default=...)``, ``default_factory``, or ``__post_init__``.

    Override with either signature — the extra ``Context`` parameter is
    optional, dispatched by arity like ``grid_post_init``:

        def grid_render(self) -> None: ...
        def grid_render(self, ctx: Context[MyState]) -> None: ...

    A static type checker sees the one-parameter form as an invalid
    override; add ``# ty: ignore[invalid-method-override]`` on the
    override line.
    """

grid_render_extra_small

grid_render_extra_small() -> None

Refine layout when the viewport is extra small (< 40 cols).

Optional responsive counterpart to :meth:grid_render. Runs when the window enters this size tier — on the first render and on later resizes that cross into it — not every frame, so a per-frame @on_tick mutation is not overwritten by a size hook resetting the same field. Keep shared per-frame logic in grid_render and size-specific setup here. Overriding any grid_render_* variant opts the class into breakpoint dispatch; a class that overrides none pays no per-frame cost.

Source code in xnano/grids.py
@responsive_noop
def grid_render_extra_small(self) -> None:
    """Refine layout when the viewport is extra small (< 40 cols).

    Optional responsive counterpart to :meth:`grid_render`. Runs when
    the window enters this size tier — on the first render and on
    later resizes that cross into it — not every frame, so a
    per-frame ``@on_tick`` mutation is not overwritten by a size hook
    resetting the same field. Keep shared per-frame logic in
    ``grid_render`` and size-specific setup here. Overriding any
    ``grid_render_*`` variant opts the class into breakpoint dispatch;
    a class that overrides none pays no per-frame cost.
    """

grid_render_small

grid_render_small() -> None

Refine layout when the viewport is small (40–79 cols).

See :meth:grid_render_extra_small.

Source code in xnano/grids.py
@responsive_noop
def grid_render_small(self) -> None:
    """Refine layout when the viewport is small (40–79 cols).

    See :meth:`grid_render_extra_small`.
    """

grid_render_medium

grid_render_medium() -> None

Refine layout when the viewport is medium (80–119 cols).

See :meth:grid_render_extra_small.

Source code in xnano/grids.py
@responsive_noop
def grid_render_medium(self) -> None:
    """Refine layout when the viewport is medium (80–119 cols).

    See :meth:`grid_render_extra_small`.
    """

grid_render_large

grid_render_large() -> None

Refine layout when the viewport is large (120–159 cols).

See :meth:grid_render_extra_small.

Source code in xnano/grids.py
@responsive_noop
def grid_render_large(self) -> None:
    """Refine layout when the viewport is large (120–159 cols).

    See :meth:`grid_render_extra_small`.
    """

grid_render_extra_large

grid_render_extra_large() -> None

Refine layout when the viewport is extra large (>= 160 cols).

See :meth:grid_render_extra_small.

Source code in xnano/grids.py
@responsive_noop
def grid_render_extra_large(self) -> None:
    """Refine layout when the viewport is extra large (>= 160 cols).

    See :meth:`grid_render_extra_small`.
    """

grid_play_effect

grid_play_effect(
    effect: AbstractEffect,
    *,
    fields: list[str] | None = None
) -> bool
grid_play_effect(
    effect: KnownEffectKind,
    *,
    duration_ms: int = 300,
    color: ColorLike | None = None,
    background: ColorLike | None = None,
    direction: EffectMotion | None = None,
    gradient_length: int | None = None,
    randomness: int | None = None,
    interpolation: EffectInterpolation | None = None,
    effects: Sequence[AbstractEffect] | None = None,
    child: AbstractEffect | None = None,
    times: int | None = None,
    fields: list[str] | None = None,
    key: str | None = None
) -> bool
grid_play_effect(
    effect: KnownEffectKind | AbstractEffect,
    *,
    duration_ms: int = 300,
    color: ColorLike | None = None,
    background: ColorLike | None = None,
    direction: EffectMotion | None = None,
    gradient_length: int | None = None,
    randomness: int | None = None,
    interpolation: EffectInterpolation | None = None,
    effects: Sequence[AbstractEffect] | None = None,
    child: AbstractEffect | None = None,
    times: int | None = None,
    fields: list[str] | None = None,
    key: str | None = None
) -> bool

Run a visual effect on one or more layout field areas.

Each layout field is tagged with its name as an effect key during rendering, so effects can target field content rects on the frame after grid_render.

Pass a custom AbstractEffect subclass or provide a known effect kind with typed keyword arguments.

Parameters:

  • effect (KnownEffectKind | AbstractEffect) –

    A built effect instance or a known effect kind string.

  • duration_ms (int, default: 300 ) –

    Duration of the effect in milliseconds.

  • color (ColorLike | None, default: None ) –

    Foreground or accent color for color-driven effects.

  • background (ColorLike | None, default: None ) –

    Background color for two-color effects.

  • direction (EffectMotion | None, default: None ) –

    Motion direction for slide and sweep effects.

  • gradient_length (int | None, default: None ) –

    Gradient length for slide and sweep effects.

  • randomness (int | None, default: None ) –

    Randomness for slide and sweep effects.

  • interpolation (EffectInterpolation | None, default: None ) –

    Interpolation curve for the effect.

  • effects (Sequence[AbstractEffect] | None, default: None ) –

    Child effects for sequence and parallel composition.

  • child (AbstractEffect | None, default: None ) –

    Child effect for repeat and delay composition.

  • times (int | None, default: None ) –

    Repeat count for repeat effects.

  • fields (list[str] | None, default: None ) –

    Layout field names to target. When omitted or empty, no effect is started.

  • key (str | None, default: None ) –

    Identity used to de-duplicate this effect per target field — see AbstractEffect.key. Only meaningful when effect is a known-kind string; ignored when effect is already a built AbstractEffect instance (set key on the instance itself in that case).

Returns:

  • bool

    True when at least one field area was found and an effect

  • bool

    started.

Source code in xnano/grids.py
@warn_renamed_attribute(
    "BaseGrid.grid_play_effect", "BaseGrid.grid_effect"
)
def grid_play_effect(
    self,
    effect: KnownEffectKind | AbstractEffect,
    *,
    duration_ms: int = 300,
    color: ColorLike | None = None,
    background: ColorLike | None = None,
    direction: EffectMotion | None = None,
    gradient_length: int | None = None,
    randomness: int | None = None,
    interpolation: EffectInterpolation | None = None,
    effects: Sequence[AbstractEffect] | None = None,
    child: AbstractEffect | None = None,
    times: int | None = None,
    fields: list[str] | None = None,
    key: str | None = None,
) -> bool:
    """Run a visual effect on one or more layout field areas.

    Each layout field is tagged with its name as an effect key during
    rendering, so effects can target field content rects on the frame
    after ``grid_render``.

    Pass a custom ``AbstractEffect`` subclass or
    provide a known effect kind with typed keyword arguments.

    Args:
        effect: A built effect instance or a known effect kind string.
        duration_ms: Duration of the effect in milliseconds.
        color: Foreground or accent color for color-driven effects.
        background: Background color for two-color effects.
        direction: Motion direction for slide and sweep effects.
        gradient_length: Gradient length for slide and sweep effects.
        randomness: Randomness for slide and sweep effects.
        interpolation: Interpolation curve for the effect.
        effects: Child effects for sequence and parallel composition.
        child: Child effect for repeat and delay composition.
        times: Repeat count for repeat effects.
        fields: Layout field names to target. When omitted or empty, no
            effect is started.
        key: Identity used to de-duplicate this effect per target
            field — see ``AbstractEffect.key``. Only meaningful when
            ``effect`` is a known-kind string; ignored when ``effect``
            is already a built ``AbstractEffect`` instance (set
            ``key`` on the instance itself in that case).

    Returns:
        ``True`` when at least one field area was found and an effect
        started.
    """
    return bool(
        self.grid_effect(
            effect,
            duration_ms=duration_ms,
            color=color,
            background=background,
            direction=direction,
            gradient_length=gradient_length,
            randomness=randomness,
            interpolation=interpolation,
            effects=effects,
            child=child,
            times=times,
            fields=fields,
            key=key,
        )
    )

grid_effect

grid_effect(
    effect: KnownEffectKind | AbstractEffect,
    *,
    duration_ms: int | None = None,
    color: ColorLike | None = None,
    background: ColorLike | None = None,
    direction: EffectMotion | None = None,
    gradient_length: int | None = None,
    randomness: int | None = None,
    interpolation: EffectInterpolation | None = None,
    effects: Sequence[AbstractEffect] | None = None,
    child: AbstractEffect | None = None,
    times: int | None = None,
    fields: list[str] | None = None,
    key: str | None = None
) -> "EffectHandle"

Run a visual effect on one or more layout field areas.

Returns an EffectHandle: truthy when at least one field was targeted, with .active and .cancel(), and usable as a context manager that cancels the effect on exit.

Starting an effect never blocks. duration_ms is the animation length handed to the renderer, not a sleep — the effect advances one frame at a time, so hooks keep running while it plays. Omit it inside a with block and the effect repeats until the block exits.

Parameters:

  • effect (KnownEffectKind | AbstractEffect) –

    A built effect instance or a known effect kind string.

  • duration_ms (int | None, default: None ) –

    Animation length in milliseconds. Defaults to 300; omitted inside a with block the effect repeats until exit.

  • color (ColorLike | None, default: None ) –

    Foreground or accent color for color-driven effects.

  • background (ColorLike | None, default: None ) –

    Background color for two-color effects.

  • direction (EffectMotion | None, default: None ) –

    Motion direction for slide and sweep effects.

  • gradient_length (int | None, default: None ) –

    Gradient length for slide and sweep effects.

  • randomness (int | None, default: None ) –

    Randomness for slide and sweep effects.

  • interpolation (EffectInterpolation | None, default: None ) –

    Interpolation curve for the effect.

  • effects (Sequence[AbstractEffect] | None, default: None ) –

    Child effects for sequence and parallel composition.

  • child (AbstractEffect | None, default: None ) –

    Child effect for repeat and delay composition.

  • times (int | None, default: None ) –

    Repeat count for repeat effects.

  • fields (list[str] | None, default: None ) –

    Layout field names to target. When omitted or empty, no effect is started.

  • key (str | None, default: None ) –

    Identity used to de-duplicate this effect per target field — see AbstractEffect.key. Calling with the same key every tick replaces the running effect rather than stacking new ones.

Returns:

  • 'EffectHandle'

    A handle for the started effect.

Examples:

self.grid_effect("fade", fields=["body"])

with self.grid_effect("pulse", fields=["body"]):
    do_slow_work()
Source code in xnano/grids.py
def grid_effect(
    self,
    effect: KnownEffectKind | AbstractEffect,
    *,
    duration_ms: int | None = None,
    color: ColorLike | None = None,
    background: ColorLike | None = None,
    direction: EffectMotion | None = None,
    gradient_length: int | None = None,
    randomness: int | None = None,
    interpolation: EffectInterpolation | None = None,
    effects: Sequence[AbstractEffect] | None = None,
    child: AbstractEffect | None = None,
    times: int | None = None,
    fields: list[str] | None = None,
    key: str | None = None,
) -> "EffectHandle":
    """Run a visual effect on one or more layout field areas.

    Returns an ``EffectHandle``: truthy when at least one field was
    targeted, with ``.active`` and ``.cancel()``, and usable as a
    context manager that cancels the effect on exit.

    Starting an effect never blocks. ``duration_ms`` is the animation
    length handed to the renderer, not a sleep — the effect advances
    one frame at a time, so hooks keep running while it plays. Omit it
    inside a ``with`` block and the effect repeats until the block
    exits.

    Args:
        effect: A built effect instance or a known effect kind string.
        duration_ms: Animation length in milliseconds. Defaults to
            300; omitted inside a ``with`` block the effect repeats
            until exit.
        color: Foreground or accent color for color-driven effects.
        background: Background color for two-color effects.
        direction: Motion direction for slide and sweep effects.
        gradient_length: Gradient length for slide and sweep effects.
        randomness: Randomness for slide and sweep effects.
        interpolation: Interpolation curve for the effect.
        effects: Child effects for sequence and parallel composition.
        child: Child effect for repeat and delay composition.
        times: Repeat count for repeat effects.
        fields: Layout field names to target. When omitted or empty,
            no effect is started.
        key: Identity used to de-duplicate this effect per target
            field — see ``AbstractEffect.key``. Calling with the same
            ``key`` every tick replaces the running effect rather than
            stacking new ones.

    Returns:
        A handle for the started effect.

    Examples:
        ```python
        self.grid_effect("fade", fields=["body"])

        with self.grid_effect("pulse", fields=["body"]):
            do_slow_work()
        ```
    """
    from xnano.core.runtime import get_active_runtime
    from xnano.effects import EffectHandle, resolve_effect

    runtime = get_active_runtime()
    if runtime is None:
        return EffectHandle()
    resolved_effect = resolve_effect(
        effect,
        duration_ms=300 if duration_ms is None else duration_ms,
        color=color,
        background=background,
        direction=direction,
        gradient_length=gradient_length,
        randomness=randomness,
        interpolation=interpolation,
        effects=effects,
        child=child,
        times=times,
        key=key,
    )
    keys = runtime.play_effect(resolved_effect, fields=fields)
    return EffectHandle(
        keys=tuple(keys),
        runtime=runtime,
        effect=resolved_effect,
        fields=tuple(fields or ()),
        loop_in_context=duration_ms is None,
    )

grid_field_position

grid_field_position(name: str) -> tuple[int, int]

Return the parent-relative slide offset for a layout field.

Source code in xnano/grids.py
def grid_field_position(self, name: str) -> tuple[int, int]:
    """Return the parent-relative slide offset for a layout field."""
    return self._grid_field_position(name)

grid_set_field

grid_set_field(
    name: str,
    value: Any = UNSET,
    *,
    position: tuple[int, int] | None = None,
    strict: bool = UNSET,
    slide: Sequence[Axis] | None = UNSET,
    visible: bool | None = UNSET,
    wireframe: bool | None = UNSET,
    foreground: ColorLike | None = UNSET,
    background: ColorLike | None = UNSET,
    fill: bool | None = UNSET,
    width: SizingLike | None = UNSET,
    height: SizingLike | None = UNSET,
    gap: int | None = UNSET,
    direction: Direction | None = UNSET,
    horizontal_align: Alignment | None = UNSET,
    vertical_align: VerticalAlignment | None = UNSET,
    border: Border | None = UNSET,
    border_sides: Sequence[Side] | None = UNSET,
    border_color: ColorLike | None = UNSET,
    title: str | None = UNSET,
    title_position: FrameTitlePosition | None = UNSET,
    padding: PaddingLike | None = UNSET,
    margin: PaddingLike | None = UNSET,
    z: int | None = UNSET,
    modifiers: Sequence[CharacterModifier] | None = UNSET,
    class_name: ClassNameLike | None = UNSET,
    bold: bool = UNSET,
    dim: bool = UNSET,
    italic: bool = UNSET,
    underline: bool = UNSET,
    slow_blink: bool = UNSET,
    rapid_blink: bool = UNSET,
    reversed: bool = UNSET,
    color: ColorLike | None = UNSET,
    align: Alignment | None = UNSET
) -> None

Set a layout field's runtime value and/or per-instance field metadata.

Cannot be used on state fields. default, default_factory, init, and state cannot be changed at runtime.

For frequent, value-free style ticks (e.g. from on_tick or an effect callback), prefer grid_update_field — it skips the value/position handling this method carries for the general case.

color is a deprecated alias for foreground.

Source code in xnano/grids.py
def grid_set_field(
    self,
    name: str,
    value: Any = UNSET,
    *,
    position: tuple[int, int] | None = None,
    strict: bool = UNSET,
    slide: Sequence[Axis] | None = UNSET,
    visible: bool | None = UNSET,
    wireframe: bool | None = UNSET,
    foreground: ColorLike | None = UNSET,
    background: ColorLike | None = UNSET,
    fill: bool | None = UNSET,
    width: SizingLike | None = UNSET,
    height: SizingLike | None = UNSET,
    gap: int | None = UNSET,
    direction: Direction | None = UNSET,
    horizontal_align: Alignment | None = UNSET,
    vertical_align: VerticalAlignment | None = UNSET,
    border: Border | None = UNSET,
    border_sides: Sequence[Side] | None = UNSET,
    border_color: ColorLike | None = UNSET,
    title: str | None = UNSET,
    title_position: FrameTitlePosition | None = UNSET,
    padding: PaddingLike | None = UNSET,
    margin: PaddingLike | None = UNSET,
    z: int | None = UNSET,
    modifiers: Sequence[CharacterModifier] | None = UNSET,
    class_name: ClassNameLike | None = UNSET,
    bold: bool = UNSET,
    dim: bool = UNSET,
    italic: bool = UNSET,
    underline: bool = UNSET,
    slow_blink: bool = UNSET,
    rapid_blink: bool = UNSET,
    reversed: bool = UNSET,
    color: ColorLike | None = UNSET,
    align: Alignment | None = UNSET,
) -> None:
    """Set a layout field's runtime value and/or per-instance field metadata.

    Cannot be used on state fields. ``default``, ``default_factory``,
    ``init``, and ``state`` cannot be changed at runtime.

    For frequent, value-free style ticks (e.g. from ``on_tick`` or an
    effect callback), prefer ``grid_update_field`` — it skips the
    value/position handling this method carries for the general case.

    ``color`` is a deprecated alias for ``foreground``.
    """
    foreground = resolve_color_alias(
        foreground, color, unset=UNSET, stacklevel=3
    )
    horizontal_align = resolve_renamed_alias(
        horizontal_align,
        align,
        old="align",
        new="horizontal_align",
        unset=UNSET,
        stacklevel=3,
    )
    field_config: dict[str, Any] = {
        key: option
        for key, option in {
            "strict": strict,
            "slide": slide,
            "visible": visible,
            "wireframe": wireframe,
            "foreground": foreground,
            "background": background,
            "fill": fill,
            "width": width,
            "height": height,
            "gap": gap,
            "direction": direction,
            "horizontal_align": horizontal_align,
            "vertical_align": vertical_align,
            "border": border,
            "border_sides": border_sides,
            "border_color": border_color,
            "title": title,
            "title_position": title_position,
            "padding": padding,
            "margin": margin,
            "z": z,
            "modifiers": modifiers,
            "class_name": class_name,
            "bold": bold,
            "dim": dim,
            "italic": italic,
            "underline": underline,
            "slow_blink": slow_blink,
            "rapid_blink": rapid_blink,
            "reversed": reversed,
        }.items()
        if option is not UNSET
    }

    self._grid_apply_field_config(
        name, field_config, caller="grid_set_field"
    )

    if position is not None:
        slot = getattr(self, "_grid_last_slot_areas", {}).get(name)
        parent = getattr(self, "_grid_last_parent_area", None)
        if slot is not None and parent is not None:
            self._grid_set_field_position(
                name,
                position,
                parent_area=parent,
                slot_area=slot,
            )
        else:
            self.__dict__.setdefault("_grid_field_positions", {})[name] = (
                position
            )

    if value is not UNSET:
        field = self._grid_field_info(name)
        if self._grid_strict:
            value = self._grid_validate_field(name, value, field=field)
        object.__setattr__(self, name, value)

grid_update_field

grid_update_field(
    name: str,
    *,
    slide: Sequence[Axis] | None = UNSET,
    visible: bool | None = UNSET,
    wireframe: bool | None = UNSET,
    foreground: ColorLike | None = UNSET,
    background: ColorLike | None = UNSET,
    fill: bool | None = UNSET,
    width: SizingLike | None = UNSET,
    height: SizingLike | None = UNSET,
    gap: int | None = UNSET,
    direction: Direction | None = UNSET,
    horizontal_align: Alignment | None = UNSET,
    vertical_align: VerticalAlignment | None = UNSET,
    border: Border | None = UNSET,
    border_sides: Sequence[Side] | None = UNSET,
    border_color: ColorLike | None = UNSET,
    title: str | None = UNSET,
    title_position: FrameTitlePosition | None = UNSET,
    padding: PaddingLike | None = UNSET,
    margin: PaddingLike | None = UNSET,
    z: int | None = UNSET,
    modifiers: Sequence[CharacterModifier] | None = UNSET,
    class_name: ClassNameLike | None = UNSET,
    bold: bool = UNSET,
    dim: bool = UNSET,
    italic: bool = UNSET,
    underline: bool = UNSET,
    slow_blink: bool = UNSET,
    rapid_blink: bool = UNSET,
    reversed: bool = UNSET,
    color: ColorLike | None = UNSET,
    align: Alignment | None = UNSET
) -> None

Update a layout field's style/layout attributes, live, in-place.

A narrower sibling of grid_set_field for frequent, value-free attribute changes — pulsing a border color from on_tick, toggling a modifier from an effect callback. It has no value= or position= parameters at all, so a per-frame style tick never pays for that method's value-validation branch. Optional style patches never raise: a missing or state-only name is a no-op (no try/except needed), though unknown keyword arguments still raise as a programming error.

color is a deprecated alias for foreground.

Source code in xnano/grids.py
def grid_update_field(
    self,
    name: str,
    *,
    slide: Sequence[Axis] | None = UNSET,
    visible: bool | None = UNSET,
    wireframe: bool | None = UNSET,
    foreground: ColorLike | None = UNSET,
    background: ColorLike | None = UNSET,
    fill: bool | None = UNSET,
    width: SizingLike | None = UNSET,
    height: SizingLike | None = UNSET,
    gap: int | None = UNSET,
    direction: Direction | None = UNSET,
    horizontal_align: Alignment | None = UNSET,
    vertical_align: VerticalAlignment | None = UNSET,
    border: Border | None = UNSET,
    border_sides: Sequence[Side] | None = UNSET,
    border_color: ColorLike | None = UNSET,
    title: str | None = UNSET,
    title_position: FrameTitlePosition | None = UNSET,
    padding: PaddingLike | None = UNSET,
    margin: PaddingLike | None = UNSET,
    z: int | None = UNSET,
    modifiers: Sequence[CharacterModifier] | None = UNSET,
    class_name: ClassNameLike | None = UNSET,
    bold: bool = UNSET,
    dim: bool = UNSET,
    italic: bool = UNSET,
    underline: bool = UNSET,
    slow_blink: bool = UNSET,
    rapid_blink: bool = UNSET,
    reversed: bool = UNSET,
    color: ColorLike | None = UNSET,
    align: Alignment | None = UNSET,
) -> None:
    """Update a layout field's style/layout attributes, live, in-place.

    A narrower sibling of ``grid_set_field`` for frequent, value-free
    attribute changes — pulsing a border color from ``on_tick``,
    toggling a modifier from an effect callback. It has no ``value=``
    or ``position=`` parameters at all, so a per-frame style tick never
    pays for that method's value-validation branch. Optional style
    patches never raise: a missing or state-only ``name`` is a no-op
    (no ``try``/``except`` needed), though unknown keyword arguments
    still raise as a programming error.

    ``color`` is a deprecated alias for ``foreground``.
    """
    foreground = resolve_color_alias(
        foreground, color, unset=UNSET, stacklevel=3
    )
    horizontal_align = resolve_renamed_alias(
        horizontal_align,
        align,
        old="align",
        new="horizontal_align",
        unset=UNSET,
        stacklevel=3,
    )
    field_config: dict[str, Any] = {
        key: option
        for key, option in {
            "slide": slide,
            "visible": visible,
            "wireframe": wireframe,
            "foreground": foreground,
            "background": background,
            "fill": fill,
            "width": width,
            "height": height,
            "gap": gap,
            "direction": direction,
            "horizontal_align": horizontal_align,
            "vertical_align": vertical_align,
            "border": border,
            "border_sides": border_sides,
            "border_color": border_color,
            "title": title,
            "title_position": title_position,
            "padding": padding,
            "margin": margin,
            "z": z,
            "modifiers": modifiers,
            "class_name": class_name,
            "bold": bold,
            "dim": dim,
            "italic": italic,
            "underline": underline,
            "slow_blink": slow_blink,
            "rapid_blink": rapid_blink,
            "reversed": reversed,
        }.items()
        if option is not UNSET
    }
    self._grid_apply_field_config(
        name, field_config, caller="grid_update_field", missing="ignore"
    )

grid_set_frame

grid_set_frame(
    frame: Frame | None = UNSET,
    *,
    background: ColorLike | None = UNSET,
    border: Border | None = UNSET,
    border_color: ColorLike | None = UNSET,
    border_sides: Sequence[Side] | None = UNSET,
    title: str | None = UNSET,
    title_position: FrameTitlePosition | None = UNSET,
    padding: PaddingLike | None = UNSET
) -> None

Set this grid instance's outer frame (chrome + background fill).

The public replacement for mutating the private _grid_frame. Pass a whole frame to replace it outright, or individual keyword arguments to patch the current frame in place — a bare background fills the grid's whole area with no border required, so nested grids can be themed without any chrome. Pass frame=None to clear the frame.

Source code in xnano/grids.py
def grid_set_frame(
    self,
    frame: Frame | None = UNSET,
    *,
    background: ColorLike | None = UNSET,
    border: Border | None = UNSET,
    border_color: ColorLike | None = UNSET,
    border_sides: Sequence[Side] | None = UNSET,
    title: str | None = UNSET,
    title_position: FrameTitlePosition | None = UNSET,
    padding: PaddingLike | None = UNSET,
) -> None:
    """Set this grid instance's outer frame (chrome + background fill).

    The public replacement for mutating the private ``_grid_frame``.
    Pass a whole ``frame`` to replace it outright, or individual keyword
    arguments to patch the current frame in place — a bare
    ``background`` fills the grid's whole area with no border required,
    so nested grids can be themed without any chrome. Pass ``frame=None``
    to clear the frame.
    """
    if frame is not UNSET:
        object.__setattr__(
            self, "_grid_frame", None if frame is None else frame
        )
        return
    current = getattr(self, "_grid_frame", None) or Frame()
    patch = {
        key: value
        for key, value in {
            "background": background,
            "border": border,
            "border_color": border_color,
            "border_sides": border_sides,
            "title": title,
            "title_position": title_position,
            "padding": padding,
        }.items()
        if value is not UNSET
    }
    if not patch:
        return
    updated = dataclasses.replace(current, **patch)
    object.__setattr__(
        self, "_grid_frame", None if updated.is_empty() else updated
    )

grid_set_background

grid_set_background(background: ColorLike | None) -> None

Fill this grid instance's whole area with background.

Shorthand for grid_set_frame(background=...) — the path for theming a nested grid, replacing private _grid_frame mutation.

Source code in xnano/grids.py
def grid_set_background(self, background: ColorLike | None) -> None:
    """Fill this grid instance's whole area with ``background``.

    Shorthand for ``grid_set_frame(background=...)`` — the path for
    theming a nested grid, replacing private ``_grid_frame`` mutation.
    """
    self.grid_set_frame(background=background)

grid_schedule_update

grid_schedule_update(
    callback: Callable[[], Any] | None = None,
    *,
    field: str | None = None
) -> None

Apply an update on the UI thread before the next frame.

The thread-safe way to reflect background work in the UI: pass a callback to run on the runtime thread (so it can mutate this grid without racing the renderer), and/or a field to mark dirty. Safe to call from any thread; a no-op when no runtime is active.

Source code in xnano/grids.py
def grid_schedule_update(
    self,
    callback: Callable[[], Any] | None = None,
    *,
    field: str | None = None,
) -> None:
    """Apply an update on the UI thread before the next frame.

    The thread-safe way to reflect background work in the UI: pass a
    ``callback`` to run on the runtime thread (so it can mutate this grid
    without racing the renderer), and/or a ``field`` to mark dirty. Safe
    to call from any thread; a no-op when no runtime is active.
    """
    from xnano.core.runtime import get_active_runtime

    runtime = get_active_runtime()

    def _apply() -> None:
        if callback is not None:
            callback()
        if field is not None:
            self.grid_mark_field_dirty(field)

    if runtime is None:
        _apply()
    else:
        runtime.call_soon(_apply)

set_frame

set_frame(*args: Any, **kwargs: Any) -> None

Deprecated alias for grid_set_frame.

Source code in xnano/grids.py
@warn_renamed_attribute("BaseGrid.set_frame", "BaseGrid.grid_set_frame")
def set_frame(self, *args: Any, **kwargs: Any) -> None:
    """Deprecated alias for ``grid_set_frame``."""
    self.grid_set_frame(*args, **kwargs)

set_background

set_background(background: ColorLike | None) -> None

Deprecated alias for grid_set_background.

Source code in xnano/grids.py
@warn_renamed_attribute(
    "BaseGrid.set_background", "BaseGrid.grid_set_background"
)
def set_background(self, background: ColorLike | None) -> None:
    """Deprecated alias for ``grid_set_background``."""
    self.grid_set_background(background)

schedule_update

schedule_update(
    callback: Callable[[], Any] | None = None,
    *,
    field: str | None = None
) -> None

Deprecated alias for grid_schedule_update.

Source code in xnano/grids.py
@warn_renamed_attribute(
    "BaseGrid.schedule_update", "BaseGrid.grid_schedule_update"
)
def schedule_update(
    self,
    callback: Callable[[], Any] | None = None,
    *,
    field: str | None = None,
) -> None:
    """Deprecated alias for ``grid_schedule_update``."""
    self.grid_schedule_update(callback, field=field)

grid_get_field_state

grid_get_field_state(name: str) -> FieldState | None

Return tracked state for a field.

Parameters:

  • name (str) –

    Field attribute name.

Returns:

  • FieldState | None

    Its state, or None for an unknown field.

Source code in xnano/core/interface.py
def grid_get_field_state(self, name: str) -> FieldState | None:
    """Return tracked state for a field.

    Args:
        name: Field attribute name.

    Returns:
        Its state, or ``None`` for an unknown field.
    """
    return getattr(self, "_grid_field_states", {}).get(name)

grid_mark_field_dirty

grid_mark_field_dirty(name: str) -> None

Mark a field as changed.

Parameters:

  • name (str) –

    Field attribute name.

Source code in xnano/core/interface.py
def grid_mark_field_dirty(self, name: str) -> None:
    """Mark a field as changed.

    Args:
        name: Field attribute name.
    """
    state = self.grid_get_field_state(name)
    if state is not None:
        state.mark_dirty()
        state.value = getattr(self, name, None)

get_field_state

get_field_state(name: str) -> FieldState | None

Deprecated alias for grid_get_field_state.

Source code in xnano/core/interface.py
@warn_renamed_attribute(
    "AbstractInterface.get_field_state",
    "AbstractInterface.grid_get_field_state",
)
def get_field_state(self, name: str) -> FieldState | None:
    """Deprecated alias for ``grid_get_field_state``."""
    return self.grid_get_field_state(name)

mark_field_dirty

mark_field_dirty(name: str) -> None

Deprecated alias for grid_mark_field_dirty.

Source code in xnano/core/interface.py
@warn_renamed_attribute(
    "AbstractInterface.mark_field_dirty",
    "AbstractInterface.grid_mark_field_dirty",
)
def mark_field_dirty(self, name: str) -> None:
    """Deprecated alias for ``grid_mark_field_dirty``."""
    self.grid_mark_field_dirty(name)