@gravity-ui/page-constructor 3.3.0 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/build/cjs/editor/components/AddBlock/AddBlock.css +7 -0
- package/build/cjs/editor/components/BlockForm/BlockForm.js +8 -1
- package/build/cjs/editor/components/ControlPanel/ControlPanel.css +26 -0
- package/build/cjs/editor/components/ControlPanel/ControlPanel.d.ts +8 -0
- package/build/cjs/editor/components/ControlPanel/ControlPanel.js +24 -0
- package/build/cjs/editor/components/ControlPanel/i18n/en.json +3 -0
- package/build/cjs/editor/components/ControlPanel/i18n/index.d.ts +2 -0
- package/build/cjs/editor/components/ControlPanel/i18n/index.js +8 -0
- package/build/cjs/editor/components/ControlPanel/i18n/ru.json +3 -0
- package/build/cjs/editor/components/Layout/Layout.css +36 -0
- package/build/cjs/editor/components/Layout/Layout.d.ts +16 -0
- package/build/cjs/editor/components/Layout/Layout.js +34 -0
- package/build/cjs/editor/containers/Editor/Editor.js +21 -18
- package/build/cjs/editor/hooks/usePreviousValue.d.ts +1 -0
- package/build/cjs/editor/hooks/usePreviousValue.js +11 -0
- package/build/cjs/editor/store/index.d.ts +3 -1
- package/build/cjs/editor/store/index.js +7 -2
- package/build/cjs/editor/store/reducer.d.ts +8 -1
- package/build/cjs/editor/store/reducer.js +4 -1
- package/build/cjs/editor/styles/root.css +5 -0
- package/build/cjs/editor/types/index.d.ts +4 -0
- package/build/cjs/editor/types/index.js +6 -0
- package/build/esm/editor/components/AddBlock/AddBlock.css +7 -0
- package/build/esm/editor/components/BlockForm/BlockForm.js +8 -1
- package/build/esm/editor/components/ControlPanel/ControlPanel.css +26 -0
- package/build/esm/editor/components/ControlPanel/ControlPanel.d.ts +9 -0
- package/build/esm/editor/components/ControlPanel/ControlPanel.js +22 -0
- package/build/esm/editor/components/ControlPanel/i18n/en.json +3 -0
- package/build/esm/editor/components/ControlPanel/i18n/index.d.ts +2 -0
- package/build/esm/editor/components/ControlPanel/i18n/index.js +5 -0
- package/build/esm/editor/components/ControlPanel/i18n/ru.json +3 -0
- package/build/esm/editor/components/Layout/Layout.css +36 -0
- package/build/esm/editor/components/Layout/Layout.d.ts +17 -0
- package/build/esm/editor/components/Layout/Layout.js +32 -0
- package/build/esm/editor/containers/Editor/Editor.d.ts +0 -1
- package/build/esm/editor/containers/Editor/Editor.js +20 -18
- package/build/esm/editor/hooks/usePreviousValue.d.ts +1 -0
- package/build/esm/editor/hooks/usePreviousValue.js +8 -0
- package/build/esm/editor/store/index.d.ts +3 -1
- package/build/esm/editor/store/index.js +8 -3
- package/build/esm/editor/store/reducer.d.ts +8 -1
- package/build/esm/editor/store/reducer.js +3 -0
- package/build/esm/editor/styles/root.css +5 -0
- package/build/esm/editor/types/index.d.ts +4 -0
- package/build/esm/editor/types/index.js +5 -1
- package/package.json +1 -1
- package/build/cjs/editor/containers/Editor/Editor.css +0 -28
- package/build/esm/editor/containers/Editor/Editor.css +0 -28
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.4.0](https://github.com/gravity-ui/page-constructor/compare/v3.3.0...v3.4.0) (2023-06-16)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add editor mode switch ([#404](https://github.com/gravity-ui/page-constructor/issues/404)) ([118a369](https://github.com/gravity-ui/page-constructor/commit/118a3694459479c240ca9829c6194c1185cad4a4))
|
|
9
|
+
|
|
3
10
|
## [3.3.0](https://github.com/gravity-ui/page-constructor/compare/v3.2.0...v3.3.0) (2023-06-14)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
/* use this for style redefinitions to awoid problems with
|
|
2
2
|
unpredictable css rules order in build */
|
|
3
|
+
.pc-add-block {
|
|
4
|
+
position: fixed;
|
|
5
|
+
bottom: 32px;
|
|
6
|
+
left: calc(50% + var(--editor-left-column-width) / 2);
|
|
7
|
+
transform: translateX(-50%);
|
|
8
|
+
z-index: 110;
|
|
9
|
+
}
|
|
3
10
|
.pc-add-block__button {
|
|
4
11
|
display: inline-block;
|
|
5
12
|
margin: 0;
|
|
@@ -7,18 +7,25 @@ const dynamic_forms_1 = require("@gravity-ui/dynamic-forms");
|
|
|
7
7
|
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
8
8
|
const react_final_form_1 = require("react-final-form");
|
|
9
9
|
const config_1 = require("../../dynamic-forms-custom/config");
|
|
10
|
+
const usePreviousValue_1 = tslib_1.__importDefault(require("../../hooks/usePreviousValue"));
|
|
10
11
|
exports.BlockForm = (0, react_1.memo)((_a) => {
|
|
11
12
|
var _b = _a.data, { type } = _b, content = tslib_1.__rest(_b, ["type"]), { onChange, onSelect, active, spec: specRaw } = _a;
|
|
12
13
|
// get initial values only at first render, then the form manages data
|
|
13
14
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
14
15
|
const initialValues = (0, react_1.useMemo)(() => ({ content }), []);
|
|
16
|
+
const prevContent = (0, usePreviousValue_1.default)(content);
|
|
15
17
|
const spec = (0, react_1.useMemo)(() => (Object.assign(Object.assign({}, specRaw), { viewSpec: Object.assign(Object.assign({}, specRaw.viewSpec), { layoutOpen: active }) })), [specRaw, active]);
|
|
16
18
|
return (react_1.default.createElement(react_final_form_1.Form, { initialValues: initialValues, onSubmit: lodash_1.default.noop }, () => (react_1.default.createElement("div", { onClick: () => {
|
|
17
19
|
if (!active) {
|
|
18
20
|
onSelect();
|
|
19
21
|
}
|
|
20
22
|
} },
|
|
21
|
-
react_1.default.createElement(react_final_form_1.FormSpy, { onChange: ({ values }) =>
|
|
23
|
+
react_1.default.createElement(react_final_form_1.FormSpy, { onChange: ({ values }) => {
|
|
24
|
+
// fix for FormSpy onChange called twice without content changes
|
|
25
|
+
if (!lodash_1.default.isEqual(values.content, prevContent)) {
|
|
26
|
+
onChange(Object.assign({ type }, values.content));
|
|
27
|
+
}
|
|
28
|
+
}, subscription: { values: true } }),
|
|
22
29
|
react_1.default.createElement(dynamic_forms_1.DynamicField, { name: "content",
|
|
23
30
|
// there is no way other way to manage with form open/close state now
|
|
24
31
|
key: String(active), spec: spec, config: config_1.dynamicConfig })))));
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* use this for style redefinitions to awoid problems with
|
|
2
|
+
unpredictable css rules order in build */
|
|
3
|
+
.pc-control-panel {
|
|
4
|
+
display: flex;
|
|
5
|
+
justify-content: center;
|
|
6
|
+
width: 100%;
|
|
7
|
+
height: var(--editor-header-height);
|
|
8
|
+
padding: 8px 20px;
|
|
9
|
+
background-color: var(--yc-color-base-background);
|
|
10
|
+
border-bottom: 1px solid var(--yc-color-line-generic);
|
|
11
|
+
}
|
|
12
|
+
.pc-control-panel__icon {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
}
|
|
16
|
+
.pc-control-panel__radio-button {
|
|
17
|
+
margin-left: 12px;
|
|
18
|
+
}
|
|
19
|
+
.pc-control-panel__radio-button .yc-radio-button__option {
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
}
|
|
23
|
+
.pc-control-panel__mode-switch {
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ClassNameProps } from '../../../models';
|
|
2
|
+
import { ViewModeItem } from '../../types';
|
|
3
|
+
export interface ControlPanelProps extends ClassNameProps {
|
|
4
|
+
viewMode?: ViewModeItem;
|
|
5
|
+
onViewModeChange: (viewMode: ViewModeItem) => void;
|
|
6
|
+
}
|
|
7
|
+
declare const ControlPanel: ({ viewMode, onViewModeChange, className, }: ControlPanelProps) => JSX.Element;
|
|
8
|
+
export default ControlPanel;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const react_1 = tslib_1.__importDefault(require("react"));
|
|
5
|
+
const icons_1 = require("@gravity-ui/icons");
|
|
6
|
+
const uikit_1 = require("@gravity-ui/uikit");
|
|
7
|
+
const utils_1 = require("../../../utils");
|
|
8
|
+
const types_1 = require("../../types");
|
|
9
|
+
const i18n_1 = tslib_1.__importDefault(require("./i18n"));
|
|
10
|
+
const ICON_SIZE = 14;
|
|
11
|
+
const b = (0, utils_1.block)('control-panel');
|
|
12
|
+
const ControlPanelViewModeIcons = {
|
|
13
|
+
[types_1.ViewModeItem.Edititng]: icons_1.Pencil,
|
|
14
|
+
[types_1.ViewModeItem.View]: icons_1.Display,
|
|
15
|
+
};
|
|
16
|
+
const ControlPanel = ({ viewMode = types_1.ViewModeItem.Edititng, onViewModeChange, className, }) => (react_1.default.createElement("div", { className: b(null, className) },
|
|
17
|
+
react_1.default.createElement("div", { className: b('mode-switch') },
|
|
18
|
+
react_1.default.createElement("span", null, (0, i18n_1.default)('mode')),
|
|
19
|
+
react_1.default.createElement(uikit_1.RadioButton, { className: b('radio-button'), value: viewMode, onUpdate: (value) => onViewModeChange(value) }, Object.values(types_1.ViewModeItem).map((item) => {
|
|
20
|
+
const Icon = ControlPanelViewModeIcons[item];
|
|
21
|
+
return (react_1.default.createElement(uikit_1.RadioButton.Option, { key: item, value: item },
|
|
22
|
+
react_1.default.createElement(Icon, { className: b('icon'), width: ICON_SIZE, height: ICON_SIZE })));
|
|
23
|
+
})))));
|
|
24
|
+
exports.default = ControlPanel;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const registerKeyset_1 = require("../../../../utils/registerKeyset");
|
|
5
|
+
const en_json_1 = tslib_1.__importDefault(require("./en.json"));
|
|
6
|
+
const ru_json_1 = tslib_1.__importDefault(require("./ru.json"));
|
|
7
|
+
const COMPONENT = 'ControlPanel';
|
|
8
|
+
exports.default = (0, registerKeyset_1.registerKeyset)({ en: en_json_1.default, ru: ru_json_1.default }, COMPONENT);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* use this for style redefinitions to awoid problems with
|
|
2
|
+
unpredictable css rules order in build */
|
|
3
|
+
:root {
|
|
4
|
+
--editor-header-height: 48px;
|
|
5
|
+
--editor-divider-width: 12px;
|
|
6
|
+
--editor-left-column-width: calc(400px + var(--editor-divider-width));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.pc-editor-layout__left, .pc-editor-layout__right {
|
|
10
|
+
--yc-scrollbar-width: 0;
|
|
11
|
+
height: calc(100vh - var(--editor-header-height));
|
|
12
|
+
max-height: calc(100vh - var(--editor-header-height));
|
|
13
|
+
overflow-y: auto;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.pc-editor-layout {
|
|
17
|
+
position: relative;
|
|
18
|
+
}
|
|
19
|
+
.pc-editor-layout__panel {
|
|
20
|
+
top: 0;
|
|
21
|
+
position: sticky;
|
|
22
|
+
z-index: 2;
|
|
23
|
+
}
|
|
24
|
+
.pc-editor-layout__container {
|
|
25
|
+
position: relative;
|
|
26
|
+
display: flex;
|
|
27
|
+
justify-content: center;
|
|
28
|
+
z-index: 1;
|
|
29
|
+
}
|
|
30
|
+
.pc-editor-layout__left {
|
|
31
|
+
flex: 0 0 auto;
|
|
32
|
+
padding: 8px 20px 20px;
|
|
33
|
+
width: var(--editor-left-column-width);
|
|
34
|
+
border-right: var(--editor-divider-width) solid var(--yc-color-line-generic);
|
|
35
|
+
overflow-x: auto;
|
|
36
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React, { PropsWithChildren } from 'react';
|
|
2
|
+
import { ViewModeItem } from '../../types';
|
|
3
|
+
export interface LayoutProps {
|
|
4
|
+
mode: ViewModeItem;
|
|
5
|
+
onModeChange: (mode: ViewModeItem) => void;
|
|
6
|
+
}
|
|
7
|
+
declare const Layout: {
|
|
8
|
+
({ children, mode, onModeChange }: PropsWithChildren<LayoutProps>): JSX.Element;
|
|
9
|
+
Left: React.FC<{
|
|
10
|
+
children?: React.ReactNode;
|
|
11
|
+
}>;
|
|
12
|
+
Right: React.FC<{
|
|
13
|
+
children?: React.ReactNode;
|
|
14
|
+
}>;
|
|
15
|
+
};
|
|
16
|
+
export default Layout;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const react_1 = tslib_1.__importStar(require("react"));
|
|
5
|
+
const utils_1 = require("../../../utils");
|
|
6
|
+
const ControlPanel_1 = tslib_1.__importDefault(require("../ControlPanel/ControlPanel"));
|
|
7
|
+
const b = (0, utils_1.block)('editor-layout');
|
|
8
|
+
const Left = () => null;
|
|
9
|
+
const Right = () => null;
|
|
10
|
+
const Layout = ({ children, mode, onModeChange }) => {
|
|
11
|
+
let left, right;
|
|
12
|
+
function handleChild(child) {
|
|
13
|
+
switch (child === null || child === void 0 ? void 0 : child.type) {
|
|
14
|
+
case Left:
|
|
15
|
+
left = child === null || child === void 0 ? void 0 : child.props.children;
|
|
16
|
+
break;
|
|
17
|
+
case Right:
|
|
18
|
+
right = child === null || child === void 0 ? void 0 : child.props.children;
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (react_1.default.Children.toArray(children).length) {
|
|
23
|
+
react_1.Children.forEach(children, handleChild);
|
|
24
|
+
}
|
|
25
|
+
return (react_1.default.createElement("div", { className: b() },
|
|
26
|
+
react_1.default.createElement(ControlPanel_1.default, { viewMode: mode, onViewModeChange: onModeChange, className: b('panel') }),
|
|
27
|
+
react_1.default.createElement("div", { className: b('container') },
|
|
28
|
+
react_1.default.createElement(react_1.Fragment, null,
|
|
29
|
+
left && react_1.default.createElement("div", { className: b('left') }, left),
|
|
30
|
+
right && react_1.default.createElement("div", { className: b('right') }, right)))));
|
|
31
|
+
};
|
|
32
|
+
Layout.Left = Left;
|
|
33
|
+
Layout.Right = Right;
|
|
34
|
+
exports.default = Layout;
|
|
@@ -3,35 +3,38 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Editor = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const react_1 = tslib_1.__importStar(require("react"));
|
|
6
|
-
const utils_1 = require("../../../utils");
|
|
7
6
|
const AddBlock_1 = tslib_1.__importDefault(require("../../components/AddBlock/AddBlock"));
|
|
8
7
|
const EditBlock_1 = tslib_1.__importDefault(require("../../components/EditBlock/EditBlock"));
|
|
9
8
|
const ErrorBoundary_1 = require("../../components/ErrorBoundary/ErrorBoundary");
|
|
9
|
+
const Layout_1 = tslib_1.__importDefault(require("../../components/Layout/Layout"));
|
|
10
10
|
const useFormSpec_1 = tslib_1.__importDefault(require("../../hooks/useFormSpec"));
|
|
11
11
|
const store_1 = require("../../store");
|
|
12
|
-
const
|
|
12
|
+
const types_1 = require("../../types");
|
|
13
|
+
const utils_1 = require("../../utils");
|
|
13
14
|
const Form_1 = require("../Form/Form");
|
|
14
|
-
const b = (0, utils_1.block)('editor');
|
|
15
15
|
const Editor = (_a) => {
|
|
16
16
|
var { children, customSchema, onChange } = _a, rest = tslib_1.__rest(_a, ["children", "customSchema", "onChange"]);
|
|
17
|
-
const { content, activeBlockIndex, errorBoundaryState, onContentUpdate, onAdd, onSelect, injectEditBlockProps, } = (0, store_1.useEditorState)(rest);
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
custom
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
17
|
+
const { content, activeBlockIndex, errorBoundaryState, viewMode, onContentUpdate, onViewModeUpdate, onAdd, onSelect, injectEditBlockProps, } = (0, store_1.useEditorState)(rest);
|
|
18
|
+
const isEditingMode = viewMode === types_1.ViewModeItem.Edititng;
|
|
19
|
+
const constructorProps = (0, react_1.useMemo)(() => {
|
|
20
|
+
const custom = isEditingMode
|
|
21
|
+
? (0, utils_1.addCustomDecorator)([
|
|
22
|
+
(props) => (react_1.default.createElement(EditBlock_1.default, Object.assign({}, injectEditBlockProps(props)))),
|
|
23
|
+
// need errorBoundaryState flag to reset error on content update
|
|
24
|
+
(props) => (react_1.default.createElement(ErrorBoundary_1.ErrorBoundary, Object.assign({}, props, { key: `${(0, utils_1.getBlockId)(props)}-${errorBoundaryState}` }))),
|
|
25
|
+
], rest.custom)
|
|
26
|
+
: rest.custom;
|
|
27
|
+
return { content, custom };
|
|
28
|
+
}, [injectEditBlockProps, content, errorBoundaryState, isEditingMode, rest.custom]);
|
|
27
29
|
(0, react_1.useEffect)(() => {
|
|
28
30
|
onChange === null || onChange === void 0 ? void 0 : onChange(content);
|
|
29
31
|
}, [content, onChange]);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
const formSpecs = (0, useFormSpec_1.default)(customSchema);
|
|
33
|
+
return (react_1.default.createElement(Layout_1.default, { mode: viewMode, onModeChange: onViewModeUpdate },
|
|
34
|
+
isEditingMode && (react_1.default.createElement(Layout_1.default.Left, null,
|
|
35
|
+
react_1.default.createElement(Form_1.Form, { content: content, onChange: onContentUpdate, activeBlockIndex: activeBlockIndex, onSelect: onSelect, spec: formSpecs }))),
|
|
36
|
+
react_1.default.createElement(Layout_1.default.Right, null,
|
|
34
37
|
react_1.default.createElement(ErrorBoundary_1.ErrorBoundary, { key: errorBoundaryState }, children(constructorProps)),
|
|
35
|
-
react_1.default.createElement(AddBlock_1.default, { onAdd: onAdd
|
|
38
|
+
isEditingMode && react_1.default.createElement(AddBlock_1.default, { onAdd: onAdd }))));
|
|
36
39
|
};
|
|
37
40
|
exports.Editor = Editor;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function usePreviousValue<T>(value: T): T | undefined;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const react_1 = require("react");
|
|
4
|
+
function usePreviousValue(value) {
|
|
5
|
+
const ref = (0, react_1.useRef)();
|
|
6
|
+
(0, react_1.useEffect)(() => {
|
|
7
|
+
ref.current = value;
|
|
8
|
+
}, [value]);
|
|
9
|
+
return ref.current;
|
|
10
|
+
}
|
|
11
|
+
exports.default = usePreviousValue;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { Block, BlockDecorationProps, PageContent } from '../../models';
|
|
2
|
-
import { EditBlockProps, EditorProps } from '../types';
|
|
2
|
+
import { EditBlockProps, EditorProps, ViewModeItem } from '../types';
|
|
3
3
|
export type EditorBlockId = number | string;
|
|
4
4
|
export declare function useEditorState({ content: intialContent, custom }: Omit<EditorProps, 'children'>): {
|
|
5
5
|
activeBlockIndex: number;
|
|
6
6
|
content: PageContent;
|
|
7
7
|
errorBoundaryState: number;
|
|
8
|
+
viewMode: ViewModeItem;
|
|
8
9
|
injectEditBlockProps: ({ type, index: relativeIndex, children, }: BlockDecorationProps) => EditBlockProps;
|
|
9
10
|
onAdd: (block: Block) => void;
|
|
10
11
|
onSelect: (index: number) => void;
|
|
11
12
|
onContentUpdate: (newContent: PageContent) => void;
|
|
13
|
+
onViewModeUpdate: (newViewMode: ViewModeItem) => void;
|
|
12
14
|
};
|
|
@@ -5,13 +5,15 @@ const react_1 = require("react");
|
|
|
5
5
|
const models_1 = require("../../models");
|
|
6
6
|
const utils_1 = require("../../utils");
|
|
7
7
|
const EditBlock_1 = require("../components/EditBlock/EditBlock");
|
|
8
|
+
const types_1 = require("../types");
|
|
8
9
|
const reducer_1 = require("./reducer");
|
|
9
10
|
const utils_2 = require("./utils");
|
|
10
11
|
function useEditorState({ content: intialContent, custom }) {
|
|
11
|
-
const [{ activeBlockIndex, content, errorBoundaryState }, dispatch] = (0, react_1.useReducer)(reducer_1.reducer, {
|
|
12
|
+
const [{ activeBlockIndex, content, errorBoundaryState, viewMode }, dispatch] = (0, react_1.useReducer)(reducer_1.reducer, {
|
|
12
13
|
activeBlockIndex: 0,
|
|
13
14
|
errorBoundaryState: 0,
|
|
14
15
|
content: (0, utils_2.addEditorProps)(intialContent),
|
|
16
|
+
viewMode: types_1.ViewModeItem.Edititng,
|
|
15
17
|
});
|
|
16
18
|
return (0, react_1.useMemo)(() => {
|
|
17
19
|
const headerBlockTypes = [...models_1.HeaderBlockTypes, ...(0, utils_1.getCustomHeaderTypes)(custom)];
|
|
@@ -33,6 +35,7 @@ function useEditorState({ content: intialContent, custom }) {
|
|
|
33
35
|
};
|
|
34
36
|
const onSelect = (index) => dispatch({ type: reducer_1.SELECT_BLOCK, payload: index });
|
|
35
37
|
const onContentUpdate = (newContent) => dispatch({ type: reducer_1.UPDATE_CONTENT, payload: newContent });
|
|
38
|
+
const onViewModeUpdate = (newViewMode) => dispatch({ type: reducer_1.UPDATE_VIEW_MODE, payload: newViewMode });
|
|
36
39
|
const injectEditBlockProps = ({ type, index: relativeIndex = 0, children, }) => {
|
|
37
40
|
const orderedBlocksStartIndex = contentHasHeader ? 1 : 0;
|
|
38
41
|
const isHeader = checkIsHeader(type);
|
|
@@ -68,11 +71,13 @@ function useEditorState({ content: intialContent, custom }) {
|
|
|
68
71
|
activeBlockIndex,
|
|
69
72
|
content,
|
|
70
73
|
errorBoundaryState,
|
|
74
|
+
viewMode,
|
|
71
75
|
injectEditBlockProps,
|
|
72
76
|
onAdd,
|
|
73
77
|
onSelect,
|
|
74
78
|
onContentUpdate,
|
|
79
|
+
onViewModeUpdate,
|
|
75
80
|
};
|
|
76
|
-
}, [content, activeBlockIndex, errorBoundaryState, custom]);
|
|
81
|
+
}, [content, activeBlockIndex, errorBoundaryState, custom, viewMode]);
|
|
77
82
|
}
|
|
78
83
|
exports.useEditorState = useEditorState;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Block, PageContent } from '../../models';
|
|
2
|
+
import { ViewModeItem } from '../types';
|
|
2
3
|
export type EditorBlockId = number | string;
|
|
3
4
|
interface EditorState {
|
|
4
5
|
content: PageContent;
|
|
5
6
|
activeBlockIndex: number;
|
|
6
7
|
errorBoundaryState: number;
|
|
8
|
+
viewMode: ViewModeItem;
|
|
7
9
|
}
|
|
8
10
|
interface OrderBlockParams {
|
|
9
11
|
oldIndex: number;
|
|
@@ -20,6 +22,7 @@ export declare const ADD_BLOCK = "ADD_BLOCK";
|
|
|
20
22
|
export declare const SET_REGION = "SET_REGION";
|
|
21
23
|
export declare const ORDER_BLOCK = "ORDER_BLOCK";
|
|
22
24
|
export declare const UPDATE_CONTENT = "UPDATE_CONTENT";
|
|
25
|
+
export declare const UPDATE_VIEW_MODE = "UPDATE_VIEW_MODE";
|
|
23
26
|
interface SelectBlock {
|
|
24
27
|
type: typeof SELECT_BLOCK;
|
|
25
28
|
payload: number;
|
|
@@ -44,6 +47,10 @@ interface UpdateContent {
|
|
|
44
47
|
type: typeof UPDATE_CONTENT;
|
|
45
48
|
payload: PageContent;
|
|
46
49
|
}
|
|
47
|
-
|
|
50
|
+
interface UpdateViewMode {
|
|
51
|
+
type: typeof UPDATE_VIEW_MODE;
|
|
52
|
+
payload: ViewModeItem;
|
|
53
|
+
}
|
|
54
|
+
export type EditorAction = SelectBlock | DeleteBlock | CopyBlock | AddBlock | OrderBlock | UpdateContent | UpdateViewMode;
|
|
48
55
|
export declare const reducer: (state: EditorState, action: EditorAction) => EditorState;
|
|
49
56
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.reducer = exports.UPDATE_CONTENT = exports.ORDER_BLOCK = exports.SET_REGION = exports.ADD_BLOCK = exports.COPY_BLOCK = exports.DELETE_BLOCK = exports.SELECT_BLOCK = void 0;
|
|
3
|
+
exports.reducer = exports.UPDATE_VIEW_MODE = exports.UPDATE_CONTENT = exports.ORDER_BLOCK = exports.SET_REGION = exports.ADD_BLOCK = exports.COPY_BLOCK = exports.DELETE_BLOCK = exports.SELECT_BLOCK = void 0;
|
|
4
4
|
const utils_1 = require("./utils");
|
|
5
5
|
// actions
|
|
6
6
|
exports.SELECT_BLOCK = 'SELECT_BLOCK';
|
|
@@ -10,6 +10,7 @@ exports.ADD_BLOCK = 'ADD_BLOCK';
|
|
|
10
10
|
exports.SET_REGION = 'SET_REGION';
|
|
11
11
|
exports.ORDER_BLOCK = 'ORDER_BLOCK';
|
|
12
12
|
exports.UPDATE_CONTENT = 'UPDATE_CONTENT';
|
|
13
|
+
exports.UPDATE_VIEW_MODE = 'UPDATE_VIEW_MODE';
|
|
13
14
|
// reducer
|
|
14
15
|
const reducer = (state, action) => {
|
|
15
16
|
const { content } = state;
|
|
@@ -35,6 +36,8 @@ const reducer = (state, action) => {
|
|
|
35
36
|
const { oldIndex, newIndex } = action.payload;
|
|
36
37
|
return getNewState((0, utils_1.changeBlocksOrder)(content.blocks, oldIndex, newIndex), newIndex);
|
|
37
38
|
}
|
|
39
|
+
case exports.UPDATE_VIEW_MODE:
|
|
40
|
+
return Object.assign(Object.assign({}, state), { viewMode: action.payload });
|
|
38
41
|
default:
|
|
39
42
|
return state;
|
|
40
43
|
}
|
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ViewModeItem = void 0;
|
|
4
|
+
var ViewModeItem;
|
|
5
|
+
(function (ViewModeItem) {
|
|
6
|
+
ViewModeItem["Edititng"] = "editing";
|
|
7
|
+
ViewModeItem["View"] = "view";
|
|
8
|
+
})(ViewModeItem = exports.ViewModeItem || (exports.ViewModeItem = {}));
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
/* use this for style redefinitions to awoid problems with
|
|
2
2
|
unpredictable css rules order in build */
|
|
3
|
+
.pc-add-block {
|
|
4
|
+
position: fixed;
|
|
5
|
+
bottom: 32px;
|
|
6
|
+
left: calc(50% + var(--editor-left-column-width) / 2);
|
|
7
|
+
transform: translateX(-50%);
|
|
8
|
+
z-index: 110;
|
|
9
|
+
}
|
|
3
10
|
.pc-add-block__button {
|
|
4
11
|
display: inline-block;
|
|
5
12
|
margin: 0;
|
|
@@ -4,18 +4,25 @@ import { DynamicField } from '@gravity-ui/dynamic-forms';
|
|
|
4
4
|
import _ from 'lodash';
|
|
5
5
|
import { Form as FinalForm, FormSpy } from 'react-final-form';
|
|
6
6
|
import { dynamicConfig } from '../../dynamic-forms-custom/config';
|
|
7
|
+
import usePreviousValue from '../../hooks/usePreviousValue';
|
|
7
8
|
export const BlockForm = memo((_a) => {
|
|
8
9
|
var _b = _a.data, { type } = _b, content = __rest(_b, ["type"]), { onChange, onSelect, active, spec: specRaw } = _a;
|
|
9
10
|
// get initial values only at first render, then the form manages data
|
|
10
11
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11
12
|
const initialValues = useMemo(() => ({ content }), []);
|
|
13
|
+
const prevContent = usePreviousValue(content);
|
|
12
14
|
const spec = useMemo(() => (Object.assign(Object.assign({}, specRaw), { viewSpec: Object.assign(Object.assign({}, specRaw.viewSpec), { layoutOpen: active }) })), [specRaw, active]);
|
|
13
15
|
return (React.createElement(FinalForm, { initialValues: initialValues, onSubmit: _.noop }, () => (React.createElement("div", { onClick: () => {
|
|
14
16
|
if (!active) {
|
|
15
17
|
onSelect();
|
|
16
18
|
}
|
|
17
19
|
} },
|
|
18
|
-
React.createElement(FormSpy, { onChange: ({ values }) =>
|
|
20
|
+
React.createElement(FormSpy, { onChange: ({ values }) => {
|
|
21
|
+
// fix for FormSpy onChange called twice without content changes
|
|
22
|
+
if (!_.isEqual(values.content, prevContent)) {
|
|
23
|
+
onChange(Object.assign({ type }, values.content));
|
|
24
|
+
}
|
|
25
|
+
}, subscription: { values: true } }),
|
|
19
26
|
React.createElement(DynamicField, { name: "content",
|
|
20
27
|
// there is no way other way to manage with form open/close state now
|
|
21
28
|
key: String(active), spec: spec, config: dynamicConfig })))));
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* use this for style redefinitions to awoid problems with
|
|
2
|
+
unpredictable css rules order in build */
|
|
3
|
+
.pc-control-panel {
|
|
4
|
+
display: flex;
|
|
5
|
+
justify-content: center;
|
|
6
|
+
width: 100%;
|
|
7
|
+
height: var(--editor-header-height);
|
|
8
|
+
padding: 8px 20px;
|
|
9
|
+
background-color: var(--yc-color-base-background);
|
|
10
|
+
border-bottom: 1px solid var(--yc-color-line-generic);
|
|
11
|
+
}
|
|
12
|
+
.pc-control-panel__icon {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
}
|
|
16
|
+
.pc-control-panel__radio-button {
|
|
17
|
+
margin-left: 12px;
|
|
18
|
+
}
|
|
19
|
+
.pc-control-panel__radio-button .yc-radio-button__option {
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
}
|
|
23
|
+
.pc-control-panel__mode-switch {
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ClassNameProps } from '../../../models';
|
|
2
|
+
import { ViewModeItem } from '../../types';
|
|
3
|
+
import './ControlPanel.css';
|
|
4
|
+
export interface ControlPanelProps extends ClassNameProps {
|
|
5
|
+
viewMode?: ViewModeItem;
|
|
6
|
+
onViewModeChange: (viewMode: ViewModeItem) => void;
|
|
7
|
+
}
|
|
8
|
+
declare const ControlPanel: ({ viewMode, onViewModeChange, className, }: ControlPanelProps) => JSX.Element;
|
|
9
|
+
export default ControlPanel;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Display, Pencil } from '@gravity-ui/icons';
|
|
3
|
+
import { RadioButton } from '@gravity-ui/uikit';
|
|
4
|
+
import { block } from '../../../utils';
|
|
5
|
+
import { ViewModeItem } from '../../types';
|
|
6
|
+
import i18n from './i18n';
|
|
7
|
+
const ICON_SIZE = 14;
|
|
8
|
+
import './ControlPanel.css';
|
|
9
|
+
const b = block('control-panel');
|
|
10
|
+
const ControlPanelViewModeIcons = {
|
|
11
|
+
[ViewModeItem.Edititng]: Pencil,
|
|
12
|
+
[ViewModeItem.View]: Display,
|
|
13
|
+
};
|
|
14
|
+
const ControlPanel = ({ viewMode = ViewModeItem.Edititng, onViewModeChange, className, }) => (React.createElement("div", { className: b(null, className) },
|
|
15
|
+
React.createElement("div", { className: b('mode-switch') },
|
|
16
|
+
React.createElement("span", null, i18n('mode')),
|
|
17
|
+
React.createElement(RadioButton, { className: b('radio-button'), value: viewMode, onUpdate: (value) => onViewModeChange(value) }, Object.values(ViewModeItem).map((item) => {
|
|
18
|
+
const Icon = ControlPanelViewModeIcons[item];
|
|
19
|
+
return (React.createElement(RadioButton.Option, { key: item, value: item },
|
|
20
|
+
React.createElement(Icon, { className: b('icon'), width: ICON_SIZE, height: ICON_SIZE })));
|
|
21
|
+
})))));
|
|
22
|
+
export default ControlPanel;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* use this for style redefinitions to awoid problems with
|
|
2
|
+
unpredictable css rules order in build */
|
|
3
|
+
:root {
|
|
4
|
+
--editor-header-height: 48px;
|
|
5
|
+
--editor-divider-width: 12px;
|
|
6
|
+
--editor-left-column-width: calc(400px + var(--editor-divider-width));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.pc-editor-layout__left, .pc-editor-layout__right {
|
|
10
|
+
--yc-scrollbar-width: 0;
|
|
11
|
+
height: calc(100vh - var(--editor-header-height));
|
|
12
|
+
max-height: calc(100vh - var(--editor-header-height));
|
|
13
|
+
overflow-y: auto;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.pc-editor-layout {
|
|
17
|
+
position: relative;
|
|
18
|
+
}
|
|
19
|
+
.pc-editor-layout__panel {
|
|
20
|
+
top: 0;
|
|
21
|
+
position: sticky;
|
|
22
|
+
z-index: 2;
|
|
23
|
+
}
|
|
24
|
+
.pc-editor-layout__container {
|
|
25
|
+
position: relative;
|
|
26
|
+
display: flex;
|
|
27
|
+
justify-content: center;
|
|
28
|
+
z-index: 1;
|
|
29
|
+
}
|
|
30
|
+
.pc-editor-layout__left {
|
|
31
|
+
flex: 0 0 auto;
|
|
32
|
+
padding: 8px 20px 20px;
|
|
33
|
+
width: var(--editor-left-column-width);
|
|
34
|
+
border-right: var(--editor-divider-width) solid var(--yc-color-line-generic);
|
|
35
|
+
overflow-x: auto;
|
|
36
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React, { PropsWithChildren } from 'react';
|
|
2
|
+
import { ViewModeItem } from '../../types';
|
|
3
|
+
import './Layout.css';
|
|
4
|
+
export interface LayoutProps {
|
|
5
|
+
mode: ViewModeItem;
|
|
6
|
+
onModeChange: (mode: ViewModeItem) => void;
|
|
7
|
+
}
|
|
8
|
+
declare const Layout: {
|
|
9
|
+
({ children, mode, onModeChange }: PropsWithChildren<LayoutProps>): JSX.Element;
|
|
10
|
+
Left: React.FC<{
|
|
11
|
+
children?: React.ReactNode;
|
|
12
|
+
}>;
|
|
13
|
+
Right: React.FC<{
|
|
14
|
+
children?: React.ReactNode;
|
|
15
|
+
}>;
|
|
16
|
+
};
|
|
17
|
+
export default Layout;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React, { Children, Fragment } from 'react';
|
|
2
|
+
import { block } from '../../../utils';
|
|
3
|
+
import ControlPanel from '../ControlPanel/ControlPanel';
|
|
4
|
+
import './Layout.css';
|
|
5
|
+
const b = block('editor-layout');
|
|
6
|
+
const Left = () => null;
|
|
7
|
+
const Right = () => null;
|
|
8
|
+
const Layout = ({ children, mode, onModeChange }) => {
|
|
9
|
+
let left, right;
|
|
10
|
+
function handleChild(child) {
|
|
11
|
+
switch (child === null || child === void 0 ? void 0 : child.type) {
|
|
12
|
+
case Left:
|
|
13
|
+
left = child === null || child === void 0 ? void 0 : child.props.children;
|
|
14
|
+
break;
|
|
15
|
+
case Right:
|
|
16
|
+
right = child === null || child === void 0 ? void 0 : child.props.children;
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (React.Children.toArray(children).length) {
|
|
21
|
+
Children.forEach(children, handleChild);
|
|
22
|
+
}
|
|
23
|
+
return (React.createElement("div", { className: b() },
|
|
24
|
+
React.createElement(ControlPanel, { viewMode: mode, onViewModeChange: onModeChange, className: b('panel') }),
|
|
25
|
+
React.createElement("div", { className: b('container') },
|
|
26
|
+
React.createElement(Fragment, null,
|
|
27
|
+
left && React.createElement("div", { className: b('left') }, left),
|
|
28
|
+
right && React.createElement("div", { className: b('right') }, right)))));
|
|
29
|
+
};
|
|
30
|
+
Layout.Left = Left;
|
|
31
|
+
Layout.Right = Right;
|
|
32
|
+
export default Layout;
|
|
@@ -1,34 +1,36 @@
|
|
|
1
1
|
import { __rest } from "tslib";
|
|
2
2
|
import React, { useEffect, useMemo } from 'react';
|
|
3
|
-
import { block } from '../../../utils';
|
|
4
3
|
import AddBlock from '../../components/AddBlock/AddBlock';
|
|
5
4
|
import EditBlock from '../../components/EditBlock/EditBlock';
|
|
6
5
|
import { ErrorBoundary } from '../../components/ErrorBoundary/ErrorBoundary';
|
|
6
|
+
import Layout from '../../components/Layout/Layout';
|
|
7
7
|
import useFormSpec from '../../hooks/useFormSpec';
|
|
8
8
|
import { useEditorState } from '../../store';
|
|
9
|
+
import { ViewModeItem } from '../../types';
|
|
9
10
|
import { addCustomDecorator, getBlockId } from '../../utils';
|
|
10
11
|
import { Form } from '../Form/Form';
|
|
11
|
-
import './Editor.css';
|
|
12
|
-
const b = block('editor');
|
|
13
12
|
export const Editor = (_a) => {
|
|
14
13
|
var { children, customSchema, onChange } = _a, rest = __rest(_a, ["children", "customSchema", "onChange"]);
|
|
15
|
-
const { content, activeBlockIndex, errorBoundaryState, onContentUpdate, onAdd, onSelect, injectEditBlockProps, } = useEditorState(rest);
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
custom
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
const { content, activeBlockIndex, errorBoundaryState, viewMode, onContentUpdate, onViewModeUpdate, onAdd, onSelect, injectEditBlockProps, } = useEditorState(rest);
|
|
15
|
+
const isEditingMode = viewMode === ViewModeItem.Edititng;
|
|
16
|
+
const constructorProps = useMemo(() => {
|
|
17
|
+
const custom = isEditingMode
|
|
18
|
+
? addCustomDecorator([
|
|
19
|
+
(props) => (React.createElement(EditBlock, Object.assign({}, injectEditBlockProps(props)))),
|
|
20
|
+
// need errorBoundaryState flag to reset error on content update
|
|
21
|
+
(props) => (React.createElement(ErrorBoundary, Object.assign({}, props, { key: `${getBlockId(props)}-${errorBoundaryState}` }))),
|
|
22
|
+
], rest.custom)
|
|
23
|
+
: rest.custom;
|
|
24
|
+
return { content, custom };
|
|
25
|
+
}, [injectEditBlockProps, content, errorBoundaryState, isEditingMode, rest.custom]);
|
|
25
26
|
useEffect(() => {
|
|
26
27
|
onChange === null || onChange === void 0 ? void 0 : onChange(content);
|
|
27
28
|
}, [content, onChange]);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
const formSpecs = useFormSpec(customSchema);
|
|
30
|
+
return (React.createElement(Layout, { mode: viewMode, onModeChange: onViewModeUpdate },
|
|
31
|
+
isEditingMode && (React.createElement(Layout.Left, null,
|
|
32
|
+
React.createElement(Form, { content: content, onChange: onContentUpdate, activeBlockIndex: activeBlockIndex, onSelect: onSelect, spec: formSpecs }))),
|
|
33
|
+
React.createElement(Layout.Right, null,
|
|
32
34
|
React.createElement(ErrorBoundary, { key: errorBoundaryState }, children(constructorProps)),
|
|
33
|
-
React.createElement(AddBlock, { onAdd: onAdd
|
|
35
|
+
isEditingMode && React.createElement(AddBlock, { onAdd: onAdd }))));
|
|
34
36
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function usePreviousValue<T>(value: T): T | undefined;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { Block, BlockDecorationProps, PageContent } from '../../models';
|
|
2
|
-
import { EditBlockProps, EditorProps } from '../types';
|
|
2
|
+
import { EditBlockProps, EditorProps, ViewModeItem } from '../types';
|
|
3
3
|
export type EditorBlockId = number | string;
|
|
4
4
|
export declare function useEditorState({ content: intialContent, custom }: Omit<EditorProps, 'children'>): {
|
|
5
5
|
activeBlockIndex: number;
|
|
6
6
|
content: PageContent;
|
|
7
7
|
errorBoundaryState: number;
|
|
8
|
+
viewMode: ViewModeItem;
|
|
8
9
|
injectEditBlockProps: ({ type, index: relativeIndex, children, }: BlockDecorationProps) => EditBlockProps;
|
|
9
10
|
onAdd: (block: Block) => void;
|
|
10
11
|
onSelect: (index: number) => void;
|
|
11
12
|
onContentUpdate: (newContent: PageContent) => void;
|
|
13
|
+
onViewModeUpdate: (newViewMode: ViewModeItem) => void;
|
|
12
14
|
};
|
|
@@ -2,13 +2,15 @@ import { useMemo, useReducer } from 'react';
|
|
|
2
2
|
import { HeaderBlockTypes } from '../../models';
|
|
3
3
|
import { getCustomHeaderTypes, getHeaderBlock } from '../../utils';
|
|
4
4
|
import { EditBlockControls } from '../components/EditBlock/EditBlock';
|
|
5
|
-
import {
|
|
5
|
+
import { ViewModeItem } from '../types';
|
|
6
|
+
import { ADD_BLOCK, COPY_BLOCK, DELETE_BLOCK, ORDER_BLOCK, SELECT_BLOCK, UPDATE_CONTENT, UPDATE_VIEW_MODE, reducer, } from './reducer';
|
|
6
7
|
import { addEditorProps } from './utils';
|
|
7
8
|
export function useEditorState({ content: intialContent, custom }) {
|
|
8
|
-
const [{ activeBlockIndex, content, errorBoundaryState }, dispatch] = useReducer(reducer, {
|
|
9
|
+
const [{ activeBlockIndex, content, errorBoundaryState, viewMode }, dispatch] = useReducer(reducer, {
|
|
9
10
|
activeBlockIndex: 0,
|
|
10
11
|
errorBoundaryState: 0,
|
|
11
12
|
content: addEditorProps(intialContent),
|
|
13
|
+
viewMode: ViewModeItem.Edititng,
|
|
12
14
|
});
|
|
13
15
|
return useMemo(() => {
|
|
14
16
|
const headerBlockTypes = [...HeaderBlockTypes, ...getCustomHeaderTypes(custom)];
|
|
@@ -30,6 +32,7 @@ export function useEditorState({ content: intialContent, custom }) {
|
|
|
30
32
|
};
|
|
31
33
|
const onSelect = (index) => dispatch({ type: SELECT_BLOCK, payload: index });
|
|
32
34
|
const onContentUpdate = (newContent) => dispatch({ type: UPDATE_CONTENT, payload: newContent });
|
|
35
|
+
const onViewModeUpdate = (newViewMode) => dispatch({ type: UPDATE_VIEW_MODE, payload: newViewMode });
|
|
33
36
|
const injectEditBlockProps = ({ type, index: relativeIndex = 0, children, }) => {
|
|
34
37
|
const orderedBlocksStartIndex = contentHasHeader ? 1 : 0;
|
|
35
38
|
const isHeader = checkIsHeader(type);
|
|
@@ -65,10 +68,12 @@ export function useEditorState({ content: intialContent, custom }) {
|
|
|
65
68
|
activeBlockIndex,
|
|
66
69
|
content,
|
|
67
70
|
errorBoundaryState,
|
|
71
|
+
viewMode,
|
|
68
72
|
injectEditBlockProps,
|
|
69
73
|
onAdd,
|
|
70
74
|
onSelect,
|
|
71
75
|
onContentUpdate,
|
|
76
|
+
onViewModeUpdate,
|
|
72
77
|
};
|
|
73
|
-
}, [content, activeBlockIndex, errorBoundaryState, custom]);
|
|
78
|
+
}, [content, activeBlockIndex, errorBoundaryState, custom, viewMode]);
|
|
74
79
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Block, PageContent } from '../../models';
|
|
2
|
+
import { ViewModeItem } from '../types';
|
|
2
3
|
export type EditorBlockId = number | string;
|
|
3
4
|
interface EditorState {
|
|
4
5
|
content: PageContent;
|
|
5
6
|
activeBlockIndex: number;
|
|
6
7
|
errorBoundaryState: number;
|
|
8
|
+
viewMode: ViewModeItem;
|
|
7
9
|
}
|
|
8
10
|
interface OrderBlockParams {
|
|
9
11
|
oldIndex: number;
|
|
@@ -20,6 +22,7 @@ export declare const ADD_BLOCK = "ADD_BLOCK";
|
|
|
20
22
|
export declare const SET_REGION = "SET_REGION";
|
|
21
23
|
export declare const ORDER_BLOCK = "ORDER_BLOCK";
|
|
22
24
|
export declare const UPDATE_CONTENT = "UPDATE_CONTENT";
|
|
25
|
+
export declare const UPDATE_VIEW_MODE = "UPDATE_VIEW_MODE";
|
|
23
26
|
interface SelectBlock {
|
|
24
27
|
type: typeof SELECT_BLOCK;
|
|
25
28
|
payload: number;
|
|
@@ -44,6 +47,10 @@ interface UpdateContent {
|
|
|
44
47
|
type: typeof UPDATE_CONTENT;
|
|
45
48
|
payload: PageContent;
|
|
46
49
|
}
|
|
47
|
-
|
|
50
|
+
interface UpdateViewMode {
|
|
51
|
+
type: typeof UPDATE_VIEW_MODE;
|
|
52
|
+
payload: ViewModeItem;
|
|
53
|
+
}
|
|
54
|
+
export type EditorAction = SelectBlock | DeleteBlock | CopyBlock | AddBlock | OrderBlock | UpdateContent | UpdateViewMode;
|
|
48
55
|
export declare const reducer: (state: EditorState, action: EditorAction) => EditorState;
|
|
49
56
|
export {};
|
|
@@ -7,6 +7,7 @@ export const ADD_BLOCK = 'ADD_BLOCK';
|
|
|
7
7
|
export const SET_REGION = 'SET_REGION';
|
|
8
8
|
export const ORDER_BLOCK = 'ORDER_BLOCK';
|
|
9
9
|
export const UPDATE_CONTENT = 'UPDATE_CONTENT';
|
|
10
|
+
export const UPDATE_VIEW_MODE = 'UPDATE_VIEW_MODE';
|
|
10
11
|
// reducer
|
|
11
12
|
export const reducer = (state, action) => {
|
|
12
13
|
const { content } = state;
|
|
@@ -32,6 +33,8 @@ export const reducer = (state, action) => {
|
|
|
32
33
|
const { oldIndex, newIndex } = action.payload;
|
|
33
34
|
return getNewState(changeBlocksOrder(content.blocks, oldIndex, newIndex), newIndex);
|
|
34
35
|
}
|
|
36
|
+
case UPDATE_VIEW_MODE:
|
|
37
|
+
return Object.assign(Object.assign({}, state), { viewMode: action.payload });
|
|
35
38
|
default:
|
|
36
39
|
return state;
|
|
37
40
|
}
|
package/package.json
CHANGED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/* use this for style redefinitions to awoid problems with
|
|
2
|
-
unpredictable css rules order in build */
|
|
3
|
-
.pc-editor__form, .pc-editor__preview {
|
|
4
|
-
--yc-scrollbar-width: 0;
|
|
5
|
-
height: 100vh;
|
|
6
|
-
max-height: 100vh;
|
|
7
|
-
overflow: auto;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
.pc-editor {
|
|
11
|
-
display: flex;
|
|
12
|
-
}
|
|
13
|
-
.pc-editor__form {
|
|
14
|
-
flex: 0 0 auto;
|
|
15
|
-
padding: 20px;
|
|
16
|
-
width: 412px;
|
|
17
|
-
border-right: 12px solid var(--yc-color-line-generic);
|
|
18
|
-
}
|
|
19
|
-
.pc-editor__preview {
|
|
20
|
-
width: 100%;
|
|
21
|
-
}
|
|
22
|
-
.pc-editor__add-button {
|
|
23
|
-
position: fixed;
|
|
24
|
-
bottom: 32px;
|
|
25
|
-
left: calc(50% + 206px);
|
|
26
|
-
transform: translateX(-50%);
|
|
27
|
-
z-index: 110;
|
|
28
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/* use this for style redefinitions to awoid problems with
|
|
2
|
-
unpredictable css rules order in build */
|
|
3
|
-
.pc-editor__form, .pc-editor__preview {
|
|
4
|
-
--yc-scrollbar-width: 0;
|
|
5
|
-
height: 100vh;
|
|
6
|
-
max-height: 100vh;
|
|
7
|
-
overflow: auto;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
.pc-editor {
|
|
11
|
-
display: flex;
|
|
12
|
-
}
|
|
13
|
-
.pc-editor__form {
|
|
14
|
-
flex: 0 0 auto;
|
|
15
|
-
padding: 20px;
|
|
16
|
-
width: 412px;
|
|
17
|
-
border-right: 12px solid var(--yc-color-line-generic);
|
|
18
|
-
}
|
|
19
|
-
.pc-editor__preview {
|
|
20
|
-
width: 100%;
|
|
21
|
-
}
|
|
22
|
-
.pc-editor__add-button {
|
|
23
|
-
position: fixed;
|
|
24
|
-
bottom: 32px;
|
|
25
|
-
left: calc(50% + 206px);
|
|
26
|
-
transform: translateX(-50%);
|
|
27
|
-
z-index: 110;
|
|
28
|
-
}
|