sanity-image 1.0.2 → 1.1.0

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.
@@ -1,9 +1,12 @@
1
- import { type ImageQueryInputs } from "@sanity-image/url-builder";
1
+ import { ImageQueryInputs } from '@sanity-image/url-builder';
2
+ export { Asset, CropData, HotspotData, assetId, buildSrc, buildSrcSet, normalizeAssetId, parseImageId } from '@sanity-image/url-builder';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
+
2
5
  /**
3
6
  * These props tell `SanityImage` about your Sanity project in order to build
4
7
  * the full URLs to your images from their `_id`.
5
8
  */
6
- export type SanityImageConfigurationProps = {
9
+ type SanityImageConfigurationProps = {
7
10
  /**
8
11
  * The Sanity project ID to use. If preferred, provide `baseUrl` instead.
9
12
  */
@@ -23,7 +26,7 @@ export type SanityImageConfigurationProps = {
23
26
  * In order to set these attributes on the rendered element, these
24
27
  * `html`-prefixed props are provided.
25
28
  */
26
- export type SanityImageAttributeOverrideProps = {
29
+ type SanityImageAttributeOverrideProps = {
27
30
  /**
28
31
  * Passed through to the rendered element as `height`, overriding the default
29
32
  * behavior of setting the `height` property automatically based on the
@@ -48,22 +51,22 @@ export type SanityImageAttributeOverrideProps = {
48
51
  * Props for the `SanityImage` component itself. Does not include any props that
49
52
  * are used to build the underlying URLs.
50
53
  */
51
- export type SanityImageComponentProps = {
54
+ type SanityImageComponentProps = {
52
55
  preview?: string;
53
56
  };
54
57
  /**
55
58
  * All image-rendering props.
56
59
  */
57
- export type BaseImageProps = SanityImageAttributeOverrideProps & SanityImageComponentProps & ImageQueryInputs;
60
+ type BaseImageProps = SanityImageAttributeOverrideProps & SanityImageComponentProps & ImageQueryInputs;
58
61
  /**
59
62
  * Configuration props + image-rendering props.
60
63
  */
61
- export type FullImageProps = BaseImageProps & SanityImageConfigurationProps;
64
+ type FullImageProps = BaseImageProps & SanityImageConfigurationProps;
62
65
  /**
63
66
  * Props supporting polymorphic rendering; enables conditional typing based on
64
67
  * the `as` prop.
65
68
  */
66
- export type PolymorphicProps<T extends React.ElementType> = {
69
+ type PolymorphicProps<T extends React.ElementType> = {
67
70
  as?: T;
68
71
  } & Omit<React.ComponentPropsWithoutRef<T>, keyof FullImageProps | "as">;
69
72
  /**
@@ -71,14 +74,25 @@ export type PolymorphicProps<T extends React.ElementType> = {
71
74
  * excludes configuration props, enabling your components to render an image
72
75
  * without specifying the `baseUrl` or the `projectId` and `dataset`.
73
76
  */
74
- export type WrapperProps<T extends React.ElementType, ConfigProps extends string = keyof SanityImageConfigurationProps> = Omit<BaseImageProps, ConfigProps> & PolymorphicProps<T>;
77
+ type WrapperProps<T extends React.ElementType, ConfigProps extends string = keyof SanityImageConfigurationProps> = Omit<BaseImageProps, ConfigProps> & PolymorphicProps<T>;
75
78
  /**
76
79
  * Combined props for the `SanityImage` component with polymorphism.
77
80
  */
78
- export type SanityImageProps<T extends React.ElementType> = FullImageProps & PolymorphicProps<T>;
81
+ type SanityImageProps<T extends React.ElementType> = FullImageProps & PolymorphicProps<T>;
79
82
  /**
80
83
  * Combined props for the `ImageWithPreview` component with polymorphism.
81
84
  */
82
- export type SanityImageWithPreviewProps<T extends React.ElementType> = PolymorphicProps<T> & {
85
+ type SanityImageWithPreviewProps<T extends React.ElementType> = PolymorphicProps<T> & {
83
86
  preview: string;
84
87
  };
88
+
89
+ /**
90
+ * Renders two image tags, one with the preview image and one with the full
91
+ * image. When the full image is loaded, the preview image is removed, revealing
92
+ * the full image.
93
+ */
94
+ declare const ImageWithPreview: <T extends React.ElementType = "img">({ as, preview, style, alt, ...props }: SanityImageWithPreviewProps<T>) => react_jsx_runtime.JSX.Element;
95
+
96
+ declare const SanityImage: <T extends React.ElementType = "img">({ as: component, baseUrl, projectId, dataset, id, hotspot, crop, width, height, mode, preview, htmlWidth, htmlHeight, htmlId, queryParams, ...rest }: SanityImageProps<T>) => react_jsx_runtime.JSX.Element;
97
+
98
+ export { ImageWithPreview, SanityImage, type SanityImageProps, type WrapperProps };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,98 @@
1
- export { type Asset, type HotspotData, type CropData, buildSrc, buildSrcSet, parseImageId, assetId, normalizeAssetId, } from "@sanity-image/url-builder";
2
- export type { SanityImageProps, WrapperProps } from "./types";
3
- export { ImageWithPreview } from "./ImageWithPreview";
4
- export { SanityImage } from "./SanityImage";
1
+ import { ImageQueryInputs } from '@sanity-image/url-builder';
2
+ export { Asset, CropData, HotspotData, assetId, buildSrc, buildSrcSet, normalizeAssetId, parseImageId } from '@sanity-image/url-builder';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
+
5
+ /**
6
+ * These props tell `SanityImage` about your Sanity project in order to build
7
+ * the full URLs to your images from their `_id`.
8
+ */
9
+ type SanityImageConfigurationProps = {
10
+ /**
11
+ * The Sanity project ID to use. If preferred, provide `baseUrl` instead.
12
+ */
13
+ projectId?: string;
14
+ /**
15
+ * The Sanity dataset to use. If preferred, provide `baseUrl` instead.
16
+ */
17
+ dataset?: string;
18
+ /**
19
+ * The base URL for the Sanity CDN. If not provided, the `projectId` and
20
+ * `dataset` props will be used to construct the URL.
21
+ */
22
+ baseUrl?: string;
23
+ };
24
+ /**
25
+ * SanityImage accepts some props that conflict with native `<img>` attributes.
26
+ * In order to set these attributes on the rendered element, these
27
+ * `html`-prefixed props are provided.
28
+ */
29
+ type SanityImageAttributeOverrideProps = {
30
+ /**
31
+ * Passed through to the rendered element as `height`, overriding the default
32
+ * behavior of setting the `height` property automatically based on the
33
+ * computed output image dimensions.
34
+ */
35
+ htmlHeight?: number;
36
+ /**
37
+ * Passed through to the rendered element as `width`, overriding the default
38
+ * behavior of setting the `width` property automatically based on the
39
+ * computed output image dimensions.
40
+ */
41
+ htmlWidth?: number;
42
+ /**
43
+ * Passed through to the rendered element as `id`.
44
+ *
45
+ * The `id` prop is used to specify the Sanity Image ID, so this is the only
46
+ * way to set the `id` attribute on the rendered element.
47
+ */
48
+ htmlId?: string;
49
+ };
50
+ /**
51
+ * Props for the `SanityImage` component itself. Does not include any props that
52
+ * are used to build the underlying URLs.
53
+ */
54
+ type SanityImageComponentProps = {
55
+ preview?: string;
56
+ };
57
+ /**
58
+ * All image-rendering props.
59
+ */
60
+ type BaseImageProps = SanityImageAttributeOverrideProps & SanityImageComponentProps & ImageQueryInputs;
61
+ /**
62
+ * Configuration props + image-rendering props.
63
+ */
64
+ type FullImageProps = BaseImageProps & SanityImageConfigurationProps;
65
+ /**
66
+ * Props supporting polymorphic rendering; enables conditional typing based on
67
+ * the `as` prop.
68
+ */
69
+ type PolymorphicProps<T extends React.ElementType> = {
70
+ as?: T;
71
+ } & Omit<React.ComponentPropsWithoutRef<T>, keyof FullImageProps | "as">;
72
+ /**
73
+ * Props for the image wrapper recommended for use in consuming apps. This
74
+ * excludes configuration props, enabling your components to render an image
75
+ * without specifying the `baseUrl` or the `projectId` and `dataset`.
76
+ */
77
+ type WrapperProps<T extends React.ElementType, ConfigProps extends string = keyof SanityImageConfigurationProps> = Omit<BaseImageProps, ConfigProps> & PolymorphicProps<T>;
78
+ /**
79
+ * Combined props for the `SanityImage` component with polymorphism.
80
+ */
81
+ type SanityImageProps<T extends React.ElementType> = FullImageProps & PolymorphicProps<T>;
82
+ /**
83
+ * Combined props for the `ImageWithPreview` component with polymorphism.
84
+ */
85
+ type SanityImageWithPreviewProps<T extends React.ElementType> = PolymorphicProps<T> & {
86
+ preview: string;
87
+ };
88
+
89
+ /**
90
+ * Renders two image tags, one with the preview image and one with the full
91
+ * image. When the full image is loaded, the preview image is removed, revealing
92
+ * the full image.
93
+ */
94
+ declare const ImageWithPreview: <T extends React.ElementType = "img">({ as, preview, style, alt, ...props }: SanityImageWithPreviewProps<T>) => react_jsx_runtime.JSX.Element;
95
+
96
+ declare const SanityImage: <T extends React.ElementType = "img">({ as: component, baseUrl, projectId, dataset, id, hotspot, crop, width, height, mode, preview, htmlWidth, htmlHeight, htmlId, queryParams, ...rest }: SanityImageProps<T>) => react_jsx_runtime.JSX.Element;
97
+
98
+ export { ImageWithPreview, SanityImage, type SanityImageProps, type WrapperProps };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var I=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var z=Object.prototype.hasOwnProperty;var C=(i,e)=>{for(var o in e)I(i,o,{get:e[o],enumerable:!0})},D=(i,e,o,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of q(e))!z.call(i,t)&&t!==o&&I(i,t,{get:()=>e[t],enumerable:!(s=$(e,t))||s.enumerable});return i};var M=i=>D(I({},"__esModule",{value:!0}),i);var H={};C(H,{ImageWithPreview:()=>u,SanityImage:()=>E,assetId:()=>r.assetId,buildSrc:()=>r.buildSrc,buildSrcSet:()=>r.buildSrcSet,normalizeAssetId:()=>r.normalizeAssetId,parseImageId:()=>r.parseImageId});module.exports=M(H);var r=require("@sanity-image/url-builder");var c=require("react"),m=require("react/jsx-runtime"),u=({as:i,preview:e,style:o,alt:s,...t})=>{let[a,y]=(0,c.useState)(!1),d=(0,c.useRef)(null),p=()=>{y(!0)};(0,c.useEffect)(()=>{d.current?.complete&&p()},[]);let h=i??"img";return(0,m.jsxs)(m.Fragment,{children:[!a&&(0,m.jsx)(h,{src:e,alt:a?"":s,id:t.id,className:t.className,width:t.width,height:t.height,style:{aspectRatio:`${t.width} / ${t.height}`,...o},"data-lqip":!0}),(0,m.jsx)(h,{"data-loading":a?null:!0,alt:a?s:"",onLoad:p,ref:d,style:a?o:{...k,...o},...t})]})},k={height:"10px",width:"10px",position:"absolute",zIndex:-10,opacity:0,pointerEvents:"none",userSelect:"none"};var g=require("@sanity-image/url-builder");var w=require("react/jsx-runtime"),E=({as:i,baseUrl:e,projectId:o,dataset:s,id:t,hotspot:a,crop:y,width:d,height:p,mode:h="contain",preview:S,htmlWidth:R,htmlHeight:T,htmlId:W,queryParams:A,...f})=>{if(!t)throw new Error("Missing required `id` prop for <SanityImage>.");if(!e&&(!o||!s))throw new Error("Missing required `baseUrl` or `projectId` and `dataset` props for <SanityImage>.");e=e??`https://cdn.sanity.io/images/${o}/${s}/`;let P=t.endsWith("-svg"),x=S&&!P?u:i??"img",n={alt:f.alt??"",loading:f.loading??"lazy",id:W,...f};if(P){let l=(0,g.buildSvgAttributes)({id:t,baseUrl:e});return i==="source"&&(l.srcSet=l.src,delete l.src),(0,w.jsx)(x,{...l,...n})}let v={baseUrl:e,id:t,crop:y,hotspot:a,width:d,height:p,mode:h,queryParams:A},{src:L,...b}=(0,g.buildSrc)(v);return n.srcSet=(0,g.buildSrcSet)(v).join(", "),n.src=L,n.width=R??b.width,n.height=T??b.height,S&&(n.as=i??"img",n.preview=S),(0,w.jsx)(x,{...n})};0&&(module.exports={ImageWithPreview,SanityImage,assetId,buildSrc,buildSrcSet,normalizeAssetId,parseImageId});
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/ImageWithPreview.tsx","../src/SanityImage.tsx"],"sourcesContent":["export {\n type Asset,\n type HotspotData,\n type CropData,\n buildSrc,\n buildSrcSet,\n parseImageId,\n assetId,\n normalizeAssetId,\n} from \"@sanity-image/url-builder\"\nexport type { SanityImageProps, WrapperProps } from \"./types\"\nexport { ImageWithPreview } from \"./ImageWithPreview\"\nexport { SanityImage } from \"./SanityImage\"\n","import { useEffect, useRef, useState } from \"react\"\nimport type { SanityImageWithPreviewProps } from \"./types\"\n\n/**\n * Renders two image tags, one with the preview image and one with the full\n * image. When the full image is loaded, the preview image is removed, revealing\n * the full image.\n */\nexport const ImageWithPreview = <T extends React.ElementType = \"img\">({\n as,\n preview,\n style,\n alt,\n ...props\n}: SanityImageWithPreviewProps<T>) => {\n const [loaded, setLoaded] = useState(false)\n const ref = useRef<HTMLImageElement>(null)\n\n const onLoad = () => {\n setLoaded(true)\n }\n\n useEffect(() => {\n // If the image is already loaded when mounted, call onLoad\n if (ref.current?.complete) {\n onLoad()\n }\n }, [])\n\n const Img = as ?? \"img\"\n\n return (\n <>\n {!loaded && (\n <Img\n src={preview}\n alt={loaded ? \"\" : alt}\n id={props.id}\n className={props.className}\n width={props.width}\n height={props.height}\n style={{\n // Set the aspect ratio to match the full image\n aspectRatio: `${props.width} / ${props.height}`,\n ...style,\n }}\n data-lqip\n />\n )}\n <Img\n data-loading={loaded ? null : true}\n alt={loaded ? alt : \"\"}\n onLoad={onLoad}\n ref={ref}\n style={\n loaded\n ? style\n : {\n ...baseStyles,\n ...style,\n }\n }\n {...props}\n />\n </>\n )\n}\n\nconst baseStyles: React.CSSProperties = {\n // must be > 4px to be lazy loaded\n height: \"10px\",\n\n // must be > 4px to be lazy loaded\n width: \"10px\",\n\n // Cannot use negative x or y values, visibility: hidden, or display: none\n // to hide or the image might not get loaded.\n position: \"absolute\",\n zIndex: -10,\n opacity: 0,\n\n // Disable pointer events and user select to prevent the image\n // from interfering with UI while it's loading/hidden.\n pointerEvents: \"none\",\n userSelect: \"none\",\n}\n","import {\n buildSrc,\n buildSrcSet,\n buildSvgAttributes,\n} from \"@sanity-image/url-builder\"\nimport type { SanityImageProps } from \"./types\"\nimport { ImageWithPreview } from \"./ImageWithPreview\"\n\nexport const SanityImage = <T extends React.ElementType = \"img\">({\n as: component,\n\n // Sanity url\n baseUrl,\n projectId,\n dataset,\n\n // Image definition data\n id,\n hotspot,\n crop,\n width,\n height,\n mode = \"contain\",\n\n // Data for LQIP (preview image)\n preview,\n\n // Native-behavior overrides\n htmlWidth,\n htmlHeight,\n htmlId,\n\n // Image query string params\n queryParams,\n\n // Any remaining props are passed through to the rendered component\n ...rest\n}: SanityImageProps<T>) => {\n if (!id) throw new Error(\"Missing required `id` prop for <SanityImage>.\")\n if (!baseUrl && (!projectId || !dataset))\n throw new Error(\n \"Missing required `baseUrl` or `projectId` and `dataset` props for <SanityImage>.\"\n )\n\n baseUrl = baseUrl ?? `https://cdn.sanity.io/images/${projectId}/${dataset}/`\n\n const isSvg = id.endsWith(\"-svg\")\n\n const ImageComponent =\n preview && !isSvg ? ImageWithPreview : (component ?? \"img\")\n\n const componentProps: Record<string, unknown> = {\n alt: rest.alt ?? \"\",\n loading: rest.loading ?? \"lazy\",\n id: htmlId,\n ...rest,\n }\n\n if (isSvg) {\n // Sanity ignores all transformations for SVGs, so we can just render the\n // component without passing a query string and without doing anything for\n // the preview.\n const baseAttributes: Record<string, unknown> = buildSvgAttributes({\n id,\n baseUrl,\n })\n\n // If this is a <source> element, we need to set the `srcSet` attribute and not\n // the `src` attribute, otherwise it will be ignored in <picture> elements.\n if (component === \"source\") {\n baseAttributes.srcSet = baseAttributes.src\n delete baseAttributes.src\n }\n\n return <ImageComponent {...baseAttributes} {...componentProps} />\n }\n\n // Create default src and build srcSet\n const srcParams = {\n baseUrl,\n id,\n crop,\n hotspot,\n width,\n height,\n mode,\n queryParams,\n }\n\n const { src, ...outputDimensions } = buildSrc(srcParams)\n componentProps.srcSet = buildSrcSet(srcParams).join(\", \")\n componentProps.src = src\n componentProps.width = htmlWidth ?? outputDimensions.width\n componentProps.height = htmlHeight ?? outputDimensions.height\n\n if (preview) {\n componentProps.as = component ?? \"img\"\n componentProps.preview = preview\n }\n\n return <ImageComponent {...componentProps} />\n}\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,sBAAAE,EAAA,gBAAAC,EAAA,qKAAAC,EAAAJ,GAAA,IAAAK,EASO,qCCTP,IAAAC,EAA4C,iBAgCxCC,EAAA,6BAxBSC,EAAmB,CAAsC,CACpE,GAAAC,EACA,QAAAC,EACA,MAAAC,EACA,IAAAC,EACA,GAAGC,CACL,IAAsC,CACpC,GAAM,CAACC,EAAQC,CAAS,KAAI,YAAS,EAAK,EACpCC,KAAM,UAAyB,IAAI,EAEnCC,EAAS,IAAM,CACnBF,EAAU,EAAI,CAChB,KAEA,aAAU,IAAM,CAEVC,EAAI,SAAS,UACfC,EAAO,CAEX,EAAG,CAAC,CAAC,EAEL,IAAMC,EAAMT,GAAM,MAElB,SACE,oBACG,WAACK,MACA,OAACI,EAAA,CACC,IAAKR,EACL,IAAKI,EAAS,GAAKF,EACnB,GAAIC,EAAM,GACV,UAAWA,EAAM,UACjB,MAAOA,EAAM,MACb,OAAQA,EAAM,OACd,MAAO,CAEL,YAAa,GAAGA,EAAM,KAAK,MAAMA,EAAM,MAAM,GAC7C,GAAGF,CACL,EACA,YAAS,GACX,KAEF,OAACO,EAAA,CACC,eAAcJ,EAAS,KAAO,GAC9B,IAAKA,EAASF,EAAM,GACpB,OAAQK,EACR,IAAKD,EACL,MACEF,EACIH,EACA,CACE,GAAGQ,EACH,GAAGR,CACL,EAEL,GAAGE,EACN,GACF,CAEJ,EAEMM,EAAkC,CAEtC,OAAQ,OAGR,MAAO,OAIP,SAAU,WACV,OAAQ,IACR,QAAS,EAIT,cAAe,OACf,WAAY,MACd,ECrFA,IAAAC,EAIO,qCAsEI,IAAAC,EAAA,6BAlEEC,EAAc,CAAsC,CAC/D,GAAIC,EAGJ,QAAAC,EACA,UAAAC,EACA,QAAAC,EAGA,GAAAC,EACA,QAAAC,EACA,KAAAC,EACA,MAAAC,EACA,OAAAC,EACA,KAAAC,EAAO,UAGP,QAAAC,EAGA,UAAAC,EACA,WAAAC,EACA,OAAAC,EAGA,YAAAC,EAGA,GAAGC,CACL,IAA2B,CACzB,GAAI,CAACX,EAAI,MAAM,IAAI,MAAM,+CAA+C,EACxE,GAAI,CAACH,IAAY,CAACC,GAAa,CAACC,GAC9B,MAAM,IAAI,MACR,kFACF,EAEFF,EAAUA,GAAW,gCAAgCC,CAAS,IAAIC,CAAO,IAEzE,IAAMa,EAAQZ,EAAG,SAAS,MAAM,EAE1Ba,EACJP,GAAW,CAACM,EAAQE,EAAoBlB,GAAa,MAEjDmB,EAA0C,CAC9C,IAAKJ,EAAK,KAAO,GACjB,QAASA,EAAK,SAAW,OACzB,GAAIF,EACJ,GAAGE,CACL,EAEA,GAAIC,EAAO,CAIT,IAAMI,KAA0C,sBAAmB,CACjE,GAAAhB,EACA,QAAAH,CACF,CAAC,EAID,OAAID,IAAc,WAChBoB,EAAe,OAASA,EAAe,IACvC,OAAOA,EAAe,QAGjB,OAACH,EAAA,CAAgB,GAAGG,EAAiB,GAAGD,EAAgB,CACjE,CAGA,IAAME,EAAY,CAChB,QAAApB,EACA,GAAAG,EACA,KAAAE,EACA,QAAAD,EACA,MAAAE,EACA,OAAAC,EACA,KAAAC,EACA,YAAAK,CACF,EAEM,CAAE,IAAAQ,EAAK,GAAGC,CAAiB,KAAI,YAASF,CAAS,EACvD,OAAAF,EAAe,UAAS,eAAYE,CAAS,EAAE,KAAK,IAAI,EACxDF,EAAe,IAAMG,EACrBH,EAAe,MAAQR,GAAaY,EAAiB,MACrDJ,EAAe,OAASP,GAAcW,EAAiB,OAEnDb,IACFS,EAAe,GAAKnB,GAAa,MACjCmB,EAAe,QAAUT,MAGpB,OAACO,EAAA,CAAgB,GAAGE,EAAgB,CAC7C","names":["index_exports","__export","ImageWithPreview","SanityImage","__toCommonJS","import_url_builder","import_react","import_jsx_runtime","ImageWithPreview","as","preview","style","alt","props","loaded","setLoaded","ref","onLoad","Img","baseStyles","import_url_builder","import_jsx_runtime","SanityImage","component","baseUrl","projectId","dataset","id","hotspot","crop","width","height","mode","preview","htmlWidth","htmlHeight","htmlId","queryParams","rest","isSvg","ImageComponent","ImageWithPreview","componentProps","baseAttributes","srcParams","src","outputDimensions"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import{buildSrc as O,buildSrcSet as Q,parseImageId as V,assetId as X,normalizeAssetId as Y}from"@sanity-image/url-builder";import{useEffect as R,useRef as T,useState as W}from"react";import{Fragment as L,jsx as I,jsxs as $}from"react/jsx-runtime";var l=({as:s,preview:i,style:r,alt:n,...t})=>{let[o,d]=W(!1),a=T(null),m=()=>{d(!0)};R(()=>{a.current?.complete&&m()},[]);let c=s??"img";return $(L,{children:[!o&&I(c,{src:i,alt:o?"":n,id:t.id,className:t.className,width:t.width,height:t.height,style:{aspectRatio:`${t.width} / ${t.height}`,...r},"data-lqip":!0}),I(c,{"data-loading":o?null:!0,alt:o?n:"",onLoad:m,ref:a,style:o?r:{...A,...r},...t})]})},A={height:"10px",width:"10px",position:"absolute",zIndex:-10,opacity:0,pointerEvents:"none",userSelect:"none"};import{buildSrc as q,buildSrcSet as z,buildSvgAttributes as C}from"@sanity-image/url-builder";import{jsx as w}from"react/jsx-runtime";var D=({as:s,baseUrl:i,projectId:r,dataset:n,id:t,hotspot:o,crop:d,width:a,height:m,mode:c="contain",preview:p,htmlWidth:P,htmlHeight:x,htmlId:v,queryParams:b,...h})=>{if(!t)throw new Error("Missing required `id` prop for <SanityImage>.");if(!i&&(!r||!n))throw new Error("Missing required `baseUrl` or `projectId` and `dataset` props for <SanityImage>.");i=i??`https://cdn.sanity.io/images/${r}/${n}/`;let u=t.endsWith("-svg"),y=p&&!u?l:s??"img",e={alt:h.alt??"",loading:h.loading??"lazy",id:v,...h};if(u){let g=C({id:t,baseUrl:i});return s==="source"&&(g.srcSet=g.src,delete g.src),w(y,{...g,...e})}let S={baseUrl:i,id:t,crop:d,hotspot:o,width:a,height:m,mode:c,queryParams:b},{src:E,...f}=q(S);return e.srcSet=z(S).join(", "),e.src=E,e.width=P??f.width,e.height=x??f.height,p&&(e.as=s??"img",e.preview=p),w(y,{...e})};export{l as ImageWithPreview,D as SanityImage,X as assetId,O as buildSrc,Q as buildSrcSet,Y as normalizeAssetId,V as parseImageId};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/ImageWithPreview.tsx","../src/SanityImage.tsx"],"sourcesContent":["export {\n type Asset,\n type HotspotData,\n type CropData,\n buildSrc,\n buildSrcSet,\n parseImageId,\n assetId,\n normalizeAssetId,\n} from \"@sanity-image/url-builder\"\nexport type { SanityImageProps, WrapperProps } from \"./types\"\nexport { ImageWithPreview } from \"./ImageWithPreview\"\nexport { SanityImage } from \"./SanityImage\"\n","import { useEffect, useRef, useState } from \"react\"\nimport type { SanityImageWithPreviewProps } from \"./types\"\n\n/**\n * Renders two image tags, one with the preview image and one with the full\n * image. When the full image is loaded, the preview image is removed, revealing\n * the full image.\n */\nexport const ImageWithPreview = <T extends React.ElementType = \"img\">({\n as,\n preview,\n style,\n alt,\n ...props\n}: SanityImageWithPreviewProps<T>) => {\n const [loaded, setLoaded] = useState(false)\n const ref = useRef<HTMLImageElement>(null)\n\n const onLoad = () => {\n setLoaded(true)\n }\n\n useEffect(() => {\n // If the image is already loaded when mounted, call onLoad\n if (ref.current?.complete) {\n onLoad()\n }\n }, [])\n\n const Img = as ?? \"img\"\n\n return (\n <>\n {!loaded && (\n <Img\n src={preview}\n alt={loaded ? \"\" : alt}\n id={props.id}\n className={props.className}\n width={props.width}\n height={props.height}\n style={{\n // Set the aspect ratio to match the full image\n aspectRatio: `${props.width} / ${props.height}`,\n ...style,\n }}\n data-lqip\n />\n )}\n <Img\n data-loading={loaded ? null : true}\n alt={loaded ? alt : \"\"}\n onLoad={onLoad}\n ref={ref}\n style={\n loaded\n ? style\n : {\n ...baseStyles,\n ...style,\n }\n }\n {...props}\n />\n </>\n )\n}\n\nconst baseStyles: React.CSSProperties = {\n // must be > 4px to be lazy loaded\n height: \"10px\",\n\n // must be > 4px to be lazy loaded\n width: \"10px\",\n\n // Cannot use negative x or y values, visibility: hidden, or display: none\n // to hide or the image might not get loaded.\n position: \"absolute\",\n zIndex: -10,\n opacity: 0,\n\n // Disable pointer events and user select to prevent the image\n // from interfering with UI while it's loading/hidden.\n pointerEvents: \"none\",\n userSelect: \"none\",\n}\n","import {\n buildSrc,\n buildSrcSet,\n buildSvgAttributes,\n} from \"@sanity-image/url-builder\"\nimport type { SanityImageProps } from \"./types\"\nimport { ImageWithPreview } from \"./ImageWithPreview\"\n\nexport const SanityImage = <T extends React.ElementType = \"img\">({\n as: component,\n\n // Sanity url\n baseUrl,\n projectId,\n dataset,\n\n // Image definition data\n id,\n hotspot,\n crop,\n width,\n height,\n mode = \"contain\",\n\n // Data for LQIP (preview image)\n preview,\n\n // Native-behavior overrides\n htmlWidth,\n htmlHeight,\n htmlId,\n\n // Image query string params\n queryParams,\n\n // Any remaining props are passed through to the rendered component\n ...rest\n}: SanityImageProps<T>) => {\n if (!id) throw new Error(\"Missing required `id` prop for <SanityImage>.\")\n if (!baseUrl && (!projectId || !dataset))\n throw new Error(\n \"Missing required `baseUrl` or `projectId` and `dataset` props for <SanityImage>.\"\n )\n\n baseUrl = baseUrl ?? `https://cdn.sanity.io/images/${projectId}/${dataset}/`\n\n const isSvg = id.endsWith(\"-svg\")\n\n const ImageComponent =\n preview && !isSvg ? ImageWithPreview : (component ?? \"img\")\n\n const componentProps: Record<string, unknown> = {\n alt: rest.alt ?? \"\",\n loading: rest.loading ?? \"lazy\",\n id: htmlId,\n ...rest,\n }\n\n if (isSvg) {\n // Sanity ignores all transformations for SVGs, so we can just render the\n // component without passing a query string and without doing anything for\n // the preview.\n const baseAttributes: Record<string, unknown> = buildSvgAttributes({\n id,\n baseUrl,\n })\n\n // If this is a <source> element, we need to set the `srcSet` attribute and not\n // the `src` attribute, otherwise it will be ignored in <picture> elements.\n if (component === \"source\") {\n baseAttributes.srcSet = baseAttributes.src\n delete baseAttributes.src\n }\n\n return <ImageComponent {...baseAttributes} {...componentProps} />\n }\n\n // Create default src and build srcSet\n const srcParams = {\n baseUrl,\n id,\n crop,\n hotspot,\n width,\n height,\n mode,\n queryParams,\n }\n\n const { src, ...outputDimensions } = buildSrc(srcParams)\n componentProps.srcSet = buildSrcSet(srcParams).join(\", \")\n componentProps.src = src\n componentProps.width = htmlWidth ?? outputDimensions.width\n componentProps.height = htmlHeight ?? outputDimensions.height\n\n if (preview) {\n componentProps.as = component ?? \"img\"\n componentProps.preview = preview\n }\n\n return <ImageComponent {...componentProps} />\n}\n"],"mappings":"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","names":["buildSrc","buildSrcSet","parseImageId","assetId","normalizeAssetId","useEffect","useRef","useState","Fragment","jsx","jsxs","ImageWithPreview","as","preview","style","alt","props","loaded","setLoaded","ref","onLoad","Img","baseStyles","buildSrc","buildSrcSet","buildSvgAttributes","jsx","SanityImage","component","baseUrl","projectId","dataset","id","hotspot","crop","width","height","mode","preview","htmlWidth","htmlHeight","htmlId","queryParams","rest","isSvg","ImageComponent","ImageWithPreview","componentProps","baseAttributes","buildSvgAttributes","srcParams","src","outputDimensions","buildSrc","buildSrcSet"]}
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "sanity-image",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "author": "Corey Ward <corey@hey.com>",
5
5
  "license": "MIT",
6
6
  "repository": "https://github.com/coreyward/sanity-image",
7
7
  "types": "dist/index.d.ts",
8
- "main": "dist/cjs/index.js",
9
- "module": "dist/mjs/index.js",
8
+ "main": "dist/index.js",
9
+ "module": "dist/index.mjs",
10
10
  "exports": {
11
11
  ".": {
12
12
  "types": "./dist/index.d.ts",
13
- "import": "./dist/mjs/index.js",
14
- "require": "./dist/cjs/index.js"
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.js"
15
15
  }
16
16
  },
17
17
  "files": [
@@ -22,7 +22,7 @@
22
22
  "react": "^18.0.0 || ^19.0.0"
23
23
  },
24
24
  "dependencies": {
25
- "@sanity-image/url-builder": "1.0.1"
25
+ "@sanity-image/url-builder": "1.1.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@eslint/eslintrc": "^3.3.3",
@@ -34,7 +34,6 @@
34
34
  "@types/probe-image-size": "^7.2.0",
35
35
  "@types/react": "^18.3.28",
36
36
  "@types/react-dom": "^18.3.7",
37
- "esbuild": "^0.25.12",
38
37
  "eslint": "^9.39.2",
39
38
  "eslint-plugin-import": "^2.32.0",
40
39
  "eslint-plugin-react": "^7.37.5",
@@ -45,9 +44,8 @@
45
44
  "react": "^18.3.0",
46
45
  "react-dom": "^18.3.0",
47
46
  "react-test-renderer": "^18.3.0",
48
- "rimraf": "^6.1.3",
49
47
  "size-limit": "^12.0.0",
50
- "ts-node": "^10.9.1",
48
+ "tsup": "^8.5.1",
51
49
  "typescript": "^5.9.3",
52
50
  "typescript-eslint": "^8.56.0",
53
51
  "vitest": "^4.0.18"
@@ -57,18 +55,17 @@
57
55
  },
58
56
  "size-limit": [
59
57
  {
60
- "path": "dist/cjs/index.js",
58
+ "path": "dist/index.js",
61
59
  "limit": "4 kB"
62
60
  },
63
61
  {
64
- "path": "dist/mjs/index.js",
62
+ "path": "dist/index.mjs",
65
63
  "limit": "3 kB"
66
64
  }
67
65
  ],
68
66
  "scripts": {
69
67
  "build": "pnpm build:url-builder && pnpm build:sanity-image",
70
- "build:sanity-image": "rimraf dist && node ./scripts/build.mjs && tsc -p tsconfig.build.json",
71
- "postbuild:sanity-image": "./scripts/postbuild.sh",
68
+ "build:sanity-image": "tsup",
72
69
  "build:url-builder": "pnpm --filter @sanity-image/url-builder run build",
73
70
  "size": "size-limit",
74
71
  "test": "vitest run",
@@ -1,7 +0,0 @@
1
- import type { SanityImageWithPreviewProps } from "./types";
2
- /**
3
- * Renders two image tags, one with the preview image and one with the full
4
- * image. When the full image is loaded, the preview image is removed, revealing
5
- * the full image.
6
- */
7
- export declare const ImageWithPreview: <T extends React.ElementType = "img">({ as, preview, style, alt, ...props }: SanityImageWithPreviewProps<T>) => import("react/jsx-runtime").JSX.Element;
@@ -1,2 +0,0 @@
1
- import type { SanityImageProps } from "./types";
2
- export declare const SanityImage: <T extends React.ElementType = "img">({ as: component, baseUrl, projectId, dataset, id, hotspot, crop, width, height, mode, preview, htmlWidth, htmlHeight, htmlId, queryParams, ...rest }: SanityImageProps<T>) => import("react/jsx-runtime").JSX.Element;
package/dist/cjs/index.js DELETED
@@ -1,2 +0,0 @@
1
- "use strict";var x=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var J=Object.prototype.hasOwnProperty;var Q=(e,t)=>{for(var i in t)x(e,i,{get:t[i],enumerable:!0})},U=(e,t,i,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of j(t))!J.call(e,r)&&r!==i&&x(e,r,{get:()=>t[r],enumerable:!(o=H(t,r))||o.enumerable});return e};var B=e=>U(x({},"__esModule",{value:!0}),e);var X={};Q(X,{ImageWithPreview:()=>$,SanityImage:()=>O,assetId:()=>P,buildSrc:()=>M,buildSrcSet:()=>b,normalizeAssetId:()=>z,parseImageId:()=>I});module.exports=B(X);var F=/^image-([\da-f]+)-(\d+x\d+)-(\w+)$/,I=e=>{let t=F.exec(e),[,i,o,r]=t??[];if(!t||!i||!o||!r)throw new Error(`Could not parse image ID "${e}"`);let[a,d]=o.split("x").map(u=>Number.parseInt(u,10));if(Number.isNaN(a)||Number.isNaN(d)||!a||!d)throw new Error(`Invalid dimensions "${o}"`);return{assetId:i,dimensions:{height:d,width:a,aspectRatio:a/d},format:r}},W=e=>{let t=e.lastIndexOf("-");return e.slice(6,t)+"."+e.slice(t+1)},M=({baseUrl:e,...t})=>{let{metadata:i,...o}=v({...t,options:{includeMetadata:!0}});if(!i)throw new Error("Missing image output metadata");return{src:`${`${e}${W(t.id)}`}?${L(o)}`,width:i.outputDimensions.width,height:i.outputDimensions.height}},b=({id:e,mode:t="contain",width:i,height:o,hotspot:r,crop:a,baseUrl:d,...u})=>{let{w:h,h:m}=v({id:e,mode:t,width:i,height:o,hotspot:r,crop:a}),p=`${d}${W(e)}`,l=G(h).map(s=>{let n=Math.round(h*s),S=m&&Math.round(m*s);if(s<1&&n<50)return null;let f=v({id:e,mode:t,width:n,height:S,hotspot:r,crop:a,...u});return`${p}?${L(f)} ${f.w}w`}).filter(s=>!!s);return Array.from(new Set(l))},_=({id:e,baseUrl:t})=>{let{assetId:i,dimensions:o,format:r}=I(e);return{src:`${t}${i}-${o.width}x${o.height}.${r}`,width:o.width,height:o.height}},G=e=>e<160?[.5,1,2]:e<750?[.5,1,1.5,2]:e<1400?[.25,.5,.75,1,1.5,2]:[.25,.5,.75,1,1.25,1.5,1.75,2],v=({id:e,mode:t="contain",width:i,height:o,hotspot:r,crop:a,queryParams:d,options:{includeMetadata:u=!1}={}})=>{let h=I(e).dimensions,{width:m,height:p,aspectRatio:l}=a?q(h,a):h;if(i||(o?(i=Math.round(o*l),o=void 0):i=Math.round(m/2)),t==="cover"&&(!i||!o||i/o===l)?t="contain":t==="contain"&&o&&(i=Math.min(i,Math.round(o*l)),o=void 0),i>m||o&&o>p){let n=o?i/o:l;n>=l?(i=m,o=o&&Math.round(i/n)):(o=p,i=Math.round(o*n))}let s={w:i,q:75,fit:"max",...d};if(s.fm||(s.auto="format"),a&&(s.rect=K(h,a)),t==="cover")if(s.fit="crop",o&&(s.h=o),r){let n=a?(r.x-a.left)/(1-a.left-a.right):r.x,S=a?(r.y-a.top)/(1-a.top-a.bottom):r.y;s["fp-x"]=T(C(n,0,1),3),s["fp-y"]=T(C(S,0,1),3)}else s.crop="entropy";if(u){let n=o??Math.round(i/l);s.metadata={sourceDimensions:h,outputDimensions:{width:i,height:n,aspectRatio:i/n}}}return s},C=(e,t,i)=>Math.max(t,Math.min(i,e)),T=(e,t)=>Math.round(e*Math.pow(10,t))/Math.pow(10,t),q=(e,t)=>{if(t.left+t.right>=1||t.top+t.bottom>=1)throw new Error(`Invalid crop: ${JSON.stringify(t)}; crop values must be less than 1`);let i=Math.round(e.width*(1-t.left-t.right)),o=Math.round(e.height*(1-t.top-t.bottom)),r=i/o;return{width:i,height:o,aspectRatio:r}},K=(e,t)=>{let{width:i,height:o}=q(e,t);return[Math.round(t.left*e.width),Math.round(t.top*e.height),i,o].join(",")},L=e=>new URLSearchParams(Object.entries(e).sort(([t],[i])=>t.localeCompare(i)).map(([t,i])=>[t,String(i)])).toString().replace(/%2C/g,","),P=e=>"_id"in e?e._id:e._ref,z=e=>{let{_ref:t,...i}=e;return{...i,_id:P(e)}};var w=require("react"),g=require("react/jsx-runtime"),$=({as:e,preview:t,style:i,alt:o,...r})=>{let[a,d]=(0,w.useState)(!1),u=(0,w.useRef)(null),h=()=>{d(!0)};(0,w.useEffect)(()=>{var p;(p=u.current)!=null&&p.complete&&h()},[]);let m=e??"img";return(0,g.jsxs)(g.Fragment,{children:[!a&&(0,g.jsx)(m,{src:t,alt:a?"":o,id:r.id,className:r.className,width:r.width,height:r.height,style:{aspectRatio:`${r.width} / ${r.height}`,...i},"data-lqip":!0}),(0,g.jsx)(m,{"data-loading":a?null:!0,alt:a?o:"",onLoad:h,ref:u,style:a?i:{...V,...i},...r})]})},V={height:"10px",width:"10px",position:"absolute",zIndex:-10,opacity:0,pointerEvents:"none",userSelect:"none"};var R=require("react/jsx-runtime"),O=({as:e,baseUrl:t,projectId:i,dataset:o,id:r,hotspot:a,crop:d,width:u,height:h,mode:m="contain",preview:p,htmlWidth:l,htmlHeight:s,htmlId:n,queryParams:S,...f})=>{if(!r)throw new Error("Missing required `id` prop for <SanityImage>.");if(!t&&(!i||!o))throw new Error("Missing required `baseUrl` or `projectId` and `dataset` props for <SanityImage>.");t=t??`https://cdn.sanity.io/images/${i}/${o}/`;let E=r.endsWith("-svg"),N=p&&!E?$:e??"img",c={alt:f.alt??"",loading:f.loading??"lazy",id:n,...f};if(E){let y=_({id:r,baseUrl:t});return e==="source"&&(y.srcSet=y.src,delete y.src),(0,R.jsx)(N,{...y,...c})}let D={baseUrl:t,id:r,crop:d,hotspot:a,width:u,height:h,mode:m,queryParams:S},{src:k,...A}=M(D);return c.srcSet=b(D).join(", "),c.src=k,c.width=l??A.width,c.height=s??A.height,p&&(c.as=e??"img",c.preview=p),(0,R.jsx)(N,{...c})};0&&(module.exports={ImageWithPreview,SanityImage,assetId,buildSrc,buildSrcSet,normalizeAssetId,parseImageId});
2
- //# sourceMappingURL=index.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/index.ts", "../../packages/url-builder/src/parseImageId.ts", "../../packages/url-builder/src/urlBuilder.ts", "../../packages/url-builder/src/assetId.ts", "../../src/ImageWithPreview.tsx", "../../src/SanityImage.tsx"],
4
- "sourcesContent": ["export {\n type Asset,\n type HotspotData,\n type CropData,\n buildSrc,\n buildSrcSet,\n parseImageId,\n assetId,\n normalizeAssetId,\n} from \"@sanity-image/url-builder\"\nexport type { SanityImageProps, WrapperProps } from \"./types\"\nexport { ImageWithPreview } from \"./ImageWithPreview\"\nexport { SanityImage } from \"./SanityImage\"\n", "import type { ImageIdParts } from \"./types\"\n\nexport const SANITY_IMAGE_ID_PATTERN = /^image-([\\da-f]+)-(\\d+x\\d+)-(\\w+)$/\n\n/**\n * Parse an image id string into its component parts.\n *\n * @param {string} id The image id string to parse in the format `image-<hash>-<width>x<height>.<ext>`\n * @returns {ImageIdParts} An object containing the asset ID, dimensions, and format\n */\nexport const parseImageId = (id: string): ImageIdParts => {\n const match = SANITY_IMAGE_ID_PATTERN.exec(id)\n const [, assetId, dimensions, format] = match ?? []\n\n if (!match || !assetId || !dimensions || !format) {\n throw new Error(`Could not parse image ID \"${id}\"`)\n }\n\n const [width, height] = dimensions\n .split(\"x\")\n .map((value: string): number => Number.parseInt(value, 10))\n\n if (Number.isNaN(width) || Number.isNaN(height) || !width || !height) {\n throw new Error(`Invalid dimensions \"${dimensions}\"`)\n }\n\n return {\n assetId,\n dimensions: { height, width, aspectRatio: width / height },\n format,\n }\n}\n\n/**\n * Convert an image id to a URL path segment for the Sanity Image API. Input is\n * not validated.\n *\n * @example\n * imageIdToUrlPath(\"image-<hash>-<width>x<height>-<ext>\")\n * // => \"<hash>-<width>x<height>.<ext>\"\n */\nexport const imageIdToUrlPath = (id: string): string => {\n // This can be implemented with `parseImageId` but it's more computationally expensive\n // than this more naive implementation.\n\n const formatSeparatorIndex = id.lastIndexOf(\"-\")\n\n return (\n id.slice(6, formatSeparatorIndex) + \".\" + id.slice(formatSeparatorIndex + 1)\n )\n}\n", "import { imageIdToUrlPath, parseImageId } from \"./parseImageId\"\nimport type {\n ComputedImageData,\n CropData,\n ImageIdParts,\n ImageQueryInputs,\n ImageQueryParams,\n ImageSrcInputs,\n} from \"./types\"\n\n/**\n * Convert ImageSrcInputs into a full image URL and computed output dimensions.\n */\nexport const buildSrc = ({\n baseUrl,\n ...inputParams\n}: ImageSrcInputs): ComputedImageData => {\n const { metadata, ...queryParams } = buildQueryParams({\n ...inputParams,\n options: { includeMetadata: true },\n })\n\n // Narrowing for TS\n if (!metadata) {\n throw new Error(\"Missing image output metadata\")\n }\n\n const imageUrl = `${baseUrl}${imageIdToUrlPath(inputParams.id)}`\n\n return {\n src: `${imageUrl}?${buildQueryString(queryParams)}`,\n width: metadata.outputDimensions.width,\n height: metadata.outputDimensions.height,\n }\n}\n\nexport const buildSrcSet = ({\n id,\n mode = \"contain\",\n width,\n height,\n hotspot,\n crop,\n baseUrl,\n ...inputParams\n}: ImageSrcInputs): string[] => {\n // Determine base computed width\n const { w, h } = buildQueryParams({ id, mode, width, height, hotspot, crop })\n\n // URL of the image without any query parameters\n const imageUrl = `${baseUrl}${imageIdToUrlPath(id)}`\n\n // Build srcset\n const srcSetEntries: string[] = dynamicMultipliers(w)\n .map((multiple) => {\n const computedWidth = Math.round(w * multiple)\n const computedHeight = h && Math.round(h * multiple)\n\n // Ignore tiny entries; the extra data in the HTML is almost never worth it\n if (multiple < 1 && computedWidth < 50) return null\n\n const params: Omit<ImageQueryParams, \"metadata\"> = buildQueryParams({\n id,\n mode,\n width: computedWidth,\n height: computedHeight,\n hotspot,\n crop,\n ...inputParams,\n })\n\n return `${imageUrl}?${buildQueryString(params)} ${params.w}w`\n })\n .filter((entry): entry is string => Boolean(entry))\n\n return Array.from(new Set(srcSetEntries))\n}\n\nexport const buildSvgAttributes = ({ id, baseUrl }: ImageSrcInputs) => {\n const { assetId, dimensions, format } = parseImageId(id)\n\n return {\n src: `${baseUrl}${assetId}-${dimensions.width}x${dimensions.height}.${format}`,\n width: dimensions.width,\n height: dimensions.height,\n }\n}\n\nconst dynamicMultipliers = (width: number): number[] => {\n // For really small images, use larger steps\n if (width < 160) {\n return [0.5, 1, 2]\n }\n\n // For typical width images, use standard steps\n if (width < 750) {\n return [0.5, 1, 1.5, 2]\n }\n\n // For larger images, include 0.25x and 0.75x steps\n if (width < 1400) {\n return [0.25, 0.5, 0.75, 1, 1.5, 2]\n }\n\n // For really large images, use a wider range of steps at the low end, and smaller steps at the high end\n return [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]\n}\n\n/**\n * Constructs a query parameters object for the Sanity image URL based on the inputs provided.\n */\nexport const buildQueryParams = ({\n id,\n mode = \"contain\",\n width,\n height,\n hotspot,\n crop,\n queryParams,\n options: { includeMetadata = false } = {},\n}: ImageQueryInputs & {\n options?: {\n /** Include data about the image in the response */\n includeMetadata?: boolean\n }\n}): ImageQueryParams => {\n const sourceDimensions = parseImageId(id).dimensions\n\n // If crop is provided, compute post-crop dimensions\n const {\n width: maxWidth,\n height: maxHeight,\n aspectRatio: sourceAspectRatio,\n } = crop ? croppedImageSize(sourceDimensions, crop) : sourceDimensions\n\n // Determine width if not provided\n if (!width) {\n if (height) {\n // Compute width based on height and default ratio\n width = Math.round(height * sourceAspectRatio)\n\n // Discard `height` since we have to be in `contain` mode and we've converted it into `width`\n height = undefined\n } else {\n // Use 1/2 of the max image width by default to allow for 2x scale-up\n width = Math.round(maxWidth / 2)\n }\n }\n\n // Override `cover` mode if both width and height haven't been provided, or if\n // the requested aspect ratio matches the source aspect ratio. In these cases\n // the result will be the same as `contain` mode anyways, and `contain` mode\n // is simpler and saves a few bytes in the URL.\n if (\n mode === \"cover\" &&\n (!width || !height || width / height === sourceAspectRatio)\n ) {\n mode = \"contain\"\n } else if (mode === \"contain\" && height) {\n // Similarly, if `contain` mode is used and a height is provided, we can\n // convert it into a width by adjusting the width such that the\n // aspect-ratio\u2013constrained result will respect the height provided.\n width = Math.min(width, Math.round(height * sourceAspectRatio))\n height = undefined\n }\n\n // Clamp min and max dimensions while preserving requested aspect ratio\n if (width > maxWidth || (height && height > maxHeight)) {\n const requestedAspectRatio = height ? width / height : sourceAspectRatio\n\n if (requestedAspectRatio >= sourceAspectRatio) {\n // Clamp width\n width = maxWidth\n height = height && Math.round(width / requestedAspectRatio)\n } else {\n // Clamp height\n height = maxHeight\n width = Math.round(height * requestedAspectRatio)\n }\n }\n\n // Note: when converting params to a query string initially, we need to\n // use an object or map instead of URLSearchParams, since the latter will\n // allow multiple params with the same name, which is not supported by the\n // Sanity Image API.\n const params: ImageQueryParams = {\n w: width,\n q: 75,\n // Default fit mode; overriden for `mode=cover` below\n fit: \"max\",\n ...queryParams,\n }\n\n // If an explicit format has not been requested, use auto format\n if (!params.fm) params.auto = \"format\"\n\n if (crop) {\n // Convert crop to rect param)\n params.rect = buildRect(sourceDimensions, crop)\n }\n\n if (mode === \"cover\") {\n params.fit = \"crop\"\n\n if (height) {\n params.h = height\n }\n\n if (hotspot) {\n // Hotspot is relative to post-`rect` dimensions; if `crop` is present,\n // the hotspot inputs need to be adjusted accordingly\n const x = crop\n ? (hotspot.x - crop.left) / (1 - crop.left - crop.right)\n : hotspot.x\n const y = crop\n ? (hotspot.y - crop.top) / (1 - crop.top - crop.bottom)\n : hotspot.y\n\n params[\"fp-x\"] = roundWithPrecision(clamp(x, 0, 1), 3)\n params[\"fp-y\"] = roundWithPrecision(clamp(y, 0, 1), 3)\n } else {\n // If no hotspot is provided, use Sanity\u2019s `entropy` crop mode\n params.crop = \"entropy\"\n }\n }\n\n if (includeMetadata) {\n // Height will be set if the aspect ratio varies from `sourceAspectRatio`\n const outputHeight = height ?? Math.round(width / sourceAspectRatio)\n\n params.metadata = {\n sourceDimensions,\n outputDimensions: {\n width,\n height: outputHeight,\n aspectRatio: width / outputHeight,\n },\n }\n }\n\n return params\n}\n\nconst clamp = (value: number, min: number, max: number): number =>\n Math.max(min, Math.min(max, value))\n\nconst roundWithPrecision = (value: number, precision: number): number =>\n Math.round(value * Math.pow(10, precision)) / Math.pow(10, precision)\n\nexport const croppedImageSize = (\n /** Source/original image dimensions */\n dimensions: { width: number; height: number },\n crop: CropData\n): ImageIdParts[\"dimensions\"] => {\n if (crop.left + crop.right >= 1 || crop.top + crop.bottom >= 1) {\n throw new Error(\n `Invalid crop: ${JSON.stringify(crop)}; crop values must be less than 1`\n )\n }\n\n const width = Math.round(dimensions.width * (1 - crop.left - crop.right))\n const height = Math.round(dimensions.height * (1 - crop.top - crop.bottom))\n const aspectRatio = width / height\n\n return { width, height, aspectRatio }\n}\n\n/**\n * Build a `rect` value to crop the image.\n */\nexport const buildRect = (\n /** Source/original image dimensions */\n dimensions: { width: number; height: number },\n crop: CropData\n): string => {\n const { width, height } = croppedImageSize(dimensions, crop)\n\n return [\n Math.round(crop.left * dimensions.width),\n Math.round(crop.top * dimensions.height),\n width,\n height,\n ].join(\",\")\n}\n\n/**\n * Converts an object of query params into a query string. The keys are sorted\n * alphabetically to maximize cache-hit rates. Commas are not URL-encoded since\n * doing so is unnecessary, adds extra data, and makes it harder to read.\n */\nexport const buildQueryString = (\n params: Partial<{\n [K in keyof Omit<ImageQueryParams, \"metadata\">]: ImageQueryParams[K]\n }>\n): string => {\n const searchParams = new URLSearchParams(\n Object.entries(params)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, value]) => [key, String(value)])\n )\n\n return searchParams.toString().replace(/%2C/g, \",\") // don't urlencode commas\n}\n", "type AssetLike = { _id: string } | { _ref: string }\n\n/**\n * Get the asset ID of a Sanity image asset whether it has an `_id` or `_ref`\n * field.\n */\nexport const assetId = (asset: AssetLike) =>\n \"_id\" in asset ? asset._id : asset._ref\n\n/**\n * Normalize an asset object to have an `_id` field. This is useful when you\n * have an asset object with a `_ref` field and you need to convert it to an\n * `_id` field. Or if you don't know which you have and you want to ensure you\n * have an `_id` field.\n */\nexport const normalizeAssetId = <T extends Record<string, unknown>>(\n asset: AssetLike & T\n): Omit<T, \"_ref\"> & { _id: string } => {\n const { _ref, ...rest } = asset\n return { ...rest, _id: assetId(asset) }\n}\n", "import { useEffect, useRef, useState } from \"react\"\nimport type { SanityImageWithPreviewProps } from \"./types\"\n\n/**\n * Renders two image tags, one with the preview image and one with the full\n * image. When the full image is loaded, the preview image is removed, revealing\n * the full image.\n */\nexport const ImageWithPreview = <T extends React.ElementType = \"img\">({\n as,\n preview,\n style,\n alt,\n ...props\n}: SanityImageWithPreviewProps<T>) => {\n const [loaded, setLoaded] = useState(false)\n const ref = useRef<HTMLImageElement>(null)\n\n const onLoad = () => {\n setLoaded(true)\n }\n\n useEffect(() => {\n // If the image is already loaded when mounted, call onLoad\n if (ref.current?.complete) {\n onLoad()\n }\n }, [])\n\n const Img = as ?? \"img\"\n\n return (\n <>\n {!loaded && (\n <Img\n src={preview}\n alt={loaded ? \"\" : alt}\n id={props.id}\n className={props.className}\n width={props.width}\n height={props.height}\n style={{\n // Set the aspect ratio to match the full image\n aspectRatio: `${props.width} / ${props.height}`,\n ...style,\n }}\n data-lqip\n />\n )}\n <Img\n data-loading={loaded ? null : true}\n alt={loaded ? alt : \"\"}\n onLoad={onLoad}\n ref={ref}\n style={\n loaded\n ? style\n : {\n ...baseStyles,\n ...style,\n }\n }\n {...props}\n />\n </>\n )\n}\n\nconst baseStyles: React.CSSProperties = {\n // must be > 4px to be lazy loaded\n height: \"10px\",\n\n // must be > 4px to be lazy loaded\n width: \"10px\",\n\n // Cannot use negative x or y values, visibility: hidden, or display: none\n // to hide or the image might not get loaded.\n position: \"absolute\",\n zIndex: -10,\n opacity: 0,\n\n // Disable pointer events and user select to prevent the image\n // from interfering with UI while it's loading/hidden.\n pointerEvents: \"none\",\n userSelect: \"none\",\n}\n", "import {\n buildSrc,\n buildSrcSet,\n buildSvgAttributes,\n} from \"@sanity-image/url-builder\"\nimport type { SanityImageProps } from \"./types\"\nimport { ImageWithPreview } from \"./ImageWithPreview\"\n\nexport const SanityImage = <T extends React.ElementType = \"img\">({\n as: component,\n\n // Sanity url\n baseUrl,\n projectId,\n dataset,\n\n // Image definition data\n id,\n hotspot,\n crop,\n width,\n height,\n mode = \"contain\",\n\n // Data for LQIP (preview image)\n preview,\n\n // Native-behavior overrides\n htmlWidth,\n htmlHeight,\n htmlId,\n\n // Image query string params\n queryParams,\n\n // Any remaining props are passed through to the rendered component\n ...rest\n}: SanityImageProps<T>) => {\n if (!id) throw new Error(\"Missing required `id` prop for <SanityImage>.\")\n if (!baseUrl && (!projectId || !dataset))\n throw new Error(\n \"Missing required `baseUrl` or `projectId` and `dataset` props for <SanityImage>.\"\n )\n\n baseUrl = baseUrl ?? `https://cdn.sanity.io/images/${projectId}/${dataset}/`\n\n const isSvg = id.endsWith(\"-svg\")\n\n const ImageComponent =\n preview && !isSvg ? ImageWithPreview : (component ?? \"img\")\n\n const componentProps: Record<string, unknown> = {\n alt: rest.alt ?? \"\",\n loading: rest.loading ?? \"lazy\",\n id: htmlId,\n ...rest,\n }\n\n if (isSvg) {\n // Sanity ignores all transformations for SVGs, so we can just render the\n // component without passing a query string and without doing anything for\n // the preview.\n const baseAttributes: Record<string, unknown> = buildSvgAttributes({\n id,\n baseUrl,\n })\n\n // If this is a <source> element, we need to set the `srcSet` attribute and not\n // the `src` attribute, otherwise it will be ignored in <picture> elements.\n if (component === \"source\") {\n baseAttributes.srcSet = baseAttributes.src\n delete baseAttributes.src\n }\n\n return <ImageComponent {...baseAttributes} {...componentProps} />\n }\n\n // Create default src and build srcSet\n const srcParams = {\n baseUrl,\n id,\n crop,\n hotspot,\n width,\n height,\n mode,\n queryParams,\n }\n\n const { src, ...outputDimensions } = buildSrc(srcParams)\n componentProps.srcSet = buildSrcSet(srcParams).join(\", \")\n componentProps.src = src\n componentProps.width = htmlWidth ?? outputDimensions.width\n componentProps.height = htmlHeight ?? outputDimensions.height\n\n if (preview) {\n componentProps.as = component ?? \"img\"\n componentProps.preview = preview\n }\n\n return <ImageComponent {...componentProps} />\n}\n"],
5
- "mappings": "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",
6
- "names": ["index_exports", "__export", "ImageWithPreview", "SanityImage", "w", "D", "C", "p", "__toCommonJS", "SANITY_IMAGE_ID_PATTERN", "parseImageId", "id", "match", "assetId", "dimensions", "format", "width", "height", "value", "imageIdToUrlPath", "formatSeparatorIndex", "buildSrc", "baseUrl", "inputParams", "metadata", "queryParams", "buildQueryParams", "buildQueryString", "buildSrcSet", "mode", "hotspot", "crop", "w", "h", "imageUrl", "srcSetEntries", "dynamicMultipliers", "multiple", "computedWidth", "computedHeight", "params", "entry", "buildSvgAttributes", "includeMetadata", "sourceDimensions", "maxWidth", "maxHeight", "sourceAspectRatio", "croppedImageSize", "requestedAspectRatio", "buildRect", "x", "y", "roundWithPrecision", "clamp", "outputHeight", "min", "max", "precision", "aspectRatio", "a", "b", "key", "asset", "normalizeAssetId", "_ref", "rest", "import_react", "import_jsx_runtime", "ImageWithPreview", "as", "preview", "style", "alt", "props", "loaded", "setLoaded", "ref", "onLoad", "_a", "Img", "baseStyles", "import_jsx_runtime", "SanityImage", "component", "baseUrl", "projectId", "dataset", "id", "hotspot", "crop", "width", "height", "mode", "preview", "htmlWidth", "htmlHeight", "htmlId", "queryParams", "rest", "isSvg", "ImageComponent", "ImageWithPreview", "componentProps", "baseAttributes", "A", "srcParams", "src", "outputDimensions", "w", "D"]
7
- }
@@ -1,3 +0,0 @@
1
- {
2
- "type": "commonjs"
3
- }
package/dist/mjs/index.js DELETED
@@ -1,2 +0,0 @@
1
- var L=/^image-([\da-f]+)-(\d+x\d+)-(\w+)$/,y=i=>{let t=L.exec(i),[,e,o,r]=t??[];if(!t||!e||!o||!r)throw new Error(`Could not parse image ID "${i}"`);let[a,d]=o.split("x").map(p=>Number.parseInt(p,10));if(Number.isNaN(a)||Number.isNaN(d)||!a||!d)throw new Error(`Invalid dimensions "${o}"`);return{assetId:e,dimensions:{height:d,width:a,aspectRatio:a/d},format:r}},N=i=>{let t=i.lastIndexOf("-");return i.slice(6,t)+"."+i.slice(t+1)},I=({baseUrl:i,...t})=>{let{metadata:e,...o}=S({...t,options:{includeMetadata:!0}});if(!e)throw new Error("Missing image output metadata");return{src:`${`${i}${N(t.id)}`}?${C(o)}`,width:e.outputDimensions.width,height:e.outputDimensions.height}},M=({id:i,mode:t="contain",width:e,height:o,hotspot:r,crop:a,baseUrl:d,...p})=>{let{w:h,h:m}=S({id:i,mode:t,width:e,height:o,hotspot:r,crop:a}),l=`${d}${N(i)}`,u=z(h).map(s=>{let n=Math.round(h*s),f=m&&Math.round(m*s);if(s<1&&n<50)return null;let g=S({id:i,mode:t,width:n,height:f,hotspot:r,crop:a,...p});return`${l}?${C(g)} ${g.w}w`}).filter(s=>!!s);return Array.from(new Set(u))},D=({id:i,baseUrl:t})=>{let{assetId:e,dimensions:o,format:r}=y(i);return{src:`${t}${e}-${o.width}x${o.height}.${r}`,width:o.width,height:o.height}},z=i=>i<160?[.5,1,2]:i<750?[.5,1,1.5,2]:i<1400?[.25,.5,.75,1,1.5,2]:[.25,.5,.75,1,1.25,1.5,1.75,2],S=({id:i,mode:t="contain",width:e,height:o,hotspot:r,crop:a,queryParams:d,options:{includeMetadata:p=!1}={}})=>{let h=y(i).dimensions,{width:m,height:l,aspectRatio:u}=a?A(h,a):h;if(e||(o?(e=Math.round(o*u),o=void 0):e=Math.round(m/2)),t==="cover"&&(!e||!o||e/o===u)?t="contain":t==="contain"&&o&&(e=Math.min(e,Math.round(o*u)),o=void 0),e>m||o&&o>l){let n=o?e/o:u;n>=u?(e=m,o=o&&Math.round(e/n)):(o=l,e=Math.round(o*n))}let s={w:e,q:75,fit:"max",...d};if(s.fm||(s.auto="format"),a&&(s.rect=O(h,a)),t==="cover")if(s.fit="crop",o&&(s.h=o),r){let n=a?(r.x-a.left)/(1-a.left-a.right):r.x,f=a?(r.y-a.top)/(1-a.top-a.bottom):r.y;s["fp-x"]=E(R(n,0,1),3),s["fp-y"]=E(R(f,0,1),3)}else s.crop="entropy";if(p){let n=o??Math.round(e/u);s.metadata={sourceDimensions:h,outputDimensions:{width:e,height:n,aspectRatio:e/n}}}return s},R=(i,t,e)=>Math.max(t,Math.min(e,i)),E=(i,t)=>Math.round(i*Math.pow(10,t))/Math.pow(10,t),A=(i,t)=>{if(t.left+t.right>=1||t.top+t.bottom>=1)throw new Error(`Invalid crop: ${JSON.stringify(t)}; crop values must be less than 1`);let e=Math.round(i.width*(1-t.left-t.right)),o=Math.round(i.height*(1-t.top-t.bottom)),r=e/o;return{width:e,height:o,aspectRatio:r}},O=(i,t)=>{let{width:e,height:o}=A(i,t);return[Math.round(t.left*i.width),Math.round(t.top*i.height),e,o].join(",")},C=i=>new URLSearchParams(Object.entries(i).sort(([t],[e])=>t.localeCompare(e)).map(([t,e])=>[t,String(e)])).toString().replace(/%2C/g,","),T=i=>"_id"in i?i._id:i._ref,k=i=>{let{_ref:t,...e}=i;return{...e,_id:T(i)}};import{useEffect as H,useRef as j,useState as J}from"react";import{Fragment as U,jsx as W,jsxs as B}from"react/jsx-runtime";var b=({as:i,preview:t,style:e,alt:o,...r})=>{let[a,d]=J(!1),p=j(null),h=()=>{d(!0)};H(()=>{p.current?.complete&&h()},[]);let m=i??"img";return B(U,{children:[!a&&W(m,{src:t,alt:a?"":o,id:r.id,className:r.className,width:r.width,height:r.height,style:{aspectRatio:`${r.width} / ${r.height}`,...e},"data-lqip":!0}),W(m,{"data-loading":a?null:!0,alt:a?o:"",onLoad:h,ref:p,style:a?e:{...Q,...e},...r})]})},Q={height:"10px",width:"10px",position:"absolute",zIndex:-10,opacity:0,pointerEvents:"none",userSelect:"none"};import{jsx as _}from"react/jsx-runtime";var F=({as:i,baseUrl:t,projectId:e,dataset:o,id:r,hotspot:a,crop:d,width:p,height:h,mode:m="contain",preview:l,htmlWidth:u,htmlHeight:s,htmlId:n,queryParams:f,...g})=>{if(!r)throw new Error("Missing required `id` prop for <SanityImage>.");if(!t&&(!e||!o))throw new Error("Missing required `baseUrl` or `projectId` and `dataset` props for <SanityImage>.");t=t??`https://cdn.sanity.io/images/${e}/${o}/`;let $=r.endsWith("-svg"),x=l&&!$?b:i??"img",c={alt:g.alt??"",loading:g.loading??"lazy",id:n,...g};if($){let w=D({id:r,baseUrl:t});return i==="source"&&(w.srcSet=w.src,delete w.src),_(x,{...w,...c})}let v={baseUrl:t,id:r,crop:d,hotspot:a,width:p,height:h,mode:m,queryParams:f},{src:q,...P}=I(v);return c.srcSet=M(v).join(", "),c.src=q,c.width=u??P.width,c.height=s??P.height,l&&(c.as=i??"img",c.preview=l),_(x,{...c})};export{b as ImageWithPreview,F as SanityImage,T as assetId,I as buildSrc,M as buildSrcSet,k as normalizeAssetId,y as parseImageId};
2
- //# sourceMappingURL=index.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../packages/url-builder/src/parseImageId.ts", "../../packages/url-builder/src/urlBuilder.ts", "../../packages/url-builder/src/assetId.ts", "../../src/ImageWithPreview.tsx", "../../src/SanityImage.tsx"],
4
- "sourcesContent": ["import type { ImageIdParts } from \"./types\"\n\nexport const SANITY_IMAGE_ID_PATTERN = /^image-([\\da-f]+)-(\\d+x\\d+)-(\\w+)$/\n\n/**\n * Parse an image id string into its component parts.\n *\n * @param {string} id The image id string to parse in the format `image-<hash>-<width>x<height>.<ext>`\n * @returns {ImageIdParts} An object containing the asset ID, dimensions, and format\n */\nexport const parseImageId = (id: string): ImageIdParts => {\n const match = SANITY_IMAGE_ID_PATTERN.exec(id)\n const [, assetId, dimensions, format] = match ?? []\n\n if (!match || !assetId || !dimensions || !format) {\n throw new Error(`Could not parse image ID \"${id}\"`)\n }\n\n const [width, height] = dimensions\n .split(\"x\")\n .map((value: string): number => Number.parseInt(value, 10))\n\n if (Number.isNaN(width) || Number.isNaN(height) || !width || !height) {\n throw new Error(`Invalid dimensions \"${dimensions}\"`)\n }\n\n return {\n assetId,\n dimensions: { height, width, aspectRatio: width / height },\n format,\n }\n}\n\n/**\n * Convert an image id to a URL path segment for the Sanity Image API. Input is\n * not validated.\n *\n * @example\n * imageIdToUrlPath(\"image-<hash>-<width>x<height>-<ext>\")\n * // => \"<hash>-<width>x<height>.<ext>\"\n */\nexport const imageIdToUrlPath = (id: string): string => {\n // This can be implemented with `parseImageId` but it's more computationally expensive\n // than this more naive implementation.\n\n const formatSeparatorIndex = id.lastIndexOf(\"-\")\n\n return (\n id.slice(6, formatSeparatorIndex) + \".\" + id.slice(formatSeparatorIndex + 1)\n )\n}\n", "import { imageIdToUrlPath, parseImageId } from \"./parseImageId\"\nimport type {\n ComputedImageData,\n CropData,\n ImageIdParts,\n ImageQueryInputs,\n ImageQueryParams,\n ImageSrcInputs,\n} from \"./types\"\n\n/**\n * Convert ImageSrcInputs into a full image URL and computed output dimensions.\n */\nexport const buildSrc = ({\n baseUrl,\n ...inputParams\n}: ImageSrcInputs): ComputedImageData => {\n const { metadata, ...queryParams } = buildQueryParams({\n ...inputParams,\n options: { includeMetadata: true },\n })\n\n // Narrowing for TS\n if (!metadata) {\n throw new Error(\"Missing image output metadata\")\n }\n\n const imageUrl = `${baseUrl}${imageIdToUrlPath(inputParams.id)}`\n\n return {\n src: `${imageUrl}?${buildQueryString(queryParams)}`,\n width: metadata.outputDimensions.width,\n height: metadata.outputDimensions.height,\n }\n}\n\nexport const buildSrcSet = ({\n id,\n mode = \"contain\",\n width,\n height,\n hotspot,\n crop,\n baseUrl,\n ...inputParams\n}: ImageSrcInputs): string[] => {\n // Determine base computed width\n const { w, h } = buildQueryParams({ id, mode, width, height, hotspot, crop })\n\n // URL of the image without any query parameters\n const imageUrl = `${baseUrl}${imageIdToUrlPath(id)}`\n\n // Build srcset\n const srcSetEntries: string[] = dynamicMultipliers(w)\n .map((multiple) => {\n const computedWidth = Math.round(w * multiple)\n const computedHeight = h && Math.round(h * multiple)\n\n // Ignore tiny entries; the extra data in the HTML is almost never worth it\n if (multiple < 1 && computedWidth < 50) return null\n\n const params: Omit<ImageQueryParams, \"metadata\"> = buildQueryParams({\n id,\n mode,\n width: computedWidth,\n height: computedHeight,\n hotspot,\n crop,\n ...inputParams,\n })\n\n return `${imageUrl}?${buildQueryString(params)} ${params.w}w`\n })\n .filter((entry): entry is string => Boolean(entry))\n\n return Array.from(new Set(srcSetEntries))\n}\n\nexport const buildSvgAttributes = ({ id, baseUrl }: ImageSrcInputs) => {\n const { assetId, dimensions, format } = parseImageId(id)\n\n return {\n src: `${baseUrl}${assetId}-${dimensions.width}x${dimensions.height}.${format}`,\n width: dimensions.width,\n height: dimensions.height,\n }\n}\n\nconst dynamicMultipliers = (width: number): number[] => {\n // For really small images, use larger steps\n if (width < 160) {\n return [0.5, 1, 2]\n }\n\n // For typical width images, use standard steps\n if (width < 750) {\n return [0.5, 1, 1.5, 2]\n }\n\n // For larger images, include 0.25x and 0.75x steps\n if (width < 1400) {\n return [0.25, 0.5, 0.75, 1, 1.5, 2]\n }\n\n // For really large images, use a wider range of steps at the low end, and smaller steps at the high end\n return [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]\n}\n\n/**\n * Constructs a query parameters object for the Sanity image URL based on the inputs provided.\n */\nexport const buildQueryParams = ({\n id,\n mode = \"contain\",\n width,\n height,\n hotspot,\n crop,\n queryParams,\n options: { includeMetadata = false } = {},\n}: ImageQueryInputs & {\n options?: {\n /** Include data about the image in the response */\n includeMetadata?: boolean\n }\n}): ImageQueryParams => {\n const sourceDimensions = parseImageId(id).dimensions\n\n // If crop is provided, compute post-crop dimensions\n const {\n width: maxWidth,\n height: maxHeight,\n aspectRatio: sourceAspectRatio,\n } = crop ? croppedImageSize(sourceDimensions, crop) : sourceDimensions\n\n // Determine width if not provided\n if (!width) {\n if (height) {\n // Compute width based on height and default ratio\n width = Math.round(height * sourceAspectRatio)\n\n // Discard `height` since we have to be in `contain` mode and we've converted it into `width`\n height = undefined\n } else {\n // Use 1/2 of the max image width by default to allow for 2x scale-up\n width = Math.round(maxWidth / 2)\n }\n }\n\n // Override `cover` mode if both width and height haven't been provided, or if\n // the requested aspect ratio matches the source aspect ratio. In these cases\n // the result will be the same as `contain` mode anyways, and `contain` mode\n // is simpler and saves a few bytes in the URL.\n if (\n mode === \"cover\" &&\n (!width || !height || width / height === sourceAspectRatio)\n ) {\n mode = \"contain\"\n } else if (mode === \"contain\" && height) {\n // Similarly, if `contain` mode is used and a height is provided, we can\n // convert it into a width by adjusting the width such that the\n // aspect-ratio\u2013constrained result will respect the height provided.\n width = Math.min(width, Math.round(height * sourceAspectRatio))\n height = undefined\n }\n\n // Clamp min and max dimensions while preserving requested aspect ratio\n if (width > maxWidth || (height && height > maxHeight)) {\n const requestedAspectRatio = height ? width / height : sourceAspectRatio\n\n if (requestedAspectRatio >= sourceAspectRatio) {\n // Clamp width\n width = maxWidth\n height = height && Math.round(width / requestedAspectRatio)\n } else {\n // Clamp height\n height = maxHeight\n width = Math.round(height * requestedAspectRatio)\n }\n }\n\n // Note: when converting params to a query string initially, we need to\n // use an object or map instead of URLSearchParams, since the latter will\n // allow multiple params with the same name, which is not supported by the\n // Sanity Image API.\n const params: ImageQueryParams = {\n w: width,\n q: 75,\n // Default fit mode; overriden for `mode=cover` below\n fit: \"max\",\n ...queryParams,\n }\n\n // If an explicit format has not been requested, use auto format\n if (!params.fm) params.auto = \"format\"\n\n if (crop) {\n // Convert crop to rect param)\n params.rect = buildRect(sourceDimensions, crop)\n }\n\n if (mode === \"cover\") {\n params.fit = \"crop\"\n\n if (height) {\n params.h = height\n }\n\n if (hotspot) {\n // Hotspot is relative to post-`rect` dimensions; if `crop` is present,\n // the hotspot inputs need to be adjusted accordingly\n const x = crop\n ? (hotspot.x - crop.left) / (1 - crop.left - crop.right)\n : hotspot.x\n const y = crop\n ? (hotspot.y - crop.top) / (1 - crop.top - crop.bottom)\n : hotspot.y\n\n params[\"fp-x\"] = roundWithPrecision(clamp(x, 0, 1), 3)\n params[\"fp-y\"] = roundWithPrecision(clamp(y, 0, 1), 3)\n } else {\n // If no hotspot is provided, use Sanity\u2019s `entropy` crop mode\n params.crop = \"entropy\"\n }\n }\n\n if (includeMetadata) {\n // Height will be set if the aspect ratio varies from `sourceAspectRatio`\n const outputHeight = height ?? Math.round(width / sourceAspectRatio)\n\n params.metadata = {\n sourceDimensions,\n outputDimensions: {\n width,\n height: outputHeight,\n aspectRatio: width / outputHeight,\n },\n }\n }\n\n return params\n}\n\nconst clamp = (value: number, min: number, max: number): number =>\n Math.max(min, Math.min(max, value))\n\nconst roundWithPrecision = (value: number, precision: number): number =>\n Math.round(value * Math.pow(10, precision)) / Math.pow(10, precision)\n\nexport const croppedImageSize = (\n /** Source/original image dimensions */\n dimensions: { width: number; height: number },\n crop: CropData\n): ImageIdParts[\"dimensions\"] => {\n if (crop.left + crop.right >= 1 || crop.top + crop.bottom >= 1) {\n throw new Error(\n `Invalid crop: ${JSON.stringify(crop)}; crop values must be less than 1`\n )\n }\n\n const width = Math.round(dimensions.width * (1 - crop.left - crop.right))\n const height = Math.round(dimensions.height * (1 - crop.top - crop.bottom))\n const aspectRatio = width / height\n\n return { width, height, aspectRatio }\n}\n\n/**\n * Build a `rect` value to crop the image.\n */\nexport const buildRect = (\n /** Source/original image dimensions */\n dimensions: { width: number; height: number },\n crop: CropData\n): string => {\n const { width, height } = croppedImageSize(dimensions, crop)\n\n return [\n Math.round(crop.left * dimensions.width),\n Math.round(crop.top * dimensions.height),\n width,\n height,\n ].join(\",\")\n}\n\n/**\n * Converts an object of query params into a query string. The keys are sorted\n * alphabetically to maximize cache-hit rates. Commas are not URL-encoded since\n * doing so is unnecessary, adds extra data, and makes it harder to read.\n */\nexport const buildQueryString = (\n params: Partial<{\n [K in keyof Omit<ImageQueryParams, \"metadata\">]: ImageQueryParams[K]\n }>\n): string => {\n const searchParams = new URLSearchParams(\n Object.entries(params)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, value]) => [key, String(value)])\n )\n\n return searchParams.toString().replace(/%2C/g, \",\") // don't urlencode commas\n}\n", "type AssetLike = { _id: string } | { _ref: string }\n\n/**\n * Get the asset ID of a Sanity image asset whether it has an `_id` or `_ref`\n * field.\n */\nexport const assetId = (asset: AssetLike) =>\n \"_id\" in asset ? asset._id : asset._ref\n\n/**\n * Normalize an asset object to have an `_id` field. This is useful when you\n * have an asset object with a `_ref` field and you need to convert it to an\n * `_id` field. Or if you don't know which you have and you want to ensure you\n * have an `_id` field.\n */\nexport const normalizeAssetId = <T extends Record<string, unknown>>(\n asset: AssetLike & T\n): Omit<T, \"_ref\"> & { _id: string } => {\n const { _ref, ...rest } = asset\n return { ...rest, _id: assetId(asset) }\n}\n", "import { useEffect, useRef, useState } from \"react\"\nimport type { SanityImageWithPreviewProps } from \"./types\"\n\n/**\n * Renders two image tags, one with the preview image and one with the full\n * image. When the full image is loaded, the preview image is removed, revealing\n * the full image.\n */\nexport const ImageWithPreview = <T extends React.ElementType = \"img\">({\n as,\n preview,\n style,\n alt,\n ...props\n}: SanityImageWithPreviewProps<T>) => {\n const [loaded, setLoaded] = useState(false)\n const ref = useRef<HTMLImageElement>(null)\n\n const onLoad = () => {\n setLoaded(true)\n }\n\n useEffect(() => {\n // If the image is already loaded when mounted, call onLoad\n if (ref.current?.complete) {\n onLoad()\n }\n }, [])\n\n const Img = as ?? \"img\"\n\n return (\n <>\n {!loaded && (\n <Img\n src={preview}\n alt={loaded ? \"\" : alt}\n id={props.id}\n className={props.className}\n width={props.width}\n height={props.height}\n style={{\n // Set the aspect ratio to match the full image\n aspectRatio: `${props.width} / ${props.height}`,\n ...style,\n }}\n data-lqip\n />\n )}\n <Img\n data-loading={loaded ? null : true}\n alt={loaded ? alt : \"\"}\n onLoad={onLoad}\n ref={ref}\n style={\n loaded\n ? style\n : {\n ...baseStyles,\n ...style,\n }\n }\n {...props}\n />\n </>\n )\n}\n\nconst baseStyles: React.CSSProperties = {\n // must be > 4px to be lazy loaded\n height: \"10px\",\n\n // must be > 4px to be lazy loaded\n width: \"10px\",\n\n // Cannot use negative x or y values, visibility: hidden, or display: none\n // to hide or the image might not get loaded.\n position: \"absolute\",\n zIndex: -10,\n opacity: 0,\n\n // Disable pointer events and user select to prevent the image\n // from interfering with UI while it's loading/hidden.\n pointerEvents: \"none\",\n userSelect: \"none\",\n}\n", "import {\n buildSrc,\n buildSrcSet,\n buildSvgAttributes,\n} from \"@sanity-image/url-builder\"\nimport type { SanityImageProps } from \"./types\"\nimport { ImageWithPreview } from \"./ImageWithPreview\"\n\nexport const SanityImage = <T extends React.ElementType = \"img\">({\n as: component,\n\n // Sanity url\n baseUrl,\n projectId,\n dataset,\n\n // Image definition data\n id,\n hotspot,\n crop,\n width,\n height,\n mode = \"contain\",\n\n // Data for LQIP (preview image)\n preview,\n\n // Native-behavior overrides\n htmlWidth,\n htmlHeight,\n htmlId,\n\n // Image query string params\n queryParams,\n\n // Any remaining props are passed through to the rendered component\n ...rest\n}: SanityImageProps<T>) => {\n if (!id) throw new Error(\"Missing required `id` prop for <SanityImage>.\")\n if (!baseUrl && (!projectId || !dataset))\n throw new Error(\n \"Missing required `baseUrl` or `projectId` and `dataset` props for <SanityImage>.\"\n )\n\n baseUrl = baseUrl ?? `https://cdn.sanity.io/images/${projectId}/${dataset}/`\n\n const isSvg = id.endsWith(\"-svg\")\n\n const ImageComponent =\n preview && !isSvg ? ImageWithPreview : (component ?? \"img\")\n\n const componentProps: Record<string, unknown> = {\n alt: rest.alt ?? \"\",\n loading: rest.loading ?? \"lazy\",\n id: htmlId,\n ...rest,\n }\n\n if (isSvg) {\n // Sanity ignores all transformations for SVGs, so we can just render the\n // component without passing a query string and without doing anything for\n // the preview.\n const baseAttributes: Record<string, unknown> = buildSvgAttributes({\n id,\n baseUrl,\n })\n\n // If this is a <source> element, we need to set the `srcSet` attribute and not\n // the `src` attribute, otherwise it will be ignored in <picture> elements.\n if (component === \"source\") {\n baseAttributes.srcSet = baseAttributes.src\n delete baseAttributes.src\n }\n\n return <ImageComponent {...baseAttributes} {...componentProps} />\n }\n\n // Create default src and build srcSet\n const srcParams = {\n baseUrl,\n id,\n crop,\n hotspot,\n width,\n height,\n mode,\n queryParams,\n }\n\n const { src, ...outputDimensions } = buildSrc(srcParams)\n componentProps.srcSet = buildSrcSet(srcParams).join(\", \")\n componentProps.src = src\n componentProps.width = htmlWidth ?? outputDimensions.width\n componentProps.height = htmlHeight ?? outputDimensions.height\n\n if (preview) {\n componentProps.as = component ?? \"img\"\n componentProps.preview = preview\n }\n\n return <ImageComponent {...componentProps} />\n}\n"],
5
- "mappings": "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",
6
- "names": ["SANITY_IMAGE_ID_PATTERN", "parseImageId", "id", "match", "assetId", "dimensions", "format", "width", "height", "value", "imageIdToUrlPath", "formatSeparatorIndex", "buildSrc", "baseUrl", "inputParams", "metadata", "queryParams", "buildQueryParams", "buildQueryString", "buildSrcSet", "mode", "hotspot", "crop", "w", "h", "imageUrl", "srcSetEntries", "dynamicMultipliers", "multiple", "computedWidth", "computedHeight", "params", "entry", "buildSvgAttributes", "includeMetadata", "sourceDimensions", "maxWidth", "maxHeight", "sourceAspectRatio", "croppedImageSize", "requestedAspectRatio", "buildRect", "x", "y", "roundWithPrecision", "clamp", "outputHeight", "min", "max", "precision", "aspectRatio", "a", "b", "key", "asset", "normalizeAssetId", "_ref", "rest", "useEffect", "useRef", "useState", "Fragment", "jsx", "jsxs", "ImageWithPreview", "as", "preview", "style", "alt", "props", "loaded", "setLoaded", "ref", "onLoad", "Img", "baseStyles", "jsx", "SanityImage", "component", "baseUrl", "projectId", "dataset", "id", "hotspot", "crop", "width", "height", "mode", "preview", "htmlWidth", "htmlHeight", "htmlId", "queryParams", "rest", "isSvg", "ImageComponent", "ImageWithPreview", "componentProps", "baseAttributes", "A", "srcParams", "src", "outputDimensions", "w", "D"]
7
- }
@@ -1,3 +0,0 @@
1
- {
2
- "type": "module"
3
- }