feat: multi-component-selector (#1728)
<!-- This is an auto-generated description by cubic. --> ## Summary by cubic Adds multi-component selection in the preview and sends all selected components to chat for targeted edits. Updates overlays, UI, and IPC to support arrays, smarter context focusing, and cross-platform path normalization. - **New Features** - Select multiple components in the iframe; selection mode stays active until you deactivate it. - Show a scrollable list of selections with remove buttons and a Clear all; remove from the list or click an overlay in the preview to deselect. Sending clears all overlays. - Separate hover vs selected overlays with labels on hover; overlays persist after deactivation and re-position on layout changes/resizes. - Chat input and streaming now send selectedComponents; server builds per-component snippets and focuses their files in smart context. - **Migration** - Replace selectedComponentPreviewAtom with selectedComponentsPreviewAtom (ComponentSelection[]). - ChatStreamParams now uses selectedComponents; migrate any single-selection usages. - previewIframeRefAtom added for clearing overlays from the parent. <sup>Written for commit da0d64cc9e9f83fbf4b975278f6c869f0d3a8c7d. Summary will update automatically on new commits.</sup> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
committed by
GitHub
parent
c4591996ea
commit
2a7f5a8909
@@ -14,11 +14,11 @@ testSkipIfWindows("select component", async ({ po }) => {
|
||||
.click();
|
||||
|
||||
await po.snapshotPreview();
|
||||
await po.snapshotSelectedComponentDisplay();
|
||||
await po.snapshotSelectedComponentsDisplay();
|
||||
|
||||
await po.sendPrompt("[dump] make it smaller");
|
||||
await po.snapshotPreview();
|
||||
await expect(po.getSelectedComponentDisplay()).not.toBeVisible();
|
||||
await expect(po.getSelectedComponentsDisplay()).not.toBeVisible();
|
||||
|
||||
await po.snapshotServerDump("all-messages");
|
||||
|
||||
@@ -27,6 +27,34 @@ testSkipIfWindows("select component", async ({ po }) => {
|
||||
await po.snapshotServerDump("last-message");
|
||||
});
|
||||
|
||||
testSkipIfWindows("select multiple components", async ({ po }) => {
|
||||
await po.setUp();
|
||||
await po.sendPrompt("tc=basic");
|
||||
await po.clickTogglePreviewPanel();
|
||||
await po.clickPreviewPickElement();
|
||||
|
||||
await po
|
||||
.getPreviewIframeElement()
|
||||
.contentFrame()
|
||||
.getByRole("heading", { name: "Welcome to Your Blank App" })
|
||||
.click();
|
||||
|
||||
await po
|
||||
.getPreviewIframeElement()
|
||||
.contentFrame()
|
||||
.getByText("Made with Dyad")
|
||||
.click();
|
||||
|
||||
await po.snapshotPreview();
|
||||
await po.snapshotSelectedComponentsDisplay();
|
||||
|
||||
await po.sendPrompt("[dump] make both smaller");
|
||||
await po.snapshotPreview();
|
||||
await expect(po.getSelectedComponentsDisplay()).not.toBeVisible();
|
||||
|
||||
await po.snapshotServerDump("last-message");
|
||||
});
|
||||
|
||||
testSkipIfWindows("deselect component", async ({ po }) => {
|
||||
await po.setUp();
|
||||
await po.sendPrompt("tc=basic");
|
||||
@@ -40,19 +68,50 @@ testSkipIfWindows("deselect component", async ({ po }) => {
|
||||
.click();
|
||||
|
||||
await po.snapshotPreview();
|
||||
await po.snapshotSelectedComponentDisplay();
|
||||
await po.snapshotSelectedComponentsDisplay();
|
||||
|
||||
// Deselect the component and make sure the state has reverted
|
||||
await po.clickDeselectComponent();
|
||||
|
||||
await po.snapshotPreview();
|
||||
await expect(po.getSelectedComponentDisplay()).not.toBeVisible();
|
||||
await expect(po.getSelectedComponentsDisplay()).not.toBeVisible();
|
||||
|
||||
// Send one more prompt to make sure it's a normal message.
|
||||
await po.sendPrompt("[dump] tc=basic");
|
||||
await po.snapshotServerDump("last-message");
|
||||
});
|
||||
|
||||
testSkipIfWindows(
|
||||
"deselect individual component from multiple",
|
||||
async ({ po }) => {
|
||||
await po.setUp();
|
||||
await po.sendPrompt("tc=basic");
|
||||
await po.clickTogglePreviewPanel();
|
||||
await po.clickPreviewPickElement();
|
||||
|
||||
await po
|
||||
.getPreviewIframeElement()
|
||||
.contentFrame()
|
||||
.getByRole("heading", { name: "Welcome to Your Blank App" })
|
||||
.click();
|
||||
|
||||
await po
|
||||
.getPreviewIframeElement()
|
||||
.contentFrame()
|
||||
.getByText("Made with Dyad")
|
||||
.click();
|
||||
|
||||
await po.snapshotSelectedComponentsDisplay();
|
||||
|
||||
await po.clickDeselectComponent({ index: 0 });
|
||||
|
||||
await po.snapshotPreview();
|
||||
await po.snapshotSelectedComponentsDisplay();
|
||||
|
||||
await expect(po.getSelectedComponentsDisplay()).toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
testSkipIfWindows("upgrade app to select component", async ({ po }) => {
|
||||
await po.setUp();
|
||||
await po.importApp("select-component");
|
||||
@@ -94,7 +153,7 @@ testSkipIfWindows("select component next.js", async ({ po }) => {
|
||||
.click();
|
||||
|
||||
await po.snapshotPreview();
|
||||
await po.snapshotSelectedComponentDisplay();
|
||||
await po.snapshotSelectedComponentsDisplay();
|
||||
|
||||
await po.sendPrompt("[dump] make it smaller");
|
||||
await po.snapshotPreview();
|
||||
|
||||
Reference in New Issue
Block a user