@windstream/react-shared-components 0.2.10 → 0.2.12

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.
@@ -0,0 +1,79 @@
1
+ "use client";
2
+
3
+ import React, { useEffect, useRef } from "react";
4
+ import { IframeEmbedProps, bgColorMap } from "./types";
5
+
6
+ /**
7
+ * IframeEmbed — A generic, responsive iframe component for embedding third-party content
8
+ * such as Brand Featured badges, widgets, or any external HTML page.
9
+ *
10
+ * Features:
11
+ * - **Auto-resize:** Listens for `postMessage` events with an `{ iframeHeight: number }` payload
12
+ * from the embedded page and adjusts the iframe height dynamically.
13
+ * - **Background color:** Supports predefined background colors (`gray90`, `green`, `white`)
14
+ * behind the iframe, defaulting to transparent.
15
+ * - **Lazy loading:** The iframe uses `loading="lazy"` for performance.
16
+ * - **Anchor support:** An optional `anchorId` is applied to the wrapping `<section>` for
17
+ * deep-linking or scroll-to navigation.
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * <IframeEmbed
22
+ * iframeUrl="https://api.brandfeatured.com/badges/badge-news_dark.html?id=123"
23
+ * backgroundColor="green"
24
+ * anchorId="brand-badge"
25
+ * />
26
+ * ```
27
+ */
28
+ export const IframeEmbed: React.FC<IframeEmbedProps> = ({
29
+ iframeUrl,
30
+ anchorId,
31
+ backgroundColor,
32
+ height,
33
+ }) => {
34
+ const iframeRef = useRef<HTMLIFrameElement>(null);
35
+
36
+ useEffect(() => {
37
+ if (!iframeUrl) return;
38
+
39
+ const handleMessage = (event: MessageEvent) => {
40
+ const height = event.data?.iframeHeight;
41
+ if (
42
+ typeof height === "number" &&
43
+ Number.isFinite(height) &&
44
+ height > 0 &&
45
+ height <= 10000 &&
46
+ iframeRef.current
47
+ ) {
48
+ iframeRef.current.style.height = `${height}px`;
49
+ }
50
+ };
51
+
52
+ window.addEventListener("message", handleMessage);
53
+ return () => window.removeEventListener("message", handleMessage);
54
+ }, [iframeUrl]);
55
+
56
+ if (!iframeUrl) return null;
57
+
58
+ return (
59
+ <section id={anchorId} className="w-full">
60
+ <iframe
61
+ ref={iframeRef}
62
+ src={iframeUrl}
63
+ width="100%"
64
+ frameBorder="0"
65
+ scrolling="no"
66
+ style={{
67
+ background: backgroundColor
68
+ ? bgColorMap[backgroundColor]
69
+ : "transparent",
70
+ ...(height ? { height: `${height}px` } : {}),
71
+ }}
72
+ title="Iframe Embed"
73
+ loading="lazy"
74
+ />
75
+ </section>
76
+ );
77
+ };
78
+
79
+ export default IframeEmbed;
@@ -0,0 +1,18 @@
1
+ export const bgColorMap = {
2
+ gray90: "#464646",
3
+ green: "#24A76A",
4
+ white: "#FFFFFF",
5
+ } as const;
6
+
7
+ export type BackgroundColor = keyof typeof bgColorMap;
8
+
9
+ export type IframeEmbedProps = {
10
+ /** The full URL of the third-party iframe to embed (e.g., Brand Featured badge URL). */
11
+ iframeUrl: string;
12
+ /** Optional HTML `id` for the wrapping `<section>`, useful for anchor linking or scroll-to navigation. */
13
+ anchorId?: string;
14
+ /** Optional background color applied behind the iframe. Defaults to `"transparent"` when not provided. */
15
+ backgroundColor?: BackgroundColor;
16
+ /** Optional initial/minimum height (in px) for the iframe before postMessage auto-resize kicks in. */
17
+ height?: number;
18
+ };
@@ -89,6 +89,9 @@ export type { EmailInputBlockProps } from "./blocks/email-input-block/types";
89
89
  export { default as CartRetentionBanner } from "./blocks/cart-retention-banner";
90
90
  export type { TypeCartRetentionBannerFields as CartRetentionBannerProps } from "./blocks/cart-retention-banner/types";
91
91
 
92
+ export { IframeEmbed } from "./blocks/iframe-embed";
93
+ export type { IframeEmbedProps } from "./blocks/iframe-embed/types";
94
+
92
95
  // Contentful Rich Text Hooks & Utils
93
96
  export { toDocument } from "../utils/contentful/to-document";
94
97