@redocly/theme 0.4.16 → 0.5.1
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/ApiOnboarding/AppCustomAttributes.d.ts +5 -0
- package/lib/ApiOnboarding/AppCustomAttributes.js +8 -0
- package/lib/ColorModeSwitcher/ColorModeSwitcher.js +23 -10
- package/lib/EditPageButton/EditPageButton.d.ts +1 -1
- package/lib/EditPageButton/EditPageButton.js +5 -1
- package/lib/Footer/Footer.js +2 -2
- package/lib/Footer/FooterColumn.js +1 -1
- package/lib/LastUpdated/LastUpdated.js +30 -7
- package/lib/Markdown/Admonition.js +3 -0
- package/lib/Markdown/CodeSample/CodeSample.js +14 -14
- package/lib/Markdown/MarkdownLayout.d.ts +1 -1
- package/lib/Markdown/MarkdownLayout.js +5 -1
- package/lib/Navbar/Navbar.js +2 -2
- package/lib/Navbar/NavbarItem.js +1 -1
- package/lib/PageNavigation/NextPageLink.js +30 -7
- package/lib/PageNavigation/PageNavigation.js +8 -3
- package/lib/PageNavigation/PreviousPageLink.js +4 -4
- package/lib/Sidebar/MenuLink.d.ts +3 -4
- package/lib/Sidebar/MenuLink.js +2 -6
- package/lib/Sidebar/SidebarLayout.js +2 -2
- package/lib/Sidebar/types/MenuStyle.js +0 -1
- package/lib/TableOfContent/TableOfContent.d.ts +0 -1
- package/lib/TableOfContent/TableOfContent.js +5 -7
- package/lib/config.d.ts +385 -0
- package/lib/config.js +113 -0
- package/lib/globalStyle.js +3 -5
- package/lib/hooks/index.d.ts +1 -0
- package/lib/hooks/index.js +1 -0
- package/lib/hooks/useActiveHeading.js +1 -1
- package/lib/hooks/useActiveSectionId.js +1 -1
- package/lib/hooks/useThemeConfig.d.ts +1 -0
- package/lib/hooks/useThemeConfig.js +6 -0
- package/lib/icons/ColorModeIcon/ColorModeIcon.js +3 -3
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/mocks/Link.js +12 -2
- package/lib/mocks/hooks/index.d.ts +2 -5
- package/lib/mocks/hooks/index.js +22 -6
- package/lib/mocks/types.d.ts +0 -11
- package/lib/mocks/types.js +1 -0
- package/lib/types/config.d.ts +5 -0
- package/lib/types/config.js +3 -0
- package/lib/ui/index.d.ts +0 -1
- package/lib/ui/index.js +0 -1
- package/lib/utils/args-typecheck.js +1 -1
- package/package.json +30 -34
- package/src/ApiOnboarding/AppCustomAttributes.tsx +6 -0
- package/src/ColorModeSwitcher/ColorModeSwitcher.tsx +29 -12
- package/src/EditPageButton/EditPageButton.tsx +6 -2
- package/src/Footer/Footer.tsx +2 -2
- package/src/Footer/FooterColumn.tsx +7 -1
- package/src/LastUpdated/LastUpdated.tsx +8 -6
- package/src/Markdown/Admonition.tsx +3 -0
- package/src/Markdown/CodeSample/CodeSample.tsx +15 -16
- package/src/Markdown/MarkdownLayout.tsx +9 -3
- package/src/Navbar/Navbar.tsx +2 -2
- package/src/Navbar/NavbarItem.tsx +1 -1
- package/src/PageNavigation/NextPageLink.tsx +8 -5
- package/src/PageNavigation/PageNavigation.tsx +7 -3
- package/src/PageNavigation/PreviousPageLink.tsx +7 -4
- package/src/Sidebar/MenuLink.tsx +3 -8
- package/src/Sidebar/SidebarLayout.tsx +2 -2
- package/src/Sidebar/types/MenuStyle.ts +0 -1
- package/src/TableOfContent/TableOfContent.tsx +5 -7
- package/src/config.ts +130 -0
- package/src/globalStyle.ts +3 -5
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useActiveHeading.ts +3 -1
- package/src/hooks/useActiveSectionId.ts +1 -1
- package/src/hooks/useThemeConfig.ts +1 -0
- package/src/icons/ColorModeIcon/ColorModeIcon.tsx +3 -3
- package/src/index.ts +3 -0
- package/src/mocks/Link.tsx +8 -2
- package/src/mocks/hooks/index.ts +22 -9
- package/src/mocks/types.ts +2 -11
- package/{settings.yaml → src/settings.yaml} +0 -0
- package/src/types/config.ts +5 -0
- package/src/types/portal/src/shared/constants.d.ts +0 -1
- package/src/types/portal/src/shared/types/nav.d.ts +3 -0
- package/src/ui/index.tsx +0 -1
- package/src/utils/args-typecheck.ts +1 -1
- package/lib/hooks/useDefaultThemeSettings.d.ts +0 -2
- package/lib/hooks/useDefaultThemeSettings.js +0 -10
- package/lib/ui/UniversalLink.d.ts +0 -17
- package/lib/ui/UniversalLink.js +0 -79
- package/src/hooks/useDefaultThemeSettings.ts +0 -7
- package/src/ui/UniversalLink.tsx +0 -97
package/lib/mocks/hooks/index.js
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useSidebarSiblingsData = exports.
|
|
4
|
-
function
|
|
3
|
+
exports.useSidebarSiblingsData = exports.useThemeConfig = void 0;
|
|
4
|
+
function useThemeConfig() {
|
|
5
5
|
return {
|
|
6
|
-
|
|
6
|
+
search: { hide: false, placement: 'navbar' },
|
|
7
|
+
markdown: {
|
|
8
|
+
toc: { maxDepth: 3, header: 'Table of contents', hide: false },
|
|
9
|
+
lastUpdatedBlock: { hide: false, format: 'timeago', locale: 'en-US' },
|
|
10
|
+
copyCodeSnippet: {
|
|
11
|
+
hide: false,
|
|
12
|
+
buttonText: 'Copy',
|
|
13
|
+
tooltipText: 'Copy to clipboard',
|
|
14
|
+
toasterText: 'Copied',
|
|
15
|
+
toasterDuration: 1500,
|
|
16
|
+
},
|
|
17
|
+
editPage: {
|
|
18
|
+
baseUrl: '',
|
|
19
|
+
text: 'Edit this page',
|
|
20
|
+
},
|
|
21
|
+
frontmatterKeysToResolve: ['image', 'links'],
|
|
22
|
+
},
|
|
7
23
|
navigation: {
|
|
8
|
-
nextPageLink: { label: 'next page theme
|
|
9
|
-
prevPageLink: { label: 'prev page theme
|
|
24
|
+
nextPageLink: { label: 'next page theme config label' },
|
|
25
|
+
prevPageLink: { label: 'prev page theme config label' },
|
|
10
26
|
},
|
|
11
27
|
colorMode: {
|
|
12
28
|
modes: ['light', 'dark'],
|
|
@@ -14,7 +30,7 @@ function useThemeSettings(_) {
|
|
|
14
30
|
},
|
|
15
31
|
};
|
|
16
32
|
}
|
|
17
|
-
exports.
|
|
33
|
+
exports.useThemeConfig = useThemeConfig;
|
|
18
34
|
function useSidebarSiblingsData() {
|
|
19
35
|
return {
|
|
20
36
|
nextPage: {
|
package/lib/mocks/types.d.ts
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
1
|
export declare type ActiveItem<T> = T;
|
|
2
2
|
export declare type SearchDocument = any;
|
|
3
3
|
export declare type OperationParameter = any;
|
|
4
|
-
export interface RawTheme {
|
|
5
|
-
name: string;
|
|
6
|
-
settings: {
|
|
7
|
-
lastUpdatedBlock?: {
|
|
8
|
-
hide?: boolean;
|
|
9
|
-
format?: 'timeago' | 'iso' | 'short' | 'long';
|
|
10
|
-
locale?: string;
|
|
11
|
-
};
|
|
12
|
-
[k: string]: any;
|
|
13
|
-
};
|
|
14
|
-
}
|
package/lib/mocks/types.js
CHANGED
package/lib/ui/index.d.ts
CHANGED
|
@@ -5,6 +5,5 @@ export * from '../ui/Box';
|
|
|
5
5
|
export * from '../ui/Dropdown';
|
|
6
6
|
export * from '../ui/Flex';
|
|
7
7
|
export * from '../ui/Jumbotron';
|
|
8
|
-
export * from '../ui/UniversalLink';
|
|
9
8
|
export declare const LandingLayout: ({ children }: React.PropsWithChildren<object>) => React.ReactNode;
|
|
10
9
|
export declare const EmptyLayout: ({ children }: React.PropsWithChildren<object>) => React.ReactNode;
|
package/lib/ui/index.js
CHANGED
|
@@ -21,7 +21,6 @@ __exportStar(require("../ui/Box"), exports);
|
|
|
21
21
|
__exportStar(require("../ui/Dropdown"), exports);
|
|
22
22
|
__exportStar(require("../ui/Flex"), exports);
|
|
23
23
|
__exportStar(require("../ui/Jumbotron"), exports);
|
|
24
|
-
__exportStar(require("../ui/UniversalLink"), exports);
|
|
25
24
|
const LandingLayout = ({ children }) => children;
|
|
26
25
|
exports.LandingLayout = LandingLayout;
|
|
27
26
|
exports.EmptyLayout = exports.LandingLayout;
|
|
@@ -8,7 +8,7 @@ function isEmptyArray(items) {
|
|
|
8
8
|
exports.isEmptyArray = isEmptyArray;
|
|
9
9
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
10
10
|
function isPrimitive(arg) {
|
|
11
|
-
return ['string', 'boolean', 'number'].includes(typeof arg);
|
|
11
|
+
return ['string', 'boolean', 'number', 'undefined'].includes(typeof arg);
|
|
12
12
|
}
|
|
13
13
|
exports.isPrimitive = isPrimitive;
|
|
14
14
|
//# sourceMappingURL=args-typecheck.js.map
|
package/package.json
CHANGED
|
@@ -1,38 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/theme",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Shared UI components",
|
|
5
5
|
"author": "team@redocly.com",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
7
7
|
"main": "lib/index.js",
|
|
8
8
|
"types": "lib/index.d.ts",
|
|
9
9
|
"exports": {
|
|
10
|
+
"./package.json": "./package.json",
|
|
11
|
+
"./config.js": "./lib/config.js",
|
|
12
|
+
"./config": "./lib/config.js",
|
|
10
13
|
".": "./lib/index.js",
|
|
11
14
|
"./Sidebar/*": "./lib/Sidebar/*.js",
|
|
12
15
|
"./*": "./lib/*/index.js",
|
|
13
16
|
"./src/": "./src/"
|
|
14
17
|
},
|
|
15
18
|
"scripts": {
|
|
16
|
-
"start": "npm-run-all --parallel storybook
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"generate-tokens": "ts-node scripts/generate-css-tokens.ts",
|
|
20
|
-
"generate-tokens:watch": "ts-node-dev --respawn scripts/generate-css-tokens.ts",
|
|
19
|
+
"start": "npm-run-all --parallel storybook storybook:tokens:watch",
|
|
20
|
+
"watch": "tsc -p tsconfig.build.json && (concurrently \"tsc -w -p tsconfig.build.json\" \"tsc-alias -w -p tsconfig.build.json\")",
|
|
21
|
+
"ts:check": "tsc --noEmit --skipLibCheck",
|
|
21
22
|
"clean": "rm -rf lib",
|
|
22
23
|
"compile": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
23
24
|
"build": "npm run clean && npm run compile",
|
|
24
|
-
"build:on-rebuild": "tsc-alias -p tsconfig.build.json",
|
|
25
|
-
"build:watch": "npm run clean && tsc-watch --project tsconfig.build.json --onSuccess \"npm run build:on-rebuild\"",
|
|
26
|
-
"lint": "eslint . --ext .ts,.tsx --cache",
|
|
27
|
-
"lint:fix": "eslint . --ext .ts,.tsx --fix",
|
|
28
|
-
"prettier-base": "prettier \"**/*.{json,js,jsx,ts,tsx,yml,yaml,html,md}\"",
|
|
29
|
-
"prettier": "npm run prettier-base -- --write",
|
|
30
|
-
"prettier:check": "npm run prettier-base -- --check",
|
|
31
|
-
"ts:check": "tsc --noEmit --skipLibCheck",
|
|
32
25
|
"test": "jest",
|
|
26
|
+
"test:update": "jest -u",
|
|
33
27
|
"test:watch": "jest --watch",
|
|
34
28
|
"test:coverage": "jest --coverage",
|
|
35
|
-
"test:
|
|
29
|
+
"test:coverage:html": "jest --coverage --coverageReporters html",
|
|
30
|
+
"e2e": "npx chromatic -b storybook:build --auto-accept-changes main --exit-once-uploaded",
|
|
31
|
+
"storybook": "start-storybook -p 6006",
|
|
32
|
+
"storybook:build": "npm run storybook:tokens && build-storybook",
|
|
33
|
+
"storybook:tokens": "ts-node scripts/generate-css-tokens.ts",
|
|
34
|
+
"storybook:tokens:watch": "ts-node-dev --respawn scripts/generate-css-tokens.ts",
|
|
36
35
|
"chromatic": "chromatic --exit-zero-on-changes"
|
|
37
36
|
},
|
|
38
37
|
"peerDependencies": {
|
|
@@ -41,8 +40,9 @@
|
|
|
41
40
|
"react": "^17.0.2",
|
|
42
41
|
"react-dom": "^17.0.2",
|
|
43
42
|
"react-router-dom": "^5.3.0",
|
|
44
|
-
"styled-components": "^5.3.
|
|
45
|
-
"styled-system": "^5.1.5"
|
|
43
|
+
"styled-components": "^5.3.6",
|
|
44
|
+
"styled-system": "^5.1.5",
|
|
45
|
+
"zod": ">=3.19.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@storybook/addon-actions": "^6.5.9",
|
|
@@ -55,7 +55,6 @@
|
|
|
55
55
|
"@storybook/core-common": "^6.5.9",
|
|
56
56
|
"@storybook/manager-webpack5": "^6.5.9",
|
|
57
57
|
"@storybook/node-logger": "^6.5.9",
|
|
58
|
-
"@storybook/preset-create-react-app": "^4.1.0",
|
|
59
58
|
"@storybook/react": "^6.5.9",
|
|
60
59
|
"@storybook/testing-library": "^0.0.11",
|
|
61
60
|
"@storybook/theming": "^6.5.9",
|
|
@@ -75,34 +74,31 @@
|
|
|
75
74
|
"@types/styled-system": "^5.1.13",
|
|
76
75
|
"@typescript-eslint/eslint-plugin": "^5.23.0",
|
|
77
76
|
"@typescript-eslint/parser": "^5.23.0",
|
|
78
|
-
"chromatic": "^6.
|
|
79
|
-
"esbuild": "^0.
|
|
80
|
-
"jest": "^29.
|
|
81
|
-
"jest-environment-jsdom": "^29.
|
|
77
|
+
"chromatic": "^6.10.2",
|
|
78
|
+
"esbuild": "^0.15.11",
|
|
79
|
+
"jest": "^29.2.0",
|
|
80
|
+
"jest-environment-jsdom": "^29.2.0",
|
|
82
81
|
"jest-styled-components": "^7.1.1",
|
|
83
82
|
"jest-when": "^3.5.1",
|
|
84
|
-
"lint-staged": "^12.4.1",
|
|
85
|
-
"lodash": "^4.17.21",
|
|
86
83
|
"lodash.throttle": "^4.1.1",
|
|
87
84
|
"npm-run-all": "^4.1.5",
|
|
88
|
-
"prettier": "2.6.2",
|
|
89
85
|
"react": "^17.0.2",
|
|
90
86
|
"react-dom": "^17.0.2",
|
|
91
|
-
"react-refresh": "^0.
|
|
87
|
+
"react-refresh": "^0.14.0",
|
|
92
88
|
"react-router-dom": "^5.3.0",
|
|
93
|
-
"react-scripts": "5.0.1",
|
|
94
89
|
"storybook-addon-pseudo-states": "^1.15.1",
|
|
95
|
-
"storybook-design-token": "^2.1
|
|
96
|
-
"styled-components": "^5.3.
|
|
90
|
+
"storybook-design-token": "^2.7.1",
|
|
91
|
+
"styled-components": "^5.3.6",
|
|
97
92
|
"styled-system": "^5.1.5",
|
|
98
93
|
"ts-jest": "^29.0.3",
|
|
99
94
|
"ts-node": "^10.7.0",
|
|
100
|
-
"ts-node-dev": "^
|
|
101
|
-
"tsc-alias": "^1.
|
|
102
|
-
"tsc-watch": "^5.0.3",
|
|
95
|
+
"ts-node-dev": "^2.0.0",
|
|
96
|
+
"tsc-alias": "^1.7.0",
|
|
103
97
|
"tsconfig-paths-webpack-plugin": "^3.5.2",
|
|
104
|
-
"typescript": "^4.
|
|
105
|
-
"webpack": "^5.72.0"
|
|
98
|
+
"typescript": "^4.8.4",
|
|
99
|
+
"webpack": "^5.72.0",
|
|
100
|
+
"concurrently": "^7.4.0",
|
|
101
|
+
"zod": ">=3.19.1"
|
|
106
102
|
},
|
|
107
103
|
"dependencies": {
|
|
108
104
|
"timeago.js": "^4.0.2"
|
|
@@ -2,28 +2,26 @@ import React, { useState } from 'react';
|
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
|
|
4
4
|
import { ColorModeIcon } from '@theme/icons/ColorModeIcon';
|
|
5
|
-
import { useMount } from '@theme/hooks';
|
|
6
|
-
import { useDefaultThemeSettings } from '@theme/hooks/useDefaultThemeSettings';
|
|
5
|
+
import { useMount, useThemeConfig } from '@theme/hooks';
|
|
7
6
|
|
|
8
7
|
export function ColorModeSwitcher(): JSX.Element | null {
|
|
9
|
-
const themeSettings =
|
|
8
|
+
const themeSettings = useThemeConfig();
|
|
10
9
|
const colorMode = themeSettings.colorMode;
|
|
11
10
|
const [activeColorMode, setActiveColorMode] = useState('');
|
|
11
|
+
const modes = colorMode?.modes || ['light', 'dark'];
|
|
12
|
+
const defaultColor = colorMode?.default || modes[0] || 'light';
|
|
12
13
|
|
|
13
14
|
useMount(() => {
|
|
14
|
-
setActiveColorMode(document.documentElement.className ||
|
|
15
|
+
setActiveColorMode(document.documentElement.className || defaultColor);
|
|
15
16
|
});
|
|
16
17
|
|
|
17
|
-
if (
|
|
18
|
+
if (colorMode?.hide) {
|
|
18
19
|
return null;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
const handelChangeColorMode = () => {
|
|
22
|
-
const activeIndex =
|
|
23
|
-
const mode =
|
|
24
|
-
activeIndex < colorMode.modes.length - 1
|
|
25
|
-
? colorMode.modes[activeIndex + 1]
|
|
26
|
-
: colorMode.modes[0];
|
|
23
|
+
const activeIndex = modes.indexOf(activeColorMode);
|
|
24
|
+
const mode = activeIndex < modes.length - 1 ? modes[activeIndex + 1] : modes[0];
|
|
27
25
|
setActiveColorMode(mode);
|
|
28
26
|
localStorage.setItem('colorSchema', mode);
|
|
29
27
|
document.documentElement.className = `${mode} notransition`;
|
|
@@ -37,16 +35,35 @@ export function ColorModeSwitcher(): JSX.Element | null {
|
|
|
37
35
|
<Wrapper
|
|
38
36
|
data-component-name="ColorModeSwitcher/ColorModeSwitcher"
|
|
39
37
|
onClick={handelChangeColorMode}
|
|
38
|
+
modes={modes}
|
|
40
39
|
>
|
|
41
|
-
|
|
40
|
+
{modes.map((mode) => (
|
|
41
|
+
<ColorModeIcon mode={mode} key={mode} />
|
|
42
|
+
))}
|
|
42
43
|
</Wrapper>
|
|
43
44
|
);
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
const Wrapper = styled.div
|
|
47
|
+
const Wrapper = styled.div<{ modes: string[] }>`
|
|
47
48
|
margin-left: var(--navbar-item-padding-horizontal);
|
|
48
49
|
display: flex;
|
|
49
50
|
align-items: center;
|
|
50
51
|
cursor: pointer;
|
|
51
52
|
user-select: none;
|
|
53
|
+
|
|
54
|
+
${ColorModeIcon} {
|
|
55
|
+
display: none;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
${({ modes }: { modes: string[] }) => {
|
|
59
|
+
const items = modes.map((mode) => {
|
|
60
|
+
return `
|
|
61
|
+
html.${mode} & ${ColorModeIcon}.${mode} {
|
|
62
|
+
display: block;
|
|
63
|
+
}
|
|
64
|
+
`;
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return items.join('');
|
|
68
|
+
}}
|
|
52
69
|
`;
|
|
@@ -6,13 +6,13 @@ import { Link } from '@portal/Link';
|
|
|
6
6
|
export interface EditPageButtonProps {
|
|
7
7
|
text: string;
|
|
8
8
|
to: string;
|
|
9
|
-
icon
|
|
9
|
+
icon?: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export const EditPageButton = ({ text, to, icon }: EditPageButtonProps): JSX.Element => {
|
|
13
13
|
return (
|
|
14
14
|
<EditButton to={to}>
|
|
15
|
-
<ButtonIcon src={icon} />
|
|
15
|
+
{icon ? <ButtonIcon src={icon} /> : null}
|
|
16
16
|
<ButtonText>{text}</ButtonText>
|
|
17
17
|
</EditButton>
|
|
18
18
|
);
|
|
@@ -26,6 +26,10 @@ const EditButton = styled(Link)`
|
|
|
26
26
|
font-size: var(--font-size-base);
|
|
27
27
|
font-family: var(--font-family-base);
|
|
28
28
|
text-decoration: none;
|
|
29
|
+
|
|
30
|
+
@media print {
|
|
31
|
+
display: none;
|
|
32
|
+
}
|
|
29
33
|
`;
|
|
30
34
|
|
|
31
35
|
const ButtonIcon = styled.img`
|
package/src/Footer/Footer.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import styled from 'styled-components';
|
|
|
4
4
|
import { FooterColumns } from '@theme/Footer/FooterColumns';
|
|
5
5
|
import { FooterCopyright } from '@theme/Footer/FooterCopyright';
|
|
6
6
|
import { isEmptyArray } from '@theme/utils';
|
|
7
|
-
import {
|
|
7
|
+
import { useThemeConfig } from '@theme/hooks';
|
|
8
8
|
import type { NavGroupRecord, ResolvedNavItem } from '@theme/types/portal';
|
|
9
9
|
|
|
10
10
|
interface FooterProps {
|
|
@@ -12,7 +12,7 @@ interface FooterProps {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export function Footer({ data: { columns, copyrightText } }: FooterProps): JSX.Element | null {
|
|
15
|
-
const { footer } =
|
|
15
|
+
const { footer } = useThemeConfig();
|
|
16
16
|
|
|
17
17
|
if (isEmptyArray(columns) || !copyrightText || footer?.hide) {
|
|
18
18
|
return null;
|
|
@@ -22,7 +22,13 @@ export function FooterColumn({ column }: FooterColumnProps): JSX.Element {
|
|
|
22
22
|
{columnItem.label}
|
|
23
23
|
</FooterSeparator>
|
|
24
24
|
) : (
|
|
25
|
-
<FooterLink
|
|
25
|
+
<FooterLink
|
|
26
|
+
key={columnItemIndex}
|
|
27
|
+
to={columnItem.link}
|
|
28
|
+
external={columnItem.external}
|
|
29
|
+
target={columnItem.target}
|
|
30
|
+
data-cy={columnItem.label}
|
|
31
|
+
>
|
|
26
32
|
{columnItem.label}
|
|
27
33
|
</FooterLink>
|
|
28
34
|
);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
import { format } from 'timeago.js';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { useThemeConfig } from '@theme/hooks/useThemeConfig';
|
|
6
6
|
|
|
7
7
|
const FORMATS = {
|
|
8
8
|
timeago: (date: Date, locale: string) => format(date, locale),
|
|
@@ -20,18 +20,19 @@ export interface LastUpdatedProps {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export function LastUpdated(props: LastUpdatedProps): JSX.Element | null {
|
|
23
|
-
const { lastUpdatedBlock } =
|
|
23
|
+
const { markdown: { lastUpdatedBlock = {} } = {} } = useThemeConfig();
|
|
24
24
|
|
|
25
25
|
if (lastUpdatedBlock?.hide) {
|
|
26
26
|
return null;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const lastModified = props.lastModified;
|
|
30
|
-
const format = props.format || lastUpdatedBlock
|
|
31
|
-
const locale = props.locale || lastUpdatedBlock
|
|
30
|
+
const format = props.format || lastUpdatedBlock.format || 'timeago';
|
|
31
|
+
const locale = props.locale || lastUpdatedBlock.locale || 'en-US';
|
|
32
32
|
const isoDate = lastModified.toISOString().split('T')[0];
|
|
33
33
|
|
|
34
|
-
const lastUpdatedString = FORMATS[format](lastModified, locale);
|
|
34
|
+
const lastUpdatedString = FORMATS[format as keyof typeof FORMATS](lastModified, locale);
|
|
35
|
+
|
|
35
36
|
const separator = format === 'timeago' ? ' ' : ' on ';
|
|
36
37
|
|
|
37
38
|
return (
|
|
@@ -41,6 +42,7 @@ export function LastUpdated(props: LastUpdatedProps): JSX.Element | null {
|
|
|
41
42
|
data-print-datetime={isoDate}
|
|
42
43
|
>
|
|
43
44
|
Last updated{separator}
|
|
45
|
+
{/* TODO: fix issue with snapshot tests - they should not depend on current date */}
|
|
44
46
|
<time dateTime={isoDate}>{lastUpdatedString}</time>
|
|
45
47
|
</Wrapper>
|
|
46
48
|
);
|
|
@@ -36,6 +36,9 @@ const Wrapper = styled.div<AdmonitionTypeProps>`
|
|
|
36
36
|
font-weight: var(--admonition-font-weight);
|
|
37
37
|
line-height: var(--admonition-line-height);
|
|
38
38
|
|
|
39
|
+
print-color-adjust: exact;
|
|
40
|
+
-webkit-print-color-adjust: exact;
|
|
41
|
+
|
|
39
42
|
${({ type }) => `
|
|
40
43
|
background-color: var(--admonition-${type}-background-color);
|
|
41
44
|
color: var(--admonition-${type}-text-color);
|
|
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
|
|
2
2
|
import styled, { css } from 'styled-components';
|
|
3
3
|
|
|
4
4
|
import { ClipboardService } from '@theme/utils/ClipboardService';
|
|
5
|
-
import {
|
|
5
|
+
import { useThemeConfig } from '@theme/hooks/useThemeConfig';
|
|
6
6
|
|
|
7
7
|
export type CodeSampleProps = {
|
|
8
8
|
language: string;
|
|
@@ -10,37 +10,28 @@ export type CodeSampleProps = {
|
|
|
10
10
|
rawContent: string;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
const defaultCopyCodeSnippet = {
|
|
14
|
-
hide: false,
|
|
15
|
-
buttonText: 'Copy',
|
|
16
|
-
tooltipText: 'Copy the code snippet',
|
|
17
|
-
toasterText: 'Copied',
|
|
18
|
-
toasterDuration: 1500,
|
|
19
|
-
};
|
|
20
|
-
|
|
21
13
|
export function CodeSample({ rawContent, highlighted, language }: CodeSampleProps): JSX.Element {
|
|
22
14
|
const langClassName = language ? `language-${language}` : '';
|
|
23
|
-
const { copyCodeSnippet } =
|
|
24
|
-
const copyCodeProps = { ...defaultCopyCodeSnippet, ...copyCodeSnippet };
|
|
15
|
+
const { markdown: { copyCodeSnippet = {} } = {} } = useThemeConfig();
|
|
25
16
|
|
|
26
17
|
const [isCopied, setIsCopied] = useState(false);
|
|
27
18
|
|
|
28
19
|
const copyCode = (code: string) => {
|
|
29
20
|
ClipboardService.copyCustom(code);
|
|
30
21
|
setIsCopied(true);
|
|
31
|
-
setTimeout(() => setIsCopied(false),
|
|
22
|
+
setTimeout(() => setIsCopied(false), copyCodeSnippet.toasterDuration);
|
|
32
23
|
};
|
|
33
24
|
|
|
34
25
|
return (
|
|
35
26
|
<Wrapper className="code-sample" data-component-name="Markdown/CodeSample/CodeSample">
|
|
36
|
-
{!
|
|
27
|
+
{!copyCodeSnippet.hide && (
|
|
37
28
|
<CodeSampleButtonContainer onClick={() => copyCode(rawContent)}>
|
|
38
29
|
{!isCopied && (
|
|
39
|
-
<CopyCodeButton title={
|
|
40
|
-
{
|
|
30
|
+
<CopyCodeButton title={copyCodeSnippet.tooltipText || 'Copy to clipboard'}>
|
|
31
|
+
{copyCodeSnippet.buttonText}
|
|
41
32
|
</CopyCodeButton>
|
|
42
33
|
)}
|
|
43
|
-
{isCopied && <DoneIndicator>{
|
|
34
|
+
{isCopied && <DoneIndicator>{copyCodeSnippet.toasterText}</DoneIndicator>}
|
|
44
35
|
</CodeSampleButtonContainer>
|
|
45
36
|
)}
|
|
46
37
|
<pre className={langClassName}>
|
|
@@ -64,6 +55,10 @@ const CopyCodeButton = styled.div`
|
|
|
64
55
|
&:hover {
|
|
65
56
|
cursor: pointer;
|
|
66
57
|
}
|
|
58
|
+
|
|
59
|
+
@media print {
|
|
60
|
+
display: none;
|
|
61
|
+
}
|
|
67
62
|
`;
|
|
68
63
|
|
|
69
64
|
const DoneIndicator = styled.div`
|
|
@@ -150,6 +145,10 @@ const Wrapper = styled.div`
|
|
|
150
145
|
border-radius: var(--code-block-border-radius);
|
|
151
146
|
font-family: var(--code-font-family);
|
|
152
147
|
background-color: var(--code-block-background-color);
|
|
148
|
+
|
|
149
|
+
print-color-adjust: exact;
|
|
150
|
+
-webkit-print-color-adjust: exact;
|
|
151
|
+
|
|
153
152
|
code {
|
|
154
153
|
background-color: transparent;
|
|
155
154
|
border: 0;
|
|
@@ -6,6 +6,7 @@ import { ContainerWrapper } from '@theme/Markdown/ContainerWrapper';
|
|
|
6
6
|
import { PageNavigation } from '@theme/PageNavigation/PageNavigation';
|
|
7
7
|
import { EditPageButton } from '@theme/EditPageButton';
|
|
8
8
|
import { LastUpdated } from '@theme/LastUpdated/LastUpdated';
|
|
9
|
+
import { useThemeConfig } from '@theme/hooks';
|
|
9
10
|
|
|
10
11
|
type MarkdownLayoutProps = {
|
|
11
12
|
tableOfContent: React.ReactNode;
|
|
@@ -13,7 +14,7 @@ type MarkdownLayoutProps = {
|
|
|
13
14
|
editPage?: {
|
|
14
15
|
to: string;
|
|
15
16
|
text: string;
|
|
16
|
-
icon
|
|
17
|
+
icon?: string;
|
|
17
18
|
};
|
|
18
19
|
/** String in ISO format */
|
|
19
20
|
lastModified?: string | null;
|
|
@@ -25,13 +26,18 @@ export function MarkdownLayout({
|
|
|
25
26
|
editPage,
|
|
26
27
|
lastModified,
|
|
27
28
|
}: MarkdownLayoutProps): JSX.Element {
|
|
29
|
+
const { markdown } = useThemeConfig();
|
|
30
|
+
const { editPage: themeEditPage } = markdown || {};
|
|
31
|
+
|
|
32
|
+
const mergedConf = editPage ? { ...editPage, ...themeEditPage } : undefined;
|
|
33
|
+
|
|
28
34
|
return (
|
|
29
35
|
<PageWrapper data-component-name="Markdown/MarkdownLayout">
|
|
30
36
|
<ContainerWrapper withToc={true}>
|
|
31
37
|
<LayoutTop>
|
|
32
38
|
{lastModified && <LastUpdated lastModified={new Date(lastModified)} />}
|
|
33
|
-
{
|
|
34
|
-
<EditPageButton text={
|
|
39
|
+
{mergedConf && (
|
|
40
|
+
<EditPageButton text={mergedConf.text} to={mergedConf.to} icon={mergedConf.icon} />
|
|
35
41
|
)}
|
|
36
42
|
</LayoutTop>
|
|
37
43
|
{markdownWrapper}
|
package/src/Navbar/Navbar.tsx
CHANGED
|
@@ -6,7 +6,7 @@ import { useMobileMenu } from '@theme/hooks/useMobileMenu';
|
|
|
6
6
|
import { MobileNavbarMenuButton } from '@theme/Navbar/MobileNavbarMenuButton';
|
|
7
7
|
import { MobileNavbarMenu } from '@theme/Navbar/MobileNavbarMenu';
|
|
8
8
|
import { ColorModeSwitcher } from '@theme/ColorModeSwitcher/ColorModeSwitcher';
|
|
9
|
-
import {
|
|
9
|
+
import { useThemeConfig } from '@theme/hooks/useThemeConfig';
|
|
10
10
|
import type { ResolvedConfigLinks } from '@theme/types/portal';
|
|
11
11
|
|
|
12
12
|
interface NavbarProps {
|
|
@@ -18,7 +18,7 @@ interface NavbarProps {
|
|
|
18
18
|
|
|
19
19
|
export function Navbar({ menu, logo, search, profile }: NavbarProps): JSX.Element | null {
|
|
20
20
|
const [isOpen, setIsOpen] = useMobileMenu(false);
|
|
21
|
-
const { search: searchSettings, navbar } =
|
|
21
|
+
const { search: searchSettings, navbar } = useThemeConfig();
|
|
22
22
|
const hideSearch =
|
|
23
23
|
searchSettings?.hide || (searchSettings?.placement && searchSettings?.placement !== 'navbar');
|
|
24
24
|
|
|
@@ -28,7 +28,7 @@ export function NavbarItem({ navItem, className }: NavbarItemProps): JSX.Element
|
|
|
28
28
|
data-component-name="Navbar/NavbarItem"
|
|
29
29
|
className={className}
|
|
30
30
|
>
|
|
31
|
-
<NavbarLink to={item.link} active={isActive}>
|
|
31
|
+
<NavbarLink to={item.link} external={item.external} target={item.target} active={isActive}>
|
|
32
32
|
<NavbarLabel>{item.label}</NavbarLabel>
|
|
33
33
|
</NavbarLink>
|
|
34
34
|
</NavbarMenuItem>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
|
|
4
4
|
import { useSidebarSiblingsData } from '@portal/hooks';
|
|
5
5
|
import { Button } from '@theme/Button/Button';
|
|
6
|
-
import {
|
|
6
|
+
import { useThemeConfig } from '@theme/hooks/useThemeConfig';
|
|
7
7
|
import type { ResolvedNavItemWithLink } from '@theme/types/portal';
|
|
8
8
|
|
|
9
9
|
interface NextPageType {
|
|
@@ -12,13 +12,16 @@ interface NextPageType {
|
|
|
12
12
|
|
|
13
13
|
export function NextPageLink(): JSX.Element {
|
|
14
14
|
const { nextPage }: NextPageType = useSidebarSiblingsData() || {};
|
|
15
|
-
const { navigation } =
|
|
15
|
+
const { navigation } = useThemeConfig();
|
|
16
16
|
|
|
17
|
-
if (!nextPage || navigation?.
|
|
17
|
+
if (!nextPage || navigation?.nextPageLink?.hide) {
|
|
18
18
|
return <div> </div>;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const label = navigation?.nextPageLink?.label ||
|
|
21
|
+
const label = (navigation?.nextPageLink?.label || 'Next to {label}').replace(
|
|
22
|
+
'{label}',
|
|
23
|
+
nextPage.label || nextPage.routeSlug || '',
|
|
24
|
+
);
|
|
22
25
|
|
|
23
26
|
return (
|
|
24
27
|
<StyledButton
|
|
@@ -3,12 +3,12 @@ import styled from 'styled-components';
|
|
|
3
3
|
|
|
4
4
|
import { PreviousPageLink } from '@theme/PageNavigation/PreviousPageLink';
|
|
5
5
|
import { NextPageLink } from '@theme/PageNavigation/NextPageLink';
|
|
6
|
-
import {
|
|
6
|
+
import { useThemeConfig } from '@theme/hooks/useThemeConfig';
|
|
7
7
|
|
|
8
8
|
export function PageNavigation(): JSX.Element | null {
|
|
9
|
-
const { navigation } =
|
|
9
|
+
const { navigation } = useThemeConfig();
|
|
10
10
|
|
|
11
|
-
if (navigation?.hide) {
|
|
11
|
+
if (navigation?.prevPageLink?.hide && navigation?.nextPageLink?.hide) {
|
|
12
12
|
return null;
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -24,4 +24,8 @@ const PageNavigationWrapper = styled.div`
|
|
|
24
24
|
display: flex;
|
|
25
25
|
justify-content: space-between;
|
|
26
26
|
margin: 25px 0;
|
|
27
|
+
|
|
28
|
+
@media print {
|
|
29
|
+
display: none;
|
|
30
|
+
}
|
|
27
31
|
`;
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
|
|
4
4
|
import { useSidebarSiblingsData } from '@portal/hooks';
|
|
5
|
-
import {
|
|
5
|
+
import { useThemeConfig } from '@theme/hooks/useThemeConfig';
|
|
6
6
|
import { Button } from '@theme/Button/Button';
|
|
7
7
|
import type { ResolvedNavItemWithLink } from '@theme/types/portal';
|
|
8
8
|
|
|
@@ -12,13 +12,16 @@ interface PreviousPageType {
|
|
|
12
12
|
|
|
13
13
|
export function PreviousPageLink(): JSX.Element {
|
|
14
14
|
const { prevPage }: PreviousPageType = useSidebarSiblingsData() || {};
|
|
15
|
-
const { navigation } =
|
|
15
|
+
const { navigation } = useThemeConfig();
|
|
16
16
|
|
|
17
|
-
if (!prevPage || navigation?.
|
|
17
|
+
if (!prevPage || navigation?.prevPageLink?.hide) {
|
|
18
18
|
return <div> </div>;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const label = navigation?.prevPageLink?.label ||
|
|
21
|
+
const label = (navigation?.prevPageLink?.label || 'Back to {label}').replace(
|
|
22
|
+
'{label}',
|
|
23
|
+
prevPage.label || prevPage.routeSlug || '',
|
|
24
|
+
);
|
|
22
25
|
|
|
23
26
|
return (
|
|
24
27
|
<StyledButton
|