@sima-land/moleculas 16.0.0-alpha.5 → 16.0.0-alpha.6

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.
Files changed (36) hide show
  1. package/common/components/media-modal/__mocks__/index.js +1 -0
  2. package/common/components/media-modal/parts/all-round-view.js +2 -2
  3. package/common/components/media-modal/parts/index.js +2 -2
  4. package/common/components/media-modal/parts/media-content.d.ts +3 -1
  5. package/common/components/media-modal/parts/media-content.js +20 -5
  6. package/common/components/media-modal/parts/media-view.js +13 -2
  7. package/common/components/media-modal/parts/media-view.module.scss +5 -0
  8. package/common/components/media-modal/parts/product-brief.js +6 -2
  9. package/common/components/media-modal/parts/product-brief.module.scss +5 -0
  10. package/common/components/media-modal/parts/thumbnail.js +9 -5
  11. package/common/components/media-modal/parts/thumbnail.module.scss +5 -0
  12. package/common/components/modifier/index.js +15 -1
  13. package/common/components/modifier/modifiers.module.scss +21 -0
  14. package/common/components/product-info/parts.js +2 -2
  15. package/common/components/rating-counter/index.d.ts +11 -1
  16. package/common/components/rating-counter/index.js +4 -4
  17. package/common/components/rating-counter/rating-counter-util.scss +1 -1
  18. package/common/hooks/index.d.ts +12 -0
  19. package/common/hooks/index.js +23 -0
  20. package/desktop/components/gallery-modal/components/all-round-view.js +13 -6
  21. package/desktop/components/gallery-modal/components/all-round-view.module.scss +5 -0
  22. package/desktop/components/gallery-modal/components/thumbnail.js +2 -2
  23. package/desktop/components/gallery-modal/utils.d.ts +3 -1
  24. package/desktop/components/gallery-modal/utils.js +15 -3
  25. package/desktop/components/promotion-card/index.js +2 -2
  26. package/mobile/components/modifiers-list/index.js +2 -2
  27. package/mobile/components/modifiers-list/modifier-item/index.js +2 -2
  28. package/mobile/components/person-info/index.js +8 -8
  29. package/mobile/components/product-row/index.js +5 -5
  30. package/mobile/components/pseudo-input/index.js +2 -2
  31. package/mobile/components/search-bar/index.js +6 -6
  32. package/mobile/components/select-screen/index.js +2 -2
  33. package/package.json +2 -2
  34. package/common/components/rating-counter/star.svg +0 -5
  35. package/common/icons/eighteen-plus.svg +0 -5
  36. package/common/icons/touch-x.svg +0 -6
@@ -92,6 +92,7 @@ exports.mixed = [
92
92
  type: 'video',
93
93
  data: {
94
94
  src: 'https://cdn2.static1-sima-land.com/flv/3404953.mp4',
95
+ thumbnail: 'https://loremflickr.com/240/240?random=16',
95
96
  },
96
97
  },
97
98
  {
@@ -42,7 +42,7 @@ const react_1 = __importStar(require("react"));
42
42
  const breakpoint_1 = require("@sima-land/ui-nucleons/hooks/breakpoint");
43
43
  const all_round_view_1 = require("../../../../desktop/components/gallery-modal/components/all-round-view");
44
44
  const utils_1 = require("../utils");
45
- const touch_x_svg_1 = __importDefault(require("../../../icons/touch-x.svg"));
45
+ const TouchScrollX_1 = __importDefault(require("@sima-land/ui-quarks/icons/64x64/Colorful/TouchScrollX"));
46
46
  const all_round_view_module_scss_1 = __importDefault(require("./all-round-view.module.scss"));
47
47
  /**
48
48
  * Просмотр 360.
@@ -73,6 +73,6 @@ function AfterMount(_a) {
73
73
  }, []);
74
74
  return (react_1.default.createElement("div", { className: all_round_view_module_scss_1.default.root },
75
75
  !desktop && tutorial && (react_1.default.createElement("div", { className: all_round_view_module_scss_1.default.tutorial, onPointerUp: acceptTutorial },
76
- react_1.default.createElement(touch_x_svg_1.default, null))),
76
+ react_1.default.createElement(TouchScrollX_1.default, null))),
77
77
  react_1.default.createElement(all_round_view_1.AllRoundView, Object.assign({}, props, { controls: desktop, state: state, onStateChange: setState }))));
78
78
  }
@@ -10,11 +10,11 @@ const define_slots_1 = require("@sima-land/ui-nucleons/helpers/define-slots");
10
10
  const breakpoint_1 = require("@sima-land/ui-nucleons/hooks/breakpoint");
11
11
  const utils_1 = require("../utils");
12
12
  const scroll_section_1 = require("./scroll-section");
13
- const left_1 = __importDefault(require("@sima-land/ui-quarks/icons/16x16/Stroked/Arrows/left"));
13
+ const Left_1 = __importDefault(require("@sima-land/ui-quarks/icons/16x16/Stroked/Arrows/Left"));
14
14
  const parts_module_scss_1 = __importDefault(require("./parts.module.scss"));
15
15
  exports.Preset = {
16
16
  headerTabs: (userProps) => (Object.assign({ view: 'clean-underline' }, userProps)),
17
- headerButton: (userProps) => (Object.assign({ size: 's', startIcon: left_1.default, iconGutter: 4, className: parts_module_scss_1.default['header-button'], children: 'Вернуться к основному товару' }, userProps)),
17
+ headerButton: (userProps) => (Object.assign({ size: 's', startIcon: Left_1.default, iconGutter: 4, className: parts_module_scss_1.default['header-button'], children: 'Вернуться к основному товару' }, userProps)),
18
18
  };
19
19
  /**
20
20
  * Формирует layout для шапки модального окна медиа.
@@ -1,10 +1,12 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { MediaData } from '../types';
3
3
  export interface MediaContentProps {
4
- items: MediaData[];
4
+ children?: ReactNode;
5
5
  targetIndex?: number;
6
6
  onChangeTargetIndex?: (newIndex: number) => void;
7
7
  loading?: boolean;
8
+ /** @deprecated */
9
+ items?: MediaData[];
8
10
  }
9
11
  export interface FitSquareProps {
10
12
  children?: ReactNode;
@@ -50,26 +50,28 @@ exports.MediaContent = MediaContent;
50
50
  * @param props Свойства.
51
51
  * @return Элемент.
52
52
  */
53
- function MediaCarousel({ items, targetIndex, onChangeTargetIndex, loading }) {
53
+ function MediaCarousel({ items: itemsProp, children, targetIndex, onChangeTargetIndex, loading, }) {
54
54
  const ref = (0, react_1.useRef)(null);
55
55
  const area = (0, utils_1.useClientRect)(ref);
56
+ const items = toViewPropsList(itemsProp, children);
56
57
  return (react_1.default.createElement("div", { ref: ref, className: media_content_module_scss_1.default.carousel }, area.ready && (react_1.default.createElement(carousel_1.Carousel, { infinite: false, targetIndex: targetIndex, onChangeTargetIndex: onChangeTargetIndex, draggable: true, containerProps: {
57
58
  className: media_content_module_scss_1.default.carousel,
58
59
  // в случае если будет работать некорректно - дать возможность задавать пропсы для Carousel
59
60
  [page_scroll_lock_1.BSL_IGNORE_ATTR]: true,
60
- }, withControls: false, items: items, renderItem: data => (react_1.default.createElement("div", { className: media_content_module_scss_1.default['carousel-item'] },
61
+ }, withControls: false, items: items, renderItem: (props) => (react_1.default.createElement("div", { className: media_content_module_scss_1.default['carousel-item'] },
61
62
  react_1.default.createElement(FitSquare, Object.assign({}, area),
62
- react_1.default.createElement(media_view_1.MediaView, { media: data, loading: loading })))) }))));
63
+ react_1.default.createElement(media_view_1.MediaView, Object.assign({ loading: loading }, props))))) }))));
63
64
  }
64
65
  /**
65
66
  * Отображает медиа-контент в виде слайдера.
66
67
  * @param props Свойства.
67
68
  * @return Элемент.
68
69
  */
69
- function MediaSlider({ items, targetIndex, onChangeTargetIndex, loading }) {
70
+ function MediaSlider({ items: itemsProp, children, targetIndex, onChangeTargetIndex, loading, }) {
70
71
  const [position, setPosition] = (0, react_1.useState)(0);
71
72
  const ref = (0, react_1.useRef)(null);
72
73
  const area = (0, utils_1.useClientRect)(ref);
74
+ const items = toViewPropsList(itemsProp, children);
73
75
  const total = items.length;
74
76
  const controls = total > 1;
75
77
  const correction = controls ? -(2 * (56 + 24)) : 0;
@@ -85,13 +87,26 @@ function MediaSlider({ items, targetIndex, onChangeTargetIndex, loading }) {
85
87
  onChangeTargetIndex === null || onChangeTargetIndex === void 0 ? void 0 : onChangeTargetIndex(next);
86
88
  } })),
