fix(ui): сохранить контекст и фокус контейнеров

This commit is contained in:
Denozordec committed 2026-10-01 11:13:29 +07:00
1 parent 3ceb8c038c
commit 71cc6fa3a7
12 files changed
+128 -27

No files matched your search

+22 -19
View File
@@ -1,6 +1,6 @@
"use client"
import { useEffect, useMemo, useState, type ReactNode } from "react"
import { useMemo, useState, type ReactNode } from "react"
import {
Alert,
AlertDescription,
@@ -29,6 +29,7 @@ import {
TriangleAlertIcon,
} from "lucide-react"
import { cn } from "@/lib/utils"
import { toast } from "sonner"
export type CodeExportFormat = {
id: string
@@ -88,6 +89,7 @@ export interface CodeExportSheetProps {
liveLabel?: string
className?: string
/** Extra content under format tabs (e.g. meta strip) */
returnFocus?: () => HTMLElement | null
beforeCode?: ReactNode
}
@@ -108,20 +110,18 @@ function CodeExportSheet({
liveLabel = "С роутера",
className,
beforeCode,
returnFocus,
}: CodeExportSheetProps) {
const firstId = formats[0]?.id ?? "default"
const [tab, setTab] = useState(initialFormatId ?? firstId)
const [copied, setCopied] = useState(false)
useEffect(() => {
if (!open) return
setTab(
initialFormatId && formats.some((f) => f.id === initialFormatId)
? initialFormatId
: firstId,
)
setCopied(false)
}, [open, initialFormatId, firstId, formats])
const initialTab = initialFormatId && formats.some(format => format.id === initialFormatId) ? initialFormatId : firstId
const resetKey = JSON.stringify([open, initialTab])
const [previousKey, setPreviousKey] = useState(resetKey)
const [tab, setTab] = useState(initialTab)
const [copiedCode, setCopiedCode] = useState<string | null>(null)
if (previousKey !== resetKey) {
setPreviousKey(resetKey)
if (open) { setTab(initialTab); setCopiedCode(null) }
}
const active = useMemo(
() => formats.find((f) => f.id === tab) ?? formats[0],
@@ -129,23 +129,26 @@ function CodeExportSheet({
)
const code = active?.code ?? ""
const copied = !!code && copiedCode === code
const emptyMessage = active?.emptyMessage
const filename = active?.filename ?? "export.txt"
const canCopy = Boolean(code) && !emptyMessage
const isLive = Boolean(active?.isLive)
const showTabs = formats.length > 1
function handleCopy() {
async function handleCopy() {
if (!canCopy) return
void navigator.clipboard.writeText(code).then(() => {
setCopied(true)
setTimeout(() => setCopied(false), 1800)
})
setCopiedCode(null)
try {
await navigator.clipboard.writeText(code)
setCopiedCode(code)
setTimeout(() => setCopiedCode(null), 1800)
} catch { setCopiedCode(null); toast.error("Не удалось скопировать. Повторите действие или скачайте файл.") }
}
return (
<Sheet open={open} onOpenChange={(v) => { if (!v) onClose() }}>
<SheetContent
<SheetContent finalFocus={returnFocus}
className={cn(
"flex w-full flex-col gap-0 overflow-hidden p-0 sm:max-w-xl",
className,