@redocly/theme 0.58.0-next.9 → 0.59.0-next.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/Catalog/CatalogEntity/CatalogEntity.d.ts +5 -1
- package/lib/components/Catalog/CatalogEntity/CatalogEntity.js +4 -4
- package/lib/components/Catalog/CatalogEntity/CatalogEntityMetadata.js +3 -3
- package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.js +1 -1
- package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.js +1 -1
- package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.d.ts +5 -1
- package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.js +9 -7
- package/lib/components/CodeBlock/CodeBlock.d.ts +5 -12
- package/lib/components/CodeBlock/CodeBlockControls.d.ts +3 -3
- package/lib/components/CodeBlock/CodeBlockControls.js +1 -1
- package/lib/components/CodeBlock/CodeBlockDropdown.d.ts +2 -2
- package/lib/components/CodeBlock/CodeBlockDropdown.js +4 -13
- package/lib/components/CodeBlock/CodeBlockTabs.d.ts +2 -2
- package/lib/components/CodeBlock/CodeBlockTabs.js +4 -3
- package/lib/components/JsonViewer/JsonViewer.d.ts +1 -1
- package/lib/components/JsonViewer/JsonViewer.js +9 -10
- package/lib/components/PageActions/PageActions.d.ts +4 -1
- package/lib/components/PageActions/PageActions.js +2 -2
- package/lib/components/Panel/variables.js +1 -0
- package/lib/components/Tag/Tag.d.ts +3 -2
- package/lib/components/Tag/Tag.js +21 -5
- package/lib/components/Tag/variables.dark.js +135 -0
- package/lib/components/Tag/variables.js +120 -58
- package/lib/core/constants/catalog.js +4 -0
- package/lib/core/contexts/CodeSnippetContext.d.ts +14 -6
- package/lib/core/contexts/CodeSnippetContext.js +57 -14
- package/lib/core/hooks/use-codeblock-tabs-controls.d.ts +2 -2
- package/lib/core/hooks/use-local-state.js +22 -18
- package/lib/core/hooks/use-page-actions.d.ts +2 -1
- package/lib/core/hooks/use-page-actions.js +48 -6
- package/lib/core/hooks/use-tabs.d.ts +11 -6
- package/lib/core/hooks/use-tabs.js +117 -207
- package/lib/core/openapi/index.d.ts +1 -0
- package/lib/core/openapi/index.js +3 -1
- package/lib/core/types/l10n.d.ts +1 -1
- package/lib/core/types/open-api-server.d.ts +1 -0
- package/lib/core/utils/index.d.ts +1 -0
- package/lib/core/utils/index.js +1 -0
- package/lib/core/utils/tabs.d.ts +1 -0
- package/lib/core/utils/tabs.js +8 -0
- package/lib/icons/CursorIcon/CursorIcon.d.ts +9 -0
- package/lib/icons/CursorIcon/CursorIcon.js +22 -0
- package/lib/layouts/DocumentationLayout.js +1 -3
- package/lib/markdoc/components/CodeGroup/CodeGroup.js +49 -27
- package/lib/markdoc/components/Tabs/Tab.js +1 -1
- package/lib/markdoc/components/Tabs/TabList.d.ts +2 -14
- package/lib/markdoc/components/Tabs/TabList.js +65 -16
- package/lib/markdoc/components/Tabs/Tabs.d.ts +2 -2
- package/lib/markdoc/components/Tabs/Tabs.js +11 -87
- package/lib/markdoc/tags/tabs.js +5 -0
- package/package.json +4 -4
- package/src/components/Catalog/CatalogEntity/CatalogEntity.tsx +15 -2
- package/src/components/Catalog/CatalogEntity/CatalogEntityMetadata.tsx +3 -3
- package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations.tsx +1 -1
- package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.tsx +1 -1
- package/src/components/Catalog/CatalogEntity/CatalogEntitySchema.tsx +27 -18
- package/src/components/CodeBlock/CodeBlock.tsx +5 -11
- package/src/components/CodeBlock/CodeBlockControls.tsx +4 -7
- package/src/components/CodeBlock/CodeBlockDropdown.tsx +11 -20
- package/src/components/CodeBlock/CodeBlockTabs.tsx +8 -8
- package/src/components/JsonViewer/JsonViewer.tsx +16 -9
- package/src/components/PageActions/PageActions.tsx +6 -4
- package/src/components/Panel/variables.ts +1 -0
- package/src/components/Tag/Tag.tsx +33 -8
- package/src/components/Tag/variables.dark.ts +135 -0
- package/src/components/Tag/variables.ts +120 -58
- package/src/core/constants/catalog.ts +4 -0
- package/src/core/contexts/CodeSnippetContext.tsx +54 -18
- package/src/core/hooks/use-codeblock-tabs-controls.ts +2 -2
- package/src/core/hooks/use-local-state.ts +28 -19
- package/src/core/hooks/use-page-actions.ts +63 -6
- package/src/core/hooks/use-tabs.ts +160 -238
- package/src/core/openapi/index.ts +1 -0
- package/src/core/types/l10n.ts +13 -0
- package/src/core/types/open-api-server.ts +1 -0
- package/src/core/utils/index.ts +1 -0
- package/src/core/utils/tabs.ts +4 -0
- package/src/icons/CursorIcon/CursorIcon.tsx +35 -0
- package/src/layouts/DocumentationLayout.tsx +3 -10
- package/src/markdoc/components/CodeGroup/CodeGroup.tsx +81 -52
- package/src/markdoc/components/Tabs/Tab.tsx +1 -0
- package/src/markdoc/components/Tabs/TabList.tsx +85 -30
- package/src/markdoc/components/Tabs/Tabs.tsx +12 -125
- package/src/markdoc/tags/tabs.ts +5 -0
|
@@ -31,42 +31,64 @@ const contexts_1 = require("../../../core/contexts");
|
|
|
31
31
|
function CodeGroup(props) {
|
|
32
32
|
const mode = props.mode || 'tabs';
|
|
33
33
|
const isTabsMode = mode === 'tabs';
|
|
34
|
-
const rawSnippets = React.useMemo(() =>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
lang: childProps.props.lang || '',
|
|
40
|
-
props: childProps.props,
|
|
41
|
-
};
|
|
42
|
-
}), [props.children]);
|
|
43
|
-
const [activeSnippetName, setActiveSnippetName] = (0, contexts_1.useActiveCodeSnippetName)(mode);
|
|
44
|
-
const snippets = React.useMemo(() => Object.fromEntries(rawSnippets.map((snippet) => {
|
|
45
|
-
const getItemName = (snippet) => isTabsMode ? snippet === null || snippet === void 0 ? void 0 : snippet.name : (snippet === null || snippet === void 0 ? void 0 : snippet.languageName) || '';
|
|
46
|
-
const name = getItemName(snippet);
|
|
47
|
-
const items = rawSnippets.map((item) => ({
|
|
48
|
-
name: getItemName(item),
|
|
49
|
-
lang: item.lang,
|
|
50
|
-
}));
|
|
34
|
+
const rawSnippets = React.useMemo(() => parseSnippetsFromChildren(props.children), [props.children]);
|
|
35
|
+
const groupId = React.useMemo(() => generateGroupId(rawSnippets, mode), [rawSnippets, mode]);
|
|
36
|
+
const [activeSnippetId, setActiveSnippetId] = (0, contexts_1.useActiveCodeSnippetId)(groupId, rawSnippets);
|
|
37
|
+
const snippets = React.useMemo(() => {
|
|
38
|
+
const items = createItemsFromSnippets(rawSnippets, isTabsMode);
|
|
51
39
|
const itemsProps = {
|
|
52
40
|
items,
|
|
53
|
-
onChange: (
|
|
54
|
-
|
|
55
|
-
},
|
|
56
|
-
value: activeSnippetName || getItemName(rawSnippets[0]),
|
|
41
|
+
onChange: (id) => setActiveSnippetId(id),
|
|
42
|
+
value: activeSnippetId,
|
|
57
43
|
};
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
44
|
+
return Object.fromEntries(rawSnippets.map((snippet) => {
|
|
45
|
+
const snippetProps = Object.assign(Object.assign(Object.assign({}, snippet.props), { header: Object.assign(Object.assign({}, snippet.props.header), { title: isTabsMode ? undefined : snippet.name }) }), (isTabsMode ? { tabs: itemsProps } : { dropdown: itemsProps }));
|
|
46
|
+
return [snippet.id, snippetProps];
|
|
47
|
+
}));
|
|
48
|
+
}, [rawSnippets, activeSnippetId, isTabsMode, setActiveSnippetId]);
|
|
49
|
+
const activeSnippet = snippets[activeSnippetId];
|
|
63
50
|
if (!activeSnippet) {
|
|
64
51
|
return null;
|
|
65
52
|
}
|
|
66
53
|
return React.createElement(CodeBlock_1.CodeBlock, Object.assign({}, activeSnippet));
|
|
67
54
|
}
|
|
55
|
+
function generateContentHash(content) {
|
|
56
|
+
let hash = 0;
|
|
57
|
+
for (let i = 0; i < content.length; i++) {
|
|
58
|
+
hash = content.charCodeAt(i) + ((hash << 5) - hash);
|
|
59
|
+
}
|
|
60
|
+
return Math.abs(hash);
|
|
61
|
+
}
|
|
62
|
+
// Generate unique group ID for CodeGroup instance
|
|
63
|
+
// Examples: "dropdown-8901234", "tabs-1234567"
|
|
64
|
+
function generateGroupId(rawSnippets, mode) {
|
|
65
|
+
const content = rawSnippets.map((s) => s.id + (s.props.source || '')).join('|') + `|${mode}`;
|
|
66
|
+
const hash = generateContentHash(content);
|
|
67
|
+
return `${mode}-${hash}`;
|
|
68
|
+
}
|
|
68
69
|
function getTabName(props, idx) {
|
|
69
70
|
var _a;
|
|
70
|
-
|
|
71
|
+
const fallbackName = `Tab ${idx + 1}`;
|
|
72
|
+
return String(((_a = props.header) === null || _a === void 0 ? void 0 : _a.title) || props.file || (0, utils_1.langToName)(props.lang || '') || fallbackName);
|
|
73
|
+
}
|
|
74
|
+
function parseSnippetsFromChildren(children) {
|
|
75
|
+
return React.Children.toArray(children).map((child, idx) => {
|
|
76
|
+
const childProps = child;
|
|
77
|
+
const props = childProps.props;
|
|
78
|
+
return {
|
|
79
|
+
name: getTabName(props, idx),
|
|
80
|
+
languageName: String((0, utils_1.langToName)(props.lang || 'Default') || ''),
|
|
81
|
+
lang: props.lang || '',
|
|
82
|
+
props,
|
|
83
|
+
id: `${props.lang || ''}-${idx}`,
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function createItemsFromSnippets(snippets, isTabsMode) {
|
|
88
|
+
return snippets.map((snippet) => ({
|
|
89
|
+
name: isTabsMode ? snippet.name : snippet.languageName || '',
|
|
90
|
+
lang: snippet.lang,
|
|
91
|
+
id: snippet.id,
|
|
92
|
+
}));
|
|
71
93
|
}
|
|
72
94
|
//# sourceMappingURL=CodeGroup.js.map
|
|
@@ -11,7 +11,7 @@ const TabList_1 = require("../../../markdoc/components/Tabs/TabList");
|
|
|
11
11
|
const GenericIcon_1 = require("../../../icons/GenericIcon/GenericIcon");
|
|
12
12
|
function TabComponent({ tabId, label, size, disabled, setRef, onKeyDown, onClick, icon, iconRawContent, }) {
|
|
13
13
|
return (react_1.default.createElement(TabList_1.TabItem, { "data-component-name": "Markdoc/Tabs/Tab", size: size, tabIndex: 0 },
|
|
14
|
-
react_1.default.createElement(TabList_1.TabButtonLink, { id: `tab-${tabId}`, role: "tab", "aria-selected": "false", "aria-controls": `panel-${tabId}`, tabIndex: -1, size: size, disabled: disabled, ref: setRef, onKeyDown: onKeyDown, onClick: onClick },
|
|
14
|
+
react_1.default.createElement(TabList_1.TabButtonLink, { id: `tab-${tabId}`, "data-label": label, role: "tab", "aria-selected": "false", "aria-controls": `panel-${tabId}`, tabIndex: -1, size: size, disabled: disabled, ref: setRef, onKeyDown: onKeyDown, onClick: onClick },
|
|
15
15
|
react_1.default.createElement(LabelWrapper, null,
|
|
16
16
|
react_1.default.createElement(GenericIcon_1.GenericIcon, { icon: icon, rawContent: iconRawContent }),
|
|
17
17
|
label))));
|
|
@@ -4,22 +4,10 @@ import { TabItemProps, TabsSize } from '../../../markdoc/components/Tabs/Tabs';
|
|
|
4
4
|
type TabListProps = {
|
|
5
5
|
childrenArray: React.ReactElement<TabItemProps>[];
|
|
6
6
|
size: TabsSize;
|
|
7
|
-
overflowTabs: number[];
|
|
8
|
-
visibleTabs: number[];
|
|
9
|
-
setTabRef: (element: HTMLButtonElement | null, index: number) => void;
|
|
10
|
-
onTabClick: (labelOrIndex: string | number) => void;
|
|
11
|
-
handleKeyboard: (event: React.KeyboardEvent<HTMLButtonElement>, index: number) => void;
|
|
12
|
-
getTabId: (label: string, index: number) => string;
|
|
13
7
|
activeTab: string;
|
|
14
|
-
|
|
15
|
-
highlightStyle: {
|
|
16
|
-
left: number;
|
|
17
|
-
width: number;
|
|
18
|
-
};
|
|
19
|
-
allTabsHidden: boolean;
|
|
20
|
-
tabsContainerRef: React.RefObject<HTMLUListElement | null>;
|
|
8
|
+
onTabChange: (tab: string) => void;
|
|
21
9
|
};
|
|
22
|
-
export declare function TabList({ childrenArray, size,
|
|
10
|
+
export declare function TabList({ childrenArray, size, activeTab, onTabChange, }: TabListProps): JSX.Element;
|
|
23
11
|
export declare const TabListContainer: import("styled-components").StyledComponent<"ul", any, {}, never>;
|
|
24
12
|
export declare const TabItem: import("styled-components").StyledComponent<"li", any, {
|
|
25
13
|
active?: boolean;
|
|
@@ -22,35 +22,42 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
26
|
exports.TabButtonLink = exports.TabItem = exports.TabListContainer = void 0;
|
|
30
27
|
exports.TabList = TabList;
|
|
31
|
-
const react_1 =
|
|
28
|
+
const react_1 = __importStar(require("react"));
|
|
32
29
|
const styled_components_1 = __importStar(require("styled-components"));
|
|
33
30
|
const Tab_1 = require("../../../markdoc/components/Tabs/Tab");
|
|
34
31
|
const Dropdown_1 = require("../../../components/Dropdown/Dropdown");
|
|
35
32
|
const DropdownMenu_1 = require("../../../components/Dropdown/DropdownMenu");
|
|
36
33
|
const DropdownMenuItem_1 = require("../../../components/Dropdown/DropdownMenuItem");
|
|
37
34
|
const Button_1 = require("../../../components/Button/Button");
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
const hooks_1 = require("../../../core/hooks");
|
|
36
|
+
const utils_1 = require("../../../core/utils");
|
|
37
|
+
function TabList({ childrenArray, size, activeTab, onTabChange, }) {
|
|
38
|
+
const tabsContainerRef = (0, react_1.useRef)(null);
|
|
39
|
+
const { allTabsHidden, overflowTabs, visibleTabs, handleKeyboard, onTabClick, setTabRef } = (0, hooks_1.useTabs)({
|
|
40
|
+
activeTab,
|
|
41
|
+
onTabChange,
|
|
42
|
+
containerRef: tabsContainerRef,
|
|
43
|
+
totalTabs: childrenArray.length,
|
|
44
|
+
});
|
|
45
|
+
const { highlightStyle } = useHighlightBarAnimation({
|
|
46
|
+
activeTab,
|
|
47
|
+
childrenArray,
|
|
48
|
+
overflowTabs,
|
|
49
|
+
tabsContainerRef,
|
|
50
|
+
visibleTabs,
|
|
51
|
+
});
|
|
52
|
+
return (react_1.default.createElement(exports.TabListContainer, { role: "tablist", ref: tabsContainerRef },
|
|
53
|
+
react_1.default.createElement(HighlightBar, { size: size, style: highlightStyle },
|
|
41
54
|
react_1.default.createElement("div", null)),
|
|
42
55
|
childrenArray.map((child, index) => {
|
|
43
56
|
if (!visibleTabs.includes(index))
|
|
44
57
|
return null;
|
|
45
58
|
const { label, icon } = child.props;
|
|
46
|
-
const tabId = getTabId(label, index);
|
|
47
|
-
return (react_1.default.createElement(Tab_1.Tab, { key: `key-${tabId}`, tabId: tabId, label: label, icon: icon, size: size, disabled: child.props.disable, setRef: (el) => {
|
|
48
|
-
setTabRef(el, index);
|
|
49
|
-
if (el) {
|
|
50
|
-
el.setAttribute('data-label', label);
|
|
51
|
-
el.setAttribute('data-animating', isAnimating.toString());
|
|
52
|
-
}
|
|
53
|
-
}, onKeyDown: (event) => handleKeyboard(event, index), onClick: () => {
|
|
59
|
+
const tabId = (0, utils_1.getTabId)(label, index);
|
|
60
|
+
return (react_1.default.createElement(Tab_1.Tab, { key: `key-${tabId}`, tabId: tabId, label: label, icon: icon, size: size, disabled: child.props.disable, setRef: (el) => setTabRef(el, index), onKeyDown: (event) => handleKeyboard(event, index), onClick: () => {
|
|
54
61
|
var _a, _b;
|
|
55
62
|
(_b = (_a = child.props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
56
63
|
onTabClick(label);
|
|
@@ -61,12 +68,54 @@ function TabList({ childrenArray, size, overflowTabs, visibleTabs, setTabRef, on
|
|
|
61
68
|
: undefined }, allTabsHidden ? activeTab : 'More'), alignment: "start", withArrow: true },
|
|
62
69
|
react_1.default.createElement(DropdownMenu_1.DropdownMenu, null, overflowTabs.map((index) => {
|
|
63
70
|
const { label } = childrenArray[index].props;
|
|
64
|
-
const tabId = getTabId(label, index);
|
|
71
|
+
const tabId = (0, utils_1.getTabId)(label, index);
|
|
65
72
|
return (react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { key: `more-${tabId}`, active: activeTab === label, onAction: () => {
|
|
73
|
+
var _a, _b;
|
|
74
|
+
(_b = (_a = childrenArray[index].props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
66
75
|
onTabClick(index);
|
|
67
76
|
}, disabled: childrenArray[index].props.disable }, label));
|
|
68
77
|
})))))));
|
|
69
78
|
}
|
|
79
|
+
const useHighlightBarAnimation = (props) => {
|
|
80
|
+
const { childrenArray, activeTab, tabsContainerRef, visibleTabs, overflowTabs } = props;
|
|
81
|
+
const [highlightStyle, setHighlightStyle] = react_1.default.useState({
|
|
82
|
+
left: 0,
|
|
83
|
+
width: 0,
|
|
84
|
+
});
|
|
85
|
+
(0, react_1.useEffect)(() => {
|
|
86
|
+
const activeIndex = childrenArray.findIndex((child) => child.props.label === activeTab);
|
|
87
|
+
const container = tabsContainerRef.current;
|
|
88
|
+
if (!container || activeIndex === -1) {
|
|
89
|
+
setHighlightStyle({ left: 0, width: 0 });
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const activeTabElement = container.querySelector(`[data-label="${activeTab}"]`);
|
|
93
|
+
if (!activeTabElement)
|
|
94
|
+
return;
|
|
95
|
+
container.querySelectorAll('[data-label]').forEach((el) => {
|
|
96
|
+
el.classList.remove('active');
|
|
97
|
+
});
|
|
98
|
+
const { offsetLeft, offsetWidth } = activeTabElement;
|
|
99
|
+
if (visibleTabs.includes(activeIndex)) {
|
|
100
|
+
activeTabElement.classList.add('active');
|
|
101
|
+
setHighlightStyle({ left: offsetLeft, width: offsetWidth });
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (overflowTabs.includes(activeIndex)) {
|
|
105
|
+
const moreButton = container.querySelector('button');
|
|
106
|
+
if (!moreButton)
|
|
107
|
+
return;
|
|
108
|
+
const moreButtonRect = moreButton.getBoundingClientRect();
|
|
109
|
+
const containerRect = container.getBoundingClientRect();
|
|
110
|
+
setHighlightStyle({
|
|
111
|
+
left: moreButtonRect.left - containerRect.left,
|
|
112
|
+
width: moreButtonRect.width,
|
|
113
|
+
});
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
}, [activeTab, childrenArray, visibleTabs, overflowTabs, tabsContainerRef]);
|
|
117
|
+
return { highlightStyle };
|
|
118
|
+
};
|
|
70
119
|
exports.TabListContainer = styled_components_1.default.ul `
|
|
71
120
|
position: relative;
|
|
72
121
|
display: flex;
|
|
@@ -12,12 +12,12 @@ export type TabItemProps = {
|
|
|
12
12
|
icon?: React.ReactNode | string;
|
|
13
13
|
};
|
|
14
14
|
type TabsProps = {
|
|
15
|
+
id?: string;
|
|
15
16
|
children: React.ReactElement<TabItemProps>[];
|
|
16
17
|
className?: string;
|
|
17
18
|
size: TabsSize;
|
|
18
|
-
forceReady?: boolean;
|
|
19
19
|
initialTab?: string;
|
|
20
20
|
};
|
|
21
|
-
export declare function Tabs({ children, className, size,
|
|
21
|
+
export declare function Tabs({ id, children, className, size, initialTab: propInitialTab, }: TabsProps): JSX.Element;
|
|
22
22
|
export declare const TabContent: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
23
23
|
export {};
|
|
@@ -22,101 +22,35 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
25
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
29
|
exports.TabContent = exports.TabsSize = void 0;
|
|
27
30
|
exports.Tabs = Tabs;
|
|
28
31
|
const react_1 = __importStar(require("react"));
|
|
29
|
-
const styled_components_1 =
|
|
32
|
+
const styled_components_1 = __importDefault(require("styled-components"));
|
|
30
33
|
const hooks_1 = require("../../../core/hooks");
|
|
31
34
|
const TabList_1 = require("../../../markdoc/components/Tabs/TabList");
|
|
35
|
+
const utils_1 = require("../../../core/utils");
|
|
32
36
|
var TabsSize;
|
|
33
37
|
(function (TabsSize) {
|
|
34
38
|
TabsSize["SMALL"] = "small";
|
|
35
39
|
TabsSize["MEDIUM"] = "medium";
|
|
36
40
|
})(TabsSize || (exports.TabsSize = TabsSize = {}));
|
|
37
|
-
function Tabs({ children, className, size,
|
|
41
|
+
function Tabs({ id, children, className, size, initialTab: propInitialTab, }) {
|
|
38
42
|
var _a, _b;
|
|
39
43
|
const [childrenArray, setChildrenArray] = (0, react_1.useState)(react_1.default.Children.toArray(children));
|
|
44
|
+
const initialTab = (_b = propInitialTab !== null && propInitialTab !== void 0 ? propInitialTab : (_a = childrenArray[0]) === null || _a === void 0 ? void 0 : _a.props.label) !== null && _b !== void 0 ? _b : '';
|
|
45
|
+
const { activeTab, setActiveTab } = (0, hooks_1.useActiveTab)({ tabsId: id, initialTab });
|
|
40
46
|
(0, react_1.useEffect)(() => {
|
|
41
47
|
setChildrenArray(react_1.default.Children.toArray(children));
|
|
42
48
|
}, [children]);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const defaultInitialTab = (_b = (_a = childrenArray[0]) === null || _a === void 0 ? void 0 : _a.props.label) !== null && _b !== void 0 ? _b : '';
|
|
46
|
-
const initialTab = propInitialTab !== null && propInitialTab !== void 0 ? propInitialTab : defaultInitialTab;
|
|
47
|
-
const { activeTab, setTabRef, onTabClick, handleKeyboard, getTabId, visibleTabs, overflowTabs, ready, allTabsHidden, } = (0, hooks_1.useTabs)({
|
|
48
|
-
initialTab,
|
|
49
|
-
totalTabs: childrenArray.length,
|
|
50
|
-
containerRef: tabsContainerRef,
|
|
51
|
-
});
|
|
52
|
-
const [prevTab, setPrevTab] = react_1.default.useState(initialTab);
|
|
53
|
-
const [highlightStyle, setHighlightStyle] = react_1.default.useState({
|
|
54
|
-
left: 0,
|
|
55
|
-
width: 0,
|
|
56
|
-
});
|
|
57
|
-
(0, react_1.useEffect)(() => {
|
|
58
|
-
setPrevTab(activeTab);
|
|
59
|
-
setIsAnimating(true);
|
|
60
|
-
const activeIndex = childrenArray.findIndex((child) => child.props.label === activeTab);
|
|
61
|
-
const container = tabsContainerRef.current;
|
|
62
|
-
if (container) {
|
|
63
|
-
container.querySelectorAll('[data-label]').forEach((el) => {
|
|
64
|
-
el.classList.remove('active');
|
|
65
|
-
});
|
|
66
|
-
container.getBoundingClientRect();
|
|
67
|
-
requestAnimationFrame(() => {
|
|
68
|
-
if (activeIndex >= 0) {
|
|
69
|
-
let activeTabElement = null;
|
|
70
|
-
let startPosition = { left: 0, width: 0 };
|
|
71
|
-
if (visibleTabs.includes(activeIndex)) {
|
|
72
|
-
activeTabElement = container.querySelector(`[data-label="${activeTab}"]`);
|
|
73
|
-
}
|
|
74
|
-
else if (overflowTabs.includes(activeIndex)) {
|
|
75
|
-
const moreButton = container.querySelector('button');
|
|
76
|
-
if (moreButton) {
|
|
77
|
-
const moreButtonRect = moreButton.getBoundingClientRect();
|
|
78
|
-
const containerRect = container.getBoundingClientRect();
|
|
79
|
-
startPosition = {
|
|
80
|
-
left: moreButtonRect.left - containerRect.left,
|
|
81
|
-
width: moreButtonRect.width,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
if (activeTabElement) {
|
|
86
|
-
const { offsetLeft, offsetWidth } = activeTabElement;
|
|
87
|
-
if (overflowTabs.includes(activeIndex)) {
|
|
88
|
-
setHighlightStyle(startPosition);
|
|
89
|
-
requestAnimationFrame(() => {
|
|
90
|
-
setHighlightStyle({ left: offsetLeft, width: offsetWidth });
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
setHighlightStyle({ left: offsetLeft, width: offsetWidth });
|
|
95
|
-
}
|
|
96
|
-
if (visibleTabs.includes(activeIndex)) {
|
|
97
|
-
activeTabElement === null || activeTabElement === void 0 ? void 0 : activeTabElement.classList.add('active');
|
|
98
|
-
}
|
|
99
|
-
return () => {
|
|
100
|
-
container.querySelectorAll('[data-label]').forEach((el) => {
|
|
101
|
-
el.classList.remove('active');
|
|
102
|
-
});
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
setHighlightStyle({ left: 0, width: 0 });
|
|
107
|
-
setIsAnimating(false);
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
setHighlightStyle({ left: 0, width: 0 });
|
|
112
|
-
setIsAnimating(false);
|
|
113
|
-
}
|
|
114
|
-
}, [activeTab, prevTab, childrenArray, visibleTabs, overflowTabs]);
|
|
115
|
-
return (react_1.default.createElement(TabsContainer, { "data-component-name": "Markdoc/Tabs/Tabs", className: className, isReady: ready || forceReady },
|
|
116
|
-
react_1.default.createElement(TabList_1.TabList, { size: size, childrenArray: childrenArray, overflowTabs: overflowTabs, setTabRef: setTabRef, onTabClick: onTabClick, handleKeyboard: handleKeyboard, getTabId: getTabId, activeTab: activeTab, isAnimating: isAnimating, highlightStyle: highlightStyle, visibleTabs: visibleTabs, allTabsHidden: allTabsHidden, tabsContainerRef: tabsContainerRef }),
|
|
49
|
+
return (react_1.default.createElement(TabsContainer, { "data-component-name": "Markdoc/Tabs/Tabs", className: className, key: id },
|
|
50
|
+
react_1.default.createElement(TabList_1.TabList, { size: size, childrenArray: childrenArray, activeTab: activeTab, onTabChange: setActiveTab }),
|
|
117
51
|
childrenArray.map((child, index) => {
|
|
118
52
|
const { label } = child.props;
|
|
119
|
-
const tabId = getTabId(label, index);
|
|
53
|
+
const tabId = (0, utils_1.getTabId)(label, index);
|
|
120
54
|
return label === activeTab ? (react_1.default.createElement(exports.TabContent, { key: `content-${tabId}`, id: `panel-${tabId}`, "aria-labelledby": `tab-${tabId}`, tabIndex: 0, role: "tabpanel" }, child.props.children)) : null;
|
|
121
55
|
})));
|
|
122
56
|
}
|
|
@@ -132,16 +66,6 @@ const TabsContainer = styled_components_1.default.div `
|
|
|
132
66
|
padding: var(--md-tabs-container-padding);
|
|
133
67
|
border: var(--md-tabs-container-border);
|
|
134
68
|
|
|
135
|
-
${({ isReady }) => !isReady
|
|
136
|
-
? (0, styled_components_1.css) `
|
|
137
|
-
visibility: hidden;
|
|
138
|
-
overflow: hidden;
|
|
139
|
-
`
|
|
140
|
-
: (0, styled_components_1.css) `
|
|
141
|
-
visibility: visible;
|
|
142
|
-
overflow: visible;
|
|
143
|
-
`}
|
|
144
|
-
|
|
145
69
|
ol[class^='Tabs__TabList'] {
|
|
146
70
|
margin: 0;
|
|
147
71
|
padding: 0;
|
package/lib/markdoc/tags/tabs.js
CHANGED
|
@@ -22,6 +22,11 @@ exports.tabs = {
|
|
|
22
22
|
return new markdoc_1.default.Tag('Tabs', attributes, tabsContent);
|
|
23
23
|
},
|
|
24
24
|
attributes: {
|
|
25
|
+
/*
|
|
26
|
+
A unique persistent identifier assigned to a component.
|
|
27
|
+
This value is used as a key for the query parameter that stores the active tab to enable deep linking.
|
|
28
|
+
*/
|
|
29
|
+
id: { type: String },
|
|
25
30
|
size: { type: String, matches: ['small', 'medium'], default: 'medium' },
|
|
26
31
|
},
|
|
27
32
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/theme",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.59.0-next.0",
|
|
4
4
|
"description": "Shared UI components lib",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"theme",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"react": "^19.1.0",
|
|
33
33
|
"react-dom": "^19.1.0",
|
|
34
34
|
"react-router-dom": "^6.21.1",
|
|
35
|
-
"styled-components": "^4.1.1 || ^5.3.11",
|
|
35
|
+
"styled-components": "^4.1.1 || ^5.3.11 || ^6.0.0",
|
|
36
36
|
"styled-system": "^5.1.5"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
"openapi-sampler": "1.6.1",
|
|
88
88
|
"react-calendar": "5.1.0",
|
|
89
89
|
"react-date-picker": "11.0.0",
|
|
90
|
-
"@redocly/config": "0.35.
|
|
91
|
-
"@redocly/realm-asyncapi-sdk": "0.
|
|
90
|
+
"@redocly/config": "0.35.1",
|
|
91
|
+
"@redocly/realm-asyncapi-sdk": "0.5.0-next.0"
|
|
92
92
|
},
|
|
93
93
|
"scripts": {
|
|
94
94
|
"watch": "tsc -p tsconfig.build.json && (concurrently \"tsc -w -p tsconfig.build.json\" \"tsc-alias -w -p tsconfig.build.json\")",
|
|
@@ -24,6 +24,7 @@ import { CatalogEntityRelationsGraph } from '@redocly/theme/components/Catalog/C
|
|
|
24
24
|
export type CatalogEntityProps = {
|
|
25
25
|
RedocSchema: React.ComponentType<any>;
|
|
26
26
|
StoreProvider: React.ComponentType<any>;
|
|
27
|
+
GraphqlTypeRenderer?: React.ComponentType<{ sdl: string; typeName: string }>;
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
type CatalogEntityPageProps = {
|
|
@@ -50,6 +51,7 @@ const renderDataSchemaSection = (
|
|
|
50
51
|
relatedEntity: BffCatalogRelatedEntity | null,
|
|
51
52
|
RedocSchema: React.ComponentType<any>,
|
|
52
53
|
StoreProvider: React.ComponentType<any>,
|
|
54
|
+
GraphqlTypeRenderer?: React.ComponentType<{ sdl: string; typeName: string }>,
|
|
53
55
|
): React.ReactElement | null => {
|
|
54
56
|
if (entity.type !== 'data-schema') {
|
|
55
57
|
return null;
|
|
@@ -61,11 +63,16 @@ const renderDataSchemaSection = (
|
|
|
61
63
|
relatedEntity={relatedEntity}
|
|
62
64
|
RedocSchema={RedocSchema}
|
|
63
65
|
StoreProvider={StoreProvider}
|
|
66
|
+
GraphqlTypeRenderer={GraphqlTypeRenderer}
|
|
64
67
|
/>
|
|
65
68
|
);
|
|
66
69
|
};
|
|
67
70
|
|
|
68
|
-
export function CatalogEntity({
|
|
71
|
+
export function CatalogEntity({
|
|
72
|
+
RedocSchema,
|
|
73
|
+
StoreProvider,
|
|
74
|
+
GraphqlTypeRenderer,
|
|
75
|
+
}: CatalogEntityProps) {
|
|
69
76
|
const { useTranslate, useCatalog, usePageProps } = useThemeHooks();
|
|
70
77
|
const { translate } = useTranslate();
|
|
71
78
|
const { entity, relations, catalogConfig, entitiesCatalogConfig, relatedEntity } =
|
|
@@ -98,7 +105,13 @@ export function CatalogEntity({ RedocSchema, StoreProvider }: CatalogEntityProps
|
|
|
98
105
|
tag={entity.key}
|
|
99
106
|
/>
|
|
100
107
|
<CatalogEntityProperties entity={entity} />
|
|
101
|
-
{renderDataSchemaSection(
|
|
108
|
+
{renderDataSchemaSection(
|
|
109
|
+
entity,
|
|
110
|
+
relatedEntity,
|
|
111
|
+
RedocSchema,
|
|
112
|
+
StoreProvider,
|
|
113
|
+
GraphqlTypeRenderer,
|
|
114
|
+
)}
|
|
102
115
|
<CatalogTwoColumnsSection>
|
|
103
116
|
{renderFirstColumnEntitySection(entity)}
|
|
104
117
|
<CatalogEntityLinks entity={entity} />
|
|
@@ -16,7 +16,7 @@ export type CatalogEntityMetadataProps = {
|
|
|
16
16
|
|
|
17
17
|
function renderMetadataValue(value: any): React.JSX.Element {
|
|
18
18
|
if (isPlainObject(value)) {
|
|
19
|
-
return <JsonViewerWrapper data={value} expandLevel={3}
|
|
19
|
+
return <JsonViewerWrapper data={value} expandLevel={3} controls={false} />;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
if (Array.isArray(value)) {
|
|
@@ -25,7 +25,7 @@ function renderMetadataValue(value: any): React.JSX.Element {
|
|
|
25
25
|
{value.map((item, index) => (
|
|
26
26
|
<div key={index}>
|
|
27
27
|
{isPlainObject(item) ? (
|
|
28
|
-
<JsonViewerWrapper data={item} expandLevel={3}
|
|
28
|
+
<JsonViewerWrapper data={item} expandLevel={3} controls={false} />
|
|
29
29
|
) : (
|
|
30
30
|
<span>{String(item)}</span>
|
|
31
31
|
)}
|
|
@@ -41,7 +41,7 @@ function renderMetadataValue(value: any): React.JSX.Element {
|
|
|
41
41
|
export function CatalogEntityMetadata({ entity }: CatalogEntityMetadataProps) {
|
|
42
42
|
const { useTranslate } = useThemeHooks();
|
|
43
43
|
const { translate } = useTranslate();
|
|
44
|
-
const { schema, ...metadata } = entity.metadata || {};
|
|
44
|
+
const { schema, sdl, ...metadata } = entity.metadata || {};
|
|
45
45
|
const metadataToShow = Object.entries(metadata).filter(
|
|
46
46
|
([key]) => !(entity.type === 'api-description' && key === 'descriptionFile'),
|
|
47
47
|
);
|
|
@@ -46,7 +46,7 @@ export function CatalogEntityApiDescriptionRelations({
|
|
|
46
46
|
}: CatalogEntityApiDescriptionRelationsProps): JSX.Element {
|
|
47
47
|
return (
|
|
48
48
|
<div data-component-name="Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityApiDescriptionRelations">
|
|
49
|
-
<Tabs key={entity.id}
|
|
49
|
+
<Tabs key={entity.id} size={TabsSize.MEDIUM}>
|
|
50
50
|
<TabItem
|
|
51
51
|
label="Operations"
|
|
52
52
|
icon={<MoleculesIcon />}
|
package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations.tsx
CHANGED
|
@@ -74,7 +74,7 @@ export function CatalogEntityTeamRelations({
|
|
|
74
74
|
}: CatalogEntityTeamRelationsProps): JSX.Element {
|
|
75
75
|
return (
|
|
76
76
|
<div data-component-name="Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityTeamRelations">
|
|
77
|
-
<Tabs
|
|
77
|
+
<Tabs size={TabsSize.MEDIUM}>
|
|
78
78
|
<TabItem label="Members" icon={<PeopleIcon />} onClick={() => setFilter('type:user')}>
|
|
79
79
|
<CatalogEntityRelationsTable
|
|
80
80
|
key="members-table"
|
|
@@ -13,6 +13,7 @@ export type CatalogEntitySchemaProps = {
|
|
|
13
13
|
relatedEntity: BffCatalogRelatedEntity | null;
|
|
14
14
|
RedocSchema: React.ComponentType<any>;
|
|
15
15
|
StoreProvider: React.ComponentType<any>;
|
|
16
|
+
GraphqlTypeRenderer?: React.ComponentType<{ sdl: string; typeName: string }>;
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
export function CatalogEntitySchema({
|
|
@@ -20,37 +21,45 @@ export function CatalogEntitySchema({
|
|
|
20
21
|
relatedEntity,
|
|
21
22
|
RedocSchema,
|
|
22
23
|
StoreProvider,
|
|
24
|
+
GraphqlTypeRenderer,
|
|
23
25
|
}: CatalogEntitySchemaProps) {
|
|
24
26
|
const { useTranslate } = useThemeHooks();
|
|
25
27
|
const { translate } = useTranslate();
|
|
26
28
|
const { definition, parsedSchema, rawSchema } = useCatalogEntitySchema({ entity, relatedEntity });
|
|
29
|
+
const isGraphql = entity.metadata?.specType === 'graphql';
|
|
30
|
+
const graphqlSDL = entity?.metadata?.sdl;
|
|
27
31
|
|
|
28
32
|
return (
|
|
29
33
|
<MetadataWrapper data-component-name="Catalog/CatalogEntity/CatalogEntityMetadata">
|
|
30
34
|
<HeaderWrapper>
|
|
31
35
|
<Heading>{translate('catalog.entity.schema.title')}</Heading>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
{!isGraphql && (
|
|
37
|
+
<CopyButton
|
|
38
|
+
data={rawSchema}
|
|
39
|
+
buttonText="Copy Schema"
|
|
40
|
+
type="compound"
|
|
41
|
+
variant="secondary"
|
|
42
|
+
iconPosition="right"
|
|
43
|
+
size="medium"
|
|
44
|
+
></CopyButton>
|
|
45
|
+
)}
|
|
40
46
|
</HeaderWrapper>
|
|
41
47
|
<SplitViewWrapper>
|
|
42
48
|
<SchemaContentWrapper>
|
|
43
|
-
|
|
44
|
-
<
|
|
45
|
-
|
|
49
|
+
{isGraphql && graphqlSDL && GraphqlTypeRenderer ? (
|
|
50
|
+
<GraphqlTypeRenderer sdl={graphqlSDL} typeName={entity.title} />
|
|
51
|
+
) : (
|
|
52
|
+
<StoreProvider definition={definition}>
|
|
53
|
+
<RedocSchema schema={parsedSchema} />
|
|
54
|
+
</StoreProvider>
|
|
55
|
+
)}
|
|
46
56
|
</SchemaContentWrapper>
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
expandLevel={3}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
</SchemaSampleWrapper>
|
|
57
|
+
|
|
58
|
+
{!isGraphql && (
|
|
59
|
+
<SchemaSampleWrapper>
|
|
60
|
+
<JsonViewer data={Sampler.sample({ ...parsedSchema })} expandLevel={3} />
|
|
61
|
+
</SchemaSampleWrapper>
|
|
62
|
+
)}
|
|
54
63
|
</SplitViewWrapper>
|
|
55
64
|
</MetadataWrapper>
|
|
56
65
|
);
|
|
@@ -18,8 +18,8 @@ export type CodeBlockProps = {
|
|
|
18
18
|
header?: CodeBlockControlsProps;
|
|
19
19
|
dataTestId?: string;
|
|
20
20
|
className?: string;
|
|
21
|
-
tabs?:
|
|
22
|
-
dropdown?:
|
|
21
|
+
tabs?: CodeBlockItems;
|
|
22
|
+
dropdown?: CodeBlockItems;
|
|
23
23
|
withLineNumbers?: boolean;
|
|
24
24
|
startLineNumber?: number;
|
|
25
25
|
highlightedHtml?: string;
|
|
@@ -37,15 +37,9 @@ type UnstableExternalCodeSample = {
|
|
|
37
37
|
get: (source: ExternalSource) => string;
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
-
export type
|
|
41
|
-
items: { name: string; lang?: string }[];
|
|
42
|
-
onChange: (
|
|
43
|
-
value: string;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export type CodeBlockDropdownItems = {
|
|
47
|
-
items: { name: string; lang?: string }[];
|
|
48
|
-
onChange: (name: string | string[]) => void;
|
|
40
|
+
export type CodeBlockItems = {
|
|
41
|
+
items: { name: string; lang?: string; id: string }[];
|
|
42
|
+
onChange: (id: string) => void;
|
|
49
43
|
value: string;
|
|
50
44
|
};
|
|
51
45
|
|