87
89
  react_1.default.createElement(FitSquare, { width: area.width + correction, height: area.height },
88
- react_1.default.createElement(media_view_1.MediaView, { media: items[position], loading: loading })),
90
+ react_1.default.createElement(media_view_1.MediaView, Object.assign({ loading: loading }, items[position]))),
89
91
  controls && (react_1.default.createElement(arrow_button_1.ArrowButton, { direction: 'right', onClick: () => {
90
92
  const next = (position + 1) % total;
91
93
  setPosition(next);
92
94
  onChangeTargetIndex === null || onChangeTargetIndex === void 0 ? void 0 : onChangeTargetIndex(next);
93
95
  } }))))));
94
96
  }
97
+ /**
98
+ * Получив пропсы items и children вернет массив пропсов для MediaView.
99
+ * @param items Проп items.
100
+ * @param children Проп children.
101
+ * @return Массив пропсов для MediaVuew.
102
+ */
103
+ function toViewPropsList(items, children) {
104
+ var _a;
105
+ return ((_a = items === null || items === void 0 ? void 0 : items.map(media => ({ media }))) !== null && _a !== void 0 ? _a : react_1.Children.toArray(children).reduce((acc, item) => {
106
+ (0, react_1.isValidElement)(item) && item.type === media_view_1.MediaView && acc.push(item.props);
107
+ return acc;
108
+ }, []));
109
+ }
95
110
  /**
96
111
  * Вписывает квадрат в заданную прямоугольную область.
97
112
  * @param props Свойства.
@@ -30,9 +30,11 @@ exports.MediaView = void 0;
30
30
  const react_1 = __importStar(require("react"));
31
31
  const image_overlay_1 = require("../../../../desktop/components/gallery-modal/components/image-overlay");
32
32
  const breakpoint_1 = require("@sima-land/ui-nucleons/hooks/breakpoint");
33
- const media_view_module_scss_1 = __importDefault(require("./media-view.module.scss"));
34
33
  const classnames_1 = __importDefault(require("classnames"));
35
34
  const all_round_view_1 = require("./all-round-view");
35
+ const image_broken_svg_1 = __importDefault(require("../../../icons/image-broken.svg"));
36
+ const media_view_module_scss_1 = __importDefault(require("./media-view.module.scss"));
37
+ const hooks_1 = require("../../../hooks");
36
38
  /**
37
39
  * Отображает медиа-контент - 360, видео или изображение.
38
40
  * @param props Свойства.
@@ -40,6 +42,14 @@ const all_round_view_1 = require("./all-round-view");
40
42
  */
41
43
  function MediaView({ media, loading, videoProps }) {
42
44
  const desktop = (0, breakpoint_1.useBreakpoint)('xs+');
45
+ let imageSrc = undefined;
46
+ if ((media === null || media === void 0 ? void 0 : media.type) === 'image') {
47
+ imageSrc = media.data.src;
48
+ }
49
+ else if ((media === null || media === void 0 ? void 0 : media.type) === 'video') {
50
+ imageSrc = media.data.thumbnail;
51
+ }
52
+ const { failed, handleError } = (0, hooks_1.useImageStub)(imageSrc);
43
53
  const videoRef = (0, react_1.useRef)(null);
44
54
  const videoSrc = (media === null || media === void 0 ? void 0 : media.type) === 'video' ? media.data.src : null;
45
55
  (0, react_1.useEffect)(() => {
@@ -54,7 +64,8 @@ function MediaView({ media, loading, videoProps }) {
54
64
  }
55
65
  return (react_1.default.createElement("div", { className: (0, classnames_1.default)(media_view_module_scss_1.default.root) },
56
66
  (media === null || media === void 0 ? void 0 : media.type) === 'image' && (react_1.default.createElement(image_overlay_1.ImageOverlay, { className: media_view_module_scss_1.default.image },
57
- react_1.default.createElement("img", { src: media.data.src, alt: media.data.alt || '' }))),
67
+ failed && react_1.default.createElement(image_broken_svg_1.default, null),
68
+ !failed && react_1.default.createElement("img", { src: media.data.src, alt: media.data.alt || '', onError: handleError }))),
58
69
  (media === null || media === void 0 ? void 0 : media.type) === 'video' && (react_1.default.createElement("video", Object.assign({ autoPlay: false, controls: true, controlsList: 'nodownload' }, videoProps, { ref: videoRef }),
59
70
  react_1.default.createElement("source", { src: media.data.src }))),
60
71
  (media === null || media === void 0 ? void 0 : media.type) === '360' && react_1.default.createElement(all_round_view_1.AllRoundView, { photos: media.data.photos, controls: desktop })));
@@ -27,4 +27,9 @@
27
27
  height: 100%;
28
28
  object-fit: contain;
29
29
  }
30
+ .image svg {
31
+ display: block;
32
+ width: 100%;
33
+ height: 100%;
34
+ }
30
35
  }
@@ -18,9 +18,11 @@ exports.ProductBrief = void 0;
18
18
  const react_1 = __importDefault(require("react"));
19
19
  const image_overlay_1 = require("../../../../desktop/components/gallery-modal/components/image-overlay");
20
20
  const price_1 = require("@sima-land/ui-nucleons/price");
21
+ const breakpoint_1 = require("@sima-land/ui-nucleons/hooks/breakpoint");
22
+ const hooks_1 = require("../../../hooks");
21
23
  const bind_1 = __importDefault(require("classnames/bind"));
24
+ const image_broken_svg_1 = __importDefault(require("../../../icons/image-broken.svg"));
22
25
  const product_brief_module_scss_1 = __importDefault(require("./product-brief.module.scss"));
23
- const breakpoint_1 = require("@sima-land/ui-nucleons/hooks/breakpoint");
24
26
  const cx = bind_1.default.bind(product_brief_module_scss_1.default);
