@meduza/ui-kit-2 0.4.4 → 0.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.4.4",
2
+ "version": "0.4.5",
3
3
  "license": "MIT",
4
4
  "description": "UIKit for Meduza",
5
5
  "repository": "https://github.com/meduza-corp/ui-kit-2.git",
@@ -1,17 +1,6 @@
1
- /* stylelint-disable declaration-empty-line-before */
2
1
  @import '../vars';
3
2
 
4
- .root {
5
- display: inline;
6
-
7
- line-height: inherit;
8
- }
9
-
10
- .root svg {
11
- vertical-align: top;
12
- }
13
-
14
- .items {
3
+ .root:not(:first-child) {
15
4
  margin-left: 1px;
16
5
 
17
6
  vertical-align: top;
@@ -1,21 +1,14 @@
1
1
  import React from 'react'
2
2
  import { render } from '@testing-library/react'
3
3
  import { DocumentItemsCount } from './'
4
- // import { DocumentItemsCountProps } from './DocumentItemsCount.types'
5
-
6
- import styles from './DocumentItemsCount.module.css'
7
4
 
8
5
  describe('Document Items Count', () => {
9
- // let props: DocumentItemsCountProps
10
-
11
6
  const renderComponent = () =>
12
7
  render(<DocumentItemsCount type="card" items={4} />)
13
8
 
14
9
  it('should have root style', () => {
15
- const { getByTestId } = renderComponent()
16
-
17
- const documentItemsCount = getByTestId('document-items-count')
10
+ const { container } = renderComponent()
18
11
 
19
- expect(documentItemsCount).toHaveClass(styles.root)
12
+ expect(container).toBeInTheDocument
20
13
  })
21
14
  })
@@ -45,9 +45,9 @@ export const DocumentItemsCount: React.FC<DocumentItemsCountProps> = ({
45
45
  )}`
46
46
 
47
47
  return (
48
- <div data-testid="document-items-count" className={styles.root}>
48
+ <>
49
49
  {children}
50
- <span className={styles.items}>{itemsCount}</span>
51
- </div>
50
+ <span className={styles.root}>{itemsCount}</span>
51
+ </>
52
52
  )
53
53
  }
@@ -6,7 +6,6 @@ import { Spoiler } from '../Spoiler'
6
6
  import { HalfBlock } from '../HalfBlock'
7
7
  import { Cover } from '../Cover'
8
8
  import { RelatedRichBlock } from '../RelatedRichBlock'
9
- import { ShopRelatedBlock } from '../ShopRelatedBlock'
10
9
  import { BlockProvider } from '../utils/BlockContext'
11
10
 
12
11
  export const RawHtmlBlock: React.FC<RawHtmlBlockProps> = ({
@@ -48,10 +47,6 @@ export const RawHtmlBlock: React.FC<RawHtmlBlockProps> = ({
48
47
  return <RelatedRichBlock block={block} styleContext={styleContext} />
49
48
  }
50
49
 
51
- case 'related_shop': {
52
- return <ShopRelatedBlock block={block} styleContext={styleContext} />
53
- }
54
-
55
50
  default: {
56
51
  return (
57
52
  <BlockProvider value={context}>
package/src/index.tsx CHANGED
@@ -40,7 +40,6 @@ export * from './Footnote'
40
40
  export * from './RelatedRichBlock'
41
41
  export * from './SensitiveBlock'
42
42
  export * from './DonatesTeaser'
43
- export * from './ShopRelatedBlock'
44
43
  export * from './AnnouncementInText'
45
44
  export * from './Tooltip'
46
45
  // /* PLOP_INJECT_LINK */ //
@@ -1,210 +0,0 @@
1
- @import '../vars.css';
2
-
3
- .root {
4
- position: relative;
5
- z-index: 10;
6
-
7
- display: block;
8
- overflow: hidden;
9
-
10
- color: #000;
11
-
12
- text-decoration: none;
13
-
14
- border-radius: 8px;
15
- outline-width: 0;
16
-
17
- @media $mobile {
18
- color: #fff;
19
- }
20
- }
21
-
22
- .root:hover {
23
- @media $mobile {
24
- opacity: 0.95;
25
- }
26
- }
27
-
28
- .root::after {
29
- position: absolute;
30
- top: 0;
31
- right: 0;
32
- bottom: 0;
33
- left: 0;
34
- z-index: 20;
35
-
36
- border-radius: 8px;
37
-
38
- content: '';
39
- }
40
-
41
- .root::before {
42
- display: block;
43
-
44
- width: 100%;
45
- }
46
-
47
- .root::after {
48
- box-shadow: inset 0 4px #b88b59, inset 0 5px rgba(0, 0, 0, 0.2),
49
- inset 0 0 0 1px rgba(0, 0, 0, 0.1);
50
- }
51
-
52
- .root,
53
- .wrapper {
54
- margin: 16px 0;
55
-
56
- @media $portraitTablet {
57
- margin: 25px 0;
58
- }
59
- }
60
-
61
- .overlay,
62
- .overlayHeader {
63
- position: absolute;
64
- right: 0;
65
- left: 0;
66
- z-index: 10;
67
- }
68
-
69
- .overlay {
70
- bottom: 0;
71
-
72
- height: 295px;
73
- }
74
-
75
- .overlayHeader {
76
- top: 0;
77
-
78
- height: 150px;
79
- }
80
-
81
- .body {
82
- display: flex;
83
- flex-flow: column nowrap;
84
- justify-content: flex-end;
85
-
86
- padding: 12px 15px;
87
-
88
- background-color: #f7f7f7;
89
-
90
- @media $mobile {
91
- position: absolute;
92
- right: 0;
93
- bottom: 0;
94
- left: 0;
95
- z-index: 10;
96
-
97
- min-height: 295px;
98
- padding: 20px;
99
-
100
- background-color: transparent;
101
- }
102
- }
103
-
104
- .hasGradient .body {
105
- @media $mobile {
106
- position: absolute;
107
- right: 0;
108
- bottom: 0;
109
- left: 0;
110
- z-index: 10;
111
-
112
- min-height: 295px;
113
-
114
- background-color: transparent;
115
- }
116
- }
117
-
118
- .picture {
119
- position: relative;
120
- }
121
-
122
- .picture::after {
123
- position: absolute;
124
- right: 1px;
125
- bottom: 0;
126
- left: 1px;
127
- z-index: 10;
128
-
129
- border-bottom: 1px solid rgba(0, 0, 0, 0.1);
130
-
131
- content: '';
132
-
133
- @media $mobile {
134
- content: '';
135
- }
136
- }
137
-
138
- .tag {
139
- position: absolute;
140
- top: 14px;
141
- right: 15px;
142
- left: 15px;
143
- z-index: 10;
144
-
145
- color: rgba(255, 255, 255, 0.7);
146
-
147
- font-size: 12px;
148
-
149
- @media $landscapeTablet {
150
- top: 16px;
151
- right: 20px;
152
- left: 20px;
153
- }
154
- }
155
-
156
- .center {
157
- width: 100%;
158
- max-width: 650px;
159
- margin-right: auto;
160
- margin-left: auto;
161
- }
162
-
163
- .title {
164
- font-weight: 700;
165
- font-size: 19px;
166
- font-family: $secondaryFont;
167
- line-height: 23px;
168
-
169
- @media $landscapeTablet {
170
- font-size: 1.3rem;
171
- line-height: 1.6rem;
172
- }
173
- }
174
-
175
- .price {
176
- display: block;
177
- }
178
-
179
- /* Themes */
180
-
181
- .dark {
182
- color: #000;
183
- }
184
-
185
- .dark .tag {
186
- color: rgba(0, 0, 0, 0.7);
187
- }
188
-
189
- .light {
190
- @media $mobile {
191
- color: #fff;
192
- text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
193
- }
194
- }
195
-
196
- /* Display */
197
-
198
- .mobile {
199
- @media $mobile {
200
- display: none;
201
- }
202
- }
203
-
204
- .desktop {
205
- display: none;
206
-
207
- @media $mobile {
208
- display: block;
209
- }
210
- }
@@ -1,12 +0,0 @@
1
- @import '../vars.css';
2
-
3
- .root {
4
- display: block;
5
-
6
- max-width: 650px;
7
- margin: 0 auto;
8
- }
9
-
10
- .card + .card {
11
- margin-top: 40px;
12
- }
@@ -1,52 +0,0 @@
1
- import React from 'react'
2
- import { ShopRelatedBlock } from '.'
3
- import { PreviewWrapper } from '../_storybook/PreviewWrapper'
4
-
5
- import styles from './ShopRelatedBlock.stories.module.css'
6
- import mock from './mock.json'
7
-
8
- export default {
9
- title: 'Main / ShopRelatedBlock',
10
- component: ShopRelatedBlock,
11
- parameters: {
12
- themeWrapperSideBySide: true
13
- }
14
- }
15
-
16
- const Example: React.FC = () => {
17
- return (
18
- <>
19
- <div className={styles.root}>
20
- <div className={styles.card}>
21
- <ShopRelatedBlock block={mock.rich} styleContext={['no_mods']} />
22
- </div>
23
- <div className={styles.card}>
24
- <ShopRelatedBlock block={mock.rich_dark} styleContext={['no_mods']} />
25
- </div>
26
- <div className={styles.card}>
27
- <ShopRelatedBlock
28
- block={mock.rich_and_featured_mobile}
29
- styleContext={['no_mods']}
30
- />
31
- </div>
32
- <div className={styles.card}>
33
- <ShopRelatedBlock
34
- block={mock.rich_and_featured_desktop}
35
- styleContext={['no_mods']}
36
- />
37
- </div>
38
- </div>
39
- </>
40
- )
41
- }
42
-
43
- export const Default: React.FC = () => (
44
- <>
45
- <PreviewWrapper theme="light">
46
- <Example />
47
- </PreviewWrapper>
48
- {/* <PreviewWrapper theme="dark">
49
- <Example />
50
- </PreviewWrapper> */}
51
- </>
52
- )
@@ -1,20 +0,0 @@
1
- import React from 'react'
2
- import { render } from '@testing-library/react'
3
- import { ShopRelatedBlock } from '.'
4
- import { ShopRelatedBlockProps } from './ShopRelatedBlock.types'
5
-
6
- import styles from './ShopRelatedBlock.module.css'
7
-
8
- describe('Related Rich Block', () => {
9
- let props: ShopRelatedBlockProps
10
-
11
- const renderComponent = () => render(<ShopRelatedBlock {...props} />)
12
-
13
- it('should have root style', () => {
14
- const { getByTestId } = renderComponent()
15
-
16
- const ShopRelatedBlock = getByTestId('realated-rich-block')
17
-
18
- expect(ShopRelatedBlock).toHaveClass(styles.root)
19
- })
20
- })
@@ -1,4 +0,0 @@
1
- export interface ShopRelatedBlockProps {
2
- block?: any
3
- styleContext?: any
4
- }
@@ -1,120 +0,0 @@
1
- /* eslint-disable react/jsx-no-target-blank */
2
- import React, { useEffect } from 'react'
3
-
4
- import { useInView } from 'react-intersection-observer'
5
- import { ShopRelatedBlockProps } from './ShopRelatedBlock.types'
6
-
7
- import postMessage from '../utils/postMessage'
8
- import { makeClassName, ClassNames } from '../utils/makeClassName'
9
- import makeStyleContext from '../utils/makeStyleContext'
10
- import generateGradient from '../utils/generateGradient'
11
-
12
- import { Tag } from '../Tag'
13
- import { Image } from '../Image'
14
-
15
- import styles from './ShopRelatedBlock.module.css'
16
-
17
- export const ShopRelatedBlock: React.FC<ShopRelatedBlockProps> = ({
18
- block: {
19
- only_on: onlyOn,
20
- data: {
21
- url,
22
- cover: {
23
- urls,
24
- gradients,
25
- tag,
26
- layout,
27
- ratio,
28
- first_title: firstTitle,
29
- second_title: secondTitle
30
- }
31
- }
32
- },
33
- styleContext
34
- }) => {
35
- const style: React.CSSProperties = {}
36
- const styleHeader: React.CSSProperties = {}
37
-
38
- const [ref, inView] = useInView({
39
- threshold: 0,
40
- triggerOnce: true
41
- })
42
-
43
- useEffect(() => {
44
- if (inView) {
45
- if (
46
- (onlyOn === 'mobile' && window.innerWidth <= 511) ||
47
- (onlyOn === 'desktop' && window.innerWidth >= 512) ||
48
- !onlyOn
49
- ) {
50
- postMessage('productRelated', url, 'view')
51
- }
52
- }
53
- }, [inView])
54
-
55
- const handleClick = () => {
56
- postMessage('productRelated', url, 'click')
57
- }
58
-
59
- let classNames: ClassNames = [
60
- [styles.root, true],
61
- [styles.hasGradient, !!gradients],
62
- [styles[onlyOn], !!onlyOn && !!styles[onlyOn]]
63
- ]
64
-
65
- if (styleContext) {
66
- classNames = makeStyleContext(classNames, styleContext, styles)
67
- }
68
-
69
- if (gradients) {
70
- styleHeader.backgroundImage = generateGradient(
71
- gradients.bg_rgb,
72
- 'mediaBlockTop'
73
- )
74
-
75
- const theme = [gradients.text_rgb === '0,0,0' ? 'dark' : 'light']
76
- classNames = makeStyleContext(classNames, theme, styles)
77
-
78
- if (onlyOn === 'desktop') {
79
- style.backgroundImage = generateGradient(
80
- gradients.bg_rgb,
81
- 'mediaBlockBottom'
82
- )
83
- }
84
- }
85
-
86
- return (
87
- <a
88
- data-testid="related-rich-block"
89
- className={makeClassName(classNames)}
90
- href={url}
91
- target="_blank"
92
- onClick={(): void => handleClick()}
93
- ref={ref}
94
- >
95
- {layout === 'rich' && (
96
- <>
97
- <div className={styles.overlay} style={style} />
98
- <div className={styles.overlayHeader} style={styleHeader} />
99
- </>
100
- )}
101
-
102
- <div className={styles.tag}>
103
- <Tag size="small" theme="inherit" styleContext="richRelated">
104
- {tag}
105
- </Tag>
106
- </div>
107
- <div className={styles.cover}>
108
- <div className={styles.picture}>
109
- <Image optimized={urls} ratio={ratio} display="narrow" />
110
- </div>
111
- </div>
112
- <div className={styles.body}>
113
- <h2 className={styles.title}>
114
- {firstTitle}
115
- <span className={styles.price}>{secondTitle}</span>
116
- </h2>
117
- </div>
118
- </a>
119
- )
120
- }
@@ -1,153 +0,0 @@
1
- {
2
- "rich": {
3
- "type": "related_shop",
4
- "data": {
5
- "url": "https://meduza.io/",
6
-
7
- "cover": {
8
- "ratio": 1.5,
9
- "layout": "rich",
10
- "urls": {
11
- "w325": {
12
- "1x": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
13
- "2x": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
14
- "1x_webp": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
15
- "2x_webp": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg"
16
- },
17
- "w600": {
18
- "1x": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
19
- "2x": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
20
- "1x_webp": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
21
- "2x_webp": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg"
22
- }
23
- },
24
- "gradients": {
25
- "text_rgb": "0,0,0",
26
- "bg_rgb": "214, 216, 207"
27
- },
28
- "tag": "Можно купить",
29
- "first_title": "Шторка для камеры",
30
- "second_title": "500р."
31
- }
32
- },
33
- "only_on": "mobile"
34
- },
35
-
36
- "rich_dark": {
37
- "type": "related_rich",
38
- "data": {
39
- "url": "https://meduza.io/",
40
- "fallback": {
41
- "data": {
42
- "title": "Не богато вышло",
43
- "related": [
44
- {
45
- "title": "«Если кто-нибудь видит меня и слышит, пожалуйста, распространите это видео любым способом! Чтобы я существовал!»",
46
- "second": "Автор фильма «Котлован» — о том, как сделал его из обращений россиян к Путину",
47
- "layout": "rich",
48
- "url": "feature/2018/09/18/na-rossiyskuyu-bolnitsu-pervye-podali-v-sud-za-otkaz-v-poseschenii-umirayuschego-v-reanimatsii-rodstvennika-sud-vstal-na-storonu-medikov",
49
- "id": "0-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
50
- }
51
- ]
52
- },
53
- "only_on": "desktop"
54
- },
55
- "cover": {
56
- "ratio": 1.5,
57
- "layout": "rich",
58
- "urls": {
59
- "w325": {
60
- "1x": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
61
- "2x": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
62
- "1x_webp": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
63
- "2x_webp": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg"
64
- },
65
- "w600": {
66
- "1x": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
67
- "2x": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
68
- "1x_webp": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
69
- "2x_webp": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg"
70
- }
71
- },
72
- "first_title": "Шторка для камеры",
73
- "second_title": "500р.",
74
-
75
- "tag": "Можно купить",
76
- "gradients": {
77
- "text_rgb": "255,255,255",
78
- "bg_rgb": "0,0,0"
79
- }
80
- }
81
- },
82
- "only_on": "desktop"
83
- },
84
-
85
- "rich_and_featured_desktop": {
86
- "type": "related_rich",
87
- "data": {
88
- "url": "https://meduza.io/",
89
-
90
- "cover": {
91
- "ratio": 1.5,
92
- "layout": "rich",
93
- "urls": {
94
- "w325": {
95
- "1x": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
96
- "2x": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
97
- "1x_webp": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
98
- "2x_webp": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg"
99
- },
100
- "w600": {
101
- "1x": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
102
- "2x": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
103
- "1x_webp": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg",
104
- "2x_webp": "//meduza.io/image/attachments/images/006/942/207/original/SvVDNHQAimcm6VGxS21y1A.jpg"
105
- }
106
- },
107
- "first_title": "Шторка для камеры",
108
- "second_title": "500р.",
109
-
110
- "tag": "Можно купить",
111
- "gradients": {
112
- "text_rgb": "0,0,0",
113
- "bg_rgb": "214, 216, 207"
114
- }
115
- }
116
- },
117
- "only_on": "desktop"
118
- },
119
-
120
- "rich_and_featured_mobile": {
121
- "type": "related_rich",
122
- "data": {
123
- "url": "https://meduza.io/",
124
-
125
- "cover": {
126
- "ratio": 0.63,
127
- "layout": "rich",
128
- "urls": {
129
- "w325": {
130
- "1x": "http://meduza.io/impro/YW9jtqBkQc7dgyPKdgtvS8JlSvPyIgY7p-7-9C49csw/fill/325/0/ce/1/aHR0cHM6Ly9tZWR1/emEuaW8vaW1hZ2Uv/YXR0YWNobWVudHMv/aW1hZ2VzLzAwNC81/NDMvOTE4L29yaWdp/bmFsLzRDeHQwdFR5/YWhlUGhnZHd4YVBz/R1EuanBn.jpg",
131
- "2x": "http://meduza.io/impro/jQf0sx4Df9y23YQ0HKyGauLGYB6kMxQ_jR2QExB4_Q0/fill/650/0/ce/1/aHR0cHM6Ly9tZWR1/emEuaW8vaW1hZ2Uv/YXR0YWNobWVudHMv/aW1hZ2VzLzAwNC81/NDMvOTE4L29yaWdp/bmFsLzRDeHQwdFR5/YWhlUGhnZHd4YVBz/R1EuanBn.jpg",
132
- "1x_webp": "http://meduza.io/impro/dROSpimx8lYjBAbaWxhjPzPggOoz_RxV8useloSPgbQ/fill/325/0/ce/1/aHR0cHM6Ly9tZWR1/emEuaW8vaW1hZ2Uv/YXR0YWNobWVudHMv/aW1hZ2VzLzAwNC81/NDMvOTE4L29yaWdp/bmFsLzRDeHQwdFR5/YWhlUGhnZHd4YVBz/R1EuanBn.webp",
133
- "2x_webp": "http://meduza.io/impro/dgkov3ooEbjTSe1sUvY-NLVUr6y56Dbmtpke_g-i65c/fill/650/0/ce/1/aHR0cHM6Ly9tZWR1/emEuaW8vaW1hZ2Uv/YXR0YWNobWVudHMv/aW1hZ2VzLzAwNC81/NDMvOTE4L29yaWdp/bmFsLzRDeHQwdFR5/YWhlUGhnZHd4YVBz/R1EuanBn.webp"
134
- },
135
- "w600": {
136
- "1x": "http://meduza.io/impro/03bNGjN3Exb5vIT4jm4-VouBTahiFgH9gF8MhGd5hdw/fill/600/0/ce/1/aHR0cHM6Ly9tZWR1/emEuaW8vaW1hZ2Uv/YXR0YWNobWVudHMv/aW1hZ2VzLzAwNC81/NDMvOTE4L29yaWdp/bmFsLzRDeHQwdFR5/YWhlUGhnZHd4YVBz/R1EuanBn.jpg",
137
- "2x": "http://meduza.io/impro/k7qCc2LDxE-qv6L2P5LBGo-Qmdlm68WxC2OIi6yg_SY/fill/1200/0/ce/1/aHR0cHM6Ly9tZWR1/emEuaW8vaW1hZ2Uv/YXR0YWNobWVudHMv/aW1hZ2VzLzAwNC81/NDMvOTE4L29yaWdp/bmFsLzRDeHQwdFR5/YWhlUGhnZHd4YVBz/R1EuanBn.jpg",
138
- "1x_webp": "http://meduza.io/impro/4So4ZS9GWd3WTs4fUY7Lbk4CiKkoPhUQiigwXxZVGo0/fill/600/0/ce/1/aHR0cHM6Ly9tZWR1/emEuaW8vaW1hZ2Uv/YXR0YWNobWVudHMv/aW1hZ2VzLzAwNC81/NDMvOTE4L29yaWdp/bmFsLzRDeHQwdFR5/YWhlUGhnZHd4YVBz/R1EuanBn.webp",
139
- "2x_webp": "http://meduza.io/impro/VZ5TtAH8GN9hENkyuoPhG7TvCLemOhHf1fgJKG9i5T4/fill/1200/0/ce/1/aHR0cHM6Ly9tZWR1/emEuaW8vaW1hZ2Uv/YXR0YWNobWVudHMv/aW1hZ2VzLzAwNC81/NDMvOTE4L29yaWdp/bmFsLzRDeHQwdFR5/YWhlUGhnZHd4YVBz/R1EuanBn.webp"
140
- }
141
- },
142
- "tag": "Можно купить",
143
- "gradients": {
144
- "text_rgb": "255,255,255",
145
- "bg_rgb": "0,0,0"
146
- },
147
- "first_title": "Шторка для камеры",
148
- "second_title": "500р."
149
- }
150
- },
151
- "only_on": "mobile"
152
- }
153
- }