@redocly/theme 0.56.0 → 0.57.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/CatalogEntities.js +1 -1
- package/lib/components/Dropdown/Dropdown.d.ts +2 -1
- package/lib/components/Dropdown/Dropdown.js +3 -2
- package/lib/components/Dropdown/variables.js +1 -1
- package/lib/core/hooks/__mocks__/search/use-recent-searches.d.ts +2 -2
- package/lib/core/hooks/__mocks__/search/use-recent-searches.js +2 -1
- package/lib/core/hooks/__mocks__/search/use-search-filter.d.ts +2 -2
- package/lib/core/hooks/__mocks__/search/use-search-filter.js +2 -1
- package/lib/core/hooks/__mocks__/search/use-suggested-pages.d.ts +2 -2
- package/lib/core/hooks/__mocks__/search/use-suggested-pages.js +2 -1
- package/lib/core/hooks/__mocks__/use-controlled-state.d.ts +1 -1
- package/lib/core/hooks/__mocks__/use-controlled-state.js +2 -1
- package/lib/core/hooks/__mocks__/use-input-key-commands.d.ts +3 -3
- package/lib/core/hooks/__mocks__/use-input-key-commands.js +3 -2
- package/lib/core/hooks/__mocks__/use-mobile-menu.d.ts +1 -1
- package/lib/core/hooks/__mocks__/use-mobile-menu.js +2 -1
- package/lib/core/hooks/__mocks__/use-theme-config.d.ts +2 -2
- package/lib/core/hooks/__mocks__/use-theme-config.js +2 -1
- package/lib/core/hooks/__mocks__/use-theme-hooks.d.ts +47 -47
- package/lib/core/hooks/__mocks__/use-theme-hooks.js +38 -37
- package/lib/core/hooks/__mocks__/use-time-ago.d.ts +2 -2
- package/lib/core/hooks/__mocks__/use-time-ago.js +2 -1
- package/lib/core/hooks/catalog/useCatalogEntities.js +6 -4
- package/lib/core/hooks/code-walkthrough/__mocks__/MockIntersectionObserver.js +4 -3
- package/lib/core/hooks/menu/__mocks__/use-mobile-menu-items.d.ts +1 -1
- package/lib/core/hooks/menu/__mocks__/use-mobile-menu-items.js +2 -1
- package/lib/core/hooks/use-page-actions.js +5 -1
- package/lib/core/types/l10n.d.ts +1 -1
- package/lib/core/types/user-claims.d.ts +2 -0
- package/lib/core/utils/dynamic.d.ts +7 -0
- package/lib/core/utils/dynamic.js +59 -0
- package/lib/core/utils/index.d.ts +1 -0
- package/lib/core/utils/index.js +1 -0
- package/lib/icons/GenericIcon/GenericIcon.d.ts +2 -2
- package/lib/icons/GenericIcon/GenericIcon.js +8 -3
- package/lib/icons/__tests__/IconTestUtils.d.ts +0 -1
- package/lib/icons/__tests__/IconTestUtils.js +8 -7
- package/package.json +11 -15
- package/src/components/Catalog/CatalogEntities.tsx +1 -1
- package/src/components/Dropdown/Dropdown.tsx +4 -1
- package/src/components/Dropdown/variables.ts +1 -1
- package/src/core/hooks/__mocks__/search/use-recent-searches.ts +3 -1
- package/src/core/hooks/__mocks__/search/use-search-filter.ts +3 -1
- package/src/core/hooks/__mocks__/search/use-suggested-pages.ts +3 -1
- package/src/core/hooks/__mocks__/use-controlled-state.ts +3 -1
- package/src/core/hooks/__mocks__/use-input-key-commands.ts +4 -2
- package/src/core/hooks/__mocks__/use-mobile-menu.ts +3 -1
- package/src/core/hooks/__mocks__/use-theme-config.ts +3 -1
- package/src/core/hooks/__mocks__/use-theme-hooks.ts +39 -37
- package/src/core/hooks/__mocks__/use-time-ago.ts +3 -1
- package/src/core/hooks/catalog/useCatalogEntities.ts +7 -4
- package/src/core/hooks/code-walkthrough/__mocks__/MockIntersectionObserver.ts +5 -3
- package/src/core/hooks/menu/__mocks__/use-mobile-menu-items.ts +3 -1
- package/src/core/hooks/use-page-actions.ts +5 -1
- package/src/core/types/l10n.ts +2 -0
- package/src/core/types/user-claims.ts +2 -0
- package/src/core/utils/dynamic.tsx +83 -0
- package/src/core/utils/index.ts +1 -0
- package/src/icons/GenericIcon/GenericIcon.tsx +13 -4
- package/src/icons/__tests__/IconTestUtils.tsx +5 -4
|
@@ -0,0 +1,59 @@
|
|
|
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.dynamic = dynamic;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
function dynamic(factory, { ssr = true, loading } = {}) {
|
|
9
|
+
const Component = react_1.default.lazy(() => factory().then((mod) => {
|
|
10
|
+
// Case 1: factory() => import('./SomeModule') - direct import
|
|
11
|
+
// Case 2: factory() => import('./SomeModule').then(mod => mod.default) - extract default
|
|
12
|
+
if (typeof mod === 'function') {
|
|
13
|
+
return { default: mod };
|
|
14
|
+
}
|
|
15
|
+
// Case 3: factory() => import('./SomeModule').then(mod => ({ default: mod.default })) - manual wrap
|
|
16
|
+
// Case 4: factory() => import('./SomeModule').then(mod => ({ default: mod.Named })) - manual wrap named
|
|
17
|
+
if (mod && typeof mod === 'object' && 'default' in mod) {
|
|
18
|
+
const defaultExport = mod.default;
|
|
19
|
+
// Handle both function components and React component objects
|
|
20
|
+
if (typeof defaultExport === 'function') {
|
|
21
|
+
return { default: defaultExport };
|
|
22
|
+
}
|
|
23
|
+
if (defaultExport && typeof defaultExport === 'object' && '$$typeof' in defaultExport) {
|
|
24
|
+
return { default: defaultExport };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// Case 5: factory() => import('./SomeModule').then(mod => mod.Named) - find named export
|
|
28
|
+
if (mod && typeof mod === 'object') {
|
|
29
|
+
const modObj = mod;
|
|
30
|
+
for (const key in modObj) {
|
|
31
|
+
const value = modObj[key];
|
|
32
|
+
if (typeof value === 'function') {
|
|
33
|
+
return { default: value };
|
|
34
|
+
}
|
|
35
|
+
if (value && typeof value === 'object' && '$$typeof' in value) {
|
|
36
|
+
return { default: value };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
throw new Error('Dynamic import did not return a valid React component');
|
|
41
|
+
}));
|
|
42
|
+
const LoadingComponent = loading || (() => null);
|
|
43
|
+
return (props) => {
|
|
44
|
+
const [hasMounted, setHasMounted] = react_1.default.useState(false);
|
|
45
|
+
react_1.default.useEffect(() => {
|
|
46
|
+
setHasMounted(true);
|
|
47
|
+
}, []);
|
|
48
|
+
if (ssr) {
|
|
49
|
+
return (react_1.default.createElement(react_1.default.Suspense, { fallback: react_1.default.createElement(LoadingComponent, Object.assign({}, props)) },
|
|
50
|
+
react_1.default.createElement(Component, Object.assign({}, props))));
|
|
51
|
+
}
|
|
52
|
+
if (!hasMounted) {
|
|
53
|
+
return react_1.default.createElement(LoadingComponent, Object.assign({}, props));
|
|
54
|
+
}
|
|
55
|
+
return (react_1.default.createElement(react_1.default.Suspense, { fallback: react_1.default.createElement(LoadingComponent, Object.assign({}, props)) },
|
|
56
|
+
react_1.default.createElement(Component, Object.assign({}, props))));
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=dynamic.js.map
|
package/lib/core/utils/index.js
CHANGED
|
@@ -52,4 +52,5 @@ __exportStar(require("./parse-style-string"), exports);
|
|
|
52
52
|
__exportStar(require("./lang-to-name"), exports);
|
|
53
53
|
__exportStar(require("./enhanced-smoothstep"), exports);
|
|
54
54
|
__exportStar(require("./icon-resolver"), exports);
|
|
55
|
+
__exportStar(require("./dynamic"), exports);
|
|
55
56
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
export
|
|
2
|
+
export type GenericIconProps = {
|
|
3
3
|
icon: string | React.ReactNode;
|
|
4
4
|
srcSet?: string;
|
|
5
5
|
rawContent?: string;
|
|
@@ -7,5 +7,5 @@ export interface GenericIconProps {
|
|
|
7
7
|
color?: string;
|
|
8
8
|
alt?: string;
|
|
9
9
|
className?: string;
|
|
10
|
-
}
|
|
10
|
+
};
|
|
11
11
|
export declare function GenericIcon({ icon, srcSet, rawContent, size, color, alt, className, }: GenericIconProps): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | React.JSX.Element | null | undefined;
|
|
@@ -33,19 +33,24 @@ const CDNIcon_1 = require("../../icons/CDNIcon/CDNIcon");
|
|
|
33
33
|
const utils_1 = require("../../core/utils");
|
|
34
34
|
const InlineSvg_1 = require("../../markdoc/components/InlineSvg/InlineSvg");
|
|
35
35
|
const Image_1 = require("../../components/Image/Image");
|
|
36
|
+
const INVALID_ICON_NAME = 'image-slash';
|
|
36
37
|
function GenericIcon({ icon, srcSet, rawContent, size, color, alt, className, }) {
|
|
37
38
|
if (srcSet) {
|
|
38
|
-
return React.createElement(
|
|
39
|
+
return React.createElement(IconSrcSetImg, { srcSet: srcSet, alt: alt, className: className });
|
|
39
40
|
}
|
|
40
41
|
const resolvedIcon = icon && typeof icon === 'string' ? (0, utils_1.resolveIcon)(icon) : null;
|
|
41
|
-
const iconComponent = rawContent ? (React.createElement(IconSvg, { fileRawContent: rawContent, className: className })) : (resolvedIcon === null || resolvedIcon === void 0 ? void 0 : resolvedIcon.type) === 'link' ? (React.createElement(IconImg, { src: resolvedIcon.value, alt: alt, className: className })) : (resolvedIcon === null || resolvedIcon === void 0 ? void 0 : resolvedIcon.type) === 'font-awesome' ? (React.createElement(CDNIcon_1.CDNIcon, { name: resolvedIcon.name, type: resolvedIcon.style, size: size, color: color, className: className })) : (icon);
|
|
42
|
+
const iconComponent = rawContent ? (React.createElement(IconSvg, { fileRawContent: rawContent, className: className })) : (resolvedIcon === null || resolvedIcon === void 0 ? void 0 : resolvedIcon.type) === 'link' ? (React.createElement(IconImg, { src: resolvedIcon.value, alt: alt, className: className })) : (resolvedIcon === null || resolvedIcon === void 0 ? void 0 : resolvedIcon.type) === 'font-awesome' ? (React.createElement(CDNIcon_1.CDNIcon, { name: resolvedIcon.name, type: resolvedIcon.style, size: size, color: color, className: className })) : (resolvedIcon === null || resolvedIcon === void 0 ? void 0 : resolvedIcon.type) === 'invalid' ? (React.createElement(CDNIcon_1.CDNIcon, { name: INVALID_ICON_NAME, size: size, color: color, className: className })) : (icon);
|
|
42
43
|
return iconComponent;
|
|
43
44
|
}
|
|
44
45
|
const IconImg = styled_components_1.default.img `
|
|
45
46
|
width: var(--icon-width, 16px);
|
|
46
47
|
height: var(--icon-height, 16px);
|
|
47
48
|
display: inline-block;
|
|
48
|
-
|
|
49
|
+
vertical-align: middle;
|
|
50
|
+
`;
|
|
51
|
+
const IconSrcSetImg = (0, styled_components_1.default)(Image_1.Image) `
|
|
52
|
+
width: var(--icon-width, 16px);
|
|
53
|
+
height: var(--icon-height, 16px);
|
|
49
54
|
`;
|
|
50
55
|
const IconSvg = (0, styled_components_1.default)(InlineSvg_1.InlineSvg) `
|
|
51
56
|
width: var(--icon-width, 16px);
|
|
@@ -6,42 +6,43 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.testIconComponent = testIconComponent;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
8
|
const react_2 = require("@testing-library/react");
|
|
9
|
-
require("
|
|
9
|
+
const vitest_1 = require("vitest");
|
|
10
10
|
function testIconComponent(IconComponent, componentName) {
|
|
11
11
|
const dataName = `icons/${componentName}/${componentName}`;
|
|
12
12
|
return {
|
|
13
13
|
rendersCorrectlyWithDefaultProps: () => {
|
|
14
14
|
const { container } = (0, react_2.render)(react_1.default.createElement(IconComponent, null));
|
|
15
15
|
const svgElement = container.querySelector('svg');
|
|
16
|
-
expect(svgElement).
|
|
16
|
+
(0, vitest_1.expect)(svgElement).toBeTruthy();
|
|
17
17
|
// Check if styles are applied either via style attribute or CSS class
|
|
18
18
|
const element = container.firstChild;
|
|
19
19
|
const hasStyleAttr = element.style.height === '16px' && element.style.width === '16px';
|
|
20
20
|
const elementClass = element.getAttribute('class') || '';
|
|
21
21
|
const hasClassName = elementClass.includes('sc-'); // styled-components class
|
|
22
|
-
expect(hasStyleAttr || hasClassName).toBeTruthy();
|
|
22
|
+
(0, vitest_1.expect)(hasStyleAttr || hasClassName).toBeTruthy();
|
|
23
23
|
},
|
|
24
24
|
appliesCustomSizeAndColor: () => {
|
|
25
25
|
var _a;
|
|
26
26
|
const { container } = (0, react_2.render)(react_1.default.createElement(IconComponent, { size: "24px", color: "--color-primary" }));
|
|
27
27
|
const svgElement = container.querySelector('svg');
|
|
28
|
-
expect(svgElement).
|
|
28
|
+
(0, vitest_1.expect)(svgElement).toBeTruthy();
|
|
29
29
|
const element = container.firstChild;
|
|
30
30
|
const pathElement = container.querySelector('path');
|
|
31
31
|
// Check if size styles are applied either via style attribute or CSS class
|
|
32
32
|
const hasSizeStyle = element.style.height === '24px' && element.style.width === '24px';
|
|
33
33
|
const elementClass = element.getAttribute('class') || '';
|
|
34
34
|
const hasClassName = elementClass.includes('sc-'); // styled-components class
|
|
35
|
-
expect(hasSizeStyle || hasClassName).toBeTruthy();
|
|
35
|
+
(0, vitest_1.expect)(hasSizeStyle || hasClassName).toBeTruthy();
|
|
36
36
|
// Check if color is applied either via style attribute or CSS class
|
|
37
37
|
const hasColorStyle = ((_a = pathElement.getAttribute('style')) === null || _a === void 0 ? void 0 : _a.includes('fill: var(--color-primary)')) ||
|
|
38
38
|
pathElement.getAttribute('fill') === 'var(--color-primary)' ||
|
|
39
39
|
elementClass.includes('sc-'); // check styled-components class on the root element
|
|
40
|
-
expect(hasColorStyle).toBeTruthy();
|
|
40
|
+
(0, vitest_1.expect)(hasColorStyle).toBeTruthy();
|
|
41
41
|
},
|
|
42
42
|
hasCorrectDataComponentName: () => {
|
|
43
43
|
const { container } = (0, react_2.render)(react_1.default.createElement(IconComponent, null));
|
|
44
|
-
expect(container.firstChild).
|
|
44
|
+
(0, vitest_1.expect)(container.firstChild).toHaveProperty('getAttribute');
|
|
45
|
+
(0, vitest_1.expect)(container.firstChild.getAttribute('data-component-name')).toBe(dataName);
|
|
45
46
|
},
|
|
46
47
|
};
|
|
47
48
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/theme",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.57.0-next.1",
|
|
4
4
|
"description": "Shared UI components lib",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"theme",
|
|
@@ -38,13 +38,10 @@
|
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@markdoc/markdoc": "0.5.2",
|
|
40
40
|
"@shikijs/types": "1.24.2",
|
|
41
|
-
"@testing-library/jest-dom": "6.6.3",
|
|
42
41
|
"@testing-library/react": "16.3.0",
|
|
43
42
|
"@testing-library/user-event": "14.6.1",
|
|
44
43
|
"@types/file-saver": "2.0.7",
|
|
45
44
|
"@types/highlight-words-core": "1.2.3",
|
|
46
|
-
"@types/jest": "29.5.11",
|
|
47
|
-
"@types/jest-when": "3.5.5",
|
|
48
45
|
"@types/lodash.debounce": "4.0.9",
|
|
49
46
|
"@types/lodash.throttle": "4.1.9",
|
|
50
47
|
"@types/node": "22.15.3",
|
|
@@ -53,11 +50,10 @@
|
|
|
53
50
|
"@types/react-dom": "^19.1.4",
|
|
54
51
|
"@types/styled-components": "5.1.34",
|
|
55
52
|
"@types/styled-system": "5.1.22",
|
|
53
|
+
"@vitest/coverage-v8": "^3.1.1",
|
|
54
|
+
"@vitest/ui": "3.2.4",
|
|
56
55
|
"concurrently": "7.6.0",
|
|
57
|
-
"
|
|
58
|
-
"jest-environment-jsdom": "29.5.0",
|
|
59
|
-
"jest-styled-components": "7.2.0",
|
|
60
|
-
"jest-when": "3.6.0",
|
|
56
|
+
"vitest-when": "0.6.2",
|
|
61
57
|
"json-schema-to-ts": "2.7.2",
|
|
62
58
|
"npm-run-all2": "5.0.2",
|
|
63
59
|
"react-refresh": "0.14.2",
|
|
@@ -66,13 +62,13 @@
|
|
|
66
62
|
"rimraf": "5.0.7",
|
|
67
63
|
"styled-components": "5.3.11",
|
|
68
64
|
"styled-system": "5.1.5",
|
|
69
|
-
"ts-jest": "29.1.2",
|
|
70
65
|
"ts-node": "10.9.2",
|
|
71
66
|
"ts-node-dev": "2.0.0",
|
|
72
67
|
"tsc-alias": "1.8.10",
|
|
73
68
|
"tsconfig-paths": "4.2.0",
|
|
74
69
|
"tsconfig-paths-webpack-plugin": "3.5.2",
|
|
75
70
|
"typescript": "5.6.2",
|
|
71
|
+
"vitest": "3.2.4",
|
|
76
72
|
"webpack": "5.94.0"
|
|
77
73
|
},
|
|
78
74
|
"dependencies": {
|
|
@@ -90,7 +86,7 @@
|
|
|
90
86
|
"react-calendar": "5.1.0",
|
|
91
87
|
"react-date-picker": "11.0.0",
|
|
92
88
|
"@redocly/config": "0.28.0",
|
|
93
|
-
"@redocly/realm-asyncapi-sdk": "0.
|
|
89
|
+
"@redocly/realm-asyncapi-sdk": "0.3.0-next.0"
|
|
94
90
|
},
|
|
95
91
|
"scripts": {
|
|
96
92
|
"watch": "tsc -p tsconfig.build.json && (concurrently \"tsc -w -p tsconfig.build.json\" \"tsc-alias -w -p tsconfig.build.json\")",
|
|
@@ -98,10 +94,10 @@
|
|
|
98
94
|
"clean": "rimraf lib",
|
|
99
95
|
"compile": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
100
96
|
"build": "npm run clean && npm run compile",
|
|
101
|
-
"test": "
|
|
102
|
-
"test:update": "
|
|
103
|
-
"test:watch": "
|
|
104
|
-
"test:coverage": "
|
|
105
|
-
"test:coverage:html": "
|
|
97
|
+
"test": "vitest run",
|
|
98
|
+
"test:update": "vitest run --update",
|
|
99
|
+
"test:watch": "vitest",
|
|
100
|
+
"test:coverage": "vitest run --coverage",
|
|
101
|
+
"test:coverage:html": "vitest run --coverage --reporter=html"
|
|
106
102
|
}
|
|
107
103
|
}
|
|
@@ -58,7 +58,7 @@ export function CatalogEntities(props: CatalogEntitiesProps): JSX.Element {
|
|
|
58
58
|
limit: LOAD_MORE_THRESHOLD,
|
|
59
59
|
filter:
|
|
60
60
|
initialFilter && filterQuery
|
|
61
|
-
?
|
|
61
|
+
? `(${initialFilter}) AND (${filterQuery})`
|
|
62
62
|
: initialFilter || filterQuery,
|
|
63
63
|
sort: sortOption || undefined,
|
|
64
64
|
search: searchQuery,
|
|
@@ -29,6 +29,7 @@ export type DropdownProps = PropsWithChildren<{
|
|
|
29
29
|
withArrow?: boolean;
|
|
30
30
|
|
|
31
31
|
onClick?: (event: React.UIEvent) => void;
|
|
32
|
+
onClose?: () => void;
|
|
32
33
|
}>;
|
|
33
34
|
|
|
34
35
|
export function Dropdown({
|
|
@@ -43,6 +44,7 @@ export function Dropdown({
|
|
|
43
44
|
placement,
|
|
44
45
|
alignment,
|
|
45
46
|
onClick,
|
|
47
|
+
onClose,
|
|
46
48
|
}: DropdownProps): JSX.Element {
|
|
47
49
|
const dropdownRef = useRef<HTMLDivElement | null>(null);
|
|
48
50
|
const [isOpen, setIsOpen] = useControlledState<boolean>(false, active);
|
|
@@ -53,6 +55,7 @@ export function Dropdown({
|
|
|
53
55
|
|
|
54
56
|
const handleClose = () => {
|
|
55
57
|
setIsOpen(false);
|
|
58
|
+
onClose?.();
|
|
56
59
|
};
|
|
57
60
|
|
|
58
61
|
const handleChildClick = () => {
|
|
@@ -126,7 +129,7 @@ const DropdownWrapper = styled.div`
|
|
|
126
129
|
`;
|
|
127
130
|
|
|
128
131
|
const ChildrenWrapper = styled.div<{ placement?: string; alignment?: string; isOpen?: boolean }>`
|
|
129
|
-
padding-top: var(--dropdown-menu-
|
|
132
|
+
padding-top: var(--dropdown-menu-padding-top);
|
|
130
133
|
position: absolute;
|
|
131
134
|
top: ${({ placement }) => (placement === 'top' ? 'auto' : '100%')};
|
|
132
135
|
bottom: ${({ placement }) => (placement === 'top' ? '100%' : 'auto')};
|
|
@@ -9,7 +9,7 @@ export const dropdown = css`
|
|
|
9
9
|
--dropdown-menu-line-height: var(--line-height-base); // @presenter LineHeight
|
|
10
10
|
--dropdown-menu-text-color: var(--text-color-secondary); // @presenter Color
|
|
11
11
|
|
|
12
|
-
--dropdown-menu-
|
|
12
|
+
--dropdown-menu-padding-top: var(--spacing-xxs);
|
|
13
13
|
--dropdown-menu-min-width: 100px;
|
|
14
14
|
--dropdown-menu-max-width: 424px;
|
|
15
15
|
--dropdown-menu-max-height: 300px;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
export const useThemeHooks = vi.fn(() => ({
|
|
4
|
+
useTranslate: vi.fn(() => ({
|
|
5
|
+
translate: vi.fn((key: string, defaultValue: string) =>
|
|
4
6
|
defaultValue
|
|
5
7
|
? typeof defaultValue !== 'string'
|
|
6
8
|
? (defaultValue as any).defaultValue
|
|
@@ -8,21 +10,21 @@ export const useThemeHooks = jest.fn(() => ({
|
|
|
8
10
|
: key,
|
|
9
11
|
),
|
|
10
12
|
})),
|
|
11
|
-
useTelemetry:
|
|
12
|
-
send:
|
|
13
|
+
useTelemetry: vi.fn(() => ({
|
|
14
|
+
send: vi.fn(),
|
|
13
15
|
})),
|
|
14
|
-
useBreadcrumbs:
|
|
15
|
-
usePageSharedData:
|
|
16
|
-
useCatalogClassic:
|
|
16
|
+
useBreadcrumbs: vi.fn().mockReturnValue([]),
|
|
17
|
+
usePageSharedData: vi.fn().mockReturnValue({}),
|
|
18
|
+
useCatalogClassic: vi.fn(() => ({
|
|
17
19
|
groups: [],
|
|
18
20
|
filters: [],
|
|
19
21
|
filterTerm: '',
|
|
20
|
-
setFilterTerm:
|
|
22
|
+
setFilterTerm: vi.fn(),
|
|
21
23
|
})),
|
|
22
|
-
useL10n:
|
|
23
|
-
changeLanguage:
|
|
24
|
+
useL10n: vi.fn(() => ({
|
|
25
|
+
changeLanguage: vi.fn(),
|
|
24
26
|
})),
|
|
25
|
-
useL10nConfig:
|
|
27
|
+
useL10nConfig: vi.fn(() => ({
|
|
26
28
|
currentLocale: 'en',
|
|
27
29
|
defaultLocale: 'en',
|
|
28
30
|
locales: [
|
|
@@ -31,42 +33,42 @@ export const useThemeHooks = jest.fn(() => ({
|
|
|
31
33
|
{ code: 'uk', name: 'Ukraine' },
|
|
32
34
|
],
|
|
33
35
|
})),
|
|
34
|
-
usePreloadHistory:
|
|
35
|
-
push:
|
|
36
|
+
usePreloadHistory: vi.fn(() => ({
|
|
37
|
+
push: vi.fn(),
|
|
36
38
|
})),
|
|
37
|
-
useCurrentProduct:
|
|
38
|
-
useProducts:
|
|
39
|
-
useSearch:
|
|
40
|
-
query:
|
|
41
|
-
setQuery:
|
|
39
|
+
useCurrentProduct: vi.fn(),
|
|
40
|
+
useProducts: vi.fn(() => []),
|
|
41
|
+
useSearch: vi.fn(() => ({
|
|
42
|
+
query: vi.fn().mockReturnValue(''),
|
|
43
|
+
setQuery: vi.fn(),
|
|
42
44
|
items: [],
|
|
43
45
|
isLoading: false,
|
|
44
46
|
})),
|
|
45
|
-
useAiSearch:
|
|
46
|
-
askQuestion:
|
|
47
|
+
useAiSearch: vi.fn(() => ({
|
|
48
|
+
askQuestion: vi.fn(),
|
|
47
49
|
references: [],
|
|
48
50
|
})),
|
|
49
|
-
useFacetQuery:
|
|
51
|
+
useFacetQuery: vi.fn(() => ({
|
|
50
52
|
searchFacet: null,
|
|
51
|
-
setSearchFacet:
|
|
52
|
-
setSearchFacetQuery:
|
|
53
|
+
setSearchFacet: vi.fn(),
|
|
54
|
+
setSearchFacetQuery: vi.fn(),
|
|
53
55
|
})),
|
|
54
|
-
useMarkdownText:
|
|
56
|
+
useMarkdownText: vi.fn(() => {
|
|
55
57
|
return null;
|
|
56
58
|
}),
|
|
57
|
-
useUserMenu:
|
|
59
|
+
useUserMenu: vi.fn(() => ({
|
|
58
60
|
userData: {
|
|
59
61
|
isAuthenticated: true,
|
|
60
62
|
name: 'test-name',
|
|
61
63
|
email: 'test-email@test.xyz',
|
|
62
64
|
picture: 'picture',
|
|
63
65
|
},
|
|
64
|
-
handleLogout:
|
|
66
|
+
handleLogout: vi.fn(),
|
|
65
67
|
loginUrl: 'https://login.redoc.ly',
|
|
66
68
|
hasDeveloperOnboarding: true,
|
|
67
69
|
})),
|
|
68
|
-
usePageVersions:
|
|
69
|
-
useSidebarItems:
|
|
70
|
+
usePageVersions: vi.fn(),
|
|
71
|
+
useSidebarItems: vi.fn().mockReturnValue({
|
|
70
72
|
currentItems: [
|
|
71
73
|
{
|
|
72
74
|
label: 'Item',
|
|
@@ -77,14 +79,14 @@ export const useThemeHooks = jest.fn(() => ({
|
|
|
77
79
|
label: 'Item',
|
|
78
80
|
},
|
|
79
81
|
],
|
|
80
|
-
popDrilldownState:
|
|
81
|
-
pushDrilldownState:
|
|
82
|
+
popDrilldownState: vi.fn(),
|
|
83
|
+
pushDrilldownState: vi.fn(),
|
|
82
84
|
}),
|
|
83
|
-
useSidebarSiblingsData:
|
|
84
|
-
useSubmitFeedback:
|
|
85
|
-
submitFeedback:
|
|
85
|
+
useSidebarSiblingsData: vi.fn(),
|
|
86
|
+
useSubmitFeedback: vi.fn(() => ({
|
|
87
|
+
submitFeedback: vi.fn(),
|
|
86
88
|
})),
|
|
87
|
-
useLoadAndNavigate:
|
|
88
|
-
usePageProps:
|
|
89
|
-
usePageData:
|
|
89
|
+
useLoadAndNavigate: vi.fn(),
|
|
90
|
+
usePageProps: vi.fn().mockReturnValue({}),
|
|
91
|
+
usePageData: vi.fn().mockReturnValue(null),
|
|
90
92
|
}));
|
|
@@ -6,11 +6,14 @@ export function useCatalogEntities({ entitiesTypes, excludedEntities }: UseCatal
|
|
|
6
6
|
const initialExcludedEntitiesFilter = excludedEntities?.length
|
|
7
7
|
? `-key:${excludedEntities.map((entity) => entity.key).join(',')}`
|
|
8
8
|
: '';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
|
|
10
|
+
if (initialTypesFilter && initialExcludedEntitiesFilter) {
|
|
11
|
+
return {
|
|
12
|
+
initialFilter: `(${initialTypesFilter}) AND (${initialExcludedEntitiesFilter})`,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
12
15
|
|
|
13
16
|
return {
|
|
14
|
-
initialFilter,
|
|
17
|
+
initialFilter: initialTypesFilter || initialExcludedEntitiesFilter,
|
|
15
18
|
};
|
|
16
19
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { vi } from 'vitest';
|
|
2
|
+
|
|
1
3
|
export class MockIntersectionObserver {
|
|
2
4
|
public readonly root: Element | Document | null;
|
|
3
5
|
public readonly rootMargin: string;
|
|
@@ -11,9 +13,9 @@ export class MockIntersectionObserver {
|
|
|
11
13
|
this.root = null;
|
|
12
14
|
this.rootMargin = '0px';
|
|
13
15
|
this.thresholds = [1];
|
|
14
|
-
this.observe =
|
|
15
|
-
this.unobserve =
|
|
16
|
-
this.disconnect =
|
|
16
|
+
this.observe = vi.fn();
|
|
17
|
+
this.unobserve = vi.fn();
|
|
18
|
+
this.disconnect = vi.fn();
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
takeRecords(): any[] {
|
|
@@ -20,7 +20,8 @@ export function usePageActions(pageSlug: string): PageAction[] {
|
|
|
20
20
|
|
|
21
21
|
const { navigation } = useThemeConfig();
|
|
22
22
|
// Can't use any actions if no markdown files are generated for LLMs
|
|
23
|
-
const
|
|
23
|
+
const pageProps = usePageProps();
|
|
24
|
+
const isLlmsDisabled = pageProps?.seo?.llmstxt?.hide || pageProps?.frontmatter?.excludeFromSearch;
|
|
24
25
|
const { isPublic } = usePageData() || {};
|
|
25
26
|
|
|
26
27
|
const actions: PageAction[] = useMemo(() => {
|
|
@@ -60,6 +61,9 @@ export function usePageActions(pageSlug: string): PageAction[] {
|
|
|
60
61
|
onClick: async () => {
|
|
61
62
|
try {
|
|
62
63
|
const result = await fetch(mdPageUrl);
|
|
64
|
+
if (result.status !== 200) {
|
|
65
|
+
throw new Error('Failed to fetch markdown content');
|
|
66
|
+
}
|
|
63
67
|
const text = await result.text();
|
|
64
68
|
|
|
65
69
|
ClipboardService.copyCustom(text);
|
package/src/core/types/l10n.ts
CHANGED
|
@@ -257,6 +257,8 @@ export type TranslationKey =
|
|
|
257
257
|
| 'openapi.collapseAll'
|
|
258
258
|
| 'openapi.viewSecurityDetails'
|
|
259
259
|
| 'openapi.noResponseExample'
|
|
260
|
+
| 'openapi.discriminator.searchPlaceholder'
|
|
261
|
+
| 'openapi.discriminator.searchNoResults'
|
|
260
262
|
| 'openapi.noResponseContent'
|
|
261
263
|
| 'openapi.noRequestPayload'
|
|
262
264
|
| 'openapi.hidePattern'
|