@windstream/react-shared-components 0.2.57 → 0.2.59
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/contentful/index.d.ts +15 -1
- package/dist/contentful/index.esm.js +5 -5
- package/dist/contentful/index.esm.js.map +1 -1
- package/dist/contentful/index.js +5 -5
- package/dist/contentful/index.js.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/next/index.esm.js +1 -17
- package/dist/next/index.esm.js.map +1 -1
- package/dist/next/index.js +1 -17
- package/dist/next/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/utils/index.d.ts +11 -1
- package/dist/utils/index.esm.js +1 -1
- package/dist/utils/index.esm.js.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/brand-button/index.tsx +2 -2
- package/src/components/next-image/index.tsx +1 -1
- package/src/components/video-link/contentful-video-embed.tsx +1 -1
- package/src/components/video-link/index.tsx +1 -1
- package/src/components/video-link/vimeo-embed.tsx +1 -1
- package/src/components/video-link/youtube-embed.tsx +1 -1
- package/src/contentful/blocks/button/index.tsx +11 -0
- package/src/contentful/blocks/cart-retention-banner/CartRetentionBanner.stories.tsx +89 -1
- package/src/contentful/blocks/cart-retention-banner/index.test.tsx +85 -0
- package/src/contentful/blocks/cart-retention-banner/index.tsx +222 -39
- package/src/contentful/blocks/cart-retention-banner/types.ts +34 -0
- package/src/contentful/blocks/dynamic-form/form-field.tsx +1 -1
- package/src/contentful/blocks/modal/index.tsx +14 -3
- package/src/contentful/blocks/shape-background-wrapper/index.test.tsx +17 -1
- package/src/contentful/blocks/shape-background-wrapper/index.tsx +30 -0
- package/src/contentful/index.ts +5 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/wifi-grant-redirect.ts +49 -0
|
@@ -59,7 +59,13 @@ export const Modal: React.FC<ExtendedModalProps> = props => {
|
|
|
59
59
|
<Dialog.Content
|
|
60
60
|
onOpenAutoFocus={e => e.preventDefault()}
|
|
61
61
|
className={cx(
|
|
62
|
-
|
|
62
|
+
// `rounded-modal` isn't a registered Tailwind token - use an explicit radius.
|
|
63
|
+
"relative mx-auto w-full overflow-hidden rounded-[24px] shadow-drop focus:outline-none",
|
|
64
|
+
// Only fall back to the default surface color / padding when
|
|
65
|
+
// the caller hasn't supplied its own override (avoids two
|
|
66
|
+
// competing `bg-*`/`p-*` classes racing on CSS order).
|
|
67
|
+
!/(^|\s)bg-/.test(bodyClassName ?? "") && "bg-bg",
|
|
68
|
+
!/(^|\s)p-/.test(bodyClassName ?? "") && "p-[25px]",
|
|
63
69
|
bodyClassName
|
|
64
70
|
)}
|
|
65
71
|
style={{ maxWidth: sizeToPixel[size || "lg"] }}
|
|
@@ -68,12 +74,17 @@ export const Modal: React.FC<ExtendedModalProps> = props => {
|
|
|
68
74
|
<Dialog.Close asChild={true}>
|
|
69
75
|
<Button
|
|
70
76
|
showButtonAs="unstyled"
|
|
71
|
-
|
|
77
|
+
// Pin icon color: button always sits on a light bg-bg
|
|
78
|
+
// square, so it must not inherit a light text color (e.g.
|
|
79
|
+
// text-white) from a dark bodyClassName like navy.
|
|
80
|
+
// z-10: keeps the button clickable above positioned body
|
|
81
|
+
// content (e.g. ShapeBackgroundWrapper's decorative layer).
|
|
82
|
+
buttonClassName="absolute right-0 top-0 z-10 mr-2 mt-2"
|
|
72
83
|
>
|
|
73
84
|
<MaterialIcon name="close" />
|
|
74
85
|
</Button>
|
|
75
86
|
</Dialog.Close>
|
|
76
|
-
<div className="custom-modal-body max-h-[85vh] overflow-
|
|
87
|
+
<div className="custom-modal-body max-h-[85vh] overflow-y-auto scroll-smooth [scrollbar-color:rgba(0,0,0,0.2)_transparent] [scrollbar-width:thin] [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-black/20 hover:[&::-webkit-scrollbar-thumb]:bg-black/30 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar]:w-1.5">
|
|
77
88
|
{title ? (
|
|
78
89
|
<Text
|
|
79
90
|
className={cx(
|
|
@@ -130,9 +130,25 @@ describe("ShapeBackgroundWrapper", () => {
|
|
|
130
130
|
expect(svgs[0]).toHaveAttribute("height", "3666");
|
|
131
131
|
});
|
|
132
132
|
|
|
133
|
+
it("renders both mobile and desktop path5 SVGs when path='path5'", () => {
|
|
134
|
+
const { container } = render(
|
|
135
|
+
<ShapeBackgroundWrapper path="path5" background="white">
|
|
136
|
+
<span>Path5</span>
|
|
137
|
+
</ShapeBackgroundWrapper>
|
|
138
|
+
);
|
|
139
|
+
const svgs = container.querySelectorAll("svg");
|
|
140
|
+
expect(svgs).toHaveLength(2);
|
|
141
|
+
expect(svgs[0]).toHaveAttribute("width", "367");
|
|
142
|
+
expect(svgs[0]).toHaveAttribute("height", "644");
|
|
143
|
+
expect(svgs[0]).toHaveClass("md:hidden");
|
|
144
|
+
expect(svgs[1]).toHaveAttribute("width", "367");
|
|
145
|
+
expect(svgs[1]).toHaveAttribute("height", "448");
|
|
146
|
+
expect(svgs[1]).toHaveClass("md:block");
|
|
147
|
+
});
|
|
148
|
+
|
|
133
149
|
it("does not render SVG for unrecognized path value", () => {
|
|
134
150
|
const { container } = render(
|
|
135
|
-
<ShapeBackgroundWrapper path={"
|
|
151
|
+
<ShapeBackgroundWrapper path={"path6" as any} background="white">
|
|
136
152
|
<span>Unknown</span>
|
|
137
153
|
</ShapeBackgroundWrapper>
|
|
138
154
|
);
|
|
@@ -118,6 +118,36 @@ export const ShapeBackgroundWrapper: React.FC<ShapeBackgroundWrapperProps> = ({
|
|
|
118
118
|
<path d="M1662.93 3664.31C2153.52 3637.23 2442.1 3474.65 2872.31 2646.41C3278.25 1865.1 4009.1 647.091 3634.26 264.381C3417.79 27.9951 3025.37 31.7826 2716.76 13.902C2511.72 8.81709 2327.31 8.87474 2126.55 0.512528C2060.73 -2.00052 2040.7 85.9483 2101.3 114.088C2417.76 260.743 2628.86 431.51 2731.94 722.143C2940.79 1225.9 2508.91 2178.82 2150.63 2656.7C1779.64 3169.63 1293.64 3217.84 798.345 3136.04C534.128 3085.8 291.072 2986.98 92.1133 2864.4C33.4593 2828.06 -29.3236 2901.01 15.967 2953.13C371.841 3364.12 1128.29 3656.09 1663.56 3665.34" />
|
|
119
119
|
</svg>
|
|
120
120
|
)}
|
|
121
|
+
{path === "path5" && (
|
|
122
|
+
// Exact Figma export, cropped via viewBox at 0,0 (no translate hack needed);
|
|
123
|
+
// mobile/desktop swap via CSS breakpoint since the crop window differs by height.
|
|
124
|
+
<>
|
|
125
|
+
<svg
|
|
126
|
+
className={`shape-bg-svg pointer-events-none absolute left-0 top-0 z-0 block md:hidden ${variantClass} fill-current ${fillClass}`}
|
|
127
|
+
width="367"
|
|
128
|
+
height="644"
|
|
129
|
+
viewBox="0 0 367 644"
|
|
130
|
+
fill="none"
|
|
131
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
132
|
+
aria-hidden="true"
|
|
133
|
+
focusable="false"
|
|
134
|
+
>
|
|
135
|
+
<path d="M-2083.1 549.586C-1857.78 764.836 -1656.5 828.759 -1081.83 673.557C-539.683 527.203 347.968 344.365 364.89 7.43135C381.862 -193.724 210.008 -373.544 84.6305 -523.879C-1.85227 -620.854 -81.806 -706.094 -164.9 -802.494C-192.25 -834.002 -242.154 -805.661 -229.077 -765.61C-160.659 -556.59 -149.205 -385.975 -240.751 -214.056C-386.348 97.8893 -1020.17 305.621 -1399.44 344.278C-1800.65 392.049 -2033.89 187.954 -2210.22 -76.0251C-2301.18 -219.67 -2360.21 -374.3 -2388.99 -518.696C-2397.38 -561.352 -2458.78 -559.193 -2463.58 -515.969C-2501.97 -175.709 -2310.97 298.878 -2083.31 550.316" />
|
|
136
|
+
</svg>
|
|
137
|
+
<svg
|
|
138
|
+
className={`shape-bg-svg pointer-events-none absolute left-0 top-0 z-0 hidden md:block ${variantClass} fill-current ${fillClass}`}
|
|
139
|
+
width="367"
|
|
140
|
+
height="448"
|
|
141
|
+
viewBox="0 0 367 448"
|
|
142
|
+
fill="none"
|
|
143
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
144
|
+
aria-hidden="true"
|
|
145
|
+
focusable="false"
|
|
146
|
+
>
|
|
147
|
+
<path d="M-2083.1 549.587C-1857.78 764.837 -1656.5 828.759 -1081.83 673.557C-539.682 527.203 347.968 344.365 364.89 7.43156C381.863 -193.724 210.008 -373.543 84.6307 -523.879C-1.85203 -620.854 -81.8058 -706.094 -164.9 -802.494C-192.249 -834.001 -242.154 -805.661 -229.077 -765.609C-160.658 -556.59 -149.205 -385.975 -240.751 -214.056C-386.348 97.8895 -1020.17 305.621 -1399.44 344.278C-1800.65 392.049 -2033.89 187.954 -2210.22 -76.0249C-2301.18 -219.669 -2360.21 -374.3 -2388.99 -518.696C-2397.38 -561.352 -2458.78 -559.193 -2463.58 -515.969C-2501.97 -175.709 -2310.97 298.879 -2083.31 550.317" />
|
|
148
|
+
</svg>
|
|
149
|
+
</>
|
|
150
|
+
)}
|
|
121
151
|
|
|
122
152
|
<div className="shape-bg-content relative z-[1]">{children}</div>
|
|
123
153
|
</div>
|
package/src/contentful/index.ts
CHANGED
|
@@ -98,6 +98,11 @@ export type { EmailInputBlockProps } from "./blocks/email-input-block/types";
|
|
|
98
98
|
|
|
99
99
|
export { default as CartRetentionBanner } from "./blocks/cart-retention-banner";
|
|
100
100
|
export type { TypeCartRetentionBannerFields as CartRetentionBannerProps } from "./blocks/cart-retention-banner/types";
|
|
101
|
+
export type {
|
|
102
|
+
CartRetentionBannerImagePosition,
|
|
103
|
+
CartRetentionBannerBackgroundColor,
|
|
104
|
+
CartRetentionBannerImageAccentColor,
|
|
105
|
+
} from "./blocks/cart-retention-banner/types";
|
|
101
106
|
|
|
102
107
|
export { IframeEmbed } from "./blocks/iframe-embed";
|
|
103
108
|
export type { IframeEmbedProps } from "./blocks/iframe-embed/types";
|
package/src/utils/index.ts
CHANGED
|
@@ -27,6 +27,11 @@ export type {
|
|
|
27
27
|
} from "../types/utm";
|
|
28
28
|
export { UTM_PARAM_NAMES } from "../types/utm";
|
|
29
29
|
|
|
30
|
+
export {
|
|
31
|
+
buildWifiGrantRedirectUrl,
|
|
32
|
+
redirectToWifiGrantUrl,
|
|
33
|
+
} from "./wifi-grant-redirect";
|
|
34
|
+
|
|
30
35
|
// Contentful utilities (server-safe, no "use client")
|
|
31
36
|
export { toDocument } from "./contentful/to-document";
|
|
32
37
|
export {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wifi Grant Redirect Helpers
|
|
3
|
+
*
|
|
4
|
+
* Builds the captive-portal redirect URL for Wi-Fi splash pages (e.g. /free-public-wifi).
|
|
5
|
+
* The portal controller appends base_grant_url to the page URL; continue_url always
|
|
6
|
+
* points at the fixed success page below (not read from the portal's query params).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const WIFI_GRANT_CONTINUE_URL = "https://www.gokinetic.com/free-public-wifi/success";
|
|
10
|
+
const ALLOWED_BASE_GRANT_PROTOCOL = "https:";
|
|
11
|
+
// Cisco Meraki captive-portal domain; grant URLs use a per-node subdomain (e.g. n143.network-auth.com).
|
|
12
|
+
const ALLOWED_BASE_GRANT_DOMAIN = "network-auth.com";
|
|
13
|
+
|
|
14
|
+
// Restricts redirects to the known captive-portal domain to prevent open redirect via base_grant_url.
|
|
15
|
+
function getSafeBaseGrantUrl(rawBaseGrantUrl: string): URL | null {
|
|
16
|
+
try {
|
|
17
|
+
const parsed = new URL(rawBaseGrantUrl);
|
|
18
|
+
if (parsed.protocol !== ALLOWED_BASE_GRANT_PROTOCOL) return null;
|
|
19
|
+
const { hostname } = parsed;
|
|
20
|
+
const isAllowedHost =
|
|
21
|
+
hostname === ALLOWED_BASE_GRANT_DOMAIN ||
|
|
22
|
+
hostname.endsWith(`.${ALLOWED_BASE_GRANT_DOMAIN}`);
|
|
23
|
+
if (!isAllowedHost) return null;
|
|
24
|
+
return parsed;
|
|
25
|
+
} catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function buildWifiGrantRedirectUrl(): string | null {
|
|
31
|
+
if (typeof window === "undefined") return null;
|
|
32
|
+
const params = new URLSearchParams(window.location.search);
|
|
33
|
+
const baseGrantUrl = params.get("base_grant_url");
|
|
34
|
+
if (!baseGrantUrl) return null;
|
|
35
|
+
|
|
36
|
+
const safeBaseGrantUrl = getSafeBaseGrantUrl(baseGrantUrl);
|
|
37
|
+
if (!safeBaseGrantUrl) return null;
|
|
38
|
+
|
|
39
|
+
safeBaseGrantUrl.searchParams.set("continue_url", WIFI_GRANT_CONTINUE_URL);
|
|
40
|
+
safeBaseGrantUrl.searchParams.set("duration", "86400");
|
|
41
|
+
return safeBaseGrantUrl.toString();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function redirectToWifiGrantUrl(): boolean {
|
|
45
|
+
const redirectUrl = buildWifiGrantRedirectUrl();
|
|
46
|
+
if (!redirectUrl) return false;
|
|
47
|
+
window.location.href = redirectUrl;
|
|
48
|
+
return true;
|
|
49
|
+
}
|