sanity-image 0.0.1 → 0.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.
- package/dist/.DS_Store +0 -0
- package/dist/ImageWithPreview.d.ts +8 -0
- package/dist/SanityImage.d.ts +3 -0
- package/dist/builder.d.ts +6 -0
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/package.json +3 -0
- package/dist/imageUrls.d.ts +19 -0
- package/dist/index.d.ts +5 -0
- package/dist/mjs/index.js +2 -0
- package/dist/mjs/index.js.map +7 -0
- package/dist/mjs/package.json +3 -0
- package/dist/parseImageRef.d.ts +9 -0
- package/dist/types.d.ts +147 -0
- package/package.json +37 -25
- package/.prettierrc +0 -4
- package/README.md +0 -54
- package/dist/index.js +0 -1
package/dist/.DS_Store
ADDED
|
Binary file
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { ImageWithPreviewProps } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Renders two image tags, one with the preview image and one with the full
|
|
5
|
+
* image. When the full image is loaded, the preview image is removed, revealing
|
|
6
|
+
* the full image.
|
|
7
|
+
*/
|
|
8
|
+
export declare const ImageWithPreview: <T extends React.ElementType<any> = "img">({ as, preview, ...props }: ImageWithPreviewProps<T>) => JSX.Element;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import React, { type ReactElement } from "react";
|
|
2
|
+
import { PolymorphicComponentProp, SanityImageProps } from "./types";
|
|
3
|
+
export declare const SanityImage: <T extends React.ElementType<any> = "img">({ as: component, builder, asset, hotspot, crop, width, height, htmlWidth, htmlHeight, options, config, _type, _key, alt, ...rest }: PolymorphicComponentProp<T, SanityImageProps>) => ReactElement;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var q=Object.create;var b=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var G=Object.getPrototypeOf,Y=Object.prototype.hasOwnProperty;var J=(e,r)=>{for(var t in r)b(e,t,{get:r[t],enumerable:!0})},C=(e,r,t,i)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of D(r))!Y.call(e,o)&&o!==t&&b(e,o,{get:()=>r[o],enumerable:!(i=H(r,o))||i.enumerable});return e};var U=(e,r,t)=>(t=e!=null?q(G(e)):{},C(r||!e||!e.__esModule?b(t,"default",{value:e,enumerable:!0}):t,e)),K=e=>C(b({},"__esModule",{value:!0}),e);var Z={};J(Z,{ImageWithPreview:()=>y,SanityImage:()=>L,buildSource:()=>B,buildSourceSet:()=>S,createBuilder:()=>W,imageUrl:()=>f,parseImageRef:()=>c});module.exports=K(Z);var M=U(require("@sanity/image-url")),W=({dataset:e,projectId:r})=>(0,M.default)({dataset:e,projectId:r});var Q=/^image-([\da-f]+)-(\d+x\d+)-(\w+)$/,c=e=>{let r=Q.exec(e),[,t,i,o]=r!=null?r:[];if(!r||!t||!i||!o)throw new Error(`Could not parse image ID "${e}"`);let[a,n]=i.split("x").map(g=>Number.parseInt(g,10));if(Number.isNaN(a)||Number.isNaN(n)||!a||!n)throw new Error(`Invalid dimensions "${i}"`);return{assetId:t,dimensions:{height:n,width:a},format:o}};var j={auto:"format",fit:"max",quality:75},B=(e,r,{width:t,height:i,...o})=>{let{dimensions:a}=c(e._id),n=a.width/a.height;return t=t||a.width,i=i||Math.round(t/n),f(e,r,{...o,height:i,width:t})},S=(e,r,t)=>{var R,x,w;let{dimensions:i}=c(e._id),o=(R=t.fit)!=null?R:j.fit,a=i.width/i.height,n=(x=t.width)!=null?x:i.width,g=(w=t.height)!=null?w:Math.round(n/a),p=n/g,P=a,h=i.width,E=i.height;if(e.crop&&Object.values(e.crop).some(m=>m>0)){let m=i.width-e.crop.left*i.width-e.crop.right*i.width,s=i.height-e.crop.top*i.height-e.crop.bottom*i.height;P=m/s,P>a?E=s:h=m}return Object.values([.5,.75,1,1.5,2].reduce((m,s)=>{let l=f(e,r,{...t,dpr:s}),u=Math.round(o&&["fillmax","max","min"].includes(o)?p<a?Math.min(E/(g*s)*(n*s),n*s):Math.min(n*s,h):n*s);return m[u]||(m[u]=`${l} ${u}w`),m},{})).join(", ")},f=(e,r,t={})=>{let i={...j,...t},o=r.image(e);return V(Object.keys(i),o),Object.entries(i).forEach(([a,n])=>{o=Array.isArray(n)?o[a](...n):o[a](n)}),o.url()};function V(e,r){if(!e.every(t=>X(t,r)))throw new Error("Invalid image URL parameter provided")}function X(e,r){return e in r}var d=U(require("react")),y=({as:e,preview:r,...t})=>{let[i,o]=(0,d.useState)(!1),a=(0,d.useRef)(null),n=()=>{o(!0)};(0,d.useEffect)(()=>{var p;(p=a.current)!=null&&p.complete&&n()});let g=e||"img";return d.default.createElement(d.default.Fragment,null,!i&&d.default.createElement(g,{alt:t.alt,className:t.className,"data-lqip":!0,height:t.height,id:t.id,src:r,style:t.style,width:t.width}),d.default.createElement(g,{"data-loading":i?null:!0,onLoad:n,ref:a,style:i?void 0:{height:"10px !important",opacity:0,pointerEvents:"none",position:"absolute",userSelect:"none",width:"10px !important",zIndex:-10},...t}))};var v=U(require("react"));var L=({as:e,builder:r,asset:t,hotspot:i,crop:o,width:a,height:n,htmlWidth:g,htmlHeight:p,options:P={},config:h={},_type:E,_key:R,alt:x="",...w})=>{var A,N,T;let m=e!=null?e:"img",s=(T=(A=t.metadata)==null?void 0:A.preview)!=null?T:(N=t.metadata)==null?void 0:N.lqip,l={...w,alt:x||""},u={_id:"_id"in t?t._id:t._ref,crop:o,hotspot:i};if(c(u._id).format==="svg")return v.default.createElement(m,{src:f(u,r),...l});let O=B(u,r,{...h,height:n,width:a}),$=S(u,r,{...h,height:n,width:a});if(P.aspectRatio){let{dimensions:I}=c(u._id);if(a&&n)l.width=a,l.height=n;else{o=o!=null?o:{bottom:0,left:0,right:0,top:0};let z=I.width*(1-o.left-o.right),F=I.height*(1-o.top-o.bottom),k=z/F;l.width=a!=null?a:I.width,l.height=Math.round(l.width/k)}}g&&(l.width=g),p&&(l.height=p);let ee=s?y:m,_={...l,loading:"lazy",src:O,srcSet:$,style:{...l.style,...i&&{objectPosition:[i.x,i.y].map(I=>(I*100).toFixed(2)+"%").join(" ")}}};return s?v.default.createElement(y,{..._,as:m,preview:s}):v.default.createElement(m,{..._})};0&&(module.exports={ImageWithPreview,SanityImage,buildSource,buildSourceSet,createBuilder,imageUrl,parseImageRef});
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/index.ts", "../../src/builder.ts", "../../src/parseImageRef.ts", "../../src/imageUrls.ts", "../../src/ImageWithPreview.tsx", "../../src/SanityImage.tsx"],
|
|
4
|
+
"sourcesContent": ["export { createBuilder } from \"./builder\"\nexport { imageUrl, buildSource, buildSourceSet } from \"./imageUrls\"\nexport { ImageWithPreview } from \"./ImageWithPreview\"\nexport { parseImageRef } from \"./parseImageRef\"\nexport { SanityImage } from \"./SanityImage\"\n", "import sanityImageUrl from \"@sanity/image-url\"\n\ntype BuilderConfig = {\n dataset: string\n projectId: string\n}\n\nexport const createBuilder = ({ dataset, projectId }: BuilderConfig) =>\n sanityImageUrl({ dataset, projectId })\n", "import { ImageRefParts } from \"./types\"\n\nexport const SANITY_REF_PATTERN = /^image-([\\da-f]+)-(\\d+x\\d+)-(\\w+)$/\n\n/**\n * Parse an image reference string into its component parts.\n *\n * @param {string} id The image reference string to parse in the format `image-<hash>-<width>x<height>.<ext>`\n * @returns {ImageRefParts} An object containing the asset ID, dimensions, and format\n */\nexport const parseImageRef = (id: string): ImageRefParts => {\n const match = SANITY_REF_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 },\n format,\n }\n}\n", "import { type ImageUrlBuilder } from \"@sanity/image-url/lib/types/builder\"\nimport { parseImageRef } from \"./parseImageRef\"\nimport { Asset, ImageBuilderParameter, ImageBuilderParameters } from \"./types\"\n\nexport const DEFAULT_IMAGE_CONFIG: ImageBuilderParameters = {\n auto: \"format\",\n fit: \"max\",\n quality: 75,\n}\n\n/**\n * Returns the default `src` for the image based on the expected width (and\n * height) of the displayed image.\n */\nexport const buildSource = (\n asset: Asset,\n builder: ImageUrlBuilder,\n { width, height, ...config }: ImageBuilderParameters\n): string => {\n const { dimensions } = parseImageRef(asset._id)\n\n const origRatio = dimensions.width / dimensions.height\n width = width || dimensions.width\n height = height || Math.round(width / origRatio)\n\n return imageUrl(asset, builder, {\n ...config,\n height,\n width,\n })\n}\n\n/**\n * Returns a `srcSet` string for the image based on the expected width. The\n * generated `srcSet` will include images at 0.5x, 0.75x, 1x, 1.5x, and 2x the\n * expected width.\n *\n * This method also considers the FitMode configuration. If Sanity will not\n * scale up the image in the supplied mode, the `srcSet` will not include links\n * to images larger than the original image.\n */\nexport const buildSourceSet = (\n asset: Asset,\n builder: ImageUrlBuilder,\n config: ImageBuilderParameters\n): string => {\n const { dimensions } = parseImageRef(asset._id)\n const fitMode = config.fit ?? DEFAULT_IMAGE_CONFIG.fit\n\n // Determine dimensions and ratios for srcSet calculations\n const origRatio = dimensions.width / dimensions.height\n const width = config.width ?? dimensions.width\n const height = config.height ?? Math.round(width / origRatio)\n const targetRatio = width / height\n let cropRatio = origRatio\n let maxWidth = dimensions.width\n let maxHeight = dimensions.height\n\n // Compensate for dimensional changes if image was cropped in Sanity\n if (asset.crop && Object.values(asset.crop).some((n) => n > 0)) {\n const cropWidth =\n dimensions.width -\n asset.crop.left * dimensions.width -\n asset.crop.right * dimensions.width\n const cropHeight =\n dimensions.height -\n asset.crop.top * dimensions.height -\n asset.crop.bottom * dimensions.height\n\n cropRatio = cropWidth / cropHeight\n if (cropRatio > origRatio) {\n maxHeight = cropHeight\n } else {\n maxWidth = cropWidth\n }\n }\n\n return Object.values(\n [0.5, 0.75, 1, 1.5, 2].reduce((set: { [size: number]: string }, dpr) => {\n const url = imageUrl(asset, builder, { ...config, dpr })\n const size = Math.round(\n // For modes where Sanity will not scale up, determine\n // the anticipated final width based on the params\n fitMode && [\"fillmax\", \"max\", \"min\"].includes(fitMode)\n ? targetRatio < origRatio\n ? Math.min(\n (maxHeight / (height * dpr)) * (width * dpr),\n width * dpr\n )\n : Math.min(width * dpr, maxWidth)\n : width * dpr\n )\n\n // Avoid duplicate sizes in srcSet list\n if (!set[size]) {\n set[size] = `${url} ${size}w`\n }\n\n return set\n }, {})\n ).join(\", \")\n}\n\nexport const imageUrl = (\n asset: Asset,\n builder: ImageUrlBuilder,\n parameters: ImageBuilderParameters = {}\n): string => {\n const combinedParameters = { ...DEFAULT_IMAGE_CONFIG, ...parameters }\n let imageUrlBuilder = builder.image(asset)\n\n validateImageUrlParameters(Object.keys(combinedParameters), imageUrlBuilder)\n\n Object.entries(combinedParameters).forEach(([key, value]) => {\n imageUrlBuilder = Array.isArray(value)\n ? (imageUrlBuilder as any)[key](...value)\n : (imageUrlBuilder as any)[key](value)\n })\n\n return imageUrlBuilder.url()\n}\n\nfunction validateImageUrlParameters(\n keys: string[],\n imageUrlBuilder: ImageUrlBuilder\n): asserts keys is ImageBuilderParameter[] {\n if (!keys.every((key) => validateImageUrlParameter(key, imageUrlBuilder))) {\n throw new Error(`Invalid image URL parameter provided`)\n }\n}\n\nfunction validateImageUrlParameter(\n key: string,\n imageUrlBuilder: ImageUrlBuilder\n): key is ImageBuilderParameter {\n return key in imageUrlBuilder\n}\n", "import React, { useEffect, useRef, useState } from \"react\"\nimport { ImageWithPreviewProps } 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 ...props\n}: ImageWithPreviewProps<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 (ref.current?.complete) {\n onLoad()\n }\n })\n\n const Img = as || \"img\"\n\n return (\n <>\n {!loaded && (\n <Img\n alt={props.alt}\n className={props.className}\n data-lqip\n height={props.height}\n id={props.id}\n src={preview}\n style={props.style}\n width={props.width}\n />\n )}\n <Img\n data-loading={loaded ? null : true}\n onLoad={onLoad}\n ref={ref}\n style={\n loaded\n ? undefined\n : {\n // must be > 4px to be lazy loaded\n height: \"10px !important\",\n\n // must be > 4px to be lazy loaded\n opacity: 0,\n\n pointerEvents: \"none\",\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 userSelect: \"none\",\n width: \"10px !important\",\n zIndex: -10,\n }\n }\n {...props}\n />\n </>\n )\n}\n", "import React, {\n type ReactElement,\n type ElementType,\n type ComponentPropsWithoutRef,\n} from \"react\"\nimport { Asset, PolymorphicComponentProp, SanityImageProps } from \"./types\"\nimport { parseImageRef } from \"./parseImageRef\"\nimport { buildSource, buildSourceSet, imageUrl } from \"./imageUrls\"\nimport { ImageWithPreview } from \"./ImageWithPreview\"\n\nexport const SanityImage = <T extends ElementType = \"img\">({\n as: component,\n builder,\n\n asset,\n hotspot,\n crop,\n\n width,\n height,\n htmlWidth,\n htmlHeight,\n\n options = {},\n config = {},\n\n // Swallowing these params for convenience\n _type,\n _key,\n\n alt = \"\",\n ...rest\n}: PolymorphicComponentProp<T, SanityImageProps>): ReactElement => {\n const ImageComponent = component ?? \"img\"\n const preview = asset.metadata?.preview ?? asset.metadata?.lqip\n\n const props: typeof rest & {\n alt: string\n width?: number\n height?: number\n } = {\n ...rest,\n alt: alt || \"\",\n }\n\n // Rebuild `asset` with only the properties needed for the image\n const image: Asset = {\n _id: \"_id\" in asset ? asset._id : asset._ref,\n crop,\n hotspot,\n }\n\n // Short circuit for SVG images\n if (parseImageRef(image._id).format === \"svg\") {\n return <ImageComponent src={imageUrl(image, builder)} {...props} />\n }\n\n // Create default src and build srcSet\n const source = buildSource(image, builder, { ...config, height, width })\n const sourceSet = buildSourceSet(image, builder, { ...config, height, width })\n\n if (options.aspectRatio) {\n // If enabled, this will estimate the final aspect ratio based on\n // the dimensions of the original image and the crop parameter,\n // then use this aspect ratio to apply `width` and `height` attrs\n // to both the preview and final images.\n //\n // Note: No attempts are made to compensate for the `fit` mode or\n // image params that transform the final output dimensions in this\n // early proof-of-concept version.\n const { dimensions } = parseImageRef(image._id)\n\n // Short circuit if both width and height are set. This will result\n // in the final aspect ratio matching the aspect ration of the\n // provided width and height props, ignoring the image dimensions.\n //\n // This relies on a bug in the @sanity/image-url library that\n // results in images being cropped with fit modes where they\n // should not be.\n if (width && height) {\n props.width = width\n props.height = height\n } else {\n // If `crop` isn't set, use fallback values.\n crop = crop ?? { bottom: 0, left: 0, right: 0, top: 0 }\n\n const croppedWidth = dimensions.width * (1 - crop.left - crop.right)\n const croppedHeight = dimensions.height * (1 - crop.top - crop.bottom)\n const ratio = croppedWidth / croppedHeight\n\n props.width = width ?? dimensions.width\n props.height = Math.round(props.width / ratio)\n }\n }\n\n if (htmlWidth) props.width = htmlWidth\n if (htmlHeight) props.height = htmlHeight\n\n const Image = preview ? ImageWithPreview : ImageComponent\n\n const componentProps: ComponentPropsWithoutRef<typeof Image> = {\n ...props,\n loading: \"lazy\",\n src: source,\n srcSet: sourceSet,\n style: {\n ...props.style,\n ...(hotspot && {\n objectPosition: [hotspot.x, hotspot.y]\n .map((value) => (value * 100).toFixed(2) + \"%\")\n .join(\" \"),\n }),\n },\n }\n\n return preview ? (\n <ImageWithPreview\n {...componentProps}\n as={ImageComponent}\n preview={preview}\n />\n ) : (\n <ImageComponent {...componentProps} />\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["src_exports", "__export", "ImageWithPreview", "SanityImage", "buildSource", "buildSourceSet", "createBuilder", "imageUrl", "parseImageRef", "__toCommonJS", "import_image_url", "createBuilder", "dataset", "projectId", "sanityImageUrl", "SANITY_REF_PATTERN", "parseImageRef", "id", "match", "assetId", "dimensions", "format", "width", "height", "value", "DEFAULT_IMAGE_CONFIG", "buildSource", "asset", "builder", "width", "height", "config", "dimensions", "parseImageRef", "origRatio", "imageUrl", "buildSourceSet", "_a", "_b", "_c", "fitMode", "targetRatio", "cropRatio", "maxWidth", "maxHeight", "n", "cropWidth", "cropHeight", "set", "dpr", "url", "size", "parameters", "combinedParameters", "imageUrlBuilder", "validateImageUrlParameters", "key", "value", "keys", "validateImageUrlParameter", "import_react", "ImageWithPreview", "as", "preview", "props", "loaded", "setLoaded", "ref", "onLoad", "_a", "Img", "React", "import_react", "SanityImage", "component", "builder", "asset", "hotspot", "crop", "width", "height", "htmlWidth", "htmlHeight", "options", "config", "_type", "_key", "alt", "rest", "_a", "_b", "_c", "ImageComponent", "preview", "props", "image", "parseImageRef", "React", "imageUrl", "source", "buildSource", "sourceSet", "buildSourceSet", "dimensions", "croppedWidth", "croppedHeight", "ratio", "Image", "ImageWithPreview", "componentProps", "value"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ImageUrlBuilder } from "@sanity/image-url/lib/types/builder";
|
|
2
|
+
import { Asset, ImageBuilderParameters } from "./types";
|
|
3
|
+
export declare const DEFAULT_IMAGE_CONFIG: ImageBuilderParameters;
|
|
4
|
+
/**
|
|
5
|
+
* Returns the default `src` for the image based on the expected width (and
|
|
6
|
+
* height) of the displayed image.
|
|
7
|
+
*/
|
|
8
|
+
export declare const buildSource: (asset: Asset, builder: ImageUrlBuilder, { width, height, ...config }: ImageBuilderParameters) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Returns a `srcSet` string for the image based on the expected width. The
|
|
11
|
+
* generated `srcSet` will include images at 0.5x, 0.75x, 1x, 1.5x, and 2x the
|
|
12
|
+
* expected width.
|
|
13
|
+
*
|
|
14
|
+
* This method also considers the FitMode configuration. If Sanity will not
|
|
15
|
+
* scale up the image in the supplied mode, the `srcSet` will not include links
|
|
16
|
+
* to images larger than the original image.
|
|
17
|
+
*/
|
|
18
|
+
export declare const buildSourceSet: (asset: Asset, builder: ImageUrlBuilder, config: ImageBuilderParameters) => string;
|
|
19
|
+
export declare const imageUrl: (asset: Asset, builder: ImageUrlBuilder, parameters?: ImageBuilderParameters) => string;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import M from"@sanity/image-url";var W=({dataset:r,projectId:n})=>M({dataset:r,projectId:n});var j=/^image-([\da-f]+)-(\d+x\d+)-(\w+)$/,c=r=>{let n=j.exec(r),[,t,e,a]=n??[];if(!n||!t||!e||!a)throw new Error(`Could not parse image ID "${r}"`);let[i,o]=e.split("x").map(s=>Number.parseInt(s,10));if(Number.isNaN(i)||Number.isNaN(o)||!i||!o)throw new Error(`Invalid dimensions "${e}"`);return{assetId:t,dimensions:{height:o,width:i},format:a}};var U={auto:"format",fit:"max",quality:75},S=(r,n,{width:t,height:e,...a})=>{let{dimensions:i}=c(r._id),o=i.width/i.height;return t=t||i.width,e=e||Math.round(t/o),h(r,n,{...a,height:e,width:t})},v=(r,n,t)=>{let{dimensions:e}=c(r._id),a=t.fit??U.fit,i=e.width/e.height,o=t.width??e.width,s=t.height??Math.round(o/i),I=o/s,y=i,u=e.width,x=e.height;if(r.crop&&Object.values(r.crop).some(l=>l>0)){let l=e.width-r.crop.left*e.width-r.crop.right*e.width,m=e.height-r.crop.top*e.height-r.crop.bottom*e.height;y=l/m,y>i?x=m:u=l}return Object.values([.5,.75,1,1.5,2].reduce((l,m)=>{let b=h(r,n,{...t,dpr:m}),g=Math.round(a&&["fillmax","max","min"].includes(a)?I<i?Math.min(x/(s*m)*(o*m),o*m):Math.min(o*m,u):o*m);return l[g]||(l[g]=`${b} ${g}w`),l},{})).join(", ")},h=(r,n,t={})=>{let e={...U,...t},a=n.image(r);return L(Object.keys(e),a),Object.entries(e).forEach(([i,o])=>{a=Array.isArray(o)?a[i](...o):a[i](o)}),a.url()};function L(r,n){if(!r.every(t=>O(t,n)))throw new Error("Invalid image URL parameter provided")}function O(r,n){return r in n}import P,{useEffect as $,useRef as z,useState as F}from"react";var w=({as:r,preview:n,...t})=>{let[e,a]=F(!1),i=z(null),o=()=>{a(!0)};$(()=>{i.current?.complete&&o()});let s=r||"img";return P.createElement(P.Fragment,null,!e&&P.createElement(s,{alt:t.alt,className:t.className,"data-lqip":!0,height:t.height,id:t.id,src:n,style:t.style,width:t.width}),P.createElement(s,{"data-loading":e?null:!0,onLoad:o,ref:i,style:e?void 0:{height:"10px !important",opacity:0,pointerEvents:"none",position:"absolute",userSelect:"none",width:"10px !important",zIndex:-10},...t}))};import E from"react";var k=({as:r,builder:n,asset:t,hotspot:e,crop:a,width:i,height:o,htmlWidth:s,htmlHeight:I,options:y={},config:u={},_type:x,_key:l,alt:m="",...b})=>{let g=r??"img",B=t.metadata?.preview??t.metadata?.lqip,d={...b,alt:m||""},p={_id:"_id"in t?t._id:t._ref,crop:a,hotspot:e};if(c(p._id).format==="svg")return E.createElement(g,{src:h(p,n),...d});let _=S(p,n,{...u,height:o,width:i}),A=v(p,n,{...u,height:o,width:i});if(y.aspectRatio){let{dimensions:f}=c(p._id);if(i&&o)d.width=i,d.height=o;else{a=a??{bottom:0,left:0,right:0,top:0};let N=f.width*(1-a.left-a.right),T=f.height*(1-a.top-a.bottom),C=N/T;d.width=i??f.width,d.height=Math.round(d.width/C)}}s&&(d.width=s),I&&(d.height=I);let q=B?w:g,R={...d,loading:"lazy",src:_,srcSet:A,style:{...d.style,...e&&{objectPosition:[e.x,e.y].map(f=>(f*100).toFixed(2)+"%").join(" ")}}};return B?E.createElement(w,{...R,as:g,preview:B}):E.createElement(g,{...R})};export{w as ImageWithPreview,k as SanityImage,S as buildSource,v as buildSourceSet,W as createBuilder,h as imageUrl,c as parseImageRef};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/builder.ts", "../../src/parseImageRef.ts", "../../src/imageUrls.ts", "../../src/ImageWithPreview.tsx", "../../src/SanityImage.tsx"],
|
|
4
|
+
"sourcesContent": ["import sanityImageUrl from \"@sanity/image-url\"\n\ntype BuilderConfig = {\n dataset: string\n projectId: string\n}\n\nexport const createBuilder = ({ dataset, projectId }: BuilderConfig) =>\n sanityImageUrl({ dataset, projectId })\n", "import { ImageRefParts } from \"./types\"\n\nexport const SANITY_REF_PATTERN = /^image-([\\da-f]+)-(\\d+x\\d+)-(\\w+)$/\n\n/**\n * Parse an image reference string into its component parts.\n *\n * @param {string} id The image reference string to parse in the format `image-<hash>-<width>x<height>.<ext>`\n * @returns {ImageRefParts} An object containing the asset ID, dimensions, and format\n */\nexport const parseImageRef = (id: string): ImageRefParts => {\n const match = SANITY_REF_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 },\n format,\n }\n}\n", "import { type ImageUrlBuilder } from \"@sanity/image-url/lib/types/builder\"\nimport { parseImageRef } from \"./parseImageRef\"\nimport { Asset, ImageBuilderParameter, ImageBuilderParameters } from \"./types\"\n\nexport const DEFAULT_IMAGE_CONFIG: ImageBuilderParameters = {\n auto: \"format\",\n fit: \"max\",\n quality: 75,\n}\n\n/**\n * Returns the default `src` for the image based on the expected width (and\n * height) of the displayed image.\n */\nexport const buildSource = (\n asset: Asset,\n builder: ImageUrlBuilder,\n { width, height, ...config }: ImageBuilderParameters\n): string => {\n const { dimensions } = parseImageRef(asset._id)\n\n const origRatio = dimensions.width / dimensions.height\n width = width || dimensions.width\n height = height || Math.round(width / origRatio)\n\n return imageUrl(asset, builder, {\n ...config,\n height,\n width,\n })\n}\n\n/**\n * Returns a `srcSet` string for the image based on the expected width. The\n * generated `srcSet` will include images at 0.5x, 0.75x, 1x, 1.5x, and 2x the\n * expected width.\n *\n * This method also considers the FitMode configuration. If Sanity will not\n * scale up the image in the supplied mode, the `srcSet` will not include links\n * to images larger than the original image.\n */\nexport const buildSourceSet = (\n asset: Asset,\n builder: ImageUrlBuilder,\n config: ImageBuilderParameters\n): string => {\n const { dimensions } = parseImageRef(asset._id)\n const fitMode = config.fit ?? DEFAULT_IMAGE_CONFIG.fit\n\n // Determine dimensions and ratios for srcSet calculations\n const origRatio = dimensions.width / dimensions.height\n const width = config.width ?? dimensions.width\n const height = config.height ?? Math.round(width / origRatio)\n const targetRatio = width / height\n let cropRatio = origRatio\n let maxWidth = dimensions.width\n let maxHeight = dimensions.height\n\n // Compensate for dimensional changes if image was cropped in Sanity\n if (asset.crop && Object.values(asset.crop).some((n) => n > 0)) {\n const cropWidth =\n dimensions.width -\n asset.crop.left * dimensions.width -\n asset.crop.right * dimensions.width\n const cropHeight =\n dimensions.height -\n asset.crop.top * dimensions.height -\n asset.crop.bottom * dimensions.height\n\n cropRatio = cropWidth / cropHeight\n if (cropRatio > origRatio) {\n maxHeight = cropHeight\n } else {\n maxWidth = cropWidth\n }\n }\n\n return Object.values(\n [0.5, 0.75, 1, 1.5, 2].reduce((set: { [size: number]: string }, dpr) => {\n const url = imageUrl(asset, builder, { ...config, dpr })\n const size = Math.round(\n // For modes where Sanity will not scale up, determine\n // the anticipated final width based on the params\n fitMode && [\"fillmax\", \"max\", \"min\"].includes(fitMode)\n ? targetRatio < origRatio\n ? Math.min(\n (maxHeight / (height * dpr)) * (width * dpr),\n width * dpr\n )\n : Math.min(width * dpr, maxWidth)\n : width * dpr\n )\n\n // Avoid duplicate sizes in srcSet list\n if (!set[size]) {\n set[size] = `${url} ${size}w`\n }\n\n return set\n }, {})\n ).join(\", \")\n}\n\nexport const imageUrl = (\n asset: Asset,\n builder: ImageUrlBuilder,\n parameters: ImageBuilderParameters = {}\n): string => {\n const combinedParameters = { ...DEFAULT_IMAGE_CONFIG, ...parameters }\n let imageUrlBuilder = builder.image(asset)\n\n validateImageUrlParameters(Object.keys(combinedParameters), imageUrlBuilder)\n\n Object.entries(combinedParameters).forEach(([key, value]) => {\n imageUrlBuilder = Array.isArray(value)\n ? (imageUrlBuilder as any)[key](...value)\n : (imageUrlBuilder as any)[key](value)\n })\n\n return imageUrlBuilder.url()\n}\n\nfunction validateImageUrlParameters(\n keys: string[],\n imageUrlBuilder: ImageUrlBuilder\n): asserts keys is ImageBuilderParameter[] {\n if (!keys.every((key) => validateImageUrlParameter(key, imageUrlBuilder))) {\n throw new Error(`Invalid image URL parameter provided`)\n }\n}\n\nfunction validateImageUrlParameter(\n key: string,\n imageUrlBuilder: ImageUrlBuilder\n): key is ImageBuilderParameter {\n return key in imageUrlBuilder\n}\n", "import React, { useEffect, useRef, useState } from \"react\"\nimport { ImageWithPreviewProps } 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 ...props\n}: ImageWithPreviewProps<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 (ref.current?.complete) {\n onLoad()\n }\n })\n\n const Img = as || \"img\"\n\n return (\n <>\n {!loaded && (\n <Img\n alt={props.alt}\n className={props.className}\n data-lqip\n height={props.height}\n id={props.id}\n src={preview}\n style={props.style}\n width={props.width}\n />\n )}\n <Img\n data-loading={loaded ? null : true}\n onLoad={onLoad}\n ref={ref}\n style={\n loaded\n ? undefined\n : {\n // must be > 4px to be lazy loaded\n height: \"10px !important\",\n\n // must be > 4px to be lazy loaded\n opacity: 0,\n\n pointerEvents: \"none\",\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 userSelect: \"none\",\n width: \"10px !important\",\n zIndex: -10,\n }\n }\n {...props}\n />\n </>\n )\n}\n", "import React, {\n type ReactElement,\n type ElementType,\n type ComponentPropsWithoutRef,\n} from \"react\"\nimport { Asset, PolymorphicComponentProp, SanityImageProps } from \"./types\"\nimport { parseImageRef } from \"./parseImageRef\"\nimport { buildSource, buildSourceSet, imageUrl } from \"./imageUrls\"\nimport { ImageWithPreview } from \"./ImageWithPreview\"\n\nexport const SanityImage = <T extends ElementType = \"img\">({\n as: component,\n builder,\n\n asset,\n hotspot,\n crop,\n\n width,\n height,\n htmlWidth,\n htmlHeight,\n\n options = {},\n config = {},\n\n // Swallowing these params for convenience\n _type,\n _key,\n\n alt = \"\",\n ...rest\n}: PolymorphicComponentProp<T, SanityImageProps>): ReactElement => {\n const ImageComponent = component ?? \"img\"\n const preview = asset.metadata?.preview ?? asset.metadata?.lqip\n\n const props: typeof rest & {\n alt: string\n width?: number\n height?: number\n } = {\n ...rest,\n alt: alt || \"\",\n }\n\n // Rebuild `asset` with only the properties needed for the image\n const image: Asset = {\n _id: \"_id\" in asset ? asset._id : asset._ref,\n crop,\n hotspot,\n }\n\n // Short circuit for SVG images\n if (parseImageRef(image._id).format === \"svg\") {\n return <ImageComponent src={imageUrl(image, builder)} {...props} />\n }\n\n // Create default src and build srcSet\n const source = buildSource(image, builder, { ...config, height, width })\n const sourceSet = buildSourceSet(image, builder, { ...config, height, width })\n\n if (options.aspectRatio) {\n // If enabled, this will estimate the final aspect ratio based on\n // the dimensions of the original image and the crop parameter,\n // then use this aspect ratio to apply `width` and `height` attrs\n // to both the preview and final images.\n //\n // Note: No attempts are made to compensate for the `fit` mode or\n // image params that transform the final output dimensions in this\n // early proof-of-concept version.\n const { dimensions } = parseImageRef(image._id)\n\n // Short circuit if both width and height are set. This will result\n // in the final aspect ratio matching the aspect ration of the\n // provided width and height props, ignoring the image dimensions.\n //\n // This relies on a bug in the @sanity/image-url library that\n // results in images being cropped with fit modes where they\n // should not be.\n if (width && height) {\n props.width = width\n props.height = height\n } else {\n // If `crop` isn't set, use fallback values.\n crop = crop ?? { bottom: 0, left: 0, right: 0, top: 0 }\n\n const croppedWidth = dimensions.width * (1 - crop.left - crop.right)\n const croppedHeight = dimensions.height * (1 - crop.top - crop.bottom)\n const ratio = croppedWidth / croppedHeight\n\n props.width = width ?? dimensions.width\n props.height = Math.round(props.width / ratio)\n }\n }\n\n if (htmlWidth) props.width = htmlWidth\n if (htmlHeight) props.height = htmlHeight\n\n const Image = preview ? ImageWithPreview : ImageComponent\n\n const componentProps: ComponentPropsWithoutRef<typeof Image> = {\n ...props,\n loading: \"lazy\",\n src: source,\n srcSet: sourceSet,\n style: {\n ...props.style,\n ...(hotspot && {\n objectPosition: [hotspot.x, hotspot.y]\n .map((value) => (value * 100).toFixed(2) + \"%\")\n .join(\" \"),\n }),\n },\n }\n\n return preview ? (\n <ImageWithPreview\n {...componentProps}\n as={ImageComponent}\n preview={preview}\n />\n ) : (\n <ImageComponent {...componentProps} />\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["sanityImageUrl", "createBuilder", "dataset", "projectId", "SANITY_REF_PATTERN", "parseImageRef", "id", "match", "assetId", "dimensions", "format", "width", "height", "value", "DEFAULT_IMAGE_CONFIG", "buildSource", "asset", "builder", "width", "height", "config", "dimensions", "parseImageRef", "origRatio", "imageUrl", "buildSourceSet", "fitMode", "targetRatio", "cropRatio", "maxWidth", "maxHeight", "n", "cropWidth", "cropHeight", "set", "dpr", "url", "size", "parameters", "combinedParameters", "imageUrlBuilder", "validateImageUrlParameters", "key", "value", "keys", "validateImageUrlParameter", "React", "useEffect", "useRef", "useState", "ImageWithPreview", "as", "preview", "props", "loaded", "setLoaded", "ref", "onLoad", "Img", "React", "SanityImage", "component", "builder", "asset", "hotspot", "crop", "width", "height", "htmlWidth", "htmlHeight", "options", "config", "_type", "_key", "alt", "rest", "ImageComponent", "preview", "props", "image", "parseImageRef", "React", "imageUrl", "source", "buildSource", "sourceSet", "buildSourceSet", "dimensions", "croppedWidth", "croppedHeight", "ratio", "Image", "ImageWithPreview", "componentProps", "value"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ImageRefParts } from "./types";
|
|
2
|
+
export declare const SANITY_REF_PATTERN: RegExp;
|
|
3
|
+
/**
|
|
4
|
+
* Parse an image reference string into its component parts.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} id The image reference string to parse in the format `image-<hash>-<width>x<height>.<ext>`
|
|
7
|
+
* @returns {ImageRefParts} An object containing the asset ID, dimensions, and format
|
|
8
|
+
*/
|
|
9
|
+
export declare const parseImageRef: (id: string) => ImageRefParts;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { type ImageUrlBuilder } from "@sanity/image-url/lib/types/builder";
|
|
3
|
+
import { type AutoMode, type CropMode, type FitMode, type ImageFormat, type ImageUrlBuilderOptionsWithAliases, type SanityImageSource, type Orientation } from "@sanity/image-url/lib/types/types";
|
|
4
|
+
export type PolymorphicComponentProp<T extends React.ElementType, Props = {}> = React.PropsWithChildren<Props & AsProp<T>> & Omit<React.ComponentPropsWithoutRef<T>, PropsToOmit<T, Props>>;
|
|
5
|
+
type AsProp<T extends React.ElementType> = {
|
|
6
|
+
/**
|
|
7
|
+
* By default, the component will render an `<img>` tag. You can override this
|
|
8
|
+
* by passing a different component or HTML tag name.
|
|
9
|
+
*/
|
|
10
|
+
as?: T;
|
|
11
|
+
};
|
|
12
|
+
type PropsToOmit<C extends React.ElementType, P> = keyof (AsProp<C> & P);
|
|
13
|
+
export type SanityImageProps = {
|
|
14
|
+
/**
|
|
15
|
+
* Object with either an `_id` or a `_ref` property representing the Sanity.io
|
|
16
|
+
* image `_id` and optionally metadata with a base-64 encoded preview image.
|
|
17
|
+
*/
|
|
18
|
+
asset: AssetProperty;
|
|
19
|
+
hotspot?: HotspotData;
|
|
20
|
+
crop?: CropData;
|
|
21
|
+
/**
|
|
22
|
+
* The Sanity image builder instance to use for generating the image URL.
|
|
23
|
+
*/
|
|
24
|
+
builder: ImageUrlBuilder;
|
|
25
|
+
/**
|
|
26
|
+
* Ignored prop to make it easier to expand an asset fetched from GROQ.
|
|
27
|
+
*/
|
|
28
|
+
_key?: unknown;
|
|
29
|
+
/**
|
|
30
|
+
* Ignored prop to make it easier to expand an asset fetched from GROQ.
|
|
31
|
+
*/
|
|
32
|
+
_type?: unknown;
|
|
33
|
+
/**
|
|
34
|
+
* `alt` attribute for the image; set to an empty string if not provided.
|
|
35
|
+
*/
|
|
36
|
+
alt?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Only used for determining the dimensions of the generated assets, not for
|
|
39
|
+
* layout. Use CSS to specify how the browser should render the image instead.
|
|
40
|
+
*/
|
|
41
|
+
width?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Only used for determining the dimensions of the generated assets, not for
|
|
44
|
+
* layout. Use CSS to specify how the browser should render the image instead.
|
|
45
|
+
*/
|
|
46
|
+
height?: number;
|
|
47
|
+
/**
|
|
48
|
+
* Passed through to the <img> tag as `height`, overriding the `aspectRatio`
|
|
49
|
+
* option, if enabled.
|
|
50
|
+
*/
|
|
51
|
+
htmlHeight?: number;
|
|
52
|
+
/**
|
|
53
|
+
* Passed through to the <img> tag as `width`, overriding the `aspectRatio`
|
|
54
|
+
* option, if enabled.
|
|
55
|
+
*/
|
|
56
|
+
htmlWidth?: number;
|
|
57
|
+
config?: ImageBuilderParameters;
|
|
58
|
+
options?: {
|
|
59
|
+
/**
|
|
60
|
+
* If enabled, this will estimate the final aspect ratio based on the
|
|
61
|
+
* dimensions of the original image and the crop parameter, then use this
|
|
62
|
+
* aspect ratio to apply `width` and `height` attrs to both the preview and
|
|
63
|
+
* final images.
|
|
64
|
+
*
|
|
65
|
+
* Note: No attempts are made to compensate for the `fit` mode or image
|
|
66
|
+
* params that transform the final output dimensions in this early
|
|
67
|
+
* proof-of-concept version.
|
|
68
|
+
*/
|
|
69
|
+
aspectRatio?: boolean;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
export type ImageWithPreviewProps<T extends React.ElementType> = {
|
|
73
|
+
preview: string;
|
|
74
|
+
} & AsProp<T> & React.ComponentPropsWithRef<T>;
|
|
75
|
+
type CropData = {
|
|
76
|
+
bottom: number;
|
|
77
|
+
left: number;
|
|
78
|
+
right: number;
|
|
79
|
+
top: number;
|
|
80
|
+
};
|
|
81
|
+
type HotspotData = {
|
|
82
|
+
height: number;
|
|
83
|
+
width: number;
|
|
84
|
+
x: number;
|
|
85
|
+
y: number;
|
|
86
|
+
};
|
|
87
|
+
type AssetMetadata = {
|
|
88
|
+
lqip?: string;
|
|
89
|
+
preview?: string;
|
|
90
|
+
};
|
|
91
|
+
type IdAsset = {
|
|
92
|
+
_id: string;
|
|
93
|
+
metadata?: AssetMetadata;
|
|
94
|
+
};
|
|
95
|
+
type RefAsset = {
|
|
96
|
+
_ref: string;
|
|
97
|
+
metadata?: AssetMetadata;
|
|
98
|
+
};
|
|
99
|
+
type AssetProperty = IdAsset | RefAsset;
|
|
100
|
+
export type Asset = {
|
|
101
|
+
_id: string;
|
|
102
|
+
crop?: CropData;
|
|
103
|
+
hotspot?: HotspotData;
|
|
104
|
+
metadata?: AssetMetadata;
|
|
105
|
+
};
|
|
106
|
+
export type ImageRefParts = {
|
|
107
|
+
assetId: string;
|
|
108
|
+
dimensions: {
|
|
109
|
+
height: number;
|
|
110
|
+
width: number;
|
|
111
|
+
};
|
|
112
|
+
format: string;
|
|
113
|
+
};
|
|
114
|
+
export type ImageBuilderParameter = keyof ImageBuilderParameters;
|
|
115
|
+
export type ImageBuilderParameters = {
|
|
116
|
+
auto?: AutoMode;
|
|
117
|
+
bg?: string;
|
|
118
|
+
blur?: number;
|
|
119
|
+
crop?: CropMode;
|
|
120
|
+
dataset?: string;
|
|
121
|
+
dpr?: number;
|
|
122
|
+
fit?: FitMode;
|
|
123
|
+
flipHorizontal?: boolean;
|
|
124
|
+
flipVertical?: boolean;
|
|
125
|
+
focalPoint?: [number, number];
|
|
126
|
+
forceDownload?: boolean | string;
|
|
127
|
+
format?: ImageFormat;
|
|
128
|
+
height?: number;
|
|
129
|
+
ignoreImageParams?: boolean;
|
|
130
|
+
image?: SanityImageSource;
|
|
131
|
+
invert?: boolean;
|
|
132
|
+
maxHeight?: number;
|
|
133
|
+
maxWidth?: number;
|
|
134
|
+
minHeight?: number;
|
|
135
|
+
minWidth?: number;
|
|
136
|
+
orientation?: Orientation;
|
|
137
|
+
pad?: number;
|
|
138
|
+
projectId?: string;
|
|
139
|
+
quality?: number;
|
|
140
|
+
rect?: [number, number, number, number];
|
|
141
|
+
saturation?: number;
|
|
142
|
+
sharpen?: number;
|
|
143
|
+
size?: [number, number];
|
|
144
|
+
width?: number;
|
|
145
|
+
withOptions?: Partial<ImageUrlBuilderOptionsWithAliases>;
|
|
146
|
+
};
|
|
147
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,35 +1,47 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sanity-image",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"
|
|
5
|
-
"main": "./dist/index.js",
|
|
6
|
-
"repository": "https://github.com/coreyward/sanity-image",
|
|
7
|
-
"author": "Corey Ward <corey.atx@gmail.com>",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"author": "Corey Ward <corey@hey.com>",
|
|
8
5
|
"license": "MIT",
|
|
9
|
-
"
|
|
6
|
+
"main": "dist/cjs/index.js",
|
|
7
|
+
"module": "dist/mjs/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/mjs/index.js",
|
|
12
|
+
"require": "./dist/cjs/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"/dist"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@sanity/image-url": "^1.0.2"
|
|
20
|
+
},
|
|
10
21
|
"peerDependencies": {
|
|
11
|
-
"react": "^16.8.0"
|
|
12
|
-
"@sanity/client": "^0.144.0",
|
|
13
|
-
"@sanity/image-url": "^0.140.15"
|
|
22
|
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
|
14
23
|
},
|
|
15
24
|
"devDependencies": {
|
|
16
|
-
"@
|
|
17
|
-
"@
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"prettier": "^
|
|
26
|
-
"
|
|
27
|
-
"react": "^
|
|
28
|
-
"
|
|
29
|
-
"
|
|
25
|
+
"@types/node": "^18.13.0",
|
|
26
|
+
"@types/react": "^18.0.28",
|
|
27
|
+
"esbuild": "^0.17.8",
|
|
28
|
+
"eslint": "^8.34.0",
|
|
29
|
+
"eslint-config-prettier": "^8.6.0",
|
|
30
|
+
"eslint-config-standard": "^17.0.0",
|
|
31
|
+
"eslint-plugin-import": "^2.27.5",
|
|
32
|
+
"eslint-plugin-n": "^15.6.1",
|
|
33
|
+
"eslint-plugin-node": "^11.1.0",
|
|
34
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
35
|
+
"eslint-plugin-promise": "^6.1.1",
|
|
36
|
+
"eslint-plugin-react": "^7.32.2",
|
|
37
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
38
|
+
"prettier": "^2.8.4",
|
|
39
|
+
"react": "^18.2.0",
|
|
40
|
+
"rimraf": "^4.1.2",
|
|
41
|
+
"typescript": "^4.9.5"
|
|
30
42
|
},
|
|
31
43
|
"scripts": {
|
|
32
|
-
"build": "
|
|
33
|
-
"
|
|
44
|
+
"build": "rimraf dist && node ./scripts/build.js && tsc",
|
|
45
|
+
"postbuild": "./scripts/postbuild.sh"
|
|
34
46
|
}
|
|
35
47
|
}
|
package/.prettierrc
DELETED
package/README.md
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# Sanity Image
|
|
2
|
-
|
|
3
|
-
React component wrapper around
|
|
4
|
-
[@sanity/image-url](https://github.com/sanity-io/image-url).
|
|
5
|
-
|
|
6
|
-
## Getting Started
|
|
7
|
-
|
|
8
|
-
```
|
|
9
|
-
yarn add sanity-image
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
Or, with npm:
|
|
13
|
-
|
|
14
|
-
```
|
|
15
|
-
npm install --save sanity-image
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
If you don’t already have `@sanity/client` and `@sanity/image-url` in your
|
|
19
|
-
project, you will need to add them
|
|
20
|
-
(`yarn add @sanity/client @sanity/image-url`).
|
|
21
|
-
|
|
22
|
-
## Usage
|
|
23
|
-
|
|
24
|
-
Since `@sanity/image-url` uses your Sanity projectID and dataset to build image
|
|
25
|
-
urls, you will need to provide those. The preferred way of doing this is by
|
|
26
|
-
wrapping your application with the provided `SanityClient` component:
|
|
27
|
-
|
|
28
|
-
```jsx
|
|
29
|
-
import React from "react"
|
|
30
|
-
import Image, { SanityClient } from "sanity-image"
|
|
31
|
-
|
|
32
|
-
const App = ({ title, image }) => (
|
|
33
|
-
<SanityClient
|
|
34
|
-
dataset="<your_sanity_dataset>"
|
|
35
|
-
projectId="<your_sanity_project_id>"
|
|
36
|
-
>
|
|
37
|
-
<h1>{title}</h1>
|
|
38
|
-
<div>
|
|
39
|
-
<Image asset={image} size={[300, 200]} blur={10} alt="Example" />
|
|
40
|
-
</div>
|
|
41
|
-
</SanityClient>
|
|
42
|
-
)
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
All supported props provided to `Image` will be forwarded. Arrays will be
|
|
46
|
-
converted into arguments, (e.g. `rect=[1,2,3,4]` will become
|
|
47
|
-
`rect(1, 2, 3, 4)`). As with `@sanity/image-url`, if you provide hotspot and
|
|
48
|
-
crop details along with the asset they will automatically be used when cropping
|
|
49
|
-
the image.
|
|
50
|
-
|
|
51
|
-
## Options
|
|
52
|
-
|
|
53
|
-
The
|
|
54
|
-
[full list of options can be found here](https://github.com/sanity-io/image-url#builder-methods).
|
package/dist/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports=function(r){var t={};function e(n){if(t[n])return t[n].exports;var a=t[n]={i:n,l:!1,exports:{}};return r[n].call(a.exports,a,a.exports,e),a.l=!0,a.exports}return e.m=r,e.c=t,e.d=function(r,t,n){e.o(r,t)||Object.defineProperty(r,t,{enumerable:!0,get:n})},e.r=function(r){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(r,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(r,"__esModule",{value:!0})},e.t=function(r,t){if(1&t&&(r=e(r)),8&t)return r;if(4&t&&"object"==typeof r&&r&&r.__esModule)return r;var n=Object.create(null);if(e.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:r}),2&t&&"string"!=typeof r)for(var a in r)e.d(n,a,function(t){return r[t]}.bind(null,a));return n},e.n=function(r){var t=r&&r.__esModule?function(){return r.default}:function(){return r};return e.d(t,"a",t),t},e.o=function(r,t){return Object.prototype.hasOwnProperty.call(r,t)},e.p="",e(e.s=4)}([function(r,t){r.exports=require("prop-types")},function(r,t){r.exports=require("react")},function(r,t){r.exports=require("@sanity/client")},function(r,t){r.exports=require("@sanity/image-url")},function(r,t,e){"use strict";e.r(t),e.d(t,"SanityClientContext",(function(){return b})),e.d(t,"SanityClient",(function(){return y}));var n=e(1),a=e.n(n),i=e(0),o=e.n(i),u=e(2),l=e.n(u),c=e(3),f=e.n(c);function p(){return(p=Object.assign||function(r){for(var t=1;t<arguments.length;t++){var e=arguments[t];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(r[n]=e[n])}return r}).apply(this,arguments)}function s(r){return function(r){if(Array.isArray(r)){for(var t=0,e=new Array(r.length);t<r.length;t++)e[t]=r[t];return e}}(r)||function(r){if(Symbol.iterator in Object(r)||"[object Arguments]"===Object.prototype.toString.call(r))return Array.from(r)}(r)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}function m(r,t){return function(r){if(Array.isArray(r))return r}(r)||function(r,t){if(!(Symbol.iterator in Object(r)||"[object Arguments]"===Object.prototype.toString.call(r)))return;var e=[],n=!0,a=!1,i=void 0;try{for(var o,u=r[Symbol.iterator]();!(n=(o=u.next()).done)&&(e.push(o.value),!t||e.length!==t);n=!0);}catch(r){a=!0,i=r}finally{try{n||null==u.return||u.return()}finally{if(a)throw i}}return e}(r,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function d(r,t){if(null==r)return{};var e,n,a=function(r,t){if(null==r)return{};var e,n,a={},i=Object.keys(r);for(n=0;n<i.length;n++)e=i[n],t.indexOf(e)>=0||(a[e]=r[e]);return a}(r,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(r);for(n=0;n<i.length;n++)e=i[n],t.indexOf(e)>=0||Object.prototype.propertyIsEnumerable.call(r,e)&&(a[e]=r[e])}return a}var b=a.a.createContext(),y=function(r){var t=r.children,e=d(r,["children"]);return a.a.createElement(b.Provider,{value:l()(e)},t)};y.propTypes={projectId:o.a.string.isRequired,dataset:o.a.string.isRequired,token:o.a.string,useCdn:o.a.bool};var g=function(r){var t=r.asset,e=r.dataset,i=r.projectId,o=r.width,u=r.height,l=r.size,c=r.focalPoint,y=r.minWidth,g=r.maxWidth,h=r.minHeight,v=r.maxHeight,O=r.blur,j=r.sharpen,x=r.invert,w=r.rect,P=r.format,S=r.auto,q=r.orientation,H=r.quality,I=r.forceDownload,A=r.flipHorizontal,z=r.flipVertical,W=r.crop,T=r.fit,_=r.dpr,C=r.ignoreImageParams,E=d(r,["asset","dataset","projectId","width","height","size","focalPoint","minWidth","maxWidth","minHeight","maxHeight","blur","sharpen","invert","rect","format","auto","orientation","quality","forceDownload","flipHorizontal","flipVertical","crop","fit","dpr","ignoreImageParams"]),R=Object(n.useContext)(b),D=f()(R),M=Object.entries({dataset:e,projectId:i,width:o,height:u,size:l,focalPoint:c,minWidth:y,maxWidth:g,minHeight:h,maxHeight:v,blur:O,sharpen:j,invert:x,rect:w,format:P,auto:S,orientation:q,quality:H,forceDownload:I,flipHorizontal:A,flipVertical:z,crop:W,fit:T,dpr:_,ignoreImageParams:C}).reduce((function(r,t){var e=m(t,2),n=e[0],a=e[1];return a?Array.isArray(a)?r[n].apply(r,s(a)):r[n](a):r}),D.image(t));return a.a.createElement("img",p({src:M.url(),alt:""},E))};t.default=g,g.propTypes={asset:o.a.oneOfType([o.a.shape({asset:o.a.shape({_id:o.a.string.isRequired}).isRequired,hotspot:o.a.shape({height:o.a.number,width:o.a.number,x:o.a.number,y:o.a.number}),crop:o.a.shape({bottom:o.a.number,left:o.a.number,right:o.a.number,top:o.a.number})}),o.a.string]).isRequired,dataset:o.a.string,projectId:o.a.string,width:o.a.number,height:o.a.number,size:o.a.arrayOf(o.a.number),focalPoint:o.a.arrayOf(o.a.number),minWidth:o.a.number,maxWidth:o.a.number,minHeight:o.a.number,maxHeight:o.a.number,blur:o.a.number,sharpen:o.a.number,invert:o.a.bool,rect:o.a.arrayOf(o.a.number),format:o.a.oneOf(["jpg","pjpg","png","webp"]),auto:o.a.oneOf(["format"]),orientation:o.a.oneOf([0,90,180,270]),quality:o.a.number,forceDownload:o.a.string,flipHorizontal:o.a.bool,flipVertical:o.a.bool,fit:o.a.string,crop:o.a.string,dpr:o.a.number,ignoreImageParams:o.a.bool}}]);
|