feat(plugins): accept inline SVG and component icons

Every contribution `icon` now takes a Lucide name, `{ svg }`, or a
component. Attachment sources take only the first two because composer
drafts persist the source icon.

The daemon's provider-icon check and the app's inline-SVG check are the
same function in the shared SDK root, so a plugin sees the same reasons
in both places. The app parses each icon once at registration and fails
the plugin with that reason. Rendering goes through one module that
turns any form into a component, so surfaces never branch on the form.
This commit is contained in:
Mohamed Boudra
2026-10-19 07:51:46 +02:00
parent d61dcaf1df
commit b29bd98b5f
41 changed files with 826 additions and 237 deletions
@@ -0,0 +1,5 @@
/** Inline SVG icon. `currentColor` follows the surface's icon color. */
export const counterIcon = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="3" width="18" height="18" rx="4" />
<path d="M7.5 8v8M10.5 8v8M13.5 8v8M16.5 8v8M6 15l12-6" />
</svg>`;
@@ -1,11 +1,12 @@
import type { PluginClientContext } from "@getpaseo/plugin/client";
import { counterIcon } from "./client/icons";
import { contributeClient, ExamplePanel } from "./client/main";
export default function contribute(client: PluginClientContext) {
client.addWorkspacePanel({
id: "counter",
title: "Plugin counter",
icon: "Blocks",
icon: { svg: counterIcon },
context: "workspace",
locations: ["workspace", "explorer"],
Component: ExamplePanel,