@gravity-ui/page-constructor 5.14.4-alpha.1 → 5.14.4-alpha.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.
- package/build/cjs/editor-v2/components/BigOverlay/BigOverlay.js +6 -3
- package/build/cjs/editor-v2/components/MiddleScreen/MiddleScreen.css +5 -3
- package/build/cjs/editor-v2/components/MiddleScreen/MiddleScreen.js +16 -11
- package/build/cjs/editor-v2/components/SourceCode/SourceCode.css +18 -6
- package/build/cjs/editor-v2/components/SourceCode/SourceCode.js +26 -5
- package/build/cjs/editor-v2/components/TopBar/TopBar.d.ts +4 -0
- package/build/cjs/editor-v2/components/TopBar/TopBar.js +2 -2
- package/build/cjs/editor-v2/components/ViewSwitches/ViewSwitches.css +7 -0
- package/build/cjs/editor-v2/components/ViewSwitches/ViewSwitches.d.ts +4 -2
- package/build/cjs/editor-v2/components/ViewSwitches/ViewSwitches.js +11 -14
- package/build/cjs/editor-v2/constants.d.ts +1 -0
- package/build/cjs/editor-v2/constants.js +4 -0
- package/build/cjs/editor-v2/context/iframeContext/store.d.ts +4 -0
- package/build/cjs/editor-v2/context/iframeContext/store.js +27 -1
- package/build/esm/editor-v2/components/BigOverlay/BigOverlay.js +7 -4
- package/build/esm/editor-v2/components/MiddleScreen/MiddleScreen.css +5 -3
- package/build/esm/editor-v2/components/MiddleScreen/MiddleScreen.js +16 -11
- package/build/esm/editor-v2/components/SourceCode/SourceCode.css +18 -6
- package/build/esm/editor-v2/components/SourceCode/SourceCode.js +27 -6
- package/build/esm/editor-v2/components/TopBar/TopBar.d.ts +4 -0
- package/build/esm/editor-v2/components/TopBar/TopBar.js +2 -2
- package/build/esm/editor-v2/components/ViewSwitches/ViewSwitches.css +7 -0
- package/build/esm/editor-v2/components/ViewSwitches/ViewSwitches.d.ts +4 -2
- package/build/esm/editor-v2/components/ViewSwitches/ViewSwitches.js +13 -15
- package/build/esm/editor-v2/constants.d.ts +1 -0
- package/build/esm/editor-v2/constants.js +1 -0
- package/build/esm/editor-v2/context/iframeContext/store.d.ts +4 -0
- package/build/esm/editor-v2/context/iframeContext/store.js +27 -1
- package/package.json +1 -1
|
@@ -9,6 +9,7 @@ const iframeContext_1 = require("../../context/iframeContext");
|
|
|
9
9
|
const messagesContext_1 = require("../../context/messagesContext");
|
|
10
10
|
const b = (0, utils_1.block)('big-overlay');
|
|
11
11
|
const BigOverlay = ({ className }) => {
|
|
12
|
+
const { zoom } = (0, iframeContext_1.useIframeStore)();
|
|
12
13
|
const { iframeElement } = (0, react_1.useContext)(iframeContext_1.IframeContext);
|
|
13
14
|
const [mousePosition, setMousePosition] = (0, react_1.useState)(undefined);
|
|
14
15
|
(0, messagesContext_1.useMessageObserver)(types_1.ActionTypes.OverlayModeOnMove, (payload, meta) => {
|
|
@@ -16,12 +17,14 @@ const BigOverlay = ({ className }) => {
|
|
|
16
17
|
const { x, y } = payload.cursor;
|
|
17
18
|
const iframeRect = iframeElement === null || iframeElement === void 0 ? void 0 : iframeElement.getClientRects().item(0);
|
|
18
19
|
if (iframeRect) {
|
|
19
|
-
const
|
|
20
|
-
const
|
|
20
|
+
const zoomedX = (x * zoom) / 100;
|
|
21
|
+
const zoomedY = (y * zoom) / 100;
|
|
22
|
+
const newX = meta.source === 'editor' ? x : zoomedX + iframeRect.x;
|
|
23
|
+
const newY = meta.source === 'editor' ? y : zoomedY + iframeRect.y;
|
|
21
24
|
setMousePosition({ x: newX, y: newY });
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
|
-
}, [iframeElement]);
|
|
27
|
+
}, [iframeElement, zoom]);
|
|
25
28
|
(0, messagesContext_1.useMessageObserver)(types_1.ActionTypes.InsertModeDisable, () => {
|
|
26
29
|
setMousePosition(undefined);
|
|
27
30
|
});
|
|
@@ -17,11 +17,13 @@ body {
|
|
|
17
17
|
flex-direction: column;
|
|
18
18
|
}
|
|
19
19
|
.pc-middle-screen__topbar {
|
|
20
|
-
height:
|
|
20
|
+
height: 40px;
|
|
21
21
|
}
|
|
22
|
-
.pc-middle-
|
|
22
|
+
.pc-middle-screen__wrapper {
|
|
23
23
|
height: 100%;
|
|
24
|
-
|
|
24
|
+
}
|
|
25
|
+
.pc-middle-screen__canvas {
|
|
26
|
+
transform-origin: left top;
|
|
25
27
|
overflow-y: scroll;
|
|
26
28
|
position: relative;
|
|
27
29
|
}
|
|
@@ -10,20 +10,25 @@ const Overlay_1 = tslib_1.__importDefault(require("../Overlay/Overlay"));
|
|
|
10
10
|
const TopBar_1 = tslib_1.__importDefault(require("../TopBar/TopBar"));
|
|
11
11
|
const b = (0, utils_1.block)('middle-screen');
|
|
12
12
|
const MiddleScreen = ({ className }) => {
|
|
13
|
-
const { url, height } = (0, iframeContext_1.useIframeStore)();
|
|
13
|
+
const { url, height, zoom, decreaseZoom, increaseZoom, setZoom } = (0, iframeContext_1.useIframeStore)();
|
|
14
14
|
const { initialized } = (0, editorContext_1.useEditorStore)();
|
|
15
15
|
const { setIframeElement } = (0, react_1.useContext)(iframeContext_1.IframeContext);
|
|
16
16
|
return (react_1.default.createElement("div", { className: b(null, className) },
|
|
17
17
|
react_1.default.createElement("div", { className: b('topbar') },
|
|
18
|
-
react_1.default.createElement(TopBar_1.default,
|
|
19
|
-
react_1.default.createElement("div", { className: b('
|
|
20
|
-
react_1.default.createElement("
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
react_1.default.createElement(TopBar_1.default, { onZoomUpdate: setZoom, zoom: zoom, onDecreaseZoom: decreaseZoom, onIncreaseZoom: increaseZoom })),
|
|
19
|
+
react_1.default.createElement("div", { className: b('wrapper') },
|
|
20
|
+
react_1.default.createElement("div", { className: b('canvas', { hidden: !initialized }), style: {
|
|
21
|
+
transform: `scale(${zoom}%)`,
|
|
22
|
+
height: `${(100 / zoom) * 100}%`,
|
|
23
|
+
width: `${(100 / zoom) * 100}%`,
|
|
24
|
+
} },
|
|
25
|
+
react_1.default.createElement("iframe", { ref: (element) => {
|
|
26
|
+
if (element) {
|
|
27
|
+
setIframeElement(element);
|
|
28
|
+
}
|
|
29
|
+
}, className: b('iframe'), src: url, height: `${height}px`, width: "100%", frameBorder: "0" }),
|
|
30
|
+
react_1.default.createElement(Overlay_1.default, { className: b('overlay') }),
|
|
31
|
+
!initialized && (react_1.default.createElement("div", { className: b('loading') },
|
|
32
|
+
react_1.default.createElement(uikit_1.Loader, { size: 'l' })))))));
|
|
28
33
|
};
|
|
29
34
|
exports.default = MiddleScreen;
|
|
@@ -11,22 +11,34 @@ body {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
.pc-source-code {
|
|
14
|
-
|
|
14
|
+
height: 100%;
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
gap: 10px;
|
|
19
|
+
}
|
|
20
|
+
.pc-source-code__code {
|
|
15
21
|
white-space: pre;
|
|
16
22
|
font-family: var(--g-font-family-monospace);
|
|
17
23
|
font-size: var(--g-text-code-inline-1-font-size);
|
|
18
24
|
line-height: var(--g-text-code-inline-1-line-height);
|
|
19
25
|
font-weight: var(--g-text-code-font-weight);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
gap: 10px;
|
|
26
|
+
padding: 0 10px 10px;
|
|
27
|
+
overflow: auto;
|
|
23
28
|
}
|
|
24
|
-
.pc-source-
|
|
25
|
-
|
|
29
|
+
.pc-source-code__head {
|
|
30
|
+
display: flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: flex-start;
|
|
33
|
+
gap: 8px;
|
|
34
|
+
padding: 10px 10px 0;
|
|
26
35
|
}
|
|
27
36
|
.pc-source-code__textarea textarea {
|
|
28
37
|
font-family: var(--g-font-family-monospace);
|
|
29
38
|
font-size: var(--g-text-code-inline-1-font-size);
|
|
30
39
|
line-height: var(--g-text-code-inline-1-line-height);
|
|
31
40
|
font-weight: var(--g-text-code-font-weight);
|
|
41
|
+
}
|
|
42
|
+
.pc-source-code__alert {
|
|
43
|
+
margin-bottom: 8px;
|
|
32
44
|
}
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const react_1 = tslib_1.__importStar(require("react"));
|
|
5
|
+
const icons_1 = require("@gravity-ui/icons");
|
|
5
6
|
const uikit_1 = require("@gravity-ui/uikit");
|
|
7
|
+
const js_yaml_1 = tslib_1.__importDefault(require("js-yaml"));
|
|
6
8
|
const utils_1 = require("../../../utils");
|
|
7
9
|
const useContentConfigStore_1 = require("../../context/contentConfig/hooks/useContentConfigStore");
|
|
8
10
|
const b = (0, utils_1.block)('source-code');
|
|
@@ -10,25 +12,44 @@ const SourceCode = ({ className }) => {
|
|
|
10
12
|
const { config, setConfig } = (0, useContentConfigStore_1.useContentConfigStore)();
|
|
11
13
|
const [isOpen, setIsOpen] = (0, react_1.useState)(false);
|
|
12
14
|
const [tempConfig, setTempConfig] = (0, react_1.useState)('');
|
|
15
|
+
const [format, setFormat] = (0, react_1.useState)('yaml');
|
|
13
16
|
const onUpdate = () => {
|
|
14
17
|
let object;
|
|
15
18
|
try {
|
|
16
|
-
|
|
19
|
+
if (tempConfig.trim().startsWith('{') && tempConfig.trim().endsWith('}')) {
|
|
20
|
+
object = JSON.parse(tempConfig);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
object = js_yaml_1.default.load(tempConfig);
|
|
24
|
+
}
|
|
17
25
|
}
|
|
18
26
|
catch (_a) {
|
|
19
27
|
// eslint-disable-next-line no-console
|
|
20
28
|
console.error('JSON.parse failed');
|
|
21
29
|
}
|
|
22
|
-
|
|
30
|
+
if (object) {
|
|
31
|
+
setConfig(object);
|
|
32
|
+
}
|
|
23
33
|
setIsOpen(false);
|
|
24
34
|
};
|
|
35
|
+
const text = format === 'yaml' ? js_yaml_1.default.dump(config) : JSON.stringify(config, null, 2);
|
|
25
36
|
return (react_1.default.createElement("div", { className: b(null, className) },
|
|
26
|
-
react_1.default.createElement(
|
|
27
|
-
|
|
37
|
+
react_1.default.createElement("div", { className: b('head') },
|
|
38
|
+
react_1.default.createElement(uikit_1.RadioButton, { value: format, onUpdate: setFormat },
|
|
39
|
+
react_1.default.createElement(uikit_1.RadioButton.Option, { value: 'yaml', content: 'YAML' }),
|
|
40
|
+
react_1.default.createElement(uikit_1.RadioButton.Option, { value: 'json', content: 'JSON' })),
|
|
41
|
+
react_1.default.createElement(uikit_1.CopyToClipboard, { text: text, timeout: 1000 }, (status) => (react_1.default.createElement(uikit_1.Button, null,
|
|
42
|
+
status === 'pending' ? (react_1.default.createElement(uikit_1.Icon, { data: icons_1.Copy })) : (react_1.default.createElement(uikit_1.Icon, { data: icons_1.CopyCheck })),
|
|
43
|
+
"Copy"))),
|
|
44
|
+
react_1.default.createElement(uikit_1.Button, { onClick: () => setIsOpen(true) },
|
|
45
|
+
react_1.default.createElement(uikit_1.Icon, { data: icons_1.ArrowDownToSquare }),
|
|
46
|
+
"Import")),
|
|
47
|
+
react_1.default.createElement("div", { className: b('code') }, text),
|
|
28
48
|
react_1.default.createElement(uikit_1.Dialog, { onClose: () => setIsOpen(false), open: isOpen, size: 'l' },
|
|
29
49
|
react_1.default.createElement(uikit_1.Dialog.Header, { caption: "New configuration" }),
|
|
30
50
|
react_1.default.createElement(uikit_1.Dialog.Body, null,
|
|
31
|
-
react_1.default.createElement(uikit_1.
|
|
51
|
+
react_1.default.createElement(uikit_1.Alert, { className: b('alert'), theme: 'info', title: 'You can use YAML or JSON', message: 'The editor will automatically understand which format is needed.' }),
|
|
52
|
+
react_1.default.createElement(uikit_1.TextArea, { className: b('textarea'), value: tempConfig, onUpdate: setTempConfig, rows: 25 })),
|
|
32
53
|
react_1.default.createElement(uikit_1.Dialog.Footer, { showError: false, listenKeyEnter: true, preset: 'default', textButtonApply: 'Apply', textButtonCancel: 'Cancel', onClickButtonApply: onUpdate, onClickButtonCancel: () => setIsOpen(false) }))));
|
|
33
54
|
};
|
|
34
55
|
exports.default = SourceCode;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ClassNameProps } from '../../../models';
|
|
3
3
|
interface TopBarProps extends ClassNameProps {
|
|
4
|
+
onZoomUpdate: (zoom: number) => void;
|
|
5
|
+
onDecreaseZoom: () => void;
|
|
6
|
+
onIncreaseZoom: () => void;
|
|
7
|
+
zoom: number;
|
|
4
8
|
}
|
|
5
9
|
declare const TopBar: React.FC<TopBarProps>;
|
|
6
10
|
export default TopBar;
|
|
@@ -6,10 +6,10 @@ const utils_1 = require("../../../utils");
|
|
|
6
6
|
const Source_1 = tslib_1.__importDefault(require("../Source/Source"));
|
|
7
7
|
const ViewSwitches_1 = tslib_1.__importDefault(require("../ViewSwitches/ViewSwitches"));
|
|
8
8
|
const b = (0, utils_1.block)('topbar');
|
|
9
|
-
const TopBar = ({ className }) => {
|
|
9
|
+
const TopBar = ({ zoom, onDecreaseZoom, onIncreaseZoom, onZoomUpdate, className, }) => {
|
|
10
10
|
return (react_1.default.createElement("div", { className: b(null, className) },
|
|
11
11
|
react_1.default.createElement("div", { className: b('switches') },
|
|
12
|
-
react_1.default.createElement(ViewSwitches_1.default,
|
|
12
|
+
react_1.default.createElement(ViewSwitches_1.default, { onZoomUpdate: onZoomUpdate, onDecreaseZoom: onDecreaseZoom, onIncreaseZoom: onIncreaseZoom, zoom: zoom })),
|
|
13
13
|
react_1.default.createElement(Source_1.default, { className: b('source') })));
|
|
14
14
|
};
|
|
15
15
|
exports.default = TopBar;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { RadioButtonOption } from '@gravity-ui/uikit';
|
|
3
2
|
import { ClassNameProps } from '../../../models';
|
|
4
3
|
interface ViewSwitchesProps extends ClassNameProps {
|
|
4
|
+
onZoomUpdate: (zoom: number) => void;
|
|
5
|
+
onDecreaseZoom: () => void;
|
|
6
|
+
onIncreaseZoom: () => void;
|
|
7
|
+
zoom: number;
|
|
5
8
|
}
|
|
6
|
-
export declare const options2: RadioButtonOption[];
|
|
7
9
|
declare const ViewSwitches: React.FC<ViewSwitchesProps>;
|
|
8
10
|
export default ViewSwitches;
|
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.options2 = void 0;
|
|
4
3
|
const tslib_1 = require("tslib");
|
|
5
4
|
const react_1 = tslib_1.__importDefault(require("react"));
|
|
6
5
|
const icons_1 = require("@gravity-ui/icons");
|
|
7
6
|
const uikit_1 = require("@gravity-ui/uikit");
|
|
8
7
|
const utils_1 = require("../../../utils");
|
|
8
|
+
const constants_1 = require("../../constants");
|
|
9
9
|
const b = (0, utils_1.block)('view-switches');
|
|
10
|
-
const
|
|
11
|
-
{ value: 'edit-mode', content: react_1.default.createElement(uikit_1.Icon, { data: icons_1.SquareDashedText }) },
|
|
12
|
-
{ value: 'preview-mode', content: react_1.default.createElement(uikit_1.Icon, { data: icons_1.Eye }) },
|
|
13
|
-
];
|
|
14
|
-
exports.options2 = [
|
|
15
|
-
{ value: 'desktop-mode', content: react_1.default.createElement(uikit_1.Icon, { data: icons_1.Display }) },
|
|
16
|
-
{ value: 'tablet-mode', content: react_1.default.createElement(uikit_1.Icon, { data: icons_1.Square }) },
|
|
17
|
-
{ value: 'phone-mode', content: react_1.default.createElement(uikit_1.Icon, { data: icons_1.Smartphone }) },
|
|
18
|
-
];
|
|
19
|
-
// TODO: To be done
|
|
20
|
-
const ViewSwitches = ({ className }) => {
|
|
10
|
+
const ViewSwitches = ({ zoom, onIncreaseZoom, onDecreaseZoom, onZoomUpdate, className, }) => {
|
|
21
11
|
return (react_1.default.createElement("div", { className: b(null, className) },
|
|
22
|
-
react_1.default.createElement(
|
|
23
|
-
|
|
12
|
+
react_1.default.createElement("div", { className: b('zoom') },
|
|
13
|
+
react_1.default.createElement(uikit_1.Button, { view: 'flat', onClick: onDecreaseZoom },
|
|
14
|
+
react_1.default.createElement(uikit_1.Icon, { data: icons_1.Minus })),
|
|
15
|
+
react_1.default.createElement(uikit_1.Select, { multiple: false, value: [String(zoom)], options: constants_1.ZOOM_STEPS.map((step) => ({
|
|
16
|
+
value: String(step),
|
|
17
|
+
content: `${String(step)}%`,
|
|
18
|
+
})), onUpdate: (value) => onZoomUpdate(Number(value)) }),
|
|
19
|
+
react_1.default.createElement(uikit_1.Button, { view: 'flat', onClick: onIncreaseZoom },
|
|
20
|
+
react_1.default.createElement(uikit_1.Icon, { data: icons_1.Plus })))));
|
|
24
21
|
};
|
|
25
22
|
exports.default = ViewSwitches;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ZOOM_STEPS: number[];
|
|
@@ -2,9 +2,13 @@ import { WithStoreReducer } from '../../../common/types';
|
|
|
2
2
|
export interface IframeState {
|
|
3
3
|
url: string;
|
|
4
4
|
height?: number;
|
|
5
|
+
zoom: number;
|
|
5
6
|
}
|
|
6
7
|
export interface IframeMethods extends WithStoreReducer {
|
|
7
8
|
setUrl: (url: string) => void;
|
|
9
|
+
setZoom: (zoom: number) => void;
|
|
10
|
+
increaseZoom: () => void;
|
|
11
|
+
decreaseZoom: () => void;
|
|
8
12
|
}
|
|
9
13
|
export type IframeStore = IframeState & IframeMethods;
|
|
10
14
|
export declare const createIframeStore: (overrideInitialState?: Partial<IframeState> | undefined) => import("zustand").UseBoundStore<Omit<Omit<import("zustand").StoreApi<IframeState & IframeMethods>, "subscribe"> & {
|
|
@@ -2,11 +2,37 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createIframeStore = void 0;
|
|
4
4
|
const types_1 = require("../../../common/types");
|
|
5
|
+
const constants_1 = require("../../constants");
|
|
5
6
|
const store_1 = require("../../utils/store");
|
|
6
7
|
exports.createIframeStore = (0, store_1.initializeStore)({
|
|
7
8
|
url: '',
|
|
8
9
|
height: 400,
|
|
9
|
-
|
|
10
|
+
zoom: 100,
|
|
11
|
+
}, (set, get) => ({
|
|
12
|
+
setZoom: function (zoom) {
|
|
13
|
+
if (zoom > 0) {
|
|
14
|
+
set((state) => (Object.assign(Object.assign({}, state), { zoom })));
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
increaseZoom: function () {
|
|
18
|
+
const currentZoom = get().zoom;
|
|
19
|
+
for (const step of constants_1.ZOOM_STEPS) {
|
|
20
|
+
if (currentZoom < step) {
|
|
21
|
+
get().setZoom(step);
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
decreaseZoom: function () {
|
|
27
|
+
const currentZoom = get().zoom;
|
|
28
|
+
const reverseSteps = constants_1.ZOOM_STEPS.slice().reverse();
|
|
29
|
+
for (const step of reverseSteps) {
|
|
30
|
+
if (currentZoom > step) {
|
|
31
|
+
get().setZoom(step);
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
10
36
|
setUrl: (url) => set((state) => (Object.assign(Object.assign({}, state), { url }))),
|
|
11
37
|
reducer: (action) => {
|
|
12
38
|
switch (action.type) {
|
|
@@ -2,11 +2,12 @@ import React, { useContext, useState } from 'react';
|
|
|
2
2
|
import { Stop } from '@gravity-ui/icons';
|
|
3
3
|
import { ActionTypes, } from '../../../common/types';
|
|
4
4
|
import { block } from '../../../utils';
|
|
5
|
-
import { IframeContext } from '../../context/iframeContext';
|
|
5
|
+
import { IframeContext, useIframeStore } from '../../context/iframeContext';
|
|
6
6
|
import { useMessageObserver } from '../../context/messagesContext';
|
|
7
7
|
import './BigOverlay.css';
|
|
8
8
|
const b = block('big-overlay');
|
|
9
9
|
const BigOverlay = ({ className }) => {
|
|
10
|
+
const { zoom } = useIframeStore();
|
|
10
11
|
const { iframeElement } = useContext(IframeContext);
|
|
11
12
|
const [mousePosition, setMousePosition] = useState(undefined);
|
|
12
13
|
useMessageObserver(ActionTypes.OverlayModeOnMove, (payload, meta) => {
|
|
@@ -14,12 +15,14 @@ const BigOverlay = ({ className }) => {
|
|
|
14
15
|
const { x, y } = payload.cursor;
|
|
15
16
|
const iframeRect = iframeElement === null || iframeElement === void 0 ? void 0 : iframeElement.getClientRects().item(0);
|
|
16
17
|
if (iframeRect) {
|
|
17
|
-
const
|
|
18
|
-
const
|
|
18
|
+
const zoomedX = (x * zoom) / 100;
|
|
19
|
+
const zoomedY = (y * zoom) / 100;
|
|
20
|
+
const newX = meta.source === 'editor' ? x : zoomedX + iframeRect.x;
|
|
21
|
+
const newY = meta.source === 'editor' ? y : zoomedY + iframeRect.y;
|
|
19
22
|
setMousePosition({ x: newX, y: newY });
|
|
20
23
|
}
|
|
21
24
|
}
|
|
22
|
-
}, [iframeElement]);
|
|
25
|
+
}, [iframeElement, zoom]);
|
|
23
26
|
useMessageObserver(ActionTypes.InsertModeDisable, () => {
|
|
24
27
|
setMousePosition(undefined);
|
|
25
28
|
});
|
|
@@ -17,11 +17,13 @@ body {
|
|
|
17
17
|
flex-direction: column;
|
|
18
18
|
}
|
|
19
19
|
.pc-middle-screen__topbar {
|
|
20
|
-
height:
|
|
20
|
+
height: 40px;
|
|
21
21
|
}
|
|
22
|
-
.pc-middle-
|
|
22
|
+
.pc-middle-screen__wrapper {
|
|
23
23
|
height: 100%;
|
|
24
|
-
|
|
24
|
+
}
|
|
25
|
+
.pc-middle-screen__canvas {
|
|
26
|
+
transform-origin: left top;
|
|
25
27
|
overflow-y: scroll;
|
|
26
28
|
position: relative;
|
|
27
29
|
}
|
|
@@ -8,20 +8,25 @@ import TopBar from '../TopBar/TopBar';
|
|
|
8
8
|
import './MiddleScreen.css';
|
|
9
9
|
const b = block('middle-screen');
|
|
10
10
|
const MiddleScreen = ({ className }) => {
|
|
11
|
-
const { url, height } = useIframeStore();
|
|
11
|
+
const { url, height, zoom, decreaseZoom, increaseZoom, setZoom } = useIframeStore();
|
|
12
12
|
const { initialized } = useEditorStore();
|
|
13
13
|
const { setIframeElement } = useContext(IframeContext);
|
|
14
14
|
return (React.createElement("div", { className: b(null, className) },
|
|
15
15
|
React.createElement("div", { className: b('topbar') },
|
|
16
|
-
React.createElement(TopBar,
|
|
17
|
-
React.createElement("div", { className: b('
|
|
18
|
-
React.createElement("
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
16
|
+
React.createElement(TopBar, { onZoomUpdate: setZoom, zoom: zoom, onDecreaseZoom: decreaseZoom, onIncreaseZoom: increaseZoom })),
|
|
17
|
+
React.createElement("div", { className: b('wrapper') },
|
|
18
|
+
React.createElement("div", { className: b('canvas', { hidden: !initialized }), style: {
|
|
19
|
+
transform: `scale(${zoom}%)`,
|
|
20
|
+
height: `${(100 / zoom) * 100}%`,
|
|
21
|
+
width: `${(100 / zoom) * 100}%`,
|
|
22
|
+
} },
|
|
23
|
+
React.createElement("iframe", { ref: (element) => {
|
|
24
|
+
if (element) {
|
|
25
|
+
setIframeElement(element);
|
|
26
|
+
}
|
|
27
|
+
}, className: b('iframe'), src: url, height: `${height}px`, width: "100%", frameBorder: "0" }),
|
|
28
|
+
React.createElement(Overlay, { className: b('overlay') }),
|
|
29
|
+
!initialized && (React.createElement("div", { className: b('loading') },
|
|
30
|
+
React.createElement(Loader, { size: 'l' })))))));
|
|
26
31
|
};
|
|
27
32
|
export default MiddleScreen;
|
|
@@ -11,22 +11,34 @@ body {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
.pc-source-code {
|
|
14
|
-
|
|
14
|
+
height: 100%;
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
gap: 10px;
|
|
19
|
+
}
|
|
20
|
+
.pc-source-code__code {
|
|
15
21
|
white-space: pre;
|
|
16
22
|
font-family: var(--g-font-family-monospace);
|
|
17
23
|
font-size: var(--g-text-code-inline-1-font-size);
|
|
18
24
|
line-height: var(--g-text-code-inline-1-line-height);
|
|
19
25
|
font-weight: var(--g-text-code-font-weight);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
gap: 10px;
|
|
26
|
+
padding: 0 10px 10px;
|
|
27
|
+
overflow: auto;
|
|
23
28
|
}
|
|
24
|
-
.pc-source-
|
|
25
|
-
|
|
29
|
+
.pc-source-code__head {
|
|
30
|
+
display: flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: flex-start;
|
|
33
|
+
gap: 8px;
|
|
34
|
+
padding: 10px 10px 0;
|
|
26
35
|
}
|
|
27
36
|
.pc-source-code__textarea textarea {
|
|
28
37
|
font-family: var(--g-font-family-monospace);
|
|
29
38
|
font-size: var(--g-text-code-inline-1-font-size);
|
|
30
39
|
line-height: var(--g-text-code-inline-1-line-height);
|
|
31
40
|
font-weight: var(--g-text-code-font-weight);
|
|
41
|
+
}
|
|
42
|
+
.pc-source-code__alert {
|
|
43
|
+
margin-bottom: 8px;
|
|
32
44
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { ArrowDownToSquare, Copy, CopyCheck } from '@gravity-ui/icons';
|
|
3
|
+
import { Alert, Button, CopyToClipboard, Dialog, Icon, RadioButton, TextArea, } from '@gravity-ui/uikit';
|
|
4
|
+
import yaml from 'js-yaml';
|
|
3
5
|
import { block } from '../../../utils';
|
|
4
6
|
import { useContentConfigStore } from '../../context/contentConfig/hooks/useContentConfigStore';
|
|
5
7
|
import './SourceCode.css';
|
|
@@ -8,25 +10,44 @@ const SourceCode = ({ className }) => {
|
|
|
8
10
|
const { config, setConfig } = useContentConfigStore();
|
|
9
11
|
const [isOpen, setIsOpen] = useState(false);
|
|
10
12
|
const [tempConfig, setTempConfig] = useState('');
|
|
13
|
+
const [format, setFormat] = useState('yaml');
|
|
11
14
|
const onUpdate = () => {
|
|
12
15
|
let object;
|
|
13
16
|
try {
|
|
14
|
-
|
|
17
|
+
if (tempConfig.trim().startsWith('{') && tempConfig.trim().endsWith('}')) {
|
|
18
|
+
object = JSON.parse(tempConfig);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
object = yaml.load(tempConfig);
|
|
22
|
+
}
|
|
15
23
|
}
|
|
16
24
|
catch (_a) {
|
|
17
25
|
// eslint-disable-next-line no-console
|
|
18
26
|
console.error('JSON.parse failed');
|
|
19
27
|
}
|
|
20
|
-
|
|
28
|
+
if (object) {
|
|
29
|
+
setConfig(object);
|
|
30
|
+
}
|
|
21
31
|
setIsOpen(false);
|
|
22
32
|
};
|
|
33
|
+
const text = format === 'yaml' ? yaml.dump(config) : JSON.stringify(config, null, 2);
|
|
23
34
|
return (React.createElement("div", { className: b(null, className) },
|
|
24
|
-
React.createElement(
|
|
25
|
-
|
|
35
|
+
React.createElement("div", { className: b('head') },
|
|
36
|
+
React.createElement(RadioButton, { value: format, onUpdate: setFormat },
|
|
37
|
+
React.createElement(RadioButton.Option, { value: 'yaml', content: 'YAML' }),
|
|
38
|
+
React.createElement(RadioButton.Option, { value: 'json', content: 'JSON' })),
|
|
39
|
+
React.createElement(CopyToClipboard, { text: text, timeout: 1000 }, (status) => (React.createElement(Button, null,
|
|
40
|
+
status === 'pending' ? (React.createElement(Icon, { data: Copy })) : (React.createElement(Icon, { data: CopyCheck })),
|
|
41
|
+
"Copy"))),
|
|
42
|
+
React.createElement(Button, { onClick: () => setIsOpen(true) },
|
|
43
|
+
React.createElement(Icon, { data: ArrowDownToSquare }),
|
|
44
|
+
"Import")),
|
|
45
|
+
React.createElement("div", { className: b('code') }, text),
|
|
26
46
|
React.createElement(Dialog, { onClose: () => setIsOpen(false), open: isOpen, size: 'l' },
|
|
27
47
|
React.createElement(Dialog.Header, { caption: "New configuration" }),
|
|
28
48
|
React.createElement(Dialog.Body, null,
|
|
29
|
-
React.createElement(
|
|
49
|
+
React.createElement(Alert, { className: b('alert'), theme: 'info', title: 'You can use YAML or JSON', message: 'The editor will automatically understand which format is needed.' }),
|
|
50
|
+
React.createElement(TextArea, { className: b('textarea'), value: tempConfig, onUpdate: setTempConfig, rows: 25 })),
|
|
30
51
|
React.createElement(Dialog.Footer, { showError: false, listenKeyEnter: true, preset: 'default', textButtonApply: 'Apply', textButtonCancel: 'Cancel', onClickButtonApply: onUpdate, onClickButtonCancel: () => setIsOpen(false) }))));
|
|
31
52
|
};
|
|
32
53
|
export default SourceCode;
|
|
@@ -2,6 +2,10 @@ import React from 'react';
|
|
|
2
2
|
import { ClassNameProps } from '../../../models';
|
|
3
3
|
import './TopBar.css';
|
|
4
4
|
interface TopBarProps extends ClassNameProps {
|
|
5
|
+
onZoomUpdate: (zoom: number) => void;
|
|
6
|
+
onDecreaseZoom: () => void;
|
|
7
|
+
onIncreaseZoom: () => void;
|
|
8
|
+
zoom: number;
|
|
5
9
|
}
|
|
6
10
|
declare const TopBar: React.FC<TopBarProps>;
|
|
7
11
|
export default TopBar;
|
|
@@ -4,10 +4,10 @@ import Source from '../Source/Source';
|
|
|
4
4
|
import ViewSwitches from '../ViewSwitches/ViewSwitches';
|
|
5
5
|
import './TopBar.css';
|
|
6
6
|
const b = block('topbar');
|
|
7
|
-
const TopBar = ({ className }) => {
|
|
7
|
+
const TopBar = ({ zoom, onDecreaseZoom, onIncreaseZoom, onZoomUpdate, className, }) => {
|
|
8
8
|
return (React.createElement("div", { className: b(null, className) },
|
|
9
9
|
React.createElement("div", { className: b('switches') },
|
|
10
|
-
React.createElement(ViewSwitches,
|
|
10
|
+
React.createElement(ViewSwitches, { onZoomUpdate: onZoomUpdate, onDecreaseZoom: onDecreaseZoom, onIncreaseZoom: onIncreaseZoom, zoom: zoom })),
|
|
11
11
|
React.createElement(Source, { className: b('source') })));
|
|
12
12
|
};
|
|
13
13
|
export default TopBar;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { RadioButtonOption } from '@gravity-ui/uikit';
|
|
3
2
|
import { ClassNameProps } from '../../../models';
|
|
4
3
|
import './ViewSwitches.css';
|
|
5
4
|
interface ViewSwitchesProps extends ClassNameProps {
|
|
5
|
+
onZoomUpdate: (zoom: number) => void;
|
|
6
|
+
onDecreaseZoom: () => void;
|
|
7
|
+
onIncreaseZoom: () => void;
|
|
8
|
+
zoom: number;
|
|
6
9
|
}
|
|
7
|
-
export declare const options2: RadioButtonOption[];
|
|
8
10
|
declare const ViewSwitches: React.FC<ViewSwitchesProps>;
|
|
9
11
|
export default ViewSwitches;
|
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { Icon,
|
|
2
|
+
import { Minus, Plus } from '@gravity-ui/icons';
|
|
3
|
+
import { Button, Icon, Select } from '@gravity-ui/uikit';
|
|
4
4
|
import { block } from '../../../utils';
|
|
5
|
+
import { ZOOM_STEPS } from '../../constants';
|
|
5
6
|
import './ViewSwitches.css';
|
|
6
7
|
const b = block('view-switches');
|
|
7
|
-
const
|
|
8
|
-
{ value: 'edit-mode', content: React.createElement(Icon, { data: SquareDashedText }) },
|
|
9
|
-
{ value: 'preview-mode', content: React.createElement(Icon, { data: Eye }) },
|
|
10
|
-
];
|
|
11
|
-
export const options2 = [
|
|
12
|
-
{ value: 'desktop-mode', content: React.createElement(Icon, { data: Display }) },
|
|
13
|
-
{ value: 'tablet-mode', content: React.createElement(Icon, { data: Square }) },
|
|
14
|
-
{ value: 'phone-mode', content: React.createElement(Icon, { data: Smartphone }) },
|
|
15
|
-
];
|
|
16
|
-
// TODO: To be done
|
|
17
|
-
const ViewSwitches = ({ className }) => {
|
|
8
|
+
const ViewSwitches = ({ zoom, onIncreaseZoom, onDecreaseZoom, onZoomUpdate, className, }) => {
|
|
18
9
|
return (React.createElement("div", { className: b(null, className) },
|
|
19
|
-
React.createElement(
|
|
20
|
-
|
|
10
|
+
React.createElement("div", { className: b('zoom') },
|
|
11
|
+
React.createElement(Button, { view: 'flat', onClick: onDecreaseZoom },
|
|
12
|
+
React.createElement(Icon, { data: Minus })),
|
|
13
|
+
React.createElement(Select, { multiple: false, value: [String(zoom)], options: ZOOM_STEPS.map((step) => ({
|
|
14
|
+
value: String(step),
|
|
15
|
+
content: `${String(step)}%`,
|
|
16
|
+
})), onUpdate: (value) => onZoomUpdate(Number(value)) }),
|
|
17
|
+
React.createElement(Button, { view: 'flat', onClick: onIncreaseZoom },
|
|
18
|
+
React.createElement(Icon, { data: Plus })))));
|
|
21
19
|
};
|
|
22
20
|
export default ViewSwitches;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ZOOM_STEPS: number[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const ZOOM_STEPS = [25, 33, 50, 75, 100, 125, 150, 200, 250, 300];
|
|
@@ -2,9 +2,13 @@ import { WithStoreReducer } from '../../../common/types';
|
|
|
2
2
|
export interface IframeState {
|
|
3
3
|
url: string;
|
|
4
4
|
height?: number;
|
|
5
|
+
zoom: number;
|
|
5
6
|
}
|
|
6
7
|
export interface IframeMethods extends WithStoreReducer {
|
|
7
8
|
setUrl: (url: string) => void;
|
|
9
|
+
setZoom: (zoom: number) => void;
|
|
10
|
+
increaseZoom: () => void;
|
|
11
|
+
decreaseZoom: () => void;
|
|
8
12
|
}
|
|
9
13
|
export type IframeStore = IframeState & IframeMethods;
|
|
10
14
|
export declare const createIframeStore: (overrideInitialState?: Partial<IframeState> | undefined) => import("zustand").UseBoundStore<Omit<Omit<import("zustand").StoreApi<IframeState & IframeMethods>, "subscribe"> & {
|
|
@@ -1,9 +1,35 @@
|
|
|
1
1
|
import { ActionTypes } from '../../../common/types';
|
|
2
|
+
import { ZOOM_STEPS } from '../../constants';
|
|
2
3
|
import { initializeStore } from '../../utils/store';
|
|
3
4
|
export const createIframeStore = initializeStore({
|
|
4
5
|
url: '',
|
|
5
6
|
height: 400,
|
|
6
|
-
|
|
7
|
+
zoom: 100,
|
|
8
|
+
}, (set, get) => ({
|
|
9
|
+
setZoom: function (zoom) {
|
|
10
|
+
if (zoom > 0) {
|
|
11
|
+
set((state) => (Object.assign(Object.assign({}, state), { zoom })));
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
increaseZoom: function () {
|
|
15
|
+
const currentZoom = get().zoom;
|
|
16
|
+
for (const step of ZOOM_STEPS) {
|
|
17
|
+
if (currentZoom < step) {
|
|
18
|
+
get().setZoom(step);
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
decreaseZoom: function () {
|
|
24
|
+
const currentZoom = get().zoom;
|
|
25
|
+
const reverseSteps = ZOOM_STEPS.slice().reverse();
|
|
26
|
+
for (const step of reverseSteps) {
|
|
27
|
+
if (currentZoom > step) {
|
|
28
|
+
get().setZoom(step);
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
7
33
|
setUrl: (url) => set((state) => (Object.assign(Object.assign({}, state), { url }))),
|
|
8
34
|
reducer: (action) => {
|
|
9
35
|
switch (action.type) {
|