Skip to content

metanno.ui

AnnotatedImage [source]

An interactive image viewer that supports drawing, selecting, and styling geometric shapes (polygons, rectangles, points...) as annotations.

Under the hood, we use Konva to render the image and its annotations.

Examples

from pret import component, create_store, use_store_snapshot, use_event_callback
from metanno import AnnotatedImage
import time

# Reactive store holding the annotation list
img_state = create_store([
    {
        "id": "1",
        "type": "polygon",
        "points": [10, 10, 50, 20],
        "label": "OBJ",
        "style": "primary",
    }
])

# Style preset referenced from the annotation above
img_annotation_styles = {
    "primary": {
        "strokeColor": "red",
        "strokeWidth": 2,
        "fillColor": "rgba(255,0,0,0.5)",
        "labelPosition": "center",
        "align": "center",
        "verticalAlign": "top",
    },
    "secondary": {
        "strokeColor": "blue",
        "strokeWidth": 2,
        "fillColor": "#0000ff80",
        "textColor": "white",
    }
}

@component
def MyImage():
    tracked_state = use_store_snapshot(img_state)

    @use_event_callback
    def on_mouse_select(modkeys, shapes):
        # Toggle 'mouseSelected' flag
        for shp in shapes:
            img_state.append({
                "id": str(time.time()),
                "points": shp["points"],
                "label": "OBJ",
                "style": "primary",
            })

    @use_event_callback
    def on_click(shape_idx, modkeys):
        if shape_idx is None:
            img_state.clear()
        else:
            old_style = img_state[shape_idx].get("style", "primary")
            new_style = "secondary" if old_style == "primary" else "primary"
            img_state[shape_idx]["style"] = new_style

    return AnnotatedImage(
        image="https://picsum.photos/400/300",
        annotations=tracked_state,
        annotation_styles=img_annotation_styles,
        on_mouse_select=on_mouse_select,
        on_click=on_click,
    )

MyImage()

Parameters

PARAMETER DESCRIPTION
annotations

List of annotation objects drawn on top of the image. Each annotation must contain the geometric type and points fields (defining the shape) plus optional metadata such as:

  • id: Optional unique identifier.
  • label: Human-readable text shown next to the shape.
  • style: Key that looks up visual properties in annotation_styles.
  • selected / highlighted / mouseSelected: Booleans used by the component when rendering interaction state.

TYPE: Any

annotation_styles

Named style presets referenced by the style field of an annotation. Each preset may define properties such as stroke color, fill color, opacity, font size, and label alignment, using the following properties:

  • strokeColor (str): Color of the shape's stroke (e.g. "#ff0000").
  • strokeWidth (int): Width of the shape's stroke in pixels.
  • fillColor (str): Background color of the shape (e.g. "#0000ff80").
  • opacity (float): Opacity of the shape's fill (0.0 to 1.0).
  • shape (str): Shape type, e.g. "polygon", "rectangle", "circle", etc.
  • fontSize (int): Font size for the label text.
  • align ("left" | "center" | "right"): Horizontal alignment of the label text.
  • verticalAlign ("top" | "middle" | "bottom"): Vertical alignment of the label text.

TYPE: Any

image

Source URL or base-64 data URI of the image to annotate.

TYPE: str

mouse_selection

Temporary shapes being drawn by the user while the mouse button is held down. Supplied back to on_mouse_select when the gesture ends.

TYPE: Any

style

Inline CSS-compatible style overrides for the root element of the component.

TYPE: Any

handle

Optional imperative handle that the parent may call (empty for now).

TYPE: Any

key

React key for stable reconciliation.

TYPE: Union[str, int]

on_click

Invoked when the user clicks on an existing shape.

  • shape_id: Identifier of the clicked annotation
  • modkeys: List of pressed modifier keys (e.g. ["Shift"])

TYPE: Any

on_key_press

Invoked when the component has focus and the user presses a key.

  • key: The key name ("Escape", "Delete" …)
  • modkeys: Concurrently pressed modifier keys

TYPE: Any

on_mouse_enter_shape

Hover callbacks fired when the mouse pointer enters or leaves a shape.

TYPE: Any

on_mouse_select

Fired after the user completes a drag selection.

  • modkeys: Modifier keys pressed during selection
  • shapes: All shapes inside the lasso / rectangle

TYPE: Any

Table [source]

A component for displaying a table with various features such as filtering, highlighting rows, and handling cell changes.

Examples

from pret import component, create_store, use_store_snapshot, use_event_callback
from metanno import Table

