Git Product home page Git Product logo

next-sanity-image's People

Contributors

aaronbentley avatar alfredbirk avatar andershagbard avatar breadadams avatar bryndyment avatar elmarburke avatar fevernova90 avatar gpoole avatar jimcresswell avatar jndao avatar lime avatar lorenzodejong avatar semantic-release-bot avatar stipsan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

next-sanity-image's Issues

Make if more clear that default layout is "responsive" and not "intrinsic"

Hi, and thanks for a great work 👏

Is it possible to highlight more in the README that this library change the default layout from intrinsic to responsive? We find it very confusing now since the Next.js API documents intrinsic as default and it took quite a long time before we realized that this is changed to responsive by this library 😅

Argument of type "import('path/to/project/.../sanity/client) is not assignable to parameter of type import('path/to/project/.../sanity-next-image)

Since updating to Next 11, I am getting a Type error shown below:

Argument of type 'import("/path/to/project/node_modules/@sanity/client/sanityClient").SanityClient' is not assignable to parameter of type 'import("/path/to/project/node_modules/next-sanity-image/node_modules/@sanity/image-url/lib/types/types").SanityClient'.
  Types of property 'clientConfig' are incompatible.

My code:
sanity.ts:

import sanityClient from '@sanity/client'

export default sanityClient({
  projectId: 'projectId',
  dataset: 'production',
  useCdn: true,
})

component.ts:

...
const serializers = {
  {
    types: {
      image: function imageSerializer(props){
        const imageProps = useNextSanityImage(sanity, props.node)
        return (
          <div className="w-full rounded-lg">
            <Image {...imageProps} sizes="(max-width: 750) 100vw, 750px" />
          </div>
      )
      }
    }
  }
}
...

It seems like sanity/client and sanity-next-image are not having the same type for the sanity client object

Any help on how to fix this ?

Update to work with Next 12 and image transformations

👋

The fix for Next 12 does not remove all the warnings. If you use image transformations, you'll still see a lot of warnings because the imageBuilder returns a w instead of a width parameter.

We've discussed this with Sanity, and they suggest to manually add the width as a workaround that satisfies both Next.js and doesn't effect the image from Sanity.

Screenshot 2021-12-01 at 14 53 23

Hotspots and Crops not respected

If you have hotspots set or image is cropped using Sanity's built in tools, it's not respected with next-sanity-image. There should be a way to either automatically or via a prop use any crop or hotspots set by the Sanity user.

example schema:

import { FaRegImage } from "react-icons/fa";
export default {
  name: "figure",
  title: "Image",
  type: "image",
  options: {
    hotspot: true,   // if this is set to true, user can set hotspots and crop the image, so their selected preference should follow to display
    metadata: ["lqip"],
  },
  icon: FaRegImage,
  fields: [
    {
      name: "alt",
      type: "string",
      title: "Alternative text",
      description: "Important for SEO and accessibility. Describe the image",
      options: {
        isHighlighted: true,
      },
      validation: (Rule) => [Rule.required().error("You need to set Alt text")],
    },
  ],
  preview: {
    select: {
      imageUrl: "asset.url",
      title: "alt",
    },
  },
};

Image with src has unused properties assigned. Please remove "width" and "height".

Warning:

Image with src "https://cdn.sanity.io/images/blabla-667x500.jpg?q=75&fit=clip&auto=format" and "layout='fill'" has unused properties assigned. Please remove "width" and "height".

When using the plugin like this:

{coverImage && imageUrl && (
  <Image {...coverImageProps} alt={alt} layout="fill" objectFit="cover" />
)}

Hotspot and Crop

After trying for a long time to make the crop and hotspot work, I finally landed on a solution.

This ticket aims to help others facing the same issue, but I also believe that the docs should be updated accordingly.

For the hotspot I managed to get it working using the solution by @danieljb #32 (comment)

Hi @zRelux, as far as I understand this library does not respect Sanity’s hotspot feature.

A quick workaround is to set objectPosition calculated from Sanity’s image data:

import Img from "next/image";
import { useNextSanityImage } from "next-sanity-image";

