@saltcorn/builder 0.6.4 → 0.7.0-beta.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.
@@ -53,7 +53,7 @@ const Link = ({
53
53
  <span
54
54
  className={`${textStyle} is-builder-link ${
55
55
  selected ? "selected-node" : ""
56
- } ${isFormula.text ? "text-monospace" : ""} ${link_style} ${link_size}`}
56
+ } ${isFormula.text ? "font-monospace" : ""} ${link_style} ${link_size}`}
57
57
  {...blockProps(block)}
58
58
  ref={(dom) => connect(drag(dom))}
59
59
  style={
@@ -66,7 +66,7 @@ const Link = ({
66
66
  : {}
67
67
  }
68
68
  >
69
- <DynamicFontAwesomeIcon icon={link_icon} className="mr-1" />
69
+ <DynamicFontAwesomeIcon icon={link_icon} className="me-1" />
70
70
  {isFormula.text ? `=${text}` : text}
71
71
  </span>
72
72
  );
@@ -139,7 +139,7 @@ const LinkSettings = () => {
139
139
  <td>
140
140
  <select
141
141
  value={link_src}
142
- className="form-control"
142
+ className="form-control form-select"
143
143
  onChange={(e) =>
144
144
  setProp((prop) => {
145
145
  prop.link_src = e.target.value;
@@ -181,7 +181,7 @@ const LinkSettings = () => {
181
181
  <td>
182
182
  <select
183
183
  value={url}
184
- className="form-control"
184
+ className="form-control form-select"
185
185
  onChange={setAProp("url")}
186
186
  >
187
187
  <option></option>
@@ -200,7 +200,7 @@ const LinkSettings = () => {
200
200
  <td>
201
201
  <select
202
202
  value={url}
203
- className="form-control"
203
+ className="form-control form-select"
204
204
  onChange={setAProp("url")}
205
205
  >
206
206
  <option></option>
@@ -39,11 +39,10 @@ const SearchBar = ({ has_dropdown, children, show_badges }) => {
39
39
  connect(drag(dom));
40
40
  }}
41
41
  >
42
- <div className="input-group-prepend">
43
- <button className="btn btn-outline-secondary" disabled>
44
- <i className="fas fa-search"></i>
45
- </button>
46
- </div>
42
+ <button className="btn btn-outline-secondary" disabled>
43
+ <i className="fas fa-search"></i>
44
+ </button>
45
+
47
46
  <input
48
47
  type="text"
49
48
  className="form-control bg-light"
@@ -51,31 +50,29 @@ const SearchBar = ({ has_dropdown, children, show_badges }) => {
51
50
  disabled
52
51
  />
53
52
 
54
- <div className="input-group-append">
55
- {show_badges && (
56
- <div className="input-group-text">
57
- <span className="badge badge-primary">X:Y</span>
53
+ {show_badges && (
54
+ <div className="input-group-text">
55
+ <span className="badge bg-primary">X:Y</span>
56
+ </div>
57
+ )}
58
+ {has_dropdown && (
59
+ <Fragment>
60
+ <button
61
+ className="btn btn-outline-secondary"
62
+ onClick={() => setDropdown(!showDropdown)}
63
+ >
64
+ <FontAwesomeIcon icon={faCaretDown} />
65
+ </button>
66
+ <div
67
+ className={`dropdown-menu searchbar-dropdown ${
68
+ showDropdown ? "show" : ""
69
+ }`}
70
+ style={{ width: dropWidth, left: 0 }}
71
+ >
72
+ <div className="canvas">{children}</div>
58
73
  </div>
59
- )}
60
- {has_dropdown && (
61
- <Fragment>
62
- <button
63
- className="btn btn-outline-secondary"
64
- onClick={() => setDropdown(!showDropdown)}
65
- >
66
- <FontAwesomeIcon icon={faCaretDown} />
67
- </button>
68
- <div
69
- className={`dropdown-menu searchbar-dropdown ${
70
- showDropdown ? "show" : ""
71
- }`}
72
- style={{ width: dropWidth, left: 0 }}
73
- >
74
- <div className="canvas">{children}</div>
75
- </div>
76
- </Fragment>
77
- )}
78
- </div>
74
+ </Fragment>
75
+ )}
79
76
  </div>
80
77
  );
81
78
  };
@@ -128,12 +128,14 @@ const TabsSettings = () => {
128
128
  tabsStyle: node.data.props.tabsStyle,
129
129
  ntabs: node.data.props.ntabs,
130
130
  independent: node.data.props.independent,
131
+ deeplink: node.data.props.deeplink,
131
132
  titles: node.data.props.titles,
132
133
  }));
133
134
  const {
134
135
  actions: { setProp },
135
136
  titles,
136
137
  tabsStyle,
138
+ deeplink,
137
139
  independent,
138
140
  ntabs,
139
141
  } = node;
@@ -147,7 +149,7 @@ const TabsSettings = () => {
147
149
  <td>
148
150
  <select
149
151
  value={tabsStyle}
150
- className="form-control"
152
+ className="form-control form-select"
151
153
  onChange={(e) =>
152
154
  setProp((prop) => {
153
155
  prop.tabsStyle = e.target.value;
@@ -194,7 +196,7 @@ const TabsSettings = () => {
194
196
  </td>
195
197
  </tr>
196
198
  ))}
197
- {tabsStyle === "Accordion" && (
199
+ {tabsStyle === "Accordion" ? (
198
200
  <tr>
199
201
  <td colSpan="2">
200
202
  <div className="form-check">
@@ -213,6 +215,25 @@ const TabsSettings = () => {
213
215
  </div>
214
216
  </td>
215
217
  </tr>
218
+ ) : (
219
+ <tr>
220
+ <td colSpan="2">
221
+ <div className="form-check">
222
+ <input
223
+ className="form-check-input"
224
+ name="block"
225
+ type="checkbox"
226
+ checked={deeplink}
227
+ onChange={(e) => {
228
+ if (e.target) {
229
+ setProp((prop) => (prop.deeplink = e.target.checked));
230
+ }
231
+ }}
232
+ />
233
+ <label className="form-check-label">Deep link</label>
234
+ </div>
235
+ </td>
236
+ </tr>
216
237
  )}
217
238
  </tbody>
218
239
  </table>
@@ -228,6 +249,7 @@ Tabs.craft = {
228
249
  ntabs: 2,
229
250
  tabsStyle: "Tabs",
230
251
  independent: false,
252
+ deeplink: true,
231
253
  },
232
254
  displayName: "Tabs",
233
255
  related: {
@@ -15,6 +15,8 @@ import {
15
15
  TextStyleRow,
16
16
  DynamicFontAwesomeIcon,
17
17
  isBlock,
18
+ reactifyStyles,
19
+ SettingsRow,
18
20
  } from "./utils";
19
21
  import ContentEditable from "react-contenteditable";
20
22
  import optionsCtx from "../context";
@@ -74,7 +76,16 @@ export /**
74
76
  * @category saltcorn-builder
75
77
  * @subcategory components
76
78
  */
77
- const Text = ({ text, block, inline, isFormula, textStyle, icon, font }) => {
79
+ const Text = ({
80
+ text,
81
+ block,
82
+ inline,
83
+ isFormula,
84
+ textStyle,
85
+ icon,
86
+ font,
87
+ style,
88
+ }) => {
78
89
  const {
79
90
  connectors: { connect, drag },
80
91
  selected,
@@ -92,14 +103,17 @@ const Text = ({ text, block, inline, isFormula, textStyle, icon, font }) => {
92
103
  <div
93
104
  className={`${
94
105
  isBlock(block, inline, textStyle) ? "d-block" : "d-inline-block"
95
- } ${textStyle} is-text ${isFormula.text ? "text-monospace" : ""} ${
106
+ } ${textStyle} is-text ${isFormula.text ? "font-monospace" : ""} ${
96
107
  selected ? "selected-node" : ""
97
108
  }`}
98
109
  ref={(dom) => connect(drag(dom))}
99
110
  onClick={(e) => selected && setEditable(true)}
100
- style={font ? { fontFamily: font } : {}}
111
+ style={{
112
+ ...(font ? { fontFamily: font } : {}),
113
+ ...reactifyStyles(style || {}),
114
+ }}
101
115
  >
102
- <DynamicFontAwesomeIcon icon={icon} className="mr-1" />
116
+ <DynamicFontAwesomeIcon icon={icon} className="me-1" />
103
117
  {isFormula.text ? (
104
118
  <Fragment>
105
119
  =
@@ -146,6 +160,7 @@ const TextSettings = () => {
146
160
  labelFor: node.data.props.labelFor,
147
161
  icon: node.data.props.icon,
148
162
  font: node.data.props.font,
163
+ style: node.data.props.style,
149
164
  }));
150
165
  const {
151
166
  actions: { setProp },
@@ -157,6 +172,7 @@ const TextSettings = () => {
157
172
  labelFor,
158
173
  icon,
159
174
  font,
175
+ style,
160
176
  } = node;
161
177
  const { mode, fields } = useContext(optionsCtx);
162
178
  const setAProp = (key) => (e) => {
@@ -208,7 +224,11 @@ const TextSettings = () => {
208
224
  {mode === "edit" && (
209
225
  <Fragment>
210
226
  <label>Label for Field</label>
211
- <select value={labelFor} onChange={setAProp("labelFor")}>
227
+ <select
228
+ value={labelFor}
229
+ onChange={setAProp("labelFor")}
230
+ className="form-control form-select"
231
+ >
212
232
  <option value={""}></option>
213
233
  {fields.map((f, ix) => (
214
234
  <option key={ix} value={f.name}>
@@ -235,19 +255,48 @@ const TextSettings = () => {
235
255
  />
236
256
  </td>
237
257
  </tr>
238
- <tr>
239
- <td>
240
- <label>Font</label>
241
- </td>
242
- <td>
243
- <input
244
- type="text"
245
- className="form-control"
246
- value={font}
247
- onChange={setAProp("font")}
248
- />
249
- </td>
250
- </tr>
258
+ <SettingsRow
259
+ field={{
260
+ name: "font",
261
+ label: "Font family",
262
+ type: "Font",
263
+ }}
264
+ node={node}
265
+ setProp={setProp}
266
+ />
267
+ <SettingsRow
268
+ field={{
269
+ name: "font-size",
270
+ label: "Font size",
271
+ type: "DimUnits",
272
+ }}
273
+ node={node}
274
+ setProp={setProp}
275
+ isStyle={true}
276
+ />
277
+ <SettingsRow
278
+ field={{
279
+ name: "font-weight",
280
+ label: "Weight",
281
+ type: "Integer",
282
+ min: 100,
283
+ max: 900,
284
+ step: 100,
285
+ }}
286
+ node={node}
287
+ setProp={setProp}
288
+ isStyle={true}
289
+ />
290
+ <SettingsRow
291
+ field={{
292
+ name: "line-height",
293
+ label: "Line height",
294
+ type: "DimUnits",
295
+ }}
296
+ node={node}
297
+ setProp={setProp}
298
+ isStyle={true}
299
+ />
251
300
  </tbody>
252
301
  </table>
253
302
  <BlockOrInlineSetting
@@ -272,6 +321,7 @@ Text.craft = {
272
321
  textStyle: "",
273
322
  labelFor: "",
274
323
  font: "",
324
+ style: {},
275
325
  },
276
326
  displayName: "Text",
277
327
  related: {
@@ -94,7 +94,7 @@ const ToggleFilterSettings = () => {
94
94
  <td>
95
95
  <select
96
96
  value={name}
97
- className="form-control"
97
+ className="form-control form-select"
98
98
  onChange={(e) => {
99
99
  setProp((prop) => (prop.name = e.target.value));
100
100
  const field = options.fields.find(
@@ -121,7 +121,7 @@ const ToggleFilterSettings = () => {
121
121
  {isBool ? (
122
122
  <select
123
123
  value={value}
124
- className="w-100"
124
+ className="w-100 form-select"
125
125
  onChange={setAProp("value")}
126
126
  >
127
127
  <option value="on">True</option>
@@ -145,7 +145,7 @@ const ToggleFilterSettings = () => {
145
145
  <td>
146
146
  <select
147
147
  value={preset_value}
148
- className="form-control"
148
+ className="form-control form-select"
149
149
  onChange={setAProp("preset_value")}
150
150
  >
151
151
  <option value=""></option>
@@ -176,7 +176,7 @@ const ToggleFilterSettings = () => {
176
176
  </td>
177
177
  <td>
178
178
  <select
179
- className="form-control"
179
+ className="form-control form-select"
180
180
  value={size}
181
181
  onChange={setAProp("size")}
182
182
  >
@@ -195,7 +195,7 @@ const ToggleFilterSettings = () => {
195
195
  </td>
196
196
  <td>
197
197
  <select
198
- className="form-control"
198
+ className="form-control form-select"
199
199
  value={style}
200
200
  onChange={setAProp("style")}
201
201
  >
@@ -109,7 +109,7 @@ const ViewSettings = () => {
109
109
  <label>View to {options.mode === "show" ? "embed" : "show"}</label>
110
110
  <select
111
111
  value={view}
112
- className="form-control"
112
+ className="form-control form-select"
113
113
  onChange={(e) => {
114
114
  setProp((prop) => (prop.view = e.target.value));
115
115
  }}
@@ -127,7 +127,7 @@ const ViewSettings = () => {
127
127
  <label>State</label>
128
128
  <select
129
129
  value={state}
130
- className="form-control"
130
+ className="form-control form-select"
131
131
  onChange={setAProp("state")}
132
132
  >
133
133
  <option value="shared">Shared</option>
@@ -72,7 +72,7 @@ const ViewLink = ({
72
72
  : {}
73
73
  }
74
74
  >
75
- {link_icon ? <i className={`${link_icon} mr-1`}></i> : ""}
75
+ {link_icon ? <i className={`${link_icon} me-1`}></i> : ""}
76
76
  {displabel}
77
77
  </span>
78
78
  );
@@ -120,7 +120,7 @@ const ViewLinkSettings = () => {
120
120
  <label>View to link to</label>
121
121
  <select
122
122
  value={name}
123
- className="form-control"
123
+ className="form-control form-select"
124
124
  onChange={(e) =>
125
125
  setProp((prop) => (prop.name = e.target.value))
126
126
  }
@@ -130,22 +130,21 @@ const OrFormula = ({ setProp, isFormula, node, nodekey, children }) => {
130
130
  ) : (
131
131
  children
132
132
  )}
133
- <div className="input-group-append">
134
- <button
135
- className={`btn activate-formula ${
136
- isFormula[nodekey] ? "btn-secondary" : "btn-outline-secondary"
137
- }`}
138
- title="Calculated formula"
139
- type="button"
140
- onClick={switchIsFml}
141
- >
142
- <i className="fas fa-calculator"></i>
143
- </button>
144
- </div>
133
+
134
+ <button
135
+ className={`btn activate-formula ${
136
+ isFormula[nodekey] ? "btn-secondary" : "btn-outline-secondary"
137
+ }`}
138
+ title="Calculated formula"
139
+ type="button"
140
+ onClick={switchIsFml}
141
+ >
142
+ <i className="fas fa-calculator"></i>
143
+ </button>
145
144
  </div>
146
145
  {isFormula[nodekey] && (
147
146
  <div style={{ marginTop: "-5px" }}>
148
- <small className="text-muted text-monospace">FORMULA</small>
147
+ <small className="text-muted font-monospace">FORMULA</small>
149
148
  </div>
150
149
  )}
151
150
  </Fragment>
@@ -167,6 +166,7 @@ const MinRoleSetting = ({ minRole, setProp }) => {
167
166
  <div>
168
167
  <label>Minimum Role</label>
169
168
  <select
169
+ className="form-control form-select"
170
170
  value={minRole}
171
171
  onChange={(e) => (e) => {
172
172
  if (e.target) {
@@ -204,7 +204,7 @@ const MinRoleSettingRow = ({ minRole, setProp }) => {
204
204
  <td>
205
205
  <select
206
206
  value={minRole}
207
- className="form-control"
207
+ className="form-control form-select"
208
208
  onChange={(e) => {
209
209
  if (e.target) {
210
210
  const target_value = e.target.value;
@@ -236,7 +236,7 @@ const TextStyleSelect = ({ textStyle, setProp }) => {
236
236
  return (
237
237
  <select
238
238
  value={textStyle}
239
- className="form-control"
239
+ className="form-control form-select"
240
240
  onChange={(e) => {
241
241
  if (e.target) {
242
242
  const target_value = e.target.value;
@@ -251,12 +251,12 @@ const TextStyleSelect = ({ textStyle, setProp }) => {
251
251
  <option value="h4">Heading 4</option>
252
252
  <option value="h5">Heading 5</option>
253
253
  <option value="h6">Heading 6</option>
254
- <option value="font-weight-bold">Bold</option>
255
- <option value="font-italic">Italics</option>
254
+ <option value="fw-bold">Bold</option>
255
+ <option value="fst-italic">Italics</option>
256
256
  <option value="small">Small</option>
257
257
  <option value="text-muted">Muted</option>
258
258
  <option value="text-underline">Underline</option>
259
- <option value="text-monospace">Monospace</option>
259
+ <option value="font-monospace">Monospace</option>
260
260
  </select>
261
261
  );
262
262
  };
@@ -321,7 +321,7 @@ const Accordion = ({ titles, children }) => {
321
321
  <div
322
322
  className={`bg-${
323
323
  isCurrent ? "primary" : "secondary"
324
- } pl-1 text-white w-100 mt-1`}
324
+ } ps-1 text-white w-100 mt-1`}
325
325
  onClick={() => setCurrentTab(ix)}
