thymer docs
Documentation/Plugins/Collection plugins

Collection plugins

Every collection is defined by a JSON configuration plus optional JavaScript. Collection Settings… → Edit Code opens both. The settings dialog edits the same configuration with forms, so you can mix: define fields and views in the dialog, add behavior in code.

Configuration

A field has a stable id, a label, a type and a few options:

{
  "id": "hours",
  "label": "Hours",
  "type": "number",
  "icon": "ti-clock",
  "many": false,
  "read_only": false,
  "active": true
}

Views have an id, a label, a type, the field_ids they show, and their sort, grouping and query. Keep ids stable when you rename things: values and views refer to fields by id. A managed section can mark fields, views or sidebar settings as controlled by the plugin, which disables them in the settings dialog.

Formulas and property behavior

this.properties.formula(name, fn) computes a property; see Formulas. render() draws a property your own way, customSort() sorts it your own way, and the choice hooks fill a Choice property’s options from code.

Custom views

Add a view with "type": "custom" to the configuration, then register its behavior:

class Plugin extends CollectionPlugin {
  onLoad() {
    this.views.register("Timeline", (ctx) => {
      let nodes = new Map();
      return {
        onLoad() { /* build the view in ctx.element */ },
        onRefresh({records, invalidatedGuids}) { /* update changed records */ },
        onDestroy() { nodes.clear(); },
      };
    });
  }
}

ctx gives you the view’s element, the visible properties, the records and navigation helpers. Keep the view’s state inside the registration function: two panels can show the same view at once. onRefresh tells you which records changed; null means all of them, an empty set none. Update what changed instead of rebuilding everything.

Built-in views have hooks too, such as afterRenderBoardCard() for adding buttons to board cards.

Commands and interface

Extension API
Command palette command this.ui.addCommandPaletteCommand()
Status bar item this.ui.addStatusBarItem()
Notification this.ui.addToaster()
Custom panel this.ui.registerCustomPanelType()
Sidebar widget this.ui.addSidebarWidget()
Button on this collection this.addCollectionNavigationButton()

Use the UI API’s buttons, icons and panels so your plugin looks like Thymer in every theme. Release timers and listeners in onUnload(); with hot reload, a plugin is unloaded and loaded many times.