// untested
function ImageComponent({ image }) {
  /*
    {
      "_type": "image",
      "asset": {
        "_ref": "image-[…]-jpg",
        "_type": "reference"
      },
      "crop": {
        "_type": "sanity.imageCrop",
        "bottom": 0,
        "left": 0,
        "right": 0,
        "top": 0
      },
      "hotspot": {
        "_type": "sanity.imageHotspot",
        "height": 0.07233187772925773,
        "width": 0.07423580786026142,
        "x": 0.5611353711790394,
        "y": 0.7135109170305682
      }
    }
  */
  const imageProps = useNextSanityImage(client, image);

  const attributes = {};
  if (image.hotspot?.x && image.hotspot?.y) {
    const { x, y } = image.hotspot;
    attributes.objectPosition = `${x * 100}% ${y * 100}%`;
  }
  return (
    <Image {...imageProps} {...attributes} />
  );
}

This only works in certain layout and objectFit combinations and depends on CSS styling (e.g. whether the image component is constraint to an aspect ratio). Note, this does not take the hotspot ellipse (width and height attributes) into account.

I tried to use a custom url builder to apply image transformations as described in the README but that did not work without manually passing in fit=crop&crop=focalpoint&fp-x=${image.hotspot.x}&fp-y=${image.hotspot.y} and disregards the hotspot ellipse, too. There also seems to be a bug #24 pending in Sanity’s image-url.

And for the crop, I got it working by changing the default fit behavior from the lib to 'crop':

const imageProps = useNextSanityImage(client, image, {
  imageBuilder: (imageUrlBuilder) => imageUrlBuilder.fit('crop'),
})

Based on this solution, I created this generic Image component that is working perfectly for me so far:

'use client' // Remove this line if you are not using the experimental 'app' folder from Next 13

import { useNextSanityImage } from 'next-sanity-image'
import Img from 'next/image'

import { SanityImageObject } from '@sanity/image-url/lib/types/types'
import client from 'client'

type Props = {
  image?: SanityImageObject & { alt?: string }
  className?: string
}

const Image = ({ image, className }: Props) => {
  const imageProps = useNextSanityImage(client, image, {
    imageBuilder: (imageUrlBuilder) => imageUrlBuilder.fit('crop'),
  })

  if (!image?.asset) return <></>

  let objectPosition = undefined

  if (image.hotspot?.x && image.hotspot?.y) {
    const { x, y } = image.hotspot
    objectPosition = `${x * 100}% ${y * 100}%`
  }
  
  return (
    <Img
      {...imageProps}
      style={{ objectFit: 'cover', objectPosition: objectPosition }}
      alt={image.alt ?? ''}
      className={className}
      sizes="(max-width: 800px) 100vw, 800px"
    />
  )
}

export default Image

Hopefully this will help others :)

Possibility to combine next-sanity-image with block-content-to-react

I am trying to render block content via Next.js. block-content-to-react works wonderfully, but unfortunately uses standard HTML <img> tags. I am not too familiar with BlockContent serializers. I am wondering if this library exposes a default serializer you can use, or if there is example code available with how to write a custom serializer with this library.

Getting exception `configuration must contain projectId`

Using a very basic configuration, I get an exception configuration must contain projectId. see below for usage. absolutely certain that the instantiated sanityClient is working since all my groq queries are fine. Is there anything that I might be missing?

sanity/client 2.1.4
next 10.0.5

// Image wrapper
import Img from 'next/image';
import {useNextSanityImage} from 'next-sanity-image';
import sanityClient from '@/services/sanityClient';

const Image = ({src}) => {
  const imageProps = useNextSanityImage(sanityClient, src);

  return <Img {...imageProps} />;
};

export default Image;

Loading assets twice

First, thanks for the hook! Currently using it as described in the documentation, but just noticed that it's loading assets twice!

it loads e.g. w=3840 and w=1920

using these props

{...imageProps} // the output of useNextSanityImage
sizes="(max-width: 800px) 100vw, 800px"

image

Responsive example not working

Whenever I add the images part to my next.config.js:

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
  images: {
    domains: ["cdn.sanity.io"],
    loader: "custom",
  },
};

module.exports = nextConfig;

The following message pops up:

error - Error: Image with src "[object Object]" is missing "loader" prop.
Read more: https://nextjs.org/docs/messages/next-image-missing-loader
    at Image (webpack-internal:///./node_modules/next/dist/client/image.js:64:19)
}
null

Do I need some additional configuration somewhere?

Next 14 breaks with next-sanity-image when deployed to Vercel

