@starlightcms/react-sdk 0.8.0 → 0.10.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.
Files changed (90) hide show
  1. package/README.md +57 -0
  2. package/dist/cjs/ResponsiveImage/index.d.ts +61 -13
  3. package/dist/cjs/ResponsiveImage/index.d.ts.map +1 -1
  4. package/dist/cjs/ResponsiveImage/index.js +63 -1
  5. package/dist/cjs/ResponsiveImage/index.js.map +1 -1
  6. package/dist/cjs/ResponsiveImage/types.d.ts +52 -0
  7. package/dist/cjs/ResponsiveImage/types.d.ts.map +1 -0
  8. package/dist/cjs/ResponsiveImage/types.js +3 -0
  9. package/dist/cjs/ResponsiveImage/types.js.map +1 -0
  10. package/dist/cjs/VisualContent/blocks/HTML.d.ts +11 -0
  11. package/dist/cjs/VisualContent/blocks/HTML.d.ts.map +1 -1
  12. package/dist/cjs/VisualContent/blocks/HTML.js +11 -0
  13. package/dist/cjs/VisualContent/blocks/HTML.js.map +1 -1
  14. package/dist/cjs/VisualContent/blocks/Header.d.ts +13 -2
  15. package/dist/cjs/VisualContent/blocks/Header.d.ts.map +1 -1
  16. package/dist/cjs/VisualContent/blocks/Header.js +11 -0
  17. package/dist/cjs/VisualContent/blocks/Header.js.map +1 -1
  18. package/dist/cjs/VisualContent/blocks/Image.d.ts +21 -1
  19. package/dist/cjs/VisualContent/blocks/Image.d.ts.map +1 -1
  20. package/dist/cjs/VisualContent/blocks/Image.js +22 -1
  21. package/dist/cjs/VisualContent/blocks/Image.js.map +1 -1
  22. package/dist/cjs/VisualContent/blocks/List.d.ts +11 -0
  23. package/dist/cjs/VisualContent/blocks/List.d.ts.map +1 -1
  24. package/dist/cjs/VisualContent/blocks/List.js +11 -0
  25. package/dist/cjs/VisualContent/blocks/List.js.map +1 -1
  26. package/dist/cjs/VisualContent/blocks/Paragraph.d.ts +11 -0
  27. package/dist/cjs/VisualContent/blocks/Paragraph.d.ts.map +1 -1
  28. package/dist/cjs/VisualContent/blocks/Paragraph.js +11 -0
  29. package/dist/cjs/VisualContent/blocks/Paragraph.js.map +1 -1
  30. package/dist/cjs/VisualContent/blocks/Quote.d.ts +11 -0
  31. package/dist/cjs/VisualContent/blocks/Quote.d.ts.map +1 -1
  32. package/dist/cjs/VisualContent/blocks/Quote.js +11 -0
  33. package/dist/cjs/VisualContent/blocks/Quote.js.map +1 -1
  34. package/dist/cjs/VisualContent/index.d.ts +55 -3
  35. package/dist/cjs/VisualContent/index.d.ts.map +1 -1
  36. package/dist/cjs/VisualContent/index.js +56 -1
  37. package/dist/cjs/VisualContent/index.js.map +1 -1
  38. package/dist/cjs/VisualContent/styles.d.ts +11 -0
  39. package/dist/cjs/VisualContent/styles.d.ts.map +1 -1
  40. package/dist/cjs/VisualContent/styles.js +11 -0
  41. package/dist/cjs/VisualContent/styles.js.map +1 -1
  42. package/dist/cjs/VisualContent/types.d.ts +22 -2
  43. package/dist/cjs/VisualContent/types.d.ts.map +1 -1
  44. package/dist/cjs/VisualContent/types.js.map +1 -1
  45. package/dist/cjs/index.js +5 -1
  46. package/dist/cjs/index.js.map +1 -1
  47. package/dist/esm/ResponsiveImage/index.d.ts +61 -13
  48. package/dist/esm/ResponsiveImage/index.d.ts.map +1 -1
  49. package/dist/esm/ResponsiveImage/index.js +59 -1
  50. package/dist/esm/ResponsiveImage/index.js.map +1 -1
  51. package/dist/esm/ResponsiveImage/types.d.ts +52 -0
  52. package/dist/esm/ResponsiveImage/types.d.ts.map +1 -0
  53. package/dist/esm/ResponsiveImage/types.js +2 -0
  54. package/dist/esm/ResponsiveImage/types.js.map +1 -0
  55. package/dist/esm/VisualContent/blocks/HTML.d.ts +11 -0
  56. package/dist/esm/VisualContent/blocks/HTML.d.ts.map +1 -1
  57. package/dist/esm/VisualContent/blocks/HTML.js +11 -0
  58. package/dist/esm/VisualContent/blocks/HTML.js.map +1 -1
  59. package/dist/esm/VisualContent/blocks/Header.d.ts +13 -2
  60. package/dist/esm/VisualContent/blocks/Header.d.ts.map +1 -1
  61. package/dist/esm/VisualContent/blocks/Header.js +11 -0
  62. package/dist/esm/VisualContent/blocks/Header.js.map +1 -1
  63. package/dist/esm/VisualContent/blocks/Image.d.ts +21 -1
  64. package/dist/esm/VisualContent/blocks/Image.d.ts.map +1 -1
  65. package/dist/esm/VisualContent/blocks/Image.js +17 -0
  66. package/dist/esm/VisualContent/blocks/Image.js.map +1 -1
  67. package/dist/esm/VisualContent/blocks/List.d.ts +11 -0
  68. package/dist/esm/VisualContent/blocks/List.d.ts.map +1 -1
  69. package/dist/esm/VisualContent/blocks/List.js +11 -0
  70. package/dist/esm/VisualContent/blocks/List.js.map +1 -1
  71. package/dist/esm/VisualContent/blocks/Paragraph.d.ts +11 -0
  72. package/dist/esm/VisualContent/blocks/Paragraph.d.ts.map +1 -1
  73. package/dist/esm/VisualContent/blocks/Paragraph.js +11 -0
  74. package/dist/esm/VisualContent/blocks/Paragraph.js.map +1 -1
  75. package/dist/esm/VisualContent/blocks/Quote.d.ts +11 -0
  76. package/dist/esm/VisualContent/blocks/Quote.d.ts.map +1 -1
  77. package/dist/esm/VisualContent/blocks/Quote.js +11 -0
  78. package/dist/esm/VisualContent/blocks/Quote.js.map +1 -1
  79. package/dist/esm/VisualContent/index.d.ts +55 -3
  80. package/dist/esm/VisualContent/index.d.ts.map +1 -1
  81. package/dist/esm/VisualContent/index.js +51 -0
  82. package/dist/esm/VisualContent/index.js.map +1 -1
  83. package/dist/esm/VisualContent/styles.d.ts +11 -0
  84. package/dist/esm/VisualContent/styles.d.ts.map +1 -1
  85. package/dist/esm/VisualContent/styles.js +11 -0
  86. package/dist/esm/VisualContent/styles.js.map +1 -1
  87. package/dist/esm/VisualContent/types.d.ts +22 -2
  88. package/dist/esm/VisualContent/types.d.ts.map +1 -1
  89. package/dist/esm/VisualContent/types.js.map +1 -1
  90. package/package.json +8 -2
