@elastic/eui-docusaurus-theme 2.0.0 → 2.2.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 +18 -44
- package/lib/.tsbuildinfo-client +1 -1
- package/lib/components/demo/actions_bar/actions_bar.d.ts +3 -2
- package/lib/components/demo/actions_bar/actions_bar.js +2 -2
- package/lib/components/demo/code_transformer.js +1 -1
- package/lib/components/demo/codesandbox/open_action.js +7 -4
- package/lib/components/demo/demo.d.ts +30 -4
- package/lib/components/demo/demo.js +2 -2
- package/lib/theme/Demo/actions.d.ts +2 -1
- package/lib/theme/DocBreadcrumbs/Items/Home/index.js +4 -1
- package/lib/theme/DocCard/index.d.ts +5 -0
- package/lib/theme/DocCard/index.js +44 -0
- package/package.json +3 -3
- package/src/components/demo/actions_bar/actions_bar.tsx +8 -2
- package/src/components/demo/code_transformer.ts +1 -1
- package/src/components/demo/codesandbox/open_action.tsx +8 -5
- package/src/components/demo/demo.tsx +32 -3
- package/src/theme/Demo/actions.tsx +2 -1
- package/src/theme/DocBreadcrumbs/Items/Home/index.tsx +4 -1
- package/src/theme/DocCard/index.tsx +104 -0
- package/src/theme/theme.d.ts +5 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { DemoSourceMeta } from '../demo';
|
|
1
|
+
import { DemoSourceMeta, ExtraFiles } from '../demo';
|
|
2
2
|
export interface DemoActionsBarProps {
|
|
3
3
|
activeSource: DemoSourceMeta | null;
|
|
4
4
|
sources: DemoSourceMeta[];
|
|
5
|
+
extraFiles?: ExtraFiles;
|
|
5
6
|
isSourceOpen: boolean;
|
|
6
7
|
setSourceOpen(isOpen: boolean): void;
|
|
7
8
|
onClickReloadExample(): void;
|
|
8
9
|
onClickCopyToClipboard(): void;
|
|
9
10
|
}
|
|
10
|
-
export declare const DemoActionsBar: ({ isSourceOpen, setSourceOpen, activeSource, sources, onClickReloadExample, onClickCopyToClipboard, }: DemoActionsBarProps) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
11
|
+
export declare const DemoActionsBar: ({ isSourceOpen, setSourceOpen, activeSource, sources, extraFiles, onClickReloadExample, onClickCopyToClipboard, }: DemoActionsBarProps) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -28,7 +28,7 @@ const getDemoActionsBarStyles = (euiTheme) => {
|
|
|
28
28
|
`,
|
|
29
29
|
};
|
|
30
30
|
};
|
|
31
|
-
export const DemoActionsBar = ({ isSourceOpen, setSourceOpen, activeSource, sources, onClickReloadExample, onClickCopyToClipboard, }) => {
|
|
31
|
+
export const DemoActionsBar = ({ isSourceOpen, setSourceOpen, activeSource, sources, extraFiles, onClickReloadExample, onClickCopyToClipboard, }) => {
|
|
32
32
|
const styles = useEuiMemoizedStyles(getDemoActionsBarStyles);
|
|
33
|
-
return (_jsxs(EuiFlexGroup, { alignItems: "center", css: styles.actionsBar, gutterSize: "s", children: [_jsx(EuiButton, { css: styles.button, onClick: () => setSourceOpen(!isSourceOpen), size: "s", color: "text", minWidth: false, children: isSourceOpen ? 'Hide source' : 'Show source' }), extraActions.map((ActionComponent) => (_jsx(ActionComponent, { sources: sources, activeSource: activeSource }))), _jsx(EuiToolTip, { content: "Copy to clipboard", children: _jsx(EuiButtonIcon, { size: "s", iconType: "copyClipboard", color: "text", onClick: onClickCopyToClipboard, "aria-label": "Copy code to clipboard" }) }), _jsx(EuiToolTip, { content: "Reload example", children: _jsx(EuiButtonIcon, { size: "s", iconType: "refresh", color: "text", onClick: onClickReloadExample, "aria-label": "Reload example" }) })] }));
|
|
33
|
+
return (_jsxs(EuiFlexGroup, { alignItems: "center", css: styles.actionsBar, gutterSize: "s", children: [_jsx(EuiButton, { css: styles.button, onClick: () => setSourceOpen(!isSourceOpen), size: "s", color: "text", minWidth: false, children: isSourceOpen ? 'Hide source' : 'Show source' }), extraActions.map((ActionComponent) => (_jsx(ActionComponent, { sources: sources, extraFiles: extraFiles, activeSource: activeSource }))), _jsx(EuiToolTip, { content: "Copy to clipboard", children: _jsx(EuiButtonIcon, { size: "s", iconType: "copyClipboard", color: "text", onClick: onClickCopyToClipboard, "aria-label": "Copy code to clipboard" }) }), _jsx(EuiToolTip, { content: "Reload example", children: _jsx(EuiButtonIcon, { size: "s", iconType: "refresh", color: "text", onClick: onClickReloadExample, "aria-label": "Reload example" }) })] }));
|
|
34
34
|
};
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
6
6
|
* Side Public License, v 1.
|
|
7
7
|
*/
|
|
8
|
-
const IMPORT_REGEX = /^import [^'"]* from ['"]([
|
|
8
|
+
const IMPORT_REGEX = /^import [^'"]* from ['"]([^'"\n ]*)['"];?/gm;
|
|
9
9
|
const DEFAULT_EXPORT_REGEX = /export default /;
|
|
10
10
|
const COMPONENT_ONLY_REGEX = /^\(?</;
|
|
11
11
|
/**
|
|
@@ -61,11 +61,14 @@ const processTsxSource = (source) => {
|
|
|
61
61
|
// to support that setting via tsconfig.json
|
|
62
62
|
return `/** @jsxImportSource @emotion/react */\n${source}`;
|
|
63
63
|
};
|
|
64
|
-
export const createOpenInCodeSandboxAction = ({ files = {}, dependencies }) => ({ activeSource }) => {
|
|
64
|
+
export const createOpenInCodeSandboxAction = ({ files = {}, dependencies }) => ({ extraFiles, activeSource }) => {
|
|
65
65
|
const parameters = useMemo(() => {
|
|
66
66
|
const source = activeSource?.code || '';
|
|
67
67
|
// Compute list of extra files that may be passed
|
|
68
|
-
const
|
|
68
|
+
const codeSandboxFiles = Object.entries({
|
|
69
|
+
...files,
|
|
70
|
+
...extraFiles,
|
|
71
|
+
}).reduce((acc, [file, content]) => {
|
|
69
72
|
acc[file] = { content };
|
|
70
73
|
return acc;
|
|
71
74
|
}, {});
|
|
@@ -83,9 +86,9 @@ export const createOpenInCodeSandboxAction = ({ files = {}, dependencies }) => (
|
|
|
83
86
|
},
|
|
84
87
|
},
|
|
85
88
|
},
|
|
86
|
-
...
|
|
89
|
+
...codeSandboxFiles,
|
|
87
90
|
},
|
|
88
91
|
});
|
|
89
|
-
}, [activeSource]);
|
|
92
|
+
}, [activeSource, extraFiles]);
|
|
90
93
|
return (_jsxs("form", { action: "https://codesandbox.io/api/v1/sandboxes/define", method: "POST", target: "_blank", children: [_jsx("input", { type: "hidden", name: "parameters", value: parameters }), _jsx("input", { type: "hidden", name: "query", value: `module=/demo.tsx&view=split` }), _jsx(EuiToolTip, { content: "Open in CodeSandbox", children: _jsx(EuiButtonIcon, { type: "submit", size: "s", iconType: CodeSandboxIcon, color: "text", "aria-label": "Open in CodeSandbox" }) })] }));
|
|
91
94
|
};
|
|
@@ -5,19 +5,45 @@ export interface DemoSourceMeta {
|
|
|
5
5
|
isActive: boolean;
|
|
6
6
|
filename?: string;
|
|
7
7
|
}
|
|
8
|
+
export type ExtraFiles = Record<string, string>;
|
|
8
9
|
export interface DemoProps extends PropsWithChildren {
|
|
9
10
|
/**
|
|
10
11
|
* Whether the source code editor is open by default
|
|
11
12
|
*/
|
|
12
13
|
isSourceOpen?: boolean;
|
|
13
14
|
/**
|
|
14
|
-
* Allows to
|
|
15
|
-
*
|
|
15
|
+
* Allows to pass additional variables available within the demo.
|
|
16
|
+
* The key is the variable name and the value is the variable itself (component, function, object, etc).
|
|
16
17
|
*
|
|
17
|
-
*
|
|
18
|
+
* @example
|
|
19
|
+
* ````mdx
|
|
20
|
+
* ```mdx-code-block
|
|
21
|
+
* import { MyComponent } from './my_component';
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* <Demo scope={{ MyComponent }}>
|
|
25
|
+
* ```tsx
|
|
26
|
+
* export default () => <MyComponent />
|
|
27
|
+
* ```
|
|
28
|
+
* </Demo>
|
|
29
|
+
* ````
|
|
18
30
|
*/
|
|
19
31
|
scope?: Record<string, unknown>;
|
|
32
|
+
/**
|
|
33
|
+
* Allows to pass extra files that will be added to the Codesandbox instance.
|
|
34
|
+
* The key is the filename and the value is the serialized file content.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ````mdx
|
|
38
|
+
* ```mdx-code-block
|
|
39
|
+
* import iconSvgSource from '!raw-loader!./icon.svg';
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* <Demo extraFiles={{ 'icon.svg': iconSvgSource }} />
|
|
43
|
+
* ````
|
|
44
|
+
*/
|
|
45
|
+
extraFiles?: ExtraFiles;
|
|
20
46
|
previewPadding?: DemoPreviewProps['padding'];
|
|
21
47
|
previewWrapper?: DemoPreviewProps['wrapperComponent'];
|
|
22
48
|
}
|
|
23
|
-
export declare const Demo: ({ children, scope, isSourceOpen: _isSourceOpen, previewPadding, previewWrapper, }: DemoProps) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
49
|
+
export declare const Demo: ({ children, scope, extraFiles, isSourceOpen: _isSourceOpen, previewPadding, previewWrapper, }: DemoProps) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
@@ -31,7 +31,7 @@ const getDemoStyles = (euiTheme) => ({
|
|
|
31
31
|
word-break: break-word;
|
|
32
32
|
`,
|
|
33
33
|
});
|
|
34
|
-
export const Demo = ({ children, scope, isSourceOpen: _isSourceOpen = false, previewPadding, previewWrapper, }) => {
|
|
34
|
+
export const Demo = ({ children, scope, extraFiles, isSourceOpen: _isSourceOpen = false, previewPadding, previewWrapper, }) => {
|
|
35
35
|
const styles = useEuiMemoizedStyles(getDemoStyles);
|
|
36
36
|
const [sources, setSources] = useState([]);
|
|
37
37
|
const [isSourceOpen, setIsSourceOpen] = useState(_isSourceOpen);
|
|
@@ -52,7 +52,7 @@ export const Demo = ({ children, scope, isSourceOpen: _isSourceOpen = false, pre
|
|
|
52
52
|
const onClickReloadExample = useCallback(() => {
|
|
53
53
|
setLiveProviderKey((liveProviderKey) => liveProviderKey + 1);
|
|
54
54
|
}, []);
|
|
55
|
-
return (_jsx("div", { css: styles.demo, children: _jsxs(DemoContext.Provider, { value: { sources, addSource }, children: [_jsxs(LiveProvider, { code: activeSource?.code || '', transformCode: demoCodeTransformer, theme: prismThemes.dracula, scope: finalScope, children: [_jsx(DemoPreview, { padding: previewPadding, wrapperComponent: previewWrapper }), _jsx(DemoActionsBar, { isSourceOpen: isSourceOpen, setSourceOpen: setIsSourceOpen, activeSource: activeSource, sources: sources, onClickCopyToClipboard: onClickCopyToClipboard, onClickReloadExample: onClickReloadExample }), isSourceOpen && _jsx(DemoEditor, {})] }, liveProviderKey), Children.map(children, (child, index) => {
|
|
55
|
+
return (_jsx("div", { css: styles.demo, children: _jsxs(DemoContext.Provider, { value: { sources, addSource }, children: [_jsxs(LiveProvider, { code: activeSource?.code || '', transformCode: demoCodeTransformer, theme: prismThemes.dracula, scope: finalScope, children: [_jsx(DemoPreview, { padding: previewPadding, wrapperComponent: previewWrapper }), _jsx(DemoActionsBar, { isSourceOpen: isSourceOpen, setSourceOpen: setIsSourceOpen, activeSource: activeSource, extraFiles: extraFiles, sources: sources, onClickCopyToClipboard: onClickCopyToClipboard, onClickReloadExample: onClickReloadExample }), isSourceOpen && _jsx(DemoEditor, {})] }, liveProviderKey), Children.map(children, (child, index) => {
|
|
56
56
|
if (isElement(child) && child.type === DemoSource) {
|
|
57
57
|
return child;
|
|
58
58
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ComponentType } from 'react';
|
|
2
|
-
import { DemoSourceMeta } from '../../components/demo/demo';
|
|
2
|
+
import { DemoSourceMeta, ExtraFiles } from '../../components/demo/demo';
|
|
3
3
|
export type ActionComponentProps = {
|
|
4
4
|
activeSource: DemoSourceMeta | null;
|
|
5
5
|
sources: DemoSourceMeta[];
|
|
6
|
+
extraFiles?: ExtraFiles;
|
|
6
7
|
};
|
|
7
8
|
export type ActionComponent = ComponentType<ActionComponentProps>;
|
|
8
9
|
export declare const extraActions: ActionComponent[];
|
|
@@ -3,13 +3,16 @@ import Link from '@docusaurus/Link';
|
|
|
3
3
|
import useBaseUrl from '@docusaurus/useBaseUrl';
|
|
4
4
|
import { translate } from '@docusaurus/Translate';
|
|
5
5
|
import { EuiIcon, useEuiMemoizedStyles } from '@elastic/eui';
|
|
6
|
+
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
6
7
|
import { getItemStyles } from '../item.styles';
|
|
7
8
|
export default function HomeBreadcrumbItem() {
|
|
8
9
|
const homeHref = useBaseUrl('/');
|
|
10
|
+
const { siteConfig } = useDocusaurusContext();
|
|
11
|
+
const { title } = siteConfig;
|
|
9
12
|
const styles = useEuiMemoizedStyles(getItemStyles);
|
|
10
13
|
return (_jsxs("li", { className: "breadcrumbs__item", css: styles.item, children: [_jsx(Link, { "aria-label": translate({
|
|
11
14
|
id: 'theme.docs.breadcrumbs.home',
|
|
12
15
|
message: 'Home page',
|
|
13
16
|
description: 'The ARIA label for the home page in the breadcrumbs',
|
|
14
|
-
}), className: "breadcrumbs__link", href: homeHref, children:
|
|
17
|
+
}), className: "breadcrumbs__link", href: homeHref, children: title }), _jsx(EuiIcon, { type: "arrowRight", size: "s", css: styles.icon })] }));
|
|
15
18
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
2
|
+
import { useDocById, findFirstSidebarItemLink, } from '@docusaurus/plugin-content-docs/client';
|
|
3
|
+
import { usePluralForm } from '@docusaurus/theme-common';
|
|
4
|
+
import isInternalUrl from '@docusaurus/isInternalUrl';
|
|
5
|
+
import { translate } from '@docusaurus/Translate';
|
|
6
|
+
import { EuiCard, EuiIcon } from '@elastic/eui';
|
|
7
|
+
function useCategoryItemsPlural() {
|
|
8
|
+
const { selectMessage } = usePluralForm();
|
|
9
|
+
return (count) => selectMessage(count, translate({
|
|
10
|
+
message: '1 item|{count} items',
|
|
11
|
+
id: 'theme.docs.DocCard.categoryDescription.plurals',
|
|
12
|
+
description: 'The default description for a category card in the generated index about how many items this category includes',
|
|
13
|
+
}, { count }));
|
|
14
|
+
}
|
|
15
|
+
function CardLayout({ href, icon, title, description, }) {
|
|
16
|
+
return (_jsx(EuiCard, { icon: _jsx(EuiIcon, { size: "l", type: icon }), title: title, description: description || '', titleSize: "xs", layout: "horizontal", href: href }));
|
|
17
|
+
}
|
|
18
|
+
function CardCategory({ item }) {
|
|
19
|
+
const href = findFirstSidebarItemLink(item);
|
|
20
|
+
const categoryItemsPlural = useCategoryItemsPlural();
|
|
21
|
+
// Unexpected: categories that don't have a link have been filtered upfront
|
|
22
|
+
if (!href) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
return (_jsx(CardLayout, { href: href,
|
|
26
|
+
// Coincidentally, `folderOpen` is the same icon in EUI icon library
|
|
27
|
+
icon: "folderOpen", title: item.label, description: item.description ?? categoryItemsPlural(item.items.length) }));
|
|
28
|
+
}
|
|
29
|
+
function CardLink({ item }) {
|
|
30
|
+
// We update Docusaurus `link` icon to EUI `popout` icon
|
|
31
|
+
const icon = isInternalUrl(item.href) ? 'document' : 'popout';
|
|
32
|
+
const doc = useDocById(item.docId ?? undefined);
|
|
33
|
+
return (_jsx(CardLayout, { href: item.href, icon: icon, title: item.label, description: item.description ?? doc?.description }));
|
|
34
|
+
}
|
|
35
|
+
export default function DocCard({ item, }) {
|
|
36
|
+
switch (item.type) {
|
|
37
|
+
case 'link':
|
|
38
|
+
return _jsx(CardLink, { item: item });
|
|
39
|
+
case 'category':
|
|
40
|
+
return _jsx(CardCategory, { item: item });
|
|
41
|
+
default:
|
|
42
|
+
throw new Error(`unknown item type ${JSON.stringify(item)}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elastic/eui-docusaurus-theme",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "EUI theme for Docusaurus",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"scripts": {
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"@docusaurus/theme-common": "^3.7.0",
|
|
41
41
|
"@docusaurus/utils-validation": "^3.7.0",
|
|
42
42
|
"@elastic/datemath": "^5.0.3",
|
|
43
|
-
"@elastic/eui": "^
|
|
44
|
-
"@elastic/eui-theme-borealis": "^5.
|
|
43
|
+
"@elastic/eui": "^112.1.0",
|
|
44
|
+
"@elastic/eui-theme-borealis": "^5.4.0",
|
|
45
45
|
"@emotion/css": "^11.11.2",
|
|
46
46
|
"@emotion/react": "^11.11.4",
|
|
47
47
|
"@types/react-window": "^1.8.8",
|
|
@@ -17,11 +17,12 @@ import {
|
|
|
17
17
|
} from '@elastic/eui';
|
|
18
18
|
import { css } from '@emotion/react';
|
|
19
19
|
import { extraActions } from '@theme/Demo/actions';
|
|
20
|
-
import { DemoSourceMeta } from '../demo';
|
|
20
|
+
import { DemoSourceMeta, ExtraFiles } from '../demo';
|
|
21
21
|
|
|
22
22
|
export interface DemoActionsBarProps {
|
|
23
23
|
activeSource: DemoSourceMeta | null;
|
|
24
24
|
sources: DemoSourceMeta[];
|
|
25
|
+
extraFiles?: ExtraFiles;
|
|
25
26
|
isSourceOpen: boolean;
|
|
26
27
|
setSourceOpen(isOpen: boolean): void;
|
|
27
28
|
onClickReloadExample(): void;
|
|
@@ -53,6 +54,7 @@ export const DemoActionsBar = ({
|
|
|
53
54
|
setSourceOpen,
|
|
54
55
|
activeSource,
|
|
55
56
|
sources,
|
|
57
|
+
extraFiles,
|
|
56
58
|
onClickReloadExample,
|
|
57
59
|
onClickCopyToClipboard,
|
|
58
60
|
}: DemoActionsBarProps) => {
|
|
@@ -70,7 +72,11 @@ export const DemoActionsBar = ({
|
|
|
70
72
|
{isSourceOpen ? 'Hide source' : 'Show source'}
|
|
71
73
|
</EuiButton>
|
|
72
74
|
{extraActions.map((ActionComponent) => (
|
|
73
|
-
<ActionComponent
|
|
75
|
+
<ActionComponent
|
|
76
|
+
sources={sources}
|
|
77
|
+
extraFiles={extraFiles}
|
|
78
|
+
activeSource={activeSource}
|
|
79
|
+
/>
|
|
74
80
|
))}
|
|
75
81
|
<EuiToolTip content="Copy to clipboard">
|
|
76
82
|
<EuiButtonIcon
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Side Public License, v 1.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
const IMPORT_REGEX = /^import [^'"]* from ['"]([
|
|
9
|
+
const IMPORT_REGEX = /^import [^'"]* from ['"]([^'"\n ]*)['"];?/gm;
|
|
10
10
|
const DEFAULT_EXPORT_REGEX = /export default /;
|
|
11
11
|
const COMPONENT_ONLY_REGEX = /^\(?</;
|
|
12
12
|
|
|
@@ -74,17 +74,20 @@ const processTsxSource = (source: string) => {
|
|
|
74
74
|
|
|
75
75
|
export const createOpenInCodeSandboxAction =
|
|
76
76
|
({ files = {}, dependencies }: Options): ActionComponent =>
|
|
77
|
-
({ activeSource }) => {
|
|
77
|
+
({ extraFiles, activeSource }) => {
|
|
78
78
|
const parameters: string = useMemo(() => {
|
|
79
79
|
const source = activeSource?.code || '';
|
|
80
80
|
|
|
81
81
|
// Compute list of extra files that may be passed
|
|
82
|
-
const
|
|
82
|
+
const codeSandboxFiles = Object.entries({
|
|
83
|
+
...files,
|
|
84
|
+
...extraFiles,
|
|
85
|
+
}).reduce(
|
|
83
86
|
(acc, [file, content]) => {
|
|
84
87
|
acc[file] = { content };
|
|
85
88
|
return acc;
|
|
86
89
|
},
|
|
87
|
-
{} as Record<string, { content:
|
|
90
|
+
{} as Record<string, { content: unknown }>
|
|
88
91
|
);
|
|
89
92
|
|
|
90
93
|
return getParameters({
|
|
@@ -101,10 +104,10 @@ export const createOpenInCodeSandboxAction =
|
|
|
101
104
|
},
|
|
102
105
|
},
|
|
103
106
|
},
|
|
104
|
-
...
|
|
107
|
+
...codeSandboxFiles,
|
|
105
108
|
},
|
|
106
109
|
} as any);
|
|
107
|
-
}, [activeSource]);
|
|
110
|
+
}, [activeSource, extraFiles]);
|
|
108
111
|
|
|
109
112
|
return (
|
|
110
113
|
<form
|
|
@@ -38,18 +38,45 @@ export interface DemoSourceMeta {
|
|
|
38
38
|
filename?: string;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
export type ExtraFiles = Record<string, string>;
|
|
42
|
+
|
|
41
43
|
export interface DemoProps extends PropsWithChildren {
|
|
42
44
|
/**
|
|
43
45
|
* Whether the source code editor is open by default
|
|
44
46
|
*/
|
|
45
47
|
isSourceOpen?: boolean;
|
|
46
48
|
/**
|
|
47
|
-
* Allows to
|
|
48
|
-
*
|
|
49
|
+
* Allows to pass additional variables available within the demo.
|
|
50
|
+
* The key is the variable name and the value is the variable itself (component, function, object, etc).
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ````mdx
|
|
54
|
+
* ```mdx-code-block
|
|
55
|
+
* import { MyComponent } from './my_component';
|
|
56
|
+
* ```
|
|
49
57
|
*
|
|
50
|
-
*
|
|
58
|
+
* <Demo scope={{ MyComponent }}>
|
|
59
|
+
* ```tsx
|
|
60
|
+
* export default () => <MyComponent />
|
|
61
|
+
* ```
|
|
62
|
+
* </Demo>
|
|
63
|
+
* ````
|
|
51
64
|
*/
|
|
52
65
|
scope?: Record<string, unknown>;
|
|
66
|
+
/**
|
|
67
|
+
* Allows to pass extra files that will be added to the Codesandbox instance.
|
|
68
|
+
* The key is the filename and the value is the serialized file content.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ````mdx
|
|
72
|
+
* ```mdx-code-block
|
|
73
|
+
* import iconSvgSource from '!raw-loader!./icon.svg';
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* <Demo extraFiles={{ 'icon.svg': iconSvgSource }} />
|
|
77
|
+
* ````
|
|
78
|
+
*/
|
|
79
|
+
extraFiles?: ExtraFiles;
|
|
53
80
|
previewPadding?: DemoPreviewProps['padding'];
|
|
54
81
|
previewWrapper?: DemoPreviewProps['wrapperComponent'];
|
|
55
82
|
}
|
|
@@ -69,6 +96,7 @@ const getDemoStyles = (euiTheme: UseEuiTheme) => ({
|
|
|
69
96
|
export const Demo = ({
|
|
70
97
|
children,
|
|
71
98
|
scope,
|
|
99
|
+
extraFiles,
|
|
72
100
|
isSourceOpen: _isSourceOpen = false,
|
|
73
101
|
previewPadding,
|
|
74
102
|
previewWrapper,
|
|
@@ -123,6 +151,7 @@ export const Demo = ({
|
|
|
123
151
|
isSourceOpen={isSourceOpen}
|
|
124
152
|
setSourceOpen={setIsSourceOpen}
|
|
125
153
|
activeSource={activeSource}
|
|
154
|
+
extraFiles={extraFiles}
|
|
126
155
|
sources={sources}
|
|
127
156
|
onClickCopyToClipboard={onClickCopyToClipboard}
|
|
128
157
|
onClickReloadExample={onClickReloadExample}
|
|
@@ -8,11 +8,12 @@
|
|
|
8
8
|
|
|
9
9
|
import { ComponentType } from 'react';
|
|
10
10
|
|
|
11
|
-
import { DemoSourceMeta } from '../../components/demo/demo';
|
|
11
|
+
import { DemoSourceMeta, ExtraFiles } from '../../components/demo/demo';
|
|
12
12
|
|
|
13
13
|
export type ActionComponentProps = {
|
|
14
14
|
activeSource: DemoSourceMeta | null;
|
|
15
15
|
sources: DemoSourceMeta[];
|
|
16
|
+
extraFiles?: ExtraFiles;
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
export type ActionComponent = ComponentType<ActionComponentProps>;
|
|
@@ -11,11 +11,14 @@ import Link from '@docusaurus/Link';
|
|
|
11
11
|
import useBaseUrl from '@docusaurus/useBaseUrl';
|
|
12
12
|
import { translate } from '@docusaurus/Translate';
|
|
13
13
|
import { EuiIcon, useEuiMemoizedStyles } from '@elastic/eui';
|
|
14
|
+
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
14
15
|
|
|
15
16
|
import { getItemStyles } from '../item.styles';
|
|
16
17
|
|
|
17
18
|
export default function HomeBreadcrumbItem(): JSX.Element {
|
|
18
19
|
const homeHref = useBaseUrl('/');
|
|
20
|
+
const { siteConfig } = useDocusaurusContext();
|
|
21
|
+
const { title } = siteConfig;
|
|
19
22
|
|
|
20
23
|
const styles = useEuiMemoizedStyles(getItemStyles);
|
|
21
24
|
|
|
@@ -30,7 +33,7 @@ export default function HomeBreadcrumbItem(): JSX.Element {
|
|
|
30
33
|
className="breadcrumbs__link"
|
|
31
34
|
href={homeHref}
|
|
32
35
|
>
|
|
33
|
-
|
|
36
|
+
{title}
|
|
34
37
|
</Link>
|
|
35
38
|
<EuiIcon type="arrowRight" size="s" css={styles.icon} />
|
|
36
39
|
</li>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
useDocById,
|
|
4
|
+
findFirstSidebarItemLink,
|
|
5
|
+
} from '@docusaurus/plugin-content-docs/client';
|
|
6
|
+
import { usePluralForm } from '@docusaurus/theme-common';
|
|
7
|
+
import isInternalUrl from '@docusaurus/isInternalUrl';
|
|
8
|
+
import { translate } from '@docusaurus/Translate';
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
PropSidebarItemCategory,
|
|
12
|
+
PropSidebarItemLink,
|
|
13
|
+
} from '@docusaurus/plugin-content-docs';
|
|
14
|
+
|
|
15
|
+
import { EuiCard, EuiIcon } from '@elastic/eui';
|
|
16
|
+
|
|
17
|
+
function useCategoryItemsPlural() {
|
|
18
|
+
const { selectMessage } = usePluralForm();
|
|
19
|
+
return (count: number) =>
|
|
20
|
+
selectMessage(
|
|
21
|
+
count,
|
|
22
|
+
translate(
|
|
23
|
+
{
|
|
24
|
+
message: '1 item|{count} items',
|
|
25
|
+
id: 'theme.docs.DocCard.categoryDescription.plurals',
|
|
26
|
+
description:
|
|
27
|
+
'The default description for a category card in the generated index about how many items this category includes',
|
|
28
|
+
},
|
|
29
|
+
{ count }
|
|
30
|
+
)
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function CardLayout({
|
|
35
|
+
href,
|
|
36
|
+
icon,
|
|
37
|
+
title,
|
|
38
|
+
description,
|
|
39
|
+
}: {
|
|
40
|
+
href: string;
|
|
41
|
+
icon: string;
|
|
42
|
+
title: string;
|
|
43
|
+
description?: string;
|
|
44
|
+
}): ReactNode {
|
|
45
|
+
return (
|
|
46
|
+
<EuiCard
|
|
47
|
+
icon={<EuiIcon size="l" type={icon} />}
|
|
48
|
+
title={title}
|
|
49
|
+
description={description || ''}
|
|
50
|
+
titleSize="xs"
|
|
51
|
+
layout="horizontal"
|
|
52
|
+
href={href}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function CardCategory({ item }: { item: PropSidebarItemCategory }): ReactNode {
|
|
58
|
+
const href = findFirstSidebarItemLink(item);
|
|
59
|
+
const categoryItemsPlural = useCategoryItemsPlural();
|
|
60
|
+
|
|
61
|
+
// Unexpected: categories that don't have a link have been filtered upfront
|
|
62
|
+
if (!href) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<CardLayout
|
|
68
|
+
href={href}
|
|
69
|
+
// Coincidentally, `folderOpen` is the same icon in EUI icon library
|
|
70
|
+
icon="folderOpen"
|
|
71
|
+
title={item.label}
|
|
72
|
+
description={item.description ?? categoryItemsPlural(item.items.length)}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function CardLink({ item }: { item: PropSidebarItemLink }): ReactNode {
|
|
78
|
+
// We update Docusaurus `link` icon to EUI `popout` icon
|
|
79
|
+
const icon = isInternalUrl(item.href) ? 'document' : 'popout';
|
|
80
|
+
const doc = useDocById(item.docId ?? undefined);
|
|
81
|
+
return (
|
|
82
|
+
<CardLayout
|
|
83
|
+
href={item.href}
|
|
84
|
+
icon={icon}
|
|
85
|
+
title={item.label}
|
|
86
|
+
description={item.description ?? doc?.description}
|
|
87
|
+
/>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export default function DocCard({
|
|
92
|
+
item,
|
|
93
|
+
}: {
|
|
94
|
+
item: PropSidebarItemCategory | PropSidebarItemLink;
|
|
95
|
+
}): ReactNode {
|
|
96
|
+
switch (item.type) {
|
|
97
|
+
case 'link':
|
|
98
|
+
return <CardLink item={item} />;
|
|
99
|
+
case 'category':
|
|
100
|
+
return <CardCategory item={item} />;
|
|
101
|
+
default:
|
|
102
|
+
throw new Error(`unknown item type ${JSON.stringify(item)}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
package/src/theme/theme.d.ts
CHANGED
|
@@ -585,11 +585,15 @@ declare module '@theme/Demo/default_scope' {
|
|
|
585
585
|
|
|
586
586
|
declare module '@theme/Demo/actions' {
|
|
587
587
|
import type { ComponentType } from 'react';
|
|
588
|
-
import type {
|
|
588
|
+
import type {
|
|
589
|
+
DemoSourceMeta,
|
|
590
|
+
ExtraFiles,
|
|
591
|
+
} from '@elastic/eui-docusaurus-theme/components/demo/demo';
|
|
589
592
|
|
|
590
593
|
export type ActionComponentProps = {
|
|
591
594
|
activeSource: DemoSourceMeta;
|
|
592
595
|
sources: DemoSourceMeta[];
|
|
596
|
+
extraFiles?: ExtraFiles;
|
|
593
597
|
};
|
|
594
598
|
|
|
595
599
|
export type ActionComponent = ComponentType<ActionComponentProps>;
|