Hello,

After updating to NextJS 14, my project in which next-sanity-image is a dependency broke when deploying to Vercel.

Error log below:

next-sanity-image-error

Currently working around this by setting "npm install --legacy-peer-deps" in the Vercel Build & Development Settings for the project.

Can't use `.height()` in `imageBuilder`

Setting .height(...) in options.imageBuilder results in "stretched" images, even with position: relative set to a parent element, likely due to the <Image/> component from next/image not being able to handle explicit heights.

FYI: Use in conjunction with .width(...) (e.g. .width(200).height(200)) does get expected results — a 200x200 px image.

Best way to filter empty image fields?

Hi,
Previously I have been using the Sanity UrlBuilder and filtering empty fields from there:

import imageUrlBuilder from '@sanity/image-url'
import sanityClient from '../client'
import BlockContent from '@sanity/block-content-to-react'

export default function Blurb({ blurb }) {
  const builder = imageUrlBuilder(sanityClient)

  function urlFor(source) {
    if (!source) {
      return
    } else {
      return builder.image(source)
    }
  }

  return (
    <>
      <img src={urlFor(blurb.mainImage)} />
      <h1>{blurb.heading}</h1>
      <div><BlockContent blocks={blurb.body} /></div>
    </>
  )
}

However I'm having a lot of trouble working out how to do this using the next-sanity plugin. Sorry for this, I am quite new.

Webp on supported browsers

First of all, thanks a lot for this plugin. It makes things easy.

next/image supports conversion to webp format on supported browsers. Similarly, Sanity also supports webp transformations. So, how can I use that feature while using your plugin? is it possible now? if yes, can you show an example? webp on modern browsers, JPG on old/unsupported browsers.

If no, I have realized you are also planning for a v2 release. Would you consider this feature as well?

Thanks again

~Surjith

Bundle image as static asset

Is there a way to download the static image and bundle it into the build assets? I would like to bundle my static assets in with my website when I build it and deploy to a static host (s3).

Currently I can reference images by the Sanity CDN but I'd rather these are on my own URL rather than the Sanity CDN.

Typescript: Issue with StaticImport type

Hi there!

It seems like something with Next/Image's complex types is causing some trouble with the next-sanity-image library (screenshot below.)

It seems like no matter what useNextSanityImage returns, next/image gets mad that src is a string instead of a StaticImport. Any typescript guidance would be appreciated!

Error screenshot:
image

Relevant Code
import { ImageUrlBuilder } from '@sanity/image-url/lib/types/builder'
import { SanityImageSource } from '@sanity/image-url/lib/types/types'
import { useNextSanityImage, UseNextSanityImageBuilderOptions } from 'next-sanity-image'
import Image from 'next/image'
import React, { FunctionComponent } from 'react'
import configuredSanityClient from './sanity'

// This custom url builder insists on using the images' width as the max width instead of scaling the image up.
// It's likely that we'll need to use different imgBuilders with different behaviors for different Next/Image layout types
const customImageURLBuilder = (
  imageUrlBuilder: ImageUrlBuilder,
  options: UseNextSanityImageBuilderOptions,
) => {
  return imageUrlBuilder
    .width(
      options.width && options.width != 0
        ? Math.min(options.originalImageDimensions.width, options.width)
        : options.originalImageDimensions.width,
    )
    .auto('format')
}

const NextSanityImageWithCustomBuilder = (image: SanityImageSource) =>
  useNextSanityImage(configuredSanityClient, image, {
    imageBuilder: customImageURLBuilder as any,
    enableBlurUp: false
  })

type NextSanityImageProps = {
  alt?: string,
  image: SanityImageSource,
  layout?: 'fill' | 'fixed' | 'intrinsic' | 'responsive' | undefined
}

const NextSanityImage: FunctionComponent<NextSanityImageProps> = ({
  image,
  layout = 'intrinsic',
  alt,
  ...rest
}) => {
  const imageProps = NextSanityImageWithCustomBuilder(image)

  if (layout === 'fill') {
    return (
      <Image
        {...imageProps}
        data-gumlet="false"
        layout="fill"
        alt={alt}
        {...rest}
        width={undefined}
        height={undefined}
      />
    )
  } else {
    return (
      <Image alt={alt} {...imageProps} data-gumlet="false" layout={layout} {...rest} />
    )
  }
}

