@windstream/react-shared-components 0.1.11 → 0.1.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windstream/react-shared-components",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "type": "module",
5
5
  "description": "Shared React components for Kinetic applications",
6
6
  "main": "dist/index.js",
@@ -1,7 +1,10 @@
1
1
  "use client";
2
2
 
3
3
  import { forwardRef } from "react";
4
- import NextJsImage, { type ImageProps as NextImageProps } from "next/image";
4
+ import NextJsImage, {
5
+ type ImageLoaderProps,
6
+ type ImageProps as NextImageProps,
7
+ } from "next/image";
5
8
 
6
9
  import { cx } from "@shared/utils";
7
10
 
@@ -9,21 +12,40 @@ export interface NextImageComponentProps extends NextImageProps {
9
12
  className?: string;
10
13
  }
11
14
 
15
+ /**
16
+ * Image loader that uses Contentful's Image API to serve optimized WebP images
17
+ * at the requested width and quality, avoiding an extra round-trip through
18
+ * the Next.js image optimization server.
19
+ */
20
+ const contentfulImageLoader = ({ src, width, quality }: ImageLoaderProps) => {
21
+ const url = new URL(src);
22
+ url.searchParams.set("w", String(width));
23
+ url.searchParams.set("q", String(quality || 90));
24
+ url.searchParams.set("fm", "webp");
25
+ return url.toString();
26
+ };
27
+
12
28
  export const NextImage = forwardRef<HTMLImageElement, NextImageComponentProps>(
13
29
  ({ className, ...props }, ref) => {
14
- // Only disable optimization for SVG files from Contentful
15
- // Remove query params before checking file extension
16
30
  const srcString = typeof props.src === "string" ? props.src : "";
17
31
  const urlWithoutParams = srcString.toLowerCase().split("?")[0] || "";
32
+ const isContentfulImage = srcString.includes("images.ctfassets.net");
18
33
  const isSvgFromContentful =
19
- srcString.includes("images.ctfassets.net") &&
20
- urlWithoutParams.endsWith(".svg");
34
+ isContentfulImage && urlWithoutParams.endsWith(".svg");
35
+
36
+ // Use Contentful's Image API for non-SVG Contentful images;
37
+ // skip optimization entirely for SVGs.
38
+ const loaderProps =
39
+ isContentfulImage && !isSvgFromContentful
40
+ ? { loader: contentfulImageLoader, unoptimized: false }
41
+ : { unoptimized: isSvgFromContentful };
42
+
21
43
  return (
22
44
  <NextJsImage
23
45
  ref={ref}
24
46
  className={cx(className)}
25
47
  {...props}
26
- unoptimized={isSvgFromContentful}
48
+ {...loaderProps}
27
49
  />
28
50
  );
29
51
  }
@@ -147,8 +147,9 @@ export const PrimaryHero: React.FC<PrimaryHeroProps> = props => {
147
147
  src={badgeImage}
148
148
  alt={"Badge"}
149
149
  className="absolute left-5 top-5 aspect-square w-26 object-cover object-center"
150
- width={100}
151
- height={100}
150
+ width={104}
151
+ height={104}
152
+ quality={90}
152
153
  loading="eager"
153
154
  />
154
155
  ) : null}
@@ -157,8 +158,10 @@ export const PrimaryHero: React.FC<PrimaryHeroProps> = props => {
157
158
  src={carouselImages[0]}
158
159
  alt={"Hero"}
159
160
  className="aspect-[1.71:1] sm:aspect-[1.41:1] w-full rounded-[40px] object-cover object-center sm:h-[420px]"
160
- width={350}
161
- height={205}
161
+ width={1024}
162
+ height={600}
163
+ sizes="100vw"
164
+ quality={90}
162
165
  loading="eager"
163
166
  />
164
167
  ) : null}
@@ -205,8 +208,9 @@ export const PrimaryHero: React.FC<PrimaryHeroProps> = props => {
205
208
  src={badgeImage}
206
209
  alt={"Badge"}
207
210
  className="absolute -left-26 top-18 aspect-square w-52 object-cover object-center"
208
- width={200}
209
- height={200}
211
+ width={208}
212
+ height={208}
213
+ quality={90}
210
214
  loading="eager"
211
215
  />
212
216
  ) : null}
@@ -217,6 +221,7 @@ export const PrimaryHero: React.FC<PrimaryHeroProps> = props => {
217
221
  className="aspect-square rounded-[40px] object-cover object-center"
218
222
  width={600}
219
223
  height={600}
224
+ quality={90}
220
225
  loading="eager"
221
226
  />
222
227
  ) : null}