@softize/opus 8.7.1 → 8.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -2,6 +2,7 @@ import * as React from "react"
|
|
|
2
2
|
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
|
|
3
3
|
import { DropdownMenu as MenuPrimitive } from "radix-ui"
|
|
4
4
|
|
|
5
|
+
import { useDismissOnIframeFocus } from "../../lib/dismiss-on-iframe.ts"
|
|
5
6
|
import { cn } from '../../lib/cn.ts'
|
|
6
7
|
|
|
7
8
|
function Menu({
|
|
@@ -34,9 +35,13 @@ function MenuContent({
|
|
|
34
35
|
sideOffset = 4,
|
|
35
36
|
...props
|
|
36
37
|
}: React.ComponentProps<typeof MenuPrimitive.Content>) {
|
|
38
|
+
// Mesma razão do Popover: clique dentro de iframe não chega aqui fora.
|
|
39
|
+
const ref = React.useRef<HTMLDivElement>(null)
|
|
40
|
+
useDismissOnIframeFocus(ref)
|
|
37
41
|
return (
|
|
38
42
|
<MenuPrimitive.Portal>
|
|
39
43
|
<MenuPrimitive.Content
|
|
44
|
+
ref={ref}
|
|
40
45
|
data-slot="menu-content"
|
|
41
46
|
sideOffset={sideOffset}
|
|
42
47
|
className={cn(
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
2
|
import { Popover as PopoverPrimitive } from "radix-ui"
|
|
3
3
|
|
|
4
|
+
import { useDismissOnIframeFocus } from "../../lib/dismiss-on-iframe.ts"
|
|
4
5
|
import { cn } from '../../lib/cn.ts'
|
|
5
6
|
|
|
6
7
|
function Popover({
|
|
@@ -21,9 +22,14 @@ function PopoverContent({
|
|
|
21
22
|
sideOffset = 4,
|
|
22
23
|
...props
|
|
23
24
|
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
|
|
25
|
+
// Clique dentro de um iframe não chega no documento de fora — sem isto, o popover fica
|
|
26
|
+
// pendurado sobre o conteúdo. Na cabine, o preview É um iframe.
|
|
27
|
+
const ref = React.useRef<HTMLDivElement>(null)
|
|
28
|
+
useDismissOnIframeFocus(ref)
|
|
24
29
|
return (
|
|
25
30
|
<PopoverPrimitive.Portal>
|
|
26
31
|
<PopoverPrimitive.Content
|
|
32
|
+
ref={ref}
|
|
27
33
|
data-slot="popover-content"
|
|
28
34
|
align={align}
|
|
29
35
|
sideOffset={sideOffset}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Fecha a camada flutuante quando o clique cai DENTRO de um iframe.
|
|
5
|
+
*
|
|
6
|
+
* O navegador entrega o clique ao documento do iframe, e o documento de fora nunca fica
|
|
7
|
+
* sabendo. Como toda dispensa por "clique fora" escuta eventos do documento de fora, o
|
|
8
|
+
* popover/menu simplesmente NÃO fecha — fica pendurado sobre o conteúdo, e a pessoa
|
|
9
|
+
* precisa achar um pedaço de página livre pra clicar.
|
|
10
|
+
*
|
|
11
|
+
* Não é caso de borda pra nós: a cabine embute o preview num iframe, então metade da tela
|
|
12
|
+
* é justamente a área onde clicar não fecha nada.
|
|
13
|
+
*
|
|
14
|
+
* O sinal utilizável é o `blur` da JANELA somado a "quem está com o foco agora é um
|
|
15
|
+
* iframe". Trocar de aba ou de aplicativo também dispara `blur`, mas ali o elemento ativo
|
|
16
|
+
* não é iframe — e fechar o menu de quem só foi ver outra janela seria pior que o defeito.
|
|
17
|
+
*
|
|
18
|
+
* A dispensa sai como um Escape sintético em vez de uma chamada direta: quem renderiza o
|
|
19
|
+
* conteúdo (Popover, Menu) não tem acesso ao estado de aberto — ele é de quem usa. Escape
|
|
20
|
+
* é o canal que a própria biblioteca já escuta pra dispensar, então funciona sem obrigar
|
|
21
|
+
* cada call site a passar um `onClose`.
|
|
22
|
+
*/
|
|
23
|
+
export function useDismissOnIframeFocus(ref: React.RefObject<HTMLElement | null>): void {
|
|
24
|
+
React.useEffect(() => {
|
|
25
|
+
const onBlur = (): void => {
|
|
26
|
+
// `requestAnimationFrame`: no instante do `blur` o `activeElement` ainda pode ser o
|
|
27
|
+
// anterior; o navegador atualiza no tick seguinte.
|
|
28
|
+
requestAnimationFrame(() => {
|
|
29
|
+
if (document.activeElement?.tagName !== 'IFRAME') return
|
|
30
|
+
ref.current?.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
window.addEventListener('blur', onBlur)
|
|
34
|
+
return () => window.removeEventListener('blur', onBlur)
|
|
35
|
+
}, [ref])
|
|
36
|
+
}
|