25
27
  /**
26
28
  * Блок товара-рекомендации.
@@ -30,6 +32,7 @@ const cx = bind_1.default.bind(product_brief_module_scss_1.default);
30
32
  function ProductBrief(_a) {
31
33
  var { size: sizeProp, imageSrc, title, price, currency, footer, className, href, onLinkClick, loading } = _a, restProps = __rest(_a, ["size", "imageSrc", "title", "price", "currency", "footer", "className", "href", "onLinkClick", "loading"]);
32
34
  const desktop = (0, breakpoint_1.useBreakpoint)('xs+');
35
+ const { failed, handleError } = (0, hooks_1.useImageStub)(imageSrc);
33
36
  const size = (sizeProp !== null && sizeProp !== void 0 ? sizeProp : desktop) ? 'l' : 's';
34
37
  if (loading) {
35
38
  return react_1.default.createElement(ProductBriefSkeleton, { size: size });
@@ -37,7 +40,8 @@ function ProductBrief(_a) {
37
40
  return (react_1.default.createElement("div", Object.assign({ className: cx('root', `size-${size}`, className) }, restProps),
38
41
  react_1.default.createElement("a", { className: product_brief_module_scss_1.default.image, href: href, onClick: onLinkClick },
39
42
  react_1.default.createElement(image_overlay_1.ImageOverlay, { className: product_brief_module_scss_1.default.overlay },
40
- react_1.default.createElement("img", { src: imageSrc }))),
43
+ failed && react_1.default.createElement(image_broken_svg_1.default, null),
44
+ !failed && react_1.default.createElement("img", { src: imageSrc, onError: handleError }))),
41
45
  react_1.default.createElement("div", { className: product_brief_module_scss_1.default.info },
42
46
  react_1.default.createElement("a", { className: product_brief_module_scss_1.default.title, href: href, onClick: onLinkClick }, title),
43
47
  price && react_1.default.createElement(price_1.Price, { className: product_brief_module_scss_1.default.price, value: price, currencyGrapheme: currency })),
@@ -15,6 +15,11 @@
15
15
  height: 100%;
16
16
  object-fit: contain;
17
17
  }
18
+ > svg {
19
+ display: block;
20
+ width: 100%;
21
+ height: 100%;
22
+ }
18
23
  }
19
24
  }
20
25
 
@@ -29,11 +29,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.Thumbnail = exports.ThumbnailContext = void 0;
30
30
  const react_1 = __importStar(require("react"));
31
31
  const image_overlay_1 = require("../../../../desktop/components/gallery-modal/components/image-overlay");
32
- const play_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Filled/play"));
32
+ const Play_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Filled/Play"));
33
33
  const _360_svg_1 = __importDefault(require("../../../../desktop/components/gallery-modal/icons/360.svg"));
34
+ const price_1 = require("@sima-land/ui-nucleons/price");
35
+ const hooks_1 = require("../../../hooks");
34
36
  const bind_1 = __importDefault(require("classnames/bind"));
37
+ const image_broken_svg_1 = __importDefault(require("../../../icons/image-broken.svg"));
35
38
  const thumbnail_module_scss_1 = __importDefault(require("./thumbnail.module.scss"));
36
- const price_1 = require("@sima-land/ui-nucleons/price");
37
39
  exports.ThumbnailContext = (0, react_1.createContext)({});
38
40
  const cx = bind_1.default.bind(thumbnail_module_scss_1.default);
39
41
  /**
@@ -44,6 +46,7 @@ const cx = bind_1.default.bind(thumbnail_module_scss_1.default);
44
46
  function Thumbnail({ size: sizeFromProps, type, src, alt, checked, onClick, className, loading, title, price, currency, }) {
45
47
  var _a;
46
48
  const { size: sizeFromContext } = (0, react_1.useContext)(exports.ThumbnailContext);
49
+ const { failed, handleError } = (0, hooks_1.useImageStub)(src);
47
50
  const size = (_a = sizeFromProps !== null && sizeFromProps !== void 0 ? sizeFromProps : sizeFromContext) !== null && _a !== void 0 ? _a : 'l';
48
51
  const rootClassName = cx('root', `size-${size}`, (type === null || type === void 0 ? void 0 : type.startsWith('icon-')) && 'iconic', checked && 'checked', loading && 'loading', className);
49
52
  if (loading) {
@@ -54,10 +57,11 @@ function Thumbnail({ size: sizeFromProps, type, src, alt, checked, onClick, clas
54
57
  return (react_1.default.createElement("button", { className: rootClassName, onClick: onClick, "data-testid": 'thumbnail' },
55
58
  react_1.default.createElement("span", { className: cx('content') },
56
59
  (type === null || type === void 0 ? void 0 : type.startsWith('preview-')) && (react_1.default.createElement(image_overlay_1.ImageOverlay, { className: cx('image') },
57
- react_1.default.createElement("img", { src: src, alt: alt }))),
58
- type === 'preview-video' && react_1.default.createElement("span", { className: cx('play') }),
60
+ failed && react_1.default.createElement(image_broken_svg_1.default, null),
61
+ !failed && react_1.default.createElement("img", { src: src, alt: alt, onError: handleError }))),
62
+ !failed && type === 'preview-video' && react_1.default.createElement("span", { className: cx('play') }),
59
63
  type === 'icon-360' && react_1.default.createElement(_360_svg_1.default, { fill: 'currentColor' }),
60
- type === 'icon-video' && react_1.default.createElement(play_1.default, { width: 32, height: 32, fill: 'currentColor' })),
64
+ type === 'icon-video' && react_1.default.createElement(Play_1.default, { width: 32, height: 32, fill: 'currentColor' })),
61
65
  (title || price) && (react_1.default.createElement("span", { className: cx('info') },
62
66
  title && react_1.default.createElement("span", { className: cx('title') }, title),
63
67
  price && react_1.default.createElement(price_1.Price, { className: cx('price'), value: price, currencyGrapheme: currency })))));
@@ -98,6 +98,11 @@
98
98
  height: 100%;
99
99
  object-fit: contain;
100
100
  }
101
+ > svg {
102
+ display: block;
103
+ width: 100%;
104
+ height: 100%;
105
+ }
101
106
  }
102
107
  &::after {
103
108
  content: '';
@@ -40,8 +40,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
40
40
  exports.MoreButton = exports.Modifier = void 0;
41
41
  const react_1 = __importStar(require("react"));
42
42
  const hint_1 = require("@sima-land/ui-nucleons/hint");
43
+ const ImageBroken_1 = __importDefault(require("@sima-land/ui-quarks/icons/40x40/Stroked/ImageBroken"));
43
44
  const bind_1 = __importDefault(require("classnames/bind"));
44
45
  const modifiers_module_scss_1 = __importDefault(require("./modifiers.module.scss"));
46
+ const hooks_1 = require("../../hooks");
45
47
  const cx = bind_1.default.bind(modifiers_module_scss_1.default);
46
48
  /**
47
49
  * Кнопка модификатора (аналога товара).
@@ -74,7 +76,7 @@ function Modifier(_a) {
74
76
  return (react_1.default.createElement(react_1.default.Fragment, null,
75
77
  react_1.default.createElement("a", Object.assign({}, props, { className: cx('root', `size-${size}`, { active, disabled }, className), "data-testid": testId }),
76
78
  content.type === 'color' && (react_1.default.createElement("span", { className: cx('color'), role: 'banner', style: { background: content.color } })),
77
- content.type === 'image' && (react_1.default.createElement("span", { className: cx('image'), role: 'banner', style: { backgroundImage: `url(${content.src})` } })),
79
+ content.type === 'image' && react_1.default.createElement(Image, { src: content.src }),
78
80
  content.type === 'text' && (react_1.default.createElement("span", Object.assign({ ref: refs.setReference, className: cx('text') }, getReferenceProps()), content.text)),
79
81
  typeof count === 'number' && (react_1.default.createElement("span", { className: cx('counter') }, count > 99 ? '99+' : count)),
80
82
  crossedOut && (react_1.default.createElement("svg", { width: '100%', height: '100%', className: cx('diagonal') },
@@ -83,6 +85,18 @@ function Modifier(_a) {
83
85
  hint && (react_1.default.createElement(hint_1.Hint, Object.assign({ open: open, hintRef: refs.setFloating, arrowRef: refs.setArrow }, getFloatingProps()), hint))));
84
86
  }
85
87
  exports.Modifier = Modifier;
88
+ /**
89
+ * Картинка с заглушкой в случае ошибки загрузки.
90
+ * @param props Свойства.
91
+ * @return Элемент.
92
+ */
93
+ function Image(_a) {
94
+ var { src, onError } = _a, rest = __rest(_a, ["src", "onError"]);
95
+ const { failed, handleError } = (0, hooks_1.useImageStub)(src, onError);
96
+ return (react_1.default.createElement("span", { className: cx('image-wrapper', { fail: failed }) },
97
+ failed && react_1.default.createElement(ImageBroken_1.default, null),
98
+ react_1.default.createElement("img", Object.assign({ className: cx('image') }, rest, { src: src, onError: handleError }))));
99
+ }
86
100
  /**
87
101
  * Кнопка "+N" для показа полного списка модификаторов.
88
102
  * @param props Свойства.
@@ -97,6 +97,27 @@
97
97
  background-size: cover;
98
98
  }
99
99
 
100
+ .image-wrapper {
101
+ border-radius: inherit;
102
+ display: flex;
103
+ align-items: center;
104
+ justify-content: center;
105
+ position: absolute;
106
+ top: 0;
107
+ left: 0;
108
+ width: 100%;
109
+ height: 100%;
110
+ background: colors.$basic-gray4;
111
+ &.fail {
112
+ --modifier-media-opacity: 0;
113
+ }
114
+ > svg {
115
+ width: calc(48%);
116
+ height: calc(48%);
117
+ fill: colors.$basic-gray24;
118
+ }
119
+ }
120
+
100
121
  .text {
101
122
  padding: var(--modifier-padding);
102
123
  display: block;
@@ -47,7 +47,7 @@ const image_overlay_1 = require("../../../desktop/components/gallery-modal/compo
47
47
  const badge_list_1 = require("../badge-list");
48
48
  const utils_1 = require("./utils");
49
49
  const rating_counter_1 = require("../rating-counter");
50
- const eighteen_plus_svg_1 = __importDefault(require("../../icons/eighteen-plus.svg"));
50
+ const EighteenPlus_1 = __importDefault(require("@sima-land/ui-quarks/icons/64x64/Stroked/EighteenPlus"));
51
51
  const image_broken_svg_1 = __importDefault(require("../../icons/image-broken.svg"));
52
52
  const bind_1 = __importDefault(require("classnames/bind"));
53
53
  const product_info_module_scss_1 = __importDefault(require("./product-info.module.scss"));
@@ -81,7 +81,7 @@ const Image = ({ src, alt, href, onClick, children, opacity }) => {
81
81
  (0, react_1.useEffect)(() => setBroken(false), [src]);
82
82
  return (react_1.default.createElement(image_overlay_1.ImageOverlay, { className: cx('image-overlay') }, restriction === 'adult' ? (react_1.default.createElement(react_1.default.Fragment, null,
83
83
  react_1.default.createElement("img", { onError: () => setBroken(true), alt: alt, src: src, className: cx('image', 'adult', { broken }), "data-testid": 'product-info:adult-image' }),
84
- react_1.default.createElement(eighteen_plus_svg_1.default, { className: cx('adult-icon') }))) : (react_1.default.createElement(react_1.default.Fragment, null,
84
+ react_1.default.createElement(EighteenPlus_1.default, { className: cx('adult-icon') }))) : (react_1.default.createElement(react_1.default.Fragment, null,
85
85
  react_1.default.createElement("a", { href: href, className: cx('image-link'), onClick: onClick, "data-testid": 'product-info:image-link' },
86
86
  react_1.default.createElement("img", { onError: () => setBroken(true), alt: alt, src: src, className: cx('image', { broken }), style: { opacity: typeof opacity === 'number' ? opacity : defaultOpacity }, "data-testid": 'product-info:image' }),
87
87
  broken && react_1.default.createElement(image_broken_svg_1.default, { className: cx('broken-icon') })),
@@ -1,5 +1,13 @@
1
- import { HTMLAttributes } from 'react';
1
+ import { CSSProperties, HTMLAttributes } from 'react';
2
2
  export type RatingCounterSize = 's' | 'm' | 'unset';
3
+ export interface RatingCounterStyle extends CSSProperties {
4
+ '--rating-icon-size'?: string;
5
+ '--rating-value-size'?: string;
6
+ '--rating-value-height'?: string;
7
+ '--rating-count-gutter'?: string;
8
+ '--rating-count-size'?: string;
9
+ '--rating-count-height'?: string;
10
+ }
3
11
  interface CustomProps {
4
12
  /**
5
13
  * Размер.
@@ -12,6 +20,8 @@ interface CustomProps {
12
20
  reviewCount: number;
13
21
  /** Нужно ли отключить эффект при наведении. */