table_state = create_store([
    {"id": "1", "date": "2023-01-01", "text": "Sample text 1", "type": "ENT", "labels": ["ready"]},
    {"id": "2", "date": "2023-01-03", "text": "Sample text 2", "type": "OTHER", "labels": ["ready", "danger"]},
    {"id": "3", "date": "2023-01-05", "text": "Sample text 3", "type": "ENT", "labels": ["blue"]},
    {"id": "4", "date": "2023-01-07", "text": "Sample text 4", "type": "OTHER", "labels": ["bad"]},
    {"id": "5", "date": "2023-01-09", "text": "Sample text 5", "type": "ENT", "labels": []},
    {"id": "6", "date": "2023-01-11", "text": "Sample text 6", "type": "OTHER", "labels": ["custom"]},
    {"id": "7", "date": "2023-01-13", "text": "Sample text 7", "type": "FOO", "labels": ["ready"]},
    {"id": "8", "date": "2023-01-15", "text": "Sample text 8", "type": "FOO2", "labels": ["danger"]},
    {"id": "9", "date": "2023-01-17", "text": "Sample text 9", "type": "FOO3", "labels": ["blue"]},
    {"id": "10", "date": "2023-01-19", "text": "Sample text 10", "type": "ENT", "labels": ["bad"]},
    {"id": "11", "date": "2023-01-21", "text": "Sample text 11", "type": "OTHER", "labels": ["custom"]},
    {"id": "12", "date": "2023-01-23", "text": "Sample text 12", "type": "ENT", "labels": ["ready"]},
    {"id": "13", "date": "2023-01-25", "text": "Sample text 13", "type": "OTHER", "labels": ["danger"]},
    {"id": "14", "date": "2023-01-27", "text": "Sample text 14", "type": "FOO2", "labels": ["blue"]},
    {"id": "15", "date": "2023-01-29", "text": "Sample text 15", "type": "FOO3", "labels": ["bad"]},
])

columns = [
    {"key": "id", "kind": "text", "name": "id", "filterable": True},
    {"key": "date", "kind": "text", "name": "end", "filterable": True},
    {"key": "text", "kind": "text", "name": "text", "filterable": True, "editable": True},
    {"key": "type", "kind": "text", "name": "label", "filterable": True, "editable": True, "choices": ["ENT", "OTHER", "STUFF", "FOO", "FOO2", "FOO3"]},
    {"key": "labels", "kind": "multi-text", "name": "labels", "filterable": True, "editable": True, "choices": ["ready", "danger", "blue", "bad", "custom"]},
]

@component
def MyTable():
    @use_event_callback
    def on_cell_change(row_id, row_idx, col, new_value):
        table_state[row_idx][col] = new_value

    view_state = use_store_snapshot(table_state)
    return Table(
        primary_key="id",
        rows=view_state,
        columns=columns,
        auto_filter=True,
        on_cell_change=on_cell_change,
    )

MyTable()

Parameters

PARAMETER DESCRIPTION
rows

The data for each row in the table, where each row is a dictionary mapping column keys to their values.

TYPE: List[Dict[str, Any]]

columns

The columns to display in the table:

  • key: Unique identifier for the column.
  • name: Display name of the column.
  • kind: Type of data in the column (e.g., "text", "hyperlink", "multi-text", "boolean", ...).
  • editable: Whether the column is editable.
  • filterable: Whether the column can be filtered.
  • choices: Optional list of choices for the column (if applicable).

TYPE: ColumnData

primary_key

The key used to uniquely identify each row in the table.

TYPE: str

filters

The current filters applied to the table, mapping column keys to filter values.

TYPE: Dict[str, str]

highlighted_rows

List of row indices that should be highlighted.

TYPE: List[int]

handle

Imperative handle for actions that can be performed on the table, such as scrolling:

  • scroll_to_row_idx(row_idx: int): Scrolls the table to the specified row index.
  • scroll_to_row_id(row_id: str): Scrolls the table to the specified row ID.
  • focus(): Sets focus on the currently open cell or full table if no cell is open.

TYPE: Dict[str, Any]

auto_filter

Whether to automatically apply filters as the user types.

TYPE: bool

input_value

The current input value to show in the input field when the user is editing a cell. If undefined, this is automatically handled by the component.

TYPE: Union[str, Hyperlink]

suggestions

List of suggestions to show when the user is typing in the input field.

TYPE: List[Any]

position

The current position of the cursor in the table, including:

  • row_id: Key of the row where the cursor is located.
  • row_idx: Index of the row where the cursor is located.
  • col: Key of the column where the cursor is located.
  • mode: Mode of interaction, either "EDIT" or "SELECT".

TYPE: Position

