@gravity-ui/page-constructor 1.8.0 → 1.8.2-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/build/cjs/blocks/Tabs/Tabs.css +64 -24
  3. package/build/cjs/blocks/Tabs/Tabs.d.ts +1 -1
  4. package/build/cjs/blocks/Tabs/Tabs.js +34 -27
  5. package/build/cjs/blocks/Tabs/schema.d.ts +68 -17
  6. package/build/cjs/blocks/Tabs/schema.js +14 -19
  7. package/build/cjs/components/ButtonTabs/ButtonTabs.css +12 -0
  8. package/build/cjs/components/ButtonTabs/ButtonTabs.d.ts +13 -0
  9. package/build/cjs/components/ButtonTabs/ButtonTabs.js +26 -0
  10. package/build/cjs/components/Image/Image.css +4 -0
  11. package/build/cjs/components/Image/Image.js +3 -1
  12. package/build/cjs/components/Media/Media.js +1 -1
  13. package/build/cjs/components/VideoBlock/VideoBlock.d.ts +2 -0
  14. package/build/cjs/components/VideoBlock/VideoBlock.js +7 -6
  15. package/build/cjs/constructor-items.d.ts +1 -1
  16. package/build/cjs/models/constructor-items/blocks.d.ts +7 -5
  17. package/build/cjs/sub-blocks/HubspotForm/HubspotForm.css +3 -0
  18. package/build/cjs/text-transform/blocks.js +11 -4
  19. package/build/esm/blocks/Tabs/Tabs.css +64 -24
  20. package/build/esm/blocks/Tabs/Tabs.d.ts +1 -1
  21. package/build/esm/blocks/Tabs/Tabs.js +35 -28
  22. package/build/esm/blocks/Tabs/schema.d.ts +68 -17
  23. package/build/esm/blocks/Tabs/schema.js +14 -20
  24. package/build/esm/components/ButtonTabs/ButtonTabs.css +12 -0
  25. package/build/esm/components/ButtonTabs/ButtonTabs.d.ts +14 -0
  26. package/build/esm/components/ButtonTabs/ButtonTabs.js +24 -0
  27. package/build/esm/components/Image/Image.css +4 -0
  28. package/build/esm/components/Image/Image.d.ts +1 -0
  29. package/build/esm/components/Image/Image.js +4 -1
  30. package/build/esm/components/Media/Media.js +1 -1
  31. package/build/esm/components/VideoBlock/VideoBlock.d.ts +2 -0
  32. package/build/esm/components/VideoBlock/VideoBlock.js +6 -6
  33. package/build/esm/constructor-items.d.ts +1 -1
  34. package/build/esm/models/constructor-items/blocks.d.ts +7 -5
  35. package/build/esm/sub-blocks/HubspotForm/HubspotForm.css +3 -0
  36. package/build/esm/text-transform/blocks.js +11 -4
  37. package/package.json +4 -1
  38. package/server/models/constructor-items/blocks.d.ts +7 -5
  39. package/server/text-transform/blocks.js +11 -4
@@ -23,7 +23,6 @@ const createItemsParser = (fields) => (transformer, items) => items.map((item) =
23
23
  }
24
24
  });
25
25
  exports.createItemsParser = createItemsParser;
