@prismicio/react 2.1.2 → 2.4.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/index.cjs +80 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +226 -16
- package/dist/index.js +80 -10
- package/dist/index.js.map +1 -1
- package/package.json +23 -23
- package/src/PrismicImage.tsx +185 -0
- package/src/PrismicLink.tsx +33 -24
- package/src/PrismicProvider.tsx +14 -6
- package/src/PrismicRichText.tsx +23 -7
- package/src/PrismicToolbar.tsx +13 -0
- package/src/SliceZone.tsx +52 -21
- package/src/index.ts +3 -0
- package/src/lib/devMsg.ts +20 -0
- package/src/lib/pascalCase.ts +1 -1
|
@@ -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="") 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(
|
|
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="") 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(
|
|
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. You can resolve this warning by removing either the "widths" or "pixelDensities" prop. "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);
|
package/src/PrismicLink.tsx
CHANGED
|
@@ -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,9 +38,10 @@ export interface LinkProps {
|
|
|
37
38
|
* Props for `<PrismicLink>`.
|
|
38
39
|
*/
|
|
39
40
|
export type PrismicLinkProps<
|
|
40
|
-
InternalComponent extends React.ElementType<LinkProps> =
|
|
41
|
-
ExternalComponent extends React.ElementType<LinkProps> =
|
|
42
|
-
|
|
41
|
+
InternalComponent extends React.ElementType<LinkProps> = typeof defaultInternalComponent,
|
|
42
|
+
ExternalComponent extends React.ElementType<LinkProps> = typeof defaultInternalComponent,
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
|
+
LinkResolverFunction extends prismicH.LinkResolverFunction<any> = prismicH.LinkResolverFunction,
|
|
43
45
|
> = Omit<
|
|
44
46
|
React.ComponentPropsWithoutRef<InternalComponent> &
|
|
45
47
|
React.ComponentPropsWithoutRef<ExternalComponent>,
|
|
@@ -117,25 +119,11 @@ const defaultInternalComponent = "a";
|
|
|
117
119
|
*/
|
|
118
120
|
const defaultExternalComponent = "a";
|
|
119
121
|
|
|
120
|
-
/**
|
|
121
|
-
* React component that renders a link from a Prismic Link field.
|
|
122
|
-
*
|
|
123
|
-
* Different components can be rendered depending on whether the link is
|
|
124
|
-
* internal or external. This is helpful when integrating with client-side
|
|
125
|
-
* routers, such as a router-specific Link component.
|
|
126
|
-
*
|
|
127
|
-
* If a link is configured to open in a new window using `target="_blank"`,
|
|
128
|
-
* `rel="noopener noreferrer"` is set by default.
|
|
129
|
-
*
|
|
130
|
-
* @param props - Props for the component.
|
|
131
|
-
*
|
|
132
|
-
* @returns The internal or external link component depending on whether the
|
|
133
|
-
* link is internal or external.
|
|
134
|
-
*/
|
|
135
122
|
const _PrismicLink = <
|
|
136
123
|
InternalComponent extends React.ElementType<LinkProps> = typeof defaultInternalComponent,
|
|
137
124
|
ExternalComponent extends React.ElementType<LinkProps> = typeof defaultExternalComponent,
|
|
138
|
-
|
|
125
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
126
|
+
LinkResolverFunction extends prismicH.LinkResolverFunction<any> = prismicH.LinkResolverFunction,
|
|
139
127
|
>(
|
|
140
128
|
props: PrismicLinkProps<
|
|
141
129
|
InternalComponent,
|
|
@@ -158,12 +146,15 @@ const _PrismicLink = <
|
|
|
158
146
|
href = prismicH.asLink(props.field, linkResolver);
|
|
159
147
|
}
|
|
160
148
|
|
|
149
|
+
const isInternal = href && isInternalURL(href);
|
|
150
|
+
|
|
161
151
|
const target =
|
|
162
152
|
props.target ||
|
|
163
153
|
("field" in props &&
|
|
164
154
|
props.field &&
|
|
165
155
|
"target" in props.field &&
|
|
166
156
|
props.field.target) ||
|
|
157
|
+
(!isInternal && "_blank") ||
|
|
167
158
|
undefined;
|
|
168
159
|
|
|
169
160
|
const rel =
|
|
@@ -179,8 +170,6 @@ const _PrismicLink = <
|
|
|
179
170
|
context.externalLinkComponent ||
|
|
180
171
|
defaultExternalComponent;
|
|
181
172
|
|
|
182
|
-
const isInternal = href && isInternalURL(href);
|
|
183
|
-
|
|
184
173
|
const Component = isInternal ? InternalComponent : ExternalComponent;
|
|
185
174
|
|
|
186
175
|
const passthroughProps: typeof props = Object.assign({}, props);
|
|
@@ -213,10 +202,30 @@ const _PrismicLink = <
|
|
|
213
202
|
) : null;
|
|
214
203
|
};
|
|
215
204
|
|
|
205
|
+
if (!__PRODUCTION__) {
|
|
206
|
+
_PrismicLink.displayName = "PrismicLink";
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* React component that renders a link from a Prismic Link field.
|
|
211
|
+
*
|
|
212
|
+
* Different components can be rendered depending on whether the link is
|
|
213
|
+
* internal or external. This is helpful when integrating with client-side
|
|
214
|
+
* routers, such as a router-specific Link component.
|
|
215
|
+
*
|
|
216
|
+
* If a link is configured to open in a new window using `target="_blank"`,
|
|
217
|
+
* `rel="noopener noreferrer"` is set by default.
|
|
218
|
+
*
|
|
219
|
+
* @param props - Props for the component.
|
|
220
|
+
*
|
|
221
|
+
* @returns The internal or external link component depending on whether the
|
|
222
|
+
* link is internal or external.
|
|
223
|
+
*/
|
|
216
224
|
export const PrismicLink = React.forwardRef(_PrismicLink) as <
|
|
217
|
-
InternalComponent extends React.ElementType<LinkProps
|
|
218
|
-
ExternalComponent extends React.ElementType<LinkProps
|
|
219
|
-
|
|
225
|
+
InternalComponent extends React.ElementType<LinkProps> = typeof defaultInternalComponent,
|
|
226
|
+
ExternalComponent extends React.ElementType<LinkProps> = typeof defaultExternalComponent,
|
|
227
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
228
|
+
LinkResolverFunction extends prismicH.LinkResolverFunction<any> = prismicH.LinkResolverFunction,
|
|
220
229
|
>(
|
|
221
230
|
props: PrismicLinkProps<
|
|
222
231
|
InternalComponent,
|
package/src/PrismicProvider.tsx
CHANGED
|
@@ -10,7 +10,10 @@ import { JSXFunctionSerializer, JSXMapSerializer } from "./types";
|
|
|
10
10
|
* React context value containing shared configuration for `@prismicio/react`
|
|
11
11
|
* components and hooks.
|
|
12
12
|
*/
|
|
13
|
-
export type PrismicContextValue
|
|
13
|
+
export type PrismicContextValue<
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
LinkResolverFunction extends prismicH.LinkResolverFunction<any> = prismicH.LinkResolverFunction,
|
|
16
|
+
> = {
|
|
14
17
|
/**
|
|
15
18
|
* A `@prismicio/client` instance used to fetch content from a Prismic
|
|
16
19
|
* repository. This is used by `@prismicio/react` hooks, such as
|
|
@@ -26,7 +29,7 @@ export type PrismicContextValue = {
|
|
|
26
29
|
* repository's content, a Link Resolver does not need to be provided.
|
|
27
30
|
* @see Learn about Link Resolvers and Route Resolvers {@link https://prismic.io/docs/core-concepts/link-resolver-route-resolver}
|
|
28
31
|
*/
|
|
29
|
-
linkResolver?:
|
|
32
|
+
linkResolver?: LinkResolverFunction;
|
|
30
33
|
|
|
31
34
|
/**
|
|
32
35
|
* A map or function that maps a Rich Text block to a React component.
|
|
@@ -81,7 +84,9 @@ export const PrismicContext = React.createContext<PrismicContextValue>({});
|
|
|
81
84
|
/**
|
|
82
85
|
* Props for `<PrismicProvider>`.
|
|
83
86
|
*/
|
|
84
|
-
export type PrismicProviderProps
|
|
87
|
+
export type PrismicProviderProps<
|
|
88
|
+
LinkResolverFunction extends prismicH.LinkResolverFunction,
|
|
89
|
+
> = PrismicContextValue<LinkResolverFunction>;
|
|
85
90
|
|
|
86
91
|
/**
|
|
87
92
|
* React context provider to share configuration for `@prismicio/react`
|
|
@@ -89,15 +94,18 @@ export type PrismicProviderProps = PrismicContextValue;
|
|
|
89
94
|
*
|
|
90
95
|
* @returns A React context provider with shared configuration.
|
|
91
96
|
*/
|
|
92
|
-
export const PrismicProvider =
|
|
97
|
+
export const PrismicProvider = <
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
99
|
+
LinkResolverFunction extends prismicH.LinkResolverFunction<any>,
|
|
100
|
+
>({
|
|
93
101
|
client,
|
|
94
102
|
linkResolver,
|
|
95
103
|
richTextComponents,
|
|
96
104
|
internalLinkComponent,
|
|
97
105
|
externalLinkComponent,
|
|
98
106
|
children,
|
|
99
|
-
}: PrismicProviderProps): JSX.Element => {
|
|
100
|
-
const value = React.useMemo<PrismicContextValue
|
|
107
|
+
}: PrismicProviderProps<LinkResolverFunction>): JSX.Element => {
|
|
108
|
+
const value = React.useMemo<PrismicContextValue<LinkResolverFunction>>(
|
|
101
109
|
() => ({
|
|
102
110
|
client,
|
|
103
111
|
linkResolver,
|
package/src/PrismicRichText.tsx
CHANGED
|
@@ -13,7 +13,10 @@ import { usePrismicContext } from "./usePrismicContext";
|
|
|
13
13
|
/**
|
|
14
14
|
* Props for `<PrismicRichText>`.
|
|
15
15
|
*/
|
|
16
|
-
export type PrismicRichTextProps
|
|
16
|
+
export type PrismicRichTextProps<
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
+
LinkResolverFunction extends prismicH.LinkResolverFunction<any> = prismicH.LinkResolverFunction,
|
|
19
|
+
> = {
|
|
17
20
|
/**
|
|
18
21
|
* The Prismic Rich Text field to render.
|
|
19
22
|
*/
|
|
@@ -27,7 +30,7 @@ export type PrismicRichTextProps = {
|
|
|
27
30
|
* repository's content, a Link Resolver does not need to be provided.
|
|
28
31
|
* @see Learn about Link Resolvers and Route Resolvers {@link https://prismic.io/docs/core-concepts/link-resolver-route-resolver}
|
|
29
32
|
*/
|
|
30
|
-
linkResolver?:
|
|
33
|
+
linkResolver?: LinkResolverFunction;
|
|
31
34
|
|
|
32
35
|
/**
|
|
33
36
|
* A function that maps a Rich Text block to a React component.
|
|
@@ -79,10 +82,19 @@ export type PrismicRichTextProps = {
|
|
|
79
82
|
* @defaultValue `<a>`
|
|
80
83
|
*/
|
|
81
84
|
externalLinkComponent?: PrismicLinkProps["externalComponent"];
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The value to be rendered when the field is empty. If a fallback is not
|
|
88
|
+
* given, `null` will be rendered.
|
|
89
|
+
*/
|
|
90
|
+
fallback?: React.ReactNode;
|
|
82
91
|
};
|
|
83
92
|
|
|
84
|
-
type CreateDefaultSerializerArgs
|
|
85
|
-
|
|
93
|
+
type CreateDefaultSerializerArgs<
|
|
94
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
95
|
+
LinkResolverFunction extends prismicH.LinkResolverFunction<any> = prismicH.LinkResolverFunction,
|
|
96
|
+
> = {
|
|
97
|
+
linkResolver: LinkResolverFunction | undefined;
|
|
86
98
|
internalLinkComponent: PrismicRichTextProps["internalLinkComponent"];
|
|
87
99
|
externalLinkComponent: PrismicRichTextProps["externalLinkComponent"];
|
|
88
100
|
};
|
|
@@ -214,8 +226,11 @@ const createDefaultSerializer = (
|
|
|
214
226
|
* @see Learn about Rich Text fields {@link https://prismic.io/docs/core-concepts/rich-text-title}
|
|
215
227
|
* @see Learn about Rich Text serializers {@link https://prismic.io/docs/core-concepts/html-serializer}
|
|
216
228
|
*/
|
|
217
|
-
export const PrismicRichText =
|
|
218
|
-
|
|
229
|
+
export const PrismicRichText = <
|
|
230
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
231
|
+
LinkResolverFunction extends prismicH.LinkResolverFunction<any> = prismicH.LinkResolverFunction,
|
|
232
|
+
>(
|
|
233
|
+
props: PrismicRichTextProps<LinkResolverFunction>,
|
|
219
234
|
): JSX.Element | null => {
|
|
220
235
|
const context = usePrismicContext();
|
|
221
236
|
|
|
@@ -255,7 +270,7 @@ export const PrismicRichText = (
|
|
|
255
270
|
|
|
256
271
|
return <>{serialized}</>;
|
|
257
272
|
} else {
|
|
258
|
-
return null;
|
|
273
|
+
return props.fallback != null ? <>{props.fallback}</> : null;
|
|
259
274
|
}
|
|
260
275
|
}, [
|
|
261
276
|
props.field,
|
|
@@ -263,6 +278,7 @@ export const PrismicRichText = (
|
|
|
263
278
|
props.externalLinkComponent,
|
|
264
279
|
props.components,
|
|
265
280
|
props.linkResolver,
|
|
281
|
+
props.fallback,
|
|
266
282
|
context.linkResolver,
|
|
267
283
|
context.richTextComponents,
|
|
268
284
|
]);
|
package/src/PrismicToolbar.tsx
CHANGED
|
@@ -43,6 +43,19 @@ export const PrismicToolbar = ({
|
|
|
43
43
|
script.dataset.repositoryName = repositoryName;
|
|
44
44
|
script.dataset.type = type;
|
|
45
45
|
|
|
46
|
+
// Disable Happy DOM `<script>` evaluation during
|
|
47
|
+
// tests.
|
|
48
|
+
//
|
|
49
|
+
// This is a patch ONLY INCLUDED DURING TESTS. It will
|
|
50
|
+
// be pruned during code minification in non-test
|
|
51
|
+
// environments.
|
|
52
|
+
//
|
|
53
|
+
// @see https://github.com/capricorn86/happy-dom/blob/02ae081e36f990c06171eda44f9d885fd9413d73/packages/happy-dom/src/nodes/html-script-element/HTMLScriptElement.ts#L191-L209
|
|
54
|
+
if (process.env.NODE_ENV === "test") {
|
|
55
|
+
// @ts-expect-error - `_evaluateScript` is a Happy DOM-specific property.
|
|
56
|
+
script._evaluateScript = false;
|
|
57
|
+
}
|
|
58
|
+
|
|
46
59
|
document.body.appendChild(script);
|
|
47
60
|
}
|
|
48
61
|
}, [repositoryName, type, src]);
|
package/src/SliceZone.tsx
CHANGED
|
@@ -4,24 +4,57 @@ import * as prismicT from "@prismicio/types";
|
|
|
4
4
|
import { __PRODUCTION__ } from "./lib/__PRODUCTION__";
|
|
5
5
|
import { pascalCase, PascalCase } from "./lib/pascalCase";
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Returns the type of a `SliceLike` type.
|
|
9
|
+
*
|
|
10
|
+
* @typeParam Slice - The Slice from which the type will be extracted.
|
|
11
|
+
*/
|
|
12
|
+
type ExtractSliceType<Slice extends SliceLike> = Slice extends SliceLikeRestV2
|
|
13
|
+
? Slice["slice_type"]
|
|
14
|
+
: Slice extends SliceLikeGraphQL
|
|
15
|
+
? Slice["type"]
|
|
16
|
+
: never;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The minimum required properties to represent a Prismic Slice from the Prismic
|
|
20
|
+
* Rest API V2 for the `<SliceZone>` component.
|
|
21
|
+
*
|
|
22
|
+
* If using Prismic's Rest API V2, use the `Slice` export from
|
|
23
|
+
* `@prismicio/types` for a full interface.
|
|
24
|
+
*
|
|
25
|
+
* @typeParam SliceType - Type name of the Slice.
|
|
26
|
+
*/
|
|
27
|
+
export type SliceLikeRestV2<SliceType extends string = string> = {
|
|
28
|
+
slice_type: prismicT.Slice<SliceType>["slice_type"];
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The minimum required properties to represent a Prismic Slice from the Prismic
|
|
33
|
+
* GraphQL API for the `<SliceZone>` component.
|
|
34
|
+
*
|
|
35
|
+
* @typeParam SliceType - Type name of the Slice.
|
|
36
|
+
*/
|
|
37
|
+
export type SliceLikeGraphQL<SliceType extends string = string> = {
|
|
38
|
+
type: prismicT.Slice<SliceType>["slice_type"];
|
|
39
|
+
};
|
|
40
|
+
|
|
7
41
|
/**
|
|
8
42
|
* The minimum required properties to represent a Prismic Slice for the
|
|
9
43
|
* `<SliceZone>` component.
|
|
10
44
|
*
|
|
11
|
-
* If using Prismic's
|
|
12
|
-
* for a full interface.
|
|
45
|
+
* If using Prismic's Rest API V2, use the `Slice` export from
|
|
46
|
+
* `@prismicio/types` for a full interface.
|
|
13
47
|
*
|
|
14
48
|
* @typeParam SliceType - Type name of the Slice.
|
|
15
49
|
*/
|
|
16
|
-
export type SliceLike<SliceType extends string = string> =
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
>;
|
|
50
|
+
export type SliceLike<SliceType extends string = string> =
|
|
51
|
+
| SliceLikeRestV2<SliceType>
|
|
52
|
+
| SliceLikeGraphQL<SliceType>;
|
|
20
53
|
|
|
21
54
|
/**
|
|
22
55
|
* A looser version of the `SliceZone` type from `@prismicio/types` using `SliceLike`.
|
|
23
56
|
*
|
|
24
|
-
* If using Prismic's
|
|
57
|
+
* If using Prismic's Rest API V2, use the `SliceZone` export from
|
|
25
58
|
* `@prismicio/types` for the full type.
|
|
26
59
|
*
|
|
27
60
|
* @typeParam TSlice - The type(s) of a Slice in the Slice Zone.
|
|
@@ -97,10 +130,7 @@ export type SliceZoneComponents<
|
|
|
97
130
|
// signals to future developers that it is a placeholder and should be
|
|
98
131
|
// implemented.
|
|
99
132
|
{
|
|
100
|
-
[SliceType in
|
|
101
|
-
TSlice["slice_type"],
|
|
102
|
-
never
|
|
103
|
-
>]: SliceComponentType<
|
|
133
|
+
[SliceType in ExtractSliceType<TSlice>]: SliceComponentType<
|
|
104
134
|
Extract<TSlice, SliceLike<SliceType>> extends never
|
|
105
135
|
? SliceLike
|
|
106
136
|
: Extract<TSlice, SliceLike<SliceType>>,
|
|
@@ -119,19 +149,18 @@ export const TODOSliceComponent = __PRODUCTION__
|
|
|
119
149
|
: <TSlice extends SliceLike, TContext>({
|
|
120
150
|
slice,
|
|
121
151
|
}: SliceComponentProps<TSlice, TContext>): JSX.Element | null => {
|
|
152
|
+
const type = "slice_type" in slice ? slice.slice_type : slice.type;
|
|
153
|
+
|
|
122
154
|
React.useEffect(() => {
|
|
123
155
|
console.warn(
|
|
124
|
-
`[SliceZone] Could not find a component for Slice type "${
|
|
156
|
+
`[SliceZone] Could not find a component for Slice type "${type}"`,
|
|
125
157
|
slice,
|
|
126
158
|
);
|
|
127
|
-
}, [slice]);
|
|
159
|
+
}, [slice, type]);
|
|
128
160
|
|
|
129
161
|
return (
|
|
130
|
-
<section
|
|
131
|
-
|
|
132
|
-
data-slice-type={slice.slice_type}
|
|
133
|
-
>
|
|
134
|
-
Could not find a component for Slice type “{slice.slice_type}
|
|
162
|
+
<section data-slice-zone-todo-component="" data-slice-type={type}>
|
|
163
|
+
Could not find a component for Slice type “{type}
|
|
135
164
|
”
|
|
136
165
|
</section>
|
|
137
166
|
);
|
|
@@ -149,7 +178,7 @@ type SliceZoneResolverArgs<TSlice extends SliceLike = SliceLike> = {
|
|
|
149
178
|
/**
|
|
150
179
|
* The name of the Slice.
|
|
151
180
|
*/
|
|
152
|
-
sliceName: PascalCase<TSlice
|
|
181
|
+
sliceName: PascalCase<ExtractSliceType<TSlice>>;
|
|
153
182
|
|
|
154
183
|
/**
|
|
155
184
|
* The index of the Slice in the Slice Zone.
|
|
@@ -243,14 +272,16 @@ export const SliceZone = <TSlice extends SliceLike, TContext>({
|
|
|
243
272
|
}: SliceZoneProps<TSlice, TContext>): JSX.Element => {
|
|
244
273
|
const renderedSlices = React.useMemo(() => {
|
|
245
274
|
return slices.map((slice, index) => {
|
|
246
|
-
|
|
275
|
+
const type = "slice_type" in slice ? slice.slice_type : slice.type;
|
|
276
|
+
|
|
277
|
+
let Comp = (components[type as keyof typeof components] ||
|
|
247
278
|
defaultComponent) as SliceComponentType<TSlice, TContext>;
|
|
248
279
|
|
|
249
280
|
// TODO: Remove `resolver` in v3 in favor of `components`.
|
|
250
281
|
if (resolver) {
|
|
251
282
|
const resolvedComp = resolver({
|
|
252
283
|
slice,
|
|
253
|
-
sliceName: pascalCase(
|
|
284
|
+
sliceName: pascalCase(type),
|
|
254
285
|
i: index,
|
|
255
286
|
});
|
|
256
287
|
|
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
|
+
};
|
package/src/lib/pascalCase.ts
CHANGED
|
@@ -34,7 +34,7 @@ type InnerCamelCaseStringArray<
|
|
|
34
34
|
|
|
35
35
|
type CamelCaseStringArray<Parts extends readonly string[]> = Parts extends [
|
|
36
36
|
`${infer FirstPart}`,
|
|
37
|
-
...infer RemainingParts
|
|
37
|
+
...infer RemainingParts,
|
|
38
38
|
]
|
|
39
39
|
? Uncapitalize<`${FirstPart}${InnerCamelCaseStringArray<
|
|
40
40
|
RemainingParts,
|