@redocly/theme 0.1.31 → 0.1.32

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.
@@ -4,7 +4,8 @@ interface NavbarProps {
4
4
  menu: ResolvedConfigLinks;
5
5
  logo: React.ReactNode;
6
6
  search: React.ReactNode;
7
+ profile?: React.ReactNode;
7
8
  }
8
- export declare function Navbar({ menu, logo, search }: NavbarProps): JSX.Element | null;
9
+ export declare function Navbar({ menu, logo, search, profile }: NavbarProps): JSX.Element | null;
9
10
  export declare const NavbarContainer: import("styled-components").StyledComponent<"nav", any, {}, never>;
10
11
  export {};
package/Navbar/Navbar.js CHANGED
@@ -33,7 +33,7 @@ var useMobileMenu_1 = require("../hooks/useMobileMenu");
33
33
  var MobileNavbarMenuButton_1 = require("../Navbar/MobileNavbarMenuButton");
34
34
  var MobileNavbarMenu_1 = require("../Navbar/MobileNavbarMenu");
35
35
  function Navbar(_a) {
36
- var menu = _a.menu, logo = _a.logo, search = _a.search;
36
+ var menu = _a.menu, logo = _a.logo, search = _a.search, profile = _a.profile;
37
37
  var _b = __read((0, useMobileMenu_1.useMobileMenu)(false), 2), isOpen = _b[0], setIsOpen = _b[1];
38
38
  var _c = (0, hooks_1.useThemeSettings)(constants_1.DEFAULT_THEME_NAME), searchSettings = _c.search, navbar = _c.navbar;
39
39
  var hideSearch = (searchSettings === null || searchSettings === void 0 ? void 0 : searchSettings.hide) || ((searchSettings === null || searchSettings === void 0 ? void 0 : searchSettings.placement) && (searchSettings === null || searchSettings === void 0 ? void 0 : searchSettings.placement) !== 'navbar');
@@ -47,7 +47,8 @@ function Navbar(_a) {
47
47
  isOpen && react_1.default.createElement(MobileNavbarMenu_1.MobileNavbarMenu, { closeMenu: closeMobileMenu, menuItems: menu }),
48
48
  logo,
49
49
  react_1.default.createElement(Navbar_1.NavbarMenu, { menuItems: menu }),
50
- hideSearch ? null : search));
50
+ hideSearch ? null : search,
51
+ profile));
51
52
  }
52
53
  exports.Navbar = Navbar;