326
326
  >
327
327
  <span className="w-1em">
@@ -565,12 +565,12 @@ export /**
565
565
  const ConfigForm = ({ fields, configuration, setProp, node, onChange }) => (
566
566
  <div>
567
567
  {fields.map((f, ix) => {
568
- if (f.showIf && node && node.configuration) {
568
+ if (f.showIf && configuration) {
569
569
  let noshow = false;
570
570
  Object.entries(f.showIf).forEach(([nm, value]) => {
571
571
  if (Array.isArray(value))
572
- noshow = noshow || value.includes(node.configuration[nm]);
573
- else noshow = noshow || value !== node.configuration[nm];
572
+ noshow = noshow || value.includes(configuration[nm]);
573
+ else noshow = noshow || value !== configuration[nm];
574
574
  });
575
575
  if (noshow) return null;
576
576
  }
@@ -625,6 +625,8 @@ const ConfigField = ({
625
625
  * @param {object} v
626
626
  * @returns {void}
627
627
  */
628
+ const options = useContext(optionsCtx);
629
+
628
630
  const myOnChange = (v) => {
629
631
  setProp((prop) => {
630
632
  if (configuration) {
@@ -660,7 +662,7 @@ const ConfigField = ({
660
662
  : field.attributes.options;
661
663
  return (
662
664
  <select
663
- className="form-control"
665
+ className="form-control form-select"
664
666
  value={value || ""}
665
667
  onChange={(e) => e.target && myOnChange(e.target.value)}
666
668
  >
@@ -684,6 +686,20 @@ const ConfigField = ({
684
686
  />
685
687
  );
686
688
  },
689
+ Font: () => (
690
+ <select
691
+ className="form-control form-select"
692
+ value={value || ""}
693
+ onChange={(e) => e.target && myOnChange(e.target.value)}
694
+ >
695
+ <option value={""}></option>
696
+ {Object.entries(options.fonts || {}).map(([nm, ff], ix) => (
697
+ <option key={ix} value={ff}>
698
+ {nm}
699
+ </option>
700
+ ))}
701
+ </select>
702
+ ),
687
703
  Integer: () => (
688
704
  <input
689
705
  type="number"
@@ -736,7 +752,7 @@ const ConfigField = ({
736
752
  ),
737
753
  select: () => (
738
754
  <select
739
- className="form-control"
755
+ className="form-control form-select"
740
756
  value={value || ""}
741
757
  onChange={(e) => e.target && myOnChange(e.target.value)}
742
758
  >
@@ -1031,7 +1047,7 @@ const ButtonOrLinkSettingsRows = ({
1031
1047
  </td>
1032
1048
  <td>
1033
1049
  <select
1034
- className="form-control"
1050
+ className="form-control form-select"
1035
1051
  value={values[keyPrefix + "style"]}
1036
1052
  onChange={setAProp(keyPrefix + "style")}
1037
1053
  >
@@ -1063,7 +1079,7 @@ const ButtonOrLinkSettingsRows = ({
1063
1079
  </td>
1064
1080
  <td>
1065
1081
  <select
1066
- className="form-control"
1082
+ className="form-control form-select"
1067
1083
  value={values[keyPrefix + "size"]}
1068
1084
  onChange={setAProp(keyPrefix + "size")}
1069
1085
  >
@@ -25,6 +25,7 @@ import { SearchBar } from "./elements/SearchBar";
25
25
  import { Container } from "./elements/Container";
26
26
  import { DropDownFilter } from "./elements/DropDownFilter";
27
27
  import { ToggleFilter } from "./elements/ToggleFilter";
28
+ import { DropMenu } from "./elements/DropMenu";
28
29
 
29
30
  /**
30
31
  * @param {object} segment
@@ -69,6 +70,7 @@ const allElements = [
69
70
  DropDownFilter,
70
71
  Tabs,
71
72
  ToggleFilter,
73
+ DropMenu,
72
74
  ];
73
75
 
74
76
  export /**
@@ -128,6 +130,7 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
128
130
  inline={segment.inline || false}
129
131
  textStyle={segment.textStyle || ""}
130
132
  labelFor={segment.labelFor || ""}
133
+ style={segment.style || {}}
131
134
  icon={segment.icon}
132
135
  font={segment.font || ""}
133
136
  />
@@ -225,6 +228,7 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
225
228
  titles={segment.titles}
226
229
  ntabs={segment.ntabs}
227
230
  independent={segment.independent}
231
+ deeplink={segment.deeplink}
228
232
  tabsStyle={segment.tabsStyle}
229
233
  contents={segment.contents.map(toTag)}
230
234
  />
@@ -394,6 +398,7 @@ const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
394
398
  textStyle: node.props.textStyle,
395
399
  isFormula: node.props.isFormula,
396
400
  labelFor: node.props.labelFor,
401
+ style: node.props.style,
397
402
  icon: node.props.icon,
398
403
  font: node.props.font,
399
404
  };
@@ -417,6 +422,7 @@ const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
417
422
  titles: node.props.titles,
418
423
  tabsStyle: node.props.tabsStyle,
419
424
  independent: node.props.independent,
425
+ deeplink: node.props.deeplink,
420
426
  ntabs: node.props.ntabs,
421
427
  };
422
428
  }