export default NextSanityImage

useSanityNextImage: TypeScript error "No overload matches this call"

Hey, thank you for your work on this library, it makes working with Sanity assets in Next.js a breeze 😃

I'm trying building an image component, but I'm running into a TypeScript error that I'm not sure how to resolve (I'm still learning TypeScript so please bear with me).

TypeScript is yelling at me, with the error message of:

No overload matches this call.

Overload 1 of 3, '(sanityClient: SanityClientLike, image: null, options?: UseNextSanityImageOptions | undefined): null', gave the following error.
    Argument of type 'SanityClient' is not assignable to parameter of type 'SanityClientLike'.
      Property 'clientConfig' is missing in type 'SanityClient' but required in type 'SanityClientLike'.

Overload 2 of 3, '(sanityClient: SanityClientLike, image: SanityImageSource, options?: UseNextSanityImageOptions | undefined): UseNextSanityImageProps', gave the following error.
    Argument of type 'SanityClient' is not assignable to parameter of type 'SanityClientLike'.

Overload 3 of 3, '(sanityClient: SanityClientLike, image: SanityImageSource | null, options?: UseNextSanityImageOptions | undefined): UseNextSanityImageProps | null', gave the following error.
    Argument of type 'SanityClient' is not assignable to parameter of type 'SanityClientLike'.

Here's my code so far:

'use client'
import {
    ImageUrlBuilder,
    useNextSanityImage,
    UseNextSanityImageBuilderOptions,
    UseNextSanityImageProps
} from 'next-sanity-image'
import { default as NextImage } from 'next/image'
import { sanityClient } from '../../lib/sanity.client'

type ImageProps = {
    image: {
        asset: {
            altText?: string
            metadata: {
                lqip: string
                palette: {
                    dominant: {
                        background: string
                    }
                }
            }
        }
        [key: string]: any
    }
    priority?: boolean
    [key: string]: any
}

/**
 * Image component, composes NextImage
 */
const Image = ({ image, priority = false, ...rest }: ImageProps) => {
    /**
     * Get Sanity image props, allowing for custom imageBuilder transforms
     */
    const imageProps: UseNextSanityImageProps = useNextSanityImage(
        sanityClient,  // ⛔️ <- Here's where TypeScript yells at me!
        image,
        {
            imageBuilder: (
                imageUrlBuilder: ImageUrlBuilder,
                options: UseNextSanityImageBuilderOptions
            ) => {
                /**
                 * Destructure options
                 */
                const {
                    width = undefined,
                    // originalImageDimensions = {},
                    // croppedImageDimensions = {},
                    quality = undefined
                } = options

                return imageUrlBuilder
                    .width(
                        width ||
                            Math.min(
                                options.originalImageDimensions.width,
                                1920
                            )
                    )
                    .quality(quality || 75)
                    .fit('clip')
            }
        }
    )

    /**
     * If no image/asset props return null
     */
    if (!imageProps) return null

    /**
     * Destructure asset props
     */
    const {
        asset: {
            altText = '',
            metadata: {
                lqip = '',
                palette: {
                    dominant: { background = '' }
                }
            }
        }
    } = image

    return (
        <div className='relative block h-[50vh] w-screen'>
            <NextImage
                src={imageProps.src}
                loader={imageProps.loader}
                alt={altText}
                priority={priority}
                fill
                sizes='(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw'
                placeholder='blur'
                blurDataURL={lqip}
                quality={90}
                style={{
                    objectFit: 'cover',
                    backgroundColor: background
                }}
                {...rest}
            />
        </div>
    )
}

export default Image

And here's the file I define the Sanity Client config:

import { createClient } from 'next-sanity'

export const projectId = process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!
export const dataset = process.env.NEXT_PUBLIC_SANITY_DATASET!
export const apiVersion = process.env.NEXT_PUBLIC_SANITY_API_VERSION!

export const sanityClient = createClient({
    projectId,
    dataset,
    apiVersion,
    useCdn: false
})

Whereabouts am I going wrong here? Have I missed something kinda silly? I'm assuming it's something I've missed or typed incorrectly?

I've only been working with TypeScript for a few weeks, here's hoping someone can educate me & point me in the right direction 🤞

Need a solution when the image object is empty

