-
Notifications
You must be signed in to change notification settings - Fork 279
/
Copy pathNextImage.tsx
106 lines (91 loc) · 2.96 KB
/
NextImage.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import { mediaApi } from '@sitecore-jss/sitecore-jss/media';
import PropTypes from 'prop-types';
import React from 'react';
import {
getEEMarkup,
ImageProps,
ImageField,
ImageFieldValue,
withMetadata,
} from '@sitecore-jss/sitecore-jss-react';
import Image, { ImageProps as NextImageProperties } from 'next/image';
type NextImageProps = Omit<ImageProps, 'media'> & Partial<NextImageProperties>;
export const NextImage: React.FC<NextImageProps> = withMetadata(
({ editable, imageParams, field, mediaUrlPrefix, fill, priority, ...otherProps }) => {
// next handles src and we use a custom loader,
// throw error if these are present
if (otherProps.src) {
throw new Error('Detected src prop. If you wish to use src, use next/image directly.');
}
const dynamicMedia = field as ImageField | ImageFieldValue;
if (
!field ||
(!dynamicMedia.editable && !dynamicMedia.value && !(dynamicMedia as ImageFieldValue).src)
) {
return null;
}
const imageField = dynamicMedia as ImageField;
// we likely have an experience editor value, should be a string
if (editable && imageField.editable) {
return getEEMarkup(
imageField,
imageParams as { [paramName: string]: string | number },
mediaUrlPrefix as RegExp,
otherProps as { src: string }
);
}
// some wise-guy/gal is passing in a 'raw' image object value
const img: ImageFieldValue = (dynamicMedia as ImageFieldValue).src
? (field as ImageFieldValue)
: (dynamicMedia.value as ImageFieldValue);
if (!img) {
return null;
}
const attrs = {
...img,
...otherProps,
fill,
priority,
src: mediaApi.updateImageUrl(
img.src as string,
imageParams as { [paramName: string]: string | number },
mediaUrlPrefix as RegExp
),
};
const imageProps = {
...attrs,
// force replace /media with /jssmedia in src since we _know_ we will be adding a 'mw' query string parameter
// this is required for Sitecore media API resizing to work properly
src: mediaApi.replaceMediaUrlPrefix(attrs.src, mediaUrlPrefix as RegExp),
};
// Exclude `width`, `height` in case image is responsive, `fill` is used
if (imageProps.fill) {
delete imageProps.width;
delete imageProps.height;
}
if (attrs) {
return <Image alt="" {...imageProps} />;
}
return null; // we can't handle the truth
}
);
NextImage.propTypes = {
field: PropTypes.oneOfType([
PropTypes.shape({
src: PropTypes.string.isRequired,
}),
PropTypes.shape({
value: PropTypes.object,
editable: PropTypes.string,
}),
]),
editable: PropTypes.bool,
mediaUrlPrefix: PropTypes.instanceOf(RegExp),
imageParams: PropTypes.objectOf(
PropTypes.oneOfType([PropTypes.number.isRequired, PropTypes.string.isRequired]).isRequired
),
};
NextImage.defaultProps = {
editable: true,
};
NextImage.displayName = 'NextImage';