@@ -4,6 +4,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const react_1 = __importDefault(require("react"));
7
+ /**
8
+ * VisualContent renderer component that renders `paragraph` type blocks
9
+ * as `<p>` elements.
10
+ *
11
+ * See {@doclink components/VisualContent/#customizing-components | the guide page on the VisualContent component}
12
+ * to learn how to customize block renderer components like this one.
13
+ *
14
+ * @param props VisualDataBlock object. See {@link ParagraphBlock} to learn the
15
+ * type of data this component receives.
16
+ * @group VisualContent Renderers
17
+ */
7
18
  const Paragraph = ({ data }) => {
8
19
  return (react_1.default.createElement("p", { className: "sl-content-block sl-paragraph", dangerouslySetInnerHTML: { __html: data.text } }));
9
20
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Paragraph.js","sourceRoot":"","sources":["../../../../src/VisualContent/blocks/Paragraph.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAiC;AAGjC,MAAM,SAAS,GAAwC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;IAClE,OAAO,CACL,qCACE,SAAS,EAAC,+BAA+B,EACzC,uBAAuB,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,GAC9C,CACH,CAAA;AACH,CAAC,CAAA;AAED,kBAAe,SAAS,CAAA","sourcesContent":["import React, { FC } from 'react'\nimport { ParagraphBlock, VisualDataBlock } from '@starlightcms/js-sdk'\n\nconst Paragraph: FC<VisualDataBlock<ParagraphBlock>> = ({ data }) => {\n return (\n <p\n className=\"sl-content-block sl-paragraph\"\n dangerouslySetInnerHTML={{ __html: data.text }}\n />\n )\n}\n\nexport default Paragraph\n"]}
1
+ {"version":3,"file":"Paragraph.js","sourceRoot":"","sources":["../../../../src/VisualContent/blocks/Paragraph.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAiC;AAGjC;;;;;;;;;;GAUG;AACH,MAAM,SAAS,GAAwC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;IAClE,OAAO,CACL,qCACE,SAAS,EAAC,+BAA+B,EACzC,uBAAuB,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,GAC9C,CACH,CAAA;AACH,CAAC,CAAA;AAED,kBAAe,SAAS,CAAA","sourcesContent":["import React, { FC } from 'react'\nimport { ParagraphBlock, VisualDataBlock } from '@starlightcms/js-sdk'\n\n/**\n * VisualContent renderer component that renders `paragraph` type blocks\n * as `<p>` elements.\n *\n * See {@doclink components/VisualContent/#customizing-components | the guide page on the VisualContent component}\n * to learn how to customize block renderer components like this one.\n *\n * @param props VisualDataBlock object. See {@link ParagraphBlock} to learn the\n * type of data this component receives.\n * @group VisualContent Renderers\n */\nconst Paragraph: FC<VisualDataBlock<ParagraphBlock>> = ({ data }) => {\n return (\n <p\n className=\"sl-content-block sl-paragraph\"\n dangerouslySetInnerHTML={{ __html: data.text }}\n />\n )\n}\n\nexport default Paragraph\n"]}
@@ -1,5 +1,16 @@
1
1
  import { FC } from 'react';
2
2
  import { QuoteBlock, VisualDataBlock } from '@starlightcms/js-sdk';
3
+ /**
4
+ * VisualContent renderer component that renders `quote` type blocks
5
+ * as `<blockquote>` elements.
6
+ *
7
+ * See {@doclink components/VisualContent/#customizing-components | the guide page on the VisualContent component}
8
+ * to learn how to customize block renderer components like this one.
9
+ *
10
+ * @param props VisualDataBlock object. See {@link QuoteBlock} to learn the
11
+ * type of data this component receives.
12
+ * @group VisualContent Renderers
13
+ */
3
14
  declare const Quote: FC<VisualDataBlock<QuoteBlock>>;
4
15
  export default Quote;
5
16
  //# sourceMappingURL=Quote.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Quote.d.ts","sourceRoot":"","sources":["../../../../src/VisualContent/blocks/Quote.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,EAAE,EAAE,MAAM,OAAO,CAAA;AACjC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAElE,QAAA,MAAM,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAI1C,CAAA;AAED,eAAe,KAAK,CAAA"}
1
+ {"version":3,"file":"Quote.d.ts","sourceRoot":"","sources":["../../../../src/VisualContent/blocks/Quote.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,EAAE,EAAE,MAAM,OAAO,CAAA;AACjC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAElE;;;;;;;;;;GAUG;AACH,QAAA,MAAM,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAI1C,CAAA;AAED,eAAe,KAAK,CAAA"}
@@ -4,6 +4,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const react_1 = __importDefault(require("react"));
7
+ /**
8
+ * VisualContent renderer component that renders `quote` type blocks
9
+ * as `<blockquote>` elements.
10
+ *
11
+ * See {@doclink components/VisualContent/#customizing-components | the guide page on the VisualContent component}
12
+ * to learn how to customize block renderer components like this one.
13
+ *
14
+ * @param props VisualDataBlock object. See {@link QuoteBlock} to learn the
15
+ * type of data this component receives.
16
+ * @group VisualContent Renderers
17
+ */
7
18
  const Quote = ({ data }) => {
8
19
  return (react_1.default.createElement("blockquote", { className: "sl-content-block sl-quote" }, data.text));
9
20
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Quote.js","sourceRoot":"","sources":["../../../../src/VisualContent/blocks/Quote.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAiC;AAGjC,MAAM,KAAK,GAAoC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;IAC1D,OAAO,CACL,8CAAY,SAAS,EAAC,2BAA2B,IAAE,IAAI,CAAC,IAAI,CAAc,CAC3E,CAAA;AACH,CAAC,CAAA;AAED,kBAAe,KAAK,CAAA","sourcesContent":["import React, { FC } from 'react'\nimport { QuoteBlock, VisualDataBlock } from '@starlightcms/js-sdk'\n\nconst Quote: FC<VisualDataBlock<QuoteBlock>> = ({ data }) => {\n return (\n <blockquote className=\"sl-content-block sl-quote\">{data.text}</blockquote>\n )\n}\n\nexport default Quote\n"]}
1
+ {"version":3,"file":"Quote.js","sourceRoot":"","sources":["../../../../src/VisualContent/blocks/Quote.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAiC;AAGjC;;;;;;;;;;GAUG;AACH,MAAM,KAAK,GAAoC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;IAC1D,OAAO,CACL,8CAAY,SAAS,EAAC,2BAA2B,IAAE,IAAI,CAAC,IAAI,CAAc,CAC3E,CAAA;AACH,CAAC,CAAA;AAED,kBAAe,KAAK,CAAA","sourcesContent":["import React, { FC } from 'react'\nimport { QuoteBlock, VisualDataBlock } from '@starlightcms/js-sdk'\n\n/**\n * VisualContent renderer component that renders `quote` type blocks\n * as `<blockquote>` elements.\n *\n * See {@doclink components/VisualContent/#customizing-components | the guide page on the VisualContent component}\n * to learn how to customize block renderer components like this one.\n *\n * @param props VisualDataBlock object. See {@link QuoteBlock} to learn the\n * type of data this component receives.\n * @group VisualContent Renderers\n */\nconst Quote: FC<VisualDataBlock<QuoteBlock>> = ({ data }) => {\n return (\n <blockquote className=\"sl-content-block sl-quote\">{data.text}</blockquote>\n )\n}\n\nexport default Quote\n"]}
@@ -1,12 +1,64 @@
1
- import { FC } from 'react';
1
+ /// <reference types="react" />
2
2
  import { VisualContentProps } from './types';
3
3
  import { VisualContentStyles } from './styles';
4
4
  import Paragraph from './blocks/Paragraph';
5
5
  import Header from './blocks/Header';
6
6
  import Quote from './blocks/Quote';
7
- import Image from './blocks/Image';
7
+ import Image, { ImageOptions } from './blocks/Image';
8
8
  import HTML from './blocks/HTML';
9
9
  import List from './blocks/List';
10
- export declare const VisualContent: FC<VisualContentProps>;
10
+ /**
11
+ * Renders HTML content from data returned by a Visual Editor field on Starlight.
12
+ *
13
+ * The only required prop is `content`, which is the data returned by a Visual
14
+ * Editor field. Additionally, you can provide custom components to render each
15
+ * data block type.
16
+ *
17
+ * You can also pass the `excerpt` boolean prop to only render a portion of the
18
+ * content, which is useful to summarize the content in lists.
19
+ *
20
+ * To learn how to customize the rendered content, take a look at the
21
+ * [Customizing the output](#) guide page.
22
+ *
23
+ * @example Requesting an entry and rendering its content.
24
+ *
25
+ * Assume we created a "Posts" model with a slug of `posts`, and placed a Visual
26
+ * Editor field with a key of `post_content` on it.
27
+ *
28
+ * ```jsx
29
+ * import Starlight, { VisualContent } from '@starlightcms/react-sdk'
30
+ *
31
+ * const EntryComponent = ({ slug }) => {
32
+ * const [entry, setEntry] = useState(null)
33
+ *
34
+ * // This is just an example, you could fetch
35
+ * // the entry any way you want.
36
+ * useEffect(async () => {
37
+ * const response = await Starlight.posts.entries.get(slug)
38
+ *
39
+ * setEntry(response.data)
40
+ * }, [ slug ])
41
+ *
42
+ * // After fetching, content will be on the `entry.data.post_content` property.
43
+ * return (
44
+ * entry ? (
45
+ * <article>
46
+ * <h1>{entry.title}</h1>
47
+ * <VisualContent content={entry.data.post_content} />
48
+ * </article>
49
+ * ) : (
50
+ * <div>Loading...</div>
51
+ * )
52
+ * )
53
+ * }
54
+ *
55
+ * ```
56
+ *
57
+ * @param props Component props. See {@link VisualContentProps} to see the
58
+ * available options.
59
+ * @group VisualContent
60
+ */
61
+ export declare const VisualContent: ({ content, components, excerpt, excerptLength, }: VisualContentProps) => JSX.Element;
11
62
  export { VisualContentStyles, Paragraph as ParagraphComponent, Header as HeaderComponent, Quote as QuoteComponent, Image as ImageComponent, HTML as HTMLComponent, List as ListComponent, };
63
+ export type { VisualContentProps, ImageOptions };
12
64
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/VisualContent/index.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,EAAE,EAAW,MAAM,OAAO,CAAA;AAE1C,OAAO,EAAmB,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,SAAS,MAAM,oBAAoB,CAAA;AAC1C,OAAO,MAAM,MAAM,iBAAiB,CAAA;AACpC,OAAO,KAAK,MAAM,gBAAgB,CAAA;AAClC,OAAO,KAAK,MAAM,gBAAgB,CAAA;AAClC,OAAO,IAAI,MAAM,eAAe,CAAA;AAChC,OAAO,IAAI,MAAM,eAAe,CAAA;AAWhC,eAAO,MAAM,aAAa,EAAE,EAAE,CAAC,kBAAkB,CAuDhD,CAAA;AAED,OAAO,EACL,mBAAmB,EACnB,SAAS,IAAI,kBAAkB,EAC/B,MAAM,IAAI,eAAe,EACzB,KAAK,IAAI,cAAc,EACvB,KAAK,IAAI,cAAc,EACvB,IAAI,IAAI,aAAa,EACrB,IAAI,IAAI,aAAa,GACtB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/VisualContent/index.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAmB,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,SAAS,MAAM,oBAAoB,CAAA;AAC1C,OAAO,MAAM,MAAM,iBAAiB,CAAA;AACpC,OAAO,KAAK,MAAM,gBAAgB,CAAA;AAClC,OAAO,KAAK,EAAE,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,IAAI,MAAM,eAAe,CAAA;AAChC,OAAO,IAAI,MAAM,eAAe,CAAA;AAWhC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,eAAO,MAAM,aAAa,qDAKvB,kBAAkB,KAAG,WAkDvB,CAAA;AAED,OAAO,EACL,mBAAmB,EACnB,SAAS,IAAI,kBAAkB,EAC/B,MAAM,IAAI,eAAe,EACzB,KAAK,IAAI,cAAc,EACvB,KAAK,IAAI,cAAc,EACvB,IAAI,IAAI,aAAa,EACrB,IAAI,IAAI,aAAa,GACtB,CAAA;AAED,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,CAAA"}
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -46,6 +50,57 @@ const defaultComponents = {
46
50
  raw: HTML_1.default,
47
51
  list: List_1.default,
48
52
  };
53
+ /**
54
+ * Renders HTML content from data returned by a Visual Editor field on Starlight.
55
+ *
56
+ * The only required prop is `content`, which is the data returned by a Visual
57
+ * Editor field. Additionally, you can provide custom components to render each
58
+ * data block type.
59
+ *
60
+ * You can also pass the `excerpt` boolean prop to only render a portion of the
61
+ * content, which is useful to summarize the content in lists.
62
+ *
63
+ * To learn how to customize the rendered content, take a look at the
64
+ * [Customizing the output](#) guide page.
65
+ *
66
+ * @example Requesting an entry and rendering its content.
67
+ *
68
+ * Assume we created a "Posts" model with a slug of `posts`, and placed a Visual
69
+ * Editor field with a key of `post_content` on it.
70
+ *
71
+ * ```jsx
72
+ * import Starlight, { VisualContent } from '@starlightcms/react-sdk'
73
+ *
74
+ * const EntryComponent = ({ slug }) => {
75
+ * const [entry, setEntry] = useState(null)
76
+ *
77
+ * // This is just an example, you could fetch
78
+ * // the entry any way you want.
79
+ * useEffect(async () => {
80
+ * const response = await Starlight.posts.entries.get(slug)
81
+ *
82
+ * setEntry(response.data)
83
+ * }, [ slug ])
84
+ *
85
+ * // After fetching, content will be on the `entry.data.post_content` property.
86
+ * return (
87
+ * entry ? (
88
+ * <article>
89
+ * <h1>{entry.title}</h1>
90
+ * <VisualContent content={entry.data.post_content} />
91
+ * </article>
92
+ * ) : (
93
+ * <div>Loading...</div>
94
+ * )
95
+ * )
96
+ * }
97
+ *
98
+ * ```
99
+ *
100
+ * @param props Component props. See {@link VisualContentProps} to see the
101
+ * available options.
102
+ * @group VisualContent
103
+ */
49
104
  const VisualContent = ({ content, components = {}, excerpt = false, excerptLength = 40, }) => {
50
105
  const componentList = (0, react_1.useMemo)(() => (Object.assign(Object.assign({}, defaultComponents), components)), [components]);
51
106
  if (!content) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/VisualContent/index.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAA0C;AAG1C,qCAA8C;AA2E5C,oGA3EO,4BAAmB,OA2EP;AA1ErB,mEAA0C;AA2E3B,6BA3ER,mBAAS,CA2EiB;AA1EjC,6DAAoC;AA2ExB,0BA3EL,gBAAM,CA2Ec;AA1E3B,2DAAkC;AA2EvB,yBA3EJ,eAAK,CA2Ea;AA1EzB,2DAAkC;AA2EvB,yBA3EJ,eAAK,CA2Ea;AA1EzB,yDAAgC;AA2EtB,wBA3EH,cAAI,CA2EY;AA1EvB,yDAAgC;AA2EtB,wBA3EH,cAAI,CA2EY;AAzEvB,MAAM,iBAAiB,GAAoB;IACzC,SAAS,EAAE,mBAAS;IACpB,MAAM,EAAE,gBAAM;IACd,KAAK,EAAE,eAAK;IACZ,KAAK,EAAE,eAAK;IACZ,GAAG,EAAE,cAAI;IACT,IAAI,EAAE,cAAI;CACX,CAAA;AAEM,MAAM,aAAa,GAA2B,CAAC,EACpD,OAAO,EACP,UAAU,GAAG,EAAE,EACf,OAAO,GAAG,KAAK,EACf,aAAa,GAAG,EAAE,GACnB,EAAE,EAAE;IACH,MAAM,aAAa,GAAG,IAAA,eAAO,EAC3B,GAAG,EAAE,CAAC,iCAAM,iBAAiB,GAAK,UAAU,EAAG,EAC/C,CAAC,UAAU,CAAC,CACb,CAAA;IAED,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,IAAI,CAAA;KACZ;IAED,IAAI,OAAO,EAAE;QACX,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAA;QAExE,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAA;QAEvB,MAAM,IAAI,GAAI,KAAyC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC5E,MAAM,WAAW,GACf,IAAI,CAAC,MAAM,GAAG,aAAa;YACzB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK;YACjD,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACpB,MAAM,SAAS,GAAG,aAAa,CAAC,SAAS,CAAA;QAEzC,OAAO,CACL,8BAAC,SAAS,IACR,GAAG,EAAE,KAAK,CAAC,EAAE,EACb,EAAE,EAAE,KAAK,CAAC,EAAE,EACZ,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,IAAI,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,GAC3B,CACH,CAAA;KACF;IAED,OAAO,CACL,uCAAK,SAAS,EAAC,mBAAmB,IAC/B,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAC5B,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAE3C,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAA;QAE3B,OAAO,CACL,8BAAC,SAAS,IACR,GAAG,EAAE,KAAK,CAAC,EAAE,EACb,EAAE,EAAE,KAAK,CAAC,EAAE,EACZ,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,IAAI,EAAE,KAAK,CAAC,IAAa,GACzB,CACH,CAAA;IACH,CAAC,CAAC,CACE,CACP,CAAA;AACH,CAAC,CAAA;AAvDY,QAAA,aAAa,iBAuDzB","sourcesContent":["import React, { FC, useMemo } from 'react'\nimport { VisualDataBlock, ParagraphBlock } from '@starlightcms/js-sdk'\nimport { BlockComponents, VisualContentProps } from './types'\nimport { VisualContentStyles } from './styles'\nimport Paragraph from './blocks/Paragraph'\nimport Header from './blocks/Header'\nimport Quote from './blocks/Quote'\nimport Image from './blocks/Image'\nimport HTML from './blocks/HTML'\nimport List from './blocks/List'\n\nconst defaultComponents: BlockComponents = {\n paragraph: Paragraph,\n header: Header,\n quote: Quote,\n image: Image,\n raw: HTML,\n list: List,\n}\n\nexport const VisualContent: FC<VisualContentProps> = ({\n content,\n components = {},\n excerpt = false,\n excerptLength = 40,\n}) => {\n const componentList = useMemo(\n () => ({ ...defaultComponents, ...components }),\n [components]\n )\n\n if (!content) {\n return null\n }\n\n if (excerpt) {\n const block = content.blocks.find((block) => block.type === 'paragraph')\n\n if (!block) return null\n\n const text = (block as VisualDataBlock<ParagraphBlock>).data.text.split(' ')\n const excerptText =\n text.length > excerptLength\n ? text.splice(0, excerptLength).join(' ') + '...'\n : text.join(' ')\n const Component = componentList.paragraph\n\n return (\n <Component\n key={block.id}\n id={block.id}\n type={block.type}\n data={{ text: excerptText }}\n />\n )\n }\n\n return (\n <div className=\"sl-visual-content\">\n {content.blocks.map((block) => {\n const Component = componentList[block.type]\n\n if (!Component) return null\n\n return (\n <Component\n key={block.id}\n id={block.id}\n type={block.type}\n data={block.data as never}\n />\n )\n })}\n </div>\n )\n}\n\nexport {\n VisualContentStyles,\n Paragraph as ParagraphComponent,\n Header as HeaderComponent,\n Quote as QuoteComponent,\n Image as ImageComponent,\n HTML as HTMLComponent,\n List as ListComponent,\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/VisualContent/index.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAsC;AAGtC,qCAA8C;AA8H5C,oGA9HO,4BAAmB,OA8HP;AA7HrB,mEAA0C;AA8H3B,6BA9HR,mBAAS,CA8HiB;AA7HjC,6DAAoC;AA8HxB,0BA9HL,gBAAM,CA8Hc;AA7H3B,2DAAkC;AA8HvB,yBA9HJ,eAAK,CA8Ha;AA7HzB,2DAAoD;AA8HzC,yBA9HJ,eAAK,CA8Ha;AA7HzB,yDAAgC;AA8HtB,wBA9HH,cAAI,CA8HY;AA7HvB,yDAAgC;AA8HtB,wBA9HH,cAAI,CA8HY;AA5HvB,MAAM,iBAAiB,GAAoB;IACzC,SAAS,EAAE,mBAAS;IACpB,MAAM,EAAE,gBAAM;IACd,KAAK,EAAE,eAAK;IACZ,KAAK,EAAE,eAAK;IACZ,GAAG,EAAE,cAAI;IACT,IAAI,EAAE,cAAI;CACX,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACI,MAAM,aAAa,GAAG,CAAC,EAC5B,OAAO,EACP,UAAU,GAAG,EAAE,EACf,OAAO,GAAG,KAAK,EACf,aAAa,GAAG,EAAE,GACC,EAAe,EAAE;IACpC,MAAM,aAAa,GAAG,IAAA,eAAO,EAC3B,GAAG,EAAE,CAAC,iCAAM,iBAAiB,GAAK,UAAU,EAAG,EAC/C,CAAC,UAAU,CAAC,CACb,CAAA;IAED,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,IAA8B,CAAA;KACtC;IAED,IAAI,OAAO,EAAE;QACX,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAA;QAExE,IAAI,CAAC,KAAK;YAAE,OAAO,IAA8B,CAAA;QAEjD,MAAM,IAAI,GAAI,KAAyC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC5E,MAAM,WAAW,GACf,IAAI,CAAC,MAAM,GAAG,aAAa;YACzB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK;YACjD,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACpB,MAAM,SAAS,GAAG,aAAa,CAAC,SAAS,CAAA;QAEzC,OAAO,CACL,8BAAC,SAAS,IACR,GAAG,EAAE,KAAK,CAAC,EAAE,EACb,EAAE,EAAE,KAAK,CAAC,EAAE,EACZ,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,IAAI,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,GAC3B,CACH,CAAA;KACF;IAED,OAAO,CACL,uCAAK,SAAS,EAAC,mBAAmB,IAC/B,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAC5B,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAE3C,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAA;QAE3B,OAAO,CACL,8BAAC,SAAS,IACR,GAAG,EAAE,KAAK,CAAC,EAAE,EACb,EAAE,EAAE,KAAK,CAAC,EAAE,EACZ,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,IAAI,EAAE,KAAK,CAAC,IAAa,GACzB,CACH,CAAA;IACH,CAAC,CAAC,CACE,CACP,CAAA;AACH,CAAC,CAAA;AAvDY,QAAA,aAAa,iBAuDzB","sourcesContent":["import React, { useMemo } from 'react'\nimport { VisualDataBlock, ParagraphBlock } from '@starlightcms/js-sdk'\nimport { BlockComponents, VisualContentProps } from './types'\nimport { VisualContentStyles } from './styles'\nimport Paragraph from './blocks/Paragraph'\nimport Header from './blocks/Header'\nimport Quote from './blocks/Quote'\nimport Image, { ImageOptions } from './blocks/Image'\nimport HTML from './blocks/HTML'\nimport List from './blocks/List'\n\nconst defaultComponents: BlockComponents = {\n paragraph: Paragraph,\n header: Header,\n quote: Quote,\n image: Image,\n raw: HTML,\n list: List,\n}\n\n/**\n * Renders HTML content from data returned by a Visual Editor field on Starlight.\n *\n * The only required prop is `content`, which is the data returned by a Visual\n * Editor field. Additionally, you can provide custom components to render each\n * data block type.\n *\n * You can also pass the `excerpt` boolean prop to only render a portion of the\n * content, which is useful to summarize the content in lists.\n *\n * To learn how to customize the rendered content, take a look at the\n * [Customizing the output](#) guide page.\n *\n * @example Requesting an entry and rendering its content.\n *\n * Assume we created a \"Posts\" model with a slug of `posts`, and placed a Visual\n * Editor field with a key of `post_content` on it.\n *\n * ```jsx\n * import Starlight, { VisualContent } from '@starlightcms/react-sdk'\n *\n * const EntryComponent = ({ slug }) => {\n * const [entry, setEntry] = useState(null)\n *\n * // This is just an example, you could fetch\n * // the entry any way you want.\n * useEffect(async () => {\n * const response = await Starlight.posts.entries.get(slug)\n *\n * setEntry(response.data)\n * }, [ slug ])\n *\n * // After fetching, content will be on the `entry.data.post_content` property.\n * return (\n * entry ? (\n * <article>\n * <h1>{entry.title}</h1>\n * <VisualContent content={entry.data.post_content} />\n * </article>\n * ) : (\n * <div>Loading...</div>\n * )\n * )\n * }\n *\n * ```\n *\n * @param props Component props. See {@link VisualContentProps} to see the\n * available options.\n * @group VisualContent\n */\nexport const VisualContent = ({\n content,\n components = {},\n excerpt = false,\n excerptLength = 40,\n}: VisualContentProps): JSX.Element => {\n const componentList = useMemo(\n () => ({ ...defaultComponents, ...components }),\n [components]\n )\n\n if (!content) {\n return null as unknown as JSX.Element\n }\n\n if (excerpt) {\n const block = content.blocks.find((block) => block.type === 'paragraph')\n\n if (!block) return null as unknown as JSX.Element\n\n const text = (block as VisualDataBlock<ParagraphBlock>).data.text.split(' ')\n const excerptText =\n text.length > excerptLength\n ? text.splice(0, excerptLength).join(' ') + '...'\n : text.join(' ')\n const Component = componentList.paragraph\n\n return (\n <Component\n key={block.id}\n id={block.id}\n type={block.type}\n data={{ text: excerptText }}\n />\n )\n }\n\n return (\n <div className=\"sl-visual-content\">\n {content.blocks.map((block) => {\n const Component = componentList[block.type]\n\n if (!Component) return null\n\n return (\n <Component\n key={block.id}\n id={block.id}\n type={block.type}\n data={block.data as never}\n />\n )\n })}\n </div>\n )\n}\n\nexport {\n VisualContentStyles,\n Paragraph as ParagraphComponent,\n Header as HeaderComponent,\n Quote as QuoteComponent,\n Image as ImageComponent,\n HTML as HTMLComponent,\n List as ListComponent,\n}\n\nexport type { VisualContentProps, ImageOptions }\n"]}
@@ -1,3 +1,14 @@
1
1
  /// <reference types="react" />
2
+ /**
3
+ * Renders a `<style>` tag with rules that style the rendered
4
+ * {@link VisualContent} HTML. While not required for VisualContent to work,
5
+ * using these rules is a quick way to make the content look the same way as it
6
+ * does on the Starlight content editor.
7
+ *
8
+ * You only need to render this component once in your application,
9
+ * preferably in the `<head>` section.
10
+ *
11
+ * @group VisualContent
12
+ */
2
13
  export declare const VisualContentStyles: () => JSX.Element;
3
14
  //# sourceMappingURL=styles.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/VisualContent/styles.tsx"],"names":[],"mappings":";AA6BA,eAAO,MAAM,mBAAmB,QAAO,WAEtC,CAAA"}
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/VisualContent/styles.tsx"],"names":[],"mappings":";AA6BA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,QAAO,WAEtC,CAAA"}
@@ -31,6 +31,17 @@ const styles = `
31
31
  .sl__color__text--brown{color:rgb(159,107,83)}
32
32
  .sl__color__text--gray{color:rgb(120,119,116)}
33
33
  `;
34
+ /**
35
+ * Renders a `<style>` tag with rules that style the rendered
36
+ * {@link VisualContent} HTML. While not required for VisualContent to work,
37
+ * using these rules is a quick way to make the content look the same way as it
38
+ * does on the Starlight content editor.
39
+ *
40
+ * You only need to render this component once in your application,
41
+ * preferably in the `<head>` section.
42
+ *
43
+ * @group VisualContent
44
+ */
34
45
  const VisualContentStyles = () => {
35
46
  return react_1.default.createElement("style", { dangerouslySetInnerHTML: { __html: styles } });
36
47
  };
@@ -1 +1 @@
1
- {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../src/VisualContent/styles.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AAEzB,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;CAyBd,CAAA;AAEM,MAAM,mBAAmB,GAAG,GAAgB,EAAE;IACnD,OAAO,yCAAO,uBAAuB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAI,CAAA;AAC/D,CAAC,CAAA;AAFY,QAAA,mBAAmB,uBAE/B","sourcesContent":["import React from 'react'\n\nconst styles = `\n .sl-visual-content *{max-width:100%}\n .sl-visual-content>figure{margin:1em 0}\n .sl-list{list-style:none;padding-left:1em}\n .sl-list>li{margin:.5em 0}\n .sl-list>li::before{content: \"•\";margin-right:.5em}\n .sl__color{padding:2px 0;border-radius:4px}\n .sl__color__bg--red{background-color:rgb(253,235,236)}\n .sl__color__bg--pink{background-color:rgb(253,235,236)}\n .sl__color__bg--purple{background-color:rgb(244,240,247)}\n .sl__color__bg--blue{background-color:rgb(231,243,248)}\n .sl__color__bg--green{background-color:rgb(237,243,236)}\n .sl__color__bg--yellow{background-color:rgb(251,243,219)}\n .sl__color__bg--orange{background-color:rgb(251,236,221)}\n .sl__color__bg--brown{background-color:rgb(244,238,238)}\n .sl__color__bg--gray{background-color:rgb(241,241,239)}\n .sl__color__text--red{color:rgb(212,76,71)}\n .sl__color__text--pink{color:rgb(193,76,138)}\n .sl__color__text--purple{color:rgb(144,101,176)}\n .sl__color__text--blue{color:rgb(51,126,169)}\n .sl__color__text--green{color:rgb(68,131,97)}\n .sl__color__text--yellow{color:rgb(203,145,47)}\n .sl__color__text--orange{color:rgb(217,115,13)}\n .sl__color__text--brown{color:rgb(159,107,83)}\n .sl__color__text--gray{color:rgb(120,119,116)}\n`\n\nexport const VisualContentStyles = (): JSX.Element => {\n return <style dangerouslySetInnerHTML={{ __html: styles }} />\n}\n"]}
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../src/VisualContent/styles.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AAEzB,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;CAyBd,CAAA;AAED;;;;;;;;;;GAUG;AACI,MAAM,mBAAmB,GAAG,GAAgB,EAAE;IACnD,OAAO,yCAAO,uBAAuB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAI,CAAA;AAC/D,CAAC,CAAA;AAFY,QAAA,mBAAmB,uBAE/B","sourcesContent":["import React from 'react'\n\nconst styles = `\n .sl-visual-content *{max-width:100%}\n .sl-visual-content>figure{margin:1em 0}\n .sl-list{list-style:none;padding-left:1em}\n .sl-list>li{margin:.5em 0}\n .sl-list>li::before{content: \"•\";margin-right:.5em}\n .sl__color{padding:2px 0;border-radius:4px}\n .sl__color__bg--red{background-color:rgb(253,235,236)}\n .sl__color__bg--pink{background-color:rgb(253,235,236)}\n .sl__color__bg--purple{background-color:rgb(244,240,247)}\n .sl__color__bg--blue{background-color:rgb(231,243,248)}\n .sl__color__bg--green{background-color:rgb(237,243,236)}\n .sl__color__bg--yellow{background-color:rgb(251,243,219)}\n .sl__color__bg--orange{background-color:rgb(251,236,221)}\n .sl__color__bg--brown{background-color:rgb(244,238,238)}\n .sl__color__bg--gray{background-color:rgb(241,241,239)}\n .sl__color__text--red{color:rgb(212,76,71)}\n .sl__color__text--pink{color:rgb(193,76,138)}\n .sl__color__text--purple{color:rgb(144,101,176)}\n .sl__color__text--blue{color:rgb(51,126,169)}\n .sl__color__text--green{color:rgb(68,131,97)}\n .sl__color__text--yellow{color:rgb(203,145,47)}\n .sl__color__text--orange{color:rgb(217,115,13)}\n .sl__color__text--brown{color:rgb(159,107,83)}\n .sl__color__text--gray{color:rgb(120,119,116)}\n`\n\n/**\n * Renders a `<style>` tag with rules that style the rendered\n * {@link VisualContent} HTML. While not required for VisualContent to work,\n * using these rules is a quick way to make the content look the same way as it\n * does on the Starlight content editor.\n *\n * You only need to render this component once in your application,\n * preferably in the `<head>` section.\n *\n * @group VisualContent\n */\nexport const VisualContentStyles = (): JSX.Element => {\n return <style dangerouslySetInnerHTML={{ __html: styles }} />\n}\n"]}
@@ -9,11 +9,31 @@ export interface BlockComponents extends Implements<Record<BlockType, unknown>,
9
9
  raw: ComponentType<VisualDataBlock<HTMLBlock>>;
10
10
  list: ComponentType<VisualDataBlock<ListBlock>>;
11
11
  }
12
- export declare type VisualContentProps = {
12
+ /**
13
+ * Props accepted by the {@link VisualContent} component.
14
+ * @group VisualContent
15
+ */
16
+ export interface VisualContentProps {
17
+ /**
18
+ * The content to render. It should be the object returned by
19
+ * Starlight on a Visual Editor field. Required.
20
+ */
13
21
  content?: VisualData;
22
+ /**
23
+ * An optional object of React components. You can pass any
24
+ * number of replacement components that will render blocks of a given type.
25
+ */
14
26
  components?: Partial<BlockComponents>;
27
+ /**
28
+ * If true, only a small portion of the content will be rendered,
29
+ * and block types other than text paragraphs will be ignored. Defaults to false.
30
+ */
15
31
  excerpt?: boolean;
32
+ /**
33
+ * Defines the maximum number of words to render when
34
+ * excerpt is true. Defaults to 40.
35
+ */
16
36
  excerptLength?: number;
17
- };
37
+ }
18
38
  export {};
19
39
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/VisualContent/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AACrC,OAAO,EACL,WAAW,EACX,UAAU,EACV,cAAc,EACd,UAAU,EACV,UAAU,EACV,eAAe,EACf,SAAS,EACT,SAAS,EACT,SAAS,EACV,MAAM,sBAAsB,CAAA;AAG7B,aAAK,UAAU,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEzD,MAAM,WAAW,eACf,SAAQ,UAAU,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,CAAC;IAC/D,SAAS,EAAE,aAAa,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAA;IACzD,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,CAAA;IACnD,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAA;IACjD,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAA;IACjD,GAAG,EAAE,aAAa,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAA;IAC9C,IAAI,EAAE,aAAa,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAA;CAChD;AAED,oBAAY,kBAAkB,GAAG;IAC/B,OAAO,CAAC,EAAE,UAAU,CAAA;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;IACrC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/VisualContent/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AACrC,OAAO,EACL,WAAW,EACX,UAAU,EACV,cAAc,EACd,UAAU,EACV,UAAU,EACV,eAAe,EACf,SAAS,EACT,SAAS,EACT,SAAS,EACV,MAAM,sBAAsB,CAAA;AAG7B,aAAK,UAAU,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEzD,MAAM,WAAW,eACf,SAAQ,UAAU,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,CAAC;IAC/D,SAAS,EAAE,aAAa,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAA;IACzD,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,CAAA;IACnD,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAA;IACjD,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAA;IACjD,GAAG,EAAE,aAAa,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAA;IAC9C,IAAI,EAAE,aAAa,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAA;CAChD;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,OAAO,CAAC,EAAE,UAAU,CAAA;IACpB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;IACrC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/VisualContent/types.ts"],"names":[],"mappings":"","sourcesContent":["import { ComponentType } from 'react'\nimport {\n HeaderBlock,\n ImageBlock,\n ParagraphBlock,\n QuoteBlock,\n VisualData,\n VisualDataBlock,\n BlockType,\n HTMLBlock,\n ListBlock,\n} from '@starlightcms/js-sdk'\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ntype Implements<T, U extends T> = Record<string, unknown>\n\nexport interface BlockComponents\n extends Implements<Record<BlockType, unknown>, BlockComponents> {\n paragraph: ComponentType<VisualDataBlock<ParagraphBlock>>\n header: ComponentType<VisualDataBlock<HeaderBlock>>\n quote: ComponentType<VisualDataBlock<QuoteBlock>>\n image: ComponentType<VisualDataBlock<ImageBlock>>\n raw: ComponentType<VisualDataBlock<HTMLBlock>>\n list: ComponentType<VisualDataBlock<ListBlock>>\n}\n\nexport type VisualContentProps = {\n content?: VisualData\n components?: Partial<BlockComponents>\n excerpt?: boolean\n excerptLength?: number\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/VisualContent/types.ts"],"names":[],"mappings":"","sourcesContent":["import { ComponentType } from 'react'\nimport {\n HeaderBlock,\n ImageBlock,\n ParagraphBlock,\n QuoteBlock,\n VisualData,\n VisualDataBlock,\n BlockType,\n HTMLBlock,\n ListBlock,\n} from '@starlightcms/js-sdk'\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ntype Implements<T, U extends T> = Record<string, unknown>\n\nexport interface BlockComponents\n extends Implements<Record<BlockType, unknown>, BlockComponents> {\n paragraph: ComponentType<VisualDataBlock<ParagraphBlock>>\n header: ComponentType<VisualDataBlock<HeaderBlock>>\n quote: ComponentType<VisualDataBlock<QuoteBlock>>\n image: ComponentType<VisualDataBlock<ImageBlock>>\n raw: ComponentType<VisualDataBlock<HTMLBlock>>\n list: ComponentType<VisualDataBlock<ListBlock>>\n}\n\n/**\n * Props accepted by the {@link VisualContent} component.\n * @group VisualContent\n */\nexport interface VisualContentProps {\n /**\n * The content to render. It should be the object returned by\n * Starlight on a Visual Editor field. Required.\n */\n content?: VisualData\n /**\n * An optional object of React components. You can pass any\n * number of replacement components that will render blocks of a given type.\n */\n components?: Partial<BlockComponents>\n /**\n * If true, only a small portion of the content will be rendered,\n * and block types other than text paragraphs will be ignored. Defaults to false.\n */\n excerpt?: boolean\n /**\n * Defines the maximum number of words to render when\n * excerpt is true. Defaults to 40.\n */\n excerptLength?: number\n}\n"]}
package/dist/cjs/index.js CHANGED
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,kEAA4C;AAC5C,uDAAoC;AAEpC,kDAA+B;AAC/B,oDAAiC;AAEjC,kBAAe,gBAAS,CAAA","sourcesContent":["import Starlight from '@starlightcms/js-sdk'\nexport * from '@starlightcms/js-sdk'\n\nexport * from './VisualContent'\nexport * from './ResponsiveImage'\n\nexport default Starlight\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,kEAA4C;AAC5C,uDAAoC;AAEpC,kDAA+B;AAC/B,oDAAiC;AAEjC,kBAAe,gBAAS,CAAA","sourcesContent":["import Starlight from '@starlightcms/js-sdk'\nexport * from '@starlightcms/js-sdk'\n\nexport * from './VisualContent'\nexport * from './ResponsiveImage'\n\nexport default Starlight\n"]}
@@ -1,16 +1,64 @@
1
- import { ReactNode, RefObject } from 'react';
2
- import { MediaObject } from '@starlightcms/js-sdk';
1
+ import { ReactNode } from 'react';
2
+ import { ResponsiveImageProps } from './types';
3
+ /**
4
+ * Renders a `<style>` tag with a rule that disables lazy-loading when JavaScript
5
+ * is disabled in the browser. This is useful to web crawlers that don't run
6
+ * JS files, which is important for SEO.
7
+ *
8
+ * You only need to render this component once in your application,
9
+ * preferably in the `<head>` section.
10
+ *
11
+ * @group ResponsiveImage
12
+ */
3
13
  export declare const GlobalLazyloadStyles: () => ReactNode;
4
- declare type ResponsiveImageProps = {
5
- className?: string;
6
- image: MediaObject | string;
7
- sizes?: string;
8
- alt?: string;
9
- variation?: string;
10
- background?: string;
11
- lazyRoot?: RefObject<HTMLElement> | null;
12
- lazyRootMargin?: string;
13
- };
14
+ /**
15
+ * Renders an image from a given Starlight media object. The Starlight
16
+ * optimized image will be rendered by default if no `variation` prop is passed.
17
+ *
18
+ * If the `sizes` prop is passed, a responsive image will be rendered by
19
+ * generating a "src-set" property.
20
+ *
21
+ * The image will be lazy-loaded, which means that it should only load
22
+ * when the browser viewport gets near the image.
23
+ *
24
+ * @example Requesting an entry and rendering an image.
25
+ *
26
+ * Assume we created a "Posts" model with a slug of `posts`, and placed a Media
27
+ * File field with a key of `featured_image` on it.
28
+ *
29
+ * ```jsx
30
+ * import Starlight, { ResponsiveImage } from '@starlightcms/react-sdk'
31
+ *
32
+ * const EntryComponent = ({ slug }) => {
33
+ * const [entry, setEntry] = useState(null)
34
+ *
35
+ * useEffect(async () => {
36
+ * // This is just an example, you could fetch
37
+ * // the entry any way you want.
38
+ * const response = await Starlight.posts.entries.get(slug)
39
+ *
40
+ * setEntry(response.data)
41
+ * }, [ slug ])
42
+ *
43
+ * // After fetching, the image will be on the `entry.data.featured_image` property.
44
+ * return (
45
+ * entry ? (
46
+ * <article>
47
+ * <h1>{entry.title}</h1>
48
+ * <ResponsiveImage image={entry.data.featured_image} />
49
+ * </article>
50
+ * ) : (
51
+ * <div>Loading...</div>
52
+ * )
53
+ * )
54
+ * }
55
+ *
56
+ * ```
57
+ *
58
+ * @param props Component props. See {@link ResponsiveImageProps} to see the
59
+ * available options.
60
+ * @group ResponsiveImage
61
+ */
14
62
  export declare const ResponsiveImage: ({ className, image, sizes, alt, variation, background, lazyRoot, lazyRootMargin, }: ResponsiveImageProps) => JSX.Element;
15
- export {};
63
+ export type { ResponsiveImageProps };
16
64
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ResponsiveImage/index.tsx"],"names":[],"mappings":"AAAA,OAAc,EACZ,SAAS,EACT,SAAS,EAKV,MAAM,OAAO,CAAA;AACd,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAKlD,eAAO,MAAM,oBAAoB,QAAO,SAMvC,CAAA;AAED,aAAK,oBAAoB,GAAG;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,WAAW,GAAG,MAAM,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC,WAAW,CAAC,GAAG,IAAI,CAAA;IACxC,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,eAAO,MAAM,eAAe,uFASzB,oBAAoB,KAAG,WA2GzB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ResponsiveImage/index.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,SAAS,EAAwC,MAAM,OAAO,CAAA;AAE9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAK9C;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,QAAO,SAMvC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,eAAO,MAAM,eAAe,uFASzB,oBAAoB,KAAG,WA2GzB,CAAA;AAED,YAAY,EAAE,oBAAoB,EAAE,CAAA"}
@@ -1,9 +1,67 @@
1
- import React, { useEffect, useMemo, useRef, useState, } from 'react';
1
+ import React, { useEffect, useMemo, useRef, useState } from 'react';
2
2
  const transparentImage = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
3
+ /**
4
+ * Renders a `<style>` tag with a rule that disables lazy-loading when JavaScript
5
+ * is disabled in the browser. This is useful to web crawlers that don't run
6
+ * JS files, which is important for SEO.
7
+ *
8
+ * You only need to render this component once in your application,
9
+ * preferably in the `<head>` section.
10
+ *
11
+ * @group ResponsiveImage
12
+ */
3
13
  export const GlobalLazyloadStyles = () => {
4
14
  return (React.createElement("noscript", null,
5
15
  React.createElement("style", null, 'img.sl-lazyload{display: none;}')));
6
16
  };
17
+ /**
18
+ * Renders an image from a given Starlight media object. The Starlight
19
+ * optimized image will be rendered by default if no `variation` prop is passed.
20
+ *
21
+ * If the `sizes` prop is passed, a responsive image will be rendered by
22
+ * generating a "src-set" property.
23
+ *
24
+ * The image will be lazy-loaded, which means that it should only load
25
+ * when the browser viewport gets near the image.
26
+ *
27
+ * @example Requesting an entry and rendering an image.
28
+ *
29
+ * Assume we created a "Posts" model with a slug of `posts`, and placed a Media
30
+ * File field with a key of `featured_image` on it.
31
+ *
32
+ * ```jsx
33
+ * import Starlight, { ResponsiveImage } from '@starlightcms/react-sdk'
34
+ *
35
+ * const EntryComponent = ({ slug }) => {
36
+ * const [entry, setEntry] = useState(null)
37
+ *
38
+ * useEffect(async () => {
39
+ * // This is just an example, you could fetch
40
+ * // the entry any way you want.
41
+ * const response = await Starlight.posts.entries.get(slug)
42
+ *
43
+ * setEntry(response.data)
44
+ * }, [ slug ])
45
+ *
46
+ * // After fetching, the image will be on the `entry.data.featured_image` property.
47
+ * return (
48
+ * entry ? (
49
+ * <article>
50
+ * <h1>{entry.title}</h1>
51
+ * <ResponsiveImage image={entry.data.featured_image} />
52
+ * </article>
53
+ * ) : (
54
+ * <div>Loading...</div>
55
+ * )
56
+ * )
57
+ * }
58
+ *
59
+ * ```
60
+ *
61
+ * @param props Component props. See {@link ResponsiveImageProps} to see the
62
+ * available options.
63
+ * @group ResponsiveImage
64
+ */
7
65
  export const ResponsiveImage = ({ className = '', image, sizes = '', alt = typeof image === 'string' ? '' : image.alt, variation = 'optimized', background = '', lazyRoot, lazyRootMargin = '200px', }) => {
8
66
  const imageRef = useRef(null);
9
67
  // When true, the image may load normally
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ResponsiveImage/index.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, {\n ReactNode,\n RefObject,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { MediaObject } from '@starlightcms/js-sdk'\n\nconst transparentImage =\n 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='\n\nexport const GlobalLazyloadStyles = (): ReactNode => {\n return (\n <noscript>\n <style>{'img.sl-lazyload{display: none;}'}</style>\n </noscript>\n )\n}\n\ntype ResponsiveImageProps = {\n className?: string\n image: MediaObject | string\n sizes?: string\n alt?: string\n variation?: string\n background?: string\n lazyRoot?: RefObject<HTMLElement> | null\n lazyRootMargin?: string\n}\n\nexport const ResponsiveImage = ({\n className = '',\n image,\n sizes = '',\n alt = typeof image === 'string' ? '' : image.alt,\n variation = 'optimized',\n background = '',\n lazyRoot,\n lazyRootMargin = '200px',\n}: ResponsiveImageProps): JSX.Element => {\n const imageRef = useRef<HTMLImageElement>(null)\n\n // When true, the image may load normally\n const [canLoad, setCanLoad] = useState(false)\n\n // When true, the image has been successfully loaded by the browser\n const [hasLoaded, setHasLoaded] = useState(false)\n\n // Get the optimized variation if available\n const source = useMemo(() => {\n // If the given image was a string, simply return it\n if (typeof image === 'string' || !image.files) return\n\n const chosenVariation = image.files.find(\n (file) => file.variation === variation\n )\n\n return chosenVariation\n ? chosenVariation\n : image.files.find((file) => file.variation === 'original')\n }, [image, variation])\n\n // Create a srcset\n const sourceSet = useMemo(() => {\n if (!source) return\n\n // source is only defined if image is a MediaObject, so we assert it as one\n const img = image as MediaObject\n\n const sets = []\n const large = img.files.find((file) => file.variation === 'large')\n const medium = img.files.find((file) => file.variation === 'medium')\n const thumbnail = img.files.find((file) => file.variation === 'thumbnail')\n\n if (thumbnail)\n sets.push(`${encodeURI(thumbnail.path)} ${thumbnail.meta?.width}w`)\n if (medium) sets.push(`${encodeURI(medium.path)} 600w`)\n if (large) sets.push(`${encodeURI(large.path)} 1200w`)\n sets.push(`${encodeURI(source.path)} ${source.meta?.width}w`)\n\n return sets.join(',')\n }, [source, image])\n\n const imageStyle = useMemo(() => {\n return {\n backgroundColor:\n background || hasLoaded || typeof image === 'string'\n ? 'transparent'\n : `#${source?.background_color ?? 'transparent'}`,\n }\n }, [background, source, hasLoaded, image])\n\n useEffect(() => {\n let ref: HTMLImageElement | null = null\n const observer = new IntersectionObserver(\n (entries, observer) => {\n if (entries[0].intersectionRatio > 0) {\n // Image entered the viewport, set it as loadable\n setCanLoad(true)\n\n // Stop observing the image\n observer.unobserve(ref as HTMLImageElement)\n }\n },\n {\n root: lazyRoot?.current,\n rootMargin: lazyRootMargin,\n }\n )\n\n if (imageRef.current) {\n ref = imageRef.current\n observer.observe(ref)\n }\n\n const loadHandler = () => {\n // After loading the image, the \"hasLoaded\" flag is used to hide the background color\n setHasLoaded(true)\n }\n\n ref?.addEventListener('load', loadHandler)\n\n return () => {\n if (ref) {\n observer.unobserve(ref)\n ref.removeEventListener('load', loadHandler)\n }\n }\n }, [source])\n\n return (\n <>\n <img\n ref={imageRef}\n className={'sl-lazyload ' + className}\n style={imageStyle}\n src={canLoad ? source?.path || (image as string) : transparentImage}\n srcSet={canLoad ? (sourceSet ? sourceSet : undefined) : undefined}\n sizes={canLoad ? (sourceSet ? sizes : undefined) : undefined}\n alt={alt}\n />\n <noscript>\n <img src={(source && source.path) || (image as string)} alt={alt} />\n </noscript>\n </>\n )\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ResponsiveImage/index.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { ReactNode, useEffect, useMemo, useRef, useState } from 'react'\nimport { MediaObject } from '@starlightcms/js-sdk'\nimport { ResponsiveImageProps } from './types'\n\nconst transparentImage =\n 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='\n\n/**\n * Renders a `<style>` tag with a rule that disables lazy-loading when JavaScript\n * is disabled in the browser. This is useful to web crawlers that don't run\n * JS files, which is important for SEO.\n *\n * You only need to render this component once in your application,\n * preferably in the `<head>` section.\n *\n * @group ResponsiveImage\n */\nexport const GlobalLazyloadStyles = (): ReactNode => {\n return (\n <noscript>\n <style>{'img.sl-lazyload{display: none;}'}</style>\n </noscript>\n )\n}\n\n/**\n * Renders an image from a given Starlight media object. The Starlight\n * optimized image will be rendered by default if no `variation` prop is passed.\n *\n * If the `sizes` prop is passed, a responsive image will be rendered by\n * generating a \"src-set\" property.\n *\n * The image will be lazy-loaded, which means that it should only load\n * when the browser viewport gets near the image.\n *\n * @example Requesting an entry and rendering an image.\n *\n * Assume we created a \"Posts\" model with a slug of `posts`, and placed a Media\n * File field with a key of `featured_image` on it.\n *\n * ```jsx\n * import Starlight, { ResponsiveImage } from '@starlightcms/react-sdk'\n *\n * const EntryComponent = ({ slug }) => {\n * const [entry, setEntry] = useState(null)\n *\n * useEffect(async () => {\n * // This is just an example, you could fetch\n * // the entry any way you want.\n * const response = await Starlight.posts.entries.get(slug)\n *\n * setEntry(response.data)\n * }, [ slug ])\n *\n * // After fetching, the image will be on the `entry.data.featured_image` property.\n * return (\n * entry ? (\n * <article>\n * <h1>{entry.title}</h1>\n * <ResponsiveImage image={entry.data.featured_image} />\n * </article>\n * ) : (\n * <div>Loading...</div>\n * )\n * )\n * }\n *\n * ```\n *\n * @param props Component props. See {@link ResponsiveImageProps} to see the\n * available options.\n * @group ResponsiveImage\n */\nexport const ResponsiveImage = ({\n className = '',\n image,\n sizes = '',\n alt = typeof image === 'string' ? '' : image.alt,\n variation = 'optimized',\n background = '',\n lazyRoot,\n lazyRootMargin = '200px',\n}: ResponsiveImageProps): JSX.Element => {\n const imageRef = useRef<HTMLImageElement>(null)\n\n // When true, the image may load normally\n const [canLoad, setCanLoad] = useState(false)\n\n // When true, the image has been successfully loaded by the browser\n const [hasLoaded, setHasLoaded] = useState(false)\n\n // Get the optimized variation if available\n const source = useMemo(() => {\n // If the given image was a string, simply return it\n if (typeof image === 'string' || !image.files) return\n\n const chosenVariation = image.files.find(\n (file) => file.variation === variation\n )\n\n return chosenVariation\n ? chosenVariation\n : image.files.find((file) => file.variation === 'original')\n }, [image, variation])\n\n // Create a srcset\n const sourceSet = useMemo(() => {\n if (!source) return\n\n // source is only defined if image is a MediaObject, so we assert it as one\n const img = image as MediaObject\n\n const sets = []\n const large = img.files.find((file) => file.variation === 'large')\n const medium = img.files.find((file) => file.variation === 'medium')\n const thumbnail = img.files.find((file) => file.variation === 'thumbnail')\n\n if (thumbnail)\n sets.push(`${encodeURI(thumbnail.path)} ${thumbnail.meta?.width}w`)\n if (medium) sets.push(`${encodeURI(medium.path)} 600w`)\n if (large) sets.push(`${encodeURI(large.path)} 1200w`)\n sets.push(`${encodeURI(source.path)} ${source.meta?.width}w`)\n\n return sets.join(',')\n }, [source, image])\n\n const imageStyle = useMemo(() => {\n return {\n backgroundColor:\n background || hasLoaded || typeof image === 'string'\n ? 'transparent'\n : `#${source?.background_color ?? 'transparent'}`,\n }\n }, [background, source, hasLoaded, image])\n\n useEffect(() => {\n let ref: HTMLImageElement | null = null\n const observer = new IntersectionObserver(\n (entries, observer) => {\n if (entries[0].intersectionRatio > 0) {\n // Image entered the viewport, set it as loadable\n setCanLoad(true)\n\n // Stop observing the image\n observer.unobserve(ref as HTMLImageElement)\n }\n },\n {\n root: lazyRoot?.current,\n rootMargin: lazyRootMargin,\n }\n )\n\n if (imageRef.current) {\n ref = imageRef.current\n observer.observe(ref)\n }\n\n const loadHandler = () => {\n // After loading the image, the \"hasLoaded\" flag is used to hide the background color\n setHasLoaded(true)\n }\n\n ref?.addEventListener('load', loadHandler)\n\n return () => {\n if (ref) {\n observer.unobserve(ref)\n ref.removeEventListener('load', loadHandler)\n }\n }\n }, [source])\n\n return (\n <>\n <img\n ref={imageRef}\n className={'sl-lazyload ' + className}\n style={imageStyle}\n src={canLoad ? source?.path || (image as string) : transparentImage}\n srcSet={canLoad ? (sourceSet ? sourceSet : undefined) : undefined}\n sizes={canLoad ? (sourceSet ? sizes : undefined) : undefined}\n alt={alt}\n />\n <noscript>\n <img src={(source && source.path) || (image as string)} alt={alt} />\n </noscript>\n </>\n )\n}\n\nexport type { ResponsiveImageProps }\n"]}
@@ -0,0 +1,52 @@
1
+ import { MediaObject } from '@starlightcms/js-sdk';
2
+ import { RefObject } from 'react';
3
+ /**
4
+ * Props accepted by the {@link ResponsiveImage} component.
5
+ * @group ResponsiveImage
6
+ */
7
+ export interface ResponsiveImageProps {
8
+ className?: string;
9
+ /**
10
+ * The image to render. It should be a URI string or the object returned by
11
+ * Starlight on a Media File field. Required.
12
+ */
13
+ image: MediaObject | string;
14
+ /**
15
+ * An HTML <img> `sizes` attribute. If provided, the browser will render the
16
+ * best fit image size variation to the current viewport size. See
17
+ * [the MDN documentation on the sizes property](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-sizes)
18
+ * to learn how to configure this attribute.
19
+ */
20
+ sizes?: string;
21
+ /**
22
+ * Alternate text description of the image. If set and the given image is a
23
+ * Starlight media object, it will overwrite this image's alternative text
24
+ * set in Starlight.
25
+ */
26
+ alt?: string;
27
+ /**
28
+ * Defines which image variation will be rendered. Defaults to `optimized`.
29
+ */
30
+ variation?: string;
31
+ /**
32
+ * Defines the background color of the image while it loads. It accepts any
33
+ * CSS color, including `transparent`. Defaults to the color generated by
34
+ * Starlight when the image was uploaded, or transparent when the given image
35
+ * is a URI string.
36
+ */
37
+ background?: string;
38
+ /**
39
+ * Defines the scrollable parent of the image. Set this to the nearest
40
+ * scrollable HTMLElement parent of this image if lazy-loading is not working.
41
+ * See [the MDN documentation on IntersectionObserver.root](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/root)
42
+ * to learn more.
43
+ */
44
+ lazyRoot?: RefObject<HTMLElement> | null;
45
+ /**
46
+ * Defines how close to the viewport an image has to be to start loading.
47
+ * See [the MDN documentation on IntersectionObserver.rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/rootMargin)
48
+ * to learn more. Defaults to 200px.
49
+ */
50
+ lazyRootMargin?: string;
51
+ }
52
+ //# sourceMappingURL=types.d.ts.map