@gravity-ui/page-constructor 4.42.0 → 4.42.2

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 (88) hide show
  1. package/build/cjs/blocks/CardLayout/schema.d.ts +24 -0
  2. package/build/cjs/blocks/Companies/schema.d.ts +4 -0
  3. package/build/cjs/blocks/Companies/schema.js +3 -0
  4. package/build/cjs/blocks/ContentLayout/schema.d.ts +12 -0
  5. package/build/cjs/blocks/ExtendedFeatures/schema.d.ts +12 -0
  6. package/build/cjs/blocks/FilterBlock/schema.d.ts +24 -0
  7. package/build/cjs/blocks/Form/schema.d.ts +12 -0
  8. package/build/cjs/blocks/Header/schema.d.ts +12 -0
  9. package/build/cjs/blocks/HeaderSlider/schema.d.ts +12 -0
  10. package/build/cjs/blocks/Icons/schema.d.ts +42 -0
  11. package/build/cjs/blocks/Icons/schema.js +4 -1
  12. package/build/cjs/blocks/Map/schema.d.ts +12 -0
  13. package/build/cjs/blocks/Media/schema.d.ts +24 -0
  14. package/build/cjs/blocks/PromoFeaturesBlock/schema.d.ts +12 -0
  15. package/build/cjs/blocks/Questions/schema.d.ts +12 -0
  16. package/build/cjs/blocks/Slider/schema.d.ts +12 -0
  17. package/build/cjs/blocks/Table/schema.d.ts +12 -0
  18. package/build/cjs/blocks/Tabs/schema.d.ts +12 -0
  19. package/build/cjs/components/Author/Author.css +4 -2
  20. package/build/cjs/components/Author/Author.js +2 -2
  21. package/build/cjs/editor/components/CodeEditor/CodeEditor.css +2 -5
  22. package/build/cjs/editor/components/CodeEditor/CodeEditor.d.ts +2 -2
  23. package/build/cjs/editor/components/CodeEditor/CodeEditor.js +12 -9
  24. package/build/cjs/editor/containers/Editor/Editor.d.ts +1 -1
  25. package/build/cjs/editor/containers/Editor/Editor.js +19 -8
  26. package/build/cjs/editor/containers/Form/Form.js +3 -1
  27. package/build/cjs/editor/containers/Form/hooks.d.ts +8 -0
  28. package/build/cjs/editor/containers/Form/hooks.js +39 -0
  29. package/build/cjs/editor/context.d.ts +2 -0
  30. package/build/cjs/editor/types/index.d.ts +2 -0
  31. package/build/cjs/models/constructor-items/common.d.ts +1 -0
  32. package/build/cjs/models/constructor-items/sub-blocks.d.ts +12 -1
  33. package/build/cjs/schema/constants.d.ts +4 -0
  34. package/build/cjs/schema/validators/common.d.ts +13 -1
  35. package/build/cjs/schema/validators/common.js +8 -1
  36. package/build/cjs/sub-blocks/Divider/schema.d.ts +1 -1
  37. package/build/cjs/sub-blocks/Quote/Quote.css +11 -18
  38. package/build/cjs/sub-blocks/Quote/Quote.js +7 -6
  39. package/build/cjs/sub-blocks/Quote/schema.d.ts +4 -0
  40. package/build/cjs/sub-blocks/Quote/schema.js +4 -1
  41. package/build/cjs/text-transform/config.js +10 -4
  42. package/build/esm/blocks/CardLayout/schema.d.ts +24 -0
  43. package/build/esm/blocks/Companies/schema.d.ts +4 -0
  44. package/build/esm/blocks/Companies/schema.js +3 -0
  45. package/build/esm/blocks/ContentLayout/schema.d.ts +12 -0
  46. package/build/esm/blocks/ExtendedFeatures/schema.d.ts +12 -0
  47. package/build/esm/blocks/FilterBlock/schema.d.ts +24 -0
  48. package/build/esm/blocks/Form/schema.d.ts +12 -0
  49. package/build/esm/blocks/Header/schema.d.ts +12 -0
  50. package/build/esm/blocks/HeaderSlider/schema.d.ts +12 -0
  51. package/build/esm/blocks/Icons/schema.d.ts +42 -0
  52. package/build/esm/blocks/Icons/schema.js +5 -2
  53. package/build/esm/blocks/Map/schema.d.ts +12 -0
  54. package/build/esm/blocks/Media/schema.d.ts +24 -0
  55. package/build/esm/blocks/PromoFeaturesBlock/schema.d.ts +12 -0
  56. package/build/esm/blocks/Questions/schema.d.ts +12 -0
  57. package/build/esm/blocks/Slider/schema.d.ts +12 -0
  58. package/build/esm/blocks/Table/schema.d.ts +12 -0
  59. package/build/esm/blocks/Tabs/schema.d.ts +12 -0
  60. package/build/esm/components/Author/Author.css +4 -2
  61. package/build/esm/components/Author/Author.js +2 -2
  62. package/build/esm/editor/components/CodeEditor/CodeEditor.css +2 -5
  63. package/build/esm/editor/components/CodeEditor/CodeEditor.d.ts +2 -2
  64. package/build/esm/editor/components/CodeEditor/CodeEditor.js +13 -10
  65. package/build/esm/editor/containers/Editor/Editor.d.ts +1 -1
  66. package/build/esm/editor/containers/Editor/Editor.js +19 -8
  67. package/build/esm/editor/containers/Form/Form.js +3 -1
  68. package/build/esm/editor/containers/Form/hooks.d.ts +8 -0
  69. package/build/esm/editor/containers/Form/hooks.js +34 -0
  70. package/build/esm/editor/context.d.ts +2 -0
  71. package/build/esm/editor/types/index.d.ts +2 -0
  72. package/build/esm/models/constructor-items/common.d.ts +1 -0
  73. package/build/esm/models/constructor-items/sub-blocks.d.ts +12 -1
  74. package/build/esm/schema/constants.d.ts +4 -0
  75. package/build/esm/schema/validators/common.d.ts +13 -1
  76. package/build/esm/schema/validators/common.js +8 -1
  77. package/build/esm/sub-blocks/Divider/schema.d.ts +1 -1
  78. package/build/esm/sub-blocks/Quote/Quote.css +11 -18
  79. package/build/esm/sub-blocks/Quote/Quote.js +8 -7
  80. package/build/esm/sub-blocks/Quote/schema.d.ts +4 -0
  81. package/build/esm/sub-blocks/Quote/schema.js +4 -1
  82. package/build/esm/text-transform/config.js +10 -4
  83. package/package.json +1 -1
  84. package/server/models/constructor-items/common.d.ts +1 -0
  85. package/server/models/constructor-items/sub-blocks.d.ts +12 -1
  86. package/server/text-transform/config.js +10 -4
  87. package/styles/variables.scss +2 -0
  88. package/widget/index.js +1 -1
