@saltcorn/builder 1.0.0-rc.9 → 1.1.0-beta.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/dist/builder_bundle.js +2 -92
- package/package.json +2 -2
- package/src/components/Builder.js +11 -1
- package/src/components/Library.js +1 -2
- package/src/components/elements/Action.js +1 -0
- package/src/components/elements/Aggregation.js +4 -4
- package/src/components/elements/Columns.js +1 -1
- package/src/components/elements/Container.js +56 -0
- package/src/components/elements/DropDownFilter.js +1 -1
- package/src/components/elements/DropMenu.js +4 -1
- package/src/components/elements/Field.js +4 -4
- package/src/components/elements/Image.js +1 -1
- package/src/components/elements/JoinField.js +2 -2
- package/src/components/elements/LineBreak.js +11 -4
- package/src/components/elements/Link.js +1 -0
- package/src/components/elements/ListColumn.js +1 -1
- package/src/components/elements/Tabs.js +1 -1
- package/src/components/elements/Text.js +5 -6
- package/src/components/elements/ToggleFilter.js +1 -1
- package/src/components/elements/ViewLink.js +1 -0
- package/src/components/elements/utils.js +112 -22
- package/src/components/elements/faicons.js +0 -1643
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/builder",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0-beta.0",
|
|
4
4
|
"description": "Drag and drop view builder for Saltcorn, open-source no-code platform",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"homepage": "https://saltcorn.com",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"@babel/preset-react": "7.24.7",
|
|
21
21
|
"@craftjs/core": "0.1.0-beta.20",
|
|
22
22
|
"@craftjs/utils": "0.1.0-beta.20",
|
|
23
|
-
"@saltcorn/common-code": "1.
|
|
23
|
+
"@saltcorn/common-code": "1.1.0-beta.0",
|
|
24
24
|
"saltcorn-craft-layers-noeye": "0.1.0-beta.22",
|
|
25
25
|
"@fonticonpicker/react-fonticonpicker": "1.2.0",
|
|
26
26
|
"@fortawesome/fontawesome-svg-core": "1.2.34",
|
|
@@ -411,7 +411,6 @@ const Builder = ({ options, layout, mode }) => {
|
|
|
411
411
|
|
|
412
412
|
const canvasHeight =
|
|
413
413
|
Math.max(windowHeight - builderTop, builderHeight, 600) - 10;
|
|
414
|
-
|
|
415
414
|
return (
|
|
416
415
|
<ErrorBoundary>
|
|
417
416
|
<Editor onRender={RenderNode}>
|
|
@@ -558,6 +557,17 @@ const Builder = ({ options, layout, mode }) => {
|
|
|
558
557
|
</Provider>
|
|
559
558
|
<div className="d-none preview-scratchpad"></div>
|
|
560
559
|
</Editor>
|
|
560
|
+
<style>
|
|
561
|
+
{options.icons
|
|
562
|
+
.filter((icon) => icon.startsWith("unicode-"))
|
|
563
|
+
.map(
|
|
564
|
+
(icon) =>
|
|
565
|
+
`i.${icon}:after {content: '${String.fromCharCode(
|
|
566
|
+
parseInt(icon.substring(8, 12), 16)
|
|
567
|
+
)}'}`
|
|
568
|
+
)
|
|
569
|
+
.join("\n")}
|
|
570
|
+
</style>
|
|
561
571
|
</ErrorBoundary>
|
|
562
572
|
);
|
|
563
573
|
};
|
|
@@ -16,7 +16,6 @@ import { useEditor, useNode } from "@craftjs/core";
|
|
|
16
16
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
17
17
|
import { faPlus, faTimes } from "@fortawesome/free-solid-svg-icons";
|
|
18
18
|
import FontIconPicker from "@fonticonpicker/react-fonticonpicker";
|
|
19
|
-
import faIcons from "./elements/faicons";
|
|
20
19
|
import { craftToSaltcorn, layoutToNodes } from "./storage";
|
|
21
20
|
import optionsCtx from "./context";
|
|
22
21
|
import { WrapElem } from "./Toolbox";
|
|
@@ -272,7 +271,7 @@ const Library = ({ expanded }) => {
|
|
|
272
271
|
<FontIconPicker
|
|
273
272
|
className="w-100"
|
|
274
273
|
value={icon}
|
|
275
|
-
icons={
|
|
274
|
+
icons={options.icons}
|
|
276
275
|
onChange={setIcon}
|
|
277
276
|
isMulti={false}
|
|
278
277
|
/>
|
|
@@ -127,7 +127,7 @@ const AggregationSettings = () => {
|
|
|
127
127
|
</td>
|
|
128
128
|
<td>
|
|
129
129
|
<select
|
|
130
|
-
className="form-control form-select"
|
|
130
|
+
className="relation form-control form-select"
|
|
131
131
|
value={agg_relation}
|
|
132
132
|
onChange={(e) => {
|
|
133
133
|
if (!e.target) return;
|
|
@@ -156,7 +156,7 @@ const AggregationSettings = () => {
|
|
|
156
156
|
</td>
|
|
157
157
|
<td>
|
|
158
158
|
<select
|
|
159
|
-
className="form-control form-select"
|
|
159
|
+
className="agg_field form-control form-select"
|
|
160
160
|
value={agg_field}
|
|
161
161
|
onChange={setAProp("agg_field")}
|
|
162
162
|
>
|
|
@@ -175,7 +175,7 @@ const AggregationSettings = () => {
|
|
|
175
175
|
<td>
|
|
176
176
|
<select
|
|
177
177
|
value={stat}
|
|
178
|
-
className="form-control form-select"
|
|
178
|
+
className="stat form-control form-select"
|
|
179
179
|
onChange={setAProp("stat")}
|
|
180
180
|
onBlur={setAProp("stat")}
|
|
181
181
|
>
|
|
@@ -245,7 +245,7 @@ const AggregationSettings = () => {
|
|
|
245
245
|
<td>
|
|
246
246
|
<select
|
|
247
247
|
value={agg_fieldview}
|
|
248
|
-
className="form-control form-select"
|
|
248
|
+
className="agg_fieldview form-control form-select"
|
|
249
249
|
onChange={(e) => {
|
|
250
250
|
if (!e.target) return;
|
|
251
251
|
const value = e.target.value;
|
|
@@ -93,7 +93,7 @@ const Columns = ({
|
|
|
93
93
|
} = useNode((node) => ({ selected: node.events.selected }));
|
|
94
94
|
return (
|
|
95
95
|
<div
|
|
96
|
-
className={`row ${selected ? "selected-node" : ""} ${
|
|
96
|
+
className={`row builder-columns ${selected ? "selected-node" : ""} ${
|
|
97
97
|
typeof gx !== "undefined" && gx !== null ? `gx-${gx}` : ""
|
|
98
98
|
} ${typeof gy !== "undefined" && gy !== null ? `gy-${gy}` : ""}`}
|
|
99
99
|
ref={(dom) => connect(drag(dom))}
|
|
@@ -253,6 +253,7 @@ const ContainerSettings = () => {
|
|
|
253
253
|
htmlElement,
|
|
254
254
|
imgResponsiveWidths,
|
|
255
255
|
click_action,
|
|
256
|
+
style,
|
|
256
257
|
} = node;
|
|
257
258
|
const options = useContext(optionsCtx);
|
|
258
259
|
const { uploadedFiles } = useContext(previewCtx);
|
|
@@ -331,6 +332,61 @@ const ContainerSettings = () => {
|
|
|
331
332
|
node={node}
|
|
332
333
|
setProp={setProp}
|
|
333
334
|
/>
|
|
335
|
+
<SettingsRow
|
|
336
|
+
field={{
|
|
337
|
+
name: "position",
|
|
338
|
+
label: "Position",
|
|
339
|
+
type: "select",
|
|
340
|
+
options: ["static", "relative", "fixed", "absolute", "sticky"],
|
|
341
|
+
}}
|
|
342
|
+
node={node}
|
|
343
|
+
setProp={setProp}
|
|
344
|
+
isStyle={true}
|
|
345
|
+
/>
|
|
346
|
+
{style?.position && style?.position !== "static" ? (
|
|
347
|
+
<Fragment>
|
|
348
|
+
<SettingsRow
|
|
349
|
+
field={{
|
|
350
|
+
name: "top",
|
|
351
|
+
label: "Top",
|
|
352
|
+
type: "DimUnits",
|
|
353
|
+
}}
|
|
354
|
+
node={node}
|
|
355
|
+
setProp={setProp}
|
|
356
|
+
isStyle={true}
|
|
357
|
+
/>
|
|
358
|
+
<SettingsRow
|
|
359
|
+
field={{
|
|
360
|
+
name: "right",
|
|
361
|
+
label: "Right",
|
|
362
|
+
type: "DimUnits",
|
|
363
|
+
}}
|
|
364
|
+
node={node}
|
|
365
|
+
setProp={setProp}
|
|
366
|
+
isStyle={true}
|
|
367
|
+
/>
|
|
368
|
+
<SettingsRow
|
|
369
|
+
field={{
|
|
370
|
+
name: "bottom",
|
|
371
|
+
label: "Bottom",
|
|
372
|
+
type: "DimUnits",
|
|
373
|
+
}}
|
|
374
|
+
node={node}
|
|
375
|
+
setProp={setProp}
|
|
376
|
+
isStyle={true}
|
|
377
|
+
/>
|
|
378
|
+
<SettingsRow
|
|
379
|
+
field={{
|
|
380
|
+
name: "left",
|
|
381
|
+
label: "Left",
|
|
382
|
+
type: "DimUnits",
|
|
383
|
+
}}
|
|
384
|
+
node={node}
|
|
385
|
+
setProp={setProp}
|
|
386
|
+
isStyle={true}
|
|
387
|
+
/>
|
|
388
|
+
</Fragment>
|
|
389
|
+
) : null}
|
|
334
390
|
<tr>
|
|
335
391
|
<td colSpan="2">
|
|
336
392
|
<div className="form-check">
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* @subcategory components / elements
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import React, { Fragment, useState } from "react";
|
|
7
|
+
import React, { Fragment, useState, useContext } from "react";
|
|
8
|
+
import optionsCtx from "../context";
|
|
8
9
|
import { Element, useNode } from "@craftjs/core";
|
|
9
10
|
import { Column } from "./Column";
|
|
10
11
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
@@ -109,6 +110,7 @@ const DropMenuSettings = () => {
|
|
|
109
110
|
label,
|
|
110
111
|
block,
|
|
111
112
|
} = node;
|
|
113
|
+
const options = useContext(optionsCtx);
|
|
112
114
|
return (
|
|
113
115
|
<table className="w-100">
|
|
114
116
|
<tbody>
|
|
@@ -126,6 +128,7 @@ const DropMenuSettings = () => {
|
|
|
126
128
|
keyPrefix="action_"
|
|
127
129
|
values={node}
|
|
128
130
|
allowRunOnLoad={false}
|
|
131
|
+
faIcons={options.icons}
|
|
129
132
|
/>
|
|
130
133
|
<tr>
|
|
131
134
|
<td colSpan="2">
|
|
@@ -160,7 +160,7 @@ const FieldSettings = () => {
|
|
|
160
160
|
<td>
|
|
161
161
|
<select
|
|
162
162
|
value={name}
|
|
163
|
-
className="form-control form-select"
|
|
163
|
+
className="field form-control form-select"
|
|
164
164
|
onChange={(e) => {
|
|
165
165
|
if (!e.target) return;
|
|
166
166
|
const value = e.target.value;
|
|
@@ -200,7 +200,7 @@ const FieldSettings = () => {
|
|
|
200
200
|
<td>
|
|
201
201
|
<select
|
|
202
202
|
value={fieldview}
|
|
203
|
-
className="form-control form-select"
|
|
203
|
+
className="fieldview form-control form-select"
|
|
204
204
|
onChange={(e) => {
|
|
205
205
|
if (!e.target) return;
|
|
206
206
|
const value = e.target.value;
|
|
@@ -225,7 +225,7 @@ const FieldSettings = () => {
|
|
|
225
225
|
<td>
|
|
226
226
|
<div className="form-check">
|
|
227
227
|
<input
|
|
228
|
-
className="form-check-input"
|
|
228
|
+
className="click-to-edit form-check-input"
|
|
229
229
|
name="inline"
|
|
230
230
|
type="checkbox"
|
|
231
231
|
checked={click_to_edit}
|
|
@@ -275,7 +275,7 @@ const FieldSettings = () => {
|
|
|
275
275
|
<label>On change action</label>
|
|
276
276
|
<select
|
|
277
277
|
value={onchange_action}
|
|
278
|
-
className="form-control form-select"
|
|
278
|
+
className="on-change-action form-control form-select"
|
|
279
279
|
onChange={(e) => {
|
|
280
280
|
if (!e.target) return;
|
|
281
281
|
const value = e.target.value;
|
|
@@ -477,7 +477,7 @@ const JoinFieldSettings = () => {
|
|
|
477
477
|
<td>
|
|
478
478
|
<select
|
|
479
479
|
value={fieldview}
|
|
480
|
-
className="form-control form-select"
|
|
480
|
+
className="fieldview form-control form-select"
|
|
481
481
|
onChange={(e) => {
|
|
482
482
|
if (!e.target) return;
|
|
483
483
|
const value = e.target.value;
|
|
@@ -500,7 +500,7 @@ const JoinFieldSettings = () => {
|
|
|
500
500
|
<td>
|
|
501
501
|
<div className="form-check">
|
|
502
502
|
<input
|
|
503
|
-
className="form-check-input"
|
|
503
|
+
className="click-to-edit form-check-input"
|
|
504
504
|
name="inline"
|
|
505
505
|
type="checkbox"
|
|
506
506
|
checked={click_to_edit}
|
|
@@ -15,12 +15,14 @@ export /**
|
|
|
15
15
|
* @category saltcorn-builder
|
|
16
16
|
* @subcategory components
|
|
17
17
|
*/
|
|
18
|
-
const LineBreak = () => {
|
|
18
|
+
const LineBreak = ({ hr, page_break_after }) => {
|
|
19
19
|
const {
|
|
20
20
|
selected,
|
|
21
21
|
connectors: { connect, drag },
|
|
22
22
|
} = useNode((node) => ({ selected: node.events.selected }));
|
|
23
|
-
return (
|
|
23
|
+
return hr || page_break_after ? (
|
|
24
|
+
<hr></hr>
|
|
25
|
+
) : (
|
|
24
26
|
<Fragment>
|
|
25
27
|
<span
|
|
26
28
|
className={selected ? "selected-node" : ""}
|
|
@@ -33,14 +35,19 @@ const LineBreak = () => {
|
|
|
33
35
|
);
|
|
34
36
|
};
|
|
35
37
|
|
|
38
|
+
const fields = [
|
|
39
|
+
{ label: "Page break", name: "page_break_after", type: "Bool" },
|
|
40
|
+
{ label: "Horizontal rule", name: "hr", type: "Bool" },
|
|
41
|
+
];
|
|
42
|
+
|
|
36
43
|
/**
|
|
37
44
|
* @type {object}
|
|
38
45
|
*/
|
|
39
46
|
LineBreak.craft = {
|
|
40
47
|
displayName: "LineBreak",
|
|
41
48
|
related: {
|
|
42
|
-
settings: SettingsFromFields(
|
|
49
|
+
settings: SettingsFromFields(fields),
|
|
43
50
|
segment_type: "line_break",
|
|
44
|
-
fields
|
|
51
|
+
fields,
|
|
45
52
|
},
|
|
46
53
|
};
|
|
@@ -23,7 +23,6 @@ import ContentEditable from "react-contenteditable";
|
|
|
23
23
|
import optionsCtx from "../context";
|
|
24
24
|
import CKEditor from "ckeditor4-react";
|
|
25
25
|
import FontIconPicker from "@fonticonpicker/react-fonticonpicker";
|
|
26
|
-
import faIcons from "./faicons";
|
|
27
26
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
28
27
|
import fas from "@fortawesome/free-solid-svg-icons";
|
|
29
28
|
import far from "@fortawesome/free-regular-svg-icons";
|
|
@@ -104,9 +103,9 @@ const Text = ({
|
|
|
104
103
|
<div
|
|
105
104
|
className={`${
|
|
106
105
|
isBlock(block, inline, textStyle) ? "d-block" : "d-inline-block"
|
|
107
|
-
} ${textStyle
|
|
108
|
-
|
|
109
|
-
}`}
|
|
106
|
+
} ${Array.isArray(textStyle) ? textStyle.join(" ") : textStyle} is-text ${
|
|
107
|
+
isFormula.text ? "font-monospace" : ""
|
|
108
|
+
} ${selected ? "selected-node" : ""}`}
|
|
110
109
|
ref={(dom) => connect(drag(dom))}
|
|
111
110
|
onClick={(e) => selected && setEditable(true)}
|
|
112
111
|
style={{
|
|
@@ -177,7 +176,7 @@ const TextSettings = () => {
|
|
|
177
176
|
font,
|
|
178
177
|
style,
|
|
179
178
|
} = node;
|
|
180
|
-
const { mode, fields } = useContext(optionsCtx);
|
|
179
|
+
const { mode, fields, icons } = useContext(optionsCtx);
|
|
181
180
|
const setAProp = setAPropGen(setProp);
|
|
182
181
|
const allowFormula = mode === "show" || mode === "list";
|
|
183
182
|
|
|
@@ -251,7 +250,7 @@ const TextSettings = () => {
|
|
|
251
250
|
<FontIconPicker
|
|
252
251
|
className="w-100"
|
|
253
252
|
value={icon}
|
|
254
|
-
icons={
|
|
253
|
+
icons={icons}
|
|
255
254
|
onChange={(value) => setProp((prop) => (prop.icon = value))}
|
|
256
255
|
isMulti={false}
|
|
257
256
|
/>
|