@redocly/theme 0.70.0-next.8 → 0.70.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/components/LoadProgressBar/LoadProgressBar.d.ts +8 -0
- package/lib/components/LoadProgressBar/LoadProgressBar.js +122 -0
- package/lib/core/constants/index.d.ts +1 -0
- package/lib/core/constants/index.js +1 -0
- package/lib/core/constants/prompt.d.ts +9 -0
- package/lib/core/constants/prompt.js +33 -0
- package/lib/core/hooks/index.d.ts +3 -0
- package/lib/core/hooks/index.js +3 -0
- package/lib/core/hooks/prompt/use-prompt-actions.d.ts +7 -0
- package/lib/core/hooks/prompt/use-prompt-actions.js +19 -0
- package/lib/core/hooks/prompt/use-prompt-text-limit.d.ts +19 -0
- package/lib/core/hooks/prompt/use-prompt-text-limit.js +35 -0
- package/lib/core/hooks/use-page-actions.js +4 -8
- package/lib/core/hooks/use-pointer-border-highlight.d.ts +7 -0
- package/lib/core/hooks/use-pointer-border-highlight.js +29 -0
- package/lib/core/hooks/use-telemetry-fallback.d.ts +2 -0
- package/lib/core/hooks/use-telemetry-fallback.js +2 -0
- package/lib/core/styles/dark.js +14 -12
- package/lib/core/styles/global.js +16 -54
- package/lib/core/types/index.d.ts +1 -0
- package/lib/core/types/l10n.d.ts +1 -1
- package/lib/core/types/prompt.d.ts +9 -0
- package/lib/core/types/prompt.js +3 -0
- package/lib/core/utils/get-ai-prompt-link.d.ts +15 -0
- package/lib/core/utils/get-ai-prompt-link.js +29 -0
- package/lib/core/utils/index.d.ts +1 -0
- package/lib/core/utils/index.js +1 -0
- package/lib/core/utils/urls.js +1 -1
- package/lib/core/utils/with-load-progress.d.ts +3 -0
- package/lib/core/utils/with-load-progress.js +24 -19
- package/lib/ext/configure.d.ts +1 -1
- package/lib/ext/configure.js +0 -1
- package/lib/icons/LinkIcon/LinkIconSymbol.d.ts +12 -0
- package/lib/icons/LinkIcon/LinkIconSymbol.js +41 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/markdoc/components/Cards/Card.js +1 -1
- package/lib/markdoc/components/Prompt/Prompt.d.ts +15 -0
- package/lib/markdoc/components/Prompt/Prompt.js +163 -0
- package/lib/markdoc/components/Prompt/PromptActions.d.ts +13 -0
- package/lib/markdoc/components/Prompt/PromptActions.js +43 -0
- package/lib/markdoc/components/Prompt/PromptBody.d.ts +14 -0
- package/lib/markdoc/components/Prompt/PromptBody.js +99 -0
- package/lib/markdoc/components/Prompt/PromptCopyButton.d.ts +10 -0
- package/lib/markdoc/components/Prompt/PromptCopyButton.js +28 -0
- package/lib/markdoc/components/Prompt/PromptHeader.d.ts +9 -0
- package/lib/markdoc/components/Prompt/PromptHeader.js +57 -0
- package/lib/markdoc/components/Prompt/PromptShowHideButton.d.ts +7 -0
- package/lib/markdoc/components/Prompt/PromptShowHideButton.js +21 -0
- package/lib/markdoc/components/Prompt/PromptToggleLabel.d.ts +7 -0
- package/lib/markdoc/components/Prompt/PromptToggleLabel.js +28 -0
- package/lib/markdoc/components/Prompt/variables.d.ts +1 -0
- package/lib/markdoc/components/Prompt/variables.dark.d.ts +1 -0
- package/lib/markdoc/components/Prompt/variables.dark.js +8 -0
- package/lib/markdoc/components/Prompt/variables.js +44 -0
- package/lib/markdoc/components/default.d.ts +1 -0
- package/lib/markdoc/components/default.js +1 -0
- package/lib/markdoc/default.d.ts +2 -0
- package/lib/markdoc/default.js +2 -0
- package/lib/markdoc/tags/code-walkthrough.d.ts +1 -1
- package/lib/markdoc/tags/code-walkthrough.js +3 -5
- package/lib/markdoc/tags/prompt.d.ts +2 -0
- package/lib/markdoc/tags/prompt.js +56 -0
- package/package.json +2 -7
- package/src/components/LoadProgressBar/LoadProgressBar.tsx +113 -0
- package/src/core/constants/index.ts +1 -0
- package/src/core/constants/prompt.ts +34 -0
- package/src/core/hooks/__mocks__/index.ts +3 -0
- package/src/core/hooks/__mocks__/use-theme-hooks.ts +2 -0
- package/src/core/hooks/index.ts +3 -0
- package/src/core/hooks/prompt/use-prompt-actions.ts +28 -0
- package/src/core/hooks/prompt/use-prompt-text-limit.ts +59 -0
- package/src/core/hooks/use-page-actions.ts +4 -9
- package/src/core/hooks/use-pointer-border-highlight.ts +46 -0
- package/src/core/hooks/use-telemetry-fallback.ts +2 -0
- package/src/core/styles/dark.ts +2 -0
- package/src/core/styles/global.ts +2 -40
- package/src/core/types/index.ts +1 -0
- package/src/core/types/l10n.ts +11 -0
- package/src/core/types/prompt.ts +11 -0
- package/src/core/utils/get-ai-prompt-link.ts +30 -0
- package/src/core/utils/index.ts +1 -0
- package/src/core/utils/urls.ts +1 -1
- package/src/core/utils/with-load-progress.ts +23 -18
- package/src/ext/configure.ts +1 -1
- package/src/icons/LinkIcon/LinkIconSymbol.tsx +51 -0
- package/src/index.ts +1 -0
- package/src/markdoc/components/Cards/Card.tsx +1 -1
- package/src/markdoc/components/Prompt/Prompt.tsx +219 -0
- package/src/markdoc/components/Prompt/PromptActions.tsx +104 -0
- package/src/markdoc/components/Prompt/PromptBody.tsx +107 -0
- package/src/markdoc/components/Prompt/PromptCopyButton.tsx +73 -0
- package/src/markdoc/components/Prompt/PromptHeader.tsx +81 -0
- package/src/markdoc/components/Prompt/PromptShowHideButton.tsx +43 -0
- package/src/markdoc/components/Prompt/PromptToggleLabel.tsx +41 -0
- package/src/markdoc/components/Prompt/variables.dark.ts +5 -0
- package/src/markdoc/components/Prompt/variables.ts +41 -0
- package/src/markdoc/components/default.ts +1 -0
- package/src/markdoc/default.ts +2 -0
- package/src/markdoc/tags/code-walkthrough.ts +4 -12
- package/src/markdoc/tags/prompt.ts +58 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.PromptBody = PromptBody;
|
|
40
|
+
const react_1 = __importDefault(require("react"));
|
|
41
|
+
const styled_components_1 = __importStar(require("styled-components"));
|
|
42
|
+
const Button_1 = require("../../../components/Button/Button");
|
|
43
|
+
const ChevronDownIcon_1 = require("../../../icons/ChevronDownIcon/ChevronDownIcon");
|
|
44
|
+
const ChevronUpIcon_1 = require("../../../icons/ChevronUpIcon/ChevronUpIcon");
|
|
45
|
+
const hooks_1 = require("../../../core/hooks");
|
|
46
|
+
function PromptBody({ prompt, textRef, textLimit, isExpanded, hasHiddenText, onToggleExpanded, controls, className, }) {
|
|
47
|
+
const { useTranslate } = (0, hooks_1.useThemeHooks)();
|
|
48
|
+
const { translate } = useTranslate();
|
|
49
|
+
return (react_1.default.createElement(PromptBodyWrapper, { "data-component-name": "Markdoc/Prompt/PromptBody", className: className },
|
|
50
|
+
react_1.default.createElement(ZoneWrapper, null,
|
|
51
|
+
react_1.default.createElement(TextWrapper, { ref: textRef, $textLimit: textLimit }, prompt),
|
|
52
|
+
controls),
|
|
53
|
+
hasHiddenText || isExpanded ? (react_1.default.createElement(Button_1.Button, { variant: "ghost", size: "small", icon: isExpanded ? react_1.default.createElement(ChevronUpIcon_1.ChevronUpIcon, null) : react_1.default.createElement(ChevronDownIcon_1.ChevronDownIcon, null), iconPosition: "right", onClick: onToggleExpanded }, isExpanded
|
|
54
|
+
? translate('promptTag.showLess', 'Show less')
|
|
55
|
+
: translate('promptTag.showFullPrompt', 'Show full prompt'))) : null));
|
|
56
|
+
}
|
|
57
|
+
const PromptBodyWrapper = styled_components_1.default.div `
|
|
58
|
+
display: flex;
|
|
59
|
+
flex-direction: column;
|
|
60
|
+
align-items: flex-start;
|
|
61
|
+
gap: var(--prompt-body-toggle-gap);
|
|
62
|
+
`;
|
|
63
|
+
const ZoneWrapper = styled_components_1.default.div `
|
|
64
|
+
display: flex;
|
|
65
|
+
align-items: flex-start;
|
|
66
|
+
width: 100%;
|
|
67
|
+
gap: var(--prompt-body-gap);
|
|
68
|
+
padding: var(--prompt-body-padding-vertical) var(--prompt-body-padding-horizontal);
|
|
69
|
+
background-color: var(--prompt-body-bg-color);
|
|
70
|
+
border-radius: var(--prompt-body-border-radius);
|
|
71
|
+
`;
|
|
72
|
+
/* width: 0 keeps the nowrap text from widening the block; flex-grow gives the text the real width. */
|
|
73
|
+
const TextWrapper = styled_components_1.default.div `
|
|
74
|
+
flex: 1 1 0;
|
|
75
|
+
width: 0;
|
|
76
|
+
min-width: 0;
|
|
77
|
+
white-space: pre-wrap;
|
|
78
|
+
overflow: visible;
|
|
79
|
+
overflow-wrap: anywhere;
|
|
80
|
+
font-size: var(--prompt-body-font-size);
|
|
81
|
+
line-height: var(--prompt-body-line-height);
|
|
82
|
+
color: var(--prompt-body-text-color);
|
|
83
|
+
|
|
84
|
+
${({ $textLimit }) => $textLimit === 'maxLines' &&
|
|
85
|
+
(0, styled_components_1.css) `
|
|
86
|
+
display: -webkit-box;
|
|
87
|
+
-webkit-box-orient: vertical;
|
|
88
|
+
-webkit-line-clamp: var(--prompt-body-max-lines);
|
|
89
|
+
overflow: hidden;
|
|
90
|
+
`}
|
|
91
|
+
|
|
92
|
+
${({ $textLimit }) => $textLimit === 'oneLine' &&
|
|
93
|
+
(0, styled_components_1.css) `
|
|
94
|
+
white-space: nowrap;
|
|
95
|
+
overflow: hidden;
|
|
96
|
+
text-overflow: ellipsis;
|
|
97
|
+
`}
|
|
98
|
+
`;
|
|
99
|
+
//# sourceMappingURL=PromptBody.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { JSX } from 'react';
|
|
2
|
+
export type PromptCopyButtonPlacement = 'header' | 'body' | 'standalone';
|
|
3
|
+
export type PromptCopyButtonProps = {
|
|
4
|
+
prompt: string;
|
|
5
|
+
/** `header` next to the split button, `body` inside the prompt zone, `standalone` for the button-only variant. */
|
|
6
|
+
placement: PromptCopyButtonPlacement;
|
|
7
|
+
onCopy: () => void;
|
|
8
|
+
className?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function PromptCopyButton({ prompt, placement, onCopy, className, }: PromptCopyButtonProps): JSX.Element;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PromptCopyButton = PromptCopyButton;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const styled_components_1 = __importDefault(require("styled-components"));
|
|
9
|
+
const CopyButton_1 = require("../../../components/Buttons/CopyButton");
|
|
10
|
+
const hooks_1 = require("../../../core/hooks");
|
|
11
|
+
function PromptCopyButton({ prompt, placement, onCopy, className, }) {
|
|
12
|
+
const { useTranslate } = (0, hooks_1.useThemeHooks)();
|
|
13
|
+
const { translate } = useTranslate();
|
|
14
|
+
if (placement === 'standalone') {
|
|
15
|
+
return (react_1.default.createElement(CopyButton_1.CopyButton, { data: prompt, type: "compound", variant: "secondary", size: "small", buttonText: translate('promptTag.copy.buttonText', 'Copy prompt'), onCopyClick: onCopy, dataTestId: "prompt-copy-button", className: className }));
|
|
16
|
+
}
|
|
17
|
+
if (placement === 'header') {
|
|
18
|
+
return (react_1.default.createElement(HeaderCopyButtonWrapper, { data: prompt, variant: "outlined", size: "small", onCopyClick: onCopy, dataTestId: "prompt-header-copy-button", className: className }));
|
|
19
|
+
}
|
|
20
|
+
return (react_1.default.createElement(CopyButton_1.CopyButton, { data: prompt, variant: "text", size: "small", onCopyClick: onCopy, dataTestId: "prompt-copy-button", className: className }));
|
|
21
|
+
}
|
|
22
|
+
/* The outlined border adds to the box; the smaller padding keeps the 24px height of the sibling buttons. */
|
|
23
|
+
const HeaderCopyButtonWrapper = (0, styled_components_1.default)(CopyButton_1.CopyButton) `
|
|
24
|
+
&& .button {
|
|
25
|
+
--button-icon-padding: var(--prompt-header-copy-button-padding);
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
28
|
+
//# sourceMappingURL=PromptCopyButton.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { JSX, ReactNode } from 'react';
|
|
2
|
+
export type PromptHeaderProps = {
|
|
3
|
+
title?: string;
|
|
4
|
+
icon?: string;
|
|
5
|
+
iconRawContent?: string;
|
|
6
|
+
controls?: ReactNode;
|
|
7
|
+
className?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function PromptHeader({ title, icon, iconRawContent, controls, className, }: PromptHeaderProps): JSX.Element;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PromptHeader = PromptHeader;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const styled_components_1 = __importDefault(require("styled-components"));
|
|
9
|
+
const AiStarsIcon_1 = require("../../../icons/AiStarsIcon/AiStarsIcon");
|
|
10
|
+
const GenericIcon_1 = require("../../../icons/GenericIcon/GenericIcon");
|
|
11
|
+
function PromptHeader({ title, icon, iconRawContent, controls, className, }) {
|
|
12
|
+
return (react_1.default.createElement(PromptHeaderWrapper, { "data-component-name": "Markdoc/Prompt/PromptHeader", className: className },
|
|
13
|
+
react_1.default.createElement(IconWrapper, null, icon ? (react_1.default.createElement(GenericIcon_1.GenericIcon, { icon: icon, rawContent: iconRawContent })) : (react_1.default.createElement(AiStarsIcon_1.AiStarsIcon, { color: "--prompt-icon-color" }))),
|
|
14
|
+
title ? react_1.default.createElement(TitleWrapper, null, title) : null,
|
|
15
|
+
controls ? react_1.default.createElement(ControlsWrapper, null, controls) : null));
|
|
16
|
+
}
|
|
17
|
+
const PromptHeaderWrapper = styled_components_1.default.div `
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
gap: var(--prompt-header-gap);
|
|
21
|
+
`;
|
|
22
|
+
const IconWrapper = styled_components_1.default.div `
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
flex-shrink: 0;
|
|
27
|
+
width: var(--prompt-icon-size);
|
|
28
|
+
height: var(--prompt-icon-size);
|
|
29
|
+
color: var(--prompt-icon-color);
|
|
30
|
+
--icon-width: var(--prompt-icon-size);
|
|
31
|
+
--icon-height: var(--prompt-icon-size);
|
|
32
|
+
--icon-color: var(--prompt-icon-color);
|
|
33
|
+
|
|
34
|
+
svg {
|
|
35
|
+
width: 100%;
|
|
36
|
+
height: 100%;
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
const TitleWrapper = styled_components_1.default.div `
|
|
40
|
+
flex: 1;
|
|
41
|
+
min-width: 0;
|
|
42
|
+
overflow: hidden;
|
|
43
|
+
text-overflow: ellipsis;
|
|
44
|
+
white-space: nowrap;
|
|
45
|
+
font-size: var(--prompt-title-font-size);
|
|
46
|
+
font-weight: var(--prompt-title-font-weight);
|
|
47
|
+
line-height: var(--prompt-title-line-height);
|
|
48
|
+
color: var(--prompt-title-text-color);
|
|
49
|
+
`;
|
|
50
|
+
const ControlsWrapper = styled_components_1.default.div `
|
|
51
|
+
display: flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
flex-shrink: 0;
|
|
54
|
+
margin-left: auto;
|
|
55
|
+
gap: var(--prompt-header-actions-gap);
|
|
56
|
+
`;
|
|
57
|
+
//# sourceMappingURL=PromptHeader.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { JSX } from 'react';
|
|
2
|
+
export type PromptShowHideButtonProps = {
|
|
3
|
+
isPromptVisible: boolean;
|
|
4
|
+
onToggle: () => void;
|
|
5
|
+
className?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function PromptShowHideButton({ isPromptVisible, onToggle, className, }: PromptShowHideButtonProps): JSX.Element;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PromptShowHideButton = PromptShowHideButton;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const Button_1 = require("../../../components/Button/Button");
|
|
9
|
+
const ChevronDownIcon_1 = require("../../../icons/ChevronDownIcon/ChevronDownIcon");
|
|
10
|
+
const ChevronUpIcon_1 = require("../../../icons/ChevronUpIcon/ChevronUpIcon");
|
|
11
|
+
const hooks_1 = require("../../../core/hooks");
|
|
12
|
+
const PromptToggleLabel_1 = require("../../../markdoc/components/Prompt/PromptToggleLabel");
|
|
13
|
+
function PromptShowHideButton({ isPromptVisible, onToggle, className, }) {
|
|
14
|
+
const { useTranslate } = (0, hooks_1.useThemeHooks)();
|
|
15
|
+
const { translate } = useTranslate();
|
|
16
|
+
const showPromptLabel = translate('promptTag.showPrompt', 'Show prompt');
|
|
17
|
+
const hidePromptLabel = translate('promptTag.hidePrompt', 'Hide prompt');
|
|
18
|
+
return (react_1.default.createElement(Button_1.Button, { "data-component-name": "Markdoc/Prompt/PromptShowHideButton", className: className, variant: "text", size: "small", icon: isPromptVisible ? react_1.default.createElement(ChevronUpIcon_1.ChevronUpIcon, null) : react_1.default.createElement(ChevronDownIcon_1.ChevronDownIcon, null), iconPosition: "right", onClick: onToggle },
|
|
19
|
+
react_1.default.createElement(PromptToggleLabel_1.PromptToggleLabel, { active: isPromptVisible ? hidePromptLabel : showPromptLabel, inactive: isPromptVisible ? showPromptLabel : hidePromptLabel })));
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=PromptShowHideButton.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PromptToggleLabel = PromptToggleLabel;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const styled_components_1 = __importDefault(require("styled-components"));
|
|
9
|
+
/* Both labels share one grid cell, so the toggle keeps the width of the longer label
|
|
10
|
+
and the buttons next to it do not move when the label changes. */
|
|
11
|
+
function PromptToggleLabel({ active, inactive, className, }) {
|
|
12
|
+
return (react_1.default.createElement(PromptToggleLabelWrapper, { "data-component-name": "Markdoc/Prompt/PromptToggleLabel", className: className },
|
|
13
|
+
react_1.default.createElement("span", null, active),
|
|
14
|
+
react_1.default.createElement("span", { "aria-hidden": "true" }, inactive)));
|
|
15
|
+
}
|
|
16
|
+
const PromptToggleLabelWrapper = styled_components_1.default.span `
|
|
17
|
+
display: grid;
|
|
18
|
+
text-align: center;
|
|
19
|
+
|
|
20
|
+
> span {
|
|
21
|
+
grid-area: 1 / 1;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
> span[aria-hidden='true'] {
|
|
25
|
+
visibility: hidden;
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
28
|
+
//# sourceMappingURL=PromptToggleLabel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const promptTag: import("styled-components").RuleSet<object>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const promptTagDarkMode: import("styled-components").RuleSet<object>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.promptTagDarkMode = void 0;
|
|
4
|
+
const styled_components_1 = require("styled-components");
|
|
5
|
+
exports.promptTagDarkMode = (0, styled_components_1.css) `
|
|
6
|
+
--prompt-body-bg-color: var(--color-brand-subtle-bg, var(--color-warm-grey-3)); // @presenter Color
|
|
7
|
+
`;
|
|
8
|
+
//# sourceMappingURL=variables.dark.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.promptTag = void 0;
|
|
4
|
+
const styled_components_1 = require("styled-components");
|
|
5
|
+
exports.promptTag = (0, styled_components_1.css) `
|
|
6
|
+
/**
|
|
7
|
+
* @tokens Prompt
|
|
8
|
+
**/
|
|
9
|
+
--prompt-bg-color: var(--bg-color); // @presenter Color
|
|
10
|
+
--prompt-border-color: var(--border-color-secondary); // @presenter Color
|
|
11
|
+
--prompt-border-width: var(--border-width); // @presenter Border
|
|
12
|
+
--prompt-border-radius: var(--border-radius-xl); // @presenter BorderRadius
|
|
13
|
+
--prompt-margin: var(--spacing-base) 0; // @presenter Spacing
|
|
14
|
+
--prompt-padding-vertical: var(--spacing-sm); // @presenter Spacing
|
|
15
|
+
--prompt-padding-horizontal: var(--spacing-base); // @presenter Spacing
|
|
16
|
+
--prompt-gap: var(--spacing-sm); // @presenter Spacing
|
|
17
|
+
--prompt-border-highlight-color-start: var(--search-ai-gradient-start-color, var(--search-ai-gradient-start-color-legacy)); // @presenter Color
|
|
18
|
+
--prompt-border-highlight-color-end: var(--search-ai-gradient-end-color, var(--search-ai-gradient-end-color-legacy)); // @presenter Color
|
|
19
|
+
--prompt-border-highlight-size: 120px;
|
|
20
|
+
--prompt-border-highlight-transition: opacity 0.2s ease-out;
|
|
21
|
+
|
|
22
|
+
--prompt-header-gap: var(--spacing-xs); // @presenter Spacing
|
|
23
|
+
--prompt-header-actions-gap: var(--spacing-xxs); // @presenter Spacing
|
|
24
|
+
--prompt-header-copy-button-padding: var(--spacing-xxs); // @presenter Spacing
|
|
25
|
+
--prompt-icon-size: 18px;
|
|
26
|
+
--prompt-icon-color: var(--color-primary-base, var(--color-warm-grey-11)); // @presenter Color
|
|
27
|
+
--prompt-title-font-size: var(--font-size-base); // @presenter FontSize
|
|
28
|
+
--prompt-title-font-weight: var(--font-weight-semibold); // @presenter FontWeight
|
|
29
|
+
--prompt-title-line-height: var(--line-height-base); // @presenter LineHeight
|
|
30
|
+
--prompt-title-text-color: var(--text-color-primary); // @presenter Color
|
|
31
|
+
|
|
32
|
+
--prompt-body-bg-color: var(--color-primary-bg, var(--color-warm-grey-2)); // @presenter Color
|
|
33
|
+
--prompt-body-border-radius: var(--border-radius-lg); // @presenter BorderRadius
|
|
34
|
+
--prompt-body-padding-vertical: var(--spacing-xs); // @presenter Spacing
|
|
35
|
+
--prompt-body-padding-horizontal: var(--spacing-sm); // @presenter Spacing
|
|
36
|
+
--prompt-body-gap: var(--spacing-xxs); // @presenter Spacing
|
|
37
|
+
--prompt-body-font-size: var(--font-size-base); // @presenter FontSize
|
|
38
|
+
--prompt-body-line-height: var(--line-height-base); // @presenter LineHeight
|
|
39
|
+
--prompt-body-text-color: var(--text-color-primary); // @presenter Color
|
|
40
|
+
--prompt-body-max-lines: 5;
|
|
41
|
+
--prompt-body-toggle-gap: var(--spacing-xxs); // @presenter Spacing
|
|
42
|
+
// @tokens End
|
|
43
|
+
`;
|
|
44
|
+
//# sourceMappingURL=variables.js.map
|
|
@@ -28,3 +28,4 @@ export * from '../../markdoc/components/Icon/Icon';
|
|
|
28
28
|
export * from '../../markdoc/components/ConnectMCP/ConnectMCP';
|
|
29
29
|
export * from '../../markdoc/components/LoginButton/LoginButton';
|
|
30
30
|
export * from '../../markdoc/components/MarkdownLink/MarkdownLink';
|
|
31
|
+
export * from '../../markdoc/components/Prompt/Prompt';
|
|
@@ -44,4 +44,5 @@ __exportStar(require("../../markdoc/components/Icon/Icon"), exports);
|
|
|
44
44
|
__exportStar(require("../../markdoc/components/ConnectMCP/ConnectMCP"), exports);
|
|
45
45
|
__exportStar(require("../../markdoc/components/LoginButton/LoginButton"), exports);
|
|
46
46
|
__exportStar(require("../../markdoc/components/MarkdownLink/MarkdownLink"), exports);
|
|
47
|
+
__exportStar(require("../../markdoc/components/Prompt/Prompt"), exports);
|
|
47
48
|
//# sourceMappingURL=default.js.map
|
package/lib/markdoc/default.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ import { icon } from '../markdoc/tags/icon';
|
|
|
30
30
|
import { connectMcp } from '../markdoc/tags/connect-mcp';
|
|
31
31
|
import { loginButton } from '../markdoc/tags/login-button';
|
|
32
32
|
import { diagram } from '../markdoc/tags/diagram';
|
|
33
|
+
import { prompt } from '../markdoc/tags/prompt';
|
|
33
34
|
export declare const tags: {
|
|
34
35
|
[accordion.tagName]: import("./tags/types").MarkdocTagSchema;
|
|
35
36
|
[accordionGroup.tagName]: import("./tags/types").MarkdocTagSchema;
|
|
@@ -56,4 +57,5 @@ export declare const tags: {
|
|
|
56
57
|
[connectMcp.tagName]: import("./tags/types").MarkdocTagSchema;
|
|
57
58
|
[loginButton.tagName]: import("./tags/types").MarkdocTagSchema;
|
|
58
59
|
[diagram.tagName]: import("./tags/types").MarkdocTagSchema;
|
|
60
|
+
[prompt.tagName]: import("./tags/types").MarkdocTagSchema;
|
|
59
61
|
};
|
package/lib/markdoc/default.js
CHANGED
|
@@ -72,6 +72,7 @@ const icon_1 = require("../markdoc/tags/icon");
|
|
|
72
72
|
const connect_mcp_1 = require("../markdoc/tags/connect-mcp");
|
|
73
73
|
const login_button_1 = require("../markdoc/tags/login-button");
|
|
74
74
|
const diagram_1 = require("../markdoc/tags/diagram");
|
|
75
|
+
const prompt_1 = require("../markdoc/tags/prompt");
|
|
75
76
|
exports.tags = {
|
|
76
77
|
[accordion_1.accordion.tagName]: accordion_1.accordion.schema,
|
|
77
78
|
[accordion_group_1.accordionGroup.tagName]: accordion_group_1.accordionGroup.schema,
|
|
@@ -98,5 +99,6 @@ exports.tags = {
|
|
|
98
99
|
[connect_mcp_1.connectMcp.tagName]: connect_mcp_1.connectMcp.schema,
|
|
99
100
|
[login_button_1.loginButton.tagName]: login_button_1.loginButton.schema,
|
|
100
101
|
[diagram_1.diagram.tagName]: diagram_1.diagram.schema,
|
|
102
|
+
[prompt_1.prompt.tagName]: prompt_1.prompt.schema,
|
|
101
103
|
};
|
|
102
104
|
//# sourceMappingURL=default.js.map
|
|
@@ -2,7 +2,7 @@ import type { Node, RenderableTreeNode } from '@markdoc/markdoc';
|
|
|
2
2
|
import type { MarkdocSchemaWrapper } from '../../markdoc/tags/types';
|
|
3
3
|
import type { CodeWalkthroughConditions, CodeWalkthroughFilter, TogglesMarkdocAttr, InputsMarkdocAttr } from '../../core/types';
|
|
4
4
|
export declare const codeWalkthrough: MarkdocSchemaWrapper;
|
|
5
|
-
export declare function collectStepsFromChildren(children: RenderableTreeNode[]
|
|
5
|
+
export declare function collectStepsFromChildren(children: RenderableTreeNode[]): RenderableTreeNode[];
|
|
6
6
|
export declare function collectTogglesFromChildren(children: Node[], toggles?: TogglesMarkdocAttr): TogglesMarkdocAttr;
|
|
7
7
|
export declare function collectInputsFromChildren(children: RenderableTreeNode[], inputs?: InputsMarkdocAttr): InputsMarkdocAttr;
|
|
8
8
|
export declare function validateCodeWalkthroughCondition(conditions: CodeWalkthroughConditions, filters: Record<string, CodeWalkthroughFilter>, allToggles: string[]): string[];
|
|
@@ -56,9 +56,7 @@ exports.codeWalkthrough = {
|
|
|
56
56
|
const steps = collectStepsFromChildren(children);
|
|
57
57
|
const inputs = collectInputsFromChildren(children);
|
|
58
58
|
const toggles = collectTogglesFromChildren(node.children);
|
|
59
|
-
return new markdoc_1.default.Tag('CodeWalkthrough', Object.assign(Object.assign({}, attributes), { filters: node.attributes.filters || {}, filesets: node.attributes.resolvedFilesets || [], steps: steps.map((step) =>
|
|
60
|
-
return Object.assign({}, ((step === null || step === void 0 ? void 0 : step.attributes) || {}));
|
|
61
|
-
}), inputs,
|
|
59
|
+
return new markdoc_1.default.Tag('CodeWalkthrough', Object.assign(Object.assign({}, attributes), { filters: node.attributes.filters || {}, filesets: node.attributes.resolvedFilesets || [], steps: steps.map((step) => step.attributes), inputs,
|
|
62
60
|
toggles }), children);
|
|
63
61
|
},
|
|
64
62
|
validate(node) {
|
|
@@ -147,14 +145,14 @@ exports.codeWalkthrough = {
|
|
|
147
145
|
render: 'CodeWalkthrough',
|
|
148
146
|
},
|
|
149
147
|
};
|
|
150
|
-
function collectStepsFromChildren(children
|
|
148
|
+
function collectStepsFromChildren(children) {
|
|
151
149
|
return children.flatMap((child) => {
|
|
152
150
|
const isTag = markdoc_1.default.Tag.isTag(child);
|
|
153
151
|
if (!isTag)
|
|
154
152
|
return [];
|
|
155
153
|
if (child.name === 'CodeStep')
|
|
156
154
|
return [child];
|
|
157
|
-
return collectStepsFromChildren(child.children
|
|
155
|
+
return collectStepsFromChildren(child.children);
|
|
158
156
|
});
|
|
159
157
|
}
|
|
160
158
|
function collectTogglesFromChildren(children, toggles = {}) {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.prompt = void 0;
|
|
7
|
+
const markdoc_1 = __importDefault(require("@markdoc/markdoc"));
|
|
8
|
+
const constants_1 = require("../../core/constants");
|
|
9
|
+
const ALLOWED_ACTIONS = Object.values(constants_1.AI_PROMPT_TARGETS);
|
|
10
|
+
exports.prompt = {
|
|
11
|
+
schema: {
|
|
12
|
+
render: 'Prompt',
|
|
13
|
+
attributes: {
|
|
14
|
+
title: { type: String },
|
|
15
|
+
icon: { type: String, resolver: 'relativeOrCdnIcon' },
|
|
16
|
+
iconRawContent: { type: String, render: true }, // internal
|
|
17
|
+
actions: { type: Array, default: [] },
|
|
18
|
+
hidePrompt: { type: Boolean, default: false },
|
|
19
|
+
singleLine: { type: Boolean, default: false },
|
|
20
|
+
buttonOnly: { type: Boolean, default: false },
|
|
21
|
+
rawContent: { type: String, render: false, resolver: 'tagRawContent' }, // internal
|
|
22
|
+
},
|
|
23
|
+
transform(node, config) {
|
|
24
|
+
const attributes = node.transformAttributes(config);
|
|
25
|
+
const actions = Array.isArray(attributes.actions)
|
|
26
|
+
? [...new Set(attributes.actions.filter((action) => ALLOWED_ACTIONS.includes(action)))]
|
|
27
|
+
: [];
|
|
28
|
+
const prompt = getRawBody(node);
|
|
29
|
+
return new markdoc_1.default.Tag('Prompt', Object.assign(Object.assign({}, attributes), { actions, prompt }), []);
|
|
30
|
+
},
|
|
31
|
+
validate(node) {
|
|
32
|
+
const errors = [];
|
|
33
|
+
const { actions } = node.attributes;
|
|
34
|
+
if (Array.isArray(actions)) {
|
|
35
|
+
for (const action of actions) {
|
|
36
|
+
if (!ALLOWED_ACTIONS.includes(action)) {
|
|
37
|
+
errors.push({
|
|
38
|
+
id: 'prompt-unknown-action',
|
|
39
|
+
level: 'error',
|
|
40
|
+
message: `attribute "actions" contains unknown value "${action}"; allowed values: ${ALLOWED_ACTIONS.join(', ')}`,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return errors;
|
|
46
|
+
},
|
|
47
|
+
// The prompt is for human readers: it stays out of the .md page, llms.txt, and AI search.
|
|
48
|
+
renderForLlms: () => '',
|
|
49
|
+
},
|
|
50
|
+
tagName: constants_1.PROMPT_TAG,
|
|
51
|
+
};
|
|
52
|
+
function getRawBody(node) {
|
|
53
|
+
const rawContent = node.attributes.rawContent;
|
|
54
|
+
return typeof rawContent === 'string' ? rawContent : '';
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=prompt.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/theme",
|
|
3
|
-
"version": "0.70.0
|
|
3
|
+
"version": "0.70.0",
|
|
4
4
|
"description": "Shared UI components lib",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"theme",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@babel/core": "7.29.7",
|
|
44
44
|
"@markdoc/markdoc": "0.5.2",
|
|
45
|
-
"@redocly/realm-asyncapi-sdk": "0.16.0
|
|
45
|
+
"@redocly/realm-asyncapi-sdk": "0.16.0",
|
|
46
46
|
"@redocly/tooling-test-utils": "0.0.0",
|
|
47
47
|
"@shikijs/types": "3.21.0",
|
|
48
48
|
"@testing-library/react": "16.3.0",
|
|
@@ -52,7 +52,6 @@
|
|
|
52
52
|
"@types/lodash.debounce": "4.0.9",
|
|
53
53
|
"@types/lodash.throttle": "4.1.9",
|
|
54
54
|
"@types/node": "24.1.0",
|
|
55
|
-
"@types/nprogress": "0.2.3",
|
|
56
55
|
"@types/react": "^19.2.7",
|
|
57
56
|
"@types/react-dom": "^19.2.3",
|
|
58
57
|
"@vitest/coverage-v8": "4.1.11",
|
|
@@ -62,10 +61,7 @@
|
|
|
62
61
|
"resize-observer-polyfill": "1.5.1",
|
|
63
62
|
"rimraf": "5.0.7",
|
|
64
63
|
"styled-components": "^6.4.2",
|
|
65
|
-
"ts-node": "10.9.2",
|
|
66
64
|
"tsc-alias": "1.8.16",
|
|
67
|
-
"tsconfig-paths": "4.2.0",
|
|
68
|
-
"tsconfig-paths-webpack-plugin": "3.5.2",
|
|
69
65
|
"typescript": "6.0.3",
|
|
70
66
|
"vitest": "4.1.11",
|
|
71
67
|
"vitest-when": "0.6.2",
|
|
@@ -84,7 +80,6 @@
|
|
|
84
80
|
"jszip": "3.10.1",
|
|
85
81
|
"lodash.debounce": "^4.0.8",
|
|
86
82
|
"lodash.throttle": "4.1.1",
|
|
87
|
-
"nprogress": "0.2.0",
|
|
88
83
|
"openapi-sampler": "^1.7.6",
|
|
89
84
|
"react-calendar": "5.1.0",
|
|
90
85
|
"react-date-picker": "11.0.0"
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState, useSyncExternalStore } from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
|
|
4
|
+
import type { JSX } from 'react';
|
|
5
|
+
|
|
6
|
+
import { isLoadInProgress, subscribeToLoadProgress } from '@redocly/theme/core/utils';
|
|
7
|
+
|
|
8
|
+
export type LoadProgressBarProps = {
|
|
9
|
+
/** Also shows the bar while the host's own navigation is pending. */
|
|
10
|
+
pending?: boolean;
|
|
11
|
+
className?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const START = 0.08;
|
|
15
|
+
const MAX_PENDING = 0.994;
|
|
16
|
+
const TRICKLE_MS = 100;
|
|
17
|
+
const SETTLE_MS = 200;
|
|
18
|
+
// [below, step]: large steps at first, smaller ones near the end.
|
|
19
|
+
const TRICKLE_STEPS = [
|
|
20
|
+
[0.2, 0.1],
|
|
21
|
+
[0.5, 0.04],
|
|
22
|
+
[0.8, 0.02],
|
|
23
|
+
[0.99, 0.005],
|
|
24
|
+
] as const;
|
|
25
|
+
|
|
26
|
+
function trickle(progress: number): number {
|
|
27
|
+
const step = TRICKLE_STEPS.find(([below]) => progress < below)?.[1] ?? 0;
|
|
28
|
+
return Math.min(progress + step, MAX_PENDING);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** A top-of-page bar while a page load is pending. */
|
|
32
|
+
export function LoadProgressBar({
|
|
33
|
+
pending = false,
|
|
34
|
+
className,
|
|
35
|
+
}: LoadProgressBarProps): JSX.Element | null {
|
|
36
|
+
const loading = useSyncExternalStore(subscribeToLoadProgress, isLoadInProgress, () => false);
|
|
37
|
+
const active = pending || loading;
|
|
38
|
+
const [progress, setProgress] = useState<number | null>(null);
|
|
39
|
+
const [fading, setFading] = useState(false);
|
|
40
|
+
const shown = useRef(false);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (active) {
|
|
44
|
+
shown.current = true;
|
|
45
|
+
setFading(false);
|
|
46
|
+
setProgress((current) => (current === null || current === 1 ? START : current));
|
|
47
|
+
const timer = setInterval(
|
|
48
|
+
() => setProgress((current) => trickle(current ?? START)),
|
|
49
|
+
TRICKLE_MS,
|
|
50
|
+
);
|
|
51
|
+
return () => clearInterval(timer);
|
|
52
|
+
}
|
|
53
|
+
if (!shown.current) return undefined;
|
|
54
|
+
|
|
55
|
+
setProgress(1);
|
|
56
|
+
const fade = setTimeout(() => setFading(true), SETTLE_MS);
|
|
57
|
+
const hide = setTimeout(() => {
|
|
58
|
+
shown.current = false;
|
|
59
|
+
setProgress(null);
|
|
60
|
+
setFading(false);
|
|
61
|
+
}, SETTLE_MS * 2);
|
|
62
|
+
return () => {
|
|
63
|
+
clearTimeout(fade);
|
|
64
|
+
clearTimeout(hide);
|
|
65
|
+
};
|
|
66
|
+
}, [active]);
|
|
67
|
+
|
|
68
|
+
if (progress === null) return null;
|
|
69
|
+
|
|
70
|
+
// The id and class names come from the replaced nprogress library: custom styles target them.
|
|
71
|
+
return (
|
|
72
|
+
<LoadProgressBarWrapper
|
|
73
|
+
id="nprogress"
|
|
74
|
+
data-component-name="LoadProgressBar/LoadProgressBar"
|
|
75
|
+
className={className}
|
|
76
|
+
aria-hidden="true"
|
|
77
|
+
$fading={fading}
|
|
78
|
+
>
|
|
79
|
+
<Bar className="bar" $progress={progress}>
|
|
80
|
+
<Peg className="peg" />
|
|
81
|
+
</Bar>
|
|
82
|
+
</LoadProgressBarWrapper>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const LoadProgressBarWrapper = styled.div<{ $fading: boolean }>`
|
|
87
|
+
pointer-events: none;
|
|
88
|
+
opacity: ${({ $fading }) => ($fading ? 0 : 1)};
|
|
89
|
+
transition: opacity ${SETTLE_MS}ms linear;
|
|
90
|
+
`;
|
|
91
|
+
|
|
92
|
+
// The offset changes on each tick: as a styled rule, each value would add a class.
|
|
93
|
+
const Bar = styled.div.attrs<{ $progress: number }>(({ $progress }) => ({
|
|
94
|
+
style: { transform: `translate3d(${($progress - 1) * 100}%, 0, 0)` },
|
|
95
|
+
}))`
|
|
96
|
+
position: fixed;
|
|
97
|
+
z-index: var(--z-index-popover);
|
|
98
|
+
top: 0;
|
|
99
|
+
left: 0;
|
|
100
|
+
width: 100%;
|
|
101
|
+
height: var(--load-progress-bar-height);
|
|
102
|
+
background: var(--load-progress-bar-color);
|
|
103
|
+
transition: transform ${SETTLE_MS}ms ease;
|
|
104
|
+
`;
|
|
105
|
+
|
|
106
|
+
const Peg = styled.div`
|
|
107
|
+
position: absolute;
|
|
108
|
+
right: 0;
|
|
109
|
+
width: 100px;
|
|
110
|
+
height: 100%;
|
|
111
|
+
box-shadow: var(--load-progress-bar-shadow);
|
|
112
|
+
transform: rotate(3deg) translate(0, -4px);
|
|
113
|
+
`;
|