@datocms/astro 0.1.13 → 0.2.1
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 +50 -38
- package/package.json +63 -50
- package/src/Image/Image.astro +14 -22
- package/src/Image/README.md +124 -0
- package/src/Image/buildSrcSet.ts +9 -16
- package/src/Image/index.ts +3 -1
- package/src/Image/types.ts +2 -2
- package/src/QueryListener/QueryListener.astro +56 -0
- package/src/QueryListener/README.md +67 -0
- package/src/QueryListener/index.ts +4 -0
- package/src/QueryListener/types.ts +12 -0
- package/src/Seo/README.md +57 -0
- package/src/Seo/Seo.astro +2 -2
- package/src/Seo/index.ts +3 -3
- package/src/Seo/renderMetaTagsToString.tsx +1 -3
- package/src/Seo/types.ts +9 -20
- package/src/StructuredText/Node.astro +15 -26
- package/src/StructuredText/README.md +42 -96
- package/src/StructuredText/StructuredText.astro +4 -6
- package/src/StructuredText/index.ts +2 -2
- package/src/StructuredText/nodes/Blockquote.astro +1 -1
- package/src/StructuredText/nodes/Code.astro +3 -3
- package/src/StructuredText/nodes/Heading.astro +1 -1
- package/src/StructuredText/nodes/Link.astro +3 -3
- package/src/StructuredText/nodes/List.astro +2 -2
- package/src/StructuredText/nodes/ListItem.astro +1 -1
- package/src/StructuredText/nodes/Paragraph.astro +1 -1
- package/src/StructuredText/nodes/Root.astro +1 -1
- package/src/StructuredText/nodes/Span.astro +8 -8
- package/src/StructuredText/nodes/ThematicBreak.astro +1 -1
- package/src/StructuredText/types.ts +1 -1
- package/src/StructuredText/utils.ts +71 -73
- package/src/index.ts +4 -0
- package/src/VideoPlayer/VideoPlayer.astro +0 -30
- package/src/VideoPlayer/index.ts +0 -2
- package/src/VideoPlayer/types.ts +0 -72
- package/src/VideoPlayer/utils.ts +0 -50
- package/src/useVideoPlayer/index.ts +0 -55
package/README.md
CHANGED
|
@@ -1,54 +1,66 @@
|
|
|
1
|
-
|
|
1
|
+
<!--datocms-autoinclude-header start-->
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
<a href="https://www.datocms.com/"><img src="https://www.datocms.com/images/full_logo.svg" height="60"></a>
|
|
4
|
+
|
|
5
|
+
👉 [Visit the DatoCMS homepage](https://www.datocms.com) or see [What is DatoCMS?](#what-is-datocms)
|
|
6
|
+
|
|
7
|
+
<!--datocms-autoinclude-header end-->
|
|
8
|
+
|
|
9
|
+
# @datocms/astro
|
|
10
|
+
|
|
11
|
+
[](https://github.com/datocms/astro-datocms/blob/master/LICENSE) [](https://www.npmjs.com/package/@datocms/astro)
|
|
12
|
+
|
|
13
|
+
A set of TypeScript-ready components and utilities to work faster with [DatoCMS](https://www.datocms.com/) in Astro project. Integrates seamlessly with [DatoCMS's GraphQL Content Delivery API](https://www.datocms.com/docs/content-delivery-api).
|
|
6
14
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
[](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/basics/devcontainer.json)
|
|
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 -->
|
|
10
17
|
|
|
11
|
-
|
|
18
|
+
- [Features](#features)
|
|
19
|
+
- [Installation](#installation)
|
|
20
|
+
- [What is DatoCMS?](#what-is-datocms)
|
|
12
21
|
|
|
13
|
-
|
|
22
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
14
23
|
|
|
15
|
-
##
|
|
24
|
+
## Features
|
|
16
25
|
|
|
17
|
-
|
|
26
|
+
`@datocms/astro` contains ready-to-use Astro components and helpers:
|
|
18
27
|
|
|
19
|
-
|
|
20
|
-
/
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
│ └── pages/
|
|
29
|
-
│ └── index.astro
|
|
30
|
-
└── package.json
|
|
28
|
+
- [`<Image />`](src/Image)
|
|
29
|
+
- [`<Seo />`](src/Seo)
|
|
30
|
+
- [`<StructuredText />`](src/StructuredText)
|
|
31
|
+
- [`<QueryListener />`](src/QueryListener)
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
npm install @datocms/astro
|
|
31
37
|
```
|
|
32
38
|
|
|
33
|
-
|
|
39
|
+
<!--datocms-autoinclude-footer start-->
|
|
40
|
+
|
|
41
|
+
# What is DatoCMS?
|
|
42
|
+
|
|
43
|
+
<a href="https://www.datocms.com/"><img src="https://www.datocms.com/images/full_logo.svg" height="60"></a>
|
|
44
|
+
|
|
45
|
+
[DatoCMS](https://www.datocms.com/) is the REST & GraphQL Headless CMS for the modern web.
|
|
34
46
|
|
|
35
|
-
|
|
47
|
+
Trusted by over 25,000 enterprise businesses, agency partners, and individuals across the world, DatoCMS users create online content at scale from a central hub and distribute it via API. We ❤️ our [developers](https://www.datocms.com/team/best-cms-for-developers), [content editors](https://www.datocms.com/team/content-creators) and [marketers](https://www.datocms.com/team/cms-digital-marketing)!
|
|
36
48
|
|
|
37
|
-
|
|
49
|
+
**Quick links:**
|
|
38
50
|
|
|
39
|
-
|
|
51
|
+
- ⚡️ Get started with a [free DatoCMS account](https://dashboard.datocms.com/signup)
|
|
52
|
+
- 🔖 Go through the [docs](https://www.datocms.com/docs)
|
|
53
|
+
- ⚙️ Get [support from us and the community](https://community.datocms.com/)
|
|
54
|
+
- 🆕 Stay up to date on new features and fixes on the [changelog](https://www.datocms.com/product-updates)
|
|
40
55
|
|
|
41
|
-
|
|
56
|
+
**Our featured repos:**
|
|
42
57
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
| `npm run preview` | Preview your build locally, before deploying |
|
|
49
|
-
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
|
50
|
-
| `npm run astro -- --help` | Get help using the Astro CLI |
|
|
58
|
+
- [datocms/react-datocms](https://github.com/datocms/react-datocms): React helper components for images, Structured Text rendering, and more
|
|
59
|
+
- [datocms/js-rest-api-clients](https://github.com/datocms/js-rest-api-clients): Node and browser JavaScript clients for updating and administering your content. For frontend fetches, we recommend using our [GraphQL Content Delivery API](https://www.datocms.com/docs/content-delivery-api) instead.
|
|
60
|
+
- [datocms/cli](https://github.com/datocms/cli): Command-line interface that includes our [Contentful importer](https://github.com/datocms/cli/tree/main/packages/cli-plugin-contentful) and [Wordpress importer](https://github.com/datocms/cli/tree/main/packages/cli-plugin-wordpress)
|
|
61
|
+
- [datocms/plugins](https://github.com/datocms/plugins): Example plugins we've made that extend the editor/admin dashboard
|
|
62
|
+
- [DatoCMS Starters](https://www.datocms.com/marketplace/starters) has examples for various Javascript frontend frameworks
|
|
51
63
|
|
|
52
|
-
|
|
64
|
+
Or see [all our public repos](https://github.com/orgs/datocms/repositories?q=&type=public&language=&sort=stargazers)
|
|
53
65
|
|
|
54
|
-
|
|
66
|
+
<!--datocms-autoinclude-footer end-->
|
package/package.json
CHANGED
|
@@ -1,52 +1,65 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
2
|
+
"name": "@datocms/astro",
|
|
3
|
+
"description": "A set of components and utilities to work faster with DatoCMS in Astro projects.",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"version": "0.2.1",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git://github.com/datocms/astro-datocms.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/datocms/astro-datocms",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"author": "Stefano Verna <s.verna@datocms.com>",
|
|
14
|
+
"contributors": [
|
|
15
|
+
"Silvano Stralla <silvano@datocms.com>"
|
|
16
|
+
],
|
|
17
|
+
"keywords": [
|
|
18
|
+
"astro",
|
|
19
|
+
"withastro",
|
|
20
|
+
"astro-component",
|
|
21
|
+
"datocms",
|
|
22
|
+
"typescript",
|
|
23
|
+
"ui"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"prepare": "npx simple-git-hooks",
|
|
27
|
+
"lint": "prettier --check .",
|
|
28
|
+
"format": "npm run toc && npx prettier . --write",
|
|
29
|
+
"toc": "doctoc --github README.md src",
|
|
30
|
+
"test": "echo 1"
|
|
31
|
+
},
|
|
32
|
+
"exports": {
|
|
33
|
+
".": "./src/index.ts",
|
|
34
|
+
"./Image": "./src/Image/index.ts",
|
|
35
|
+
"./StructuredText": "./src/StructuredText/index.ts",
|
|
36
|
+
"./Seo": "./src/Seo/index.ts",
|
|
37
|
+
"./QueryListener": "./src/QueryListener/index.ts"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=18.0.0"
|
|
41
|
+
},
|
|
42
|
+
"files": [
|
|
43
|
+
"src"
|
|
44
|
+
],
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@0no-co/graphql.web": "^1.0.7",
|
|
47
|
+
"datocms-listen": "^1.0.0",
|
|
48
|
+
"datocms-structured-text-utils": "^4.0.1"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"astro": "*"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"astro": "^4.13.1",
|
|
55
|
+
"doctoc": "^2.2.1",
|
|
56
|
+
"np": "^10.0.7",
|
|
57
|
+
"prettier": "^3.3.3",
|
|
58
|
+
"prettier-plugin-astro": "^0.14.1",
|
|
59
|
+
"simple-git-hooks": "^2.11.1",
|
|
60
|
+
"typescript": "^5.5.4"
|
|
61
|
+
},
|
|
62
|
+
"simple-git-hooks": {
|
|
63
|
+
"pre-commit": "npm run format"
|
|
64
|
+
}
|
|
52
65
|
}
|
package/src/Image/Image.astro
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
2
|
import { buildSrcSet } from './buildSrcSet';
|
|
4
3
|
import type { ImageProps } from './types';
|
|
5
4
|
|
|
6
|
-
interface Props extends ImageProps {}
|
|
5
|
+
interface Props extends ImageProps {}
|
|
7
6
|
|
|
8
7
|
const {
|
|
9
8
|
data,
|
|
@@ -21,52 +20,45 @@ const placeholderStyle =
|
|
|
21
20
|
usePlaceholder && data.base64
|
|
22
21
|
? {
|
|
23
22
|
backgroundImage: `url("${data.base64}")`,
|
|
24
|
-
backgroundSize:
|
|
25
|
-
backgroundRepeat:
|
|
26
|
-
backgroundPosition:
|
|
27
|
-
color:
|
|
23
|
+
backgroundSize: 'cover',
|
|
24
|
+
backgroundRepeat: 'no-repeat',
|
|
25
|
+
backgroundPosition: '50% 50%',
|
|
26
|
+
color: 'transparent',
|
|
28
27
|
}
|
|
29
28
|
: usePlaceholder && data.bgColor
|
|
30
|
-
? { backgroundColor: data.bgColor ?? undefined, color:
|
|
29
|
+
? { backgroundColor: data.bgColor ?? undefined, color: 'transparent' }
|
|
31
30
|
: undefined;
|
|
32
31
|
|
|
33
32
|
const { width } = data;
|
|
34
33
|
|
|
35
|
-
const height =
|
|
36
|
-
data.height ?? Math.round(data.aspectRatio ? width / data.aspectRatio : 0);
|
|
34
|
+
const height = data.height ?? Math.round(data.aspectRatio ? width / data.aspectRatio : 0);
|
|
37
35
|
|
|
38
36
|
const sizingStyle = {
|
|
39
37
|
aspectRatio: `${width} / ${height}`,
|
|
40
|
-
width:
|
|
38
|
+
width: '100%',
|
|
41
39
|
maxWidth: `${width}px`,
|
|
42
|
-
height:
|
|
40
|
+
height: 'auto',
|
|
43
41
|
};
|
|
44
42
|
---
|
|
45
43
|
|
|
46
44
|
<picture class={pictureClass} style={pictureStyle}>
|
|
47
45
|
{
|
|
48
46
|
data.webpSrcSet && (
|
|
49
|
-
<source
|
|
50
|
-
srcset={data.webpSrcSet}
|
|
51
|
-
sizes={sizes ?? data.sizes ?? null}
|
|
52
|
-
type="image/webp"
|
|
53
|
-
/>
|
|
47
|
+
<source srcset={data.webpSrcSet} sizes={sizes ?? data.sizes ?? null} type="image/webp" />
|
|
54
48
|
)
|
|
55
49
|
}
|
|
56
50
|
<source
|
|
57
|
-
srcset={data.srcSet ??
|
|
58
|
-
buildSrcSet(data.src, data.width, srcSetCandidates) ??
|
|
59
|
-
null}
|
|
51
|
+
srcset={data.srcSet ?? buildSrcSet(data.src, data.width, srcSetCandidates) ?? null}
|
|
60
52
|
sizes={sizes ?? data.sizes ?? null}
|
|
61
53
|
/>
|
|
62
54
|
{
|
|
63
55
|
data.src && (
|
|
64
56
|
<img
|
|
65
57
|
src={data.src}
|
|
66
|
-
alt={data.alt ??
|
|
58
|
+
alt={data.alt ?? ''}
|
|
67
59
|
title={data.title ?? null}
|
|
68
|
-
fetchpriority={priority ?
|
|
69
|
-
loading={priority ? undefined :
|
|
60
|
+
fetchpriority={priority ? 'high' : undefined}
|
|
61
|
+
loading={priority ? undefined : 'lazy'}
|
|
70
62
|
class={imgClass}
|
|
71
63
|
style={{
|
|
72
64
|
...placeholderStyle,
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# Progressive responsive image
|
|
2
|
+
|
|
3
|
+
`<Image>` is a TypeScript-ready Astro component specially designed to work seamlessly with DatoCMS’s [`responsiveImage` GraphQL query](https://www.datocms.com/docs/content-delivery-api/uploads#responsive-images) which optimizes image loading for your websites.
|
|
4
|
+
|
|
5
|
+
### Out-of-the-box features
|
|
6
|
+
|
|
7
|
+
- Completely native, with no JavaScript footprint
|
|
8
|
+
- Offers optimized version of images for browsers that support WebP/AVIF format
|
|
9
|
+
- Generates multiple smaller images so smartphones and tablets don’t download desktop-sized images
|
|
10
|
+
- Efficiently lazy loads images to speed initial page load and save bandwidth
|
|
11
|
+
- Holds the image position so your page doesn’t jump while images load
|
|
12
|
+
- Uses either blur-up or background color techniques to show a preview of the image while it loads
|
|
13
|
+
|
|
14
|
+
### Table of contents
|
|
15
|
+
|
|
16
|
+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
17
|
+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
18
|
+
|
|
19
|
+
- [Setup](#setup)
|
|
20
|
+
- [Usage](#usage)
|
|
21
|
+
- [Example](#example)
|
|
22
|
+
- [The `ResponsiveImage` object](#the-responsiveimage-object)
|
|
23
|
+
- [`<Image />`](#image-)
|
|
24
|
+
- [Props](#props)
|
|
25
|
+
|
|
26
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
27
|
+
|
|
28
|
+
### Setup
|
|
29
|
+
|
|
30
|
+
You can import the component like this:
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
import { Image } from '@datocms/astro/Image';
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
1. Use `<Image>` in place of the regular `<img />` tag
|
|
39
|
+
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)
|
|
40
|
+
|
|
41
|
+
The GraphQL query returns multiple thumbnails with optimized compression. The components automatically set up the "blur-up" effect as well as lazy loading of images further down the screen.
|
|
42
|
+
|
|
43
|
+
## Example
|
|
44
|
+
|
|
45
|
+
Here is a minimal starting point:
|
|
46
|
+
|
|
47
|
+
```astro
|
|
48
|
+
---
|
|
49
|
+
import { Image } from '@datocms/astro/Image';
|
|
50
|
+
import { executeQuery } from '@datocms/cda-client';
|
|
51
|
+
|
|
52
|
+
const query = gql`
|
|
53
|
+
query {
|
|
54
|
+
blogPost {
|
|
55
|
+
title
|
|
56
|
+
cover {
|
|
57
|
+
responsiveImage(imgixParams: { fit: crop, w: 300, h: 300, auto: format }) {
|
|
58
|
+
# always required
|
|
59
|
+
src
|
|
60
|
+
width
|
|
61
|
+
height
|
|
62
|
+
# not required, but strongly suggested!
|
|
63
|
+
alt
|
|
64
|
+
title
|
|
65
|
+
# blur-up placeholder, JPEG format, base64-encoded, or...
|
|
66
|
+
base64
|
|
67
|
+
# background color placeholder
|
|
68
|
+
bgColor
|
|
69
|
+
# you can omit sizes if you explicitly pass the sizes prop to the image component
|
|
70
|
+
sizes
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
`;
|
|
76
|
+
|
|
77
|
+
const { blogPost } = await executeQuery(query, { token: '<YOUR-API-TOKEN>' });
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
<Image data={blogPost.cover.responsiveImage} />
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## The `ResponsiveImage` object
|
|
84
|
+
|
|
85
|
+
The `data` prop of both components 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.
|
|
86
|
+
|
|
87
|
+
- The minimum required properties for `data` are: `src`, `width` and `height`;
|
|
88
|
+
- `alt` and `title`, while not mandatory, are all highly suggested, so remember to use them!
|
|
89
|
+
- If you don't request `srcSet`, the component will auto-generate an `srcset` based on `src` + the `srcSetCandidates` prop (it can help reducing the GraphQL response size drammatically when many images are returned);
|
|
90
|
+
- We strongly to suggest to always specify [`{ auto: format }`](https://docs.imgix.com/apis/rendering/auto/auto#format) in your `imgixParams`, instead of requesting `webpSrcSet`, so that you can also take advantage of more performant optimizations (AVIF), without increasing GraphQL response size;
|
|
91
|
+
- If you request both the `bgColor` and `base64` property, the latter will take precedence, so just avoid querying both fields at the same time, as it will only make the GraphQL response bigger :wink:;
|
|
92
|
+
- You can avoid requesting `sizes` and directly pass a `sizes` prop to the component to reduce the GraphQL response size;
|
|
93
|
+
|
|
94
|
+
Here's a complete recap of what `responsiveImage` offers:
|
|
95
|
+
|
|
96
|
+
| property | type | required | description |
|
|
97
|
+
| ----------- | ------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
98
|
+
| src | string | :white_check_mark: | The `src` attribute for the image |
|
|
99
|
+
| width | integer | :white_check_mark: | The width of the image |
|
|
100
|
+
| height | integer | :white_check_mark: | The height of the image |
|
|
101
|
+
| alt | string | :x: | Alternate text (`alt`) for the image (not required, but strongly suggested!) |
|
|
102
|
+
| title | string | :x: | Title attribute (`title`) for the image (not required, but strongly suggested!) |
|
|
103
|
+
| sizes | string | :x: | The HTML5 `sizes` attribute for the image (omit it if you're already passing a `sizes` prop to the Image component) |
|
|
104
|
+
| base64 | string | :x: | A base64-encoded thumbnail to offer during image loading |
|
|
105
|
+
| bgColor | string | :x: | The background color for the image placeholder (omit it if you're already requesting `base64`) |
|
|
106
|
+
| srcSet | string | :x: | The HTML5 `srcSet` attribute for the image (can be omitted, the Image component knows how to build it based on `src`) |
|
|
107
|
+
| webpSrcSet | string | :x: | The HTML5 `srcSet` attribute for the image in WebP format (deprecated, it's better to use the [`auto=format`](https://docs.imgix.com/apis/rendering/auto/auto#format) Imgix transform instead) |
|
|
108
|
+
| aspectRatio | float | :x: | The aspect ratio (width/height) of the image |
|
|
109
|
+
|
|
110
|
+
## `<Image />`
|
|
111
|
+
|
|
112
|
+
### Props
|
|
113
|
+
|
|
114
|
+
| prop | type | default | required | description |
|
|
115
|
+
| ---------------- | ------------------------ | ---------------------------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
116
|
+
| data | `ResponsiveImage` object | | :white_check_mark: | The actual response you get from a DatoCMS `responsiveImage` GraphQL query \*\*\*\* |
|
|
117
|
+
| pictureClass | string | null | :x: | Additional CSS class for the root `<picture>` tag |
|
|
118
|
+
| pictureStyle | CSS properties | null | :x: | Additional CSS rules to add to the root `<picture>` tag |
|
|
119
|
+
| imgClass | string | null | :x: | Additional CSS class for the `<img>` tag |
|
|
120
|
+
| imgStyle | CSS properties | null | :x: | Additional CSS rules to add to the `<img>` tag |
|
|
121
|
+
| priority | Boolean | false | :x: | Disables lazy loading, and sets the image [fetchPriority](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/fetchPriority) to "high" |
|
|
122
|
+
| sizes | string | undefined | :x: | The HTML5 [`sizes`](https://web.dev/learn/design/responsive-images/#sizes) attribute for the image (will be used `data.sizes` as a fallback) |
|
|
123
|
+
| usePlaceholder | Boolean | true | :x: | Whether the image should use a blurred image placeholder |
|
|
124
|
+
| srcSetCandidates | Array<number> | [0.25, 0.5, 0.75, 1, 1.5, 2, 3, 4] | :x: | If `data` does not contain `srcSet`, the candidates for the `srcset` attribute of the image will be auto-generated based on these width multipliers |
|
package/src/Image/buildSrcSet.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
const bogusBaseUrl = "https://example.com/";
|
|
1
|
+
const bogusBaseUrl = 'https://example.com/';
|
|
3
2
|
|
|
4
3
|
export const buildSrcSet = (
|
|
5
4
|
src: string | null | undefined,
|
|
6
5
|
width: number | undefined,
|
|
7
|
-
candidateMultipliers: number[]
|
|
6
|
+
candidateMultipliers: number[],
|
|
8
7
|
) => {
|
|
9
8
|
if (!(src && width)) {
|
|
10
9
|
return undefined;
|
|
@@ -15,20 +14,14 @@ export const buildSrcSet = (
|
|
|
15
14
|
const url = new URL(src, bogusBaseUrl);
|
|
16
15
|
|
|
17
16
|
if (multiplier !== 1) {
|
|
18
|
-
url.searchParams.set(
|
|
19
|
-
const maxH = url.searchParams.get(
|
|
20
|
-
const maxW = url.searchParams.get(
|
|
17
|
+
url.searchParams.set('dpr', `${multiplier}`);
|
|
18
|
+
const maxH = url.searchParams.get('max-h');
|
|
19
|
+
const maxW = url.searchParams.get('max-w');
|
|
21
20
|
if (maxH) {
|
|
22
|
-
url.searchParams.set(
|
|
23
|
-
"max-h",
|
|
24
|
-
`${Math.floor(Number.parseInt(maxH) * multiplier)}`
|
|
25
|
-
);
|
|
21
|
+
url.searchParams.set('max-h', `${Math.floor(Number.parseInt(maxH) * multiplier)}`);
|
|
26
22
|
}
|
|
27
23
|
if (maxW) {
|
|
28
|
-
url.searchParams.set(
|
|
29
|
-
"max-w",
|
|
30
|
-
`${Math.floor(Number.parseInt(maxW) * multiplier)}`
|
|
31
|
-
);
|
|
24
|
+
url.searchParams.set('max-w', `${Math.floor(Number.parseInt(maxW) * multiplier)}`);
|
|
32
25
|
}
|
|
33
26
|
}
|
|
34
27
|
|
|
@@ -38,8 +31,8 @@ export const buildSrcSet = (
|
|
|
38
31
|
return null;
|
|
39
32
|
}
|
|
40
33
|
|
|
41
|
-
return `${url.toString().replace(bogusBaseUrl,
|
|
34
|
+
return `${url.toString().replace(bogusBaseUrl, '/')} ${finalWidth}w`;
|
|
42
35
|
})
|
|
43
36
|
.filter(Boolean)
|
|
44
|
-
.join(
|
|
37
|
+
.join(',');
|
|
45
38
|
};
|
package/src/Image/index.ts
CHANGED
package/src/Image/types.ts
CHANGED
|
@@ -56,11 +56,11 @@ export type ImageProps = {
|
|
|
56
56
|
* -> https://web.dev/learn/design/responsive-images/#sizes
|
|
57
57
|
* -> https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-sizes
|
|
58
58
|
**/
|
|
59
|
-
sizes?: HTMLImageElement[
|
|
59
|
+
sizes?: HTMLImageElement['sizes'];
|
|
60
60
|
/**
|
|
61
61
|
* If `data` does not contain `srcSet`, the candidates for the `srcset` of the image will be auto-generated based on these width multipliers
|
|
62
62
|
*
|
|
63
63
|
* Default candidate multipliers are [0.25, 0.5, 0.75, 1, 1.5, 2, 3, 4]
|
|
64
64
|
**/
|
|
65
65
|
srcSetCandidates?: number[];
|
|
66
|
-
}
|
|
66
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { QueryListenerOptions } from './types';
|
|
3
|
+
import { print } from '@0no-co/graphql.web';
|
|
4
|
+
|
|
5
|
+
type Props<QueryResult, QueryVariables> = QueryListenerOptions<QueryResult, QueryVariables>;
|
|
6
|
+
|
|
7
|
+
const { query, ...rest } = Astro.props;
|
|
8
|
+
|
|
9
|
+
const stringifiedQuery = typeof query === 'object' ? print(query) : query;
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<datocms-query-listener data-config={JSON.stringify({ ...rest, query: stringifiedQuery })}>
|
|
13
|
+
</datocms-query-listener>
|
|
14
|
+
|
|
15
|
+
<script>
|
|
16
|
+
import { subscribeToQuery as subscribeToQueryFn } from 'datocms-listen';
|
|
17
|
+
import type { QueryListenerOptions } from './types';
|
|
18
|
+
|
|
19
|
+
class QueryListener extends HTMLElement {
|
|
20
|
+
config: QueryListenerOptions<unknown, unknown>;
|
|
21
|
+
updatesReceived: number = 0;
|
|
22
|
+
|
|
23
|
+
constructor() {
|
|
24
|
+
super();
|
|
25
|
+
|
|
26
|
+
if (!this.dataset.config) {
|
|
27
|
+
throw new Error('Missing config');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
this.config = JSON.parse(this.dataset.config);
|
|
31
|
+
|
|
32
|
+
import('datocms-listen').then(({ subscribeToQuery }) => {
|
|
33
|
+
this.run(subscribeToQuery);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
run(subscribeToQuery: typeof subscribeToQueryFn) {
|
|
38
|
+
subscribeToQuery<unknown, unknown>({
|
|
39
|
+
...this.config,
|
|
40
|
+
onUpdate: () => {
|
|
41
|
+
this.updatesReceived += 1;
|
|
42
|
+
|
|
43
|
+
if (this.updatesReceived > 1) {
|
|
44
|
+
document.location.reload();
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
onChannelError: (error) => {
|
|
48
|
+
console.error('[QueryListener]', error);
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Tell the browser to use our AstroHeart class for <astro-heart> elements.
|
|
55
|
+
customElements.define('datocms-query-listener', QueryListener);
|
|
56
|
+
</script>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Live real-time updates
|
|
2
|
+
|
|
3
|
+
`<QueryListener />` is an Astro component that you can use to implement client-side reload of the page as soon as the content of a query 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.
|
|
4
|
+
|
|
5
|
+
Live reloads are great to get instant previews of your content while editing it inside DatoCMS.
|
|
6
|
+
|
|
7
|
+
`<QueryListener />` is based on the `subscribeToQuery` helper provided by the [datocms-listen](https://www.npmjs.com/package/datocms-listen) package.
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
12
|
+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
13
|
+
|
|
14
|
+
- [Installation](#installation)
|
|
15
|
+
- [Reference](#reference)
|
|
16
|
+
- [Initialization options](#initialization-options)
|
|
17
|
+
|
|
18
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
npm install --save @datocms/astro
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Reference
|
|
27
|
+
|
|
28
|
+
Import `<QueryListener>` from `@datocms/astro` and use it inside your components setup function like this:
|
|
29
|
+
|
|
30
|
+
```astro
|
|
31
|
+
---
|
|
32
|
+
import { QueryListener } from '@datocms/astro/QueryListener';
|
|
33
|
+
import { executeQuery } from '@datocms/cda-client';
|
|
34
|
+
|
|
35
|
+
const query = gql`
|
|
36
|
+
query {
|
|
37
|
+
homepage {
|
|
38
|
+
title
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
const data = await executeQuery(query, { token: '<YOUR-API-TOKEN>' });
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
<h1>{data.homepage.title}</h1>
|
|
47
|
+
|
|
48
|
+
<QueryListener query={query} token="<YOUR-API-TOKEN>" />
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Initialization options
|
|
52
|
+
|
|
53
|
+
| prop | type | required | description | default |
|
|
54
|
+
| ------------------ | ------------------------------------------------------------------------------------------ | ------------------ | ------------------------------------------------------------------------------------------------ | ------------------------------------ |
|
|
55
|
+
| enabled | boolean | :x: | Whether the subscription has to be performed or not | true |
|
|
56
|
+
| query | string \| [`TypedDocumentNode`](https://github.com/dotansimha/graphql-typed-document-node) | :white_check_mark: | The GraphQL query to subscribe | |
|
|
57
|
+
| token | string | :white_check_mark: | DatoCMS API token to use | |
|
|
58
|
+
| variables | Object | :x: | GraphQL variables for the query | |
|
|
59
|
+
| includeDrafts | boolean | :x: | If true, draft records will be returned | |
|
|
60
|
+
| excludeInvalid | boolean | :x: | If true, invalid records will be filtered out | |
|
|
61
|
+
| environment | string | :x: | The name of the DatoCMS environment where to perform the query (defaults to primary environment) | |
|
|
62
|
+
| contentLink | `'vercel-1'` or `undefined` | :x: | If true, embed metadata that enable Content Link | |
|
|
63
|
+
| baseEditingUrl | string | :x: | The base URL of the DatoCMS project | |
|
|
64
|
+
| cacheTags | boolean | :x: | If true, receive the Cache Tags associated with the query | |
|
|
65
|
+
| initialData | Object | :x: | The initial data to use on the first render | |
|
|
66
|
+
| reconnectionPeriod | number | :x: | In case of network errors, the period (in ms) to wait to reconnect | 1000 |
|
|
67
|
+
| baseUrl | string | :x: | The base URL to use to perform the query | `https://graphql-listen.datocms.com` |
|