npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@biggleszx/react-sanity-image

v0.3.0

Published

Simple React components for presenting images from Sanity

Downloads

105

Readme

react-sanity-image

Simple React components for making use of images hosted on the Sanity.io CDN. I'm using Next.js and didn't really like the extra markup and apparent complexity of next/image so decided to try to create some simple components to provide some of that functionality at lower cognitive cost, and without being Next-specific. I'm not sure if this was a good decision. This package provides:

  • An Img component that generates srcset values for a specified range of image widths (or a sensible defaults in DEFAULT_SOURCE_WIDTHS).
  • Also accepts an optional aspectRatio prop to ensure generated images are cropped to a specific ratio.
  • A Picture component that wraps the above, providing a media prop allowing different aspect ratios to be specified for different media conditions, to satisfy the art-direction use-case.
  • Images support optional lqip prop which displays the image's Low Quality Image Placeholder as a background-image.
  • Images support WebP format using Sanity's automatic content negotiation.
  • Images have width and height attributes set automatically based on the supplied aspectRatio or intrinsic size of the image, to prevent layout shifts.

This package is currently distributed in ES Module and CommonJS formats. This is my first npm package and I don't really know what I'm doing but those two options seemed popular. Structure of this package and README is inspired by next-sanity-image, with thanks.

Installation

npm install --save @biggleszx/react-sanity-image

The components require you to pass in a SanityClient instance, so you'll also need to install that if you haven't already:

npm install --save @sanity/client

Usage

Import the component(s) you want to use:

const { Img, Picture } = require('@biggleszx/react-sanity-image');
// or
import { Img, Picture } from '@biggleszx/react-sanity-image';

Instantiate the Sanity client (see the SanityClient docs for more information about the properties used):

const client = sanityClient({
    projectId: 'xxxxxxxx',
    dataset: 'production',
    apiVersion: '2022-03-14',
    useCdn: true,
});

Assuming you've already queried a document from Sanity that includes an image field (there's an example here; let's say it's person and the field is person.image), render the Img component like this:

// Basic usage at intrinsic aspect ratio
<Img
    client={client}
    image={person.image}
/>

// Passing options to the URL builder, including `sourceWidths` to override `DEFAULT_SOURCE_WIDTHS`
<Img
    client={client}
    image={person.image}
    builderOptions={{
        blur: 50,
        sourceWidths: [100, 200, 300],
    }}
/>

// Specifying aspect ratio and `sizes` attribute, and enabling `lqip`
<Img
    client={client}
    image={person.image}
    aspectRatio={9/16}
    sizes="50vw"
    lqip
/>

// Any other props will be passed to the rendered `<img>` element
<Img
    client={client}
    image={person.image}
    alt={person.name}
    loading="lazy"
/>

The Picture component is similar but supports an additional media prop for adding extra sources:

<Picture
    client={client}
    image={person.image}
    aspectRatio={1/1}
    media={[{
        media: '(min-width: 1024px)',
        aspectRatio: 9/16,
    }]}
    sizes="(min-width: 1024px) 50vw, 100vw"
/>

It also supports builderOptions like Img does, which will be applied to all URLs that are created:

<Picture
    client={client}
    image={person.image}
    builderOptions={{
        blur: 50
    }}
/>

Order of media items matters the same way ordering source elements inside <picture> matters (i.e. the browser will use the first match that it encounters).

Sanity's CDN will automatically serve WebP format images to browsers that support them, so there's no need to include any extra sources for these (you can't specify the type attribute at the moment anyway).

Finally, any extra props passed to Picture will be set on the rendered <picture> element. If you want to specify extra props for the <img> element inside it, use imgProps:

<Picture
    client={client}
    image={person.image}
    className="my-picture-class"
    imgProps={{
        alt: person.name,
        loading: 'lazy',
    }}
/>

Development

Clone the project, activate nvm, if that's your thing, and install:

$ git clone [email protected]:BigglesZX/react-sanity-image.git
$ cd react-sanity-image
$ nvm use  # `nvm install` if necessary
$ npm install

Storybook is included to facilitate local development and testing. You'll need to configure a connection to a Sanity project from which an image asset can be retrieved for use in stories.

Copy the included .env.example file to .env and edit it to add your project details and the ID of an asset to fetch. You can find one by querying imageAsset documents within your project (*[_type == "sanity.imageAsset"]).

SANITY_PROJECT_ID="xxxxxxxx"
SANITY_DATASET="production"
SANITY_ASSET_ID="image-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-1024x1024-jpg"

Add the contents of the .env file to your environment using whatever means you like (dotenv, etc) – the simplest way is to source the file in Bash-like shells:

$ source .env

Lastly you'll need to allow CORS access to Sanity from the Storybook instance. Head to the Sanity management dashboard, click on your project, then choose the API tab and click CORS origins. Click Add CORS origin and enter http://localhost:6006 (or other Storybook origin). You don't need to allow credentials.

Start Storybook:

$ npm run storybook

API

Img

| property | type | description | | ---------------- | ---- | ----------- | | client | SanityClient | Client instance to use when building image URLs | | image | SanityImageSource | A reference to a Sanity image asset. You can pass in any asset that is also supported by the image() method of @sanity/image-url. | | aspectRatio | number | null | Aspect ratio (height ÷ width) to which the source image should be cropped, e.g. 9/16 or 0.5625 for a 16:9 image. If omitted or set to null, the intrinsic aspect ratio of the source will be used. | | lqip | boolean| Set to true to use the image's Low Quality Image Placeholder as a placeholder (via CSS background-image). Requires that lqip be enabled in the image field's metadata setting – I think this needs to be present at time of of upload, but maybe not in recent versions. | | sizes | string | String to use for the rendered <img> element's sizes attribute. See example in Usage above. | | builderOptions | ImageUrlBuilderOptionsWithAliases | The options that will be passed to the URL builder |

Picture

| property | type | description | | ---------------- | ---- | ----------- | | client | SanityClient | Client instance to use when building image URLs | | image | SanityImageSource | A reference to a Sanity image asset. You can pass in any asset that is also supported by the image() method of @sanity/image-url. | | aspectRatio | number | null | Aspect ratio (height ÷ width) to which the source image should be cropped for the default source, i.e. if no media conditions match. If omitted or set to null, the intrinsic aspect ratio of the source will be used. | | lqip | boolean| Set to true to use the image's Low Quality Image Placeholder as a placeholder | | media | [{ media: string, aspectRatio: number, sizes: string }] | Specify an array of media conditions and aspect ratios which will be used to render <source> elements in the resulting <picture>. Order of items matters (the browser will use the first match it encounters). See example in Usage above. | | sizes | string | String to use for the rendered <img> element's sizes attribute. See example in Usage above. | | imgProps | object | Any extra props to pass through to the rendered <img> element | | builderOptions | ImageUrlBuilderOptionsWithAliases | The options that will be passed to the URL builder |

Creating a new version for npm

This is mostly for my benefit.

  1. Bump version number in package.json
  2. Update CHANGELOG
  3. $ git commit ...
  4. $ git tag -a x.x.x (check git tag for current)
  5. $ git push origin main
  6. $ git push --tags
  7. $ npm publish --access public

TODO

  • Correct various as-yet unrealised bad decisions.