26
- const parseItems = (0, exports.createItemsParser)(['title', 'text']);
27
26
  function parseTableBlock(transformer, content) {
28
27
  const legend = content === null || content === void 0 ? void 0 : content.legend;
29
28
  return Object.assign(Object.assign({}, (content || {})), { legend: legend && legend.map((string) => transformer(string)) });
@@ -49,9 +48,13 @@ function parseSlider(transformer, block) {
49
48
  }
50
49
  const parseTitle = (transformer, title) => typeof title === 'object' && 'text' in title
51
50
  ? Object.assign(Object.assign({}, title), { text: transformer(title.text) }) : title && transformer(title);
51
+ const parseItemsTitle = (transformer, items) => items.map((_a) => {
52
+ var { title } = _a, rest = (0, tslib_1.__rest)(_a, ["title"]);
53
+ return (Object.assign({ title: title && parseTitle(transformer, title) }, rest));
54
+ });
52
55
  function parsePriceDetailedBlock(transformer, block) {
53
56
  const { priceType } = block;
54
- const transformedBlockItems = block.items.map((item) => {
57
+ block.items = block.items.map((item) => {
55
58
  const { description, items: details = [] } = item;
56
59
  if (priceType === 'marked-list') {
57
60
  item.items = details.map((detail) => {
@@ -68,7 +71,6 @@ function parsePriceDetailedBlock(transformer, block) {
68
71
  item.description = transformer(description);
69
72
  return item;
70
73
  });
71
- block.items = transformedBlockItems;
72
74
  return block;
73
75
  }
74
76
  const parseContentLayout = (transformer, content) => {
@@ -226,7 +228,12 @@ const config = {
226
228
  {
227
229
  fields: ['items'],
228
230
  transformer: yfmTransformer,
229
- parser: parseItems,
231
+ parser: (0, exports.createItemsParser)(['text', 'additionalInfo']),
232
+ },
233
+ {
234
+ fields: ['items'],
235
+ transformer: typografTransformer,
236
+ parser: parseItemsTitle,
230
237
  },
231
238
  ],
232
239
  [models_1.BlockType.TableBlock]: [
@@ -1,68 +1,108 @@
1
- .pc-TabsBlock__content-title.pc-TabsBlock__content-title > * {
1
+ .pc-tabs-block__content-title.pc-tabs-block__content-title > * {
2
2
  margin: 0;
3
3
  }
4
4
 
5
5
  /* use this for style redefinitions to awoid problems with
6
6
  unpredictable css rules order in build */
7
- .pc-TabsBlock__block-title {
8
- margin-bottom: 12px;
7
+ .pc-tabs-block__block-title {
8
+ margin-bottom: 24px;
9
9
  }
10
- .pc-TabsBlock__tabs.pc-TabsBlock__tabs {
11
- flex-wrap: nowrap;
12
- overflow-x: auto;
13
- margin-bottom: 32px;
10
+ .pc-tabs-block__block-title_centered {
11
+ display: flex;
12
+ justify-content: center;
13
+ flex-wrap: wrap;
14
+ margin-left: auto;
15
+ margin-right: auto;
16
+ text-align: center;
14
17
  }
15
-
16
- .pc-TabsBlock__image {
18
+ .pc-tabs-block__tabs_centered {
19
+ display: flex;
20
+ justify-content: center;
21
+ flex-wrap: wrap;
22
+ }
23
+ .pc-tabs-block__row_reverse {
24
+ flex-direction: row-reverse;
25
+ }
26
+ .pc-tabs-block__row_reverse .pc-tabs-block__content-wrapper {
27
+ margin: 24px 32px 0 0;
28
+ }
29
+ .pc-tabs-block__image {
17
30
  width: 100%;
18
31
  height: auto;
19
32
  object-fit: cover;
20
33
  display: block;
21
34
  }
22
- .pc-TabsBlock__image, .pc-TabsBlock__media {
35
+ .pc-tabs-block__image, .pc-tabs-block__media {
23
36
  box-shadow: 0 2px 8px var(--pc-color-sfx-shadow), 0 4px 24px var(--pc-color-sfx-shadow);
24
37
  overflow-x: hidden;
25
38
  border-radius: var(--pc-border-radius);
26
39
  }
27
- .pc-TabsBlock__caption {
40
+ .pc-tabs-block__caption {
28
41
  font-size: var(--yc-text-body-2-font-size);
29
42
  line-height: var(--yc-text-body-2-line-height);
30
43
  margin: 12px 0 0;
31
44
  color: var(--yc-color-text-secondary);
32
45
  }
33
- .pc-TabsBlock__content {
46
+ .pc-tabs-block__content {
34
47
  display: flex;
35
48
  flex-direction: column;
36
49
  }
37
- .pc-TabsBlock__content-wrapper_margin {
50
+ .pc-tabs-block__content_centered {
51
+ margin: 0 auto;
52
+ }
53
+ .pc-tabs-block__col_centered {
54
+ margin: 0 auto;
55
+ }
56
+ .pc-tabs-block__content-wrapper_margin {
38
57
  margin: 24px 0 0 32px;
39
58
  }
40
- .pc-TabsBlock__content-title {
59
+ .pc-tabs-block__content-title {
41
60
  margin: 0 auto 12px;
42
61
  }
43
- .pc-TabsBlock__content-title.pc-TabsBlock__content-title > * {
62
+ .pc-tabs-block__content-title.pc-tabs-block__content-title > * {
44
63
  font-size: var(--yc-text-header-1-font-size);
45
64
  line-height: var(--yc-text-header-1-line-height);
46
65
  color: var(--pc-text-header-color);
47
66
  font-weight: var(--yc-text-accent-font-weight);
48
67
  }
49
68
 
50
- .pc-TabsBlock__tabs, .pc-TabsBlock__link {
51
- font-size: var(--yc-text-body-2-font-size);
52
- line-height: var(--yc-text-body-2-line-height);
53
- }
54
69
  @media (max-width: 769px) {
55
- .pc-TabsBlock__content-wrapper_margin {
70
+ .pc-tabs-block__tabs {
71
+ display: flex;
72
+ flex-wrap: nowrap;
73
+ justify-content: flex-start;
74
+ overflow: auto;
75
+ margin-left: -48px;
76
+ margin-right: -48px;
77
+ padding-left: 48px;
78
+ padding-right: 40px;
79
+ }
80
+ .pc-tabs-block__content-wrapper_margin {
56
81
  margin: 0 0 32px 0;
57
82
  }
83
+ .pc-tabs-block__row_reverse {
84
+ flex-direction: column-reverse;
85
+ }
86
+ .pc-tabs-block__row_reverse .pc-tabs-block__content > * {
87
+ margin-top: 32px;
88
+ padding-bottom: 0;
89
+ }
90
+ }
91
+ @media (max-width: 577px) {
92
+ .pc-tabs-block__tabs {
93
+ margin-left: -24px;
94
+ margin-right: -24px;
95
+ padding-left: 24px;
96
+ padding-right: 16px;
97
+ }
58
98
  }
59
99
  @media (min-width: 769px) {
60
- .pc-TabsBlock.pc-AnimateBlock .pc-TabsBlock__media, .pc-AnimateBlock .pc-TabsBlock .pc-TabsBlock__media {
100
+ .pc-tabs-block.pc-AnimateBlock .pc-tabs-block__media, .pc-AnimateBlock .pc-tabs-block .pc-tabs-block__media {
61
101
  position: relative;
62
102
  top: 100px;
63
103
  opacity: 0;
64
104
  }
65
- .pc-TabsBlock.pc-AnimateBlock.animate .pc-TabsBlock__media, .pc-AnimateBlock .pc-TabsBlock.animate .pc-TabsBlock__media {
105
+ .pc-tabs-block.pc-AnimateBlock.animate .pc-tabs-block__media, .pc-AnimateBlock .pc-tabs-block.animate .pc-tabs-block__media {
66
106
  top: 0;
67
107
  opacity: 1;
68
108
  transition: top 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94), opacity 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
@@ -70,12 +110,12 @@ unpredictable css rules order in build */
70
110
  }
71
111
  }
72
112
  @media (min-width: 769px) {
73
- .pc-TabsBlock.pc-AnimateBlock .pc-TabsBlock__image, .pc-AnimateBlock .pc-TabsBlock .pc-TabsBlock__image {
113
+ .pc-tabs-block.pc-AnimateBlock .pc-tabs-block__image, .pc-AnimateBlock .pc-tabs-block .pc-tabs-block__image {
74
114
  position: relative;
75
115
  top: 100px;
76
116
  opacity: 0;
77
117
  }
78
- .pc-TabsBlock.pc-AnimateBlock.animate .pc-TabsBlock__image, .pc-AnimateBlock .pc-TabsBlock.animate .pc-TabsBlock__image {
118
+ .pc-tabs-block.pc-AnimateBlock.animate .pc-tabs-block__image, .pc-AnimateBlock .pc-tabs-block.animate .pc-tabs-block__image {
79
119
  top: 0;
80
120
  opacity: 1;
81
121
  transition: top 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94), opacity 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
@@ -1,4 +1,4 @@
1
1
  import { TabsBlockProps } from '../../models';
2
2
  import './Tabs.css';
3
- export declare const TabsBlock: ({ items, title, description, animated }: TabsBlockProps) => JSX.Element;
3
+ export declare const TabsBlock: ({ items, title, description, animated, tabsColSizes, centered, direction, }: TabsBlockProps) => JSX.Element;
4
4
  export default TabsBlock;
@@ -1,51 +1,58 @@
1
- import React, { Fragment, useContext, useState } from 'react';
2
- import { Tabs } from '@gravity-ui/uikit';
1
+ import React, { Fragment, useContext, useRef, useState } from 'react';
3
2
  import { block, getThemedValue } from '../../utils';
4
3
  import { Row, Col, GridColumnOrderClasses } from '../../grid';
5
- import YFMWrapper from '../../components/YFMWrapper/YFMWrapper';
6
4
  import AnimateBlock from '../../components/AnimateBlock/AnimateBlock';
7
5
  import BlockHeader from '../../components/BlockHeader/BlockHeader';
8
6
  import FullScreenImage from '../../components/FullscreenImage/FullscreenImage';
9
7
  import Media from '../../components/Media/Media';
10
- import Links from '../../components/Link/Links';
11
8
  import { ThemeValueContext } from '../../context/theme/ThemeValueContext';
12
9
  import { getMediaImage } from '../../components/Media/Image/utils';
10
+ import ButtonTabs from '../../components/ButtonTabs/ButtonTabs';
11
+ import { Content } from '../../sub-blocks';
12
+ import { getHeight } from '../../components/VideoBlock/VideoBlock';
13
13
  import './Tabs.css';
14
- const b = block('TabsBlock');
15
- export const TabsBlock = ({ items, title, description, animated }) => {
14
+ const b = block('tabs-block');
15
+ export const TabsBlock = ({ items, title, description, animated, tabsColSizes, centered, direction = 'media-content', }) => {
16
+ var _a;
16
17
  const [activeTab, setActiveTab] = useState(items[0].tabName);
17
18
  const [play, setPlay] = useState(false);
18
19
  const { themeValue: theme } = useContext(ThemeValueContext);
19
20
  const tabs = items.map(({ tabName }) => ({ title: tabName, id: tabName }));
20
21
  const activeTabData = items.find(({ tabName }) => tabName === activeTab);
22
+ const isReverse = direction === 'content-media';
23
+ const ref = useRef(null);
24
+ const mediaWidth = (_a = ref === null || ref === void 0 ? void 0 : ref.current) === null || _a === void 0 ? void 0 : _a.offsetWidth;
25
+ const mediaHeight = mediaWidth && getHeight(mediaWidth);
21
26
  let imageProps;
22
27
  if (activeTabData) {
23
28
  const themedImage = getThemedValue(activeTabData.image, theme);
24
29
  imageProps = themedImage && getMediaImage(themedImage);
25
30
  }
26
31
  const showMedia = Boolean((activeTabData === null || activeTabData === void 0 ? void 0 : activeTabData.media) || imageProps);
32
+ const showText = Boolean(activeTabData === null || activeTabData === void 0 ? void 0 : activeTabData.text);
33
+ const textContent = activeTabData && showText && (React.createElement(Col, { sizes: { all: 12, md: showMedia ? 4 : 8 }, className: b('content', { centered: centered }) },
34
+ React.createElement("div", { className: b('content-wrapper', {
35
+ margin: Boolean(((activeTabData === null || activeTabData === void 0 ? void 0 : activeTabData.media) || imageProps) && !isReverse),
36
+ }) },
37
+ React.createElement(Content, { title: activeTabData.title, text: activeTabData.text, additionalInfo: activeTabData.additionalInfo, size: "s", links: [
38
+ ...(activeTabData.link ? [activeTabData.link] : []),
39
+ ...(activeTabData.links || []),
40
+ ], buttons: activeTabData.buttons, colSizes: { all: 12 } }))));
41
+ const mediaContent = showMedia && (React.createElement(Col, { sizes: { all: 12, md: 8 }, orders: {
42
+ all: GridColumnOrderClasses.Last,
43
+ md: GridColumnOrderClasses.First,
44
+ }, className: b('col', { centered: centered }) },
45
+ React.createElement("div", { ref: ref }, (activeTabData === null || activeTabData === void 0 ? void 0 : activeTabData.media) && (React.createElement(Media, Object.assign({}, getThemedValue(activeTabData.media, theme), { key: activeTab, className: b('media'), playVideo: play, height: mediaHeight })))),
46
+ imageProps && (React.createElement(Fragment, null,
47
+ React.createElement(FullScreenImage, Object.assign({}, imageProps, { imageClassName: b('image') })),
48
+ (activeTabData === null || activeTabData === void 0 ? void 0 : activeTabData.caption) && (React.createElement("p", { className: b('caption') }, activeTabData.caption))))));
27
49
  return (React.createElement(AnimateBlock, { className: b(), onScroll: () => setPlay(true), animate: animated },
28
- React.createElement(BlockHeader, { title: title, description: description, className: b('block-title') }),
29
- React.createElement(Tabs, { className: b('tabs'), items: tabs, activeTab: activeTab, onSelectTab: setActiveTab, size: "l" }),
30
- activeTabData && (React.createElement(Row, null,
31
- showMedia && (React.createElement(Col, { sizes: { all: 12, md: 8 }, orders: {
32
- all: GridColumnOrderClasses.Last,
33
- md: GridColumnOrderClasses.First,
34
- } },
35
- (activeTabData === null || activeTabData === void 0 ? void 0 : activeTabData.media) && (React.createElement(Media, Object.assign({}, getThemedValue(activeTabData.media, theme), { key: activeTab, className: b('media'), playVideo: play }))),
36
- imageProps && (React.createElement(Fragment, null,
37
- React.createElement(FullScreenImage, Object.assign({}, imageProps, { imageClassName: b('image') })),
38
- activeTabData && (React.createElement("p", { className: b('caption') }, activeTabData.caption)))))),
39
- React.createElement(Col, { sizes: { all: 12, md: showMedia ? 4 : 8 }, className: b('content') },
40
- React.createElement("div", { className: b('content-wrapper', {
41
- margin: Boolean((activeTabData === null || activeTabData === void 0 ? void 0 : activeTabData.media) || imageProps),
42
- }) },
43
- React.createElement("h4", { className: b('content-title') },
44
- React.createElement(YFMWrapper, { content: activeTabData.title, modifiers: { constructor: true } })),
45
- React.createElement(YFMWrapper, { content: activeTabData.text, modifiers: { constructor: true } }),
46
- React.createElement(Links, { links: [
47
- ...(activeTabData.link ? [activeTabData.link] : []),
48
- ...(activeTabData.links || []),
49
- ], className: b('link') })))))));
50
+ React.createElement(BlockHeader, { title: title, description: description, className: b('block-title', { centered: centered }) }),
51
+ React.createElement(Row, null,
52
+ React.createElement(Col, { sizes: tabsColSizes },
53
+ React.createElement(ButtonTabs, { items: tabs, onSelectTab: setActiveTab, activeTab: activeTab, className: b('tabs', { centered: centered }) }))),
54
+ activeTabData && (React.createElement(Row, { className: b('row', { reverse: isReverse }) },
55
+ mediaContent,
56
+ textContent))));
50
57
  };
51
58
  export default TabsBlock;
@@ -6,12 +6,6 @@ export declare const tabsItem: {
6
6
  tabName: {
7
7
  type: string;
8
8
  };
9
- title: {
10
- type: string;
11
- };
12
- text: {
13
- type: string;
14
- };
15
9
  caption: {
16
10
  type: string;
17
11
  };
@@ -184,17 +178,6 @@ export declare const tabsItem: {
184
178
  when: {};
185
179
  };
186
180
  };
187
- links: {
188
- type: string;
189
- items: {
190
- type: string;
191
- properties: {
192
- when: {
193
- type: string;
194
- };
195
- };
196
- };
197
- };
198
181
  image: {
199
182
  oneOf: ({
200
183
  oneOf: ({
@@ -215,6 +198,66 @@ export declare const tabsItem: {
215
198
  properties: {};
216
199
  })[];
217
200
  };
201
+ title?: {
202
+ oneOf: ({
203
+ type: string;
204
+ additionalProperties: boolean;
205
+ required: string[];
206
+ properties: {
207
+ text: {
208
+ type: string;
209
+ };
210
+ textSize: {
211
+ type: string;
212
+ enum: string[];
213
+ };
214
+ url: {
215
+ type: string;
216
+ };
217
+ resetMargin: {
218
+ type: string;
219
+ };
220
+ };
221
+ } | {
222
+ type: string;
223
+ })[];
224
+ } | undefined;
225
+ text?: {
226
+ type: string;
227
+ } | undefined;
228
+ additionalInfo?: {
229
+ type: string;
230
+ } | undefined;
231
+ size?: {
232
+ type: string;
233
+ enum: string[];
234
+ } | undefined;
235
+ links?: {
236
+ type: string;
237
+ items: {
238
+ type: string;
239
+ properties: {
240
+ when: {
241
+ type: string;
242
+ };
243
+ };
244
+ };
245
+ } | undefined;
246
+ buttons?: {
247
+ type: string;
248
+ items: {
249
+ type: string;
250
+ properties: {
251
+ when: {
252
+ type: string;
253
+ };
254
+ };
255
+ };
256
+ } | undefined;
257
+ theme?: {
258
+ type: string;
259
+ enum: string[];
260
+ } | undefined;
218
261
  };
219
262
  };
220
263
  export declare const TabsBlock: {
@@ -245,6 +288,14 @@ export declare const TabsBlock: {
245
288
  description: {
246
289
  type: string;
247
290
  };
291
+ tabsColSizes: {};
292
+ direction: {
293
+ type: string;
294
+ enum: string[];
295
+ };
296
+ centered: {
297
+ type: string;
298
+ };
248
299
  items: {
249
300
  type: string;
250
301
  items: {
@@ -1,32 +1,23 @@
1
1
  import { filteredArray } from '../../schema/validators/utils';
2
- import { LinkProps, withTheme, BlockBaseProps, TitleProps, MediaProps, } from '../../schema/validators/common';
2
+ import { LinkProps, withTheme, BlockBaseProps, TitleProps, MediaProps, containerSizesArray, sizeNumber, mediaDirection, } from '../../schema/validators/common';
3
3
  import { ImageProps } from '../../components/Image/schema';
4
+ import _ from 'lodash';
5
+ import { ContentBase } from '../../sub-blocks/Content/schema';
6
+ const TabsItemContentProps = _.omit(ContentBase, ['size', 'colSizes', 'centered', 'theme']);
4
7
  export const tabsItem = {
5
8
  type: 'object',
6
9
  additionalProperties: false,
7
- required: ['tabName', 'text'],
8
- properties: {
9
- tabName: {
10
+ required: ['tabName'],
11
+ properties: Object.assign(Object.assign({}, TabsItemContentProps), { tabName: {
10
12
  type: 'string',
11
- },
12
- title: {
13
+ }, caption: {
13
14
  type: 'string',
14
- },
15
- text: {
16
- type: 'string',
17
- },
18
- caption: {
19
- type: 'string',
20
- },
21
- media: withTheme({
15
+ }, media: withTheme({
22
16
  type: 'object',
23
17
  properties: MediaProps,
24
- }),
18
+ }),
25
19
  //TODO deprecated
26
- link: LinkProps,
27
- links: filteredArray(LinkProps),
28
- image: withTheme(ImageProps),
29
- },
20
+ link: LinkProps, image: withTheme(ImageProps) }),
30
21
  };
31
22
  export const TabsBlock = {
32
23
  'tabs-block': {
@@ -34,6 +25,9 @@ export const TabsBlock = {
34
25
  required: ['title', 'items'],
35
26
  properties: Object.assign(Object.assign({}, BlockBaseProps), { title: TitleProps, description: {
36
27
  type: 'string',
37
- }, items: filteredArray(tabsItem) }),
28
+ }, tabsColSizes: containerSizesArray.reduce((acc, size) => (Object.assign(Object.assign({}, acc), { [size]: sizeNumber })), {}), direction: {
29
+ type: 'string',
30
+ enum: mediaDirection,
31
+ }, centered: { type: 'boolean' }, items: filteredArray(tabsItem) }),
38
32
  },
39
33
  };
@@ -0,0 +1,12 @@
1
+ /* use this for style redefinitions to awoid problems with
2
+ unpredictable css rules order in build */
3
+ .pc-button-tabs {
4
+ margin-bottom: 20px;
5
+ }
6
+ .pc-button-tabs__item {
7
+ margin-right: 8px;
8
+ margin-bottom: 12px;
9
+ }
10
+ .pc-button-tabs__item_active {
11
+ pointer-events: none;
12
+ }
@@ -0,0 +1,14 @@
1
+ import { ButtonProps } from '../../models';
2
+ import './ButtonTabs.css';
3
+ export interface ButtonTabsItemProps extends Omit<ButtonProps, 'url' | 'primary' | 'target' | 'text'> {
4
+ id: string;
5
+ title: string;
6
+ }
7
+ export interface ButtonTabsProps {
8
+ className?: string;
9
+ items: ButtonTabsItemProps[];
10
+ activeTab?: string;
11
+ onSelectTab?: (tabId: string) => void;
12
+ }
13
+ declare const ButtonTabs: (props: ButtonTabsProps) => JSX.Element;
14
+ export default ButtonTabs;
@@ -0,0 +1,24 @@
1
+ import React, { useCallback, useMemo } from 'react';
2
+ import { block } from '../../utils';
3
+ import { Button } from '../index';
4
+ import './ButtonTabs.css';
5
+ const b = block('button-tabs');
6
+ const ButtonTabs = (props) => {
7
+ const { className, items, activeTab, onSelectTab } = props;
8
+ const activeTabId = useMemo(() => {
9
+ if (activeTab) {
10
+ return activeTab;
11
+ }
12
+ return items[0].id;
13
+ }, [activeTab, items]);
14
+ const handleClick = useCallback((tabId) => {
15
+ if (onSelectTab) {
16
+ onSelectTab(tabId);
17
+ }
18
+ }, [onSelectTab]);
19
+ return (React.createElement("div", { className: b(null, className) }, items.map((item) => {
20
+ const isActive = item.id === activeTabId;
21
+ return (React.createElement(Button, { text: item.title, className: b('item', { active: isActive }), key: item.title, size: 'l', onClick: () => handleClick(item.id), theme: isActive ? 'monochrome' : 'normal' }));
22
+ })));
23
+ };
24
+ export default ButtonTabs;
@@ -0,0 +1,4 @@
1
+ .pc-image {
2
+ height: 100%;
3
+ width: 100%;
4
+ }
@@ -1,5 +1,6 @@
1
1
  import { CSSProperties, MouseEventHandler } from 'react';
2
2
  import { ImageDeviceProps, ImageObjectProps } from '../../models';
3
+ import './Image.css';
3
4
  export interface ImageProps extends Partial<ImageObjectProps>, Partial<ImageDeviceProps> {
4
5
  style?: CSSProperties;
5
6
  className?: string;
@@ -1,6 +1,9 @@
1
1
  import React, { useContext, useState, Fragment } from 'react';
2
2
  import { ProjectSettingsContext } from '../../context/projectSettingsContext';
3
3
  import { BREAKPOINTS } from '../../constants';
4
+ import { block } from '../../utils';
5
+ import './Image.css';
6
+ const b = block('image');
4
7
  const checkWebP = (src) => {
5
8
  return src.endsWith('.webp') ? src : src + '.webp';
6
9
  };
@@ -17,7 +20,7 @@ const Image = (props) => {
17
20
  disableCompress ||
18
21
  imageSrc.endsWith('.svg') ||
19
22
  imgLoadingError;
20
- return (React.createElement("picture", null,
23
+ return (React.createElement("picture", { className: b() },
21
24
  mobile && (React.createElement(Fragment, null,
22
25
  !disableWebp && (React.createElement("source", { srcSet: checkWebP(mobile), type: "image/webp", media: `(max-width: ${BREAKPOINTS.sm}px)` })),
23
26
  React.createElement("source", { srcSet: mobile, media: `(max-width: ${BREAKPOINTS.sm}px)` }))),
@@ -19,7 +19,7 @@ export const Media = (props) => {
19
19
  result.push(React.createElement(Video, { key: "video", video: video, videoClassName: videoClassName, height: height, metrika: metrika, playVideo: playVideo, previewImg: previewImg, playButton: playButton, customBarControlsClassName: customBarControlsClassName, hasVideoFallback: hasVideoFallback, setHasVideoFallback: setHasVideoFallback }));
20
20
  }
21
21
  if (youtube) {
22
- result = (React.createElement(YoutubeBlock, { className: b('youtube', youtubeClassName), record: youtube, attributes: { color: 'white', rel: '0' }, previewImg: previewImg }));
22
+ result = (React.createElement(YoutubeBlock, { className: b('youtube', youtubeClassName), record: youtube, attributes: { color: 'white', rel: '0' }, previewImg: previewImg, height: height }));
23
23
  }
24
24
  if (dataLens) {
25
25
  result = React.createElement(DataLens, { dataLens: dataLens });
@@ -4,6 +4,7 @@ export declare const AUTOPLAY_ATTRIBUTES: {
4
4
  autoplay: number;
5
5
  mute: number;
6
6
  };
7
+ export declare function getHeight(width: number): number;
7
8
  export interface VideoBlockProps {
8
9
  id?: string;
9
10
  stream?: string;
@@ -12,6 +13,7 @@ export interface VideoBlockProps {
12
13
  className?: string;
13
14
  previewImg?: string;
14
15
  playButton?: React.ReactNode;
16
+ height?: number;
15
17
  }
16
18
  declare const VideoBlock: (props: VideoBlockProps) => JSX.Element | null;
17
19
  export default VideoBlock;
@@ -30,17 +30,17 @@ function getVideoSrc(stream, record) {
30
30
  }
31
31
  return src;
32
32
  }
33
- function getHeight(width) {
33
+ export function getHeight(width) {
34
34
  return (width / 16) * 9;
35
35
  }
36
36
  const VideoBlock = (props) => {
37
- const { stream, record, attributes, className, id, previewImg, playButton } = props;
37
+ const { stream, record, attributes, className, id, previewImg, playButton, height } = props;
38
38
  const src = getVideoSrc(stream, record);
39
39
  const ref = useRef(null);
40
40
  const iframeRef = useRef();
41
41
  const [hidePreview, setHidePreview] = useState(false);
42
42
  const norender = (!stream && !record) || !src;
43
- const [height, setHeight] = useState();
43
+ const [currentHeight, setCurrentHeight] = useState(height || undefined);
44
44
  const fullId = `${iframeId}-${id || src}`;
45
45
  const onPreviewClick = useCallback(() => {
46
46
  if (iframeRef.current) {
@@ -50,14 +50,14 @@ const VideoBlock = (props) => {
50
50
  }, [src, attributes]);
51
51
  useEffect(() => {
52
52
  const updateSize = _.debounce(() => {
53
- setHeight(ref.current ? Math.round(getHeight(ref.current.offsetWidth)) : undefined);
53
+ setCurrentHeight(ref.current ? Math.floor(getHeight(ref.current.offsetWidth)) : undefined);
54
54
  }, 100);
55
55
  updateSize();
56
56
  window.addEventListener('resize', updateSize);
57
57
  return () => {
58
58
  window.removeEventListener('resize', updateSize);
59
59
  };
60
- }, []);
60
+ }, [height]);
61
61
  useEffect(() => {
62
62
  if (norender) {
63
63
  return;
@@ -86,7 +86,7 @@ const VideoBlock = (props) => {
86
86
  if (norender) {
87
87
  return null;
88
88
  }
89
- return (React.createElement("div", { className: b(null, className), ref: ref, style: { height } }, previewImg && !hidePreview && (React.createElement("div", { className: b('preview'), onClick: onPreviewClick },
89
+ return (React.createElement("div", { className: b(null, className), ref: ref, style: { height: currentHeight } }, previewImg && !hidePreview && (React.createElement("div", { className: b('preview'), onClick: onPreviewClick },
90
90
  React.createElement(Image, { src: previewImg, className: b('image') }),
91
91
  playButton || (React.createElement("button", { className: b('button') },
92
92
  React.createElement(Icon, { className: b('icon'), data: PlayVideo, size: 24 })))))));
@@ -11,7 +11,7 @@ export declare const blockMap: {
11
11
  "info-block": (props: import("./models").InfoBlockProps) => JSX.Element;
12
12
  "security-block": (props: import("./models").SecurityBlockProps) => JSX.Element;
13
13
  "table-block": (props: import("./models").TableBlockProps) => JSX.Element;
14
- "tabs-block": ({ items, title, description, animated }: import("./models").TabsBlockProps) => JSX.Element;
14
+ "tabs-block": ({ items, title, description, animated, tabsColSizes, centered, direction, }: import("./models").TabsBlockProps) => JSX.Element;
15
15
  "link-table-block": ({ items, title, description, linkTheme }: import("./models").LinkTableBlockProps) => JSX.Element;
16
16
  "header-block": (props: import("./models").WithChildren<import("./models").HeaderBlockProps & import("./models").ClassNameProps>) => JSX.Element;
17
17
  "icons-block": ({ title, size, items }: import("./models").IconsBlockProps) => JSX.Element;
@@ -219,18 +219,20 @@ export interface TableBlockProps {
219
219
  title: string;
220
220
  table: TableProps;
221
221
  }
222
- export interface TabsBlockItem {
222
+ export interface TabsBlockItem extends Omit<ContentBlockProps, 'size' | 'colSizes' | 'centered' | 'theme'> {
223
223
  tabName: string;
224
- title: string;
225
- text: string;
224
+ /**
225
+ * @deprecated Use array links from ContentBlockProps instead
226
+ */
226
227
  link?: LinkProps;
227
228
  image?: ThemedImage;
228
- disableCompress?: boolean;
229
229
  caption?: string;
230
230
  media?: ThemedMediaProps;
231
- links?: LinkProps[];
232
231
  }
233
232
  export interface TabsBlockProps extends BlockHeaderProps, Animatable {
233
+ tabsColSizes?: GridColumnSizesType;
234
+ centered?: boolean;
235
+ direction?: MediaDirection;
234
236
  items: TabsBlockItem[];
235
237
  }
236
238
  export interface LinkTableBlockProps extends BlockHeaderProps {
@@ -16,6 +16,9 @@ unpredictable css rules order in build */
16
16
  padding: 5px 0 0;
17
17
  position: relative;
18
18
  }
19
+ .pc-hubspot-form .hs-form-field:only-child > label {
20
+ width: 100%;
21
+ }
19
22
  .pc-hubspot-form .hs-form-field .input {
20
23
  box-sizing: border-box;
21
24
  display: inline-block;