@apify/ui-library 0.71.1-featcolortokens-178953.63 → 0.71.1-featcolortokens-178953.67

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 (86) hide show
  1. package/dist/tsconfig.build.tsbuildinfo +1 -1
  2. package/package.json +3 -2
  3. package/src/codemods/generate_typograpy_tokens_files.mjs +137 -0
  4. package/src/components/action_link.tsx +60 -0
  5. package/src/components/actor_template_card.tsx +116 -0
  6. package/src/components/badge.tsx +148 -0
  7. package/src/components/banner.tsx +94 -0
  8. package/src/components/blog_article.tsx +85 -0
  9. package/src/components/box.tsx +127 -0
  10. package/src/components/button.tsx +305 -0
  11. package/src/components/chip.tsx +128 -0
  12. package/src/components/code/action_button.tsx +96 -0
  13. package/src/components/code/code_block/code_block.styled.tsx +180 -0
  14. package/src/components/code/code_block/code_block.tsx +224 -0
  15. package/src/components/code/code_block/code_block_with_tabs.tsx +257 -0
  16. package/src/components/code/code_block/utils.tsx +67 -0
  17. package/src/components/code/index.ts +5 -0
  18. package/src/components/code/inline_code/inline_code.tsx +62 -0
  19. package/src/components/code/one_line_code/one_line_code.tsx +228 -0
  20. package/src/components/code/prism_highlighter.tsx +180 -0
  21. package/src/components/color_wheel_gradient.tsx +31 -0
  22. package/src/components/floating/index.ts +3 -0
  23. package/src/components/floating/menu.tsx +189 -0
  24. package/src/components/floating/menu_common.tsx +31 -0
  25. package/src/components/floating/menu_components.tsx +99 -0
  26. package/src/components/image.tsx +24 -0
  27. package/src/components/index.ts +22 -0
  28. package/src/components/link.tsx +114 -0
  29. package/src/components/message.tsx +153 -0
  30. package/src/components/rating.tsx +106 -0
  31. package/src/components/readme_renderer/index.ts +3 -0
  32. package/src/components/readme_renderer/pythonize_value.ts +76 -0
  33. package/src/components/readme_renderer/table_of_contents.tsx +272 -0
  34. package/src/components/readme_renderer/utils.tsx +46 -0
  35. package/src/components/simple_markdown/index.ts +2 -0
  36. package/src/components/simple_markdown/simple_markdown.tsx +214 -0
  37. package/src/components/simple_markdown/simple_markdown_components.tsx +293 -0
  38. package/src/components/tabs/index.ts +2 -0
  39. package/src/components/tabs/tab.tsx +217 -0
  40. package/src/components/tabs/tabs.tsx +169 -0
  41. package/src/components/tag.tsx +196 -0
  42. package/src/components/text/heading_content.tsx +56 -0
  43. package/src/components/text/heading_marketing.tsx +55 -0
  44. package/src/components/text/heading_shared.tsx +55 -0
  45. package/src/components/text/index.ts +19 -0
  46. package/src/components/text/text_base.tsx +52 -0
  47. package/src/components/text/text_content.tsx +104 -0
  48. package/src/components/text/text_marketing.tsx +152 -0
  49. package/src/components/text/text_shared.tsx +95 -0
  50. package/src/components/tile/horizontal_tile.tsx +77 -0
  51. package/src/components/tile/index.ts +2 -0
  52. package/src/components/tile/shared.ts +27 -0
  53. package/src/components/tile/vertical_tile.tsx +59 -0
  54. package/src/components/to_consolidate/card.tsx +141 -0
  55. package/src/components/to_consolidate/index.ts +4 -0
  56. package/src/components/to_consolidate/markdown.tsx +609 -0
  57. package/src/components/to_consolidate/pagination.tsx +136 -0
  58. package/src/components/to_consolidate/tab_number_chip.tsx +31 -0
  59. package/src/design_system/colors/build_color_tokens.js +183 -0
  60. package/src/design_system/colors/figma_color_tokens.dark.json +886 -0
  61. package/src/design_system/colors/figma_color_tokens.light.json +886 -0
  62. package/src/design_system/colors/generated/colors_theme.dark.ts +110 -0
  63. package/src/design_system/colors/generated/colors_theme.light.ts +110 -0
  64. package/src/design_system/colors/generated/css_variables.dark.ts +147 -0
  65. package/src/design_system/colors/generated/css_variables.light.ts +147 -0
  66. package/src/design_system/colors/generated/css_variables_palette.dark.ts +74 -0
  67. package/src/design_system/colors/generated/css_variables_palette.light.ts +74 -0
  68. package/src/design_system/colors/generated/properties_theme.ts +179 -0
  69. package/src/design_system/colors/index.ts +7 -0
  70. package/src/design_system/supernova_typography_tokens.json +657 -0
  71. package/src/design_system/theme.ts +25 -0
  72. package/src/design_system/tokens/index.ts +5 -0
  73. package/src/design_system/tokens/layouts.ts +29 -0
  74. package/src/design_system/tokens/radiuses.ts +22 -0
  75. package/src/design_system/tokens/shadows.ts +22 -0
  76. package/src/design_system/tokens/spaces.ts +15 -0
  77. package/src/design_system/tokens/transitions.ts +19 -0
  78. package/src/design_system/typography_theme.ts +197 -0
  79. package/src/index.ts +8 -0
  80. package/src/type_utils.ts +7 -0
  81. package/src/ui_dependency_provider.tsx +58 -0
  82. package/src/utils/copy_to_clipboard.ts +24 -0
  83. package/src/utils/image_color.ts +42 -0
  84. package/src/utils/index.ts +4 -0
  85. package/src/utils/resize_observer.ts +18 -0
  86. package/src/utils/sanitization.ts +14 -0