14
22
  hoverDisabled?: boolean;
23
+ /** Стили корневого элемента. */
24
+ style?: RatingCounterStyle;
15
25
  /** Идентификатор для систем автоматизированного тестирования. */
16
26
  'data-testid'?: string;
17
27
  }
@@ -16,8 +16,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.RatingCounter = void 0;
18
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"));
19
+ const Star_1 = __importDefault(require("@sima-land/ui-quarks/icons/16x16/Filled/Star"));
20
+ const get_declination_1 = require("@sima-land/ui-nucleons/helpers/get-declination");
21
21
  const bind_1 = __importDefault(require("classnames/bind"));
22
22
  const rating_counter_module_scss_1 = __importDefault(require("./rating-counter.module.scss"));
23
23
  const cx = bind_1.default.bind(rating_counter_module_scss_1.default);
@@ -29,10 +29,10 @@ const cx = bind_1.default.bind(rating_counter_module_scss_1.default);
29
29
  function RatingCounter(_a) {
30
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
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') }),
32
+ react_1.default.createElement(Star_1.default, { className: cx('star') }),
33
33
  value > 0 && react_1.default.createElement("span", { className: cx('value') }, String(value).replace('.', ',')),
34
34
  react_1.default.createElement("span", { className: cx('count') }, reviewCount > 0
35
- ? `${reviewCount} ${(0, get_declination_1.default)(reviewCount, ['отзыв', 'отзыва', 'отзывов'])}`
35
+ ? `${reviewCount} ${(0, get_declination_1.getDeclination)(reviewCount, ['отзыв', 'отзыва', 'отзывов'])}`
36
36
  : 'Нет отзывов')));
37
37
  }
38
38
  exports.RatingCounter = RatingCounter;
@@ -11,7 +11,7 @@
11
11
  --rating-icon-size: 24px;
12
12
  --rating-value-size: 16px;
13
13
  --rating-value-height: 24px;
14
- --rating-count-gutter: 8px;
14
+ --rating-count-gutter: 12px;
15
15
  --rating-count-size: 14px;
16
16
  --rating-count-height: 20px;
17
17
  }
@@ -0,0 +1,12 @@
1
+ import { ReactEventHandler } from 'react';
2
+ /**
3
+ * Хук состояния ошибки загрузки изображения.
4
+ * @param src Ссылка на картинку.
5
+ * @param onError Обработчик ошибки.
6
+ * @return Управление состоянием.
7
+ */
8
+ export declare function useImageStub(src?: string, onError?: ReactEventHandler<HTMLImageElement>): {
9
+ failed: boolean;
10
+ setFailed: import("react").Dispatch<import("react").SetStateAction<boolean>>;
11
+ handleError: ReactEventHandler<HTMLImageElement>;
12
+ };
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useImageStub = void 0;
4
+ const hooks_1 = require("@sima-land/ui-nucleons/hooks");
5
+ const react_1 = require("react");
6
+ /**
7
+ * Хук состояния ошибки загрузки изображения.
8
+ * @param src Ссылка на картинку.
9
+ * @param onError Обработчик ошибки.
10
+ * @return Управление состоянием.
11
+ */
12
+ function useImageStub(src, onError) {
13
+ const [failed, setFailed] = (0, react_1.useState)(false);
14
+ (0, hooks_1.useIsomorphicLayoutEffect)(() => {
15
+ setFailed(false);
16
+ }, [src]);
17
+ const handleError = (0, react_1.useCallback)(event => {
18
+ setFailed(true);
19
+ onError === null || onError === void 0 ? void 0 : onError(event);
20
+ }, [onError]);
21
+ return { failed, setFailed, handleError };
22
+ }
23
+ exports.useImageStub = useImageStub;
@@ -38,6 +38,7 @@ const _360_svg_1 = __importDefault(require("../icons/360.svg"));
38
38
  const pause_svg_1 = __importDefault(require("../icons/pause.svg"));
39
39
  const turn_left_svg_1 = __importDefault(require("../icons/turn-left.svg"));
40
40
  const turn_right_svg_1 = __importDefault(require("../icons/turn-right.svg"));
41
+ const image_broken_svg_1 = __importDefault(require("../../../../common/icons/image-broken.svg"));
41
42
  const cx = bind_1.default.bind(all_round_view_module_scss_1.default);
42
43
  /**
43
44
  * 3д-просмотр.
@@ -55,23 +56,28 @@ const AllRoundView = ({ photos, controls = true, state: stateProp = 'autoplay',
55
56
  const ChangeState = (bindState) => () => setState(bindState);
56
57
  const [index, setIndex] = (0, react_1.useState)(0);
57
58
  const indexRef = (0, identity_1.useIdentityRef)(index);
58
- const photosReady = (0, utils_1.useImagesLoad)(photos);
59
+ const imagesStatus = (0, utils_1.useImagesLoad)(photos);
60
+ const ready = imagesStatus === 'done';
61
+ const failed = imagesStatus === 'fail';
59
62
  // запуск/остановка вращения
60
63
  (0, react_1.useEffect)(() => {
61
- if (state !== 'default' && photosReady) {
64
+ if (state !== 'default' && ready) {
62
65
  const timerId = window.setInterval(() => {
63
66
  const increment = state === 'turn-left' ? -1 : 1;
64
67
  setIndex((photos.length + (indexRef.current + increment)) % photos.length);
65
68
  }, 1000 / 30);
66
69
  return () => window.clearInterval(timerId);
67
70
  }
68
- }, [state, photosReady]);
71
+ }, [state, ready]);
69
72
  // перетаскивание
70
73
  (0, react_1.useEffect)(() => {
71
74
  // переданное число всегда замениться на такое, которое будет в промежутке от 0 до количества фото
72
75
  // eslint-disable-next-line require-jsdoc
73
76
  const wrap = (value) => (photos.length + value) % photos.length;
74
77
  const image = imageRef.current;
78
+ if (!image) {
79
+ return;
80
+ }
75
81
  const offList = [
76
82
  (0, on_1.default)(image, 'pointerdown', e => {
77
83
  e.preventDefault();
@@ -101,7 +107,7 @@ const AllRoundView = ({ photos, controls = true, state: stateProp = 'autoplay',
101
107
  }),
102
108
  ];
103
109
  return () => offList.forEach(fn => fn());
104
- }, [photos.length]);
110
+ }, [photos.length, failed]);
105
111
  const HINT = (react_1.default.createElement(react_1.default.Fragment, null,
106
112
  "\u0412\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u0432\u0440\u0430\u0449\u0430\u0442\u044C \u0442\u043E\u0432\u0430\u0440,",
107
113
  react_1.default.createElement("br", null),
@@ -109,8 +115,9 @@ const AllRoundView = ({ photos, controls = true, state: stateProp = 'autoplay',
109
115
  react_1.default.createElement("br", null),
110
116
  "\u043C\u044B\u0448\u0438 \u043D\u0430 \u0444\u043E\u0442\u043E\u0433\u0440\u0430\u0444\u0438\u0438"));
111
117
  return (react_1.default.createElement("div", { className: cx('root') },
112
- react_1.default.createElement("img", { "data-testid": 'gallery-modal:360-current-photo', ref: imageRef, src: photos[index] }),
113
- controls && (react_1.default.createElement("div", { className: cx('controls') },
118
+ failed && react_1.default.createElement(image_broken_svg_1.default, { className: cx('stub') }),
119
+ !failed && (react_1.default.createElement("img", { "data-testid": 'gallery-modal:360-current-photo', ref: imageRef, src: photos[index] })),
120
+ !failed && controls && (react_1.default.createElement("div", { className: cx('controls') },
114
121
  react_1.default.createElement("button", { className: cx('control', 'turn'), disabled: autoplay, onPointerDown: ChangeState('turn-left'), onPointerUp: ChangeState('default'), onPointerLeave: ChangeState('default'), "data-testid": 'gallery-modal:360-turn-left-button' },
115
122
  react_1.default.createElement(turn_right_svg_1.default, null)),
116
123
  react_1.default.createElement(with_hint_1.WithHint, { hint: HINT }, (ref, toggleHint) => (react_1.default.createElement("button", { ref: ref, className: cx('control', 'primary', autoplay && 'pause'), onClick: () => {
@@ -11,6 +11,11 @@
11
11
  width: 100%;
12
12
  height: 100%;
13
13
  }
14
+ .stub {
15
+ display: block;
16
+ width: 100%;
17
+ height: 100%;
18
+ }
14
19
  }
15
20
 
16
21
  .controls {
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Thumbnail = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const image_overlay_1 = require("./image-overlay");
9
- const play_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Filled/play"));
9
+ const Play_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Filled/Play"));
10
10
  const bind_1 = __importDefault(require("classnames/bind"));
11
11
  const thumbnail_module_scss_1 = __importDefault(require("./thumbnail.module.scss"));
12
12
  const _360_svg_1 = __importDefault(require("../icons/360.svg"));
@@ -18,7 +18,7 @@ const cx = bind_1.default.bind(thumbnail_module_scss_1.default);
18
18
  */
