@redocly/theme 0.55.0-next.4 → 0.55.0-next.6
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/Button/Button.d.ts +1 -0
- package/lib/components/Dropdown/variables.js +1 -1
- package/lib/components/Image/Image.js +2 -2
- package/lib/components/Select/Select.js +19 -3
- package/lib/components/Select/SelectInput.d.ts +1 -0
- package/lib/components/Select/SelectInput.js +7 -3
- package/lib/components/VersionPicker/VersionPicker.js +22 -3
- package/lib/components/VersionPicker/variables.js +1 -0
- package/lib/core/utils/index.d.ts +1 -0
- package/lib/core/utils/index.js +1 -0
- package/lib/core/utils/parse-style-string.d.ts +1 -0
- package/lib/core/utils/parse-style-string.js +23 -0
- package/lib/markdoc/components/Tabs/TabList.d.ts +1 -4
- package/lib/markdoc/components/Tabs/TabList.js +16 -36
- package/lib/markdoc/components/Tabs/Tabs.js +0 -7
- package/package.json +2 -2
- package/src/components/Button/Button.tsx +1 -1
- package/src/components/Dropdown/variables.ts +1 -1
- package/src/components/Image/Image.tsx +5 -9
- package/src/components/Select/Select.tsx +24 -1
- package/src/components/Select/SelectInput.tsx +20 -1
- package/src/components/VersionPicker/VersionPicker.tsx +32 -2
- package/src/components/VersionPicker/variables.ts +1 -0
- package/src/core/utils/index.ts +1 -0
- package/src/core/utils/parse-style-string.ts +21 -0
- package/src/markdoc/components/Tabs/TabList.tsx +38 -69
- package/src/markdoc/components/Tabs/Tabs.tsx +0 -8
|
@@ -18,6 +18,7 @@ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElemen
|
|
|
18
18
|
title?: string;
|
|
19
19
|
tabIndex?: number;
|
|
20
20
|
onClick?: (e?: any) => void;
|
|
21
|
+
ref?: React.Ref<HTMLButtonElement>;
|
|
21
22
|
type?: 'button' | 'submit' | 'reset';
|
|
22
23
|
}
|
|
23
24
|
export declare function generateClassName({ variant, tone, size, extraClass, }: ButtonProps): string;
|
|
@@ -42,7 +42,7 @@ exports.dropdown = (0, styled_components_1.css) `
|
|
|
42
42
|
|
|
43
43
|
--dropdown-menu-item-color-dangerous: var(--color-error-base);
|
|
44
44
|
|
|
45
|
-
--dropdown-menu-item-border-color-focused: var(--color-
|
|
45
|
+
--dropdown-menu-item-border-color-focused: var(--button-border-color-focused);
|
|
46
46
|
// @tokens End
|
|
47
47
|
`;
|
|
48
48
|
//# sourceMappingURL=variables.js.map
|
|
@@ -58,8 +58,8 @@ function Image(props) {
|
|
|
58
58
|
(_a = lightboxContainerRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
59
59
|
}
|
|
60
60
|
}, [lightboxImage]);
|
|
61
|
-
const combinedStyles = Object.assign(Object.assign(Object.assign({}, (withLightbox && { cursor: 'pointer' })), (border && { border })), (typeof style === 'string' ?
|
|
62
|
-
const lightboxOverlayStyles = typeof lightboxStyle === 'string' ?
|
|
61
|
+
const combinedStyles = Object.assign(Object.assign(Object.assign({}, (withLightbox && { cursor: 'pointer' })), (border && { border })), (typeof style === 'string' ? (0, utils_1.parseStyleString)(style) : style));
|
|
62
|
+
const lightboxOverlayStyles = typeof lightboxStyle === 'string' ? (0, utils_1.parseStyleString)(lightboxStyle) : lightboxStyle;
|
|
63
63
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
64
64
|
lightboxImage ? (react_1.default.createElement(LightboxContainer, { ref: lightboxContainerRef, onClick: handleCloseLightbox, onKeyDown: handleLightboxKeyDown, tabIndex: 0 },
|
|
65
65
|
react_1.default.createElement(Overlay, { style: lightboxOverlayStyles }),
|
|
@@ -151,11 +151,23 @@ function Select(props) {
|
|
|
151
151
|
return !!selectedOptions.find((selectOption) => selectOption.value === option.value || selectOption.value === option.label);
|
|
152
152
|
};
|
|
153
153
|
const renderDefaultInput = (inputRef) => {
|
|
154
|
-
return (react_1.default.createElement(SelectInput_1.SelectInput, { id: inputId, selectedOptions: selectedOptions, searchValue: searchValue, placeholder: placeholder, stickyValue: stickyInputValue, multiple: multiple, searchable: searchable, clearable: clearable, customIcon: icon, inputRef: inputRef, onlyIcon: onlyIcon, clearHandler: clearHandler, searchHandler: searchHandler, inputBlurHandler: inputBlurHandler, inputFocusHandler: inputFocusHandler, clickHandler: inputClickHandler }));
|
|
154
|
+
return (react_1.default.createElement(SelectInput_1.SelectInput, { id: inputId, listboxId: inputId, selectedOptions: selectedOptions, searchValue: searchValue, placeholder: placeholder, stickyValue: stickyInputValue, multiple: multiple, searchable: searchable, clearable: clearable, customIcon: icon, inputRef: inputRef, onlyIcon: onlyIcon, clearHandler: clearHandler, searchHandler: searchHandler, inputBlurHandler: inputBlurHandler, inputFocusHandler: inputFocusHandler, clickHandler: inputClickHandler }));
|
|
155
155
|
};
|
|
156
|
-
return (react_1.default.createElement(exports.SelectWrapper, Object.assign({ "data-component-name": "Select/Select", ref: selectRef }, dataAttributes, { disabled: disabled, "data-testid": dataTestId, className: className
|
|
156
|
+
return (react_1.default.createElement(exports.SelectWrapper, Object.assign({ "data-component-name": "Select/Select", ref: selectRef }, dataAttributes, { disabled: disabled, "data-testid": dataTestId, className: className, onKeyDown: (e) => {
|
|
157
|
+
if (e.key === 'Enter' && document.activeElement === selectRef.current) {
|
|
158
|
+
e.preventDefault();
|
|
159
|
+
setDropdownActive(!dropdownActive);
|
|
160
|
+
}
|
|
161
|
+
}, tabIndex: 0, "aria-haspopup": "listbox", "aria-expanded": dropdownActive, "aria-label": "Select option", onFocus: (e) => {
|
|
162
|
+
var _a;
|
|
163
|
+
if (e.target === selectRef.current) {
|
|
164
|
+
(_a = selectInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
165
|
+
}
|
|
166
|
+
}, onMouseDown: (e) => {
|
|
167
|
+
e.preventDefault();
|
|
168
|
+
} }),
|
|
157
169
|
react_1.default.createElement(SelectDropdown, { closeOnClick: !multiple, withArrow: withArrow, trigger: renderInput ? renderInput() : renderDefaultInput(selectInputRef), triggerEvent: triggerEvent, placement: placement, alignment: alignment, active: !renderInput ? dropdownActive : undefined },
|
|
158
|
-
react_1.default.createElement(SelectDropdownMenu, { footer: footer }, filteredOptions.length === 0 ? (react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { disabled: true }, "No results")) : (filteredOptions.map((option, index) => {
|
|
170
|
+
react_1.default.createElement(SelectDropdownMenu, { role: "listbox", footer: footer }, filteredOptions.length === 0 ? (react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { disabled: true }, "No results")) : (filteredOptions.map((option, index) => {
|
|
159
171
|
return (react_1.default.createElement(react_1.Fragment, { key: index },
|
|
160
172
|
react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { onAction: () => selectHandler(option), prefix: !hideCheckmarkIcon &&
|
|
161
173
|
(checkmarkIconPosition ? checkmarkIconPosition === 'start' : false) &&
|
|
@@ -176,6 +188,10 @@ exports.SelectWrapper = styled_components_1.default.div `
|
|
|
176
188
|
color: var(--select-text-color);
|
|
177
189
|
min-width: 0;
|
|
178
190
|
|
|
191
|
+
&:focus-visible {
|
|
192
|
+
outline: 1px solid var(--button-border-color-focused);
|
|
193
|
+
}
|
|
194
|
+
|
|
179
195
|
${({ disabled }) => disabled &&
|
|
180
196
|
`
|
|
181
197
|
opacity: 0.59;
|
|
@@ -34,7 +34,7 @@ const Tag_1 = require("../../components/Tag/Tag");
|
|
|
34
34
|
const CloseIcon_1 = require("../../icons/CloseIcon/CloseIcon");
|
|
35
35
|
const Button_1 = require("../../components/Button/Button");
|
|
36
36
|
function SelectInput(props) {
|
|
37
|
-
const { id, onlyIcon, icon, customIcon, selectedOptions, placeholder, stickyValue, multiple, searchable, clearable, clearHandler, searchHandler, clickHandler, searchValue, inputBlurHandler, inputFocusHandler, } = props;
|
|
37
|
+
const { id, listboxId, onlyIcon, icon, customIcon, selectedOptions, placeholder, stickyValue, multiple, searchable, clearable, clearHandler, searchHandler, clickHandler, searchValue, inputBlurHandler, inputFocusHandler, } = props;
|
|
38
38
|
const inputRef = (0, react_1.useRef)(null);
|
|
39
39
|
const onChangeHandler = (e) => {
|
|
40
40
|
var _a;
|
|
@@ -83,10 +83,14 @@ function SelectInput(props) {
|
|
|
83
83
|
else {
|
|
84
84
|
props.inputRef.current = input;
|
|
85
85
|
}
|
|
86
|
-
}, width: multiple ? (!searchValue && selectedOptions.length ? '10px' : 'auto') : '100%'
|
|
86
|
+
}, width: multiple ? (!searchValue && selectedOptions.length ? '10px' : 'auto') : '100%', tabIndex: 0, onFocus: (e) => {
|
|
87
|
+
e.stopPropagation();
|
|
88
|
+
}, onMouseDown: (e) => {
|
|
89
|
+
e.preventDefault();
|
|
90
|
+
} }));
|
|
87
91
|
const simpleValue = selectedOptions.length ? (selectedOptions[0].label || selectedOptions[0].element || selectedOptions[0].value) : (react_1.default.createElement(SelectInternalInputPlaceholder, null, placeholder));
|
|
88
92
|
const multipleValues = selectedOptions.length ? (selectTags) : (react_1.default.createElement(SelectInternalInputPlaceholder, null, placeholder));
|
|
89
|
-
return (react_1.default.createElement(exports.SelectInputWrapper, Object.assign({}, props, { id: id, onFocus: onFocusHandler, onClick: onClickHandler }),
|
|
93
|
+
return (react_1.default.createElement(exports.SelectInputWrapper, Object.assign({}, props, { id: id, onFocus: onFocusHandler, onClick: onClickHandler, role: "button", "aria-haspopup": "listbox", "aria-controls": listboxId, "aria-owns": listboxId, "aria-label": "Select option" }),
|
|
90
94
|
!onlyIcon && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
91
95
|
react_1.default.createElement(SelectInputValue, null, multiple ? (searchable ? (react_1.default.createElement(react_1.default.Fragment, null,
|
|
92
96
|
selectTags,
|
|
@@ -54,9 +54,14 @@ function VersionPicker(props) {
|
|
|
54
54
|
};
|
|
55
55
|
if (!options.length && !(versionPicker === null || versionPicker === void 0 ? void 0 : versionPicker.showForUnversioned))
|
|
56
56
|
return null;
|
|
57
|
-
return (React.createElement(VersionsPickerWrapper, { "data-component-name": "VersionPicker/VersionPicker" },
|
|
58
|
-
React.createElement(VersionPickerLabel, { "data-translation-key": "versionPicker.label" }, translate('versionPicker.label', 'Version:')),
|
|
59
|
-
React.createElement(exports.VersionPickerSelect, { placeholder: translate('versionPicker.unversioned', 'All versions'), disabled: !options.length, options: options, value: value, onChange: handleOnChange
|
|
57
|
+
return (React.createElement(VersionsPickerWrapper, { "data-component-name": "VersionPicker/VersionPicker", role: "region", "aria-label": translate('versionPicker.label', 'Version selector') },
|
|
58
|
+
React.createElement(VersionPickerLabel, { "data-translation-key": "versionPicker.label", htmlFor: "version-picker-select" }, translate('versionPicker.label', 'Version:')),
|
|
59
|
+
React.createElement(exports.VersionPickerSelect, { placeholder: translate('versionPicker.unversioned', 'All versions'), disabled: !options.length, options: options, value: value, onChange: handleOnChange, dataAttributes: {
|
|
60
|
+
id: 'version-picker-select',
|
|
61
|
+
'aria-describedby': 'version-picker-description',
|
|
62
|
+
'aria-label': translate('versionPicker.label', 'Select version'),
|
|
63
|
+
} }),
|
|
64
|
+
React.createElement(SrOnly, { id: "version-picker-description" }, "This is version picker select, using it you can select a version of the API.")));
|
|
60
65
|
}
|
|
61
66
|
const VersionPickerLabel = styled_components_1.default.label `
|
|
62
67
|
font-size: var(--version-picker-label-font-size);
|
|
@@ -79,6 +84,10 @@ exports.VersionPickerSelect = (0, styled_components_1.default)(Select_1.Select)
|
|
|
79
84
|
border-radius: var(--version-picker-input-border-radius);
|
|
80
85
|
padding: var(--version-picker-input-padding-vertical)
|
|
81
86
|
var(--version-picker-input-padding-horizontal);
|
|
87
|
+
|
|
88
|
+
&:focus-within {
|
|
89
|
+
outline: 1px solid var(--version-picker-focus-outline-color);
|
|
90
|
+
}
|
|
82
91
|
}
|
|
83
92
|
`;
|
|
84
93
|
const VersionsPickerWrapper = styled_components_1.default.div `
|
|
@@ -89,5 +98,15 @@ const VersionsPickerWrapper = styled_components_1.default.div `
|
|
|
89
98
|
justify-content: space-between;
|
|
90
99
|
padding: var(--version-picker-padding-vertical) var(--version-picker-padding-horizontal);
|
|
91
100
|
border-bottom: var(--version-picker-border-bottom);
|
|
101
|
+
|
|
102
|
+
&:focus-visible {
|
|
103
|
+
outline: 1px solid var(--version-picker-focus-outline-color);
|
|
104
|
+
}
|
|
105
|
+
`;
|
|
106
|
+
const SrOnly = styled_components_1.default.span `
|
|
107
|
+
position: absolute;
|
|
108
|
+
width: 0;
|
|
109
|
+
height: 0;
|
|
110
|
+
overflow: hidden;
|
|
92
111
|
`;
|
|
93
112
|
//# sourceMappingURL=VersionPicker.js.map
|
|
@@ -37,6 +37,7 @@ exports.versionPicker = (0, styled_components_1.css) `
|
|
|
37
37
|
--version-picker-list-item-bg-color-active: var(--select-list-item-bg-color-active); // @presenter Color
|
|
38
38
|
--version-picker-list-item-bg-color-hover: var(--select-list-item-bg-color-hover); // @presenter Color
|
|
39
39
|
|
|
40
|
+
--version-picker-focus-outline-color: var(--button-border-color-focused);
|
|
40
41
|
// @tokens End
|
|
41
42
|
`;
|
|
42
43
|
//# sourceMappingURL=variables.js.map
|
|
@@ -32,3 +32,4 @@ export * from '../../core/utils/match-code-walkthrough-conditions';
|
|
|
32
32
|
export * from '../../core/utils/replace-inputs-with-value';
|
|
33
33
|
export * from '../../core/utils/find-closest-common-directory';
|
|
34
34
|
export * from '../../core/utils/get-user-agent';
|
|
35
|
+
export * from '../../core/utils/parse-style-string';
|
package/lib/core/utils/index.js
CHANGED
|
@@ -48,4 +48,5 @@ __exportStar(require("../../core/utils/match-code-walkthrough-conditions"), expo
|
|
|
48
48
|
__exportStar(require("../../core/utils/replace-inputs-with-value"), exports);
|
|
49
49
|
__exportStar(require("../../core/utils/find-closest-common-directory"), exports);
|
|
50
50
|
__exportStar(require("../../core/utils/get-user-agent"), exports);
|
|
51
|
+
__exportStar(require("../../core/utils/parse-style-string"), exports);
|
|
51
52
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function parseStyleString(styleString: string): React.CSSProperties;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseStyleString = parseStyleString;
|
|
4
|
+
function parseStyleString(styleString) {
|
|
5
|
+
return styleString
|
|
6
|
+
.split(';')
|
|
7
|
+
.filter((style) => style.trim().length)
|
|
8
|
+
.reduce((styleObj, style) => {
|
|
9
|
+
const colonIndex = style.indexOf(':');
|
|
10
|
+
if (colonIndex === -1)
|
|
11
|
+
return styleObj;
|
|
12
|
+
const key = style.substring(0, colonIndex).trim();
|
|
13
|
+
const value = style.substring(colonIndex + 1).trim();
|
|
14
|
+
if (key && value) {
|
|
15
|
+
const camelCaseKey = key.replace(/-[a-z]/g, (match) => {
|
|
16
|
+
return match[1].toUpperCase();
|
|
17
|
+
});
|
|
18
|
+
styleObj[camelCaseKey] = value;
|
|
19
|
+
}
|
|
20
|
+
return styleObj;
|
|
21
|
+
}, {});
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=parse-style-string.js.map
|
|
@@ -26,8 +26,5 @@ export declare const TabItem: import("styled-components").StyledComponent<"li",
|
|
|
26
26
|
size: TabsSize;
|
|
27
27
|
tabIndex?: number;
|
|
28
28
|
}, never>;
|
|
29
|
-
export declare const TabButtonLink: import("styled-components").StyledComponent<"
|
|
30
|
-
size: TabsSize;
|
|
31
|
-
disabled?: boolean;
|
|
32
|
-
}, never>;
|
|
29
|
+
export declare const TabButtonLink: import("styled-components").StyledComponent<React.FC<import("../../../components/Button/Button").ButtonProps>, any, import("../../../components/Button/Button").ButtonProps, never>;
|
|
33
30
|
export {};
|
|
@@ -22,25 +22,20 @@ 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.TabButtonLink = exports.TabItem = exports.TabListContainer = void 0;
|
|
27
30
|
exports.TabList = TabList;
|
|
28
|
-
const react_1 =
|
|
31
|
+
const react_1 = __importDefault(require("react"));
|
|
29
32
|
const styled_components_1 = __importStar(require("styled-components"));
|
|
30
33
|
const Tab_1 = require("../../../markdoc/components/Tabs/Tab");
|
|
31
34
|
const Dropdown_1 = require("../../../components/Dropdown/Dropdown");
|
|
32
35
|
const DropdownMenu_1 = require("../../../components/Dropdown/DropdownMenu");
|
|
33
36
|
const DropdownMenuItem_1 = require("../../../components/Dropdown/DropdownMenuItem");
|
|
34
|
-
const
|
|
35
|
-
const ChevronUpIcon_1 = require("../../../icons/ChevronUpIcon/ChevronUpIcon");
|
|
37
|
+
const Button_1 = require("../../../components/Button/Button");
|
|
36
38
|
function TabList({ childrenArray, size, overflowTabs, visibleTabs, setTabRef, onTabClick, handleKeyboard, getTabId, activeTab, isAnimating, highlightStyle, allTabsHidden, tabsContainerRef, }) {
|
|
37
|
-
const [isDropdownOpen, setIsDropdownOpen] = (0, react_1.useState)(false);
|
|
38
|
-
const handleDropdownOpen = (0, react_1.useCallback)(() => {
|
|
39
|
-
setIsDropdownOpen(true);
|
|
40
|
-
}, []);
|
|
41
|
-
const handleDropdownClose = (0, react_1.useCallback)(() => {
|
|
42
|
-
setIsDropdownOpen(false);
|
|
43
|
-
}, []);
|
|
44
39
|
return (react_1.default.createElement(exports.TabListContainer, { role: "tablist", ref: tabsContainerRef, "data-animating": isAnimating },
|
|
45
40
|
react_1.default.createElement(HighlightBar, { size: size, style: { left: highlightStyle.left, width: highlightStyle.width } },
|
|
46
41
|
react_1.default.createElement("div", null)),
|
|
@@ -59,20 +54,16 @@ function TabList({ childrenArray, size, overflowTabs, visibleTabs, setTabRef, on
|
|
|
59
54
|
onTabClick(label);
|
|
60
55
|
} }));
|
|
61
56
|
}),
|
|
62
|
-
react_1.default.createElement(exports.TabItem, { size: size, active: overflowTabs.some((index) => activeTab === childrenArray[index].props.label), tabIndex: 0 }, overflowTabs.length > 0 && (react_1.default.createElement(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
react_1.default.createElement(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
onTabClick(index);
|
|
73
|
-
handleDropdownClose();
|
|
74
|
-
}, disabled: childrenArray[index].props.disable }, label));
|
|
75
|
-
}))))))));
|
|
57
|
+
react_1.default.createElement(exports.TabItem, { size: size, active: overflowTabs.some((index) => activeTab === childrenArray[index].props.label), tabIndex: 0 }, overflowTabs.length > 0 && (react_1.default.createElement(Dropdown_1.Dropdown, { trigger: react_1.default.createElement(exports.TabButtonLink, { size: size, className: overflowTabs.some((index) => activeTab === childrenArray[index].props.label)
|
|
58
|
+
? 'active'
|
|
59
|
+
: undefined }, allTabsHidden ? activeTab : 'More'), alignment: "start", withArrow: true },
|
|
60
|
+
react_1.default.createElement(DropdownMenu_1.DropdownMenu, null, overflowTabs.map((index) => {
|
|
61
|
+
const { label } = childrenArray[index].props;
|
|
62
|
+
const tabId = getTabId(label, index);
|
|
63
|
+
return (react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { key: `more-${tabId}`, active: activeTab === label, onAction: () => {
|
|
64
|
+
onTabClick(index);
|
|
65
|
+
}, disabled: childrenArray[index].props.disable }, label));
|
|
66
|
+
})))))));
|
|
76
67
|
}
|
|
77
68
|
exports.TabListContainer = styled_components_1.default.ul `
|
|
78
69
|
position: relative;
|
|
@@ -166,22 +157,11 @@ const HighlightBar = styled_components_1.default.div `
|
|
|
166
157
|
border-radius: var(--md-tabs-${({ size }) => size}-active-tab-border-radius);
|
|
167
158
|
}
|
|
168
159
|
`;
|
|
169
|
-
exports.TabButtonLink = styled_components_1.default.
|
|
170
|
-
all: unset;
|
|
171
|
-
flex-grow: 1;
|
|
172
|
-
cursor: pointer;
|
|
173
|
-
width: 100%;
|
|
174
|
-
text-align: center;
|
|
160
|
+
exports.TabButtonLink = (0, styled_components_1.default)(Button_1.Button) `
|
|
175
161
|
color: var(--md-tabs-tab-text-color);
|
|
176
162
|
font-family: var(--md-tabs-tab-font-family);
|
|
177
163
|
font-style: var(--md-tabs-tab-font-style);
|
|
178
164
|
background-color: var(--md-tabs-tab-bg-color);
|
|
179
|
-
white-space: nowrap;
|
|
180
|
-
display: inline-flex;
|
|
181
|
-
align-items: center;
|
|
182
|
-
justify-content: center;
|
|
183
|
-
gap: var(--spacing-xxs);
|
|
184
|
-
z-index: 2;
|
|
185
165
|
|
|
186
166
|
transition:
|
|
187
167
|
background-color 300ms ease-in-out,
|
|
@@ -92,14 +92,7 @@ function Tabs({ children, className, size }) {
|
|
|
92
92
|
else {
|
|
93
93
|
setHighlightStyle({ left: offsetLeft, width: offsetWidth });
|
|
94
94
|
}
|
|
95
|
-
const timeoutId = setTimeout(() => {
|
|
96
|
-
if (visibleTabs.includes(activeIndex)) {
|
|
97
|
-
activeTabElement === null || activeTabElement === void 0 ? void 0 : activeTabElement.classList.add('active');
|
|
98
|
-
}
|
|
99
|
-
setIsAnimating(false);
|
|
100
|
-
}, 300);
|
|
101
95
|
return () => {
|
|
102
|
-
clearTimeout(timeoutId);
|
|
103
96
|
container.querySelectorAll('[data-label]').forEach((el) => {
|
|
104
97
|
el.classList.remove('active');
|
|
105
98
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/theme",
|
|
3
|
-
"version": "0.55.0-next.
|
|
3
|
+
"version": "0.55.0-next.6",
|
|
4
4
|
"description": "Shared UI components lib",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"theme",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"nprogress": "0.2.0",
|
|
89
89
|
"react-calendar": "5.1.0",
|
|
90
90
|
"react-date-picker": "11.0.0",
|
|
91
|
-
"@redocly/config": "0.26.
|
|
91
|
+
"@redocly/config": "0.26.2",
|
|
92
92
|
"@redocly/realm-asyncapi-sdk": "0.1.0-next.0"
|
|
93
93
|
},
|
|
94
94
|
"scripts": {
|
|
@@ -40,6 +40,6 @@ export const dropdown = css`
|
|
|
40
40
|
|
|
41
41
|
--dropdown-menu-item-color-dangerous: var(--color-error-base);
|
|
42
42
|
|
|
43
|
-
--dropdown-menu-item-border-color-focused: var(--color-
|
|
43
|
+
--dropdown-menu-item-border-color-focused: var(--button-border-color-focused);
|
|
44
44
|
// @tokens End
|
|
45
45
|
`;
|
|
@@ -3,11 +3,7 @@ import styled from 'styled-components';
|
|
|
3
3
|
|
|
4
4
|
import type { KeyboardEvent, JSX } from 'react';
|
|
5
5
|
|
|
6
|
-
import { parseSrcSet } from '@redocly/theme/core/utils';
|
|
7
|
-
|
|
8
|
-
interface CSSProperties extends React.CSSProperties {
|
|
9
|
-
cssText?: string;
|
|
10
|
-
}
|
|
6
|
+
import { parseSrcSet, parseStyleString } from '@redocly/theme/core/utils';
|
|
11
7
|
|
|
12
8
|
export type ImageProps = {
|
|
13
9
|
src?: string;
|
|
@@ -59,14 +55,14 @@ export function Image(props: ImageProps): JSX.Element {
|
|
|
59
55
|
}
|
|
60
56
|
}, [lightboxImage]);
|
|
61
57
|
|
|
62
|
-
const combinedStyles: CSSProperties = {
|
|
58
|
+
const combinedStyles: React.CSSProperties = {
|
|
63
59
|
...(withLightbox && { cursor: 'pointer' }),
|
|
64
60
|
...(border && { border }),
|
|
65
|
-
...(typeof style === 'string' ?
|
|
61
|
+
...(typeof style === 'string' ? parseStyleString(style) : style),
|
|
66
62
|
};
|
|
67
63
|
|
|
68
|
-
const lightboxOverlayStyles: CSSProperties | undefined =
|
|
69
|
-
typeof lightboxStyle === 'string' ?
|
|
64
|
+
const lightboxOverlayStyles: React.CSSProperties | undefined =
|
|
65
|
+
typeof lightboxStyle === 'string' ? parseStyleString(lightboxStyle) : lightboxStyle;
|
|
70
66
|
|
|
71
67
|
return (
|
|
72
68
|
<>
|
|
@@ -172,6 +172,7 @@ export function Select<T>(props: SelectProps<T>): JSX.Element {
|
|
|
172
172
|
return (
|
|
173
173
|
<SelectInput
|
|
174
174
|
id={inputId}
|
|
175
|
+
listboxId={inputId}
|
|
175
176
|
selectedOptions={selectedOptions}
|
|
176
177
|
searchValue={searchValue}
|
|
177
178
|
placeholder={placeholder}
|
|
@@ -199,6 +200,24 @@ export function Select<T>(props: SelectProps<T>): JSX.Element {
|
|
|
199
200
|
disabled={disabled}
|
|
200
201
|
data-testid={dataTestId}
|
|
201
202
|
className={className}
|
|
203
|
+
onKeyDown={(e) => {
|
|
204
|
+
if (e.key === 'Enter' && document.activeElement === selectRef.current) {
|
|
205
|
+
e.preventDefault();
|
|
206
|
+
setDropdownActive(!dropdownActive);
|
|
207
|
+
}
|
|
208
|
+
}}
|
|
209
|
+
tabIndex={0}
|
|
210
|
+
aria-haspopup="listbox"
|
|
211
|
+
aria-expanded={dropdownActive}
|
|
212
|
+
aria-label="Select option"
|
|
213
|
+
onFocus={(e) => {
|
|
214
|
+
if (e.target === selectRef.current) {
|
|
215
|
+
selectInputRef.current?.focus();
|
|
216
|
+
}
|
|
217
|
+
}}
|
|
218
|
+
onMouseDown={(e) => {
|
|
219
|
+
e.preventDefault();
|
|
220
|
+
}}
|
|
202
221
|
>
|
|
203
222
|
<SelectDropdown
|
|
204
223
|
closeOnClick={!multiple}
|
|
@@ -209,7 +228,7 @@ export function Select<T>(props: SelectProps<T>): JSX.Element {
|
|
|
209
228
|
alignment={alignment}
|
|
210
229
|
active={!renderInput ? dropdownActive : undefined}
|
|
211
230
|
>
|
|
212
|
-
<SelectDropdownMenu footer={footer}>
|
|
231
|
+
<SelectDropdownMenu role="listbox" footer={footer}>
|
|
213
232
|
{filteredOptions.length === 0 ? (
|
|
214
233
|
<DropdownMenuItem disabled>No results</DropdownMenuItem>
|
|
215
234
|
) : (
|
|
@@ -257,6 +276,10 @@ export const SelectWrapper = styled.div<{ disabled?: boolean }>`
|
|
|
257
276
|
color: var(--select-text-color);
|
|
258
277
|
min-width: 0;
|
|
259
278
|
|
|
279
|
+
&:focus-visible {
|
|
280
|
+
outline: 1px solid var(--button-border-color-focused);
|
|
281
|
+
}
|
|
282
|
+
|
|
260
283
|
${({ disabled }) =>
|
|
261
284
|
disabled &&
|
|
262
285
|
`
|
|
@@ -9,6 +9,7 @@ import { Button } from '@redocly/theme/components/Button/Button';
|
|
|
9
9
|
|
|
10
10
|
type SelectInputProps<T> = {
|
|
11
11
|
id?: string;
|
|
12
|
+
listboxId?: string;
|
|
12
13
|
selectedOptions: SelectOption<T>[];
|
|
13
14
|
searchValue: any;
|
|
14
15
|
stickyValue: any;
|
|
@@ -30,6 +31,7 @@ type SelectInputProps<T> = {
|
|
|
30
31
|
export function SelectInput<T>(props: SelectInputProps<T>): React.ReactNode {
|
|
31
32
|
const {
|
|
32
33
|
id,
|
|
34
|
+
listboxId,
|
|
33
35
|
onlyIcon,
|
|
34
36
|
icon,
|
|
35
37
|
customIcon,
|
|
@@ -119,6 +121,13 @@ export function SelectInput<T>(props: SelectInputProps<T>): React.ReactNode {
|
|
|
119
121
|
}
|
|
120
122
|
}}
|
|
121
123
|
width={multiple ? (!searchValue && selectedOptions.length ? '10px' : 'auto') : '100%'}
|
|
124
|
+
tabIndex={0}
|
|
125
|
+
onFocus={(e) => {
|
|
126
|
+
e.stopPropagation();
|
|
127
|
+
}}
|
|
128
|
+
onMouseDown={(e) => {
|
|
129
|
+
e.preventDefault();
|
|
130
|
+
}}
|
|
122
131
|
/>
|
|
123
132
|
);
|
|
124
133
|
|
|
@@ -135,7 +144,17 @@ export function SelectInput<T>(props: SelectInputProps<T>): React.ReactNode {
|
|
|
135
144
|
);
|
|
136
145
|
|
|
137
146
|
return (
|
|
138
|
-
<SelectInputWrapper
|
|
147
|
+
<SelectInputWrapper
|
|
148
|
+
{...props}
|
|
149
|
+
id={id}
|
|
150
|
+
onFocus={onFocusHandler}
|
|
151
|
+
onClick={onClickHandler}
|
|
152
|
+
role="button"
|
|
153
|
+
aria-haspopup="listbox"
|
|
154
|
+
aria-controls={listboxId}
|
|
155
|
+
aria-owns={listboxId}
|
|
156
|
+
aria-label="Select option"
|
|
157
|
+
>
|
|
139
158
|
{!onlyIcon && (
|
|
140
159
|
<>
|
|
141
160
|
<SelectInputValue>
|
|
@@ -35,8 +35,15 @@ export function VersionPicker(props: { versions?: Version[]; onChange: (v: Versi
|
|
|
35
35
|
if (!options.length && !versionPicker?.showForUnversioned) return null;
|
|
36
36
|
|
|
37
37
|
return (
|
|
38
|
-
<VersionsPickerWrapper
|
|
39
|
-
|
|
38
|
+
<VersionsPickerWrapper
|
|
39
|
+
data-component-name="VersionPicker/VersionPicker"
|
|
40
|
+
role="region"
|
|
41
|
+
aria-label={translate('versionPicker.label', 'Version selector')}
|
|
42
|
+
>
|
|
43
|
+
<VersionPickerLabel
|
|
44
|
+
data-translation-key="versionPicker.label"
|
|
45
|
+
htmlFor="version-picker-select"
|
|
46
|
+
>
|
|
40
47
|
{translate('versionPicker.label', 'Version:')}
|
|
41
48
|
</VersionPickerLabel>
|
|
42
49
|
<VersionPickerSelect
|
|
@@ -45,7 +52,15 @@ export function VersionPicker(props: { versions?: Version[]; onChange: (v: Versi
|
|
|
45
52
|
options={options}
|
|
46
53
|
value={value}
|
|
47
54
|
onChange={handleOnChange}
|
|
55
|
+
dataAttributes={{
|
|
56
|
+
id: 'version-picker-select',
|
|
57
|
+
'aria-describedby': 'version-picker-description',
|
|
58
|
+
'aria-label': translate('versionPicker.label', 'Select version'),
|
|
59
|
+
}}
|
|
48
60
|
/>
|
|
61
|
+
<SrOnly id="version-picker-description">
|
|
62
|
+
This is version picker select, using it you can select a version of the API.
|
|
63
|
+
</SrOnly>
|
|
49
64
|
</VersionsPickerWrapper>
|
|
50
65
|
);
|
|
51
66
|
}
|
|
@@ -72,6 +87,10 @@ export const VersionPickerSelect = styled(Select)<SelectProps>`
|
|
|
72
87
|
border-radius: var(--version-picker-input-border-radius);
|
|
73
88
|
padding: var(--version-picker-input-padding-vertical)
|
|
74
89
|
var(--version-picker-input-padding-horizontal);
|
|
90
|
+
|
|
91
|
+
&:focus-within {
|
|
92
|
+
outline: 1px solid var(--version-picker-focus-outline-color);
|
|
93
|
+
}
|
|
75
94
|
}
|
|
76
95
|
`;
|
|
77
96
|
|
|
@@ -83,4 +102,15 @@ const VersionsPickerWrapper = styled.div`
|
|
|
83
102
|
justify-content: space-between;
|
|
84
103
|
padding: var(--version-picker-padding-vertical) var(--version-picker-padding-horizontal);
|
|
85
104
|
border-bottom: var(--version-picker-border-bottom);
|
|
105
|
+
|
|
106
|
+
&:focus-visible {
|
|
107
|
+
outline: 1px solid var(--version-picker-focus-outline-color);
|
|
108
|
+
}
|
|
109
|
+
`;
|
|
110
|
+
|
|
111
|
+
const SrOnly = styled.span`
|
|
112
|
+
position: absolute;
|
|
113
|
+
width: 0;
|
|
114
|
+
height: 0;
|
|
115
|
+
overflow: hidden;
|
|
86
116
|
`;
|
|
@@ -35,5 +35,6 @@ export const versionPicker = css`
|
|
|
35
35
|
--version-picker-list-item-bg-color-active: var(--select-list-item-bg-color-active); // @presenter Color
|
|
36
36
|
--version-picker-list-item-bg-color-hover: var(--select-list-item-bg-color-hover); // @presenter Color
|
|
37
37
|
|
|
38
|
+
--version-picker-focus-outline-color: var(--button-border-color-focused);
|
|
38
39
|
// @tokens End
|
|
39
40
|
`;
|
package/src/core/utils/index.ts
CHANGED
|
@@ -32,3 +32,4 @@ export * from '@redocly/theme/core/utils/match-code-walkthrough-conditions';
|
|
|
32
32
|
export * from '@redocly/theme/core/utils/replace-inputs-with-value';
|
|
33
33
|
export * from '@redocly/theme/core/utils/find-closest-common-directory';
|
|
34
34
|
export * from '@redocly/theme/core/utils/get-user-agent';
|
|
35
|
+
export * from '@redocly/theme/core/utils/parse-style-string';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function parseStyleString(styleString: string): React.CSSProperties {
|
|
2
|
+
return styleString
|
|
3
|
+
.split(';')
|
|
4
|
+
.filter((style) => style.trim().length)
|
|
5
|
+
.reduce((styleObj: React.CSSProperties, style) => {
|
|
6
|
+
const colonIndex = style.indexOf(':');
|
|
7
|
+
if (colonIndex === -1) return styleObj;
|
|
8
|
+
|
|
9
|
+
const key = style.substring(0, colonIndex).trim();
|
|
10
|
+
const value = style.substring(colonIndex + 1).trim();
|
|
11
|
+
|
|
12
|
+
if (key && value) {
|
|
13
|
+
const camelCaseKey = key.replace(/-[a-z]/g, (match) => {
|
|
14
|
+
return match[1].toUpperCase();
|
|
15
|
+
});
|
|
16
|
+
(styleObj as any)[camelCaseKey] = value;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return styleObj;
|
|
20
|
+
}, {});
|
|
21
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import styled, { css } from 'styled-components';
|
|
3
3
|
|
|
4
4
|
import type { JSX } from 'react';
|
|
@@ -8,8 +8,7 @@ import { TabItemProps, TabsSize } from '@redocly/theme/markdoc/components/Tabs/T
|
|
|
8
8
|
import { Dropdown } from '@redocly/theme/components/Dropdown/Dropdown';
|
|
9
9
|
import { DropdownMenu } from '@redocly/theme/components/Dropdown/DropdownMenu';
|
|
10
10
|
import { DropdownMenuItem } from '@redocly/theme/components/Dropdown/DropdownMenuItem';
|
|
11
|
-
import {
|
|
12
|
-
import { ChevronUpIcon } from '@redocly/theme/icons/ChevronUpIcon/ChevronUpIcon';
|
|
11
|
+
import { Button } from '@redocly/theme/components/Button/Button';
|
|
13
12
|
|
|
14
13
|
type TabListProps = {
|
|
15
14
|
childrenArray: React.ReactElement<TabItemProps>[];
|
|
@@ -42,16 +41,6 @@ export function TabList({
|
|
|
42
41
|
allTabsHidden,
|
|
43
42
|
tabsContainerRef,
|
|
44
43
|
}: TabListProps): JSX.Element {
|
|
45
|
-
const [isDropdownOpen, setIsDropdownOpen] = useState<boolean>(false);
|
|
46
|
-
|
|
47
|
-
const handleDropdownOpen = useCallback(() => {
|
|
48
|
-
setIsDropdownOpen(true);
|
|
49
|
-
}, []);
|
|
50
|
-
|
|
51
|
-
const handleDropdownClose = useCallback(() => {
|
|
52
|
-
setIsDropdownOpen(false);
|
|
53
|
-
}, []);
|
|
54
|
-
|
|
55
44
|
return (
|
|
56
45
|
<TabListContainer role="tablist" ref={tabsContainerRef} data-animating={isAnimating}>
|
|
57
46
|
<HighlightBar size={size} style={{ left: highlightStyle.left, width: highlightStyle.width }}>
|
|
@@ -88,47 +77,41 @@ export function TabList({
|
|
|
88
77
|
tabIndex={0}
|
|
89
78
|
>
|
|
90
79
|
{overflowTabs.length > 0 && (
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
</DropdownMenuItem>
|
|
127
|
-
);
|
|
128
|
-
})}
|
|
129
|
-
</DropdownMenu>
|
|
130
|
-
</Dropdown>
|
|
131
|
-
</div>
|
|
80
|
+
<Dropdown
|
|
81
|
+
trigger={
|
|
82
|
+
<TabButtonLink
|
|
83
|
+
size={size}
|
|
84
|
+
className={
|
|
85
|
+
overflowTabs.some((index) => activeTab === childrenArray[index].props.label)
|
|
86
|
+
? 'active'
|
|
87
|
+
: undefined
|
|
88
|
+
}
|
|
89
|
+
>
|
|
90
|
+
{allTabsHidden ? activeTab : 'More'}
|
|
91
|
+
</TabButtonLink>
|
|
92
|
+
}
|
|
93
|
+
alignment="start"
|
|
94
|
+
withArrow={true}
|
|
95
|
+
>
|
|
96
|
+
<DropdownMenu>
|
|
97
|
+
{overflowTabs.map((index) => {
|
|
98
|
+
const { label } = childrenArray[index].props;
|
|
99
|
+
const tabId = getTabId(label, index);
|
|
100
|
+
return (
|
|
101
|
+
<DropdownMenuItem
|
|
102
|
+
key={`more-${tabId}`}
|
|
103
|
+
active={activeTab === label}
|
|
104
|
+
onAction={() => {
|
|
105
|
+
onTabClick(index);
|
|
106
|
+
}}
|
|
107
|
+
disabled={childrenArray[index].props.disable}
|
|
108
|
+
>
|
|
109
|
+
{label}
|
|
110
|
+
</DropdownMenuItem>
|
|
111
|
+
);
|
|
112
|
+
})}
|
|
113
|
+
</DropdownMenu>
|
|
114
|
+
</Dropdown>
|
|
132
115
|
)}
|
|
133
116
|
</TabItem>
|
|
134
117
|
</TabListContainer>
|
|
@@ -231,25 +214,11 @@ const HighlightBar = styled.div<{ size: TabsSize }>`
|
|
|
231
214
|
}
|
|
232
215
|
`;
|
|
233
216
|
|
|
234
|
-
export const TabButtonLink = styled
|
|
235
|
-
size: TabsSize;
|
|
236
|
-
disabled?: boolean;
|
|
237
|
-
}>`
|
|
238
|
-
all: unset;
|
|
239
|
-
flex-grow: 1;
|
|
240
|
-
cursor: pointer;
|
|
241
|
-
width: 100%;
|
|
242
|
-
text-align: center;
|
|
217
|
+
export const TabButtonLink = styled(Button)`
|
|
243
218
|
color: var(--md-tabs-tab-text-color);
|
|
244
219
|
font-family: var(--md-tabs-tab-font-family);
|
|
245
220
|
font-style: var(--md-tabs-tab-font-style);
|
|
246
221
|
background-color: var(--md-tabs-tab-bg-color);
|
|
247
|
-
white-space: nowrap;
|
|
248
|
-
display: inline-flex;
|
|
249
|
-
align-items: center;
|
|
250
|
-
justify-content: center;
|
|
251
|
-
gap: var(--spacing-xxs);
|
|
252
|
-
z-index: 2;
|
|
253
222
|
|
|
254
223
|
transition:
|
|
255
224
|
background-color 300ms ease-in-out,
|
|
@@ -105,15 +105,7 @@ export function Tabs({ children, className, size }: TabsProps): JSX.Element {
|
|
|
105
105
|
setHighlightStyle({ left: offsetLeft, width: offsetWidth });
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
const timeoutId = setTimeout(() => {
|
|
109
|
-
if (visibleTabs.includes(activeIndex)) {
|
|
110
|
-
activeTabElement?.classList.add('active');
|
|
111
|
-
}
|
|
112
|
-
setIsAnimating(false);
|
|
113
|
-
}, 300);
|
|
114
|
-
|
|
115
108
|
return () => {
|
|
116
|
-
clearTimeout(timeoutId);
|
|
117
109
|
container.querySelectorAll('[data-label]').forEach((el) => {
|
|
118
110
|
el.classList.remove('active');
|
|
119
111
|
});
|