@redocly/theme 0.62.0-next.0 → 0.62.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/Catalog/CatalogEntity/CatalogEntity.js +2 -2
- package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar.js +1 -1
- package/lib/components/Catalog/CatalogEntity/CatalogEntityProperties/TagsProperty.js +2 -2
- package/lib/components/Catalog/CatalogTableView/CatalogTableViewRow.js +1 -1
- package/lib/components/JsonViewer/JsonViewer.js +1 -1
- package/lib/components/Search/SearchAiMessage.js +2 -2
- package/lib/core/hooks/use-page-actions.js +3 -3
- package/lib/core/hooks/use-unique-svg-ids.d.ts +6 -0
- package/lib/core/hooks/use-unique-svg-ids.js +15 -0
- package/lib/core/openapi/index.d.ts +1 -0
- package/lib/core/openapi/index.js +3 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.js +3 -0
- package/lib/layouts/DocumentationLayout.js +4 -25
- package/lib/layouts/DocumentationLayoutBottom.d.ts +11 -0
- package/lib/layouts/DocumentationLayoutBottom.js +28 -0
- package/lib/layouts/DocumentationLayoutTop.d.ts +13 -0
- package/lib/layouts/DocumentationLayoutTop.js +33 -0
- package/package.json +3 -3
- package/src/components/Catalog/CatalogEntity/CatalogEntity.tsx +1 -1
- package/src/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar.tsx +1 -2
- package/src/components/Catalog/CatalogEntity/CatalogEntityProperties/TagsProperty.tsx +1 -1
- package/src/components/Catalog/CatalogTableView/CatalogTableViewRow.tsx +1 -2
- package/src/components/JsonViewer/JsonViewer.tsx +1 -2
- package/src/components/Search/SearchAiMessage.tsx +2 -3
- package/src/core/hooks/__mocks__/use-theme-hooks.ts +1 -0
- package/src/core/hooks/use-page-actions.ts +3 -2
- package/src/core/hooks/use-unique-svg-ids.ts +12 -0
- package/src/core/openapi/index.ts +1 -0
- package/src/index.ts +3 -0
- package/src/layouts/DocumentationLayout.tsx +4 -30
- package/src/layouts/DocumentationLayoutBottom.tsx +42 -0
- package/src/layouts/DocumentationLayoutTop.tsx +52 -0
|
@@ -18,7 +18,7 @@ const hooks_1 = require("../../../core/hooks");
|
|
|
18
18
|
const CatalogEntitySchema_1 = require("../../../components/Catalog/CatalogEntity/CatalogEntitySchema");
|
|
19
19
|
const CatalogEntityMethodAndPath_1 = require("../../../components/Catalog/CatalogEntity/CatalogEntityMethodAndPath");
|
|
20
20
|
const CatalogEntityRelationsGraph_lazy_1 = require("../../../components/Catalog/CatalogEntity/CatalogEntityGraph/CatalogEntityRelationsGraph.lazy");
|
|
21
|
-
const
|
|
21
|
+
const CatalogEntityHistorySidebar_1 = require("../../../components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar");
|
|
22
22
|
const renderFirstColumnEntitySection = (entity) => {
|
|
23
23
|
switch (entity.type) {
|
|
24
24
|
case 'api-operation':
|
|
@@ -45,7 +45,7 @@ function CatalogEntity({ RedocSchema, StoreProvider, GraphqlTypeRenderer, }) {
|
|
|
45
45
|
const linkToMainCatalogLabel = translate(catalogConfig.titleTranslationKey);
|
|
46
46
|
const { searchQuery, setSearchQuery } = useCatalog();
|
|
47
47
|
return (react_1.default.createElement(CatalogPageWrapper, { "data-component-name": "Catalog/CatalogEntity/CatalogEntity" },
|
|
48
|
-
react_1.default.createElement(
|
|
48
|
+
react_1.default.createElement(CatalogEntityHistorySidebar_1.CatalogEntityHistorySidebar, { entityKey: entity.key, revision: revision, version: version }),
|
|
49
49
|
react_1.default.createElement(CatalogPageContent, null,
|
|
50
50
|
react_1.default.createElement(Breadcrumbs_1.Breadcrumbs, { additionalBreadcrumbs: [
|
|
51
51
|
{ label: linkToMainCatalogLabel, link: linkToMainCatalog },
|
package/lib/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar.js
CHANGED
|
@@ -45,7 +45,7 @@ const hooks_1 = require("../../../../core/hooks");
|
|
|
45
45
|
const MenuContainer_1 = require("../../../../components/Menu/MenuContainer");
|
|
46
46
|
const utils_1 = require("../../../../core/utils");
|
|
47
47
|
const constants_1 = require("../../../../core/constants");
|
|
48
|
-
const CatalogEntityVersionItem_1 = require("
|
|
48
|
+
const CatalogEntityVersionItem_1 = require("../../../../components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityVersionItem");
|
|
49
49
|
function CatalogEntityHistorySidebar({ entityKey, revision, version, className, }) {
|
|
50
50
|
const [isOpen, setIsOpen] = (0, react_1.useState)(false);
|
|
51
51
|
const location = (0, react_router_dom_1.useLocation)();
|
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.TagsProperty = TagsProperty;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
8
|
const TagsIcon_1 = require("../../../../icons/TagsIcon/TagsIcon");
|
|
9
|
-
const
|
|
9
|
+
const CatalogTagsWithTooltip_1 = require("../../../../components/Catalog/CatalogTagsWithTooltip");
|
|
10
10
|
const CatalogEntityPropertyCard_1 = require("../../../../components/Catalog/CatalogEntity/CatalogEntityProperties/CatalogEntityPropertyCard");
|
|
11
11
|
const hooks_1 = require("../../../../core/hooks");
|
|
12
12
|
function TagsProperty({ entity }) {
|
|
@@ -15,7 +15,7 @@ function TagsProperty({ entity }) {
|
|
|
15
15
|
return (react_1.default.createElement("div", { "data-component-name": "Catalog/CatalogEntity/CatalogEntityProperties/TagsProperty" },
|
|
16
16
|
react_1.default.createElement(CatalogEntityPropertyCard_1.CatalogEntityPropertyCard, { header: react_1.default.createElement(react_1.default.Fragment, null,
|
|
17
17
|
react_1.default.createElement(TagsIcon_1.TagsIcon, null),
|
|
18
|
-
translate('catalog.tags.label', 'Tags')), content: react_1.default.createElement(
|
|
18
|
+
translate('catalog.tags.label', 'Tags')), content: react_1.default.createElement(CatalogTagsWithTooltip_1.CatalogTagsWithTooltip, { itemsToShow: 8, items: entity.tags || [], tagProps: {
|
|
19
19
|
style: {
|
|
20
20
|
fontSize: 'var(--font-size-base)',
|
|
21
21
|
borderRadius: 'var(--border-radius)',
|
|
@@ -12,7 +12,7 @@ const CatalogEntityCell_1 = require("../../../components/Catalog/CatalogTableVie
|
|
|
12
12
|
const CatalogTagsCell_1 = require("../../../components/Catalog/CatalogTableView/CatalogTagsCell");
|
|
13
13
|
const hooks_1 = require("../../../core/hooks");
|
|
14
14
|
const CatalogEntityTypeTag_1 = require("../../../components/Catalog/CatalogEntityTypeTag");
|
|
15
|
-
const Link_1 = require("
|
|
15
|
+
const Link_1 = require("../../../components/Link/Link");
|
|
16
16
|
const baseColumns = [
|
|
17
17
|
{
|
|
18
18
|
key: 'entity',
|
|
@@ -40,7 +40,7 @@ exports.JsonViewerWrap = exports.JsonViewer = void 0;
|
|
|
40
40
|
const react_1 = __importStar(require("react"));
|
|
41
41
|
const styled_components_1 = __importDefault(require("styled-components"));
|
|
42
42
|
const CodeBlock_1 = require("../../components/CodeBlock/CodeBlock");
|
|
43
|
-
const Helpers_1 = require("
|
|
43
|
+
const Helpers_1 = require("../../components/JsonViewer/Helpers");
|
|
44
44
|
function JsonComponent({ data, expandLevel = 1, className, onCopyClick, onPanelToggle, title, controls = {}, }) {
|
|
45
45
|
const showFoldingButtons = data && Object.values(data).some((value) => typeof value === 'object' && value !== null);
|
|
46
46
|
const [expandAllSignal, setExpandAllSignal] = react_1.default.useState(undefined);
|
|
@@ -48,8 +48,8 @@ const Markdown_1 = require("../../components/Markdown/Markdown");
|
|
|
48
48
|
const DocumentIcon_1 = require("../../icons/DocumentIcon/DocumentIcon");
|
|
49
49
|
const AiStarsIcon_1 = require("../../icons/AiStarsIcon/AiStarsIcon");
|
|
50
50
|
const CheckmarkOutlineIcon_1 = require("../../icons/CheckmarkOutlineIcon/CheckmarkOutlineIcon");
|
|
51
|
-
const SearchAiActionButtons_1 = require("
|
|
52
|
-
const SearchAiNegativeFeedbackForm_1 = require("
|
|
51
|
+
const SearchAiActionButtons_1 = require("../../components/Search/SearchAiActionButtons");
|
|
52
|
+
const SearchAiNegativeFeedbackForm_1 = require("../../components/Search/SearchAiNegativeFeedbackForm");
|
|
53
53
|
function SearchAiMessageComponent({ role, content, isThinking, resources, className, messageId, feedback, onFeedbackChange, }) {
|
|
54
54
|
var _a;
|
|
55
55
|
const { useMarkdownText, useTranslate, useTelemetry } = (0, hooks_1.useThemeHooks)();
|
|
@@ -181,7 +181,7 @@ function createMCPAction({ clientType, mcpConfig, translate, onClickCallback, })
|
|
|
181
181
|
return Object.assign(Object.assign({}, sharedProps), { buttonText: translate('page.actions.connectMcp.vscode', 'Connect to VS Code'), title: translate('page.actions.connectMcp.vscode', 'Connect to VS Code'), description: translate('page.actions.connectMcp.vscodeDescription', 'Install MCP server on VS Code'), iconComponent: VSCodeIcon_1.VSCodeIcon });
|
|
182
182
|
}
|
|
183
183
|
function shouldHidePageActions(pageProps, themeConfig, openapiExcludeFromSearch) {
|
|
184
|
-
var _a, _b, _c, _d, _e, _f;
|
|
184
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
185
185
|
// Can't use any actions if no markdown files are generated for LLMs
|
|
186
186
|
if ((_b = (_a = pageProps === null || pageProps === void 0 ? void 0 : pageProps.seo) === null || _a === void 0 ? void 0 : _a.llmstxt) === null || _b === void 0 ? void 0 : _b.hide) {
|
|
187
187
|
return true;
|
|
@@ -191,8 +191,8 @@ function shouldHidePageActions(pageProps, themeConfig, openapiExcludeFromSearch)
|
|
|
191
191
|
return true;
|
|
192
192
|
}
|
|
193
193
|
// Page is excluded from search
|
|
194
|
-
const
|
|
195
|
-
|
|
194
|
+
const isOpenApiPage = ((_e = pageProps === null || pageProps === void 0 ? void 0 : pageProps.metadata) === null || _e === void 0 ? void 0 : _e.type) === 'openapi' || ((_f = pageProps === null || pageProps === void 0 ? void 0 : pageProps.metadata) === null || _f === void 0 ? void 0 : _f.subType) === 'openapi-operation';
|
|
195
|
+
const isPageExcludedFromSearch = ((_g = pageProps === null || pageProps === void 0 ? void 0 : pageProps.frontmatter) === null || _g === void 0 ? void 0 : _g.excludeFromSearch) || (isOpenApiPage && openapiExcludeFromSearch);
|
|
196
196
|
if (isPageExcludedFromSearch) {
|
|
197
197
|
return true;
|
|
198
198
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a function that appends a per-component-instance suffix to SVG ids.
|
|
3
|
+
* This prevents collisions when multiple identical SVGs are rendered on the same page,
|
|
4
|
+
* which can break `url(#...)` references (gradients, clipPath, masks, filters) on reflow.
|
|
5
|
+
*/
|
|
6
|
+
export declare function useUniqueSvgIds(): (id: string) => string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useUniqueSvgIds = useUniqueSvgIds;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
/**
|
|
6
|
+
* Returns a function that appends a per-component-instance suffix to SVG ids.
|
|
7
|
+
* This prevents collisions when multiple identical SVGs are rendered on the same page,
|
|
8
|
+
* which can break `url(#...)` references (gradients, clipPath, masks, filters) on reflow.
|
|
9
|
+
*/
|
|
10
|
+
function useUniqueSvgIds() {
|
|
11
|
+
const reactId = (0, react_1.useId)();
|
|
12
|
+
const safeSuffix = reactId.replace(/:/g, '_');
|
|
13
|
+
return (id) => `${id}-${safeSuffix}`;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=use-unique-svg-ids.js.map
|
|
@@ -25,3 +25,4 @@ export { SecurityVariablesEnvSuffix } from '../constants/environments';
|
|
|
25
25
|
export { isUndefined, isString, isNotNull, isObject } from '../utils/type-guards';
|
|
26
26
|
export { ThemeDataContext, type ThemeDataTransferObject } from '../contexts/ThemeDataContext';
|
|
27
27
|
export { SearchSessionProvider, SearchSessionContext } from '../contexts/SearchContext';
|
|
28
|
+
export { useUniqueSvgIds } from '../hooks/use-unique-svg-ids';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SearchSessionContext = exports.SearchSessionProvider = exports.ThemeDataContext = exports.isObject = exports.isNotNull = exports.isString = exports.isUndefined = exports.SecurityVariablesEnvSuffix = exports.useDialogHotKeys = exports.useSearchDialog = exports.useModalScrollLock = exports.useActiveSectionId = exports.useOutsideClick = exports.useThemeHooks = exports.useFocusTrap = exports.getUserAgent = exports.ClipboardService = exports.getOperationColor = exports.isPrimitive = exports.breakpoints = exports.GlobalStyle = exports.useMount = exports.typedMemo = exports.capitalize = exports.withPathPrefix = exports.addTrailingSlash = exports.combineUrls = exports.getPathPrefix = exports.removeLeadingSlash = exports.addLeadingSlash = exports.IS_BROWSER = void 0;
|
|
3
|
+
exports.useUniqueSvgIds = exports.SearchSessionContext = exports.SearchSessionProvider = exports.ThemeDataContext = exports.isObject = exports.isNotNull = exports.isString = exports.isUndefined = exports.SecurityVariablesEnvSuffix = exports.useDialogHotKeys = exports.useSearchDialog = exports.useModalScrollLock = exports.useActiveSectionId = exports.useOutsideClick = exports.useThemeHooks = exports.useFocusTrap = exports.getUserAgent = exports.ClipboardService = exports.getOperationColor = exports.isPrimitive = exports.breakpoints = exports.GlobalStyle = exports.useMount = exports.typedMemo = exports.capitalize = exports.withPathPrefix = exports.addTrailingSlash = exports.combineUrls = exports.getPathPrefix = exports.removeLeadingSlash = exports.addLeadingSlash = exports.IS_BROWSER = void 0;
|
|
4
4
|
var dom_1 = require("../utils/dom");
|
|
5
5
|
Object.defineProperty(exports, "IS_BROWSER", { enumerable: true, get: function () { return dom_1.IS_BROWSER; } });
|
|
6
6
|
var urls_1 = require("../utils/urls");
|
|
@@ -54,4 +54,6 @@ Object.defineProperty(exports, "ThemeDataContext", { enumerable: true, get: func
|
|
|
54
54
|
var SearchContext_1 = require("../contexts/SearchContext");
|
|
55
55
|
Object.defineProperty(exports, "SearchSessionProvider", { enumerable: true, get: function () { return SearchContext_1.SearchSessionProvider; } });
|
|
56
56
|
Object.defineProperty(exports, "SearchSessionContext", { enumerable: true, get: function () { return SearchContext_1.SearchSessionContext; } });
|
|
57
|
+
var use_unique_svg_ids_1 = require("../hooks/use-unique-svg-ids");
|
|
58
|
+
Object.defineProperty(exports, "useUniqueSvgIds", { enumerable: true, get: function () { return use_unique_svg_ids_1.useUniqueSvgIds; } });
|
|
57
59
|
//# sourceMappingURL=index.js.map
|
package/lib/index.d.ts
CHANGED
|
@@ -274,5 +274,8 @@ export * from './layouts/OIDCForbidden';
|
|
|
274
274
|
export * from './layouts/ThreePanelLayout';
|
|
275
275
|
export * from './layouts/CodeWalkthroughLayout';
|
|
276
276
|
export * from './layouts/InternalServerErrorLayout';
|
|
277
|
+
export * from './layouts/DocumentationLayout';
|
|
278
|
+
export * from './layouts/DocumentationLayoutTop';
|
|
279
|
+
export * from './layouts/DocumentationLayoutBottom';
|
|
277
280
|
export * as markdoc from './markdoc/default';
|
|
278
281
|
export * from './components/DatePicker/DatePicker';
|
package/lib/index.js
CHANGED
|
@@ -338,6 +338,9 @@ __exportStar(require("./layouts/OIDCForbidden"), exports);
|
|
|
338
338
|
__exportStar(require("./layouts/ThreePanelLayout"), exports);
|
|
339
339
|
__exportStar(require("./layouts/CodeWalkthroughLayout"), exports);
|
|
340
340
|
__exportStar(require("./layouts/InternalServerErrorLayout"), exports);
|
|
341
|
+
__exportStar(require("./layouts/DocumentationLayout"), exports);
|
|
342
|
+
__exportStar(require("./layouts/DocumentationLayoutTop"), exports);
|
|
343
|
+
__exportStar(require("./layouts/DocumentationLayoutBottom"), exports);
|
|
341
344
|
/* Markdoc */
|
|
342
345
|
exports.markdoc = __importStar(require("./markdoc/default"));
|
|
343
346
|
/* DatePicker */
|
|
@@ -6,26 +6,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.DocumentationLayout = DocumentationLayout;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
8
|
const styled_components_1 = __importDefault(require("styled-components"));
|
|
9
|
-
const EditPageButton_1 = require("../components/Buttons/EditPageButton");
|
|
10
9
|
const utils_1 = require("../core/utils");
|
|
11
|
-
const PageNavigation_1 = require("../components/PageNavigation/PageNavigation");
|
|
12
|
-
const LastUpdated_1 = require("../components/LastUpdated/LastUpdated");
|
|
13
|
-
const Breadcrumbs_1 = require("../components/Breadcrumbs/Breadcrumbs");
|
|
14
10
|
const CodeSnippetContext_1 = require("../core/contexts/CodeSnippetContext");
|
|
11
|
+
const DocumentationLayoutTop_1 = require("../layouts/DocumentationLayoutTop");
|
|
12
|
+
const DocumentationLayoutBottom_1 = require("../layouts/DocumentationLayoutBottom");
|
|
15
13
|
function DocumentationLayout({ tableOfContent, feedback, config, editPage, lastModified, nextPage, prevPage, className, children, }) {
|
|
16
14
|
var _a;
|
|
17
|
-
const { editPage: themeEditPage } = config || {};
|
|
18
|
-
const mergedConf = editPage ? Object.assign(Object.assign({}, themeEditPage), editPage) : undefined;
|
|
19
15
|
return (react_1.default.createElement(CodeSnippetContext_1.CodeSnippetProvider, null,
|
|
20
16
|
react_1.default.createElement(LayoutWrapper, { "data-component-name": "Layout/DocumentationLayout", className: className },
|
|
21
17
|
react_1.default.createElement(ContentWrapper, { withToc: !((_a = config === null || config === void 0 ? void 0 : config.toc) === null || _a === void 0 ? void 0 : _a.hide) },
|
|
22
|
-
react_1.default.createElement(
|
|
23
|
-
react_1.default.createElement(LayoutTop, null,
|
|
24
|
-
lastModified && react_1.default.createElement(LastUpdated_1.LastUpdated, { lastModified: new Date(lastModified) }),
|
|
25
|
-
mergedConf && react_1.default.createElement(EditPageButton_1.EditPageButton, { to: mergedConf.to })),
|
|
18
|
+
react_1.default.createElement(DocumentationLayoutTop_1.DocumentationLayoutTop, { config: config, editPage: editPage, lastModified: lastModified }),
|
|
26
19
|
children,
|
|
27
|
-
react_1.default.createElement(
|
|
28
|
-
react_1.default.createElement(PageNavigation_1.PageNavigation, { nextPage: nextPage, prevPage: prevPage })),
|
|
20
|
+
react_1.default.createElement(DocumentationLayoutBottom_1.DocumentationLayoutBottom, { feedback: feedback, nextPage: nextPage, prevPage: prevPage })),
|
|
29
21
|
tableOfContent)));
|
|
30
22
|
}
|
|
31
23
|
const LayoutWrapper = styled_components_1.default.div.attrs(({ className }) => ({
|
|
@@ -58,17 +50,4 @@ const ContentWrapper = styled_components_1.default.section `
|
|
|
58
50
|
width: ${({ withToc }) => (withToc ? `calc(90% - var(--toc-width))` : '90%')};
|
|
59
51
|
}
|
|
60
52
|
`;
|
|
61
|
-
const LayoutTop = styled_components_1.default.div `
|
|
62
|
-
display: flex;
|
|
63
|
-
justify-content: space-between;
|
|
64
|
-
flex-flow: row nowrap;
|
|
65
|
-
`;
|
|
66
|
-
const Breadcrumbs = (0, styled_components_1.default)(Breadcrumbs_1.Breadcrumbs) `
|
|
67
|
-
margin-bottom: var(--breadcrumbs-margin-bottom);
|
|
68
|
-
`;
|
|
69
|
-
const LayoutBottom = (0, styled_components_1.default)(LayoutTop) `
|
|
70
|
-
> * {
|
|
71
|
-
margin: 25px 0;
|
|
72
|
-
}
|
|
73
|
-
`;
|
|
74
53
|
//# sourceMappingURL=DocumentationLayout.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { JSX } from 'react';
|
|
3
|
+
import type { ResolvedNavItemWithLink } from '@redocly/config';
|
|
4
|
+
type DocumentationLayoutBottomProps = {
|
|
5
|
+
feedback: React.ReactNode;
|
|
6
|
+
nextPage?: ResolvedNavItemWithLink | null;
|
|
7
|
+
prevPage?: ResolvedNavItemWithLink | null;
|
|
8
|
+
className?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function DocumentationLayoutBottom({ feedback, nextPage, prevPage, }: React.PropsWithChildren<DocumentationLayoutBottomProps>): JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -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.DocumentationLayoutBottom = DocumentationLayoutBottom;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const styled_components_1 = __importDefault(require("styled-components"));
|
|
9
|
+
const PageNavigation_1 = require("../components/PageNavigation/PageNavigation");
|
|
10
|
+
function DocumentationLayoutBottom({ feedback, nextPage, prevPage, }) {
|
|
11
|
+
return (react_1.default.createElement(Wrapper, { "data-component-name": "Layout/DocumentationLayoutBottom" },
|
|
12
|
+
react_1.default.createElement(LayoutBottom, null, feedback),
|
|
13
|
+
react_1.default.createElement(PageNavigation_1.PageNavigation, { nextPage: nextPage, prevPage: prevPage })));
|
|
14
|
+
}
|
|
15
|
+
const Wrapper = styled_components_1.default.div `
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
`;
|
|
19
|
+
const LayoutBottom = styled_components_1.default.div `
|
|
20
|
+
display: flex;
|
|
21
|
+
justify-content: space-between;
|
|
22
|
+
flex-flow: row nowrap;
|
|
23
|
+
|
|
24
|
+
> * {
|
|
25
|
+
margin: 25px 0;
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
28
|
+
//# sourceMappingURL=DocumentationLayoutBottom.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { JSX } from 'react';
|
|
3
|
+
import type { MarkdownConfig } from '@redocly/config';
|
|
4
|
+
type DocumentationLayoutTopProps = {
|
|
5
|
+
config?: MarkdownConfig;
|
|
6
|
+
editPage?: {
|
|
7
|
+
to: string;
|
|
8
|
+
};
|
|
9
|
+
/** String in ISO format */
|
|
10
|
+
lastModified?: string | null;
|
|
11
|
+
};
|
|
12
|
+
export declare function DocumentationLayoutTop({ config, editPage, lastModified, }: React.PropsWithChildren<DocumentationLayoutTopProps>): JSX.Element;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
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.DocumentationLayoutTop = DocumentationLayoutTop;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const styled_components_1 = __importDefault(require("styled-components"));
|
|
9
|
+
const EditPageButton_1 = require("../components/Buttons/EditPageButton");
|
|
10
|
+
const LastUpdated_1 = require("../components/LastUpdated/LastUpdated");
|
|
11
|
+
const Breadcrumbs_1 = require("../components/Breadcrumbs/Breadcrumbs");
|
|
12
|
+
function DocumentationLayoutTop({ config, editPage, lastModified, }) {
|
|
13
|
+
const { editPage: themeEditPage } = config || {};
|
|
14
|
+
const mergedConf = editPage ? Object.assign(Object.assign({}, themeEditPage), editPage) : undefined;
|
|
15
|
+
return (react_1.default.createElement(Wrapper, { "data-component-name": "Layout/DocumentationLayoutTop" },
|
|
16
|
+
react_1.default.createElement(Breadcrumbs, null),
|
|
17
|
+
react_1.default.createElement(LayoutTop, null,
|
|
18
|
+
lastModified && react_1.default.createElement(LastUpdated_1.LastUpdated, { lastModified: new Date(lastModified) }),
|
|
19
|
+
mergedConf && react_1.default.createElement(EditPageButton_1.EditPageButton, { to: mergedConf.to }))));
|
|
20
|
+
}
|
|
21
|
+
const Wrapper = styled_components_1.default.div `
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: column;
|
|
24
|
+
`;
|
|
25
|
+
const LayoutTop = styled_components_1.default.div `
|
|
26
|
+
display: flex;
|
|
27
|
+
justify-content: space-between;
|
|
28
|
+
flex-flow: row nowrap;
|
|
29
|
+
`;
|
|
30
|
+
const Breadcrumbs = (0, styled_components_1.default)(Breadcrumbs_1.Breadcrumbs) `
|
|
31
|
+
margin-bottom: var(--breadcrumbs-margin-bottom);
|
|
32
|
+
`;
|
|
33
|
+
//# sourceMappingURL=DocumentationLayoutTop.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/theme",
|
|
3
|
-
"version": "0.62.0-next.
|
|
3
|
+
"version": "0.62.0-next.1",
|
|
4
4
|
"description": "Shared UI components lib",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"theme",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"vitest": "4.0.10",
|
|
64
64
|
"vitest-when": "0.6.2",
|
|
65
65
|
"webpack": "5.94.0",
|
|
66
|
-
"@redocly/realm-asyncapi-sdk": "0.8.0-next.
|
|
66
|
+
"@redocly/realm-asyncapi-sdk": "0.8.0-next.1"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
69
|
"@tanstack/react-query": "5.62.3",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"ts:check": "tsc --noEmit --skipLibCheck",
|
|
89
89
|
"clean": "rimraf lib",
|
|
90
90
|
"compile": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
91
|
-
"build": "
|
|
91
|
+
"build": "pnpm run clean && pnpm run compile",
|
|
92
92
|
"test": "vitest run",
|
|
93
93
|
"test:update": "vitest run --update",
|
|
94
94
|
"test:watch": "vitest",
|
|
@@ -20,7 +20,7 @@ import { useThemeHooks } from '@redocly/theme/core/hooks';
|
|
|
20
20
|
import { CatalogEntitySchema } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntitySchema';
|
|
21
21
|
import { CatalogEntityMethodAndPath } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityMethodAndPath';
|
|
22
22
|
import { CatalogEntityRelationsGraph } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityGraph/CatalogEntityRelationsGraph.lazy';
|
|
23
|
-
import { CatalogEntityHistorySidebar } from '@redocly/theme';
|
|
23
|
+
import { CatalogEntityHistorySidebar } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar';
|
|
24
24
|
|
|
25
25
|
export type CatalogEntityProps = {
|
|
26
26
|
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
package/src/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityHistorySidebar.tsx
CHANGED
|
@@ -7,8 +7,7 @@ import { useThemeHooks } from '@redocly/theme/core/hooks';
|
|
|
7
7
|
import { MenuContainer } from '@redocly/theme/components/Menu/MenuContainer';
|
|
8
8
|
import { transformRevisionsToVersionHistory } from '@redocly/theme/core/utils';
|
|
9
9
|
import { DEFAULT_LOCALE_PLACEHOLDER } from '@redocly/theme/core/constants';
|
|
10
|
-
|
|
11
|
-
import { CatalogEntityVersionItem } from './CatalogEntityVersionItem';
|
|
10
|
+
import { CatalogEntityVersionItem } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityHistory/CatalogEntityVersionItem';
|
|
12
11
|
|
|
13
12
|
export type CatalogHistorySidebarProps = {
|
|
14
13
|
entityKey: string;
|
|
@@ -2,7 +2,7 @@ import React, { JSX } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { BffCatalogEntity } from '@redocly/theme/core/types';
|
|
4
4
|
import { TagsIcon } from '@redocly/theme/icons/TagsIcon/TagsIcon';
|
|
5
|
-
import { CatalogTagsWithTooltip } from '@redocly/theme';
|
|
5
|
+
import { CatalogTagsWithTooltip } from '@redocly/theme/components/Catalog/CatalogTagsWithTooltip';
|
|
6
6
|
import { CatalogEntityPropertyCard } from '@redocly/theme/components/Catalog/CatalogEntity/CatalogEntityProperties/CatalogEntityPropertyCard';
|
|
7
7
|
import { useThemeHooks } from '@redocly/theme/core/hooks';
|
|
8
8
|
|
|
@@ -10,8 +10,7 @@ import { CatalogEntityCell } from '@redocly/theme/components/Catalog/CatalogTabl
|
|
|
10
10
|
import { CatalogTagsCell } from '@redocly/theme/components/Catalog/CatalogTableView/CatalogTagsCell';
|
|
11
11
|
import { useCatalogEntityDetails } from '@redocly/theme/core/hooks';
|
|
12
12
|
import { CatalogEntityTypeTag } from '@redocly/theme/components/Catalog/CatalogEntityTypeTag';
|
|
13
|
-
|
|
14
|
-
import { Link } from '../../Link/Link';
|
|
13
|
+
import { Link } from '@redocly/theme/components/Link/Link';
|
|
15
14
|
|
|
16
15
|
export type BaseEntity = {
|
|
17
16
|
id: string;
|
|
@@ -5,8 +5,7 @@ import type { JSX } from 'react';
|
|
|
5
5
|
import type { CodeBlockControlsProps } from '@redocly/theme/components/CodeBlock/CodeBlockControls';
|
|
6
6
|
|
|
7
7
|
import { CodeBlock } from '@redocly/theme/components/CodeBlock/CodeBlock';
|
|
8
|
-
|
|
9
|
-
import { JsonValue } from './Helpers';
|
|
8
|
+
import { JsonValue } from '@redocly/theme/components/JsonViewer/Helpers';
|
|
10
9
|
|
|
11
10
|
export type PanelType = 'request' | 'responses' | 'request-samples' | 'response-samples';
|
|
12
11
|
|
|
@@ -12,9 +12,8 @@ import { Markdown } from '@redocly/theme/components/Markdown/Markdown';
|
|
|
12
12
|
import { DocumentIcon } from '@redocly/theme/icons/DocumentIcon/DocumentIcon';
|
|
13
13
|
import { AiStarsIcon } from '@redocly/theme/icons/AiStarsIcon/AiStarsIcon';
|
|
14
14
|
import { CheckmarkOutlineIcon } from '@redocly/theme/icons/CheckmarkOutlineIcon/CheckmarkOutlineIcon';
|
|
15
|
-
|
|
16
|
-
import {
|
|
17
|
-
import { SearchAiNegativeFeedbackForm } from './SearchAiNegativeFeedbackForm';
|
|
15
|
+
import { SearchAiActionButtons } from '@redocly/theme/components/Search/SearchAiActionButtons';
|
|
16
|
+
import { SearchAiNegativeFeedbackForm } from '@redocly/theme/components/Search/SearchAiNegativeFeedbackForm';
|
|
18
17
|
|
|
19
18
|
export type SearchAiMessageProps = {
|
|
20
19
|
role: AiSearchConversationRole;
|
|
@@ -16,6 +16,7 @@ export const useThemeHooks = vi.fn(() => ({
|
|
|
16
16
|
send: vi.fn(),
|
|
17
17
|
sendCodeSnippetReportedMessage: vi.fn(),
|
|
18
18
|
sendPageActionsButtonClickedMessage: vi.fn(),
|
|
19
|
+
sendColorModeSwitchedMessage: vi.fn(),
|
|
19
20
|
})),
|
|
20
21
|
useBreadcrumbs: vi.fn().mockReturnValue({ breadcrumbs: [], siblings: undefined }),
|
|
21
22
|
useBanner: vi.fn(() => ({
|
|
@@ -280,9 +280,10 @@ function shouldHidePageActions(
|
|
|
280
280
|
}
|
|
281
281
|
|
|
282
282
|
// Page is excluded from search
|
|
283
|
+
const isOpenApiPage =
|
|
284
|
+
pageProps?.metadata?.type === 'openapi' || pageProps?.metadata?.subType === 'openapi-operation';
|
|
283
285
|
const isPageExcludedFromSearch =
|
|
284
|
-
pageProps?.frontmatter?.excludeFromSearch ||
|
|
285
|
-
(pageProps?.metadata?.type === 'openapi' && openapiExcludeFromSearch);
|
|
286
|
+
pageProps?.frontmatter?.excludeFromSearch || (isOpenApiPage && openapiExcludeFromSearch);
|
|
286
287
|
|
|
287
288
|
if (isPageExcludedFromSearch) {
|
|
288
289
|
return true;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useId } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns a function that appends a per-component-instance suffix to SVG ids.
|
|
5
|
+
* This prevents collisions when multiple identical SVGs are rendered on the same page,
|
|
6
|
+
* which can break `url(#...)` references (gradients, clipPath, masks, filters) on reflow.
|
|
7
|
+
*/
|
|
8
|
+
export function useUniqueSvgIds(): (id: string) => string {
|
|
9
|
+
const reactId = useId();
|
|
10
|
+
const safeSuffix = reactId.replace(/:/g, '_');
|
|
11
|
+
return (id: string): string => `${id}-${safeSuffix}`;
|
|
12
|
+
}
|
|
@@ -38,3 +38,4 @@ export { SecurityVariablesEnvSuffix } from '../constants/environments';
|
|
|
38
38
|
export { isUndefined, isString, isNotNull, isObject } from '../utils/type-guards';
|
|
39
39
|
export { ThemeDataContext, type ThemeDataTransferObject } from '../contexts/ThemeDataContext';
|
|
40
40
|
export { SearchSessionProvider, SearchSessionContext } from '../contexts/SearchContext';
|
|
41
|
+
export { useUniqueSvgIds } from '../hooks/use-unique-svg-ids';
|
package/src/index.ts
CHANGED
|
@@ -302,6 +302,9 @@ export * from '@redocly/theme/layouts/OIDCForbidden';
|
|
|
302
302
|
export * from '@redocly/theme/layouts/ThreePanelLayout';
|
|
303
303
|
export * from '@redocly/theme/layouts/CodeWalkthroughLayout';
|
|
304
304
|
export * from '@redocly/theme/layouts/InternalServerErrorLayout';
|
|
305
|
+
export * from '@redocly/theme/layouts/DocumentationLayout';
|
|
306
|
+
export * from '@redocly/theme/layouts/DocumentationLayoutTop';
|
|
307
|
+
export * from '@redocly/theme/layouts/DocumentationLayoutBottom';
|
|
305
308
|
/* Markdoc */
|
|
306
309
|
export * as markdoc from '@redocly/theme/markdoc/default';
|
|
307
310
|
/* DatePicker */
|
|
@@ -4,12 +4,10 @@ import styled from 'styled-components';
|
|
|
4
4
|
import type { JSX } from 'react';
|
|
5
5
|
import type { ResolvedNavItemWithLink, MarkdownConfig } from '@redocly/config';
|
|
6
6
|
|
|
7
|
-
import { EditPageButton } from '@redocly/theme/components/Buttons/EditPageButton';
|
|
8
7
|
import { breakpoints } from '@redocly/theme/core/utils';
|
|
9
|
-
import { PageNavigation } from '@redocly/theme/components/PageNavigation/PageNavigation';
|
|
10
|
-
import { LastUpdated } from '@redocly/theme/components/LastUpdated/LastUpdated';
|
|
11
|
-
import { Breadcrumbs as ThemeBreadcrumbs } from '@redocly/theme/components/Breadcrumbs/Breadcrumbs';
|
|
12
8
|
import { CodeSnippetProvider } from '@redocly/theme/core/contexts/CodeSnippetContext';
|
|
9
|
+
import { DocumentationLayoutTop } from '@redocly/theme/layouts/DocumentationLayoutTop';
|
|
10
|
+
import { DocumentationLayoutBottom } from '@redocly/theme/layouts/DocumentationLayoutBottom';
|
|
13
11
|
|
|
14
12
|
type DocumentationLayoutProps = {
|
|
15
13
|
tableOfContent: React.ReactNode;
|
|
@@ -36,21 +34,13 @@ export function DocumentationLayout({
|
|
|
36
34
|
className,
|
|
37
35
|
children,
|
|
38
36
|
}: React.PropsWithChildren<DocumentationLayoutProps>): JSX.Element {
|
|
39
|
-
const { editPage: themeEditPage } = config || {};
|
|
40
|
-
const mergedConf = editPage ? { ...themeEditPage, ...editPage } : undefined;
|
|
41
|
-
|
|
42
37
|
return (
|
|
43
38
|
<CodeSnippetProvider>
|
|
44
39
|
<LayoutWrapper data-component-name="Layout/DocumentationLayout" className={className}>
|
|
45
40
|
<ContentWrapper withToc={!config?.toc?.hide}>
|
|
46
|
-
<
|
|
47
|
-
<LayoutTop>
|
|
48
|
-
{lastModified && <LastUpdated lastModified={new Date(lastModified)} />}
|
|
49
|
-
{mergedConf && <EditPageButton to={mergedConf.to} />}
|
|
50
|
-
</LayoutTop>
|
|
41
|
+
<DocumentationLayoutTop config={config} editPage={editPage} lastModified={lastModified} />
|
|
51
42
|
{children}
|
|
52
|
-
<
|
|
53
|
-
<PageNavigation nextPage={nextPage} prevPage={prevPage} />
|
|
43
|
+
<DocumentationLayoutBottom feedback={feedback} nextPage={nextPage} prevPage={prevPage} />
|
|
54
44
|
</ContentWrapper>
|
|
55
45
|
{tableOfContent}
|
|
56
46
|
</LayoutWrapper>
|
|
@@ -89,19 +79,3 @@ const ContentWrapper = styled.section<{ withToc: boolean }>`
|
|
|
89
79
|
width: ${({ withToc }) => (withToc ? `calc(90% - var(--toc-width))` : '90%')};
|
|
90
80
|
}
|
|
91
81
|
`;
|
|
92
|
-
|
|
93
|
-
const LayoutTop = styled.div`
|
|
94
|
-
display: flex;
|
|
95
|
-
justify-content: space-between;
|
|
96
|
-
flex-flow: row nowrap;
|
|
97
|
-
`;
|
|
98
|
-
|
|
99
|
-
const Breadcrumbs = styled(ThemeBreadcrumbs)`
|
|
100
|
-
margin-bottom: var(--breadcrumbs-margin-bottom);
|
|
101
|
-
`;
|
|
102
|
-
|
|
103
|
-
const LayoutBottom = styled(LayoutTop)`
|
|
104
|
-
> * {
|
|
105
|
-
margin: 25px 0;
|
|
106
|
-
}
|
|
107
|
-
`;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
|
|
4
|
+
import type { JSX } from 'react';
|
|
5
|
+
import type { ResolvedNavItemWithLink } from '@redocly/config';
|
|
6
|
+
|
|
7
|
+
import { PageNavigation } from '@redocly/theme/components/PageNavigation/PageNavigation';
|
|
8
|
+
|
|
9
|
+
type DocumentationLayoutBottomProps = {
|
|
10
|
+
feedback: React.ReactNode;
|
|
11
|
+
nextPage?: ResolvedNavItemWithLink | null;
|
|
12
|
+
prevPage?: ResolvedNavItemWithLink | null;
|
|
13
|
+
className?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function DocumentationLayoutBottom({
|
|
17
|
+
feedback,
|
|
18
|
+
nextPage,
|
|
19
|
+
prevPage,
|
|
20
|
+
}: React.PropsWithChildren<DocumentationLayoutBottomProps>): JSX.Element {
|
|
21
|
+
return (
|
|
22
|
+
<Wrapper data-component-name="Layout/DocumentationLayoutBottom">
|
|
23
|
+
<LayoutBottom>{feedback}</LayoutBottom>
|
|
24
|
+
<PageNavigation nextPage={nextPage} prevPage={prevPage} />
|
|
25
|
+
</Wrapper>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const Wrapper = styled.div`
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-direction: column;
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
const LayoutBottom = styled.div`
|
|
35
|
+
display: flex;
|
|
36
|
+
justify-content: space-between;
|
|
37
|
+
flex-flow: row nowrap;
|
|
38
|
+
|
|
39
|
+
> * {
|
|
40
|
+
margin: 25px 0;
|
|
41
|
+
}
|
|
42
|
+
`;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
|
|
4
|
+
import type { JSX } from 'react';
|
|
5
|
+
import type { MarkdownConfig } from '@redocly/config';
|
|
6
|
+
|
|
7
|
+
import { EditPageButton } from '@redocly/theme/components/Buttons/EditPageButton';
|
|
8
|
+
import { LastUpdated } from '@redocly/theme/components/LastUpdated/LastUpdated';
|
|
9
|
+
import { Breadcrumbs as ThemeBreadcrumbs } from '@redocly/theme/components/Breadcrumbs/Breadcrumbs';
|
|
10
|
+
|
|
11
|
+
type DocumentationLayoutTopProps = {
|
|
12
|
+
config?: MarkdownConfig;
|
|
13
|
+
editPage?: {
|
|
14
|
+
to: string;
|
|
15
|
+
};
|
|
16
|
+
/** String in ISO format */
|
|
17
|
+
lastModified?: string | null;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export function DocumentationLayoutTop({
|
|
21
|
+
config,
|
|
22
|
+
editPage,
|
|
23
|
+
lastModified,
|
|
24
|
+
}: React.PropsWithChildren<DocumentationLayoutTopProps>): JSX.Element {
|
|
25
|
+
const { editPage: themeEditPage } = config || {};
|
|
26
|
+
const mergedConf = editPage ? { ...themeEditPage, ...editPage } : undefined;
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<Wrapper data-component-name="Layout/DocumentationLayoutTop">
|
|
30
|
+
<Breadcrumbs />
|
|
31
|
+
<LayoutTop>
|
|
32
|
+
{lastModified && <LastUpdated lastModified={new Date(lastModified)} />}
|
|
33
|
+
{mergedConf && <EditPageButton to={mergedConf.to} />}
|
|
34
|
+
</LayoutTop>
|
|
35
|
+
</Wrapper>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const Wrapper = styled.div`
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
`;
|
|
43
|
+
|
|
44
|
+
const LayoutTop = styled.div`
|
|
45
|
+
display: flex;
|
|
46
|
+
justify-content: space-between;
|
|
47
|
+
flex-flow: row nowrap;
|
|
48
|
+
`;
|
|
49
|
+
|
|
50
|
+
const Breadcrumbs = styled(ThemeBreadcrumbs)`
|
|
51
|
+
margin-bottom: var(--breadcrumbs-margin-bottom);
|
|
52
|
+
`;
|