@redocly/theme 0.7.2 → 0.7.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/Feedback/Comment.js +16 -3
- package/lib/Feedback/types.d.ts +1 -0
- package/lib/Markdown/CodeSample/CodeSample.js +47 -8
- package/lib/config.d.ts +34 -0
- package/lib/config.js +8 -0
- package/lib/globalStyle.js +10 -0
- package/lib/hooks/useReportDialog.d.ts +1 -0
- package/lib/hooks/useReportDialog.js +16 -0
- package/lib/mocks/Feedback/useSubmitFeedback.d.ts +1 -0
- package/lib/mocks/Feedback/useSubmitFeedback.js +18 -0
- package/lib/mocks/hooks/index.js +4 -0
- package/package.json +1 -1
- package/src/Feedback/Comment.tsx +19 -3
- package/src/Feedback/types.ts +1 -0
- package/src/Markdown/CodeSample/CodeSample.tsx +74 -15
- package/src/config.ts +8 -0
- package/src/globalStyle.ts +11 -0
- package/src/hooks/useReportDialog.ts +14 -0
- package/src/mocks/Feedback/useSubmitFeedback.tsx +4 -0
- package/src/mocks/hooks/index.ts +4 -0
package/lib/Feedback/Comment.js
CHANGED
|
@@ -31,7 +31,7 @@ const React = __importStar(require("react"));
|
|
|
31
31
|
const styled_components_1 = __importDefault(require("styled-components"));
|
|
32
32
|
const Button_1 = require("../Button/Button");
|
|
33
33
|
const Comment = ({ settings, onSubmit }) => {
|
|
34
|
-
const { label, submitText } = settings || {};
|
|
34
|
+
const { label, submitText, onCancel } = settings || {};
|
|
35
35
|
const [text, setText] = React.useState('');
|
|
36
36
|
const [submitValue, setSubmitValue] = React.useState('');
|
|
37
37
|
const send = () => {
|
|
@@ -48,9 +48,11 @@ const Comment = ({ settings, onSubmit }) => {
|
|
|
48
48
|
React.createElement(Label, null, submitText || 'Thank you for helping improve our documentation!')));
|
|
49
49
|
}
|
|
50
50
|
return (React.createElement(Wrapper, { "data-component-name": "Feedback/Comment" },
|
|
51
|
-
React.createElement(Label, null, label || 'Please share your feedback with us
|
|
51
|
+
React.createElement(Label, null, label || 'Please share your feedback with us.'),
|
|
52
52
|
React.createElement(TextArea, { rows: 3, onChange: handleTextAreaChange }),
|
|
53
|
-
React.createElement(
|
|
53
|
+
React.createElement(ButtonsContainer, null,
|
|
54
|
+
React.createElement(SendButton, { onClick: send }, "Send"),
|
|
55
|
+
onCancel && React.createElement(CancelButton, { onClick: onCancel }, "Cancel"))));
|
|
54
56
|
};
|
|
55
57
|
exports.Comment = Comment;
|
|
56
58
|
const Wrapper = styled_components_1.default.div `
|
|
@@ -70,6 +72,10 @@ const TextArea = styled_components_1.default.textarea `
|
|
|
70
72
|
margin: 0 0 10px 0;
|
|
71
73
|
padding: 10px;
|
|
72
74
|
`;
|
|
75
|
+
const ButtonsContainer = styled_components_1.default.div `
|
|
76
|
+
display: flex;
|
|
77
|
+
justify-content: start;
|
|
78
|
+
`;
|
|
73
79
|
const SendButton = (0, styled_components_1.default)(Button_1.Button).attrs(() => ({
|
|
74
80
|
color: 'primary',
|
|
75
81
|
})) `
|
|
@@ -77,4 +83,11 @@ const SendButton = (0, styled_components_1.default)(Button_1.Button).attrs(() =>
|
|
|
77
83
|
margin-left: 0;
|
|
78
84
|
margin-right: 0;
|
|
79
85
|
`;
|
|
86
|
+
const CancelButton = (0, styled_components_1.default)(Button_1.Button).attrs(() => ({
|
|
87
|
+
color: 'secondary',
|
|
88
|
+
})) `
|
|
89
|
+
width: 100px;
|
|
90
|
+
margin-left: 0;
|
|
91
|
+
margin-right: 0;
|
|
92
|
+
`;
|
|
80
93
|
//# sourceMappingURL=Comment.js.map
|
package/lib/Feedback/types.d.ts
CHANGED
|
@@ -28,29 +28,47 @@ const react_1 = __importStar(require("react"));
|
|
|
28
28
|
const styled_components_1 = __importStar(require("styled-components"));
|
|
29
29
|
const ClipboardService_1 = require("../../utils/ClipboardService");
|
|
30
30
|
const useThemeConfig_1 = require("../../hooks/useThemeConfig");
|
|
31
|
+
const Feedback_1 = require("../../Feedback");
|
|
32
|
+
const useSubmitFeedback_1 = require("../../mocks/Feedback/useSubmitFeedback");
|
|
33
|
+
const useReportDialog_1 = require("../../hooks/useReportDialog");
|
|
31
34
|
function CodeSample({ rawContent, highlighted, language }) {
|
|
32
35
|
const langClassName = language ? `language-${language}` : '';
|
|
33
|
-
const { markdown: { copyCodeSnippet = {} } = {} } = (0, useThemeConfig_1.useThemeConfig)();
|
|
36
|
+
const { markdown: { copyCodeSnippet = {}, reportCodeSnippet = {} } = {} } = (0, useThemeConfig_1.useThemeConfig)();
|
|
37
|
+
const { submitFeedback } = (0, useSubmitFeedback_1.useSubmitFeedback)();
|
|
34
38
|
const [isCopied, setIsCopied] = (0, react_1.useState)(false);
|
|
39
|
+
const [isDialogShown, showDialog, hideDialog] = (0, useReportDialog_1.useReportDialog)(false);
|
|
35
40
|
const copyCode = (code) => {
|
|
36
41
|
ClipboardService_1.ClipboardService.copyCustom(code);
|
|
37
42
|
setIsCopied(true);
|
|
38
|
-
setTimeout(() => setIsCopied(false), copyCodeSnippet.toasterDuration);
|
|
43
|
+
setTimeout(() => setIsCopied(false), copyCodeSnippet.toasterDuration || 1000);
|
|
39
44
|
};
|
|
40
45
|
return (react_1.default.createElement(Wrapper, { className: "code-sample", "data-component-name": "Markdown/CodeSample/CodeSample" },
|
|
41
|
-
|
|
42
|
-
!
|
|
43
|
-
|
|
46
|
+
react_1.default.createElement(CodeSampleButtonContainer, null,
|
|
47
|
+
!copyCodeSnippet.hide && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
48
|
+
!isCopied && (react_1.default.createElement(Button, { onClick: () => copyCode(rawContent), title: copyCodeSnippet.tooltipText || 'Copy to clipboard' }, copyCodeSnippet.buttonText || 'Copy')),
|
|
49
|
+
isCopied && react_1.default.createElement(DoneIndicator, null, copyCodeSnippet.toasterText || 'Copied!'))),
|
|
50
|
+
!reportCodeSnippet.hide && (react_1.default.createElement(Button, { onClick: () => showDialog(), title: reportCodeSnippet.tooltipText || 'Report a problem' }, "Report")),
|
|
51
|
+
isDialogShown && (react_1.default.createElement(ReportDialog, { id: "modal" },
|
|
52
|
+
react_1.default.createElement(Feedback_1.Comment, { settings: {
|
|
53
|
+
label: reportCodeSnippet.label || 'What is wrong with a code?',
|
|
54
|
+
onCancel: () => {
|
|
55
|
+
hideDialog();
|
|
56
|
+
},
|
|
57
|
+
}, onSubmit: (value) => {
|
|
58
|
+
submitFeedback('problem', Object.assign(Object.assign({}, value), { location: rawContent }));
|
|
59
|
+
hideDialog();
|
|
60
|
+
} })))),
|
|
44
61
|
react_1.default.createElement("pre", { className: langClassName },
|
|
45
62
|
react_1.default.createElement("code", { className: langClassName, dangerouslySetInnerHTML: { __html: highlighted } }))));
|
|
46
63
|
}
|
|
47
64
|
exports.CodeSample = CodeSample;
|
|
48
65
|
const CodeSampleButtonContainer = styled_components_1.default.div `
|
|
66
|
+
display: flex;
|
|
49
67
|
position: absolute;
|
|
50
68
|
top: 12px;
|
|
51
69
|
right: 5px;
|
|
52
70
|
`;
|
|
53
|
-
const
|
|
71
|
+
const Button = styled_components_1.default.div `
|
|
54
72
|
padding: var(--code-block-controls-padding);
|
|
55
73
|
border-radius: var(--code-block-controls-border-radius);
|
|
56
74
|
font-size: var(--code-block-controls-font-size);
|
|
@@ -124,13 +142,13 @@ const Wrapper = styled_components_1.default.div `
|
|
|
124
142
|
border-radius: 4px;
|
|
125
143
|
position: relative;
|
|
126
144
|
|
|
127
|
-
${
|
|
145
|
+
${Button},
|
|
128
146
|
${DoneIndicator} {
|
|
129
147
|
color: var(--code-block-controls-text-color);
|
|
130
148
|
background-color: var(--code-block-controls-background-color);
|
|
131
149
|
opacity: var(--code-block-controls-opacity);
|
|
132
150
|
}
|
|
133
|
-
${
|
|
151
|
+
${Button}:hover {
|
|
134
152
|
color: var(--code-block-controls-hover-text-color);
|
|
135
153
|
background-color: var(--code-block-controls-hover-background-color);
|
|
136
154
|
opacity: var(--code-block-controls-active-opacity);
|
|
@@ -208,4 +226,25 @@ const Wrapper = styled_components_1.default.div `
|
|
|
208
226
|
${darkStyleTokens};
|
|
209
227
|
}
|
|
210
228
|
`;
|
|
229
|
+
const ReportDialog = styled_components_1.default.div `
|
|
230
|
+
position: fixed;
|
|
231
|
+
top: 0;
|
|
232
|
+
left: 0;
|
|
233
|
+
width: 100vw;
|
|
234
|
+
height: 100vh;
|
|
235
|
+
background: var(--modal-overlay-background-color);
|
|
236
|
+
z-index: 10000;
|
|
237
|
+
display: flex;
|
|
238
|
+
align-items: center;
|
|
239
|
+
justify-content: center;
|
|
240
|
+
|
|
241
|
+
& > * {
|
|
242
|
+
background: var(--modal-background-color);
|
|
243
|
+
box-shadow: var(--modal-box-shadow);
|
|
244
|
+
padding: 15px;
|
|
245
|
+
margin: 15px;
|
|
246
|
+
max-width: 500px;
|
|
247
|
+
max-height: 300px;
|
|
248
|
+
}
|
|
249
|
+
`;
|
|
211
250
|
//# sourceMappingURL=CodeSample.js.map
|
package/lib/config.d.ts
CHANGED
|
@@ -379,6 +379,20 @@ export declare const ThemeConfig: z.ZodDefault<z.ZodObject<{
|
|
|
379
379
|
toasterText?: string | undefined;
|
|
380
380
|
toasterDuration?: number | undefined;
|
|
381
381
|
}>>>;
|
|
382
|
+
reportCodeSnippet: z.ZodDefault<z.ZodOptional<z.ZodObject<z.extendShape<{
|
|
383
|
+
tooltipText: z.ZodOptional<z.ZodDefault<z.ZodString>>;
|
|
384
|
+
label: z.ZodOptional<z.ZodString>;
|
|
385
|
+
}, {
|
|
386
|
+
hide: z.ZodOptional<z.ZodBoolean>;
|
|
387
|
+
}>, "strip", z.ZodTypeAny, {
|
|
388
|
+
hide?: boolean | undefined;
|
|
389
|
+
tooltipText?: string | undefined;
|
|
390
|
+
label?: string | undefined;
|
|
391
|
+
}, {
|
|
392
|
+
hide?: boolean | undefined;
|
|
393
|
+
tooltipText?: string | undefined;
|
|
394
|
+
label?: string | undefined;
|
|
395
|
+
}>>>;
|
|
382
396
|
}, "strict", z.ZodTypeAny, {
|
|
383
397
|
frontMatterKeysToResolve?: string[] | undefined;
|
|
384
398
|
lastUpdatedBlock?: {
|
|
@@ -404,6 +418,11 @@ export declare const ThemeConfig: z.ZodDefault<z.ZodObject<{
|
|
|
404
418
|
toasterText?: string | undefined;
|
|
405
419
|
toasterDuration?: number | undefined;
|
|
406
420
|
};
|
|
421
|
+
reportCodeSnippet: {
|
|
422
|
+
hide?: boolean | undefined;
|
|
423
|
+
tooltipText?: string | undefined;
|
|
424
|
+
label?: string | undefined;
|
|
425
|
+
};
|
|
407
426
|
}, {
|
|
408
427
|
frontMatterKeysToResolve?: string[] | undefined;
|
|
409
428
|
lastUpdatedBlock?: {
|
|
@@ -429,6 +448,11 @@ export declare const ThemeConfig: z.ZodDefault<z.ZodObject<{
|
|
|
429
448
|
toasterText?: string | undefined;
|
|
430
449
|
toasterDuration?: number | undefined;
|
|
431
450
|
} | undefined;
|
|
451
|
+
reportCodeSnippet?: {
|
|
452
|
+
hide?: boolean | undefined;
|
|
453
|
+
tooltipText?: string | undefined;
|
|
454
|
+
label?: string | undefined;
|
|
455
|
+
} | undefined;
|
|
432
456
|
}>>>;
|
|
433
457
|
openapi: z.ZodOptional<z.ZodObject<{}, "passthrough", z.ZodTypeAny, {}, {}>>;
|
|
434
458
|
graphql: z.ZodOptional<z.ZodObject<{}, "passthrough", z.ZodTypeAny, {}, {}>>;
|
|
@@ -550,6 +574,11 @@ export declare const ThemeConfig: z.ZodDefault<z.ZodObject<{
|
|
|
550
574
|
toasterText?: string | undefined;
|
|
551
575
|
toasterDuration?: number | undefined;
|
|
552
576
|
};
|
|
577
|
+
reportCodeSnippet: {
|
|
578
|
+
hide?: boolean | undefined;
|
|
579
|
+
tooltipText?: string | undefined;
|
|
580
|
+
label?: string | undefined;
|
|
581
|
+
};
|
|
553
582
|
} | undefined;
|
|
554
583
|
openapi?: {} | undefined;
|
|
555
584
|
graphql?: {} | undefined;
|
|
@@ -690,6 +719,11 @@ export declare const ThemeConfig: z.ZodDefault<z.ZodObject<{
|
|
|
690
719
|
toasterText?: string | undefined;
|
|
691
720
|
toasterDuration?: number | undefined;
|
|
692
721
|
} | undefined;
|
|
722
|
+
reportCodeSnippet?: {
|
|
723
|
+
hide?: boolean | undefined;
|
|
724
|
+
tooltipText?: string | undefined;
|
|
725
|
+
label?: string | undefined;
|
|
726
|
+
} | undefined;
|
|
693
727
|
} | undefined;
|
|
694
728
|
openapi?: {} | undefined;
|
|
695
729
|
graphql?: {} | undefined;
|
package/lib/config.js
CHANGED
|
@@ -155,6 +155,14 @@ exports.ThemeConfig = zod_1.z
|
|
|
155
155
|
.extend(HideConfig.shape)
|
|
156
156
|
.optional()
|
|
157
157
|
.default({}),
|
|
158
|
+
reportCodeSnippet: zod_1.z
|
|
159
|
+
.object({
|
|
160
|
+
tooltipText: zod_1.z.string().default('Report a problem').optional(),
|
|
161
|
+
label: zod_1.z.string().optional(),
|
|
162
|
+
})
|
|
163
|
+
.extend(HideConfig.shape)
|
|
164
|
+
.optional()
|
|
165
|
+
.default({ hide: true }), // TODO: temporary disabled
|
|
158
166
|
})
|
|
159
167
|
.strict()
|
|
160
168
|
.default({})
|
package/lib/globalStyle.js
CHANGED
|
@@ -1938,6 +1938,15 @@ const pages = (0, styled_components_1.css) `
|
|
|
1938
1938
|
|
|
1939
1939
|
// @tokens End
|
|
1940
1940
|
`;
|
|
1941
|
+
const modal = (0, styled_components_1.css) `
|
|
1942
|
+
body:has([id='modal']) {
|
|
1943
|
+
overflow: hidden;
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
--modal-box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.6);
|
|
1947
|
+
--modal-overlay-background-color: rgba(206, 206, 206, 0.49);
|
|
1948
|
+
--modal-background-color: var(--background-color);
|
|
1949
|
+
`;
|
|
1941
1950
|
exports.styles = (0, styled_components_1.css) `
|
|
1942
1951
|
:root {
|
|
1943
1952
|
${baseColors}
|
|
@@ -1968,6 +1977,7 @@ exports.styles = (0, styled_components_1.css) `
|
|
|
1968
1977
|
${loadProgressBar}
|
|
1969
1978
|
${apiLogsTable}
|
|
1970
1979
|
${pages}
|
|
1980
|
+
${modal}
|
|
1971
1981
|
}
|
|
1972
1982
|
|
|
1973
1983
|
:root.dark {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useReportDialog(initialState?: boolean): [boolean, () => void, () => void];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useReportDialog = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
function useReportDialog(initialState = false) {
|
|
6
|
+
const [isDialogShown, setIsShown] = (0, react_1.useState)(initialState);
|
|
7
|
+
const showDialog = () => {
|
|
8
|
+
setIsShown(true);
|
|
9
|
+
};
|
|
10
|
+
const hideDialog = () => {
|
|
11
|
+
setIsShown(false);
|
|
12
|
+
};
|
|
13
|
+
return [isDialogShown, showDialog, hideDialog];
|
|
14
|
+
}
|
|
15
|
+
exports.useReportDialog = useReportDialog;
|
|
16
|
+
//# sourceMappingURL=useReportDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useSubmitFeedback(): any;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.useSubmitFeedback = void 0;
|
|
13
|
+
function useSubmitFeedback() {
|
|
14
|
+
const submitFeedback = () => __awaiter(this, void 0, void 0, function* () { });
|
|
15
|
+
return { submitFeedback };
|
|
16
|
+
}
|
|
17
|
+
exports.useSubmitFeedback = useSubmitFeedback;
|
|
18
|
+
//# sourceMappingURL=useSubmitFeedback.js.map
|
package/lib/mocks/hooks/index.js
CHANGED
package/package.json
CHANGED
package/src/Feedback/Comment.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import { Button } from '@theme/Button/Button';
|
|
|
5
5
|
import type { CommentProps } from '@theme/Feedback';
|
|
6
6
|
|
|
7
7
|
export const Comment = ({ settings, onSubmit }: CommentProps): JSX.Element => {
|
|
8
|
-
const { label, submitText } = settings || {};
|
|
8
|
+
const { label, submitText, onCancel } = settings || {};
|
|
9
9
|
const [text, setText] = React.useState('');
|
|
10
10
|
const [submitValue, setSubmitValue] = React.useState('');
|
|
11
11
|
|
|
@@ -28,9 +28,12 @@ export const Comment = ({ settings, onSubmit }: CommentProps): JSX.Element => {
|
|
|
28
28
|
|
|
29
29
|
return (
|
|
30
30
|
<Wrapper data-component-name="Feedback/Comment">
|
|
31
|
-
<Label>{label || 'Please share your feedback with us
|
|
31
|
+
<Label>{label || 'Please share your feedback with us.'}</Label>
|
|
32
32
|
<TextArea rows={3} onChange={handleTextAreaChange} />
|
|
33
|
-
<
|
|
33
|
+
<ButtonsContainer>
|
|
34
|
+
<SendButton onClick={send}>Send</SendButton>
|
|
35
|
+
{onCancel && <CancelButton onClick={onCancel}>Cancel</CancelButton>}
|
|
36
|
+
</ButtonsContainer>
|
|
34
37
|
</Wrapper>
|
|
35
38
|
);
|
|
36
39
|
};
|
|
@@ -55,6 +58,11 @@ const TextArea = styled.textarea`
|
|
|
55
58
|
padding: 10px;
|
|
56
59
|
`;
|
|
57
60
|
|
|
61
|
+
const ButtonsContainer = styled.div`
|
|
62
|
+
display: flex;
|
|
63
|
+
justify-content: start;
|
|
64
|
+
`;
|
|
65
|
+
|
|
58
66
|
const SendButton = styled(Button).attrs(() => ({
|
|
59
67
|
color: 'primary',
|
|
60
68
|
}))`
|
|
@@ -62,3 +70,11 @@ const SendButton = styled(Button).attrs(() => ({
|
|
|
62
70
|
margin-left: 0;
|
|
63
71
|
margin-right: 0;
|
|
64
72
|
`;
|
|
73
|
+
|
|
74
|
+
const CancelButton = styled(Button).attrs(() => ({
|
|
75
|
+
color: 'secondary',
|
|
76
|
+
}))`
|
|
77
|
+
width: 100px;
|
|
78
|
+
margin-left: 0;
|
|
79
|
+
margin-right: 0;
|
|
80
|
+
`;
|
package/src/Feedback/types.ts
CHANGED
|
@@ -3,6 +3,9 @@ import styled, { css } from 'styled-components';
|
|
|
3
3
|
|
|
4
4
|
import { ClipboardService } from '@theme/utils/ClipboardService';
|
|
5
5
|
import { useThemeConfig } from '@theme/hooks/useThemeConfig';
|
|
6
|
+
import { Comment } from '@theme/Feedback';
|
|
7
|
+
import { useSubmitFeedback } from '@portal/Feedback/useSubmitFeedback';
|
|
8
|
+
import { useReportDialog } from '@theme/hooks/useReportDialog';
|
|
6
9
|
|
|
7
10
|
export type CodeSampleProps = {
|
|
8
11
|
language: string;
|
|
@@ -12,28 +15,61 @@ export type CodeSampleProps = {
|
|
|
12
15
|
|
|
13
16
|
export function CodeSample({ rawContent, highlighted, language }: CodeSampleProps): JSX.Element {
|
|
14
17
|
const langClassName = language ? `language-${language}` : '';
|
|
15
|
-
const { markdown: { copyCodeSnippet = {} } = {} } = useThemeConfig();
|
|
18
|
+
const { markdown: { copyCodeSnippet = {}, reportCodeSnippet = {} } = {} } = useThemeConfig();
|
|
19
|
+
const { submitFeedback } = useSubmitFeedback();
|
|
16
20
|
|
|
17
21
|
const [isCopied, setIsCopied] = useState(false);
|
|
22
|
+
const [isDialogShown, showDialog, hideDialog] = useReportDialog(false);
|
|
18
23
|
|
|
19
24
|
const copyCode = (code: string) => {
|
|
20
25
|
ClipboardService.copyCustom(code);
|
|
21
26
|
setIsCopied(true);
|
|
22
|
-
setTimeout(() => setIsCopied(false), copyCodeSnippet.toasterDuration);
|
|
27
|
+
setTimeout(() => setIsCopied(false), copyCodeSnippet.toasterDuration || 1000);
|
|
23
28
|
};
|
|
24
29
|
|
|
25
30
|
return (
|
|
26
31
|
<Wrapper className="code-sample" data-component-name="Markdown/CodeSample/CodeSample">
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
<CodeSampleButtonContainer>
|
|
33
|
+
{!copyCodeSnippet.hide && (
|
|
34
|
+
<>
|
|
35
|
+
{!isCopied && (
|
|
36
|
+
<Button
|
|
37
|
+
onClick={() => copyCode(rawContent)}
|
|
38
|
+
title={copyCodeSnippet.tooltipText || 'Copy to clipboard'}
|
|
39
|
+
>
|
|
40
|
+
{copyCodeSnippet.buttonText || 'Copy'}
|
|
41
|
+
</Button>
|
|
42
|
+
)}
|
|
43
|
+
{isCopied && <DoneIndicator>{copyCodeSnippet.toasterText || 'Copied!'}</DoneIndicator>}
|
|
44
|
+
</>
|
|
45
|
+
)}
|
|
46
|
+
|
|
47
|
+
{!reportCodeSnippet.hide && (
|
|
48
|
+
<Button
|
|
49
|
+
onClick={() => showDialog()}
|
|
50
|
+
title={reportCodeSnippet.tooltipText || 'Report a problem'}
|
|
51
|
+
>
|
|
52
|
+
Report
|
|
53
|
+
</Button>
|
|
54
|
+
)}
|
|
55
|
+
|
|
56
|
+
{isDialogShown && (
|
|
57
|
+
<ReportDialog id="modal">
|
|
58
|
+
<Comment
|
|
59
|
+
settings={{
|
|
60
|
+
label: reportCodeSnippet.label || 'What is wrong with a code?',
|
|
61
|
+
onCancel: () => {
|
|
62
|
+
hideDialog();
|
|
63
|
+
},
|
|
64
|
+
}}
|
|
65
|
+
onSubmit={(value) => {
|
|
66
|
+
submitFeedback('problem', { ...value, location: rawContent });
|
|
67
|
+
hideDialog();
|
|
68
|
+
}}
|
|
69
|
+
/>
|
|
70
|
+
</ReportDialog>
|
|
71
|
+
)}
|
|
72
|
+
</CodeSampleButtonContainer>
|
|
37
73
|
<pre className={langClassName}>
|
|
38
74
|
<code className={langClassName} dangerouslySetInnerHTML={{ __html: highlighted }} />
|
|
39
75
|
</pre>
|
|
@@ -42,12 +78,13 @@ export function CodeSample({ rawContent, highlighted, language }: CodeSampleProp
|
|
|
42
78
|
}
|
|
43
79
|
|
|
44
80
|
const CodeSampleButtonContainer = styled.div`
|
|
81
|
+
display: flex;
|
|
45
82
|
position: absolute;
|
|
46
83
|
top: 12px;
|
|
47
84
|
right: 5px;
|
|
48
85
|
`;
|
|
49
86
|
|
|
50
|
-
const
|
|
87
|
+
const Button = styled.div`
|
|
51
88
|
padding: var(--code-block-controls-padding);
|
|
52
89
|
border-radius: var(--code-block-controls-border-radius);
|
|
53
90
|
font-size: var(--code-block-controls-font-size);
|
|
@@ -124,13 +161,13 @@ const Wrapper = styled.div`
|
|
|
124
161
|
border-radius: 4px;
|
|
125
162
|
position: relative;
|
|
126
163
|
|
|
127
|
-
${
|
|
164
|
+
${Button},
|
|
128
165
|
${DoneIndicator} {
|
|
129
166
|
color: var(--code-block-controls-text-color);
|
|
130
167
|
background-color: var(--code-block-controls-background-color);
|
|
131
168
|
opacity: var(--code-block-controls-opacity);
|
|
132
169
|
}
|
|
133
|
-
${
|
|
170
|
+
${Button}:hover {
|
|
134
171
|
color: var(--code-block-controls-hover-text-color);
|
|
135
172
|
background-color: var(--code-block-controls-hover-background-color);
|
|
136
173
|
opacity: var(--code-block-controls-active-opacity);
|
|
@@ -208,3 +245,25 @@ const Wrapper = styled.div`
|
|
|
208
245
|
${darkStyleTokens};
|
|
209
246
|
}
|
|
210
247
|
`;
|
|
248
|
+
|
|
249
|
+
const ReportDialog = styled.div`
|
|
250
|
+
position: fixed;
|
|
251
|
+
top: 0;
|
|
252
|
+
left: 0;
|
|
253
|
+
width: 100vw;
|
|
254
|
+
height: 100vh;
|
|
255
|
+
background: var(--modal-overlay-background-color);
|
|
256
|
+
z-index: 10000;
|
|
257
|
+
display: flex;
|
|
258
|
+
align-items: center;
|
|
259
|
+
justify-content: center;
|
|
260
|
+
|
|
261
|
+
& > * {
|
|
262
|
+
background: var(--modal-background-color);
|
|
263
|
+
box-shadow: var(--modal-box-shadow);
|
|
264
|
+
padding: 15px;
|
|
265
|
+
margin: 15px;
|
|
266
|
+
max-width: 500px;
|
|
267
|
+
max-height: 300px;
|
|
268
|
+
}
|
|
269
|
+
`;
|
package/src/config.ts
CHANGED
|
@@ -164,6 +164,14 @@ export const ThemeConfig = z
|
|
|
164
164
|
.extend(HideConfig.shape)
|
|
165
165
|
.optional()
|
|
166
166
|
.default({}),
|
|
167
|
+
reportCodeSnippet: z
|
|
168
|
+
.object({
|
|
169
|
+
tooltipText: z.string().default('Report a problem').optional(),
|
|
170
|
+
label: z.string().optional(),
|
|
171
|
+
})
|
|
172
|
+
.extend(HideConfig.shape)
|
|
173
|
+
.optional()
|
|
174
|
+
.default({ hide: true }), // TODO: temporary disabled
|
|
167
175
|
})
|
|
168
176
|
.strict()
|
|
169
177
|
.default({})
|
package/src/globalStyle.ts
CHANGED
|
@@ -1965,6 +1965,16 @@ const pages = css`
|
|
|
1965
1965
|
// @tokens End
|
|
1966
1966
|
`
|
|
1967
1967
|
|
|
1968
|
+
const modal = css`
|
|
1969
|
+
body:has([id='modal']) {
|
|
1970
|
+
overflow: hidden;
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
--modal-box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.6);
|
|
1974
|
+
--modal-overlay-background-color: rgba(206, 206, 206, 0.49);
|
|
1975
|
+
--modal-background-color: var(--background-color);
|
|
1976
|
+
`
|
|
1977
|
+
|
|
1968
1978
|
export const styles = css`
|
|
1969
1979
|
:root {
|
|
1970
1980
|
${baseColors}
|
|
@@ -1995,6 +2005,7 @@ export const styles = css`
|
|
|
1995
2005
|
${loadProgressBar}
|
|
1996
2006
|
${apiLogsTable}
|
|
1997
2007
|
${pages}
|
|
2008
|
+
${modal}
|
|
1998
2009
|
}
|
|
1999
2010
|
|
|
2000
2011
|
:root.dark {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
|
|
3
|
+
export function useReportDialog(initialState = false): [boolean, () => void, () => void] {
|
|
4
|
+
const [isDialogShown, setIsShown] = useState(initialState);
|
|
5
|
+
|
|
6
|
+
const showDialog = () => {
|
|
7
|
+
setIsShown(true);
|
|
8
|
+
};
|
|
9
|
+
const hideDialog = () => {
|
|
10
|
+
setIsShown(false);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
return [isDialogShown, showDialog, hideDialog];
|
|
14
|
+
}
|
package/src/mocks/hooks/index.ts
CHANGED
|
@@ -23,6 +23,10 @@ export function useThemeConfig<T extends Record<string, unknown>>(): T & ThemeUI
|
|
|
23
23
|
toasterText: 'Copied',
|
|
24
24
|
toasterDuration: 1500,
|
|
25
25
|
},
|
|
26
|
+
reportCodeSnippet: {
|
|
27
|
+
hide: false,
|
|
28
|
+
tooltipText: 'Report a problem',
|
|
29
|
+
},
|
|
26
30
|
editPage: {
|
|
27
31
|
baseUrl: '',
|
|
28
32
|
text: 'Edit this page',
|