react-datocms 3.0.13 → 3.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 CHANGED
@@ -10,743 +10,27 @@ A set of components and utilities to work faster with [DatoCMS](https://www.dato
10
10
  </a>
11
11
  <br /><br />
12
12
 
13
- ## Table of Contents
14
-
15
- <!-- START doctoc generated TOC please keep comment here to allow auto update -->
16
- <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
17
-
18
- - [Demos](#demos)
19
- - [Installation](#installation)
20
- - [Live real-time updates](#live-real-time-updates)
21
- - [Reference](#reference)
22
- - [Initialization options](#initialization-options)
23
- - [Connection status](#connection-status)
24
- - [Error object](#error-object)
25
- - [Example](#example)
26
- - [Progressive/responsive image](#progressiveresponsive-image)
27
- - [Out-of-the-box features](#out-of-the-box-features)
28
- - [Intersection Observer](#intersection-observer)
29
- - [Usage](#usage)
30
- - [Example](#example-1)
31
- - [Props](#props)
32
- - [Layout mode](#layout-mode)
33
- - [The `ResponsiveImage` object](#the-responsiveimage-object)
34
- - [Social share, SEO and Favicon meta tags](#social-share-seo-and-favicon-meta-tags)
35
- - [`renderMetaTags()`](#rendermetatags)
36
- - [`renderMetaTagsToString()`](#rendermetatagstostring)
37
- - [`toRemixMeta()`](#toremixmeta)
38
- - [Structured text](#structured-text)
39
- - [Basic usage](#basic-usage)
40
- - [Custom renderers for inline records, blocks, and links](#custom-renderers-for-inline-records-blocks-and-links)
41
- - [Override default rendering of nodes](#override-default-rendering-of-nodes)
42
- - [Props](#props-1)
43
- - [Development](#development)
44
-
45
- <!-- END doctoc generated TOC please keep comment here to allow auto update -->
46
-
47
- ## Demos
48
-
49
- For fully working examples take a look at our [examples directory](https://github.com/datocms/react-datocms/tree/master/examples).
50
-
51
- Live demo: [https://react-datocms-example.netlify.com/](https://react-datocms-example.netlify.com/)
52
-
53
- ## Installation
13
+ # Installation
54
14
 
55
15
  ```
56
16
  npm install react-datocms
57
17
  ```
58
18
 
59
- # Live real-time updates
60
-
61
- `useQuerySubscription` is a React hook that you can use to implement client-side updates of the page as soon as the content changes. It uses DatoCMS's [Real-time Updates API](https://www.datocms.com/docs/real-time-updates-api/api-reference) to receive the updated query results in real-time, and is able to reconnect in case of network failures.
62
-
63
- Live updates are great both to get instant previews of your content while editing it inside DatoCMS, or to offer real-time updates of content to your visitors (ie. news site).
64
-
65
- - TypeScript ready;
66
- - Compatible with vanilla React, Next.js and pretty much any other React-based solution;
67
-
68
- ## Reference
69
-
70
- Import `useQuerySubscription` from `react-datocms` and use it inside your components like this:
71
-
72
- ```js
73
- const {
74
- data: QueryResult | undefined,
75
- error: ChannelErrorData | null,
76
- status: ConnectionStatus,
77
- } = useQuerySubscription(options: Options);
78
- ```
79
-
80
- ## Initialization options
81
-
82
- | prop | type | required | description | default |
83
- | ------------------ | ----------------------------------------------------------------------------------------- | ------------------ | ------------------------------------------------------------------ | ------------------------------------ |
84
- | enabled | boolean | :x: | Whether the subscription has to be performed or not | true |
85
- | query | string | :white_check_mark: | The GraphQL query to subscribe | |
86
- | token | string | :white_check_mark: | DatoCMS API token to use | |
87
- | variables | Object | :x: | GraphQL variables for the query | |
88
- | preview | boolean | :x: | If true, the Content Delivery API with draft content will be used | false |
89
- | environment | string | :x: | The name of the DatoCMS environment where to perform the query | defaults to primary environment |
90
- | initialData | Object | :x: | The initial data to use on the first render | |
91
- | reconnectionPeriod | number | :x: | In case of network errors, the period (in ms) to wait to reconnect | 1000 |
92
- | fetcher | a [fetch-like function](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) | :x: | The fetch function to use to perform the registration query | window.fetch |
93
- | eventSourceClass | an [EventSource-like](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) class | :x: | The EventSource class to use to open up the SSE connection | window.EventSource |
94
- | baseUrl | string | :x: | The base URL to use to perform the query | `https://graphql-listen.datocms.com` |
95
-
96
- ## Connection status
97
-
98
- The `status` property represents the state of the server-sent events connection. It can be one of the following:
99
-
100
- - `connecting`: the subscription channel is trying to connect
101
- - `connected`: the channel is open, we're receiving live updates
102
- - `closed`: the channel has been permanently closed due to a fatal error (ie. an invalid query)
103
-
104
- ## Error object
105
-
106
- | prop | type | description |
107
- | -------- | ------ | ------------------------------------------------------- |
108
- | code | string | The code of the error (ie. `INVALID_QUERY`) |
109
- | message | string | An human friendly message explaining the error |
110
- | response | Object | The raw response returned by the endpoint, if available |
111
-
112
- ## Example
113
-
114
- ```js
115
- import React from 'react';
116
- import { useQuerySubscription } from 'react-datocms';
117
-
118
- const App: React.FC = () => {
119
- const { status, error, data } = useQuerySubscription({
120
- enabled: true,
121
- query: `
122
- query AppQuery($first: IntType) {
123
- allBlogPosts {
124
- slug
125
- title
126
- }
127
- }`,
128
- variables: { first: 10 },
129
- token: 'YOUR_API_TOKEN',
130
- });
131
-
132
- const statusMessage = {
133
- connecting: 'Connecting to DatoCMS...',
134
- connected: 'Connected to DatoCMS, receiving live updates!',
135
- closed: 'Connection closed',
136
- };
137
-
138
- return (
139
- <div>
140
- <p>Connection status: {statusMessage[status]}</p>
141
- {error && (
142
- <div>
143
- <h1>Error: {error.code}</h1>
144
- <div>{error.message}</div>
145
- {error.response && (
146
- <pre>{JSON.stringify(error.response, null, 2)}</pre>
147
- )}
148
- </div>
149
- )}
150
- {data && (
151
- <ul>
152
- {data.allBlogPosts.map((blogPost) => (
153
- <li key={blogPost.slug}>{blogPost.title}</li>
154
- ))}
155
- </ul>
156
- )}
157
- </div>
158
- );
159
- };
160
- ```
161
-
162
- # Progressive/responsive image
163
-
164
- `<Image />` is a React component specially designed to work seamlessly with DatoCMS’s [`responsiveImage` GraphQL query](https://www.datocms.com/docs/content-delivery-api/uploads#responsive-images) that optimizes image loading for your sites.
165
-
166
- - TypeScript ready;
167
- - CSS-in-JS ready;
168
- - Usable both client and server side;
169
- - Compatible with vanilla React, Next.js and pretty much any other React-based solution;
170
-
171
- ![](docs/image-component.gif?raw=true)
172
-
173
- ## Out-of-the-box features
174
-
175
- - Offers WebP version of images for browsers that support the format
176
- - Generates multiple smaller images so smartphones and tablets don’t download desktop-sized images
177
- - Efficiently lazy loads images to speed initial page load and save bandwidth
178
- - Holds the image position so your page doesn’t jump while images load
179
- - Uses either blur-up or background color techniques to show a preview of the image while it loads
180
-
181
- ## Intersection Observer
182
-
183
- Intersection Observer is the API used to determine if the image is inside the viewport or not. [Browser support is really good](https://caniuse.com/intersectionobserver) - With Safari adding support in 12.1, all major browsers now support Intersection Observers natively.
184
-
185
- If the IntersectionObserver object is not available, the component treats the image as it's always visible in the viewport. Feel free to add a [polyfill](https://www.npmjs.com/package/intersection-observer) so that it will also 100% work on older versions of iOS and IE11.
186
-
187
- ## Usage
188
-
189
- 1. Import `Image` from `react-datocms` and use it in place of the regular `<img />` tag
190
- 2. Write a GraphQL query to your DatoCMS project using the [`responsiveImage` query](https://www.datocms.com/docs/content-delivery-api/images-and-videos#responsive-images)
191
-
192
- The GraphQL query returns multiple thumbnails with optimized compression. The `Image` component automatically sets up the “blur-up” effect as well as lazy loading of images further down the screen.
193
-
194
- ## Example
195
-
196
- For a fully working example take a look at our [examples directory](https://github.com/datocms/react-datocms/tree/master/examples).
197
-
198
- ```js
199
- import React from 'react';
200
- import { Image } from 'react-datocms';
201
-
202
- const Page = ({ data }) => (
203
- <div>
204
- <h1>{data.blogPost.title}</h1>
205
- <Image data={data.blogPost.cover.responsiveImage} />
206
- </div>
207
- );
208
-
209
- const query = gql`
210
- query {
211
- blogPost {
212
- title
213
- cover {
214
- responsiveImage(
215
- imgixParams: { fit: crop, w: 300, h: 300, auto: format }
216
- ) {
217
- # HTML5 src/srcset/sizes attributes
218
- srcSet
219
- webpSrcSet
220
- sizes
221
- src
222
-
223
- # size information (post-transformations)
224
- width
225
- height
226
- aspectRatio
227
-
228
- # SEO attributes
229
- alt
230
- title
231
-
232
- # background color placeholder or...
233
- bgColor
234
-
235
- # blur-up placeholder, JPEG format, base64-encoded
236
- base64
237
- }
238
- }
239
- }
240
- }
241
- `;
242
-
243
- export default withQuery(query)(Page);
244
- ```
245
-
246
- ## Props
247
-
248
- | prop | type | required | description | default |
249
- | --------------------- | ------------------------------------------------ | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
250
- | data | `ResponsiveImage` object | :white_check_mark: | The actual response you get from a DatoCMS `responsiveImage` GraphQL query | |
251
- | layout | 'intrinsic' \| 'fixed' \| 'responsive' \| 'fill' | :x: | The layout behavior of the image as the viewport changes size | "intrinsic" |
252
- | className | string | :x: | Additional CSS className for root node | null |
253
- | style | CSS properties | :x: | Additional CSS rules to add to the root node | null |
254
- | pictureClassName | string | :x: | Additional CSS class for the image inside the inner `<picture />` tag | null |
255
- | pictureStyle | CSS properties | :x: | Additional CSS rules to add to the image inside the inner `<picture />` tag | null |
256
- | fadeInDuration | integer | :x: | Duration (in ms) of the fade-in transition effect upoad image loading | 500 |
257
- | 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 |
258
- | 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" |
259
- | lazyLoad | Boolean | :x: | Whether enable lazy loading or not | true |
260
- | onLoad | () => void | :x: | Function triggered when the image has finished loading | undefined |
261
- | usePlaceholder | Boolean | :x: | Whether the component should use a blurred image placeholder | true |
262
-
263
- ### Layout mode
264
-
265
- With the `layout` property, you can configure the behavior of the image as the viewport changes size:
266
-
267
- - When `intrinsic` (default behaviour), the image will scale the dimensions down for smaller viewports, but maintain the original dimensions for larger viewports.
268
- - When `fixed`, the image dimensions will not change as the viewport changes (no responsiveness) similar to the native `img` element.
269
- - When `responsive`, the image will scale the dimensions down for smaller viewports and scale up for larger viewports.
270
- - When `fill`, the image will stretch both width and height to the dimensions of the parent element, provided the parent element is relative.
271
- - This is usually paired with the `objectFit` and `objectPosition` properties.
272
- - Ensure the parent element has `position: relative` in their stylesheet.
273
-
274
- Example for `layout="fill"` (useful also for background images):
275
-
276
- ```jsx
277
- <div style={{ position: 'relative', width: 200, height: 500 }}>
278
- <Image
279
- data={imageData}
280
- layout="fill"
281
- objectFit="cover"
282
- objectPosition="50% 50%"
283
- />
284
- </div>
285
- ```
286
-
287
- ### The `ResponsiveImage` object
288
-
289
- The `data` prop expects an object with the same shape as the one returned by `responsiveImage` GraphQL call. It's up to you to make a GraphQL query that will return the properties you need for a specific use of the `<Image>` component.
290
-
291
- - The minimum required properties for `data` are: `aspectRatio`, `width`, `sizes`, `srcSet` and `src`;
292
- - `alt` and `title`, while not mandatory, are all highly suggested, so remember to use them!
293
- - You either want to add the `webpSrcSet` field or specify `{ auto: format }` in your `imgixParams`, to automatically use WebP images in browsers that support the format;
294
- - If you provide both the `bgColor` and `base64` property, the latter will take precedence, so just avoiding querying both fields at the same time, it will only make the response bigger :wink:
295
-
296
- Here's a complete recap of what `responsiveImage` offers:
297
-
298
- | property | type | required | description |
299
- | ----------- | ------- | ------------------ | ----------------------------------------------------------------------------------------------- |
300
- | aspectRatio | float | :white_check_mark: | The aspect ratio (width/height) of the image |
301
- | width | integer | :white_check_mark: | The width of the image |
302
- | height | integer | :white_check_mark: | The height of the image |
303
- | sizes | string | :white_check_mark: | The HTML5 `sizes` attribute for the image |
304
- | srcSet | string | :white_check_mark: | The HTML5 `srcSet` attribute for the image |
305
- | src | string | :white_check_mark: | The fallback `src` attribute for the image |
306
- | webpSrcSet | string | :x: | The HTML5 `srcSet` attribute for the image in WebP format, for browsers that support the format |
307
- | alt | string | :x: | Alternate text (`alt`) for the image |
308
- | title | string | :x: | Title attribute (`title`) for the image |
309
- | bgColor | string | :x: | The background color for the image placeholder |
310
- | base64 | string | :x: | A base64-encoded thumbnail to offer during image loading |
311
-
312
- # Social share, SEO and Favicon meta tags
313
-
314
- 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.
315
-
316
- 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):
317
-
318
- - `_seoMetaTags` (always available on any type of record)
319
- - `faviconMetaTags` on the global `_site` object.
320
-
321
- ```graphql
322
- query {
323
- page: homepage {
324
- title
325
- seo: _seoMetaTags {
326
- attributes
327
- content
328
- tag
329
- }
330
- }
331
-
332
- site: _site {
333
- favicon: faviconMetaTags {
334
- attributes
335
- content
336
- tag
337
- }
338
- }
339
- }
340
- ```
341
-
342
- You can then concat those two arrays of tags and pass them togheter to the function, ie:
343
-
344
- ```js
345
- renderMetaTags([...data.page.seo, ...data.site.favicon]);
346
- ```
347
-
348
- ## `renderMetaTags()`
349
-
350
- 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).
351
-
352
- For a complete example take a look at our [examples directory](https://github.com/datocms/react-datocms/tree/master/examples).
353
-
354
- ```js
355
- import React from 'react';
356
- import { renderMetaTags } from 'react-datocms';
357
-
358
- function Page({ data }) {
359
- return (
360
- <div>
361
- <Helmet>
362
- {renderMetaTags([...data.page.seo, ...data.site.favicon])}
363
- </Helmet>
364
- </div>
365
- );
366
- }
367
- ```
368
-
369
- ## `renderMetaTagsToString()`
370
-
371
- This function generates an HTML string containing `<meta>` and `<link />` tags, so it can be used server-side.
372
-
373
- ```js
374
- import { renderMetaTagsToString } from 'react-datocms';
375
-
376
- const someMoreComplexHtml = `
377
- <html>
378
- <head>
379
- ${renderMetaTagsToString([...data.page.seo, ...data.site.favicon])}
380
- </head>
381
- </html>
382
- `;
383
- ```
384
-
385
- ## `toRemixMeta()`
386
-
387
- This function generates a `HtmlMetaDescriptor` object, compatibile with the [`meta`](https://remix.run/docs/en/v1.1.1/api/conventions#meta) export of the [Remix](https://remix.run/) framework:
388
-
389
- ```js
390
- import type { MetaFunction } from 'remix';
391
- import { toRemixMeta } from 'react-datocms';
392
-
393
- export const meta: MetaFunction = ({ data: { post } }) => {
394
- return toRemixMeta(post.seo);
395
- };
396
- ```
397
-
398
- Please note that the [`links`](https://remix.run/docs/en/v1.1.1/api/conventions#links) export [doesn't receive any loader data](https://github.com/remix-run/remix/issues/32) for performance reasons, so you cannot use it to declare favicons meta tags! The best way to render them is using `renderMetaTags` in your root component:
399
-
400
- ```jsx
401
- import { renderMetaTags } from 'react-datocms';
402
-
403
- export const loader = () => {
404
- return request({
405
- query: `
406
- {
407
- site: _site {
408
- favicon: faviconMetaTags(variants: [icon, msApplication, appleTouchIcon]) {
409
- ...metaTagsFragment
410
- }
411
- }
412
- }
413
- ${metaTagsFragment}
414
- `,
415
- });
416
- };
417
-
418
- export default function App() {
419
- const { site } = useLoaderData();
420
-
421
- return (
422
- <html lang="en">
423
- <head>
424
- <meta charSet="utf-8" />
425
- <meta name="viewport" content="width=device-width,initial-scale=1" />
426
- <Meta />
427
- <Links />
428
- {renderMetaTags(site.favicon)}
429
- </head>
430
- <body>
431
- <Outlet />
432
- <ScrollRestoration />
433
- <Scripts />
434
- {process.env.NODE_ENV === 'development' && <LiveReload />}
435
- </body>
436
- </html>
437
- );
438
- }
439
- ```
440
-
441
- # Structured text
442
-
443
- `<StructuredText />` is a React component that you can use to render the value contained inside a DatoCMS [Structured Text field type](https://www.datocms.com/docs/structured-text/dast).
444
-
445
- ## Basic usage
446
-
447
- ```js
448
- import React from 'react';
449
- import { StructuredText } from 'react-datocms';
450
-
451
- const Page = ({ data }) => {
452
- // data.blogPost.content = {
453
- // value: {
454
- // schema: "dast",
455
- // document: {
456
- // type: "root",
457
- // children: [
458
- // {
459
- // type: "heading",
460
- // level: 1,
461
- // children: [
462
- // {
463
- // type: "span",
464
- // value: "Hello ",
465
- // },
466
- // {
467
- // type: "span",
468
- // marks: ["strong"],
469
- // value: "world!",
470
- // },
471
- // ],
472
- // },
473
- // ],
474
- // },
475
- // },
476
- // }
477
-
478
- return (
479
- <div>
480
- <h1>{data.blogPost.title}</h1>
481
- <StructuredText data={data.blogPost.content} />
482
- {/* -> <h1>Hello <strong>world!</strong></h1> */}
483
- </div>
484
- );
485
- };
486
-
487
- const query = gql`
488
- query {
489
- blogPost {
490
- title
491
- content {
492
- value
493
- }
494
- }
495
- }
496
- `;
497
-
498
- export default withQuery(query)(Page);
499
- ```
500
-
501
- ## Custom renderers for inline records, blocks, and links
502
-
503
- You can also pass custom renderers for special nodes (inline records, record links and blocks) as an optional parameter like so:
504
-
505
- ```js
506
- import React from 'react';
507
- import { StructuredText, Image } from 'react-datocms';
508
-
509
- const Page = ({ data }) => {
510
- // data.blogPost.content ->
511
- // {
512
- // value: {
513
- // schema: "dast",
514
- // document: {
515
- // type: "root",
516
- // children: [
517
- // {
518
- // type: "heading",
519
- // level: 1,
520
- // children: [
521
- // { type: "span", value: "Welcome onboard " },
522
- // { type: "inlineItem", item: "324321" },
523
- // ],
524
- // },
525
- // {
526
- // type: "paragraph",
527
- // children: [
528
- // { type: "span", value: "So happy to have " },
529
- // {
530
- // type: "itemLink",
531
- // item: "324321",
532
- // children: [
533
- // {
534
- // type: "span",
535
- // marks: ["strong"],
536
- // value: "this awesome humang being",
537
- // },
538
- // ]
539
- // },
540
- // { type: "span", value: " in our team!" },
541
- // ]
542
- // },
543
- // { type: "block", item: "1984559" }
544
- // ],
545
- // },
546
- // },
547
- // links: [
548
- // {
549
- // id: "324321",
550
- // __typename: "TeamMemberRecord",
551
- // firstName: "Mark",
552
- // slug: "mark-smith",
553
- // },
554
- // ],
555
- // blocks: [
556
- // {
557
- // id: "324321",
558
- // __typename: "ImageRecord",
559
- // image: {
560
- // responsiveImage: { ... },
561
- // },
562
- // },
563
- // ],
564
- // }
565
-
566
- return (
567
- <div>
568
- <h1>{data.blogPost.title}</h1>
569
- <StructuredText
570
- data={data.blogPost.content}
571
- renderInlineRecord={({ record }) => {
572
- switch (record.__typename) {
573
- case 'TeamMemberRecord':
574
- return <a href={`/team/${record.slug}`}>{record.firstName}</a>;
575
- default:
576
- return null;
577
- }
578
- }}
579
- renderLinkToRecord={({ record, children, transformedMeta }) => {
580
- switch (record.__typename) {
581
- case 'TeamMemberRecord':
582
- return (
583
- <a {...transformedMeta} href={`/team/${record.slug}`}>
584
- {children}
585
- </a>
586
- );
587
- default:
588
- return null;
589
- }
590
- }}
591
- renderBlock={({ record }) => {
592
- switch (record.__typename) {
593
- case 'ImageRecord':
594
- return <Image data={record.image.responsiveImage} />;
595
- default:
596
- return null;
597
- }
598
- }}
599
- />
600
- {/*
601
- Final result:
602
-
603
- <h1>Welcome onboard <a href="/team/mark-smith">Mark</a></h1>
604
- <p>So happy to have <a href="/team/mark-smith">this awesome humang being</a> in our team!</p>
605
- <img src="https://www.datocms-assets.com/205/1597757278-austin-distel-wd1lrb9oeeo-unsplash.jpg" alt="Our team at work" />
606
- */}
607
- </div>
608
- );
609
- };
610
-
611
- const query = gql`
612
- query {
613
- blogPost {
614
- title
615
- content {
616
- value
617
- links {
618
- __typename
619
- ... on TeamMemberRecord {
620
- id
621
- firstName
622
- slug
623
- }
624
- }
625
- blocks {
626
- __typename
627
- ... on ImageRecord {
628
- id
629
- image {
630
- responsiveImage(
631
- imgixParams: { fit: crop, w: 300, h: 300, auto: format }
632
- ) {
633
- srcSet
634
- webpSrcSet
635
- sizes
636
- src
637
- width
638
- height
639
- aspectRatio
640
- alt
641
- title
642
- base64
643
- }
644
- }
645
- }
646
- }
647
- }
648
- }
649
- }
650
- `;
651
-
652
- export default withQuery(query)(Page);
653
- ```
654
-
655
- ## Override default rendering of nodes
656
-
657
- This component automatically renders all nodes except for `inline_item`, `item_link` and `block` using a set of default rules, but you might want to customize those. For example:
658
-
659
- For example:
660
-
661
- - For `heading` nodes, you might want to add an anchor;
662
- - For `code` nodes, you might want to use a custom sytax highlighting component like [`prism-react-renderer`](https://github.com/FormidableLabs/prism-react-renderer);
663
- - Apply different logic/formatting to a node based on what its parent node is (using the `ancestors` parameter)
664
-
665
- - For all possible node types, refer to the [list of typeguard functions defined in the main `structured-text` package](https://github.com/datocms/structured-text/tree/main/packages/utils#typescript-type-guards). The [DAST format documentation](https://www.datocms.com/docs/structured-text/dast) has additional details.
19
+ # Documentation
666
20
 
667
- In this case, you can easily override default rendering rules with the `customNodeRules` and `customMarkRules` props.
21
+ This package offers different components and hooks. Please refer to one of the following pages to learn more about a specific area of interest:
668
22
 
669
- ```jsx
670
- import { renderNodeRule, renderMarkRule, StructuredText } from 'react-datocms';
671
- import { isHeading, isCode } from 'datocms-structured-text-utils';
672
- import { render as toPlainText } from 'datocms-structured-text-to-plain-text';
673
- import SyntaxHighlight from 'components/SyntaxHighlight';
23
+ * [`<Image />` component for responsive/progressive images](./docs/image.md)
24
+ * [`<StructuredText />` component](./docs/structured-text.md)
25
+ * [`useQuerySubscription()` hook for live, real-time updates of content](./docs/live-real-time-updates.md)
26
+ * [`useSiteSearch()` hook to render a DatoCMS Site Search form widget](./docs/site-search.md)
27
+ * [`renderMetaTags()` and other helpers to render social share, SEO and Favicon meta tags](./docs/meta-tags.md)
674
28
 
675
- <StructuredText
676
- data={data.blogPost.content}
677
- customNodeRules={[
678
- // Add HTML anchors to heading levels for in-page navigation
679
- renderNodeRule(isHeading, ({ node, children, key }) => {
680
- const HeadingTag = `h${node.level}`;
681
- const anchor = toPlainText(node)
682
- .toLowerCase()
683
- .replace(/ /g, '-')
684
- .replace(/[^\w-]+/g, '');
29
+ # Demos
685
30
 
686
- return (
687
- <HeadingTag key={key}>
688
- {children} <a id={anchor} />
689
- <a href={`#${anchor}`} />
690
- </HeadingTag>
691
- );
692
- }),
693
-
694
- // Use a custom syntax highlighter component for code blocks
695
- renderNodeRule(isCode, ({ node, key }) => {
696
- return (
697
- <SyntaxHighlight
698
- key={key}
699
- code={node.code}
700
- language={node.language}
701
- linesToBeHighlighted={node.highlight}
702
- />
703
- );
704
- }),
705
-
706
- // Apply different formatting to top-level paragraphs
707
- renderNodeRule(
708
- isParagraph,
709
- ({ adapter: { renderNode }, node, children, key, ancestors }) => {
710
- if (isRoot(ancestors[0])) {
711
- // If this paragraph node is a top-level one, give it a special class
712
- return renderNode(
713
- 'p',
714
- { key, className: 'top-level-paragraph-container-example' },
715
- children,
716
- );
717
- } else {
718
- // Proceed with default paragraph rendering...
719
- // return renderNode('p', { key }, children);
720
-
721
- // Or even completely remove the paragraph and directly render the inner children:
722
- return children;
723
- }
724
- },
725
- ),
726
- ]}
727
- customMarkRules={[
728
- // convert "strong" marks into <b> tags
729
- renderMarkRule('strong', ({ mark, children, key }) => {
730
- return <b key={key}>{children}</b>;
731
- }),
732
- ]}
733
- />;
734
- ```
735
-
736
- Note: if you override the rules for `inline_item`, `item_link` or `block` nodes, then the `renderInlineRecord`, `renderLinkToRecord` and `renderBlock` props won't be considered!
737
-
738
- ## Props
31
+ For fully working examples take a look at our [examples directory](https://github.com/datocms/react-datocms/tree/master/examples).
739
32
 
740
- | prop | type | required | description | default |
741
- | ------------------ | --------------------------------------------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
742
- | data | `StructuredTextGraphQlResponse \| DastNode` | :white_check_mark: | The actual [field value](https://www.datocms.com/docs/structured-text/dast) you get from DatoCMS | |
743
- | renderInlineRecord | `({ record }) => ReactElement \| null` | Only required if document contains `inlineItem` nodes | Convert an `inlineItem` DAST node into React | `[]` |
744
- | renderLinkToRecord | `({ record, children }) => ReactElement \| null` | Only required if document contains `itemLink` nodes | Convert an `itemLink` DAST node into React | `null` |
745
- | renderBlock | `({ record }) => ReactElement \| null` | Only required if document contains `block` nodes | Convert a `block` DAST node into React | `null` |
746
- | 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) |
747
- | customNodeRules | `Array<RenderRule>` | :x: | Customize how nodes are converted in JSX (use `renderNodeRule()` to generate rules) | `null` |
748
- | customMarkRules | `Array<RenderMarkRule>` | :x: | Customize how marks are converted in JSX (use `renderMarkRule()` to generate rules) | `null` |
749
- | renderText | `(text: string, key: string) => ReactElement \| string \| null` | :x: | Convert a simple string text into React | `(text) => text` |
33
+ Live demo: [https://react-datocms-example.netlify.com/](https://react-datocms-example.netlify.com/)
750
34
 
751
35
  # Development
752
36