@@ -0,0 +1,214 @@
1
+ import type { Element, Root, Text as TextNode } from 'hast';
2
+ import React, { useCallback, useMemo, useRef } from 'react';
3
+ import type { Components } from 'react-markdown';
4
+ import ReactMarkdown, { uriTransformer } from 'react-markdown';
5
+ import type { ReactMarkdownOptions } from 'react-markdown/lib/react-markdown';
6
+ import rehypeRaw from 'rehype-raw';
7
+ import rehypeSanitize from 'rehype-sanitize';
8
+ import remarkGfm from 'remark-gfm';
9
+ import styled from 'styled-components';
10
+ import type { Pluggable, PluggableList } from 'unified';
11
+ import { visit } from 'unist-util-visit';
12
+
13
+ import { theme } from '../../design_system/theme.js';
14
+ import { useSharedUiDependencies } from '../../ui_dependency_provider.js';
15
+ import { Box } from '../box.js';
16
+ import { isUrlExternal } from '../link.js';
17
+ import { cleanMarkdown } from '../readme_renderer/utils.js';
18
+ import { HeadingContent } from '../text/heading_content.js';
19
+ import { Heading, Text } from '../text/index.js';
20
+ import { TextContent } from '../text/text_content.js';
21
+ import {
22
+ MarkdownBlockQuote,
23
+ MarkdownCode,
24
+ MarkdownLink,
25
+ MarkdownTable,
26
+ } from './simple_markdown_components.js';
27
+
28
+ export type SimpleMarkdownComponents = Components;
29
+
30
+ export const defaultAllowedElements = [
31
+ 'a',
32
+ 'b',
33
+ 'blockquote',
34
+ 'br',
35
+ 'center',
36
+ 'code',
37
+ 'del',
38
+ 'em',
39
+ 'h1',
40
+ 'h2',
41
+ 'h3',
42
+ 'h4',
43
+ 'h5',
44
+ 'hr',
45
+ 'i',
46
+ 'img',
47
+ 'li',
48
+ 'ol',
49
+ 'p',
50
+ 'pre',
51
+ 'span',
52
+ 'strong',
53
+ 'table',
54
+ 'tbody',
55
+ 'td',
56
+ 'tfoot',
57
+ 'th',
58
+ 'thead',
59
+ 'tr',
60
+ 'u',
61
+ 'ul',
62
+ ];
63
+
64
+ const StyledMarkdown = styled(ReactMarkdown)`
65
+ scroll-margin-top: 10px;
66
+
67
+ @font-face {
68
+ font-family: "ellipsis-font";
69
+ src: local("Courier");
70
+ unicode-range: U+2026;
71
+ size-adjust: 0%;
72
+ }
73
+
74
+ img {
75
+ max-width: 100%;
76
+ }
77
+
78
+ hr {
79
+ color: ${theme.color.neutral.border};
80
+ }
81
+ `;
82
+
83
+ // Function to recursively process unsupported elements
84
+ const unwrapUnsupportedElement = (node: Element): (Element | TextNode)[] => {
85
+ return node.children.flatMap((child) => {
86
+ if (child.type === 'text') {
87
+ return child; // Keep text as is
88
+ }
89
+ if (child.type === 'element') {
90
+ if (defaultAllowedElements.includes(child.tagName)) {
91
+ return child; // Keep supported elements
92
+ }
93
+ return unwrapUnsupportedElement(child as Element);
94
+ }
95
+ return []; // Ignore other node types
96
+ });
97
+ };
98
+
99
+ const getUnsupportedRehypeTagsSanitationPlugIn = (
100
+ allowedElements: string[],
101
+ ): Pluggable<unknown[]> => () => (tree: Root) => {
102
+ visit(tree, 'element', (node, index, parent) => {
103
+ if (!allowedElements.includes(node.tagName) && parent && typeof index === 'number') {
104
+ // Replace unsupported element with its valid children
105
+ parent.children.splice(index, 1, ...unwrapUnsupportedElement(node));
106
+ }
107
+ });
108
+ };
109
+
110
+ export const defaultRehypePlugins = [rehypeRaw];
111
+ export const defaultRemarkPlugins = [remarkGfm];
112
+
113
+ // TODO: Add Image component
114
+ const regularMarkdownSizeComponents: Components = {
115
+ h1: ({ children }) => <HeadingContent mt='space32' mb='space16' type='heading1'>{children}</HeadingContent>,
116
+ h2: ({ children }) => <HeadingContent mt='space32' mb='space16' type='heading2'>{children}</HeadingContent>,
117
+ h3: ({ children }) => <HeadingContent mt='space32' mb='space16' type='heading3'>{children}</HeadingContent>,
118
+ h4: ({ children }) => <HeadingContent mt='space32' mb='space16' type='heading4'>{children}</HeadingContent>,
119
+ h5: ({ children }) => <HeadingContent mt='space32' mb='space16' type='heading5'>{children}</HeadingContent>,
120
+ h6: ({ children }) => <HeadingContent mt='space32' mb='space16' type='heading6'>{children}</HeadingContent>,
121
+ p: ({ children }) => (<TextContent my='space16'>{children}</TextContent>),
122
+ strong: ({ children }) => <TextContent as='strong' weight='bold'>{children}</TextContent>,
123
+ b: ({ children }) => <TextContent as='b' weight='bold'>{children}</TextContent>,
124
+ th: ({ children }) => <TextContent as='th' weight='bold'>{children}</TextContent>,
125
+ blockquote: ({ children }) => <MarkdownBlockQuote>{children}</MarkdownBlockQuote>,
126
+ table: ({ children }) => <MarkdownTable>{children}</MarkdownTable>,
127
+ ul: ({ children }) => <Box as='ul' pl='space32'>{children}</Box>,
128
+ ol: ({ children, start }) => <TextContent as='ol' pl='space32' start={start}>{children}</TextContent>,
129
+ li: ({ children }) => <TextContent as='li' mt='space4'>{children}</TextContent>,
130
+ a: ({ children, href }) => <MarkdownLink to={href}>{children}</MarkdownLink>,
131
+ code: ({ children, inline }) => <MarkdownCode inline={inline} size='regular'>{children}</MarkdownCode>,
132
+ };
133
+
134
+ const smallMarkdownSizeComponents: Components = {
135
+ h1: ({ children }) => <Heading mt='space32' mb='space16' type='title2xl'>{children}</Heading>,
136
+ h2: ({ children }) => <Heading mt='space32' mb='space16' type='titleXl'>{children}</Heading>,
137
+ h3: ({ children }) => <Heading mt='space32' mb='space16' type='titleL'>{children}</Heading>,
138
+ h4: ({ children }) => <Heading mt='space32' mb='space16' type='titleM'>{children}</Heading>,
139
+ h5: ({ children }) => <Heading mt='space32' mb='space16' type='titleS'>{children}</Heading>,
140
+ h6: ({ children }) => <Heading mt='space32' mb='space16' type='titleXs'>{children}</Heading>,
141
+ p: ({ children }) => (<Text my='space16'>{children}</Text>),
142
+ strong: ({ children }) => <Text as='strong' weight='bold'>{children}</Text>,
143
+ b: ({ children }) => <Text as='b' weight='bold'>{children}</Text>,
144
+ th: ({ children }) => <Text as='th' weight='bold'>{children}</Text>,
145
+ blockquote: ({ children }) => <MarkdownBlockQuote>{children}</MarkdownBlockQuote>,
146
+ table: ({ children }) => <MarkdownTable>{children}</MarkdownTable>,
147
+ ul: ({ children }) => <Box as='ul' pl='space32'>{children}</Box>,
148
+ ol: ({ children, start }) => <Text as='ol' pl='space32' start={start}>{children}</Text>,
149
+ li: ({ children }) => <Text as='li' mt='space4'>{children}</Text>,
150
+ a: ({ children, href }) => <MarkdownLink to={href}>{children}</MarkdownLink>,
151
+ code: ({ children, inline }) => <MarkdownCode inline={inline} size='small'>{children}</MarkdownCode>,
152
+ };
153
+
154
+ type MarkdownSize = 'regular' | 'small';
155
+
156
+ interface SimpleMarkdownProps extends ReactMarkdownOptions {
157
+ size?: MarkdownSize,
158
+ }
159
+
160
+ const useDefaultUrlTransform = () => {
161
+ const { windowLocationHost } = useSharedUiDependencies();
162
+
163
+ return useCallback((url: string) => {
164
+ if (!isUrlExternal(url, windowLocationHost)) {
165
+ // We want to make sure internal links will be relative links without https://host at the beginning because Link doesn't work with these
166
+ return url.replace(/^(https?:\/\/)?(www\.)?[^/]+/, '') || '/';
167
+ }
168
+
169
+ return url;
170
+ }, [windowLocationHost]);
171
+ };
172
+
173
+ export const SimpleMarkdown: React.FC<SimpleMarkdownProps> = ({
174
+ size = 'regular', // small is default for console
175
+ children: markdown,
176
+ components,
177
+ rehypePlugins,
178
+ remarkPlugins,
179
+ transformLinkUri,
180
+ allowedElements,
181
+ ...rest
182
+ }) => {
183
+ const cleanedMarkdown = useMemo(() => cleanMarkdown(markdown), [markdown]);
184
+
185
+ const effectiveAllowedElements = useRef(allowedElements || defaultAllowedElements);
186
+
187
+ const effectiveComponents = useRef({
188
+ ...(size === 'regular' ? regularMarkdownSizeComponents : smallMarkdownSizeComponents),
189
+ ...components,
190
+ });
191
+
192
+ const rehypePluginsRef = useRef<PluggableList>([
193
+ ...(rehypePlugins || [...defaultRehypePlugins, getUnsupportedRehypeTagsSanitationPlugIn(effectiveAllowedElements.current)]),
194
+ rehypeSanitize, // lets always sanitize the output
195
+ ]);
196
+
197
+ const defaultUrlTransform = useDefaultUrlTransform();
198
+
199
+ return (
200
+ <StyledMarkdown
201
+ components={effectiveComponents.current}
202
+ rehypePlugins={rehypePluginsRef.current}
203
+ remarkPlugins={remarkPlugins || defaultRemarkPlugins}
204
+ allowedElements={effectiveAllowedElements.current}
205
+ transformLinkUri={(href, children, title) => {
206
+ const transformed = transformLinkUri ? transformLinkUri(href, children, title) : defaultUrlTransform(href);
207
+ return uriTransformer(transformed);
208
+ }}
209
+ {...rest}
210
+ >
211
+ {cleanedMarkdown}
212
+ </StyledMarkdown>
213
+ );
214
+ };
@@ -0,0 +1,293 @@
1
+ import qs from 'query-string';
2
+ import React from 'react';
3
+ import type { CodeProps, ReactMarkdownProps } from 'react-markdown/lib/ast-to-react';
4
+ import styled from 'styled-components';
5
+
6
+ import { CheckIcon, LinkIcon } from '@apify/ui-icons';
7
+
8
+ import { theme } from '../../design_system/theme.js';
9
+ import type { WithOptional } from '../../type_utils.js';
10
+ import { useCopyToClipboard } from '../../utils/index.js';
11
+ import { Box } from '../box.js';
12
+ import { CodeBlock, InlineCode, OneLineCode } from '../code/index.js';
13
+ import type { LinkProps } from '../link.js';
14
+ import { Link } from '../link.js';
15
+ import { slugifyHeadingChildren } from '../readme_renderer/utils.js';
16
+ import type { HeadingSharedProps } from '../text/heading_shared.js';
17
+ import { Heading } from '../text/index.js';
18
+ import type { SharedTextProps, SharedTextSize } from '../text/text_shared.js';
19
+
20
+ const simpleMarkdownClassNames = {
21
+ HEADING_ICON_LINK: 'headingIconLink',
22
+ } as const;
23
+
24
+ export const MarkdownPlainHeading: React.FC<HeadingSharedProps> = ({
25
+ children,
26
+ ...rest
27
+ }) => {
28
+ const id = slugifyHeadingChildren(children);
29
+
30
+ return (
31
+ <Heading
32
+ mt='space32'
33
+ mb='space16'
34
+ id={id}
35
+ {...rest}
36
+ >
37
+ {children}
38
+ </Heading>
39
+ );
40
+ };
41
+
42
+ const StyledMarkdownHeading = styled(Box)`
43
+ display: flex;
44
+ align-items: center;
45
+ gap: ${theme.space.space4};
46
+
47
+ .${simpleMarkdownClassNames.HEADING_ICON_LINK} {
48
+ height: 16px;
49
+ display: none;
50
+
51
+ svg {
52
+ max-height: 1em !important;
53
+ }
54
+ }
55
+
56
+ &:hover {
57
+ .${simpleMarkdownClassNames.HEADING_ICON_LINK} {
58
+ display: initial;
59
+ }
60
+ }
61
+ `;
62
+
63
+ /**
64
+ * Default markdown heading that renders copy icon next to it.
65
+ * Use `MarkdownPlainHeading` if you want to render simple heading instead
66
+ */
67
+ // TODO: This should be used for readmes
68
+ export const MarkdownHeadingWrapper: React.FC<HeadingSharedProps> = ({
69
+ children,
70
+ ...rest
71
+ }) => {
72
+ const id = slugifyHeadingChildren(children);
73
+
74
+ const [isCopied, handleClick] = useCopyToClipboard({
75
+ text: id ?? '',
76
+ // We want the whole URL to be copied, not just the ID
77
+ transform: (text) => {
78
+ const url = new URL(window.location.href);
79
+ url.hash = `#${text}`;
80
+ return url.toString();
81
+ },
82
+ });
83
+
84
+ return (
85
+ <StyledMarkdownHeading
86
+ mt='space32'
87
+ mb='space16'
88
+ id={id}
89
+ {...rest}
90
+ >
91
+ {children}
92
+ <Link
93
+ className={simpleMarkdownClassNames.HEADING_ICON_LINK}
94
+ onClick={handleClick}
95
+ to={`#${id}`}
96
+ >
97
+ {isCopied ? (
98
+ <CheckIcon
99
+ size="16"
100
+ color={theme.color.success.action}
101
+ />
102
+ ) : (
103
+ <LinkIcon
104
+ size="16"
105
+ color={theme.color.primary.text}
106
+ />
107
+ )}
108
+ </Link>
109
+ </StyledMarkdownHeading>
110
+ );
111
+ };
112
+
113
+ const StyledInlineCode = styled(InlineCode)`
114
+ /* If code is rendered within heading, it should inherit its font styles */
115
+ /* TODO: Look at implementation of InlineCode - maybe we can live without it */
116
+ h1 & code, h2 & code, h3 & code, h4 & code, h5 & code {
117
+ font-size: inherit !important;
118
+ line-height: inherit !important;
119
+ }
120
+
121
+ b & code, strong & code{
122
+ font-weight: inherit !important;
123
+ }
124
+ `;
125
+
126
+ type MarkdownCodeProps = Pick<CodeProps, 'inline' | 'className' | 'children'>
127
+
128
+ export const MarkdownCode: React.FC<MarkdownCodeProps & { size: SharedTextSize }> = ({
129
+ inline,
130
+ className,
131
+ children,
132
+ size,
133
+ }) => {
134
+ if (inline) {
135
+ return <StyledInlineCode size={size} className={className}>{children}</StyledInlineCode>;
136
+ }
137
+
138
+ const code = String(children).replace(/\n$/, '').trim();
139
+ const match = /language-(\w+)/.exec(className || '');
140
+ const language = match?.[1]?.toLowerCase();
141
+ const isOneLineCode = code.split('\n').length <= 1;
142
+
143
+ if (isOneLineCode) {
144
+ return (
145
+ <OneLineCode
146
+ language={language}
147
+ size={size}
148
+ fullWidth
149
+ >
150
+ {code}
151
+ </OneLineCode>
152
+ );
153
+ }
154
+
155
+ return (
156
+ <CodeBlock
157
+ content={code}
158
+ language={language}
159
+ size={size}
160
+ hideLineNumbers
161
+ fullWidth
162
+ hideBashHeader
163
+ hideBashPromptPrefixes
164
+ />
165
+ );
166
+ };
167
+
168
+ const youtubeRegex = /^(?:https?:\/\/)?(?:www\.)?(?:m\.)?(?:youtube(?:-nocookie)?\.com|youtu\.be)\/(?:watch\?v=|embed\/|v\/)?([a-zA-Z0-9\-_]+)(?:\S*)?$/;
169
+ const vimeoRegex = /^((?:https?:\/\/)?(?:player\.)?vimeo\.com(?:\/video)?\/(\d+))$/;
170
+
171
+ const getVideoSrc = (link: string) => {
172
+ const youtubeLink = link.match(youtubeRegex);
173
+ const vimeoLink = link.match(vimeoRegex);
174
+ let src;
175
+ if (youtubeLink) {
176
+ // add rel=0 to disable related videos from other channels at the end of the video
177
+ // add enablejsapi=1 to enable tracking videos via API through Google Analytics
178
+ src = qs.stringifyUrl({ url: `https://www.youtube.com/embed/${youtubeLink[1]}`, query: { rel: 0, enablejsapi: 1 } });
179
+ }
180
+ if (vimeoLink) src = `https://player.vimeo.com/video/${vimeoLink[2]}`;
181
+
182
+ return src;
183
+ };
184
+
185
+ const StyledVideo = styled.div`
186
+ width: 65%;
187
+
188
+ & > div {
189
+ position: relative;
190
+ overflow: hidden;
191
+ width: 100%;
192
+ padding-top: 56.25%;
193
+
194
+ & > iframe {
195
+ position: absolute;
196
+ top: 0;
197
+ left: 0;
198
+ bottom: 0;
199
+ right: 0;
200
+ width: 100%;
201
+ height: 100%;
202
+ border: 0px;
203
+ }
204
+ }
205
+ `;
206
+
207
+ interface MarkdownVideoProps {
208
+ src: string;
209
+ }
210
+
211
+ const MarkdownVideo = ({ src }: MarkdownVideoProps) => {
212
+ return (
213
+ <StyledVideo>
214
+ <div>
215
+ <iframe loading="lazy" allowFullScreen src={src} />
216
+ </div>
217
+ </StyledVideo>
218
+ );
219
+ };
220
+
221
+ const StyledMarkdownLink = styled(Link)`
222
+ overflow-wrap: break-word;
223
+
224
+ h1 &, h2 &, h3 &, h4 &, h5 & {
225
+ overflow-wrap: normal;
226
+ }
227
+
228
+ &:hover {
229
+ /* Links normally don't have underline, but in markdown we want to have it */
230
+ text-decoration: underline;
231
+ }
232
+ `;
233
+
234
+ export const MarkdownLink: React.FC<WithOptional<LinkProps, 'to'>> = ({
235
+ to,
236
+ children,
237
+ rel,
238
+ className,
239
+ }) => {
240
+ return (to && typeof to === 'string') ? (
241
+ <StyledMarkdownLink to={to} hideExternalIcon={true} rel={rel} className={className}>{children}</StyledMarkdownLink>
242
+ ) : (
243
+ (<span>{children}</span>) // Invalid links can be rendered as a regular span instead
244
+ );
245
+ };
246
+
247
+ export const MarkdownBlockQuote = styled(Box).attrs({
248
+ my: 'space16',
249
+ py: 'none',
250
+ forwardedAs: 'blockquote',
251
+ })`
252
+ border-left: 2px solid ${theme.color.neutral.separatorSubtle};
253
+ padding-left: ${theme.space.space16};
254
+
255
+ color: ${theme.color.neutral.textMuted};
256
+
257
+ & > p {
258
+ margin: 0;
259
+ }
260
+ `;
261
+
262
+ export const MarkdownTable = styled.table`
263
+ display: block;
264
+ overflow: auto;
265
+ border-collapse: collapse;
266
+
267
+ td, th {
268
+ border: 1px solid ${theme.color.neutral.border};
269
+ padding: ${theme.space.space16};
270
+ text-align: left;
271
+ }
272
+
273
+ tr:nth-child(even):not([class]) {
274
+ > th, > td {
275
+ background-color: inherit;
276
+ }
277
+ }
278
+ `;
279
+
280
+ // TODO: This should be used for readmes
281
+ export const MarkdownParagraphContent: React.FC<SharedTextProps & Pick<ReactMarkdownProps, 'node'>> = ({
282
+ children,
283
+ node,
284
+ }) => {
285
+ const child = node.children[0];
286
+ const isText = child?.type === 'text';
287
+
288
+ const videoSrc = isText && getVideoSrc(child.value);
289
+ if (videoSrc) return <MarkdownVideo src={videoSrc} />;
290
+
291
+ // the || null part is important because non-supported elements will fall back to this paragraph component;
292
+ return children || null;
293
+ };
@@ -0,0 +1,2 @@
1
+ export * from './tabs.js';
2
+ export * from './tab.js';