@sima-land/moleculas 16.0.0-alpha.2 → 16.0.0-alpha.3

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 (33) hide show
  1. package/common/components/media-modal/__mocks__/index.d.ts +4 -0
  2. package/common/components/media-modal/__mocks__/index.js +141 -0
  3. package/common/components/media-modal/index.d.ts +9 -0
  4. package/common/components/media-modal/index.js +23 -0
  5. package/common/components/media-modal/layout.d.ts +36 -0
  6. package/common/components/media-modal/layout.js +70 -0
  7. package/common/components/media-modal/layout.module.scss +81 -0
  8. package/common/components/media-modal/parts/index.d.ts +36 -0
  9. package/common/components/media-modal/parts/index.js +60 -0
  10. package/common/components/media-modal/parts/media.d.ts +13 -0
  11. package/common/components/media-modal/parts/media.js +118 -0
  12. package/common/components/media-modal/parts/media.module.scss +62 -0
  13. package/common/components/media-modal/parts/parts.module.scss +21 -0
  14. package/common/components/media-modal/parts/product-brief.d.ts +17 -0
  15. package/common/components/media-modal/parts/product-brief.js +42 -0
  16. package/common/components/media-modal/parts/product-brief.module.scss +100 -0
  17. package/common/components/media-modal/parts/review.d.ts +13 -0
  18. package/common/components/media-modal/parts/review.js +24 -0
  19. package/common/components/media-modal/parts/review.module.scss +70 -0
  20. package/common/components/media-modal/parts/scroll-section.d.ts +9 -0
  21. package/common/components/media-modal/parts/scroll-section.js +19 -0
  22. package/common/components/media-modal/parts/scroll-section.module.scss +18 -0
  23. package/common/components/media-modal/parts/thumbnails.d.ts +27 -0
  24. package/common/components/media-modal/parts/thumbnails.js +92 -0
  25. package/common/components/media-modal/parts/thumbnails.module.scss +104 -0
  26. package/common/components/media-modal/types.d.ts +14 -0
  27. package/common/components/media-modal/types.js +2 -0
  28. package/common/components/media-modal/utils.d.ts +16 -0
  29. package/common/components/media-modal/utils.js +50 -0
  30. package/common/components/product-info/parts.js +6 -2
  31. package/common/components/product-info/product-info.module.scss +9 -0
  32. package/common/icons/image-broken.svg +7 -0
  33. package/package.json +6 -5
