@prismicio/next 0.1.2 → 0.1.3
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/index.cjs +145 -85
- package/dist/index.d.ts +131 -62
- package/dist/index.js +143 -86
- package/package.json +24 -28
- package/src/PrismicNextImage.tsx +125 -0
- package/src/PrismicPreview.tsx +91 -54
- package/src/enableAutoPreviews.ts +4 -6
- package/src/exitPreview.ts +20 -22
- package/src/index.ts +14 -5
- package/src/lib/__PRODUCTION__.ts +7 -0
- package/src/lib/devMsg.ts +20 -0
- package/src/lib/getCookie.ts +17 -46
- package/src/lib/getPreviewCookieRepositoryName.ts +14 -0
- package/src/redirectToPreviewURL.ts +78 -21
- package/src/types.ts +1 -48
- package/src/lib/extractPreviewRefRepositoryName.ts +0 -60
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import * as prismic from '@prismicio/client';
|
|
2
|
-
import
|
|
2
|
+
import * as React from 'react';
|
|
3
3
|
import { PrismicToolbar } from '@prismicio/react';
|
|
4
4
|
import { useRouter } from 'next/router';
|
|
5
|
+
import Image from 'next/image';
|
|
6
|
+
import * as prismicH from '@prismicio/helpers';
|
|
5
7
|
|
|
6
8
|
function setPreviewData({ req, res }) {
|
|
7
9
|
const ref = req.query.token || req.cookies[prismic.cookie.preview];
|
|
@@ -11,65 +13,29 @@ function setPreviewData({ req, res }) {
|
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
function exitPreview(config) {
|
|
14
|
-
const { req } = config;
|
|
15
16
|
config.res.clearPreviewData();
|
|
16
|
-
|
|
17
|
-
const url = new URL(req.headers.referer);
|
|
18
|
-
if (url.pathname !== "/api/exit-preview") {
|
|
19
|
-
config.res.redirect(req.headers.referer);
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
config.res.redirect("/");
|
|
17
|
+
config.res.json({ success: true });
|
|
24
18
|
}
|
|
25
19
|
|
|
26
20
|
const readValue = (value) => {
|
|
27
21
|
return value.replace(/%3B/g, ";");
|
|
28
22
|
};
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const cookies = cookieString.split("; ");
|
|
23
|
+
const getCookie = (name, cookieJar) => {
|
|
24
|
+
const cookies = cookieJar.split("; ");
|
|
32
25
|
for (const cookie of cookies) {
|
|
33
26
|
const parts = cookie.split("=");
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return result;
|
|
39
|
-
};
|
|
40
|
-
const getAll = (cookieStore) => parse(cookieStore);
|
|
41
|
-
const getCookie = (name, cookieStore) => getAll(cookieStore)[name];
|
|
42
|
-
|
|
43
|
-
const extractFirstSubdomain = (host) => host.split(".")[0];
|
|
44
|
-
const extractRepositoryNameFromObjectRef = (previewRef) => {
|
|
45
|
-
try {
|
|
46
|
-
const parsed = JSON.parse(decodeURIComponent(previewRef));
|
|
47
|
-
const keys = Object.keys(parsed);
|
|
48
|
-
const domainKey = keys.find((key) => /\.prismic\.io$/.test(key));
|
|
49
|
-
if (domainKey) {
|
|
50
|
-
return extractFirstSubdomain(domainKey);
|
|
51
|
-
} else {
|
|
52
|
-
return void 0;
|
|
27
|
+
const thisName = readValue(parts[0]).replace(/%3D/g, "=");
|
|
28
|
+
if (thisName === name) {
|
|
29
|
+
const value = parts.slice(1).join("=");
|
|
30
|
+
return readValue(value);
|
|
53
31
|
}
|
|
54
|
-
} catch (e) {
|
|
55
|
-
return void 0;
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
const extractRepositoryNameFromURLRef = (previewRef) => {
|
|
59
|
-
try {
|
|
60
|
-
const url = new URL(previewRef);
|
|
61
|
-
return extractFirstSubdomain(url.host);
|
|
62
|
-
} catch (e) {
|
|
63
|
-
return void 0;
|
|
64
32
|
}
|
|
65
33
|
};
|
|
66
|
-
const extractPreviewRefRepositoryName = (previewRef) => {
|
|
67
|
-
return extractRepositoryNameFromObjectRef(previewRef) || extractRepositoryNameFromURLRef(previewRef);
|
|
68
|
-
};
|
|
69
34
|
|
|
70
|
-
const
|
|
71
|
-
return "
|
|
35
|
+
const getPreviewCookieRepositoryName = (previewCookie) => {
|
|
36
|
+
return (decodeURIComponent(previewCookie).match(/"(.+).prismic.io"/) || [])[1];
|
|
72
37
|
};
|
|
38
|
+
|
|
73
39
|
function PrismicPreview({
|
|
74
40
|
repositoryName,
|
|
75
41
|
children,
|
|
@@ -77,41 +43,57 @@ function PrismicPreview({
|
|
|
77
43
|
exitPreviewURL = "/api/exit-preview"
|
|
78
44
|
}) {
|
|
79
45
|
const router = useRouter();
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
46
|
+
const resolvedUpdatePreviewURL = router.basePath + updatePreviewURL;
|
|
47
|
+
const resolvedExitPreviewURL = router.basePath + exitPreviewURL;
|
|
48
|
+
React.useEffect(() => {
|
|
49
|
+
const startPreviewMode = async () => {
|
|
50
|
+
const res = await globalThis.fetch(resolvedUpdatePreviewURL);
|
|
51
|
+
if (res.ok) {
|
|
52
|
+
globalThis.location.reload();
|
|
53
|
+
} else {
|
|
54
|
+
console.error(`[<PrismicPreview>] Failed to start or update Preview Mode using the "${resolvedUpdatePreviewURL}" API endpoint. Does it exist?`);
|
|
86
55
|
}
|
|
87
56
|
};
|
|
88
|
-
startPreviewIfLoadedFromSharedLink();
|
|
89
57
|
const handlePrismicPreviewUpdate = async (event) => {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
await fetch(updatePreviewURL);
|
|
93
|
-
window.location.reload();
|
|
94
|
-
}
|
|
58
|
+
event.preventDefault();
|
|
59
|
+
await startPreviewMode();
|
|
95
60
|
};
|
|
96
61
|
const handlePrismicPreviewEnd = async (event) => {
|
|
97
62
|
event.preventDefault();
|
|
98
|
-
await fetch(
|
|
99
|
-
|
|
63
|
+
const res = await globalThis.fetch(resolvedExitPreviewURL);
|
|
64
|
+
if (res.ok) {
|
|
65
|
+
globalThis.location.reload();
|
|
66
|
+
} else {
|
|
67
|
+
console.error(`[<PrismicPreview>] Failed to exit Preview Mode using the "${resolvedExitPreviewURL}" API endpoint. Does it exist?`);
|
|
68
|
+
}
|
|
100
69
|
};
|
|
101
|
-
if (
|
|
70
|
+
if (router.isPreview) {
|
|
102
71
|
window.addEventListener("prismicPreviewUpdate", handlePrismicPreviewUpdate);
|
|
103
72
|
window.addEventListener("prismicPreviewEnd", handlePrismicPreviewEnd);
|
|
73
|
+
} else {
|
|
74
|
+
const prismicPreviewCookie = getCookie(prismic.cookie.preview, globalThis.document.cookie);
|
|
75
|
+
if (prismicPreviewCookie) {
|
|
76
|
+
const locationIsDescendantOfBasePath = window.location.href.startsWith(window.location.origin + router.basePath);
|
|
77
|
+
const prismicPreviewCookieRepositoryName = getPreviewCookieRepositoryName(prismicPreviewCookie);
|
|
78
|
+
if (locationIsDescendantOfBasePath && prismicPreviewCookieRepositoryName === repositoryName) {
|
|
79
|
+
startPreviewMode();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
104
82
|
}
|
|
105
83
|
return () => {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
window.removeEventListener("prismicPreviewEnd", handlePrismicPreviewEnd);
|
|
109
|
-
}
|
|
84
|
+
window.removeEventListener("prismicPreviewUpdate", handlePrismicPreviewUpdate);
|
|
85
|
+
window.removeEventListener("prismicPreviewEnd", handlePrismicPreviewEnd);
|
|
110
86
|
};
|
|
111
|
-
}, [
|
|
112
|
-
|
|
87
|
+
}, [
|
|
88
|
+
repositoryName,
|
|
89
|
+
resolvedExitPreviewURL,
|
|
90
|
+
resolvedUpdatePreviewURL,
|
|
91
|
+
router.isPreview,
|
|
92
|
+
router.basePath
|
|
93
|
+
]);
|
|
94
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, children, /* @__PURE__ */ React.createElement(PrismicToolbar, {
|
|
113
95
|
repositoryName
|
|
114
|
-
})
|
|
96
|
+
}));
|
|
115
97
|
}
|
|
116
98
|
|
|
117
99
|
const isPrismicNextPreviewData = (previewData) => {
|
|
@@ -128,26 +110,101 @@ const enableAutoPreviews = (config) => {
|
|
|
128
110
|
}
|
|
129
111
|
};
|
|
130
112
|
|
|
131
|
-
const isPrismicNextQuery = (query) =>
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const { documentId, token } = req.query;
|
|
141
|
-
const previewUrl = await client.resolvePreviewURL({
|
|
142
|
-
linkResolver,
|
|
113
|
+
const isPrismicNextQuery = (query) => {
|
|
114
|
+
return typeof query.documentId === "string" && typeof query.token === "string";
|
|
115
|
+
};
|
|
116
|
+
async function redirectToPreviewURL(config) {
|
|
117
|
+
const defaultURL = config.defaultURL || "/";
|
|
118
|
+
const basePath = config.basePath || "";
|
|
119
|
+
if (isPrismicNextQuery(config.req.query)) {
|
|
120
|
+
const previewUrl = await config.client.resolvePreviewURL({
|
|
121
|
+
linkResolver: config.linkResolver,
|
|
143
122
|
defaultURL,
|
|
144
|
-
documentID: documentId,
|
|
145
|
-
previewToken: token
|
|
123
|
+
documentID: config.req.query.documentId,
|
|
124
|
+
previewToken: config.req.query.token
|
|
146
125
|
});
|
|
147
|
-
res.redirect(previewUrl);
|
|
126
|
+
config.res.redirect(basePath + previewUrl);
|
|
148
127
|
return;
|
|
149
128
|
}
|
|
150
|
-
res.redirect(defaultURL);
|
|
129
|
+
config.res.redirect(basePath + defaultURL);
|
|
151
130
|
}
|
|
152
131
|
|
|
153
|
-
|
|
132
|
+
const camelCaseToParamCase = (input) => {
|
|
133
|
+
return input.replace(/[A-Z]/g, (match) => {
|
|
134
|
+
return `-${match.toLowerCase()}`;
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
const buildURL = (url, params) => {
|
|
138
|
+
const instance = new URL(url);
|
|
139
|
+
for (const camelCasedParamKey in params) {
|
|
140
|
+
const paramKey = camelCaseToParamCase(camelCasedParamKey);
|
|
141
|
+
const paramValue = params[camelCasedParamKey];
|
|
142
|
+
if (paramValue === void 0) {
|
|
143
|
+
instance.searchParams.delete(paramKey);
|
|
144
|
+
} else if (Array.isArray(paramValue)) {
|
|
145
|
+
instance.searchParams.set(paramKey, paramValue.join(","));
|
|
146
|
+
} else {
|
|
147
|
+
instance.searchParams.set(paramKey, `${paramValue}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const s = instance.searchParams.get("s");
|
|
151
|
+
if (s) {
|
|
152
|
+
instance.searchParams.delete("s");
|
|
153
|
+
instance.searchParams.append("s", s);
|
|
154
|
+
}
|
|
155
|
+
return instance.toString();
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const __PRODUCTION__ = process.env.NODE_ENV === "production";
|
|
159
|
+
|
|
160
|
+
var version = "0.1.3";
|
|
161
|
+
|
|
162
|
+
const devMsg = (slug) => {
|
|
163
|
+
return `https://prismic.dev/msg/next/v${version}/${slug}`;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const imgixLoader = (args) => {
|
|
167
|
+
const url = new URL(args.src);
|
|
168
|
+
const params = {
|
|
169
|
+
fit: url.searchParams.get("fit") || "max",
|
|
170
|
+
w: args.width,
|
|
171
|
+
h: void 0
|
|
172
|
+
};
|
|
173
|
+
if (args.quality) {
|
|
174
|
+
params.q = args.quality;
|
|
175
|
+
}
|
|
176
|
+
return buildURL(args.src, params);
|
|
177
|
+
};
|
|
178
|
+
const PrismicNextImage = ({
|
|
179
|
+
field,
|
|
180
|
+
imgixParams = {},
|
|
181
|
+
alt,
|
|
182
|
+
fallbackAlt,
|
|
183
|
+
layout,
|
|
184
|
+
...restProps
|
|
185
|
+
}) => {
|
|
186
|
+
if (!__PRODUCTION__) {
|
|
187
|
+
if (typeof alt === "string" && alt !== "") {
|
|
188
|
+
console.warn(`[PrismicNextImage] The "alt" prop can only be used to declare an image as decorative by passing an empty string (alt="") but was provided a non-empty string. You can resolve this warning by removing the "alt" prop or changing it to alt="". For more details, see ${devMsg("alt-must-be-an-empty-string")}`);
|
|
189
|
+
}
|
|
190
|
+
if (typeof fallbackAlt === "string" && fallbackAlt !== "") {
|
|
191
|
+
console.warn(`[PrismicNextImage] The "fallbackAlt" prop can only be used to declare an image as decorative by passing an empty string (fallbackAlt="") but was provided a non-empty string. You can resolve this warning by removing the "fallbackAlt" prop or changing it to fallbackAlt="". For more details, see ${devMsg("alt-must-be-an-empty-string")}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (prismicH.isFilled.imageThumbnail(field)) {
|
|
195
|
+
const src = buildURL(field.url, imgixParams);
|
|
196
|
+
return /* @__PURE__ */ React.createElement(Image, {
|
|
197
|
+
src,
|
|
198
|
+
width: layout === "fill" ? void 0 : field.dimensions.width,
|
|
199
|
+
height: layout === "fill" ? void 0 : field.dimensions.height,
|
|
200
|
+
alt: alt != null ? alt : field.alt || fallbackAlt,
|
|
201
|
+
loader: imgixLoader,
|
|
202
|
+
layout,
|
|
203
|
+
...restProps
|
|
204
|
+
});
|
|
205
|
+
} else {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export { PrismicNextImage, PrismicPreview, enableAutoPreviews, exitPreview, redirectToPreviewURL, setPreviewData };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prismicio/next",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Helpers to integrate Prismic into Next.js apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -41,44 +41,40 @@
|
|
|
41
41
|
"release:dry": "standard-version --dry-run",
|
|
42
42
|
"size": "size-limit",
|
|
43
43
|
"test": "npm run lint && npm run unit && npm run build && npm run size",
|
|
44
|
-
"unit": "
|
|
44
|
+
"unit": "vitest run --coverage",
|
|
45
|
+
"unit:watch": "vitest watch"
|
|
45
46
|
},
|
|
46
47
|
"dependencies": {
|
|
47
|
-
"@prismicio/
|
|
48
|
+
"@prismicio/client": "^6.4.3",
|
|
49
|
+
"@prismicio/helpers": "^2.3.0",
|
|
50
|
+
"@prismicio/react": "^2.4.0",
|
|
51
|
+
"@prismicio/types": "^0.1.27",
|
|
52
|
+
"eslint-plugin-react": "^7.30.0",
|
|
53
|
+
"eslint-plugin-react-hooks": "^4.5.0"
|
|
48
54
|
},
|
|
49
55
|
"devDependencies": {
|
|
50
|
-
"@prismicio/
|
|
51
|
-
"@prismicio/mock": "^0.0.9",
|
|
52
|
-
"@prismicio/types": "^0.1.27",
|
|
56
|
+
"@prismicio/mock": "^0.0.10",
|
|
53
57
|
"@size-limit/preset-small-lib": "^7.0.8",
|
|
54
|
-
"@
|
|
55
|
-
"@
|
|
56
|
-
"@
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"@typescript-eslint/eslint-plugin": "^5.17.0",
|
|
60
|
-
"@typescript-eslint/parser": "^5.17.0",
|
|
61
|
-
"ava": "^4.1.0",
|
|
62
|
-
"eslint": "^8.12.0",
|
|
58
|
+
"@types/react-test-renderer": "^18.0.0",
|
|
59
|
+
"@typescript-eslint/eslint-plugin": "^5.26.0",
|
|
60
|
+
"@typescript-eslint/parser": "^5.26.0",
|
|
61
|
+
"c8": "^7.11.3",
|
|
62
|
+
"eslint": "^8.16.0",
|
|
63
63
|
"eslint-config-prettier": "^8.5.0",
|
|
64
64
|
"eslint-plugin-prettier": "^4.0.0",
|
|
65
|
-
"eslint-plugin-tsdoc": "^0.2.
|
|
66
|
-
"
|
|
67
|
-
"jsdom-global": "^3.0.2",
|
|
68
|
-
"msw": "^0.39.2",
|
|
65
|
+
"eslint-plugin-tsdoc": "^0.2.16",
|
|
66
|
+
"happy-dom": "^4.0.1",
|
|
69
67
|
"next": "^12.1.4",
|
|
70
|
-
"node-fetch": "^3.2.3",
|
|
71
68
|
"nyc": "^15.1.0",
|
|
72
|
-
"prettier": "^2.6.
|
|
73
|
-
"prettier-plugin-jsdoc": "^0.3.
|
|
74
|
-
"react": "^18.
|
|
75
|
-
"react-
|
|
76
|
-
"sinon": "^13.0.1",
|
|
69
|
+
"prettier": "^2.6.2",
|
|
70
|
+
"prettier-plugin-jsdoc": "^0.3.38",
|
|
71
|
+
"react": "^18.1.0",
|
|
72
|
+
"react-test-renderer": "^18.1.0",
|
|
77
73
|
"siroc": "^0.16.0",
|
|
78
74
|
"size-limit": "^7.0.8",
|
|
79
|
-
"standard-version": "^9.
|
|
80
|
-
"
|
|
81
|
-
"
|
|
75
|
+
"standard-version": "^9.5.0",
|
|
76
|
+
"typescript": "^4.7.2",
|
|
77
|
+
"vitest": "^0.12.9"
|
|
82
78
|
},
|
|
83
79
|
"peerDependencies": {
|
|
84
80
|
"@prismicio/client": "^6.0.0",
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import Image, { ImageProps, ImageLoaderProps } from "next/image";
|
|
3
|
+
import { buildURL, ImgixURLParams } from "imgix-url-builder";
|
|
4
|
+
import * as prismicH from "@prismicio/helpers";
|
|
5
|
+
import * as prismicT from "@prismicio/types";
|
|
6
|
+
|
|
7
|
+
import { __PRODUCTION__ } from "./lib/__PRODUCTION__";
|
|
8
|
+
import { devMsg } from "./lib/devMsg";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Creates a `next/image` loader for Imgix, which Prismic uses, with an optional
|
|
12
|
+
* collection of default Imgix parameters.
|
|
13
|
+
*
|
|
14
|
+
* @see To learn about `next/image` loaders: https://nextjs.org/docs/api-reference/next/image#loader
|
|
15
|
+
* @see To learn about Imgix's URL API: https://docs.imgix.com/apis/rendering
|
|
16
|
+
*/
|
|
17
|
+
const imgixLoader = (args: ImageLoaderProps): string => {
|
|
18
|
+
const url = new URL(args.src);
|
|
19
|
+
|
|
20
|
+
const params: ImgixURLParams = {
|
|
21
|
+
fit: (url.searchParams.get("fit") as ImgixURLParams["fit"]) || "max",
|
|
22
|
+
w: args.width,
|
|
23
|
+
h: undefined,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
if (args.quality) {
|
|
27
|
+
params.q = args.quality;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return buildURL(args.src, params);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type PrismicNextImageProps = Omit<
|
|
34
|
+
ImageProps,
|
|
35
|
+
"src" | "alt" | "width" | "height"
|
|
36
|
+
> & {
|
|
37
|
+
/**
|
|
38
|
+
* The Prismic Image field or thumbnail to render.
|
|
39
|
+
*/
|
|
40
|
+
field: prismicT.ImageFieldImage | null | undefined;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* An object of Imgix URL API parameters to transform the image.
|
|
44
|
+
*
|
|
45
|
+
* @see https://docs.imgix.com/apis/rendering
|
|
46
|
+
*/
|
|
47
|
+
imgixParams?: ImgixURLParams;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Declare an image as decorative by providing `alt=""`.
|
|
51
|
+
*
|
|
52
|
+
* See:
|
|
53
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt#decorative_images
|
|
54
|
+
*/
|
|
55
|
+
alt?: "";
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Declare an image as decorative only if the Image field does not have
|
|
59
|
+
* alternative text by providing `fallbackAlt=""`.
|
|
60
|
+
*
|
|
61
|
+
* See:
|
|
62
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt#decorative_images
|
|
63
|
+
*/
|
|
64
|
+
fallbackAlt?: "";
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* React component that renders an image from a Prismic Image field or one of
|
|
69
|
+
* its thumbnails using `next/image`. It will automatically set the `alt`
|
|
70
|
+
* attribute using the Image field's `alt` property.
|
|
71
|
+
*
|
|
72
|
+
* It uses an Imgix URL-based loader by default. A custom loader can be provided
|
|
73
|
+
* with the `loader` prop. If you would like to use the Next.js Image
|
|
74
|
+
* Optimization API instead, set `loader={undefined}`.
|
|
75
|
+
*
|
|
76
|
+
* @param props - Props for the component.
|
|
77
|
+
*
|
|
78
|
+
* @returns A responsive image component using `next/image` for the given Image field.
|
|
79
|
+
*
|
|
80
|
+
* @see To learn more about `next/image`, see: https://nextjs.org/docs/api-reference/next/image
|
|
81
|
+
*/
|
|
82
|
+
export const PrismicNextImage = ({
|
|
83
|
+
field,
|
|
84
|
+
imgixParams = {},
|
|
85
|
+
alt,
|
|
86
|
+
fallbackAlt,
|
|
87
|
+
layout,
|
|
88
|
+
...restProps
|
|
89
|
+
}: PrismicNextImageProps) => {
|
|
90
|
+
if (!__PRODUCTION__) {
|
|
91
|
+
if (typeof alt === "string" && alt !== "") {
|
|
92
|
+
console.warn(
|
|
93
|
+
`[PrismicNextImage] The "alt" prop can only be used to declare an image as decorative by passing an empty string (alt="") but was provided a non-empty string. You can resolve this warning by removing the "alt" prop or changing it to alt="". For more details, see ${devMsg(
|
|
94
|
+
"alt-must-be-an-empty-string",
|
|
95
|
+
)}`,
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (typeof fallbackAlt === "string" && fallbackAlt !== "") {
|
|
100
|
+
console.warn(
|
|
101
|
+
`[PrismicNextImage] The "fallbackAlt" prop can only be used to declare an image as decorative by passing an empty string (fallbackAlt="") but was provided a non-empty string. You can resolve this warning by removing the "fallbackAlt" prop or changing it to fallbackAlt="". For more details, see ${devMsg(
|
|
102
|
+
"alt-must-be-an-empty-string",
|
|
103
|
+
)}`,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (prismicH.isFilled.imageThumbnail(field)) {
|
|
109
|
+
const src = buildURL(field.url, imgixParams);
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<Image
|
|
113
|
+
src={src}
|
|
114
|
+
width={layout === "fill" ? undefined : field.dimensions.width}
|
|
115
|
+
height={layout === "fill" ? undefined : field.dimensions.height}
|
|
116
|
+
alt={alt ?? (field.alt || fallbackAlt)}
|
|
117
|
+
loader={imgixLoader}
|
|
118
|
+
layout={layout}
|
|
119
|
+
{...restProps}
|
|
120
|
+
/>
|
|
121
|
+
);
|
|
122
|
+
} else {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
};
|