@financial-times/cp-content-pipeline-ui 4.1.3 → 4.2.0-beta.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 (65) hide show
  1. package/.storybook/main.js +11 -0
  2. package/lib/components/LiveBlogBody/index.d.ts +1 -0
  3. package/lib/components/LiveBlogBody/index.js +10 -35
  4. package/lib/components/LiveBlogBody/index.js.map +1 -1
  5. package/lib/components/LiveBlogPost/ShareButtons.d.ts +7 -0
  6. package/lib/components/LiveBlogPost/ShareButtons.js +45 -0
  7. package/lib/components/LiveBlogPost/ShareButtons.js.map +1 -0
  8. package/lib/components/LiveBlogPost/Timestamp.d.ts +6 -0
  9. package/lib/components/LiveBlogPost/Timestamp.js +31 -0
  10. package/lib/components/LiveBlogPost/Timestamp.js.map +1 -0
  11. package/lib/components/LiveBlogPost/index.d.ts +30 -0
  12. package/lib/components/LiveBlogPost/index.js +68 -0
  13. package/lib/components/LiveBlogPost/index.js.map +1 -0
  14. package/lib/components/LiveBlogPost/svgIcons.d.ts +4 -0
  15. package/lib/components/LiveBlogPost/svgIcons.js +29 -0
  16. package/lib/components/LiveBlogPost/svgIcons.js.map +1 -0
  17. package/lib/components/LiveBlogWrapper/dispatchEvent.d.ts +2 -0
  18. package/lib/components/LiveBlogWrapper/dispatchEvent.js +39 -0
  19. package/lib/components/LiveBlogWrapper/dispatchEvent.js.map +1 -0
  20. package/lib/components/LiveBlogWrapper/index.d.ts +3 -0
  21. package/lib/components/LiveBlogWrapper/index.js +142 -0
  22. package/lib/components/LiveBlogWrapper/index.js.map +1 -0
  23. package/lib/components/LiveBlogWrapper/normalisePost.d.ts +2 -0
  24. package/lib/components/LiveBlogWrapper/normalisePost.js +14 -0
  25. package/lib/components/LiveBlogWrapper/normalisePost.js.map +1 -0
  26. package/lib/components/LiveBlogWrapper/post-tracker.d.ts +138 -0
  27. package/lib/components/LiveBlogWrapper/post-tracker.js +351 -0
  28. package/lib/components/LiveBlogWrapper/post-tracker.js.map +1 -0
  29. package/lib/components/LiveBlogWrapper/test/dispatchEvent.spec.d.ts +1 -0
  30. package/lib/components/LiveBlogWrapper/test/dispatchEvent.spec.js +44 -0
  31. package/lib/components/LiveBlogWrapper/test/dispatchEvent.spec.js.map +1 -0
  32. package/lib/components/LiveBlogWrapper/test/index.spec.d.ts +1 -0
  33. package/lib/components/LiveBlogWrapper/test/index.spec.js +100 -0
  34. package/lib/components/LiveBlogWrapper/test/index.spec.js.map +1 -0
  35. package/lib/components/LiveBlogWrapper/test/normalisePost.spec.d.ts +1 -0
  36. package/lib/components/LiveBlogWrapper/test/normalisePost.spec.js +28 -0
  37. package/lib/components/LiveBlogWrapper/test/normalisePost.spec.js.map +1 -0
  38. package/lib/components/Scrollytelling/ScrollyImage.js +1 -1
  39. package/lib/components/Scrollytelling/ScrollyImage.js.map +1 -1
  40. package/lib/index.d.ts +1 -0
  41. package/lib/index.js +3 -1
  42. package/lib/index.js.map +1 -1
  43. package/lib/stories/LiveBlogPost.stories.d.ts +16 -0
  44. package/lib/stories/LiveBlogPost.stories.js +42 -0
  45. package/lib/stories/LiveBlogPost.stories.js.map +1 -0
  46. package/package.json +10 -3
  47. package/src/components/LiveBlogBody/client/main.scss +2 -0
  48. package/src/components/LiveBlogBody/index.tsx +17 -15
  49. package/src/components/LiveBlogPost/ShareButtons.tsx +86 -0
  50. package/src/components/LiveBlogPost/Timestamp.tsx +49 -0
  51. package/src/components/LiveBlogPost/index.tsx +164 -0
  52. package/src/components/LiveBlogPost/svgIcons.tsx +30 -0
  53. package/src/components/LiveBlogWrapper/dispatchEvent.ts +39 -0
  54. package/src/components/LiveBlogWrapper/index.tsx +189 -0
  55. package/src/components/LiveBlogWrapper/normalisePost.ts +11 -0
  56. package/src/components/LiveBlogWrapper/post-tracker.ts +458 -0
  57. package/src/components/LiveBlogWrapper/test/dispatchEvent.spec.ts +45 -0
  58. package/src/components/LiveBlogWrapper/test/index.spec.tsx +127 -0
  59. package/src/components/LiveBlogWrapper/test/normalisePost.spec.ts +31 -0
  60. package/src/components/Scrollytelling/ScrollyImage.tsx +1 -1
  61. package/src/index.ts +1 -0
  62. package/src/stories/LiveBlogPost.stories.scss +361 -0
  63. package/src/stories/LiveBlogPost.stories.tsx +38 -0
  64. package/src/types/x-dash.d.ts +4 -1
  65. package/tsconfig.tsbuildinfo +1 -1
