Tree — Visuals¶
Typed Visual subtypes. KPI, Table, BarChart, Sankey are the
load-bearing kinds across the four shipped apps; TextBox carries
rich-text content for Getting Started sheets. Each subtype validates
its dataset / column references at emit time.
visuals ¶
Typed Visual subtypes — one per visual kind in active use.
L.1.1 catalog: KPI ×29, Table ×22, BarChart ×13, Sankey ×2 across
the three apps. Each subtype owns its field-well shape and emits the
corresponding models.py Visual instance.
VisualLike ¶
Bases: Protocol
Structural type for tree-level visual nodes.
Typed subtypes (KPI / Table / BarChart / Sankey)
satisfy this Protocol — duck-typed so subtypes don't have to
inherit from a base class. Subtypes contribute to the L.1.7
dependency-graph walk via datasets() / calc_fields().
All visual nodes also satisfy LayoutNode (in structure.py)
via element_id + element_type so they can be placed in a
sheet's grid layout (sheet.layout.row(...).add_<kind>(...)).
visual_id is VisualId | AutoResolved — typed subtypes default
to AUTO and App._resolve_auto_ids replaces it with the
derived id before emit. The walker / emit assert via isinstance
narrowing.
KPI
dataclass
¶
KPI visual — single number per values entry, no grouping.
Field-well shape: Values=[Measure, ...]. Most KPIs use one
measure; multiple are allowed and render as side-by-side numbers.
visual_id is optional (L.1.8.5 auto-ID). When omitted, the
App's tree walker assigns v-kpi-s{sheet_idx}-{visual_idx} at
emit time. Pass an explicit VisualId(...) to override.
values
class-attribute
instance-attribute
¶
__init__ ¶
__init__(title: str, subtitle: str | None = None, values: list[Measure] = list[Measure](), visual_id: VisualId | AutoResolved = AUTO) -> None
Table
dataclass
¶
Table visual — two field-well shapes:
- Aggregated (default):
group_by=[Dim, ...]+values=[Measure, ...]. One row per distinctgroup_bycombination, aggregated byvalues. EmitsTableAggregatedFieldWells. - Unaggregated: pass
columns=[Dim, ...](and leavegroup_by/valuesempty). Each cell shows the raw column value — no aggregation, one row per source row. EmitsTableUnaggregatedFieldWells. Use this for detail/drill-source tables (AR Balances, AR Daily Statement transaction list).
Optional sort_by is a (field_ref, direction) tuple —
direction is "ASC" or "DESC".
Optional conditional_formatting passes through to the model's
raw dict (see common/clickability.py for the standard
accent-text and tint-background helpers).
visual_id is optional (L.1.8.5 auto-ID).
group_by
class-attribute
instance-attribute
¶
values
class-attribute
instance-attribute
¶
sort_by
class-attribute
instance-attribute
¶
sort_by: tuple[FieldRef, Literal['ASC', 'DESC']] | list[tuple[FieldRef, Literal['ASC', 'DESC']]] | None = None
actions
class-attribute
instance-attribute
¶
conditional_formatting
class-attribute
instance-attribute
¶
conditional_formatting: list[CellFormat] | None = None
__init__ ¶
__init__(title: str, subtitle: str | None = None, group_by: list[Dim] = list[Dim](), values: list[Measure] = list[Measure](), columns: list[Dim] = list[Dim](), sort_by: tuple[FieldRef, Literal['ASC', 'DESC']] | list[tuple[FieldRef, Literal['ASC', 'DESC']]] | None = None, actions: list[Action] = list[Action](), conditional_formatting: list[CellFormat] | None = None, visual_id: VisualId | AutoResolved = AUTO) -> None
BarChart
dataclass
¶
Bar chart visual — one bar per distinct category, height by
values.
Field-well shape: Category=[Dim, ...] + Values=[Measure, ...].
orientation ("VERTICAL" or "HORIZONTAL") and
bars_arrangement ("CLUSTERED" / "STACKED" /
"STACKED_PERCENT") pass through to the underlying
BarChartConfiguration. sort_by is a (field_id, direction)
tuple — direction "ASC" or "DESC" — and emits a
CategorySort entry. All three default to None so the
QuickSight defaults apply when not specified.
visual_id is optional (L.1.8.5 auto-ID).
category
class-attribute
instance-attribute
¶
values
class-attribute
instance-attribute
¶
orientation
class-attribute
instance-attribute
¶
orientation: Literal['HORIZONTAL', 'VERTICAL'] | None = None
bars_arrangement
class-attribute
instance-attribute
¶
bars_arrangement: Literal['CLUSTERED', 'STACKED', 'STACKED_PERCENT'] | None = None
sort_by
class-attribute
instance-attribute
¶
sort_by: tuple[FieldRef, Literal['ASC', 'DESC']] | None = None
actions
class-attribute
instance-attribute
¶
__init__ ¶
__init__(title: str, subtitle: str | None = None, category: list[Dim] = list[Dim](), values: list[Measure] = list[Measure](), colors: list[Dim] = list[Dim](), orientation: Literal['HORIZONTAL', 'VERTICAL'] | None = None, bars_arrangement: Literal['CLUSTERED', 'STACKED', 'STACKED_PERCENT'] | None = None, category_label: str | None = None, value_label: str | None = None, color_label: str | None = None, sort_by: tuple[FieldRef, Literal['ASC', 'DESC']] | None = None, actions: list[Action] = list[Action](), visual_id: VisualId | AutoResolved = AUTO) -> None
LineChart
dataclass
¶
Line chart visual — one line per distinct colors value,
plotted across category (x-axis) with height by values
(y-axis).
Field-well shape: Category=[Dim, ...] + Values=[Measure, ...]
+ Colors=[Dim, ...].
chart_type selects LINE (default), AREA, or
STACKED_AREA. sort_by is a (field_id, direction) tuple
— direction "ASC" or "DESC" — and emits a CategorySort
entry. All optional fields default to None so the QuickSight
defaults apply when not specified.
visual_id is optional (L.1.8.5 auto-ID).
category
class-attribute
instance-attribute
¶
values
class-attribute
instance-attribute
¶
chart_type
class-attribute
instance-attribute
¶
chart_type: Literal['LINE', 'AREA', 'STACKED_AREA'] | None = None
sort_by
class-attribute
instance-attribute
¶
sort_by: tuple[FieldRef, Literal['ASC', 'DESC']] | None = None
actions
class-attribute
instance-attribute
¶
__init__ ¶
__init__(title: str, subtitle: str | None = None, category: list[Dim] = list[Dim](), values: list[Measure] = list[Measure](), colors: list[Dim] = list[Dim](), chart_type: Literal['LINE', 'AREA', 'STACKED_AREA'] | None = None, category_label: str | None = None, value_label: str | None = None, sort_by: tuple[FieldRef, Literal['ASC', 'DESC']] | None = None, actions: list[Action] = list[Action](), visual_id: VisualId | AutoResolved = AUTO) -> None
Sankey
dataclass
¶
Sankey diagram visual — flows from source nodes to
target nodes, ribbon thickness by weight.
Field-well shape: each of source / target / weight is
a single Dim / Measure (the underlying model expects
lists, but every usage today has exactly one entry; emit wraps).
items_limit caps the number of source / destination nodes
rendered (matches the ItemsLimit shape on the underlying
sort configuration). OtherCategories defaults to "INCLUDE"
so capped flows roll into a "(others)" bucket rather than being
dropped silently.
visual_id is optional (L.1.8.5 auto-ID).
actions
class-attribute
instance-attribute
¶
text_boxes ¶
Tree-side wrapper for models.SheetTextBox — the rich-text box
nodes used on landing-page sheets (Getting Started).
QuickSight splits a sheet's contents into Visuals and TextBoxes
in the underlying model, but at the layout level both occupy
GridLayoutElement slots — only the ElementType differs
("VISUAL" vs "TEXT_BOX"). The LayoutNode Protocol in
structure.py abstracts over that split so callers see a single
Sheet.place(node, ...) API regardless of which underlying field
the node will eventually emit into.
TextBox
dataclass
¶
Tree-side rich-text box.
Mirrors the KPI / Table / BarChart / Sankey typed
wrapper pattern: callers construct typed nodes; the tree owns
layout / id resolution / emission. Compose content via the
common.rich_text helpers (rt.text_box(...)) and pass the
string in.
text_box_id is required (no auto-ID for text boxes — they
don't carry a _AUTO_KIND). The ID surfaces in the layout's
ElementId and the sheet's TextBoxes list.