Hello, thanks for your work, but I noticed when the "image" object is empty javascript crashes.
Eg. I have a Hero component that it should have or not the image. How can I handle it? Thanks.

Rendering an Image from a Portable Text Field

Hoping you or someone else might be able to help me better understand the expected behavior when using next-sanity-image on an image block from a portable text field....to determine if my issues are resolvable.

For some reason, no matter what I do, I have images being served from Sanity's CDN. Even when I explicitly set useCdn to false. The lqip feature and blur up is also not working.

I use next-sanity-image as following in a component called PortableTextImage.js

import sanityClient from '@lib/sanityClient';
import Image from 'next/image';
import { useNextSanityImage } from 'next-sanity-image';

const PortableTextImage = (props) => {
  const configuredSanityClient = sanityClient;
  const imageProps = useNextSanityImage(configuredSanityClient, props);
  const caption = props.description || (props.asset && props.asset.description) || null;

  return (
    <div className="md:-mx-16 lg:-mx-32">
      <Image
        {...imageProps}
        className="w-full"
        sizes="(max-width: 800px) 100vw, 1200px"
        blurDataURL="props.lqip"
        placeholder="blur"
        // render an alt tag conditionally
        alt={props.alt || props.description || props.asset.alt || props.asset.title || props.asset.description || 'Sorry, alt text for this image is missing.'}
      />
      {caption ? ( 
        <div className="text-sm lg:text-lg font-serif italic -mt-4 text-stone-500 relative md:mx-16 lg:mx-32">{caption}</div>
      ) : null}
    </div>
  );
};

export default PortableTextImage;

My image renders as follows...

Screenshot 2023-04-13 at 15 31 00

...and again, no lqip ...I am throttling the connection to confirm. I took this from development but it's the same in production.

Other relevant pieces of this puzzle might include my use of react-portable-text, used as follows to pass / parse the field and use my PortableTextImage component.

{pageData.body ? (
  <PortableText
    content={pageData.body}
    projectId={process.env.NEXT_PUBLIC_SANITY_PROJECT_ID}
    dataset={process.env.NEXT_PUBLIC_SANITY_DATASET}
    serializers={{
      image: (props) => {
        return <PortableTextImage {...props} />;
      },
    }}
  />
) : null}

Since you just bumped the version I thought I should dbl check that I am using it correctly and have not stumbled on to a bug.

Setting fill property to true produces error (Next 13)

Heya - I've just upgraded to Next 13, all seems good except for images that were previously using layout=fill which has been deprecated for the boolean fill property.

Setting fill to true results in an error: "Image ... has both "width" and "fill" properties. Only one should be used." Could next-sanity-image treat fill the same as layout=fill and omit the width and height properties please? Thanks!

Spike in Sanity Bandwidth

Has anyone seen a spike in sanity bandwidth after installing and implementing this package. I have installed this package last year around September and seen significant upward trend in bandwidth of Sanity.

Just want to understand if this package is causing this issue.

Error on deploy, Conflic sanity-client

While resolving: [email protected]

05:15:03.422 | npm ERR! Found: @sanity/[email protected]
05:15:03.423 | npm ERR! node_modules/@sanity/client
05:15:03.423 | npm ERR! @sanity/client@"^6.1.0" from the root project
05:15:03.423 | npm ERR! @sanity/client@"^6.0.0" from @sanity/[email protected]
05:15:03.423 | npm ERR! node_modules/@sanity/preview-kit
05:15:03.424 | npm ERR! @sanity/preview-kit@"^1.5.0" from [email protected]
05:15:03.424 | npm ERR! node_modules/next-sanity
05:15:03.424 | npm ERR! next-sanity@"^4.3.2" from the root project
05:15:03.424 | npm ERR! 1 more (next-sanity)
05:15:03.424 | npm ERR!
05:15:03.424 | npm ERR! Could not resolve dependency:
05:15:03.424 | npm ERR! peer @sanity/client@"^5.0.0" from [email protected]
05:15:03.425 | npm ERR! node_modules/next-sanity-image
05:15:03.425 | npm ERR! next-sanity-image@"^6.0.0" from the root project
05:15:03.425 | npm ERR!
05:15:03.426 | npm ERR! Conflicting peer dependency: @sanity/[email protected]
05:15:03.426 | npm ERR! node_modules/@sanity/client
05:15:03.426 | npm ERR! peer @sanity/client@"^5.0.0" from [email protected]
05:15:03.426 | npm ERR! node_modules/next-sanity-image
05:15:03.426 | npm ERR! next-sanity-image@"^6.0.0" from the root project

