@prismicio/react 2.2.0 → 2.3.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.
@@ -0,0 +1,185 @@
1
+ import * as React from "react";
2
+ import * as prismicT from "@prismicio/types";
3
+ import * as prismicH from "@prismicio/helpers";
4
+
5
+ import { __PRODUCTION__ } from "./lib/__PRODUCTION__";
6
+ import { devMsg } from "./lib/devMsg";
7
+
8
+ /**
9
+ * Props for `<PrismicImage>`.
10
+ */
11
+ export type PrismicImageProps = Omit<
12
+ React.DetailedHTMLProps<
13
+ React.ImgHTMLAttributes<HTMLImageElement>,
14
+ HTMLImageElement
15
+ >,
16
+ "src" | "srcset" | "alt"
17
+ > & {
18
+ /**
19
+ * The Prismic Image field or thumbnail to render.
20
+ */
21
+ field: prismicT.ImageFieldImage | null | undefined;
22
+
23
+ /**
24
+ * An object of Imgix URL API parameters to transform the image.
25
+ *
26
+ * See: https://docs.imgix.com/apis/rendering
27
+ */
28
+ imgixParams?: Parameters<typeof prismicH.asImageSrc>[1];
29
+
30
+ /**
31
+ * Declare an image as decorative by providing `alt=""`.
32
+ *
33
+ * See:
34
+ * https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt#decorative_images
35
+ */
36
+ alt?: "";
37
+
38
+ /**
39
+ * Declare an image as decorative only if the Image field does not have
40
+ * alternative text by providing `fallbackAlt=""`.
41
+ *
42
+ * See:
43
+ * https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt#decorative_images
44
+ */
45
+ fallbackAlt?: "";
46
+ } & (
47
+ | {
48
+ /**
49
+ * Widths used to build a `srcset` value for the Image field.
50
+ *
51
+ * If a `widths` prop is not given or `"defaults"` is passed, the
52
+ * following widths will be used: 640, 750, 828, 1080, 1200, 1920, 2048, 3840.
53
+ *
54
+ * If the Image field contains responsive views, each responsive view
55
+ * can be used as a width in the resulting `srcset` by passing
56
+ * `"thumbnails"` as the `widths` prop.
57
+ */
58
+ widths?:
59
+ | NonNullable<
60
+ Parameters<typeof prismicH.asImageWidthSrcSet>[1]
61
+ >["widths"]
62
+ | "defaults";
63
+ /**
64
+ * Not used when the `widths` prop is used.
65
+ */
66
+ pixelDensities?: never;
67
+ }
68
+ | {
69
+ /**
70
+ * Not used when the `widths` prop is used.
71
+ */
72
+ widths?: never;
73
+ /**
74
+ * Pixel densities used to build a `srcset` value for the Image field.
75
+ *
76
+ * If a `pixelDensities` prop is passed `"defaults"`, the following
77
+ * pixel densities will be used: 1, 2, 3.
78
+ */
79
+ pixelDensities:
80
+ | NonNullable<
81
+ Parameters<typeof prismicH.asImagePixelDensitySrcSet>[1]
82
+ >["pixelDensities"]
83
+ | "defaults";
84
+ }
85
+ );
86
+
87
+ const _PrismicImage = (
88
+ props: PrismicImageProps,
89
+ ref: React.ForwardedRef<HTMLImageElement>,
90
+ ): JSX.Element | null => {
91
+ const {
92
+ field,
93
+ alt,
94
+ fallbackAlt,
95
+ imgixParams,
96
+ widths,
97
+ pixelDensities,
98
+ ...restProps
99
+ } = props;
100
+
101
+ if (!__PRODUCTION__) {
102
+ if (typeof alt === "string" && props.alt !== "") {
103
+ console.warn(
104
+ `[PrismicImage] The alt prop can only be used to declare an image as decorative by passing an empty string (alt=""). For more details, see ${devMsg(
105
+ "alt-must-be-an-empty-string",
106
+ )}`,
107
+ );
108
+ }
109
+
110
+ if (typeof fallbackAlt === "string" && fallbackAlt !== "") {
111
+ console.warn(
112
+ `[PrismicImage] The fallbackAlt prop can only be used to declare an image as decorative by passing an empty string (fallbackAlt=""). For more details, see ${devMsg(
113
+ "alt-must-be-an-empty-string",
114
+ )}`,
115
+ );
116
+ }
117
+
118
+ if (widths && pixelDensities) {
119
+ console.warn(
120
+ `[PrismicImage] Only one of "widths" or "pixelDensities" props can be provided. "widths" will be used in this case.`,
121
+ );
122
+ }
123
+ }
124
+
125
+ if (prismicH.isFilled.imageThumbnail(field)) {
126
+ let src: string | undefined;
127
+ let srcSet: string | undefined;
128
+
129
+ if (widths || !pixelDensities) {
130
+ const res = prismicH.asImageWidthSrcSet(field, {
131
+ ...imgixParams,
132
+ widths: widths === "defaults" ? undefined : widths,
133
+ });
134
+
135
+ src = res.src;
136
+ srcSet = res.srcset;
137
+ } else if (pixelDensities) {
138
+ const res = prismicH.asImagePixelDensitySrcSet(field, {
139
+ ...imgixParams,
140
+ pixelDensities:
141
+ pixelDensities === "defaults" ? undefined : pixelDensities,
142
+ });
143
+
144
+ src = res.src;
145
+ srcSet = res.srcset;
146
+ }
147
+
148
+ return (
149
+ <img
150
+ ref={ref}
151
+ src={src}
152
+ srcSet={srcSet}
153
+ alt={alt ?? (field.alt || fallbackAlt)}
154
+ {...restProps}
155
+ />
156
+ );
157
+ } else {
158
+ return null;
159
+ }
160
+ };
161
+
162
+ if (!__PRODUCTION__) {
163
+ _PrismicImage.displayName = "PrismicImage";
164
+ }
165
+
166
+ /**
167
+ * React component that renders an image from a Prismic Image field or one of
168
+ * its thumbnails. It will automatically set the `alt` attribute using the Image
169
+ * field's `alt` property.
170
+ *
171
+ * By default, a widths-based srcset will be used to support responsive images.
172
+ * This ensures only the smallest image needed for a browser is downloaded.
173
+ *
174
+ * To use a pixel-density-based srcset, use the `pixelDensities` prop. Default
175
+ * pixel densities can be used by using `pixelDensities="defaults"`.
176
+ *
177
+ * **Note**: If you are using a framework that has a native image component,
178
+ * such as Next.js and Gatsby, prefer using those image components instead. They
179
+ * can provide deeper framework integration than `<PrismicImage>`.
180
+ *
181
+ * @param props - Props for the component.
182
+ *
183
+ * @returns A responsive image component for the given Image field.
184
+ */
185
+ export const PrismicImage = React.forwardRef(_PrismicImage);
@@ -2,6 +2,7 @@ import * as React from "react";
2
2
  import * as prismicH from "@prismicio/helpers";
