@gravity-ui/page-constructor 5.13.0 → 5.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/blocks/Questions/QuestionBlockItem/QuestionBlockItem.css +1 -0
- package/build/cjs/editor/components/AddBlock/AddBlock.css +1 -2
- package/build/cjs/editor/components/CodeEditor/CodeEditor.css +3 -1
- package/build/cjs/editor/components/ControlPanel/ControlPanel.css +2 -4
- package/build/cjs/editor/components/ControlPanel/ControlPanel.d.ts +4 -2
- package/build/cjs/editor/components/ControlPanel/ControlPanel.js +24 -15
- package/build/cjs/editor/components/ControlPanel/i18n/en.json +2 -1
- package/build/cjs/editor/components/ControlPanel/i18n/index.d.ts +1 -1
- package/build/cjs/editor/components/ControlPanel/i18n/ru.json +2 -1
- package/build/cjs/editor/components/Layout/Layout.css +10 -6
- package/build/cjs/editor/components/Layout/Layout.d.ts +4 -7
- package/build/cjs/editor/components/Layout/Layout.js +8 -10
- package/build/cjs/editor/components/PageSettings/PageSettings.css +26 -0
- package/build/cjs/editor/components/PageSettings/PageSettings.d.ts +11 -0
- package/build/cjs/editor/components/PageSettings/PageSettings.js +30 -0
- package/build/cjs/editor/components/PageSettings/i18n/en.json +3 -0
- package/build/cjs/editor/components/PageSettings/i18n/index.d.ts +1 -0
- package/build/cjs/editor/components/PageSettings/i18n/index.js +9 -0
- package/build/cjs/editor/components/PageSettings/i18n/ru.json +3 -0
- package/build/cjs/editor/containers/Editor/Editor.css +17 -0
- package/build/cjs/editor/containers/Editor/Editor.d.ts +1 -1
- package/build/cjs/editor/containers/Editor/Editor.js +17 -65
- package/build/cjs/editor/containers/Editor/hooks/useCode.d.ts +14 -0
- package/build/cjs/editor/containers/{Form/hooks.js → Editor/hooks/useCode.js} +4 -14
- package/build/cjs/editor/containers/Editor/hooks/useEditorState.d.ts +49 -0
- package/build/cjs/editor/containers/Editor/hooks/useEditorState.js +99 -0
- package/build/cjs/editor/containers/Form/Form.css +0 -10
- package/build/cjs/editor/containers/Form/Form.d.ts +1 -8
- package/build/cjs/editor/containers/Form/Form.js +14 -39
- package/build/cjs/editor/store/main/index.js +1 -1
- package/build/cjs/editor/store/settings/index.d.ts +3 -3
- package/build/cjs/editor/store/settings/index.js +4 -4
- package/build/cjs/editor/store/settings/reducer.d.ts +9 -9
- package/build/cjs/editor/store/settings/reducer.js +6 -6
- package/build/cjs/editor/types/index.d.ts +3 -4
- package/build/cjs/editor/types/index.js +7 -8
- package/build/esm/blocks/Questions/QuestionBlockItem/QuestionBlockItem.css +1 -0
- package/build/esm/editor/components/AddBlock/AddBlock.css +1 -2
- package/build/esm/editor/components/CodeEditor/CodeEditor.css +3 -1
- package/build/esm/editor/components/ControlPanel/ControlPanel.css +2 -4
- package/build/esm/editor/components/ControlPanel/ControlPanel.d.ts +4 -2
- package/build/esm/editor/components/ControlPanel/ControlPanel.js +26 -17
- package/build/esm/editor/components/ControlPanel/i18n/en.json +2 -1
- package/build/esm/editor/components/ControlPanel/i18n/index.d.ts +1 -1
- package/build/esm/editor/components/ControlPanel/i18n/ru.json +2 -1
- package/build/esm/editor/components/Layout/Layout.css +10 -6
- package/build/esm/editor/components/Layout/Layout.d.ts +4 -7
- package/build/esm/editor/components/Layout/Layout.js +9 -11
- package/build/esm/editor/components/PageSettings/PageSettings.css +26 -0
- package/build/esm/editor/components/PageSettings/PageSettings.d.ts +12 -0
- package/build/esm/editor/components/PageSettings/PageSettings.js +27 -0
- package/build/esm/editor/components/PageSettings/i18n/en.json +3 -0
- package/build/esm/editor/components/PageSettings/i18n/index.d.ts +1 -0
- package/build/esm/editor/components/PageSettings/i18n/index.js +5 -0
- package/build/esm/editor/components/PageSettings/i18n/ru.json +3 -0
- package/build/esm/editor/containers/Editor/Editor.css +17 -0
- package/build/esm/editor/containers/Editor/Editor.d.ts +2 -1
- package/build/esm/editor/containers/Editor/Editor.js +18 -66
- package/build/esm/editor/containers/Editor/hooks/useCode.d.ts +14 -0
- package/build/esm/editor/containers/{Form/hooks.js → Editor/hooks/useCode.js} +4 -14
- package/build/esm/editor/containers/Editor/hooks/useEditorState.d.ts +49 -0
- package/build/esm/editor/containers/Editor/hooks/useEditorState.js +95 -0
- package/build/esm/editor/containers/Form/Form.css +0 -10
- package/build/esm/editor/containers/Form/Form.d.ts +1 -8
- package/build/esm/editor/containers/Form/Form.js +16 -42
- package/build/esm/editor/store/main/index.js +1 -1
- package/build/esm/editor/store/settings/index.d.ts +3 -3
- package/build/esm/editor/store/settings/index.js +5 -5
- package/build/esm/editor/store/settings/reducer.d.ts +9 -9
- package/build/esm/editor/store/settings/reducer.js +6 -6
- package/build/esm/editor/types/index.d.ts +3 -4
- package/build/esm/editor/types/index.js +6 -7
- package/package.json +1 -1
- package/widget/index.js +1 -1
- package/build/cjs/editor/components/PagePropsForm/PagePropsForm.d.ts +0 -10
- package/build/cjs/editor/components/PagePropsForm/PagePropsForm.js +0 -17
- package/build/cjs/editor/containers/Form/hooks.d.ts +0 -8
- package/build/esm/editor/components/PagePropsForm/PagePropsForm.d.ts +0 -10
- package/build/esm/editor/components/PagePropsForm/PagePropsForm.js +0 -13
- package/build/esm/editor/containers/Form/hooks.d.ts +0 -8
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* use this for style redefinitions to awoid problems with
|
|
2
|
+
unpredictable css rules order in build */
|
|
3
|
+
body {
|
|
4
|
+
--pc-editor-header-height: 48px;
|
|
5
|
+
--pc-editor-code-header-height: 36px;
|
|
6
|
+
--pc-editor-divider-width: 12px;
|
|
7
|
+
--pc-editor-left-column-width: calc(400px + var(--pc-editor-divider-width));
|
|
8
|
+
--pc-editor-base-color: var(--g-color-base-brand);
|
|
9
|
+
--pc-editor-control-color: var(--g-color-base-brand);
|
|
10
|
+
--pc-editor-control-icon-color: var(--g-color-text-dark-primary);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.pc-editor-page-settings__container {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
align-items: center;
|
|
17
|
+
width: 100%;
|
|
18
|
+
padding: 12px;
|
|
19
|
+
border-bottom: 1px solid var(--g-color-line-generic);
|
|
20
|
+
}
|
|
21
|
+
.pc-editor-page-settings__container .g-disclosure__content {
|
|
22
|
+
width: 100%;
|
|
23
|
+
}
|
|
24
|
+
.pc-editor-page-settings__form {
|
|
25
|
+
margin-top: 16px;
|
|
26
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { JSONSchema4 } from 'json-schema';
|
|
2
|
+
import { PageContent } from '../../../models';
|
|
3
|
+
import './PageSettings.css';
|
|
4
|
+
export interface PageSettingsProps {
|
|
5
|
+
content: PageContent;
|
|
6
|
+
schema: JSONSchema4;
|
|
7
|
+
onChange: (content: PageContent) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare const PageSettings: {
|
|
10
|
+
({ schema, content, onChange }: PageSettingsProps): JSX.Element;
|
|
11
|
+
displayName: string;
|
|
12
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { __rest } from "tslib";
|
|
2
|
+
import React, { useMemo } from 'react';
|
|
3
|
+
import { DynamicField } from '@gravity-ui/dynamic-forms';
|
|
4
|
+
import { Disclosure } from '@gravity-ui/uikit';
|
|
5
|
+
import noop from 'lodash/noop';
|
|
6
|
+
import { Form as FinalForm, FormSpy } from 'react-final-form';
|
|
7
|
+
import { block } from '../../../utils';
|
|
8
|
+
import { dynamicConfig } from '../../dynamic-forms-custom/config';
|
|
9
|
+
import useFormSpec from '../../hooks/useFormSpec';
|
|
10
|
+
import { i18n } from './i18n';
|
|
11
|
+
import './PageSettings.css';
|
|
12
|
+
const b = block('editor-page-settings');
|
|
13
|
+
export const PageSettings = ({ schema, content, onChange }) => {
|
|
14
|
+
const spec = useFormSpec(schema);
|
|
15
|
+
const { page: pageSpec } = spec || {};
|
|
16
|
+
const initialPage = useMemo(() => {
|
|
17
|
+
const _a = content || {}, { blocks: _ } = _a, page = __rest(_a, ["blocks"]);
|
|
18
|
+
return page;
|
|
19
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
20
|
+
}, []);
|
|
21
|
+
return (React.createElement(Disclosure, { className: b('container'), summary: i18n('page-settings-title'), size: "l" },
|
|
22
|
+
React.createElement("div", { className: b('form') },
|
|
23
|
+
React.createElement(FinalForm, { initialValues: { content: initialPage }, onSubmit: noop }, () => (React.createElement("div", null,
|
|
24
|
+
React.createElement(FormSpy, { onChange: ({ values }) => onChange(Object.assign(Object.assign({}, content), values.content)), subscription: { values: true } }),
|
|
25
|
+
React.createElement(DynamicField, { name: "content", spec: pageSpec, config: dynamicConfig })))))));
|
|
26
|
+
};
|
|
27
|
+
PageSettings.displayName = 'PageSettings';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const i18n: (key: "page-settings-title", params?: import("@gravity-ui/i18n").Params | undefined) => string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* use this for style redefinitions to awoid problems with
|
|
2
|
+
unpredictable css rules order in build */
|
|
3
|
+
body {
|
|
4
|
+
--pc-editor-header-height: 48px;
|
|
5
|
+
--pc-editor-code-header-height: 36px;
|
|
6
|
+
--pc-editor-divider-width: 12px;
|
|
7
|
+
--pc-editor-left-column-width: calc(400px + var(--pc-editor-divider-width));
|
|
8
|
+
--pc-editor-base-color: var(--g-color-base-brand);
|
|
9
|
+
--pc-editor-control-color: var(--g-color-base-brand);
|
|
10
|
+
--pc-editor-control-icon-color: var(--g-color-text-dark-primary);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.pc-editor__panel {
|
|
14
|
+
top: 0;
|
|
15
|
+
position: sticky;
|
|
16
|
+
z-index: 2;
|
|
17
|
+
}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { EditorProps } from '../../types';
|
|
2
|
-
|
|
2
|
+
import './Editor.css';
|
|
3
|
+
export declare const Editor: (props: EditorProps) => JSX.Element;
|
|
@@ -1,78 +1,30 @@
|
|
|
1
|
-
import
|
|
2
|
-
import React, { useEffect, useMemo } from 'react';
|
|
1
|
+
import React from 'react';
|
|
3
2
|
import { PageConstructor, PageConstructorProvider } from '../../../containers/PageConstructor';
|
|
4
|
-
import {
|
|
3
|
+
import { block } from '../../../utils';
|
|
5
4
|
import AddBlock from '../../components/AddBlock/AddBlock';
|
|
6
|
-
import
|
|
5
|
+
import { CodeEditor } from '../../components/CodeEditor/CodeEditor';
|
|
6
|
+
import ControlPanel from '../../components/ControlPanel/ControlPanel';
|
|
7
7
|
import { ErrorBoundary } from '../../components/ErrorBoundary/ErrorBoundary';
|
|
8
8
|
import Layout from '../../components/Layout/Layout';
|
|
9
|
-
import {
|
|
9
|
+
import { PageSettings } from '../../components/PageSettings/PageSettings';
|
|
10
10
|
import { EditorContext } from '../../context';
|
|
11
|
-
import { useCodeValidator } from '../../hooks/useCodeValidator';
|
|
12
|
-
import { useMainState } from '../../store/main';
|
|
13
|
-
import { useSettingsState } from '../../store/settings';
|
|
14
|
-
import { ViewModeItem } from '../../types';
|
|
15
|
-
import { FormTab } from '../../types/index';
|
|
16
|
-
import { addCustomDecorator, checkIsMobile, getBlockId } from '../../utils';
|
|
17
11
|
import { Form } from '../Form/Form';
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const transformedContent = useMemo(() => (transformContent ? transformContent(content, { viewMode }) : content), [content, transformContent, viewMode]);
|
|
25
|
-
const schema = useMemo(() => generateDefaultSchema(customSchema), [customSchema]);
|
|
26
|
-
const codeValidator = useCodeValidator(schema);
|
|
27
|
-
const outgoingProps = useMemo(() => {
|
|
28
|
-
const custom = isEditingMode
|
|
29
|
-
? addCustomDecorator([
|
|
30
|
-
(props) => React.createElement(NotFoundBlock, Object.assign({}, props)),
|
|
31
|
-
(props) => (React.createElement(EditBlock, Object.assign({}, injectEditBlockProps(props)))),
|
|
32
|
-
// need errorBoundaryState flag to reset error on content update
|
|
33
|
-
(props) => (React.createElement(ErrorBoundary, Object.assign({}, props, { key: `${getBlockId(props)}-${errorBoundaryState}` }))),
|
|
34
|
-
], rest.custom)
|
|
35
|
-
: rest.custom;
|
|
36
|
-
return {
|
|
37
|
-
content: transformedContent,
|
|
38
|
-
custom,
|
|
39
|
-
viewMode,
|
|
40
|
-
};
|
|
41
|
-
}, [
|
|
42
|
-
injectEditBlockProps,
|
|
43
|
-
errorBoundaryState,
|
|
44
|
-
isEditingMode,
|
|
45
|
-
viewMode,
|
|
46
|
-
transformedContent,
|
|
47
|
-
rest.custom,
|
|
48
|
-
]);
|
|
49
|
-
const context = useMemo(() => ({
|
|
50
|
-
constructorProps: {
|
|
51
|
-
content: transformedContent,
|
|
52
|
-
custom: rest.custom,
|
|
53
|
-
},
|
|
54
|
-
providerProps: Object.assign(Object.assign({}, providerProps), { isMobile: checkIsMobile(viewMode), theme: constructorTheme }),
|
|
55
|
-
deviceEmulationSettings,
|
|
56
|
-
theme: editorTheme,
|
|
57
|
-
}), [
|
|
58
|
-
providerProps,
|
|
59
|
-
rest.custom,
|
|
60
|
-
viewMode,
|
|
61
|
-
transformedContent,
|
|
62
|
-
deviceEmulationSettings,
|
|
63
|
-
constructorTheme,
|
|
64
|
-
editorTheme,
|
|
65
|
-
]);
|
|
66
|
-
useEffect(() => {
|
|
67
|
-
onChange === null || onChange === void 0 ? void 0 : onChange(content);
|
|
68
|
-
}, [content, onChange]);
|
|
12
|
+
import { useEditorState } from './hooks/useEditorState';
|
|
13
|
+
import './Editor.css';
|
|
14
|
+
const b = block('editor');
|
|
15
|
+
export const Editor = (props) => {
|
|
16
|
+
const { providerProps } = props;
|
|
17
|
+
const { context, viewMode, editMode, constructorTheme, onThemeUpdate, onViewModeUpdate, onEditModeUpdate, isCodeEditMode, isFormEditMode, isDesktopViewMode, content, schema, onContentUpdate, code, codeValidator, codeFullscreeModeOn, onCodeFullscreeModeOnUpdate, activeBlockIndex, onSelect, isCodeOnlyMode, errorBoundaryState, outgoingProps, onAdd, } = useEditorState(props);
|
|
69
18
|
return (React.createElement(EditorContext.Provider, { value: context },
|
|
70
|
-
React.createElement(
|
|
71
|
-
|
|
72
|
-
|
|
19
|
+
React.createElement(ControlPanel, { viewMode: viewMode, onViewModeChange: onViewModeUpdate, editMode: editMode, onEditModeChange: onEditModeUpdate, theme: constructorTheme, className: b('panel'), onThemeChange: onThemeUpdate }),
|
|
20
|
+
isFormEditMode && isDesktopViewMode && (React.createElement(PageSettings, { content: content, schema: schema, onChange: onContentUpdate })),
|
|
21
|
+
isCodeEditMode && (React.createElement(CodeEditor, { code: code, onChange: onContentUpdate, validator: codeValidator, fullscreenModeOn: codeFullscreeModeOn, onFullscreenModeOnUpdate: onCodeFullscreeModeOnUpdate })),
|
|
22
|
+
React.createElement(Layout, { editMode: editMode, viewMode: viewMode },
|
|
23
|
+
isFormEditMode && isDesktopViewMode && (React.createElement(Layout.Left, null,
|
|
24
|
+
React.createElement(Form, { content: content, onChange: onContentUpdate, activeBlockIndex: activeBlockIndex, schema: schema, onSelect: onSelect }))),
|
|
73
25
|
!isCodeOnlyMode && (React.createElement(Layout.Right, null,
|
|
74
26
|
React.createElement(ErrorBoundary, { key: errorBoundaryState },
|
|
75
27
|
React.createElement(PageConstructorProvider, Object.assign({}, providerProps, { theme: constructorTheme }),
|
|
76
28
|
React.createElement(PageConstructor, Object.assign({}, outgoingProps)))),
|
|
77
|
-
|
|
29
|
+
isFormEditMode && React.createElement(AddBlock, { onAdd: onAdd }))))));
|
|
78
30
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PageContent } from '../../../../models';
|
|
2
|
+
type UseCodeProps = {
|
|
3
|
+
content: PageContent;
|
|
4
|
+
codeFullscreeModeOn: boolean;
|
|
5
|
+
isCodeEditMode: boolean;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Transorms PageConstructor content in JSON to YAML on code editor mode switching
|
|
9
|
+
*
|
|
10
|
+
* @param {Object} props - props parent from form
|
|
11
|
+
* @returns {string} - updated code
|
|
12
|
+
*/
|
|
13
|
+
export declare function useCode({ content, codeFullscreeModeOn, isCodeEditMode }: UseCodeProps): string;
|
|
14
|
+
export {};
|
|
@@ -1,34 +1,24 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
2
|
import yaml from 'js-yaml';
|
|
3
|
-
import usePreviousValue from '
|
|
4
|
-
import { FormTab } from '../../types';
|
|
3
|
+
import usePreviousValue from '../../../hooks/usePreviousValue';
|
|
5
4
|
/**
|
|
6
5
|
* Transorms PageConstructor content in JSON to YAML on code editor mode switching
|
|
7
6
|
*
|
|
8
7
|
* @param {Object} props - props parent from form
|
|
9
8
|
* @returns {string} - updated code
|
|
10
9
|
*/
|
|
11
|
-
export function useCode({
|
|
10
|
+
export function useCode({ content, codeFullscreeModeOn, isCodeEditMode }) {
|
|
12
11
|
var _a;
|
|
13
12
|
const [code, setCode] = useState('');
|
|
14
|
-
const prevTab = usePreviousValue(activeTab);
|
|
15
13
|
const prevContentLength = usePreviousValue((_a = content.blocks) === null || _a === void 0 ? void 0 : _a.length);
|
|
16
14
|
const prevCodeFullscreeModeOn = usePreviousValue(codeFullscreeModeOn);
|
|
17
15
|
useEffect(() => {
|
|
18
16
|
var _a;
|
|
19
|
-
const switchedToCodeEditing = activeTab !== prevTab && activeTab === FormTab.Code;
|
|
20
17
|
const blocksCountChanged = prevContentLength !== ((_a = content.blocks) === null || _a === void 0 ? void 0 : _a.length);
|
|
21
18
|
const codeModeSwitched = codeFullscreeModeOn !== prevCodeFullscreeModeOn;
|
|
22
|
-
if (blocksCountChanged ||
|
|
19
|
+
if (blocksCountChanged || isCodeEditMode || codeModeSwitched) {
|
|
23
20
|
setCode(yaml.dump(content, { lineWidth: -1 }));
|
|
24
21
|
}
|
|
25
|
-
}, [
|
|
26
|
-
activeTab,
|
|
27
|
-
prevTab,
|
|
28
|
-
content,
|
|
29
|
-
prevContentLength,
|
|
30
|
-
codeFullscreeModeOn,
|
|
31
|
-
prevCodeFullscreeModeOn,
|
|
32
|
-
]);
|
|
22
|
+
}, [isCodeEditMode, content, prevContentLength, codeFullscreeModeOn, prevCodeFullscreeModeOn]);
|
|
33
23
|
return code;
|
|
34
24
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { EditModeItem, EditorProps, ViewModeItem } from '../../../types';
|
|
2
|
+
export declare const useEditorState: ({ customSchema, onChange, providerProps, transformContent, deviceEmulationSettings, theme: editorTheme, ...rest }: EditorProps) => {
|
|
3
|
+
context: {
|
|
4
|
+
constructorProps: {
|
|
5
|
+
content: import("../../../../models").PageContent;
|
|
6
|
+
custom: import("../../../../models").CustomConfig | undefined;
|
|
7
|
+
};
|
|
8
|
+
providerProps: {
|
|
9
|
+
isMobile: boolean;
|
|
10
|
+
theme: import("../../../../models").Theme;
|
|
11
|
+
locale?: import("../../../../context/localeContext").LocaleContextProps | undefined;
|
|
12
|
+
location?: import("../../../../context/locationContext").LocationContextProps | undefined;
|
|
13
|
+
ssrConfig?: import("../../../../context/ssrContext").SSRContextProps | undefined;
|
|
14
|
+
mapsContext?: import("../../../../context/mapsContext/mapsContext").MapsContextType | undefined;
|
|
15
|
+
projectSettings?: import("../../../../context/projectSettingsContext").ProjectSettingsContextProps | undefined;
|
|
16
|
+
analytics?: import("../../../..").AnalyticsContextProps | undefined;
|
|
17
|
+
forms?: import("../../../../context/formsContext").FormsContextProps | undefined;
|
|
18
|
+
image?: import("../../../../context/imageContext").ImageContextProps | undefined;
|
|
19
|
+
};
|
|
20
|
+
deviceEmulationSettings: import("../../../types").DeviceEmulationSettings | undefined;
|
|
21
|
+
theme: import("../../../../models").Theme | undefined;
|
|
22
|
+
};
|
|
23
|
+
viewMode: ViewModeItem;
|
|
24
|
+
editMode: EditModeItem;
|
|
25
|
+
constructorTheme: import("../../../../models").Theme;
|
|
26
|
+
onThemeUpdate: (newTheme: import("../../../../models").Theme) => void;
|
|
27
|
+
onViewModeUpdate: (newViewMode: ViewModeItem) => void;
|
|
28
|
+
onEditModeUpdate: (newEditMode: EditModeItem) => void;
|
|
29
|
+
isCodeEditMode: boolean;
|
|
30
|
+
isDesktopViewMode: boolean;
|
|
31
|
+
content: import("../../../../models").PageContent;
|
|
32
|
+
schema: import("json-schema").JSONSchema4;
|
|
33
|
+
onContentUpdate: (newContent: import("../../../../models").PageContent) => void;
|
|
34
|
+
code: string;
|
|
35
|
+
codeValidator: import("../../../hooks/useCodeValidator").CodeValidator;
|
|
36
|
+
codeFullscreeModeOn: boolean;
|
|
37
|
+
onCodeFullscreeModeOnUpdate: (newCodeFullscreeModeOn: boolean) => void;
|
|
38
|
+
activeBlockIndex: number;
|
|
39
|
+
onSelect: (index: number) => void;
|
|
40
|
+
isCodeOnlyMode: boolean;
|
|
41
|
+
errorBoundaryState: number;
|
|
42
|
+
outgoingProps: {
|
|
43
|
+
content: import("../../../../models").PageContent;
|
|
44
|
+
custom: import("../../../../models").CustomConfig | undefined;
|
|
45
|
+
viewMode: ViewModeItem;
|
|
46
|
+
};
|
|
47
|
+
onAdd: (block: import("../../../../models").Block) => void;
|
|
48
|
+
isFormEditMode: boolean;
|
|
49
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { __rest } from "tslib";
|
|
2
|
+
import React, { useEffect, useMemo } from 'react';
|
|
3
|
+
import { generateDefaultSchema } from '../../../../schema';
|
|
4
|
+
import EditBlock from '../../../components/EditBlock/EditBlock';
|
|
5
|
+
import { ErrorBoundary } from '../../../components/ErrorBoundary/ErrorBoundary';
|
|
6
|
+
import { NotFoundBlock } from '../../../components/NotFoundBlock/NotFoundBlock';
|
|
7
|
+
import { useCodeValidator } from '../../../hooks/useCodeValidator';
|
|
8
|
+
import { useMainState } from '../../../store/main';
|
|
9
|
+
import { useSettingsState } from '../../../store/settings';
|
|
10
|
+
import { EditModeItem, ViewModeItem } from '../../../types';
|
|
11
|
+
import { addCustomDecorator, checkIsMobile, getBlockId } from '../../../utils';
|
|
12
|
+
import { useCode } from './useCode';
|
|
13
|
+
// Editor business logic
|
|
14
|
+
export const useEditorState = (_a) => {
|
|
15
|
+
var { customSchema, onChange, providerProps, transformContent, deviceEmulationSettings, theme: editorTheme } = _a, rest = __rest(_a, ["customSchema", "onChange", "providerProps", "transformContent", "deviceEmulationSettings", "theme"]);
|
|
16
|
+
const { content, activeBlockIndex, errorBoundaryState, onContentUpdate, onAdd, onSelect, injectEditBlockProps, } = useMainState(rest);
|
|
17
|
+
const { viewMode, editMode, onEditModeUpdate, theme: constructorTheme, onViewModeUpdate, onThemeUpdate, codeFullscreeModeOn, onCodeFullscreeModeOnUpdate, } = useSettingsState();
|
|
18
|
+
const isCodeEditMode = editMode === EditModeItem.Code;
|
|
19
|
+
const isViewEditMode = editMode === EditModeItem.View;
|
|
20
|
+
const isFormEditMode = editMode === EditModeItem.Form;
|
|
21
|
+
const isDesktopViewMode = viewMode === ViewModeItem.Desktop;
|
|
22
|
+
const isCodeOnlyMode = codeFullscreeModeOn && isCodeEditMode;
|
|
23
|
+
const transformedContent = useMemo(() => (transformContent ? transformContent(content, { viewMode }) : content), [content, transformContent, viewMode]);
|
|
24
|
+
const schema = useMemo(() => generateDefaultSchema(customSchema), [customSchema]);
|
|
25
|
+
const codeValidator = useCodeValidator(schema);
|
|
26
|
+
const outgoingProps = useMemo(() => {
|
|
27
|
+
const custom = isCodeEditMode || isViewEditMode
|
|
28
|
+
? rest.custom
|
|
29
|
+
: addCustomDecorator([
|
|
30
|
+
(props) => React.createElement(NotFoundBlock, Object.assign({}, props)),
|
|
31
|
+
(props) => (React.createElement(EditBlock, Object.assign({}, injectEditBlockProps(props)))),
|
|
32
|
+
// need errorBoundaryState flag to reset error on content update
|
|
33
|
+
(props) => (React.createElement(ErrorBoundary, Object.assign({}, props, { key: `${getBlockId(props)}-${errorBoundaryState}` }))),
|
|
34
|
+
], rest.custom);
|
|
35
|
+
return {
|
|
36
|
+
content: transformedContent,
|
|
37
|
+
custom,
|
|
38
|
+
viewMode,
|
|
39
|
+
};
|
|
40
|
+
}, [
|
|
41
|
+
injectEditBlockProps,
|
|
42
|
+
errorBoundaryState,
|
|
43
|
+
viewMode,
|
|
44
|
+
transformedContent,
|
|
45
|
+
rest.custom,
|
|
46
|
+
isCodeEditMode,
|
|
47
|
+
isViewEditMode,
|
|
48
|
+
]);
|
|
49
|
+
const context = useMemo(() => ({
|
|
50
|
+
constructorProps: {
|
|
51
|
+
content: transformedContent,
|
|
52
|
+
custom: rest.custom,
|
|
53
|
+
},
|
|
54
|
+
providerProps: Object.assign(Object.assign({}, providerProps), { isMobile: checkIsMobile(viewMode), theme: constructorTheme }),
|
|
55
|
+
deviceEmulationSettings,
|
|
56
|
+
theme: editorTheme,
|
|
57
|
+
}), [
|
|
58
|
+
providerProps,
|
|
59
|
+
rest.custom,
|
|
60
|
+
viewMode,
|
|
61
|
+
transformedContent,
|
|
62
|
+
deviceEmulationSettings,
|
|
63
|
+
constructorTheme,
|
|
64
|
+
editorTheme,
|
|
65
|
+
]);
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(content);
|
|
68
|
+
}, [content, onChange]);
|
|
69
|
+
const code = useCode({ isCodeEditMode, content, codeFullscreeModeOn });
|
|
70
|
+
return {
|
|
71
|
+
context,
|
|
72
|
+
viewMode,
|
|
73
|
+
editMode,
|
|
74
|
+
constructorTheme,
|
|
75
|
+
onThemeUpdate,
|
|
76
|
+
onViewModeUpdate,
|
|
77
|
+
onEditModeUpdate,
|
|
78
|
+
isCodeEditMode,
|
|
79
|
+
isDesktopViewMode,
|
|
80
|
+
content,
|
|
81
|
+
schema,
|
|
82
|
+
onContentUpdate,
|
|
83
|
+
code,
|
|
84
|
+
codeValidator,
|
|
85
|
+
codeFullscreeModeOn,
|
|
86
|
+
onCodeFullscreeModeOnUpdate,
|
|
87
|
+
activeBlockIndex,
|
|
88
|
+
onSelect,
|
|
89
|
+
isCodeOnlyMode,
|
|
90
|
+
errorBoundaryState,
|
|
91
|
+
outgoingProps,
|
|
92
|
+
onAdd,
|
|
93
|
+
isFormEditMode,
|
|
94
|
+
};
|
|
95
|
+
};
|
|
@@ -82,16 +82,6 @@ unpredictable css rules order in build */
|
|
|
82
82
|
.pc-editor-form + .pc-editor-form {
|
|
83
83
|
margin-top: 12px;
|
|
84
84
|
}
|
|
85
|
-
.pc-editor-form__tabs {
|
|
86
|
-
--g-color-base-brand: var(--pc-color-base-neon);
|
|
87
|
-
margin-bottom: 20px;
|
|
88
|
-
}
|
|
89
85
|
.pc-editor-form__block-form {
|
|
90
86
|
margin-bottom: 16px;
|
|
91
|
-
}
|
|
92
|
-
.pc-editor-form_code-editor-active {
|
|
93
|
-
height: calc(100% - var(--pc-editor-code-header-height));
|
|
94
|
-
}
|
|
95
|
-
.pc-editor-form_code-editor-active .pc-editor-form__tabs {
|
|
96
|
-
margin-bottom: 0;
|
|
97
87
|
}
|
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { JSONSchema4 } from 'json-schema';
|
|
3
3
|
import { PageContent } from '../../../models';
|
|
4
|
-
import { FormTab } from '../../types';
|
|
5
|
-
import { CodeEditorMessageProps } from '../../utils/validation';
|
|
6
4
|
import './Form.css';
|
|
7
5
|
export interface FormProps {
|
|
8
6
|
content: PageContent;
|
|
9
7
|
schema: JSONSchema4;
|
|
10
8
|
activeBlockIndex: number;
|
|
11
|
-
activeTab: FormTab;
|
|
12
|
-
codeFullscreeModeOn: boolean;
|
|
13
|
-
onActiveTabUpdate: (tab: FormTab) => void;
|
|
14
|
-
onCodeFullscreeModeOnUpdate: (codeFullscreeModeOn: boolean) => void;
|
|
15
|
-
codeValidator: (code: string) => CodeEditorMessageProps;
|
|
16
9
|
onChange: (content: PageContent) => void;
|
|
17
10
|
onSelect: (index: number) => void;
|
|
18
11
|
}
|
|
19
|
-
export declare const Form: React.MemoExoticComponent<({ content, onChange, activeBlockIndex, onSelect, schema
|
|
12
|
+
export declare const Form: React.MemoExoticComponent<({ content, onChange, activeBlockIndex, onSelect, schema }: FormProps) => JSX.Element>;
|
|
@@ -1,50 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { Tabs } from '@gravity-ui/uikit';
|
|
1
|
+
import React, { memo } from 'react';
|
|
2
|
+
import { Text } from '@gravity-ui/uikit';
|
|
4
3
|
import { block, getBlockKey } from '../../../utils';
|
|
5
4
|
import { BlockForm } from '../../components/BlockForm/BlockForm';
|
|
6
|
-
import { CodeEditor } from '../../components/CodeEditor/CodeEditor';
|
|
7
|
-
import { PagePropsForm } from '../../components/PagePropsForm/PagePropsForm';
|
|
8
5
|
import useFormSpec from '../../hooks/useFormSpec';
|
|
9
|
-
import { FormTab } from '../../types';
|
|
10
|
-
import { useCode } from './hooks';
|
|
11
6
|
import './Form.css';
|
|
12
7
|
const b = block('editor-form');
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}));
|
|
17
|
-
export const Form = memo(({ content, onChange, activeBlockIndex, onSelect, schema, codeValidator, activeTab, onActiveTabUpdate, codeFullscreeModeOn, onCodeFullscreeModeOnUpdate, }) => {
|
|
18
|
-
const _a = content || {}, { blocks } = _a, page = __rest(_a, ["blocks"]);
|
|
19
|
-
const code = useCode({ activeTab, content, codeFullscreeModeOn });
|
|
8
|
+
// TODO in https://github.com/gravity-ui/page-constructor/issues/884 this component will be extremely refactor
|
|
9
|
+
export const Form = memo(({ content, onChange, activeBlockIndex, onSelect, schema }) => {
|
|
10
|
+
const { blocks } = content || {};
|
|
20
11
|
const spec = useFormSpec(schema);
|
|
21
|
-
const { blocks: blocksSpec
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
React.createElement(BlockForm, { spec: blocksSpec[blockData.type], data: blockData, active: activeBlockIndex === index, onChange: (data) => {
|
|
33
|
-
onChange(Object.assign(Object.assign({}, content), { blocks: [
|
|
34
|
-
...blocks.slice(0, index),
|
|
35
|
-
data,
|
|
36
|
-
...blocks.slice(index + 1),
|
|
37
|
-
] }));
|
|
38
|
-
}, onSelect: () => onSelect(index) }))) : null)));
|
|
39
|
-
break;
|
|
40
|
-
}
|
|
41
|
-
case FormTab.Code: {
|
|
42
|
-
form = (React.createElement(CodeEditor, { code: code, onChange: onChange, validator: codeValidator, fullscreenModeOn: codeFullscreeModeOn, onFullscreenModeOnUpdate: onCodeFullscreeModeOnUpdate }));
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return (React.createElement("div", { className: b({ 'code-editor-active': activeTab === FormTab.Code }) },
|
|
47
|
-
React.createElement(Tabs, { activeTab: activeTab, className: b('tabs'), items: tabsItems, onSelectTab: onActiveTabUpdate }),
|
|
48
|
-
form));
|
|
12
|
+
const { blocks: blocksSpec } = spec || {};
|
|
13
|
+
return (React.createElement("div", { className: b() },
|
|
14
|
+
React.createElement(Text, { variant: "body-2" }, 'Blocks'),
|
|
15
|
+
blocks.map((blockData, index) => blocksSpec[blockData.type] ? (React.createElement("div", { className: b('block-form'), key: getBlockKey(blockData, index) },
|
|
16
|
+
React.createElement(BlockForm, { spec: blocksSpec[blockData.type], data: blockData, active: activeBlockIndex === index, onChange: (data) => {
|
|
17
|
+
onChange(Object.assign(Object.assign({}, content), { blocks: [
|
|
18
|
+
...blocks.slice(0, index),
|
|
19
|
+
data,
|
|
20
|
+
...blocks.slice(index + 1),
|
|
21
|
+
] }));
|
|
22
|
+
}, onSelect: () => onSelect(index) }))) : null)));
|
|
49
23
|
});
|
|
50
24
|
Form.displayName = 'Form';
|
|
@@ -12,7 +12,7 @@ export function useMainState({ content: intialContent, custom }) {
|
|
|
12
12
|
activeBlockIndex: 0,
|
|
13
13
|
errorBoundaryState: 0,
|
|
14
14
|
content: addEditorProps(intialContent),
|
|
15
|
-
viewMode: ViewModeItem.
|
|
15
|
+
viewMode: ViewModeItem.Desktop,
|
|
16
16
|
theme: DEFAULT_THEME,
|
|
17
17
|
});
|
|
18
18
|
return useMemo(() => {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Theme } from '../../../models';
|
|
2
|
-
import {
|
|
2
|
+
import { EditModeItem, ViewModeItem } from '../../types';
|
|
3
3
|
export declare function useSettingsState(): {
|
|
4
|
-
formTab: FormTab;
|
|
5
4
|
viewMode: ViewModeItem;
|
|
5
|
+
editMode: EditModeItem;
|
|
6
6
|
theme: Theme;
|
|
7
7
|
codeFullscreeModeOn: boolean;
|
|
8
|
-
onFormTabUpdate: (newFormTab: FormTab) => void;
|
|
9
8
|
onViewModeUpdate: (newViewMode: ViewModeItem) => void;
|
|
9
|
+
onEditModeUpdate: (newEditMode: EditModeItem) => void;
|
|
10
10
|
onThemeUpdate: (newTheme: Theme) => void;
|
|
11
11
|
onCodeFullscreeModeOnUpdate: (newCodeFullscreeModeOn: boolean) => void;
|
|
12
12
|
};
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { useMemo, useReducer } from 'react';
|
|
2
|
-
import { UPDATE_CODE_FULLSCREEN_MODE_ON,
|
|
2
|
+
import { UPDATE_CODE_FULLSCREEN_MODE_ON, UPDATE_EDIT_MODE, UPDATE_THEME, UPDATE_VIEW_MODE, initialState, reducer, } from './reducer';
|
|
3
3
|
export function useSettingsState() {
|
|
4
|
-
const [{
|
|
4
|
+
const [{ viewMode, editMode, theme, codeFullscreeModeOn }, dispatch] = useReducer(reducer, initialState);
|
|
5
5
|
return useMemo(() => {
|
|
6
6
|
return {
|
|
7
|
-
formTab,
|
|
8
7
|
viewMode,
|
|
8
|
+
editMode,
|
|
9
9
|
theme,
|
|
10
10
|
codeFullscreeModeOn,
|
|
11
|
-
onFormTabUpdate: (newFormTab) => dispatch({ type: UPDATE_FORM_TAB, payload: newFormTab }),
|
|
12
11
|
onViewModeUpdate: (newViewMode) => dispatch({ type: UPDATE_VIEW_MODE, payload: newViewMode }),
|
|
12
|
+
onEditModeUpdate: (newEditMode) => dispatch({ type: UPDATE_EDIT_MODE, payload: newEditMode }),
|
|
13
13
|
onThemeUpdate: (newTheme) => dispatch({ type: UPDATE_THEME, payload: newTheme }),
|
|
14
14
|
onCodeFullscreeModeOnUpdate: (newCodeFullscreeModeOn) => dispatch({ type: UPDATE_CODE_FULLSCREEN_MODE_ON, payload: newCodeFullscreeModeOn }),
|
|
15
15
|
};
|
|
16
|
-
}, [
|
|
16
|
+
}, [viewMode, theme, codeFullscreeModeOn, editMode]);
|
|
17
17
|
}
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import { Theme } from '../../../models';
|
|
2
|
-
import {
|
|
3
|
-
export declare const UPDATE_FORM_TAB = "UPDATE_FORM_TAB";
|
|
2
|
+
import { EditModeItem, ViewModeItem } from '../../types';
|
|
4
3
|
export declare const UPDATE_CODE_FULLSCREEN_MODE_ON = "UPDATE_CODE_FULLSCREEN_MODE_ON";
|
|
5
4
|
export declare const UPDATE_VIEW_MODE = "UPDATE_VIEW_MODE";
|
|
5
|
+
export declare const UPDATE_EDIT_MODE = "UPDATE_EDIT_MODE";
|
|
6
6
|
export declare const UPDATE_THEME = "UPDATE_THEME";
|
|
7
7
|
interface EditorSettingsState {
|
|
8
8
|
theme: Theme;
|
|
9
9
|
viewMode: ViewModeItem;
|
|
10
|
+
editMode: EditModeItem;
|
|
10
11
|
codeFullscreeModeOn: boolean;
|
|
11
|
-
formTab: FormTab;
|
|
12
12
|
}
|
|
13
13
|
interface UpdateViewMode {
|
|
14
14
|
type: typeof UPDATE_VIEW_MODE;
|
|
15
15
|
payload: ViewModeItem;
|
|
16
16
|
}
|
|
17
|
+
interface UpdateEditMode {
|
|
18
|
+
type: typeof UPDATE_EDIT_MODE;
|
|
19
|
+
payload: EditModeItem;
|
|
20
|
+
}
|
|
17
21
|
interface UpdateTheme {
|
|
18
22
|
type: typeof UPDATE_THEME;
|
|
19
23
|
payload: Theme;
|
|
@@ -22,16 +26,12 @@ interface UpdateCodeFullscreenModeOn {
|
|
|
22
26
|
type: typeof UPDATE_CODE_FULLSCREEN_MODE_ON;
|
|
23
27
|
payload: boolean;
|
|
24
28
|
}
|
|
25
|
-
|
|
26
|
-
type: typeof UPDATE_FORM_TAB;
|
|
27
|
-
payload: FormTab;
|
|
28
|
-
}
|
|
29
|
-
export type EditorSettingsAction = UpdateViewMode | UpdateTheme | UpdateCodeFullscreenModeOn | UpdateFormTab;
|
|
29
|
+
export type EditorSettingsAction = UpdateViewMode | UpdateEditMode | UpdateTheme | UpdateCodeFullscreenModeOn;
|
|
30
30
|
export declare const reducer: (state: EditorSettingsState, action: EditorSettingsAction) => EditorSettingsState;
|
|
31
31
|
export declare const initialState: {
|
|
32
32
|
viewMode: ViewModeItem;
|
|
33
|
+
editMode: EditModeItem;
|
|
33
34
|
theme: Theme;
|
|
34
35
|
codeFullscreeModeOn: boolean;
|
|
35
|
-
formTab: FormTab;
|
|
36
36
|
};
|
|
37
37
|
export {};
|