@@ -1,4 +1,6 @@
1
1
  /** @type { import('@storybook/react-webpack5').StorybookConfig } */
2
+ const path = require('path');
3
+ const xEngine = require('@financial-times/x-engine/src/webpack')
2
4
  const config = {
3
5
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
4
6
  addons: [
@@ -22,5 +24,14 @@ const config = {
22
24
  docs: {
23
25
  autodocs: 'tag',
24
26
  },
27
+ webpackFinal: async (config) => {
28
+ config.plugins.push(xEngine());
29
+ config.resolve.modules.push(path.resolve(__dirname,"../../../node_modules/"));
30
+ config.resolve.alias.react = path.resolve(__dirname,"../../../node_modules/react");
31
+ config.resolve.alias['react-dom'] = path.resolve(__dirname,"../../../node_modules/react-dom");
32
+
33
+
34
+ return config;
35
+ },
25
36
  }
26
37
  export default config
@@ -2,5 +2,6 @@ import React from 'react';
2
2
  import type { BodyProps } from '../Body';
3
3
  export type LiveBlogBodyProps = BodyProps & {
4
4
  isPinnedPost?: boolean;
5
+ xInteractionSerialiser?: any;
5
6
  };
6
7
  export default function LiveBlogBody({ content, components, isPinnedPost, xInteractionSerialiser, showShareButtons, showBackToTop, postTrackerConfig, }: LiveBlogBodyProps): React.JSX.Element | null;
@@ -1,48 +1,23 @@
1
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
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
28
5
  Object.defineProperty(exports, "__esModule", { value: true });
29
6
  const react_1 = __importDefault(require("react"));
30
- const x_live_blog_wrapper_1 = require("@financial-times/x-live-blog-wrapper");
31
- const RichText_1 = __importStar(require("../RichText"));
7
+ const RichText_1 = require("../RichText");
8
+ const LiveBlogWrapper_1 = require("../LiveBlogWrapper");
32
9
  function LiveBlogBody({ content, components, isPinnedPost, xInteractionSerialiser, showShareButtons, showBackToTop = true, postTrackerConfig, }) {
33
10
  if (content.__typename !== 'LiveBlogPackage')
34
11
  return null;
35
- const additionalProps = isPinnedPost
36
- ? {
37
- id: 'pinned-post-live-blog-wrapper',
38
- posts: [content.pinnedPost],
39
- }
40
- : {
41
- id: 'live-blog-wrapper',
42
- posts: (content.liveBlogPosts || []).filter((post) => post?.id !== content.pinnedPost?.id),
43
- };
12
+ let id = 'live-blog-wrapper';
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ let posts = (content.liveBlogPosts || []).filter((post) => post?.id !== content.pinnedPost?.id);
15
+ if (isPinnedPost) {
16
+ id = 'pinned-post-live-blog-wrapper';
17
+ posts = [content.pinnedPost];
18
+ }
44
19
  return (react_1.default.createElement(RichText_1.ComponentsContext.Provider, { value: components },
45
- react_1.default.createElement(x_live_blog_wrapper_1.LiveBlogWrapper, { articleUrl: `https://www.ft.com/content/${content.id}`, serialiser: xInteractionSerialiser, renderRichText: RichText_1.default, showShareButtons: showShareButtons ?? true, backToTop: showBackToTop ? 'o-topper' : undefined, postTrackerConfig: postTrackerConfig, ...additionalProps })));
20
+ react_1.default.createElement(LiveBlogWrapper_1.LiveBlogWrapper, { articleUrl: `https://www.ft.com/content/${content.id}`, id: id, posts: posts, serialiser: xInteractionSerialiser, showShareButtons: showShareButtons ?? true, backToTop: showBackToTop ? 'o-topper' : undefined, postTrackerConfig: postTrackerConfig })));
46
21
  }
47
22
  exports.default = LiveBlogBody;