Catch Image.asset not found error

I'm getting the following error when we pass image.alt but not image.asset. This plugin should send appropriate error when image.asset is not found.

image

In my code, I cannot do the following because hooks cannot call conditionally.

// This won't work
// Not able to call hooks conditionally. 

  if (!image.asset) {
    return null;
  }
 const imageProps = useNextSanityImage(client, image, {
    imageBuilder: CustomImageBuilder
  });

Image data is output in <noscript> but otherwise doesn't show up

Hey, I'm having an issue I'm sure is down to me doing something wrong, but hoped someone might be able to help?

The image data appears in the tag's, and as a blurred placeholder, but ultimately doesn't load up.

Here's what is output:

<div class="image">
  <span
    style="
      box-sizing: border-box;
      display: block;
      overflow: hidden;
      width: initial;
      height: initial;
      background: none;
      opacity: 1;
      border: 0;
      margin: 0;
      padding: 0;
      position: relative;
    "
    ><span
      style="
        box-sizing: border-box;
        display: block;
        width: initial;
        height: initial;
        background: none;
        opacity: 1;
        border: 0;
        margin: 0;
        padding: 0;
        padding-top: 81.2%;
      "
    ></span
    ><img
      src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
      decoding="async"
      data-nimg="responsive"
      style="
        position: absolute;
        top: 0;
        left: 0;
        bottom: 0;
        right: 0;
        box-sizing: border-box;
        padding: 0;
        border: none;
        margin: auto;
        display: block;
        width: 0;
        height: 0;
        min-width: 100%;
        max-width: 100%;
        min-height: 100%;
        max-height: 100%;
        filter: blur(20px);
        background-size: cover;
        background-image: url('https://cdn.sanity.io/images/vua524it/production/0ebc49d206053e55855555e84ac6440e90e9b77c-1000x812.png?w=64&amp;blur=50&amp;q=30&amp;fit=clip&amp;auto=format');
        background-position: 0% 0%;
      " />
      <noscript>
        <img
          sizes="(max-width: 1280px) 100vw, 1280px"
          srcset="
            https://cdn.sanity.io/images/vua524it/production/0ebc49d206053e55855555e84ac6440e90e9b77c-1000x812.png?w=640&amp;q=75&amp;fit=clip&amp;auto=format 640w,
            https://cdn.sanity.io/images/vua524it/production/0ebc49d206053e55855555e84ac6440e90e9b77c-1000x812.png?w=750&amp;q=75&amp;fit=clip&amp;auto=format 750w,
            .....etc.....
          "
          loading="lazy"
        />
      </noscript>
  </span>
</div>

And here's my component:

import { useNextSanityImage } from "next-sanity-image";
import Image from "next/image";

import { sanityConfig } from "../../../lib/config";
import { Headline } from "../../elements/Headline";
import * as S from "./Italy.styles";
import { Pattern } from "./Pattern";

export function Italy({ data }) {
  const imageProps = useNextSanityImage(sanityConfig, data?.image);

  console.log(imageProps);

  return (
    <S.Italy>
      <div className="content">
        <Headline data={{ headline: data?.headline }} />
      </div>

      <div className="image">
        <Image
          {...imageProps}
          layout="responsive"
          sizes="(max-width: 1280px) 100vw, 1280px"
        />
      </div>

      <Pattern />
    </S.Italy>
  );
}

And finally, the output of the console.log(imageProps):

{
    "src": "https://cdn.sanity.io/images/vua524it/production/0ebc49d206053e55855555e84ac6440e90e9b77c-1000x812.png?q=75&fit=clip&auto=format",
    "width": 1000,
    "height": 812,
    "blurDataURL": "https://cdn.sanity.io/images/vua524it/production/0ebc49d206053e55855555e84ac6440e90e9b77c-1000x812.png?w=64&blur=50&q=30&fit=clip&auto=format",
    "placeholder": "blur"
}

How to use with existing Next Images

Currently getting Image with src "/_next/static/media/logo.215ee7a5.png" is missing "loader" prop.

How to make it compatible with already existing Next Images?

Erronous placeholder type!

Hi!