53
54
  exports.NavbarContainer = styled_components_1.default.nav(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n height: var(--navbar-height);\n box-sizing: border-box;\n display: flex;\n color: var(--navbar-text-color);\n align-items: center;\n justify-content: space-between;\n flex-shrink: 0;\n\n font-size: 0.875rem;\n position: sticky;\n top: 0;\n z-index: 200;\n padding: 10px var(--sidebar-margin-left);\n background: var(--navbar-background-color);\n font-family: var(--h-font-family);\n\n ", " {\n padding: 10px var(--sidebar-margin-left);\n font-size: 1rem;\n }\n\n ", " {\n background: transparent;\n display: none;\n > :not(a, img) {\n display: none !important;\n }\n img {\n padding: 0;\n margin: 0;\n }\n }\n"], ["\n height: var(--navbar-height);\n box-sizing: border-box;\n display: flex;\n color: var(--navbar-text-color);\n align-items: center;\n justify-content: space-between;\n flex-shrink: 0;\n\n font-size: 0.875rem;\n position: sticky;\n top: 0;\n z-index: 200;\n padding: 10px var(--sidebar-margin-left);\n background: var(--navbar-background-color);\n font-family: var(--h-font-family);\n\n ", " {\n padding: 10px var(--sidebar-margin-left);\n font-size: 1rem;\n }\n\n ", " {\n background: transparent;\n display: none;\n > :not(a, img) {\n display: none !important;\n }\n img {\n padding: 0;\n margin: 0;\n }\n }\n"])), function (_a) {
@@ -31,7 +31,6 @@ exports.Profile = void 0;
31
31
  var react_1 = __importStar(require("react"));
32
32
  var styled_components_1 = __importStar(require("styled-components"));
33
33
  var utils_1 = require("../utils");
34
- var RANDOM_BG_COLOR = (0, utils_1.getRandomColor)();
35
34
  function ProfileComponent(_a) {
36
35
  var _b;
37
36
  var name = _a.name, imageUrl = _a.imageUrl, onClick = _a.onClick, color = _a.color;
@@ -44,14 +43,14 @@ function ProfileComponent(_a) {
44
43
  var avatarLetters = "".concat(name.charAt(0).toUpperCase()).concat(((_b = name.split(' ')[1]) === null || _b === void 0 ? void 0 : _b.charAt(0).toUpperCase()) || '');
45
44
  return (react_1.default.createElement(ProfileWrapper, { onClick: onClick },
46
45
  react_1.default.createElement(StyledUserName, { "data-cy": "user-name", color: color }, name),
47
- react_1.default.createElement(AvatarWrapper, { background: RANDOM_BG_COLOR },
46
+ react_1.default.createElement(AvatarWrapper, { background: (0, utils_1.stringToHslColor)(name) },
48
47
  react_1.default.createElement("span", null, avatarLetters))));
49
48
  }
50
49
  exports.Profile = (0, react_1.memo)(ProfileComponent);
51
- var ProfileWrapper = styled_components_1.default.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n display: flex;\n align-items: center;\n cursor: pointer;\n width: auto;\n"], ["\n display: flex;\n align-items: center;\n cursor: pointer;\n width: auto;\n"])));
50
+ var ProfileWrapper = styled_components_1.default.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n display: flex;\n align-items: center;\n cursor: pointer;\n width: auto;\n padding-left: calc(var(--sidebar-spacing-horizontal) * 2);\n"], ["\n display: flex;\n align-items: center;\n cursor: pointer;\n width: auto;\n padding-left: calc(var(--sidebar-spacing-horizontal) * 2);\n"])));
52
51
  var StyledUserName = styled_components_1.default.span(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n color: ", ";\n"], ["\n color: ", ";\n"])), function (_a) {
53
52
  var color = _a.color;
54
- return color || 'var(--color-content)';
53
+ return color || 'var(--navbar-text-color)';
55
54
  });
56
55
  var AvatarWrapper = styled_components_1.default.div(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n width: 40px;\n height: 40px;\n display: flex;\n overflow: hidden;\n position: relative;\n font-size: 1.25rem;\n align-items: center;\n flex-shrink: 0;\n line-height: 1;\n user-select: none;\n border-radius: 50%;\n justify-content: center;\n margin-left: 16px;\n\n ", "\n\n & > img {\n color: transparent;\n width: 100%;\n height: 100%;\n object-fit: cover;\n text-align: center;\n text-indent: 10000px;\n }\n"], ["\n width: 40px;\n height: 40px;\n display: flex;\n overflow: hidden;\n position: relative;\n font-size: 1.25rem;\n align-items: center;\n flex-shrink: 0;\n line-height: 1;\n user-select: none;\n border-radius: 50%;\n justify-content: center;\n margin-left: 16px;\n\n ", "\n\n & > img {\n color: transparent;\n width: 100%;\n height: 100%;\n object-fit: cover;\n text-align: center;\n text-indent: 10000px;\n }\n"])), function (_a) {
57
56
  var background = _a.background;
@@ -76,7 +76,7 @@ function TableOfContent(props) {
76
76
  return null;
77
77
  }
78
78
  var href = '#' + heading.id;
79
- return (react_1.default.createElement(MenuItem, { key: href, href: href, depth: heading.depth || 0, className: activeHeadingId === heading.id ? 'active' : '', dangerouslySetInnerHTML: { __html: heading.value || '' }, "data-cy": "toc-".concat(heading.value) }));
79
+ return (react_1.default.createElement(MenuItem, { key: href + idx, href: href, depth: heading.depth || 0, className: activeHeadingId === heading.id ? 'active' : '', dangerouslySetInnerHTML: { __html: heading.value || '' }, "data-cy": "toc-".concat(heading.value) }));
80
80
  }))))));
81
81
  }
82
82
  exports.TableOfContent = TableOfContent;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.1.31",
3
+ "version": "0.1.32",
4
4
  "description": "Shared UI components",
5
5
  "author": "team@redocly.com",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -13,9 +13,10 @@ interface NavbarProps {
13
13
  menu: ResolvedConfigLinks;
14
14
  logo: React.ReactNode;
15
15
  search: React.ReactNode;
16
+ profile?: React.ReactNode;
16
17
  }
17
18
 
18
- export function Navbar({ menu, logo, search }: NavbarProps): JSX.Element | null {
19
+ export function Navbar({ menu, logo, search, profile }: NavbarProps): JSX.Element | null {
19
20
  const [isOpen, setIsOpen] = useMobileMenu(false);
20
21
  const { search: searchSettings, navbar } = useThemeSettings(DEFAULT_THEME_NAME);
21
22
  const hideSearch =
@@ -35,6 +36,7 @@ export function Navbar({ menu, logo, search }: NavbarProps): JSX.Element | null
35
36
  {logo}
36
37
  <NavbarMenu menuItems={menu} />
37
38
  {hideSearch ? null : search}
39
+ {profile}
38
40
  </NavbarContainer>
39
41
  );
40
42
  }
