Something went wrong

Thank you for being patient! We're working hard on resolving the issue

Plugins - Lona Docs Log in

Plugins

Plugins control how rows render in the sheet. Each row type has a plugin that decides what cells look like, what legends to show, and how to respond to user gestures.

Overview

A plugin implements RenderPlugin and is registered by type name. When the sheet renders a row, it looks up the plugin for that row's type and delegates rendering to it.

Sheet renders row (type: "tasks")
  → PluginManager.getPlugin("tasks")
    → TaskPlugin.bindCell($cell, context)

Creating a Plugin

Implement RenderPlugin with at minimum an id, icon, makeCell(), and bindCell():

import type { RenderPlugin, BindCellContext } from "@tento-lona/sheets-ui";

export class TaskPlugin implements RenderPlugin<TaskCell, TaskLegend> {
  readonly id = "tasks";
  readonly icon = taskIconTemplate;

  makeCell(): TaskCell {
    return TaskCell.make();
  }

  bindCell($cell: TaskCell, context: BindCellContext): void {
    const { row, column, handle } = context;
    const tasks = this.getTasksForColumn(row, column);
    $cell.bind(tasks);
  }

  onResize($cell: TaskCell, context: BindCellContext): void {
    $cell.updateWidth(context.widthPx);
  }

  optionsInfo(): Option<string> {
    return null;
  }

  onBindRow(): void {}
  onViewportColumnsChanged(): void {}
  onRenderedColumnsWillChange(): void {}
}

Register it in the plugin manager:

pluginManager.register("tasks", new TaskPlugin(events, sdk));

SheetDelegate

Every plugin method receives a SheetDelegate (via context.handle) that provides access to the sheet's positioning APIs:

HandlePurposeCoordinate system
handle.popoverScroll-aware popoversColumn + RowLocalId
handle.fixedChildFixed overlays (ghosts, spans)Column + RowLocalId
handle.staticChildStatic positioned childrenRowLocalId + pixel offset
handle.tooltipTooltipsColumn + RowLocalId

These handles are what your plugin uses to show menus, tooltips, and overlays in response to user interaction.

Fixed Children

Plugins can attach persistent elements to a row (event spans, indicators, ghosts) via fixedChildrenForRow():

async fixedChildrenForRow(
  row: SheetRow.Joined.Client,
  context: FixedChildRowContext,
): Promise<SheetDelegate.FixedChildSpec[]> {
  return [{
    id: "task-progress-bar",
    x: { type: "date-range", startDate, endDate },
    inset: { left: 0, top: 0 },
    widthBehavior: "fill",
    makeElement: () => TaskProgressBar.make(),
  }];
}

Data Loading

Plugins can declare async data dependencies. The sheet calls loadData() before rendering and waits for the result:

async loadData(sheet, row, column) {
  return this.store.fetchForRange(row.id, column.toDateRange());
}

See also