fix(ai): keep assistant open for portaled controls (#236)
This commit is contained in:
1 parent
9c4d6eea54
commit
ee00a98be7
2 files changed
+19
-8
No files matched your search
@@ -49,6 +49,13 @@ import { cn } from "@/lib/utils";
|
||||
|
||||
const FREEFORM_VALUE = "custom";
|
||||
const PROMPT_VALUE_PREFIX = "prompt:";
|
||||
const AI_ASSISTANT_LAYER_SELECTOR = '[data-edgeever-ai-assistant-layer="true"]';
|
||||
|
||||
export const isAiAssistantPointerTarget = (target: EventTarget | null, panel: HTMLElement | null) => {
|
||||
if (!(target instanceof Node)) return false;
|
||||
if (panel?.contains(target)) return true;
|
||||
return target instanceof Element && Boolean(target.closest(AI_ASSISTANT_LAYER_SELECTOR));
|
||||
};
|
||||
|
||||
const promptSelectValue = (id: string) => `${PROMPT_VALUE_PREFIX}${id}`;
|
||||
|
||||
@@ -182,9 +189,7 @@ export const AiAssistantDialog = ({
|
||||
if (!open) return;
|
||||
const frame = window.requestAnimationFrame(() => instructionRef.current?.focus());
|
||||
const handlePointerDown = (event: PointerEvent) => {
|
||||
const target = event.target;
|
||||
if (!(target instanceof Node) || panelRef.current?.contains(target)) return;
|
||||
if (target instanceof Element && target.closest('[data-radix-popper-content-wrapper], [role="dialog"]')) return;
|
||||
if (isAiAssistantPointerTarget(event.target, panelRef.current)) return;
|
||||
onOpenChange(false);
|
||||
};
|
||||
window.addEventListener("pointerdown", handlePointerDown);
|
||||
@@ -432,7 +437,7 @@ export const AiAssistantDialog = ({
|
||||
<SelectTrigger aria-label={t("aiAssistant.actionLabel")} className="h-10 w-full min-w-0 sm:col-span-2">
|
||||
<SelectValue placeholder={t("aiAssistant.actionLabel")} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectContent data-edgeever-ai-assistant-layer="true">
|
||||
{prompts.length ? (
|
||||
<SelectGroup>
|
||||
<SelectLabel>{t("aiAssistant.myPrompts")}</SelectLabel>
|
||||
@@ -480,7 +485,7 @@ export const AiAssistantDialog = ({
|
||||
<SelectTrigger aria-label={t("aiAssistant.targetLanguage")} className="h-10">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectContent data-edgeever-ai-assistant-layer="true">
|
||||
{targetLanguages.map((language) => (
|
||||
<SelectItem key={language} value={language}>{t(`aiAssistant.targetLanguages.${language}`)}</SelectItem>
|
||||
))}
|
||||
@@ -496,7 +501,7 @@ export const AiAssistantDialog = ({
|
||||
clearResult();
|
||||
}}>
|
||||
<SelectTrigger aria-label={t("aiAssistant.tone")} className="h-10"><SelectValue /></SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectContent data-edgeever-ai-assistant-layer="true">
|
||||
{aiTones.map((item) => <SelectItem key={item} value={item}>{t(`aiAssistant.tones.${item}`)}</SelectItem>)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
@@ -659,7 +664,7 @@ export const AiAssistantDialog = ({
|
||||
createPromptMutation.reset();
|
||||
}
|
||||
}}>
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogContent className="sm:max-w-md" data-edgeever-ai-assistant-layer="true">
|
||||
<form
|
||||
className="grid gap-4"
|
||||
onSubmit={(event: FormEvent) => {
|
||||
|
||||
@@ -174,7 +174,13 @@ test.describe("AI custom prompts", () => {
|
||||
await slashMenu.getByText("用 AI 处理", { exact: true }).click();
|
||||
await expect(slashMenu).toBeHidden();
|
||||
await expect(editor).not.toContainText("/");
|
||||
await expect(page.getByRole("dialog", { name: "AI 笔记助手" })).toBeVisible();
|
||||
const assistant = page.getByRole("dialog", { name: "AI 笔记助手" });
|
||||
await expect(assistant).toBeVisible();
|
||||
await assistant.getByRole("combobox", { name: "处理方式" }).click();
|
||||
await expect(assistant).toBeVisible();
|
||||
await expect(page.getByRole("option", { name: "自定义指令", exact: true })).toBeVisible();
|
||||
await page.getByRole("option", { name: "自定义指令", exact: true }).click();
|
||||
await expect(assistant).toBeVisible();
|
||||
});
|
||||
|
||||
test("sends temporary files with one AI request", async ({ page }) => {
|
||||
|
||||
Reference in new issue
Block a user