@financial-times/cp-content-pipeline-ui 0.1.2

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 (89) hide show
  1. package/.toolkitrc.yml +12 -0
  2. package/CHANGELOG.md +62 -0
  3. package/README.md +27 -0
  4. package/jest.config.mjs +6 -0
  5. package/lib/components/Body/index.d.ts +8 -0
  6. package/lib/components/Body/index.js +22 -0
  7. package/lib/components/Body/index.js.map +1 -0
  8. package/lib/components/Byline/index.d.ts +7 -0
  9. package/lib/components/Byline/index.js +12 -0
  10. package/lib/components/Byline/index.js.map +1 -0
  11. package/lib/components/ImageSet/index.d.ts +3 -0
  12. package/lib/components/ImageSet/index.js +64 -0
  13. package/lib/components/ImageSet/index.js.map +1 -0
  14. package/lib/components/Layout/index.d.ts +17 -0
  15. package/lib/components/Layout/index.js +20 -0
  16. package/lib/components/Layout/index.js.map +1 -0
  17. package/lib/components/ListItem/index.d.ts +4 -0
  18. package/lib/components/ListItem/index.js +11 -0
  19. package/lib/components/ListItem/index.js.map +1 -0
  20. package/lib/components/Recommended/RecommendedTitle.d.ts +4 -0
  21. package/lib/components/Recommended/RecommendedTitle.js +11 -0
  22. package/lib/components/Recommended/RecommendedTitle.js.map +1 -0
  23. package/lib/components/Recommended/index.d.ts +3 -0
  24. package/lib/components/Recommended/index.js +16 -0
  25. package/lib/components/Recommended/index.js.map +1 -0
  26. package/lib/components/RichText/index.d.ts +16 -0
  27. package/lib/components/RichText/index.js +112 -0
  28. package/lib/components/RichText/index.js.map +1 -0
  29. package/lib/components/RichText/index.test.d.ts +1 -0
  30. package/lib/components/RichText/index.test.js +170 -0
  31. package/lib/components/RichText/index.test.js.map +1 -0
  32. package/lib/components/Topper/Columnist.d.ts +5 -0
  33. package/lib/components/Topper/Columnist.js +14 -0
  34. package/lib/components/Topper/Columnist.js.map +1 -0
  35. package/lib/components/Topper/Headline.d.ts +7 -0
  36. package/lib/components/Topper/Headline.js +20 -0
  37. package/lib/components/Topper/Headline.js.map +1 -0
  38. package/lib/components/Topper/Headshot.d.ts +4 -0
  39. package/lib/components/Topper/Headshot.js +12 -0
  40. package/lib/components/Topper/Headshot.js.map +1 -0
  41. package/lib/components/Topper/Intro.d.ts +7 -0
  42. package/lib/components/Topper/Intro.js +13 -0
  43. package/lib/components/Topper/Intro.js.map +1 -0
  44. package/lib/components/Topper/Picture.d.ts +8 -0
  45. package/lib/components/Topper/Picture.js +27 -0
  46. package/lib/components/Topper/Picture.js.map +1 -0
  47. package/lib/components/Topper/Tags.d.ts +9 -0
  48. package/lib/components/Topper/Tags.js +24 -0
  49. package/lib/components/Topper/Tags.js.map +1 -0
  50. package/lib/components/Topper/Wrapper.d.ts +8 -0
  51. package/lib/components/Topper/Wrapper.js +20 -0
  52. package/lib/components/Topper/Wrapper.js.map +1 -0
  53. package/lib/components/Topper/index.d.ts +7 -0
  54. package/lib/components/Topper/index.js +39 -0
  55. package/lib/components/Topper/index.js.map +1 -0
  56. package/lib/components/UnorderedList/index.d.ts +4 -0
  57. package/lib/components/UnorderedList/index.js +11 -0
  58. package/lib/components/UnorderedList/index.js.map +1 -0
  59. package/lib/index.d.ts +9 -0
  60. package/lib/index.js +27 -0
  61. package/lib/index.js.map +1 -0
  62. package/lib/index.test.d.ts +1 -0
  63. package/lib/index.test.js +4 -0
  64. package/lib/index.test.js.map +1 -0
  65. package/package.json +27 -0
  66. package/src/components/Body/index.tsx +35 -0
  67. package/src/components/Byline/index.tsx +12 -0
  68. package/src/components/ImageSet/index.tsx +123 -0
  69. package/src/components/Layout/index.tsx +44 -0
  70. package/src/components/ListItem/index.tsx +5 -0
  71. package/src/components/Recommended/RecommendedTitle.tsx +9 -0
  72. package/src/components/Recommended/index.tsx +23 -0
  73. package/src/components/RichText/README.md +34 -0
  74. package/src/components/RichText/index.test.tsx +166 -0
  75. package/src/components/RichText/index.tsx +136 -0
  76. package/src/components/Topper/Columnist.tsx +21 -0
  77. package/src/components/Topper/Headline.tsx +27 -0
  78. package/src/components/Topper/Headshot.tsx +9 -0
  79. package/src/components/Topper/Intro.tsx +16 -0
  80. package/src/components/Topper/Picture.tsx +70 -0
  81. package/src/components/Topper/Tags.tsx +61 -0
  82. package/src/components/Topper/Wrapper.tsx +26 -0
  83. package/src/components/Topper/index.tsx +69 -0
  84. package/src/components/UnorderedList/index.tsx +5 -0
  85. package/src/index.test.ts +1 -0
  86. package/src/index.ts +9 -0
  87. package/src/types/x-teaser.d.ts +1 -0
  88. package/tsconfig.json +14 -0
  89. package/tsconfig.tsbuildinfo +1 -0