style

Custom styles for the table component.

TYPE: Dict[str, Any]

key

A unique key for the component instance, used for React's reconciliation.

TYPE: Union[str, int]

on_input_change

Callback triggered when the input value changes in a cell:

  • row_id: Key of the row being edited.
  • row_idx: Index of the row being edited.
  • name: Key of the column being edited.
  • value: New value entered by the user.
  • cause: Reason for the change (e.g., "blur", "enter").

TYPE: Callable

on_scroll_bottom

Callback triggered when the user scrolls to the bottom of the table:

  • event: Scroll event or a dictionary indicating if the user is at the bottom.

TYPE: Callable

on_cell_change

Callback triggered when a cell's value changes:

  • row_id: Key of the row being edited.
  • row_idx: Index of the row being edited.
  • name: Key of the column being edited.
  • value: New value of the cell.

TYPE: Callable

on_click_cell_content

Callback triggered when the content of a cell is clicked (like a hyperlink):

  • row_id: Key of the row containing the clicked cell.
  • row_idx: Index of the row containing the clicked cell.
  • name: Key of the column containing the clicked cell.
  • value: Optional value of the clicked cell.

TYPE: Callable

on_filters_change

Callback triggered when filters are updated:

  • values: Dictionary mapping column keys to filter values.
  • column: Key of the column being filtered.

TYPE: Callable

on_mouse_enter_row

Callback triggered when the mouse enters a row:

  • row_id: Key of the row being hovered.
  • row_idx: Index of the row being hovered.
  • mod_keys: List of modifier keys pressed during the event.

TYPE: Callable

on_mouse_leave_row

Callback triggered when the mouse leaves a row:

  • row_id: Key of the row being hovered.
  • row_idx: Index of the row being hovered.
  • mod_keys: List of modifier keys pressed during the event.

TYPE: Callable

on_mouse_hover_row

Callback triggered when the mouse hovers over a row:

  • row_id: Key of the row being hovered, or None if not applicable.
  • row_idx: Index of the row being hovered, or None if not applicable.
  • mod_keys: List of modifier keys pressed during the event.

TYPE: Callable

on_position_change

Callback triggered when the cursor position changes:

  • row_id: Key of the row where the cursor is located, or None if not applicable.
  • row_idx: Index of the row where the cursor is located, or None if not applicable.
  • name: Key of the column where the cursor is located, or None if not applicable.
  • mode: Interaction mode, either "EDIT" or "SELECT".
  • cause: Reason for the position change (e.g., "key", "blur").

TYPE: Callable

on_subset_change

Callback triggered when the subset of visible rows changes:

  • subset: List of indices representing the new subset of rows.

TYPE: Callable

AnnotatedText [source]

The AnnotatedText is a rich text viewer that supports span-level annotations, nested token highlights, and various user event callbacks.

Examples

from pret import (
    component,
    create_store,
    use_store_snapshot,
    use_event_callback,
    use_state,
)
from metanno import AnnotatedText
from pret_joy import Button, Box

txt = (
    "Metanno brings annotation components to Pret\n"
    "to build tailored annotation tools."
)

# One span covering the word “Metanno”
spans = create_store(
    [
        {
            "id": f"span-0-7",
            "start": 0,
            "end": 7,
            "label": "OBJ",
            "highlighted": False,
        }
    ]
)

txt_annotation_styles = create_store(
    {
        "OBJ": {
            "color": "red",
            "shape": "underline",
        }
    }
)


@component
def MyText():
    tracked_spans = use_store_snapshot(spans)
    tracked_styles = use_store_snapshot(txt_annotation_styles)

    @use_event_callback
    def handle_select(ranges, modkeys):
        for sp in ranges:
            spans.extend(
                [
                    {
                        "id": f"span-{sp['begin']}-{sp['end']}",
                        "start": sp["begin"],
                        "end": sp["end"],
                        "label": "OBJ",
                    }
                ]
            )

    def on_mouse_enter_span(span_id, modkeys):
        for i, sp in enumerate(spans):
            if sp["id"] == span_id:
                spans[i]["highlighted"] = True

    def on_mouse_leave_span(span_id, modkeys):
        for i, sp in enumerate(spans):
            if sp["id"] == span_id:
                spans[i]["highlighted"] = False

    def on_span_style_change():
        old_style = txt_annotation_styles["OBJ"]["shape"]
        new_style = "box" if old_style == "underline" else "underline"
        txt_annotation_styles["OBJ"]["shape"] = new_style

    return Box(
        Button("Change style", on_click=on_span_style_change),
        Button("Remove annotations", on_click=lambda: spans.clear()),
        AnnotatedText(
            text=txt,
            spans=tracked_spans,
            annotation_styles=tracked_styles,
            on_mouse_select=handle_select,
            on_mouse_enter_span=on_mouse_enter_span,
            on_mouse_leave_span=on_mouse_leave_span,
            style={"gridColumn": "1 / -1"},
            begin_key="start",  # Custom field names
        ),
        sx={
            "p": 1,
            "display": "grid",
            "gridTemplateColumns": "repeat(2, auto)",
            "gap": 1,
        },
    )


