@gravity-ui/page-constructor 1.15.0-alpha.22 → 1.15.0-alpha.24

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 (178) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +3 -35
  3. package/build/cjs/blocks/Share/Share.js +1 -7
  4. package/build/cjs/blocks/Slider/Arrow/Arrow.js +2 -2
  5. package/build/cjs/blocks/Slider/Slider.css +0 -4
  6. package/build/cjs/components/BackLink/BackLink.js +2 -9
  7. package/build/cjs/components/Button/Button.d.ts +0 -1
  8. package/build/cjs/components/Button/Button.js +1 -9
  9. package/build/cjs/components/CardBase/CardBase.js +1 -8
  10. package/build/cjs/components/Foldable/Foldable.css +4 -1
  11. package/build/cjs/components/Foldable/Foldable.js +7 -10
  12. package/build/cjs/components/FullscreenImage/FullscreenImage.js +8 -6
  13. package/build/cjs/components/FullscreenMedia/FullScreenMedia.css +70 -0
  14. package/build/cjs/components/FullscreenMedia/FullScreenMedia.d.ts +9 -0
  15. package/build/cjs/components/FullscreenMedia/FullScreenMedia.js +40 -0
  16. package/build/cjs/components/HeightCalculator/HeightCalculator.d.ts +4 -0
  17. package/build/cjs/components/HeightCalculator/HeightCalculator.js +4 -0
  18. package/build/cjs/components/Link/Link.js +1 -8
  19. package/build/cjs/components/Media/Media.js +3 -2
  20. package/build/cjs/components/MetaInfo/MetaInfo.css +13 -0
  21. package/build/cjs/components/MetaInfo/MetaInfo.d.ts +6 -0
  22. package/build/cjs/components/MetaInfo/MetaInfo.js +8 -0
  23. package/build/cjs/components/MetaInfo/schema.d.ts +8 -0
  24. package/build/cjs/components/MetaInfo/schema.js +10 -0
  25. package/build/cjs/components/ReactPlayer/ReactPlayer.js +2 -8
  26. package/build/cjs/components/VideoBlock/VideoBlock.d.ts +1 -0
  27. package/build/cjs/components/VideoBlock/VideoBlock.js +6 -10
  28. package/build/cjs/components/YandexForm/YandexForm.js +1 -7
  29. package/build/cjs/components/index.d.ts +2 -0
  30. package/build/cjs/components/index.js +5 -1
  31. package/build/cjs/constructor-items.d.ts +4 -0
  32. package/build/cjs/constructor-items.js +4 -0
  33. package/build/cjs/containers/PageConstructor/PageConstructor.css +1 -0
  34. package/build/cjs/containers/PageConstructor/components/ConstructorBlocks/ConstructorBlocks.js +6 -4
  35. package/build/cjs/containers/PageConstructor/components/ConstructorItem/ConstructorItem.d.ts +1 -2
  36. package/build/cjs/containers/PageConstructor/components/ConstructorItem/ConstructorItem.js +2 -4
  37. package/build/cjs/context/blockIdContext/blockIdContext.d.ts +3 -0
  38. package/build/cjs/context/{blockPositionContext/blockPositionContext.js → blockIdContext/blockIdContext.js} +2 -2
  39. package/build/cjs/context/blockIdContext/index.d.ts +1 -0
  40. package/build/cjs/context/{blockPositionContext → blockIdContext}/index.js +1 -1
  41. package/build/cjs/hooks/index.d.ts +1 -0
  42. package/build/cjs/hooks/index.js +1 -0
  43. package/build/cjs/hooks/useAnalyticsEvent.d.ts +7 -0
  44. package/build/cjs/hooks/useAnalyticsEvent.js +16 -0
  45. package/build/cjs/hooks/useHeightCalculator.d.ts +6 -0
  46. package/build/cjs/hooks/useHeightCalculator.js +27 -0
  47. package/build/cjs/models/common.d.ts +11 -0
  48. package/build/cjs/models/common.js +13 -1
  49. package/build/cjs/models/constructor-items/common.d.ts +1 -19
  50. package/build/cjs/models/constructor-items/sub-blocks.d.ts +15 -0
  51. package/build/cjs/models/constructor-items/sub-blocks.js +4 -0
  52. package/build/cjs/navigation/components/NavigationItem/NavigationItem.js +4 -5
  53. package/build/cjs/schema/index.js +1 -0
  54. package/build/cjs/schema/validators/sub-blocks.d.ts +1 -0
  55. package/build/cjs/schema/validators/sub-blocks.js +1 -0
  56. package/build/cjs/sub-blocks/BannerCard/BannerCard.js +2 -1
  57. package/build/cjs/sub-blocks/HubspotForm/HubspotForm.css +14 -9
  58. package/build/cjs/sub-blocks/HubspotForm/HubspotFormContainer.d.ts +1 -1
  59. package/build/cjs/sub-blocks/HubspotForm/HubspotFormContainer.js +26 -8
  60. package/build/cjs/sub-blocks/HubspotForm/index.js +5 -9
  61. package/build/cjs/sub-blocks/LayoutItem/LayoutItem.css +16 -0
  62. package/build/cjs/sub-blocks/LayoutItem/LayoutItem.d.ts +3 -0
  63. package/build/cjs/sub-blocks/LayoutItem/LayoutItem.js +21 -0
  64. package/build/cjs/sub-blocks/LayoutItem/schema.d.ts +218 -0
  65. package/build/cjs/sub-blocks/LayoutItem/schema.js +18 -0
  66. package/build/cjs/sub-blocks/LayoutItem/utils.d.ts +28 -0
  67. package/build/cjs/sub-blocks/LayoutItem/utils.js +12 -0
  68. package/build/cjs/sub-blocks/Quote/Quote.js +1 -8
  69. package/build/cjs/sub-blocks/index.d.ts +1 -0
  70. package/build/cjs/sub-blocks/index.js +3 -1
  71. package/build/cjs/text-transform/blocks.js +17 -0
  72. package/build/cjs/utils/analytics.d.ts +2 -0
  73. package/build/cjs/utils/analytics.js +17 -0
  74. package/build/cjs/utils/blocks.d.ts +0 -7
  75. package/build/cjs/utils/blocks.js +1 -5
  76. package/build/cjs/utils/hubspot.d.ts +2 -1
  77. package/build/cjs/utils/hubspot.js +5 -1
  78. package/build/cjs/utils/index.d.ts +1 -0
  79. package/build/cjs/utils/index.js +1 -0
  80. package/build/esm/blocks/Share/Share.js +4 -10
  81. package/build/esm/blocks/Slider/Arrow/Arrow.js +2 -2
  82. package/build/esm/blocks/Slider/Slider.css +0 -4
  83. package/build/esm/components/BackLink/BackLink.js +4 -11
  84. package/build/esm/components/Button/Button.d.ts +0 -1
  85. package/build/esm/components/Button/Button.js +4 -12
  86. package/build/esm/components/CardBase/CardBase.js +4 -11
  87. package/build/esm/components/Foldable/Foldable.css +4 -1
  88. package/build/esm/components/Foldable/Foldable.js +8 -11
  89. package/build/esm/components/FullscreenImage/FullscreenImage.js +9 -7
  90. package/build/esm/components/FullscreenMedia/FullScreenMedia.css +70 -0
  91. package/build/esm/components/FullscreenMedia/FullScreenMedia.d.ts +10 -0
  92. package/build/esm/components/FullscreenMedia/FullScreenMedia.js +38 -0
  93. package/build/esm/components/HeightCalculator/HeightCalculator.d.ts +4 -0
  94. package/build/esm/components/HeightCalculator/HeightCalculator.js +4 -0
  95. package/build/esm/components/Link/Link.js +4 -11
  96. package/build/esm/components/Media/Media.js +3 -2
  97. package/build/esm/components/MetaInfo/MetaInfo.css +13 -0
  98. package/build/esm/components/MetaInfo/MetaInfo.d.ts +7 -0
  99. package/build/esm/components/MetaInfo/MetaInfo.js +6 -0
  100. package/build/esm/components/MetaInfo/schema.d.ts +8 -0
  101. package/build/esm/components/MetaInfo/schema.js +8 -0
  102. package/build/esm/components/ReactPlayer/ReactPlayer.js +3 -9
  103. package/build/esm/components/VideoBlock/VideoBlock.d.ts +1 -0
  104. package/build/esm/components/VideoBlock/VideoBlock.js +6 -10
  105. package/build/esm/components/YandexForm/YandexForm.js +4 -10
  106. package/build/esm/components/index.d.ts +2 -0
  107. package/build/esm/components/index.js +2 -0
  108. package/build/esm/constructor-items.d.ts +4 -0
  109. package/build/esm/constructor-items.js +5 -1
  110. package/build/esm/containers/PageConstructor/PageConstructor.css +1 -0
  111. package/build/esm/containers/PageConstructor/components/ConstructorBlocks/ConstructorBlocks.js +7 -5
  112. package/build/esm/containers/PageConstructor/components/ConstructorItem/ConstructorItem.d.ts +1 -2
  113. package/build/esm/containers/PageConstructor/components/ConstructorItem/ConstructorItem.js +2 -4
  114. package/build/esm/context/blockIdContext/blockIdContext.d.ts +3 -0
  115. package/build/esm/context/blockIdContext/blockIdContext.js +2 -0
  116. package/build/esm/context/blockIdContext/index.d.ts +1 -0
  117. package/build/esm/context/blockIdContext/index.js +1 -0
  118. package/build/esm/hooks/index.d.ts +1 -0
  119. package/build/esm/hooks/index.js +1 -0
  120. package/build/esm/hooks/useAnalyticsEvent.d.ts +7 -0
  121. package/build/esm/hooks/useAnalyticsEvent.js +12 -0
  122. package/build/esm/hooks/useHeightCalculator.d.ts +6 -0
  123. package/build/esm/hooks/useHeightCalculator.js +24 -0
  124. package/build/esm/models/common.d.ts +11 -0
  125. package/build/esm/models/common.js +12 -0
  126. package/build/esm/models/constructor-items/common.d.ts +1 -19
  127. package/build/esm/models/constructor-items/sub-blocks.d.ts +15 -0
  128. package/build/esm/models/constructor-items/sub-blocks.js +4 -0
  129. package/build/esm/navigation/components/NavigationItem/NavigationItem.js +4 -5
  130. package/build/esm/schema/index.js +1 -0
  131. package/build/esm/schema/validators/sub-blocks.d.ts +1 -0
  132. package/build/esm/schema/validators/sub-blocks.js +1 -0
  133. package/build/esm/sub-blocks/BannerCard/BannerCard.js +3 -2
  134. package/build/esm/sub-blocks/HubspotForm/HubspotForm.css +14 -9
  135. package/build/esm/sub-blocks/HubspotForm/HubspotFormContainer.d.ts +1 -1
  136. package/build/esm/sub-blocks/HubspotForm/HubspotFormContainer.js +26 -8
  137. package/build/esm/sub-blocks/HubspotForm/index.js +7 -11
  138. package/build/esm/sub-blocks/LayoutItem/LayoutItem.css +16 -0
  139. package/build/esm/sub-blocks/LayoutItem/LayoutItem.d.ts +4 -0
  140. package/build/esm/sub-blocks/LayoutItem/LayoutItem.js +20 -0
  141. package/build/esm/sub-blocks/LayoutItem/schema.d.ts +218 -0
  142. package/build/esm/sub-blocks/LayoutItem/schema.js +14 -0
  143. package/build/esm/sub-blocks/LayoutItem/utils.d.ts +28 -0
  144. package/build/esm/sub-blocks/LayoutItem/utils.js +6 -0
  145. package/build/esm/sub-blocks/Quote/Quote.js +4 -11
  146. package/build/esm/sub-blocks/index.d.ts +1 -0
  147. package/build/esm/sub-blocks/index.js +1 -0
  148. package/build/esm/text-transform/blocks.js +17 -0
  149. package/build/esm/utils/analytics.d.ts +2 -0
  150. package/build/esm/utils/analytics.js +13 -0
  151. package/build/esm/utils/blocks.d.ts +0 -7
  152. package/build/esm/utils/blocks.js +0 -3
  153. package/build/esm/utils/hubspot.d.ts +2 -1
  154. package/build/esm/utils/hubspot.js +5 -1
  155. package/build/esm/utils/index.d.ts +1 -0
  156. package/build/esm/utils/index.js +1 -0
  157. package/package.json +5 -2
  158. package/server/models/common.d.ts +11 -0
  159. package/server/models/common.js +13 -1
  160. package/server/models/constructor-items/common.d.ts +1 -19
  161. package/server/models/constructor-items/sub-blocks.d.ts +15 -0
  162. package/server/models/constructor-items/sub-blocks.js +4 -0
  163. package/server/text-transform/blocks.js +17 -0
  164. package/server/utils/analytics.d.ts +2 -0
  165. package/server/utils/analytics.js +17 -0
  166. package/server/utils/blocks.d.ts +0 -7
  167. package/server/utils/blocks.js +1 -5
  168. package/server/utils/hubspot.d.ts +2 -1
  169. package/server/utils/hubspot.js +5 -1
  170. package/server/utils/index.d.ts +1 -0
  171. package/server/utils/index.js +1 -0
  172. package/styles/root.scss +1 -0
  173. package/build/cjs/context/blockPositionContext/blockPositionContext.d.ts +0 -3
  174. package/build/cjs/context/blockPositionContext/index.d.ts +0 -1
  175. package/build/esm/context/blockPositionContext/blockPositionContext.d.ts +0 -3
  176. package/build/esm/context/blockPositionContext/blockPositionContext.js +0 -2
  177. package/build/esm/context/blockPositionContext/index.d.ts +0 -1
  178. package/build/esm/context/blockPositionContext/index.js +0 -1
