mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-23 09:07:46 +02:00
PluginSlotMount used to subscribe to inflightImports inside its own
effect to know when to re-render after a plugin module loaded. Under
React StrictMode, usePluginModuleLoader's effect double-invokes: the
first call kicks off the import and sets cancelled=true in its
cleanup, and the second call finds the contributions already
loading so it returns early without arming its own setTick. When the
import finally resolves, no one re-renders the slot, the
missingBehavior placeholder sticks ("Paperclip Triage: Triage"), and
the user has to click-navigate to recover.
Switch to a global pluginKey-keyed listener set that loadPluginModule
notifies from its finally block. Each PluginSlotMount subscribes for
the lifetime of its render and is told once per pluginKey when the
registry has been populated, independent of which effect kicked off
the load.
Also fix two breadcrumb papercuts that showed up in QA:
- titleFromRouteSplat: skip 1-2 char marker segments ("q", "i") and
use the next named segment, so /PAP/triage/q/PRs shows "PRs" in
the breadcrumb instead of "Q".
- buildDocumentTitle: dedupe the trailing "Paperclip" when the
company name itself is "Paperclip" (avoids "Triage • Paperclip •
Paperclip" in the browser tab).
Co-Authored-By: Paperclip <noreply@paperclip.ing>
@paperclipai/ui
Published static assets for the Paperclip board UI.
What gets published
The npm package contains the production build under dist/. It does not ship the UI source tree or workspace-only dependencies.
Storybook
Storybook config, stories, and fixtures live under ui/storybook/.
pnpm --filter @paperclipai/ui storybook
pnpm --filter @paperclipai/ui build-storybook
Typical use
Install the package, then serve or copy the built files from node_modules/@paperclipai/ui/dist.