Selections and the properties panel
Selections and the properties panel
Section titled “Selections and the properties panel”The shell owns one properties panel on the right. Plugins never declare
it: they publish what the user selected, and contribute forms per
selection kind. Several plugins may contribute to the same kind (a plugin
depending on Notes can add a “Planning” section to tasks); each form becomes a
collapsible section, ordered by order.
1. Publish the selection (one per work-area tab; the panel follows the active tab, a closed tab loses its selection):
ctx.registerHandler("my-plugin/item.select", ({ payload }) => { // Table: { rowId, rowIds }, graph: { nodeId, nodeIds } / { edgeId, edgeIds }. const ids = payload.rowIds ?? payload.nodeIds ?? []; ctx.selection.set(payload, ids.length ? { kind: "my-plugin:item", ids, context: { docId: payload.docId }, // merged into every commit payload } : null);});// Deleted entities leave every selection:ctx.selection.prune("my-plugin:item", removedIds);A compound selection publishes several entries at once, e.g. an edge and the
flow it represents: ctx.selection.set(payload, [{ kind: "graph:edge", ids }, { kind: "my-plugin:flow", ids: [flowId], context }]). The properties panel
renders the forms of every entry as separate sections; each section reads and
commits only its own entry’s ids, kind and context. get / current
return the first entry, getAll(scope) / currentAll every entry.
ctx.selection.get(viewContext) gives the selection of a view’s tab, so the
view can highlight it: tables take activeIds, graphs selectedIds.
Tables report Ctrl/Cmd-click (toggle), Shift-click (range) and Ctrl+A in
rowIds; graphs report Ctrl/Cmd-tap and Shift-drag boxes in nodeIds /
edgeIds. Single-item payload fields (rowId, nodeId, edgeId) remain.
2. Contribute a form in ui.json (or ctx.ui.registerPropertyForm):
"propertyForms": [{ "id": "task", "selection": "task", // bare name => "<pluginId>:task" "title": "panel.task", "titleMany": "panel.taskMany", "order": 10, "values": { "ref": "selectedTasks" }, "event": "notes-tsx/task.property.set", "fields": [ { "key": "name", "type": "text", "label": "tasks.name", "multi": false }, { "key": "color", "type": "color", "label": "tasks.color" } ]}]valuesis evaluated with{ selection: { kind, ids, context }, ...context }and returns one record per selected id (or a single record).- With several records, a field showing the same value everywhere displays it;
a differing one shows Multiple values until the user clicks to set them
all.
multi: falsekeeps a field out of bulk editing. - A commit emits
eventwith{ ...context, key, value, ids, kind, context }. Apply every id in that one handler: it is one transaction, so one undo step. Committing an unchanged value emits nothing. panel.form/panel.formsstill work for plugin-owned panels, but new plugins should usepropertyForms.
Columns and fields that depend on the document
Section titled “Columns and fields that depend on the document”The columns of a table and the fields of a propertyForms entry are a fixed
list, or a value selector when they depend on the view:
{ "id": "tasks", "type": "table", "config": { "rows": { "ref": "taskRows" }, "columns": { "ref": "taskColumns" } } }- Register the source under
values. It is evaluated with the placement context, asrowsis; forfields, with the selection, asvaluesis. - It returns the same declarations as a fixed list: titles and labels are i18n
keys. An entry with no
keyortypeis left out. - Return the same array while nothing changed: the table reads the source on every render.
A table of sub-items in a form
Section titled “A table of sub-items in a form”A form field of type table embeds a table; its config is a whole table
declaration (rows, columns, create / commit / delete events). Its rows
binding receives the form context (the selection, docId…), and every event
carries that context too, so the handler finds the parent in
context.selection.ids[0]. With several items selected the field shows a hint
instead of the table.
{ "key": "subtasks", "type": "table", "label": "tasks.subtasks", "multi": false, "config": { "rows": { "ref": "subtaskRows" }, "creatable": true, "deletable": true, "createEvent": "notes-tsx/subtask.add", "commitEvent": "notes-tsx/subtask.update", "deleteEvent": "notes-tsx/subtask.remove", "columns": [{ "key": "done", "type": "boolean", "title": "tasks.done", "editable": true }, { "key": "name", "type": "text", "title": "tasks.name", "editable": true }] } }Documentation under CC BY 4.0 · © SCFlow contributors ·Back to supplychainflow.org