react-datocms 4.0.6 → 4.0.8

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.
Files changed (37) hide show
  1. package/dist/cjs/Image/__tests__/index.test.js +17 -1
  2. package/dist/cjs/Image/__tests__/index.test.js.map +1 -1
  3. package/dist/cjs/Image/index.js +8 -3
  4. package/dist/cjs/Image/index.js.map +1 -1
  5. package/dist/cjs/Seo/__tests__/index.test.js +5 -1
  6. package/dist/cjs/Seo/__tests__/index.test.js.map +1 -1
  7. package/dist/cjs/Seo/index.js +5 -1
  8. package/dist/cjs/Seo/index.js.map +1 -1
  9. package/dist/cjs/StructuredText/__tests__/index.test.js +5 -1
  10. package/dist/cjs/StructuredText/__tests__/index.test.js.map +1 -1
  11. package/dist/cjs/StructuredText/index.js +5 -1
  12. package/dist/cjs/StructuredText/index.js.map +1 -1
  13. package/dist/cjs/index.js +5 -1
  14. package/dist/cjs/index.js.map +1 -1
  15. package/dist/cjs/useQuerySubscription/index.js +1 -1
  16. package/dist/cjs/useSiteSearch/index.js +6 -2
  17. package/dist/cjs/useSiteSearch/index.js.map +1 -1
  18. package/dist/esm/Image/__tests__/index.test.js +12 -0
  19. package/dist/esm/Image/__tests__/index.test.js.map +1 -1
  20. package/dist/esm/Image/index.d.ts +3 -3
  21. package/dist/esm/Image/index.js +3 -2
  22. package/dist/esm/Image/index.js.map +1 -1
  23. package/dist/esm/Seo/types.d.ts +3 -3
  24. package/dist/esm/StructuredText/index.d.ts +8 -8
  25. package/dist/esm/useQuerySubscription/index.d.ts +4 -4
  26. package/dist/esm/useQuerySubscription/index.js +1 -1
  27. package/dist/esm/useSiteSearch/index.d.ts +8 -8
  28. package/dist/esm/useSiteSearch/index.js +1 -1
  29. package/dist/types/Image/index.d.ts +3 -3
  30. package/dist/types/Seo/types.d.ts +3 -3
  31. package/dist/types/StructuredText/index.d.ts +8 -8
  32. package/dist/types/useQuerySubscription/index.d.ts +4 -4
  33. package/dist/types/useSiteSearch/index.d.ts +8 -8
  34. package/package.json +31 -1
  35. package/src/Image/__tests__/__snapshots__/index.test.tsx.snap +343 -0
  36. package/src/Image/__tests__/index.test.tsx +21 -0
  37. package/src/Image/index.tsx +4 -2
@@ -1,6 +1,6 @@
1
1
  import React, { CSSProperties } from 'react';
