@sima-land/moleculas 15.3.0 → 15.4.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/common/components/badge/index.js +1 -1
- package/common/components/badge-list/index.js +2 -2
- package/common/components/intractive-image/interactive-image.module.scss +4 -4
- package/common/components/product-info/index.js +3 -1
- package/common/components/product-info/parts.d.ts +3 -0
- package/common/components/product-info/parts.js +6 -0
- package/common/components/product-info/product-info.module.scss +11 -0
- package/common/components/product-info/types.d.ts +2 -0
- package/common/components/rating-counter/index.d.ts +25 -0
- package/common/components/rating-counter/index.js +38 -0
- package/common/components/rating-counter/rating-counter-util.scss +17 -0
- package/common/components/rating-counter/rating-counter.module.scss +66 -0
- package/common/components/rating-counter/star.svg +5 -0
- package/desktop/components/breadcrumbs/index.js +1 -1
- 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:
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
display: flex;
|
|
23
23
|
justify-content: center;
|
|
24
24
|
align-items: center;
|
|
25
|
-
width:
|
|
26
|
-
height:
|
|
25
|
+
width: 52px;
|
|
26
|
+
height: 52px;
|
|
27
27
|
background: rgba(colors.$basic-gray87, 0.4);
|
|
28
28
|
border-radius: 50%;
|
|
29
29
|
transform: translate(-50%, -50%);
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
&::after {
|
|
35
35
|
content: '';
|
|
36
36
|
display: block;
|
|
37
|
-
width:
|
|
38
|
-
height:
|
|
37
|
+
width: 20px;
|
|
38
|
+
height: 20px;
|
|
39
39
|
background: #fff;
|
|
40
40
|
border-radius: 50%;
|
|
41
41
|
}
|
|
@@ -15,7 +15,7 @@ exports.UNAVAILABLE_REASON = {
|
|
|
15
15
|
onlyForLegalEntities: 'Товар доступен только для юридических лиц',
|
|
16
16
|
};
|
|
17
17
|
const ProductInfo = ({ restriction, children }) => {
|
|
18
|
-
const { image, badges, prices, title, trademark, footer, secondaryInfo } = (0, define_slots_1.defineSlots)(children, {
|
|
18
|
+
const { image, badges, prices, title, trademark, footer, secondaryInfo, ratingCounter } = (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,
|
|
@@ -23,6 +23,7 @@ const ProductInfo = ({ restriction, children }) => {
|
|
|
23
23
|
trademark: parts_1.Parts.TrademarkLink,
|
|
24
24
|
footer: parts_1.Parts.Footer,
|
|
25
25
|
secondaryInfo: parts_1.Parts.SecondaryInfo,
|
|
26
|
+
ratingCounter: parts_1.Parts.RatingCounter,
|
|
26
27
|
});
|
|
27
28
|
return (react_1.default.createElement(utils_1.ProductInfoContext.Provider, { value: { restriction } },
|
|
28
29
|
image,
|
|
@@ -31,6 +32,7 @@ const ProductInfo = ({ restriction, children }) => {
|
|
|
31
32
|
title,
|
|
32
33
|
restriction !== 'adult' && secondaryInfo,
|
|
33
34
|
!restriction && trademark,
|
|
35
|
+
restriction !== 'adult' && ratingCounter,
|
|
34
36
|
footer));
|
|
35
37
|
};
|
|
36
38
|
exports.ProductInfo = ProductInfo;
|
|
@@ -3,6 +3,7 @@ import { LinkProps } from '@sima-land/ui-nucleons/link';
|
|
|
3
3
|
import { HintProps } from '@sima-land/ui-nucleons/hint';
|
|
4
4
|
import { StrokedSVGProps } from '@sima-land/ui-nucleons/stroked-svg';
|
|
5
5
|
import { BadgeListProps } from '../badge-list';
|
|
6
|
+
import { RatingCounterProps } from '../rating-counter';
|
|
6
7
|
export interface ImageProps {
|
|
7
8
|
src?: string;
|
|
8
9
|
alt?: string;
|
|
@@ -14,6 +15,7 @@ export interface ImageProps {
|
|
|
14
15
|
declare function SecondaryInfo({ children }: {
|
|
15
16
|
children: ReactNode;
|
|
16
17
|
}): JSX.Element;
|
|
18
|
+
declare function CustomRatingCounter({ className, ...rest }: RatingCounterProps): JSX.Element;
|
|
17
19
|
export declare const Parts: {
|
|
18
20
|
readonly Image: ({ src, alt, href, onClick, children, opacity }: ImageProps) => JSX.Element;
|
|
19
21
|
readonly ImageButton: ({ icon, fill, onClick, hint, hintDirection, "data-testid": testId, position, }: {
|
|
@@ -38,6 +40,7 @@ export declare const Parts: {
|
|
|
38
40
|
readonly Title: ({ children, href, onClick }: Pick<LinkProps, 'children' | 'href' | 'onClick'>) => JSX.Element;
|
|
39
41
|
readonly TrademarkLink: ({ href, children, onClick, }: Pick<LinkProps, 'href' | 'children' | 'onClick'>) => JSX.Element;
|
|
40
42
|
readonly SecondaryInfo: typeof SecondaryInfo;
|
|
43
|
+
readonly RatingCounter: typeof CustomRatingCounter;
|
|
41
44
|
readonly Footer: React.FC<{}>;
|
|
42
45
|
readonly FooterContext: React.Context<{
|
|
43
46
|
className?: string | undefined;
|
|
@@ -42,6 +42,7 @@ const with_hint_1 = require("@sima-land/ui-nucleons/with-hint");
|
|
|
42
42
|
const image_overlay_1 = require("../../../desktop/components/gallery-modal/components/image-overlay");
|
|
43
43
|
const badge_list_1 = require("../badge-list");
|
|
44
44
|
const utils_1 = require("./utils");
|
|
45
|
+
const rating_counter_1 = require("../rating-counter");
|
|
45
46
|
const eighteen_plus_svg_1 = __importDefault(require("../../icons/eighteen-plus.svg"));
|
|
46
47
|
const bind_1 = __importDefault(require("classnames/bind"));
|
|
47
48
|
const product_info_module_scss_1 = __importDefault(require("./product-info.module.scss"));
|
|
@@ -168,6 +169,10 @@ const WaitListAddedLink = (_a) => {
|
|
|
168
169
|
function SecondaryInfo({ children }) {
|
|
169
170
|
return react_1.default.createElement("div", { className: cx('secondary-info') }, children);
|
|
170
171
|
}
|
|
172
|
+
function CustomRatingCounter(_a) {
|
|
173
|
+
var { className } = _a, rest = __rest(_a, ["className"]);
|
|
174
|
+
return react_1.default.createElement(rating_counter_1.RatingCounter, Object.assign({ size: 'unset', className: cx('rating', className), hoverDisabled: true }, rest));
|
|
175
|
+
}
|
|
171
176
|
exports.Parts = {
|
|
172
177
|
// основные компоненты-слоты и компоненты-запчасти
|
|
173
178
|
Image,
|
|
@@ -177,6 +182,7 @@ exports.Parts = {
|
|
|
177
182
|
Title,
|
|
178
183
|
TrademarkLink,
|
|
179
184
|
SecondaryInfo,
|
|
185
|
+
RatingCounter: CustomRatingCounter,
|
|
180
186
|
// компоненты-слоты и компоненты-запчасти, предназначенные для вывода футера (dcе что ниже ссылки на торговую марку)
|
|
181
187
|
Footer,
|
|
182
188
|
FooterContext,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
@use 'node_modules/@sima-land/ui-nucleons/colors';
|
|
2
2
|
@use 'node_modules/@sima-land/ui-nucleons/breakpoints';
|
|
3
|
+
@use '../rating-counter/rating-counter-util';
|
|
3
4
|
|
|
4
5
|
.image-overlay {
|
|
5
6
|
position: relative;
|
|
@@ -188,6 +189,16 @@
|
|
|
188
189
|
text-overflow: ellipsis;
|
|
189
190
|
}
|
|
190
191
|
|
|
192
|
+
.rating {
|
|
193
|
+
margin-top: 8px;
|
|
194
|
+
@include breakpoints.down('mm') {
|
|
195
|
+
@include rating-counter-util.size-s;
|
|
196
|
+
}
|
|
197
|
+
@include breakpoints.up('mm') {
|
|
198
|
+
@include rating-counter-util.size-m;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
191
202
|
// футер
|
|
192
203
|
.footer {
|
|
193
204
|
margin-top: 16px;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
2
|
+
export declare type RatingCounterSize = 's' | 'm' | 'unset';
|
|
3
|
+
interface CustomProps {
|
|
4
|
+
/**
|
|
5
|
+
* Размер.
|
|
6
|
+
* При указании "unset" необходимо определить стили самостоятельно с помощью миксина из rating-counter-util.scss.
|
|
7
|
+
*/
|
|
8
|
+
size?: RatingCounterSize;
|
|
9
|
+
/** Значение рейтинга. */
|
|
10
|
+
value: number;
|
|
11
|
+
/** Количество отзывов. */
|
|
12
|
+
reviewCount: number;
|
|
13
|
+
/** Нужно ли отключить эффект при наведении. */
|
|
14
|
+
hoverDisabled?: boolean;
|
|
15
|
+
/** Идентификатор для систем автоматизированного тестирования. */
|
|
16
|
+
'data-testid'?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare type RatingCounterProps = CustomProps & Omit<HTMLAttributes<HTMLDivElement>, keyof CustomProps>;
|
|
19
|
+
/**
|
|
20
|
+
* Счетчик рейтинга.
|
|
21
|
+
* @param props Свойства.
|
|
22
|
+
* @return Элемент.
|
|
23
|
+
*/
|
|
24
|
+
export declare function RatingCounter({ size, value, reviewCount, className, hoverDisabled, 'data-testid': testId, ...restProps }: RatingCounterProps): JSX.Element;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.RatingCounter = void 0;
|
|
18
|
+
const react_1 = __importDefault(require("react"));
|
|
19
|
+
const star_svg_1 = __importDefault(require("./star.svg"));
|
|
20
|
+
const get_declination_1 = __importDefault(require("@sima-land/ui-nucleons/helpers/get-declination"));
|
|
21
|
+
const bind_1 = __importDefault(require("classnames/bind"));
|
|
22
|
+
const rating_counter_module_scss_1 = __importDefault(require("./rating-counter.module.scss"));
|
|
23
|
+
const cx = bind_1.default.bind(rating_counter_module_scss_1.default);
|
|
24
|
+
/**
|
|
25
|
+
* Счетчик рейтинга.
|
|
26
|
+
* @param props Свойства.
|
|
27
|
+
* @return Элемент.
|
|
28
|
+
*/
|
|
29
|
+
function RatingCounter(_a) {
|
|
30
|
+
var { size = 's', value, reviewCount, className, hoverDisabled, 'data-testid': testId = 'rating-counter' } = _a, restProps = __rest(_a, ["size", "value", "reviewCount", "className", "hoverDisabled", 'data-testid']);
|
|
31
|
+
return (react_1.default.createElement("div", Object.assign({ className: cx('root', `size-${size}`, !(value > 0) && 'empty', hoverDisabled && 'hover-disabled', className), "data-testid": testId }, restProps),
|
|
32
|
+
react_1.default.createElement(star_svg_1.default, { className: cx('star') }),
|
|
33
|
+
value > 0 && react_1.default.createElement("span", { className: cx('value') }, String(value).replace('.', ',')),
|
|
34
|
+
react_1.default.createElement("span", { className: cx('count') }, reviewCount > 0
|
|
35
|
+
? `${reviewCount} ${(0, get_declination_1.default)(reviewCount, ['отзыв', 'отзыва', 'отзывов'])}`
|
|
36
|
+
: 'Нет отзывов')));
|
|
37
|
+
}
|
|
38
|
+
exports.RatingCounter = RatingCounter;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
@mixin size-s {
|
|
2
|
+
--rating-icon-size: 16px;
|
|
3
|
+
--rating-value-size: 12px;
|
|
4
|
+
--rating-value-height: 16px;
|
|
5
|
+
--rating-count-gutter: 8px;
|
|
6
|
+
--rating-count-size: 12px;
|
|
7
|
+
--rating-count-height: 16px;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@mixin size-m {
|
|
11
|
+
--rating-icon-size: 24px;
|
|
12
|
+
--rating-value-size: 16px;
|
|
13
|
+
--rating-value-height: 24px;
|
|
14
|
+
--rating-count-gutter: 8px;
|
|
15
|
+
--rating-count-size: 14px;
|
|
16
|
+
--rating-count-height: 20px;
|
|
17
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
@use 'node_modules/@sima-land/ui-nucleons/colors';
|
|
2
|
+
@use 'node_modules/@sima-land/ui-nucleons/breakpoints';
|
|
3
|
+
@use './rating-counter-util';
|
|
4
|
+
|
|
5
|
+
.root {
|
|
6
|
+
display: inline-flex;
|
|
7
|
+
flex-wrap: nowrap;
|
|
8
|
+
align-items: center;
|
|
9
|
+
white-space: nowrap;
|
|
10
|
+
--rating-icon-color: #{colors.$additional-amber};
|
|
11
|
+
--rating-count-color: #{colors.$basic-gray38};
|
|
12
|
+
&:hover:not(.hover-disabled) {
|
|
13
|
+
cursor: pointer;
|
|
14
|
+
--rating-count-color: #{colors.$basic-gray54};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// модификаторы
|
|
19
|
+
.empty {
|
|
20
|
+
--rating-icon-color: #{colors.$basic-gray12};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.size-s {
|
|
24
|
+
@include rating-counter-util.size-s;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.size-m {
|
|
28
|
+
@include rating-counter-util.size-m;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// составляющие
|
|
32
|
+
.star {
|
|
33
|
+
flex-shrink: 0;
|
|
34
|
+
display: block;
|
|
35
|
+
width: var(--rating-icon-size);
|
|
36
|
+
height: var(--rating-icon-size);
|
|
37
|
+
fill: var(--rating-icon-color);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.value {
|
|
41
|
+
font-weight: 700;
|
|
42
|
+
color: #{colors.$additional-amber};
|
|
43
|
+
font-size: var(--rating-value-size);
|
|
44
|
+
line-height: var(--rating-value-height);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.count {
|
|
48
|
+
overflow: hidden;
|
|
49
|
+
color: var(--rating-count-color);
|
|
50
|
+
font-size: var(--rating-count-size);
|
|
51
|
+
line-height: var(--rating-count-height);
|
|
52
|
+
text-overflow: ellipsis;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// отступы
|
|
56
|
+
.star + .value {
|
|
57
|
+
margin-left: 4px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.star + .count {
|
|
61
|
+
margin-left: var(--rating-count-gutter);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.value + .count {
|
|
65
|
+
margin-left: var(--rating-count-gutter);
|
|
66
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path
|
|
3
|
+
d="M7.53601 1.54543C7.70396 1.12719 8.29603 1.12719 8.46398 1.54543L10.1755 5.80741L14.7577 6.11811C15.2074 6.1486 15.3904 6.71169 15.0445 7.00066L11.52 9.94542L12.6405 14.3994C12.7505 14.8365 12.2715 15.1845 11.8897 14.9449L7.99999 12.5028L4.11024 14.9449C3.72853 15.1845 3.24953 14.8365 3.35949 14.3994L4.47999 9.94542L0.955488 7.00067C0.609623 6.71169 0.792582 6.1486 1.24225 6.11811L5.82451 5.80741L7.53601 1.54543Z"
|
|
4
|
+
fill="#000" />
|
|
5
|
+
</svg>
|
|
@@ -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,
|
|
@@ -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;
|