@@ -3,8 +3,8 @@ import { block } from '../../../utils';
3
3
  import ToggleArrow from '../../../components/ToggleArrow/ToggleArrow';
4
4
  import './Arrow.css';
5
5
  const b = block('slider-block-arrow');
6
- const Arrow = ({ type, handleClick, className, size = 16 }) => (React.createElement("div", { className: b({ type }, className), onClick: () => handleClick && handleClick(type) },
7
- React.createElement("button", { className: b('button') },
6
+ const Arrow = ({ type, handleClick, className, size = 16 }) => (React.createElement("div", { className: b({ type }, className) },
7
+ React.createElement("button", { className: b('button'), onClick: () => handleClick && handleClick(type) },
8
8
  React.createElement("div", { className: b('icon-wrapper') },
9
9
  React.createElement(ToggleArrow, { size: size, type: 'horizontal', iconType: "navigation", className: b('icon') })))));
10
10
  export default Arrow;
@@ -179,11 +179,7 @@ unpredictable css rules order in build */
179
179
  }
180
180
  .pc-SliderBlock_type_media-card .slick-arrow {
181
181
  display: none;
182
- height: 100%;
183
182
  width: 64px;
184
- top: 0;
185
- }
186
- .pc-SliderBlock_type_media-card .slick-arrow button {
187
183
  top: 50%;
188
184
  transform: translate(0, -50%);
189
185
  }
@@ -2,20 +2,13 @@ import React, { useCallback, useContext } from 'react';
2
2
  import { Button, Icon } from '@gravity-ui/uikit';
3
3
  import { ArrowSidebar } from '../../icons';
4
4
  import { LocationContext } from '../../context/locationContext';
5
- import { BlockPositionContext } from '../../context/blockPositionContext';
6
- import { useAnalytics } from '../../hooks';
7
- import { PredefinedEventTypes } from '../../models';
8
- const COMPONENT_NAME = 'backlink';
5
+ import { useAnalytics, useAnalyticsEvent } from '../../hooks';
6
+ import { DefaultEventNames } from '../../models';
9
7
  export default function BackLink(props) {
10
8
  const { history } = useContext(LocationContext);
11
9
  const { url, title, theme = 'default', size = 'l', className, shouldHandleBackAction = false, onClick, } = props;
12
- const context = useContext(BlockPositionContext);
13
- const handleAnalytics = useAnalytics({
14
- name: 'back-link-click',
15
- type: PredefinedEventTypes.Default,
16
- context: context || COMPONENT_NAME,
17
- target: url,
18
- });
10
+ const defaultEvent = useAnalyticsEvent(DefaultEventNames.ShareButton, url);
11
+ const handleAnalytics = useAnalytics(defaultEvent);
19
12
  const backActionHandler = useCallback(async () => {
20
13
  handleAnalytics();
21
14
  if (!history) {
@@ -4,7 +4,6 @@ export interface ButtonProps extends Omit<ButtonParams, 'url'> {
4
4
  className?: string;
5
5
  url?: string;
6
6
  onClick?: () => void;
7
- context?: string;
8
7
  }
9
8
  declare const Button: (props: ButtonProps) => JSX.Element;
10
9
  export default Button;
@@ -1,29 +1,21 @@
1
1
  import { __rest } from "tslib";
2
- import React, { useCallback, useContext, useMemo } from 'react';
2
+ import React, { useCallback, useContext } from 'react';
3
3
  import { Platform, Button as CommonButton, Icon, StoreBadge } from '@gravity-ui/uikit';
4
4
  import { block, setUrlTld } from '../../utils';
5
- import { PredefinedEventTypes } from '../../models';
5
+ import { DefaultEventNames } from '../../models';
6
6
  import { toCommonSize, toCommonView } from './utils';
7
7
  import { LocaleContext } from '../../context/localeContext/localeContext';
8
- import { BlockPositionContext } from '../../context/blockPositionContext';
9
8
  import { useMetrika } from '../../hooks/useMetrika';
10
- import { useAnalytics } from '../../hooks';
9
+ import { useAnalytics, useAnalyticsEvent } from '../../hooks';
11
10
  import { Github } from '../../icons';
12
11
  import './Button.css';
13
- const COMPONENT_NAME = 'button';
14
12
  const b = block('button-block');
15
13
  const Button = (props) => {
16
14
  const handleMetrika = useMetrika();
17
15
  const { lang, tld } = useContext(LocaleContext);
18
16
  const { className, metrikaGoals, pixelEvents, analyticsEvents, size = 'l', theme = 'normal', url, img, onClick: onClickOrigin, text } = props, rest = __rest(props, ["className", "metrikaGoals", "pixelEvents", "analyticsEvents", "size", "theme", "url", "img", "onClick", "text"]);
19
- const context = useContext(BlockPositionContext);
20
17
  const defaultImgPosition = 'left';
21
- const defaultEvent = useMemo(() => ({
22
- name: 'button-click',
23
- type: PredefinedEventTypes.Default,
24
- context: context || COMPONENT_NAME,
25
- target: url,
26
- }), [context, url]);
18
+ const defaultEvent = useAnalyticsEvent(DefaultEventNames.Button, url);
27
19
  const handleAnalytics = useAnalytics(defaultEvent);
28
20
  const onClick = useCallback(() => {
29
21
  handleMetrika({ metrikaGoals, pixelEvents });
@@ -1,11 +1,10 @@
1
- import React, { Children, Fragment, useMemo, useContext, } from 'react';
1
+ import React, { Children, Fragment } from 'react';
2
2
  import { block } from '../../utils';
3
- import { BlockPositionContext } from '../../context/blockPositionContext';
4
3
  import BackgroundImage from '../BackgroundImage/BackgroundImage';
5
4
  import RouterLink from '../RouterLink/RouterLink';
6
5
  import { useMetrika } from '../../hooks/useMetrika';
7
- import { PredefinedEventTypes } from '../../models/common';
8
- import { useAnalytics } from '../../hooks';
6
+ import { DefaultEventNames } from '../../models/common';
7
+ import { useAnalytics, useAnalyticsEvent } from '../../hooks';
9
8
  import './CardBase.css';
10
9
  const b = block('card-base-block');
11
10
  const Header = () => null;
@@ -14,13 +13,7 @@ const Footer = () => null;
14
13
  export const Layout = (props) => {
15
14
  const { className, bodyClassName, metrikaGoals, pixelEvents, analyticsEvents, contentClassName, children, url, target, border = 'shadow', } = props;
16
15
  const handleMetrika = useMetrika();
17
- const context = useContext(BlockPositionContext);
18
- const defaultEvent = useMemo(() => ({
19
- name: 'card-base-click',
20
- type: PredefinedEventTypes.Default,
21
- context,
22
- target: url,
23
- }), [context, url]);
16
+ const defaultEvent = useAnalyticsEvent(DefaultEventNames.CardBase, url);
24
17
  const handleAnalytics = useAnalytics(defaultEvent);
25
18
  let header, content, footer, image, headerClass, footerClass;
26
19
  function handleChild(child) {
@@ -1,7 +1,10 @@
1
1
  /* use this for style redefinitions to awoid problems with
2
2
  unpredictable css rules order in build */
3
- .pc-foldable-block__content-container {
3
+ .pc-foldable-block {
4
4
  height: 0;
5
5
  overflow-y: hidden;
6
6
  transition: height 300ms, margin-bottom 300ms;
7
+ }
8
+ .pc-foldable-block__content-container {
9
+ overflow: auto;
7
10
  }
@@ -1,21 +1,18 @@
1
- import React, { useRef, useState, useCallback, useEffect } from 'react';
1
+ import React, { useRef, useEffect } from 'react';
2
2
  import { block } from '../../utils';
3
- import HeightCalculator from '../../components/HeightCalculator/HeightCalculator';
3
+ import useHeightCalculator from '../../hooks/useHeightCalculator';
4
4
  import './Foldable.css';
5
5
  const b = block('foldable-block');
6
6
  const Foldable = ({ isOpened, children, className }) => {
7
+ const blockRef = useRef(null);
7
8
  const contentRef = useRef(null);
8
- const [contentHeight, setContentHeight] = useState();
9
- const onHeightCalculation = useCallback((height) => {
10
- setContentHeight(height);
11
- }, []);
9
+ const contentHeight = useHeightCalculator(contentRef);
12
10
  useEffect(() => {
13
- if (contentRef && contentRef.current) {
14
- contentRef.current.style.height = isOpened ? `${contentHeight}px` : '0';
11
+ if (blockRef && blockRef.current) {
12
+ blockRef.current.style.height = isOpened && contentHeight ? `${contentHeight}px` : '0';
15
13
  }
16
14
  }, [isOpened, contentHeight]);
17
- return (React.createElement("div", { className: b(null, className) },
18
- React.createElement("div", { ref: contentRef, className: b('content-container', { open: isOpened }) }, children),
19
- React.createElement(HeightCalculator, { onCalculate: onHeightCalculation }, children)));
15
+ return (React.createElement("div", { ref: blockRef, className: b({ open: isOpened }, className) },
16
+ React.createElement("div", { ref: contentRef, className: b('content-container') }, children)));
20
17
  };
21
18
  export default Foldable;
@@ -1,27 +1,29 @@
1
- import React, { useState, useCallback } from 'react';
1
+ import React, { useState } from 'react';
2
2
  import { Icon, Modal } from '@gravity-ui/uikit';
3
3
  import { block } from '../../utils';
4
4
  import Image from '../Image/Image';
5
5
  import { PreviewClose, FullScreen } from '../../icons';
6
6
  import './FullScreenImage.css';
7
7
  const b = block('FullScreenImage');
8
+ const FULL_SCREEN_ICON_SIZE = 18;
9
+ const CLOSE_ICON_SIZE = 30;
8
10
  const FullScreenImage = (props) => {
9
11
  const { imageClassName, modalImageClass, imageStyle } = props;
10
12
  const [isOpened, setIsOpened] = useState(false);
11
13
  const [isMouseEnter, setIsMouseEnter] = useState(false);
12
- const openModal = useCallback(() => setIsOpened(true), []);
13
- const closeModal = useCallback(() => setIsOpened(false), []);
14
- const showFullScreenIcon = useCallback(() => setIsMouseEnter(true), []);
15
- const hideFullScreenIcon = useCallback(() => setIsMouseEnter(false), []);
14
+ const openModal = () => setIsOpened(true);
15
+ const closeModal = () => setIsOpened(false);
16
+ const showFullScreenIcon = () => setIsMouseEnter(true);
17
+ const hideFullScreenIcon = () => setIsMouseEnter(false);
16
18
  return (React.createElement("div", { className: b() },
17
19
  React.createElement("div", { className: b('image-wrapper'), onMouseEnter: showFullScreenIcon, onMouseLeave: hideFullScreenIcon },
18
20
  React.createElement(Image, Object.assign({}, props, { className: b('image', imageClassName), onClick: openModal, style: imageStyle })),
19
21
  React.createElement("div", { className: b('icon-wrapper', { visible: isMouseEnter }), onClick: openModal },
20
- React.createElement(Icon, { data: FullScreen, width: 18, height: 18, className: b('icon') }))),
22
+ React.createElement(Icon, { data: FullScreen, width: FULL_SCREEN_ICON_SIZE, height: FULL_SCREEN_ICON_SIZE, className: b('icon') }))),
21
23
  isOpened && (React.createElement(Modal, { open: isOpened, onClose: closeModal, className: b('modal') },
22
24
  React.createElement("div", { className: b('modal-content') },
23
25
  React.createElement("div", { className: b('icon-wrapper', { visible: true }), onClick: closeModal },
24
- React.createElement(Icon, { data: PreviewClose, width: 30, height: 30, className: b('icon', { hover: true }) })),
26
+ React.createElement(Icon, { data: PreviewClose, width: CLOSE_ICON_SIZE, height: CLOSE_ICON_SIZE, className: b('icon', { hover: true }) })),
25
27
  React.createElement(Image, Object.assign({}, props, { className: b('modal-image', modalImageClass) })))))));
26
28
  };
27
29
  export default FullScreenImage;
@@ -0,0 +1,70 @@
1
+ /* use this for style redefinitions to awoid problems with
2
+ unpredictable css rules order in build */
3
+ .pc-full-screen-media__modal-media_type_youtube, .pc-full-screen-media__modal-media_type_video video, .pc-full-screen-media__modal-media_type_image {
4
+ display: block;
5
+ position: relative;
6
+ width: 100%;
7
+ max-width: 1232px;
8
+ max-height: 70vh;
9
+ }
10
+
11
+ .pc-full-screen-media__media {
12
+ cursor: pointer;
13
+ }
14
+ .pc-full-screen-media__media-wrapper {
15
+ cursor: pointer;
16
+ position: relative;
17
+ }
18
+ .pc-full-screen-media__modal-content {
19
+ position: relative;
20
+ }
21
+ .pc-full-screen-media__inline-media {
22
+ transform: translateZ(0);
23
+ }
24
+ .pc-full-screen-media__modal-media {
25
+ border-radius: var(--pc-border-radius);
26
+ }
27
+ .pc-full-screen-media__modal-media_type_youtube {
28
+ width: min(65vw, 1232px);
29
+ height: calc(min(65vw, 1232px) * 9 / 16);
30
+ }
31
+ .pc-full-screen-media__modal .yc-modal__content, .pc-full-screen-media__modal-image {
32
+ border-radius: var(--pc-border-radius);
33
+ }
34
+ .pc-full-screen-media__icon-wrapper {
35
+ display: flex;
36
+ align-items: center;
37
+ justify-content: center;
38
+ position: absolute;
39
+ right: 16px;
40
+ top: 16px;
41
+ width: 36px;
42
+ height: 36px;
43
+ border-radius: 8px;
44
+ background-color: var(--yc-color-base-simple-hover-solid);
45
+ cursor: pointer;
46
+ z-index: 10;
47
+ }
48
+ .pc-full-screen-media__modal-content .pc-full-screen-media__icon-wrapper, .pc-full-screen-media__media-wrapper .pc-full-screen-media__icon-wrapper {
49
+ opacity: 0;
50
+ transition: opacity 0.3s;
51
+ pointer-events: none;
52
+ }
53
+ .pc-full-screen-media__modal-content:hover .pc-full-screen-media__icon-wrapper, .pc-full-screen-media__media-wrapper:hover .pc-full-screen-media__icon-wrapper {
54
+ opacity: 1;
55
+ pointer-events: inherit;
56
+ }
57
+ .pc-full-screen-media__icon {
58
+ color: var(--yc-color-text-hint);
59
+ }
60
+ .pc-full-screen-media__icon_hover:hover {
61
+ color: var(--yc-color-text-secondary);
62
+ }
63
+ @media (max-width: 577px) {
64
+ .pc-full-screen-media__icon-wrapper {
65
+ display: none;
66
+ }
67
+ .pc-full-screen-media__modal {
68
+ display: none !important; /* stylelint-disable-line declaration-no-important */
69
+ }
70
+ }
@@ -0,0 +1,10 @@
1
+ /// <reference types="react" />
2
+ import { MediaAllProps } from '../Media/Media';
3
+ import './FullScreenMedia.css';
4
+ export type ChildMediaRenderProps = Pick<MediaAllProps, 'fullScreen' | 'imageClassName' | 'videoClassName' | 'youtubeClassName' | 'className'>;
5
+ export interface FullScreenMediaProps {
6
+ showFullScreenIcon?: boolean;
7
+ children: (props?: ChildMediaRenderProps) => JSX.Element;
8
+ }
9
+ declare const FullScreenMedia: ({ children, showFullScreenIcon }: FullScreenMediaProps) => JSX.Element;
10
+ export default FullScreenMedia;
@@ -0,0 +1,38 @@
1
+ import React, { useContext, useState } from 'react';
2
+ import { Icon, Modal } from '@gravity-ui/uikit';
3
+ import { block } from '../../utils';
4
+ import { PreviewClose, FullScreen } from '../../icons';
5
+ import { MobileContext } from '../../context/mobileContext';
6
+ import './FullScreenMedia.css';
7
+ const b = block('full-screen-media');
8
+ const FULL_SCREEN_ICON_SIZE = 18;
9
+ const CLOSE_ICON_SIZE = 30;
10
+ const getMediaClass = (type) => b('modal-media', { type });
11
+ const FullScreenMedia = ({ children, showFullScreenIcon = true }) => {
12
+ const [isOpened, setIsOpened] = useState(false);
13
+ const isMobile = useContext(MobileContext);
14
+ const openModal = (e) => {
15
+ e.stopPropagation();
16
+ setIsOpened(true);
17
+ };
18
+ const closeModal = () => setIsOpened(false);
19
+ if (isMobile) {
20
+ return children();
21
+ }
22
+ return (React.createElement("div", { className: b() },
23
+ React.createElement("div", { className: b('media-wrapper'), onClickCapture: openModal },
24
+ children({ className: b('inline-media') }),
25
+ showFullScreenIcon && (React.createElement("div", { className: b('icon-wrapper'), onClickCapture: openModal },
26
+ React.createElement(Icon, { data: FullScreen, width: FULL_SCREEN_ICON_SIZE, height: FULL_SCREEN_ICON_SIZE, className: b('icon') })))),
27
+ isOpened && (React.createElement(Modal, { open: isOpened, onClose: closeModal, className: b('modal') },
28
+ React.createElement("div", { className: b('modal-content') },
29
+ React.createElement("div", { className: b('icon-wrapper', { visible: true }), onClick: closeModal },
30
+ React.createElement(Icon, { data: PreviewClose, width: CLOSE_ICON_SIZE, height: CLOSE_ICON_SIZE, className: b('icon', { hover: true }) })),
31
+ children({
32
+ imageClassName: getMediaClass('image'),
33
+ videoClassName: getMediaClass('video'),
34
+ youtubeClassName: getMediaClass('youtube'),
35
+ fullScreen: true,
36
+ }))))));
37
+ };
38
+ export default FullScreenMedia;
@@ -3,5 +3,9 @@ import './HeightCalculator.css';
3
3
  export interface HeightCalculatorProps {
4
4
  onCalculate: (height: number) => void;
5
5
  }
6
+ /**
7
+ * @deprecated Will be removed, use the useHeightCalculator hook instead.
8
+ * @returns The HeightCalculator component.
9
+ */
6
10
  declare const HeightCalculator: ({ onCalculate, children }: WithChildren<HeightCalculatorProps>) => JSX.Element | null;
7
11
  export default HeightCalculator;
@@ -3,6 +3,10 @@ import _ from 'lodash';
3
3
  import { block } from '../../utils';
4
4
  import './HeightCalculator.css';
5
5
  const b = block('height-calculator');
6
+ /**
7
+ * @deprecated Will be removed, use the useHeightCalculator hook instead.
8
+ * @returns The HeightCalculator component.
9
+ */
6
10
  const HeightCalculator = ({ onCalculate, children }) => {
7
11
  const [isCalculating, setIsCalculating] = useState(true);
8
12
  const container = useRef(null);
@@ -1,15 +1,14 @@
1
- import React, { Fragment, useContext, useMemo } from 'react';
1
+ import React, { Fragment, useContext } from 'react';
2
2
  import { Icon } from '@gravity-ui/uikit';
3
3
  import { block, getLinkProps, setUrlTld } from '../../utils';
4
- import { PredefinedEventTypes, } from '../../models';
4
+ import { DefaultEventNames } from '../../models';
5
5
  import { Chevron } from '../../icons';
6
6
  import FileLink from '../FileLink/FileLink';
7
7
  import BackLink from '../BackLink/BackLink';
8
8
  import { LocaleContext } from '../../context/localeContext/localeContext';
9
9
  import { LocationContext } from '../../context/locationContext/locationContext';
10
- import { BlockPositionContext } from '../../context/blockPositionContext';
11
10
  import { useMetrika } from '../../hooks/useMetrika';
12
- import { useAnalytics } from '../../hooks';
11
+ import { useAnalytics, useAnalyticsEvent } from '../../hooks';
13
12
  import './Link.css';
14
13
  const b = block('link-block');
15
14
  const WORD_JOINER_SYM = '\u200b';
@@ -28,13 +27,7 @@ function getArrowSize(size) {
28
27
  const LinkBlock = (props) => {
29
28
  const { text, url, arrow, metrikaGoals, pixelEvents, analyticsEvents, theme = 'file-link', colorTheme = 'light', textSize = 'm', className, target, children, } = props;
30
29
  const handleMetrika = useMetrika();
31
- const context = useContext(BlockPositionContext);
32
- const defaultEvent = useMemo(() => ({
33
- name: 'link-click',
34
- type: PredefinedEventTypes.Default,
35
- context,
36
- target: url,
37
- }), [context, url]);
30
+ const defaultEvent = useAnalyticsEvent(DefaultEventNames.Link, url);
38
31
  const handleAnalytics = useAnalytics(defaultEvent);
39
32
  const { hostname } = useContext(LocationContext);
40
33
  const { tld } = useContext(LocaleContext);
@@ -7,7 +7,7 @@ import YoutubeBlock from '../VideoBlock/VideoBlock';
7
7
  import './Media.css';
8
8
  const b = block('Media');
9
9
  export const Media = (props) => {
10
- const { image, video, youtube, dataLens, color, height, previewImg, parallax = false, metrika, analyticsEvents, } = props;
10
+ const { image, video, youtube, dataLens, color, height, previewImg, parallax = false, metrika, fullScreen, analyticsEvents, } = props;
11
11
  const { className, imageClassName, videoClassName, youtubeClassName, playVideo = true, isBackground, playButton, customBarControlsClassName, } = props;
12
12
  const [hasVideoFallback, setHasVideoFallback] = useState(false);
13
13
  const content = useMemo(() => {
@@ -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, analyticsEvents: analyticsEvents, 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, height: height }));
22
+ result = (React.createElement(YoutubeBlock, { className: b('youtube', youtubeClassName), record: youtube, attributes: { color: 'white', rel: '0' }, previewImg: previewImg, height: height, fullScreen: fullScreen }));
23
23
  }
24
24
  if (dataLens) {
25
25
  result = React.createElement(DataLens, { dataLens: dataLens });
@@ -43,6 +43,7 @@ export const Media = (props) => {
43
43
  playButton,
44
44
  customBarControlsClassName,
45
45
  youtubeClassName,
46
+ fullScreen,
46
47
  ]);
47
48
  return (React.createElement("div", { className: b(null, className), style: { backgroundColor: color } }, content));
48
49
  };
@@ -0,0 +1,13 @@
1
+ /* use this for style redefinitions to awoid problems with
2
+ unpredictable css rules order in build */
3
+ .pc-meta-info {
4
+ font-size: var(--yc-text-body-2-font-size);
5
+ line-height: var(--yc-text-body-2-line-height);
6
+ display: flex;
7
+ align-items: center;
8
+ font-weight: 500;
9
+ color: var(--pc-media-card-meta-info-color);
10
+ }
11
+ .pc-meta-info__item:not(:first-child) {
12
+ margin-left: 16px;
13
+ }
@@ -0,0 +1,7 @@
1
+ import { ClassNameProps } from 'src/models';
2
+ import './MetaInfo.css';
3
+ export interface MetaInfpoProps extends ClassNameProps {
4
+ items: string[];
5
+ }
6
+ declare const MetaInfo: ({ items, className }: MetaInfpoProps) => JSX.Element;
7
+ export default MetaInfo;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import { block } from '../../utils';
3
+ import './MetaInfo.css';
4
+ const b = block('meta-info');
5
+ const MetaInfo = ({ items, className }) => (React.createElement("h4", { className: b(null, className) }, items.map((metaInfoItem) => (React.createElement("div", { key: metaInfoItem, className: b('item') }, metaInfoItem)))));
6
+ export default MetaInfo;
@@ -0,0 +1,8 @@
1
+ declare const metaInfo: {
2
+ type: string;
3
+ items: {
4
+ type: string;
5
+ contentType: string;
6
+ };
7
+ };
8
+ export default metaInfo;
@@ -0,0 +1,8 @@
1
+ const metaInfo = {
2
+ type: 'array',
3
+ items: {
4
+ type: 'string',
5
+ contentType: 'text',
6
+ },
7
+ };
8
+ export default metaInfo;
@@ -3,14 +3,13 @@ import ReactPlayer from 'react-player';
3
3
  import React, { useCallback, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState, } from 'react';
4
4
  import { Icon } from '@gravity-ui/uikit';
5
5
  import { block } from '../../utils';
6
- import { PlayButtonThemes, PlayButtonType, MediaVideoControlsType, PredefinedEventTypes, } from '../../models';
6
+ import { PlayButtonThemes, PlayButtonType, MediaVideoControlsType, PredefinedEventTypes, DefaultEventNames, } from '../../models';
7
7
  import CustomBarControls from './CustomBarControls';
8
8
  import { VideoContext } from '../../context/videoContext';
9
9
  import { MetrikaContext } from '../../context/metrikaContext';
10
10
  import { MobileContext } from '../../context/mobileContext';
11
- import { BlockPositionContext } from '../../context/blockPositionContext';
11
+ import { useAnalytics, useAnalyticsEvent } from '../../hooks';
12
12
  import { PlayVideo } from '../../icons';
13
- import { useAnalytics } from '../../hooks';
14
13
  import './ReactPlayer.css';
15
14
  const b = block('ReactPlayer');
16
15
  const FPS = 60;
@@ -39,12 +38,7 @@ export const ReactPlayerBlock = React.forwardRef((props, originRef) => {
39
38
  }
40
39
  return [];
41
40
  }, [analyticsEvents]);
42
- const context = useContext(BlockPositionContext);
43
- const defaultEvent = useMemo(() => ({
44
- name: 'react-player-controls-click',
45
- type: PredefinedEventTypes.Default,
46
- context,
47
- }), [context]);
41
+ const defaultEvent = useAnalyticsEvent(DefaultEventNames.ReactPlayerControls);
48
42
  const handleAnalytics = useAnalytics(defaultEvent);
49
43
  useImperativeHandle(originRef, () => ({
50
44
  pause: () => setIsPlaying(false),
@@ -14,6 +14,7 @@ export interface VideoBlockProps {
14
14
  previewImg?: string;
15
15
  playButton?: React.ReactNode;
16
16
  height?: number;
17
+ fullScreen?: boolean;
17
18
  }
18
19
  declare const VideoBlock: (props: VideoBlockProps) => JSX.Element | null;
19
20
  export default VideoBlock;
@@ -1,5 +1,6 @@
1
1
  import React, { useRef, useState, useCallback, useEffect } from 'react';
2
2
  import _ from 'lodash';
3
+ import { v4 as uuidv4 } from 'uuid';
3
4
  import { Icon } from '@gravity-ui/uikit';
4
5
  import { block, getPageSearchParams } from '../../utils';
5
6
  import Image from '../Image/Image';
@@ -15,7 +16,6 @@ export const AUTOPLAY_ATTRIBUTES = {
15
16
  mute: 1,
16
17
  };
17
18
  const b = block('VideoBlock');
18
- const iframeId = 'video-block';
19
19
  function getVideoSrc(stream, record) {
20
20
  if (!stream && !record) {
21
21
  return null;
@@ -34,14 +34,14 @@ 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, height } = props;
37
+ const { stream, record, attributes, className, id, previewImg, playButton, height, fullScreen } = 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
43
  const [currentHeight, setCurrentHeight] = useState(height || undefined);
44
- const fullId = `${iframeId}-${id || src}`;
44
+ const fullId = id || uuidv4();
45
45
  const onPreviewClick = useCallback(() => {
46
46
  if (iframeRef.current) {
47
47
  iframeRef.current.src = `${src}?${getPageSearchParams(Object.assign(Object.assign({}, AUTOPLAY_ATTRIBUTES), (attributes || {})))}`;
@@ -62,12 +62,8 @@ const VideoBlock = (props) => {
62
62
  if (norender) {
63
63
  return;
64
64
  }
65
- const prevPageVideo = document.getElementById(fullId);
66
65
  const fullSrc = `${src}?${getPageSearchParams(attributes || {})}`;
67
- if (prevPageVideo) {
68
- prevPageVideo.src = fullSrc;
69
- }
70
- else if (ref.current) {
66
+ if (ref.current && !iframeRef.current) {
71
67
  const iframe = document.createElement('iframe');
72
68
  iframe.id = fullId;
73
69
  iframe.src = fullSrc;
@@ -79,14 +75,14 @@ const VideoBlock = (props) => {
79
75
  ref.current.appendChild(iframe);
80
76
  iframeRef.current = iframe;
81
77
  }
82
- }, [stream, record, norender, src, fullId, attributes, iframeRef]);
78
+ }, [stream, record, norender, src, fullId, attributes, iframeRef, fullScreen]);
83
79
  useEffect(() => {
84
80
  setHidePreview(false);
85
81
  }, [src, setHidePreview]);
86
82
  if (norender) {
87
83
  return null;
88
84
  }
89
- return (React.createElement("div", { className: b(null, className), ref: ref, style: { height: currentHeight } }, previewImg && !hidePreview && (React.createElement("div", { className: b('preview'), onClick: onPreviewClick },
85
+ return (React.createElement("div", { className: b(null, className), ref: ref, style: { height: currentHeight } }, previewImg && !hidePreview && !fullScreen && (React.createElement("div", { className: b('preview'), onClick: onPreviewClick },
90
86
  React.createElement(Image, { src: previewImg, className: b('image'), containerClassName: b('image-wrapper') }),
91
87
  playButton || (React.createElement("button", { className: b('button') },
92
88
  React.createElement(Icon, { className: b('icon'), data: PlayVideo, size: 24 })))))));
@@ -1,12 +1,11 @@
1
- import React, { useCallback, useContext, useEffect, useMemo, useRef } from 'react';
1
+ import React, { useCallback, useContext, useEffect, useRef } from 'react';
2
2
  import { HEADER_HEIGHT } from '../constants';
3
3
  import { LocaleContext } from '../../context/localeContext';
4
4
  import { MobileContext } from '../../context/mobileContext';
5
- import { BlockPositionContext } from '../../context/blockPositionContext';
6
5
  import { block } from '../../utils';
7
- import { PredefinedEventTypes } from '../../models/common';
6
+ import { DefaultEventNames } from '../../models/common';
8
7
  import { useMetrika } from '../../hooks/useMetrika';
9
- import { useAnalytics } from '../../hooks';
8
+ import { useAnalytics, useAnalyticsEvent } from '../../hooks';
10
9
  export const YANDEX_FORM_ORIGIN = 'https://forms.yandex.ru';
11
10
  const CONTAINER_ID = 'pc-yandex-form-container';
12
11
  const b = block('yandex-form');
@@ -16,12 +15,7 @@ const YandexForm = (props) => {
16
15
  const iframeRef = useRef();
17
16
  const yaFormOrigin = customFormOrigin || YANDEX_FORM_ORIGIN;
18
17
  const handleMetrika = useMetrika();
19
- const context = useContext(BlockPositionContext);
20
- const defaultEvent = useMemo(() => ({
21
- name: 'yndex-form-submit',
22
- type: PredefinedEventTypes.Default,
23
- context: context,
24
- }), [context]);
18
+ const defaultEvent = useAnalyticsEvent(DefaultEventNames.YandexFormSubmit);
25
19
  const handleAnalytics = useAnalytics(defaultEvent);
26
20
  const isMobile = useContext(MobileContext);
27
21
  const locale = useContext(LocaleContext);
@@ -33,4 +33,6 @@ export { default as OverflowScroller } from './OverflowScroller/OverflowScroller
33
33
  export { default as Author } from './Author/Author';
34
34
  export { default as RouterLink } from './RouterLink/RouterLink';
35
35
  export { default as HTML } from './HTML/HTML';
36
+ export { default as MetaInfo } from './MetaInfo/MetaInfo';
37
+ export { default as FullScreenMedia } from './FullscreenMedia/FullScreenMedia';
36
38
  export type { RouterLinkProps } from './RouterLink/RouterLink';
@@ -33,3 +33,5 @@ export { default as OverflowScroller } from './OverflowScroller/OverflowScroller
33
33
  export { default as Author } from './Author/Author';
34
34
  export { default as RouterLink } from './RouterLink/RouterLink';
35
35
  export { default as HTML } from './HTML/HTML';
36
+ export { default as MetaInfo } from './MetaInfo/MetaInfo';
37
+ export { default as FullScreenMedia } from './FullscreenMedia/FullScreenMedia';
@@ -34,6 +34,10 @@ export declare const subBlockMap: {
34
34
  "media-card": ({ border, ...mediaProps }: import("./models").MediaCardProps) => JSX.Element;
35
35
  "banner-card": (props: import("./models").BannerCardProps) => JSX.Element;
36
36
  "news-card": (props: import("./models").NewsCardProps) => JSX.Element;
37
+ "layout-item": ({ content: { links, ...content }, metaInfo, media, border, fullScreen, className, }: import("./models").LayoutItemProps) => JSX.Element;
38
+ /**
39
+ * @deprecated Use LayoutItem
40
+ */
37
41
  "card-with-image": ({ title, description, image, disableCompress, links, border, fullScreen, className, additionalInfo, buttons, }: import("./models").CardWithImageProps) => JSX.Element;
38
42
  "background-card": (props: import("./models").BackgroundCardProps) => JSX.Element;
39
43
  "basic-card": (props: import("./models").BasicCardProps) => JSX.Element;