react-datocms 1.6.7 → 2.1.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/README.md +144 -63
- package/dist/cjs/Image/__tests__/index.test.js +32 -28
- package/dist/cjs/Image/__tests__/index.test.js.map +1 -1
- package/dist/cjs/Image/index.js +37 -22
- package/dist/cjs/Image/index.js.map +1 -1
- package/dist/cjs/Seo/__tests__/index.test.js +277 -37
- package/dist/cjs/Seo/__tests__/index.test.js.map +1 -1
- package/dist/cjs/Seo/index.js +13 -60
- package/dist/cjs/Seo/index.js.map +1 -1
- package/dist/cjs/Seo/remixUtils.js +42 -0
- package/dist/cjs/Seo/remixUtils.js.map +1 -0
- package/dist/cjs/Seo/renderMetaTags.js +40 -0
- package/dist/cjs/Seo/renderMetaTags.js.map +1 -0
- package/dist/cjs/Seo/renderMetaTagsToString.js +22 -0
- package/dist/cjs/Seo/renderMetaTagsToString.js.map +1 -0
- package/dist/cjs/Seo/types.js +5 -0
- package/dist/cjs/Seo/types.js.map +1 -0
- package/dist/esm/Image/__tests__/index.test.js +36 -32
- package/dist/esm/Image/__tests__/index.test.js.map +1 -1
- package/dist/esm/Image/index.d.ts +23 -6
- package/dist/esm/Image/index.js +40 -24
- package/dist/esm/Image/index.js.map +1 -1
- package/dist/esm/Seo/__tests__/index.test.js +276 -36
- package/dist/esm/Seo/__tests__/index.test.js.map +1 -1
- package/dist/esm/Seo/index.d.ts +4 -12
- package/dist/esm/Seo/index.js +4 -55
- package/dist/esm/Seo/index.js.map +1 -1
- package/dist/esm/Seo/remixUtils.d.ts +24 -0
- package/dist/esm/Seo/remixUtils.js +37 -0
- package/dist/esm/Seo/remixUtils.js.map +1 -0
- package/dist/esm/Seo/renderMetaTags.d.ts +3 -0
- package/dist/esm/Seo/renderMetaTags.js +33 -0
- package/dist/esm/Seo/renderMetaTags.js.map +1 -0
- package/dist/esm/Seo/renderMetaTagsToString.d.ts +2 -0
- package/dist/esm/Seo/renderMetaTagsToString.js +18 -0
- package/dist/esm/Seo/renderMetaTagsToString.js.map +1 -0
- package/dist/esm/Seo/types.d.ts +37 -0
- package/dist/esm/Seo/types.js +4 -0
- package/dist/esm/Seo/types.js.map +1 -0
- package/dist/types/Image/index.d.ts +23 -6
- package/dist/types/Seo/index.d.ts +4 -12
- package/dist/types/Seo/remixUtils.d.ts +24 -0
- package/dist/types/Seo/renderMetaTags.d.ts +3 -0
- package/dist/types/Seo/renderMetaTagsToString.d.ts +2 -0
- package/dist/types/Seo/types.d.ts +37 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ A set of components and utilities to work faster with [DatoCMS](https://www.dato
|
|
|
6
6
|
|
|
7
7
|
<br /><br />
|
|
8
8
|
<a href="https://www.datocms.com/">
|
|
9
|
-
|
|
9
|
+
<img src="https://www.datocms.com/images/full_logo.svg" height="60">
|
|
10
10
|
</a>
|
|
11
11
|
<br /><br />
|
|
12
12
|
|
|
@@ -28,15 +28,18 @@ A set of components and utilities to work faster with [DatoCMS](https://www.dato
|
|
|
28
28
|
- [Usage](#usage)
|
|
29
29
|
- [Example](#example-1)
|
|
30
30
|
- [Props](#props)
|
|
31
|
+
- [Layout mode](#layout-mode)
|
|
31
32
|
- [The `ResponsiveImage` object](#the-responsiveimage-object)
|
|
32
33
|
- [Social share, SEO and Favicon meta tags](#social-share-seo-and-favicon-meta-tags)
|
|
33
|
-
- [
|
|
34
|
-
- [
|
|
34
|
+
- [`renderMetaTags()`](#rendermetatags)
|
|
35
|
+
- [`renderMetaTagsToString()`](#rendermetatagstostring)
|
|
36
|
+
- [`toRemixMeta()` and `toRemixLinks()`](#toremixmeta-and-toremixlinks)
|
|
35
37
|
- [Structured text](#structured-text)
|
|
36
38
|
- [Basic usage](#basic-usage)
|
|
37
39
|
- [Custom renderers for inline records, blocks, and links](#custom-renderers-for-inline-records-blocks-and-links)
|
|
38
|
-
- [Override default
|
|
40
|
+
- [Override default rendering of nodes](#override-default-rendering-of-nodes)
|
|
39
41
|
- [Props](#props-1)
|
|
42
|
+
- [Development](#development)
|
|
40
43
|
|
|
41
44
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
42
45
|
|
|
@@ -237,18 +240,44 @@ export default withQuery(query)(Page);
|
|
|
237
240
|
|
|
238
241
|
## Props
|
|
239
242
|
|
|
240
|
-
| prop | type
|
|
241
|
-
| --------------------- |
|
|
242
|
-
| data | `ResponsiveImage` object
|
|
243
|
-
|
|
|
244
|
-
|
|
|
245
|
-
|
|
|
246
|
-
|
|
|
247
|
-
|
|
|
248
|
-
|
|
|
249
|
-
|
|
|
250
|
-
|
|
|
251
|
-
|
|
|
243
|
+
| prop | type | required | description | default |
|
|
244
|
+
| --------------------- | ------------------------------------------------ | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
|
|
245
|
+
| data | `ResponsiveImage` object | :white_check_mark: | The actual response you get from a DatoCMS `responsiveImage` GraphQL query | |
|
|
246
|
+
| layout | 'intrinsic' \| 'fixed' \| 'responsive' \| 'fill' | :x: | The layout behavior of the image as the viewport changes size | "intrinsic" |
|
|
247
|
+
| className | string | :x: | Additional CSS className for root node | null |
|
|
248
|
+
| style | CSS properties | :x: | Additional CSS rules to add to the root node | null |
|
|
249
|
+
| pictureClassName | string | :x: | Additional CSS class for the image inside the inner `<picture />` tag | null |
|
|
250
|
+
| pictureStyle | CSS properties | :x: | Additional CSS rules to add to the image inside the inner `<picture />` tag | null |
|
|
251
|
+
| fadeInDuration | integer | :x: | Duration (in ms) of the fade-in transition effect upoad image loading | 500 |
|
|
252
|
+
| intersectionThreshold | float | :x: | Indicate at what percentage of the placeholder visibility the loading of the image should be triggered. A value of 0 means that as soon as even one pixel is visible, the callback will be run. A value of 1.0 means that the threshold isn't considered passed until every pixel is visible. | 0 |
|
|
253
|
+
| intersectionMargin | string | :x: | Margin around the placeholder. Can have values similar to the CSS margin property (top, right, bottom, left). The values can be percentages. This set of values serves to grow or shrink each side of the placeholder element's bounding box before computing intersections. | "0px 0px 0px 0px" |
|
|
254
|
+
| lazyLoad | Boolean | :x: | Whether enable lazy loading or not | true |
|
|
255
|
+
| onLoad | () => void | :x: | Function triggered when the image has finished loading | undefined |
|
|
256
|
+
| usePlaceholder | Boolean | :x: | Whether the component should use a blurred image placeholder | true |
|
|
257
|
+
|
|
258
|
+
### Layout mode
|
|
259
|
+
|
|
260
|
+
With the `layout` property, you can configure the behavior of the image as the viewport changes size:
|
|
261
|
+
|
|
262
|
+
- When `intrinsic` (default behaviour), the image will scale the dimensions down for smaller viewports, but maintain the original dimensions for larger viewports.
|
|
263
|
+
- When `fixed`, the image dimensions will not change as the viewport changes (no responsiveness) similar to the native `img` element.
|
|
264
|
+
- When `responsive`, the image will scale the dimensions down for smaller viewports and scale up for larger viewports.
|
|
265
|
+
- When `fill`, the image will stretch both width and height to the dimensions of the parent element, provided the parent element is relative.
|
|
266
|
+
- This is usually paired with the `objectFit` and `objectPosition` properties.
|
|
267
|
+
- Ensure the parent element has `position: relative` in their stylesheet.
|
|
268
|
+
|
|
269
|
+
Example for `layout="fill"` (useful also for background images):
|
|
270
|
+
|
|
271
|
+
```jsx
|
|
272
|
+
<div style={{ position: 'relative', width: 200, height: 500 }}>
|
|
273
|
+
<Image
|
|
274
|
+
data={imageData}
|
|
275
|
+
layout="fill"
|
|
276
|
+
objectFit="cover"
|
|
277
|
+
objectPosition="50% 50%"
|
|
278
|
+
/>
|
|
279
|
+
</div>
|
|
280
|
+
```
|
|
252
281
|
|
|
253
282
|
### The `ResponsiveImage` object
|
|
254
283
|
|
|
@@ -277,59 +306,92 @@ Here's a complete recap of what `responsiveImage` offers:
|
|
|
277
306
|
|
|
278
307
|
# Social share, SEO and Favicon meta tags
|
|
279
308
|
|
|
280
|
-
Just like the image component
|
|
309
|
+
Just like for the image component this package offers a number of utilities designed to work seamlessly with DatoCMS’s [`_seoMetaTags` and `faviconMetaTags` GraphQL queries](https://www.datocms.com/docs/content-delivery-api/seo) so that you can easily handle SEO, social shares and favicons in your pages.
|
|
281
310
|
|
|
282
|
-
|
|
283
|
-
- Compatible with any GraphQL library (Apollo, graphql-hooks, graphql-request, etc.);
|
|
284
|
-
- Usable both client and server side;
|
|
285
|
-
- Compatible with vanilla React, Next.js and pretty much any other React-based solution;
|
|
311
|
+
All the utilities take an array of `SeoOrFaviconTag`s in the exact form they're returned by the following [DatoCMS GraphQL API queries](https://www.datocms.com/docs/content-delivery-api/seo):
|
|
286
312
|
|
|
287
|
-
|
|
313
|
+
- `_seoMetaTags` (always available on any type of record)
|
|
314
|
+
- `faviconMetaTags` on the global `_site` object.
|
|
288
315
|
|
|
289
|
-
|
|
316
|
+
```graphql
|
|
317
|
+
query {
|
|
318
|
+
page: homepage {
|
|
319
|
+
title
|
|
320
|
+
seo: _seoMetaTags {
|
|
321
|
+
attributes
|
|
322
|
+
content
|
|
323
|
+
tag
|
|
324
|
+
}
|
|
325
|
+
}
|
|
290
326
|
|
|
291
|
-
|
|
292
|
-
|
|
327
|
+
site: _site {
|
|
328
|
+
favicon: faviconMetaTags {
|
|
329
|
+
attributes
|
|
330
|
+
content
|
|
331
|
+
tag
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
```
|
|
293
336
|
|
|
294
|
-
You can
|
|
337
|
+
You can then concat those two arrays of tags and pass them togheter to the function, ie:
|
|
295
338
|
|
|
296
|
-
|
|
339
|
+
```js
|
|
340
|
+
renderMetaTags([...data.page.seo, ...data.site.favicon]);
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## `renderMetaTags()`
|
|
344
|
+
|
|
345
|
+
This function generates React `<meta>` and `<link />` elements, so it is compatible with React packages like [`react-helmet`](https://www.npmjs.com/package/react-helmet).
|
|
297
346
|
|
|
298
|
-
For a
|
|
347
|
+
For a complete example take a look at our [examples directory](https://github.com/datocms/react-datocms/tree/master/examples).
|
|
299
348
|
|
|
300
349
|
```js
|
|
301
350
|
import React from 'react';
|
|
302
351
|
import { renderMetaTags } from 'react-datocms';
|
|
303
352
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
<
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
353
|
+
function Page({ data }) {
|
|
354
|
+
return (
|
|
355
|
+
<div>
|
|
356
|
+
<Helmet>
|
|
357
|
+
{renderMetaTags([...data.page.seo, ...data.site.favicon])}
|
|
358
|
+
</Helmet>
|
|
359
|
+
</div>
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
```
|
|
310
363
|
|
|
311
|
-
|
|
312
|
-
query {
|
|
313
|
-
page: homepage {
|
|
314
|
-
title
|
|
315
|
-
seo: _seoMetaTags {
|
|
316
|
-
attributes
|
|
317
|
-
content
|
|
318
|
-
tag
|
|
319
|
-
}
|
|
320
|
-
}
|
|
364
|
+
## `renderMetaTagsToString()`
|
|
321
365
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
366
|
+
This function generates an HTML string containing `<meta>` and `<link />` tags, so it can be used server-side.
|
|
367
|
+
|
|
368
|
+
```js
|
|
369
|
+
import { renderMetaTagsToString } from 'react-datocms';
|
|
370
|
+
|
|
371
|
+
const someMoreComplexHtml = `
|
|
372
|
+
<html>
|
|
373
|
+
<head>
|
|
374
|
+
${renderMetaTagsToString([...data.page.seo, ...data.site.favicon])}
|
|
375
|
+
</head>
|
|
376
|
+
</html>
|
|
330
377
|
`;
|
|
378
|
+
```
|
|
331
379
|
|
|
332
|
-
|
|
380
|
+
## `toRemixMeta()` and `toRemixLinks()`
|
|
381
|
+
|
|
382
|
+
These two functions generate `HtmlMetaDescriptor` and `RemixHtmlLinkDescriptor` objects, compatibile with [`meta`](https://remix.run/docs/en/v1.1.1/api/conventions#meta) and [`links`](https://remix.run/docs/en/v1.1.1/api/conventions#links) exports of the [Remix](https://remix.run/) framework:
|
|
383
|
+
|
|
384
|
+
```js
|
|
385
|
+
import type { LinksFunction, MetaFunction } from 'remix';
|
|
386
|
+
import { toRemixLinks, toRemixMeta } from 'react-datocms';
|
|
387
|
+
|
|
388
|
+
export const links: LinksFunction = ({ data: { site } }) => {
|
|
389
|
+
return toRemixLinks(site.favicon);
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
export const meta: MetaFunction = ({ data: { post, site } }) => {
|
|
393
|
+
return toRemixMeta([...post.seo, ...site.favicon]);
|
|
394
|
+
};
|
|
333
395
|
```
|
|
334
396
|
|
|
335
397
|
# Structured text
|
|
@@ -343,8 +405,7 @@ import React from 'react';
|
|
|
343
405
|
import { StructuredText } from 'react-datocms';
|
|
344
406
|
|
|
345
407
|
const Page = ({ data }) => {
|
|
346
|
-
// data.blogPost.content
|
|
347
|
-
// {
|
|
408
|
+
// data.blogPost.content = {
|
|
348
409
|
// value: {
|
|
349
410
|
// schema: "dast",
|
|
350
411
|
// document: {
|
|
@@ -570,7 +631,6 @@ import SyntaxHighlight from 'components/SyntaxHighlight';
|
|
|
570
631
|
<StructuredText
|
|
571
632
|
data={data.blogPost.content}
|
|
572
633
|
customRules={[
|
|
573
|
-
|
|
574
634
|
// Add HTML anchors to heading levels for in-page navigation
|
|
575
635
|
renderRule(isHeading, ({ node, children, key }) => {
|
|
576
636
|
const HeadingTag = `h${node.level}`;
|
|
@@ -586,7 +646,7 @@ import SyntaxHighlight from 'components/SyntaxHighlight';
|
|
|
586
646
|
</HeadingTag>
|
|
587
647
|
);
|
|
588
648
|
}),
|
|
589
|
-
|
|
649
|
+
|
|
590
650
|
// Use a custom syntax highlighter component for code blocks
|
|
591
651
|
renderRule(isCode, ({ node, key }) => {
|
|
592
652
|
return (
|
|
@@ -598,14 +658,18 @@ import SyntaxHighlight from 'components/SyntaxHighlight';
|
|
|
598
658
|
/>
|
|
599
659
|
);
|
|
600
660
|
}),
|
|
601
|
-
|
|
661
|
+
|
|
602
662
|
// Apply different formatting to top-level paragraphs
|
|
603
663
|
renderRule(
|
|
604
664
|
isParagraph,
|
|
605
665
|
({ adapter: { renderNode }, node, children, key, ancestors }) => {
|
|
606
666
|
if (isRoot(ancestors[0])) {
|
|
607
667
|
// If this paragraph node is a top-level one, give it a special class
|
|
608
|
-
return renderNode(
|
|
668
|
+
return renderNode(
|
|
669
|
+
'p',
|
|
670
|
+
{ key, className: 'top-level-paragraph-container-example' },
|
|
671
|
+
children,
|
|
672
|
+
);
|
|
609
673
|
} else {
|
|
610
674
|
// Proceed with default paragraph rendering...
|
|
611
675
|
// return renderNode('p', { key }, children);
|
|
@@ -613,10 +677,8 @@ import SyntaxHighlight from 'components/SyntaxHighlight';
|
|
|
613
677
|
// Or even completely remove the paragraph and directly render the inner children:
|
|
614
678
|
return children;
|
|
615
679
|
}
|
|
616
|
-
}
|
|
617
|
-
)
|
|
618
|
-
|
|
619
|
-
|
|
680
|
+
},
|
|
681
|
+
),
|
|
620
682
|
]}
|
|
621
683
|
/>;
|
|
622
684
|
```
|
|
@@ -634,3 +696,22 @@ Note: if you override the rules for `inline_item`, `item_link` or `block` nodes,
|
|
|
634
696
|
| metaTransformer | `({ node, meta }) => Object \| null` | :x: | Transform `link` and `itemLink` meta property into HTML props | [See function](https://github.com/datocms/structured-text/blob/main/packages/generic-html-renderer/src/index.ts#L61) |
|
|
635
697
|
| customRules | `Array<RenderRule>` | :x: | Customize how document is converted in JSX (use `renderRule()` to generate) | `null` |
|
|
636
698
|
| renderText | `(text: string, key: string) => ReactElement \| string \| null` | :x: | Convert a simple string text into React | `(text) => text` |
|
|
699
|
+
|
|
700
|
+
# Development
|
|
701
|
+
|
|
702
|
+
This repository contains a number of demos/examples. You can use them to locally test your changes to the package with `npm link`:
|
|
703
|
+
|
|
704
|
+
```
|
|
705
|
+
npm link
|
|
706
|
+
cd examples/images-and-seo/vanilla-react
|
|
707
|
+
npm link react-datocms
|
|
708
|
+
npm run start
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
Now on another terminal you can run:
|
|
712
|
+
|
|
713
|
+
```
|
|
714
|
+
npm run watch
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
This will re-compile the package everytime you make a change, and the example project will pick those changes instantly.
|
|
@@ -24,41 +24,45 @@ var enzyme_1 = require("enzyme");
|
|
|
24
24
|
var index_1 = require("../index");
|
|
25
25
|
var test_utils_1 = require("react-intersection-observer/test-utils");
|
|
26
26
|
var data = {
|
|
27
|
-
alt:
|
|
27
|
+
alt: 'DatoCMS swag',
|
|
28
28
|
aspectRatio: 1.7777777777777777,
|
|
29
|
-
base64:
|
|
29
|
+
base64: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHBwgHBgoICAgLFQoLDhgQDg0NDh0eHREYIx8lJCIrHB0dLSs7GikyKSEuKjUlKDk1MjIyHyo4PTc+PDcxPjUBCgsLDg0OHBAQHDsoIig7Ozs7Ozs7OzsvOzs7Ozs7Ozs7Lzs7Ozs7Ozs7OzsvOzs7NTsvLy87NTU1Ly8vLzsvL//AABEIAA0AGAMBIgACEQEDEQH/xAAYAAACAwAAAAAAAAAAAAAAAAAGBwABBP/EACEQAAEEAAYDAAAAAAAAAAAAAAEAAgMEBQYHESEiFWFx/8QAFQEBAQAAAAAAAAAAAAAAAAAAAwL/xAAZEQADAAMAAAAAAAAAAAAAAAAAAQIRITH/2gAMAwEAAhEDEQA/AFxLgDWTsAd1J5TGy7hEYqNAaNgECX7sjLMQAHJTEy1Zcarfia4lJMauAxqBhLY6ZlaOzDurWvUOd3jZPfCiEh4xs//Z',
|
|
30
30
|
height: 421,
|
|
31
|
-
sizes:
|
|
32
|
-
src:
|
|
33
|
-
srcSet:
|
|
34
|
-
title:
|
|
31
|
+
sizes: '(max-width: 750px) 100vw, 750px',
|
|
32
|
+
src: 'https://www.datocms-assets.com/205/image.png?ar=16%3A9&fit=crop&w=750',
|
|
33
|
+
srcSet: 'https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=0.25&fit=crop&w=750 187w,↵https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=0.5&fit=crop&w=750 375w,↵https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=0.75&fit=crop&w=750 562w,↵https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=1&fit=crop&w=750 750w,↵https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=1.5&fit=crop&w=750 1125w,↵https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=2&fit=crop&w=750 1500w,↵https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=3&fit=crop&w=750 2250w,↵https://www.datocms-assets.com/205/image.png?ar=16%3A9&dpr=4&fit=crop&w=750 3000w',
|
|
34
|
+
title: 'These are awesome, we know that.',
|
|
35
35
|
width: 750
|
|
36
36
|
};
|
|
37
|
-
describe(
|
|
37
|
+
describe('Image', function () {
|
|
38
38
|
// intersectionThreshold is an hack to make tests work
|
|
39
39
|
// we need the library to generate a different IntersectionObserver for each test
|
|
40
40
|
// otherwise the IntersectionObserver mocking won't work
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
41
|
+
['intrinsic', 'fixed', 'responsive', 'fill'].forEach(function (layout) {
|
|
42
|
+
describe("layout=" + layout, function () {
|
|
43
|
+
describe('not visible', function () {
|
|
44
|
+
it('renders the blur-up thumb', function () {
|
|
45
|
+
var wrapper = enzyme_1.mount(React.createElement(index_1.Image, { data: data, layout: layout, intersectionThreshold: 0.1 }));
|
|
46
|
+
expect(wrapper).toMatchSnapshot();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
describe('visible', function () {
|
|
50
|
+
it('renders the image', function () {
|
|
51
|
+
var wrapper = enzyme_1.mount(React.createElement(index_1.Image, { data: data, layout: layout, intersectionThreshold: 0.2 }));
|
|
52
|
+
test_utils_1.mockAllIsIntersecting(true);
|
|
53
|
+
wrapper.update();
|
|
54
|
+
expect(wrapper).toMatchSnapshot();
|
|
55
|
+
});
|
|
56
|
+
describe('image loaded', function () {
|
|
57
|
+
it('shows the image', function () {
|
|
58
|
+
var wrapper = enzyme_1.mount(React.createElement(index_1.Image, { data: data, layout: layout, intersectionThreshold: 0.3 }));
|
|
59
|
+
test_utils_1.mockAllIsIntersecting(true);
|
|
60
|
+
wrapper.update();
|
|
61
|
+
wrapper.find('img').last().simulate('load');
|
|
62
|
+
wrapper.update();
|
|
63
|
+
expect(wrapper).toMatchSnapshot();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
62
66
|
});
|
|
63
67
|
});
|
|
64
68
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../../src/Image/__tests__/index.test.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA,2CAA+B;AAC/B,iCAA+B;AAC/B,kCAAiC;AACjC,qEAA+E;AAE/E,IAAM,IAAI,GAAG;IACX,GAAG,EAAE,cAAc;IACnB,WAAW,EAAE,kBAAkB;IAC/B,MAAM,EACJ,igBAAigB;IACngB,MAAM,EAAE,GAAG;IACX,KAAK,EAAE,iCAAiC;IACxC,GAAG,EAAE,uEAAuE;IAC5E,MAAM,EACJ,8pBAA8pB;IAChqB,KAAK,EAAE,kCAAkC;IACzC,KAAK,EAAE,GAAG;CACX,CAAC;AAEF,QAAQ,CAAC,OAAO,EAAE;IAChB,sDAAsD;IACtD,iFAAiF;IACjF,wDAAwD;
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../../src/Image/__tests__/index.test.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA,2CAA+B;AAC/B,iCAA+B;AAC/B,kCAAiC;AACjC,qEAA+E;AAE/E,IAAM,IAAI,GAAG;IACX,GAAG,EAAE,cAAc;IACnB,WAAW,EAAE,kBAAkB;IAC/B,MAAM,EACJ,igBAAigB;IACngB,MAAM,EAAE,GAAG;IACX,KAAK,EAAE,iCAAiC;IACxC,GAAG,EAAE,uEAAuE;IAC5E,MAAM,EACJ,8pBAA8pB;IAChqB,KAAK,EAAE,kCAAkC;IACzC,KAAK,EAAE,GAAG;CACX,CAAC;AAEF,QAAQ,CAAC,OAAO,EAAE;IAChB,sDAAsD;IACtD,iFAAiF;IACjF,wDAAwD;IAEvD,CAAC,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,CAAW,CAAC,OAAO,CAAC,UAAC,MAAM;QACrE,QAAQ,CAAC,YAAU,MAAQ,EAAE;YAC3B,QAAQ,CAAC,aAAa,EAAE;gBACtB,EAAE,CAAC,2BAA2B,EAAE;oBAC9B,IAAM,OAAO,GAAG,cAAK,CACnB,oBAAC,aAAK,IAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,EAAE,GAAG,GAAI,CAClE,CAAC;oBACF,MAAM,CAAC,OAAO,CAAC,CAAC,eAAe,EAAE,CAAC;gBACpC,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,QAAQ,CAAC,SAAS,EAAE;gBAClB,EAAE,CAAC,mBAAmB,EAAE;oBACtB,IAAM,OAAO,GAAG,cAAK,CACnB,oBAAC,aAAK,IAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,EAAE,GAAG,GAAI,CAClE,CAAC;oBACF,kCAAqB,CAAC,IAAI,CAAC,CAAC;oBAC5B,OAAO,CAAC,MAAM,EAAE,CAAC;oBACjB,MAAM,CAAC,OAAO,CAAC,CAAC,eAAe,EAAE,CAAC;gBACpC,CAAC,CAAC,CAAC;gBAEH,QAAQ,CAAC,cAAc,EAAE;oBACvB,EAAE,CAAC,iBAAiB,EAAE;wBACpB,IAAM,OAAO,GAAG,cAAK,CACnB,oBAAC,aAAK,IAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,EAAE,GAAG,GAAI,CAClE,CAAC;wBACF,kCAAqB,CAAC,IAAI,CAAC,CAAC;wBAC5B,OAAO,CAAC,MAAM,EAAE,CAAC;wBACjB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;wBAC5C,OAAO,CAAC,MAAM,EAAE,CAAC;wBACjB,MAAM,CAAC,OAAO,CAAC,CAAC,eAAe,EAAE,CAAC;oBACpC,CAAC,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/cjs/Image/index.js
CHANGED
|
@@ -34,9 +34,9 @@ exports.Image = void 0;
|
|
|
34
34
|
var react_1 = __importStar(require("react"));
|
|
35
35
|
require("intersection-observer");
|
|
36
36
|
var react_intersection_observer_1 = require("react-intersection-observer");
|
|
37
|
-
var isSsr = typeof window ===
|
|
37
|
+
var isSsr = typeof window === 'undefined';
|
|
38
38
|
var universalBtoa = isSsr
|
|
39
|
-
? function (str) { return Buffer.from(str.toString(),
|
|
39
|
+
? function (str) { return Buffer.from(str.toString(), 'binary').toString('base64'); }
|
|
40
40
|
: window.btoa;
|
|
41
41
|
var isIntersectionObserverAvailable = isSsr
|
|
42
42
|
? false
|
|
@@ -67,24 +67,30 @@ var imageShowStrategy = function (_a) {
|
|
|
67
67
|
}
|
|
68
68
|
return true;
|
|
69
69
|
};
|
|
70
|
-
|
|
70
|
+
exports.Image = react_1.forwardRef(function (_a, ref) {
|
|
71
71
|
var _b;
|
|
72
|
-
var className = _a.className,
|
|
73
|
-
var
|
|
74
|
-
var handleLoad =
|
|
72
|
+
var className = _a.className, _c = _a.fadeInDuration, fadeInDuration = _c === void 0 ? 500 : _c, intersectionTreshold = _a.intersectionTreshold, intersectionThreshold = _a.intersectionThreshold, intersectionMargin = _a.intersectionMargin, pictureClassName = _a.pictureClassName, _d = _a.lazyLoad, lazyLoad = _d === void 0 ? true : _d, style = _a.style, pictureStyle = _a.pictureStyle, _e = _a.layout, layout = _e === void 0 ? 'intrinsic' : _e, objectFit = _a.objectFit, objectPosition = _a.objectPosition, data = _a.data, onLoad = _a.onLoad, _f = _a.usePlaceholder, usePlaceholder = _f === void 0 ? true : _f;
|
|
73
|
+
var _g = react_1.useState(false), loaded = _g[0], setLoaded = _g[1];
|
|
74
|
+
var handleLoad = function () {
|
|
75
|
+
onLoad === null || onLoad === void 0 ? void 0 : onLoad();
|
|
75
76
|
setLoaded(true);
|
|
76
|
-
}
|
|
77
|
-
var
|
|
77
|
+
};
|
|
78
|
+
var _h = react_intersection_observer_1.useInView({
|
|
78
79
|
threshold: intersectionThreshold || intersectionTreshold || 0,
|
|
79
|
-
rootMargin: intersectionMargin ||
|
|
80
|
+
rootMargin: intersectionMargin || '0px 0px 0px 0px',
|
|
80
81
|
triggerOnce: true
|
|
81
|
-
}),
|
|
82
|
+
}), viewRef = _h[0], inView = _h[1];
|
|
83
|
+
var callbackRef = react_1.useCallback(function (_ref) {
|
|
84
|
+
viewRef(_ref);
|
|
85
|
+
if (ref)
|
|
86
|
+
ref.current = _ref;
|
|
87
|
+
}, [viewRef]);
|
|
82
88
|
var absolutePositioning = {
|
|
83
|
-
position:
|
|
89
|
+
position: 'absolute',
|
|
84
90
|
left: 0,
|
|
85
91
|
top: 0,
|
|
86
|
-
width:
|
|
87
|
-
height:
|
|
92
|
+
width: '100%',
|
|
93
|
+
height: '100%'
|
|
88
94
|
};
|
|
89
95
|
var addImage = imageAddStrategy({
|
|
90
96
|
lazyLoad: lazyLoad,
|
|
@@ -98,26 +104,35 @@ var Image = function (_a) {
|
|
|
98
104
|
});
|
|
99
105
|
var webpSource = data.webpSrcSet && (react_1["default"].createElement("source", { srcSet: data.webpSrcSet, sizes: data.sizes, type: "image/webp" }));
|
|
100
106
|
var regularSource = data.srcSet && (react_1["default"].createElement("source", { srcSet: data.srcSet, sizes: data.sizes }));
|
|
101
|
-
var transition =
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
107
|
+
var transition = fadeInDuration > 0 ? "opacity " + fadeInDuration + "ms" : undefined;
|
|
108
|
+
var placeholder = usePlaceholder ? (react_1["default"].createElement("img", { role: "presentation", src: data.base64, style: __assign({ backgroundColor: data.bgColor, opacity: showImage ? 0 : 1, transition: transition,
|
|
109
|
+
objectFit: objectFit,
|
|
110
|
+
objectPosition: objectPosition }, absolutePositioning) })) : null;
|
|
105
111
|
var width = data.width, aspectRatio = data.aspectRatio;
|
|
106
112
|
var height = data.height || width / aspectRatio;
|
|
107
113
|
var svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"" + width + "\" height=\"" + height + "\"></svg>";
|
|
108
|
-
var sizer = (react_1["default"].createElement("img", { className: pictureClassName, style:
|
|
109
|
-
|
|
114
|
+
var sizer = layout !== 'fill' ? (react_1["default"].createElement("img", { className: pictureClassName, style: {
|
|
115
|
+
display: 'block',
|
|
116
|
+
width: '100%'
|
|
117
|
+
}, src: "data:image/svg+xml;base64," + universalBtoa(svg), role: "presentation" })) : null;
|
|
118
|
+
return (react_1["default"].createElement("div", { ref: callbackRef, className: className, style: __assign(__assign({ overflow: 'hidden' }, (layout === 'fill'
|
|
119
|
+
? absolutePositioning
|
|
120
|
+
: layout === 'intrinsic'
|
|
121
|
+
? { position: 'relative', width: '100%', maxWidth: width }
|
|
122
|
+
: layout === 'fixed'
|
|
123
|
+
? { position: 'relative', width: width }
|
|
124
|
+
: { position: 'relative', width: '100%' })), style) },
|
|
110
125
|
sizer,
|
|
111
126
|
placeholder,
|
|
112
127
|
addImage && (react_1["default"].createElement("picture", null,
|
|
113
128
|
webpSource,
|
|
114
129
|
regularSource,
|
|
115
|
-
data.src && (react_1["default"].createElement("img", { src: data.src, alt: data.alt, title: data.title, onLoad: handleLoad, className: pictureClassName, style: __assign(__assign(__assign({
|
|
130
|
+
data.src && (react_1["default"].createElement("img", { src: data.src, alt: data.alt, title: data.title, onLoad: handleLoad, className: pictureClassName, style: __assign(__assign(__assign({ opacity: showImage ? 1 : 0, transition: transition }, absolutePositioning), { objectFit: objectFit,
|
|
131
|
+
objectPosition: objectPosition }), pictureStyle) })))),
|
|
116
132
|
react_1["default"].createElement("noscript", null,
|
|
117
133
|
react_1["default"].createElement("picture", null,
|
|
118
134
|
webpSource,
|
|
119
135
|
regularSource,
|
|
120
136
|
data.src && (react_1["default"].createElement("img", { src: data.src, alt: (_b = data.alt) !== null && _b !== void 0 ? _b : '', title: data.title, className: pictureClassName, style: __assign(__assign({}, absolutePositioning), pictureStyle), loading: "lazy" }))))));
|
|
121
|
-
};
|
|
122
|
-
exports.Image = Image;
|
|
137
|
+
});
|
|
123
138
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/Image/index.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/Image/index.tsx"],"names":[],"mappings":"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"}
|