2
- declare type Maybe<T> = T | null;
3
- export declare type ResponsiveImageType = {
2
+ type Maybe<T> = T | null;
3
+ export type ResponsiveImageType = {
4
4
  /** A base64-encoded thumbnail to offer during image loading */
5
5
  base64?: Maybe<string>;
6
6
  /** The height of the image */
@@ -24,7 +24,7 @@ export declare type ResponsiveImageType = {
24
24
  /** Title attribute (`title`) for the image */
25
25
  title?: Maybe<string>;
26
26
  };
27
- export declare type ImagePropTypes = {
27
+ export type ImagePropTypes = {
28
28
  /** The actual response you get from a DatoCMS `responsiveImage` GraphQL query */
29
29
  data: ResponsiveImageType;
30
30
  /** Additional CSS className for root node */
@@ -40,6 +40,6 @@ export interface SeoLinkTag {
40
40
  content?: null;
41
41
  attributes: FaviconAttributes | AppleTouchIconAttributes;
42
42
  }
43
- export declare type SeoTag = SeoTitleTag | SeoMetaTag;
44
- export declare type FaviconTag = SeoMetaTag | SeoLinkTag;
45
- export declare type SeoOrFaviconTag = SeoTag | FaviconTag;
43
+ export type SeoTag = SeoTitleTag | SeoMetaTag;
44
+ export type FaviconTag = SeoMetaTag | SeoLinkTag;
45
+ export type SeoOrFaviconTag = SeoTag | FaviconTag;
@@ -4,28 +4,28 @@ import { ReactElement } from 'react';
4
4
  export { renderNodeRule, renderMarkRule, RenderError };
5
5
  export { renderNodeRule as renderRule };
6
6
  export type { StructuredTextGraphQlResponse, StructuredTextDocument, StructuredTextGraphQlResponseRecord, };
7
- declare type AdapterReturn = ReactElement | string | null;
7
+ type AdapterReturn = ReactElement | string | null;
8
8
  export declare const defaultAdapter: {
9
9
  renderNode: (...args: any) => AdapterReturn;
10
10
  renderFragment: (children: ReactElement | null[], key: string) => AdapterReturn;
11
11
  renderText: (text: string, key: string) => AdapterReturn;
12
12
  };
13
13
  export declare function appendKeyToValidElement(element: ReactElement | null, key: string): ReactElement | null;
14
- declare type H = typeof defaultAdapter.renderNode;
15
- declare type T = typeof defaultAdapter.renderText;
16
- declare type F = typeof defaultAdapter.renderFragment;
17
- export declare type RenderInlineRecordContext<R extends StructuredTextGraphQlResponseRecord> = {
14
+ type H = typeof defaultAdapter.renderNode;
15
+ type T = typeof defaultAdapter.renderText;
16
+ type F = typeof defaultAdapter.renderFragment;
17
+ export type RenderInlineRecordContext<R extends StructuredTextGraphQlResponseRecord> = {
18
18
  record: R;
19
19
  };
20
- export declare type RenderRecordLinkContext<R extends StructuredTextGraphQlResponseRecord> = {
20
+ export type RenderRecordLinkContext<R extends StructuredTextGraphQlResponseRecord> = {
21
21
  record: R;
22
22
  children: RenderResult<H, T, F>;
23
23
  transformedMeta: TransformedMeta;
24
24
  };
25
- export declare type RenderBlockContext<R extends StructuredTextGraphQlResponseRecord> = {
25
+ export type RenderBlockContext<R extends StructuredTextGraphQlResponseRecord> = {
26
26
  record: R;
27
27
  };
28
- export declare type StructuredTextPropTypes<R1 extends StructuredTextGraphQlResponseRecord, R2 extends StructuredTextGraphQlResponseRecord = R1> = {
28
+ export type StructuredTextPropTypes<R1 extends StructuredTextGraphQlResponseRecord, R2 extends StructuredTextGraphQlResponseRecord = R1> = {
29
29
  /** The actual field value you get from DatoCMS **/
30
30
  data: StructuredTextGraphQlResponse<R1, R2> | StructuredTextDocument | Node | null | undefined;
31
31
  /** A set of additional rules to convert nodes to JSX **/
@@ -1,18 +1,18 @@
1
1
  import { ChannelErrorData, ConnectionStatus, Options } from 'datocms-listen';
2
- export declare type SubscribeToQueryOptions<QueryResult, QueryVariables> = Omit<Options<QueryResult, QueryVariables>, 'onStatusChange' | 'onUpdate' | 'onChannelError'>;
3
- export declare type EnabledQueryListenerOptions<QueryResult, QueryVariables> = {
2
+ export type SubscribeToQueryOptions<QueryResult, QueryVariables> = Omit<Options<QueryResult, QueryVariables>, 'onStatusChange' | 'onUpdate' | 'onChannelError'>;
3
+ export type EnabledQueryListenerOptions<QueryResult, QueryVariables> = {
4
4
  /** Whether the subscription has to be performed or not */
5
5
  enabled?: true;
6
6
  /** The initial data to use while the initial request is being performed */
7
7
  initialData?: QueryResult;
8
8
  } & SubscribeToQueryOptions<QueryResult, QueryVariables>;
9
- export declare type DisabledQueryListenerOptions<QueryResult, QueryVariables> = {
9
+ export type DisabledQueryListenerOptions<QueryResult, QueryVariables> = {
10
10
  /** Whether the subscription has to be performed or not */
11
11
  enabled: false;
12
12
  /** The initial data to use while the initial request is being performed */
13
13
  initialData?: QueryResult;
14
14
  } & Partial<SubscribeToQueryOptions<QueryResult, QueryVariables>>;
15
- export declare type QueryListenerOptions<QueryResult, QueryVariables> = EnabledQueryListenerOptions<QueryResult, QueryVariables> | DisabledQueryListenerOptions<QueryResult, QueryVariables>;
15
+ export type QueryListenerOptions<QueryResult, QueryVariables> = EnabledQueryListenerOptions<QueryResult, QueryVariables> | DisabledQueryListenerOptions<QueryResult, QueryVariables>;
16
16
  export declare function useQuerySubscription<QueryResult = any, QueryVariables = Record<string, any>>(options: QueryListenerOptions<QueryResult, QueryVariables>): {
17
17
  error: ChannelErrorData | null;
18
18
  status: ConnectionStatus;
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- declare type SearchResultInstancesHrefSchema = {
2
+ type SearchResultInstancesHrefSchema = {
3
3
  page?: {
4
4
  offset?: number;
5
5
  limit?: number;
@@ -14,13 +14,13 @@ declare type SearchResultInstancesHrefSchema = {
14
14
  };
15
15
  [k: string]: unknown;
16
16
  };
17
- declare type SearchResultInstancesTargetSchema = {
17
+ type SearchResultInstancesTargetSchema = {
18
18
  data: RawSearchResult[];
19
19
  meta: {
20
20
  total_count: number;
21
21
  };
22
22
  };
23
- export declare type RawSearchResult = {
23
+ export type RawSearchResult = {
24
24
  type: 'search_result';
25
25
  id: string;
26
26
  attributes: {
@@ -42,8 +42,8 @@ declare class GenericClient {
42
42
  rawList(queryParams: SearchResultInstancesHrefSchema): Promise<SearchResultInstancesTargetSchema>;
43
43
  };
44
44
  }
45
- declare type Highlighter = (match: string, key: string, context: 'title' | 'bodyExcerpt') => React.ReactNode;
46
- export declare type UseSiteSearchConfig<Client extends GenericClient> = {
45
+ type Highlighter = (match: string, key: string, context: 'title' | 'bodyExcerpt') => React.ReactNode;
46
+ export type UseSiteSearchConfig<Client extends GenericClient> = {
47
47
  client: Client;
48
48
  buildTriggerId: string;
49
49
  fuzzySearch?: boolean;
@@ -55,19 +55,19 @@ export declare type UseSiteSearchConfig<Client extends GenericClient> = {
55
55
  query?: string;
56
56
  };
57
57
  };
58
- declare type SearchResult = {
58
+ type SearchResult = {
59
59
  id: string;
60
60
  title: React.ReactNode;
61
61
  bodyExcerpt: React.ReactNode;
62
62
  url: string;
63
63
  raw: RawSearchResult;
64
64
  };
65
- export declare type UseSiteSearchData = {
65
+ export type UseSiteSearchData = {
66
66
  pageResults: SearchResult[];
67
67
  totalResults: number;
68
68
  totalPages: number;
69
69
  };
70
- export declare type UseSiteSearchResult = {
70
+ export type UseSiteSearchResult = {
71
71
  state: {
72
72
  query: string;
73
73
  setQuery: (newQuery: string) => void;
package/package.json CHANGED
@@ -1,9 +1,39 @@
1
1
  {
2
2
  "name": "react-datocms",
3
- "version": "4.0.6",
3
+ "version": "4.0.8",
4
4
  "types": "dist/types/index.d.ts",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
7
+ "exports": {
8
+ ".": "./dist/cjs/index.js",
9
+ "./seo": "./dist/cjs/Seo/index.js",
10
+ "./image": "./dist/cjs/Image/index.js",
11
+ "./structured-text": "./dist/cjs/StructuredText/index.js",
12
+ "./use-query-subscription": "./dist/cjs/useQuerySubscription/index.js",
13
+ "./use-site-search": "./dist/cjs/useSiteSearch/index.js"
14
+ },
15
+ "typesVersions": {
16
+ "*": {
17
+ "*": [
18
+ "dist/types/index.d.ts"
19
+ ],
20
+ "seo": [
21
+ "./dist/types/Seo/index.d.ts"
22
+ ],
23
+ "image": [
24
+ "./dist/types/Image/index.d.ts"
25
+ ],
26
+ "structured-text": [
27
+ "./dist/types/StructuredText/index.d.ts"
28
+ ],
29
+ "use-query-subscription": [
30
+ "./dist/types/useQuerySubscription/index.d.ts"
31
+ ],
32
+ "use-site-search": [
33
+ "./dist/types/useSiteSearch/index.d.ts"
34
+ ]
35
+ }
36
+ },
7
37
  "sideEffects": false,
8
38
  "files": [
9
39
  "dist",
@@ -230,6 +230,87 @@ exports[`Image layout=fill visible renders the image (minimal data) 1`] = `
230
230
  </ForwardRef>
231
231
  `;
232
232
 
233
+ exports[`Image layout=fill visible renders the image (relative URL) 1`] = `
234
+ <ForwardRef
235
+ data={
236
+ Object {
237
+ "base64": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLFQoLDhgQDg0NDh0eHREYIx8lJCIrHB0dLSs7GikyKSEuKjUlKDk1MjIyHyo4PTc+PDcxPjUBCgsLDg0OHBAQHDsoIig7Ozs7Ozs7OzsvOzs7Ozs7Ozs7Lzs7Ozs7Ozs7OzsvOzs7NTsvLy87NTU1Ly8vLzsvL//AABEIAA0AGAMBIgACEQEDEQH/xAAYAAACAwAAAAAAAAAAAAAAAAAGBwABBP/EACEQAAEEAAYDAAAAAAAAAAAAAAEAAgMEBQYHESEiFWFx/8QAFQEBAQAAAAAAAAAAAAAAAAAAAwL/xAAZEQADAAMAAAAAAAAAAAAAAAAAAQIRITH/2gAMAwEAAhEDEQA/AFxLgDWTsAd1J5TGy7hEYqNAaNgECX7sjLMQAHJTEy1Zcarfia4lJMauAxqBhLY6ZlaOzDurWvUOd3jZPfCiEh4xs//Z",
238
+ "height": 421,
239
+ "src": "/205/image.png?ar=16%3A9&fit=crop&w=750",
240
+ "width": 750,
241
+ }
242
+ }
243
+ intersectionThreshold={0.2}
244
+ layout="fill"
245
+ >
246
+ <div
247
+ style={
248
+ Object {
249
+ "height": "100%",
250
+ "left": 0,
251
+ "maxHeight": "none",
252
+ "maxWidth": "none",
253
+ "overflow": "hidden",
254
+ "position": "absolute",
255
+ "top": 0,
256
+ "width": "100%",
257
+ }
258
+ }
259
+ >
260
+ <img
261
+ alt=""
262
+ aria-hidden="true"
263
+ role="presentation"
264
+ src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLFQoLDhgQDg0NDh0eHREYIx8lJCIrHB0dLSs7GikyKSEuKjUlKDk1MjIyHyo4PTc+PDcxPjUBCgsLDg0OHBAQHDsoIig7Ozs7Ozs7OzsvOzs7Ozs7Ozs7Lzs7Ozs7Ozs7OzsvOzs7NTsvLy87NTU1Ly8vLzsvL//AABEIAA0AGAMBIgACEQEDEQH/xAAYAAACAwAAAAAAAAAAAAAAAAAGBwABBP/EACEQAAEEAAYDAAAAAAAAAAAAAAEAAgMEBQYHESEiFWFx/8QAFQEBAQAAAAAAAAAAAAAAAAAAAwL/xAAZEQADAAMAAAAAAAAAAAAAAAAAAQIRITH/2gAMAwEAAhEDEQA/AFxLgDWTsAd1J5TGy7hEYqNAaNgECX7sjLMQAHJTEy1Zcarfia4lJMauAxqBhLY6ZlaOzDurWvUOd3jZPfCiEh4xs//Z"
265
+ style={
266
+ Object {
267
+ "backgroundColor": undefined,
268
+ "height": "110%",
269
+ "left": "-5%",
270
+ "maxHeight": "none",
271
+ "maxWidth": "none",
272
+ "objectFit": undefined,
273
+ "objectPosition": undefined,
274
+ "opacity": 1,
275
+ "position": "absolute",
276
+ "top": "-5%",
277
+ "transition": "opacity 500ms",
278
+ "width": "110%",
279
+ }
280
+ }
281
+ />
282
+ <picture>
283
+ <source
284
+ srcSet="/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=0.25 187w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=0.5 375w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=0.75 562w,/205/image.png?ar=16%3A9&fit=crop&w=750 750w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=1.5 1125w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=2 1500w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=3 2250w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=4 3000w"
285
+ />
286
+ <img
287
+ alt=""
288
+ onLoad={[Function]}
289
+ src="/205/image.png?ar=16%3A9&fit=crop&w=750"
290
+ style={
291
+ Object {
292
+ "height": "100%",
293
+ "left": 0,
294
+ "maxHeight": "none",
295
+ "maxWidth": "none",
296
+ "objectFit": undefined,
297
+ "objectPosition": undefined,
298
+ "opacity": 0,
299
+ "position": "absolute",
300
+ "top": 0,
301
+ "transition": "opacity 500ms",
302
+ "width": "100%",
303
+ }
304
+ }
305
+ />
306
+ </picture>
307
+ <noscript>
308
+ <picture />
309
+ </noscript>
310
+ </div>
311
+ </ForwardRef>
312
+ `;
313
+
233
314
  exports[`Image layout=fill visible renders the image 1`] = `
234
315
  <ForwardRef
235
316
  data={
@@ -566,6 +647,93 @@ exports[`Image layout=fixed visible renders the image (minimal data) 1`] = `
566
647
  </ForwardRef>
567
648
  `;
568
649
 
650
+ exports[`Image layout=fixed visible renders the image (relative URL) 1`] = `
651
+ <ForwardRef
652
+ data={
653
+ Object {
654
+ "base64": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLFQoLDhgQDg0NDh0eHREYIx8lJCIrHB0dLSs7GikyKSEuKjUlKDk1MjIyHyo4PTc+PDcxPjUBCgsLDg0OHBAQHDsoIig7Ozs7Ozs7OzsvOzs7Ozs7Ozs7Lzs7Ozs7Ozs7OzsvOzs7NTsvLy87NTU1Ly8vLzsvL//AABEIAA0AGAMBIgACEQEDEQH/xAAYAAACAwAAAAAAAAAAAAAAAAAGBwABBP/EACEQAAEEAAYDAAAAAAAAAAAAAAEAAgMEBQYHESEiFWFx/8QAFQEBAQAAAAAAAAAAAAAAAAAAAwL/xAAZEQADAAMAAAAAAAAAAAAAAAAAAQIRITH/2gAMAwEAAhEDEQA/AFxLgDWTsAd1J5TGy7hEYqNAaNgECX7sjLMQAHJTEy1Zcarfia4lJMauAxqBhLY6ZlaOzDurWvUOd3jZPfCiEh4xs//Z",
655
+ "height": 421,
656
+ "src": "/205/image.png?ar=16%3A9&fit=crop&w=750",
657
+ "width": 750,
658
+ }
659
+ }
660
+ intersectionThreshold={0.2}
661
+ layout="fixed"
662
+ >
663
+ <div
664
+ style={
665
+ Object {
666
+ "overflow": "hidden",
667
+ "position": "relative",
668
+ "width": 750,
669
+ }
670
+ }
671
+ >
672
+ <img
673
+ alt=""
674
+ aria-hidden="true"
675
+ src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI3NTAiIGhlaWdodD0iNDIxIj48L3N2Zz4="
676
+ style={
677
+ Object {
678
+ "display": "block",
679
+ "width": "100%",
680
+ }
681
+ }
682
+ />
683
+ <img
684
+ alt=""
685
+ aria-hidden="true"
686
+ role="presentation"
687
+ src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLFQoLDhgQDg0NDh0eHREYIx8lJCIrHB0dLSs7GikyKSEuKjUlKDk1MjIyHyo4PTc+PDcxPjUBCgsLDg0OHBAQHDsoIig7Ozs7Ozs7OzsvOzs7Ozs7Ozs7Lzs7Ozs7Ozs7OzsvOzs7NTsvLy87NTU1Ly8vLzsvL//AABEIAA0AGAMBIgACEQEDEQH/xAAYAAACAwAAAAAAAAAAAAAAAAAGBwABBP/EACEQAAEEAAYDAAAAAAAAAAAAAAEAAgMEBQYHESEiFWFx/8QAFQEBAQAAAAAAAAAAAAAAAAAAAwL/xAAZEQADAAMAAAAAAAAAAAAAAAAAAQIRITH/2gAMAwEAAhEDEQA/AFxLgDWTsAd1J5TGy7hEYqNAaNgECX7sjLMQAHJTEy1Zcarfia4lJMauAxqBhLY6ZlaOzDurWvUOd3jZPfCiEh4xs//Z"
688
+ style={
689
+ Object {
690
+ "backgroundColor": undefined,
691
+ "height": "110%",
692
+ "left": "-5%",
693
+ "maxHeight": "none",
694
+ "maxWidth": "none",
695
+ "objectFit": undefined,
696
+ "objectPosition": undefined,
697
+ "opacity": 1,
698
+ "position": "absolute",
699
+ "top": "-5%",
700
+ "transition": "opacity 500ms",
701
+ "width": "110%",
702
+ }
703
+ }
704
+ />
705
+ <picture>
706
+ <source
707
+ srcSet="/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=0.25 187w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=0.5 375w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=0.75 562w,/205/image.png?ar=16%3A9&fit=crop&w=750 750w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=1.5 1125w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=2 1500w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=3 2250w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=4 3000w"
708
+ />
709
+ <img
710
+ alt=""
711
+ onLoad={[Function]}
712
+ src="/205/image.png?ar=16%3A9&fit=crop&w=750"
713
+ style={
714
+ Object {
715
+ "height": "100%",
716
+ "left": 0,
717
+ "maxHeight": "none",
718
+ "maxWidth": "none",
719
+ "objectFit": undefined,
720
+ "objectPosition": undefined,
721
+ "opacity": 0,
722
+ "position": "absolute",
723
+ "top": 0,
724
+ "transition": "opacity 500ms",
725
+ "width": "100%",
726
+ }
727
+ }
728
+ />
729
+ </picture>
730
+ <noscript>
731
+ <picture />
732
+ </noscript>
733
+ </div>
734
+ </ForwardRef>
735
+ `;
736
+
569
737
  exports[`Image layout=fixed visible renders the image 1`] = `
570
738
  <ForwardRef
571
739
  data={
@@ -911,6 +1079,94 @@ exports[`Image layout=intrinsic visible renders the image (minimal data) 1`] = `
911
1079
  </ForwardRef>
912
1080
  `;
913
1081
 
1082
+ exports[`Image layout=intrinsic visible renders the image (relative URL) 1`] = `
1083
+ <ForwardRef
1084
+ data={
1085
+ Object {
1086
+ "base64": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLFQoLDhgQDg0NDh0eHREYIx8lJCIrHB0dLSs7GikyKSEuKjUlKDk1MjIyHyo4PTc+PDcxPjUBCgsLDg0OHBAQHDsoIig7Ozs7Ozs7OzsvOzs7Ozs7Ozs7Lzs7Ozs7Ozs7OzsvOzs7NTsvLy87NTU1Ly8vLzsvL//AABEIAA0AGAMBIgACEQEDEQH/xAAYAAACAwAAAAAAAAAAAAAAAAAGBwABBP/EACEQAAEEAAYDAAAAAAAAAAAAAAEAAgMEBQYHESEiFWFx/8QAFQEBAQAAAAAAAAAAAAAAAAAAAwL/xAAZEQADAAMAAAAAAAAAAAAAAAAAAQIRITH/2gAMAwEAAhEDEQA/AFxLgDWTsAd1J5TGy7hEYqNAaNgECX7sjLMQAHJTEy1Zcarfia4lJMauAxqBhLY6ZlaOzDurWvUOd3jZPfCiEh4xs//Z",
1087
+ "height": 421,
1088
+ "src": "/205/image.png?ar=16%3A9&fit=crop&w=750",
1089
+ "width": 750,
1090
+ }
1091
+ }
1092
+ intersectionThreshold={0.2}
1093
+ layout="intrinsic"
1094
+ >
1095
+ <div
1096
+ style={
1097
+ Object {
1098
+ "maxWidth": 750,
1099
+ "overflow": "hidden",
1100
+ "position": "relative",
1101
+ "width": "100%",
1102
+ }
1103
+ }
1104
+ >
1105
+ <img
1106
+ alt=""
1107
+ aria-hidden="true"
1108
+ src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI3NTAiIGhlaWdodD0iNDIxIj48L3N2Zz4="
1109
+ style={
1110
+ Object {
1111
+ "display": "block",
1112
+ "width": "100%",
1113
+ }
1114
+ }
1115
+ />
1116
+ <img
1117
+ alt=""
1118
+ aria-hidden="true"
1119
+ role="presentation"
1120
+ src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLFQoLDhgQDg0NDh0eHREYIx8lJCIrHB0dLSs7GikyKSEuKjUlKDk1MjIyHyo4PTc+PDcxPjUBCgsLDg0OHBAQHDsoIig7Ozs7Ozs7OzsvOzs7Ozs7Ozs7Lzs7Ozs7Ozs7OzsvOzs7NTsvLy87NTU1Ly8vLzsvL//AABEIAA0AGAMBIgACEQEDEQH/xAAYAAACAwAAAAAAAAAAAAAAAAAGBwABBP/EACEQAAEEAAYDAAAAAAAAAAAAAAEAAgMEBQYHESEiFWFx/8QAFQEBAQAAAAAAAAAAAAAAAAAAAwL/xAAZEQADAAMAAAAAAAAAAAAAAAAAAQIRITH/2gAMAwEAAhEDEQA/AFxLgDWTsAd1J5TGy7hEYqNAaNgECX7sjLMQAHJTEy1Zcarfia4lJMauAxqBhLY6ZlaOzDurWvUOd3jZPfCiEh4xs//Z"
1121
+ style={
1122
+ Object {
1123
+ "backgroundColor": undefined,
1124
+ "height": "110%",
1125
+ "left": "-5%",
1126
+ "maxHeight": "none",
1127
+ "maxWidth": "none",
1128
+ "objectFit": undefined,
1129
+ "objectPosition": undefined,
1130
+ "opacity": 1,
1131
+ "position": "absolute",
1132
+ "top": "-5%",
1133
+ "transition": "opacity 500ms",
1134
+ "width": "110%",
1135
+ }
1136
+ }
1137
+ />
1138
+ <picture>
1139
+ <source
1140
+ srcSet="/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=0.25 187w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=0.5 375w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=0.75 562w,/205/image.png?ar=16%3A9&fit=crop&w=750 750w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=1.5 1125w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=2 1500w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=3 2250w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=4 3000w"
1141
+ />
1142
+ <img
1143
+ alt=""
1144
+ onLoad={[Function]}
1145
+ src="/205/image.png?ar=16%3A9&fit=crop&w=750"
1146
+ style={
1147
+ Object {
1148
+ "height": "100%",
1149
+ "left": 0,
1150
+ "maxHeight": "none",
1151
+ "maxWidth": "none",
1152
+ "objectFit": undefined,
1153
+ "objectPosition": undefined,
1154
+ "opacity": 0,
1155
+ "position": "absolute",
1156
+ "top": 0,
1157
+ "transition": "opacity 500ms",
1158
+ "width": "100%",
1159
+ }
1160
+ }
1161
+ />
1162
+ </picture>
1163
+ <noscript>
1164
+ <picture />
1165
+ </noscript>
1166
+ </div>
1167
+ </ForwardRef>
1168
+ `;
1169
+
914
1170
  exports[`Image layout=intrinsic visible renders the image 1`] = `
915
1171
  <ForwardRef
916
1172
  data={
@@ -1254,6 +1510,93 @@ exports[`Image layout=responsive visible renders the image (minimal data) 1`] =
1254
1510
  </ForwardRef>
1255
1511
  `;
1256
1512
 
1513
+ exports[`Image layout=responsive visible renders the image (relative URL) 1`] = `
1514
+ <ForwardRef
1515
+ data={
1516
+ Object {
1517
+ "base64": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLFQoLDhgQDg0NDh0eHREYIx8lJCIrHB0dLSs7GikyKSEuKjUlKDk1MjIyHyo4PTc+PDcxPjUBCgsLDg0OHBAQHDsoIig7Ozs7Ozs7OzsvOzs7Ozs7Ozs7Lzs7Ozs7Ozs7OzsvOzs7NTsvLy87NTU1Ly8vLzsvL//AABEIAA0AGAMBIgACEQEDEQH/xAAYAAACAwAAAAAAAAAAAAAAAAAGBwABBP/EACEQAAEEAAYDAAAAAAAAAAAAAAEAAgMEBQYHESEiFWFx/8QAFQEBAQAAAAAAAAAAAAAAAAAAAwL/xAAZEQADAAMAAAAAAAAAAAAAAAAAAQIRITH/2gAMAwEAAhEDEQA/AFxLgDWTsAd1J5TGy7hEYqNAaNgECX7sjLMQAHJTEy1Zcarfia4lJMauAxqBhLY6ZlaOzDurWvUOd3jZPfCiEh4xs//Z",
1518
+ "height": 421,
1519
+ "src": "/205/image.png?ar=16%3A9&fit=crop&w=750",
1520
+ "width": 750,
1521
+ }
1522
+ }
1523
+ intersectionThreshold={0.2}
1524
+ layout="responsive"
1525
+ >
1526
+ <div
1527
+ style={
1528
+ Object {
1529
+ "overflow": "hidden",
1530
+ "position": "relative",
1531
+ "width": "100%",
1532
+ }
1533
+ }
1534
+ >
1535
+ <img
1536
+ alt=""
1537
+ aria-hidden="true"
1538
+ src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI3NTAiIGhlaWdodD0iNDIxIj48L3N2Zz4="
1539
+ style={
1540
+ Object {
1541
+ "display": "block",
1542
+ "width": "100%",
1543
+ }
1544
+ }
1545
+ />
1546
+ <img
1547
+ alt=""
1548
+ aria-hidden="true"
1549
+ role="presentation"
1550
+ src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLFQoLDhgQDg0NDh0eHREYIx8lJCIrHB0dLSs7GikyKSEuKjUlKDk1MjIyHyo4PTc+PDcxPjUBCgsLDg0OHBAQHDsoIig7Ozs7Ozs7OzsvOzs7Ozs7Ozs7Lzs7Ozs7Ozs7OzsvOzs7NTsvLy87NTU1Ly8vLzsvL//AABEIAA0AGAMBIgACEQEDEQH/xAAYAAACAwAAAAAAAAAAAAAAAAAGBwABBP/EACEQAAEEAAYDAAAAAAAAAAAAAAEAAgMEBQYHESEiFWFx/8QAFQEBAQAAAAAAAAAAAAAAAAAAAwL/xAAZEQADAAMAAAAAAAAAAAAAAAAAAQIRITH/2gAMAwEAAhEDEQA/AFxLgDWTsAd1J5TGy7hEYqNAaNgECX7sjLMQAHJTEy1Zcarfia4lJMauAxqBhLY6ZlaOzDurWvUOd3jZPfCiEh4xs//Z"
1551
+ style={
1552
+ Object {
1553
+ "backgroundColor": undefined,
1554
+ "height": "110%",
1555
+ "left": "-5%",
1556
+ "maxHeight": "none",
1557
+ "maxWidth": "none",
1558
+ "objectFit": undefined,
1559
+ "objectPosition": undefined,
1560
+ "opacity": 1,
1561
+ "position": "absolute",
1562
+ "top": "-5%",
1563
+ "transition": "opacity 500ms",
1564
+ "width": "110%",
1565
+ }
1566
+ }
1567
+ />
1568
+ <picture>
1569
+ <source
1570
+ srcSet="/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=0.25 187w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=0.5 375w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=0.75 562w,/205/image.png?ar=16%3A9&fit=crop&w=750 750w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=1.5 1125w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=2 1500w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=3 2250w,/205/image.png?ar=16%3A9&fit=crop&w=750&dpr=4 3000w"
1571
+ />
1572
+ <img
1573
+ alt=""
1574
+ onLoad={[Function]}
1575
+ src="/205/image.png?ar=16%3A9&fit=crop&w=750"
1576
+ style={
1577
+ Object {
1578
+ "height": "100%",
1579
+ "left": 0,
1580
+ "maxHeight": "none",
1581
+ "maxWidth": "none",
1582
+ "objectFit": undefined,
1583
+ "objectPosition": undefined,
1584
+ "opacity": 0,
1585
+ "position": "absolute",
1586
+ "top": 0,
1587
+ "transition": "opacity 500ms",
1588
+ "width": "100%",
1589
+ }
1590
+ }
1591
+ />
1592
+ </picture>
1593
+ <noscript>
1594
+ <picture />
1595
+ </noscript>
1596
+ </div>
1597
+ </ForwardRef>
1598
+ `;
1599
+
1257
1600
  exports[`Image layout=responsive visible renders the image 1`] = `
1258
1601
  <ForwardRef
1259
1602
  data={
@@ -26,6 +26,14 @@ const minimalData = {
26
26
  width: 750,
27
27
  };
28
28
 
29
+ const minimalDataWithRelativeUrl = {
30
+ base64:
31
+ 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLFQoLDhgQDg0NDh0eHREYIx8lJCIrHB0dLSs7GikyKSEuKjUlKDk1MjIyHyo4PTc+PDcxPjUBCgsLDg0OHBAQHDsoIig7Ozs7Ozs7OzsvOzs7Ozs7Ozs7Lzs7Ozs7Ozs7OzsvOzs7NTsvLy87NTU1Ly8vLzsvL//AABEIAA0AGAMBIgACEQEDEQH/xAAYAAACAwAAAAAAAAAAAAAAAAAGBwABBP/EACEQAAEEAAYDAAAAAAAAAAAAAAEAAgMEBQYHESEiFWFx/8QAFQEBAQAAAAAAAAAAAAAAAAAAAwL/xAAZEQADAAMAAAAAAAAAAAAAAAAAAQIRITH/2gAMAwEAAhEDEQA/AFxLgDWTsAd1J5TGy7hEYqNAaNgECX7sjLMQAHJTEy1Zcarfia4lJMauAxqBhLY6ZlaOzDurWvUOd3jZPfCiEh4xs//Z',
32
+ height: 421,
33
+ src: '/205/image.png?ar=16%3A9&fit=crop&w=750',
34
+ width: 750,
35
+ };
36
+
29
37
  describe('Image', () => {
30
38
  // intersectionThreshold is an hack to make tests work
31
39
  // we need the library to generate a different IntersectionObserver for each test
@@ -65,6 +73,19 @@ describe('Image', () => {
65
73
  expect(wrapper).toMatchSnapshot();
66
74
  });
67
75
 
76
+ it('renders the image (relative URL)', () => {
77
+ const wrapper = mount(
78
+ <Image
79
+ data={minimalDataWithRelativeUrl}
80
+ layout={layout}
81
+ intersectionThreshold={0.2}
82
+ />,
83
+ );
84
+ mockAllIsIntersecting(true);
85
+ wrapper.update();
86
+ expect(wrapper).toMatchSnapshot();
87
+ });
88
+
68
89
  describe('image loaded', () => {
69
90
  it('shows the image', () => {
70
91
  const wrapper = mount(
@@ -146,6 +146,8 @@ const imageShowStrategy = ({ lazyLoad, loaded }: State) => {
146
146
  return true;
147
147
  };
148
148
 
149
+ const bogusBaseUrl = 'https://example.com/';
150
+
149
151
  const buildSrcSet = (
150
152
  src: string | null | undefined,
151
153
  width: number | undefined,
@@ -157,7 +159,7 @@ const buildSrcSet = (
157
159
 
158
160
  return candidateMultipliers
159
161
  .map((multiplier) => {
160
- const url = new URL(src);
162
+ const url = new URL(src, bogusBaseUrl);
161
163
 
162
164
  if (multiplier !== 1) {
163
165
  url.searchParams.set('dpr', `${multiplier}`);
@@ -183,7 +185,7 @@ const buildSrcSet = (
183
185
  return null;
184
186
  }
185
187
 
186
- return `${url.toString()} ${finalWidth}w`;
188
+ return `${url.toString().replace(bogusBaseUrl, '/')} ${finalWidth}w`;
187
189
  })
188
190
  .filter(Boolean)
189
191
  .join(',');