Skip to content

xnano.components.bar

xnano.components.bar

xnano.components.bar


Render compact trends and distributions with configurable glyphs.

Classes:

  • Bar

    Compact inline bar chart for a sequence of samples.

Functions:

Attributes:

BarDirection module-attribute

BarDirection: TypeAlias = Literal['up', 'down']

Whether bar samples grow upward or downward.

BarGlyphPreset module-attribute

BarGlyphPreset: TypeAlias = Literal[
    "blocks", "braille", "ascii"
]

Named glyph ladders for compact bar rendering.

BarGlyphs module-attribute

Explicit ordered symbols or a named preset.

Bar dataclass

Bar(
    data: Sequence[int | float] = tuple(),
    foreground: "ColorLike | None" = None,
    colors: Sequence["ColorLike"] | None = None,
    background: "ColorLike | None" = None,
    max_value: int | float | None = None,
    direction: BarDirection = "up",
    glyphs: BarGlyphs = "blocks",
    absent_color: "ColorLike | None" = None,
    absent_glyph: str | None = None,
    *,
    visible: bool = True,
    z: int = 0,
    fit_content: bool = False
)

Bases: Component

Compact inline bar chart for a sequence of samples.

Fills its layout slot by default and scales sample heights across the available vertical area when using the native sparkline path. Supply colors with one entry per sample to tint individual bars.

Example

Bar(data=(2, 5, 3, 8), color="cyan")

Attributes:

Methods:

  • component_post_init

    Resolve and validate the glyph ladder once.

  • compose

    Compose sparkline content, with a native/canvas paint path.

  • get_frame

    Optional frame/panel chrome around composed content.

  • get_size

    Return the preferred cell size of this component.

  • before_render

    Called before rendering; returns the effective render area.

  • after_render

    Called after rendering for optional post-paint work.

  • compose_extra_small

    Compose content when the viewport is extra small (< 40 cols).

  • compose_small

    Compose content when the viewport is small (40–79 cols).

  • compose_medium

    Compose content when the viewport is medium (80–119 cols).

  • compose_large

    Compose content when the viewport is large (120–159 cols).

  • compose_extra_large

    Compose content when the viewport is extra large (>= 160 cols).

  • handle_keyboard

    Optional keyboard handler while focused.

  • handle_paste

    Optional paste handler while focused.

data class-attribute instance-attribute

data: Sequence[int | float] = dataclasses.field(
    default_factory=tuple
)

Sequence of sample values.

foreground class-attribute instance-attribute

foreground: 'ColorLike | None' = None

Default bar foreground color (deprecated alias: color).

colors class-attribute instance-attribute

colors: Sequence['ColorLike'] | None = None

Optional per-bar foreground colors, one per data entry.

background class-attribute instance-attribute

background: 'ColorLike | None' = None

Widget background color.

max_value class-attribute instance-attribute

max_value: int | float | None = None

Explicit y-axis ceiling; None auto-scales to the dataset max.

direction class-attribute instance-attribute

direction: BarDirection = 'up'

Whether samples grow "up" or "down".

glyphs class-attribute instance-attribute

glyphs: BarGlyphs = 'blocks'

Ordered fill ladder or a named preset (blocks/braille/ascii).

absent_color class-attribute instance-attribute

absent_color: 'ColorLike | None' = None

Color applied to zero or absent samples.

absent_glyph class-attribute instance-attribute

absent_glyph: str | None = None

Glyph drawn for absent samples.

fit_content class-attribute instance-attribute

fit_content: bool = dataclasses.field(
    default=False, kw_only=True
)

Whether layout should use the sparkline's natural width.

resolved_glyphs property

resolved_glyphs: tuple[str, ...]

Resolved ordered glyph ladder used for rendering.

visible class-attribute instance-attribute

visible: bool = dataclasses.field(
    default=True, kw_only=True
)

Whether this component paints at all.

z class-attribute instance-attribute

z: int = dataclasses.field(default=0, kw_only=True)

Stacking order among sibling content.

focused property

focused: bool

Whether this component currently holds field focus.

component_post_init

component_post_init() -> None

Resolve and validate the glyph ladder once.

Source code in xnano/components/bar.py
def component_post_init(self) -> None:
    """Resolve and validate the glyph ladder once."""
    self._resolved_glyphs = resolve_bar_glyphs(self.glyphs)
    if self.direction not in ("up", "down"):
        raise ValueError(f"Unsupported bar direction: {self.direction!r}")
    if self.absent_glyph is not None and not _is_single_cell_glyph(
        self.absent_glyph
    ):
        raise ValueError(
            "absent_glyph must occupy a single terminal cell."
        )
    if self.colors is not None and len(self.colors) != len(self.data):
        raise ValueError("colors must contain one entry per data sample.")

compose

compose(ctx: 'ComponentRenderContext')

Compose sparkline content, with a native/canvas paint path.

Returns:

  • Interface-neutral content for this bar.

Source code in xnano/components/bar.py
def compose(self, ctx: "ComponentRenderContext"):
    """Compose sparkline content, with a native/canvas paint path.

    Returns:
        Interface-neutral content for this bar.
    """
    if not self._uses_native_sparkline():
        return self._compose_glyph_canvas(ctx)

    return self._compose_sparkline_content()

get_frame

get_frame() -> Any | None

Optional frame/panel chrome around composed content.

Source code in xnano/components/component.py
def get_frame(self) -> Any | None:
    """Optional frame/panel chrome around composed content."""
    return None

get_size

get_size(ctx: ComponentRenderContext[StateT]) -> Size

Return the preferred cell size of this component.

