@saltcorn/builder 1.6.0-alpha.8 → 1.6.0-beta.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/dist/builder_bundle.js +7 -7
- package/dist/builder_bundle.js.LICENSE.txt +2 -0
- package/package.json +3 -2
- package/src/components/Builder.js +367 -186
- package/src/components/RenderNode.js +21 -3
- package/src/components/Toolbox.js +100 -22
- package/src/components/elements/Action.js +11 -121
- package/src/components/elements/ArrayManager.js +10 -5
- package/src/components/elements/BoxModelEditor.js +24 -23
- package/src/components/elements/Card.js +26 -1
- package/src/components/elements/Columns.js +158 -110
- package/src/components/elements/Container.js +43 -8
- package/src/components/elements/CustomLayer.js +285 -0
- package/src/components/elements/DropDownFilter.js +8 -1
- package/src/components/elements/DropMenu.js +10 -4
- package/src/components/elements/HTMLCode.js +3 -1
- package/src/components/elements/MonacoEditor.js +120 -15
- package/src/components/elements/Prompt.js +285 -0
- package/src/components/elements/SearchBar.js +28 -5
- package/src/components/elements/Table.js +10 -12
- package/src/components/elements/Text.js +59 -15
- package/src/components/elements/View.js +19 -7
- package/src/components/elements/ViewLink.js +1 -0
- package/src/components/elements/utils.js +133 -30
- package/src/components/storage.js +33 -7
- package/src/index.js +10 -0
- package/src/utils/responsive_utils.js +139 -0
|
@@ -47,7 +47,7 @@ const RenderNode = ({ render }) => {
|
|
|
47
47
|
} = useNode((node) => ({
|
|
48
48
|
isHover: node.events.hovered,
|
|
49
49
|
dom: node.dom,
|
|
50
|
-
name: node.data.custom.displayName || node.data.displayName,
|
|
50
|
+
name: node.data.custom.displayName || node.data.props?.custom?.displayName || node.data.displayName,
|
|
51
51
|
moveable: query.node(node.id).isDraggable(),
|
|
52
52
|
deletable: query.node(node.id).isDeletable(),
|
|
53
53
|
parent: node.data.parent,
|
|
@@ -80,9 +80,27 @@ const RenderNode = ({ render }) => {
|
|
|
80
80
|
currentDOM.style.left = left;
|
|
81
81
|
}, [dom, getPos]);
|
|
82
82
|
|
|
83
|
+
const hiddenColumnParents = new Set(["Card", "Container", "Table", "DropMenu"]);
|
|
83
84
|
useEffect(() => {
|
|
84
|
-
if (
|
|
85
|
-
|
|
85
|
+
if (!isActive) return;
|
|
86
|
+
if (name === "Column" && parent && parent !== "ROOT") {
|
|
87
|
+
const parentNode = query.node(parent).get();
|
|
88
|
+
const parentName = parentNode?.data?.displayName;
|
|
89
|
+
const parentLinked = parentNode?.data?.linkedNodes;
|
|
90
|
+
if (
|
|
91
|
+
hiddenColumnParents.has(parentName) &&
|
|
92
|
+
parentLinked &&
|
|
93
|
+
Object.values(parentLinked).includes(id)
|
|
94
|
+
) {
|
|
95
|
+
const currentlySelected = query.getEvent("selected").all();
|
|
96
|
+
const otherSelected = currentlySelected.filter((nid) => nid !== id);
|
|
97
|
+
if (otherSelected.length > 0) {
|
|
98
|
+
actions.selectNode([...otherSelected, parent]);
|
|
99
|
+
} else {
|
|
100
|
+
actions.selectNode(parent);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
86
104
|
}, [isActive]);
|
|
87
105
|
|
|
88
106
|
useEffect(() => {
|
|
@@ -29,6 +29,7 @@ import { View } from "./elements/View";
|
|
|
29
29
|
import { SearchBar } from "./elements/SearchBar";
|
|
30
30
|
import { Link } from "./elements/Link";
|
|
31
31
|
import { Page } from "./elements/Page";
|
|
32
|
+
import { Prompt } from "./elements/Prompt";
|
|
32
33
|
import optionsCtx from "./context";
|
|
33
34
|
import {
|
|
34
35
|
BoundingBox,
|
|
@@ -84,6 +85,7 @@ const WrapElem = ({
|
|
|
84
85
|
} d-inline-flex wrap-builder-elem align-items-center justify-content-center`}
|
|
85
86
|
title={title}
|
|
86
87
|
ref={disable ? undefined : (ref) => connectors.create(ref, children)}
|
|
88
|
+
onContextMenu={(e) => e.preventDefault()}
|
|
87
89
|
>
|
|
88
90
|
<div
|
|
89
91
|
className={`inner ${innerClass || ""}`}
|
|
@@ -115,7 +117,7 @@ const TextElem = ({ connectors }) => {
|
|
|
115
117
|
fontSize="22px"
|
|
116
118
|
title={t("Text")}
|
|
117
119
|
bold
|
|
118
|
-
label=
|
|
120
|
+
label="Text"
|
|
119
121
|
>
|
|
120
122
|
<Text text="Hello world" block={false} textStyle={""} />
|
|
121
123
|
</WrapElem>
|
|
@@ -137,7 +139,7 @@ const ColumnsElem = ({ connectors }) => {
|
|
|
137
139
|
innerClass="mt-m1px"
|
|
138
140
|
icon="fas fa-columns"
|
|
139
141
|
title={t("Split into columns")}
|
|
140
|
-
label=
|
|
142
|
+
label="Columns"
|
|
141
143
|
>
|
|
142
144
|
<Columns contents={[]} setting_col_n={1} />
|
|
143
145
|
</WrapElem>
|
|
@@ -158,7 +160,7 @@ const TabsElem = ({ connectors }) => {
|
|
|
158
160
|
connectors={connectors}
|
|
159
161
|
icon={<SegmentedNav className="mb-2 h4" />}
|
|
160
162
|
title={t("Tabbed content")}
|
|
161
|
-
label=
|
|
163
|
+
label="Tabs"
|
|
162
164
|
>
|
|
163
165
|
<Tabs contents={[]} />
|
|
164
166
|
</WrapElem>
|
|
@@ -180,7 +182,7 @@ const LineBreakElem = ({ connectors }) => {
|
|
|
180
182
|
text="↵"
|
|
181
183
|
fontSize="26px"
|
|
182
184
|
title={t("Line break")}
|
|
183
|
-
label=
|
|
185
|
+
label="Break"
|
|
184
186
|
>
|
|
185
187
|
<LineBreak />
|
|
186
188
|
</WrapElem>
|
|
@@ -201,7 +203,7 @@ const HTMLElem = ({ connectors }) => {
|
|
|
201
203
|
connectors={connectors}
|
|
202
204
|
icon="fas fa-code"
|
|
203
205
|
title={t("HTML code")}
|
|
204
|
-
label=
|
|
206
|
+
label="Code"
|
|
205
207
|
>
|
|
206
208
|
<HTMLCode text={""} />
|
|
207
209
|
</WrapElem>
|
|
@@ -222,7 +224,7 @@ const CardElem = ({ connectors }) => {
|
|
|
222
224
|
connectors={connectors}
|
|
223
225
|
title={t("Card")}
|
|
224
226
|
icon="far fa-square"
|
|
225
|
-
label=
|
|
227
|
+
label="Card"
|
|
226
228
|
>
|
|
227
229
|
<Element canvas is={Card} isFormula={{}} url=""></Element>
|
|
228
230
|
</WrapElem>
|
|
@@ -243,7 +245,7 @@ const ImageElem = ({ connectors, images }) => {
|
|
|
243
245
|
connectors={connectors}
|
|
244
246
|
icon="fas fa-image"
|
|
245
247
|
title={t("Image")}
|
|
246
|
-
label=
|
|
248
|
+
label="Image"
|
|
247
249
|
>
|
|
248
250
|
<Image fileid={images.length > 0 ? images[0].id : 0} />
|
|
249
251
|
</WrapElem>
|
|
@@ -264,7 +266,7 @@ const LinkElem = ({ connectors }) => {
|
|
|
264
266
|
connectors={connectors}
|
|
265
267
|
icon="fas fa-link"
|
|
266
268
|
title={t("Link")}
|
|
267
|
-
label=
|
|
269
|
+
label="Link"
|
|
268
270
|
>
|
|
269
271
|
<Link />
|
|
270
272
|
</WrapElem>
|
|
@@ -285,7 +287,7 @@ const ViewElem = ({ connectors, views, isPageEdit }) => {
|
|
|
285
287
|
connectors={connectors}
|
|
286
288
|
icon="fas fa-eye"
|
|
287
289
|
title={t("Embed a view")}
|
|
288
|
-
label=
|
|
290
|
+
label="View"
|
|
289
291
|
disable={!views || views.length < (!isPageEdit ? 2 : 1)}
|
|
290
292
|
>
|
|
291
293
|
<View
|
|
@@ -311,7 +313,7 @@ const SearchElem = ({ connectors }) => {
|
|
|
311
313
|
connectors={connectors}
|
|
312
314
|
icon="fas fa-search"
|
|
313
315
|
title={t("Search bar")}
|
|
314
|
-
label=
|
|
316
|
+
label="Search"
|
|
315
317
|
>
|
|
316
318
|
<Element canvas is={SearchBar}></Element>
|
|
317
319
|
</WrapElem>
|
|
@@ -332,7 +334,7 @@ const ContainerElem = ({ connectors }) => {
|
|
|
332
334
|
connectors={connectors}
|
|
333
335
|
icon={<BoundingBox className="mb-2 h5" />}
|
|
334
336
|
title={t("Container")}
|
|
335
|
-
label=
|
|
337
|
+
label="Contain"
|
|
336
338
|
>
|
|
337
339
|
<Element canvas is={Container}></Element>
|
|
338
340
|
</WrapElem>
|
|
@@ -353,7 +355,7 @@ const FieldElem = ({ connectors, fields, field_view_options }) => {
|
|
|
353
355
|
connectors={connectors}
|
|
354
356
|
icon="fas fa-asterisk"
|
|
355
357
|
title={t("Field")}
|
|
356
|
-
label=
|
|
358
|
+
label="Field"
|
|
357
359
|
>
|
|
358
360
|
<Field
|
|
359
361
|
name={fields[0].name}
|
|
@@ -380,7 +382,7 @@ const DropDownFilterElem = ({ connectors, fields }) => {
|
|
|
380
382
|
connectors={connectors}
|
|
381
383
|
icon="far fa-caret-square-down"
|
|
382
384
|
title={t("Dropdown filter")}
|
|
383
|
-
label=
|
|
385
|
+
label="Select"
|
|
384
386
|
>
|
|
385
387
|
<DropDownFilter
|
|
386
388
|
name={fields[0].name}
|
|
@@ -399,7 +401,7 @@ const DropMenuElem = ({ connectors }) => {
|
|
|
399
401
|
connectors={connectors}
|
|
400
402
|
icon="far fa-caret-square-down"
|
|
401
403
|
title={t("Dropdown menu")}
|
|
402
|
-
label=
|
|
404
|
+
label="DropMenu"
|
|
403
405
|
>
|
|
404
406
|
<Element canvas is={DropMenu}></Element>
|
|
405
407
|
</WrapElem>
|
|
@@ -413,7 +415,7 @@ const PageElem = ({ connectors, pages }) => {
|
|
|
413
415
|
connectors={connectors}
|
|
414
416
|
icon="fa-fw far fa-file"
|
|
415
417
|
title={t("Embed a page")}
|
|
416
|
-
label=
|
|
418
|
+
label="Page"
|
|
417
419
|
disable={pages.length <= 1}
|
|
418
420
|
>
|
|
419
421
|
<Page page={pages.length > 0 ? pages[0].name : "page"} />
|
|
@@ -436,7 +438,7 @@ const ToggleFilterElem = ({ connectors, fields }) => {
|
|
|
436
438
|
connectors={connectors}
|
|
437
439
|
icon="fas fa-toggle-on"
|
|
438
440
|
title={t("Toggle filter")}
|
|
439
|
-
label=
|
|
441
|
+
label="Toggle"
|
|
440
442
|
>
|
|
441
443
|
<ToggleFilter name={fields[0].name} value={""} label={""} block={false} />
|
|
442
444
|
</WrapElem>
|
|
@@ -457,7 +459,7 @@ const JoinFieldElem = ({ connectors, options }) => {
|
|
|
457
459
|
connectors={connectors}
|
|
458
460
|
icon={<Diagram3Fill className="mb-2 h5" />}
|
|
459
461
|
title={t("Join field")}
|
|
460
|
-
label=
|
|
462
|
+
label="Join"
|
|
461
463
|
disable={options.parent_field_list.length === 0}
|
|
462
464
|
>
|
|
463
465
|
<JoinField
|
|
@@ -484,7 +486,7 @@ const ViewLinkElem = ({ connectors, options }) => {
|
|
|
484
486
|
connectors={connectors}
|
|
485
487
|
icons={["fas fa-eye", "fas fa-link"]}
|
|
486
488
|
title={t("Link to a view")}
|
|
487
|
-
label=
|
|
489
|
+
label="ViewLink"
|
|
488
490
|
disable={!options.views || options.views.length < 2}
|
|
489
491
|
>
|
|
490
492
|
<ViewLink
|
|
@@ -510,7 +512,7 @@ const ActionElem = ({ connectors, options }) => {
|
|
|
510
512
|
return (
|
|
511
513
|
<WrapElem
|
|
512
514
|
connectors={connectors}
|
|
513
|
-
label=
|
|
515
|
+
label="Action"
|
|
514
516
|
icon="fas fa-running"
|
|
515
517
|
title={t("Action button")}
|
|
516
518
|
>
|
|
@@ -549,7 +551,7 @@ const AggregationElem = ({ connectors, child_field_list, agg_field_opts }) => {
|
|
|
549
551
|
connectors={connectors}
|
|
550
552
|
text="∑"
|
|
551
553
|
title={t("Aggregation")}
|
|
552
|
-
label=
|
|
554
|
+
label="Aggreg8"
|
|
553
555
|
bold
|
|
554
556
|
fontSize="16px"
|
|
555
557
|
disable={child_field_list.length === 0}
|
|
@@ -574,15 +576,71 @@ const TableElem = ({ connectors }) => {
|
|
|
574
576
|
innerClass="mt-m1px"
|
|
575
577
|
icon="fas fa-table"
|
|
576
578
|
title={t("Table")}
|
|
577
|
-
label=
|
|
579
|
+
label="Table"
|
|
578
580
|
>
|
|
579
581
|
<Table contents={[[], []]} rows={2} columns={2} />
|
|
580
582
|
</WrapElem>
|
|
581
583
|
);
|
|
582
584
|
};
|
|
583
585
|
|
|
586
|
+
const PromptContainerElem = ({ connectors }) => {
|
|
587
|
+
const { t } = useTranslation();
|
|
588
|
+
return (
|
|
589
|
+
<WrapElem
|
|
590
|
+
connectors={connectors}
|
|
591
|
+
icon="fas fa-robot"
|
|
592
|
+
title={t("Generate with AI")}
|
|
593
|
+
label="Generate"
|
|
594
|
+
>
|
|
595
|
+
<Prompt promptType="container" promptText="" />
|
|
596
|
+
</WrapElem>
|
|
597
|
+
);
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
const PromptViewElem = ({ connectors }) => {
|
|
601
|
+
const { t } = useTranslation();
|
|
602
|
+
return (
|
|
603
|
+
<WrapElem
|
|
604
|
+
connectors={connectors}
|
|
605
|
+
icon="fas fa-eye"
|
|
606
|
+
title={t("Prompt View")}
|
|
607
|
+
label="Prompt View"
|
|
608
|
+
>
|
|
609
|
+
<Prompt promptType="view" promptText="" />
|
|
610
|
+
</WrapElem>
|
|
611
|
+
);
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
const PromptFieldElem = ({ connectors }) => {
|
|
615
|
+
const { t } = useTranslation();
|
|
616
|
+
return (
|
|
617
|
+
<WrapElem
|
|
618
|
+
connectors={connectors}
|
|
619
|
+
icon="fas fa-i-cursor"
|
|
620
|
+
title={t("Prompt Field")}
|
|
621
|
+
label="Prompt Field"
|
|
622
|
+
>
|
|
623
|
+
<Prompt promptType="field" promptText="" />
|
|
624
|
+
</WrapElem>
|
|
625
|
+
);
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
const PromptActionElem = ({ connectors }) => {
|
|
629
|
+
const { t } = useTranslation();
|
|
630
|
+
return (
|
|
631
|
+
<WrapElem
|
|
632
|
+
connectors={connectors}
|
|
633
|
+
icon="fas fa-bolt"
|
|
634
|
+
title={t("Prompt Action")}
|
|
635
|
+
label="Prompt Action"
|
|
636
|
+
>
|
|
637
|
+
<Prompt promptType="action" promptText="" />
|
|
638
|
+
</WrapElem>
|
|
639
|
+
);
|
|
640
|
+
};
|
|
641
|
+
|
|
584
642
|
const chunkToolBox = (elems, expanded) => {
|
|
585
|
-
const chunks = chunk(elems, expanded ? 3 : 2);
|
|
643
|
+
const chunks = chunk(elems.filter(Boolean), expanded ? 3 : 2);
|
|
586
644
|
return chunks.map((es, ix) => (
|
|
587
645
|
<div className="toolbar-row" key={ix}>
|
|
588
646
|
{es.map((e, j) => (
|
|
@@ -638,6 +696,10 @@ const ToolboxShow = ({ expanded }) => {
|
|
|
638
696
|
<DropMenuElem connectors={connectors} />,
|
|
639
697
|
<TableElem connectors={connectors} />,
|
|
640
698
|
<PageElem connectors={connectors} pages={pages} />,
|
|
699
|
+
options.has_copilot_generate && <PromptContainerElem connectors={connectors} />,
|
|
700
|
+
// <PromptViewElem connectors={connectors} />,
|
|
701
|
+
// <PromptFieldElem connectors={connectors} />,
|
|
702
|
+
// <PromptActionElem connectors={connectors} />,
|
|
641
703
|
],
|
|
642
704
|
expanded
|
|
643
705
|
);
|
|
@@ -696,6 +758,10 @@ const ToolboxList = ({ expanded }) => {
|
|
|
696
758
|
<DropMenuElem connectors={connectors} />
|
|
697
759
|
),
|
|
698
760
|
// <TableElem connectors={connectors} />,
|
|
761
|
+
options.has_copilot_generate && <PromptContainerElem connectors={connectors} />,
|
|
762
|
+
// <PromptViewElem connectors={connectors} />,
|
|
763
|
+
// <PromptFieldElem connectors={connectors} />,
|
|
764
|
+
// <PromptActionElem connectors={connectors} />,
|
|
699
765
|
options.allowMultipleElementsPerColumn &&
|
|
700
766
|
!disable_toolbox?.line_break && (
|
|
701
767
|
<LineBreakElem connectors={connectors} />
|
|
@@ -750,6 +816,10 @@ const ToolboxFilter = ({ expanded }) => {
|
|
|
750
816
|
<TableElem connectors={connectors} />,
|
|
751
817
|
<DropMenuElem connectors={connectors} />,
|
|
752
818
|
<PageElem connectors={connectors} pages={pages} />,
|
|
819
|
+
options.has_copilot_generate && <PromptContainerElem connectors={connectors} />,
|
|
820
|
+
// <PromptViewElem connectors={connectors} />,
|
|
821
|
+
// <PromptFieldElem connectors={connectors} />,
|
|
822
|
+
// <PromptActionElem connectors={connectors} />,
|
|
753
823
|
],
|
|
754
824
|
expanded
|
|
755
825
|
);
|
|
@@ -787,6 +857,10 @@ const ToolboxEdit = ({ expanded }) => {
|
|
|
787
857
|
<DropMenuElem connectors={connectors} />,
|
|
788
858
|
<TableElem connectors={connectors} />,
|
|
789
859
|
<ViewLinkElem connectors={connectors} options={options} />,
|
|
860
|
+
options.has_copilot_generate && <PromptContainerElem connectors={connectors} />,
|
|
861
|
+
// <PromptViewElem connectors={connectors} />,
|
|
862
|
+
// <PromptFieldElem connectors={connectors} />,
|
|
863
|
+
// <PromptActionElem connectors={connectors} />,
|
|
790
864
|
],
|
|
791
865
|
expanded
|
|
792
866
|
);
|
|
@@ -819,6 +893,10 @@ const ToolboxPage = ({ expanded }) => {
|
|
|
819
893
|
<DropMenuElem connectors={connectors} />,
|
|
820
894
|
<PageElem connectors={connectors} pages={pages} />,
|
|
821
895
|
<TableElem connectors={connectors} />,
|
|
896
|
+
options.has_copilot_generate && <PromptContainerElem connectors={connectors} />,
|
|
897
|
+
// <PromptViewElem connectors={connectors} />,
|
|
898
|
+
// <PromptFieldElem connectors={connectors} />,
|
|
899
|
+
// <PromptActionElem connectors={connectors} />,
|
|
822
900
|
],
|
|
823
901
|
expanded
|
|
824
902
|
);
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
/*global notifyAlert, apply_showif*/
|
|
7
7
|
|
|
8
|
-
import React, { Fragment, useContext, useEffect
|
|
8
|
+
import React, { Fragment, useContext, useEffect } from "react";
|
|
9
9
|
import { useNode } from "@craftjs/core";
|
|
10
10
|
import useTranslation from "../../hooks/useTranslation";
|
|
11
11
|
import optionsCtx from "../context";
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
} from "./utils";
|
|
26
26
|
import { ntimes } from "./Columns";
|
|
27
27
|
import { ArrayManager } from "./ArrayManager";
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
import Select from "react-select";
|
|
30
30
|
|
|
31
31
|
export /**
|
|
@@ -55,6 +55,7 @@ const Action = ({
|
|
|
55
55
|
action_bgcol,
|
|
56
56
|
action_bordercol,
|
|
57
57
|
action_textcol,
|
|
58
|
+
action_class
|
|
58
59
|
}) => {
|
|
59
60
|
const {
|
|
60
61
|
selected,
|
|
@@ -65,7 +66,7 @@ const Action = ({
|
|
|
65
66
|
*/
|
|
66
67
|
return (
|
|
67
68
|
<button
|
|
68
|
-
className={`btn ${action_style || "btn-primary"} ${action_size || ""} ${
|
|
69
|
+
className={`btn ${action_style || "btn-primary"} ${action_size || ""} ${action_class || ""} ${
|
|
69
70
|
selected ? "selected-node" : ""
|
|
70
71
|
} ${block ? "d-block" : ""}`}
|
|
71
72
|
ref={(dom) => connect(drag(dom))}
|
|
@@ -146,13 +147,6 @@ const ActionSettings = () => {
|
|
|
146
147
|
const options = useContext(optionsCtx);
|
|
147
148
|
const getCfgFields = (fv) => (options.actionConfigForms || {})[fv];
|
|
148
149
|
const cfgFields = getCfgFields(name);
|
|
149
|
-
const cfgFieldsForForm =
|
|
150
|
-
name === "run_js_code"
|
|
151
|
-
? (cfgFields || []).filter((f) => f.name !== "code")
|
|
152
|
-
: cfgFields;
|
|
153
|
-
|
|
154
|
-
const runJsCodeModalOnly = false;
|
|
155
|
-
const [codeModalOpen, setCodeModalOpen] = useState(false);
|
|
156
150
|
const setAProp = setAPropGen(setProp);
|
|
157
151
|
const use_setting_action_n =
|
|
158
152
|
setting_action_n || setting_action_n === 0 ? setting_action_n : 0;
|
|
@@ -274,7 +268,7 @@ const ActionSettings = () => {
|
|
|
274
268
|
<td>
|
|
275
269
|
<select
|
|
276
270
|
value={action_row_variable}
|
|
277
|
-
className="form-control form-select
|
|
271
|
+
className="form-control form-select"
|
|
278
272
|
onChange={(e) => {
|
|
279
273
|
if (!e.target) return;
|
|
280
274
|
const value = e.target.value;
|
|
@@ -457,116 +451,12 @@ const ActionSettings = () => {
|
|
|
457
451
|
) : null}
|
|
458
452
|
</Fragment>
|
|
459
453
|
) : cfgFields ? (
|
|
460
|
-
<
|
|
461
|
-
{
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
className="btn btn-secondary btn-sm"
|
|
467
|
-
onClick={() => setCodeModalOpen(true)}
|
|
468
|
-
>
|
|
469
|
-
{t("Open Code Popup")}
|
|
470
|
-
</button>
|
|
471
|
-
</div>
|
|
472
|
-
) : null}
|
|
473
|
-
{name === "run_js_code" && !runJsCodeModalOnly ? (
|
|
474
|
-
<Fragment>
|
|
475
|
-
<ConfigForm
|
|
476
|
-
fields={(cfgFields || []).filter((f) => f.name === "code")}
|
|
477
|
-
configuration={configuration}
|
|
478
|
-
setProp={setProp}
|
|
479
|
-
node={node}
|
|
480
|
-
openPopup={() => setCodeModalOpen(true)}
|
|
481
|
-
/>
|
|
482
|
-
{/* <div className="builder-config-field mt-2" data-field-name="code-modal-trigger">
|
|
483
|
-
<button
|
|
484
|
-
type="button"
|
|
485
|
-
className="btn btn-secondary btn-sm"
|
|
486
|
-
onClick={() => setCodeModalOpen(true)}
|
|
487
|
-
>
|
|
488
|
-
{t("Open Code Popup")}
|
|
489
|
-
</button>
|
|
490
|
-
</div> */}
|
|
491
|
-
<ConfigForm
|
|
492
|
-
fields={cfgFieldsForForm}
|
|
493
|
-
configuration={configuration}
|
|
494
|
-
setProp={setProp}
|
|
495
|
-
node={node}
|
|
496
|
-
/>
|
|
497
|
-
</Fragment>
|
|
498
|
-
) : (
|
|
499
|
-
<ConfigForm
|
|
500
|
-
fields={runJsCodeModalOnly ? cfgFieldsForForm : cfgFields}
|
|
501
|
-
configuration={configuration}
|
|
502
|
-
setProp={setProp}
|
|
503
|
-
node={node}
|
|
504
|
-
/>
|
|
505
|
-
)}
|
|
506
|
-
{name === "run_js_code" && codeModalOpen ? (
|
|
507
|
-
<div
|
|
508
|
-
className={`modal fade ${codeModalOpen ? "show" : ""}`}
|
|
509
|
-
style={{
|
|
510
|
-
display: codeModalOpen ? "block" : "none",
|
|
511
|
-
zIndex: 1055,
|
|
512
|
-
}}
|
|
513
|
-
tabIndex={-1}
|
|
514
|
-
role="dialog"
|
|
515
|
-
aria-labelledby="codeModalLabel"
|
|
516
|
-
aria-hidden={!codeModalOpen}
|
|
517
|
-
>
|
|
518
|
-
<div
|
|
519
|
-
className="modal-backdrop fade show"
|
|
520
|
-
style={{ zIndex: 1050 }}
|
|
521
|
-
onClick={() => setCodeModalOpen(false)}
|
|
522
|
-
aria-hidden="true"
|
|
523
|
-
/>
|
|
524
|
-
<div
|
|
525
|
-
className="modal-dialog modal-dialog-centered modal-lg"
|
|
526
|
-
role="document"
|
|
527
|
-
style={{ zIndex: 1060 }}
|
|
528
|
-
onClick={(e) => e.stopPropagation()}
|
|
529
|
-
>
|
|
530
|
-
<div className="modal-content code-modal">
|
|
531
|
-
<div className="modal-header">
|
|
532
|
-
<h5 className="modal-title" id="codeModalLabel">
|
|
533
|
-
{t("Code")}
|
|
534
|
-
</h5>
|
|
535
|
-
<button
|
|
536
|
-
type="button"
|
|
537
|
-
className="btn-close"
|
|
538
|
-
aria-label="Close"
|
|
539
|
-
onClick={() => setCodeModalOpen(false)}
|
|
540
|
-
/>
|
|
541
|
-
</div>
|
|
542
|
-
<div className="modal-body">
|
|
543
|
-
<MultiLineCodeEditor
|
|
544
|
-
setProp={setProp}
|
|
545
|
-
value={configuration?.code ?? ""}
|
|
546
|
-
onChange={(code) =>
|
|
547
|
-
setProp((prop) => {
|
|
548
|
-
if (!prop.configuration)
|
|
549
|
-
prop.configuration = {};
|
|
550
|
-
prop.configuration.code = code;
|
|
551
|
-
})
|
|
552
|
-
}
|
|
553
|
-
isModalEditor
|
|
554
|
-
/>
|
|
555
|
-
</div>
|
|
556
|
-
<div className="modal-footer">
|
|
557
|
-
<button
|
|
558
|
-
type="button"
|
|
559
|
-
className="btn btn-secondary"
|
|
560
|
-
onClick={() => setCodeModalOpen(false)}
|
|
561
|
-
>
|
|
562
|
-
{t("Close")}
|
|
563
|
-
</button>
|
|
564
|
-
</div>
|
|
565
|
-
</div>
|
|
566
|
-
</div>
|
|
567
|
-
</div>
|
|
568
|
-
) : null}
|
|
569
|
-
</Fragment>
|
|
454
|
+
<ConfigForm
|
|
455
|
+
fields={cfgFields}
|
|
456
|
+
configuration={configuration}
|
|
457
|
+
setProp={setProp}
|
|
458
|
+
node={node}
|
|
459
|
+
/>
|
|
570
460
|
) : null}
|
|
571
461
|
{cfg_link ? (
|
|
572
462
|
<a className="d-block mt-2" target="_blank" href={cfg_link}>
|
|
@@ -56,6 +56,8 @@ export const ArrayManager = ({
|
|
|
56
56
|
managedArrays,
|
|
57
57
|
manageContents,
|
|
58
58
|
initialAddProps,
|
|
59
|
+
contentsKey = "contents",
|
|
60
|
+
onLayoutChange,
|
|
59
61
|
}) => {
|
|
60
62
|
const { t } = useTranslation();
|
|
61
63
|
const { actions, query, connectors } = useEditor((state, query) => {
|
|
@@ -77,13 +79,14 @@ export const ArrayManager = ({
|
|
|
77
79
|
node.id,
|
|
78
80
|
options
|
|
79
81
|
);
|
|
80
|
-
layout.
|
|
82
|
+
layout[contentsKey].splice(rmIx, 1);
|
|
81
83
|
|
|
82
84
|
managedArrays.forEach((arrNm) => {
|
|
83
|
-
|
|
85
|
+
if (layout[arrNm]) layout[arrNm].splice(rmIx, 1);
|
|
84
86
|
});
|
|
85
87
|
layout[countProp] = node[countProp] - 1;
|
|
86
|
-
layout[currentProp] = node[currentProp] - 1;
|
|
88
|
+
layout[currentProp] = Math.max(0, node[currentProp] - 1);
|
|
89
|
+
if (onLayoutChange) onLayoutChange(layout, "delete");
|
|
87
90
|
actions.delete(node.id);
|
|
88
91
|
layoutToNodes(layout, query, actions, parentId, options, sibIx);
|
|
89
92
|
} else {
|
|
@@ -119,7 +122,7 @@ export const ArrayManager = ({
|
|
|
119
122
|
options
|
|
120
123
|
);
|
|
121
124
|
|
|
122
|
-
swapElements(layout
|
|
125
|
+
swapElements(layout[contentsKey], curIx, curIx + delta);
|
|
123
126
|
|
|
124
127
|
managedArrays.forEach((arrNm) => {
|
|
125
128
|
if (arrNm.includes(".")) {
|
|
@@ -130,6 +133,7 @@ export const ArrayManager = ({
|
|
|
130
133
|
swapElements(layout[arrNm], curIx, curIx + delta);
|
|
131
134
|
});
|
|
132
135
|
layout[currentProp] = node[currentProp] + delta;
|
|
136
|
+
if (onLayoutChange) onLayoutChange(layout, "move");
|
|
133
137
|
actions.delete(node.id);
|
|
134
138
|
layoutToNodes(layout, query, actions, parentId, options, sibIx);
|
|
135
139
|
} else
|
|
@@ -156,7 +160,7 @@ export const ArrayManager = ({
|
|
|
156
160
|
options
|
|
157
161
|
);
|
|
158
162
|
|
|
159
|
-
layout.
|
|
163
|
+
layout[contentsKey].push(null);
|
|
160
164
|
managedArrays.forEach((arrNm) => {
|
|
161
165
|
if (initialAddProps?.[arrNm])
|
|
162
166
|
layout[arrNm][node[countProp]] = initialAddProps?.[arrNm];
|
|
@@ -164,6 +168,7 @@ export const ArrayManager = ({
|
|
|
164
168
|
layout[currentProp] = +node[countProp];
|
|
165
169
|
layout[countProp] = +node[countProp] + 1;
|
|
166
170
|
|
|
171
|
+
if (onLayoutChange) onLayoutChange(layout, "add");
|
|
167
172
|
actions.delete(node.id);
|
|
168
173
|
layoutToNodes(layout, query, actions, parentId, options, sibIx);
|
|
169
174
|
} else
|
|
@@ -7,6 +7,12 @@
|
|
|
7
7
|
import React, { useContext, Fragment, useState } from "react";
|
|
8
8
|
import useTranslation from "../../hooks/useTranslation";
|
|
9
9
|
import { SettingsRow, SettingsSectionHeaderRow, bstyleopt } from "./utils";
|
|
10
|
+
import PreviewCtx from "../preview_context";
|
|
11
|
+
import {
|
|
12
|
+
getDeviceSizeNode,
|
|
13
|
+
getDeviceSizeSetProp,
|
|
14
|
+
getDisplaySize,
|
|
15
|
+
} from "../../utils/responsive_utils";
|
|
10
16
|
/*
|
|
11
17
|
Contains code from https://github.com/tpaksu/boxmodel
|
|
12
18
|
Copyright (c) 2017 Taha Paksu
|
|
@@ -24,6 +30,7 @@ export /**
|
|
|
24
30
|
*/
|
|
25
31
|
const BoxModelEditor = ({ setProp, node, sizeWithStyle }) => {
|
|
26
32
|
const { t } = useTranslation();
|
|
33
|
+
const { previewDevice } = useContext(PreviewCtx);
|
|
27
34
|
const [selectedCategory, setSelectedCategory] = useState(false);
|
|
28
35
|
const [selectedDirection, setSelectedDirection] = useState(false);
|
|
29
36
|
const selectedProperty = !selectedCategory
|
|
@@ -35,7 +42,13 @@ const BoxModelEditor = ({ setProp, node, sizeWithStyle }) => {
|
|
|
35
42
|
setSelectedCategory(c);
|
|
36
43
|
setSelectedDirection(d);
|
|
37
44
|
};
|
|
38
|
-
|
|
45
|
+
const isDesktop = !previewDevice || previewDevice === "desktop";
|
|
46
|
+
const deviceLabel = previewDevice === "mobile"
|
|
47
|
+
? ` (${t("mobile")})`
|
|
48
|
+
: previewDevice === "tablet"
|
|
49
|
+
? ` (${t("tablet")})`
|
|
50
|
+
: "";
|
|
51
|
+
|
|
39
52
|
const style = node.style;
|
|
40
53
|
return (
|
|
41
54
|
<Fragment>
|
|
@@ -147,13 +160,7 @@ const BoxModelEditor = ({ setProp, node, sizeWithStyle }) => {
|
|
|
147
160
|
autoComplete="off"
|
|
148
161
|
name="boxmodel-ex-1_width"
|
|
149
162
|
size="3"
|
|
150
|
-
value={
|
|
151
|
-
sizeWithStyle
|
|
152
|
-
? style["width"]
|
|
153
|
-
: node.width
|
|
154
|
-
? `${node.width}${node.widthUnit || "px"}`
|
|
155
|
-
: ""
|
|
156
|
-
}
|
|
163
|
+
value={getDisplaySize(node, "width", previewDevice, sizeWithStyle)}
|
|
157
164
|
/>
|
|
158
165
|
x
|
|
159
166
|
<input
|
|
@@ -162,13 +169,7 @@ const BoxModelEditor = ({ setProp, node, sizeWithStyle }) => {
|
|
|
162
169
|
autoComplete="off"
|
|
163
170
|
name="boxmodel-ex-1_height"
|
|
164
171
|
size="3"
|
|
165
|
-
value={
|
|
166
|
-
sizeWithStyle
|
|
167
|
-
? style["height"]
|
|
168
|
-
: node.height
|
|
169
|
-
? `${node.height}${node.heightUnit || "px"}`
|
|
170
|
-
: ""
|
|
171
|
-
}
|
|
172
|
+
value={getDisplaySize(node, "height", previewDevice, sizeWithStyle)}
|
|
172
173
|
/>
|
|
173
174
|
</div>
|
|
174
175
|
<span
|
|
@@ -276,13 +277,13 @@ const BoxModelEditor = ({ setProp, node, sizeWithStyle }) => {
|
|
|
276
277
|
<SettingsRow
|
|
277
278
|
field={{
|
|
278
279
|
name: "width",
|
|
279
|
-
label: t("width"),
|
|
280
|
+
label: t("width") + deviceLabel,
|
|
280
281
|
type: "DimUnits",
|
|
281
282
|
horiz: true,
|
|
282
283
|
}}
|
|
283
|
-
node={node}
|
|
284
|
-
setProp={setProp}
|
|
285
|
-
isStyle={!!sizeWithStyle}
|
|
284
|
+
node={isDesktop ? node : getDeviceSizeNode(node, "width", previewDevice)}
|
|
285
|
+
setProp={isDesktop ? setProp : getDeviceSizeSetProp(setProp, "width", previewDevice)}
|
|
286
|
+
isStyle={isDesktop ? !!sizeWithStyle : true}
|
|
286
287
|
/>
|
|
287
288
|
<SettingsRow
|
|
288
289
|
field={{
|
|
@@ -307,10 +308,10 @@ const BoxModelEditor = ({ setProp, node, sizeWithStyle }) => {
|
|
|
307
308
|
isStyle={true}
|
|
308
309
|
/>
|
|
309
310
|
<SettingsRow
|
|
310
|
-
field={{ name: "height", label: t("height"), type: "DimUnits" }}
|
|
311
|
-
node={node}
|
|
312
|
-
setProp={setProp}
|
|
313
|
-
isStyle={!!sizeWithStyle}
|
|
311
|
+
field={{ name: "height", label: t("height") + deviceLabel, type: "DimUnits" }}
|
|
312
|
+
node={isDesktop ? node : getDeviceSizeNode(node, "height", previewDevice)}
|
|
313
|
+
setProp={isDesktop ? setProp : getDeviceSizeSetProp(setProp, "height", previewDevice)}
|
|
314
|
+
isStyle={isDesktop ? !!sizeWithStyle : true}
|
|
314
315
|
/>
|
|
315
316
|
<SettingsRow
|
|
316
317
|
field={{
|