@lidofinance/ui-faq 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,122 @@
1
+ # @lidofinance/ui-faq
2
+
3
+ FAQ UI components and parse utils.
4
+
5
+ ## Installation
6
+
7
+ * React 17 || 18
8
+
9
+ ```bash
10
+ yarn add @lidofinance/faq
11
+
12
+ # and additional
13
+ yarn add next@^12.3.0 styled-components@^5.3.5 @lidofinance/lido-ui@^3.6.1 axios@^1.5.0 cache-manager@^5.2.3
14
+
15
+ # and warehouse packages
16
+ yarn add @lidofinance/analytics-matomo@^0.37.0 @lidofinance/next-ui-primitives@^0.37.0
17
+ ```
18
+
19
+ ## Using
20
+
21
+ There is SSR example (using `getStaticProps`), but also you can use `getFAQ` on client side inside any client component
22
+
23
+ ```tsx
24
+ import { FC } from 'react';
25
+ import { GetStaticProps } from 'next';
26
+ import Head from 'next/head';
27
+ import { FaqAccordion, getFAQ, FAQItem, PageFAQ } from '@lidofinance/ui-faq';
28
+ import { serverAxios } from 'utilsApi';
29
+
30
+
31
+ interface ExampleProps {
32
+ faqList: FAQItem[];
33
+ }
34
+
35
+ const IndexPage: FC<ExampleProps> = ({ faqList }) => (
36
+ <FaqAccordion faqList={faqList} />
37
+ );
38
+
39
+ export default IndexPage;
40
+
41
+ export const getStaticProps: GetStaticProps<ExampleProps> = async () => {
42
+ let foundPage: PageFAQ | undefined;
43
+ const pageIdentification = 'index_page';
44
+
45
+ try {
46
+ const pages = await getFAQ(serverRuntimeConfig.faqContentUrl, {
47
+ // default axios instance without logger, metrics, timeout
48
+ axiosInstance: serverAxios, // or clientAxios
49
+ // cache default is true
50
+ cache: true,
51
+ // memoryCacheConfig default is undefined
52
+ memoryCacheConfig: { max: 100, ttl: 6 * 100 * 1000 },
53
+ });
54
+
55
+ // or custom axios and without cache
56
+ // const pages = await getFAQ(serverRuntimeConfig.faqContentUrl, {
57
+ // axiosInstance: clientAxios,
58
+ // cache: false,
59
+ // });
60
+
61
+ // or use internal FAQ pkg axios and use cache
62
+ // const pages = await getFAQ(serverRuntimeConfig.faqContentUrl);
63
+
64
+ // bacause `getFAQ` returns data for all pages
65
+ foundPage = pages.find(
66
+ (page: PageFAQ) => page['identification'] === pageIdentification,
67
+ );
68
+ } catch {
69
+ // noop
70
+ }
71
+
72
+ return {
73
+ props: {
74
+ faqList: foundPage?.['faq'] ?? [],
75
+ },
76
+ };
77
+ };
78
+ ```
79
+
80
+ ### Matomo analytics
81
+
82
+ Client side example. Let's make with [matomo analytics](https://www.npmjs.com/package/@lidofinance/analytics-matomo)!
83
+
84
+ ```tsx
85
+ // See: @lidofinance/analytics-matomo
86
+ import { MATOMO_CLICK_EVENTS } from './matomoClickEvents';
87
+
88
+ export const matomoEventMap = new Map();
89
+
90
+ // Exact match required - 'https://lido.fi' or 'https://lido.fi/?ref=<ref>' not be working!
91
+ matomoEventMap.set('https://lido.fi/', MATOMO_CLICK_EVENTS.faqLidoLandingLink);
92
+ // Exact match required - 'example' or 'example/?ref=<ref>' not be working!
93
+ matomoEventMap.set('/example', MATOMO_CLICK_EVENTS.faqExamplePageLocalLink);
94
+ // Important: you should match `href` with `faqContentUrl` at source, not with `<FaqAccordion ... />` HTML output!
95
+
96
+ const ExamplePage2: FC = () => {
97
+ const [foundPage, setFoundPage] = useState<PageFAQ | undefined>(undefined);
98
+
99
+ useEffect(() => {
100
+ void (async () => {
101
+ try {
102
+ const pageIdentification = 'example_page_2';
103
+ const pages = await getFAQ(dynamics.faqContentUrl);
104
+
105
+ setFoundPage(
106
+ pages.find(
107
+ (page: PageFAQ) => page['identification'] === pageIdentification,
108
+ ),
109
+ );
110
+ } catch {
111
+ // noop
112
+ }
113
+ })();
114
+ }, []);
115
+
116
+ return (
117
+ <FaqAccordion faqList={faqList} matomoEventMap={matomoEventMap} />
118
+ )
119
+ };
120
+
121
+ export default ExamplePage2;
122
+ ```
package/README.mdx ADDED
@@ -0,0 +1,4 @@
1
+ import { Markdown } from '@storybook/addon-docs';
2
+ import ReadMe from './README.md?raw';
3
+
4
+ <Markdown>{ReadMe}</Markdown>
@@ -0,0 +1,46 @@
1
+ import { FC } from "react";
2
+ import { Axios } from "axios";
3
+ import { MemoryConfig } from "cache-manager";
4
+ import { PluggableList } from "unified";
5
+ export type FAQItem = {
6
+ answer: string;
7
+ question: string;
8
+ questionId: string;
9
+ };
10
+ export type FAQAccordionOnActionProps = {
11
+ questionId: string;
12
+ question: string;
13
+ answer: string;
14
+ accordionIndex: number;
15
+ };
16
+ export type FAQAccordionOnLinkClickProps = FAQAccordionOnActionProps & {
17
+ linkContent: string;
18
+ linkHref?: string | undefined;
19
+ };
20
+ export type FAQAccordionProps = {
21
+ faqList?: FAQItem[] | undefined;
22
+ onLinkClick?: (props: FAQAccordionOnLinkClickProps) => void | undefined;
23
+ onQuestionOpenOrClose?: (props: FAQAccordionOnActionProps) => void | undefined;
24
+ };
25
+ export const isFAQItem: (obj: FAQItem) => obj is FAQItem;
26
+ export const isFAQAccordionProps: (obj: any) => obj is FAQAccordionProps;
27
+ export * from 'styled-components';
28
+ export const FaqItem: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, {}, never>;
29
+ export const FaqAccordion: FC<FAQAccordionProps>;
30
+ export const parseYamlFileWithMdContent: (md: string, remarkPlugins?: PluggableList) => Promise<{
31
+ content: string;
32
+ data: Record<string, any>;
33
+ }>;
34
+ export type PageFAQ = {
35
+ identification: string;
36
+ faq: FAQItem[];
37
+ };
38
+ export const isPageFAQ: (obj: PageFAQ) => obj is PageFAQ;
39
+ export type GetFaqOptionsProps = {
40
+ axiosInstance: Axios;
41
+ cache?: boolean;
42
+ memoryCacheConfig?: MemoryConfig | undefined;
43
+ };
44
+ export const getFAQ: (faqUrl: string, { axiosInstance, cache, memoryCacheConfig }?: GetFaqOptionsProps) => Promise<PageFAQ[]>;
45
+
46
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"mappings":";;;;AAAA,sBAAsB;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wCAAwC;IACtC,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,2CAA2C,yBAAyB,GAAG;IACrE,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC9B,CAAA;AAED,gCAAgC;IAC9B,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,SAAS,CAAA;IAC/B,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,4BAA4B,KAAK,IAAI,GAAG,SAAS,CAAA;IACvE,qBAAqB,CAAC,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,IAAI,GAAG,SAAS,CAAA;CAC/E,CAAA;AAED,OAAO,MAAM,iBAAkB,OAAO,mBAErC,CAAA;AAED,OAAO,MAAM,2BAA4B,GAAG,6BAE3C,CAAA;AClBD,cAAc,mBAAmB,CAAA;ACVjC,OAAO,MAAM,gHAuBZ,CAAA;ACfD,OAAO,MAAM,cAAc,GAAG,iBAAiB,CAiD9C,CAAA;AMtCD,OAAO,MAAM,iCACP,MAAM,kBACM,aAAa,KAC5B,QAAQ;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,MAAM,EAAE,GAAG,CAAC,CAAA;CAAE,CAQxD,CAAA;AAED,sBAAsB;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,EAAE,CAAA;CAAE,CAAA;AAEhE,OAAO,MAAM,iBAAkB,OAAO,mBAErC,CAAA;AAED,iCAAiC;IAC/B,aAAa,EAAE,KAAK,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,iBAAiB,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;CAC7C,CAAA;AAID,OAAO,MAAM,iBACH,MAAM,uEAEb,QAAQ,OAAO,EAAE,CA8BnB,CAAA","sources":["packages/ui/faq/src/src/components/faqAccordion/types.ts","packages/ui/faq/src/styledComponentsWrapper.ts","packages/ui/faq/src/src/components/faqAccordion/styles.tsx","packages/ui/faq/src/src/components/faqAccordion/faqAccordion.tsx","packages/ui/faq/src/src/components/faqAccordion/index.tsx","packages/ui/faq/src/src/components/index.ts","packages/ui/faq/src/src/utils/remarkPlugins/type.ts","packages/ui/faq/src/src/utils/remarkPlugins/getFrontmatter.ts","packages/ui/faq/src/src/utils/remarkPlugins/index.ts","packages/ui/faq/src/src/utils/index.ts","packages/ui/faq/src/src/index.ts","packages/ui/faq/src/index.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,null,"export * from './components'\nexport * from './utils'\n"],"names":[],"version":3,"file":"index.d.ts.map"}
package/dist/index.js ADDED
@@ -0,0 +1,236 @@
1
+ import {jsx as $loPuo$jsx, Fragment as $loPuo$Fragment} from "react/jsx-runtime";
2
+ import "react";
3
+ import $loPuo$reactmarkdown from "react-markdown";
4
+ import $loPuo$reacttotext from "react-to-text";
5
+ import {LidoLink as $loPuo$LidoLink} from "@lidofinance/next-ui-primitives";
6
+ import * as $loPuo$lidofinancelidoui from "@lidofinance/lido-ui";
7
+ import $loPuo$styledcomponents from "styled-components";
8
+ import $loPuo$axios from "axios";
9
+ import {caching as $loPuo$caching} from "cache-manager";
10
+ import {unified as $loPuo$unified} from "unified";
11
+ import $loPuo$remarkparse from "remark-parse";
12
+ import $loPuo$remarkstringify from "remark-stringify";
13
+ import $loPuo$remarkfrontmatter from "remark-frontmatter";
14
+ import $loPuo$remarkdirective from "remark-directive";
15
+ import $loPuo$jsyaml from "js-yaml";
16
+
17
+ function $parcel$exportWildcard(dest, source) {
18
+ Object.keys(source).forEach(function(key) {
19
+ if (key === 'default' || key === '__esModule' || dest.hasOwnProperty(key)) {
20
+ return;
21
+ }
22
+
23
+ Object.defineProperty(dest, key, {
24
+ enumerable: true,
25
+ get: function get() {
26
+ return source[key];
27
+ }
28
+ });
29
+ });
30
+
31
+ return dest;
32
+ }
33
+ function $parcel$export(e, n, v, s) {
34
+ Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
35
+ }
36
+ var $4e053a1b8b64ce9e$exports = {};
37
+ var $49bd0fe341d564cb$exports = {};
38
+ var $17df517d232bb386$exports = {};
39
+
40
+ $parcel$export($17df517d232bb386$exports, "FaqAccordion", function () { return $17df517d232bb386$export$821fcbaf011feac1; });
41
+
42
+
43
+
44
+
45
+
46
+
47
+ var $b871f2fb17bf3607$exports = {};
48
+
49
+ $parcel$export($b871f2fb17bf3607$exports, "FaqItem", function () { return $b871f2fb17bf3607$export$eb463a824a473e05; });
50
+ // Styled Components v5 has issues with ESM modules:
51
+ // https://github.com/styled-components/styled-components/issues/115
52
+ // https://github.com/rollup/rollup/issues/4438
53
+ // It can be solved by using Styled Components v6, which is in beta ATM
54
+ // But it will be better to stop using styled-components at all.
55
+ // This is a temporary workaround, which seems to work well.
56
+
57
+ // @ts-expect-error Property 'default' does not exist on type 'StyledInterface'.
58
+ const $f7fa192b95611bbe$var$styled = (0, $loPuo$styledcomponents).default || (0, $loPuo$styledcomponents);
59
+ var $f7fa192b95611bbe$export$2e2bcd8739ae039 = $f7fa192b95611bbe$var$styled;
60
+
61
+
62
+ const $b871f2fb17bf3607$export$eb463a824a473e05 = (0, $f7fa192b95611bbe$export$2e2bcd8739ae039).div`
63
+ p {
64
+ margin: 0 0 1.6em;
65
+ }
66
+
67
+ :is(p, ul) + p,
68
+ p + :is(ul, ol) {
69
+ margin-top: -1.6em;
70
+ }
71
+
72
+ :is(ul, ol) > li {
73
+ margin-top: 0;
74
+ margin-bottom: 0;
75
+
76
+ & > p {
77
+ margin-top: 0;
78
+ margin-bottom: 0;
79
+ }
80
+ }
81
+
82
+ a {
83
+ text-decoration: none;
84
+ }
85
+ `;
86
+
87
+
88
+ const { Accordion: $17df517d232bb386$var$Accordion } = $loPuo$lidofinancelidoui;
89
+ const $17df517d232bb386$export$821fcbaf011feac1 = ({ faqList: faqList, onLinkClick: onLinkClick, onQuestionOpenOrClose: onQuestionOpenOrClose })=>/*#__PURE__*/ (0, $loPuo$jsx)((0, $loPuo$Fragment), {
90
+ children: faqList?.map(({ questionId: questionId, question: question, answer: answer }, index)=>/*#__PURE__*/ (0, $loPuo$jsx)($17df517d232bb386$var$Accordion, {
91
+ defaultExpanded: index === 0,
92
+ summary: String(question),
93
+ onClick: ()=>{
94
+ onQuestionOpenOrClose?.({
95
+ questionId: questionId,
96
+ question: question,
97
+ answer: answer,
98
+ accordionIndex: index
99
+ });
100
+ },
101
+ children: /*#__PURE__*/ (0, $loPuo$jsx)((0, $b871f2fb17bf3607$export$eb463a824a473e05), {
102
+ children: /*#__PURE__*/ (0, $loPuo$jsx)((0, $loPuo$reactmarkdown), {
103
+ components: {
104
+ a: ({ children: children, href: href, ...rest })=>{
105
+ const linkContent = (0, $loPuo$reacttotext)(children);
106
+ return /*#__PURE__*/ (0, $loPuo$jsx)((0, $loPuo$LidoLink), {
107
+ ...rest,
108
+ href: href ?? "#",
109
+ onClick: ()=>{
110
+ onLinkClick?.({
111
+ questionId: questionId,
112
+ question: question,
113
+ answer: answer,
114
+ accordionIndex: index,
115
+ linkContent: linkContent,
116
+ linkHref: href
117
+ });
118
+ },
119
+ children: linkContent
120
+ });
121
+ }
122
+ },
123
+ children: answer
124
+ })
125
+ })
126
+ }, question))
127
+ });
128
+
129
+
130
+
131
+ var $30e3952008c9e88b$exports = {};
132
+
133
+ $parcel$export($30e3952008c9e88b$exports, "isFAQItem", function () { return $30e3952008c9e88b$export$cfc7e514f00a6e18; });
134
+ $parcel$export($30e3952008c9e88b$exports, "isFAQAccordionProps", function () { return $30e3952008c9e88b$export$e9472c8e1e3c866b; });
135
+ const $30e3952008c9e88b$export$cfc7e514f00a6e18 = (obj)=>{
136
+ return "answer" in obj && "question" in obj;
137
+ };
138
+ const $30e3952008c9e88b$export$e9472c8e1e3c866b = (obj)=>{
139
+ return Array.isArray(obj.faqList);
140
+ };
141
+
142
+
143
+ $parcel$exportWildcard($49bd0fe341d564cb$exports, $17df517d232bb386$exports);
144
+ $parcel$exportWildcard($49bd0fe341d564cb$exports, $b871f2fb17bf3607$exports);
145
+ $parcel$exportWildcard($49bd0fe341d564cb$exports, $30e3952008c9e88b$exports);
146
+
147
+
148
+ $parcel$exportWildcard($4e053a1b8b64ce9e$exports, $49bd0fe341d564cb$exports);
149
+
150
+
151
+ var $4d7a07a404732d40$exports = {};
152
+
153
+ $parcel$export($4d7a07a404732d40$exports, "parseYamlFileWithMdContent", function () { return $4d7a07a404732d40$export$dd386c14013925ba; });
154
+ $parcel$export($4d7a07a404732d40$exports, "isPageFAQ", function () { return $4d7a07a404732d40$export$5c49e5abe2bae48e; });
155
+ $parcel$export($4d7a07a404732d40$exports, "getFAQ", function () { return $4d7a07a404732d40$export$24d135d299ddf6e6; });
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+ const $9f620ec94f086a5a$export$6e7a2400c9873c8e = ()=>(tree, file)=>{
165
+ const node = tree.children[0];
166
+ if (node?.type === "yaml") {
167
+ const data = (0, $loPuo$jsyaml).load(node.value);
168
+ file.data.frontmatter = data;
169
+ tree.children.splice(0, 1);
170
+ } else file.data.frontmatter = {};
171
+ };
172
+
173
+
174
+
175
+
176
+
177
+
178
+ const $4d7a07a404732d40$var$ttlMs = 600000 /* 10 minutes */ ;
179
+ const $4d7a07a404732d40$var$memoryCacheConfigDefault = {
180
+ max: 100,
181
+ ttl: $4d7a07a404732d40$var$ttlMs
182
+ };
183
+ let $4d7a07a404732d40$var$memoryCache;
184
+ const $4d7a07a404732d40$var$getMemoryCacheInstance = async (memoryCacheConfig = $4d7a07a404732d40$var$memoryCacheConfigDefault)=>{
185
+ $4d7a07a404732d40$var$memoryCache ??= await (0, $loPuo$caching)("memory", memoryCacheConfig);
186
+ return $4d7a07a404732d40$var$memoryCache;
187
+ };
188
+ const $4d7a07a404732d40$export$dd386c14013925ba = async (md, remarkPlugins)=>{
189
+ const file = await (0, $loPuo$unified)().use((0, $loPuo$remarkparse)).use((0, $loPuo$remarkstringify)).use(remarkPlugins || []).process(md);
190
+ return {
191
+ content: String(file),
192
+ data: file.data
193
+ };
194
+ };
195
+ const $4d7a07a404732d40$export$5c49e5abe2bae48e = (obj)=>{
196
+ return "identification" in obj && "faq" in obj;
197
+ };
198
+ const $4d7a07a404732d40$var$faqOptionsDefault = {
199
+ axiosInstance: (0, $loPuo$axios),
200
+ cache: true
201
+ };
202
+ const $4d7a07a404732d40$export$24d135d299ddf6e6 = async (faqUrl, { axiosInstance: axiosInstance, cache: cache, memoryCacheConfig: memoryCacheConfig } = $4d7a07a404732d40$var$faqOptionsDefault)=>{
203
+ let memoryCacheInstance;
204
+ let rawFaqData;
205
+ if (cache) {
206
+ memoryCacheInstance = await $4d7a07a404732d40$var$getMemoryCacheInstance(memoryCacheConfig);
207
+ rawFaqData = await memoryCacheInstance.get(faqUrl);
208
+ }
209
+ if (!rawFaqData) {
210
+ rawFaqData = (await axiosInstance.get(faqUrl)).data;
211
+ if (cache && memoryCacheInstance) await memoryCacheInstance.set(faqUrl, rawFaqData, $4d7a07a404732d40$var$ttlMs);
212
+ }
213
+ // Temporary solution
214
+ // The CMS, while generating md, adds an '\_' between the text and
215
+ // the link, which is then replaced by 'nbsp;' (non-breaking space)
216
+ // and interferes correct content display
217
+ // To fix this, we replace '\_' with ' '
218
+ const fixedFileContent = rawFaqData.replace(/\\_\[/gm, " [").replace(/\)\\_/gm, ") ");
219
+ const { data: data } = await $4d7a07a404732d40$export$dd386c14013925ba(fixedFileContent, [
220
+ (0, $loPuo$remarkdirective),
221
+ [
222
+ (0, $loPuo$remarkfrontmatter),
223
+ [
224
+ "yaml"
225
+ ]
226
+ ],
227
+ (0, $9f620ec94f086a5a$export$6e7a2400c9873c8e)
228
+ ]);
229
+ return data?.frontmatter?.pages ?? [];
230
+ };
231
+
232
+
233
+
234
+
235
+ export {$17df517d232bb386$export$821fcbaf011feac1 as FaqAccordion, $b871f2fb17bf3607$export$eb463a824a473e05 as FaqItem, $30e3952008c9e88b$export$cfc7e514f00a6e18 as isFAQItem, $30e3952008c9e88b$export$e9472c8e1e3c866b as isFAQAccordionProps, $4d7a07a404732d40$export$dd386c14013925ba as parseYamlFileWithMdContent, $4d7a07a404732d40$export$5c49e5abe2bae48e as isPageFAQ, $4d7a07a404732d40$export$24d135d299ddf6e6 as getFAQ};
236
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"mappings":"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","sources":["packages/ui/faq/src/index.ts","packages/ui/faq/src/components/index.ts","packages/ui/faq/src/components/faqAccordion/index.tsx","packages/ui/faq/src/components/faqAccordion/faqAccordion.tsx","packages/ui/faq/src/components/faqAccordion/styles.tsx","packages/ui/faq/styledComponentsWrapper.ts","packages/ui/faq/src/components/faqAccordion/types.ts","packages/ui/faq/src/utils/index.ts","packages/ui/faq/src/utils/remarkPlugins/index.ts","packages/ui/faq/src/utils/remarkPlugins/getFrontmatter.ts","packages/ui/faq/src/utils/remarkPlugins/type.ts"],"sourcesContent":["export * from './components'\nexport * from './utils'\n","export * from './faqAccordion'\n","export * from './faqAccordion'\nexport * from './styles'\nexport * from './types'\n","import React, { FC } from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport reactToText from 'react-to-text'\nimport { LidoLink } from '@lidofinance/next-ui-primitives'\nimport * as LidoUI from '@lidofinance/lido-ui'\nconst { Accordion } = LidoUI\n\nimport { FAQAccordionProps } from './types'\nimport { FaqItem } from './styles'\n\nexport const FaqAccordion: FC<FAQAccordionProps> = ({ faqList, onLinkClick, onQuestionOpenOrClose }) => (\n <>\n {faqList?.map(({ questionId, question, answer }, index) => (\n <Accordion\n key={question}\n defaultExpanded={index === 0}\n summary={String(question)}\n onClick={() => {\n onQuestionOpenOrClose?.({\n questionId,\n question,\n answer,\n accordionIndex: index,\n })\n }}\n >\n <FaqItem>\n <ReactMarkdown\n components={{\n a: ({ children, href, ...rest }) => {\n const linkContent = reactToText(children)\n\n return (\n <LidoLink\n {...rest}\n href={href ?? '#'}\n onClick={() => {\n onLinkClick?.({\n questionId,\n question,\n answer,\n accordionIndex: index,\n linkContent,\n linkHref: href,\n })\n }}\n >\n {linkContent}\n </LidoLink>\n )\n },\n }}\n >\n {answer}\n </ReactMarkdown>\n </FaqItem>\n </Accordion>\n ))}\n </>\n)\n","import styled from '../../../styledComponentsWrapper'\n\nexport const FaqItem = styled.div`\n p {\n margin: 0 0 1.6em;\n }\n\n :is(p, ul) + p,\n p + :is(ul, ol) {\n margin-top: -1.6em;\n }\n\n :is(ul, ol) > li {\n margin-top: 0;\n margin-bottom: 0;\n\n & > p {\n margin-top: 0;\n margin-bottom: 0;\n }\n }\n\n a {\n text-decoration: none;\n }\n`\n","// Styled Components v5 has issues with ESM modules:\n// https://github.com/styled-components/styled-components/issues/115\n// https://github.com/rollup/rollup/issues/4438\n// It can be solved by using Styled Components v6, which is in beta ATM\n// But it will be better to stop using styled-components at all.\n// This is a temporary workaround, which seems to work well.\n\nimport _styled, { StyledInterface } from 'styled-components'\n\n// @ts-expect-error Property 'default' does not exist on type 'StyledInterface'.\nconst styled: StyledInterface = _styled.default || _styled\n\nexport * from 'styled-components'\nexport default styled\n","export type FAQItem = {\n answer: string\n question: string\n questionId: string\n}\n\nexport type FAQAccordionOnActionProps = {\n questionId: string\n question: string\n answer: string\n accordionIndex: number\n}\n\nexport type FAQAccordionOnLinkClickProps = FAQAccordionOnActionProps & {\n linkContent: string\n linkHref?: string | undefined\n}\n\nexport type FAQAccordionProps = {\n faqList?: FAQItem[] | undefined\n onLinkClick?: (props: FAQAccordionOnLinkClickProps) => void | undefined\n onQuestionOpenOrClose?: (props: FAQAccordionOnActionProps) => void | undefined\n}\n\nexport const isFAQItem = (obj: FAQItem): obj is FAQItem => {\n return 'answer' in obj && 'question' in obj\n}\n\nexport const isFAQAccordionProps = (obj: any): obj is FAQAccordionProps => {\n return Array.isArray(obj.faqList)\n}\n","import axios, { Axios } from 'axios'\nimport { caching, MemoryCache, MemoryConfig } from 'cache-manager'\nimport { unified, PluggableList } from 'unified'\nimport remarkParse from 'remark-parse'\nimport remarkStringify from 'remark-stringify'\nimport remarkFrontmatter from 'remark-frontmatter'\nimport remarkDirective from 'remark-directive'\n\nimport { FAQItem } from '../components'\nimport { getFrontmatter } from './remarkPlugins'\n\nconst ttlMs = 6 * 100 * 1000 /* 10 minutes */\nconst memoryCacheConfigDefault = { max: 100, ttl: ttlMs }\nlet memoryCache: MemoryCache\n\nconst getMemoryCacheInstance = async (memoryCacheConfig: MemoryConfig = memoryCacheConfigDefault) => {\n memoryCache ??= await caching('memory', memoryCacheConfig)\n\n return memoryCache\n}\n\nexport const parseYamlFileWithMdContent = async (\n md: string,\n remarkPlugins?: PluggableList,\n): Promise<{ content: string; data: Record<string, any> }> => {\n const file = await unified()\n .use(remarkParse)\n .use(remarkStringify)\n .use(remarkPlugins || [])\n .process(md)\n\n return { content: String(file), data: file.data }\n}\n\nexport type PageFAQ = { identification: string; faq: FAQItem[] }\n\nexport const isPageFAQ = (obj: PageFAQ): obj is PageFAQ => {\n return 'identification' in obj && 'faq' in obj\n}\n\nexport type GetFaqOptionsProps = {\n axiosInstance: Axios\n cache?: boolean\n memoryCacheConfig?: MemoryConfig | undefined\n}\n\nconst faqOptionsDefault: GetFaqOptionsProps = { axiosInstance: axios, cache: true }\n\nexport const getFAQ = async (\n faqUrl: string,\n { axiosInstance, cache, memoryCacheConfig } = faqOptionsDefault,\n): Promise<PageFAQ[]> => {\n let memoryCacheInstance: MemoryCache | undefined\n let rawFaqData: string | undefined\n\n if (cache) {\n memoryCacheInstance = await getMemoryCacheInstance(memoryCacheConfig)\n rawFaqData = await memoryCacheInstance.get(faqUrl)\n }\n\n if (!rawFaqData) {\n rawFaqData = (await axiosInstance.get(faqUrl)).data as string\n\n if (cache && memoryCacheInstance) {\n await memoryCacheInstance.set(faqUrl, rawFaqData, ttlMs)\n }\n }\n\n // Temporary solution\n // The CMS, while generating md, adds an '\\_' between the text and\n // the link, which is then replaced by 'nbsp;' (non-breaking space)\n // and interferes correct content display\n // To fix this, we replace '\\_' with ' '\n const fixedFileContent = rawFaqData.replace(/\\\\_\\[/gm, ' [').replace(/\\)\\\\_/gm, ') ')\n\n const { data } = await parseYamlFileWithMdContent(fixedFileContent, [\n remarkDirective,\n [remarkFrontmatter, ['yaml']],\n getFrontmatter,\n ])\n return data?.frontmatter?.pages ?? []\n}\n","export * from './getFrontmatter'\nexport * from './type'\n","import yaml from 'js-yaml'\n\nimport { Tree, VFileWithOutput } from './type'\n\n// eslint-disable-next-line unicorn/consistent-function-scoping\nexport const getFrontmatter = () => (tree: Tree, file: VFileWithOutput<null>) => {\n const node = tree.children[0]\n\n if (node?.type === 'yaml') {\n const data = yaml.load(node.value)\n file.data.frontmatter = data\n tree.children.splice(0, 1)\n } else {\n file.data.frontmatter = {}\n }\n}\n","import { Root, Parent, Content } from 'mdast'\nimport { VFileWithOutput } from 'unified'\n\nexport type Tree = Root\n\nexport type Node = Parent\n\nexport type { Content, VFileWithOutput }\n"],"names":[],"version":3,"file":"index.js.map"}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@lidofinance/ui-faq",
3
+ "description": "FAQ",
4
+ "repository": "https://github.com/lidofinance/warehouse.git",
5
+ "homepage": "https://github.com/lidofinance/warehouse/tree/main/packages/ui/faq",
6
+ "bugs": {
7
+ "url": "https://github.com/lidofinance/warehouse/issues"
8
+ },
9
+ "license": "MIT",
10
+ "version": "0.38.0",
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "engines": {
15
+ "node": ">= 16",
16
+ "browsers": "> 0.5%, last 2 versions, not dead"
17
+ },
18
+ "type": "module",
19
+ "source": "./src/index.ts",
20
+ "module": "dist/index.js",
21
+ "types": "dist/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "import": "./dist/index.js"
25
+ }
26
+ },
27
+ "scripts": {
28
+ "build": "parcel build",
29
+ "lint": "eslint . && prettier --check src",
30
+ "lint:fix": "eslint --fix . && prettier --check src --write",
31
+ "types": "tsc --noEmit"
32
+ },
33
+ "peerDependencies": {
34
+ "@lidofinance/lido-ui": "^3.7.3",
35
+ "@lidofinance/next-ui-primitives": "~0.38.0",
36
+ "axios": "^1.5.0",
37
+ "cache-manager": "^5.2.3",
38
+ "react": "17 || 18",
39
+ "styled-components": "^5.3.5"
40
+ },
41
+ "devDependencies": {
42
+ "@lidofinance/config-prettier": "~0.38.0",
43
+ "@lidofinance/lido-ui": "^3.7.3",
44
+ "@lidofinance/next-ui-primitives": "~0.38.0",
45
+ "@storybook/react": "^7.0.7",
46
+ "@types/js-yaml": "^4.0.5",
47
+ "@types/mdast": "^3.0.11",
48
+ "@types/react": "^18.0.25",
49
+ "@types/styled-components": "^5.1.26",
50
+ "axios": "^1.5.0",
51
+ "cache-manager": "^5.2.3",
52
+ "react-to-text": "^2.0.1"
53
+ },
54
+ "dependencies": {
55
+ "js-yaml": "^4.1.0",
56
+ "mdast": "^3.0.0",
57
+ "react-markdown": "^8.0.7",
58
+ "react-to-text": "^2.0.1",
59
+ "remark-directive": "^2.0.1",
60
+ "remark-frontmatter": "^4.0.1",
61
+ "remark-parse": "^10.0.2",
62
+ "remark-stringify": "^10.0.3",
63
+ "unified": "^10.1.2"
64
+ }
65
+ }