3
3
  import * as prismicT from "@prismicio/types";
4
4
 
5
+ import { __PRODUCTION__ } from "./lib/__PRODUCTION__";
5
6
  import { isInternalURL } from "./lib/isInternalURL";
6
7
 
7
8
  import { usePrismicContext } from "./usePrismicContext";
@@ -37,8 +38,8 @@ export interface LinkProps {
37
38
  * Props for `<PrismicLink>`.
38
39
  */
39
40
  export type PrismicLinkProps<
40
- InternalComponent extends React.ElementType<LinkProps> = React.ElementType<LinkProps>,
41
- ExternalComponent extends React.ElementType<LinkProps> = React.ElementType<LinkProps>,
41
+ InternalComponent extends React.ElementType<LinkProps> = typeof defaultInternalComponent,
42
+ ExternalComponent extends React.ElementType<LinkProps> = typeof defaultInternalComponent,
42
43
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
44
  LinkResolverFunction extends prismicH.LinkResolverFunction<any> = prismicH.LinkResolverFunction,
44
45
  > = Omit<
@@ -118,26 +119,11 @@ const defaultInternalComponent = "a";
118
119
  */
119
120
  const defaultExternalComponent = "a";
120
121
 
121
- /**
122
- * React component that renders a link from a Prismic Link field.
123
- *
124
- * Different components can be rendered depending on whether the link is
125
- * internal or external. This is helpful when integrating with client-side
126
- * routers, such as a router-specific Link component.
127
- *
128
- * If a link is configured to open in a new window using `target="_blank"`,
129
- * `rel="noopener noreferrer"` is set by default.
130
- *
131
- * @param props - Props for the component.
132
- *
133
- * @returns The internal or external link component depending on whether the
134
- * link is internal or external.
135
- */
136
122
  const _PrismicLink = <
137
- InternalComponent extends React.ElementType<LinkProps>,
138
- ExternalComponent extends React.ElementType<LinkProps>,
123
+ InternalComponent extends React.ElementType<LinkProps> = typeof defaultInternalComponent,
124
+ ExternalComponent extends React.ElementType<LinkProps> = typeof defaultExternalComponent,
139
125
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
140
- LinkResolverFunction extends prismicH.LinkResolverFunction<any>,
126
+ LinkResolverFunction extends prismicH.LinkResolverFunction<any> = prismicH.LinkResolverFunction,
141
127
  >(
142
128
  props: PrismicLinkProps<
143
129
  InternalComponent,
@@ -215,11 +201,30 @@ const _PrismicLink = <
215
201
  ) : null;
216
202
  };
