Files
moeka-project/packages/stage-ui
leafyy 52a9f429ed feat(plugin-host): add combined lifecycle controls (#2476)
## Summary

- Add combined `Enable and Load` and `Disable and Unload` controls to
Plugin Host Debug.
- Keep enablement persistence and runtime lifecycle changes in one
sequential store action.
- Add tests for ordering, busy state, and failure handling.
- Localize the new controls and fallback error messages in English and
Simplified Chinese.

## Verification

- `pnpm exec vitest run --config packages/stage-ui/vitest.config.ts
--project node src/stores/devtools/plugin-host-debug.test.ts`
- `pnpm -F @proj-airi/i18n test`
- `pnpm -F @proj-airi/i18n build`
- `pnpm run build:packages`
- `pnpm typecheck`
- `pnpm lint`
- Manually tested the bundled `devtools-sample-plugin` in the Electron
Plugin Host Debug page. Both combined actions updated the persisted
registry and runtime session state without restarting the app.

## Visual changes

| Before | After |
|---|---|
| ![Plugin Host Debug
before](https://github.com/user-attachments/assets/c9b3a6ec-699b-444a-ba01-50bbc2ffa3ad)
| ![Plugin Host Debug
after](https://github.com/user-attachments/assets/889dec79-a157-42a8-98f5-906d2e0b41f3)
|
| Plugin Host Debug | Plugin Host Debug with combined lifecycle controls
|
2026-09-07 19:04:17 +08:00
..
2026-03-12 05:09:32 +08:00
2026-08-26 20:13:10 +08:00
2026-08-26 20:13:10 +08:00
2026-08-26 20:13:10 +08:00

Stage UI

Shared core for stage

Button analytics

Register the shared plugin once in each Vue application:

import { trackButtonPlugin } from '@proj-airi/stage-ui/directives/track-button'

createApp(App)
  .use(trackButtonPlugin)
  .mount('#app')

Buttons that represent a product-analysis click intent can then declare a typed event without wrapping their business handler:

<Button
  v-track-button="{ name: 'update_check_clicked', channel: selectedChannel }"
  @click="checkForUpdates()"
/>

Keep async outcomes, confirmed state changes, impressions, and lifecycle events in their owning business flows instead of attaching them to the initial click.

Histoire (UI storyboard)

https://histoire.dev/

pnpm -F @proj-airi/stage-ui run story:dev

Project structure

  1. If a story is bound to a specific component, it can be placed beside the component in the src folder. e.g., MyComponent.story.vue
  2. If a story is not bound to a specific component, then it should be placed in the stories folder. e.g., MyStory.story.vue