@redocly/theme 0.32.1 → 0.32.3
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/components/Catalog/CatalogCard.js +3 -1
- package/lib/components/CodeBlock/CodeBlock.d.ts +12 -1
- package/lib/components/CodeBlock/CodeBlock.js +3 -3
- package/lib/components/CodeBlock/CodeBlockContainer.d.ts +2 -0
- package/lib/components/CodeBlock/CodeBlockContainer.js +96 -84
- package/lib/components/CodeBlock/CodeBlockControls.d.ts +3 -1
- package/lib/components/CodeBlock/CodeBlockControls.js +36 -2
- package/lib/components/Profile/LoginLink.js +6 -3
- package/lib/icons/FileIcon/FileIcon.d.ts +1 -0
- package/lib/icons/FileIcon/FileIcon.js +5 -1
- package/package.json +1 -1
- package/src/components/Catalog/CatalogCard.tsx +3 -1
- package/src/components/CodeBlock/CodeBlock.tsx +21 -2
- package/src/components/CodeBlock/CodeBlockContainer.tsx +99 -85
- package/src/components/CodeBlock/CodeBlockControls.tsx +60 -2
- package/src/components/Profile/LoginLink.tsx +8 -4
- package/src/icons/FileIcon/FileIcon.tsx +5 -0
|
@@ -79,7 +79,8 @@ const StyledCard = styled_components_1.default.div.attrs({ 'data-cy': 'Catalog/C
|
|
|
79
79
|
font-size: var(--catalog-card-font-size);
|
|
80
80
|
font-weight: var(--catalog-card-font-weight);
|
|
81
81
|
background-color: var(--catalog-card-background-color);
|
|
82
|
-
border: var(--catalog-card-border-width) var(--catalog-card-border-style)
|
|
82
|
+
border: var(--catalog-card-border-width) var(--catalog-card-border-style)
|
|
83
|
+
var(--catalog-card-border-color);
|
|
83
84
|
transition: all 0.2s ease-in-out;
|
|
84
85
|
border-radius: var(--catalog-card-border-radius);
|
|
85
86
|
cursor: pointer;
|
|
@@ -98,6 +99,7 @@ const StyledCard = styled_components_1.default.div.attrs({ 'data-cy': 'Catalog/C
|
|
|
98
99
|
fill: var(--catalog-card-icon-hover-color);
|
|
99
100
|
}
|
|
100
101
|
}
|
|
102
|
+
}
|
|
101
103
|
`;
|
|
102
104
|
const CardTitle = styled_components_1.default.h4 `
|
|
103
105
|
color: var(--catalog-card-title-color);
|
|
@@ -7,10 +7,14 @@ export interface CodeBlockProps {
|
|
|
7
7
|
header?: CodeBlockControlsProps;
|
|
8
8
|
dataTestId?: string;
|
|
9
9
|
className?: string;
|
|
10
|
+
tabs?: FileTabs;
|
|
10
11
|
withLineNumbers?: boolean;
|
|
11
12
|
startLineNumber?: number;
|
|
12
13
|
highlightedHtml?: string;
|
|
14
|
+
skipHighlight?: boolean;
|
|
13
15
|
codeBlockRef?: (instance: HTMLPreElement | null) => void;
|
|
16
|
+
codeBlockMaxHeight?: string;
|
|
17
|
+
hideCodeColors?: boolean;
|
|
14
18
|
}
|
|
15
19
|
export interface Sample {
|
|
16
20
|
lang: string;
|
|
@@ -19,6 +23,13 @@ export interface Sample {
|
|
|
19
23
|
export type UnstableExternalCodeSample = Sample & {
|
|
20
24
|
get: (source: ExternalSource) => string;
|
|
21
25
|
};
|
|
26
|
+
export type FileTabs = {
|
|
27
|
+
files: {
|
|
28
|
+
name: string;
|
|
29
|
+
}[];
|
|
30
|
+
handleTabSwitch: (name: string) => void;
|
|
31
|
+
activeTabName: string;
|
|
32
|
+
};
|
|
22
33
|
export interface ExternalSource {
|
|
23
34
|
sample: UnstableExternalCodeSample;
|
|
24
35
|
exampleName?: string;
|
|
@@ -26,4 +37,4 @@ export interface ExternalSource {
|
|
|
26
37
|
properties?: any;
|
|
27
38
|
operation?: any;
|
|
28
39
|
}
|
|
29
|
-
export declare function CodeBlock({ lang, source, externalSource, header, dataTestId, codeBlockRef, highlightedHtml, withLineNumbers, startLineNumber, className, }: CodeBlockProps): JSX.Element;
|
|
40
|
+
export declare function CodeBlock({ lang, source, externalSource, header, dataTestId, codeBlockRef, highlightedHtml, withLineNumbers, startLineNumber, className, codeBlockMaxHeight, tabs, hideCodeColors, }: CodeBlockProps): JSX.Element;
|
|
@@ -32,7 +32,7 @@ const styled_components_1 = __importDefault(require("styled-components"));
|
|
|
32
32
|
const utils_1 = require("../../utils");
|
|
33
33
|
const Feedback_1 = require("../../components/Feedback");
|
|
34
34
|
const CodeBlock_1 = require("../../components/CodeBlock");
|
|
35
|
-
function CodeBlock({ lang, source, externalSource, header, dataTestId = 'source-code', codeBlockRef, highlightedHtml, withLineNumbers, startLineNumber, className, }) {
|
|
35
|
+
function CodeBlock({ lang, source, externalSource, header, dataTestId = 'source-code', codeBlockRef, highlightedHtml, withLineNumbers, startLineNumber, className, codeBlockMaxHeight, tabs, hideCodeColors, }) {
|
|
36
36
|
var _a;
|
|
37
37
|
const [sourceCode, setSourceCode] = (0, react_1.useState)(source !== null && source !== void 0 ? source : '');
|
|
38
38
|
const highlightedCode = highlightedHtml || (0, utils_1.highlight)(sourceCode, lang);
|
|
@@ -53,13 +53,13 @@ function CodeBlock({ lang, source, externalSource, header, dataTestId = 'source-
|
|
|
53
53
|
controls.copy.data = sourceCode;
|
|
54
54
|
}
|
|
55
55
|
return (react_1.default.createElement(Wrapper, { "data-component-name": "CodeBlock/CodeBlock", className: className },
|
|
56
|
-
react_1.default.createElement(CodeBlock_1.CodeBlockControls, { className: header === null || header === void 0 ? void 0 : header.className, title: header === null || header === void 0 ? void 0 : header.title, controls: controls }),
|
|
56
|
+
react_1.default.createElement(CodeBlock_1.CodeBlockControls, { tabs: tabs, className: header === null || header === void 0 ? void 0 : header.className, title: header === null || header === void 0 ? void 0 : header.title, controls: controls }),
|
|
57
57
|
react_1.default.createElement(ContainerWrapper, null,
|
|
58
58
|
react_1.default.createElement(CodeBlock_1.CodeBlockContainer, { ref: codeBlockRef, className: withLineNumbers ? 'line-numbers' : '', dangerouslySetInnerHTML: {
|
|
59
59
|
__html: withLineNumbers
|
|
60
60
|
? (0, utils_1.addLineNumbers)(highlightedCode, startLineNumber)
|
|
61
61
|
: highlightedCode,
|
|
62
|
-
}, "data-cy": dataTestId, withControls: true }),
|
|
62
|
+
}, "data-cy": dataTestId, hideCodeColors: hideCodeColors, maxHeight: codeBlockMaxHeight, withControls: true }),
|
|
63
63
|
reportDialog.visible && (react_1.default.createElement(Feedback_1.ReportDialog, Object.assign({}, reportDialog.props, { location: sourceCode, lang: lang }))))));
|
|
64
64
|
}
|
|
65
65
|
exports.CodeBlock = CodeBlock;
|
|
@@ -32,7 +32,6 @@ exports.CodeBlockContainer = styled_components_1.default.pre.attrs(({ className
|
|
|
32
32
|
})) `
|
|
33
33
|
&& {
|
|
34
34
|
overflow-x: auto;
|
|
35
|
-
max-height: var(--code-block-max-height);
|
|
36
35
|
font-family: var(--code-block-font-family);
|
|
37
36
|
line-height: var(--code-block-line-height);
|
|
38
37
|
font-weight: var(--code-block-font-weight);
|
|
@@ -42,7 +41,7 @@ exports.CodeBlockContainer = styled_components_1.default.pre.attrs(({ className
|
|
|
42
41
|
color: var(--code-block-text-color);
|
|
43
42
|
font-size: var(--code-block-font-size);
|
|
44
43
|
white-space: var(--code-wrap, pre);
|
|
45
|
-
max-height: var(--code-block-max-height, 600px);
|
|
44
|
+
max-height: ${({ maxHeight }) => maxHeight ? maxHeight : 'var(--code-block-max-height, 600px);'};
|
|
46
45
|
word-break: var(--code-block-word-break, initial);
|
|
47
46
|
|
|
48
47
|
${(withControls) => withControls
|
|
@@ -56,93 +55,106 @@ exports.CodeBlockContainer = styled_components_1.default.pre.attrs(({ className
|
|
|
56
55
|
border-radius: var(--code-block-border-radius);
|
|
57
56
|
border: 1px solid var(--code-block-border-color);
|
|
58
57
|
`}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
*/
|
|
63
|
-
code[class*='language-'],
|
|
64
|
-
pre[class*='language-'] {
|
|
65
|
-
text-shadow: 0 -0.1em 0.2em black;
|
|
66
|
-
text-align: left;
|
|
67
|
-
word-spacing: normal;
|
|
68
|
-
word-break: normal;
|
|
69
|
-
word-wrap: normal;
|
|
70
|
-
line-height: 1.5;
|
|
71
|
-
|
|
72
|
-
-moz-tab-size: 4;
|
|
73
|
-
-o-tab-size: 4;
|
|
74
|
-
tab-size: 4;
|
|
75
|
-
|
|
76
|
-
-webkit-hyphens: none;
|
|
77
|
-
-moz-hyphens: none;
|
|
78
|
-
-ms-hyphens: none;
|
|
79
|
-
hyphens: none;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
@media print {
|
|
58
|
+
/**
|
|
59
|
+
* Based on prism-dark.css
|
|
60
|
+
*/
|
|
83
61
|
code[class*='language-'],
|
|
84
62
|
pre[class*='language-'] {
|
|
85
|
-
text-shadow:
|
|
63
|
+
text-shadow: 0 -0.1em 0.2em black;
|
|
64
|
+
text-align: left;
|
|
65
|
+
word-spacing: normal;
|
|
66
|
+
word-break: normal;
|
|
67
|
+
word-wrap: normal;
|
|
68
|
+
line-height: 1.5;
|
|
69
|
+
|
|
70
|
+
-moz-tab-size: 4;
|
|
71
|
+
-o-tab-size: 4;
|
|
72
|
+
tab-size: 4;
|
|
73
|
+
|
|
74
|
+
-webkit-hyphens: none;
|
|
75
|
+
-moz-hyphens: none;
|
|
76
|
+
-ms-hyphens: none;
|
|
77
|
+
hyphens: none;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@media print {
|
|
81
|
+
code[class*='language-'],
|
|
82
|
+
pre[class*='language-'] {
|
|
83
|
+
text-shadow: none;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* Code blocks */
|
|
88
|
+
|
|
89
|
+
pre[class*='language-'] {
|
|
90
|
+
padding: 1em;
|
|
91
|
+
margin: 0.5em 0;
|
|
92
|
+
overflow: auto;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.token.punctuation {
|
|
96
|
+
opacity: 1;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.namespace {
|
|
100
|
+
opacity: 0.7;
|
|
86
101
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
.token.selector,
|
|
105
|
-
.token.attr-name,
|
|
106
|
-
.token.string,
|
|
107
|
-
.token.char,
|
|
108
|
-
.token.builtin,
|
|
109
|
-
.token.inserted {
|
|
110
|
-
& + a,
|
|
111
|
-
& + a:visited {
|
|
112
|
-
color: var(--code-block-tokens-link-color);
|
|
113
|
-
text-decoration: underline;
|
|
102
|
+
|
|
103
|
+
.token.selector,
|
|
104
|
+
.token.attr-name,
|
|
105
|
+
.token.string,
|
|
106
|
+
.token.char,
|
|
107
|
+
.token.builtin,
|
|
108
|
+
.token.inserted {
|
|
109
|
+
& + a,
|
|
110
|
+
& + a:visited {
|
|
111
|
+
color: var(--code-block-tokens-link-color);
|
|
112
|
+
text-decoration: underline;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.token.property.string {
|
|
117
|
+
color: var(--code-block-tokens-property-string-color);
|
|
114
118
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
.token.important,
|
|
122
|
-
.token.bold {
|
|
123
|
-
font-weight: bold;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
.token.italic {
|
|
127
|
-
font-style: italic;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
.token.entity {
|
|
131
|
-
cursor: help;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
.code-line {
|
|
135
|
-
&:before {
|
|
136
|
-
content: attr(data-line-number);
|
|
137
|
-
display: inline-block;
|
|
138
|
-
min-width: 2em;
|
|
139
|
-
padding-right: 0.8em;
|
|
140
|
-
text-align: right;
|
|
141
|
-
pointer-events: none;
|
|
142
|
-
user-select: none;
|
|
119
|
+
|
|
120
|
+
.token.important,
|
|
121
|
+
.token.bold {
|
|
122
|
+
font-weight: bold;
|
|
143
123
|
}
|
|
144
|
-
}
|
|
145
124
|
|
|
146
|
-
|
|
125
|
+
.token.italic {
|
|
126
|
+
font-style: italic;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.token.entity {
|
|
130
|
+
cursor: help;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.code-line {
|
|
134
|
+
&:before {
|
|
135
|
+
content: attr(data-line-number);
|
|
136
|
+
display: inline-block;
|
|
137
|
+
min-width: 2em;
|
|
138
|
+
padding-right: 0.8em;
|
|
139
|
+
text-align: right;
|
|
140
|
+
pointer-events: none;
|
|
141
|
+
user-select: none;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.highlighted {
|
|
146
|
+
background: var(--bg-overlay);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
${(0, utils_1.generateCodeBlockTokens)()}
|
|
150
|
+
|
|
151
|
+
${({ hideCodeColors }) => hideCodeColors &&
|
|
152
|
+
(0, styled_components_1.css) `
|
|
153
|
+
.code-line:not(.highlighted),
|
|
154
|
+
.code-line:not(.highlighted) > span,
|
|
155
|
+
.code-line:not(.highlighted) > span > span {
|
|
156
|
+
color: grey;
|
|
157
|
+
}
|
|
158
|
+
`}
|
|
147
159
|
`;
|
|
148
160
|
//# sourceMappingURL=CodeBlockContainer.js.map
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { FileTabs } from '../../components/CodeBlock';
|
|
2
3
|
export interface CodeBlockControlsProps {
|
|
3
4
|
children?: React.ReactNode;
|
|
4
5
|
className?: string;
|
|
5
6
|
title?: React.ReactNode | string;
|
|
6
7
|
controls?: ControlItems;
|
|
8
|
+
tabs?: FileTabs;
|
|
7
9
|
}
|
|
8
10
|
interface ControlItems {
|
|
9
11
|
copy?: CopyControlProps;
|
|
@@ -29,5 +31,5 @@ interface CopyControlProps extends ControlProps {
|
|
|
29
31
|
handleOutside?: boolean;
|
|
30
32
|
}
|
|
31
33
|
export type ControlItemType = 'text' | 'icon';
|
|
32
|
-
export declare function CodeBlockControls({ children, className, title, controls, }: CodeBlockControlsProps): JSX.Element | null;
|
|
34
|
+
export declare function CodeBlockControls({ children, className, title, controls, tabs, }: CodeBlockControlsProps): JSX.Element | null;
|
|
33
35
|
export {};
|
|
@@ -11,15 +11,27 @@ const CopyButton_1 = require("../../components/CopyButton/CopyButton");
|
|
|
11
11
|
const icons_1 = require("../../icons");
|
|
12
12
|
const hooks_1 = require("../../hooks");
|
|
13
13
|
const telemetry_1 = require("../../mocks/telemetry");
|
|
14
|
-
|
|
14
|
+
const components_1 = require("../../components");
|
|
15
|
+
function CodeBlockControls({ children, className, title, controls, tabs, }) {
|
|
15
16
|
var _a, _b, _c, _d, _e, _f;
|
|
16
17
|
const { codeSnippet } = (0, hooks_1.useThemeConfig)();
|
|
17
18
|
const controlsType = (codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.elementFormat) || 'icon';
|
|
18
19
|
const { copy, expand, collapse, select, deselect, report } = controls
|
|
19
20
|
? controls
|
|
20
21
|
: { copy: null, expand: null, collapse: null, select: null, deselect: null, report: null };
|
|
22
|
+
const FileTabs = () => {
|
|
23
|
+
return (react_1.default.createElement(CodeTabsBlock, null, tabs === null || tabs === void 0 ? void 0 : tabs.files.map(({ name }) => {
|
|
24
|
+
const isActive = name === tabs.activeTabName;
|
|
25
|
+
return (react_1.default.createElement(CodeTabButton, { active: isActive, key: name, onClick: () => {
|
|
26
|
+
tabs.handleTabSwitch(name);
|
|
27
|
+
} },
|
|
28
|
+
react_1.default.createElement(icons_1.SmallFileIcon, null),
|
|
29
|
+
name));
|
|
30
|
+
})));
|
|
31
|
+
};
|
|
21
32
|
const defaultControls = controls ? (react_1.default.createElement(react_1.default.Fragment, null,
|
|
22
|
-
react_1.default.createElement(Title, null, title),
|
|
33
|
+
title && react_1.default.createElement(Title, null, title),
|
|
34
|
+
tabs && react_1.default.createElement(FileTabs, null),
|
|
23
35
|
react_1.default.createElement(ControlsWrapper, null,
|
|
24
36
|
report && ((_a = report === null || report === void 0 ? void 0 : report.props) === null || _a === void 0 ? void 0 : _a.visible) ? (react_1.default.createElement(CodeBlock_1.CodeBlockControlButton, Object.assign({ "data-cy": "report-button", "data-testid": "report-button", asIcon: controlsType === 'icon', title: (_b = report.props) === null || _b === void 0 ? void 0 : _b.tooltip }, report.props), controlsType === 'icon' ? react_1.default.createElement(icons_1.ReportIcon, null) : ((_c = report.props) === null || _c === void 0 ? void 0 : _c.buttonText) || 'Report')) : null,
|
|
25
37
|
expand && !((_d = codeSnippet === null || codeSnippet === void 0 ? void 0 : codeSnippet.expand) === null || _d === void 0 ? void 0 : _d.hide) ? (react_1.default.createElement(CodeBlock_1.CodeBlockControlButton, { "data-cy": "expand-all", "data-testid": "expand-all", asIcon: controlsType === 'icon', onClick: expand === null || expand === void 0 ? void 0 : expand.onClick, title: (expand === null || expand === void 0 ? void 0 : expand.tooltipText) || 'Expand all' }, controlsType === 'icon' ? react_1.default.createElement(icons_1.ExpandIcon, null) : (expand === null || expand === void 0 ? void 0 : expand.label) ? expand.label : 'Expand all')) : null,
|
|
@@ -60,4 +72,26 @@ const ControlsWrapper = styled_components_1.default.div `
|
|
|
60
72
|
opacity: 1;
|
|
61
73
|
}
|
|
62
74
|
`;
|
|
75
|
+
const CodeTabsBlock = styled_components_1.default.div `
|
|
76
|
+
background: transparent;
|
|
77
|
+
border-radius: var(--global-border-radius) 0;
|
|
78
|
+
display: flex;
|
|
79
|
+
flex-wrap: wrap;
|
|
80
|
+
margin: 12px 0;
|
|
81
|
+
justify-content: flex-start;
|
|
82
|
+
flex-direction: row;
|
|
83
|
+
padding: 0 12px;
|
|
84
|
+
`;
|
|
85
|
+
const CodeTabButton = (0, styled_components_1.default)(components_1.Button) `
|
|
86
|
+
border: none;
|
|
87
|
+
padding: 8px 12px;
|
|
88
|
+
background: ${({ active }) => (active ? 'var(--color-primary-base)' : 'transparent')};
|
|
89
|
+
color: ${({ active }) => (active ? '#fff' : 'var(--text-base)')};
|
|
90
|
+
font-size: var(--font-size-sm);
|
|
91
|
+
|
|
92
|
+
&:hover {
|
|
93
|
+
background: var(--color-primary-bg-hover);
|
|
94
|
+
border: none;
|
|
95
|
+
}
|
|
96
|
+
`;
|
|
63
97
|
//# sourceMappingURL=CodeBlockControls.js.map
|
|
@@ -12,9 +12,11 @@ const telemetry_1 = require("../../mocks/telemetry");
|
|
|
12
12
|
function LoginLink({ href }) {
|
|
13
13
|
const { userProfile } = (0, useThemeConfig_1.useThemeConfig)();
|
|
14
14
|
const { translate } = (0, hooks_1.useTranslate)();
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const handleLoginClick = () => {
|
|
16
|
+
telemetry_1.telemetry.send('login_button_clicked', {});
|
|
17
|
+
window.location.href = href;
|
|
18
|
+
};
|
|
19
|
+
return (react_1.default.createElement(StyledLink, { "data-translation-key": "theme.profile.login", onClick: () => handleLoginClick(), "data-cy": href }, translate('theme.profile.login', (userProfile === null || userProfile === void 0 ? void 0 : userProfile.loginLabel) || 'Login')));
|
|
18
20
|
}
|
|
19
21
|
exports.LoginLink = LoginLink;
|
|
20
22
|
const StyledLink = styled_components_1.default.a.attrs(() => ({
|
|
@@ -30,5 +32,6 @@ const StyledLink = styled_components_1.default.a.attrs(() => ({
|
|
|
30
32
|
&:hover {
|
|
31
33
|
color: var(--navbar-item-hover-text-color);
|
|
32
34
|
}
|
|
35
|
+
cursor: pointer;
|
|
33
36
|
`;
|
|
34
37
|
//# sourceMappingURL=LoginLink.js.map
|
|
@@ -3,4 +3,5 @@ interface IconProps {
|
|
|
3
3
|
className?: string;
|
|
4
4
|
}
|
|
5
5
|
export declare const FileIcon: import("styled-components").StyledComponent<({ className }: IconProps) => React.JSX.Element, any, {}, never>;
|
|
6
|
+
export declare const SmallFileIcon: import("styled-components").StyledComponent<({ className }: IconProps) => React.JSX.Element, any, {}, never>;
|
|
6
7
|
export {};
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.FileIcon = void 0;
|
|
6
|
+
exports.SmallFileIcon = exports.FileIcon = void 0;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
8
|
const styled_components_1 = __importDefault(require("styled-components"));
|
|
9
9
|
const Icon = ({ className }) => (react_1.default.createElement("svg", { "data-component-name": "icons/FileIcon", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: className },
|
|
@@ -14,4 +14,8 @@ exports.FileIcon = (0, styled_components_1.default)(Icon) `
|
|
|
14
14
|
height: 1.3em;
|
|
15
15
|
vertical-align: middle;
|
|
16
16
|
`;
|
|
17
|
+
exports.SmallFileIcon = (0, styled_components_1.default)(Icon) `
|
|
18
|
+
width: 1em;
|
|
19
|
+
height: 1em;
|
|
20
|
+
`;
|
|
17
21
|
//# sourceMappingURL=FileIcon.js.map
|
package/package.json
CHANGED
|
@@ -76,7 +76,8 @@ const StyledCard = styled.div.attrs({ 'data-cy': 'Catalog/CatalogCard' })`
|
|
|
76
76
|
font-size: var(--catalog-card-font-size);
|
|
77
77
|
font-weight: var(--catalog-card-font-weight);
|
|
78
78
|
background-color: var(--catalog-card-background-color);
|
|
79
|
-
border: var(--catalog-card-border-width) var(--catalog-card-border-style)
|
|
79
|
+
border: var(--catalog-card-border-width) var(--catalog-card-border-style)
|
|
80
|
+
var(--catalog-card-border-color);
|
|
80
81
|
transition: all 0.2s ease-in-out;
|
|
81
82
|
border-radius: var(--catalog-card-border-radius);
|
|
82
83
|
cursor: pointer;
|
|
@@ -95,6 +96,7 @@ const StyledCard = styled.div.attrs({ 'data-cy': 'Catalog/CatalogCard' })`
|
|
|
95
96
|
fill: var(--catalog-card-icon-hover-color);
|
|
96
97
|
}
|
|
97
98
|
}
|
|
99
|
+
}
|
|
98
100
|
`;
|
|
99
101
|
|
|
100
102
|
const CardTitle = styled.h4`
|
|
@@ -14,11 +14,14 @@ export interface CodeBlockProps {
|
|
|
14
14
|
header?: CodeBlockControlsProps;
|
|
15
15
|
dataTestId?: string;
|
|
16
16
|
className?: string;
|
|
17
|
-
|
|
17
|
+
tabs?: FileTabs;
|
|
18
18
|
withLineNumbers?: boolean;
|
|
19
19
|
startLineNumber?: number;
|
|
20
20
|
highlightedHtml?: string;
|
|
21
|
+
skipHighlight?: boolean;
|
|
21
22
|
codeBlockRef?: (instance: HTMLPreElement | null) => void;
|
|
23
|
+
codeBlockMaxHeight?: string;
|
|
24
|
+
hideCodeColors?: boolean;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
export interface Sample {
|
|
@@ -30,6 +33,12 @@ export type UnstableExternalCodeSample = Sample & {
|
|
|
30
33
|
get: (source: ExternalSource) => string;
|
|
31
34
|
};
|
|
32
35
|
|
|
36
|
+
export type FileTabs = {
|
|
37
|
+
files: { name: string }[];
|
|
38
|
+
handleTabSwitch: (name: string) => void;
|
|
39
|
+
activeTabName: string;
|
|
40
|
+
};
|
|
41
|
+
|
|
33
42
|
export interface ExternalSource {
|
|
34
43
|
sample: UnstableExternalCodeSample;
|
|
35
44
|
exampleName?: string;
|
|
@@ -49,6 +58,9 @@ export function CodeBlock({
|
|
|
49
58
|
withLineNumbers,
|
|
50
59
|
startLineNumber,
|
|
51
60
|
className,
|
|
61
|
+
codeBlockMaxHeight,
|
|
62
|
+
tabs,
|
|
63
|
+
hideCodeColors,
|
|
52
64
|
}: CodeBlockProps): JSX.Element {
|
|
53
65
|
const [sourceCode, setSourceCode] = useState<string>(source ?? '');
|
|
54
66
|
|
|
@@ -78,7 +90,12 @@ export function CodeBlock({
|
|
|
78
90
|
|
|
79
91
|
return (
|
|
80
92
|
<Wrapper data-component-name="CodeBlock/CodeBlock" className={className}>
|
|
81
|
-
<CodeBlockControls
|
|
93
|
+
<CodeBlockControls
|
|
94
|
+
tabs={tabs}
|
|
95
|
+
className={header?.className}
|
|
96
|
+
title={header?.title}
|
|
97
|
+
controls={controls}
|
|
98
|
+
/>
|
|
82
99
|
<ContainerWrapper>
|
|
83
100
|
<CodeBlockContainer
|
|
84
101
|
ref={codeBlockRef}
|
|
@@ -89,6 +106,8 @@ export function CodeBlock({
|
|
|
89
106
|
: highlightedCode,
|
|
90
107
|
}}
|
|
91
108
|
data-cy={dataTestId}
|
|
109
|
+
hideCodeColors={hideCodeColors}
|
|
110
|
+
maxHeight={codeBlockMaxHeight}
|
|
92
111
|
withControls={true}
|
|
93
112
|
/>
|
|
94
113
|
{reportDialog.visible && (
|
|
@@ -5,10 +5,9 @@ import { generateCodeBlockTokens } from '@theme/utils';
|
|
|
5
5
|
export const CodeBlockContainer = styled.pre.attrs<{ className?: string }>(({ className }) => ({
|
|
6
6
|
'data-component-name': 'CodeBlock/CodeBlockContainer',
|
|
7
7
|
className,
|
|
8
|
-
}))<{ withControls?: boolean }>`
|
|
8
|
+
}))<{ withControls?: boolean; maxHeight?: string; hideCodeColors?: boolean }>`
|
|
9
9
|
&& {
|
|
10
10
|
overflow-x: auto;
|
|
11
|
-
max-height: var(--code-block-max-height);
|
|
12
11
|
font-family: var(--code-block-font-family);
|
|
13
12
|
line-height: var(--code-block-line-height);
|
|
14
13
|
font-weight: var(--code-block-font-weight);
|
|
@@ -18,7 +17,8 @@ export const CodeBlockContainer = styled.pre.attrs<{ className?: string }>(({ cl
|
|
|
18
17
|
color: var(--code-block-text-color);
|
|
19
18
|
font-size: var(--code-block-font-size);
|
|
20
19
|
white-space: var(--code-wrap, pre);
|
|
21
|
-
max-height:
|
|
20
|
+
max-height: ${({ maxHeight }) =>
|
|
21
|
+
maxHeight ? maxHeight : 'var(--code-block-max-height, 600px);'};
|
|
22
22
|
word-break: var(--code-block-word-break, initial);
|
|
23
23
|
|
|
24
24
|
${(withControls) =>
|
|
@@ -33,92 +33,106 @@ export const CodeBlockContainer = styled.pre.attrs<{ className?: string }>(({ cl
|
|
|
33
33
|
border-radius: var(--code-block-border-radius);
|
|
34
34
|
border: 1px solid var(--code-block-border-color);
|
|
35
35
|
`}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
*/
|
|
40
|
-
code[class*='language-'],
|
|
41
|
-
pre[class*='language-'] {
|
|
42
|
-
text-shadow: 0 -0.1em 0.2em black;
|
|
43
|
-
text-align: left;
|
|
44
|
-
word-spacing: normal;
|
|
45
|
-
word-break: normal;
|
|
46
|
-
word-wrap: normal;
|
|
47
|
-
line-height: 1.5;
|
|
48
|
-
|
|
49
|
-
-moz-tab-size: 4;
|
|
50
|
-
-o-tab-size: 4;
|
|
51
|
-
tab-size: 4;
|
|
52
|
-
|
|
53
|
-
-webkit-hyphens: none;
|
|
54
|
-
-moz-hyphens: none;
|
|
55
|
-
-ms-hyphens: none;
|
|
56
|
-
hyphens: none;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
@media print {
|
|
36
|
+
/**
|
|
37
|
+
* Based on prism-dark.css
|
|
38
|
+
*/
|
|
60
39
|
code[class*='language-'],
|
|
61
40
|
pre[class*='language-'] {
|
|
62
|
-
text-shadow:
|
|
41
|
+
text-shadow: 0 -0.1em 0.2em black;
|
|
42
|
+
text-align: left;
|
|
43
|
+
word-spacing: normal;
|
|
44
|
+
word-break: normal;
|
|
45
|
+
word-wrap: normal;
|
|
46
|
+
line-height: 1.5;
|
|
47
|
+
|
|
48
|
+
-moz-tab-size: 4;
|
|
49
|
+
-o-tab-size: 4;
|
|
50
|
+
tab-size: 4;
|
|
51
|
+
|
|
52
|
+
-webkit-hyphens: none;
|
|
53
|
+
-moz-hyphens: none;
|
|
54
|
+
-ms-hyphens: none;
|
|
55
|
+
hyphens: none;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@media print {
|
|
59
|
+
code[class*='language-'],
|
|
60
|
+
pre[class*='language-'] {
|
|
61
|
+
text-shadow: none;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* Code blocks */
|
|
66
|
+
|
|
67
|
+
pre[class*='language-'] {
|
|
68
|
+
padding: 1em;
|
|
69
|
+
margin: 0.5em 0;
|
|
70
|
+
overflow: auto;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.token.punctuation {
|
|
74
|
+
opacity: 1;
|
|
63
75
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
.token.selector,
|
|
82
|
-
.token.attr-name,
|
|
83
|
-
.token.string,
|
|
84
|
-
.token.char,
|
|
85
|
-
.token.builtin,
|
|
86
|
-
.token.inserted {
|
|
87
|
-
& + a,
|
|
88
|
-
& + a:visited {
|
|
89
|
-
color: var(--code-block-tokens-link-color);
|
|
90
|
-
text-decoration: underline;
|
|
76
|
+
|
|
77
|
+
.namespace {
|
|
78
|
+
opacity: 0.7;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.token.selector,
|
|
82
|
+
.token.attr-name,
|
|
83
|
+
.token.string,
|
|
84
|
+
.token.char,
|
|
85
|
+
.token.builtin,
|
|
86
|
+
.token.inserted {
|
|
87
|
+
& + a,
|
|
88
|
+
& + a:visited {
|
|
89
|
+
color: var(--code-block-tokens-link-color);
|
|
90
|
+
text-decoration: underline;
|
|
91
|
+
}
|
|
91
92
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
93
|
+
|
|
94
|
+
.token.property.string {
|
|
95
|
+
color: var(--code-block-tokens-property-string-color);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.token.important,
|
|
99
|
+
.token.bold {
|
|
100
|
+
font-weight: bold;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.token.italic {
|
|
104
|
+
font-style: italic;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.token.entity {
|
|
108
|
+
cursor: help;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.code-line {
|
|
112
|
+
&:before {
|
|
113
|
+
content: attr(data-line-number);
|
|
114
|
+
display: inline-block;
|
|
115
|
+
min-width: 2em;
|
|
116
|
+
padding-right: 0.8em;
|
|
117
|
+
text-align: right;
|
|
118
|
+
pointer-events: none;
|
|
119
|
+
user-select: none;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.highlighted {
|
|
124
|
+
background: var(--bg-overlay);
|
|
120
125
|
}
|
|
121
|
-
}
|
|
122
126
|
|
|
123
|
-
|
|
127
|
+
${generateCodeBlockTokens()}
|
|
128
|
+
|
|
129
|
+
${({ hideCodeColors }) =>
|
|
130
|
+
hideCodeColors &&
|
|
131
|
+
css`
|
|
132
|
+
.code-line:not(.highlighted),
|
|
133
|
+
.code-line:not(.highlighted) > span,
|
|
134
|
+
.code-line:not(.highlighted) > span > span {
|
|
135
|
+
color: grey;
|
|
136
|
+
}
|
|
137
|
+
`}
|
|
124
138
|
`;
|
|
@@ -3,15 +3,25 @@ import styled from 'styled-components';
|
|
|
3
3
|
|
|
4
4
|
import { CodeBlockControlButton } from '@theme/components/CodeBlock';
|
|
5
5
|
import { CopyButton } from '@theme/components/CopyButton/CopyButton';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
CollapseIcon,
|
|
8
|
+
DeselectIcon,
|
|
9
|
+
ExpandIcon,
|
|
10
|
+
ReportIcon,
|
|
11
|
+
SelectIcon,
|
|
12
|
+
SmallFileIcon,
|
|
13
|
+
} from '@theme/icons';
|
|
7
14
|
import { useThemeConfig } from '@theme/hooks';
|
|
8
15
|
import { telemetry } from '@portal/telemetry';
|
|
16
|
+
import { Button } from '@theme/components';
|
|
17
|
+
import type { FileTabs } from '@theme/components/CodeBlock';
|
|
9
18
|
|
|
10
19
|
export interface CodeBlockControlsProps {
|
|
11
20
|
children?: React.ReactNode;
|
|
12
21
|
className?: string;
|
|
13
22
|
title?: React.ReactNode | string;
|
|
14
23
|
controls?: ControlItems;
|
|
24
|
+
tabs?: FileTabs;
|
|
15
25
|
}
|
|
16
26
|
|
|
17
27
|
interface ControlItems {
|
|
@@ -47,6 +57,7 @@ export function CodeBlockControls({
|
|
|
47
57
|
className,
|
|
48
58
|
title,
|
|
49
59
|
controls,
|
|
60
|
+
tabs,
|
|
50
61
|
}: CodeBlockControlsProps): JSX.Element | null {
|
|
51
62
|
const { codeSnippet } = useThemeConfig();
|
|
52
63
|
const controlsType = (codeSnippet?.elementFormat as ControlItemType) || 'icon';
|
|
@@ -54,9 +65,32 @@ export function CodeBlockControls({
|
|
|
54
65
|
? controls
|
|
55
66
|
: { copy: null, expand: null, collapse: null, select: null, deselect: null, report: null };
|
|
56
67
|
|
|
68
|
+
const FileTabs = () => {
|
|
69
|
+
return (
|
|
70
|
+
<CodeTabsBlock>
|
|
71
|
+
{tabs?.files.map(({ name }) => {
|
|
72
|
+
const isActive = name === tabs.activeTabName;
|
|
73
|
+
return (
|
|
74
|
+
<CodeTabButton
|
|
75
|
+
active={isActive}
|
|
76
|
+
key={name}
|
|
77
|
+
onClick={() => {
|
|
78
|
+
tabs.handleTabSwitch(name);
|
|
79
|
+
}}
|
|
80
|
+
>
|
|
81
|
+
<SmallFileIcon />
|
|
82
|
+
{name}
|
|
83
|
+
</CodeTabButton>
|
|
84
|
+
);
|
|
85
|
+
})}
|
|
86
|
+
</CodeTabsBlock>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
57
90
|
const defaultControls = controls ? (
|
|
58
91
|
<>
|
|
59
|
-
<Title>{title}</Title>
|
|
92
|
+
{title && <Title>{title}</Title>}
|
|
93
|
+
{tabs && <FileTabs />}
|
|
60
94
|
<ControlsWrapper>
|
|
61
95
|
{report && report?.props?.visible ? (
|
|
62
96
|
<CodeBlockControlButton
|
|
@@ -186,3 +220,27 @@ const ControlsWrapper = styled.div`
|
|
|
186
220
|
opacity: 1;
|
|
187
221
|
}
|
|
188
222
|
`;
|
|
223
|
+
|
|
224
|
+
const CodeTabsBlock = styled.div`
|
|
225
|
+
background: transparent;
|
|
226
|
+
border-radius: var(--global-border-radius) 0;
|
|
227
|
+
display: flex;
|
|
228
|
+
flex-wrap: wrap;
|
|
229
|
+
margin: 12px 0;
|
|
230
|
+
justify-content: flex-start;
|
|
231
|
+
flex-direction: row;
|
|
232
|
+
padding: 0 12px;
|
|
233
|
+
`;
|
|
234
|
+
|
|
235
|
+
const CodeTabButton = styled(Button)<{ active: boolean }>`
|
|
236
|
+
border: none;
|
|
237
|
+
padding: 8px 12px;
|
|
238
|
+
background: ${({ active }) => (active ? 'var(--color-primary-base)' : 'transparent')};
|
|
239
|
+
color: ${({ active }) => (active ? '#fff' : 'var(--text-base)')};
|
|
240
|
+
font-size: var(--font-size-sm);
|
|
241
|
+
|
|
242
|
+
&:hover {
|
|
243
|
+
background: var(--color-primary-bg-hover);
|
|
244
|
+
border: none;
|
|
245
|
+
}
|
|
246
|
+
`;
|
|
@@ -13,13 +13,16 @@ export function LoginLink({ href }: LoginLinkProps): JSX.Element {
|
|
|
13
13
|
const { userProfile } = useThemeConfig();
|
|
14
14
|
const { translate } = useTranslate();
|
|
15
15
|
|
|
16
|
+
const handleLoginClick = () => {
|
|
17
|
+
telemetry.send('login_button_clicked', {});
|
|
18
|
+
window.location.href = href;
|
|
19
|
+
};
|
|
20
|
+
|
|
16
21
|
return (
|
|
17
22
|
<StyledLink
|
|
18
|
-
href={href}
|
|
19
23
|
data-translation-key="theme.profile.login"
|
|
20
|
-
onClick={() =>
|
|
21
|
-
|
|
22
|
-
}}
|
|
24
|
+
onClick={() => handleLoginClick()}
|
|
25
|
+
data-cy={href}
|
|
23
26
|
>
|
|
24
27
|
{translate('theme.profile.login', userProfile?.loginLabel || 'Login')}
|
|
25
28
|
</StyledLink>
|
|
@@ -39,4 +42,5 @@ const StyledLink = styled.a.attrs(() => ({
|
|
|
39
42
|
&:hover {
|
|
40
43
|
color: var(--navbar-item-hover-text-color);
|
|
41
44
|
}
|
|
45
|
+
cursor: pointer;
|
|
42
46
|
`;
|