package/.toolkitrc.yml ADDED
@@ -0,0 +1,12 @@
1
+ plugins:
2
+ - '@dotcom-tool-kit/npm'
3
+ - '../../tool-kit/placeholder-hook'
4
+
5
+ hooks:
6
+ publish:tag:
7
+ - NpmPublish
8
+
9
+ options:
10
+ '../../tool-kit/placeholder-hook':
11
+ hooks:
12
+ - publish:tag
package/CHANGELOG.md ADDED
@@ -0,0 +1,62 @@
1
+ # Changelog
2
+
3
+ ## [0.1.2](https://github.com/Financial-Times/cp-content-pipeline/compare/cp-content-pipeline-ui-v0.1.1...cp-content-pipeline-ui-v0.1.2) (2022-09-27)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * make an innocuous change to trigger a rerelease of these packages ([7ed623d](https://github.com/Financial-Times/cp-content-pipeline/commit/7ed623d126ddc00bc99ee050ddbba1cb18b01ee9))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * devDependencies
15
+ * @financial-times/cp-content-pipeline-client bumped from ^0.2.0 to ^0.2.1
16
+
17
+ ## [0.1.1](https://github.com/Financial-Times/cp-content-pipeline/compare/cp-content-pipeline-ui-v0.1.0...cp-content-pipeline-ui-v0.1.1) (2022-09-27)
18
+
19
+
20
+ ### Features
21
+
22
+ * add Columnist tag to Opinion topper ([b50dc42](https://github.com/Financial-Times/cp-content-pipeline/commit/b50dc42113f3e477b5b30588d886e84fd800d718))
23
+ * add componentMap record for Link ([99a51bd](https://github.com/Financial-Times/cp-content-pipeline/commit/99a51bdb1eda59e6c5d226094a70988f6490a123))
24
+ * add data-image-type attribute to image ([88200bb](https://github.com/Financial-Times/cp-content-pipeline/commit/88200bb366374a6e926124af68564b9a60581508))
25
+ * add Headshot to topper ([a832390](https://github.com/Financial-Times/cp-content-pipeline/commit/a8323906e74d1fdd5d877e12efb9d2168ba20fef))
26
+ * add image caption and alt ([3dd2dd8](https://github.com/Financial-Times/cp-content-pipeline/commit/3dd2dd8cf88a33f8114470b57ea8cba4ea69e352))
27
+ * add LeadImages to Topper ([cb7ad3a](https://github.com/Financial-Times/cp-content-pipeline/commit/cb7ad3af32f5d63fe949686dc2a0d4b80e940f4c))
28
+ * add metadata and BrandedTopper ([57fc4c5](https://github.com/Financial-Times/cp-content-pipeline/commit/57fc4c524b2b690ba993563d971ad10b14b85c10))
29
+ * add OpinionTopper type ([4fc3e38](https://github.com/Financial-Times/cp-content-pipeline/commit/4fc3e386b6cd45b8dc06bee51515f6a8889bd817))
30
+ * add PictureInline variant ([7d3f721](https://github.com/Financial-Times/cp-content-pipeline/commit/7d3f721fec6c9a79a21d076a5517955a15b7089d))
31
+ * add topper image copyright ([49f7c26](https://github.com/Financial-Times/cp-content-pipeline/commit/49f7c26f0ea9a3df1ec3b8ada8c1e9266b824c9c))
32
+ * add topper modifiers ([0ced250](https://github.com/Financial-Times/cp-content-pipeline/commit/0ced25069427db0b1e32dad9b50491cda71b9129))
33
+ * add width attribute to image ([c64f550](https://github.com/Financial-Times/cp-content-pipeline/commit/c64f550b843ead71aef0de839d568b2271ef55e2))
34
+ * allow different image widths and breakpoints ([1210b62](https://github.com/Financial-Times/cp-content-pipeline/commit/1210b62e9f778ee09a9ecd1998bffbefb4234c2d))
35
+ * create byline component and add it to topper ([56d6ed1](https://github.com/Financial-Times/cp-content-pipeline/commit/56d6ed1af1dd31e2f51e95b5e538578d5802a726))
36
+ * expect all imagesets to query for a standard image ([e969747](https://github.com/Financial-Times/cp-content-pipeline/commit/e96974764a6f19eceb3f80e281d046c91e1cbdef))
37
+ * export all UI components in the index ([c7726c2](https://github.com/Financial-Times/cp-content-pipeline/commit/c7726c23adfaaafed846751f2f0a5dc5ce071d53))
38
+ * provide all possible resolutions for image sources ([4d9d586](https://github.com/Financial-Times/cp-content-pipeline/commit/4d9d586ec4578bbd9d8d12e5333ad1f5f9f4e1ff))
39
+ * render all imagesets as <picture> elements ([5ac2051](https://github.com/Financial-Times/cp-content-pipeline/commit/5ac20513a2e07cd7378f21e8bf49e635ad03ba62))
40
+ * render an img tag for single images ([772058e](https://github.com/Financial-Times/cp-content-pipeline/commit/772058e26803b9092fb2de671b0ee0426ec4fb5d))
41
+ * render Layout components ([a134e30](https://github.com/Financial-Times/cp-content-pipeline/commit/a134e301f6eaddd6eb665489b76dfd36097a8903))
42
+ * render topper intro ([e0f5c4c](https://github.com/Financial-Times/cp-content-pipeline/commit/e0f5c4cce964ebf460806e6175e6a7ad180d1780))
43
+ * reserve image width/height to prevent layout shift ([59d2d31](https://github.com/Financial-Times/cp-content-pipeline/commit/59d2d314625f47b73f422ac1a71d7c3afe7fbe6f))
44
+ * set class on article body based on full width images ([337d694](https://github.com/Financial-Times/cp-content-pipeline/commit/337d694486b9d6f8d65c74fdf12e918b01410f4a))
45
+ * turn Body into a generic RichText type ([e0a2b04](https://github.com/Financial-Times/cp-content-pipeline/commit/e0a2b04c8fbadcd9779b53aa30a2c16387b768db))
46
+ * use correct class for standfirst/summary ([6ad5a1f](https://github.com/Financial-Times/cp-content-pipeline/commit/6ad5a1f9193a733ede550f034863b4009f70b228))
47
+ * use correct image data for different topper themes ([319abde](https://github.com/Financial-Times/cp-content-pipeline/commit/319abde3c62b57f97ea0ed109147517a47ac8848))
48
+ * use ImageSource type for image sources ([db767df](https://github.com/Financial-Times/cp-content-pipeline/commit/db767dfd6cd505b33981373d849d70ae0a343dae))
49
+ * use interfaces to represent topper types ([c032c97](https://github.com/Financial-Times/cp-content-pipeline/commit/c032c9780fef7f28b1f9259697e1f234a9466e1e))
50
+
51
+
52
+ ### Bug Fixes
53
+
54
+ * fix media query output when between widths ([7e1f8c6](https://github.com/Financial-Times/cp-content-pipeline/commit/7e1f8c6ea7d96207656920a7054695255d4a4b38))
55
+ * only render figcaption if there is a copyright ([e3a9e93](https://github.com/Financial-Times/cp-content-pipeline/commit/e3a9e9363b380ad4422daea89974c05036a3a484))
56
+
57
+
58
+ ### Dependencies
59
+
60
+ * The following workspace dependencies were updated
61
+ * devDependencies
62
+ * @financial-times/cp-content-pipeline-client bumped from ^0.0.0 to ^0.2.0
package/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # Components
2
+
3
+ This package provides a set of React components that can be used to render the content received from the GraphQL API.
4
+
5
+ The `<Body>` component does the bulk of the work in rendering the entire content tree into a set of defined React components.
6
+
7
+ A default set of components have been provided for rendering all elements that constitute an FT content body - however these can be overridden for clients that have different rendering requirements.
8
+
9
+ ## Installing
10
+
11
+ TODO
12
+
13
+ ## Usage
14
+
15
+ ```
16
+ import { Body, Recommended } from '@financial-times/cp-content-pipeline-ui'
17
+ const removeOutboundLinks = (props) => <span>{...props.children}</span>
18
+ const removeImageFromRecommended = (props) => <Recommended {...props} teaser={{ ...props.teaser, showImage:false }}/>
19
+
20
+ ...
21
+ const componentOverrides = {
22
+ Link: removeOutboundLinks,
23
+ Recommended: removeImageFromRecommended
24
+ };
25
+ <Body content={articleData} components={componentOverrides}>
26
+
27
+ ```
@@ -0,0 +1,6 @@
1
+ import base from '../../jest.config.base.mjs'
2
+
3
+ export default {
4
+ ...base,
5
+ testEnvironment: 'jsdom',
6
+ }
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ import type { ArticleQuery } from '@financial-times/cp-content-pipeline-client';
3
+ import type { ComponentMapRecord } from '../RichText/index.js';
4
+ export declare type BodyProps = {
5
+ content: ArticleQuery['content'];
6
+ components: ComponentMapRecord;
7
+ };
8
+ export default function Body({ content, components }: BodyProps): JSX.Element | null;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ const RichText_1 = __importDefault(require("../RichText"));
8
+ function Body({ content, components }) {
9
+ var _a;
10
+ if (!((_a = content === null || content === void 0 ? void 0 : content.body) === null || _a === void 0 ? void 0 : _a.structured)) {
11
+ return null;
12
+ }
13
+ return (react_1.default.createElement("div", { className: "article-content" },
14
+ react_1.default.createElement("article", { id: "site-content", className: "article article-grid" },
15
+ react_1.default.createElement("div", { className: "article__content" },
16
+ react_1.default.createElement("div", { className: "article__content-body n-content-body js-article__content-body" },
17
+ react_1.default.createElement("div", { className: "article__content-body n-content-body js-article__content-body" },
18
+ react_1.default.createElement("article", { className: "n-content-body" },
19
+ react_1.default.createElement(RichText_1.default, { structuredContent: content.body.structured, components: components }))))))));
20
+ }
21
+ exports.default = Body;
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Body/index.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAyB;AACzB,2DAAkC;AAUlC,SAAwB,IAAI,CAAC,EAAE,OAAO,EAAE,UAAU,EAAa;;IAC7D,IAAI,CAAC,CAAA,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,0CAAE,UAAU,CAAA,EAAE;QAC9B,OAAO,IAAI,CAAA;KACZ;IAED,OAAO,CACL,uCAAK,SAAS,EAAC,iBAAiB;QAC9B,2CAAS,EAAE,EAAC,cAAc,EAAC,SAAS,EAAC,sBAAsB;YACzD,uCAAK,SAAS,EAAC,kBAAkB;gBAC/B,uCAAK,SAAS,EAAC,+DAA+D;oBAC5E,uCAAK,SAAS,EAAC,+DAA+D;wBAC5E,2CAAS,SAAS,EAAC,gBAAgB;4BACjC,8BAAC,kBAAQ,IACP,iBAAiB,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU,EAC1C,UAAU,EAAE,UAAU,GACtB,CACM,CACN,CACF,CACF,CACE,CACN,CACP,CAAA;AACH,CAAC;AAvBD,uBAuBC"}
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ import { StructuredTreeFragment } from "@financial-times/cp-content-pipeline-client";
3
+ declare type BylineProps = {
4
+ structuredContent: StructuredTreeFragment;
5
+ };
6
+ export default function Byline({ structuredContent }: BylineProps): JSX.Element;
7
+ export {};
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ const index_js_1 = __importDefault(require("../RichText/index.js"));
8
+ function Byline({ structuredContent }) {
9
+ return react_1.default.createElement(index_js_1.default, { structuredContent: structuredContent });
10
+ }
11
+ exports.default = Byline;
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Byline/index.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAyB;AAGzB,oEAA4C;AAM5C,SAAwB,MAAM,CAAC,EAAE,iBAAiB,EAAe;IACzD,OAAO,8BAAC,kBAAQ,IAAC,iBAAiB,EAAE,iBAAiB,GAAI,CAAA;AACjE,CAAC;AAFD,yBAEC"}
@@ -0,0 +1,3 @@
1
+ /// <reference types="react" />
2
+ import type { ImageSetFragment } from '@financial-times/cp-content-pipeline-client';
3
+ export default function ImageSet(fragment: ImageSetFragment): JSX.Element;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ const srcSet = (image) => image.sources.map((src) => `${src.url} ${src.dpr}x`).join(',');
8
+ const figureClassNameMap = {
9
+ PictureFullBleed: 'n-content-picture n-content-picture--wide n-content-layout__container',
10
+ PictureInline: 'n-content-image n-content-image--inline',
11
+ PictureStandard: 'n-content-image n-content-image--full',
12
+ };
13
+ function Source({ image }) {
14
+ const media = [
15
+ image.minDisplayWidth && `(min-width: ${image.minDisplayWidth})`,
16
+ image.maxDisplayWidth && `(max-width: ${image.maxDisplayWidth})`,
17
+ ]
18
+ .filter(Boolean)
19
+ .join(' and ');
20
+ // only need to have sources for different screen breakpoints
21
+ if (!media.length)
22
+ return null;
23
+ return (react_1.default.createElement("source", { media: media, srcSet: srcSet(image), width: image.originalWidth, height: image.originalHeight }));
24
+ }
25
+ function Image({ image, alt, type }) {
26
+ const props = {
27
+ src: image.sources[0].url,
28
+ alt,
29
+ srcSet: image.sources.length > 1 ? srcSet(image) : undefined,
30
+ 'data-image-type': type.toLowerCase(),
31
+ width: image.originalWidth,
32
+ height: image.originalHeight,
33
+ };
34
+ return react_1.default.createElement("img", { ...props });
35
+ }
36
+ const isValidImage = (image) => Boolean(image) && image !== 'PictureImages';
37
+ const validImages = (images) => Object.values(images).filter(isValidImage);
38
+ function Figure({ picture }) {
39
+ if (!picture.images) {
40
+ throw new Error(`ImageSet of type ${picture.__typename} has no images. Check that they are present in the query`);
41
+ }
42
+ if (!picture.images.standard ||
43
+ 'minDisplayWidth' in picture.images.standard ||
44
+ 'maxDisplayWidth' in picture.images.standard) {
45
+ throw new Error(`ImageSet must include a "standard" image, without any breakpoint restrictions.`);
46
+ }
47
+ const pictureImages = validImages(picture.images);
48
+ return (react_1.default.createElement("figure", { className: figureClassNameMap[picture.__typename] || 'n-content-image' },
49
+ react_1.default.createElement("picture", null,
50
+ pictureImages.map((image, index) => (react_1.default.createElement(Source, { key: index, image: image }))),
51
+ react_1.default.createElement(Image, { image: picture.images.standard, alt: picture.alt, type: picture.imageType })),
52
+ picture.caption && (react_1.default.createElement("figcaption", { className: "n-content-picture__caption" }, picture.caption))));
53
+ }
54
+ function ImageSet(fragment) {
55
+ if (fragment.picture.__typename === 'PictureFullBleed') {
56
+ return (react_1.default.createElement("div", { className: "n-content-layout", "data-layout-width": "full-grid" },
57
+ react_1.default.createElement(Figure, { ...fragment })));
58
+ }
59
+ else {
60
+ return react_1.default.createElement(Figure, { ...fragment });
61
+ }
62
+ }
63
+ exports.default = ImageSet;
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ImageSet/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { ReactNode } from 'react';
2
+ declare type LayoutProps = {
3
+ children: ReactNode;
4
+ dataLayoutName: string;
5
+ dataLayoutWidth: 'full-grid' | 'fullWidth';
6
+ };
7
+ declare type LayoutContainerProps = {
8
+ children: ReactNode;
9
+ };
10
+ declare type LayoutSlotProps = {
11
+ children: ReactNode;
12
+ dataLayoutWidth: string;
13
+ };
14
+ export declare function Layout({ children, dataLayoutName, dataLayoutWidth, }: LayoutProps): JSX.Element;
15
+ export declare function LayoutContainer({ children }: LayoutContainerProps): JSX.Element;
16
+ export declare function LayoutSlot({ children, dataLayoutWidth }: LayoutSlotProps): JSX.Element;
17
+ export {};
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LayoutSlot = exports.LayoutContainer = exports.Layout = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ function Layout({ children, dataLayoutName, dataLayoutWidth, }) {
9
+ return (react_1.default.createElement("div", { className: "n-content-layout", "data-layout-name": dataLayoutName, "data-layout-width": dataLayoutWidth }, children));
10
+ }
11
+ exports.Layout = Layout;
12
+ function LayoutContainer({ children }) {
13
+ return react_1.default.createElement("div", { className: "n-content-layout__container" }, children);
14
+ }
15
+ exports.LayoutContainer = LayoutContainer;
16
+ function LayoutSlot({ children, dataLayoutWidth }) {
17
+ return (react_1.default.createElement("div", { className: "n-content-layout__slot", "data-layout-width": dataLayoutWidth }, children));
18
+ }
19
+ exports.LayoutSlot = LayoutSlot;
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Layout/index.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAwC;AAiBxC,SAAgB,MAAM,CAAC,EACrB,QAAQ,EACR,cAAc,EACd,eAAe,GACH;IACZ,OAAO,CACL,uCACE,SAAS,EAAC,kBAAkB,sBACV,cAAc,uBACb,eAAe,IAEjC,QAAQ,CACL,CACP,CAAA;AACH,CAAC;AAdD,wBAcC;AAED,SAAgB,eAAe,CAAC,EAAE,QAAQ,EAAwB;IAChE,OAAO,uCAAK,SAAS,EAAC,6BAA6B,IAAE,QAAQ,CAAO,CAAA;AACtE,CAAC;AAFD,0CAEC;AAED,SAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAmB;IACvE,OAAO,CACL,uCAAK,SAAS,EAAC,wBAAwB,uBAAoB,eAAe,IACvE,QAAQ,CACL,CACP,CAAA;AACH,CAAC;AAND,gCAMC"}
@@ -0,0 +1,4 @@
1
+ import { ReactNode } from 'react';
2
+ export default function ListItem({ children }: {
3
+ children: ReactNode;
4
+ }): JSX.Element;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ function ListItem({ children }) {
8
+ return react_1.default.createElement("li", null, children);
9
+ }
10
+ exports.default = ListItem;
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ListItem/index.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAwC;AAExC,SAAwB,QAAQ,CAAC,EAAE,QAAQ,EAA2B;IACpE,OAAO,0CAAK,QAAQ,CAAM,CAAA;AAC5B,CAAC;AAFD,2BAEC"}
@@ -0,0 +1,4 @@
1
+ import { ReactNode } from 'react';
2
+ export default function RecommendedTitle({ children, }: {
3
+ children: ReactNode;
4
+ }): JSX.Element;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ function RecommendedTitle({ children, }) {
8
+ return react_1.default.createElement("h2", { className: "n-content-recommended__title" }, children);
9
+ }
10
+ exports.default = RecommendedTitle;
11
+ //# sourceMappingURL=RecommendedTitle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RecommendedTitle.js","sourceRoot":"","sources":["../../../src/components/Recommended/RecommendedTitle.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAwC;AAExC,SAAwB,gBAAgB,CAAC,EACvC,QAAQ,GAGT;IACC,OAAO,sCAAI,SAAS,EAAC,8BAA8B,IAAE,QAAQ,CAAM,CAAA;AACrE,CAAC;AAND,mCAMC"}
@@ -0,0 +1,3 @@
1
+ /// <reference types="react" />
2
+ import type { RecommendedFragment } from '@financial-times/cp-content-pipeline-client';
3
+ export default function RecommendedComponent({ title, teaser, }: RecommendedFragment): JSX.Element;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const react_1 = __importDefault(require("react"));
7
+ //HACK: worked around missing Teaser type by declaring a module x-teaser.d.ts
8
+ const Teaser_cjs_js_1 = require("@financial-times/x-teaser/dist/Teaser.cjs.js");
9
+ const RecommendedTitle_1 = __importDefault(require("./RecommendedTitle"));
10
+ function RecommendedComponent({ title, teaser, }) {
11
+ return (react_1.default.createElement("aside", { className: "n-content-recommended--single-story" },
12
+ react_1.default.createElement(RecommendedTitle_1.default, null, title),
13
+ react_1.default.createElement(Teaser_cjs_js_1.Teaser, { modifiers: ['stacked'], ...Teaser_cjs_js_1.presets.SmallHeavy, ...teaser })));
14
+ }
15
+ exports.default = RecommendedComponent;
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Recommended/index.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAyB;AAEzB,6EAA6E;AAC7E,gFAA8E;AAC9E,0EAAiD;AAIjD,SAAwB,oBAAoB,CAAC,EAC3C,KAAK,EACL,MAAM,GACc;IACpB,OAAO,CACL,yCAAO,SAAS,EAAC,qCAAqC;QACpD,8BAAC,0BAAgB,QAAE,KAAK,CAAoB;QAC5C,8BAAC,sBAAM,IACL,SAAS,EAAE,CAAC,SAAS,CAAC,KAClB,uBAAO,CAAC,UAAU,KAClB,MAAM,GACV,CACI,CACT,CAAA;AACH,CAAC;AAdD,uCAcC"}
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import * as hast from 'hast';
3
+ import type { Reference, StructuredContentFragment } from '@financial-times/cp-content-pipeline-client';
4
+ export declare type ComponentMapRecord = Record<string, React.ElementType>;
5
+ export declare type RenderHastTreeArguments = {
6
+ root: hast.Root;
7
+ components: ComponentMapRecord;
8
+ references?: Reference[];
9
+ };
10
+ declare type WithOptionalProperty<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
11
+ export declare type RichTextProps = {
12
+ structuredContent: WithOptionalProperty<StructuredContentFragment, 'references'>;
13
+ components?: ComponentMapRecord;
14
+ };
15
+ export default function RichText({ structuredContent, components, }: RichTextProps): JSX.Element | null;
16
+ export {};
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = 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);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
26
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
27
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
28
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
29
+ };
30
+ var __importDefault = (this && this.__importDefault) || function (mod) {
31
+ return (mod && mod.__esModule) ? mod : { "default": mod };
32
+ };
33
+ var _HastToJSX_instances, _HastToJSX_getPropsForNode, _HastToJSX_renderChild;
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ const react_1 = __importStar(require("react"));
36
+ const Recommended_1 = __importDefault(require("../Recommended"));
37
+ const ImageSet_1 = __importDefault(require("../ImageSet"));
38
+ const RecommendedTitle_1 = __importDefault(require("../Recommended/RecommendedTitle"));
39
+ const UnorderedList_1 = __importDefault(require("../UnorderedList"));
40
+ const ListItem_1 = __importDefault(require("../ListItem"));
41
+ const Layout_1 = require("../Layout");
42
+ /* This will be the default set of components we provide, that most
43
+ * clients can use to render a workable article page
44
+ */
45
+ const componentMap = {
46
+ Paragraph: 'p',
47
+ Recommended: Recommended_1.default,
48
+ UnorderedList: UnorderedList_1.default,
49
+ ListItem: ListItem_1.default,
50
+ FTContent: (props) => react_1.default.createElement("a", { href: props.url }, props.children),
51
+ RecommendedTitle: RecommendedTitle_1.default,
52
+ Link: (props) => react_1.default.createElement("a", { href: props.href }, props.children),
53
+ ImageSet: ImageSet_1.default,
54
+ Layout: Layout_1.Layout,
55
+ LayoutContainer: Layout_1.LayoutContainer,
56
+ LayoutSlot: Layout_1.LayoutSlot,
57
+ LayoutImage: ImageSet_1.default,
58
+ Experimental: (props) => props.children,
59
+ };
60
+ function isHastElement(element) {
61
+ return element.tagName !== undefined;
62
+ }
63
+ class HastToJSX {
64
+ constructor(components, references) {
65
+ _HastToJSX_instances.add(this);
66
+ this.index = 0;
67
+ this.components = components;
68
+ this.references = references;
69
+ }
70
+ render(tree) {
71
+ const children = tree.children.map((node) => __classPrivateFieldGet(this, _HastToJSX_instances, "m", _HastToJSX_renderChild).call(this, node));
72
+ return react_1.default.createElement(react_1.default.Fragment, null, children);
73
+ }
74
+ }
75
+ _HastToJSX_instances = new WeakSet(), _HastToJSX_getPropsForNode = function _HastToJSX_getPropsForNode(node) {
76
+ var _a, _b, _c;
77
+ const reference = typeof ((_a = node.properties) === null || _a === void 0 ? void 0 : _a.dataReferenceId) === 'number'
78
+ ? (_b = this.references) === null || _b === void 0 ? void 0 : _b[(_c = node.properties) === null || _c === void 0 ? void 0 : _c.dataReferenceId]
79
+ : {};
80
+ return {
81
+ ...node.properties,
82
+ ...reference,
83
+ key: this.index++,
84
+ };
85
+ }, _HastToJSX_renderChild = function _HastToJSX_renderChild(node) {
86
+ if (node.type === 'text') {
87
+ return node.value;
88
+ }
89
+ else if (!isHastElement(node)) {
90
+ return null;
91
+ }
92
+ const component = this.components[node.tagName];
93
+ if (component) {
94
+ const childElements = node.children
95
+ .map((child) => __classPrivateFieldGet(this, _HastToJSX_instances, "m", _HastToJSX_renderChild).call(this, child))
96
+ .filter(Boolean);
97
+ return (0, react_1.createElement)(component, __classPrivateFieldGet(this, _HastToJSX_instances, "m", _HastToJSX_getPropsForNode).call(this, node), childElements);
98
+ }
99
+ };
100
+ function RichText({ structuredContent, components, }) {
101
+ if (!structuredContent) {
102
+ return null;
103
+ }
104
+ const componentsWithOverrides = {
105
+ ...componentMap,
106
+ ...components,
107
+ };
108
+ const renderer = new HastToJSX(componentsWithOverrides, structuredContent.references);
109
+ return renderer.render(structuredContent.tree);
110
+ }
111
+ exports.default = RichText;
112
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/RichText/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};