@cloud-ru/uikit-product-site-header 1.2.2 → 1.3.1
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/CHANGELOG.md +22 -0
- package/dist/cjs/components/HeaderItems/HeaderItem.js +2 -2
- package/dist/cjs/components/HeaderItems/types.d.ts +3 -0
- package/dist/cjs/helperComponents/Icon/Icon.d.ts +15 -0
- package/dist/cjs/helperComponents/Icon/Icon.js +17 -0
- package/dist/cjs/helperComponents/Icon/index.d.ts +1 -0
- package/dist/cjs/helperComponents/Icon/index.js +17 -0
- package/dist/cjs/helperComponents/Icon/styles.module.css +45 -0
- package/dist/cjs/helperComponents/LinkItemHeader/LinkItemHeader.d.ts +3 -1
- package/dist/cjs/helperComponents/LinkItemHeader/LinkItemHeader.js +5 -4
- package/dist/cjs/helperComponents/LinkItemHeader/styles.module.css +3 -0
- package/dist/cjs/helperComponents/MoreButton/MoreButton.js +1 -1
- package/dist/esm/components/HeaderItems/HeaderItem.js +2 -2
- package/dist/esm/components/HeaderItems/types.d.ts +3 -0
- package/dist/esm/helperComponents/Icon/Icon.d.ts +15 -0
- package/dist/esm/helperComponents/Icon/Icon.js +11 -0
- package/dist/esm/helperComponents/Icon/index.d.ts +1 -0
- package/dist/esm/helperComponents/Icon/index.js +1 -0
- package/dist/esm/helperComponents/Icon/styles.module.css +45 -0
- package/dist/esm/helperComponents/LinkItemHeader/LinkItemHeader.d.ts +3 -1
- package/dist/esm/helperComponents/LinkItemHeader/LinkItemHeader.js +6 -5
- package/dist/esm/helperComponents/LinkItemHeader/styles.module.css +3 -0
- package/dist/esm/helperComponents/MoreButton/MoreButton.js +1 -1
- package/package.json +5 -5
- package/src/components/HeaderItems/HeaderItem.tsx +2 -0
- package/src/components/HeaderItems/types.ts +4 -0
- package/src/helperComponents/Icon/Icon.tsx +31 -0
- package/src/helperComponents/Icon/index.ts +1 -0
- package/src/helperComponents/Icon/styles.module.scss +56 -0
- package/src/helperComponents/LinkItemHeader/LinkItemHeader.tsx +5 -1
- package/src/helperComponents/LinkItemHeader/styles.module.scss +3 -0
- package/src/helperComponents/MoreButton/MoreButton.tsx +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,28 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## 1.3.1 (2026-02-18)
|
|
7
|
+
|
|
8
|
+
### Only dependencies have been changed
|
|
9
|
+
* [@cloud-ru/uikit-product-button-predefined@1.1.6]($PUBLIC_PROJECT_URL/blob/master/packages/button-predefined/CHANGELOG.md)
|
|
10
|
+
* [@cloud-ru/uikit-product-icons@17.0.4]($PUBLIC_PROJECT_URL/blob/master/packages/icons/CHANGELOG.md)
|
|
11
|
+
* [@cloud-ru/uikit-product-mobile-modal@2.0.5]($PUBLIC_PROJECT_URL/blob/master/packages/mobile-modal/CHANGELOG.md)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# 1.3.0 (2026-02-17)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* **SITE-10702:** add icon for header menu items ([e4b57e1](https://github.com/cloud-ru-tech/uikit-product/commit/e4b57e19cd9d0647f158a4431d46c9cb83fa958f))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
6
28
|
## 1.2.2 (2026-02-16)
|
|
7
29
|
|
|
8
30
|
|
|
@@ -68,7 +68,7 @@ function HeaderItems({ linkItems, isMobileTabletView, activeLinkItemId }) {
|
|
|
68
68
|
if (!linkItems || isMobileTabletView)
|
|
69
69
|
return null;
|
|
70
70
|
const isVisibleEmpty = visibleItems.length === 0;
|
|
71
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.wrapper, children: [(0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.linkItemsContainer, styles_module_scss_1.default.hiddenRow), ref: hiddenRowElementRef, children: linkItems.map((linkItem, index) => ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: (0, classnames_1.default)(styles_module_scss_1.default.lastItemContainer, linkItem.className), ref: setItemElement(linkItem, index) }, linkItem.dataAttributes, { children: (0, jsx_runtime_1.jsx)(helperComponents_1.LinkItemHeader, { label: linkItem.label, target: linkItem.target, href: linkItem.href, onClick: linkItem.onClick }) }), linkItem.id))) }), (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.linkItemsContainer, {
|
|
71
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.wrapper, children: [(0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.linkItemsContainer, styles_module_scss_1.default.hiddenRow), ref: hiddenRowElementRef, children: linkItems.map((linkItem, index) => ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: (0, classnames_1.default)(styles_module_scss_1.default.lastItemContainer, linkItem.className), ref: setItemElement(linkItem, index) }, linkItem.dataAttributes, { children: (0, jsx_runtime_1.jsx)(helperComponents_1.LinkItemHeader, { label: linkItem.label, target: linkItem.target, href: linkItem.href, onClick: linkItem.onClick, icon: linkItem.icon }) }), linkItem.id))) }), (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.linkItemsContainer, {
|
|
72
72
|
[styles_module_scss_1.default.linkItemsFirstViewContainer]: isVisibleEmpty,
|
|
73
|
-
}), children: [(isVisibleEmpty ? linkItems : visibleItems).map(linkItem => ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: (0, classnames_1.default)(styles_module_scss_1.default.lastItemContainer, linkItem.className) }, linkItem.dataAttributes, { children: (0, jsx_runtime_1.jsx)(helperComponents_1.LinkItemHeader, { label: linkItem.label, href: linkItem.href, onClick: linkItem.onClick, active: activeLinkItemId === linkItem.id }) }), linkItem.id))), hiddenItems.length > 0 && (0, jsx_runtime_1.jsx)(helperComponents_1.MoreButton, { linkItemsArray: hiddenItems, activeItemId: activeLinkItemId })] })] }));
|
|
73
|
+
}), children: [(isVisibleEmpty ? linkItems : visibleItems).map(linkItem => ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: (0, classnames_1.default)(styles_module_scss_1.default.lastItemContainer, linkItem.className) }, linkItem.dataAttributes, { children: (0, jsx_runtime_1.jsx)(helperComponents_1.LinkItemHeader, { label: linkItem.label, href: linkItem.href, onClick: linkItem.onClick, active: activeLinkItemId === linkItem.id, icon: linkItem.icon }) }), linkItem.id))), hiddenItems.length > 0 && (0, jsx_runtime_1.jsx)(helperComponents_1.MoreButton, { linkItemsArray: hiddenItems, activeItemId: activeLinkItemId })] })] }));
|
|
74
74
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IconProps } from '../../helperComponents/Icon';
|
|
1
2
|
export type LinkItem = {
|
|
2
3
|
/** id Элемента */
|
|
3
4
|
id: string;
|
|
@@ -15,4 +16,6 @@ export type LinkItem = {
|
|
|
15
16
|
dataAttributes?: {
|
|
16
17
|
[key: string]: string;
|
|
17
18
|
};
|
|
19
|
+
/** Иконка */
|
|
20
|
+
icon?: IconProps['icon'] | null;
|
|
18
21
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { JSXElementConstructor, ReactNode } from 'react';
|
|
2
|
+
export type IconElement = JSXElementConstructor<{
|
|
3
|
+
size?: number;
|
|
4
|
+
className?: string;
|
|
5
|
+
}>;
|
|
6
|
+
export type IconProps = {
|
|
7
|
+
icon: ReactNode | IconElement | {
|
|
8
|
+
src: string;
|
|
9
|
+
alt?: string;
|
|
10
|
+
};
|
|
11
|
+
size: 's' | 'm' | 'l';
|
|
12
|
+
'data-test-id'?: string;
|
|
13
|
+
decor?: boolean;
|
|
14
|
+
};
|
|
15
|
+
export declare function Icon({ icon: Icon, size, 'data-test-id': dataTestId, decor }: IconProps): string | number | boolean | Iterable<ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Icon = Icon;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
|
|
9
|
+
const isElementConstructor = (icon) => typeof icon === 'object' && icon !== null && 'render' in icon;
|
|
10
|
+
function Icon({ icon: Icon, size = 'm', 'data-test-id': dataTestId, decor }) {
|
|
11
|
+
const isIcon = isElementConstructor(Icon);
|
|
12
|
+
const isImg = !isIcon && typeof Icon === 'object' && Icon !== null && 'src' in Icon;
|
|
13
|
+
if (isIcon || isImg) {
|
|
14
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.icon, "data-size": size, "data-test-id": dataTestId, "data-decor": decor || undefined, children: [isIcon && (0, jsx_runtime_1.jsx)(Icon, {}), isImg && (0, jsx_runtime_1.jsx)("img", { src: Icon.src, alt: Icon.alt })] }));
|
|
15
|
+
}
|
|
16
|
+
return Icon;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Icon';
|
|
@@ -0,0 +1,17 @@
|
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./Icon"), exports);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
.icon{
|
|
2
|
+
flex-shrink:0;
|
|
3
|
+
color:var(--sys-graphite-text-main, #222222);
|
|
4
|
+
position:relative;
|
|
5
|
+
}
|
|
6
|
+
.icon svg,
|
|
7
|
+
.icon img{
|
|
8
|
+
width:100% !important;
|
|
9
|
+
height:100% !important;
|
|
10
|
+
}
|
|
11
|
+
.icon[data-decor]{
|
|
12
|
+
padding:8px;
|
|
13
|
+
}
|
|
14
|
+
.icon[data-decor] svg,
|
|
15
|
+
.icon[data-decor] img{
|
|
16
|
+
position:absolute;
|
|
17
|
+
top:8px;
|
|
18
|
+
left:8px;
|
|
19
|
+
width:calc(100% - 2 * 8px) !important;
|
|
20
|
+
height:calc(100% - 2 * 8px) !important;
|
|
21
|
+
}
|
|
22
|
+
.icon[data-decor]:before{
|
|
23
|
+
position:absolute;
|
|
24
|
+
top:0;
|
|
25
|
+
left:0;
|
|
26
|
+
content:"";
|
|
27
|
+
display:block;
|
|
28
|
+
width:100%;
|
|
29
|
+
height:100%;
|
|
30
|
+
opacity:50%;
|
|
31
|
+
background-color:var(--sys-graphite-decor-default, #ececec);
|
|
32
|
+
border-radius:var(--radius-icon-predefined-decor-square-m, 4px);
|
|
33
|
+
}
|
|
34
|
+
.icon[data-size=s]{
|
|
35
|
+
height:16px;
|
|
36
|
+
width:16px;
|
|
37
|
+
}
|
|
38
|
+
.icon[data-size=m]{
|
|
39
|
+
height:24px;
|
|
40
|
+
width:24px;
|
|
41
|
+
}
|
|
42
|
+
.icon[data-size=l]{
|
|
43
|
+
height:48px;
|
|
44
|
+
width:48px;
|
|
45
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IconProps } from '../Icon';
|
|
1
2
|
type LinkItemHeaderProps = {
|
|
2
3
|
href?: string;
|
|
3
4
|
target?: string;
|
|
@@ -5,6 +6,7 @@ type LinkItemHeaderProps = {
|
|
|
5
6
|
withoutHover?: boolean;
|
|
6
7
|
active?: boolean;
|
|
7
8
|
onClick?: () => void;
|
|
9
|
+
icon?: IconProps['icon'] | null;
|
|
8
10
|
};
|
|
9
|
-
export declare function LinkItemHeader({ href, label, onClick, withoutHover, target, active }: LinkItemHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export declare function LinkItemHeader({ href, label, onClick, withoutHover, target, active, icon }: LinkItemHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
10
12
|
export {};
|
|
@@ -7,13 +7,14 @@ exports.LinkItemHeader = LinkItemHeader;
|
|
|
7
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
8
|
const classnames_1 = __importDefault(require("classnames"));
|
|
9
9
|
const typography_1 = require("@snack-uikit/typography");
|
|
10
|
+
const Icon_1 = require("../Icon");
|
|
10
11
|
const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
|
|
11
|
-
function LinkItemHeader({ href, label, onClick, withoutHover, target, active }) {
|
|
12
|
+
function LinkItemHeader({ href, label, onClick, withoutHover, target, active, icon }) {
|
|
12
13
|
if (href) {
|
|
13
|
-
return ((0, jsx_runtime_1.
|
|
14
|
+
return ((0, jsx_runtime_1.jsxs)("a", { href: href, target: target, onClick: onClick, className: styles_module_scss_1.default.item, children: [(0, jsx_runtime_1.jsx)(typography_1.Typography.SansTitleS, { children: label }), icon && (0, jsx_runtime_1.jsx)(Icon_1.Icon, { icon: icon, size: 's' })] }));
|
|
14
15
|
}
|
|
15
|
-
return ((0, jsx_runtime_1.
|
|
16
|
+
return ((0, jsx_runtime_1.jsxs)("button", { onClick: onClick, className: (0, classnames_1.default)(styles_module_scss_1.default.item, styles_module_scss_1.default.button, {
|
|
16
17
|
[styles_module_scss_1.default.active]: active,
|
|
17
18
|
[styles_module_scss_1.default.hovered]: !withoutHover && !active,
|
|
18
|
-
}), children: (0, jsx_runtime_1.jsx)(typography_1.Typography.SansTitleS, { children: label }) }));
|
|
19
|
+
}), children: [(0, jsx_runtime_1.jsx)(typography_1.Typography.SansTitleS, { children: label }), icon && (0, jsx_runtime_1.jsx)(Icon_1.Icon, { icon: icon, size: 's' })] }));
|
|
19
20
|
}
|
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
color:var(--sys-graphite-accent-default, #222222);
|
|
15
15
|
transition:color 0.3s ease-in-out;
|
|
16
16
|
cursor:pointer;
|
|
17
|
+
display:flex;
|
|
18
|
+
align-items:center;
|
|
19
|
+
gap:var(--dimension-050m, 4px);
|
|
17
20
|
}
|
|
18
21
|
.item:hover{
|
|
19
22
|
color:var(--sys-graphite-accent-hovered, #383838);
|
|
@@ -25,5 +25,5 @@ function MoreButton({ linkItemsArray, activeItemId }) {
|
|
|
25
25
|
}, item.className) }, item.dataAttributes, { children: (0, jsx_runtime_1.jsx)(LinkItemHeader_1.LinkItemHeader, { label: item.label, onClick: () => {
|
|
26
26
|
item.onClick && item.onClick();
|
|
27
27
|
onClickOpen();
|
|
28
|
-
}, href: item.href, withoutHover: true }) }), item.id))) }), children: (0, jsx_runtime_1.jsx)("button", { className: styles_module_scss_1.default.button, onClick: onClickOpen, children: (0, jsx_runtime_1.jsx)(uikit_product_icons_1.MoreSVG, {}) }) }));
|
|
28
|
+
}, href: item.href, icon: item.icon, withoutHover: true }) }), item.id))) }), children: (0, jsx_runtime_1.jsx)("button", { className: styles_module_scss_1.default.button, onClick: onClickOpen, children: (0, jsx_runtime_1.jsx)(uikit_product_icons_1.MoreSVG, {}) }) }));
|
|
29
29
|
}
|
|
@@ -62,7 +62,7 @@ export function HeaderItems({ linkItems, isMobileTabletView, activeLinkItemId })
|
|
|
62
62
|
if (!linkItems || isMobileTabletView)
|
|
63
63
|
return null;
|
|
64
64
|
const isVisibleEmpty = visibleItems.length === 0;
|
|
65
|
-
return (_jsxs("div", { className: styles.wrapper, children: [_jsx("div", { className: cn(styles.linkItemsContainer, styles.hiddenRow), ref: hiddenRowElementRef, children: linkItems.map((linkItem, index) => (_jsx("div", Object.assign({ className: cn(styles.lastItemContainer, linkItem.className), ref: setItemElement(linkItem, index) }, linkItem.dataAttributes, { children: _jsx(LinkItemHeader, { label: linkItem.label, target: linkItem.target, href: linkItem.href, onClick: linkItem.onClick }) }), linkItem.id))) }), _jsxs("div", { className: cn(styles.linkItemsContainer, {
|
|
65
|
+
return (_jsxs("div", { className: styles.wrapper, children: [_jsx("div", { className: cn(styles.linkItemsContainer, styles.hiddenRow), ref: hiddenRowElementRef, children: linkItems.map((linkItem, index) => (_jsx("div", Object.assign({ className: cn(styles.lastItemContainer, linkItem.className), ref: setItemElement(linkItem, index) }, linkItem.dataAttributes, { children: _jsx(LinkItemHeader, { label: linkItem.label, target: linkItem.target, href: linkItem.href, onClick: linkItem.onClick, icon: linkItem.icon }) }), linkItem.id))) }), _jsxs("div", { className: cn(styles.linkItemsContainer, {
|
|
66
66
|
[styles.linkItemsFirstViewContainer]: isVisibleEmpty,
|
|
67
|
-
}), children: [(isVisibleEmpty ? linkItems : visibleItems).map(linkItem => (_jsx("div", Object.assign({ className: cn(styles.lastItemContainer, linkItem.className) }, linkItem.dataAttributes, { children: _jsx(LinkItemHeader, { label: linkItem.label, href: linkItem.href, onClick: linkItem.onClick, active: activeLinkItemId === linkItem.id }) }), linkItem.id))), hiddenItems.length > 0 && _jsx(MoreButton, { linkItemsArray: hiddenItems, activeItemId: activeLinkItemId })] })] }));
|
|
67
|
+
}), children: [(isVisibleEmpty ? linkItems : visibleItems).map(linkItem => (_jsx("div", Object.assign({ className: cn(styles.lastItemContainer, linkItem.className) }, linkItem.dataAttributes, { children: _jsx(LinkItemHeader, { label: linkItem.label, href: linkItem.href, onClick: linkItem.onClick, active: activeLinkItemId === linkItem.id, icon: linkItem.icon }) }), linkItem.id))), hiddenItems.length > 0 && _jsx(MoreButton, { linkItemsArray: hiddenItems, activeItemId: activeLinkItemId })] })] }));
|
|
68
68
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IconProps } from '../../helperComponents/Icon';
|
|
1
2
|
export type LinkItem = {
|
|
2
3
|
/** id Элемента */
|
|
3
4
|
id: string;
|
|
@@ -15,4 +16,6 @@ export type LinkItem = {
|
|
|
15
16
|
dataAttributes?: {
|
|
16
17
|
[key: string]: string;
|
|
17
18
|
};
|
|
19
|
+
/** Иконка */
|
|
20
|
+
icon?: IconProps['icon'] | null;
|
|
18
21
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { JSXElementConstructor, ReactNode } from 'react';
|
|
2
|
+
export type IconElement = JSXElementConstructor<{
|
|
3
|
+
size?: number;
|
|
4
|
+
className?: string;
|
|
5
|
+
}>;
|
|
6
|
+
export type IconProps = {
|
|
7
|
+
icon: ReactNode | IconElement | {
|
|
8
|
+
src: string;
|
|
9
|
+
alt?: string;
|
|
10
|
+
};
|
|
11
|
+
size: 's' | 'm' | 'l';
|
|
12
|
+
'data-test-id'?: string;
|
|
13
|
+
decor?: boolean;
|
|
14
|
+
};
|
|
15
|
+
export declare function Icon({ icon: Icon, size, 'data-test-id': dataTestId, decor }: IconProps): string | number | boolean | Iterable<ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import styles from './styles.module.css';
|
|
3
|
+
const isElementConstructor = (icon) => typeof icon === 'object' && icon !== null && 'render' in icon;
|
|
4
|
+
export function Icon({ icon: Icon, size = 'm', 'data-test-id': dataTestId, decor }) {
|
|
5
|
+
const isIcon = isElementConstructor(Icon);
|
|
6
|
+
const isImg = !isIcon && typeof Icon === 'object' && Icon !== null && 'src' in Icon;
|
|
7
|
+
if (isIcon || isImg) {
|
|
8
|
+
return (_jsxs("div", { className: styles.icon, "data-size": size, "data-test-id": dataTestId, "data-decor": decor || undefined, children: [isIcon && _jsx(Icon, {}), isImg && _jsx("img", { src: Icon.src, alt: Icon.alt })] }));
|
|
9
|
+
}
|
|
10
|
+
return Icon;
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Icon';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Icon';
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
.icon{
|
|
2
|
+
flex-shrink:0;
|
|
3
|
+
color:var(--sys-graphite-text-main, #222222);
|
|
4
|
+
position:relative;
|
|
5
|
+
}
|
|
6
|
+
.icon svg,
|
|
7
|
+
.icon img{
|
|
8
|
+
width:100% !important;
|
|
9
|
+
height:100% !important;
|
|
10
|
+
}
|
|
11
|
+
.icon[data-decor]{
|
|
12
|
+
padding:8px;
|
|
13
|
+
}
|
|
14
|
+
.icon[data-decor] svg,
|
|
15
|
+
.icon[data-decor] img{
|
|
16
|
+
position:absolute;
|
|
17
|
+
top:8px;
|
|
18
|
+
left:8px;
|
|
19
|
+
width:calc(100% - 2 * 8px) !important;
|
|
20
|
+
height:calc(100% - 2 * 8px) !important;
|
|
21
|
+
}
|
|
22
|
+
.icon[data-decor]:before{
|
|
23
|
+
position:absolute;
|
|
24
|
+
top:0;
|
|
25
|
+
left:0;
|
|
26
|
+
content:"";
|
|
27
|
+
display:block;
|
|
28
|
+
width:100%;
|
|
29
|
+
height:100%;
|
|
30
|
+
opacity:50%;
|
|
31
|
+
background-color:var(--sys-graphite-decor-default, #ececec);
|
|
32
|
+
border-radius:var(--radius-icon-predefined-decor-square-m, 4px);
|
|
33
|
+
}
|
|
34
|
+
.icon[data-size=s]{
|
|
35
|
+
height:16px;
|
|
36
|
+
width:16px;
|
|
37
|
+
}
|
|
38
|
+
.icon[data-size=m]{
|
|
39
|
+
height:24px;
|
|
40
|
+
width:24px;
|
|
41
|
+
}
|
|
42
|
+
.icon[data-size=l]{
|
|
43
|
+
height:48px;
|
|
44
|
+
width:48px;
|
|
45
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IconProps } from '../Icon';
|
|
1
2
|
type LinkItemHeaderProps = {
|
|
2
3
|
href?: string;
|
|
3
4
|
target?: string;
|
|
@@ -5,6 +6,7 @@ type LinkItemHeaderProps = {
|
|
|
5
6
|
withoutHover?: boolean;
|
|
6
7
|
active?: boolean;
|
|
7
8
|
onClick?: () => void;
|
|
9
|
+
icon?: IconProps['icon'] | null;
|
|
8
10
|
};
|
|
9
|
-
export declare function LinkItemHeader({ href, label, onClick, withoutHover, target, active }: LinkItemHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export declare function LinkItemHeader({ href, label, onClick, withoutHover, target, active, icon }: LinkItemHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
10
12
|
export {};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import cn from 'classnames';
|
|
3
3
|
import { Typography } from '@snack-uikit/typography';
|
|
4
|
+
import { Icon } from '../Icon';
|
|
4
5
|
import styles from './styles.module.css';
|
|
5
|
-
export function LinkItemHeader({ href, label, onClick, withoutHover, target, active }) {
|
|
6
|
+
export function LinkItemHeader({ href, label, onClick, withoutHover, target, active, icon }) {
|
|
6
7
|
if (href) {
|
|
7
|
-
return (
|
|
8
|
+
return (_jsxs("a", { href: href, target: target, onClick: onClick, className: styles.item, children: [_jsx(Typography.SansTitleS, { children: label }), icon && _jsx(Icon, { icon: icon, size: 's' })] }));
|
|
8
9
|
}
|
|
9
|
-
return (
|
|
10
|
+
return (_jsxs("button", { onClick: onClick, className: cn(styles.item, styles.button, {
|
|
10
11
|
[styles.active]: active,
|
|
11
12
|
[styles.hovered]: !withoutHover && !active,
|
|
12
|
-
}), children: _jsx(Typography.SansTitleS, { children: label }) }));
|
|
13
|
+
}), children: [_jsx(Typography.SansTitleS, { children: label }), icon && _jsx(Icon, { icon: icon, size: 's' })] }));
|
|
13
14
|
}
|
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
color:var(--sys-graphite-accent-default, #222222);
|
|
15
15
|
transition:color 0.3s ease-in-out;
|
|
16
16
|
cursor:pointer;
|
|
17
|
+
display:flex;
|
|
18
|
+
align-items:center;
|
|
19
|
+
gap:var(--dimension-050m, 4px);
|
|
17
20
|
}
|
|
18
21
|
.item:hover{
|
|
19
22
|
color:var(--sys-graphite-accent-hovered, #383838);
|
|
@@ -19,5 +19,5 @@ export function MoreButton({ linkItemsArray, activeItemId }) {
|
|
|
19
19
|
}, item.className) }, item.dataAttributes, { children: _jsx(LinkItemHeader, { label: item.label, onClick: () => {
|
|
20
20
|
item.onClick && item.onClick();
|
|
21
21
|
onClickOpen();
|
|
22
|
-
}, href: item.href, withoutHover: true }) }), item.id))) }), children: _jsx("button", { className: styles.button, onClick: onClickOpen, children: _jsx(MoreSVG, {}) }) }));
|
|
22
|
+
}, href: item.href, icon: item.icon, withoutHover: true }) }), item.id))) }), children: _jsx("button", { className: styles.button, onClick: onClickOpen, children: _jsx(MoreSVG, {}) }) }));
|
|
23
23
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloud-ru/uikit-product-site-header",
|
|
3
3
|
"title": "Siteheader",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.3.1",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"*.css",
|
|
7
7
|
"*.woff",
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
},
|
|
37
37
|
"scripts": {},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@cloud-ru/uikit-product-button-predefined": "1.1.
|
|
40
|
-
"@cloud-ru/uikit-product-icons": "17.0.
|
|
41
|
-
"@cloud-ru/uikit-product-mobile-modal": "2.0.
|
|
39
|
+
"@cloud-ru/uikit-product-button-predefined": "1.1.6",
|
|
40
|
+
"@cloud-ru/uikit-product-icons": "17.0.4",
|
|
41
|
+
"@cloud-ru/uikit-product-mobile-modal": "2.0.5",
|
|
42
42
|
"@cloud-ru/uikit-product-site-layout": "1.1.2",
|
|
43
43
|
"@cloud-ru/uikit-product-utils": "9.0.2",
|
|
44
44
|
"@snack-uikit/alert": "0.16.17",
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"@cloud-ru/figma-tokens-web": "*"
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "009354890e4be8948b4b89fcaaeaa23542217b65"
|
|
56
56
|
}
|
|
@@ -101,6 +101,7 @@ export function HeaderItems({ linkItems, isMobileTabletView, activeLinkItemId }:
|
|
|
101
101
|
target={linkItem.target}
|
|
102
102
|
href={linkItem.href}
|
|
103
103
|
onClick={linkItem.onClick}
|
|
104
|
+
icon={linkItem.icon}
|
|
104
105
|
/>
|
|
105
106
|
</div>
|
|
106
107
|
))}
|
|
@@ -122,6 +123,7 @@ export function HeaderItems({ linkItems, isMobileTabletView, activeLinkItemId }:
|
|
|
122
123
|
href={linkItem.href}
|
|
123
124
|
onClick={linkItem.onClick}
|
|
124
125
|
active={activeLinkItemId === linkItem.id}
|
|
126
|
+
icon={linkItem.icon}
|
|
125
127
|
/>
|
|
126
128
|
</div>
|
|
127
129
|
))}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { IconProps } from '../../helperComponents/Icon';
|
|
2
|
+
|
|
1
3
|
export type LinkItem = {
|
|
2
4
|
/** id Элемента */
|
|
3
5
|
id: string;
|
|
@@ -15,4 +17,6 @@ export type LinkItem = {
|
|
|
15
17
|
dataAttributes?: {
|
|
16
18
|
[key: string]: string;
|
|
17
19
|
};
|
|
20
|
+
/** Иконка */
|
|
21
|
+
icon?: IconProps['icon'] | null;
|
|
18
22
|
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { JSXElementConstructor, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import styles from './styles.module.scss';
|
|
4
|
+
|
|
5
|
+
export type IconElement = JSXElementConstructor<{ size?: number; className?: string }>;
|
|
6
|
+
|
|
7
|
+
export type IconProps = {
|
|
8
|
+
icon: ReactNode | IconElement | { src: string; alt?: string };
|
|
9
|
+
size: 's' | 'm' | 'l';
|
|
10
|
+
'data-test-id'?: string;
|
|
11
|
+
decor?: boolean;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const isElementConstructor = (icon: IconProps['icon']): icon is IconElement =>
|
|
15
|
+
typeof icon === 'object' && icon !== null && 'render' in icon;
|
|
16
|
+
|
|
17
|
+
export function Icon({ icon: Icon, size = 'm', 'data-test-id': dataTestId, decor }: IconProps) {
|
|
18
|
+
const isIcon = isElementConstructor(Icon);
|
|
19
|
+
const isImg = !isIcon && typeof Icon === 'object' && Icon !== null && 'src' in Icon;
|
|
20
|
+
|
|
21
|
+
if (isIcon || isImg) {
|
|
22
|
+
return (
|
|
23
|
+
<div className={styles.icon} data-size={size} data-test-id={dataTestId} data-decor={decor || undefined}>
|
|
24
|
+
{isIcon && <Icon />}
|
|
25
|
+
{isImg && <img src={Icon.src} alt={Icon.alt} />}
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return Icon as ReactNode;
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Icon';
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
@use '@cloud-ru/figma-tokens-web/build/scss/components/styles-tokens-element' as ste;
|
|
2
|
+
|
|
3
|
+
$decor-padding: 8px;
|
|
4
|
+
|
|
5
|
+
.icon {
|
|
6
|
+
flex-shrink: 0;
|
|
7
|
+
color: ste.$sys-graphite-text-main;
|
|
8
|
+
position: relative;
|
|
9
|
+
|
|
10
|
+
svg,
|
|
11
|
+
img {
|
|
12
|
+
width: 100% !important; /* stylelint-disable-line declaration-no-important */
|
|
13
|
+
height: 100% !important; /* stylelint-disable-line declaration-no-important */
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
&[data-decor] {
|
|
17
|
+
padding: $decor-padding;
|
|
18
|
+
|
|
19
|
+
& svg,
|
|
20
|
+
img {
|
|
21
|
+
position: absolute;
|
|
22
|
+
top: 8px;
|
|
23
|
+
left: 8px;
|
|
24
|
+
width: calc(100% - 2 * #{$decor-padding}) !important; /* stylelint-disable-line declaration-no-important */
|
|
25
|
+
height: calc(100% - 2 * #{$decor-padding}) !important; /* stylelint-disable-line declaration-no-important */
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&:before {
|
|
29
|
+
position: absolute;
|
|
30
|
+
top: 0;
|
|
31
|
+
left: 0;
|
|
32
|
+
content: '';
|
|
33
|
+
display: block;
|
|
34
|
+
width: 100%;
|
|
35
|
+
height: 100%;
|
|
36
|
+
opacity: 50%;
|
|
37
|
+
background-color: ste.$sys-graphite-decor-default;
|
|
38
|
+
border-radius: ste.$radius-icon-predefined-decor-square-m;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&[data-size='s'] {
|
|
43
|
+
height: 16px;
|
|
44
|
+
width: 16px;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
&[data-size='m'] {
|
|
48
|
+
height: 24px;
|
|
49
|
+
width: 24px;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
&[data-size='l'] {
|
|
53
|
+
height: 48px;
|
|
54
|
+
width: 48px;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -2,6 +2,7 @@ import cn from 'classnames';
|
|
|
2
2
|
|
|
3
3
|
import { Typography } from '@snack-uikit/typography';
|
|
4
4
|
|
|
5
|
+
import { Icon, IconProps } from '../Icon';
|
|
5
6
|
import styles from './styles.module.scss';
|
|
6
7
|
|
|
7
8
|
type LinkItemHeaderProps = {
|
|
@@ -11,13 +12,15 @@ type LinkItemHeaderProps = {
|
|
|
11
12
|
withoutHover?: boolean;
|
|
12
13
|
active?: boolean;
|
|
13
14
|
onClick?: () => void;
|
|
15
|
+
icon?: IconProps['icon'] | null;
|
|
14
16
|
};
|
|
15
17
|
|
|
16
|
-
export function LinkItemHeader({ href, label, onClick, withoutHover, target, active }: LinkItemHeaderProps) {
|
|
18
|
+
export function LinkItemHeader({ href, label, onClick, withoutHover, target, active, icon }: LinkItemHeaderProps) {
|
|
17
19
|
if (href) {
|
|
18
20
|
return (
|
|
19
21
|
<a href={href} target={target} onClick={onClick} className={styles.item}>
|
|
20
22
|
<Typography.SansTitleS>{label}</Typography.SansTitleS>
|
|
23
|
+
{icon && <Icon icon={icon} size='s' />}
|
|
21
24
|
</a>
|
|
22
25
|
);
|
|
23
26
|
}
|
|
@@ -31,6 +34,7 @@ export function LinkItemHeader({ href, label, onClick, withoutHover, target, act
|
|
|
31
34
|
})}
|
|
32
35
|
>
|
|
33
36
|
<Typography.SansTitleS>{label}</Typography.SansTitleS>
|
|
37
|
+
{icon && <Icon icon={icon} size='s' />}
|
|
34
38
|
</button>
|
|
35
39
|
);
|
|
36
40
|
}
|