Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v3 - support image assets from shared Sanity project #702

Merged
merged 5 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/blog/components/postCard/PostCard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";
import { SanityImage } from "src/components/image/SanityImage";
import Text from "src/components/text/Text";
import { useConvertSanityImageToNextImage } from "src/utils/hooks/useConvertImage";
import { Post } from "studio/lib/interfaces/pages";

import styles from "./postCard.module.css";
Expand All @@ -14,14 +14,13 @@ export const PostCard = ({
slug: string;
focusRef?: React.Ref<HTMLAnchorElement>;
}) => {
const renderedImage = useConvertSanityImageToNextImage(post.lead.image);
const postLink = `/${slug}/${post.slug.current}`;
return (
<li className={styles.cardWrapper}>
<a href={postLink} className={styles.card} ref={focusRef}>
{renderedImage && (
{post.lead.image && (
<div className={styles.image} aria-hidden={true}>
{renderedImage}
<SanityImage image={post.lead.image} />
</div>
)}
<Text type="caption">{post.category}</Text>
Expand Down
14 changes: 9 additions & 5 deletions src/blog/components/postPreview/PostPreview.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
"use client";
import { PortableTextBlock } from "sanity";

import { SanityImage } from "src/components/image/SanityImage";
import CustomLink from "src/components/link/CustomLink";
import { RichText } from "src/components/richText/RichText";
import Text from "src/components/text/Text";
import { useConvertSanityImageToNextImage } from "src/utils/hooks/useConvertImage";
import { LinkType } from "studio/lib/interfaces/navigation";
import { Post } from "studio/lib/interfaces/pages";

Expand All @@ -21,8 +21,6 @@ const PostPreview = ({
alignImageToRight = true,
slug,
}: PostPreviewProps) => {
const renderedImage = useConvertSanityImageToNextImage(post.lead.image);

const link = {
_key: "string",
_type: "string",
Expand Down Expand Up @@ -60,14 +58,20 @@ const PostPreview = ({

const truncatedText = truncateFirstBlock(post.lead.richText, 400);

const hasImage = post.lead.image !== undefined;

return (
<article className={styles.wrapper}>
<div
className={`${styles.postPreview} ${alignImageToRight ? styles.right : ""}`}
>
{renderedImage && <div className={styles.image}>{renderedImage}</div>}
{hasImage && (
<div className={styles.image}>
<SanityImage image={post.lead.image} />
</div>
)}
<div
className={`${styles.content} ${renderedImage ? styles.maxWidthSmall : styles.maxWidthLarge}`}
className={`${styles.content} ${hasImage ? styles.maxWidthSmall : styles.maxWidthLarge}`}
>
<div>
<Text type="caption">{post.category}</Text>
Expand Down
78 changes: 78 additions & 0 deletions src/components/image/SanityImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"use client";

import { SanityImageSource } from "@sanity/image-url/lib/types/types";
import Image from "next/image";
import { UseNextSanityImageProps, useNextSanityImage } from "next-sanity-image";
import { useEffect, useState } from "react";

import { client } from "studio/lib/client";
import { IImage } from "studio/lib/interfaces/media";
import { sharedClient } from "studioShared/lib/client";

/**
* Builds Next.js props for a given Sanity image from an unknown Sanity project.
*
* Each generated image source is checked for existence in order to pick the correct source project.
*
* NOTE: It is assumed that an image id is only valid for a single project.
* The result of providing an id that resolves to a valid image in multiple projects is therefore not well-defined.
*
* @param image asset props for image from unknown Sanity project
*/
const useNextSanityGlobalImage = (
image: SanityImageSource,
): UseNextSanityImageProps | null => {
const studioImage = useNextSanityImage(client, image);
const sharedImage = useNextSanityImage(sharedClient, image);

const [globalImage, setGlobalImage] =
useState<UseNextSanityImageProps | null>(null);

useEffect(() => {
fetch(studioImage.src).then((r) => r.ok && setGlobalImage(studioImage));
fetch(sharedImage.src).then((r) => r.ok && setGlobalImage(sharedImage));
}, [studioImage, sharedImage]);

return globalImage;
};

const SanityAssetImage = ({ image }: { image: IImage }) => {
const imageProps = useNextSanityGlobalImage(image);
const objectPosition = image.hotspot
? `${image.hotspot.x * 100}% ${image.hotspot.y * 100}%`
: "50% 50%"; // Default to center if no hotspot is defined
if (!imageProps) {
return null;
}
return (
<Image
alt={image?.alt || ""}
{...imageProps}
width={imageProps.width}
height={imageProps.height}
style={{
objectFit: "cover",
objectPosition,
maxWidth: "100%",
maxHeight: "100%",
height: "auto",
width: "auto",
}}
/>
);
};

export function SanityImage({ image }: { image: IImage }) {
if (image?.src) {
return (
<Image
alt={image?.alt || ""}
src={image.src.src}
style={{ objectFit: "cover", height: "100%" }}
mathiazom marked this conversation as resolved.
Show resolved Hide resolved
width={300}
height={300}
/>
);
}
return <SanityAssetImage image={image} />;
}
12 changes: 6 additions & 6 deletions src/components/navigation/footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

import { ReactNode } from "react";

import { SanityImage } from "src/components/image/SanityImage";
import CustomLink from "src/components/link/CustomLink";
import SoMeLink from "src/components/link/SoMeLink";
import Text from "src/components/text/Text";
import { useConvertSanityImageToNextImage } from "src/utils/hooks/useConvertImage";
import { BrandAssets } from "studio/lib/interfaces/brandAssets";
import { CompanyInfo } from "studio/lib/interfaces/companyDetails";
import { LegalDocument } from "studio/lib/interfaces/legalDocuments";
Expand All @@ -32,15 +32,15 @@ const Footer = ({
soMeData,
legalData,
}: IFooter) => {
const renderedLogo = useConvertSanityImageToNextImage(
brandAssets?.secondaryLogo,
);

const currentYear = new Date().getFullYear();

return (
<footer className={styles.footer}>
<div className={styles.logo}>{renderedLogo}</div>
{brandAssets?.secondaryLogo && (
<div className={styles.logo}>
<SanityImage image={brandAssets.secondaryLogo} />
</div>
)}
<nav className={styles.nav}>
{renderLinks(navigationData)}
{soMeData && renderSoMe(navigationData, soMeData)}
Expand Down
5 changes: 2 additions & 3 deletions src/components/navigation/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import { usePathname } from "next/navigation";
import { useEffect, useState } from "react";
import { FocusOn } from "react-focus-on";

import { SanityImage } from "src/components/image/SanityImage";
import LanguageSwitcher from "src/components/languageSwitcher/LanguageSwitcher";
import CustomLink from "src/components/link/CustomLink";
import LinkButton from "src/components/linkButton/LinkButton";
import { getHref } from "src/utils/get";
import { useConvertSanityImageToNextImage } from "src/utils/hooks/useConvertImage";
import { BrandAssets } from "studio/lib/interfaces/brandAssets";
import { ILink, Navigation } from "studio/lib/interfaces/navigation";
import { callToActionFieldID } from "studio/schemas/fields/callToActionFields";
Expand All @@ -29,7 +29,6 @@ export const Header = ({ data, assets }: IHeader) => {
const pathname = usePathname();
const [isOpen, setIsOpen] = useState(false);
const [isScrolled, setIsScrolled] = useState(false);
const renderedLogo = useConvertSanityImageToNextImage(assets?.primaryLogo);
const sidebarData = data.sidebar || data.main;

const links = filterLinks(data.main, linkID);
Expand Down Expand Up @@ -80,7 +79,7 @@ export const Header = ({ data, assets }: IHeader) => {
{assets?.primaryLogo && (
<div className={styles.logo}>
<Link href="/" aria-label="Home">
{renderedLogo}
<SanityImage image={assets.primaryLogo} />
</Link>
</div>
)}
Expand Down
13 changes: 6 additions & 7 deletions src/components/richText/RichText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { PortableText, PortableTextReactComponents } from "@portabletext/react";
import { ReactNode } from "react";
import { PortableTextBlock } from "sanity";

import { SanityImage } from "src/components/image/SanityImage";
import Text from "src/components/text/Text";
import textStyles from "src/components/text/text.module.css";
import { useConvertSanityImageToNextImage } from "src/utils/hooks/useConvertImage";
import { getReactNodeTextContent } from "src/utils/reactNode";

import styles from "./richText.module.css";
Expand All @@ -20,11 +20,6 @@ const formatId = (children: ReactNode): string => {
.replace(/[^\w-]+/g, "");
};

const SanityImage = ({ value }: { value: PortableTextBlock }) => {
const ImageElement = useConvertSanityImageToNextImage(value);
return <div className={styles.image}>{ImageElement}</div>;
};

const myPortableTextComponents: Partial<PortableTextReactComponents> = {
block: {
h2: ({ children }) => (
Expand Down Expand Up @@ -53,7 +48,11 @@ const myPortableTextComponents: Partial<PortableTextReactComponents> = {
number: ({ children }) => <li className={textStyles.body}>{children}</li>,
},
types: {
image: SanityImage,
image: ({ value }) => (
<div className={styles.image}>
<SanityImage image={value} />
</div>
),
},
};

Expand Down
12 changes: 6 additions & 6 deletions src/components/sections/article/Article.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use client";
import { SanityImage } from "src/components/image/SanityImage";
import CustomLink from "src/components/link/CustomLink";
import { RichText } from "src/components/richText/RichText";
import Text from "src/components/text/Text";
import { useConvertSanityImageToNextImage } from "src/utils/hooks/useConvertImage";
import { ArticleSection } from "studio/lib/interfaces/pages";

import styles from "./article.module.css";
Expand All @@ -12,16 +12,16 @@ interface ArticleProps {
}

const Article = ({ article }: ArticleProps) => {
const renderedImage = useConvertSanityImageToNextImage(
article?.imageExtended,
);

return (
<article className={styles.wrapper} id={article._key}>
<div
className={`${styles.article} ${article.imageExtended.imageAlignment == "right" ? styles.right : ""}`}
>
<div className={styles.image}>{renderedImage}</div>
{article?.imageExtended && (
<div className={styles.image}>
<SanityImage image={article.imageExtended} />
</div>
)}
<div className={styles.content}>
<div>
<Text type="caption">{article.tag}</Text>
Expand Down
9 changes: 6 additions & 3 deletions src/components/sections/grid/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import { PortableText, PortableTextReactComponents } from "@portabletext/react";
import { PortableTextBlock } from "sanity";

import { SanityImage } from "src/components/image/SanityImage";
import Text from "src/components/text/Text";
import { useConvertSanityImageToNextImage } from "src/utils/hooks/useConvertImage";
import { IImage } from "studio/lib/interfaces/media";
import { GridSection } from "studio/lib/interfaces/pages";

Expand Down Expand Up @@ -39,10 +39,13 @@ const Element = ({
image: IImage;
};
}) => {
const renderImage = useConvertSanityImageToNextImage(item.image);
return (
<li className={styles.listItem}>
{renderImage && <div className={styles.image}>{renderImage}</div>}
{item.image && (
<div className={styles.image}>
<SanityImage image={item.image} />
</div>
)}
<Text>{item.basicTitle}</Text>
{item.richText && (
<PortableText
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
"use client";
import { SanityImage } from "src/components/image/SanityImage";
import Text from "src/components/text/Text";
import { useConvertSanityImageToNextImage } from "src/utils/hooks/useConvertImage";
import { ImageSection } from "studio/lib/interfaces/pages";

import styles from "./imageSectionComponent.module.css";

const ImageSectionComponent = ({ section }: { section: ImageSection }) => {
const renderedImage = useConvertSanityImageToNextImage(section.image);
return (
<article className={styles.article}>
<Text type="h2">{section.basicTitle}</Text>
{renderedImage && <div className={styles.image}>{renderedImage}</div>}
{section.image && (
<div className={styles.image}>
<SanityImage image={section.image} />
</div>
)}
</article>
);
};
Expand Down
9 changes: 0 additions & 9 deletions src/components/sections/logoSalad/LogoRender.tsx

This file was deleted.

4 changes: 2 additions & 2 deletions src/components/sections/logoSalad/LogoSalad.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { PortableText, PortableTextReactComponents } from "@portabletext/react";

import { SanityImage } from "src/components/image/SanityImage";
import Text from "src/components/text/Text";
import { LogoSaladSection } from "studio/lib/interfaces/pages";

import { RenderLogo } from "./LogoRender";
import styles from "./logoSalad.module.css";

interface LogoSaladProps {
Expand Down Expand Up @@ -32,7 +32,7 @@ export const LogoSalad = ({ logoSalad }: LogoSaladProps) => {
(logo) =>
logo && (
<li key={logo._key}>
<RenderLogo asset={logo} />
<SanityImage image={logo} />
</li>
),
)}
Expand Down
10 changes: 0 additions & 10 deletions src/components/sections/testimonials/RenderAvatar.tsx

This file was deleted.

Loading