Ran into an issue when using this library with the type definition for placeholder which doesn't match up with the one in next/image. According to their doc it isn't a string, but instead 'blur' | 'empty' | undefined.

I put in a workaround with a typeguard in my project, but i figured i'd let you know.

https://github.com/bundlesandbatches/next-sanity-image/blob/cfb99cfa8f9cfd993e1f4c07bcd5667b09826ddf/src/types.ts#L53

Here is the next docs for this prop

Keep up the good work ✨

Problems processing multiple urls in the same component

Hi,
Thanks for your work on the plugin : )
I'm trying to process a bunch of "product" images and came up with this function:

  function imageProps(i, imgNumber) {
    return useNextSanityImage(
        sanityClient,
        products[i].[imgNumber]
      )
  }

however when I try to call it more than once in the component I get this error:
Unhandled Runtime Error

Error: Rendered more hooks than during the previous render.
Source

components/ProductSliders.js (11:8) @ imageProps

   9 | function imageProps(i, imgNumber) {
  10 |   return useNextSanityImage(
> 11 |       sanityClient,
     |      ^
  12 |       products[i].[imgNumber]
  13 |     )
  14 | }

Your help much appreciated.

TypeScript Types Don't Allow `enableBlurUp` to be False

Versions

The Error

const imageProps = useNextSanityImage(
  sanityClient,
  image,
  {
    enableBlurUp: false,
  },
);
error TS2769: No overload matches this call.
  Overload 1 of 2, '(sanityClient: SanityClientLike, image: SanityImageSource | null, options?: (UseNextSanityImageOptions & { enableBlurUp?: true | undefined; }) | undefined): (Required<...> & { ...; }) | null', gave the following error.
    Argument of type '{ blurUpImageWidth: number; blurUpImageQuality: number; blurUpAmount: number; } | { enableBlurUp: false; }' is not assignable to parameter of type '(UseNextSanityImageOptions & { enableBlurUp?: true | undefined; }) | undefined'.
      Type '{ enableBlurUp: false; }' is not assignable to type 'UseNextSanityImageOptions & { enableBlurUp?: true | undefined; }'.
        Type '{ enableBlurUp: false; }' is not assignable to type '{ enableBlurUp?: true | undefined; }'.
          Types of property 'enableBlurUp' are incompatible.
            Type 'false' is not assignable to type 'true | undefined'.
  Overload 2 of 2, '(sanityClient: SanityClientLike, image: SanityImageSource | null, options?: (UseNextSanityImageOptions & { enableBlurUp: false; }) | undefined): (Omit<...> & { ...; }) | null', gave the following error.
    Argument of type '{ blurUpImageWidth: number; blurUpImageQuality: number; blurUpAmount: number; } | { enableBlurUp: false; }' is not assignable to parameter of type '(UseNextSanityImageOptions & { enableBlurUp: false; }) | undefined'.
      Type '{ blurUpImageWidth: number; blurUpImageQuality: number; blurUpAmount: number; }' is not assignable to type 'UseNextSanityImageOptions & { enableBlurUp: false; }'.
        Property 'enableBlurUp' is missing in type '{ blurUpImageWidth: number; blurUpImageQuality: number; blurUpAmount: number; }' but required in type '{ enableBlurUp: false; }'.

The Source

Here are the types in the current version of the NPM package:

import { SanityClientLike, SanityImageSource } from '@sanity/image-url/lib/types/types';
import { UseNextSanityImageDimensions, UseNextSanityImageOptions, UseNextSanityImageProps } from './types';
export declare const DEFAULT_BLUR_UP_IMAGE_WIDTH = 64;
export declare const DEFAULT_BLUR_UP_IMAGE_QUALITY = 30;
export declare const DEFAULT_BLUR_UP_AMOUNT = 50;
export declare const DEFAULT_FALLBACK_IMAGE_WIDTH = 1920;
export declare const DEFAULT_FALLBACK_IMAGE_QUALITY = 75;
export declare function getImageDimensions(image: SanityImageSource): UseNextSanityImageDimensions;
export declare function useNextSanityImage(sanityClient: SanityClientLike, image: SanityImageSource | null, options?: UseNextSanityImageOptions & {
    enableBlurUp?: true;
}): (Required<UseNextSanityImageProps> & {
    placeholder: 'blur';
}) | null;
export declare function useNextSanityImage(sanityClient: SanityClientLike, image: SanityImageSource | null, options?: UseNextSanityImageOptions & {
    enableBlurUp: false;
}): (Omit<UseNextSanityImageProps, 'blurDataURL'> & {
    placeholder: 'empty';
}) | null;