@@ -637,6 +637,18 @@ export declare const MediaBlockBaseProps: {
637
637
  context: {
638
638
  type: string;
639
639
  };
640
+ indent: {
641
+ type: string;
642
+ additionalProperties: boolean;
643
+ properties: {
644
+ top: {
645
+ enum: string[];
646
+ };
647
+ bottom: {
648
+ enum: string[];
649
+ };
650
+ };
651
+ };
640
652
  type: {};
641
653
  when: {
642
654
  type: string;
@@ -1295,6 +1307,18 @@ export declare const MediaBlock: {
1295
1307
  context: {
1296
1308
  type: string;
1297
1309
  };
1310
+ indent: {
1311
+ type: string;
1312
+ additionalProperties: boolean;
1313
+ properties: {
1314
+ top: {
1315
+ enum: string[];
1316
+ };
1317
+ bottom: {
1318
+ enum: string[];
1319
+ };
1320
+ };
1321
+ };
1298
1322
  type: {};
1299
1323
  when: {
1300
1324
  type: string;
@@ -374,6 +374,18 @@ export declare const PromoFeaturesBlock: {
374
374
  context: {
375
375
  type: string;
376
376
  };
377
+ indent: {
378
+ type: string;
379
+ additionalProperties: boolean;
380
+ properties: {
381
+ top: {
382
+ enum: string[];
383
+ };
384
+ bottom: {
385
+ enum: string[];
386
+ };
387
+ };
388
+ };
377
389
  type: {};
378
390
  when: {
379
391
  type: string;
@@ -115,6 +115,18 @@ export declare const QuestionsBlock: {
115
115
  context: {
116
116
  type: string;
117
117
  };
118
+ indent: {
119
+ type: string;
120
+ additionalProperties: boolean;
121
+ properties: {
122
+ top: {
123
+ enum: string[];
124
+ };
125
+ bottom: {
126
+ enum: string[];
127
+ };
128
+ };
129
+ };
118
130
  type: {};
119
131
  when: {
120
132
  type: string;
@@ -215,6 +215,18 @@ export declare const SliderBlock: {
215
215
  context: {
216
216
  type: string;
217
217
  };
218
+ indent: {
219
+ type: string;
220
+ additionalProperties: boolean;
221
+ properties: {
222
+ top: {
223
+ enum: string[];
224
+ };
225
+ bottom: {
226
+ enum: string[];
227
+ };
228
+ };
229
+ };
218
230
  type: {};
219
231
  when: {
220
232
  type: string;
@@ -81,6 +81,18 @@ export declare const TableBlock: {
81
81
  context: {
82
82
  type: string;
83
83
  };
84
+ indent: {
85
+ type: string;
86
+ additionalProperties: boolean;
87
+ properties: {
88
+ top: {
89
+ enum: string[];
90
+ };
91
+ bottom: {
92
+ enum: string[];
93
+ };
94
+ };
95
+ };
84
96
  type: {};
85
97
  when: {
86
98
  type: string;
@@ -607,6 +607,18 @@ export declare const TabsBlock: {
607
607
  context: {
608
608
  type: string;
609
609
  };
610
+ indent: {
611
+ type: string;
612
+ additionalProperties: boolean;
613
+ properties: {
614
+ top: {
615
+ enum: string[];
616
+ };
617
+ bottom: {
618
+ enum: string[];
619
+ };
620
+ };
621
+ };
610
622
  type: {};
611
623
  when: {
612
624
  type: string;
@@ -5,7 +5,6 @@ unpredictable css rules order in build */
5
5
  line-height: var(--g-text-body-3-line-height);
6
6
  display: flex;
7
7
  flex-direction: column;
8
- color: var(--g-color-text-secondary);
9
8
  }
10
9
  .pc-author__avatar {
11
10
  width: 80px;
@@ -25,11 +24,11 @@ unpredictable css rules order in build */
25
24
  .pc-author__name {
26
25
  font-size: var(--g-text-body-3-font-size);
27
26
  line-height: var(--g-text-body-3-line-height);
28
- color: var(--g-color-text-primary);
29
27
  }
30
28
  .pc-author__description {
31
29
  font-size: var(--g-text-body-2-font-size);
32
30
  line-height: var(--g-text-body-2-line-height);
31
+ color: var(--g-color-text-secondary);
33
32
  padding-top: 4px;
34
33
  }
35
34
  .pc-author__label:not(:first-child) {
@@ -53,4 +52,7 @@ unpredictable css rules order in build */
53
52
  }
54
53
  .pc-author_type_line .pc-author__label:not(:first-child) {
55
54
  margin-left: 16px;
55
+ }
56
+ .pc-author_theme_dark .pc-author__description {
57
+ color: var(--g-color-text-light-secondary);
56
58
  }
@@ -6,7 +6,7 @@ import { Image } from '../index';
6
6
  import './Author.css';
7
7
  const b = block('author');
8
8
  const Author = (props) => {
9
- const { author, className, authorContainerClassName, type = AuthorType.Column, qa } = props;
9
+ const { author, className, authorContainerClassName, type = AuthorType.Column, qa, theme, } = props;
10
10
  const { firstName, secondName, description, avatar } = author;
11
11
  const name = secondName ? `${firstName} ${secondName}` : firstName;
12
12
  const isAvatarJSX = React.isValidElement(avatar);
@@ -14,7 +14,7 @@ const Author = (props) => {
14
14
  if (!isAvatarJSX && avatar) {
15
15
  avatarProps = getMediaImage(avatar);
16
16
  }
17
- return (React.createElement("div", { className: b({ type }, className), "data-qa": qa },
17
+ return (React.createElement("div", { className: b({ type, theme }, className), "data-qa": qa },
18
18
  avatar && (React.createElement("div", { className: b('avatar', authorContainerClassName) }, isAvatarJSX ? avatar : React.createElement(Image, Object.assign({}, avatarProps)))),
19
19
  React.createElement("div", { className: b('label') },
20
20
  React.createElement("div", { className: b('name') }, name),
@@ -4,17 +4,14 @@
4
4
  overflow: hidden;
5
5
  }
6
6
  .pc-code-editor_fullscreen {
7
- position: fixed;
7
+ position: absolute;
8
8
  top: 0;
9
9
  left: 0;
10
10
  width: 100%;
11
- height: 100vh;
11
+ height: 100%;
12
12
  z-index: 1000;
13
13
  background: var(--g-color-base-background);
14
14
  }
15
- .pc-code-editor_fullscreen .pc-code-editor__header {
16
- margin-top: var(--pc-editor-header-height);
17
- }
18
15
  .pc-code-editor__code {
19
16
  width: 100%;
20
17
  height: 100%;
@@ -2,12 +2,12 @@ import { PageContent } from '../../../models';
2
2
  import { CodeEditorMessageProps } from '../../utils/validation';
3
3
  import './CodeEditor.css';
4
4
  interface CodeEditorProps {
5
- content: PageContent;
5
+ code: string;
6
6
  fullscreenModeOn: boolean;
7
7
  validator: (code: string) => CodeEditorMessageProps;
8
8
  onFullscreenModeOnUpdate: (fullscreenModeOn: boolean) => void;
9
9
  onChange: (content: PageContent) => void;
10
10
  message?: CodeEditorMessageProps;
11
11
  }
12
- export declare const CodeEditor: ({ content, onChange, validator, fullscreenModeOn, onFullscreenModeOnUpdate, }: CodeEditorProps) => JSX.Element;
12
+ export declare const CodeEditor: ({ onChange, validator, fullscreenModeOn, onFullscreenModeOnUpdate, code, }: CodeEditorProps) => JSX.Element;
13
13
  export {};
@@ -1,27 +1,30 @@
1
- import React, { useCallback, useMemo, useState } from 'react';
1
+ import React, { useCallback, useContext, useState } from 'react';
2
2
  import { ChevronsCollapseUpRight, ChevronsExpandUpRight } from '@gravity-ui/icons';
3
3
  import { Button, Icon } from '@gravity-ui/uikit';
4
- import yaml from 'js-yaml';
4
+ import debounce from 'lodash/debounce';
5
5
  import MonacoEditor from 'react-monaco-editor';
6
+ import { Theme } from '../../../models';
6
7
  import { block } from '../../../utils';
8
+ import { EditorContext } from '../../context';
7
9
  import { parseCode } from '../../utils/code';
8
10
  import { options } from './constants';
9
11
  import './CodeEditor.css';
10
12
  const b = block('code-editor');
11
- export const CodeEditor = ({ content, onChange, validator, fullscreenModeOn, onFullscreenModeOnUpdate, }) => {
12
- const value = useMemo(() => yaml.dump(content), [content]);
13
- const [message, setMessage] = useState(() => validator(value));
14
- const onChangeWithValidation = useCallback((code) => {
15
- const validationResult = validator(code);
13
+ export const CodeEditor = ({ onChange, validator, fullscreenModeOn, onFullscreenModeOnUpdate, code, }) => {
14
+ const [message, setMessage] = useState(() => validator(code));
15
+ const { theme = Theme.Light } = useContext(EditorContext);
16
+ // eslint-disable-next-line react-hooks/exhaustive-deps
17
+ const onChangeWithValidation = useCallback(debounce((newCode) => {
18
+ const validationResult = validator(newCode);
16
19
  setMessage(validationResult);
17
- onChange(parseCode(code));
18
- }, [onChange, validator]);
20
+ onChange(parseCode(newCode));
21
+ }, 200), [onChange, validator]);
19
22
  return (React.createElement("div", { className: b({ fullscreen: fullscreenModeOn }) },
20
23
  React.createElement("div", { className: b('header') },
21
24
  React.createElement(Button, { view: "flat-secondary", onClick: () => onFullscreenModeOnUpdate(!fullscreenModeOn) },
22
25
  React.createElement(Icon, { data: fullscreenModeOn ? ChevronsCollapseUpRight : ChevronsExpandUpRight, size: 16 }))),
23
26
  React.createElement("div", { className: b('code') },
24
- React.createElement(MonacoEditor, { key: String(fullscreenModeOn), value: value, language: "yaml", options: options, onChange: onChangeWithValidation, theme: "vs" })),
27
+ React.createElement(MonacoEditor, { key: String(fullscreenModeOn), value: code, language: "yaml", options: options, onChange: onChangeWithValidation, theme: theme === Theme.Dark ? 'vs-dark' : 'vs' })),
25
28
  React.createElement("div", { className: b('footer') }, message && (React.createElement("div", { className: b('message-container') },
26
29
  React.createElement("div", { className: b('message', { status: message.status }) }, message.text))))));
27
30
  };
@@ -1,2 +1,2 @@
1
1
  import { EditorProps } from '../../types';
2
- export declare const Editor: ({ customSchema, onChange, providerProps, transformContent, deviceEmulationSettings, ...rest }: EditorProps) => JSX.Element;
2
+ export declare const Editor: ({ customSchema, onChange, providerProps, transformContent, deviceEmulationSettings, theme: editorTheme, ...rest }: EditorProps) => JSX.Element;
@@ -12,13 +12,15 @@ import { useCodeValidator } from '../../hooks/useCodeValidator';
12
12
  import { useMainState } from '../../store/main';
13
13
  import { useSettingsState } from '../../store/settings';
14
14
  import { ViewModeItem } from '../../types';
15
+ import { FormTab } from '../../types/index';
15
16
  import { addCustomDecorator, checkIsMobile, getBlockId } from '../../utils';
16
17
  import { Form } from '../Form/Form';
17
18
  export const Editor = (_a) => {
18
- var { customSchema, onChange, providerProps, transformContent, deviceEmulationSettings } = _a, rest = __rest(_a, ["customSchema", "onChange", "providerProps", "transformContent", "deviceEmulationSettings"]);
19
+ var { customSchema, onChange, providerProps, transformContent, deviceEmulationSettings, theme: editorTheme } = _a, rest = __rest(_a, ["customSchema", "onChange", "providerProps", "transformContent", "deviceEmulationSettings", "theme"]);
19
20
  const { content, activeBlockIndex, errorBoundaryState, onContentUpdate, onAdd, onSelect, injectEditBlockProps, } = useMainState(rest);
20
- const { viewMode, theme, onViewModeUpdate, onThemeUpdate, formTab, onFormTabUpdate, codeFullscreeModeOn, onCodeFullscreeModeOnUpdate, } = useSettingsState();
21
+ const { viewMode, theme: constructorTheme, onViewModeUpdate, onThemeUpdate, formTab, onFormTabUpdate, codeFullscreeModeOn, onCodeFullscreeModeOnUpdate, } = useSettingsState();
21
22
  const isEditingMode = viewMode === ViewModeItem.Edititng;
23
+ const isCodeOnlyMode = codeFullscreeModeOn && formTab === FormTab.Code && viewMode === ViewModeItem.Edititng;
22
24
  const transformedContent = useMemo(() => (transformContent ? transformContent(content, { viewMode }) : content), [content, transformContent, viewMode]);
23
25
  const schema = useMemo(() => generateDefaultSchema(customSchema), [customSchema]);
24
26
  const codeValidator = useCodeValidator(schema);
@@ -49,19 +51,28 @@ export const Editor = (_a) => {
49
51
  content: transformedContent,
50
52
  custom: rest.custom,
51
53
  },
52
- providerProps: Object.assign(Object.assign({}, providerProps), { isMobile: checkIsMobile(viewMode), theme }),
54
+ providerProps: Object.assign(Object.assign({}, providerProps), { isMobile: checkIsMobile(viewMode), theme: constructorTheme }),
53
55
  deviceEmulationSettings,
54
- }), [providerProps, rest.custom, viewMode, transformedContent, deviceEmulationSettings, theme]);
56
+ theme: editorTheme,
57
+ }), [
58
+ providerProps,
59
+ rest.custom,
60
+ viewMode,
61
+ transformedContent,
62
+ deviceEmulationSettings,
63
+ constructorTheme,
64
+ editorTheme,
65
+ ]);
55
66
  useEffect(() => {
56
67
  onChange === null || onChange === void 0 ? void 0 : onChange(content);
57
68
  }, [content, onChange]);
58
69
  return (React.createElement(EditorContext.Provider, { value: context },
59
- React.createElement(Layout, { mode: viewMode, onModeChange: onViewModeUpdate, theme: theme, onThemeChange: onThemeUpdate },
70
+ React.createElement(Layout, { mode: viewMode, onModeChange: onViewModeUpdate, theme: constructorTheme, onThemeChange: onThemeUpdate },
60
71
  isEditingMode && (React.createElement(Layout.Left, null,
61
72
  React.createElement(Form, { content: content, onChange: onContentUpdate, activeBlockIndex: activeBlockIndex, activeTab: formTab, codeFullscreeModeOn: codeFullscreeModeOn, schema: schema, codeValidator: codeValidator, onActiveTabUpdate: onFormTabUpdate, onCodeFullscreeModeOnUpdate: onCodeFullscreeModeOnUpdate, onSelect: onSelect }))),
62
- React.createElement(Layout.Right, null,
73
+ !isCodeOnlyMode && (React.createElement(Layout.Right, null,
63
74
  React.createElement(ErrorBoundary, { key: errorBoundaryState },
64
- React.createElement(PageConstructorProvider, Object.assign({}, providerProps, { theme: theme }),
75
+ React.createElement(PageConstructorProvider, Object.assign({}, providerProps, { theme: constructorTheme }),
65
76
  React.createElement(PageConstructor, Object.assign({}, outgoingProps)))),
66
- isEditingMode && React.createElement(AddBlock, { onAdd: onAdd })))));
77
+ isEditingMode && React.createElement(AddBlock, { onAdd: onAdd }))))));
67
78
  };
@@ -7,6 +7,7 @@ import { CodeEditor } from '../../components/CodeEditor/CodeEditor';
7
7
  import { PagePropsForm } from '../../components/PagePropsForm/PagePropsForm';
8
8
  import useFormSpec from '../../hooks/useFormSpec';
9
9
  import { FormTab } from '../../types';
10
+ import { useCode } from './hooks';
10
11
  import './Form.css';
11
12
  const b = block('editor-form');
12
13
  const tabsItems = Object.values(FormTab).map((tab) => ({
@@ -15,6 +16,7 @@ const tabsItems = Object.values(FormTab).map((tab) => ({
15
16
  }));
16
17
  export const Form = memo(({ content, onChange, activeBlockIndex, onSelect, schema, codeValidator, activeTab, onActiveTabUpdate, codeFullscreeModeOn, onCodeFullscreeModeOnUpdate, }) => {
17
18
  const _a = content || {}, { blocks } = _a, page = __rest(_a, ["blocks"]);
19
+ const code = useCode({ activeTab, content, codeFullscreeModeOn });
18
20
  const spec = useFormSpec(schema);
19
21
  const { blocks: blocksSpec, page: pageSpec } = spec || {};
20
22
  let form;
@@ -37,7 +39,7 @@ export const Form = memo(({ content, onChange, activeBlockIndex, onSelect, schem
37
39
  break;
38
40
  }
39
41
  case FormTab.Code: {
40
- form = (React.createElement(CodeEditor, { content: content, onChange: onChange, validator: codeValidator, fullscreenModeOn: codeFullscreeModeOn, onFullscreenModeOnUpdate: onCodeFullscreeModeOnUpdate }));
42
+ form = (React.createElement(CodeEditor, { code: code, onChange: onChange, validator: codeValidator, fullscreenModeOn: codeFullscreeModeOn, onFullscreenModeOnUpdate: onCodeFullscreeModeOnUpdate }));
41
43
  break;
42
44
  }
43
45
  }
@@ -0,0 +1,8 @@
1
+ import { FormProps } from './Form';
2
+ /**
3
+ * Transorms PageConstructor content in JSON to YAML on code editor mode switching
4
+ *
5
+ * @param {Object} props - props parent from form
6
+ * @returns {string} - updated code
7
+ */
8
+ export declare function useCode({ activeTab, content, codeFullscreeModeOn, }: Pick<FormProps, 'activeTab' | 'content' | 'codeFullscreeModeOn'>): string;
@@ -0,0 +1,34 @@
1
+ import { useEffect, useState } from 'react';
2
+ import yaml from 'js-yaml';
3
+ import usePreviousValue from '../../hooks/usePreviousValue';
4
+ import { FormTab } from '../../types';
5
+ /**
6
+ * Transorms PageConstructor content in JSON to YAML on code editor mode switching
7
+ *
8
+ * @param {Object} props - props parent from form
9
+ * @returns {string} - updated code
10
+ */
11
+ export function useCode({ activeTab, content, codeFullscreeModeOn, }) {
12
+ var _a;
13
+ const [code, setCode] = useState('');
14
+ const prevTab = usePreviousValue(activeTab);
15
+ const prevContentLength = usePreviousValue((_a = content.blocks) === null || _a === void 0 ? void 0 : _a.length);
16
+ const prevCodeFullscreeModeOn = usePreviousValue(codeFullscreeModeOn);
17
+ useEffect(() => {
18
+ var _a;
19
+ const switchedToCodeEditing = activeTab !== prevTab && activeTab === FormTab.Code;
20
+ const blocksCountChanged = prevContentLength !== ((_a = content.blocks) === null || _a === void 0 ? void 0 : _a.length);
21
+ const codeModeSwitched = codeFullscreeModeOn !== prevCodeFullscreeModeOn;
22
+ if (blocksCountChanged || switchedToCodeEditing || codeModeSwitched) {
23
+ setCode(yaml.dump(content, { lineWidth: -1 }));
24
+ }
25
+ }, [
26
+ activeTab,
27
+ prevTab,
28
+ content,
29
+ prevContentLength,
30
+ codeFullscreeModeOn,
31
+ prevCodeFullscreeModeOn,
32
+ ]);
33
+ return code;
34
+ }
@@ -1,9 +1,11 @@
1
1
  import React from 'react';
2
2
  import { PageConstructorProps, PageConstructorProviderProps } from '../containers/PageConstructor';
3
+ import { Theme } from '../models/common';
3
4
  import { EditorProps } from './types';
4
5
  export interface EditorContextType {
5
6
  constructorProps?: PageConstructorProps;
6
7
  providerProps?: PageConstructorProviderProps;
7
8
  deviceEmulationSettings?: EditorProps['deviceEmulationSettings'];
9
+ theme?: Theme;
8
10
  }
9
11
  export declare const EditorContext: React.Context<Partial<EditorContextType>>;
@@ -1,5 +1,6 @@
1
1
  import { PageConstructorProps, PageConstructorProviderProps } from '../../containers/PageConstructor';
2
2
  import { BlockDecorationProps, PageContent } from '../../models';
3
+ import { Theme } from '../../models/common';
3
4
  import { SchemaCustomConfig } from '../../schema';
4
5
  import { EditBlockActions } from '../components/EditBlock/EditBlock';
5
6
  export type EditorBlockId = number | string;
@@ -17,6 +18,7 @@ export interface EditorProps extends Required<Pick<PageConstructorProps, 'conten
17
18
  transformContent?: ContentTransformer;
18
19
  customSchema?: SchemaCustomConfig;
19
20
  deviceEmulationSettings?: DeviceEmulationSettings;
21
+ theme?: Theme;
20
22
  }
21
23
  export interface EditBlockEditorProps {
22
24
  isActive?: boolean;
@@ -346,6 +346,7 @@ export interface AuthorProps extends QAProps {
346
346
  className?: string;
347
347
  authorContainerClassName?: string;
348
348
  type?: AuthorType;
349
+ theme?: ContentTheme;
349
350
  }
350
351
  export interface TitleProps {
351
352
  title?: TitleItemProps | string;
@@ -63,16 +63,27 @@ export interface HubspotFormProps extends HubspotEventHandlers, AnalyticsEventsB
63
63
  createDOMElement?: boolean;
64
64
  }
65
65
  export interface QuoteProps extends Themable, CardBaseProps {
66
- text: string;
66
+ text?: string;
67
+ yfmText?: string;
67
68
  image: ThemedImage;
68
69
  logo: ImageProps;
69
70
  color?: string;
71
+ /**
72
+ * @deprecated use property button instead
73
+ */
70
74
  url?: string;
75
+ /**
76
+ * @deprecated use property button instead
77
+ */
71
78
  urlTitle?: string;
72
79
  author?: AuthorItem;
80
+ /**
81
+ * @deprecated use property button instead
82
+ */
73
83
  buttonText?: string;
74
84
  theme?: TextTheme;
75
85
  quoteType?: QuoteType;
86
+ button?: ButtonProps;
76
87
  }
77
88
  export interface BackgroundCardProps extends CardBaseProps, AnalyticsEventsBase, Omit<ContentBlockProps, 'colSizes' | 'centered'> {
78
89
  url?: string;
@@ -125,6 +125,10 @@ export declare const cardSchemas: {
125
125
  type: string;
126
126
  contentType: string;
127
127
  };
128
+ yfmText: {
129
+ type: string;
130
+ contentType: string;
131
+ };
128
132
  image: {
129
133
  oneOf: (({
130
134
  oneOf: ({
@@ -11,7 +11,7 @@ export declare const playIconThemes: string[];
11
11
  export declare const videoControlsTypes: MediaVideoControlsType[];
12
12
  export declare const fileLinkTypes: string[];
13
13
  export declare const dividerEnum: {
14
- enum: (string | number)[];
14
+ enum: string[];
15
15
  };
16
16
  export declare const sizeNumber: {
17
17
  type: string;
@@ -835,6 +835,18 @@ export declare const BlockBaseProps: {
835
835
  context: {
836
836
  type: string;
837
837
  };
838
+ indent: {
839
+ type: string;
840
+ additionalProperties: boolean;
841
+ properties: {
842
+ top: {
843
+ enum: string[];
844
+ };
845
+ bottom: {
846
+ enum: string[];
847
+ };
848
+ };
849
+ };
838
850
  type: {};
839
851
  when: {
840
852
  type: string;
@@ -13,7 +13,7 @@ export const playIconTypes = ['default', 'text'];
13
13
  export const playIconThemes = ['blue', 'grey'];
14
14
  export const videoControlsTypes = [MediaVideoControlsType.Default, MediaVideoControlsType.Custom];
15
15
  export const fileLinkTypes = ['vertical', 'horizontal'];
16
- export const dividerEnum = { enum: [0, 'xxs', 'xs', 's', 'm', 'l', 'xl', 'xxl', 'xxxl'] };
16
+ export const dividerEnum = { enum: ['0', 'xxs', 'xs', 's', 'm', 'l', 'xl', 'xxl', 'xxxl'] };
17
17
  export const sizeNumber = { type: 'number', maximum: 12, minimum: 1 };
18
18
  export const contentThemes = ['default', 'dark', 'light'];
19
19
  export const quoteTypes = Object.values(QuoteType);
@@ -453,6 +453,13 @@ export const BlockBaseProps = Object.assign(Object.assign({}, BaseProps), { anch
453
453
  type: 'boolean',
454
454
  }, context: {
455
455
  type: 'string',
456
+ }, indent: {
457
+ type: 'object',
458
+ additionalProperties: false,
459
+ properties: {
460
+ top: dividerEnum,
461
+ bottom: dividerEnum,
462
+ },
456
463
  } });
457
464
  export const TitleProps = {
458
465
  type: 'object',
@@ -6,7 +6,7 @@ export declare const Divider: {
6
6
  type: string;
7
7
  };
8
8
  size: {
9
- enum: (string | number)[];
9
+ enum: string[];
10
10
  };
11
11
  type: {};
12
12
  when: {
@@ -76,6 +76,17 @@ unpredictable css rules order in build */
76
76
  .pc-quote__content_quote-type_english-double .pc-quote__text::after {
77
77
  content: "”";
78
78
  }
79
+ .pc-quote__content .yfm {
80
+ font-size: var(--g-text-body-3-font-size);
81
+ line-height: var(--g-text-body-3-line-height);
82
+ }
83
+ .pc-quote__content .yfm > * {
84
+ display: inline;
85
+ }
86
+ .pc-quote__content .yfm:after {
87
+ position: relative;
88
+ left: -5px;
89
+ }
79
90
  .pc-quote__image {
80
91
  width: 100%;
81
92
  height: 100%;
@@ -87,24 +98,6 @@ unpredictable css rules order in build */
87
98
  align-items: flex-end;
88
99
  margin-top: 20px;
89
100
  }
90
- .pc-quote__author_theme_dark, .pc-quote_theme_dark {
91
- color: var(--g-color-text-light-primary);
92
- }
93
- .pc-quote__author_theme_dark h1,
94
- .pc-quote__author_theme_dark h2,
95
- .pc-quote__author_theme_dark h3,
96
- .pc-quote__author_theme_dark h4,
97
- .pc-quote__author_theme_dark h5,
98
- .pc-quote__author_theme_dark h6,
99
- .pc-quote__author_theme_dark .yfm, .pc-quote_theme_dark h1,
100
- .pc-quote_theme_dark h2,
101
- .pc-quote_theme_dark h3,
102
- .pc-quote_theme_dark h4,
103
- .pc-quote_theme_dark h5,
104
- .pc-quote_theme_dark h6,
105
- .pc-quote_theme_dark .yfm {
106
- color: var(--g-color-text-light-primary);
107
- }
108
101
  .pc-quote__author {
109
102
  max-width: calc(60% - 20px);
110
103
  margin-right: 20px;
@@ -1,6 +1,5 @@
1
1
  import React, { useCallback } from 'react';
2
- import { Button } from '@gravity-ui/uikit';
3
- import { Author, HTML, Image } from '../../components';
2
+ import { Author, Button, HTML, Image, YFMWrapper } from '../../components';
4
3
  import { getMediaImage } from '../../components/Media/Image/utils';
5
4
  import { useTheme } from '../../context/theme';
6
5
  import { useAnalytics } from '../../hooks';
@@ -9,23 +8,25 @@ import { block, getThemedValue } from '../../utils';
9
8
  import './Quote.css';
10
9
  const b = block('quote');
11
10
  const Quote = (props) => {
12
- const { theme: textTheme = 'light', color, image, border = 'shadow', text, logo, author, url, urlTitle, buttonText, quoteType = QuoteType.Chevron, } = props;
11
+ const { theme: textTheme = 'light', color, image, border = 'shadow', text, yfmText, logo, author, url, urlTitle, buttonText, quoteType = QuoteType.Chevron, button, } = props;
13
12
  const theme = useTheme();
14
13
  const imageThemed = getThemedValue(image, theme);
15
14
  const imageData = getMediaImage(imageThemed);
16
15
  const handleAnalytics = useAnalytics(DefaultEventNames.QuoteButton, url);
17
16
  const handleButtonClick = useCallback(() => handleAnalytics(), [handleAnalytics]);
18
17
  const renderFooter = Boolean(author || url) && (React.createElement("div", { className: b('author-wrapper') },
19
- author && (React.createElement(Author, { className: b('author', { theme: textTheme }), author: author, type: AuthorType.Line })),
20
- url && buttonText && (React.createElement(Button, { view: "outlined", size: "xl", href: url, className: b('link-button', { theme: textTheme }), onClick: handleButtonClick, title: urlTitle }, buttonText))));
18
+ author && (React.createElement(Author, { className: b('author', { theme: textTheme }), author: author, type: AuthorType.Line, theme: textTheme })),
19
+ url && buttonText && !button && (React.createElement(Button, { theme: "outlined", size: "xl", url: url, className: b('link-button', { theme: textTheme }), onClick: handleButtonClick, urlTitle: urlTitle, text: buttonText })),
20
+ button && React.createElement(Button, Object.assign({ size: "xl" }, button))));
21
21
  const logoProps = getMediaImage(logo);
22
22
  return (React.createElement("div", { className: b({ theme: textTheme, border }), style: color ? { backgroundColor: color } : {} },
23
23
  React.createElement("div", { key: text, className: b('content-wrapper') },
24
24
  React.createElement("div", null,
25
25
  React.createElement(Image, Object.assign({ className: b('logo') }, logoProps)),
26
26
  React.createElement("div", { className: b('content', { 'quote-type': quoteType }) },
27
- React.createElement("span", { className: b('text') },
28
- React.createElement(HTML, null, text)))),
27
+ text && (React.createElement("span", { className: b('text') },
28
+ React.createElement(HTML, null, text))),
29
+ yfmText && (React.createElement(YFMWrapper, { className: b('text'), content: yfmText, modifiers: { constructor: true } })))),
29
30
  renderFooter),
30
31
  React.createElement("div", { className: b('image-wrapper') },
31
32
  React.createElement(Image, Object.assign({}, imageData, { className: b('image') })))));
@@ -7,6 +7,10 @@ export declare const Quote: {
7
7
  type: string;
8
8
  contentType: string;
9
9
  };
10
+ yfmText: {
11
+ type: string;
12
+ contentType: string;
13
+ };
10
14
  image: {
11
15
  oneOf: (({
12
16
  oneOf: ({
@@ -3,10 +3,13 @@ import { BaseProps, ThemeProps, authorItem, quoteTypes, withTheme, } from '../..
3
3
  export const Quote = {
4
4
  quote: {
5
5
  additionalProperties: false,
6
- required: ['text', 'image', 'logo'],
6
+ required: ['image', 'logo'],
7
7
  properties: Object.assign(Object.assign({}, BaseProps), { text: {
8
8
  type: 'string',
9
9
  contentType: 'text',
10
+ }, yfmText: {
11
+ type: 'string',
12
+ contentType: 'text',
10
13
  }, image: withTheme(ImageProps), logo: ImageProps, color: {
11
14
  type: 'string',
12
15
  }, url: {