19
19
  const Thumbnail = ({ type, src, alt, checked, onClick, className }) => (react_1.default.createElement("button", { className: cx('root', type !== 'image' && 'iconic', checked && 'checked', className), onClick: onClick, "data-testid": 'gallery-modal:thumbnail' },
20
20
  type === '360' && react_1.default.createElement(_360_svg_1.default, { fill: 'currentColor' }),
21
- type === 'video' && react_1.default.createElement(play_1.default, { width: 32, height: 32, fill: 'currentColor' }),
21
+ type === 'video' && react_1.default.createElement(Play_1.default, { width: 32, height: 32, fill: 'currentColor' }),
22
22
  src && (react_1.default.createElement(image_overlay_1.ImageOverlay, { className: cx('image-overlay') },
23
23
  react_1.default.createElement("img", { src: src, alt: alt })))));
24
24
  exports.Thumbnail = Thumbnail;
@@ -1,10 +1,11 @@
1
1
  import React from 'react';
2
+ type Status = 'load' | 'done' | 'fail';
2
3
  /**
3
4
  * Хук, вернет true когда все фото будут загружен.
4
5
  * @param srcList Список адресов фото.
5
6
  * @return Загружены ли все фото.
6
7
  */
7
- export declare const useImagesLoad: (srcList: string[]) => boolean;
8
+ export declare function useImagesLoad(srcList: string[]): Status;
8
9
  /**
9
10
  * Хук, вернет размер квадрата вписанного в область окна галереи фото по макетам.
10
11
  * @param areaRef Реф с элементом.
@@ -14,3 +15,4 @@ export declare const useImagesLoad: (srcList: string[]) => boolean;
14
15
  export declare const useSquareFit: (areaRef: React.RefObject<HTMLDivElement | null>, { hasReview }: {
15
16
  hasReview: boolean;
16
17
  }) => number | null;
18
+ export {};
@@ -6,23 +6,35 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.useSquareFit = exports.useImagesLoad = void 0;
7
7
  const react_1 = require("react");
8
8
  const on_1 = __importDefault(require("@sima-land/ui-nucleons/helpers/on"));
9
+ const hooks_1 = require("@sima-land/ui-nucleons/hooks");
9
10
  /**
10
11
  * Хук, вернет true когда все фото будут загружен.
11
12
  * @param srcList Список адресов фото.
12
13
  * @return Загружены ли все фото.
13
14
  */
14
- const useImagesLoad = (srcList) => {
15
+ function useImagesLoad(srcList) {
16
+ const [failed, setFailed] = (0, react_1.useState)(false);
15
17
  const [loadedCount, setLoadedCount] = (0, react_1.useState)(0);
18
+ (0, hooks_1.useIsomorphicLayoutEffect)(() => {
19
+ setFailed(false);
20
+ }, srcList);
16
21
  (0, react_1.useEffect)(() => {
17
22
  srcList.forEach(src => {
18
23
  const image = new Image();
19
24
  image.onload = () => setLoadedCount(c => c + 1);
25
+ image.onerror = () => setFailed(true);
20
26
  image.src = src;
21
27
  });
22
28
  return () => setLoadedCount(0);
23
29
  }, srcList);
24
- return loadedCount === srcList.length;
25
- };
30
+ if (loadedCount === srcList.length) {
31
+ return 'done';
32
+ }
33
+ if (failed) {
34
+ return 'fail';
35
+ }
36
+ return 'load';
37
+ }
26
38
  exports.useImagesLoad = useImagesLoad;
