@redocly/theme 0.69.0-next.8 → 0.69.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/Accordion/Accordion.js +5 -1
- package/lib/components/Catalog/CatalogEntities.js +1 -0
- package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations.js +5 -3
- package/lib/components/Catalog/CatalogViewModeToggle.d.ts +1 -1
- package/lib/components/Catalog/CatalogViewModeToggle.js +2 -43
- package/lib/components/Filter/FilterInput.js +4 -2
- package/lib/components/JsonViewer/Helpers.js +12 -42
- package/lib/components/MCP/McpConnectionTabs.js +21 -11
- package/lib/components/Markdown/Markdown.js +1 -3
- package/lib/components/Markdown/styles/base-table.js +8 -0
- package/lib/components/Markdown/variables.js +1 -2
- package/lib/components/Panel/Panel.js +5 -1
- package/lib/components/Search/FilterFields/SearchFilterFieldSelect.js +22 -32
- package/lib/components/Search/SearchAiDialog.js +3 -0
- package/lib/components/Search/SearchItem.js +5 -3
- package/lib/components/Search/variables.js +1 -0
- package/lib/components/Select/Select.js +10 -5
- package/lib/components/Sidebar/Sidebar.js +2 -38
- package/lib/core/contexts/AccordionGroupContext.d.ts +1 -0
- package/lib/core/contexts/AccordionGroupContext.js +6 -0
- package/lib/core/contexts/PageActionsContext.d.ts +5 -0
- package/lib/core/contexts/PageActionsContext.js +10 -0
- package/lib/core/contexts/index.d.ts +2 -0
- package/lib/core/contexts/index.js +2 -0
- package/lib/core/hooks/code-walkthrough/use-code-walkthrough-controls.js +5 -17
- package/lib/core/hooks/code-walkthrough/use-code-walkthrough-steps.js +2 -0
- package/lib/core/hooks/menu/use-menu-item-expanded.js +1 -0
- package/lib/core/hooks/use-active-heading.js +4 -0
- package/lib/core/hooks/use-connect-mcp-button.js +7 -2
- package/lib/core/hooks/use-local-state.js +1 -0
- package/lib/core/hooks/use-mobile-menu.js +10 -2
- package/lib/core/hooks/use-product-picker.js +1 -1
- package/lib/core/hooks/use-tabs.js +4 -2
- 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/global.js +1 -0
- package/lib/core/utils/class-names.d.ts +1 -0
- package/lib/core/utils/class-names.js +7 -0
- package/lib/markdoc/components/Accordion/Accordion.js +6 -6
- package/lib/markdoc/components/Accordion/AccordionGroup.d.ts +2 -1
- package/lib/markdoc/components/Accordion/AccordionGroup.js +39 -3
- package/lib/markdoc/components/Heading/Heading.js +5 -2
- package/lib/markdoc/tags/accordion-group.js +3 -0
- package/package.json +2 -2
- package/src/components/Accordion/Accordion.tsx +7 -3
- package/src/components/Catalog/CatalogEntities.tsx +1 -0
- package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations.tsx +6 -4
- package/src/components/Catalog/CatalogViewModeToggle.tsx +2 -17
- package/src/components/Filter/FilterInput.tsx +5 -3
- package/src/components/JsonViewer/Helpers.tsx +13 -9
- package/src/components/MCP/McpConnectionTabs.tsx +32 -10
- package/src/components/Markdown/Markdown.tsx +1 -3
- package/src/components/Markdown/styles/base-table.ts +8 -0
- package/src/components/Markdown/variables.ts +1 -2
- package/src/components/Panel/Panel.tsx +7 -3
- package/src/components/Search/FilterFields/SearchFilterFieldSelect.tsx +32 -40
- package/src/components/Search/SearchAiDialog.tsx +3 -0
- package/src/components/Search/SearchItem.tsx +6 -1
- package/src/components/Search/variables.ts +1 -0
- package/src/components/Select/Select.tsx +12 -6
- package/src/components/Sidebar/Sidebar.tsx +2 -6
- package/src/core/contexts/AccordionGroupContext.tsx +3 -0
- package/src/core/contexts/PageActionsContext.tsx +7 -0
- package/src/core/contexts/index.ts +2 -0
- package/src/core/hooks/__mocks__/use-theme-hooks.ts +2 -0
- package/src/core/hooks/code-walkthrough/use-code-walkthrough-controls.ts +6 -20
- package/src/core/hooks/code-walkthrough/use-code-walkthrough-steps.ts +2 -0
- package/src/core/hooks/menu/use-menu-item-expanded.ts +1 -0
- package/src/core/hooks/use-active-heading.ts +4 -0
- package/src/core/hooks/use-connect-mcp-button.ts +8 -2
- package/src/core/hooks/use-local-state.ts +1 -0
- package/src/core/hooks/use-mobile-menu.ts +11 -3
- package/src/core/hooks/use-product-picker.ts +2 -2
- package/src/core/hooks/use-tabs.ts +4 -2
- package/src/core/hooks/use-telemetry-fallback.ts +2 -0
- package/src/core/styles/global.ts +1 -0
- package/src/core/utils/class-names.ts +8 -0
- package/src/markdoc/components/Accordion/Accordion.tsx +8 -2
- package/src/markdoc/components/Accordion/AccordionGroup.tsx +9 -2
- package/src/markdoc/components/Heading/Heading.tsx +7 -4
- package/src/markdoc/tags/accordion-group.ts +3 -0
|
@@ -16,9 +16,6 @@ function useCodeWalkthroughControls(filters, inputs, toggles, enableDeepLink) {
|
|
|
16
16
|
const location = (0, react_router_1.useLocation)();
|
|
17
17
|
const navigate = (0, react_router_1.useNavigate)();
|
|
18
18
|
const searchParams = (0, react_1.useMemo)(() => new URLSearchParams(location.search), [location.search]);
|
|
19
|
-
const filtersRef = (0, react_1.useRef)(filters);
|
|
20
|
-
const inputsRef = (0, react_1.useRef)(inputs);
|
|
21
|
-
const togglesRef = (0, react_1.useRef)(toggles);
|
|
22
19
|
const getInitialState = () => {
|
|
23
20
|
var _a, _b;
|
|
24
21
|
var _c, _d;
|
|
@@ -36,18 +33,10 @@ function useCodeWalkthroughControls(filters, inputs, toggles, enableDeepLink) {
|
|
|
36
33
|
return state;
|
|
37
34
|
};
|
|
38
35
|
const [controlsState, setControlsState] = (0, react_1.useState)(getInitialState);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
JSON.stringify(toggles) === JSON.stringify(togglesRef.current),
|
|
44
|
-
];
|
|
45
|
-
if (sameProps.every(Boolean)) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
filtersRef.current = filters;
|
|
49
|
-
inputsRef.current = inputs;
|
|
50
|
-
togglesRef.current = toggles;
|
|
36
|
+
const controlsKey = JSON.stringify([filters, inputs, toggles]);
|
|
37
|
+
const [prevControlsKey, setPrevControlsKey] = (0, react_1.useState)(controlsKey);
|
|
38
|
+
if (prevControlsKey !== controlsKey) {
|
|
39
|
+
setPrevControlsKey(controlsKey);
|
|
51
40
|
const newState = getInitialState();
|
|
52
41
|
// Preserve existing values where control type hasn't changed
|
|
53
42
|
Object.entries(newState).forEach(([id, control]) => {
|
|
@@ -58,8 +47,7 @@ function useCodeWalkthroughControls(filters, inputs, toggles, enableDeepLink) {
|
|
|
58
47
|
}
|
|
59
48
|
});
|
|
60
49
|
setControlsState(newState);
|
|
61
|
-
|
|
62
|
-
}, [filters, inputs, toggles, enableDeepLink]);
|
|
50
|
+
}
|
|
63
51
|
const changeControlState = (id, value) => {
|
|
64
52
|
setControlsState((prev) => {
|
|
65
53
|
const control = prev[id];
|
|
@@ -58,6 +58,7 @@ function useCodeWalkthroughSteps({ steps, enableDeepLink, root, }) {
|
|
|
58
58
|
startOffset: markersMinTopOffset < endOffset ? startOffset : 0,
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
|
+
// oxlint-disable-next-line react-you-might-not-need-an-effect/no-chain-state-updates -- marker geometry is derived from post-layout measurements (offsetTop, clientHeight, window.innerHeight)
|
|
61
62
|
setMarkers(markers.reduce((acc, marker, index) => {
|
|
62
63
|
var _a;
|
|
63
64
|
const step = visibleSteps[index];
|
|
@@ -171,6 +172,7 @@ function useCodeWalkthroughSteps({ steps, enableDeepLink, root, }) {
|
|
|
171
172
|
}
|
|
172
173
|
const rootTopOffset = (_c = (_a = root.current) === null || _a === void 0 ? void 0 : _a.offsetTop) !== null && _c !== void 0 ? _c : 0;
|
|
173
174
|
if (!activeStep && rootTopOffset <= options.navbarHeight) {
|
|
175
|
+
// oxlint-disable-next-line react-you-might-not-need-an-effect/no-derived-state -- seeded from root.current.offsetTop, a post-layout measurement
|
|
174
176
|
setActiveStep(((_b = visibleSteps[0]) === null || _b === void 0 ? void 0 : _b.id) || null);
|
|
175
177
|
}
|
|
176
178
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -11,6 +11,7 @@ function useMenuItemExpanded(item) {
|
|
|
11
11
|
// it's important for transitions
|
|
12
12
|
const [controlledValue, setControlledValue] = (0, react_1.useState)(isItemExpanded(item));
|
|
13
13
|
(0, react_1.useEffect)(() => {
|
|
14
|
+
// oxlint-disable-next-line react-you-might-not-need-an-effect/no-derived-state -- deferred a commit on purpose so CSS transitions still run
|
|
14
15
|
setIsExpanded(controlledValue);
|
|
15
16
|
}, [controlledValue]);
|
|
16
17
|
(0, react_1.useEffect)(() => {
|
|
@@ -205,19 +205,23 @@ function useActiveHeading(contentElement, displayedHeadings) {
|
|
|
205
205
|
return;
|
|
206
206
|
}
|
|
207
207
|
const headers = findHeaders(contentElement);
|
|
208
|
+
// oxlint-disable-next-line react-you-might-not-need-an-effect/no-chain-state-updates -- headings and the initial active heading come from DOM queries and scroll measurement, available only after layout
|
|
208
209
|
setHeadingElements(headers);
|
|
209
210
|
if (headers.length > 0 && !heading) {
|
|
210
211
|
if (isTopOfPage()) {
|
|
212
|
+
// oxlint-disable-next-line react-you-might-not-need-an-effect/no-chain-state-updates -- see above
|
|
211
213
|
setHeading(headers[0].id);
|
|
212
214
|
}
|
|
213
215
|
else {
|
|
214
216
|
const totalHeight = scrollY + window.innerHeight;
|
|
215
217
|
if (totalHeight >= document.body.scrollHeight - 10) {
|
|
218
|
+
// oxlint-disable-next-line react-you-might-not-need-an-effect/no-chain-state-updates -- see above
|
|
216
219
|
setHeading(((_a = headers[headers.length - 1]) === null || _a === void 0 ? void 0 : _a.id) || undefined);
|
|
217
220
|
}
|
|
218
221
|
else {
|
|
219
222
|
const triggerOffset = getTriggerOffset();
|
|
220
223
|
const activeHeader = findActiveHeaderByVirtualPosition(headers, scrollY, triggerOffset);
|
|
224
|
+
// oxlint-disable-next-line react-you-might-not-need-an-effect/no-chain-state-updates -- see above
|
|
221
225
|
setHeading(activeHeader.id);
|
|
222
226
|
}
|
|
223
227
|
}
|
|
@@ -11,15 +11,20 @@ const use_mcp_config_1 = require("./use-mcp-config");
|
|
|
11
11
|
const clipboard_service_1 = require("../utils/clipboard-service");
|
|
12
12
|
const mcp_1 = require("../constants/mcp");
|
|
13
13
|
const mcp_2 = require("../utils/mcp");
|
|
14
|
+
const get_base_data_attributes_1 = require("../utils/telemetry/get-base-data-attributes");
|
|
14
15
|
const COPIED_RESET_TIMEOUT = 1000;
|
|
15
16
|
function useConnectMCPButton({ options = mcp_1.DEFAULT_MCP_OPTIONS, } = {}) {
|
|
16
|
-
const { useTranslate } = (0, use_theme_hooks_1.useThemeHooks)();
|
|
17
|
+
const { useTranslate, useTelemetry } = (0, use_theme_hooks_1.useThemeHooks)();
|
|
17
18
|
const { translate } = useTranslate();
|
|
19
|
+
const telemetry = useTelemetry();
|
|
18
20
|
const { serverName, serverUrl, cursorUrl, vscodeUrl } = (0, use_mcp_config_1.useMCPConfig)();
|
|
19
21
|
const [copiedOption, setCopiedOption] = (0, react_1.useState)(null);
|
|
20
22
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
21
23
|
const resetCopied = (0, react_1.useCallback)((0, lodash_debounce_1.default)(() => setCopiedOption(null), COPIED_RESET_TIMEOUT), []);
|
|
22
24
|
const handleAction = (0, react_1.useCallback)((action) => {
|
|
25
|
+
telemetry.sendConnectMcpClickedMessage([
|
|
26
|
+
Object.assign(Object.assign({}, (0, get_base_data_attributes_1.getBaseDataAttributes)('connectMcp', 'button')), { option: action }),
|
|
27
|
+
]);
|
|
23
28
|
const connection = { serverName, url: serverUrl };
|
|
24
29
|
const copyTextMap = {
|
|
25
30
|
copy: JSON.stringify({ [serverName]: { url: serverUrl, description: 'MCP Server' } }, null, 2),
|
|
@@ -38,7 +43,7 @@ function useConnectMCPButton({ options = mcp_1.DEFAULT_MCP_OPTIONS, } = {}) {
|
|
|
38
43
|
vscode: vscodeUrl,
|
|
39
44
|
};
|
|
40
45
|
window.open(urlMap[action], '_blank');
|
|
41
|
-
}, [cursorUrl, vscodeUrl, serverUrl, serverName, resetCopied]);
|
|
46
|
+
}, [cursorUrl, vscodeUrl, serverUrl, serverName, resetCopied, telemetry]);
|
|
42
47
|
const triggerButtonText = (0, react_1.useMemo)(() => translate('page.actions.connectMcp', 'Connect MCP'), [translate]);
|
|
43
48
|
const visibleOptions = (0, react_1.useMemo)(() => options.filter(Boolean), [options]);
|
|
44
49
|
return {
|
|
@@ -22,6 +22,7 @@ function useLocalState(key, initialValue) {
|
|
|
22
22
|
(0, react_1.useEffect)(() => {
|
|
23
23
|
if (!(0, js_utils_1.isBrowser)())
|
|
24
24
|
return;
|
|
25
|
+
// oxlint-disable-next-line react-you-might-not-need-an-effect/no-derived-state -- localStorage is read after mount so SSR and client hydrate from the same value
|
|
25
26
|
setValue(getStoredValue(key, initialValue));
|
|
26
27
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
27
28
|
}, [key]);
|
|
@@ -7,9 +7,17 @@ const use_modal_scroll_lock_1 = require("./use-modal-scroll-lock");
|
|
|
7
7
|
function useMobileMenu(initialState = false) {
|
|
8
8
|
const location = (0, react_router_1.useLocation)();
|
|
9
9
|
const [isOpen, setIsOpen] = (0, react_1.useState)(initialState);
|
|
10
|
-
|
|
10
|
+
const locationKey = `${location.pathname}${location.hash}`;
|
|
11
|
+
const [prevLocationKey, setPrevLocationKey] = (0, react_1.useState)(locationKey);
|
|
12
|
+
if (isOpen && prevLocationKey !== locationKey) {
|
|
13
|
+
setPrevLocationKey(locationKey);
|
|
14
|
+
setIsOpen(false);
|
|
15
|
+
}
|
|
11
16
|
(0, use_modal_scroll_lock_1.useModalScrollLock)(isOpen);
|
|
12
|
-
const openMobileMenu = () =>
|
|
17
|
+
const openMobileMenu = () => {
|
|
18
|
+
setPrevLocationKey(locationKey);
|
|
19
|
+
setIsOpen(true);
|
|
20
|
+
};
|
|
13
21
|
const closeMobileMenu = () => setIsOpen(false);
|
|
14
22
|
return { isOpen, openMobileMenu, closeMobileMenu };
|
|
15
23
|
}
|
|
@@ -33,7 +33,7 @@ function useProductPicker() {
|
|
|
33
33
|
Array.from(root.classList)
|
|
34
34
|
.filter((c) => c.startsWith('product-'))
|
|
35
35
|
.forEach((c) => root.classList.remove(c));
|
|
36
|
-
root.classList.add((0, utils_1.getProductClassName)(freshProduct.name));
|
|
36
|
+
root.classList.add((0, utils_2.getSafeClassName)((0, utils_1.getProductClassName)(freshProduct.name)));
|
|
37
37
|
}
|
|
38
38
|
loadAndNavigate({ navigate, to: (0, utils_2.withPathPrefix)(freshProduct.link) });
|
|
39
39
|
}
|
|
@@ -220,12 +220,14 @@ const useActiveTab = ({ initialTab, tabsId }) => {
|
|
|
220
220
|
const [activeTab, setActiveTab] = (0, react_1.useState)(undefined);
|
|
221
221
|
const resolvedActiveTab = activeTab !== null && activeTab !== void 0 ? activeTab : initialTab;
|
|
222
222
|
const prevActiveTabRef = (0, react_1.useRef)(resolvedActiveTab);
|
|
223
|
+
const isTabResolvedFromHashRef = (0, react_1.useRef)(false);
|
|
223
224
|
(0, react_1.useEffect)(() => {
|
|
224
|
-
if (
|
|
225
|
+
if (isTabResolvedFromHashRef.current) {
|
|
225
226
|
return;
|
|
226
227
|
}
|
|
228
|
+
isTabResolvedFromHashRef.current = true;
|
|
227
229
|
setActiveTab(getInitialTab({ initialTab, hash: location.hash, tabsId }));
|
|
228
|
-
}, [
|
|
230
|
+
}, [initialTab, location.hash, tabsId]);
|
|
229
231
|
(0, react_1.useEffect)(() => {
|
|
230
232
|
const hasActiveTabChanged = prevActiveTabRef.current !== resolvedActiveTab;
|
|
231
233
|
if (!tabsId || !hasActiveTabChanged) {
|
|
@@ -34,6 +34,8 @@ export declare const useTelemetryFallback: () => {
|
|
|
34
34
|
sendProductPickerChangedMessage: () => void;
|
|
35
35
|
sendLogoClickedMessage: () => void;
|
|
36
36
|
sendCodeSnippetReportedMessage: () => void;
|
|
37
|
+
sendConnectMcpClickedMessage: () => void;
|
|
38
|
+
sendMcpConnectionSnippetCopiedMessage: () => void;
|
|
37
39
|
sendMobileMenuClosedMessage: () => void;
|
|
38
40
|
sendMobileMenuOpenedMessage: () => void;
|
|
39
41
|
sendPageViewedMessage: () => void;
|
|
@@ -39,6 +39,8 @@ const useTelemetryFallback = () => ({
|
|
|
39
39
|
sendProductPickerChangedMessage: () => { },
|
|
40
40
|
sendLogoClickedMessage: () => { },
|
|
41
41
|
sendCodeSnippetReportedMessage: () => { },
|
|
42
|
+
sendConnectMcpClickedMessage: () => { },
|
|
43
|
+
sendMcpConnectionSnippetCopiedMessage: () => { },
|
|
42
44
|
sendMobileMenuClosedMessage: () => { },
|
|
43
45
|
sendMobileMenuOpenedMessage: () => { },
|
|
44
46
|
sendPageViewedMessage: () => { },
|
|
@@ -592,6 +592,7 @@ const links = (0, styled_components_1.css) `
|
|
|
592
592
|
|
|
593
593
|
// @tokens End
|
|
594
594
|
`;
|
|
595
|
+
// oxlint-disable-next-line theme/css-variable-pattern -- `--schema-labels--text-color` is a documented public variable
|
|
595
596
|
const apiReferenceDocs = (0, styled_components_1.css) `
|
|
596
597
|
/* === ref docs and graphql docs specific === */
|
|
597
598
|
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSafeClassName = getSafeClassName;
|
|
3
4
|
exports.concatClassNames = concatClassNames;
|
|
4
5
|
const SPACE_DELIMITER = ' ';
|
|
6
|
+
// EasyList/AdGuard ship generic cosmetic rules that hide these exact class tokens on every
|
|
7
|
+
// site; the trailing underscore keeps the class usable without matching the filter lists.
|
|
8
|
+
const ADBLOCK_HIDDEN_CLASS_NAMES = new Set(['product-ad', 'product-ads', 'product-inlist-ad']);
|
|
9
|
+
function getSafeClassName(className) {
|
|
10
|
+
return ADBLOCK_HIDDEN_CLASS_NAMES.has(className) ? `${className}_` : className;
|
|
11
|
+
}
|
|
5
12
|
function concatClassNames(...args) {
|
|
6
13
|
return args
|
|
7
14
|
.map((className) => (className ? className.trim() : className))
|
|
@@ -32,21 +32,21 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
36
|
exports.Accordion = Accordion;
|
|
40
|
-
const react_1 =
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
41
38
|
const styled_components_1 = __importStar(require("styled-components"));
|
|
42
39
|
const ChevronRightIcon_1 = require("../../../icons/ChevronRightIcon/ChevronRightIcon");
|
|
43
40
|
const constants_1 = require("../../../core/constants");
|
|
41
|
+
const contexts_1 = require("../../../core/contexts");
|
|
44
42
|
function Accordion({ title, expanded = false, className, children, 'data-source': dataSource, 'data-hash': dataHash, }) {
|
|
45
|
-
|
|
43
|
+
const groupName = (0, react_1.useContext)(contexts_1.AccordionGroupContext);
|
|
44
|
+
return (react_1.default.createElement(AccordionWrapper, { className: className, open: expanded, name: groupName !== null && groupName !== void 0 ? groupName : undefined, "data-component-name": constants_1.ACCORDION_COMPONENT_NAME, "data-source": dataSource, "data-hash": dataHash },
|
|
46
45
|
react_1.default.createElement(AccordionSummary, null,
|
|
47
46
|
react_1.default.createElement(ChevronRightIcon_1.ChevronRightIcon, { color: "--md-accordion-chevron-icon-color", size: "var(--md-accordion-chevron-icon-size)" }),
|
|
48
47
|
title),
|
|
49
|
-
react_1.default.createElement(AccordionBody, null,
|
|
48
|
+
react_1.default.createElement(AccordionBody, null,
|
|
49
|
+
react_1.default.createElement(contexts_1.AccordionGroupContext.Provider, { value: null }, children))));
|
|
50
50
|
}
|
|
51
51
|
const AccordionWrapper = styled_components_1.default.details `
|
|
52
52
|
margin: var(--md-accordion-margin);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { JSX, PropsWithChildren } from 'react';
|
|
2
2
|
export type AccordionGroupProps = {
|
|
3
|
+
singleExpanded?: boolean;
|
|
3
4
|
className?: string;
|
|
4
5
|
};
|
|
5
|
-
export declare function AccordionGroup({ className, children, }: PropsWithChildren<AccordionGroupProps>): JSX.Element;
|
|
6
|
+
export declare function AccordionGroup({ singleExpanded, className, children, }: PropsWithChildren<AccordionGroupProps>): JSX.Element;
|
|
@@ -1,14 +1,50 @@
|
|
|
1
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
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
5
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
39
|
exports.AccordionGroup = AccordionGroup;
|
|
7
|
-
const react_1 =
|
|
40
|
+
const react_1 = __importStar(require("react"));
|
|
8
41
|
const styled_components_1 = __importDefault(require("styled-components"));
|
|
9
42
|
const constants_1 = require("../../../core/constants");
|
|
10
|
-
|
|
11
|
-
|
|
43
|
+
const contexts_1 = require("../../../core/contexts");
|
|
44
|
+
function AccordionGroup({ singleExpanded = false, className, children, }) {
|
|
45
|
+
const groupName = (0, react_1.useId)();
|
|
46
|
+
return (react_1.default.createElement(AccordionGroupWrapper, { className: className, "data-component-name": constants_1.ACCORDION_GROUP_COMPONENT_NAME },
|
|
47
|
+
react_1.default.createElement(contexts_1.AccordionGroupContext.Provider, { value: singleExpanded ? groupName : null }, children)));
|
|
12
48
|
}
|
|
13
49
|
const AccordionGroupWrapper = styled_components_1.default.div `
|
|
14
50
|
margin: var(--md-accordion-group-margin);
|
|
@@ -45,6 +45,7 @@ const utils_1 = require("../../../core/utils");
|
|
|
45
45
|
const LinkIcon_1 = require("../../../icons/LinkIcon/LinkIcon");
|
|
46
46
|
const PageActions_1 = require("../../../components/PageActions/PageActions");
|
|
47
47
|
const hooks_1 = require("../../../core/hooks");
|
|
48
|
+
const contexts_1 = require("../../../core/contexts");
|
|
48
49
|
const constants_1 = require("../../../core/constants");
|
|
49
50
|
function renderWithSpanWrapper(children) {
|
|
50
51
|
const childrenArray = react_1.default.Children.toArray(children);
|
|
@@ -68,10 +69,12 @@ function renderWithSpanWrapper(children) {
|
|
|
68
69
|
}
|
|
69
70
|
function Heading({ level, id, children, 'data-source': dataSource, 'data-hash': dataHash, className, __idx, }) {
|
|
70
71
|
var _a, _b;
|
|
72
|
+
var _c;
|
|
71
73
|
const { pathname } = (0, react_router_1.useLocation)();
|
|
72
74
|
const { usePageProps } = (0, hooks_1.useThemeHooks)();
|
|
73
75
|
const pageProps = usePageProps();
|
|
74
|
-
|
|
76
|
+
// The page-type fallback is only for backward compatibility; templates set the scope.
|
|
77
|
+
const withPageActions = (_c = (0, react_1.useContext)(contexts_1.PageActionsContext)) !== null && _c !== void 0 ? _c : (((_a = pageProps === null || pageProps === void 0 ? void 0 : pageProps.metadata) === null || _a === void 0 ? void 0 : _a.type) === 'markdown' || ((_b = pageProps === null || pageProps === void 0 ? void 0 : pageProps.metadata) === null || _b === void 0 ? void 0 : _b.type) === 'asciidoc');
|
|
75
78
|
const headingTextId = `${id}-heading-text`;
|
|
76
79
|
const linkEl = (react_1.default.createElement("a", { "aria-labelledby": headingTextId, href: `#${id}`, className: (0, utils_1.concatClassNames)(constants_1.ANCHOR_CLASS, 'before') },
|
|
77
80
|
react_1.default.createElement(LinkIcon_1.LinkIcon, { "aria-hidden": "true", focusable: "false", color: "--heading-anchor-color" })));
|
|
@@ -80,7 +83,7 @@ function Heading({ level, id, children, 'data-source': dataSource, 'data-hash':
|
|
|
80
83
|
react_1.default.createElement(HeadingContentWrapper, null,
|
|
81
84
|
linkEl,
|
|
82
85
|
headingText,
|
|
83
|
-
|
|
86
|
+
withPageActions && __idx === 0 ? react_1.default.createElement(PageActions_1.PageActions, { pageSlug: pathname }) : null)));
|
|
84
87
|
}
|
|
85
88
|
const HeadingContentWrapper = styled_components_1.default.div `
|
|
86
89
|
display: flex;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/theme",
|
|
3
|
-
"version": "0.69.0
|
|
3
|
+
"version": "0.69.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.15.0
|
|
45
|
+
"@redocly/realm-asyncapi-sdk": "0.15.0",
|
|
46
46
|
"@shikijs/types": "3.21.0",
|
|
47
47
|
"@testing-library/react": "16.3.0",
|
|
48
48
|
"@testing-library/user-event": "14.6.1",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
|
|
4
4
|
import type { BaseSyntheticEvent, PropsWithChildren, ReactNode, JSX } from 'react';
|
|
@@ -32,6 +32,12 @@ export function Accordion({
|
|
|
32
32
|
}: PropsWithChildren<AccordionProps>): JSX.Element {
|
|
33
33
|
const [isExpanded, setExpanded] = useState(expanded);
|
|
34
34
|
const [animate, setAnimate] = useState(false);
|
|
35
|
+
const [prevExpanded, setPrevExpanded] = useState(expanded);
|
|
36
|
+
|
|
37
|
+
if (prevExpanded !== expanded) {
|
|
38
|
+
setPrevExpanded(expanded);
|
|
39
|
+
setExpanded(expanded);
|
|
40
|
+
}
|
|
35
41
|
|
|
36
42
|
const toggle = ({ target }: BaseSyntheticEvent): void => {
|
|
37
43
|
if (target instanceof HTMLAnchorElement || !isExpandable) return;
|
|
@@ -40,8 +46,6 @@ export function Accordion({
|
|
|
40
46
|
onToggle?.(!isExpanded);
|
|
41
47
|
};
|
|
42
48
|
|
|
43
|
-
useEffect(() => setExpanded(expanded), [expanded]);
|
|
44
|
-
|
|
45
49
|
return (
|
|
46
50
|
<AccordionWrapper
|
|
47
51
|
className={className}
|
|
@@ -88,6 +88,7 @@ export function CatalogEntities(props: CatalogEntitiesProps): JSX.Element {
|
|
|
88
88
|
(query.isPlaceholderData && entities && entities.length >= LOAD_MORE_THRESHOLD);
|
|
89
89
|
|
|
90
90
|
useEffect(() => {
|
|
91
|
+
// oxlint-disable-next-line react-you-might-not-need-an-effect/no-pass-data-to-parent -- the entities query lives in this ejectable component; the fetched total is mirrored up so the portal page header can show the count
|
|
91
92
|
setEntitiesCounter(total || 0);
|
|
92
93
|
}, [total, setEntitiesCounter]);
|
|
93
94
|
|
package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelations.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { JSX, useState,
|
|
1
|
+
import React, { JSX, useState, useMemo } from 'react';
|
|
2
2
|
|
|
3
3
|
import type { CatalogEntityConfig, EntitiesCatalogConfig } from '@redocly/config';
|
|
4
4
|
import type { BffCatalogEntity, BffCatalogRelatedEntityList } from '@redocly/theme/core/types';
|
|
@@ -35,10 +35,12 @@ export function CatalogEntityRelations({
|
|
|
35
35
|
const { sortOption, setSortOption, handleSortClick, isColumnSorted } = useCatalogSort();
|
|
36
36
|
|
|
37
37
|
const [filter, setFilter] = useState<string | undefined>(ENTITY_DEFAULT_FILTERS[entity.type]);
|
|
38
|
+
const [prevEntityKey, setPrevEntityKey] = useState(entity.key);
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
if (prevEntityKey !== entity.key) {
|
|
41
|
+
setPrevEntityKey(entity.key);
|
|
42
|
+
setFilter(ENTITY_DEFAULT_FILTERS[entity.type]);
|
|
43
|
+
}
|
|
42
44
|
|
|
43
45
|
const combinedFilter = useMemo(() => {
|
|
44
46
|
const baseFilter = filter ?? ENTITY_DEFAULT_FILTERS[entity.type];
|
|
@@ -1,31 +1,16 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
|
|
4
4
|
import { TableIcon } from '@redocly/theme/icons/TableIcon/TableIcon';
|
|
5
5
|
import { CardsIcon } from '@redocly/theme/icons/CardsIcon/CardsIcon';
|
|
6
6
|
import { CatalogViewMode } from '@redocly/theme/core/types';
|
|
7
7
|
|
|
8
|
-
function useViewMode(initialViewMode: CatalogViewMode) {
|
|
9
|
-
const [viewMode, setViewMode] = useState<CatalogViewMode | null>(null);
|
|
10
|
-
|
|
11
|
-
useEffect(() => {
|
|
12
|
-
setViewMode(initialViewMode);
|
|
13
|
-
}, [initialViewMode]);
|
|
14
|
-
|
|
15
|
-
return viewMode;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
8
|
export type CatalogViewModeToggleProps = {
|
|
19
9
|
viewMode: CatalogViewMode;
|
|
20
10
|
onViewModeChange: (mode: CatalogViewMode) => void;
|
|
21
11
|
};
|
|
22
12
|
|
|
23
|
-
export function CatalogViewModeToggle({
|
|
24
|
-
viewMode: initialViewMode,
|
|
25
|
-
onViewModeChange,
|
|
26
|
-
}: CatalogViewModeToggleProps) {
|
|
27
|
-
const viewMode = useViewMode(initialViewMode);
|
|
28
|
-
|
|
13
|
+
export function CatalogViewModeToggle({ viewMode, onViewModeChange }: CatalogViewModeToggleProps) {
|
|
29
14
|
return (
|
|
30
15
|
<ViewModeToggleWrapper data-component-name="Catalog/CatalogViewModeToggle">
|
|
31
16
|
<ViewModeButton
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
|
|
4
4
|
import type { JSX } from 'react';
|
|
@@ -16,10 +16,12 @@ export function FilterInput(props: FilterInputProps): JSX.Element {
|
|
|
16
16
|
const { value: initialValue, onChange, dataTestId } = props;
|
|
17
17
|
|
|
18
18
|
const [value, setValue] = useState(initialValue);
|
|
19
|
+
const [prevInitialValue, setPrevInitialValue] = useState(initialValue);
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
if (prevInitialValue !== initialValue) {
|
|
22
|
+
setPrevInitialValue(initialValue);
|
|
21
23
|
setValue(initialValue);
|
|
22
|
-
}
|
|
24
|
+
}
|
|
23
25
|
|
|
24
26
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
25
27
|
const newValue = e.target.value;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
|
|
4
4
|
import type { JSX } from 'react';
|
|
@@ -23,14 +23,16 @@ export function JsonValue(props: {
|
|
|
23
23
|
expandAllSignal ?? level < defaultExpandLevel,
|
|
24
24
|
);
|
|
25
25
|
const isExpanded = expandAllSignal !== undefined && level > 0 ? expandAllSignal : isExpandedState;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
const [prevExpandAllSignal, setPrevExpandAllSignal] = React.useState(expandAllSignal);
|
|
27
|
+
const [prevLevel, setPrevLevel] = React.useState(level);
|
|
28
|
+
|
|
29
|
+
if (prevExpandAllSignal !== expandAllSignal || prevLevel !== level) {
|
|
30
|
+
setPrevExpandAllSignal(expandAllSignal);
|
|
31
|
+
setPrevLevel(level);
|
|
32
|
+
if (expandAllSignal !== undefined && !(expandAllSignal === false && level === 0)) {
|
|
31
33
|
setExpanded(expandAllSignal);
|
|
32
34
|
}
|
|
33
|
-
}
|
|
35
|
+
}
|
|
34
36
|
|
|
35
37
|
const keys: string[] =
|
|
36
38
|
(value && Object.keys(value).filter((key) => value[key] !== undefined)) || []; // filter out undefined properties
|
|
@@ -131,12 +133,14 @@ function JsonKeyValue(props: {
|
|
|
131
133
|
expandAllSignal ?? level < defaultExpandLevel,
|
|
132
134
|
);
|
|
133
135
|
const isExpanded = expandAllSignal !== undefined ? expandAllSignal : isExpandedState;
|
|
136
|
+
const [prevExpandAllSignal, setPrevExpandAllSignal] = React.useState(expandAllSignal);
|
|
134
137
|
|
|
135
|
-
|
|
138
|
+
if (prevExpandAllSignal !== expandAllSignal) {
|
|
139
|
+
setPrevExpandAllSignal(expandAllSignal);
|
|
136
140
|
if (expandAllSignal !== undefined) {
|
|
137
141
|
setExpanded(expandAllSignal);
|
|
138
142
|
}
|
|
139
|
-
}
|
|
143
|
+
}
|
|
140
144
|
|
|
141
145
|
const openingPunctuation = Array.isArray(value) ? '[' : '{';
|
|
142
146
|
const closingPunctuation = Array.isArray(value) ? ']' : '}';
|