@m13v/seo-components 0.38.4 → 0.38.5
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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useEffect, useState } from "react";
|
|
4
|
+
import { createPortal } from "react-dom";
|
|
4
5
|
import { motion, AnimatePresence } from "framer-motion";
|
|
5
6
|
import { trackGetStartedClick } from "../lib/track";
|
|
6
7
|
import { useCapture } from "../lib/analytics-context";
|
|
@@ -133,6 +134,15 @@ export function InstallEmailGate({
|
|
|
133
134
|
const [submitting, setSubmitting] = useState(false);
|
|
134
135
|
const [error, setError] = useState("");
|
|
135
136
|
const [copied, setCopied] = useState<"command" | "config" | null>(null);
|
|
137
|
+
// Mounted flag so we can portal the modal to document.body on the client
|
|
138
|
+
// without breaking SSR hydration. The modal escapes any transformed parent
|
|
139
|
+
// (e.g. .reveal-up) that would otherwise trap position: fixed inside that
|
|
140
|
+
// ancestor's stacking context, allowing clicks to leak through to the
|
|
141
|
+
// underlying page.
|
|
142
|
+
const [mounted, setMounted] = useState(false);
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
setMounted(true);
|
|
145
|
+
}, []);
|
|
136
146
|
|
|
137
147
|
useEffect(() => {
|
|
138
148
|
if (stage === "closed") return;
|
|
@@ -286,28 +296,8 @@ export function InstallEmailGate({
|
|
|
286
296
|
? "group inline-flex h-11 items-center gap-2 rounded-md bg-zinc-900 px-5 text-sm font-medium text-white transition-colors hover:bg-zinc-800"
|
|
287
297
|
: "inline-flex items-center justify-center rounded-md border border-zinc-300 bg-white px-5 py-2.5 text-sm font-medium text-zinc-800 transition-colors hover:border-zinc-400";
|
|
288
298
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
{renderTrigger ? (
|
|
292
|
-
renderTrigger({ onClick: onOpen })
|
|
293
|
-
) : (
|
|
294
|
-
<button type="button" onClick={onOpen} className={`${buttonClass} ${className}`.trim()}>
|
|
295
|
-
{label}
|
|
296
|
-
{variant === "primary" && (
|
|
297
|
-
<svg
|
|
298
|
-
className="h-4 w-4 transition-transform group-hover:translate-x-0.5"
|
|
299
|
-
fill="none"
|
|
300
|
-
viewBox="0 0 24 24"
|
|
301
|
-
stroke="currentColor"
|
|
302
|
-
strokeWidth={2}
|
|
303
|
-
>
|
|
304
|
-
<path strokeLinecap="round" strokeLinejoin="round" d="M13 7l5 5m0 0l-5 5m5-5H6" />
|
|
305
|
-
</svg>
|
|
306
|
-
)}
|
|
307
|
-
</button>
|
|
308
|
-
)}
|
|
309
|
-
|
|
310
|
-
<AnimatePresence>
|
|
299
|
+
const overlay = (
|
|
300
|
+
<AnimatePresence>
|
|
311
301
|
{stage !== "closed" && (
|
|
312
302
|
<motion.div
|
|
313
303
|
key="backdrop"
|
|
@@ -505,6 +495,35 @@ export function InstallEmailGate({
|
|
|
505
495
|
</motion.div>
|
|
506
496
|
)}
|
|
507
497
|
</AnimatePresence>
|
|
498
|
+
);
|
|
499
|
+
|
|
500
|
+
return (
|
|
501
|
+
<>
|
|
502
|
+
{renderTrigger ? (
|
|
503
|
+
renderTrigger({ onClick: onOpen })
|
|
504
|
+
) : (
|
|
505
|
+
<button type="button" onClick={onOpen} className={`${buttonClass} ${className}`.trim()}>
|
|
506
|
+
{label}
|
|
507
|
+
{variant === "primary" && (
|
|
508
|
+
<svg
|
|
509
|
+
className="h-4 w-4 transition-transform group-hover:translate-x-0.5"
|
|
510
|
+
fill="none"
|
|
511
|
+
viewBox="0 0 24 24"
|
|
512
|
+
stroke="currentColor"
|
|
513
|
+
strokeWidth={2}
|
|
514
|
+
>
|
|
515
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M13 7l5 5m0 0l-5 5m5-5H6" />
|
|
516
|
+
</svg>
|
|
517
|
+
)}
|
|
518
|
+
</button>
|
|
519
|
+
)}
|
|
520
|
+
{/* Portal the modal to document.body so a transformed ancestor (e.g.
|
|
521
|
+
`.reveal-up` with `transform: translateY`) can't trap position:fixed
|
|
522
|
+
inside its own stacking context, which would let clicks leak through
|
|
523
|
+
to elements layered on top of the modal at viewport level. */}
|
|
524
|
+
{mounted && typeof document !== "undefined"
|
|
525
|
+
? createPortal(overlay, document.body)
|
|
526
|
+
: null}
|
|
508
527
|
</>
|
|
509
528
|
);
|
|
510
529
|
}
|