Aller au contenu

Declarative shape palettes

panel.palette groups vector shape templates into independently collapsible sections. It is exclusive with tree, list, graph, form, forms, value and custom components; an optional panel toolbar is still allowed. PaletteDefinition, PaletteSection and PaletteItem are exported from @app/kernel/plugin-api.

{
"id": "shapes", "surface": "leftSidebar", "title": "palette.title",
"palette": {
"columns": 3,
"selectedIds": { "ref": "selectedShapeIds" },
"emptyText": "palette.empty",
"sections": [{
"id": "basic", "title": "palette.basic",
"items": { "ref": "basicShapes" },
"transfer": { "export": { "kind": "my-plugin/shape" } },
"selectEvent": "my-plugin/shape.select",
"addEvent": "my-plugin/shape.add",
"addTitle": "palette.add",
"defaultCollapsed": false
}]
}
}

Register basicShapes through ctx.ui.define({ values: { basicShapes } }) as a ValueSource<PaletteItem[]>, or read the raw item array with { "from": "slice", "path": "shapes" }. Foreign value refs are supported. Each item has id, label, optional shape, CSS color, icon, description and custom data. Section titles and addTitle are plugin i18n keys. Item labels and descriptions are translated by default; set translate: false on a section to display data-provided names literally (without namespacing or translation). Shapes and outline/silhouette/URL icons use the graph contracts. columns is 2 (default) or 3; className applies to the scrolling palette.

Reactive sections. "sections": { "ref": "paletteSections" } (or a slice/context selector) replaces the array with a ValueSource<PaletteSection[]> that the panel re-reads whenever it notifies. It yields runtime section contracts, not manifest fragments: each section carries items as an array or an actual ValueSource<PaletteItem[]> (no nested ref selectors), plus the usual transfer, defaultCollapsed, selectEvent, addEvent, addTitle and translate. Runtime titles, addTitle and item texts are used as given: pass ctx.i18n.key(...) keys, or set translate: false to show the title and item texts literally. Keep section ids stable: the collapsed state is kept per id.

Filters. palette.filters renders compact wrapping checkbox chips under the panel header and above the first section:

"filters": {
"options": [{ "id": "energy", "label": "Energy", "color": "#f59e0b" }],
"selectedIds": { "ref": "activeFlowDomains" },
"changeEvent": "my-plugin/palette.filter",
"mode": "multiple"
}

options may be a static array or a value selector for dynamic options. Labels are displayed literally. Filters are controlled: a click emits { selectedIds, filterId, checked, context }; the owner stores selectedIds, and its section items sources return the filtered items. mode: "single" replaces the active option, and clicking the active option clears it. Without changeEvent, options render disabled. Malformed runtime IDs/options are ignored. Types: PaletteFilters, PaletteFilterOption.

A plain pointer drag carries one TransferItem using the section’s exact export kind, item id, label, source plugin id and data (custom fields plus label, shape, color, icon and description). The graph must declare that kind in config.transfer.accept and a dropEvent; its owning plugin creates the node from payload.items[0].data at payload.position. The shell never creates or persists domain objects.

Optional section selectEvent receives { id, data, sectionId, context } on a click/release with less than 5 pixels of movement, or keyboard activation; dragging and cancelled gestures never select. data is the card’s custom data, not the expanded transfer template. Panel palette.selectedIds is an optional value source (the same selectors as graphs) containing the IDs to highlight; the owner updates it. Optional addEvent shows a small plus next to the count and receives { sectionId, context }. It opens a folded section and leaves an open section open; it does not trigger the section toggle. addTitle overrides its translated tooltip. context is the same placement context used when reading items/selected IDs and carrying the transfer source, including the panel’s pluginId.

The palette context also carries selectionScope (panel:<pluginId>.<panelId>). A plugin can publish the palette selection there — ctx.selection.set(payload.context.selectionScope, { kind, ids, context: { docId } }) from its selectEvent / addEvent handlers — and the shell’s properties panel follows it, even when no work-area view is open. The current selection is always the most recently published source: clicking a palette card shows its properties, clicking in a table or graph (or switching tabs) brings that view’s selection back. Scopes of other tabs never leak into the current selection, and the scope of a closed tab disappears. The owning plugin stays responsible for clearing a panel selection whose document closes (ctx.selection.set(scope, null)) and for pruning deleted entities (ctx.selection.prune(kind, ids)). Bind the panel’s palette.selectedIds to the same scope so the selected cards stay highlighted.

Documentation sous licence CC BY 4.0 · © les contributeurs de SCFlow ·Retour à supplychainflow.org