@redocly/theme 0.9.10 → 0.9.12-alpha.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/Catalog/Filter.d.ts +3 -1
- package/lib/Catalog/Filter.js +83 -4
- package/lib/Profile/Profile.js +18 -8
- package/lib/Profile/UserProfile.d.ts +1 -1
- package/lib/Profile/UserProfile.js +2 -36
- package/lib/Profile/UserProfileMenu.d.ts +8 -0
- package/lib/Profile/UserProfileMenu.js +87 -0
- package/lib/config.d.ts +9 -9
- package/lib/config.js +1 -1
- package/lib/globalStyle.js +61 -0
- package/lib/hooks/useActiveSectionId.d.ts +2 -2
- package/lib/hooks/useActiveSectionId.js +5 -5
- package/lib/hooks/useNavbarHeight.d.ts +1 -1
- package/package.json +24 -22
- package/src/Catalog/Catalog.tsx +1 -1
- package/src/Catalog/Filter.tsx +123 -3
- package/src/Profile/Profile.tsx +18 -8
- package/src/Profile/UserProfile.tsx +8 -47
- package/src/Profile/UserProfileMenu.tsx +83 -0
- package/src/config.ts +1 -1
- package/src/globalStyle.ts +62 -0
- package/src/hooks/useActiveSectionId.ts +7 -5
- package/src/hooks/useNavbarHeight.ts +1 -1
- package/src/types/portal/src/shared/types/catalog.d.ts +3 -1
package/lib/Catalog/Filter.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import type { ResolvedFilter } from '@theme/types/portal/src/shared/types/catalog';
|
|
3
3
|
export declare function Filter({ filter }: {
|
|
4
|
-
filter: ResolvedFilter
|
|
4
|
+
filter: ResolvedFilter & {
|
|
5
|
+
selectedOptions: any;
|
|
6
|
+
};
|
|
5
7
|
}): JSX.Element | null;
|
package/lib/Catalog/Filter.js
CHANGED
|
@@ -7,19 +7,36 @@ exports.Filter = void 0;
|
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
8
|
const styled_components_1 = __importDefault(require("styled-components"));
|
|
9
9
|
const Checkbox_1 = require("../ui/Checkbox");
|
|
10
|
+
// TODO: figure out how to fix this
|
|
11
|
+
const DatePicker =
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires, import/order, import/no-extraneous-dependencies
|
|
13
|
+
require('react-date-picker').default;
|
|
14
|
+
// disabled type checking for selectedOptions
|
|
10
15
|
function Filter({ filter }) {
|
|
11
|
-
var _a;
|
|
16
|
+
var _a, _b;
|
|
12
17
|
if (!filter.parentUsed)
|
|
13
18
|
return null;
|
|
14
19
|
return (react_1.default.createElement(FilterGroup, { key: filter.property + filter.title },
|
|
15
|
-
react_1.default.createElement(FilterTitle, null,
|
|
16
|
-
|
|
20
|
+
react_1.default.createElement(FilterTitle, null,
|
|
21
|
+
filter.title,
|
|
22
|
+
((_a = filter.selectedOptions) === null || _a === void 0 ? void 0 : _a.size) ? (react_1.default.createElement("a", { onClick: () => filter.selectOption('') }, " Clear ")) : null),
|
|
23
|
+
filter.type === 'select' ? (react_1.default.createElement(StyledSelect, { onChange: (e) => filter.selectOption(e.target.value), value: ((_b = filter.selectedOptions.values().next()) === null || _b === void 0 ? void 0 : _b.value) || '' },
|
|
17
24
|
react_1.default.createElement("option", { key: "none", value: "" }, "All"),
|
|
18
25
|
filter.filteredOptions.map((value) => (react_1.default.createElement("option", { key: value.value, value: value.value },
|
|
19
26
|
value.value,
|
|
20
27
|
" (",
|
|
21
28
|
value.count,
|
|
22
|
-
")"))))) :
|
|
29
|
+
")"))))) : filter.type === 'date-range' ? (react_1.default.createElement(react_1.default.Fragment, null,
|
|
30
|
+
react_1.default.createElement(DatePickerWrapper, null,
|
|
31
|
+
react_1.default.createElement("span", null, " From: "),
|
|
32
|
+
react_1.default.createElement(DatePicker, { closeCalendar: true, format: "y-MM-dd", dayPlaceholder: "DD", monthPlaceholder: "MM", yearPlaceholder: "YYYY", value: filter.selectedOptions.from ? new Date(filter.selectedOptions.from) : null, minDetail: "decade", maxDate: new Date(), onChange: (from) => {
|
|
33
|
+
filter.selectOption(Object.assign(Object.assign({}, filter.selectedOptions), { from: formatDateWithNoTimeZone(from) }));
|
|
34
|
+
} })),
|
|
35
|
+
react_1.default.createElement(DatePickerWrapper, null,
|
|
36
|
+
react_1.default.createElement("span", null, " To: "),
|
|
37
|
+
react_1.default.createElement(DatePicker, { closeCalendar: true, dayPlaceholder: "DD", monthPlaceholder: "MM", yearPlaceholder: "YYYY", format: "y-MM-dd", minDate: filter.selectedOptions.from ? new Date(filter.selectedOptions.from) : undefined, value: filter.selectedOptions.to ? new Date(filter.selectedOptions.to) : null, minDetail: "decade", onChange: (to) => {
|
|
38
|
+
filter.selectOption(Object.assign(Object.assign({}, filter.selectedOptions), { to: formatDateWithNoTimeZone(to) }));
|
|
39
|
+
} })))) : (filter.filteredOptions.map((value) => {
|
|
23
40
|
const id = 'filter--' + filter.property + '--' + slug(value.value);
|
|
24
41
|
return (react_1.default.createElement(FilterValue, { key: id },
|
|
25
42
|
react_1.default.createElement(Checkbox_1.Checkbox, { type: "checkbox", id: id, checked: filter.selectedOptions.has(value.value), onChange: () => filter.toggleOption(value.value) }),
|
|
@@ -44,6 +61,11 @@ const FilterTitle = styled_components_1.default.h4 `
|
|
|
44
61
|
font-weight: var(--font-weight-bold);
|
|
45
62
|
margin: 0;
|
|
46
63
|
margin-bottom: 16px;
|
|
64
|
+
|
|
65
|
+
> a {
|
|
66
|
+
font-size: 14px;
|
|
67
|
+
cursor: pointer;
|
|
68
|
+
}
|
|
47
69
|
`;
|
|
48
70
|
const FilterValue = styled_components_1.default.label `
|
|
49
71
|
display: block;
|
|
@@ -78,9 +100,66 @@ const StyledSelect = styled_components_1.default.select `
|
|
|
78
100
|
background-position: right 10px center;
|
|
79
101
|
background-size: 1em;
|
|
80
102
|
width: 100%;
|
|
103
|
+
padding-right: 25px;
|
|
81
104
|
`;
|
|
82
105
|
// TODO: import from portal
|
|
83
106
|
function slug(str) {
|
|
84
107
|
return str.replace(/\s/g, '-').toLowerCase();
|
|
85
108
|
}
|
|
109
|
+
const DatePickerWrapper = styled_components_1.default.div `
|
|
110
|
+
display: flex;
|
|
111
|
+
flex-direction: row;
|
|
112
|
+
margin-bottom: 5px;
|
|
113
|
+
|
|
114
|
+
align-items: center;
|
|
115
|
+
gap: 10px;
|
|
116
|
+
|
|
117
|
+
> span {
|
|
118
|
+
width: 50px;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.react-date-picker {
|
|
122
|
+
flex: 1;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.react-calendar__tile--now {
|
|
126
|
+
background: #cbf7f1;
|
|
127
|
+
color: black;
|
|
128
|
+
|
|
129
|
+
&:enabled:hover,
|
|
130
|
+
&:enabled:focus {
|
|
131
|
+
background: #b1efe7;
|
|
132
|
+
color: black;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.react-date-picker__inputGroup__input:invalid {
|
|
137
|
+
background: rgb(255 125 0 / 10%);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.react-date-picker__button {
|
|
141
|
+
padding: 4px 4px;
|
|
142
|
+
svg {
|
|
143
|
+
width: 12px;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.react-date-picker__wrapper {
|
|
148
|
+
border: 1px solid rgba(0, 0, 0, 0.23);
|
|
149
|
+
border-radius: var(--border-radius);
|
|
150
|
+
padding: var(--input-padding);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.react-date-picker__inputGroup__input {
|
|
154
|
+
width: 20px;
|
|
155
|
+
}
|
|
156
|
+
`;
|
|
157
|
+
function padZero(num) {
|
|
158
|
+
return num < 10 ? '0' + num : num;
|
|
159
|
+
}
|
|
160
|
+
function formatDateWithNoTimeZone(date) {
|
|
161
|
+
if (!date)
|
|
162
|
+
return date;
|
|
163
|
+
return `${date.getFullYear()}-${padZero(date.getMonth() + 1)}-${padZero(date.getDate())}`;
|
|
164
|
+
}
|
|
86
165
|
//# sourceMappingURL=Filter.js.map
|
package/lib/Profile/Profile.js
CHANGED
|
@@ -52,7 +52,13 @@ const ProfileWrapper = styled_components_1.default.div.attrs(() => ({
|
|
|
52
52
|
padding: 0 var(--navbar-item-padding-horizontal);
|
|
53
53
|
`;
|
|
54
54
|
const StyledUserName = styled_components_1.default.span `
|
|
55
|
-
|
|
55
|
+
font-family: var(--profile-name-font-family);
|
|
56
|
+
font-size: var(--profile-name-font-size);
|
|
57
|
+
font-weight: var(--profile-name-font-weight);
|
|
58
|
+
color: var(--profile-name-text-color);
|
|
59
|
+
padding: var(--profile-name-padding-vertical) var(--profile-name-padding-horizontal);
|
|
60
|
+
margin: 0 var(--profile-name-margin-horizontal);
|
|
61
|
+
|
|
56
62
|
display: none;
|
|
57
63
|
|
|
58
64
|
${({ theme }) => { var _a; return (_a = theme.mediaQueries) === null || _a === void 0 ? void 0 : _a.medium; }} {
|
|
@@ -60,19 +66,23 @@ const StyledUserName = styled_components_1.default.span `
|
|
|
60
66
|
}
|
|
61
67
|
`;
|
|
62
68
|
const AvatarWrapper = styled_components_1.default.div `
|
|
63
|
-
width:
|
|
64
|
-
height:
|
|
69
|
+
width: var(--profile-avatar-width);
|
|
70
|
+
height: var(--profile-avatar-height);
|
|
65
71
|
display: flex;
|
|
66
72
|
overflow: hidden;
|
|
67
73
|
position: relative;
|
|
68
|
-
font-size: 1.25rem;
|
|
69
74
|
align-items: center;
|
|
70
75
|
flex-shrink: 0;
|
|
71
|
-
line-height: 1;
|
|
72
|
-
user-select: none;
|
|
73
|
-
border-radius: 50%;
|
|
74
76
|
justify-content: center;
|
|
75
|
-
|
|
77
|
+
user-select: none;
|
|
78
|
+
|
|
79
|
+
font-family: var(--profile-avatar-font-family);
|
|
80
|
+
font-size: var(--profile-avatar-font-size);
|
|
81
|
+
line-height: var(--profile-avatar-line-height);
|
|
82
|
+
font-weight: var(--profile-avatar-font-weight);
|
|
83
|
+
|
|
84
|
+
border-radius: var(--profile-avatar-border-radius);
|
|
85
|
+
margin-left: var(--profile-avatar-margin-left);
|
|
76
86
|
|
|
77
87
|
${({ background }) => (0, styled_components_1.css) `
|
|
78
88
|
background-color: ${background};
|
|
@@ -6,7 +6,7 @@ export interface UserProfileProps {
|
|
|
6
6
|
picture: string;
|
|
7
7
|
logoutDisabled?: boolean;
|
|
8
8
|
};
|
|
9
|
-
handleLogout: (
|
|
9
|
+
handleLogout: () => void;
|
|
10
10
|
hasDeveloperOnboarding?: boolean;
|
|
11
11
|
}
|
|
12
12
|
export declare function UserProfile({ userInfo, handleLogout, hasDeveloperOnboarding, }: UserProfileProps): JSX.Element;
|
|
@@ -29,18 +29,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
29
29
|
exports.UserProfile = void 0;
|
|
30
30
|
const react_1 = __importStar(require("react"));
|
|
31
31
|
const styled_components_1 = __importDefault(require("styled-components"));
|
|
32
|
-
const Link_1 = require("../mocks/Link");
|
|
33
32
|
const Profile_1 = require("../Profile/Profile");
|
|
34
33
|
const Tooltip_1 = require("../Tooltip/Tooltip");
|
|
35
|
-
const
|
|
34
|
+
const UserProfileMenu_1 = require("./UserProfileMenu");
|
|
36
35
|
function UserProfile({ userInfo, handleLogout, hasDeveloperOnboarding = false, }) {
|
|
37
36
|
const [isOpened, setIsOpened] = (0, react_1.useState)(false);
|
|
38
|
-
|
|
39
|
-
const logoutRedirect = (userProfileSettings === null || userProfileSettings === void 0 ? void 0 : userProfileSettings.logoutRedirect) || '/';
|
|
40
|
-
return (react_1.default.createElement(StyledTooltip, { isOpen: isOpened, withArrow: false, className: "copy-button", placement: "bottom", width: "100%", tip: react_1.default.createElement(StyledUl, { onClick: () => setIsOpened(false) },
|
|
41
|
-
hasDeveloperOnboarding ? (react_1.default.createElement(Link_1.Link, { to: "/apps" },
|
|
42
|
-
react_1.default.createElement(StyledLi, null, "My Apps"))) : null,
|
|
43
|
-
react_1.default.createElement(StyledLi, { onClick: () => handleLogout(logoutRedirect) }, (userProfileSettings === null || userProfileSettings === void 0 ? void 0 : userProfileSettings.logoutLabel) || 'Log out')) },
|
|
37
|
+
return (react_1.default.createElement(StyledTooltip, { isOpen: isOpened, withArrow: false, className: "copy-button", placement: "bottom", width: "100%", tip: react_1.default.createElement(UserProfileMenu_1.UserProfileMenu, { hasDeveloperOnboarding: hasDeveloperOnboarding, handleLogout: handleLogout, setIsOpened: setIsOpened }) },
|
|
44
38
|
react_1.default.createElement(Profile_1.Profile, { name: userInfo.name, imageUrl: userInfo.picture, onClick: userInfo.logoutDisabled ? undefined : () => setIsOpened(!isOpened) })));
|
|
45
39
|
}
|
|
46
40
|
exports.UserProfile = UserProfile;
|
|
@@ -49,32 +43,4 @@ const StyledTooltip = (0, styled_components_1.default)(Tooltip_1.Tooltip) `
|
|
|
49
43
|
padding: 0;
|
|
50
44
|
}
|
|
51
45
|
`;
|
|
52
|
-
const StyledUl = styled_components_1.default.ul `
|
|
53
|
-
margin: 0;
|
|
54
|
-
padding: 0;
|
|
55
|
-
list-style: none;
|
|
56
|
-
text-align: left;
|
|
57
|
-
background-color: var(--search-modal-background);
|
|
58
|
-
color: var(--search-modal-text-color);
|
|
59
|
-
min-width: 100px;
|
|
60
|
-
a {
|
|
61
|
-
text-decoration: none;
|
|
62
|
-
&:hover {
|
|
63
|
-
color: inherit;
|
|
64
|
-
}
|
|
65
|
-
&:visited {
|
|
66
|
-
color: inherit;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
`;
|
|
70
|
-
const StyledLi = styled_components_1.default.li `
|
|
71
|
-
cursor: pointer;
|
|
72
|
-
font-size: 16px;
|
|
73
|
-
list-style: none;
|
|
74
|
-
padding: 15px 20px;
|
|
75
|
-
transition: background-color 0.25s ease 0s;
|
|
76
|
-
&:hover {
|
|
77
|
-
background-color: rgba(0, 0, 0, 0.1);
|
|
78
|
-
}
|
|
79
|
-
`;
|
|
80
46
|
//# sourceMappingURL=UserProfile.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
interface UserProfileMenuProps {
|
|
3
|
+
setIsOpened: (isOpen: boolean) => void;
|
|
4
|
+
handleLogout: () => void;
|
|
5
|
+
hasDeveloperOnboarding: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function UserProfileMenu({ hasDeveloperOnboarding, setIsOpened, handleLogout, }: UserProfileMenuProps): JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
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 (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.UserProfileMenu = void 0;
|
|
30
|
+
const react_1 = __importDefault(require("react"));
|
|
31
|
+
const styled_components_1 = __importStar(require("styled-components"));
|
|
32
|
+
const Link_1 = require("../mocks/Link");
|
|
33
|
+
const hooks_1 = require("../hooks");
|
|
34
|
+
function UserProfileMenu({ hasDeveloperOnboarding, setIsOpened, handleLogout, }) {
|
|
35
|
+
var _a;
|
|
36
|
+
const { userProfile } = (0, hooks_1.useThemeConfig)();
|
|
37
|
+
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
38
|
+
react_1.default.createElement(StyledUl, { onClick: () => setIsOpened(false) },
|
|
39
|
+
hasDeveloperOnboarding ? (react_1.default.createElement(Link_1.Link, { to: "/apps" },
|
|
40
|
+
react_1.default.createElement(StyledLi, null, "My Apps"))) : null, (_a = userProfile === null || userProfile === void 0 ? void 0 : userProfile.menu) === null || _a === void 0 ? void 0 :
|
|
41
|
+
_a.map((item) => (react_1.default.createElement(Link_1.Link, { external: item.external, key: item.label, to: item.link || '' },
|
|
42
|
+
react_1.default.createElement(StyledLi, { separatorLine: item === null || item === void 0 ? void 0 : item.separatorLine }, item.label)))),
|
|
43
|
+
react_1.default.createElement(StyledLi, { onClick: () => handleLogout() }, (userProfile === null || userProfile === void 0 ? void 0 : userProfile.logoutLabel) || 'Log out'))));
|
|
44
|
+
}
|
|
45
|
+
exports.UserProfileMenu = UserProfileMenu;
|
|
46
|
+
const StyledUl = styled_components_1.default.ul `
|
|
47
|
+
margin: var(--profile-menu-margin);
|
|
48
|
+
padding: var(--profile-menu-padding);
|
|
49
|
+
list-style: none;
|
|
50
|
+
background-color: var(--profile-menu-background-color);
|
|
51
|
+
min-width: 100px;
|
|
52
|
+
a {
|
|
53
|
+
text-decoration: none;
|
|
54
|
+
}
|
|
55
|
+
`;
|
|
56
|
+
const StyledLi = styled_components_1.default.li `
|
|
57
|
+
cursor: pointer;
|
|
58
|
+
font-size: var(--profile-menu-item-font-size);
|
|
59
|
+
font-family: var(--profile-menu-item-font-family);
|
|
60
|
+
font-weight: var(--profile-menu-item-font-weight);
|
|
61
|
+
line-height: var(--profile-menu-item-line-height);
|
|
62
|
+
color: var(--profile-menu-item-text-color);
|
|
63
|
+
text-align: var(--profile-menu-item-text-align);
|
|
64
|
+
|
|
65
|
+
list-style: none;
|
|
66
|
+
|
|
67
|
+
padding: var(--profile-menu-item-padding-vertical) var(--profile-menu-item-padding-horizontal);
|
|
68
|
+
|
|
69
|
+
transition: background-color 0.25s ease 0s;
|
|
70
|
+
|
|
71
|
+
&:hover {
|
|
72
|
+
color: var(--profile-menu-item-hover-text-color);
|
|
73
|
+
background-color: var(--profile-menu-item-hover-background-color);
|
|
74
|
+
text-decoration: var(--profile-menu-item-hover-text-decoration);
|
|
75
|
+
}
|
|
76
|
+
&:active {
|
|
77
|
+
color: var(--profile-menu-item-active-text-color);
|
|
78
|
+
background-color: var(--profile-menu-item-active-background-color);
|
|
79
|
+
text-decoration: var(--profile-menu-item-active-text-decoration);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
${({ separatorLine }) => separatorLine &&
|
|
83
|
+
(0, styled_components_1.css) `
|
|
84
|
+
border-bottom: 1px solid var(--profile-menu-item-separator-line-color);
|
|
85
|
+
`}
|
|
86
|
+
`;
|
|
87
|
+
//# sourceMappingURL=UserProfileMenu.js.map
|
package/lib/config.d.ts
CHANGED
|
@@ -648,17 +648,17 @@ export declare const ThemeConfig: z.ZodDefault<z.ZodObject<{
|
|
|
648
648
|
userProfile: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
649
649
|
loginLabel: z.ZodOptional<z.ZodDefault<z.ZodString>>;
|
|
650
650
|
logoutLabel: z.ZodOptional<z.ZodDefault<z.ZodString>>;
|
|
651
|
-
|
|
651
|
+
menu: z.ZodOptional<z.ZodArray<z.ZodAny, "many">>;
|
|
652
652
|
hide: z.ZodOptional<z.ZodBoolean>;
|
|
653
653
|
}, "strip", z.ZodTypeAny, {
|
|
654
654
|
loginLabel?: string | undefined;
|
|
655
655
|
logoutLabel?: string | undefined;
|
|
656
|
-
|
|
656
|
+
menu?: any[] | undefined;
|
|
657
657
|
hide?: boolean | undefined;
|
|
658
658
|
}, {
|
|
659
659
|
loginLabel?: string | undefined;
|
|
660
660
|
logoutLabel?: string | undefined;
|
|
661
|
-
|
|
661
|
+
menu?: any[] | undefined;
|
|
662
662
|
hide?: boolean | undefined;
|
|
663
663
|
}>>>;
|
|
664
664
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
@@ -1229,17 +1229,17 @@ export declare const ThemeConfig: z.ZodDefault<z.ZodObject<{
|
|
|
1229
1229
|
userProfile: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
1230
1230
|
loginLabel: z.ZodOptional<z.ZodDefault<z.ZodString>>;
|
|
1231
1231
|
logoutLabel: z.ZodOptional<z.ZodDefault<z.ZodString>>;
|
|
1232
|
-
|
|
1232
|
+
menu: z.ZodOptional<z.ZodArray<z.ZodAny, "many">>;
|
|
1233
1233
|
hide: z.ZodOptional<z.ZodBoolean>;
|
|
1234
1234
|
}, "strip", z.ZodTypeAny, {
|
|
1235
1235
|
loginLabel?: string | undefined;
|
|
1236
1236
|
logoutLabel?: string | undefined;
|
|
1237
|
-
|
|
1237
|
+
menu?: any[] | undefined;
|
|
1238
1238
|
hide?: boolean | undefined;
|
|
1239
1239
|
}, {
|
|
1240
1240
|
loginLabel?: string | undefined;
|
|
1241
1241
|
logoutLabel?: string | undefined;
|
|
1242
|
-
|
|
1242
|
+
menu?: any[] | undefined;
|
|
1243
1243
|
hide?: boolean | undefined;
|
|
1244
1244
|
}>>>;
|
|
1245
1245
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
@@ -1810,17 +1810,17 @@ export declare const ThemeConfig: z.ZodDefault<z.ZodObject<{
|
|
|
1810
1810
|
userProfile: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
1811
1811
|
loginLabel: z.ZodOptional<z.ZodDefault<z.ZodString>>;
|
|
1812
1812
|
logoutLabel: z.ZodOptional<z.ZodDefault<z.ZodString>>;
|
|
1813
|
-
|
|
1813
|
+
menu: z.ZodOptional<z.ZodArray<z.ZodAny, "many">>;
|
|
1814
1814
|
hide: z.ZodOptional<z.ZodBoolean>;
|
|
1815
1815
|
}, "strip", z.ZodTypeAny, {
|
|
1816
1816
|
loginLabel?: string | undefined;
|
|
1817
1817
|
logoutLabel?: string | undefined;
|
|
1818
|
-
|
|
1818
|
+
menu?: any[] | undefined;
|
|
1819
1819
|
hide?: boolean | undefined;
|
|
1820
1820
|
}, {
|
|
1821
1821
|
loginLabel?: string | undefined;
|
|
1822
1822
|
logoutLabel?: string | undefined;
|
|
1823
|
-
|
|
1823
|
+
menu?: any[] | undefined;
|
|
1824
1824
|
hide?: boolean | undefined;
|
|
1825
1825
|
}>>>;
|
|
1826
1826
|
}, z.ZodTypeAny, "passthrough">>>;
|
package/lib/config.js
CHANGED
|
@@ -205,7 +205,7 @@ exports.ThemeConfig = zod_1.z
|
|
|
205
205
|
.object({
|
|
206
206
|
loginLabel: zod_1.z.string().default('Login').optional(),
|
|
207
207
|
logoutLabel: zod_1.z.string().default('Logout').optional(),
|
|
208
|
-
|
|
208
|
+
menu: zod_1.z.array(zod_1.z.any()).optional(), // should be same as navbar items type
|
|
209
209
|
})
|
|
210
210
|
.extend(HideConfig.shape)
|
|
211
211
|
.optional()
|
package/lib/globalStyle.js
CHANGED
|
@@ -1939,6 +1939,66 @@ const pages = (0, styled_components_1.css) `
|
|
|
1939
1939
|
|
|
1940
1940
|
// @tokens End
|
|
1941
1941
|
`;
|
|
1942
|
+
const userProfile = (0, styled_components_1.css) `
|
|
1943
|
+
|
|
1944
|
+
/**
|
|
1945
|
+
* @tokens User Profile
|
|
1946
|
+
*/
|
|
1947
|
+
|
|
1948
|
+
--profile-name-font-family: var(--navbar-item-font-family); // @presenter FontFamily
|
|
1949
|
+
--profile-name-font-size: var(--navbar-item-font-size); // @presenter FontSize
|
|
1950
|
+
--profile-name-font-weight: var(--font-weight-regular); // @presenter FontWeight
|
|
1951
|
+
--profile-name-line-height: var(--line-height-base); // @presenter LineHeight
|
|
1952
|
+
--profile-name-text-color: var(--navbar-text-color); // @presenter Color
|
|
1953
|
+
|
|
1954
|
+
--profile-name-padding-horizontal: 0; // @presenter Spacing
|
|
1955
|
+
--profile-name-padding-vertical: 0; // @presenter Spacing
|
|
1956
|
+
--profile-name-margin-horizontal: 0; // @presenter Spacing
|
|
1957
|
+
|
|
1958
|
+
--profile-avatar-width: 40px;
|
|
1959
|
+
--profile-avatar-height: 40px;
|
|
1960
|
+
--profile-avatar-border-radius: 50%; // @presenter BorderRadius
|
|
1961
|
+
|
|
1962
|
+
--profile-avatar-font-family: var(--navbar-item-font-family); // @presenter FontFamily
|
|
1963
|
+
--profile-avatar-font-size: var(--navbar-item-font-size) // @presenter FontSize
|
|
1964
|
+
--profile-avatar-font-weight: var(--font-weight-regular); // @presenter FontWeight
|
|
1965
|
+
--profile-avatar-line-height: var(--line-height-base); // @presenter LineHeight
|
|
1966
|
+
|
|
1967
|
+
--profile-avatar-margin-left: 16px; // @presenter Spacing
|
|
1968
|
+
--profile-avatar-padding-vertical: 16px; // @presenter Spacing
|
|
1969
|
+
--profile-avatar-padding-horizontal: 16px; // @presenter Spacing
|
|
1970
|
+
|
|
1971
|
+
|
|
1972
|
+
/**
|
|
1973
|
+
* @tokens User Profile Menu
|
|
1974
|
+
*/
|
|
1975
|
+
|
|
1976
|
+
--profile-menu-background-color: var(--background-color); // @presenter Color
|
|
1977
|
+
--profile-menu-padding: 0px; // @presenter Spacing
|
|
1978
|
+
--profile-menu-margin: 0px; // @presenter Spacing
|
|
1979
|
+
|
|
1980
|
+
--profile-menu-item-font-family: var(--navbar-item-font-family); // @presenter FontFamily
|
|
1981
|
+
--profile-menu-item-text-color: var(--text-color); // @presenter Color
|
|
1982
|
+
--profile-menu-item-font-size: var(--navbar-item-font-size); // @presenter FontSize
|
|
1983
|
+
--profile-menu-item-font-weight: var(--font-weight-regular); // @presenter FontWeight
|
|
1984
|
+
--profile-menu-item-line-height: var(--line-height-base); // @presenter LineHeight
|
|
1985
|
+
--profile-menu-item-text-align: left;
|
|
1986
|
+
|
|
1987
|
+
--profile-menu-item-padding-horizontal: 15px; // @presenter Spacing
|
|
1988
|
+
--profile-menu-item-padding-vertical: 20px; // @presenter Spacing
|
|
1989
|
+
|
|
1990
|
+
--profile-menu-item-hover-background-color: var(--color-primary-300); // @presenter Color
|
|
1991
|
+
--profile-menu-item-active-background-color: var(--color-primary-300); // @presenter Color
|
|
1992
|
+
--profile-menu-item-hover-text-color: var(--navbar-text-color); // @presenter Color
|
|
1993
|
+
--profile-menu-item-hover-text-decoration: none;
|
|
1994
|
+
--profile-menu-item-active-text-color: var(--navbar-text-color); // @presenter Color
|
|
1995
|
+
--profile-menu-item-active-text-decoration: none;
|
|
1996
|
+
|
|
1997
|
+
--profile-menu-item-separator-line-color: var(--border-color); // @presenter Color
|
|
1998
|
+
|
|
1999
|
+
// @tokens End
|
|
2000
|
+
|
|
2001
|
+
`;
|
|
1942
2002
|
const modal = (0, styled_components_1.css) `
|
|
1943
2003
|
body:has(.modal) {
|
|
1944
2004
|
overflow: hidden;
|
|
@@ -1978,6 +2038,7 @@ exports.styles = (0, styled_components_1.css) `
|
|
|
1978
2038
|
${loadProgressBar}
|
|
1979
2039
|
${pages}
|
|
1980
2040
|
${modal}
|
|
2041
|
+
${userProfile}
|
|
1981
2042
|
|
|
1982
2043
|
--api-onboarding-table-text-color: #4e5356;
|
|
1983
2044
|
--api-catalog-card-min-width: 250px;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { Location } from '
|
|
1
|
+
import type { Location } from 'react-router-dom';
|
|
2
2
|
export type UseActiveSectionIdReturnType = string;
|
|
3
|
-
export declare function useActiveSectionId(location: Location, hasOverviewPage?: boolean): UseActiveSectionIdReturnType;
|
|
3
|
+
export declare function useActiveSectionId(location: Location, hasOverviewPage?: boolean, withNavbar?: boolean): UseActiveSectionIdReturnType;
|
|
@@ -7,9 +7,10 @@ exports.useActiveSectionId = void 0;
|
|
|
7
7
|
const react_1 = require("react");
|
|
8
8
|
const lodash_throttle_1 = __importDefault(require("lodash.throttle"));
|
|
9
9
|
const useNavbarHeight_1 = require("../hooks/useNavbarHeight");
|
|
10
|
-
function useActiveSectionId(location, hasOverviewPage = false) {
|
|
10
|
+
function useActiveSectionId(location, hasOverviewPage = false, withNavbar = true) {
|
|
11
11
|
const [itemId, setItemId] = (0, react_1.useState)('');
|
|
12
12
|
const navbarHeight = (0, useNavbarHeight_1.useNavbarHeight)(location);
|
|
13
|
+
const heightOffset = (withNavbar ? navbarHeight : 0) + 5; // use small padding 5px to account for rounding;
|
|
13
14
|
const scrollListener = (0, react_1.useMemo)(() => (0, lodash_throttle_1.default)(() => {
|
|
14
15
|
const sections = document.querySelectorAll('[data-section-id]');
|
|
15
16
|
if (sections.length < 2) {
|
|
@@ -19,8 +20,7 @@ function useActiveSectionId(location, hasOverviewPage = false) {
|
|
|
19
20
|
for (let i = 0; i < sections.length; i++) {
|
|
20
21
|
const section = sections[i];
|
|
21
22
|
const rect = section.getBoundingClientRect();
|
|
22
|
-
if (rect.y <
|
|
23
|
-
// use small padding 5px to account for rounding
|
|
23
|
+
if (rect.y < heightOffset && rect.bottom > heightOffset) {
|
|
24
24
|
setItemId(section.getAttribute('data-section-id') || '');
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
@@ -28,7 +28,7 @@ function useActiveSectionId(location, hasOverviewPage = false) {
|
|
|
28
28
|
if (hasOverviewPage) {
|
|
29
29
|
setItemId('');
|
|
30
30
|
}
|
|
31
|
-
}, 150), [
|
|
31
|
+
}, 150), [heightOffset, hasOverviewPage]);
|
|
32
32
|
(0, react_1.useEffect)(() => {
|
|
33
33
|
window.addEventListener('scroll', scrollListener, { capture: false });
|
|
34
34
|
setTimeout(() => {
|
|
@@ -37,7 +37,7 @@ function useActiveSectionId(location, hasOverviewPage = false) {
|
|
|
37
37
|
return () => {
|
|
38
38
|
window.removeEventListener('scroll', scrollListener);
|
|
39
39
|
};
|
|
40
|
-
}, [location,
|
|
40
|
+
}, [location, heightOffset, scrollListener]);
|
|
41
41
|
return itemId;
|
|
42
42
|
}
|
|
43
43
|
exports.useActiveSectionId = useActiveSectionId;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/theme",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.12-alpha.0",
|
|
4
4
|
"description": "Shared UI components lib",
|
|
5
5
|
"author": "team@redocly.com",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -15,25 +15,6 @@
|
|
|
15
15
|
"./*": "./lib/index.js",
|
|
16
16
|
"./src/": "./src/"
|
|
17
17
|
},
|
|
18
|
-
"scripts": {
|
|
19
|
-
"start": "npm-run-all --parallel storybook storybook:tokens:watch",
|
|
20
|
-
"watch": "tsc -p tsconfig.build.json && (concurrently \"tsc -w -p tsconfig.build.json\" \"tsc-alias -w -p tsconfig.build.json\")",
|
|
21
|
-
"ts:check": "tsc --noEmit --skipLibCheck",
|
|
22
|
-
"clean": "rm -rf lib",
|
|
23
|
-
"compile": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
24
|
-
"build": "npm run clean && npm run compile",
|
|
25
|
-
"test": "jest",
|
|
26
|
-
"test:update": "jest -u",
|
|
27
|
-
"test:watch": "jest --watch",
|
|
28
|
-
"test:coverage": "jest --coverage",
|
|
29
|
-
"test:coverage:html": "jest --coverage --coverageReporters html",
|
|
30
|
-
"e2e": "npx chromatic -b storybook:build --auto-accept-changes main --exit-once-uploaded",
|
|
31
|
-
"storybook": "start-storybook -p 6006",
|
|
32
|
-
"storybook:build": "npm run storybook:tokens && build-storybook",
|
|
33
|
-
"storybook:tokens": "ts-node scripts/generate-css-tokens.ts",
|
|
34
|
-
"storybook:tokens:watch": "ts-node-dev --respawn scripts/generate-css-tokens.ts",
|
|
35
|
-
"chromatic": "chromatic --exit-zero-on-changes"
|
|
36
|
-
},
|
|
37
18
|
"peerDependencies": {
|
|
38
19
|
"lodash.throttle": "^4.1.1",
|
|
39
20
|
"prismjs": "^1.28.0",
|
|
@@ -72,6 +53,7 @@
|
|
|
72
53
|
"@types/react-dom": "^17.0.11",
|
|
73
54
|
"@types/styled-components": "^5.1.26",
|
|
74
55
|
"@types/styled-system": "^5.1.13",
|
|
56
|
+
"@types/testing-library__jest-dom": "^5.14.5",
|
|
75
57
|
"@typescript-eslint/eslint-plugin": "^5.23.0",
|
|
76
58
|
"@typescript-eslint/parser": "^5.23.0",
|
|
77
59
|
"chromatic": "^6.10.2",
|
|
@@ -86,7 +68,7 @@
|
|
|
86
68
|
"react-refresh": "^0.14.0",
|
|
87
69
|
"react-router-dom": "^6.4.4",
|
|
88
70
|
"storybook-addon-pseudo-states": "^1.15.1",
|
|
89
|
-
"storybook-design-token": "^2.
|
|
71
|
+
"storybook-design-token": "^2.9.0",
|
|
90
72
|
"styled-components": "^5.3.6",
|
|
91
73
|
"styled-system": "^5.1.5",
|
|
92
74
|
"ts-jest": "^29.0.3",
|
|
@@ -101,6 +83,7 @@
|
|
|
101
83
|
"dependencies": {
|
|
102
84
|
"copy-to-clipboard": "^3.3.3",
|
|
103
85
|
"highlight-words-core": "^1.2.2",
|
|
86
|
+
"react-date-picker": "9.2.0",
|
|
104
87
|
"hotkeys-js": "^3.10.1",
|
|
105
88
|
"timeago.js": "^4.0.2"
|
|
106
89
|
},
|
|
@@ -124,5 +107,24 @@
|
|
|
124
107
|
]
|
|
125
108
|
}
|
|
126
109
|
}
|
|
110
|
+
},
|
|
111
|
+
"scripts": {
|
|
112
|
+
"start": "npm-run-all --parallel storybook storybook:tokens:watch",
|
|
113
|
+
"watch": "tsc -p tsconfig.build.json && (concurrently \"tsc -w -p tsconfig.build.json\" \"tsc-alias -w -p tsconfig.build.json\")",
|
|
114
|
+
"ts:check": "tsc --noEmit --skipLibCheck",
|
|
115
|
+
"clean": "rm -rf lib",
|
|
116
|
+
"compile": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
|
|
117
|
+
"build": "npm run clean && npm run compile",
|
|
118
|
+
"test": "jest",
|
|
119
|
+
"test:update": "jest -u",
|
|
120
|
+
"test:watch": "jest --watch",
|
|
121
|
+
"test:coverage": "jest --coverage",
|
|
122
|
+
"test:coverage:html": "jest --coverage --coverageReporters html",
|
|
123
|
+
"e2e": "npx chromatic -b storybook:build --auto-accept-changes main --exit-once-uploaded",
|
|
124
|
+
"storybook": "start-storybook -p 6006",
|
|
125
|
+
"storybook:build": "npm run storybook:tokens && build-storybook",
|
|
126
|
+
"storybook:tokens": "ts-node scripts/generate-css-tokens.ts",
|
|
127
|
+
"storybook:tokens:watch": "ts-node-dev --respawn scripts/generate-css-tokens.ts",
|
|
128
|
+
"chromatic": "chromatic --exit-zero-on-changes"
|
|
127
129
|
}
|
|
128
|
-
}
|
|
130
|
+
}
|
package/src/Catalog/Catalog.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
|
|
4
|
-
import type { ResolvedNavItem } from '
|
|
4
|
+
import type { ResolvedNavItem } from '../types/portal';
|
|
5
5
|
|
|
6
6
|
import type { CatalogConfig } from '@theme/types/portal/src/shared/types/catalog';
|
|
7
7
|
import { usePageSharedData } from '@portal/hooks/index.js';
|
package/src/Catalog/Filter.tsx
CHANGED
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
|
|
4
|
+
import type { DatePickerProps } from 'react-date-picker';
|
|
5
|
+
|
|
4
6
|
import type { ResolvedFilter } from '@theme/types/portal/src/shared/types/catalog';
|
|
5
7
|
import { Checkbox } from '@theme/ui/Checkbox';
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
// TODO: figure out how to fix this
|
|
10
|
+
const DatePicker: React.FC<DatePickerProps> =
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires, import/order, import/no-extraneous-dependencies
|
|
12
|
+
require('react-date-picker').default;
|
|
13
|
+
|
|
14
|
+
// disabled type checking for selectedOptions
|
|
15
|
+
export function Filter({ filter }: { filter: ResolvedFilter & { selectedOptions: any } }) {
|
|
8
16
|
if (!filter.parentUsed) return null;
|
|
9
17
|
return (
|
|
10
18
|
<FilterGroup key={filter.property + filter.title}>
|
|
11
|
-
<FilterTitle>
|
|
19
|
+
<FilterTitle>
|
|
20
|
+
{filter.title}
|
|
21
|
+
{filter.selectedOptions?.size ? (
|
|
22
|
+
<a onClick={() => filter.selectOption('')}> Clear </a>
|
|
23
|
+
) : null}
|
|
24
|
+
</FilterTitle>
|
|
12
25
|
{filter.type === 'select' ? (
|
|
13
26
|
<StyledSelect
|
|
14
27
|
onChange={(e) => filter.selectOption(e.target.value)}
|
|
15
|
-
value={filter.selectedOptions.values().next()?.value || ''}
|
|
28
|
+
value={(filter.selectedOptions as Set<any>).values().next()?.value || ''}
|
|
16
29
|
>
|
|
17
30
|
<option key="none" value="">
|
|
18
31
|
All
|
|
@@ -23,6 +36,49 @@ export function Filter({ filter }: { filter: ResolvedFilter }) {
|
|
|
23
36
|
</option>
|
|
24
37
|
))}
|
|
25
38
|
</StyledSelect>
|
|
39
|
+
) : filter.type === 'date-range' ? (
|
|
40
|
+
<>
|
|
41
|
+
<DatePickerWrapper>
|
|
42
|
+
<span> From: </span>
|
|
43
|
+
<DatePicker
|
|
44
|
+
closeCalendar={true}
|
|
45
|
+
format="y-MM-dd"
|
|
46
|
+
dayPlaceholder="DD"
|
|
47
|
+
monthPlaceholder="MM"
|
|
48
|
+
yearPlaceholder="YYYY"
|
|
49
|
+
value={filter.selectedOptions.from ? new Date(filter.selectedOptions.from) : null}
|
|
50
|
+
minDetail="decade"
|
|
51
|
+
maxDate={new Date()}
|
|
52
|
+
onChange={(from: Date) => {
|
|
53
|
+
filter.selectOption({
|
|
54
|
+
...(filter.selectedOptions as any),
|
|
55
|
+
from: formatDateWithNoTimeZone(from),
|
|
56
|
+
});
|
|
57
|
+
}}
|
|
58
|
+
/>
|
|
59
|
+
</DatePickerWrapper>
|
|
60
|
+
<DatePickerWrapper>
|
|
61
|
+
<span> To: </span>
|
|
62
|
+
<DatePicker
|
|
63
|
+
closeCalendar={true}
|
|
64
|
+
dayPlaceholder="DD"
|
|
65
|
+
monthPlaceholder="MM"
|
|
66
|
+
yearPlaceholder="YYYY"
|
|
67
|
+
format="y-MM-dd"
|
|
68
|
+
minDate={
|
|
69
|
+
filter.selectedOptions.from ? new Date(filter.selectedOptions.from) : undefined
|
|
70
|
+
}
|
|
71
|
+
value={filter.selectedOptions.to ? new Date(filter.selectedOptions.to) : null}
|
|
72
|
+
minDetail="decade"
|
|
73
|
+
onChange={(to: Date) => {
|
|
74
|
+
filter.selectOption({
|
|
75
|
+
...filter.selectedOptions,
|
|
76
|
+
to: formatDateWithNoTimeZone(to),
|
|
77
|
+
});
|
|
78
|
+
}}
|
|
79
|
+
/>
|
|
80
|
+
</DatePickerWrapper>
|
|
81
|
+
</>
|
|
26
82
|
) : (
|
|
27
83
|
filter.filteredOptions.map((value: any) => {
|
|
28
84
|
const id = 'filter--' + filter.property + '--' + slug(value.value);
|
|
@@ -59,6 +115,11 @@ const FilterTitle = styled.h4`
|
|
|
59
115
|
font-weight: var(--font-weight-bold);
|
|
60
116
|
margin: 0;
|
|
61
117
|
margin-bottom: 16px;
|
|
118
|
+
|
|
119
|
+
> a {
|
|
120
|
+
font-size: 14px;
|
|
121
|
+
cursor: pointer;
|
|
122
|
+
}
|
|
62
123
|
`;
|
|
63
124
|
|
|
64
125
|
const FilterValue = styled.label`
|
|
@@ -95,9 +156,68 @@ const StyledSelect = styled.select`
|
|
|
95
156
|
background-position: right 10px center;
|
|
96
157
|
background-size: 1em;
|
|
97
158
|
width: 100%;
|
|
159
|
+
padding-right: 25px;
|
|
98
160
|
`;
|
|
99
161
|
|
|
100
162
|
// TODO: import from portal
|
|
101
163
|
function slug(str: string): string {
|
|
102
164
|
return str.replace(/\s/g, '-').toLowerCase();
|
|
103
165
|
}
|
|
166
|
+
|
|
167
|
+
const DatePickerWrapper = styled.div`
|
|
168
|
+
display: flex;
|
|
169
|
+
flex-direction: row;
|
|
170
|
+
margin-bottom: 5px;
|
|
171
|
+
|
|
172
|
+
align-items: center;
|
|
173
|
+
gap: 10px;
|
|
174
|
+
|
|
175
|
+
> span {
|
|
176
|
+
width: 50px;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.react-date-picker {
|
|
180
|
+
flex: 1;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.react-calendar__tile--now {
|
|
184
|
+
background: #cbf7f1;
|
|
185
|
+
color: black;
|
|
186
|
+
|
|
187
|
+
&:enabled:hover,
|
|
188
|
+
&:enabled:focus {
|
|
189
|
+
background: #b1efe7;
|
|
190
|
+
color: black;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.react-date-picker__inputGroup__input:invalid {
|
|
195
|
+
background: rgb(255 125 0 / 10%);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.react-date-picker__button {
|
|
199
|
+
padding: 4px 4px;
|
|
200
|
+
svg {
|
|
201
|
+
width: 12px;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.react-date-picker__wrapper {
|
|
206
|
+
border: 1px solid rgba(0, 0, 0, 0.23);
|
|
207
|
+
border-radius: var(--border-radius);
|
|
208
|
+
padding: var(--input-padding);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.react-date-picker__inputGroup__input {
|
|
212
|
+
width: 20px;
|
|
213
|
+
}
|
|
214
|
+
`;
|
|
215
|
+
|
|
216
|
+
function padZero(num: number) {
|
|
217
|
+
return num < 10 ? '0' + num : num;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function formatDateWithNoTimeZone(date?: Date | null) {
|
|
221
|
+
if (!date) return date;
|
|
222
|
+
return `${date.getFullYear()}-${padZero(date.getMonth() + 1)}-${padZero(date.getDate())}`;
|
|
223
|
+
}
|
package/src/Profile/Profile.tsx
CHANGED
|
@@ -55,7 +55,13 @@ const ProfileWrapper = styled.div.attrs(() => ({
|
|
|
55
55
|
`;
|
|
56
56
|
|
|
57
57
|
const StyledUserName = styled.span`
|
|
58
|
-
|
|
58
|
+
font-family: var(--profile-name-font-family);
|
|
59
|
+
font-size: var(--profile-name-font-size);
|
|
60
|
+
font-weight: var(--profile-name-font-weight);
|
|
61
|
+
color: var(--profile-name-text-color);
|
|
62
|
+
padding: var(--profile-name-padding-vertical) var(--profile-name-padding-horizontal);
|
|
63
|
+
margin: 0 var(--profile-name-margin-horizontal);
|
|
64
|
+
|
|
59
65
|
display: none;
|
|
60
66
|
|
|
61
67
|
${({ theme }) => theme.mediaQueries?.medium} {
|
|
@@ -64,19 +70,23 @@ const StyledUserName = styled.span`
|
|
|
64
70
|
`;
|
|
65
71
|
|
|
66
72
|
const AvatarWrapper = styled.div<{ background?: string }>`
|
|
67
|
-
width:
|
|
68
|
-
height:
|
|
73
|
+
width: var(--profile-avatar-width);
|
|
74
|
+
height: var(--profile-avatar-height);
|
|
69
75
|
display: flex;
|
|
70
76
|
overflow: hidden;
|
|
71
77
|
position: relative;
|
|
72
|
-
font-size: 1.25rem;
|
|
73
78
|
align-items: center;
|
|
74
79
|
flex-shrink: 0;
|
|
75
|
-
line-height: 1;
|
|
76
|
-
user-select: none;
|
|
77
|
-
border-radius: 50%;
|
|
78
80
|
justify-content: center;
|
|
79
|
-
|
|
81
|
+
user-select: none;
|
|
82
|
+
|
|
83
|
+
font-family: var(--profile-avatar-font-family);
|
|
84
|
+
font-size: var(--profile-avatar-font-size);
|
|
85
|
+
line-height: var(--profile-avatar-line-height);
|
|
86
|
+
font-weight: var(--profile-avatar-font-weight);
|
|
87
|
+
|
|
88
|
+
border-radius: var(--profile-avatar-border-radius);
|
|
89
|
+
margin-left: var(--profile-avatar-margin-left);
|
|
80
90
|
|
|
81
91
|
${({ background }) => css`
|
|
82
92
|
background-color: ${background};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
|
|
4
|
-
import { Link } from '@portal/Link';
|
|
5
4
|
import { Profile } from '@theme/Profile/Profile';
|
|
6
5
|
import { Tooltip } from '@theme/Tooltip/Tooltip';
|
|
7
|
-
|
|
6
|
+
|
|
7
|
+
import { UserProfileMenu } from './UserProfileMenu';
|
|
8
8
|
|
|
9
9
|
export interface UserProfileProps {
|
|
10
10
|
userInfo: {
|
|
@@ -13,7 +13,7 @@ export interface UserProfileProps {
|
|
|
13
13
|
picture: string;
|
|
14
14
|
logoutDisabled?: boolean;
|
|
15
15
|
};
|
|
16
|
-
handleLogout: (
|
|
16
|
+
handleLogout: () => void;
|
|
17
17
|
hasDeveloperOnboarding?: boolean;
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -24,10 +24,6 @@ export function UserProfile({
|
|
|
24
24
|
}: UserProfileProps): JSX.Element {
|
|
25
25
|
const [isOpened, setIsOpened] = useState<boolean>(false);
|
|
26
26
|
|
|
27
|
-
const { userProfile: userProfileSettings } = useThemeConfig();
|
|
28
|
-
|
|
29
|
-
const logoutRedirect = userProfileSettings?.logoutRedirect || '/';
|
|
30
|
-
|
|
31
27
|
return (
|
|
32
28
|
<StyledTooltip
|
|
33
29
|
isOpen={isOpened}
|
|
@@ -36,16 +32,11 @@ export function UserProfile({
|
|
|
36
32
|
placement="bottom"
|
|
37
33
|
width="100%"
|
|
38
34
|
tip={
|
|
39
|
-
<
|
|
40
|
-
{hasDeveloperOnboarding
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
) : null}
|
|
45
|
-
<StyledLi onClick={() => handleLogout(logoutRedirect)}>
|
|
46
|
-
{userProfileSettings?.logoutLabel || 'Log out'}
|
|
47
|
-
</StyledLi>
|
|
48
|
-
</StyledUl>
|
|
35
|
+
<UserProfileMenu
|
|
36
|
+
hasDeveloperOnboarding={hasDeveloperOnboarding}
|
|
37
|
+
handleLogout={handleLogout}
|
|
38
|
+
setIsOpened={setIsOpened}
|
|
39
|
+
/>
|
|
49
40
|
}
|
|
50
41
|
>
|
|
51
42
|
<Profile
|
|
@@ -62,33 +53,3 @@ const StyledTooltip = styled(Tooltip)`
|
|
|
62
53
|
padding: 0;
|
|
63
54
|
}
|
|
64
55
|
`;
|
|
65
|
-
|
|
66
|
-
const StyledUl = styled.ul`
|
|
67
|
-
margin: 0;
|
|
68
|
-
padding: 0;
|
|
69
|
-
list-style: none;
|
|
70
|
-
text-align: left;
|
|
71
|
-
background-color: var(--search-modal-background);
|
|
72
|
-
color: var(--search-modal-text-color);
|
|
73
|
-
min-width: 100px;
|
|
74
|
-
a {
|
|
75
|
-
text-decoration: none;
|
|
76
|
-
&:hover {
|
|
77
|
-
color: inherit;
|
|
78
|
-
}
|
|
79
|
-
&:visited {
|
|
80
|
-
color: inherit;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
`;
|
|
84
|
-
|
|
85
|
-
const StyledLi = styled.li`
|
|
86
|
-
cursor: pointer;
|
|
87
|
-
font-size: 16px;
|
|
88
|
-
list-style: none;
|
|
89
|
-
padding: 15px 20px;
|
|
90
|
-
transition: background-color 0.25s ease 0s;
|
|
91
|
-
&:hover {
|
|
92
|
-
background-color: rgba(0, 0, 0, 0.1);
|
|
93
|
-
}
|
|
94
|
-
`;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled, { css } from 'styled-components';
|
|
3
|
+
|
|
4
|
+
import { Link } from '@portal/Link';
|
|
5
|
+
import { useThemeConfig } from '@theme/hooks';
|
|
6
|
+
|
|
7
|
+
interface UserProfileMenuProps {
|
|
8
|
+
setIsOpened: (isOpen: boolean) => void;
|
|
9
|
+
handleLogout: () => void;
|
|
10
|
+
hasDeveloperOnboarding: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function UserProfileMenu({
|
|
14
|
+
hasDeveloperOnboarding,
|
|
15
|
+
setIsOpened,
|
|
16
|
+
handleLogout,
|
|
17
|
+
}: UserProfileMenuProps): JSX.Element {
|
|
18
|
+
const { userProfile } = useThemeConfig();
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<>
|
|
22
|
+
<StyledUl onClick={() => setIsOpened(false)}>
|
|
23
|
+
{hasDeveloperOnboarding ? (
|
|
24
|
+
<Link to="/apps">
|
|
25
|
+
<StyledLi>My Apps</StyledLi>
|
|
26
|
+
</Link>
|
|
27
|
+
) : null}
|
|
28
|
+
|
|
29
|
+
{userProfile?.menu?.map((item) => (
|
|
30
|
+
<Link external={item.external} key={item.label} to={item.link || ''}>
|
|
31
|
+
<StyledLi separatorLine={item?.separatorLine}>{item.label}</StyledLi>
|
|
32
|
+
</Link>
|
|
33
|
+
))}
|
|
34
|
+
|
|
35
|
+
<StyledLi onClick={() => handleLogout()}>{userProfile?.logoutLabel || 'Log out'}</StyledLi>
|
|
36
|
+
</StyledUl>
|
|
37
|
+
</>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const StyledUl = styled.ul`
|
|
42
|
+
margin: var(--profile-menu-margin);
|
|
43
|
+
padding: var(--profile-menu-padding);
|
|
44
|
+
list-style: none;
|
|
45
|
+
background-color: var(--profile-menu-background-color);
|
|
46
|
+
min-width: 100px;
|
|
47
|
+
a {
|
|
48
|
+
text-decoration: none;
|
|
49
|
+
}
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
const StyledLi = styled.li<{ separatorLine?: boolean }>`
|
|
53
|
+
cursor: pointer;
|
|
54
|
+
font-size: var(--profile-menu-item-font-size);
|
|
55
|
+
font-family: var(--profile-menu-item-font-family);
|
|
56
|
+
font-weight: var(--profile-menu-item-font-weight);
|
|
57
|
+
line-height: var(--profile-menu-item-line-height);
|
|
58
|
+
color: var(--profile-menu-item-text-color);
|
|
59
|
+
text-align: var(--profile-menu-item-text-align);
|
|
60
|
+
|
|
61
|
+
list-style: none;
|
|
62
|
+
|
|
63
|
+
padding: var(--profile-menu-item-padding-vertical) var(--profile-menu-item-padding-horizontal);
|
|
64
|
+
|
|
65
|
+
transition: background-color 0.25s ease 0s;
|
|
66
|
+
|
|
67
|
+
&:hover {
|
|
68
|
+
color: var(--profile-menu-item-hover-text-color);
|
|
69
|
+
background-color: var(--profile-menu-item-hover-background-color);
|
|
70
|
+
text-decoration: var(--profile-menu-item-hover-text-decoration);
|
|
71
|
+
}
|
|
72
|
+
&:active {
|
|
73
|
+
color: var(--profile-menu-item-active-text-color);
|
|
74
|
+
background-color: var(--profile-menu-item-active-background-color);
|
|
75
|
+
text-decoration: var(--profile-menu-item-active-text-decoration);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
${({ separatorLine }) =>
|
|
79
|
+
separatorLine &&
|
|
80
|
+
css`
|
|
81
|
+
border-bottom: 1px solid var(--profile-menu-item-separator-line-color);
|
|
82
|
+
`}
|
|
83
|
+
`;
|
package/src/config.ts
CHANGED
|
@@ -215,7 +215,7 @@ export const ThemeConfig = z
|
|
|
215
215
|
.object({
|
|
216
216
|
loginLabel: z.string().default('Login').optional(),
|
|
217
217
|
logoutLabel: z.string().default('Logout').optional(),
|
|
218
|
-
|
|
218
|
+
menu: z.array(z.any()).optional(), // should be same as navbar items type
|
|
219
219
|
})
|
|
220
220
|
.extend(HideConfig.shape)
|
|
221
221
|
.optional()
|
package/src/globalStyle.ts
CHANGED
|
@@ -1965,6 +1965,67 @@ const pages = css`
|
|
|
1965
1965
|
// @tokens End
|
|
1966
1966
|
`
|
|
1967
1967
|
|
|
1968
|
+
const userProfile = css`
|
|
1969
|
+
|
|
1970
|
+
/**
|
|
1971
|
+
* @tokens User Profile
|
|
1972
|
+
*/
|
|
1973
|
+
|
|
1974
|
+
--profile-name-font-family: var(--navbar-item-font-family); // @presenter FontFamily
|
|
1975
|
+
--profile-name-font-size: var(--navbar-item-font-size); // @presenter FontSize
|
|
1976
|
+
--profile-name-font-weight: var(--font-weight-regular); // @presenter FontWeight
|
|
1977
|
+
--profile-name-line-height: var(--line-height-base); // @presenter LineHeight
|
|
1978
|
+
--profile-name-text-color: var(--navbar-text-color); // @presenter Color
|
|
1979
|
+
|
|
1980
|
+
--profile-name-padding-horizontal: 0; // @presenter Spacing
|
|
1981
|
+
--profile-name-padding-vertical: 0; // @presenter Spacing
|
|
1982
|
+
--profile-name-margin-horizontal: 0; // @presenter Spacing
|
|
1983
|
+
|
|
1984
|
+
--profile-avatar-width: 40px;
|
|
1985
|
+
--profile-avatar-height: 40px;
|
|
1986
|
+
--profile-avatar-border-radius: 50%; // @presenter BorderRadius
|
|
1987
|
+
|
|
1988
|
+
--profile-avatar-font-family: var(--navbar-item-font-family); // @presenter FontFamily
|
|
1989
|
+
--profile-avatar-font-size: var(--navbar-item-font-size) // @presenter FontSize
|
|
1990
|
+
--profile-avatar-font-weight: var(--font-weight-regular); // @presenter FontWeight
|
|
1991
|
+
--profile-avatar-line-height: var(--line-height-base); // @presenter LineHeight
|
|
1992
|
+
|
|
1993
|
+
--profile-avatar-margin-left: 16px; // @presenter Spacing
|
|
1994
|
+
--profile-avatar-padding-vertical: 16px; // @presenter Spacing
|
|
1995
|
+
--profile-avatar-padding-horizontal: 16px; // @presenter Spacing
|
|
1996
|
+
|
|
1997
|
+
|
|
1998
|
+
/**
|
|
1999
|
+
* @tokens User Profile Menu
|
|
2000
|
+
*/
|
|
2001
|
+
|
|
2002
|
+
--profile-menu-background-color: var(--background-color); // @presenter Color
|
|
2003
|
+
--profile-menu-padding: 0px; // @presenter Spacing
|
|
2004
|
+
--profile-menu-margin: 0px; // @presenter Spacing
|
|
2005
|
+
|
|
2006
|
+
--profile-menu-item-font-family: var(--navbar-item-font-family); // @presenter FontFamily
|
|
2007
|
+
--profile-menu-item-text-color: var(--text-color); // @presenter Color
|
|
2008
|
+
--profile-menu-item-font-size: var(--navbar-item-font-size); // @presenter FontSize
|
|
2009
|
+
--profile-menu-item-font-weight: var(--font-weight-regular); // @presenter FontWeight
|
|
2010
|
+
--profile-menu-item-line-height: var(--line-height-base); // @presenter LineHeight
|
|
2011
|
+
--profile-menu-item-text-align: left;
|
|
2012
|
+
|
|
2013
|
+
--profile-menu-item-padding-horizontal: 15px; // @presenter Spacing
|
|
2014
|
+
--profile-menu-item-padding-vertical: 20px; // @presenter Spacing
|
|
2015
|
+
|
|
2016
|
+
--profile-menu-item-hover-background-color: var(--color-primary-300); // @presenter Color
|
|
2017
|
+
--profile-menu-item-active-background-color: var(--color-primary-300); // @presenter Color
|
|
2018
|
+
--profile-menu-item-hover-text-color: var(--navbar-text-color); // @presenter Color
|
|
2019
|
+
--profile-menu-item-hover-text-decoration: none;
|
|
2020
|
+
--profile-menu-item-active-text-color: var(--navbar-text-color); // @presenter Color
|
|
2021
|
+
--profile-menu-item-active-text-decoration: none;
|
|
2022
|
+
|
|
2023
|
+
--profile-menu-item-separator-line-color: var(--border-color); // @presenter Color
|
|
2024
|
+
|
|
2025
|
+
// @tokens End
|
|
2026
|
+
|
|
2027
|
+
`;
|
|
2028
|
+
|
|
1968
2029
|
const modal = css`
|
|
1969
2030
|
body:has(.modal) {
|
|
1970
2031
|
overflow: hidden;
|
|
@@ -2005,6 +2066,7 @@ export const styles = css`
|
|
|
2005
2066
|
${loadProgressBar}
|
|
2006
2067
|
${pages}
|
|
2007
2068
|
${modal}
|
|
2069
|
+
${userProfile}
|
|
2008
2070
|
|
|
2009
2071
|
--api-onboarding-table-text-color: #4e5356;
|
|
2010
2072
|
--api-catalog-card-min-width: 250px;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useEffect, useState, useMemo } from 'react';
|
|
2
2
|
import throttle from 'lodash.throttle';
|
|
3
3
|
|
|
4
|
-
import type { Location } from '
|
|
4
|
+
import type { Location } from 'react-router-dom';
|
|
5
5
|
|
|
6
6
|
import { useNavbarHeight } from '@theme/hooks/useNavbarHeight';
|
|
7
7
|
|
|
@@ -10,9 +10,12 @@ export type UseActiveSectionIdReturnType = string;
|
|
|
10
10
|
export function useActiveSectionId(
|
|
11
11
|
location: Location,
|
|
12
12
|
hasOverviewPage = false,
|
|
13
|
+
withNavbar = true,
|
|
13
14
|
): UseActiveSectionIdReturnType {
|
|
14
15
|
const [itemId, setItemId] = useState<string>('');
|
|
15
16
|
const navbarHeight = useNavbarHeight(location);
|
|
17
|
+
const heightOffset = (withNavbar ? navbarHeight : 0) + 5; // use small padding 5px to account for rounding;
|
|
18
|
+
|
|
16
19
|
const scrollListener = useMemo(
|
|
17
20
|
() =>
|
|
18
21
|
throttle(() => {
|
|
@@ -24,8 +27,7 @@ export function useActiveSectionId(
|
|
|
24
27
|
for (let i = 0; i < sections.length; i++) {
|
|
25
28
|
const section = sections[i];
|
|
26
29
|
const rect = section.getBoundingClientRect();
|
|
27
|
-
if (rect.y <
|
|
28
|
-
// use small padding 5px to account for rounding
|
|
30
|
+
if (rect.y < heightOffset && rect.bottom > heightOffset) {
|
|
29
31
|
setItemId(section.getAttribute('data-section-id') || '');
|
|
30
32
|
return;
|
|
31
33
|
}
|
|
@@ -34,7 +36,7 @@ export function useActiveSectionId(
|
|
|
34
36
|
setItemId('');
|
|
35
37
|
}
|
|
36
38
|
}, 150),
|
|
37
|
-
[
|
|
39
|
+
[heightOffset, hasOverviewPage],
|
|
38
40
|
);
|
|
39
41
|
|
|
40
42
|
useEffect(() => {
|
|
@@ -46,7 +48,7 @@ export function useActiveSectionId(
|
|
|
46
48
|
return () => {
|
|
47
49
|
window.removeEventListener('scroll', scrollListener);
|
|
48
50
|
};
|
|
49
|
-
}, [location,
|
|
51
|
+
}, [location, heightOffset, scrollListener]);
|
|
50
52
|
|
|
51
53
|
return itemId;
|
|
52
54
|
}
|
|
@@ -8,7 +8,7 @@ export type FilteredCatalog = {
|
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
export type Filter = {
|
|
11
|
-
type?: 'select' | 'checkboxes';
|
|
11
|
+
type?: 'select' | 'checkboxes' | 'date-range';
|
|
12
12
|
title: string;
|
|
13
13
|
property: string;
|
|
14
14
|
parentFilter?: string;
|
|
@@ -44,6 +44,7 @@ export type ResolvedFilter = Omit<Filter, 'options'> & {
|
|
|
44
44
|
selectOption: (option: string) => void;
|
|
45
45
|
parentUsed: boolean;
|
|
46
46
|
selectedOptions: Set<string>;
|
|
47
|
+
range?: {from?: string; to?: string};
|
|
47
48
|
};
|
|
48
49
|
|
|
49
50
|
export type CatalogItem = {
|
|
@@ -51,5 +52,6 @@ export type CatalogItem = {
|
|
|
51
52
|
link: string;
|
|
52
53
|
description?: string;
|
|
53
54
|
image?: string;
|
|
55
|
+
docsLink?: string;
|
|
54
56
|
[k: string]: unknown;
|
|
55
57
|
};
|