@greatapps/common 1.1.769 → 1.1.771
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/dist/components/account/AccountModals.mjs +6 -3
- package/dist/components/account/AccountModals.mjs.map +1 -1
- package/dist/components/account/sections/ChangeEmailModal.mjs +1 -2
- package/dist/components/account/sections/ChangeEmailModal.mjs.map +1 -1
- package/dist/components/account/sections/ChangePhoneModal.mjs +1 -2
- package/dist/components/account/sections/ChangePhoneModal.mjs.map +1 -1
- package/dist/components/account/sections/MyProfileSection.mjs +5 -2
- package/dist/components/account/sections/MyProfileSection.mjs.map +1 -1
- package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
- package/dist/components/modals/AccountFrozenModal.mjs +1 -1
- package/dist/components/modals/AccountFrozenModal.mjs.map +1 -1
- package/dist/components/modals/promo/AiCreditsOfferModal/AiCreditsOfferModal.mjs +3 -2
- package/dist/components/modals/promo/AiCreditsOfferModal/AiCreditsOfferModal.mjs.map +1 -1
- package/dist/components/modals/promo/AiCreditsOfferModal/components/LoseOfferDialog.mjs +2 -2
- package/dist/components/modals/promo/AiCreditsOfferModal/components/LoseOfferDialog.mjs.map +1 -1
- package/dist/components/modals/promo/AiCreditsOfferModal/components/OfferPaymentField.mjs +1 -1
- package/dist/components/modals/promo/AiCreditsOfferModal/components/OfferPaymentField.mjs.map +1 -1
- package/dist/components/ui/form/PhoneInput.mjs +1 -1
- package/dist/components/ui/form/PhoneInput.mjs.map +1 -1
- package/dist/components/ui/form/Select.mjs +4 -1
- package/dist/components/ui/form/Select.mjs.map +1 -1
- package/dist/components/ui/overlay/Dialog.mjs +1 -12
- package/dist/components/ui/overlay/Dialog.mjs.map +1 -1
- package/dist/components/ui/overlay/Popover.mjs +4 -1
- package/dist/components/ui/overlay/Popover.mjs.map +1 -1
- package/dist/components/ui/overlay/Sheet.mjs +9 -3
- package/dist/components/ui/overlay/Sheet.mjs.map +1 -1
- package/dist/components/ui/overlay/Tooltip.mjs +4 -1
- package/dist/components/ui/overlay/Tooltip.mjs.map +1 -1
- package/dist/components/ui/overlay/layers.mjs +35 -0
- package/dist/components/ui/overlay/layers.mjs.map +1 -0
- package/dist/components/widgets/ImageUpload/ImageCropModal.mjs +1 -2
- package/dist/components/widgets/ImageUpload/ImageCropModal.mjs.map +1 -1
- package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs +2 -2
- package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs.map +1 -1
- package/dist/components/widgets/ImageUpload/ImageUpload.mjs +4 -2
- package/dist/components/widgets/ImageUpload/ImageUpload.mjs.map +1 -1
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/account/AccountModals.tsx +9 -3
- package/src/components/account/sections/ChangeEmailModal.tsx +1 -2
- package/src/components/account/sections/ChangePhoneModal.tsx +1 -2
- package/src/components/account/sections/MyProfileSection.tsx +6 -2
- package/src/components/layouts/UsersSelectorPopover.tsx +5 -0
- package/src/components/modals/AccountFrozenModal.tsx +1 -1
- package/src/components/modals/promo/AiCreditsOfferModal/AiCreditsOfferModal.tsx +12 -8
- package/src/components/modals/promo/AiCreditsOfferModal/components/LoseOfferDialog.tsx +2 -2
- package/src/components/modals/promo/AiCreditsOfferModal/components/OfferPaymentField.tsx +1 -3
- package/src/components/ui/form/PhoneInput.tsx +1 -1
- package/src/components/ui/form/Select.tsx +5 -1
- package/src/components/ui/overlay/Dialog.tsx +4 -16
- package/src/components/ui/overlay/Popover.tsx +5 -1
- package/src/components/ui/overlay/Sheet.tsx +17 -3
- package/src/components/ui/overlay/Tooltip.tsx +6 -1
- package/src/components/ui/overlay/layers.tsx +95 -0
- package/src/components/widgets/ImageUpload/ImageCropModal.tsx +2 -3
- package/src/components/widgets/ImageUpload/ImageTooSmallModal.tsx +2 -2
- package/src/components/widgets/ImageUpload/ImageUpload.tsx +15 -11
- package/src/index.ts +1 -0
|
@@ -26,6 +26,7 @@ import { readOfferStageCookie, writeOfferStageCookie } from '../../../../modules
|
|
|
26
26
|
import { useAiCreditsOfferModal } from '../../../../store/useAiCreditsOfferModal';
|
|
27
27
|
import { useModalManager } from '../../../../store/useModalManager';
|
|
28
28
|
import { LoseOfferDialog } from './components/LoseOfferDialog';
|
|
29
|
+
import { DialogLayer } from '../../../ui/overlay/layers';
|
|
29
30
|
import { OfferIllustration } from './components/OfferIllustration';
|
|
30
31
|
import { OfferPaymentField } from './components/OfferPaymentField';
|
|
31
32
|
|
|
@@ -388,14 +389,17 @@ export default function AiCreditsOfferModal() {
|
|
|
388
389
|
</DialogContent>
|
|
389
390
|
</Dialog>
|
|
390
391
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
392
|
+
{/* Irmao do `Dialog` acima, entao nasceria na mesma faixa de z. */}
|
|
393
|
+
<DialogLayer>
|
|
394
|
+
<LoseOfferDialog
|
|
395
|
+
open={confirmingExit}
|
|
396
|
+
discountLabel={discountLabel}
|
|
397
|
+
creditsLabel={creditsLabel}
|
|
398
|
+
fullPriceLabel={fullPrice != null ? formatCurrencyNumber(fullPrice) : ''}
|
|
399
|
+
onKeep={() => setConfirmingExit(false)}
|
|
400
|
+
onLose={dismiss}
|
|
401
|
+
/>
|
|
402
|
+
</DialogLayer>
|
|
399
403
|
</>
|
|
400
404
|
);
|
|
401
405
|
}
|
|
@@ -52,8 +52,8 @@ export function LoseOfferDialog({
|
|
|
52
52
|
<DialogContent
|
|
53
53
|
showCloseButton={false}
|
|
54
54
|
onOpenAutoFocus={(event) => event.preventDefault()}
|
|
55
|
-
overlayClassName="
|
|
56
|
-
className="
|
|
55
|
+
overlayClassName="bg-black/40"
|
|
56
|
+
className="flex flex-col gap-0 p-0 max-[440px]:w-[calc(100%-32px)] md:w-[420px]! lg:w-[420px]! max-w-[420px]! data-[state=open]:animate-[gp-offer-confirm-in_260ms_cubic-bezier(0.16,1,0.3,1)]"
|
|
57
57
|
>
|
|
58
58
|
<DialogHeader className="gap-3 p-5 text-left">
|
|
59
59
|
<div className="flex w-fit items-center justify-center rounded-lg bg-red-50 p-2.5">
|
|
@@ -56,8 +56,6 @@ export function OfferPaymentField({ cardId, onCardAdded }: OfferPaymentFieldProp
|
|
|
56
56
|
|
|
57
57
|
<div className="flex shrink-0 items-center gap-2">
|
|
58
58
|
<CardBrandIcon brand={card.brand} />
|
|
59
|
-
{/* `z-[1002]`: o tooltip nasce num portal e precisa passar por cima do
|
|
60
|
-
`DialogContent` (z-1001), senão fica escondido atrás do modal. */}
|
|
61
59
|
<Tooltip>
|
|
62
60
|
<TooltipTrigger asChild>
|
|
63
61
|
<button
|
|
@@ -69,7 +67,7 @@ export function OfferPaymentField({ cardId, onCardAdded }: OfferPaymentFieldProp
|
|
|
69
67
|
<IconPencil size={18} />
|
|
70
68
|
</button>
|
|
71
69
|
</TooltipTrigger>
|
|
72
|
-
<TooltipContent side="top" sideOffset={6}
|
|
70
|
+
<TooltipContent side="top" sideOffset={6}>
|
|
73
71
|
{translate('common.promo.aiCreditsOffer.editPayment')}
|
|
74
72
|
</TooltipContent>
|
|
75
73
|
</Tooltip>
|
|
@@ -144,7 +144,7 @@ export default function PhoneInput({
|
|
|
144
144
|
<IconChevronDown size={14} className={cn("text-zinc-500 transition-transform duration-200", open && "rotate-180")} />
|
|
145
145
|
</button>
|
|
146
146
|
</PopoverTrigger>
|
|
147
|
-
<PopoverContent className="w-72 p-0
|
|
147
|
+
<PopoverContent className="w-72 p-0" align="start" side="top">
|
|
148
148
|
<div className="flex items-center gap-2 p-2 border-b border-zinc-100">
|
|
149
149
|
<IconSearch size={14} className="text-zinc-400 shrink-0" />
|
|
150
150
|
<input
|
|
@@ -4,6 +4,7 @@ import * as React from "react";
|
|
|
4
4
|
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
5
5
|
import { IconCheck, IconChevronDown, IconChevronUp } from '@tabler/icons-react';
|
|
6
6
|
import { cn } from "../../../infra/utils/clsx";
|
|
7
|
+
import { useDialogLayer } from "../overlay/layers";
|
|
7
8
|
|
|
8
9
|
function Select({
|
|
9
10
|
...props
|
|
@@ -68,12 +69,15 @@ function SelectContent({
|
|
|
68
69
|
align = "center",
|
|
69
70
|
...props
|
|
70
71
|
}: React.ComponentProps<typeof SelectPrimitive.Content>) {
|
|
72
|
+
// Portaliza para o body, entao disputa z com o conteudo do modal que o abriu.
|
|
73
|
+
const layer = useDialogLayer();
|
|
71
74
|
return (
|
|
72
75
|
<SelectPrimitive.Portal>
|
|
73
76
|
<SelectPrimitive.Content
|
|
74
77
|
data-slot="select-content"
|
|
75
78
|
className={cn(
|
|
76
|
-
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative
|
|
79
|
+
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative max-h-(--radix-select-content-available-height) min-w-32 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
|
|
80
|
+
layer.popover,
|
|
77
81
|
position === "popper" &&
|
|
78
82
|
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
79
83
|
className,
|
|
@@ -4,23 +4,11 @@ import * as React from "react";
|
|
|
4
4
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
5
5
|
import { IconX } from '@tabler/icons-react';
|
|
6
6
|
import { cn } from "../../../infra/utils/clsx";
|
|
7
|
+
import { DialogDepthContext, useDialogLayer } from "./layers";
|
|
7
8
|
|
|
8
|
-
// Cada `Dialog` aninhado sobe uma
|
|
9
|
-
// de cima cubra o conteudo do modal de baixo.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const DIALOG_LAYERS = [
|
|
13
|
-
{ overlay: "z-[1000]", content: "z-[1001]" },
|
|
14
|
-
{ overlay: "z-[1010]", content: "z-[1011]" },
|
|
15
|
-
{ overlay: "z-[1020]", content: "z-[1021]" },
|
|
16
|
-
{ overlay: "z-[1030]", content: "z-[1031]" },
|
|
17
|
-
] as const;
|
|
18
|
-
|
|
19
|
-
function useDialogLayer() {
|
|
20
|
-
const depth = React.useContext(DialogDepthContext);
|
|
21
|
-
const index = Math.min(Math.max(depth - 1, 0), DIALOG_LAYERS.length - 1);
|
|
22
|
-
return DIALOG_LAYERS[index];
|
|
23
|
-
}
|
|
9
|
+
// Cada `Dialog` aninhado sobe uma faixa de z-index, para que o overlay do modal
|
|
10
|
+
// de cima cubra o conteudo do modal de baixo. A escala (e os dropdowns e
|
|
11
|
+
// tooltips que precisam acompanhar) vive em `./layers`.
|
|
24
12
|
|
|
25
13
|
function Dialog({
|
|
26
14
|
...props
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import * as React from "react"
|
|
6
6
|
import * as PopoverPrimitive from "@radix-ui/react-popover"
|
|
7
7
|
import { cn } from "../../../infra/utils/clsx"
|
|
8
|
+
import { useDialogLayer } from "./layers"
|
|
8
9
|
|
|
9
10
|
function Popover({
|
|
10
11
|
...props
|
|
@@ -24,6 +25,8 @@ function PopoverContent({
|
|
|
24
25
|
sideOffset = 4,
|
|
25
26
|
...props
|
|
26
27
|
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
|
|
28
|
+
// Portaliza para o body, entao disputa z com o conteudo do modal que o abriu.
|
|
29
|
+
const layer = useDialogLayer()
|
|
27
30
|
return (
|
|
28
31
|
<PopoverPrimitive.Portal>
|
|
29
32
|
<PopoverPrimitive.Content
|
|
@@ -31,7 +34,8 @@ function PopoverContent({
|
|
|
31
34
|
align={align}
|
|
32
35
|
sideOffset={sideOffset}
|
|
33
36
|
className={cn(
|
|
34
|
-
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2
|
|
37
|
+
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
|
|
38
|
+
layer.popover,
|
|
35
39
|
className
|
|
36
40
|
)}
|
|
37
41
|
{...props}
|
|
@@ -5,6 +5,7 @@ import * as SheetPrimitive from "@radix-ui/react-dialog";
|
|
|
5
5
|
import { IconX } from '@tabler/icons-react';
|
|
6
6
|
import { cn } from "../../../infra/utils/clsx";
|
|
7
7
|
import { hideCrisp, showCrisp } from "../../embeds/CrispEmbed";
|
|
8
|
+
import { DialogDepthContext, useDialogLayer } from "./layers";
|
|
8
9
|
|
|
9
10
|
function Sheet({ onOpenChange, modal = false, ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
|
|
10
11
|
const handleOpenChange = React.useCallback((open: boolean) => {
|
|
@@ -13,7 +14,16 @@ function Sheet({ onOpenChange, modal = false, ...props }: React.ComponentProps<t
|
|
|
13
14
|
onOpenChange?.(open);
|
|
14
15
|
}, [onOpenChange]);
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
// Mesma faixa de z do `Dialog`: um `Dialog` aberto de dentro de um `Sheet` era
|
|
18
|
+
// profundidade 1, entao o overlay dele (1000) nascia sob o conteudo do sheet
|
|
19
|
+
// (1001). Somando aqui tambem, ele passa para a faixa de cima.
|
|
20
|
+
const depth = React.useContext(DialogDepthContext);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<DialogDepthContext.Provider value={depth + 1}>
|
|
24
|
+
<SheetPrimitive.Root data-slot="sheet" modal={modal} onOpenChange={handleOpenChange} {...props} />
|
|
25
|
+
</DialogDepthContext.Provider>
|
|
26
|
+
);
|
|
17
27
|
}
|
|
18
28
|
|
|
19
29
|
function SheetTrigger({
|
|
@@ -38,12 +48,14 @@ function SheetOverlay({
|
|
|
38
48
|
className,
|
|
39
49
|
...props
|
|
40
50
|
}: React.ComponentProps<"div">) {
|
|
51
|
+
const layer = useDialogLayer();
|
|
41
52
|
return (
|
|
42
53
|
<SheetPrimitive.Close tabIndex={-1} asChild>
|
|
43
54
|
<div
|
|
44
55
|
data-slot="sheet-overlay"
|
|
45
56
|
className={cn(
|
|
46
|
-
"animate-in fade-in-0 fixed inset-0
|
|
57
|
+
"animate-in fade-in-0 fixed inset-0 bg-black/50 cursor-default",
|
|
58
|
+
layer.overlay,
|
|
47
59
|
className,
|
|
48
60
|
)}
|
|
49
61
|
{...props}
|
|
@@ -64,6 +76,7 @@ function SheetContent({
|
|
|
64
76
|
showCloseButton?: boolean;
|
|
65
77
|
noAnimation?: boolean;
|
|
66
78
|
}) {
|
|
79
|
+
const layer = useDialogLayer();
|
|
67
80
|
return (
|
|
68
81
|
<SheetPortal>
|
|
69
82
|
<SheetOverlay className={noAnimation ? "!animate-none" : undefined} />
|
|
@@ -72,7 +85,8 @@ function SheetContent({
|
|
|
72
85
|
onInteractOutside={(e) => e.preventDefault()}
|
|
73
86
|
onPointerDownOutside={(e) => e.preventDefault()}
|
|
74
87
|
className={cn(
|
|
75
|
-
"bg-background fixed
|
|
88
|
+
"bg-background fixed flex flex-col gap-4 shadow-lg",
|
|
89
|
+
layer.content,
|
|
76
90
|
!noAnimation &&
|
|
77
91
|
"data-[state=open]:animate-in data-[state=closed]:animate-out transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
|
|
78
92
|
!noAnimation &&
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import * as React from "react"
|
|
6
6
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
|
|
7
7
|
import { cn } from "../../../infra/utils/clsx"
|
|
8
|
+
import { useDialogLayer } from "./layers"
|
|
8
9
|
|
|
9
10
|
function TooltipProvider({
|
|
10
11
|
delayDuration = 0,
|
|
@@ -41,13 +42,17 @@ function TooltipContent({
|
|
|
41
42
|
children,
|
|
42
43
|
...props
|
|
43
44
|
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
|
|
45
|
+
// Portaliza para o body. Fora de modal segue no `z-50` do resto da pagina;
|
|
46
|
+
// dentro de um, sobe para a faixa dele em vez de ser remendado no call site.
|
|
47
|
+
const layer = useDialogLayer()
|
|
44
48
|
return (
|
|
45
49
|
<TooltipPrimitive.Portal>
|
|
46
50
|
<TooltipPrimitive.Content
|
|
47
51
|
data-slot="tooltip-content"
|
|
48
52
|
sideOffset={sideOffset}
|
|
49
53
|
className={cn(
|
|
50
|
-
"bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2
|
|
54
|
+
"bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance pointer-events-none",
|
|
55
|
+
layer.tooltip,
|
|
51
56
|
className
|
|
52
57
|
)}
|
|
53
58
|
{...props}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Escala unica de z-index para tudo que flutua sobre a pagina.
|
|
7
|
+
*
|
|
8
|
+
* Cada nivel de modal aninhado ganha uma faixa propria de 10 unidades, e dentro
|
|
9
|
+
* da faixa a ordem e sempre a mesma:
|
|
10
|
+
*
|
|
11
|
+
* base + 0 overlay do modal
|
|
12
|
+
* base + 1 conteudo do modal
|
|
13
|
+
* base + 2 dropdown portalizado aberto de dentro dele (Select, Popover)
|
|
14
|
+
* base + 3 tooltip portalizado aberto de dentro dele
|
|
15
|
+
*
|
|
16
|
+
* O ponto dos dois ultimos: `Select`, `Popover` e `Tooltip` renderizam num
|
|
17
|
+
* portal para o `document.body`, entao no DOM eles sao irmaos do conteudo do
|
|
18
|
+
* modal e a disputa de z e global. Com z fixo (`z-[1002]`) eles funcionavam so
|
|
19
|
+
* no primeiro nivel: dentro de um modal aninhado o conteudo sobe para 1011 e o
|
|
20
|
+
* dropdown fica preso em 1002, abrindo atras do modal. Derivar da mesma faixa
|
|
21
|
+
* resolve em qualquer profundidade.
|
|
22
|
+
*
|
|
23
|
+
* O portal preserva o contexto React (so o alvo no DOM muda), por isso o
|
|
24
|
+
* `useDialogLayer` de dentro do dropdown enxerga a profundidade do modal que o
|
|
25
|
+
* abriu.
|
|
26
|
+
*
|
|
27
|
+
* Classes literais de proposito: o Tailwind so gera o que ve escrito.
|
|
28
|
+
*/
|
|
29
|
+
const DIALOG_LAYERS = [
|
|
30
|
+
{ overlay: "z-[1000]", content: "z-[1001]", popover: "z-[1002]", tooltip: "z-[1003]" },
|
|
31
|
+
{ overlay: "z-[1010]", content: "z-[1011]", popover: "z-[1012]", tooltip: "z-[1013]" },
|
|
32
|
+
{ overlay: "z-[1020]", content: "z-[1021]", popover: "z-[1022]", tooltip: "z-[1023]" },
|
|
33
|
+
{ overlay: "z-[1030]", content: "z-[1031]", popover: "z-[1032]", tooltip: "z-[1033]" },
|
|
34
|
+
{ overlay: "z-[1040]", content: "z-[1041]", popover: "z-[1042]", tooltip: "z-[1043]" },
|
|
35
|
+
{ overlay: "z-[1050]", content: "z-[1051]", popover: "z-[1052]", tooltip: "z-[1053]" },
|
|
36
|
+
] as const;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Fora de qualquer modal. `overlay` e `content` nunca sao lidos aqui (so existem
|
|
40
|
+
* dentro de um `Dialog`/`Sheet`, que ja somam 1), mas dropdown e tooltip sim, e
|
|
41
|
+
* mantem exatamente os valores que tinham antes desta escala existir: o tooltip
|
|
42
|
+
* segue no `z-50` do resto da pagina em vez de saltar para a faixa dos modais.
|
|
43
|
+
*/
|
|
44
|
+
const ROOT_LAYER = { overlay: "z-[1000]", content: "z-[1001]", popover: "z-[1002]", tooltip: "z-50" } as const;
|
|
45
|
+
|
|
46
|
+
export type DialogLayerClasses = (typeof DIALOG_LAYERS)[number] | typeof ROOT_LAYER;
|
|
47
|
+
|
|
48
|
+
export const DialogDepthContext = React.createContext(0);
|
|
49
|
+
|
|
50
|
+
const saturationWarned = new Set<number>();
|
|
51
|
+
|
|
52
|
+
export function useDialogLayer(): DialogLayerClasses {
|
|
53
|
+
const depth = React.useContext(DialogDepthContext);
|
|
54
|
+
if (depth <= 0) return ROOT_LAYER;
|
|
55
|
+
|
|
56
|
+
if (depth > DIALOG_LAYERS.length && process.env.NODE_ENV !== "production" && !saturationWarned.has(depth)) {
|
|
57
|
+
saturationWarned.add(depth);
|
|
58
|
+
console.warn(
|
|
59
|
+
`[great-lib-common] ${depth} modais empilhados, mas a escala de z so tem ${DIALOG_LAYERS.length} faixas. ` +
|
|
60
|
+
`Deste nivel em diante todos dividem a ultima faixa e o overlay de cima cai sob o conteudo de baixo. ` +
|
|
61
|
+
`Se o empilhamento for legitimo, adicione uma faixa em ui/overlay/layers.tsx.`,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return DIALOG_LAYERS[Math.min(depth - 1, DIALOG_LAYERS.length - 1)];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Sobe uma faixa para a subarvore, sem precisar de um modal no meio.
|
|
70
|
+
*
|
|
71
|
+
* A profundidade sai da arvore React, nao da ordem de abertura, entao dois
|
|
72
|
+
* modais declarados como irmaos nascem os dois na mesma faixa e o de cima abre
|
|
73
|
+
* atras do de baixo:
|
|
74
|
+
*
|
|
75
|
+
* <>
|
|
76
|
+
* <Dialog>...</Dialog>
|
|
77
|
+
* <ConfirmDialog /> // mesma faixa do de cima
|
|
78
|
+
* </>
|
|
79
|
+
*
|
|
80
|
+
* Envolvendo o segundo, ele passa a valer um nivel a mais que o vizinho, e o
|
|
81
|
+
* ajuste e relativo: continua correto se o conjunto inteiro for parar dentro de
|
|
82
|
+
* outro modal.
|
|
83
|
+
*
|
|
84
|
+
* <>
|
|
85
|
+
* <Dialog>...</Dialog>
|
|
86
|
+
* <DialogLayer><ConfirmDialog /></DialogLayer>
|
|
87
|
+
* </>
|
|
88
|
+
*
|
|
89
|
+
* E a alternativa ao `className="z-[1003]"` na mao, que trava o modal num numero
|
|
90
|
+
* absoluto e quebra assim que ele e reaproveitado noutra profundidade.
|
|
91
|
+
*/
|
|
92
|
+
export function DialogLayer({ children }: { children: React.ReactNode }) {
|
|
93
|
+
const depth = React.useContext(DialogDepthContext);
|
|
94
|
+
return <DialogDepthContext.Provider value={depth + 1}>{children}</DialogDepthContext.Provider>;
|
|
95
|
+
}
|
|
@@ -304,10 +304,9 @@ export function ImageCropModal({
|
|
|
304
304
|
<DialogContent
|
|
305
305
|
className={
|
|
306
306
|
isTooSmall
|
|
307
|
-
? 'w-full md:w-[480px]! lg:w-[480px]! max-w-[480px]! max-[480px]:w-[calc(100%-32px)] p-0 gap-0
|
|
308
|
-
: 'w-full md:w-[650px]! lg:w-[650px]! max-w-[650px]! max-[650px]:w-[calc(100%-32px)] p-0 gap-0
|
|
307
|
+
? 'w-full md:w-[480px]! lg:w-[480px]! max-w-[480px]! max-[480px]:w-[calc(100%-32px)] p-0 gap-0'
|
|
308
|
+
: 'w-full md:w-[650px]! lg:w-[650px]! max-w-[650px]! max-[650px]:w-[calc(100%-32px)] p-0 gap-0'
|
|
309
309
|
}
|
|
310
|
-
overlayClassName="z-[1002]!"
|
|
311
310
|
>
|
|
312
311
|
{isTooSmall ? (
|
|
313
312
|
<>
|
|
@@ -35,8 +35,8 @@ export function ImageTooSmallModal({
|
|
|
35
35
|
return (
|
|
36
36
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
37
37
|
<DialogContent
|
|
38
|
-
className="w-full md:w-[480px]! lg:w-[480px]! max-w-[480px]! max-[480px]:w-[calc(100%-32px)] p-0 gap-0 z-[1003]
|
|
39
|
-
overlayClassName="z-[1002]
|
|
38
|
+
className="w-full md:w-[480px]! lg:w-[480px]! max-w-[480px]! max-[480px]:w-[calc(100%-32px)] p-0 gap-0 z-[1003]"
|
|
39
|
+
overlayClassName="z-[1002]"
|
|
40
40
|
>
|
|
41
41
|
<DialogHeader className="p-5">
|
|
42
42
|
<DialogTitle className="text-center text-[16px]!">
|
|
@@ -4,6 +4,7 @@ import { useRef } from 'react'
|
|
|
4
4
|
import { useImageUpload } from '../../../modules/images/hooks/use-image-upload.hook'
|
|
5
5
|
import { ACCEPTED_IMAGE_FORMATS_STRING } from '../../../modules/images/constants/image.constants'
|
|
6
6
|
import { ImageCropModal } from './ImageCropModal'
|
|
7
|
+
import { DialogLayer } from '../../ui/overlay/layers'
|
|
7
8
|
import { Button } from '../../ui/buttons/Button'
|
|
8
9
|
import type { ImageConfig } from '../../../modules/images/types/image.type'
|
|
9
10
|
|
|
@@ -114,17 +115,20 @@ export function ImageUpload({
|
|
|
114
115
|
)}
|
|
115
116
|
|
|
116
117
|
{originalImage && (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
118
|
+
// Abre por cima do que hospeda o widget, que normalmente e um modal.
|
|
119
|
+
<DialogLayer>
|
|
120
|
+
<ImageCropModal
|
|
121
|
+
open={showCropModal}
|
|
122
|
+
onOpenChange={setShowCropModal}
|
|
123
|
+
imageSrc={originalImage}
|
|
124
|
+
aspectRatio={config.aspectRatio}
|
|
125
|
+
onConfirm={handleCropConfirm}
|
|
126
|
+
minWidth={config.width}
|
|
127
|
+
minHeight={config.height}
|
|
128
|
+
fileName={fileName}
|
|
129
|
+
onSelectAnother={() => inputRef.current?.click()}
|
|
130
|
+
/>
|
|
131
|
+
</DialogLayer>
|
|
128
132
|
)}
|
|
129
133
|
</div>
|
|
130
134
|
)
|