chore(release): v0.20.0
Version bump via changesets.
This commit is contained in:
@@ -1,5 +1,18 @@
|
||||
# @fusion/dashboard
|
||||
|
||||
## 0.20.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ba6666f: Fix Planning Mode modal getting stuck at partial height on mobile. Two issues: (1) `useModalResizePersist` was replaying a desktop-saved pixel height into the inline `style` attribute, overriding the mobile `height: 100dvh` rule and leaving the modal at half-screen even before the keyboard appeared — now skipped on touch devices ≤768px wide. (2) When the iOS keyboard was dismissed, React reconciled the removed CSS custom properties (`--vv-height`, `--keyboard-overlap`, `--vv-offset-top`) by setting them to empty string instead of calling `removeProperty()`. On Safari that left `var(--vv-height, 100dvh)` resolving to empty (the fallback only kicks in when the variable is undefined), collapsing the modal to content height — now driven imperatively via `setProperty`/`removeProperty` on the modal ref.
|
||||
- @fusion/core@0.20.0
|
||||
- @fusion/engine@0.20.0
|
||||
- @fusion-plugin-examples/dependency-graph@0.1.9
|
||||
- @fusion-plugin-examples/droid-runtime@0.1.4
|
||||
- @fusion-plugin-examples/hermes-runtime@0.2.28
|
||||
- @fusion-plugin-examples/openclaw-runtime@0.2.28
|
||||
- @fusion-plugin-examples/paperclip-runtime@0.2.28
|
||||
|
||||
## 0.19.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -76,6 +76,11 @@ const BUNDLED_PLUGINS: BundledPlugin[] = [
|
||||
path: "./plugins/fusion-plugin-droid-runtime",
|
||||
experimental: true,
|
||||
},
|
||||
{
|
||||
id: "fusion-plugin-dependency-graph",
|
||||
name: "Dependency Graph",
|
||||
path: "./plugins/fusion-plugin-dependency-graph",
|
||||
},
|
||||
];
|
||||
|
||||
export const STATE_COLORS: Record<string, string> = {
|
||||
|
||||
@@ -231,6 +231,7 @@ describe("PluginManager", () => {
|
||||
expect(screen.getByText("Paperclip Runtime")).toBeTruthy();
|
||||
expect(screen.getByText("OpenClaw Runtime")).toBeTruthy();
|
||||
expect(screen.getByText("Droid Runtime")).toBeTruthy();
|
||||
expect(screen.getByText("Dependency Graph")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("installs bundled plugins from the bundled plugin section", async () => {
|
||||
@@ -253,6 +254,26 @@ describe("PluginManager", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("installs dependency graph from the bundled plugin section", async () => {
|
||||
render(<PluginManager addToast={addToast} />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchPlugins).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
const graphLabel = await screen.findByText("Dependency Graph");
|
||||
const graphCard = graphLabel.closest(".plugin-bundled-runtime-item");
|
||||
expect(graphCard).toBeTruthy();
|
||||
|
||||
const installButton = within(graphCard as HTMLElement).getByRole("button", { name: /Install Dependency Graph/i });
|
||||
await userEvent.click(installButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(installPlugin).toHaveBeenCalledWith({ path: "./plugins/fusion-plugin-dependency-graph" }, undefined);
|
||||
expect(addToast).toHaveBeenCalledWith("Dependency Graph installed successfully", "success");
|
||||
});
|
||||
});
|
||||
|
||||
it("renders plugin list when plugins are available", async () => {
|
||||
vi.mocked(fetchPlugins).mockResolvedValueOnce(mockPlugins);
|
||||
|
||||
@@ -266,6 +287,7 @@ describe("PluginManager", () => {
|
||||
expect(screen.getByText("v1.0.0")).toBeTruthy();
|
||||
expect(screen.getByText("v2.0.0")).toBeTruthy();
|
||||
expect(screen.getByRole("heading", { name: "Bundled Plugins" })).toBeTruthy();
|
||||
expect(screen.getByText("Dependency Graph")).toBeTruthy();
|
||||
expect(screen.getAllByText("Not installed").length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
@@ -505,32 +527,32 @@ describe("PluginManager", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps bundled plugin manageable after install", async () => {
|
||||
it("shows Manage for bundled dependency graph when already installed", async () => {
|
||||
vi.mocked(fetchPlugins).mockResolvedValueOnce([
|
||||
{
|
||||
...mockPlugins[0],
|
||||
id: "fusion-plugin-hermes-runtime",
|
||||
name: "Hermes Runtime Plugin",
|
||||
id: "fusion-plugin-dependency-graph",
|
||||
name: "Dependency Graph",
|
||||
},
|
||||
]);
|
||||
|
||||
render(<PluginManager addToast={addToast} />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText("Hermes Runtime")).toBeTruthy();
|
||||
expect(screen.getAllByText("Dependency Graph").length).toBeGreaterThanOrEqual(2);
|
||||
});
|
||||
|
||||
const hermesCard = screen.getByText("Hermes Runtime").closest(".plugin-bundled-runtime-item");
|
||||
expect(hermesCard).toBeTruthy();
|
||||
const graphCard = screen.getAllByText("Dependency Graph")[1]?.closest(".plugin-bundled-runtime-item");
|
||||
expect(graphCard).toBeTruthy();
|
||||
|
||||
const manageButton = within(hermesCard as HTMLElement).getByRole("button", { name: /^Manage$/i });
|
||||
const manageButton = within(graphCard as HTMLElement).getByRole("button", { name: /^Manage$/i });
|
||||
expect(manageButton).not.toBeDisabled();
|
||||
expect(within(hermesCard as HTMLElement).getAllByText("Installed").length).toBeGreaterThanOrEqual(1);
|
||||
expect(within(graphCard as HTMLElement).getAllByText("Installed").length).toBeGreaterThanOrEqual(1);
|
||||
|
||||
await userEvent.click(manageButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchPluginSettings).toHaveBeenCalledWith("fusion-plugin-hermes-runtime", undefined);
|
||||
expect(fetchPluginSettings).toHaveBeenCalledWith("fusion-plugin-dependency-graph", undefined);
|
||||
});
|
||||
|
||||
expect(screen.getByTestId("plugin-manager-detail")).toBeTruthy();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fusion/dashboard",
|
||||
"version": "0.19.0",
|
||||
"version": "0.20.0",
|
||||
"license": "MIT",
|
||||
"description": "Fusion dashboard: React UI and HTTP API server for monitoring and controlling the Fusion AI coding agent.",
|
||||
"homepage": "https://github.com/Runfusion/Fusion#readme",
|
||||
|
||||
Reference in New Issue
Block a user