48
23
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/LiveBlogBody/index.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kDAAyB;AACzB,8EAAsE;AAGtE,wDAAyD;AAMzD,SAAwB,YAAY,CAAC,EACnC,OAAO,EACP,UAAU,EACV,YAAY,EACZ,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,GAAG,IAAI,EACpB,iBAAiB,GACC;IAClB,IAAI,OAAO,CAAC,UAAU,KAAK,iBAAiB;QAAE,OAAO,IAAI,CAAA;IAEzD,MAAM,eAAe,GAAG,YAAY;QAClC,CAAC,CAAC;YACE,EAAE,EAAE,+BAA+B;YACnC,KAAK,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;SAC5B;QACH,CAAC,CAAC;YACE,EAAE,EAAE,mBAAmB;YACvB,KAAK,EAAE,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,MAAM,CACzC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,KAAK,OAAO,CAAC,UAAU,EAAE,EAAE,CAC9C;SACF,CAAA;IAEL,OAAO,CACL,8BAAC,4BAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,UAAU;QAC3C,8BAAC,qCAAe,IACd,UAAU,EAAE,8BAA8B,OAAO,CAAC,EAAE,EAAE,EACtD,UAAU,EAAE,sBAAsB,EAClC,cAAc,EAAE,kBAAQ,EACxB,gBAAgB,EAAE,gBAAgB,IAAI,IAAI,EAC1C,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,EACjD,iBAAiB,EAAE,iBAAiB,KAChC,eAAe,GACnB,CACyB,CAC9B,CAAA;AACH,CAAC;AApCD,+BAoCC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/LiveBlogBody/index.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAyB;AAEzB,0CAA+C;AAC/C,wDAAoD;AAUpD,SAAwB,YAAY,CAAC,EACnC,OAAO,EACP,UAAU,EACV,YAAY,EACZ,sBAAsB,EACtB,gBAAgB,EAChB,aAAa,GAAG,IAAI,EACpB,iBAAiB,GACC;IAClB,IAAI,OAAO,CAAC,UAAU,KAAK,iBAAiB;QAAE,OAAO,IAAI,CAAA;IAEzD,IAAI,EAAE,GAAG,mBAAmB,CAAA;IAC5B,8DAA8D;IAC9D,IAAI,KAAK,GAAe,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,MAAM,CAC1D,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,KAAK,OAAO,CAAC,UAAU,EAAE,EAAE,CAC9C,CAAA;IAED,IAAI,YAAY,EAAE;QAChB,EAAE,GAAG,+BAA+B,CAAA;QACpC,KAAK,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;KAC7B;IAED,OAAO,CACL,8BAAC,4BAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,UAAU;QAC3C,8BAAC,iCAAe,IACd,UAAU,EAAE,8BAA8B,OAAO,CAAC,EAAE,EAAE,EACtD,EAAE,EAAE,EAAE,EACN,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,sBAAsB,EAClC,gBAAgB,EAAE,gBAAgB,IAAI,IAAI,EAC1C,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,EACjD,iBAAiB,EAAE,iBAAiB,GACpC,CACyB,CAC9B,CAAA;AACH,CAAC;AAnCD,+BAmCC"}
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ declare const _default: ({ postId, articleUrl, title, }: {
3
+ postId: string;
4
+ articleUrl: string;
5
+ title: string;
6
+ }) => React.JSX.Element;
7
+ export default _default;
@@ -0,0 +1,45 @@
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 svgIcons_1 = require("./svgIcons");
8
+ exports.default = ({ postId, articleUrl, title, }) => {
9
+ const shareUrl = articleUrl ? new URL(articleUrl) : null;
10
+ if (shareUrl) {
11
+ shareUrl.hash = `post-${postId}`;
12
+ }
13
+ const shareUrlStr = shareUrl?.toString() ?? '';
14
+ const twitterUrl = `https://twitter.com/intent/tweet?url=${encodeURIComponent(shareUrlStr)}&text=${encodeURIComponent(title)}&via=ft`;
15
+ const facebookUrl = `http://www.facebook.com/sharer.php?u=${encodeURIComponent(shareUrlStr)}&t=${encodeURIComponent(title)}`;
16
+ const linkedInUrl = `http://www.linkedin.com/shareArticle?mini=true&url=${encodeURIComponent(shareUrlStr)}&title=${encodeURIComponent(title)}&source=Financial+Times`;
17
+ return (react_1.default.createElement("div", null,
18
+ react_1.default.createElement("div", { "data-o-component": "o-share", "data-o-share-location": `live-blog-post-${postId}`, className: "o-share o-share--small" },
19
+ react_1.default.createElement("ul", { "data-toolbar": "share" },
20
+ react_1.default.createElement("li", { className: "o-share__action", "data-share": "twitter" },
21
+ react_1.default.createElement("a", { className: "o-share__icon o-share__icon--x", rel: "noopener", href: twitterUrl, "data-trackable": "twitter" },
22
+ react_1.default.createElement("div", { className: "o-share__icon__image" },
23
+ react_1.default.createElement(svgIcons_1.TwitterSVG, null)),
24
+ react_1.default.createElement("span", { className: "o-share__text" },
25
+ "Share $",
26
+ title,
27
+ " on X (opens in a new window)"))),
28
+ react_1.default.createElement("li", { className: "o-share__action", "data-share": "facebook" },
29
+ react_1.default.createElement("a", { className: "o-share__icon o-share__icon--facebook", rel: "noopener", href: facebookUrl, "data-trackable": "facebook" },
30
+ react_1.default.createElement("div", { className: "o-share__icon__image" },
31
+ react_1.default.createElement(svgIcons_1.FacebookSVG, null)),
32
+ react_1.default.createElement("span", { className: "o-share__text" },
33
+ "Share $",
34
+ title,
35
+ " on Facebook (opens in a new window)"))),
36
+ react_1.default.createElement("li", { className: "o-share__action", "data-share": "linkedin" },
37
+ react_1.default.createElement("a", { className: "o-share__icon o-share__icon--linkedin", rel: "noopener", href: linkedInUrl, "data-trackable": "linkedin" },
38
+ react_1.default.createElement("div", { className: "o-share__icon__image" },
39
+ react_1.default.createElement(svgIcons_1.LinkedInSVG, null)),
40
+ react_1.default.createElement("span", { className: "o-share__text" },
41
+ "Share $",
42
+ title,
43
+ " on LinkedIn (opens in a new window)")))))));
44
+ };
45
+ //# sourceMappingURL=ShareButtons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ShareButtons.js","sourceRoot":"","sources":["../../../src/components/LiveBlogPost/ShareButtons.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAyB;AACzB,yCAAiE;AACjE,kBAAe,CAAC,EACd,MAAM,EACN,UAAU,EACV,KAAK,GAKN,EAAE,EAAE;IACH,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACxD,IAAI,QAAQ,EAAE;QACZ,QAAQ,CAAC,IAAI,GAAG,QAAQ,MAAM,EAAE,CAAA;KACjC;IACD,MAAM,WAAW,GAAW,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;IACtD,MAAM,UAAU,GAAG,wCAAwC,kBAAkB,CAC3E,WAAW,CACZ,SAAS,kBAAkB,CAAC,KAAK,CAAC,SAAS,CAAA;IAE5C,MAAM,WAAW,GAAG,wCAAwC,kBAAkB,CAC5E,WAAW,CACZ,MAAM,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAA;IAElC,MAAM,WAAW,GAAG,sDAAsD,kBAAkB,CAC1F,WAAW,CACZ,UAAU,kBAAkB,CAAC,KAAK,CAAC,yBAAyB,CAAA;IAE7D,OAAO,CACL;QACE,2DACmB,SAAS,2BACH,kBAAkB,MAAM,EAAE,EACjD,SAAS,EAAC,wBAAwB;YAElC,sDAAiB,OAAO;gBACtB,sCAAI,SAAS,EAAC,iBAAiB,gBAAY,SAAS;oBAClD,qCACE,SAAS,EAAC,gCAAgC,EAC1C,GAAG,EAAC,UAAU,EACd,IAAI,EAAE,UAAU,oBACD,SAAS;wBAExB,uCAAK,SAAS,EAAC,sBAAsB;4BACnC,8BAAC,qBAAU,OAAG,CACV;wBACN,wCAAM,SAAS,EAAC,eAAe;;4BACrB,KAAK;4DACR,CACL,CACD;gBACL,sCAAI,SAAS,EAAC,iBAAiB,gBAAY,UAAU;oBACnD,qCACE,SAAS,EAAC,uCAAuC,EACjD,GAAG,EAAC,UAAU,EACd,IAAI,EAAE,WAAW,oBACF,UAAU;wBAEzB,uCAAK,SAAS,EAAC,sBAAsB;4BACnC,8BAAC,sBAAW,OAAG,CACX;wBACN,wCAAM,SAAS,EAAC,eAAe;;4BACrB,KAAK;mEACR,CACL,CACD;gBACL,sCAAI,SAAS,EAAC,iBAAiB,gBAAY,UAAU;oBACnD,qCACE,SAAS,EAAC,uCAAuC,EACjD,GAAG,EAAC,UAAU,EACd,IAAI,EAAE,WAAW,oBACF,UAAU;wBAEzB,uCAAK,SAAS,EAAC,sBAAsB;4BACnC,8BAAC,sBAAW,OAAG,CACX;wBACN,wCAAM,SAAS,EAAC,eAAe;;4BACrB,KAAK;mEACR,CACL,CACD,CACF,CACD,CACF,CACP,CAAA;AACH,CAAC,CAAA"}
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export type TimestampProps = {
3
+ publishedTimestamp: string;
4
+ };
5
+ declare const _default: ({ publishedTimestamp }: TimestampProps) => React.JSX.Element;
6
+ export default _default;
@@ -0,0 +1,31 @@
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
+ exports.default = ({ publishedTimestamp }) => {
8
+ const now = new Date();
9
+ const oneDay = 24 * 60 * 60 * 1000;
10
+ const date = new Date(publishedTimestamp);
11
+ const formatted = date.toLocaleString();
12
+ let format;
13
+ let showExactTime;
14
+ if (now.getTime() - date.getTime() < oneDay) {
15
+ // display published date in 'xx minutes ago' format
16
+ // and render exact time next to it
17
+ format = 'time-ago-no-seconds';
18
+ showExactTime = true;
19
+ }
20
+ else {
21
+ // don't display time string if the post is older than one day
22
+ // because it is already included in the formatted timestamp
23
+ format = 'MMM dd, HH:mm';
24
+ showExactTime = false;
25
+ }
26
+ return (react_1.default.createElement("span", { className: "x-live-blog-post__timestamp-container" },
27
+ react_1.default.createElement("time", { "data-o-component": "o-date", className: "o-date x-live-blog-post__timestamp", dateTime: publishedTimestamp, "data-o-date-format": format, itemProp: "datePublished" },
28
+ react_1.default.createElement("span", { "data-o-date-printer": true }, formatted),
29
+ showExactTime && (react_1.default.createElement("span", { className: "o-date x-live-blog-post__timestamp-exact-time", "data-o-date-printer": true, "data-o-date-format": "HH:mm", itemProp: "exactTime" })))));
30
+ };
31
+ //# sourceMappingURL=Timestamp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Timestamp.js","sourceRoot":"","sources":["../../../src/components/LiveBlogPost/Timestamp.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAyB;AAMzB,kBAAe,CAAC,EAAE,kBAAkB,EAAkB,EAAE,EAAE;IACxD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;IACtB,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;IAClC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,kBAAkB,CAAC,CAAA;IACzC,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,EAAE,CAAA;IAEvC,IAAI,MAAc,CAAA;IAClB,IAAI,aAAsB,CAAA;IAE1B,IAAI,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,MAAM,EAAE;QAC3C,oDAAoD;QACpD,mCAAmC;QACnC,MAAM,GAAG,qBAAqB,CAAA;QAC9B,aAAa,GAAG,IAAI,CAAA;KACrB;SAAM;QACL,8DAA8D;QAC9D,4DAA4D;QAC5D,MAAM,GAAG,eAAe,CAAA;QACxB,aAAa,GAAG,KAAK,CAAA;KACtB;IAED,OAAO,CACL,wCAAM,SAAS,EAAC,uCAAuC;QACrD,4DACmB,QAAQ,EACzB,SAAS,EAAC,oCAAoC,EAC9C,QAAQ,EAAE,kBAAkB,wBACR,MAAM,EAC1B,QAAQ,EAAC,eAAe;YAExB,uEAA2B,SAAS,CAAQ;YAC3C,aAAa,IAAI,CAChB,wCACE,SAAS,EAAC,+CAA+C,qDAEtC,OAAO,EAC1B,QAAQ,EAAC,WAAW,GACd,CACT,CACI,CACF,CACR,CAAA;AACH,CAAC,CAAA"}
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import { RichTextProps } from '../RichText';
3
+ type indicators = {
4
+ isOpinion?: boolean;
5
+ };
6
+ export type LiveBlogPostProps = {
7
+ id: string;
8
+ postId: string;
9
+ title: string;
10
+ content: string;
11
+ bodyHTML: string;
12
+ body: any;
13
+ publishedTimestamp: string;
14
+ publishedDate: string;
15
+ isBreakingNews: boolean;
16
+ standout?: {
17
+ breakingNews?: boolean;
18
+ editorsChoice?: boolean;
19
+ exclusive?: boolean;
20
+ scoop?: boolean;
21
+ };
22
+ articleUrl: string;
23
+ showShareButtons: boolean;
24
+ byline: string | RichTextProps;
25
+ ad: unknown;
26
+ backToTop: string | undefined | ((arg: any) => any);
27
+ indicators?: indicators;
28
+ };
29
+ declare const LiveBlogPost: ({ id, postId, title, content, bodyHTML, body, publishedTimestamp, publishedDate, isBreakingNews, standout, articleUrl, showShareButtons, byline, ad, backToTop, indicators, }: LiveBlogPostProps) => React.JSX.Element | null;
30
+ export { LiveBlogPost };
@@ -0,0 +1,68 @@
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.LiveBlogPost = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const ShareButtons_1 = __importDefault(require("./ShareButtons"));
9
+ const Timestamp_1 = __importDefault(require("./Timestamp"));
10
+ const RichText_1 = __importDefault(require("../RichText"));
11
+ const classnames_1 = __importDefault(require("classnames"));
12
+ const LiveBlogPost = ({ id, postId, // Remove once wordpress is no longer in use
13
+ title, content, // Remove once wordpress is no longer in use
14
+ bodyHTML, //ElasticSearch
15
+ body, // cp-content-pipeline
16
+ publishedTimestamp, // Remove once wordpress is no longer in use
17
+ publishedDate, isBreakingNews, // Remove once wordpress is no longer in use
18
+ standout = {}, articleUrl, showShareButtons = false, byline, ad, backToTop, indicators = {}, }) => {
19
+ const showBreakingNewsLabel = standout.breakingNews || isBreakingNews;
20
+ let postBody;
21
+ let postByline;
22
+ let backToTopElem;
23
+ if (body && 'structured' in body) {
24
+ // Content comes from cp-content-pipeline-api
25
+ postBody = (react_1.default.createElement("div", { className: "x-live-blog-post__body n-content-body article--body" },
26
+ react_1.default.createElement(RichText_1.default, { structuredContent: body.structured })));
27
+ }
28
+ else {
29
+ // Content comes from next-es or wordpress
30
+ postBody = (react_1.default.createElement("div", { className: "x-live-blog-post__body n-content-body article--body", dangerouslySetInnerHTML: { __html: bodyHTML || content } }));
31
+ }
32
+ if (byline && typeof byline === 'object' && 'tree' in byline) {
33
+ postByline = (react_1.default.createElement("p", { className: "x-live-blog-post__byline" },
34
+ react_1.default.createElement(RichText_1.default, { structuredContent: byline })));
35
+ }
36
+ else if (typeof byline === 'string') {
37
+ postByline = react_1.default.createElement("p", { className: "x-live-blog-post__byline" }, byline);
38
+ }
39
+ if (typeof backToTop === 'string') {
40
+ backToTopElem = (react_1.default.createElement("a", { href: backToTop.includes('#') ? backToTop : `#${backToTop}`, className: "x-live-blog-post-controls__back-to-top-link" }, "Back to top"));
41
+ }
42
+ else if (typeof backToTop === 'function') {
43
+ backToTopElem = (react_1.default.createElement("button", { onClick: backToTop, className: "x-live-blog-post-controls__back-to-top-button" }, "Back to top"));
44
+ }
45
+ else {
46
+ return null;
47
+ }
48
+ return (react_1.default.createElement("article", { className: (0, classnames_1.default)('x-live-blog-post', {
49
+ 'x-live-blog-post--opinion': indicators.isOpinion,
50
+ }), "data-trackable": "live-post", id: `post-${id || postId}`, "data-x-component": "live-blog-post" },
51
+ react_1.default.createElement("div", { className: "x-live-blog-post__standout" },
52
+ indicators.isOpinion ? (react_1.default.createElement("span", { className: "icon icon-opinion icon--scale-3" })) : (''),
53
+ react_1.default.createElement("div", { className: "x-live-blog-post__right" },
54
+ react_1.default.createElement("div", { className: "x-live-blog-post__meta" },
55
+ indicators.isOpinion ? (react_1.default.createElement("span", { className: "x-live-blog-post__label--opinion" }, "Live Opinion")) : (''),
56
+ react_1.default.createElement("span", null,
57
+ react_1.default.createElement(Timestamp_1.default, { publishedTimestamp: publishedDate || publishedTimestamp }))),
58
+ react_1.default.createElement("div", null, postByline))),
59
+ showBreakingNewsLabel && (react_1.default.createElement("div", { className: "x-live-blog-post__breaking-news" }, "Breaking news")),
60
+ title && react_1.default.createElement("h2", { className: "x-live-blog-post__title" }, title),
61
+ postBody,
62
+ react_1.default.createElement("div", { className: "x-live-blog-post__controls" },
63
+ showShareButtons && (react_1.default.createElement(ShareButtons_1.default, { postId: id || postId, articleUrl: articleUrl, title: title })),
64
+ backToTopElem),
65
+ ad));
66
+ };
67
+ exports.LiveBlogPost = LiveBlogPost;
68
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/LiveBlogPost/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export declare function TwitterSVG(): React.JSX.Element;
3
+ export declare function FacebookSVG(): React.JSX.Element;
4
+ export declare function LinkedInSVG(): React.JSX.Element;
@@ -0,0 +1,29 @@
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.LinkedInSVG = exports.FacebookSVG = exports.TwitterSVG = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ /*
9
+ TODO: CI-1975 given the below comment, once we are happy this migration works, we should replace this with o-share
10
+
11
+ These icons have been copied from Origami as their TSX components are currently incompatible with next-article.
12
+ Once this is resolved, these components should be replaced with o-share https://github.com/Financial-Times/origami/tree/main/components/o-share.
13
+ */
14
+ function TwitterSVG() {
15
+ return (react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 40 40" },
16
+ react_1.default.createElement("path", { d: "M21.647 18.469 28.932 10h-1.726l-6.326 7.353L15.827 10H10l7.64 11.12L10 30h1.726l6.68-7.765L23.744 30h5.827l-7.924-11.531Zm-2.365 2.748-.774-1.107-6.16-8.81H15l4.971 7.11.774 1.107 6.462 9.242h-2.652l-5.273-7.541Z" })));
17
+ }
18
+ exports.TwitterSVG = TwitterSVG;
19
+ function FacebookSVG() {
20
+ return (react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 1024 1024" },
21
+ react_1.default.createElement("path", { d: "M643.9 342h-48.2c-37.8 0-45.1 18-45.1 44.3v58.1h90.1l-11.7 91h-78.4V769h-94V535.5H378v-91h78.6v-67.1c0-77.9 47.6-120.3 117.1-120.3 33.3 0 61.9 2.5 70.2 3.6V342z" })));
22
+ }
23
+ exports.FacebookSVG = FacebookSVG;
24
+ function LinkedInSVG() {
25
+ return (react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 1024 1024" },
26
+ react_1.default.createElement("path", { d: "M264.4 426.2h106.2v341.4H264.4V426.2zm53.2-169.7c-34.1 0-61.6 27.6-61.6 61.5 0 34 27.5 61.5 61.6 61.5 33.9 0 61.5-27.6 61.5-61.5-.1-34-27.6-61.5-61.5-61.5zm323.1 161.2c-51.6 0-86.2 28.3-100.4 55.1h-1.5v-46.7H437.2v341.4h106V598.7c0-44.5 8.4-87.7 63.6-87.7 54.5 0 55.1 50.9 55.1 90.5v166H768V580.3c0-91.9-19.9-162.6-127.3-162.6z" })));
27
+ }
28
+ exports.LinkedInSVG = LinkedInSVG;
29
+ //# sourceMappingURL=svgIcons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svgIcons.js","sourceRoot":"","sources":["../../../src/components/LiveBlogPost/svgIcons.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAAyB;AACzB;;;;;GAKG;AACH,SAAgB,UAAU;IACxB,OAAO,CACL,uCAAK,KAAK,EAAC,4BAA4B,EAAC,OAAO,EAAC,WAAW;QACzD,wCAAM,CAAC,EAAC,uNAAuN,GAAG,CAC9N,CACP,CAAA;AACH,CAAC;AAND,gCAMC;AAED,SAAgB,WAAW;IACzB,OAAO,CACL,uCAAK,KAAK,EAAC,4BAA4B,EAAC,OAAO,EAAC,eAAe;QAC7D,wCAAM,CAAC,EAAC,kKAAkK,GAAG,CACzK,CACP,CAAA;AACH,CAAC;AAND,kCAMC;AAED,SAAgB,WAAW;IACzB,OAAO,CACL,uCAAK,KAAK,EAAC,4BAA4B,EAAC,OAAO,EAAC,eAAe;QAC7D,wCAAM,CAAC,EAAC,yUAAyU,GAAG,CAChV,CACP,CAAA;AACH,CAAC;AAND,kCAMC"}
@@ -0,0 +1,2 @@
1
+ declare const dispatchEvent: (target: any, eventType: any, data: any) => void;
2
+ export { dispatchEvent };
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dispatchEvent = void 0;
4
+ /*
5
+ We dispatch live update events to notify the consuming app about added / updated posts.
6
+
7
+ Consuming app uses these events to execute tasks like initialising Origami components
8
+ on the updated elements.
9
+
10
+ We want the rendering of the updates in the DOM to finish before dispatching this event,
11
+ because the consumer needs to reference the updated DOM elements.
12
+
13
+ If we dispatch the event in the same event loop with DOM element updates, consumer app
14
+ will handle the event before the updates are complete.
15
+
16
+ window.setTimeout(fn, 0) will defer the execution of the inner function until the
17
+ current event loop completes, which is enough time for the DOM updates to finish.
18
+
19
+ More information can be found in MDN setTimeout documentation. Please refer to
20
+ "Late timeouts" heading in this page:
21
+ https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#Late_timeouts
22
+
23
+ > ... the timeout can also fire later when the page (or the OS/browser itself) is busy
24
+ > with other tasks. One important case to note is that the function or code snippet
25
+ > cannot be executed until the thread that called setTimeout() has terminated.
26
+ > ...
27
+ > This is because even though setTimeout was called with a delay of zero, it's placed on
28
+ > a queue and scheduled to run at the next opportunity; not immediately.
29
+ */
30
+ /* eslint-disable @typescript-eslint/no-explicit-any */
31
+ //TODO: CI-1975 reset any types to something better, requires quite a bit of digging
32
+ const dispatchEvent = (target, eventType, data) => {
33
+ if (typeof window === 'undefined') {
34
+ return;
35
+ }
36
+ window.setTimeout(() => target.dispatchEvent(new CustomEvent(eventType, { detail: data })), 0);
37
+ };
38
+ exports.dispatchEvent = dispatchEvent;
39
+ //# sourceMappingURL=dispatchEvent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatchEvent.js","sourceRoot":"","sources":["../../../src/components/LiveBlogWrapper/dispatchEvent.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;EAyBE;AACF,uDAAuD;AACvD,oFAAoF;AACpF,MAAM,aAAa,GAAG,CAAC,MAAW,EAAE,SAAc,EAAE,IAAS,EAAE,EAAE;IAC/D,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;QACjC,OAAM;KACP;IACD,MAAM,CAAC,UAAU,CACf,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EACxE,CAAC,CACF,CAAA;AACH,CAAC,CAAA;AAEQ,sCAAa"}
@@ -0,0 +1,3 @@
1
+ import { PostTracker } from './post-tracker';
2
+ declare const LiveBlogWrapper: any;
3
+ export { LiveBlogWrapper, PostTracker };
@@ -0,0 +1,142 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.PostTracker = exports.LiveBlogWrapper = void 0;
27
+ const react_1 = __importStar(require("react"));
28
+ const x_interaction_1 = require("@financial-times/x-interaction");
29
+ const normalisePost_1 = require("./normalisePost");
30
+ const dispatchEvent_1 = require("./dispatchEvent");
31
+ const post_tracker_1 = require("./post-tracker");
32
+ Object.defineProperty(exports, "PostTracker", { enumerable: true, get: function () { return post_tracker_1.PostTracker; } });
33
+ const LiveBlogPost_1 = require("../LiveBlogPost");
34
+ /* eslint-disable @typescript-eslint/no-explicit-any */
35
+ //TODO: CI-1975 remove "any" types
36
+ // this has been ported from x-dash, and a lot of what is expected into these arguments will take a lot of digging
37
+ // checks to see if there is already a post and if not inserts it. tracks with dispatchEvent
38
+ const withLiveBlogWrapperActions = (0, x_interaction_1.withActions)({
39
+ insertPost(newPost, wrapper) {
40
+ return (props) => {
41
+ const normalisedNewPost = (0, normalisePost_1.normalisePost)(newPost);
42
+ const newPostAlreadyExists = props.posts.find((post) => post.id === normalisedNewPost.id);
43
+ if (!newPostAlreadyExists) {
44
+ props.posts.unshift(normalisedNewPost);
45
+ (0, dispatchEvent_1.dispatchEvent)(wrapper, 'LiveBlogWrapper.INSERT_POST', {
46
+ post: normalisedNewPost,
47
+ });
48
+ }
49
+ return props;
50
+ };
51
+ },
52
+ });
53
+ class BaseLiveBlogWrapper extends react_1.Component {
54
+ constructor(props) {
55
+ super(props);
56
+ }
57
+ componentDidUpdate(prevProps) {
58
+ if (this.props.posts && this.props.posts.length && !this.state.tracker) {
59
+ this.setUp();
60
+ }
61
+ if (this.state.tracker && prevProps.posts.length !== this.state.postCount) {
62
+ this.state.tracker.observeNewElements();
63
+ this.setState({ postCount: this.props.posts.length });
64
+ }
65
+ }
66
+ componentWillUnmount() {
67
+ if (this.state.tracker) {
68
+ this.state.tracker.destroy();
69
+ }
70
+ }
71
+ setUp() {
72
+ const { onEntersViewport, onRead, onError, usePostTracker } = this.props.postTrackerConfig || {};
73
+ if (!usePostTracker) {
74
+ return;
75
+ }
76
+ if (typeof onEntersViewport !== 'function' ||
77
+ typeof onRead !== 'function' ||
78
+ typeof onError !== 'function') {
79
+ // eslint-disable-next-line no-console
80
+ console.error('onEntersViewport, onRead and onError callback functions are required to use Post tracker');
81
+ return;
82
+ }
83
+ const tracker = this.setUpPostTracking({ onEntersViewport, onRead, onError }, this.props.id);
84
+ this.setState({
85
+ tracker,
86
+ });
87
+ }
88
+ /**
89
+ *
90
+ * @param {Object} callbacks - Callbacks to be called by PostTracker class
91
+ * @param {Function} callbacks.onEntersViewport - function to be called when the criteria for `view` in Post tracker has been fulfiled
92
+ * @param {Function} callbacks.onRead - function to be called when the criteria for `read` in Post tracker has been fulfiled
93
+ * @param {Function} callbacks.onError - function to be called when PostTracker encounters an error
94
+ * @param {string} id
95
+ * @returns {PostTracker}
96
+ */
97
+ setUpPostTracking(callbacks, id) {
98
+ /**
99
+ * @type {import('./post-tracker').PostTrackerConfig}
100
+ */
101
+ const config = {
102
+ query: 'article[data-trackable="live-post"]',
103
+ minMillisecondsToReport: 5000,
104
+ returnVisibleElement: true,
105
+ observerUpdateEventString: 'LiveBlogWrapper.INSERT_POST',
106
+ liveBlogWrapperQuery: `div[data-live-blog-wrapper-id="${id}"]`,
107
+ liveBlogWrapper: this.props.liveBlogWrapperElementRef
108
+ ? this.props.liveBlogWrapperElementRef.current
109
+ : undefined,
110
+ onEntersViewport: (event) => callbacks.onEntersViewport(event),
111
+ onRead: (event) => callbacks.onRead(event),
112
+ onError: (event) => callbacks.onError(event),
113
+ };
114
+ /**
115
+ * @type {PostTracker}
116
+ */
117
+ return new post_tracker_1.PostTracker(config);
118
+ }
119
+ render() {
120
+ const { posts = [], ads = {}, articleUrl, showShareButtons, id, liveBlogWrapperElementRef, } = this.props;
121
+ //TODO: CI-1975 these types can move out when we have a posts type properly defined and shared
122
+ posts.sort((a, b) => {
123
+ const timestampA = a.publishedDate || a.publishedTimestamp;
124
+ const timestampB = b.publishedDate || b.publishedTimestamp;
125
+ // Newer posts on top
126
+ if (timestampA > timestampB) {
127
+ return -1;
128
+ }
129
+ if (timestampB > timestampA) {
130
+ return 1;
131
+ }
132
+ return 0;
133
+ });
134
+ const postElements = posts.map((post, index) => (react_1.default.createElement(LiveBlogPost_1.LiveBlogPost, { key: `live-blog-post-${post.id}`, ...post, articleUrl: articleUrl, showShareButtons: showShareButtons, ad: ads[index], backToTop: this.props.backToTop })));
135
+ return (react_1.default.createElement("div", { className: "x-live-blog-wrapper", "data-live-blog-wrapper-id": id, ref: liveBlogWrapperElementRef }, postElements));
136
+ }
137
+ }
138
+ const LiveBlogWrapper = withLiveBlogWrapperActions(BaseLiveBlogWrapper);
139
+ exports.LiveBlogWrapper = LiveBlogWrapper;
140
+ // This enables the component to work with x-interaction hydration
141
+ (0, x_interaction_1.registerComponent)(LiveBlogWrapper, 'LiveBlogWrapper');
142
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/LiveBlogWrapper/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ declare const normalisePost: (post: any) => any;
2
+ export { normalisePost };
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalisePost = void 0;
4
+ /* eslint-disable @typescript-eslint/no-explicit-any */
5
+ //TODO: CI-1975 reset any types to something better, requires some digging
6
+ // Remove this helper when we no longer need to handle incoming WordPress events.
7
+ const normalisePost = (post) => {
8
+ if (post && !post.id && post.postId) {
9
+ post.id = post.postId;
10
+ }
11
+ return post;
12
+ };
13
+ exports.normalisePost = normalisePost;
14
+ //# sourceMappingURL=normalisePost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalisePost.js","sourceRoot":"","sources":["../../../src/components/LiveBlogWrapper/normalisePost.ts"],"names":[],"mappings":";;;AAAA,uDAAuD;AACvD,0EAA0E;AAC1E,iFAAiF;AACjF,MAAM,aAAa,GAAG,CAAC,IAAS,EAAE,EAAE;IAClC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE;QACnC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,MAAM,CAAA;KACtB;IACD,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAEQ,sCAAa"}