@elastic/eui-docusaurus-theme 2.2.0 → 2.4.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/lib/.tsbuildinfo-client +1 -1
- package/lib/components/demo/actions_bar/actions_bar.d.ts +2 -1
- package/lib/components/demo/actions_bar/actions_bar.js +2 -2
- package/lib/components/demo/codesandbox/open_action.js +29 -4
- package/lib/components/demo/demo.d.ts +2 -1
- package/lib/components/demo/demo.js +2 -2
- package/lib/components/version_switcher/index.d.ts +8 -1
- package/lib/components/version_switcher/index.js +37 -9
- package/lib/theme/Admonition/Types.js +1 -1
- package/lib/theme/Demo/actions.d.ts +1 -0
- package/lib/theme/DocBreadcrumbs/Items/Home/index.js +1 -1
- package/lib/theme/DocBreadcrumbs/index.js +1 -1
- package/lib/theme/DocCard/index.js +2 -2
- package/lib/theme/DocSidebarItem/Category/index.js +1 -1
- package/lib/theme/NavbarItem/NavbarNavLink.js +1 -1
- package/lib/theme/PaginatorNavLink/index.js +1 -1
- package/lib/theme/TOCCollapsible/CollapseButton/index.js +1 -1
- package/package.json +3 -3
- package/src/components/demo/actions_bar/actions_bar.tsx +5 -1
- package/src/components/demo/codesandbox/open_action.tsx +40 -4
- package/src/components/demo/demo.tsx +3 -0
- package/src/components/version_switcher/index.tsx +46 -9
- package/src/theme/Admonition/Types.tsx +1 -1
- package/src/theme/Demo/actions.tsx +1 -0
- package/src/theme/DocBreadcrumbs/Items/Home/index.tsx +1 -1
- package/src/theme/DocBreadcrumbs/index.tsx +1 -1
- package/src/theme/DocCard/index.tsx +2 -2
- package/src/theme/DocSidebarItem/Category/index.tsx +1 -1
- package/src/theme/NavbarItem/NavbarNavLink.tsx +1 -1
- package/src/theme/PaginatorNavLink/index.tsx +2 -2
- package/src/theme/TOCCollapsible/CollapseButton/index.tsx +1 -1
- package/src/theme/theme.d.ts +1 -0
|
@@ -3,9 +3,10 @@ export interface DemoActionsBarProps {
|
|
|
3
3
|
activeSource: DemoSourceMeta | null;
|
|
4
4
|
sources: DemoSourceMeta[];
|
|
5
5
|
extraFiles?: ExtraFiles;
|
|
6
|
+
previewWrapperSource?: string;
|
|
6
7
|
isSourceOpen: boolean;
|
|
7
8
|
setSourceOpen(isOpen: boolean): void;
|
|
8
9
|
onClickReloadExample(): void;
|
|
9
10
|
onClickCopyToClipboard(): void;
|
|
10
11
|
}
|
|
11
|
-
export declare const DemoActionsBar: ({ isSourceOpen, setSourceOpen, activeSource, sources, extraFiles, onClickReloadExample, onClickCopyToClipboard, }: DemoActionsBarProps) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
12
|
+
export declare const DemoActionsBar: ({ isSourceOpen, setSourceOpen, activeSource, sources, extraFiles, previewWrapperSource, 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, extraFiles, onClickReloadExample, onClickCopyToClipboard, }) => {
|
|
31
|
+
export const DemoActionsBar = ({ isSourceOpen, setSourceOpen, activeSource, sources, extraFiles, previewWrapperSource, 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, extraFiles: extraFiles, activeSource: activeSource }))), _jsx(EuiToolTip, { content: "Copy to clipboard", children: _jsx(EuiButtonIcon, { size: "s", iconType: "
|
|
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, previewWrapperSource: previewWrapperSource, activeSource: activeSource }, ActionComponent.displayName ?? ActionComponent.name))), _jsx(EuiToolTip, { content: "Copy to clipboard", children: _jsx(EuiButtonIcon, { size: "s", iconType: "copy", 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
|
};
|
|
@@ -32,7 +32,8 @@ const indexTsxSource = dedent `
|
|
|
32
32
|
<EuiProvider cache={cache}>
|
|
33
33
|
<Demo />
|
|
34
34
|
</EuiProvider>
|
|
35
|
-
)
|
|
35
|
+
);
|
|
36
|
+
`;
|
|
36
37
|
const publicIndexHtmlSource = dedent `
|
|
37
38
|
<head>
|
|
38
39
|
<title>@elastic/eui component demo</title>
|
|
@@ -59,9 +60,21 @@ export const defaultCodeSandboxParameters = {
|
|
|
59
60
|
const processTsxSource = (source) => {
|
|
60
61
|
// jsxImportSource pragma is needed in CodeSandbox as it doesn't seem
|
|
61
62
|
// to support that setting via tsconfig.json
|
|
62
|
-
|
|
63
|
+
let processed = `/** @jsxImportSource @emotion/react */\n${source}`;
|
|
64
|
+
// Inject `@elastic/charts` CSS for demos that use the charts library,
|
|
65
|
+
// since CodeSandbox doesn't load it globally unlike the docs site
|
|
66
|
+
if (source.includes('@elastic/charts')) {
|
|
67
|
+
// Match the closing line of the @elastic/charts import (handles both
|
|
68
|
+
// single-line and multi-line imports, and both quote styles)
|
|
69
|
+
processed = processed.replace(/^(.*from ['"]@elastic\/charts['"];)$/m, [
|
|
70
|
+
'$1',
|
|
71
|
+
"import '@elastic/charts/dist/theme_only_light.css';",
|
|
72
|
+
"import '@elastic/charts/dist/theme_only_dark.css';",
|
|
73
|
+
].join('\n'));
|
|
74
|
+
}
|
|
75
|
+
return processed;
|
|
63
76
|
};
|
|
64
|
-
export const createOpenInCodeSandboxAction = ({ files = {}, dependencies }) => ({ extraFiles, activeSource }) => {
|
|
77
|
+
export const createOpenInCodeSandboxAction = ({ files = {}, dependencies }) => ({ extraFiles, activeSource, previewWrapperSource }) => {
|
|
65
78
|
const parameters = useMemo(() => {
|
|
66
79
|
const source = activeSource?.code || '';
|
|
67
80
|
// Compute list of extra files that may be passed
|
|
@@ -75,6 +88,18 @@ export const createOpenInCodeSandboxAction = ({ files = {}, dependencies }) => (
|
|
|
75
88
|
return getParameters({
|
|
76
89
|
files: {
|
|
77
90
|
...defaultCodeSandboxParameters.files,
|
|
91
|
+
...(previewWrapperSource
|
|
92
|
+
? {
|
|
93
|
+
'index.tsx': {
|
|
94
|
+
content: indexTsxSource
|
|
95
|
+
.replace("import Demo from './demo';", "import Demo from './demo';\nimport PreviewWrapper from './preview_wrapper';")
|
|
96
|
+
.replace('<Demo />', '<PreviewWrapper>\n <Demo />\n </PreviewWrapper>'),
|
|
97
|
+
},
|
|
98
|
+
'preview_wrapper.tsx': {
|
|
99
|
+
content: processTsxSource(previewWrapperSource),
|
|
100
|
+
},
|
|
101
|
+
}
|
|
102
|
+
: {}),
|
|
78
103
|
'demo.tsx': {
|
|
79
104
|
content: processTsxSource(source),
|
|
80
105
|
},
|
|
@@ -89,6 +114,6 @@ export const createOpenInCodeSandboxAction = ({ files = {}, dependencies }) => (
|
|
|
89
114
|
...codeSandboxFiles,
|
|
90
115
|
},
|
|
91
116
|
});
|
|
92
|
-
}, [activeSource, extraFiles]);
|
|
117
|
+
}, [activeSource, extraFiles, previewWrapperSource]);
|
|
93
118
|
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" }) })] }));
|
|
94
119
|
};
|
|
@@ -45,5 +45,6 @@ export interface DemoProps extends PropsWithChildren {
|
|
|
45
45
|
extraFiles?: ExtraFiles;
|
|
46
46
|
previewPadding?: DemoPreviewProps['padding'];
|
|
47
47
|
previewWrapper?: DemoPreviewProps['wrapperComponent'];
|
|
48
|
+
previewWrapperSource?: string;
|
|
48
49
|
}
|
|
49
|
-
export declare const Demo: ({ children, scope, extraFiles, isSourceOpen: _isSourceOpen, previewPadding, previewWrapper, }: DemoProps) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
50
|
+
export declare const Demo: ({ children, scope, extraFiles, isSourceOpen: _isSourceOpen, previewPadding, previewWrapper, previewWrapperSource, }: 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, extraFiles, isSourceOpen: _isSourceOpen = false, previewPadding, previewWrapper, }) => {
|
|
34
|
+
export const Demo = ({ children, scope, extraFiles, isSourceOpen: _isSourceOpen = false, previewPadding, previewWrapper, previewWrapperSource, }) => {
|
|
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, extraFiles, isSourceOpen: _isSourceOpen
|
|
|
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, extraFiles: extraFiles, 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, previewWrapperSource: previewWrapperSource, 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
|
}
|
|
@@ -19,5 +19,12 @@ export type VersionSwitcherProps = {
|
|
|
19
19
|
* List of available versions to switch to
|
|
20
20
|
*/
|
|
21
21
|
versions: string[];
|
|
22
|
+
/**
|
|
23
|
+
* URL to fetch the latest list of versions from.
|
|
24
|
+
* When provided, versions are fetched client-side from this URL,
|
|
25
|
+
* falling back to the static `versions` prop if the fetch fails.
|
|
26
|
+
* This ensures all deployed versions are always visible in the switcher.
|
|
27
|
+
*/
|
|
28
|
+
versionsUrl?: string;
|
|
22
29
|
};
|
|
23
|
-
export declare const VersionSwitcher: ({ ariaLabel, currentVersion, extraAction, previousVersionUrl, versions, }: VersionSwitcherProps) => import("@emotion/react/jsx-runtime").JSX.Element | null;
|
|
30
|
+
export declare const VersionSwitcher: ({ ariaLabel, currentVersion, extraAction, previousVersionUrl, versions, versionsUrl, }: VersionSwitcherProps) => import("@emotion/react/jsx-runtime").JSX.Element | null;
|
|
@@ -6,7 +6,7 @@ import { jsxs as _jsxs, jsx as _jsx } from "@emotion/react/jsx-runtime";
|
|
|
6
6
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
7
7
|
* Side Public License, v 1.
|
|
8
8
|
*/
|
|
9
|
-
import { useState } from 'react';
|
|
9
|
+
import { useEffect, useState } from 'react';
|
|
10
10
|
import { css } from '@emotion/react';
|
|
11
11
|
import { FixedSizeList } from 'react-window';
|
|
12
12
|
import { EuiButtonEmpty, euiFocusRing, EuiListGroupItem, EuiPopover, useEuiMemoizedStyles, } from '@elastic/eui';
|
|
@@ -33,19 +33,47 @@ const getStyles = (euiThemeContext) => {
|
|
|
33
33
|
const pronounceVersion = (version) => {
|
|
34
34
|
return `version ${version.replaceAll('.', ' point ')}`;
|
|
35
35
|
};
|
|
36
|
-
export const VersionSwitcher = ({ ariaLabel, currentVersion, extraAction, previousVersionUrl, versions, }) => {
|
|
36
|
+
export const VersionSwitcher = ({ ariaLabel, currentVersion, extraAction, previousVersionUrl, versions, versionsUrl, }) => {
|
|
37
37
|
const [isPopoverOpen, setPopoverOpen] = useState(false);
|
|
38
|
+
const [allVersions, setAllVersions] = useState(versions);
|
|
38
39
|
const styles = useEuiMemoizedStyles(getStyles);
|
|
39
|
-
|
|
40
|
+
// Fetch the latest versions list from the main deployment
|
|
41
|
+
// to ensure the switcher always shows all available versions,
|
|
42
|
+
// even on older documentation deployments
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (!versionsUrl)
|
|
45
|
+
return;
|
|
46
|
+
fetch(versionsUrl)
|
|
47
|
+
.then((response) => {
|
|
48
|
+
if (!response.ok)
|
|
49
|
+
throw new Error('Failed to fetch versions');
|
|
50
|
+
return response.json();
|
|
51
|
+
})
|
|
52
|
+
.then((data) => {
|
|
53
|
+
if (data?.euiVersions?.length) {
|
|
54
|
+
// Ensure the current version is always included
|
|
55
|
+
const fetchedVersions = data.euiVersions;
|
|
56
|
+
if (!fetchedVersions.includes(currentVersion)) {
|
|
57
|
+
fetchedVersions.push(currentVersion);
|
|
58
|
+
}
|
|
59
|
+
setAllVersions(fetchedVersions);
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
.catch(() => {
|
|
63
|
+
// Silently fall back to statically bundled versions
|
|
64
|
+
});
|
|
65
|
+
}, [versionsUrl, currentVersion]);
|
|
66
|
+
if (!allVersions?.length)
|
|
40
67
|
return null;
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
68
|
+
const latestVersion = allVersions[0];
|
|
69
|
+
const button = (_jsxs(EuiButtonEmpty, { size: "s", color: "text", iconType: "chevronSingleDown", iconSide: "right", css: styles.button, onClick: () => setPopoverOpen((isOpen) => !isOpen), "aria-label": `${pronounceVersion(currentVersion)}. Click to switch versions`, children: ["v", currentVersion] }));
|
|
70
|
+
return (_jsx(EuiPopover, { isOpen: isPopoverOpen, closePopover: () => setPopoverOpen(false), button: button, repositionOnScroll: true, panelPaddingSize: "xs", "aria-label": ariaLabel, children: _jsx(FixedSizeList, { className: "eui-yScroll", itemCount: allVersions.length, itemSize: 24, height: 200, width: 120, innerElementType: "ul", children: ({ index, style }) => {
|
|
71
|
+
const version = allVersions[index];
|
|
44
72
|
const isCurrentVersion = version === currentVersion;
|
|
45
73
|
const screenReaderVersion = pronounceVersion(version);
|
|
46
|
-
const url =
|
|
47
|
-
?
|
|
74
|
+
const url = version === latestVersion
|
|
75
|
+
? `${previousVersionUrl}/`
|
|
48
76
|
: `${previousVersionUrl}/v${version}/`;
|
|
49
|
-
return (_jsx(EuiListGroupItem, { css: styles.listItem, style: style,
|
|
77
|
+
return (_jsx(EuiListGroupItem, { css: styles.listItem, style: style, label: `v${version}`, "aria-label": screenReaderVersion, href: url, isActive: isCurrentVersion, color: isCurrentVersion ? 'primary' : 'text', extraAction: extraAction?.(version) }));
|
|
50
78
|
} }) }));
|
|
51
79
|
};
|
|
@@ -13,7 +13,7 @@ const VARIANT_TO_PROPS_MAP = {
|
|
|
13
13
|
tip: { iconType: 'faceHappy', color: 'success' },
|
|
14
14
|
info: { iconType: 'info', color: 'primary' },
|
|
15
15
|
accessibility: { iconType: 'accessibility', color: 'primary' },
|
|
16
|
-
warning: { iconType: '
|
|
16
|
+
warning: { iconType: 'warning', color: 'warning' },
|
|
17
17
|
danger: { iconType: 'error', color: 'danger' },
|
|
18
18
|
// Undocumented legacy admonition type aliases
|
|
19
19
|
secondary: {},
|
|
@@ -4,6 +4,7 @@ export type ActionComponentProps = {
|
|
|
4
4
|
activeSource: DemoSourceMeta | null;
|
|
5
5
|
sources: DemoSourceMeta[];
|
|
6
6
|
extraFiles?: ExtraFiles;
|
|
7
|
+
previewWrapperSource?: string;
|
|
7
8
|
};
|
|
8
9
|
export type ActionComponent = ComponentType<ActionComponentProps>;
|
|
9
10
|
export declare const extraActions: ActionComponent[];
|
|
@@ -14,5 +14,5 @@ export default function HomeBreadcrumbItem() {
|
|
|
14
14
|
id: 'theme.docs.breadcrumbs.home',
|
|
15
15
|
message: 'Home page',
|
|
16
16
|
description: 'The ARIA label for the home page in the breadcrumbs',
|
|
17
|
-
}), className: "breadcrumbs__link", href: homeHref, children: title }), _jsx(EuiIcon, { type: "
|
|
17
|
+
}), className: "breadcrumbs__link", href: homeHref, children: title }), _jsx(EuiIcon, { type: "chevronSingleRight", size: "s", css: styles.icon })] }));
|
|
18
18
|
}
|
|
@@ -40,7 +40,7 @@ function BreadcrumbsItem({ children, active, index, addMicrodata, }) {
|
|
|
40
40
|
itemType: 'https://schema.org/ListItem',
|
|
41
41
|
}), className: clsx('breadcrumbs__item', {
|
|
42
42
|
'breadcrumbs__item--active': active,
|
|
43
|
-
}), css: styles.item, children: [children, _jsx("meta", { itemProp: "position", content: String(index + 1) }), !active && _jsx(EuiIcon, { type: "
|
|
43
|
+
}), css: styles.item, children: [children, _jsx("meta", { itemProp: "position", content: String(index + 1) }), !active && _jsx(EuiIcon, { type: "chevronSingleRight", css: styles.icon })] }));
|
|
44
44
|
}
|
|
45
45
|
export default function DocBreadcrumbs() {
|
|
46
46
|
const breadcrumbs = useSidebarBreadcrumbs();
|
|
@@ -27,8 +27,8 @@ function CardCategory({ item }) {
|
|
|
27
27
|
icon: "folderOpen", title: item.label, description: item.description ?? categoryItemsPlural(item.items.length) }));
|
|
28
28
|
}
|
|
29
29
|
function CardLink({ item }) {
|
|
30
|
-
// We update Docusaurus `link` icon to EUI `
|
|
31
|
-
const icon = isInternalUrl(item.href) ? 'document' : '
|
|
30
|
+
// We update Docusaurus `link` icon to EUI `external` icon
|
|
31
|
+
const icon = isInternalUrl(item.href) ? 'document' : 'external';
|
|
32
32
|
const doc = useDocById(item.docId ?? undefined);
|
|
33
33
|
return (_jsx(CardLayout, { href: item.href, icon: icon, title: item.label, description: item.description ?? doc?.description }));
|
|
34
34
|
}
|
|
@@ -85,7 +85,7 @@ function CollapseButton({ collapsed, categoryLabel, onClick, ...rest }) {
|
|
|
85
85
|
id: 'theme.DocSidebarItem.collapseCategoryAriaLabel',
|
|
86
86
|
message: "Collapse sidebar category '{label}'",
|
|
87
87
|
description: 'The ARIA label to collapse the sidebar category',
|
|
88
|
-
}, { label: categoryLabel }), "aria-expanded": !collapsed, type: "button", className: "clean-btn", onClick: onClick, ...rest, children: _jsx(EuiIcon, { size: "s", type: collapsed ? '
|
|
88
|
+
}, { label: categoryLabel }), "aria-expanded": !collapsed, type: "button", className: "clean-btn", onClick: onClick, ...rest, children: _jsx(EuiIcon, { size: "s", type: collapsed ? 'chevronSingleRight' : 'chevronSingleDown' }) }));
|
|
89
89
|
}
|
|
90
90
|
export default function DocSidebarItemCategory({ item, onItemClick, activePath, level, index, ...props }) {
|
|
91
91
|
const { items, label, collapsible, className, href } = item;
|
|
@@ -39,5 +39,5 @@ export default function PaginatorNavLink(props) {
|
|
|
39
39
|
const { permalink, title, subLabel, isNext } = props;
|
|
40
40
|
const isPrev = !isNext;
|
|
41
41
|
const styles = useEuiMemoizedStyles(getStyles);
|
|
42
|
-
return (_jsxs(Link, { className: clsx('pagination-nav__link', isNext ? 'pagination-nav__link--next' : 'pagination-nav__link--prev'), css: styles.link, to: permalink, children: [subLabel && _jsx("div", { className: "pagination-nav__sublabel", children: subLabel }), _jsxs("div", { className: "pagination-nav__label", children: [isPrev && _jsx(EuiIcon, { type: "
|
|
42
|
+
return (_jsxs(Link, { className: clsx('pagination-nav__link', isNext ? 'pagination-nav__link--next' : 'pagination-nav__link--prev'), css: styles.link, to: permalink, children: [subLabel && _jsx("div", { className: "pagination-nav__sublabel", children: subLabel }), _jsxs("div", { className: "pagination-nav__label", children: [isPrev && _jsx(EuiIcon, { type: "chevronSingleLeft" }), title, isNext && _jsx(EuiIcon, { type: "chevronSingleRight" })] })] }));
|
|
43
43
|
}
|
|
@@ -19,5 +19,5 @@ const getStyles = ({ euiTheme }) => {
|
|
|
19
19
|
};
|
|
20
20
|
export default function TOCCollapsibleCollapseButton({ collapsed, ...props }) {
|
|
21
21
|
const styles = useEuiMemoizedStyles(getStyles);
|
|
22
|
-
return (_jsxs("button", { type: "button", ...props, className: clsx('clean-btn', props.className), css: styles.tocCollapsibleButton, children: [_jsx(Translate, { id: "theme.TOCCollapsible.toggleButtonLabel", description: "The label used by the button on the collapsible TOC component", children: "On this page" }), _jsx(EuiIcon, { type: collapsed ? '
|
|
22
|
+
return (_jsxs("button", { type: "button", ...props, className: clsx('clean-btn', props.className), css: styles.tocCollapsibleButton, children: [_jsx(Translate, { id: "theme.TOCCollapsible.toggleButtonLabel", description: "The label used by the button on the collapsible TOC component", children: "On this page" }), _jsx(EuiIcon, { type: collapsed ? 'chevronSingleDown' : 'chevronSingleUp' })] }));
|
|
23
23
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elastic/eui-docusaurus-theme",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.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": "^
|
|
43
|
+
"@elastic/eui": "^116.0.0",
|
|
44
|
+
"@elastic/eui-theme-borealis": "^8.0.0",
|
|
45
45
|
"@emotion/css": "^11.11.2",
|
|
46
46
|
"@emotion/react": "^11.11.4",
|
|
47
47
|
"@types/react-window": "^1.8.8",
|
|
@@ -23,6 +23,7 @@ export interface DemoActionsBarProps {
|
|
|
23
23
|
activeSource: DemoSourceMeta | null;
|
|
24
24
|
sources: DemoSourceMeta[];
|
|
25
25
|
extraFiles?: ExtraFiles;
|
|
26
|
+
previewWrapperSource?: string;
|
|
26
27
|
isSourceOpen: boolean;
|
|
27
28
|
setSourceOpen(isOpen: boolean): void;
|
|
28
29
|
onClickReloadExample(): void;
|
|
@@ -55,6 +56,7 @@ export const DemoActionsBar = ({
|
|
|
55
56
|
activeSource,
|
|
56
57
|
sources,
|
|
57
58
|
extraFiles,
|
|
59
|
+
previewWrapperSource,
|
|
58
60
|
onClickReloadExample,
|
|
59
61
|
onClickCopyToClipboard,
|
|
60
62
|
}: DemoActionsBarProps) => {
|
|
@@ -73,15 +75,17 @@ export const DemoActionsBar = ({
|
|
|
73
75
|
</EuiButton>
|
|
74
76
|
{extraActions.map((ActionComponent) => (
|
|
75
77
|
<ActionComponent
|
|
78
|
+
key={ActionComponent.displayName ?? ActionComponent.name}
|
|
76
79
|
sources={sources}
|
|
77
80
|
extraFiles={extraFiles}
|
|
81
|
+
previewWrapperSource={previewWrapperSource}
|
|
78
82
|
activeSource={activeSource}
|
|
79
83
|
/>
|
|
80
84
|
))}
|
|
81
85
|
<EuiToolTip content="Copy to clipboard">
|
|
82
86
|
<EuiButtonIcon
|
|
83
87
|
size="s"
|
|
84
|
-
iconType="
|
|
88
|
+
iconType="copy"
|
|
85
89
|
color="text"
|
|
86
90
|
onClick={onClickCopyToClipboard}
|
|
87
91
|
aria-label="Copy code to clipboard"
|
|
@@ -34,7 +34,8 @@ const indexTsxSource = dedent`
|
|
|
34
34
|
<EuiProvider cache={cache}>
|
|
35
35
|
<Demo />
|
|
36
36
|
</EuiProvider>
|
|
37
|
-
)
|
|
37
|
+
);
|
|
38
|
+
`;
|
|
38
39
|
|
|
39
40
|
const publicIndexHtmlSource = dedent`
|
|
40
41
|
<head>
|
|
@@ -69,12 +70,29 @@ export type Options = {
|
|
|
69
70
|
const processTsxSource = (source: string) => {
|
|
70
71
|
// jsxImportSource pragma is needed in CodeSandbox as it doesn't seem
|
|
71
72
|
// to support that setting via tsconfig.json
|
|
72
|
-
|
|
73
|
+
let processed = `/** @jsxImportSource @emotion/react */\n${source}`;
|
|
74
|
+
|
|
75
|
+
// Inject `@elastic/charts` CSS for demos that use the charts library,
|
|
76
|
+
// since CodeSandbox doesn't load it globally unlike the docs site
|
|
77
|
+
if (source.includes('@elastic/charts')) {
|
|
78
|
+
// Match the closing line of the @elastic/charts import (handles both
|
|
79
|
+
// single-line and multi-line imports, and both quote styles)
|
|
80
|
+
processed = processed.replace(
|
|
81
|
+
/^(.*from ['"]@elastic\/charts['"];)$/m,
|
|
82
|
+
[
|
|
83
|
+
'$1',
|
|
84
|
+
"import '@elastic/charts/dist/theme_only_light.css';",
|
|
85
|
+
"import '@elastic/charts/dist/theme_only_dark.css';",
|
|
86
|
+
].join('\n')
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return processed;
|
|
73
91
|
};
|
|
74
92
|
|
|
75
93
|
export const createOpenInCodeSandboxAction =
|
|
76
94
|
({ files = {}, dependencies }: Options): ActionComponent =>
|
|
77
|
-
({ extraFiles, activeSource }) => {
|
|
95
|
+
({ extraFiles, activeSource, previewWrapperSource }) => {
|
|
78
96
|
const parameters: string = useMemo(() => {
|
|
79
97
|
const source = activeSource?.code || '';
|
|
80
98
|
|
|
@@ -93,6 +111,24 @@ export const createOpenInCodeSandboxAction =
|
|
|
93
111
|
return getParameters({
|
|
94
112
|
files: {
|
|
95
113
|
...defaultCodeSandboxParameters.files,
|
|
114
|
+
...(previewWrapperSource
|
|
115
|
+
? {
|
|
116
|
+
'index.tsx': {
|
|
117
|
+
content: indexTsxSource
|
|
118
|
+
.replace(
|
|
119
|
+
"import Demo from './demo';",
|
|
120
|
+
"import Demo from './demo';\nimport PreviewWrapper from './preview_wrapper';"
|
|
121
|
+
)
|
|
122
|
+
.replace(
|
|
123
|
+
'<Demo />',
|
|
124
|
+
'<PreviewWrapper>\n <Demo />\n </PreviewWrapper>'
|
|
125
|
+
),
|
|
126
|
+
},
|
|
127
|
+
'preview_wrapper.tsx': {
|
|
128
|
+
content: processTsxSource(previewWrapperSource),
|
|
129
|
+
},
|
|
130
|
+
}
|
|
131
|
+
: {}),
|
|
96
132
|
'demo.tsx': {
|
|
97
133
|
content: processTsxSource(source),
|
|
98
134
|
},
|
|
@@ -107,7 +143,7 @@ export const createOpenInCodeSandboxAction =
|
|
|
107
143
|
...codeSandboxFiles,
|
|
108
144
|
},
|
|
109
145
|
} as any);
|
|
110
|
-
}, [activeSource, extraFiles]);
|
|
146
|
+
}, [activeSource, extraFiles, previewWrapperSource]);
|
|
111
147
|
|
|
112
148
|
return (
|
|
113
149
|
<form
|
|
@@ -79,6 +79,7 @@ export interface DemoProps extends PropsWithChildren {
|
|
|
79
79
|
extraFiles?: ExtraFiles;
|
|
80
80
|
previewPadding?: DemoPreviewProps['padding'];
|
|
81
81
|
previewWrapper?: DemoPreviewProps['wrapperComponent'];
|
|
82
|
+
previewWrapperSource?: string;
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
const getDemoStyles = (euiTheme: UseEuiTheme) => ({
|
|
@@ -100,6 +101,7 @@ export const Demo = ({
|
|
|
100
101
|
isSourceOpen: _isSourceOpen = false,
|
|
101
102
|
previewPadding,
|
|
102
103
|
previewWrapper,
|
|
104
|
+
previewWrapperSource,
|
|
103
105
|
}: DemoProps) => {
|
|
104
106
|
const styles = useEuiMemoizedStyles(getDemoStyles);
|
|
105
107
|
const [sources, setSources] = useState<DemoSourceMeta[]>([]);
|
|
@@ -153,6 +155,7 @@ export const Demo = ({
|
|
|
153
155
|
activeSource={activeSource}
|
|
154
156
|
extraFiles={extraFiles}
|
|
155
157
|
sources={sources}
|
|
158
|
+
previewWrapperSource={previewWrapperSource}
|
|
156
159
|
onClickCopyToClipboard={onClickCopyToClipboard}
|
|
157
160
|
onClickReloadExample={onClickReloadExample}
|
|
158
161
|
/>
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Side Public License, v 1.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { ComponentProps, useState } from 'react';
|
|
9
|
+
import { ComponentProps, useEffect, useState } from 'react';
|
|
10
10
|
import { css } from '@emotion/react';
|
|
11
11
|
import { FixedSizeList } from 'react-window';
|
|
12
12
|
import {
|
|
@@ -68,6 +68,13 @@ export type VersionSwitcherProps = {
|
|
|
68
68
|
* List of available versions to switch to
|
|
69
69
|
*/
|
|
70
70
|
versions: string[];
|
|
71
|
+
/**
|
|
72
|
+
* URL to fetch the latest list of versions from.
|
|
73
|
+
* When provided, versions are fetched client-side from this URL,
|
|
74
|
+
* falling back to the static `versions` prop if the fetch fails.
|
|
75
|
+
* This ensures all deployed versions are always visible in the switcher.
|
|
76
|
+
*/
|
|
77
|
+
versionsUrl?: string;
|
|
71
78
|
};
|
|
72
79
|
|
|
73
80
|
export const VersionSwitcher = ({
|
|
@@ -76,17 +83,47 @@ export const VersionSwitcher = ({
|
|
|
76
83
|
extraAction,
|
|
77
84
|
previousVersionUrl,
|
|
78
85
|
versions,
|
|
86
|
+
versionsUrl,
|
|
79
87
|
}: VersionSwitcherProps) => {
|
|
80
88
|
const [isPopoverOpen, setPopoverOpen] = useState(false);
|
|
89
|
+
const [allVersions, setAllVersions] = useState(versions);
|
|
81
90
|
const styles = useEuiMemoizedStyles(getStyles);
|
|
82
91
|
|
|
83
|
-
|
|
92
|
+
// Fetch the latest versions list from the main deployment
|
|
93
|
+
// to ensure the switcher always shows all available versions,
|
|
94
|
+
// even on older documentation deployments
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
if (!versionsUrl) return;
|
|
97
|
+
|
|
98
|
+
fetch(versionsUrl)
|
|
99
|
+
.then((response) => {
|
|
100
|
+
if (!response.ok) throw new Error('Failed to fetch versions');
|
|
101
|
+
return response.json();
|
|
102
|
+
})
|
|
103
|
+
.then((data) => {
|
|
104
|
+
if (data?.euiVersions?.length) {
|
|
105
|
+
// Ensure the current version is always included
|
|
106
|
+
const fetchedVersions: string[] = data.euiVersions;
|
|
107
|
+
if (!fetchedVersions.includes(currentVersion)) {
|
|
108
|
+
fetchedVersions.push(currentVersion);
|
|
109
|
+
}
|
|
110
|
+
setAllVersions(fetchedVersions);
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
.catch(() => {
|
|
114
|
+
// Silently fall back to statically bundled versions
|
|
115
|
+
});
|
|
116
|
+
}, [versionsUrl, currentVersion]);
|
|
117
|
+
|
|
118
|
+
if (!allVersions?.length) return null;
|
|
119
|
+
|
|
120
|
+
const latestVersion = allVersions[0];
|
|
84
121
|
|
|
85
122
|
const button = (
|
|
86
123
|
<EuiButtonEmpty
|
|
87
124
|
size="s"
|
|
88
125
|
color="text"
|
|
89
|
-
iconType="
|
|
126
|
+
iconType="chevronSingleDown"
|
|
90
127
|
iconSide="right"
|
|
91
128
|
css={styles.button}
|
|
92
129
|
onClick={() => setPopoverOpen((isOpen) => !isOpen)}
|
|
@@ -109,26 +146,26 @@ export const VersionSwitcher = ({
|
|
|
109
146
|
>
|
|
110
147
|
<FixedSizeList
|
|
111
148
|
className="eui-yScroll"
|
|
112
|
-
itemCount={
|
|
149
|
+
itemCount={allVersions.length}
|
|
113
150
|
itemSize={24}
|
|
114
151
|
height={200}
|
|
115
152
|
width={120}
|
|
116
153
|
innerElementType="ul"
|
|
117
154
|
>
|
|
118
155
|
{({ index, style }) => {
|
|
119
|
-
const version =
|
|
156
|
+
const version = allVersions[index];
|
|
120
157
|
const isCurrentVersion = version === currentVersion;
|
|
121
158
|
const screenReaderVersion = pronounceVersion(version!);
|
|
122
159
|
|
|
123
|
-
const url =
|
|
124
|
-
|
|
125
|
-
|
|
160
|
+
const url =
|
|
161
|
+
version === latestVersion
|
|
162
|
+
? `${previousVersionUrl}/`
|
|
163
|
+
: `${previousVersionUrl}/v${version}/`;
|
|
126
164
|
|
|
127
165
|
return (
|
|
128
166
|
<EuiListGroupItem
|
|
129
167
|
css={styles.listItem}
|
|
130
168
|
style={style}
|
|
131
|
-
size="xs"
|
|
132
169
|
label={`v${version}`}
|
|
133
170
|
aria-label={screenReaderVersion}
|
|
134
171
|
href={url}
|
|
@@ -32,7 +32,7 @@ const VARIANT_TO_PROPS_MAP: Record<
|
|
|
32
32
|
tip: { iconType: 'faceHappy', color: 'success' },
|
|
33
33
|
info: { iconType: 'info', color: 'primary' },
|
|
34
34
|
accessibility: { iconType: 'accessibility', color: 'primary' },
|
|
35
|
-
warning: { iconType: '
|
|
35
|
+
warning: { iconType: 'warning', color: 'warning' },
|
|
36
36
|
danger: { iconType: 'error', color: 'danger' },
|
|
37
37
|
// Undocumented legacy admonition type aliases
|
|
38
38
|
secondary: {},
|
|
@@ -88,7 +88,7 @@ function BreadcrumbsItem({
|
|
|
88
88
|
>
|
|
89
89
|
{children}
|
|
90
90
|
<meta itemProp="position" content={String(index + 1)} />
|
|
91
|
-
{!active && <EuiIcon type="
|
|
91
|
+
{!active && <EuiIcon type="chevronSingleRight" css={styles.icon} />}
|
|
92
92
|
</li>
|
|
93
93
|
);
|
|
94
94
|
}
|
|
@@ -75,8 +75,8 @@ function CardCategory({ item }: { item: PropSidebarItemCategory }): ReactNode {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
function CardLink({ item }: { item: PropSidebarItemLink }): ReactNode {
|
|
78
|
-
// We update Docusaurus `link` icon to EUI `
|
|
79
|
-
const icon = isInternalUrl(item.href) ? 'document' : '
|
|
78
|
+
// We update Docusaurus `link` icon to EUI `external` icon
|
|
79
|
+
const icon = isInternalUrl(item.href) ? 'document' : 'external';
|
|
80
80
|
const doc = useDocById(item.docId ?? undefined);
|
|
81
81
|
return (
|
|
82
82
|
<CardLayout
|
|
@@ -138,7 +138,7 @@ function CollapseButton({
|
|
|
138
138
|
onClick={onClick}
|
|
139
139
|
{...rest}
|
|
140
140
|
>
|
|
141
|
-
<EuiIcon size="s" type={collapsed ? '
|
|
141
|
+
<EuiIcon size="s" type={collapsed ? 'chevronSingleRight' : 'chevronSingleDown'} />
|
|
142
142
|
</button>
|
|
143
143
|
);
|
|
144
144
|
}
|
|
@@ -63,9 +63,9 @@ export default function PaginatorNavLink(props: Props): JSX.Element {
|
|
|
63
63
|
{subLabel && <div className="pagination-nav__sublabel">{subLabel}</div>}
|
|
64
64
|
|
|
65
65
|
<div className="pagination-nav__label">
|
|
66
|
-
{isPrev && <EuiIcon type="
|
|
66
|
+
{isPrev && <EuiIcon type="chevronSingleLeft" />}
|
|
67
67
|
{title}
|
|
68
|
-
{isNext && <EuiIcon type="
|
|
68
|
+
{isNext && <EuiIcon type="chevronSingleRight" />}
|
|
69
69
|
</div>
|
|
70
70
|
</Link>
|
|
71
71
|
);
|