The Possible Fix

I believe the issue is that enableBlurUp: false should be enableBlurUp?: false.

Typescript is complaining when the image argument is "string | null"

Hello,

I'm creating a component that may or may not receive an image from Sanity, so the image type is "string | null". However TS is not happy with it (using version 3.1.4), as I get Argument of type 'string | null' is not assignable to parameter of type 'null'. Type 'string' is not assignable to type 'null'. when passing the image to useNextSanityImage. It does the same if I replace string by SanityImageSource.

As the hook can handle null images, it should be ok to pass this argument, shouldn't it?

Document that @sanity/client is not strictly needed

I'm using the package without @sanity/client by providing a SanityClientLike object without problems.

As I'm using graphql I didn't want to bring in the entire sanity client (and rxjs etc), but I didn't realise the first time around that I was able to just provide the project/dataset configuration myself and skip the client

This works just fine for me:

const clientLike: SanityClientLike = {
  clientConfig: {
    projectId: "my-project",
    dataset: "my-dataset",
    apiHost: "https://cdn.sanity.io",
  },
};

const imageProps = useNextSanityImage(clientLike, image);

Happy to make a PR documenting it, although as I saw there's some issues about client versions you could probably go as far as removing it as a peerDep

How to use useNextSanityImage() when image might be undefined

Hi!

I have a case where the sanity image asset might be undefined. I tried to get around this by setting null conditionally:

const imgProps = useNextSanityImage(sanityClient, image ?? null)

But I then get the following TS error: Type 'null' is not assignable to type 'SanityImageSource'.

Is there any workaround for this case?

Image with src has a "loader" property that does not implement width.

Getting the following error when using next-sanity-image with "next": "^11.1.0",

Code:

const imgOpts = (transform) => transform.width(1920).height(1080).fit('crop');

export default function Component() {
  const imageProps = useImage(data.backgroundImage, imgOpts);
  return (
    <Img
      {...imageProps}
    />
  )
}

Console:

instrument.js?ea14:109 Image with src "[sanityUrl].jpg?rect=0,137,2640,1485&w=1920&h=1080&q=80&fit=crop&auto=format&dpr=2" has a "loader" property that does not implement width. Please implement it or use the "unoptimized" property instead.
Read more: https://nextjs.org/docs/messages/next-image-missing-loader-width 
    at Image (webpack-internal:///./node_modules/next/dist/client/image.js:307:20)

The error also links to the following page: https://nextjs.org/docs/messages/next-image-missing-loader-width
This warning was recently added in vercel/next.js#26998

Is it possible to use this feature as a pure function rather than a hook?

Hi, thank you for creating this awesome tool, it saved my time.

According to the return type is UseNextSanityImageProps, I'd wonder if it is possible to run the main function inside getStaticProps ? If that's possible, we won't need to include SanityClient into our front-end bundle, we can get the imageProps within build time or server side. Thanks.

TypeError: Cannot assign to read only property 'crop' of object '#<Object>'

Hi, thanks for a nice library!

Today I've ran into a problem though - my client uploaded PNG to Sanity and the Next.js Typescript app failed with the following error: TypeError: Cannot assign to read only property 'crop' of object '#<Object>'.

This is the image in question that I receive from BE (and which I pass as the hook's argument):

{
  _type: 'image',
  asset: {
    _ref: 'image-f5d4883f18beaed14143983cad78110e4e81ce93-1920x969-png',
    _type: 'reference'
  },
  crop: {
    _type: 'sanity.imageCrop',
    bottom: 0,
    left: 0.001763668430335097,
    right: 0,
    top: 0
  },
  hotspot: {
    _type: 'sanity.imageHotspot',
    height: 1,
    width: 0.998236331569665,
    x: 0.5008818342151675,
    y: 0.5
  }
}

This is how I use the hook: useNextSanityImage(sanityClient, props.image);. When I try/catch the error, I see that the hook returns null. Also I do not have any problem with any other image across the whole app.

"next-sanity-image": "^3.1.5"

Am I missing something obvious? Thanks in advance!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.