217
203
 
204
+ if (!__PRODUCTION__) {
205
+ _PrismicLink.displayName = "PrismicLink";
206
+ }
207
+
208
+ /**
209
+ * React component that renders a link from a Prismic Link field.
210
+ *
211
+ * Different components can be rendered depending on whether the link is
212
+ * internal or external. This is helpful when integrating with client-side
213
+ * routers, such as a router-specific Link component.
214
+ *
215
+ * If a link is configured to open in a new window using `target="_blank"`,
216
+ * `rel="noopener noreferrer"` is set by default.
217
+ *
218
+ * @param props - Props for the component.
219
+ *
220
+ * @returns The internal or external link component depending on whether the
221
+ * link is internal or external.
222
+ */
218
223
  export const PrismicLink = React.forwardRef(_PrismicLink) as <
219
- InternalComponent extends React.ElementType<LinkProps>,
220
- ExternalComponent extends React.ElementType<LinkProps>,
224
+ InternalComponent extends React.ElementType<LinkProps> = typeof defaultInternalComponent,
225
+ ExternalComponent extends React.ElementType<LinkProps> = typeof defaultExternalComponent,
221
226
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
222
- LinkResolverFunction extends prismicH.LinkResolverFunction<any>,
227
+ LinkResolverFunction extends prismicH.LinkResolverFunction<any> = prismicH.LinkResolverFunction,
223
228
  >(
224
229
  props: PrismicLinkProps<
225
230
  InternalComponent,
package/src/index.ts CHANGED
@@ -25,6 +25,9 @@ export { Element };
25
25
  // TODO: Remove in v3.
26
26
  export const Elements = Element;
27
27
 
28
+ export { PrismicImage } from "./PrismicImage";
29
+ export type { PrismicImageProps } from "./PrismicImage";
30
+
28
31
  export { SliceZone, TODOSliceComponent } from "./SliceZone";
29
32
  export type {
30
33
  SliceComponentProps,
@@ -0,0 +1,20 @@
1
+ import { version } from "../../package.json";
2
+
3
+ /**
4
+ * Returns a `prismic.dev/msg` URL for a given message slug.
5
+ *
6
+ * @example
7
+ *
8
+ * ```ts
9
+ * devMsg("missing-param");
10
+ * // => "https://prismic.dev/msg/react/v1.2.3/missing-param.md"
11
+ * ```
12
+ *
13
+ * @param slug - Slug for the message. This corresponds to a Markdown file in
14
+ * the Git repository's `/messages` directory.
15
+ *
16
+ * @returns The `prismic.dev/msg` URL for the given slug.
17
+ */
18
+ export const devMsg = (slug: string) => {
19
+ return `https://prismic.dev/msg/react/v${version}/${slug}`;
20
+ };