@saltcorn/builder 0.7.3-beta.3 → 0.7.3

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": "0.7.3-beta.3",
3
+ "version": "0.7.3",
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",
@@ -36,7 +36,8 @@
36
36
  "react-dom": "16.13.1",
37
37
  "react-transition-group": "4.4.1",
38
38
  "webpack": "4.43.0",
39
- "webpack-cli": "3.3.11"
39
+ "webpack-cli": "3.3.11",
40
+ "lodash": "4.17.11"
40
41
  },
41
42
  "publishConfig": {
42
43
  "access": "public"
@@ -49,6 +49,7 @@ import {
49
49
  faUndo,
50
50
  faRedo,
51
51
  faTrashAlt,
52
+ faSave,
52
53
  } from "@fortawesome/free-solid-svg-icons";
53
54
  import {
54
55
  Accordion,
@@ -57,6 +58,7 @@ import {
57
58
  } from "./elements/utils";
58
59
  import { InitNewElement, Library } from "./Library";
59
60
  import { RenderNode } from "./RenderNode";
61
+ import { isEqual } from "lodash";
60
62
  const { Provider } = optionsCtx;
61
63
 
62
64
  /**
@@ -387,10 +389,47 @@ const Builder = ({ options, layout, mode }) => {
387
389
  const [previews, setPreviews] = useState({});
388
390
  const [uploadedFiles, setUploadedFiles] = useState([]);
389
391
  const nodekeys = useRef([]);
392
+ const [saveTimeout, setSaveTimeout] = useState(false);
393
+ const [isSaving, setIsSaving] = useState(false);
394
+ const [savedData, setSavedData] = useState(false);
395
+ const doSave = (query) => {
396
+ if (!query.serialize) return;
390
397
 
398
+ const data = craftToSaltcorn(JSON.parse(query.serialize()));
399
+ const urlroot = options.page_id ? "pageedit" : "viewedit";
400
+ if (savedData === false) {
401
+ //do not save on first call
402
+ setSavedData(data.layout);
403
+ setIsSaving(false);
404
+ return;
405
+ }
406
+ if (isEqual(savedData, data.layout)) return;
407
+ setSavedData(data.layout);
408
+
409
+ fetch(`/${urlroot}/savebuilder/${options.page_id || options.view_id}`, {
410
+ method: "POST", // or 'PUT'
411
+ headers: {
412
+ "Content-Type": "application/json",
413
+ "CSRF-Token": options.csrfToken,
414
+ },
415
+ body: JSON.stringify(data),
416
+ }).then(() => {
417
+ setIsSaving(false);
418
+ });
419
+ };
420
+ const nodesChange = (query) => {
421
+ if (saveTimeout) clearTimeout(saveTimeout);
422
+ setIsSaving(true);
423
+ setSaveTimeout(
424
+ setTimeout(() => {
425
+ doSave(query);
426
+ setSaveTimeout(false);
427
+ }, 500)
428
+ );
429
+ };
391
430
  return (
392
431
  <ErrorBoundary>
393
- <Editor onRender={RenderNode}>
432
+ <Editor onRender={RenderNode} onNodesChange={nodesChange}>
394
433
  <Provider value={options}>
395
434
  <PreviewCtx.Provider
396
435
  value={{ previews, setPreviews, uploadedFiles, setUploadedFiles }}
@@ -458,9 +497,13 @@ const Builder = ({ options, layout, mode }) => {
458
497
  </div>
459
498
  <div className="col-sm-auto builder-sidebar">
460
499
  <div style={{ width: "16rem" }}>
461
- <SaveButton />
462
500
  <NextButton layout={layout} />
463
501
  <HistoryPanel />
502
+ <FontAwesomeIcon
503
+ icon={faSave}
504
+ title={isSaving ? "Saving..." : "All changes saved"}
505
+ className={isSaving ? "text-muted" : ""}
506
+ />
464
507
  <ViewPageLink />
465
508
  <SettingsPanel />
466
509
  </div>
@@ -180,7 +180,7 @@ const Library = () => {
180
180
  type="text"
181
181
  className="form-control"
182
182
  value={newName}
183
- onChange={(e) => setNewName(e.target.value)}
183
+ onChange={(e) => e?.target && setNewName(e.target.value)}
184
184
  />
185
185
  <br />
186
186
  <label>Icon</label>
@@ -16,6 +16,7 @@ import {
16
16
  setInitialConfig,
17
17
  ButtonOrLinkSettingsRows,
18
18
  DynamicFontAwesomeIcon,
19
+ setAPropGen,
19
20
  } from "./utils";
20
21
 
21
22
  export /**
@@ -110,6 +111,8 @@ const ActionSettings = () => {
110
111
  const options = useContext(optionsCtx);
111
112
  const getCfgFields = (fv) => (options.actionConfigForms || {})[fv];
112
113
  const cfgFields = getCfgFields(name);
114
+ const setAProp = setAPropGen(setProp);
115
+
113
116
  return (
114
117
  <div>
115
118
  <table className="w-100">
@@ -123,12 +126,10 @@ const ActionSettings = () => {
123
126
  value={name}
124
127
  className="form-control form-select"
125
128
  onChange={(e) => {
126
- setProp((prop) => (prop.name = e.target.value));
127
- setInitialConfig(
128
- setProp,
129
- e.target.value,
130
- getCfgFields(e.target.value)
131
- );
129
+ if (!e.target) return;
130
+ const value = e.target.value;
131
+ setProp((prop) => (prop.name = value));
132
+ setInitialConfig(setProp, value, getCfgFields(value));
132
133
  }}
133
134
  >
134
135
  {options.actions.map((f, ix) => (
@@ -150,9 +151,7 @@ const ActionSettings = () => {
150
151
  type="text"
151
152
  className="form-control"
152
153
  value={action_label}
153
- onChange={(e) =>
154
- setProp((prop) => (prop.action_label = e.target.value))
155
- }
154
+ onChange={setAProp("action_label")}
156
155
  />
157
156
  </OrFormula>
158
157
  </td>
@@ -172,9 +171,7 @@ const ActionSettings = () => {
172
171
  name="block"
173
172
  type="checkbox"
174
173
  checked={confirm}
175
- onChange={(e) =>
176
- setProp((prop) => (prop.confirm = e.target.checked))
177
- }
174
+ onChange={setAProp("confirm", { checked: true })}
178
175
  />
179
176
  <label className="form-check-label">User confirmation?</label>
180
177
  </div>
@@ -7,7 +7,7 @@
7
7
  import React, { useContext } from "react";
8
8
  import { useNode } from "@craftjs/core";
9
9
  import optionsCtx from "../context";
10
- import { blockProps, BlockSetting, TextStyleRow } from "./utils";
10
+ import { blockProps, BlockSetting, TextStyleRow, setAPropGen } from "./utils";
11
11
 
12
12
  export /**
13
13
  * @param {object} props
@@ -61,6 +61,8 @@ const AggregationSettings = () => {
61
61
  textStyle: node.data.props.textStyle,
62
62
  }));
63
63
  const options = useContext(optionsCtx);
64
+ const setAProp = setAPropGen(setProp);
65
+
64
66
  return (
65
67
  <table>
66
68
  <tbody>
@@ -72,13 +74,15 @@ const AggregationSettings = () => {
72
74
  <select
73
75
  className="form-control form-select"
74
76
  value={agg_relation}
75
- onChange={(e) =>
77
+ onChange={(e) => {
78
+ if (!e.target) return;
79
+ const value = e.target.value;
76
80
  setProp((prop) => {
77
- prop.agg_relation = e.target.value;
78
- const fs = options.agg_field_opts[e.target.value];
81
+ prop.agg_relation = value;
82
+ const fs = options.agg_field_opts[value];
79
83
  if (fs && fs.length > 0) prop.agg_field = fs[0];
80
- })
81
- }
84
+ });
85
+ }}
82
86
  >
83
87
  {options.child_field_list.map((f, ix) => (
84
88
  <option key={ix} value={f}>
@@ -96,9 +100,7 @@ const AggregationSettings = () => {
96
100
  <select
97
101
  className="form-control form-select"
98
102
  value={agg_field}
99
- onChange={(e) =>
100
- setProp((prop) => (prop.agg_field = e.target.value))
101
- }
103
+ onChange={setAProp("agg_field")}
102
104
  >
103
105
  {(options.agg_field_opts[agg_relation] || []).map((f, ix) => (
104
106
  <option key={ix} value={f}>
@@ -116,7 +118,7 @@ const AggregationSettings = () => {
116
118
  <select
117
119
  value={stat}
118
120
  className="form-control form-select"
119
- onChange={(e) => setProp((prop) => (prop.stat = e.target.value))}
121
+ onChange={setAProp("stat")}
120
122
  >
121
123
  <option value={"Count"}>Count</option>
122
124
  <option value={"Avg"}>Avg</option>
@@ -141,9 +143,7 @@ const AggregationSettings = () => {
141
143
  type="text"
142
144
  className="form-control"
143
145
  value={aggwhere}
144
- onChange={(e) =>
145
- setProp((prop) => (prop.aggwhere = e.target.value))
146
- }
146
+ onChange={setAProp("aggwhere")}
147
147
  />
148
148
  </td>
149
149
  </tr>
@@ -118,12 +118,14 @@ const ColumnsSettings = () => {
118
118
  step="1"
119
119
  min="1"
120
120
  max="4"
121
- onChange={(e) =>
121
+ onChange={(e) => {
122
+ if (!e.target) return;
123
+ const value = e.target.value;
122
124
  setProp((prop) => {
123
- prop.ncols = e.target.value;
124
- prop.widths = resetWidths(e.target.value);
125
- })
126
- }
125
+ prop.ncols = value;
126
+ prop.widths = resetWidths(value);
127
+ });
128
+ }}
127
129
  />
128
130
  </td>
129
131
  </tr>
@@ -148,9 +150,11 @@ const ColumnsSettings = () => {
148
150
  step="1"
149
151
  min="1"
150
152
  max={12 - (sum(widths) - widths[ix]) - 1}
151
- onChange={(e) =>
152
- setProp((prop) => (prop.widths[ix] = +e.target.value))
153
- }
153
+ onChange={(e) => {
154
+ if (!e.target) return;
155
+ const value = e.target.value;
156
+ setProp((prop) => (prop.widths[ix] = +value));
157
+ }}
154
158
  />
155
159
  ) : (
156
160
  `${12 - sum(widths)}`
@@ -161,9 +165,11 @@ const ColumnsSettings = () => {
161
165
  <select
162
166
  className="form-control form-select"
163
167
  value={breakpoints[ix]}
164
- onChange={(e) =>
165
- setProp((prop) => (prop.breakpoints[ix] = e.target.value))
166
- }
168
+ onChange={(e) => {
169
+ if (!e.target) return;
170
+ const value = e.target.value;
171
+ setProp((prop) => (prop.breakpoints[ix] = value));
172
+ }}
167
173
  >
168
174
  <option disabled>Breakpoint</option>
169
175
  <option value="">None</option>
@@ -18,6 +18,7 @@ import {
18
18
  SettingsRow,
19
19
  reactifyStyles,
20
20
  bstyleopt,
21
+ setAPropGen,
21
22
  } from "./utils";
22
23
  import {
23
24
  BorderOuter,
@@ -269,12 +270,7 @@ const ContainerSettings = () => {
269
270
  * @param {string} key
270
271
  * @returns {function}
271
272
  */
272
- const setAProp = (key) => (e) => {
273
- if (e.target) {
274
- const target_value = e.target.value;
275
- setProp((prop) => (prop[key] = target_value));
276
- }
277
- };
273
+ const setAProp = setAPropGen(setProp);
278
274
  return (
279
275
  <Accordion>
280
276
  <div accordiontitle="Box" className="w-100">
@@ -350,9 +346,7 @@ const ContainerSettings = () => {
350
346
  name="block"
351
347
  type="checkbox"
352
348
  checked={fullPageWidth}
353
- onChange={(e) =>
354
- setProp((prop) => (prop.fullPageWidth = e.target.checked))
355
- }
349
+ onChange={setAProp("fullPageWidth", { checked: true })}
356
350
  />
357
351
  <label className="form-check-label">
358
352
  Expand to full page width
@@ -536,8 +530,10 @@ const ContainerSettings = () => {
536
530
  onChange={setAProp("imgResponsiveWidths")}
537
531
  />
538
532
  <small>
539
- <i>List of widths to serve resized images,
540
- e.g. 300, 400, 600</i>
533
+ <i>
534
+ List of widths to serve resized images, e.g. 300, 400,
535
+ 600
536
+ </i>
541
537
  </small>
542
538
  </td>
543
539
  </tr>
@@ -611,9 +607,7 @@ const ContainerSettings = () => {
611
607
  name="setTextColor"
612
608
  type="checkbox"
613
609
  checked={setTextColor}
614
- onChange={(e) =>
615
- setProp((prop) => (prop.setTextColor = e.target.checked))
616
- }
610
+ onChange={setAProp("setTextColor", { checked: true })}
617
611
  />
618
612
  </label>
619
613
  </td>
@@ -782,15 +776,17 @@ const ContainerSettings = () => {
782
776
  ? true
783
777
  : showForRole[id]
784
778
  }
785
- onChange={(e) =>
779
+ onChange={(e) => {
780
+ if (!e?.target) return;
781
+ const checked = e.target.checked;
786
782
  setProp((prop) => {
787
783
  if (!prop.showForRole || prop.showForRole.length === 0)
788
784
  options.roles.forEach(
789
785
  (r) => (prop.showForRole[r.id] = true)
790
786
  );
791
- prop.showForRole[id] = e.target.checked;
792
- })
793
- }
787
+ prop.showForRole[id] = checked;
788
+ });
789
+ }}
794
790
  />
795
791
  <label className="form-check-label">{role}</label>
796
792
  </div>
@@ -806,11 +802,7 @@ const ContainerSettings = () => {
806
802
  name="block"
807
803
  type="checkbox"
808
804
  checked={show_for_owner}
809
- onChange={(e) =>
810
- setProp(
811
- (prop) => (prop.show_for_owner = e.target.checked)
812
- )
813
- }
805
+ onChange={setAProp("show_for_owner", { checked: true })}
814
806
  />
815
807
  <label className="form-check-label">Owner</label>
816
808
  </div>
@@ -7,7 +7,7 @@
7
7
  import React, { useContext, Fragment } from "react";
8
8
  import { useNode } from "@craftjs/core";
9
9
  import optionsCtx from "../context";
10
- import { blockProps, BlockSetting, TextStyleRow } from "./utils";
10
+ import { blockProps, BlockSetting, TextStyleRow, setAPropGen } from "./utils";
11
11
 
12
12
  export /**
13
13
  * @param {object} props
@@ -59,6 +59,8 @@ const DropDownFilterSettings = () => {
59
59
  where: node.data.props.where,
60
60
  }));
61
61
  const options = useContext(optionsCtx);
62
+ const setAProp = setAPropGen(setProp);
63
+
62
64
  return (
63
65
  <table className="w-100">
64
66
  <tbody>
@@ -70,7 +72,7 @@ const DropDownFilterSettings = () => {
70
72
  <select
71
73
  value={name}
72
74
  className="form-control form-select"
73
- onChange={(e) => setProp((prop) => (prop.name = e.target.value))}
75
+ onChange={setAProp("name")}
74
76
  >
75
77
  {options.fields.map((f, ix) => (
76
78
  <option key={ix} value={f.name}>
@@ -88,9 +90,7 @@ const DropDownFilterSettings = () => {
88
90
  <input
89
91
  value={neutral_label}
90
92
  className="form-control"
91
- onChange={(e) =>
92
- setProp((prop) => (prop.neutral_label = e.target.value))
93
- }
93
+ onChange={setAProp("neutral_label")}
94
94
  />
95
95
  </td>
96
96
  </tr>
@@ -102,7 +102,7 @@ const DropDownFilterSettings = () => {
102
102
  <input
103
103
  value={where}
104
104
  className="form-control"
105
- onChange={(e) => setProp((prop) => (prop.where = e.target.value))}
105
+ onChange={setAProp("where")}
106
106
  />
107
107
  </td>
108
108
  </tr>
@@ -121,9 +121,7 @@ const DropDownFilterSettings = () => {
121
121
  name="block"
122
122
  type="checkbox"
123
123
  checked={full_width}
124
- onChange={(e) =>
125
- setProp((prop) => (prop.full_width = e.target.checked))
126
- }
124
+ onChange={setAProp("full_width", { checked: true })}
127
125
  />
128
126
  <label className="form-check-label">Full width</label>
129
127
  </div>
@@ -134,8 +132,8 @@ const DropDownFilterSettings = () => {
134
132
  );
135
133
  };
136
134
 
137
- /**
138
- * @type {object}
135
+ /**
136
+ * @type {object}
139
137
  */
140
138
  DropDownFilter.craft = {
141
139
  displayName: "DropDownFilter",
@@ -140,15 +140,17 @@ const FieldSettings = () => {
140
140
  value={name}
141
141
  className="form-control form-select"
142
142
  onChange={(e) => {
143
- setProp((prop) => (prop.name = e.target.value));
144
- const newfvs = options.field_view_options[e.target.value];
143
+ if (!e.target) return;
144
+ const value = e.target.value;
145
+ setProp((prop) => (prop.name = value));
146
+ const newfvs = options.field_view_options[value];
145
147
  if (newfvs && newfvs.length > 0) {
146
148
  setProp((prop) => (prop.fieldview = newfvs[0]));
147
149
  refetchPreview({
148
- name: e.target.value,
150
+ name: value,
149
151
  fieldview: newfvs[0],
150
152
  });
151
- } else refetchPreview({ name: e.target.value });
153
+ } else refetchPreview({ name: value });
152
154
  }}
153
155
  >
154
156
  {options.fields.map((f, ix) => (
@@ -170,13 +172,12 @@ const FieldSettings = () => {
170
172
  value={fieldview}
171
173
  className="form-control form-select"
172
174
  onChange={(e) => {
173
- setProp((prop) => (prop.fieldview = e.target.value));
174
- setInitialConfig(
175
- setProp,
176
- e.target.value,
177
- getCfgFields(e.target.value)
178
- );
179
- refetchPreview({ fieldview: e.target.value });
175
+ if (!e.target) return;
176
+ const value = e.target.value;
177
+
178
+ setProp((prop) => (prop.fieldview = value));
179
+ setInitialConfig(setProp, value, getCfgFields(value));
180
+ refetchPreview({ fieldview: value });
180
181
  }}
181
182
  >
182
183
  {(fvs || []).map((fvnm, ix) => (
@@ -16,6 +16,7 @@ import {
16
16
  reactifyStyles,
17
17
  Accordion,
18
18
  OrFormula,
19
+ setAPropGen,
19
20
  } from "./utils";
20
21
 
21
22
  export /**
@@ -120,12 +121,7 @@ const ImageSettings = () => {
120
121
  });
121
122
  }
122
123
  };
123
- const setAProp = (key) => (e) => {
124
- if (e.target) {
125
- const target_value = e.target.value;
126
- setProp((prop) => (prop[key] = target_value));
127
- }
128
- };
124
+ const setAProp = setAPropGen(setProp);
129
125
  return (
130
126
  <Accordion>
131
127
  <table accordiontitle="Select image">
@@ -256,7 +252,7 @@ const ImageSettings = () => {
256
252
  )}
257
253
  {srctype !== "Upload" && (
258
254
  <tr>
259
- <td>
255
+ <td style={{ verticalAlign: "top" }}>
260
256
  <label>Responsive widths</label>
261
257
  </td>
262
258
 
@@ -122,15 +122,17 @@ const JoinFieldSettings = () => {
122
122
  value={name}
123
123
  className="form-control form-select"
124
124
  onChange={(e) => {
125
- setProp((prop) => (prop.name = e.target.value));
126
- const newfvs = options.field_view_options[e.target.value];
125
+ if (!e.target) return;
126
+ const value = e.target.value;
127
+ setProp((prop) => (prop.name = value));
128
+ const newfvs = options.field_view_options[value];
127
129
  if (newfvs && newfvs.length > 0) {
128
130
  setProp((prop) => (prop.fieldview = newfvs[0]));
129
131
  refetchPreview({
130
- name: e.target.value,
132
+ name: value,
131
133
  fieldview: newfvs[0],
132
134
  });
133
- } else refetchPreview({ name: e.target.value });
135
+ } else refetchPreview({ name: value });
134
136
  }}
135
137
  >
136
138
  {options.parent_field_list.map((f, ix) => (
@@ -152,8 +154,10 @@ const JoinFieldSettings = () => {
152
154
  value={fieldview}
153
155
  className="form-control form-select"
154
156
  onChange={(e) => {
155
- setProp((prop) => (prop.fieldview = e.target.value));
156
- refetchPreview({ fieldview: e.target.value });
157
+ if (!e.target) return;
158
+ const value = e.target.value;
159
+ setProp((prop) => (prop.fieldview = value));
160
+ refetchPreview({ fieldview: value });
157
161
  }}
158
162
  >
159
163
  {(fvs || []).map((fvnm, ix) => (
@@ -13,6 +13,7 @@ import {
13
13
  OrFormula,
14
14
  ButtonOrLinkSettingsRows,
15
15
  DynamicFontAwesomeIcon,
16
+ setAPropGen,
16
17
  } from "./utils";
17
18
  import optionsCtx from "../context";
18
19
 
@@ -111,12 +112,7 @@ const LinkSettings = () => {
111
112
  transfer_state,
112
113
  } = node;
113
114
  const options = useContext(optionsCtx);
114
- const setAProp = (key) => (e) => {
115
- if (e.target) {
116
- const target_value = e.target.value;
117
- setProp((prop) => (prop[key] = target_value));
118
- }
119
- };
115
+ const setAProp = setAPropGen(setProp);
120
116
  return (
121
117
  <div>
122
118
  <table className="w-100">
@@ -144,14 +140,16 @@ const LinkSettings = () => {
144
140
  <select
145
141
  value={link_src}
146
142
  className="form-control form-select"
147
- onChange={(e) =>
143
+ onChange={(e) => {
144
+ if (!e.target) return;
145
+ const value = e.target.value;
148
146
  setProp((prop) => {
149
- prop.link_src = e.target.value;
147
+ prop.link_src = value;
150
148
  if (e.target.value !== "URL") {
151
149
  prop.isFormula.url = false;
152
150
  }
153
- })
154
- }
151
+ });
152
+ }}
155
153
  >
156
154
  <option>URL</option>
157
155
  {(options.pages || []).length > 0 && <option>Page</option>}
@@ -237,9 +235,7 @@ const LinkSettings = () => {
237
235
  name="block"
238
236
  type="checkbox"
239
237
  checked={nofollow}
240
- onChange={(e) =>
241
- setProp((prop) => (prop.nofollow = e.target.checked))
242
- }
238
+ onChange={setAProp("nofollow", { checked: true })}
243
239
  />
244
240
  <label className="form-check-label">Nofollow</label>
245
241
  </div>
@@ -249,9 +245,7 @@ const LinkSettings = () => {
249
245
  name="block"
250
246
  type="checkbox"
251
247
  checked={target_blank}
252
- onChange={(e) =>
253
- setProp((prop) => (prop.target_blank = e.target.checked))
254
- }
248
+ onChange={setAProp("target_blank", { checked: true })}
255
249
  />
256
250
  <label className="form-check-label">Open in new tab</label>
257
251
  </div>
@@ -261,9 +255,7 @@ const LinkSettings = () => {
261
255
  name="block"
262
256
  type="checkbox"
263
257
  checked={in_modal}
264
- onChange={(e) =>
265
- setProp((prop) => (prop.in_modal = e.target.checked))
266
- }
258
+ onChange={setAProp("in_modal", { checked: true })}
267
259
  />
268
260
  <label className="form-check-label">Open in popup modal?</label>
269
261
  </div>
@@ -275,9 +267,7 @@ const LinkSettings = () => {
275
267
  name="block"
276
268
  type="checkbox"
277
269
  checked={transfer_state}
278
- onChange={(e) =>
279
- setProp((prop) => (prop.transfer_state = e.target.checked))
280
- }
270
+ onChange={setAProp("transfer_state", { checked: true })}
281
271
  />
282
272
  <label className="form-check-label">Transfer state</label>
283
273
  </div>
@@ -9,6 +9,7 @@ import { Element, useNode } from "@craftjs/core";
9
9
  import { Column } from "./Column";
10
10
  import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
11
11
  import { faCaretDown } from "@fortawesome/free-solid-svg-icons";
12
+ import { setAPropGen } from "./utils";
12
13
 
13
14
  export /**
14
15
  * @param {object} props
@@ -92,6 +93,7 @@ const SearchBarSettings = () => {
92
93
  has_dropdown: node.data.props.has_dropdown,
93
94
  show_badges: node.data.props.show_badges,
94
95
  }));
96
+ const setAProp = setAPropGen(setProp);
95
97
 
96
98
  return (
97
99
  <div>
@@ -101,9 +103,7 @@ const SearchBarSettings = () => {
101
103
  name="block"
102
104
  type="checkbox"
103
105
  checked={has_dropdown}
104
- onChange={(e) =>
105
- setProp((prop) => (prop.has_dropdown = e.target.checked))
106
- }
106
+ onChange={setAProp("has_dropdown", { checked: true })}
107
107
  />
108
108
  <label className="form-check-label">Has Dropdown</label>
109
109
  </div>
@@ -113,9 +113,7 @@ const SearchBarSettings = () => {
113
113
  name="block"
114
114
  type="checkbox"
115
115
  checked={show_badges}
116
- onChange={(e) =>
117
- setProp((prop) => (prop.show_badges = e.target.checked))
118
- }
116
+ onChange={setAProp("show_badges", { checked: true })}
119
117
  />
120
118
  <label className="form-check-label">Show current state badges</label>
121
119
  </div>