@@ -1,7 +1,7 @@
1
1
  import React, { memo } from 'react';
2
2
  import styled, { css } from 'styled-components';
3
3
 
4
- import { getRandomColor } from '@theme/utils';
4
+ import { stringToHslColor } from '@theme/utils';
5
5
 
6
6
  export interface ProfileProps {
7
7
  name: string;
@@ -10,8 +10,6 @@ export interface ProfileProps {
10
10
  onClick?: () => void;
11
11
  }
12
12
 
13
- const RANDOM_BG_COLOR: string = getRandomColor();
14
-
15
13
  function ProfileComponent({ name, imageUrl, onClick, color }: ProfileProps): JSX.Element {
16
14
  if (imageUrl) {
17
15
  return (
@@ -37,7 +35,7 @@ function ProfileComponent({ name, imageUrl, onClick, color }: ProfileProps): JSX
37
35
  <StyledUserName data-cy="user-name" color={color}>
38
36
  {name}
39
37
  </StyledUserName>
40
- <AvatarWrapper background={RANDOM_BG_COLOR}>
38
+ <AvatarWrapper background={stringToHslColor(name)}>
41
39
  <span>{avatarLetters}</span>
42
40
  </AvatarWrapper>
43
41
  </ProfileWrapper>
@@ -51,10 +49,11 @@ const ProfileWrapper = styled.div`
51
49
  align-items: center;
52
50
  cursor: pointer;
53
51
  width: auto;
52
+ padding-left: calc(var(--sidebar-spacing-horizontal) * 2);
54
53
  `;
55
54
 
56
55
  const StyledUserName = styled.span`
57
- color: ${({ color }) => color || 'var(--color-content)'};
56
+ color: ${({ color }) => color || 'var(--navbar-text-color)'};
58
57
  `;
59
58
 
60
59
  const AvatarWrapper = styled.div<{ background?: string }>`
@@ -61,7 +61,7 @@ export function TableOfContent(props: TableOfContentProps): JSX.Element | null {
61
61
  const href = '#' + heading.id;
62
62
  return (
63
63
  <MenuItem
64
- key={href}
64
+ key={href + idx}
65
65
  href={href}
66
66
  depth={heading.depth || 0}
67
67
  className={activeHeadingId === heading.id ? 'active' : ''}
@@ -1,9 +1,12 @@
1
- export const getRandomNumber = (limit: number): number => Math.floor(Math.random() * limit);
1
+ export function stringToHslColor(value: string): string {
2
+ const s = 30;
3
+ const l = 80;
4
+ let hash = 0;
2
5
 
3
- export function getRandomColor(): string {
4
- const h = getRandomNumber(360);
5
- const s = getRandomNumber(100);
6
- const l = getRandomNumber(100);
6
+ for (let i = 0; i < value.length; i++) {
7
+ hash = value.charCodeAt(i) + ((hash << 5) - hash);
8
+ }
7
9
 
8
- return `hsl(${h}deg, ${s}%, ${l}%)`;
10
+ const h = hash % 360;
11
+ return `hsl(${h}, ${s}%, ${l}%)`;
9
12
  }
package/utils/color.d.ts CHANGED
@@ -1,2 +1 @@
1
- export declare const getRandomNumber: (limit: number) => number;
2
- export declare function getRandomColor(): string;
1
+ export declare function stringToHslColor(value: string): string;
package/utils/color.js CHANGED
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getRandomColor = exports.getRandomNumber = void 0;
4
- var getRandomNumber = function (limit) { return Math.floor(Math.random() * limit); };
5
- exports.getRandomNumber = getRandomNumber;
6
- function getRandomColor() {
7
- var h = (0, exports.getRandomNumber)(360);
8
- var s = (0, exports.getRandomNumber)(100);
9
- var l = (0, exports.getRandomNumber)(100);
10
- return "hsl(".concat(h, "deg, ").concat(s, "%, ").concat(l, "%)");
3
+ exports.stringToHslColor = void 0;
4
+ function stringToHslColor(value) {
5
+ var s = 30;
6
+ var l = 80;
7
+ var hash = 0;
8
+ for (var i = 0; i < value.length; i++) {
9
+ hash = value.charCodeAt(i) + ((hash << 5) - hash);
10
+ }
11
+ var h = hash % 360;
12
+ return "hsl(".concat(h, ", ").concat(s, "%, ").concat(l, "%)");
11
13
  }
12
- exports.getRandomColor = getRandomColor;
14
+ exports.stringToHslColor = stringToHslColor;