Skip to main content

@datalayer/reactor-manager

The plugins manager lists every plugin on the platform and switches each one on and off while the application runs. It is a plugin, so it appears in its own list — and it never offers to switch itself off, because a manager that could would have no way back.

import { PluginsManagerPlugin } from '@datalayer/reactor-manager';

const reactor = buildReactorFromPlugins([PluginsManagerPlugin, /* … */]);

It contributes to the sidebar slot, so the application decides where the list lives without knowing what is in it.

What it draws, and from where​

Everything comes from the manifest, which is why a plugin that has never been fetched still has a row: displayName, description, emoji/octicon, version, and whether it is enabled. See how a plugin presents itself.

Extending it: ManagerPluginSource​

The manager opens a contribution point for sources of plugins. A plugin that knows about plugins the reactor cannot see contributes a source, and its rows appear inside the one list, in the one shape:

contributes: [
contribution(
ManagerPluginSource,
{
title: 'Backend plugins (Python)',
order: 100,
Component: BackendPluginSource,
},
{ id: 'music-backend-plugins' },
),
],

That is exactly what the music example does for its four Python plugins: the manager cannot know that POST /plugins/{name}/toggle exists on some server, and it does not have to.

PluginList is exported for a source to render its rows with, so a contributed group looks like the manager's own rather than like a second control that happens to sit nearby.

The contribution points as a table: contributionsTablePlugin​

The manager lists plugins; a contributions table lists points — for each contribution point, what the plugins put in it. It is the view a plugin's author reaches for (did my plugin contribute to every point it meant to?) and the one a host shows to explain what an extension adds. It is drawn with Primer's DataTable and, like the rest of the manager, knows no point by name: it reads the platform's describeContributions().

import { buildReactorFromPlugins } from '@datalayer/reactor';
import { ReactorSlot, useReactor } from '@datalayer/reactor/react';
import { CONTRIBUTIONS_TABLE_SLOT, contributionsTablePlugin } from '@datalayer/reactor-manager';

const reactor = buildReactorFromPlugins([
CorePlugin,
AcmePlugin,
contributionsTablePlugin({
points: MY_POINTS, // every one gets a row, empty or not
plugin: '@acme/everything', // only this plugin's contributions
labels: { 'acme.command': 'commands', 'acme.function': 'functions' },
title: 'Contribution points',
subtitle: 'Each point, and what @acme/everything contributes to it.',
}),
]);

// …in the host:
<ReactorSlot slot={CONTRIBUTIONS_TABLE_SLOT} />;
OptionWhat it does
pointsThe points to show, in this order, by id or as the points themselves. Each gets a row, so a point nothing contributed to says none instead of vanishing. Absent, every point that holds something, in the platform's order.
pluginOnly this plugin's contributions; the column is then titled Contributed by that plugin. Absent, every plugin's, each contribution followed by its plugin.
labelsA name for some points, shown beside the id.
titleThe table's title; Contributions by default, with the row count beside it.
subtitleA line under the title.
slotThe component slot it is contributed to; contributions-table (CONTRIBUTIONS_TABLE_SLOT) by default.

It follows the platform's revision, so the table changes as plugins are enabled and disabled. ContributionsTable is the component for a host that places it itself, and contributionsTableRows the pure function that computes its rows, for a test.

Both tables ship in 1.3.4. The Cells examples use them: the command palette page lists the Cells commands with commandsTablePlugin, and the plugin page lists every Cells point with what an example plugin contributes, with contributionsTablePlugin.