@saltcorn/builder 1.0.0 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/builder",
3
- "version": "1.0.0",
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.0.0",
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={faIcons}
274
+ icons={options.icons}
276
275
  onChange={setIcon}
277
276
  isMulti={false}
278
277
  />
@@ -284,6 +284,7 @@ const ActionSettings = () => {
284
284
  keyPrefix="action_"
285
285
  values={node}
286
286
  allowRunOnLoad={true}
287
+ faIcons={options.icons}
287
288
  />
288
289
  <MinRoleSettingRow minRole={minRole} setProp={setProp} />
289
290
  </tbody>
@@ -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">
@@ -82,7 +82,7 @@ const DropDownFilterSettings = () => {
82
82
  <td>
83
83
  <select
84
84
  value={name}
85
- className="form-control form-select"
85
+ className="field form-control form-select"
86
86
  onChange={setAProp("name")}
87
87
  >
88
88
  {options.fields.map((f, ix) => (
@@ -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;
@@ -216,7 +216,7 @@ const ImageSettings = () => {
216
216
  <td>
217
217
  <select
218
218
  value={field}
219
- className="form-control form-select"
219
+ className="field form-control form-select"
220
220
  onChange={setAProp("field")}
221
221
  >
222
222
  <option value=""></option>
@@ -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
  };
@@ -283,6 +283,7 @@ const LinkSettings = () => {
283
283
  linkFirst={true}
284
284
  linkIsBlank={true}
285
285
  allowRunOnLoad={false}
286
+ faIcons={options.icons}
286
287
  />
287
288
  </tbody>
288
289
  </table>
@@ -150,7 +150,7 @@ const fields = [
150
150
  required: true,
151
151
  attributes: {
152
152
  inline: true,
153
- options: ["px", "%", "vw", "em", "rem"],
153
+ options: ["px", "%", "vw", "em", "rem", "cm"],
154
154
  },
155
155
  },
156
156
  {
@@ -258,7 +258,7 @@ const TabsSettings = () => {
258
258
  <td>
259
259
  <select
260
260
  value={field}
261
- className="form-control form-select"
261
+ className="field form-control form-select"
262
262
  onChange={setAProp("field")}
263
263
  >
264
264
  {options.fields.map((f, ix) => (
@@ -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} is-text ${isFormula.text ? "font-monospace" : ""} ${
108
- selected ? "selected-node" : ""
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={faIcons}
253
+ icons={icons}
255
254
  onChange={(value) => setProp((prop) => (prop.icon = value))}
256
255
  isMulti={false}
257
256
  />
@@ -90,7 +90,7 @@ const ToggleFilterSettings = () => {
90
90
  <td>
91
91
  <select
92
92
  value={name}
93
- className="form-control form-select"
93
+ className="field form-control form-select"
94
94
  onChange={(e) => {
95
95
  if (e?.target) {
96
96
  if (!e.target) return;
@@ -331,6 +331,7 @@ const ViewLinkSettings = () => {
331
331
  linkFirst={true}
332
332
  linkIsBlank={true}
333
333
  allowRunOnLoad={false}
334
+ faIcons={options.icons}
334
335
  />
335
336
  </tbody>
336
337
  </table>