Source code in xnano/components/component.py
def get_size(self, ctx: ComponentRenderContext[StateT]) -> Size:
    """Return the preferred cell size of this component."""
    return Size(width=0, height=0)

before_render

before_render(
    ctx: ComponentRenderContext[StateT], area: "Area"
) -> "Area"

Called before rendering; returns the effective render area.

Source code in xnano/components/component.py
def before_render(
    self,
    ctx: ComponentRenderContext[StateT],
    area: "Area",
) -> "Area":
    """Called before rendering; returns the effective render area."""
    return area

after_render

after_render(
    ctx: ComponentRenderContext[StateT], area: "Area"
) -> None

Called after rendering for optional post-paint work.

Source code in xnano/components/component.py
def after_render(
    self,
    ctx: ComponentRenderContext[StateT],
    area: "Area",
) -> None:
    """Called after rendering for optional post-paint work."""
    return None

compose_extra_small

compose_extra_small(
    ctx: ComponentRenderContext[StateT],
) -> Content | None

Compose content when the viewport is extra small (< 40 cols).

Optional responsive counterpart to :meth:compose. When overridden, it is used instead of compose while the window is in this size tier. Overriding any compose_* variant opts the component into breakpoint dispatch; a component that overrides none pays no per-frame cost.

Source code in xnano/components/component.py
@responsive_noop
def compose_extra_small(
    self, ctx: ComponentRenderContext[StateT]
) -> Content | None:
    """Compose content when the viewport is extra small (< 40 cols).

    Optional responsive counterpart to :meth:`compose`. When
    overridden, it is used *instead of* ``compose`` while the window
    is in this size tier. Overriding any ``compose_*`` variant opts the
    component into breakpoint dispatch; a component that overrides none
    pays no per-frame cost.
    """
    return None

compose_small

compose_small(
    ctx: ComponentRenderContext[StateT],
) -> Content | None

Compose content when the viewport is small (40–79 cols).

See :meth:compose_extra_small.

Source code in xnano/components/component.py
@responsive_noop
def compose_small(
    self, ctx: ComponentRenderContext[StateT]
) -> Content | None:
    """Compose content when the viewport is small (40–79 cols).

    See :meth:`compose_extra_small`.
    """
    return None

compose_medium

compose_medium(
    ctx: ComponentRenderContext[StateT],
) -> Content | None

Compose content when the viewport is medium (80–119 cols).

See :meth:compose_extra_small.

Source code in xnano/components/component.py
@responsive_noop
def compose_medium(
    self, ctx: ComponentRenderContext[StateT]
) -> Content | None:
    """Compose content when the viewport is medium (80–119 cols).

    See :meth:`compose_extra_small`.
    """
    return None

compose_large

compose_large(
    ctx: ComponentRenderContext[StateT],
) -> Content | None

Compose content when the viewport is large (120–159 cols).

See :meth:compose_extra_small.

Source code in xnano/components/component.py
@responsive_noop
def compose_large(
    self, ctx: ComponentRenderContext[StateT]
) -> Content | None:
    """Compose content when the viewport is large (120–159 cols).

    See :meth:`compose_extra_small`.
    """
    return None

compose_extra_large

compose_extra_large(
    ctx: ComponentRenderContext[StateT],
) -> Content | None

Compose content when the viewport is extra large (>= 160 cols).

See :meth:compose_extra_small.

Source code in xnano/components/component.py
@responsive_noop
def compose_extra_large(
    self, ctx: ComponentRenderContext[StateT]
) -> Content | None:
    """Compose content when the viewport is extra large (>= 160 cols).

    See :meth:`compose_extra_small`.
    """
    return None

handle_keyboard

handle_keyboard(keyboard: 'KeyboardEventData') -> bool

Optional keyboard handler while focused.

Returns:

  • bool

    True when the event was consumed.

Source code in xnano/components/component.py
def handle_keyboard(self, keyboard: "KeyboardEventData") -> bool:
    """Optional keyboard handler while focused.

    Returns:
        ``True`` when the event was consumed.
    """
    return False

handle_paste

handle_paste(text: str) -> bool

Optional paste handler while focused.

Returns:

  • bool

    True when the paste was consumed.

Source code in xnano/components/component.py
def handle_paste(self, text: str) -> bool:
    """Optional paste handler while focused.

    Returns:
        ``True`` when the paste was consumed.
    """
    return False

resolve_bar_glyphs

resolve_bar_glyphs(glyphs: BarGlyphs) -> tuple[str, ...]

Resolve a preset name or symbol sequence into ordered glyphs.

Parameters:

  • glyphs (BarGlyphs) –

    Named preset or ordered symbol sequence.

Returns:

  • tuple[str, ...]

    A tuple of at least two single-cell symbols.

Raises:

Source code in xnano/components/bar.py
def resolve_bar_glyphs(glyphs: BarGlyphs) -> tuple[str, ...]:
    """Resolve a preset name or symbol sequence into ordered glyphs.

    Args:
        glyphs: Named preset or ordered symbol sequence.

    Returns:
        A tuple of at least two single-cell symbols.

    Raises:
        ValueError: When the glyph set is invalid.
    """
    if isinstance(glyphs, str) and glyphs in _GLYPH_PRESETS:
        return _GLYPH_PRESETS[glyphs]
    if isinstance(glyphs, str):
        symbols = tuple(glyphs)
    else:
        symbols = tuple(str(symbol) for symbol in glyphs)
    if len(symbols) < 2:
        raise ValueError("Bar glyphs require at least two symbols.")
    for symbol in symbols:
        if not _is_single_cell_glyph(symbol):
            raise ValueError(
                f"Bar glyph {symbol!r} must occupy a single terminal cell."
            )
    return symbols