@sima-land/moleculas 15.2.0 → 15.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/common/components/badge/index.js +1 -1
- package/common/components/badge-list/index.js +2 -2
- package/common/components/product-info/index.js +3 -1
- package/common/components/product-info/parts.d.ts +13 -2
- package/common/components/product-info/parts.js +7 -3
- package/common/components/product-info/product-info.module.scss +38 -3
- package/desktop/components/breadcrumbs/index.js +1 -1
- package/desktop/components/gallery-modal/components/review-info.js +5 -0
- package/mobile/components/breadcrumbs/index.d.ts +1 -1
- package/mobile/components/breadcrumbs/index.js +1 -1
- package/package.json +1 -1
|
@@ -47,7 +47,7 @@ const cx = bind_1.default.bind(badge_module_scss_1.default);
|
|
|
47
47
|
exports.Badge = (0, react_1.forwardRef)(function Badge(_a, ref) {
|
|
48
48
|
var { className, color, fields, href, style, 'data-testid': testId = 'badge' } = _a, restProps = __rest(_a, ["className", "color", "fields", "href", "style", 'data-testid']);
|
|
49
49
|
const iconOnly = fields.length === 1 && fields[0].type === 'svg-url';
|
|
50
|
-
return (react_1.default.createElement("a", Object.assign({ ref: ref }, restProps, { "data-testid": testId, href: href, style: Object.assign(Object.assign({}, style), { '--badge-color': color }), className: cx('root', iconOnly && 'icon-only', href && 'interactive', className), children: iconOnly ? (react_1.default.createElement("img", { className: cx('icon'), src: fields[0].value })) : (
|
|
50
|
+
return (react_1.default.createElement("a", Object.assign({ ref: ref }, restProps, { "data-testid": testId, href: href, style: Object.assign(Object.assign({}, style), { '--badge-color': color }), className: cx('root', iconOnly && 'icon-only', href && 'interactive', className), children: iconOnly ? (react_1.default.createElement("img", { className: cx('icon'), src: fields[0].value, alt: '' })) : (
|
|
51
51
|
// вложенный span нужен для того чтобы объединить `display: inline-flex` и `text-overflow: ellipsis`
|
|
52
52
|
react_1.default.createElement("span", { className: cx('content') }, fields.reduce((acc, item, i) => {
|
|
53
53
|
let result = null;
|
|
@@ -33,10 +33,10 @@ const cx = bind_1.default.bind(badge_list_module_scss_1.default);
|
|
|
33
33
|
* @param props Свойства компонента.
|
|
34
34
|
* @return Элемент.
|
|
35
35
|
*/
|
|
36
|
-
const BadgeList = ({ children, className, lineLimit, style }) => (react_1.default.createElement("div", { className: cx('root', className, lineLimit && 'line-limit'), style: lineLimit ? Object.assign(Object.assign({}, style), { '--line-limit': lineLimit }) : style }, react_1.Children.toArray(children).map(child => {
|
|
36
|
+
const BadgeList = ({ children, className, lineLimit, style }) => (react_1.default.createElement("div", { className: cx('root', className, lineLimit && 'line-limit'), style: lineLimit ? Object.assign(Object.assign({}, style), { '--line-limit': lineLimit }) : style }, react_1.Children.toArray(children).map((child, index) => {
|
|
37
37
|
switch (true) {
|
|
38
38
|
case (0, react_1.isValidElement)(child) && child.type === badge_1.Badge:
|
|
39
|
-
return react_1.default.createElement(BadgeListSlot,
|
|
39
|
+
return react_1.default.createElement(BadgeListSlot, { key: index }, child);
|
|
40
40
|
case (0, react_1.isValidElement)(child) && child.type === BadgeListSlot:
|
|
41
41
|
return child;
|
|
42
42
|
default:
|
|
@@ -15,19 +15,21 @@ exports.UNAVAILABLE_REASON = {
|
|
|
15
15
|
onlyForLegalEntities: 'Товар доступен только для юридических лиц',
|
|
16
16
|
};
|
|
17
17
|
const ProductInfo = ({ restriction, children }) => {
|
|
18
|
-
const { image, badges, prices, title, trademark, footer } = (0, define_slots_1.defineSlots)(children, {
|
|
18
|
+
const { image, badges, prices, title, trademark, footer, secondaryInfo } = (0, define_slots_1.defineSlots)(children, {
|
|
19
19
|
image: parts_1.Parts.Image,
|
|
20
20
|
badges: parts_1.Parts.Badges,
|
|
21
21
|
prices: parts_1.Parts.Prices,
|
|
22
22
|
title: parts_1.Parts.Title,
|
|
23
23
|
trademark: parts_1.Parts.TrademarkLink,
|
|
24
24
|
footer: parts_1.Parts.Footer,
|
|
25
|
+
secondaryInfo: parts_1.Parts.SecondaryInfo,
|
|
25
26
|
});
|
|
26
27
|
return (react_1.default.createElement(utils_1.ProductInfoContext.Provider, { value: { restriction } },
|
|
27
28
|
image,
|
|
28
29
|
restriction !== 'adult' && badges,
|
|
29
30
|
prices,
|
|
30
31
|
title,
|
|
32
|
+
restriction !== 'adult' && secondaryInfo,
|
|
31
33
|
!restriction && trademark,
|
|
32
34
|
footer));
|
|
33
35
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
2
|
import { LinkProps } from '@sima-land/ui-nucleons/link';
|
|
3
|
+
import { HintProps } from '@sima-land/ui-nucleons/hint';
|
|
3
4
|
import { StrokedSVGProps } from '@sima-land/ui-nucleons/stroked-svg';
|
|
4
5
|
import { BadgeListProps } from '../badge-list';
|
|
5
6
|
export interface ImageProps {
|
|
@@ -10,14 +11,22 @@ export interface ImageProps {
|
|
|
10
11
|
children?: React.ReactNode;
|
|
11
12
|
opacity?: number;
|
|
12
13
|
}
|
|
14
|
+
declare function SecondaryInfo({ children }: {
|
|
15
|
+
children: ReactNode;
|
|
16
|
+
}): JSX.Element;
|
|
13
17
|
export declare const Parts: {
|
|
14
18
|
readonly Image: ({ src, alt, href, onClick, children, opacity }: ImageProps) => JSX.Element;
|
|
15
|
-
readonly ImageButton: ({ icon, fill, onClick, hint, "data-testid": testId, }: {
|
|
19
|
+
readonly ImageButton: ({ icon, fill, onClick, hint, hintDirection, "data-testid": testId, position, }: {
|
|
16
20
|
icon: StrokedSVGProps['component'];
|
|
17
21
|
fill?: string | undefined;
|
|
18
22
|
onClick?: React.MouseEventHandler<HTMLDivElement> | undefined;
|
|
19
23
|
hint?: string | undefined;
|
|
24
|
+
hintDirection?: ("left" | "right" | "bottom" | "top") | undefined;
|
|
20
25
|
'data-testid'?: string | undefined;
|
|
26
|
+
position?: {
|
|
27
|
+
x: 'left' | 'right';
|
|
28
|
+
y: 'top' | 'bottom';
|
|
29
|
+
} | undefined;
|
|
21
30
|
}) => JSX.Element;
|
|
22
31
|
readonly Badges: (props: BadgeListProps) => JSX.Element;
|
|
23
32
|
readonly Prices: ({ price, oldPrice, currencyGrapheme, unavailableReason, }: {
|
|
@@ -28,6 +37,7 @@ export declare const Parts: {
|
|
|
28
37
|
}) => JSX.Element;
|
|
29
38
|
readonly Title: ({ children, href, onClick }: Pick<LinkProps, 'children' | 'href' | 'onClick'>) => JSX.Element;
|
|
30
39
|
readonly TrademarkLink: ({ href, children, onClick, }: Pick<LinkProps, 'href' | 'children' | 'onClick'>) => JSX.Element;
|
|
40
|
+
readonly SecondaryInfo: typeof SecondaryInfo;
|
|
31
41
|
readonly Footer: React.FC<{}>;
|
|
32
42
|
readonly FooterContext: React.Context<{
|
|
33
43
|
className?: string | undefined;
|
|
@@ -42,3 +52,4 @@ export declare const Parts: {
|
|
|
42
52
|
readonly WaitListAddButton: ({ className, ...props }: LinkProps) => JSX.Element;
|
|
43
53
|
readonly WaitListAddedLink: ({ className, ...props }: LinkProps) => JSX.Element;
|
|
44
54
|
};
|
|
55
|
+
export {};
|
|
@@ -51,17 +51,17 @@ const cx = bind_1.default.bind(product_info_module_scss_1.default);
|
|
|
51
51
|
* @param props Свойства.
|
|
52
52
|
* @return Элемент.
|
|
53
53
|
*/
|
|
54
|
-
const ImageButton = ({ icon, fill, onClick, hint, 'data-testid': testId, }) => {
|
|
54
|
+
const ImageButton = ({ icon, fill, onClick, hint, hintDirection = 'left', 'data-testid': testId, position, }) => {
|
|
55
55
|
const commonProps = {
|
|
56
56
|
role: 'banner',
|
|
57
57
|
component: icon,
|
|
58
58
|
fill,
|
|
59
59
|
strokeWidth: 1.5,
|
|
60
|
-
className: cx('image-button'),
|
|
60
|
+
className: cx('image-button', position && 'positioned', position && `${position.x}-${position.y}`),
|
|
61
61
|
onClick,
|
|
62
62
|
'data-testid': testId,
|
|
63
63
|
};
|
|
64
|
-
return hint ? (react_1.default.createElement(with_hint_1.WithHint, { hint: hint, direction:
|
|
64
|
+
return hint ? (react_1.default.createElement(with_hint_1.WithHint, { hint: hint, direction: hintDirection }, (ref, toggle) => (react_1.default.createElement(stroked_svg_1.StrokedSVG, Object.assign({}, commonProps, { ref: ref, onMouseEnter: () => toggle(true), onMouseLeave: () => toggle(false) }))))) : (react_1.default.createElement(stroked_svg_1.StrokedSVG, Object.assign({}, commonProps)));
|
|
65
65
|
};
|
|
66
66
|
/**
|
|
67
67
|
* Слот - изображение товара.
|
|
@@ -165,6 +165,9 @@ const WaitListAddedLink = (_a) => {
|
|
|
165
165
|
'\u00A0',
|
|
166
166
|
"\u043E\u0436\u0438\u0434\u0430\u043D\u0438\u044F")));
|
|
167
167
|
};
|
|
168
|
+
function SecondaryInfo({ children }) {
|
|
169
|
+
return react_1.default.createElement("div", { className: cx('secondary-info') }, children);
|
|
170
|
+
}
|
|
168
171
|
exports.Parts = {
|
|
169
172
|
// основные компоненты-слоты и компоненты-запчасти
|
|
170
173
|
Image,
|
|
@@ -173,6 +176,7 @@ exports.Parts = {
|
|
|
173
176
|
Prices,
|
|
174
177
|
Title,
|
|
175
178
|
TrademarkLink,
|
|
179
|
+
SecondaryInfo,
|
|
176
180
|
// компоненты-слоты и компоненты-запчасти, предназначенные для вывода футера (dcе что ниже ссылки на торговую марку)
|
|
177
181
|
Footer,
|
|
178
182
|
FooterContext,
|
|
@@ -63,6 +63,8 @@
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
.image-button {
|
|
66
|
+
width: 24px;
|
|
67
|
+
height: 24px;
|
|
66
68
|
display: block;
|
|
67
69
|
border: 0;
|
|
68
70
|
outline: 0;
|
|
@@ -71,13 +73,39 @@
|
|
|
71
73
|
--gutter: 8px;
|
|
72
74
|
right: var(--gutter);
|
|
73
75
|
cursor: pointer;
|
|
74
|
-
&:
|
|
76
|
+
&:not(.positioned) {
|
|
77
|
+
&:nth-child(1) {
|
|
78
|
+
top: var(--gutter);
|
|
79
|
+
}
|
|
80
|
+
&:nth-child(2) {
|
|
81
|
+
bottom: var(--gutter);
|
|
82
|
+
}
|
|
83
|
+
&:nth-child(3) {
|
|
84
|
+
top: var(--gutter);
|
|
85
|
+
left: var(--gutter);
|
|
86
|
+
}
|
|
87
|
+
&:nth-child(3) {
|
|
88
|
+
top: var(--gutter);
|
|
89
|
+
left: var(--gutter);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
&.left-top {
|
|
93
|
+
left: var(--gutter);
|
|
75
94
|
top: var(--gutter);
|
|
76
95
|
}
|
|
77
|
-
|
|
96
|
+
&.left-bottom {
|
|
97
|
+
left: var(--gutter);
|
|
78
98
|
bottom: var(--gutter);
|
|
79
99
|
}
|
|
80
|
-
|
|
100
|
+
&.right-top {
|
|
101
|
+
right: var(--gutter);
|
|
102
|
+
top: var(--gutter);
|
|
103
|
+
}
|
|
104
|
+
&.right-bottom {
|
|
105
|
+
right: var(--gutter);
|
|
106
|
+
bottom: var(--gutter);
|
|
107
|
+
}
|
|
108
|
+
&:nth-child(n + 5) {
|
|
81
109
|
display: none;
|
|
82
110
|
}
|
|
83
111
|
&:hover {
|
|
@@ -143,6 +171,13 @@
|
|
|
143
171
|
color: colors.$basic-gray87;
|
|
144
172
|
}
|
|
145
173
|
|
|
174
|
+
.secondary-info {
|
|
175
|
+
margin-top: 8px;
|
|
176
|
+
font-size: 14px;
|
|
177
|
+
line-height: 20px;
|
|
178
|
+
color: colors.$basic-gray38;
|
|
179
|
+
}
|
|
180
|
+
|
|
146
181
|
.trademark-link {
|
|
147
182
|
display: block;
|
|
148
183
|
margin-top: 8px;
|
|
@@ -55,7 +55,7 @@ const Breadcrumb = ({ data, onSiblingsPopupOpen, isSiblingActive, }) => {
|
|
|
55
55
|
return (0, on_1.default)(window, 'mousedown', togglePopup.bind(null, false));
|
|
56
56
|
}
|
|
57
57
|
}, [withPopup]);
|
|
58
|
-
const selfName = (react_1.default.createElement(link_1.Link, { color: 'basic-gray87', href: data.url }, data.name));
|
|
58
|
+
const selfName = (react_1.default.createElement(link_1.Link, { color: 'basic-gray87', href: data.url, pseudo: !data.url }, data.name));
|
|
59
59
|
return (react_1.default.createElement("div", { "data-testid": 'breadcrumb', className: cx('breadcrumb') },
|
|
60
60
|
selfName,
|
|
61
61
|
data.siblings && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
@@ -42,7 +42,12 @@ const ReviewInfo = ({ rating, author, onGoToReview, content, className, notAffec
|
|
|
42
42
|
setClamped(contentEl.scrollHeight > contentEl.clientHeight);
|
|
43
43
|
}
|
|
44
44
|
}, [opened]);
|
|
45
|
+
(0, react_1.useEffect)(() => {
|
|
46
|
+
setClamped(false);
|
|
47
|
+
setOpened(false);
|
|
48
|
+
}, [content, author]);
|
|
45
49
|
(0, react_1.useEffect)(checkClamp, [content, opened]);
|
|
50
|
+
// @todo что делать если при изменении размеров изменилось состояние обрезания?
|
|
46
51
|
(0, react_1.useEffect)(() => (0, on_1.default)(window, 'resize', checkClamp), [content, checkClamp]);
|
|
47
52
|
return (react_1.default.createElement("div", { className: cx('root', className, opened && shadows_1.BoxShadow.z2straight) },
|
|
48
53
|
loading && (react_1.default.createElement(Layout, null,
|
|
@@ -7,5 +7,5 @@ exports.Breadcrumbs = void 0;
|
|
|
7
7
|
const link_1 = require("@sima-land/ui-nucleons/link");
|
|
8
8
|
const react_1 = __importDefault(require("react"));
|
|
9
9
|
const breadcrumbs_module_scss_1 = __importDefault(require("./breadcrumbs.module.scss"));
|
|
10
|
-
const Breadcrumbs = ({ items }) => (react_1.default.createElement("nav", { className: breadcrumbs_module_scss_1.default.root }, items.map((item, index) => (react_1.default.createElement(link_1.Link, { key: index, href: item.url, color: 'basic-gray87', className: breadcrumbs_module_scss_1.default.item }, item.name)))));
|
|
10
|
+
const Breadcrumbs = ({ items }) => (react_1.default.createElement("nav", { className: breadcrumbs_module_scss_1.default.root }, items.map((item, index) => (react_1.default.createElement(link_1.Link, { key: index, href: item.url, pseudo: !item.url, color: 'basic-gray87', className: breadcrumbs_module_scss_1.default.item, "data-testid": 'breadcrumb' }, item.name)))));
|
|
11
11
|
exports.Breadcrumbs = Breadcrumbs;
|