Thank you for being patient! We're working hard on resolving the issue
Subcolumn plugins render content within a parent plugin's grid. A calendar-list plugin renders events inside a calendar row. A task-list plugin could render tasks in the same grid.
The parent plugin (e.g., calendar) discovers its children from the row
tree and calls each child's subcolumnProvider to get rendering info.
The child decides what to render. The parent decides where.
CalendarSheetPlugin.bindCell()
→ row.children() // discover child rows
→ childPlugin.subcolumnProvider // ask each child for rendering info
.subcolumnFromRow(sheet, childRow)
→ CalendarDaysRow renders each subcolumn // parent positions child content
Add a subcolumnProvider to your plugin. The provider returns a
CalendarSubcolumn that tells the parent how to render your data:
export class TaskListPlugin implements RenderPlugin<HTMLElement, HTMLElement> {
readonly id = "task-list";
readonly icon = taskIconTemplate;
subcolumnProvider: CalendarSubcolumn.Provider<TaskItem> = {
subcolumnFromRow(
sheet: SheetViewModel,
row: SheetRow.Joined.Client,
parentRow: SheetRow.Joined.Client,
): CalendarSubcolumn<TaskItem> {
return {
rowId: RowId.fromLocalId(row.id),
renderer: "cells",
width: null, // use parent's default column width
events(range: DateTime.Range<Utc>): TaskItem[] {
// Return items visible in this time range
return taskStore.getTasksInRange(row.id, range);
},
gestureItem(item: TaskItem): Option<GestureItem> {
// Wrap item for the gesture system
return new TaskGestureItem(item);
},
bindCell(
$cell: CalendarColumnCell.Basic,
item: TaskItem,
context: CalendarSubcolumn.CellBindContext,
): void {
// Render one item in a calendar cell
$cell.style.backgroundColor = item.color;
$cell.textContent = item.title;
},
};
},
};
// ... standard RenderPlugin methods for standalone rendering ...
}
Subcolumns declare their renderer type:
| Type | Use when | Example |
|---|---|---|
"cells" | Items have a start time and duration within a day | Timed events, tasks |
"spans" | Items span multiple days as horizontal bars | Multi-day events |
// Span-based subcolumn
{
renderer: "spans",
makeSpans(windowed, tzr): Promise<Span[]> {
return [{
id: "task-1",
dateRange: new NaiveDate.Range(start, end),
label: "Sprint review",
color: "var(--blue)",
}];
},
makeLayout(): HTMLElement {
return SpanLayout.make();
},
}
If your subcolumn has items that should appear in the all-day row,
implement fullDayEventsFromRow:
subcolumnProvider: CalendarSubcolumn.Provider<TaskItem, FullDayTaskItem> = {
subcolumnFromRow(sheet, row, parentRow) { /* ... */ },
fullDayEventsFromRow(row, range: NaiveDate.Range): FullDayTaskItem[] {
return taskStore.getFullDayTasks(row.id, range);
},
};
The parent's all-day plugin aggregates full-day items from all child subcolumns.
The parent calls row.children() on its own row to get child rows, then
looks up each child's plugin:
// Inside CalendarSheetPlugin.getSubcolumns()
for (const child of row.children()) {
const childPlugin = pluginManager.getPlugin(child.type);
const subcolumn = childPlugin.subcolumnProvider?.subcolumnFromRow(sheet, child, row);
if (subcolumn) subcolumns.push(subcolumn);
}
Your plugin is discovered automatically — no registration beyond the
standard pluginManager.register().