MyText()

Parameters

PARAMETER DESCRIPTION
text

Raw text content shown in the viewer.

TYPE: str

spans

Span-level annotations over text. Each span must include:

  • begin (or the value of begin_key): Begin character offset (inclusive).
  • end (or the value of end_key): End character offset (exclusive).

and may optionally include:

  • id (or the value of primary_key): Optional unique span identifier.
  • label (or the value of label_key): Category name displayed next to / above the span.
  • style (or the value of style_key): Key referencing annotation_styles.
  • selected (or the value of selected_key): styled as selected by the user.
  • highlighted (or the value of label_key): styled as highlighted by the user.

TYPE: List[Dict[str, Any]]

annotation_styles

Named style presets that control span background color, border, label placement, etc. Each style may define properties such as:

  • color (str): Color of the span. Will be overridden by backgroundColor and borderColor.
  • shape ("underline" | "box"): Visual style of the span.
  • backgroundColor (str): Background color of the span (e.g. "#0000ff80").
  • borderColor (str): Border color of the span (e.g. "#000000").
  • autoNestingLayout (bool): Whether to automatically nest overlapping spans, rather than rendering them on top of each other.

TYPE: Dict[str, Dict[str, Any]]

mouse_selection

Current mouse drag selection expressed as character‐offset ranges. Passed to on_mouse_select when the action completes.

TYPE: List[Dict[str, int]]

style

CSS style overrides for the outer element.

TYPE: Dict[str, Any]

handle

Imperative handle for actions that can be performed on the component:

  • scroll_to_line(line_idx: int, behavior: "smooth" | "instant" | "auto"): Scrolls to the given line index.
  • scroll_to_span(span_id: str, behavior: "smooth" | "instant" | "auto"): Scrolls to the given span.
  • clear_current_mouse_selection(): Clears the current mouse selection.

TYPE: Dict[str, Any]

begin_key

Name of the field in spans that contains the begin character offset.

TYPE: str DEFAULT: 'begin'

end_key

Name of the field in spans that contains the end character offset.

TYPE: str DEFAULT: 'end'

primary_key

Name of the field in spans that contains the unique span identifier.

TYPE: str DEFAULT: 'id'

label_key

Name of the field in spans that contains the human-readable label.

TYPE: str DEFAULT: 'label'

style_key

Name of the field in spans that contains the style key. This key will be used to look up visual properties in annotation_styles. If no style field is provided for a span, the style key will default to label.

TYPE: str DEFAULT: 'style'

highlighted_key

Name of the field in spans that indicates whether the span is highlighted.

TYPE: str DEFAULT: 'highlighted'

on_click_span

Called when the user clicks on a span.

  • span_id: Identifier of the clicked annotation
  • modkeys: Pressed modifier keys

TYPE: Callable[[str, List[str]], None]

on_key_press

Called when a key is pressed with focus inside the component.

  • key: Key name
  • ranges: Current selection ranges
  • modkeys: Modifier keys

TYPE: Callable[[str, List[Dict[str, int]], List[str]], None]

on_mouse_enter_span

Called when the mouse pointer enters a span.

  • span_id: Identifier of the span entered
  • modkeys: Pressed modifier keys

TYPE: Callable[[str, List[str]], None]

on_mouse_leave_span

Called when the mouse pointer leaves a span.

  • span_id: Identifier of the span left
  • modkeys: Pressed modifier keys

TYPE: Callable[[str, List[str]], None]

on_mouse_hover_spans

Triggered every time the set of hovered spans changes.

  • span_ids: List of currently hovered span identifiers
  • modkeys: Pressed modifier keys

TYPE: Callable[[List[str], List[str]], None]

on_mouse_select

Triggered when the user finishes selecting text with the mouse.

  • ranges: Final list of selected ranges
  • modkeys: Modifier keys

TYPE: Callable[[List[Dict[str, int]], List[str]], None]

key

React reconciliation key (not the same as the previous _key props), this should be used to uniquely identify the component instance if there are multiple instances next to each other.

TYPE: Union[str, int]