@@ -0,0 +1,4 @@
1
+ import { MediaData } from '../types';
2
+ export declare const data: {
3
+ media: MediaData[];
4
+ };
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.data = void 0;
4
+ exports.data = {
5
+ media: [
6
+ {
7
+ type: '360',
8
+ data: {
9
+ photos: [
10
+ 'https://cdn2.static1-sima-land.com/3d/3243668/0/700.jpg',
11
+ 'https://cdn2.static1-sima-land.com/3d/3243668/1/700.jpg',
12
+ 'https://cdn2.static1-sima-land.com/3d/3243668/2/700.jpg',
13
+ 'https://cdn2.static1-sima-land.com/3d/3243668/3/700.jpg',
14
+ 'https://cdn2.static1-sima-land.com/3d/3243668/4/700.jpg',
15
+ 'https://cdn2.static1-sima-land.com/3d/3243668/5/700.jpg',
16
+ 'https://cdn2.static1-sima-land.com/3d/3243668/6/700.jpg',
17
+ 'https://cdn2.static1-sima-land.com/3d/3243668/7/700.jpg',
18
+ 'https://cdn2.static1-sima-land.com/3d/3243668/8/700.jpg',
19
+ 'https://cdn2.static1-sima-land.com/3d/3243668/9/700.jpg',
20
+ 'https://cdn2.static1-sima-land.com/3d/3243668/10/700.jpg',
21
+ 'https://cdn2.static1-sima-land.com/3d/3243668/11/700.jpg',
22
+ 'https://cdn2.static1-sima-land.com/3d/3243668/12/700.jpg',
23
+ 'https://cdn2.static1-sima-land.com/3d/3243668/13/700.jpg',
24
+ 'https://cdn2.static1-sima-land.com/3d/3243668/14/700.jpg',
25
+ 'https://cdn2.static1-sima-land.com/3d/3243668/15/700.jpg',
26
+ 'https://cdn2.static1-sima-land.com/3d/3243668/16/700.jpg',
27
+ 'https://cdn2.static1-sima-land.com/3d/3243668/17/700.jpg',
28
+ 'https://cdn2.static1-sima-land.com/3d/3243668/18/700.jpg',
29
+ 'https://cdn2.static1-sima-land.com/3d/3243668/19/700.jpg',
30
+ 'https://cdn2.static1-sima-land.com/3d/3243668/20/700.jpg',
31
+ 'https://cdn2.static1-sima-land.com/3d/3243668/21/700.jpg',
32
+ 'https://cdn2.static1-sima-land.com/3d/3243668/22/700.jpg',
33
+ 'https://cdn2.static1-sima-land.com/3d/3243668/23/700.jpg',
34
+ 'https://cdn2.static1-sima-land.com/3d/3243668/24/700.jpg',
35
+ 'https://cdn2.static1-sima-land.com/3d/3243668/25/700.jpg',
36
+ 'https://cdn2.static1-sima-land.com/3d/3243668/26/700.jpg',
37
+ 'https://cdn2.static1-sima-land.com/3d/3243668/27/700.jpg',
38
+ 'https://cdn2.static1-sima-land.com/3d/3243668/28/700.jpg',
39
+ 'https://cdn2.static1-sima-land.com/3d/3243668/29/700.jpg',
40
+ 'https://cdn2.static1-sima-land.com/3d/3243668/30/700.jpg',
41
+ 'https://cdn2.static1-sima-land.com/3d/3243668/31/700.jpg',
42
+ 'https://cdn2.static1-sima-land.com/3d/3243668/32/700.jpg',
43
+ 'https://cdn2.static1-sima-land.com/3d/3243668/33/700.jpg',
44
+ 'https://cdn2.static1-sima-land.com/3d/3243668/34/700.jpg',
45
+ 'https://cdn2.static1-sima-land.com/3d/3243668/35/700.jpg',
46
+ 'https://cdn2.static1-sima-land.com/3d/3243668/36/700.jpg',
47
+ 'https://cdn2.static1-sima-land.com/3d/3243668/37/700.jpg',
48
+ 'https://cdn2.static1-sima-land.com/3d/3243668/38/700.jpg',
49
+ 'https://cdn2.static1-sima-land.com/3d/3243668/39/700.jpg',
50
+ 'https://cdn2.static1-sima-land.com/3d/3243668/40/700.jpg',
51
+ 'https://cdn2.static1-sima-land.com/3d/3243668/41/700.jpg',
52
+ 'https://cdn2.static1-sima-land.com/3d/3243668/42/700.jpg',
53
+ 'https://cdn2.static1-sima-land.com/3d/3243668/43/700.jpg',
54
+ 'https://cdn2.static1-sima-land.com/3d/3243668/44/700.jpg',
55
+ 'https://cdn2.static1-sima-land.com/3d/3243668/45/700.jpg',
56
+ 'https://cdn2.static1-sima-land.com/3d/3243668/46/700.jpg',
57
+ 'https://cdn2.static1-sima-land.com/3d/3243668/47/700.jpg',
58
+ 'https://cdn2.static1-sima-land.com/3d/3243668/48/700.jpg',
59
+ 'https://cdn2.static1-sima-land.com/3d/3243668/49/700.jpg',
60
+ 'https://cdn2.static1-sima-land.com/3d/3243668/50/700.jpg',
61
+ 'https://cdn2.static1-sima-land.com/3d/3243668/51/700.jpg',
62
+ 'https://cdn2.static1-sima-land.com/3d/3243668/52/700.jpg',
63
+ 'https://cdn2.static1-sima-land.com/3d/3243668/53/700.jpg',
64
+ 'https://cdn2.static1-sima-land.com/3d/3243668/54/700.jpg',
65
+ 'https://cdn2.static1-sima-land.com/3d/3243668/55/700.jpg',
66
+ 'https://cdn2.static1-sima-land.com/3d/3243668/56/700.jpg',
67
+ 'https://cdn2.static1-sima-land.com/3d/3243668/57/700.jpg',
68
+ 'https://cdn2.static1-sima-land.com/3d/3243668/58/700.jpg',
69
+ 'https://cdn2.static1-sima-land.com/3d/3243668/59/700.jpg',
70
+ 'https://cdn2.static1-sima-land.com/3d/3243668/60/700.jpg',
71
+ 'https://cdn2.static1-sima-land.com/3d/3243668/61/700.jpg',
72
+ 'https://cdn2.static1-sima-land.com/3d/3243668/62/700.jpg',
73
+ 'https://cdn2.static1-sima-land.com/3d/3243668/63/700.jpg',
74
+ 'https://cdn2.static1-sima-land.com/3d/3243668/64/700.jpg',
75
+ 'https://cdn2.static1-sima-land.com/3d/3243668/65/700.jpg',
76
+ 'https://cdn2.static1-sima-land.com/3d/3243668/66/700.jpg',
77
+ 'https://cdn2.static1-sima-land.com/3d/3243668/67/700.jpg',
78
+ 'https://cdn2.static1-sima-land.com/3d/3243668/68/700.jpg',
79
+ 'https://cdn2.static1-sima-land.com/3d/3243668/69/700.jpg',
80
+ 'https://cdn2.static1-sima-land.com/3d/3243668/70/700.jpg',
81
+ 'https://cdn2.static1-sima-land.com/3d/3243668/71/700.jpg',
82
+ 'https://cdn2.static1-sima-land.com/3d/3243668/72/700.jpg',
83
+ 'https://cdn2.static1-sima-land.com/3d/3243668/73/700.jpg',
84
+ 'https://cdn2.static1-sima-land.com/3d/3243668/74/700.jpg',
85
+ 'https://cdn2.static1-sima-land.com/3d/3243668/75/700.jpg',
86
+ 'https://cdn2.static1-sima-land.com/3d/3243668/76/700.jpg',
87
+ 'https://cdn2.static1-sima-land.com/3d/3243668/77/700.jpg',
88
+ 'https://cdn2.static1-sima-land.com/3d/3243668/78/700.jpg',
89
+ ],
90
+ },
91
+ },
92
+ {
93
+ type: 'video',
94
+ data: {
95
+ src: 'https://cdn2.static1-sima-land.com/flv/3404953.mp4',
96
+ },
97
+ },
98
+ {
99
+ type: 'image',
100
+ data: {
101
+ alt: 'Сапоги детские MINAKU, цвет синий, размер 31 - Фото 1',
102
+ src: 'https://loremflickr.com/240/240?random=1',
103
+ },
104
+ },
105
+ {
106
+ type: 'image',
107
+ data: {
108
+ alt: 'Фото из отзыва, не квадратное',
109
+ src: 'https://loremflickr.com/240/240?random=2',
110
+ },
111
+ },
112
+ {
113
+ type: 'image',
114
+ data: {
115
+ alt: 'Сапоги детские MINAKU, цвет синий, размер 31 - Фото 2',
116
+ src: 'https://loremflickr.com/240/240?random=3',
117
+ },
118
+ },
119
+ {
120
+ type: 'image',
121
+ data: {
122
+ alt: 'Сапоги детские MINAKU, цвет синий, размер 31 - Фото 3',
123
+ src: 'https://loremflickr.com/240/240?random=4',
124
+ },
125
+ },
126
+ {
127
+ type: 'image',
128
+ data: {
129
+ alt: 'Сапоги детские MINAKU, цвет синий, размер 31 - Фото 4',
130
+ src: 'https://loremflickr.com/240/240?random=5',
131
+ },
132
+ },
133
+ {
134
+ type: 'image',
135
+ data: {
136
+ alt: 'Сапоги детские MINAKU, цвет синий, размер 31 - Фото 5',
137
+ src: 'https://loremflickr.com/240/240?random=6',
138
+ },
139
+ },
140
+ ],
141
+ };
@@ -0,0 +1,9 @@
1
+ import { MediaLayout, MediaHeader, MediaMain, MediaAside, MediaFooter } from './layout';
2
+ import { Preset, HeaderLayout } from './parts';
3
+ import { ScrollSection } from './parts/scroll-section';
4
+ import { ThumbnailsProps, Thumbnail, Thumbnails } from './parts/thumbnails';
5
+ import { MediaContentProps, MediaContent } from './parts/media';
6
+ import { ReviewProps, Review } from './parts/review';
7
+ import { ProductBriefProps, ProductBrief } from './parts/product-brief';
8
+ export type { MediaContentProps, ThumbnailsProps, ProductBriefProps, ReviewProps };
9
+ export { MediaLayout, MediaHeader, MediaMain, MediaAside, MediaFooter, MediaContent, HeaderLayout, Thumbnails, Thumbnail, Review, ProductBrief, Preset, ScrollSection, };
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ScrollSection = exports.Preset = exports.ProductBrief = exports.Review = exports.Thumbnail = exports.Thumbnails = exports.HeaderLayout = exports.MediaContent = exports.MediaFooter = exports.MediaAside = exports.MediaMain = exports.MediaHeader = exports.MediaLayout = void 0;
4
+ const layout_1 = require("./layout");
5
+ Object.defineProperty(exports, "MediaLayout", { enumerable: true, get: function () { return layout_1.MediaLayout; } });
6
+ Object.defineProperty(exports, "MediaHeader", { enumerable: true, get: function () { return layout_1.MediaHeader; } });
7
+ Object.defineProperty(exports, "MediaMain", { enumerable: true, get: function () { return layout_1.MediaMain; } });
8
+ Object.defineProperty(exports, "MediaAside", { enumerable: true, get: function () { return layout_1.MediaAside; } });
9
+ Object.defineProperty(exports, "MediaFooter", { enumerable: true, get: function () { return layout_1.MediaFooter; } });
10
+ const parts_1 = require("./parts");
11
+ Object.defineProperty(exports, "Preset", { enumerable: true, get: function () { return parts_1.Preset; } });
12
+ Object.defineProperty(exports, "HeaderLayout", { enumerable: true, get: function () { return parts_1.HeaderLayout; } });
13
+ const scroll_section_1 = require("./parts/scroll-section");
14
+ Object.defineProperty(exports, "ScrollSection", { enumerable: true, get: function () { return scroll_section_1.ScrollSection; } });
15
+ const thumbnails_1 = require("./parts/thumbnails");
16
+ Object.defineProperty(exports, "Thumbnail", { enumerable: true, get: function () { return thumbnails_1.Thumbnail; } });
17
+ Object.defineProperty(exports, "Thumbnails", { enumerable: true, get: function () { return thumbnails_1.Thumbnails; } });
18
+ const media_1 = require("./parts/media");
19
+ Object.defineProperty(exports, "MediaContent", { enumerable: true, get: function () { return media_1.MediaContent; } });
20
+ const review_1 = require("./parts/review");
21
+ Object.defineProperty(exports, "Review", { enumerable: true, get: function () { return review_1.Review; } });
22
+ const product_brief_1 = require("./parts/product-brief");
23
+ Object.defineProperty(exports, "ProductBrief", { enumerable: true, get: function () { return product_brief_1.ProductBrief; } });
@@ -0,0 +1,36 @@
1
+ import { ReactNode } from 'react';
2
+ interface ContainerProps {
3
+ /** Содержимое. */
4
+ children?: ReactNode;
5
+ }
6
+ /**
7
+ * Формирует layout для модального окна медиа товара.
8
+ * @param props Свойства.
9
+ * @return Элемент.
10
+ */
11
+ export declare function MediaLayout({ children }: ContainerProps): JSX.Element;
12
+ /**
13
+ * Слот шапки MediaLayout.
14
+ * @param props Свойства.
15
+ * @return Элемент.
16
+ */
17
+ export declare function MediaHeader({ children }: ContainerProps): JSX.Element;
18
+ /**
19
+ * Слот основного контента MediaLayout.
20
+ * @param props Свойства.
21
+ * @return Элемент.
22
+ */
23
+ export declare function MediaMain({ children }: ContainerProps): JSX.Element;
24
+ /**
25
+ * Слот дополнительного контента MediaLayout.
26
+ * @param props Свойства.
27
+ * @return Элемент.
28
+ */
29
+ export declare function MediaAside({ children }: ContainerProps): JSX.Element;
30
+ /**
31
+ * Слот футера MediaLayout.
32
+ * @param props Свойства.
33
+ * @return Элемент.
34
+ */
35
+ export declare function MediaFooter({ children }: ContainerProps): JSX.Element;
36
+ export {};
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MediaFooter = exports.MediaAside = exports.MediaMain = exports.MediaHeader = exports.MediaLayout = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const define_slots_1 = require("@sima-land/ui-nucleons/helpers/define-slots");
9
+ const layout_1 = require("@sima-land/ui-nucleons/layout");
10
+ const bind_1 = __importDefault(require("classnames/bind"));
11
+ const layout_module_scss_1 = __importDefault(require("./layout.module.scss"));
12
+ const cx = bind_1.default.bind(layout_module_scss_1.default);
13
+ /**
14
+ * Формирует layout для модального окна медиа товара.
15
+ * @param props Свойства.
16
+ * @return Элемент.
17
+ */
18
+ function MediaLayout({ children }) {
19
+ const { header, main, aside, footer } = (0, define_slots_1.defineSlots)(children, {
20
+ header: MediaHeader,
21
+ main: MediaMain,
22
+ aside: MediaAside,
23
+ footer: MediaFooter,
24
+ });
25
+ const mobile = ['mxs', 'ms', 'mm', 'ml'];
26
+ return (react_1.default.createElement("div", { className: layout_module_scss_1.default.layout },
27
+ header && (react_1.default.createElement(layout_1.Layout, { disabledOn: mobile, className: layout_module_scss_1.default.header }, header)),
28
+ react_1.default.createElement(layout_1.Layout, { disabledOn: mobile, className: layout_module_scss_1.default.body },
29
+ aside && react_1.default.createElement("div", { className: layout_module_scss_1.default.aside }, aside),
30
+ react_1.default.createElement("div", { className: layout_module_scss_1.default.main }, main)),
31
+ footer && (react_1.default.createElement(layout_1.Layout, { disabledOn: mobile, className: layout_module_scss_1.default.footer },
32
+ react_1.default.createElement("div", { className: cx('footer-inner', aside && 'with-aside') }, footer)))));
33
+ }
34
+ exports.MediaLayout = MediaLayout;
35
+ /**
36
+ * Слот шапки MediaLayout.
37
+ * @param props Свойства.
38
+ * @return Элемент.
39
+ */
40
+ function MediaHeader({ children }) {
41
+ return react_1.default.createElement(react_1.default.Fragment, null, children);
42
+ }
43
+ exports.MediaHeader = MediaHeader;
44
+ /**
45
+ * Слот основного контента MediaLayout.
46
+ * @param props Свойства.
47
+ * @return Элемент.
48
+ */
49
+ function MediaMain({ children }) {
50
+ return react_1.default.createElement(react_1.default.Fragment, null, children);
51
+ }
52
+ exports.MediaMain = MediaMain;
53
+ /**
54
+ * Слот дополнительного контента MediaLayout.
55
+ * @param props Свойства.
56
+ * @return Элемент.
57
+ */
58
+ function MediaAside({ children }) {
59
+ return react_1.default.createElement(react_1.default.Fragment, null, children);
60
+ }
61
+ exports.MediaAside = MediaAside;
62
+ /**
63
+ * Слот футера MediaLayout.
64
+ * @param props Свойства.
65
+ * @return Элемент.
66
+ */
67
+ function MediaFooter({ children }) {
68
+ return react_1.default.createElement(react_1.default.Fragment, null, children);
69
+ }
70
+ exports.MediaFooter = MediaFooter;
@@ -0,0 +1,81 @@
1
+ @use 'node_modules/@sima-land/ui-nucleons/breakpoints';
2
+ @use 'node_modules/@sima-land/ui-nucleons/utils';
3
+
4
+ .layout {
5
+ display: flex;
6
+ flex-direction: column;
7
+ min-height: calc(100vh - var(--modal-header-height));
8
+ }
9
+
10
+ .body {
11
+ flex-grow: 1;
12
+ display: flex;
13
+ }
14
+
15
+ .main {
16
+ position: relative; // ВАЖНО: что иметь возможность заполнить доступную область содержимым
17
+ min-height: 50vh;
18
+ }
19
+
20
+ @include breakpoints.down('xs') {
21
+ .header + .body {
22
+ margin-top: 24px;
23
+ }
24
+ .body {
25
+ flex-direction: column-reverse;
26
+ &:first-child {
27
+ margin-top: 24px;
28
+ }
29
+ &:last-child {
30
+ margin-bottom: 24px;
31
+ }
32
+ }
33
+ .main {
34
+ min-height: max(50vh, 240px);
35
+ flex-grow: 1;
36
+ }
37
+ .aside + .main {
38
+ margin-bottom: 24px;
39
+ }
40
+ .body + .footer {
41
+ margin-top: 24px;
42
+ }
43
+ .footer {
44
+ margin-bottom: 24px;
45
+ }
46
+ }
47
+
48
+ @include breakpoints.up('xs') {
49
+ .header + .body {
50
+ margin-top: 40px;
51
+ }
52
+ .body {
53
+ &:first-child {
54
+ margin-top: 40px;
55
+ }
56
+ &:last-child {
57
+ margin-bottom: 40px;
58
+ }
59
+ }
60
+ .aside {
61
+ display: flex;
62
+ flex-direction: column;
63
+ width: 104px;
64
+ max-height: 100%;
65
+ }
66
+ .aside + .main {
67
+ margin-left: 16px;
68
+ }
69
+ .main {
70
+ flex-grow: 1;
71
+ }
72
+ .body + .footer {
73
+ margin-top: 32px;
74
+ }
75
+ .footer {
76
+ margin-bottom: 40px;
77
+ }
78
+ .footer-inner.with-aside {
79
+ margin-left: calc(104px + 16px);
80
+ }
81
+ }
@@ -0,0 +1,36 @@
1
+ import { ReactNode } from 'react';
2
+ import { TabsProps } from '@sima-land/ui-nucleons/tabs';
3
+ import { TextButtonProps } from '@sima-land/ui-nucleons/text-button';
4
+ export declare const Preset: {
5
+ readonly headerTabs: (userProps?: TabsProps) => TabsProps;
6
+ readonly headerButton: (userProps?: TextButtonProps) => TextButtonProps;
7
+ };
8
+ /**
9
+ * Формирует layout для шапки модального окна медиа.
10
+ * @param props Свойства.
11
+ * @return Элемент.
12
+ */
13
+ export declare function HeaderLayout({ children }: {
14
+ children?: ReactNode;
15
+ }): JSX.Element;
16
+ export declare namespace HeaderLayout {
17
+ var Tabs: typeof HeaderLayoutTabs;
18
+ var Button: typeof HeaderLayoutButton;
19
+ }
20
+ /**
21
+ * Слот вкладок для layout'а шапки модального окна медиа.
22
+ * @param props Свойства.
23
+ * @return Элемент.
24
+ */
25
+ declare function HeaderLayoutTabs({ children }: {
26
+ children?: ReactNode;
27
+ }): JSX.Element;
28
+ /**
29
+ * Слот кнопки для layout'а шапки модального окна медиа.
30
+ * @param props Свойства.
31
+ * @return Элемент.
32
+ */
33
+ declare function HeaderLayoutButton({ children }: {
34
+ children?: ReactNode;
35
+ }): JSX.Element;
36
+ export {};
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.HeaderLayout = exports.Preset = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const layout_1 = require("@sima-land/ui-nucleons/layout");
9
+ const define_slots_1 = require("@sima-land/ui-nucleons/helpers/define-slots");
10
+ const breakpoint_1 = require("@sima-land/ui-nucleons/hooks/breakpoint");
11
+ const utils_1 = require("../utils");
12
+ const scroll_section_1 = require("./scroll-section");
13
+ const left_1 = __importDefault(require("@sima-land/ui-quarks/icons/16x16/Stroked/Arrows/left"));
14
+ const parts_module_scss_1 = __importDefault(require("./parts.module.scss"));
15
+ exports.Preset = {
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)),
18
+ };
19
+ /**
20
+ * Формирует layout для шапки модального окна медиа.
21
+ * @param props Свойства.
22
+ * @return Элемент.
23
+ */
24
+ function HeaderLayout({ children }) {
25
+ const mounted = (0, utils_1.useMounted)();
26
+ const desktop = (0, breakpoint_1.useBreakpoint)('xs+');
27
+ const { tabs, button } = (0, define_slots_1.defineSlots)(children, {
28
+ tabs: HeaderLayoutTabs,
29
+ button: HeaderLayoutButton,
30
+ });
31
+ if (!mounted) {
32
+ return react_1.default.createElement("div", { className: parts_module_scss_1.default['header-layout'] });
33
+ }
34
+ return (react_1.default.createElement("div", { className: parts_module_scss_1.default['header-layout'] },
35
+ !desktop && (react_1.default.createElement(react_1.default.Fragment, null,
36
+ tabs && react_1.default.createElement(scroll_section_1.ScrollSection, null, tabs),
37
+ button && react_1.default.createElement(layout_1.Layout, null, button))),
38
+ desktop && (react_1.default.createElement(react_1.default.Fragment, null,
39
+ tabs,
40
+ button))));
41
+ }
42
+ exports.HeaderLayout = HeaderLayout;
43
+ HeaderLayout.Tabs = HeaderLayoutTabs;
44
+ HeaderLayout.Button = HeaderLayoutButton;
45
+ /**
46
+ * Слот вкладок для layout'а шапки модального окна медиа.
47
+ * @param props Свойства.
48
+ * @return Элемент.
49
+ */
50
+ function HeaderLayoutTabs({ children }) {
51
+ return react_1.default.createElement(react_1.default.Fragment, null, children);
52
+ }
53
+ /**
54
+ * Слот кнопки для layout'а шапки модального окна медиа.
55
+ * @param props Свойства.
56
+ * @return Элемент.
57
+ */
58
+ function HeaderLayoutButton({ children }) {
59
+ return react_1.default.createElement(react_1.default.Fragment, null, children);
60
+ }
@@ -0,0 +1,13 @@
1
+ /// <reference types="react" />
2
+ import { MediaData } from '../types';
3
+ export interface MediaContentProps {
4
+ items: MediaData[];
5
+ targetIndex?: number;
6
+ onChangeTargetIndex?: (newIndex: number) => void;
7
+ }
8
+ /**
9
+ * Отображает медиа-контент в контексте модального окна.
10
+ * @param props Свойства.
11
+ * @return Элемент.
12
+ */
13
+ export declare function MediaContent(props: MediaContentProps): JSX.Element;
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.MediaContent = void 0;
30
+ const react_1 = __importStar(require("react"));
31
+ const carousel_1 = require("@sima-land/ui-nucleons/carousel");
32
+ const arrow_button_1 = require("@sima-land/ui-nucleons/arrow-button");
33
+ const breakpoint_1 = require("@sima-land/ui-nucleons/hooks/breakpoint");
34
+ const image_overlay_1 = require("../../../../desktop/components/gallery-modal/components/image-overlay");
35
+ const all_round_view_1 = require("../../../../desktop/components/gallery-modal/components/all-round-view");
36
+ const utils_1 = require("../utils");
37
+ const media_module_scss_1 = __importDefault(require("./media.module.scss"));
38
+ /**
39
+ * Отображает медиа-контент в контексте модального окна.
40
+ * @param props Свойства.
41
+ * @return Элемент.
42
+ */
43
+ function MediaContent(props) {
44
+ const desktop = (0, breakpoint_1.useBreakpoint)('xs+');
45
+ return (react_1.default.createElement("div", { className: media_module_scss_1.default.root }, desktop ? react_1.default.createElement(MediaSlider, Object.assign({}, props)) : react_1.default.createElement(MediaCarousel, Object.assign({}, props))));
46
+ }
47
+ exports.MediaContent = MediaContent;
48
+ /**
49
+ * Отображает медиа-контент в виде карусели.
50
+ * @param props Свойства.
51
+ * @return Элемент.
52
+ */
53
+ function MediaCarousel({ items, targetIndex, onChangeTargetIndex }) {
54
+ const ref = (0, react_1.useRef)(null);
55
+ const area = (0, utils_1.useClientRect)(ref);
56
+ return (react_1.default.createElement("div", { ref: ref, className: media_module_scss_1.default.carousel }, area.ready && (react_1.default.createElement(carousel_1.Carousel, { targetIndex: targetIndex, onChangeTargetIndex: onChangeTargetIndex, draggable: true, containerProps: {
57
+ className: media_module_scss_1.default.carousel,
58
+ style: {
59
+ '--item-width': `${area.width}px`,
60
+ '--item-height': `${area.height}px`,
61
+ },
62
+ }, withControls: false, items: items, renderItem: data => (react_1.default.createElement("div", { className: media_module_scss_1.default['carousel-item'] },
63
+ react_1.default.createElement(FitSquare, Object.assign({}, area),
64
+ react_1.default.createElement(MediaView, { media: data })))) }))));
65
+ }
66
+ /**
67
+ * Отображает медиа-контент в виде слайдера.
68
+ * @param props Свойства.
69
+ * @return Элемент.
70
+ */
71
+ function MediaSlider({ items, targetIndex, onChangeTargetIndex }) {
72
+ const [position, setPosition] = (0, react_1.useState)(0);
73
+ const ref = (0, react_1.useRef)(null);
74
+ const area = (0, utils_1.useClientRect)(ref);
75
+ const total = items.length;
76
+ const controls = total > 1;
77
+ const correction = controls ? 2 * (56 + 24) : 0;
78
+ (0, react_1.useEffect)(() => {
79
+ if (typeof targetIndex === 'number') {
80
+ setPosition(targetIndex);
81
+ }
82
+ }, [targetIndex]);
83
+ return (react_1.default.createElement("div", { ref: ref, className: media_module_scss_1.default.slider }, area.ready && (react_1.default.createElement(react_1.default.Fragment, null,
84
+ controls && (react_1.default.createElement(arrow_button_1.ArrowButton, { direction: 'left', onClick: () => {
85
+ const next = position - 1 >= 0 ? position - 1 : total - 1;
86
+ setPosition(next);
87
+ onChangeTargetIndex === null || onChangeTargetIndex === void 0 ? void 0 : onChangeTargetIndex(next);
88
+ } })),
89
+ react_1.default.createElement(FitSquare, { width: area.width + correction, height: area.height },
90
+ react_1.default.createElement(MediaView, { media: items[position] })),
91
+ controls && (react_1.default.createElement(arrow_button_1.ArrowButton, { direction: 'right', onClick: () => {
92
+ const next = (position + 1) % total;
93
+ setPosition(next);
94
+ onChangeTargetIndex === null || onChangeTargetIndex === void 0 ? void 0 : onChangeTargetIndex(next);
95
+ } }))))));
96
+ }
97
+ /**
98
+ * Отображает медиа-контент - 360, видео или изображение.
99
+ * @param props Свойства.
100
+ * @return Элемент.
101
+ */
102
+ function MediaView({ media }) {
103
+ return (react_1.default.createElement("div", { className: media_module_scss_1.default.media },
104
+ media.type === 'image' && (react_1.default.createElement(image_overlay_1.ImageOverlay, { className: media_module_scss_1.default['media-image-wrap'] },
105
+ react_1.default.createElement("img", { src: media.data.src, alt: media.data.alt || '' }))),
106
+ media.type === 'video' && (react_1.default.createElement("video", { autoPlay: false, controls: true, controlsList: 'nodownload' },
107
+ react_1.default.createElement("source", { src: media.data.src }))),
108
+ media.type === '360' && react_1.default.createElement(all_round_view_1.AllRoundView, { photos: media.data.photos })));
109
+ }
110
+ /**
111
+ * Вписывает квадрат в заданную прямоугольную область.
112
+ * @param props Свойства.
113
+ * @return Элемент.
114
+ */
115
+ function FitSquare({ children, width, height }) {
116
+ const size = (0, react_1.useMemo)(() => Math.min(width, height), [width, height]);
117
+ return (react_1.default.createElement("div", { className: media_module_scss_1.default.square, style: { '--square-size': `${size}px` } }, children));
118
+ }
@@ -0,0 +1,62 @@
1
+ .root {
2
+ position: absolute;
3
+ width: 100%;
4
+ height: 100%;
5
+ }
6
+
7
+ .carousel {
8
+ position: absolute;
9
+ width: 100%;
10
+ height: 100%;
11
+ }
12
+
13
+ .carousel-item {
14
+ overflow: hidden;
15
+ width: var(--item-width);
16
+ height: var(--item-height);
17
+ flex-shrink: 0;
18
+ display: flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ }
22
+
23
+ .slider {
24
+ position: absolute;
25
+ width: 100%;
26
+ height: 100%;
27
+ display: flex;
28
+ gap: 24px;
29
+ align-items: center;
30
+ justify-content: center;
31
+ }
32
+
33
+ .square {
34
+ flex-shrink: 0;
35
+ width: var(--square-size);
36
+ height: var(--square-size);
37
+ }
38
+
39
+ .media {
40
+ --all-round-view-size: var(--square-size);
41
+ position: relative;
42
+ width: 100%;
43
+ height: 100%;
44
+ .media-image-wrap,
45
+ video {
46
+ display: block;
47
+ height: 100%;
48
+ left: 0;
49
+ position: absolute;
50
+ top: 0;
51
+ width: 100%;
52
+ }
53
+ video {
54
+ background: #000;
55
+ }
56
+ .media-image-wrap img {
57
+ display: block;
58
+ height: 100%;
59
+ object-fit: contain;
60
+ width: 100%;
61
+ }
62
+ }