27
39
  /**
28
40
  * Хук, вернет размер квадрата вписанного в область окна галереи фото по макетам.
@@ -41,7 +41,7 @@ exports.PromotionCard = void 0;
41
41
  const react_1 = __importStar(require("react"));
42
42
  const banner_title_1 = require("./banner-title");
43
43
  const estimate_1 = require("./estimate");
44
- const watch_1 = __importDefault(require("@sima-land/ui-quarks/icons/16x16/Stroked/watch"));
44
+ const Watch_1 = __importDefault(require("@sima-land/ui-quarks/icons/16x16/Stroked/Watch"));
45
45
  const classnames_1 = __importDefault(require("classnames"));
46
46
  const index_module_scss_1 = __importDefault(require("./index.module.scss"));
47
47
  const placeholder_1 = require("./placeholder");
@@ -77,7 +77,7 @@ const PromotionCard = (_a) => {
77
77
  subtitle && react_1.default.createElement("p", { className: index_module_scss_1.default.subtitle }, subtitle)),
78
78
  react_1.default.createElement("div", { className: index_module_scss_1.default.footer },
79
79
  mounted && (react_1.default.createElement("time", { className: index_module_scss_1.default.timer, "data-testid": 'promotion-card:due-date' },
80
- react_1.default.createElement(watch_1.default, { className: index_module_scss_1.default['timer-svg'] }),
80
+ react_1.default.createElement(Watch_1.default, { className: index_module_scss_1.default['timer-svg'] }),
81
81
  react_1.default.createElement(estimate_1.Estimate, { dueDate: dueDate }))),
82
82
  postfix && (react_1.default.createElement("div", { "data-testid": 'promotion-card:postfix', className: index_module_scss_1.default.postfix }, postfix)))))));
83
83
  };
@@ -7,7 +7,7 @@ exports.ModifiersList = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const modifier_item_1 = require("./modifier-item");
9
9
  const link_1 = require("@sima-land/ui-nucleons/link");
10
- const statement_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/statement"));
10
+ const Statement_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/Statement"));
11
11
  const modifiers_list_module_scss_1 = __importDefault(require("./modifiers-list.module.scss"));
12
12
  const bind_1 = __importDefault(require("classnames/bind"));
13
13
  const cx = bind_1.default.bind(modifiers_list_module_scss_1.default);
@@ -20,6 +20,6 @@ const ModifiersList = ({ items, currencyGrapheme, sizesTableUrl, wrapperProps, i
20
20
  sizesTableUrl && (react_1.default.createElement("div", { className: cx('sizes-table-wrapper') },
21
21
  react_1.default.createElement(link_1.Link, { className: cx('sizes-table-link'), href: sizesTableUrl },
22
22
  "\u0422\u0430\u0431\u043B\u0438\u0446\u0430 \u0440\u0430\u0437\u043C\u0435\u0440\u043E\u0432",
23
- react_1.default.createElement(statement_1.default, { role: 'presentation', className: cx('sizes-table-icon') })))),
23
+ react_1.default.createElement(Statement_1.default, { role: 'presentation', className: cx('sizes-table-icon') })))),
24
24
  Array.isArray(items) && (react_1.default.createElement("div", Object.assign({}, itemsContainerProps), items.map((item, index) => (react_1.default.createElement(modifier_item_1.ModifierItem, Object.assign({ key: index }, item, { onClick: () => onItemClick && onItemClick(item), currencyGrapheme: currencyGrapheme }))))))));
25
25
  exports.ModifiersList = ModifiersList;
@@ -9,7 +9,7 @@ const modifier_item_module_scss_1 = __importDefault(require("./modifier-item.mod
9
9
  const bind_1 = __importDefault(require("classnames/bind"));
10
10
  const price_1 = require("@sima-land/ui-nucleons/price");
11
11
  const text_1 = require("@sima-land/ui-nucleons/text");
12
- const check_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/check"));
12
+ const Check_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/Check"));
13
13
  const constants_1 = require("../../../../common/constants");
14
14
  exports.cx = bind_1.default.bind(modifier_item_module_scss_1.default);
15
15
  /**
@@ -34,5 +34,5 @@ const ModifierItem = ({ name, selected, type = 'text', color, image, price, curr
34
34
  Boolean(price) && (react_1.default.createElement(price_1.Price, { value: price, currencyGrapheme: currencyGrapheme, className: (0, exports.cx)('price', additionalText && 'additional') })),
35
35
  Boolean(additionalText) && (react_1.default.createElement(text_1.Text, { color: 'basic-gray38', children: additionalText, size: 12, lineHeight: 16 }))),
36
36
  react_1.default.createElement("div", { className: (0, exports.cx)('icon-wrapper') }, selected && (react_1.default.createElement("div", { className: (0, exports.cx)('icon') },
37
- react_1.default.createElement(check_1.default, { fill: '#fff', role: 'presentation' }))))));
37
+ react_1.default.createElement(Check_1.default, { fill: '#fff', role: 'presentation' }))))));
38
38
  exports.ModifierItem = ModifierItem;
@@ -10,10 +10,10 @@ const user_1 = require("@sima-land/ui-nucleons/avatar/user");
10
10
  const box_1 = require("@sima-land/ui-nucleons/box");
11
11
  const text_1 = require("@sima-land/ui-nucleons/text");
12
12
  const borders_1 = require("@sima-land/ui-nucleons/styling/borders");
13
- const mail_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/mail"));
14
- const skype_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/skype"));
15
- const phone_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/phone"));
16
- const mobile_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Filled/mobile"));
13
+ const Mail_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/Mail"));
14
+ const Skype_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/Skype"));
15
+ const Phone_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/Phone"));
16
+ const Mobile_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Filled/Mobile"));
17
17
  const person_info_module_scss_1 = __importDefault(require("./person-info.module.scss"));
18
18
  const cx = bind_1.default.bind(person_info_module_scss_1.default);
19
19
  /**
@@ -31,10 +31,10 @@ function PersonInfo({ name, appointment, photoUrl, email, skype, phoneHref, phon
31
31
  Boolean(appointment) && react_1.default.createElement("span", { className: cx('appointment') }, appointment),
32
32
  arbitraryLinkProps && (react_1.default.createElement("div", { className: cx('profile-url'), children: react_1.default.createElement("a", Object.assign({ className: cx('link') }, arbitraryLinkProps)) })),
33
33
  react_1.default.createElement("div", { className: cx('items', borders_1.InnerBorder.bottom) },
34
- Boolean(email) && (react_1.default.createElement(CommunicateLink, { href: `mailto:${email}`, primaryText: email, secondaryText: '\u042D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u0430\u044F \u043F\u043E\u0447\u0442\u0430', icon: react_1.default.createElement(mail_1.default, null) })),
35
- Boolean(skype) && (react_1.default.createElement(CommunicateLink, { href: `skype:${skype}?chat`, primaryText: skype, secondaryText: 'Skype', icon: react_1.default.createElement(skype_1.default, null) })),
36
- Boolean(phoneText) && (react_1.default.createElement(CommunicateLink, { href: phoneHref, primaryText: phoneText, secondaryText: '\u0420\u0430\u0431\u043E\u0447\u0438\u0439', icon: react_1.default.createElement(phone_1.default, null) })),
37
- Boolean(secondPhoneText) && (react_1.default.createElement(CommunicateLink, { href: secondPhoneHref, primaryText: secondPhoneText, secondaryText: '\u0421\u043E\u0442\u043E\u0432\u044B\u0439', icon: react_1.default.createElement(mobile_1.default, null) })))));
34
+ Boolean(email) && (react_1.default.createElement(CommunicateLink, { href: `mailto:${email}`, primaryText: email, secondaryText: '\u042D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u0430\u044F \u043F\u043E\u0447\u0442\u0430', icon: react_1.default.createElement(Mail_1.default, null) })),
35
+ Boolean(skype) && (react_1.default.createElement(CommunicateLink, { href: `skype:${skype}?chat`, primaryText: skype, secondaryText: 'Skype', icon: react_1.default.createElement(Skype_1.default, null) })),
36
+ Boolean(phoneText) && (react_1.default.createElement(CommunicateLink, { href: phoneHref, primaryText: phoneText, secondaryText: '\u0420\u0430\u0431\u043E\u0447\u0438\u0439', icon: react_1.default.createElement(Phone_1.default, null) })),
37
+ Boolean(secondPhoneText) && (react_1.default.createElement(CommunicateLink, { href: secondPhoneHref, primaryText: secondPhoneText, secondaryText: '\u0421\u043E\u0442\u043E\u0432\u044B\u0439', icon: react_1.default.createElement(Mobile_1.default, null) })))));
38
38
  }
39
39
  exports.PersonInfo = PersonInfo;
40
40
  /**
@@ -7,14 +7,14 @@ exports.ProductRow = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const product_row_module_scss_1 = __importDefault(require("./product-row.module.scss"));
9
9
  const bind_1 = __importDefault(require("classnames/bind"));
10
- const more_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Filled/more"));
11
10
  const link_1 = require("@sima-land/ui-nucleons/link");
12
11
  const price_1 = require("@sima-land/ui-nucleons/price");
13
12
  const box_1 = require("@sima-land/ui-nucleons/box");
14
13
  const text_1 = require("@sima-land/ui-nucleons/text");
15
14
  const stroked_svg_1 = require("@sima-land/ui-nucleons/stroked-svg");
16
- const favorite_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Filled/favorite"));
17
- const favorite_2 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/favorite"));
15
+ const More_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Filled/More"));
16
+ const Favorite_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Filled/Favorite"));
17
+ const Favorite_2 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/Favorite"));
18
18
  const colors_1 = require("@sima-land/ui-nucleons/colors");
19
19
  const cx = bind_1.default.bind(product_row_module_scss_1.default);
20
20
  /**
@@ -27,7 +27,7 @@ function ProductRow({ itemUrl, imageUrl, name, sid, isWished, count, unit, initi
27
27
  react_1.default.createElement("div", { className: cx('image-wrapper') },
28
28
  react_1.default.createElement(link_1.Link, { href: itemUrl },
29
29
  react_1.default.createElement("img", { src: imageUrl, className: cx('image') })),
30
- onWishButtonClick && (react_1.default.createElement(stroked_svg_1.StrokedSVG, { className: cx('wish-button'), fill: isWished ? colors_1.COLORS.get('additional-red') : undefined, component: isWished ? favorite_1.default : favorite_2.default, onClick: isFetchingWishItems ? undefined : onWishButtonClick }))),
30
+ onWishButtonClick && (react_1.default.createElement(stroked_svg_1.StrokedSVG, { className: cx('wish-button'), fill: isWished ? colors_1.COLORS.get('additional-red') : undefined, component: isWished ? Favorite_1.default : Favorite_2.default, onClick: isFetchingWishItems ? undefined : onWishButtonClick }))),
31
31
  react_1.default.createElement("div", { className: cx('info-column') },
32
32
  react_1.default.createElement(link_1.Link, { href: itemUrl, className: cx('link'), color: 'basic-gray87' },
33
33
  react_1.default.createElement(text_1.Text, { weight: 600 }, name)),
@@ -54,6 +54,6 @@ function ProductRow({ itemUrl, imageUrl, name, sid, isWished, count, unit, initi
54
54
  notInStock && (react_1.default.createElement(box_1.Box, { marginTop: 2 },
55
55
  react_1.default.createElement(text_1.Text, { element: 'div', color: 'basic-gray38' }, "\u041D\u0435\u0442 \u043D\u0430 \u0441\u043A\u043B\u0430\u0434\u0435")))),
56
56
  react_1.default.createElement("div", { className: cx('action-button') },
57
- react_1.default.createElement(more_1.default, { onClick: onActionsClick }))));
57
+ react_1.default.createElement(More_1.default, { onClick: onActionsClick }))));
58
58
  }
59
59
  exports.ProductRow = ProductRow;
@@ -17,7 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.PseudoInput = void 0;
18
18
  const react_1 = __importDefault(require("react"));
19
19
  const bind_1 = __importDefault(require("classnames/bind"));
20
- const search_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/search"));
20
+ const Search_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/Search"));
21
21
  const pseudo_input_module_scss_1 = __importDefault(require("./pseudo-input.module.scss"));
22
22
  const cx = bind_1.default.bind(pseudo_input_module_scss_1.default);
23
23
  /**
@@ -28,7 +28,7 @@ const cx = bind_1.default.bind(pseudo_input_module_scss_1.default);
28
28
  const PseudoInput = (_a) => {
29
29
  var { text, className } = _a, rest = __rest(_a, ["text", "className"]);
30
30
  return (react_1.default.createElement("div", Object.assign({}, rest, { role: 'button', className: cx('input', className) }),
31
- react_1.default.createElement(search_1.default, { className: cx('icon'), "aria-hidden": 'true' }),
31
+ react_1.default.createElement(Search_1.default, { className: cx('icon'), "aria-hidden": 'true' }),
32
32
  react_1.default.createElement("span", { className: cx('text') }, text)));
33
33
  };
34
34
  exports.PseudoInput = PseudoInput;
@@ -34,9 +34,9 @@ const dropdown_1 = require("@sima-land/ui-nucleons/dropdown");
34
34
  const dropdown_item_1 = require("@sima-land/ui-nucleons/dropdown-item");
35
35
  const hooks_1 = require("@sima-land/ui-nucleons/hooks/");
36
36
  const on_1 = __importDefault(require("@sima-land/ui-nucleons/helpers/on"));
37
- const cross_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Filled/cross"));
38
- const search_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/search"));
39
- const more_vert_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Filled/more-vert"));
37
+ const Cross_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Filled/Cross"));
38
+ const Search_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/Search"));
39
+ const MoreVert_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Filled/MoreVert"));
40
40
  const bind_1 = __importDefault(require("classnames/bind"));
41
41
  const search_bar_module_scss_1 = __importDefault(require("./search-bar.module.scss"));
42
42
  exports.cx = bind_1.default.bind(search_bar_module_scss_1.default);
@@ -72,19 +72,19 @@ const SearchBar = ({ value, onChange, inputMode, placeholder = 'Поиск', onC
72
72
  react_1.default.createElement("div", { className: (0, exports.cx)('buttons-container') }, startButtons.map((props, index) => (react_1.default.createElement(Button, Object.assign({}, props, { key: index }))))))),
73
73
  react_1.default.createElement("label", { className: (0, exports.cx)('input-wrapper'), onMouseDown: preventFieldBlur, "data-testid": 'search-bar:input-wrapper' },
74
74
  withSearchIcon && (react_1.default.createElement("span", { className: (0, exports.cx)('search-icon') },
75
- react_1.default.createElement(search_1.default, { fill: colors_1.COLORS.get('basic-gray38'), "aria-hidden": true }))),
75
+ react_1.default.createElement(Search_1.default, { fill: colors_1.COLORS.get('basic-gray38'), "aria-hidden": true }))),
76
76
  react_1.default.createElement("div", { className: (0, exports.cx)('input-container') },
77
77
  react_1.default.createElement("input", { ref: inputRef, value: value, onChange: onChange, className: (0, exports.cx)('search-field'), placeholder: placeholder, autoFocus: autoFocus, "data-testid": 'search-bar-input', type: 'text', inputMode: inputMode, tabIndex: 0 }),
78
78
  description && (react_1.default.createElement("div", { className: (0, exports.cx)('description-container') },
79
79
  react_1.default.createElement("span", { className: (0, exports.cx)('description') }, description)))),
80
80
  value && onClear && (react_1.default.createElement("button", { onClick: onClear, "aria-label": '\u041E\u0447\u0438\u0441\u0442\u0438\u0442\u044C', "data-testid": 'search-bar:clear-icon', className: (0, exports.cx)('clear-button') },
81
- react_1.default.createElement(cross_1.default, { fill: colors_1.COLORS.get('basic-gray38'), "aria-hidden": true })))),
81
+ react_1.default.createElement(Cross_1.default, { fill: colors_1.COLORS.get('basic-gray38'), "aria-hidden": true })))),
82
82
  Boolean(endButtons.length) && (react_1.default.createElement(react_1.default.Fragment, null,
83
83
  react_1.default.createElement("div", { className: (0, exports.cx)('after-field', needHideEndButtons && 'wide-screen') },
84
84
  react_1.default.createElement("div", { className: (0, exports.cx)('buttons-container') }, endButtons.map((props, index) => (react_1.default.createElement(Button, Object.assign({}, props, { key: index })))))),
85
85
  needHideEndButtons && (react_1.default.createElement("div", { className: (0, exports.cx)('after-field', 'narrow-screen') },
86
86
  react_1.default.createElement("div", { className: (0, exports.cx)('buttons-container') },
87
- react_1.default.createElement(Button, { text: '\u0411\u043E\u043B\u044C\u0448\u0435', ref: dropdownOpenerRef, icon: more_vert_1.default, onClick: () => toggleDropdown(!shownDropdown) })),
87
+ react_1.default.createElement(Button, { text: '\u0411\u043E\u043B\u044C\u0448\u0435', ref: dropdownOpenerRef, icon: MoreVert_1.default, onClick: () => toggleDropdown(!shownDropdown) })),
88
88
  shownDropdown && (react_1.default.createElement("div", { ref: dropdownRef, className: (0, exports.cx)('dropdown-container') },
89
89
  react_1.default.createElement(dropdown_1.Dropdown, null, endButtons.map(({ text, onClick }, index) => (react_1.default.createElement(dropdown_item_1.DropdownItem, { size: 's', key: index, onClick: event => {
90
90
  onClick(event);
@@ -40,7 +40,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
40
40
  exports.SelectScreenOption = exports.SelectScreenLayout = void 0;
41
41
  const react_1 = __importStar(require("react"));
42
42
  const layout_1 = require("@sima-land/ui-nucleons/layout");
43
- const check_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/check"));
43
+ const Check_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/Check"));
44
44
  const classnames_1 = __importDefault(require("classnames"));
45
45
  const select_screen_module_scss_1 = __importDefault(require("./select-screen.module.scss"));
46
46
  /**
@@ -63,6 +63,6 @@ const SelectScreenOption = (_a) => {
63
63
  var { children, className, selected, withSelectedIcon = selected, size = 'm' } = _a, props = __rest(_a, ["children", "className", "selected", "withSelectedIcon", "size"]);
64
64
  return (react_1.default.createElement("button", Object.assign({}, props, { type: 'button', className: (0, classnames_1.default)(select_screen_module_scss_1.default.item, className, select_screen_module_scss_1.default[`size-${size}`]), "data-testid": 'select-screen:option' }),
65
65
  children,
66
- selected && withSelectedIcon && react_1.default.createElement(check_1.default, { role: 'presentation', className: select_screen_module_scss_1.default.icon })));
66
+ selected && withSelectedIcon && react_1.default.createElement(Check_1.default, { role: 'presentation', className: select_screen_module_scss_1.default.icon })));
67
67
  };
68
68
  exports.SelectScreenOption = SelectScreenOption;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sima-land/moleculas",
3
- "version": "16.0.0-alpha.5",
3
+ "version": "16.0.0-alpha.6",
4
4
  "repository": "ssh://git@github.com:sima-land/moleculas.git",
5
5
  "author": "www.sima-land.ru team",
6
6
  "license": "Apache-2.0",
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "peerDependencies": {
34
34
  "@sima-land/ui-nucleons": "^45.0.0-alpha.3",
35
- "@sima-land/ui-quarks": "^3.6.0",
35
+ "@sima-land/ui-quarks": "^4.2.0",
36
36
  "react": ">=17",
37
37
  "react-dom": ">=17"
38
38
  },
@@ -1,5 +0,0 @@
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>
@@ -1,5 +0,0 @@
1
- <svg width="36" height="36" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg">
2
- <path fill-rule="evenodd"
3
- d="M106.163 37.2641H101.212V23.2372H87.1854V18.2862H101.212V4.2587H106.163V18.2862H120.191V23.2372H106.163V37.2641ZM70.2788 52.7828C71.5464 54.2213 73.8876 55.6569 77.3059 57.0961C80.3783 55.7891 82.5529 54.3858 83.831 52.8827C85.1099 51.3788 85.7497 49.6254 85.7497 47.6209C85.7497 45.4231 84.9714 43.6746 83.4134 42.3782C81.8561 41.0824 79.7118 40.4356 76.9846 40.4356C74.2968 40.4356 72.1918 41.088 70.6662 42.3943C69.1412 43.7006 68.3777 45.4442 68.3777 47.6209C68.3777 49.6254 69.0104 51.3472 70.2788 52.7828ZM69.0217 66.3583C67.5832 68.0449 66.8633 70.0648 66.8633 72.4166C66.8633 75.0306 67.759 77.0667 69.5532 78.5269C71.3467 79.9872 73.8658 80.7142 77.1119 80.7142C80.315 80.7142 82.8053 79.9549 84.5883 78.4299C86.3719 76.905 87.2655 74.8148 87.2655 72.1558C87.2655 70.0438 86.4282 68.1652 84.7507 66.5221C83.0739 64.8762 80.1526 63.2817 75.9848 61.7349C72.7824 63.1277 70.4616 64.6688 69.0217 66.3583ZM65.0585 54.0083C63.7698 52.039 63.1237 49.8328 63.1237 47.3917C63.1237 43.9298 64.3857 41.1689 66.9111 39.1103C69.4358 37.0524 72.814 36.0225 77.0479 36.0225C81.3464 36.0225 84.7507 37.0356 87.2655 39.0618C89.7797 41.088 91.0368 43.8869 91.0368 47.4592C91.0368 49.8117 90.3168 51.9553 88.8762 53.8951C87.4378 55.8327 85.1388 57.5967 81.9792 59.1863C85.8031 61.0368 88.5226 62.9822 90.1333 65.019C91.7469 67.0557 92.5519 69.4131 92.5519 72.0911C92.5519 76.0564 91.1858 79.2188 88.4586 81.5825C85.7286 83.9448 81.989 85.1273 77.2426 85.1273C72.2136 85.1273 68.3461 84.0094 65.6378 81.7786C62.9296 79.545 61.5762 76.3826 61.5762 72.2872C61.5762 66.8216 64.8645 62.5617 71.4395 59.5126C68.474 57.8154 66.3472 55.9804 65.0585 54.0083ZM62.0185 123.903C27.8404 123.903 0.133301 96.1964 0.133301 62.0183C0.133301 27.8402 27.8404 0.133118 62.0185 0.133118C69.2333 0.133118 76.1606 1.3677 82.5986 3.63789C82.6471 4.73608 82.6471 8.81386 82.6471 8.79698C76.2274 6.28845 69.3261 5.0841 62.0185 5.0841C30.5746 5.0841 5.08428 30.5744 5.08428 62.0183C5.08428 93.4621 30.5746 118.952 62.0185 118.952C93.4623 118.952 118.953 93.4621 118.953 62.0183C118.953 54.7296 117.583 47.7608 115.087 41.3552C117.817 41.3897 119.9 41.3897 120.38 41.3833C122.662 47.8368 123.904 54.7823 123.904 62.0183C123.904 96.1964 96.1966 123.903 62.0185 123.903ZM32.6789 50.2019L29.8434 46.4791L42.3165 36.7101H46.8273V84.4728H41.6071V50.4311C41.6071 47.5991 41.6922 44.9212 41.8651 42.3943C41.413 42.852 40.9082 43.3322 40.35 43.8335C39.7918 44.3341 37.2347 46.4573 32.6789 50.2019Z"
4
- transform="matrix(0.2903226,0,0,0.2903226,0,0)" />
5
- </svg>
@@ -1,6 +0,0 @@
1
- <svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <path d="M24.0009 16V44L18.9954 38.6608C17.6116 37.1847 15.2993 37.0924 13.8022 38.4534C12.2651 39.8507 12.1776 42.2387 13.6084 43.7447L25.7344 56.509C28.4585 59.3765 32.2403 61 36.1954 61H37.181C43.1567 61 48.0009 56.1558 48.0009 50.1801V39.75C48.0009 36.4363 45.3146 33.75 42.0009 33.75C42.0009 31.6789 40.322 30 38.2509 30H36.0009C36.0009 27.6528 34.0981 25.75 31.7509 25.75H30.0009V16C30.0009 14.3431 28.6577 13 27.0009 13C25.344 13 24.0009 14.3431 24.0009 16Z" fill="white"/>
3
- <path fill-rule="evenodd" clip-rule="evenodd" d="M27.0009 14C25.8963 14 25.0009 14.8954 25.0009 16V44C25.0009 44.4103 24.7502 44.779 24.3686 44.9299C23.987 45.0808 23.552 44.9833 23.2714 44.6839L18.2659 39.3447C17.2557 38.2672 15.5677 38.1998 14.4748 39.1933C13.3528 40.2134 13.2889 41.9566 14.3334 43.0559L26.4594 55.8202C28.9947 58.489 32.5144 60 36.1954 60H37.181C42.6044 60 47.0009 55.6035 47.0009 50.1801V39.75C47.0009 37.331 45.2831 35.3133 43.0009 34.85V39.5C43.0009 40.0523 42.5532 40.5 42.0009 40.5C41.4486 40.5 41.0009 40.0523 41.0009 39.5V33.75C41.0009 32.2312 39.7697 31 38.2509 31H37.0009V39C37.0009 39.5523 36.5532 40 36.0009 40C35.4486 40 35.0009 39.5523 35.0009 39V30C35.0009 28.2051 33.5458 26.75 31.7509 26.75H31.0009V39C31.0009 39.5523 30.5532 40 30.0009 40C29.4486 40 29.0009 39.5523 29.0009 39V16C29.0009 14.8954 28.1055 14 27.0009 14ZM31.0009 24.75V16C31.0009 13.7909 29.21 12 27.0009 12C24.7918 12 23.0009 13.7909 23.0009 16V41.4712L19.7249 37.9769C17.9675 36.1022 15.0308 35.985 13.1295 37.7135C11.1774 39.4881 11.0663 42.5208 12.8834 44.4334L25.0094 57.1977C27.9223 60.2639 31.9662 62 36.1954 62H37.181C43.709 62 49.0009 56.7081 49.0009 50.1801V39.75C49.0009 36.1912 46.3452 33.2528 42.9075 32.8082C42.4706 30.636 40.5518 29 38.2509 29H36.9058C36.4388 26.5788 34.3084 24.75 31.7509 24.75H31.0009Z" fill="#212121"/>
4
- <path d="M12.4142 9.58548L11.8284 8.9997H52.1716L51.5858 9.58548C51.1575 10.0137 50.9626 10.5565 51.0037 11.1017C51.0428 11.6195 51.2877 12.0696 51.6089 12.3908C51.9301 12.712 52.3802 12.9569 52.898 12.996C53.4432 13.0371 53.986 12.8421 54.4142 12.4139L55.5866 11.2413C56.721 10.1066 58.1401 8.68713 58.4119 8.41626C59.1895 7.64104 59.1921 6.36338 58.4142 5.58549L54.4142 1.58548C53.986 1.15724 53.4432 0.962315 52.898 1.00342C52.3802 1.04246 51.9301 1.28741 51.6089 1.60862C51.2877 1.92984 51.0428 2.37985 51.0037 2.89768C50.9626 3.4429 51.1575 3.98567 51.5858 4.41391L52.1716 4.9997H11.8284L12.4142 4.41391C12.8425 3.98567 13.0374 3.4429 12.9963 2.89769C12.9572 2.37985 12.7123 1.92984 12.3911 1.60863C12.0699 1.28741 11.6198 1.04246 11.102 1.00342C10.5568 0.962315 10.014 1.15725 9.58579 1.58548L5.58579 5.58548C4.80474 6.36653 4.80474 7.63286 5.58579 8.41391L9.58579 12.4139C10.014 12.8421 10.5568 13.0371 11.102 12.996C11.6198 12.9569 12.0699 12.712 12.3911 12.3908C12.7123 12.0696 12.9572 11.6195 12.9963 11.1017C13.0374 10.5565 12.8424 10.0137 12.4142 9.58548Z" fill="white"/>
5
- <path d="M52.2929 3.70711C51.9024 3.31658 51.9024 2.68342 52.2929 2.29289C52.6834 1.90237 53.3166 1.90237 53.7071 2.29289L57.7071 6.29289C57.9024 6.48815 58 6.74408 58 7C58 7.26609 57.9025 7.50588 57.718 7.69609C56.4022 9.05287 55.0435 10.3707 53.7071 11.7071C53.3166 12.0976 52.6834 12.0976 52.2929 11.7071C51.9024 11.3166 51.9024 10.6834 52.2929 10.2929L54.5858 8H9.41421L11.7071 10.2929C12.0976 10.6834 12.0976 11.3166 11.7071 11.7071C11.3166 12.0976 10.6834 12.0976 10.2929 11.7071L6.29289 7.70711C5.90237 7.31658 5.90237 6.68342 6.29289 6.29289L10.2929 2.29289C10.6834 1.90237 11.3166 1.90237 11.7071 2.29289C12.0976 2.68342 12.0976 3.31658 11.7071 3.70711L9.41421 6H54.5858L52.2929 3.70711Z" fill="#212121"/>
6
- </svg>