@saltcorn/builder 0.7.4-beta.0 → 0.7.4-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.
|
@@ -10,11 +10,13 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
|
10
10
|
import {
|
|
11
11
|
faChevronDown,
|
|
12
12
|
faChevronRight,
|
|
13
|
+
faInfoCircle
|
|
13
14
|
} from "@fortawesome/free-solid-svg-icons";
|
|
14
15
|
import { useNode, Element } from "@craftjs/core";
|
|
15
16
|
import FontIconPicker from "@fonticonpicker/react-fonticonpicker";
|
|
16
17
|
import faIcons from "./faicons";
|
|
17
18
|
import { Columns, ntimes } from "./Columns";
|
|
19
|
+
import Tippy from '@tippyjs/react';
|
|
18
20
|
|
|
19
21
|
export const DynamicFontAwesomeIcon = ({ icon, className }) => {
|
|
20
22
|
if (!icon) return null;
|
|
@@ -25,8 +27,8 @@ export /**
|
|
|
25
27
|
* @param {boolean} is_block
|
|
26
28
|
* @returns {object}
|
|
27
29
|
*/
|
|
28
|
-
const blockProps = (is_block) =>
|
|
29
|
-
|
|
30
|
+
const blockProps = (is_block) =>
|
|
31
|
+
is_block ? { style: { display: "block" } } : {};
|
|
30
32
|
|
|
31
33
|
export /**
|
|
32
34
|
* @param {object} props
|
|
@@ -37,23 +39,23 @@ export /**
|
|
|
37
39
|
* @subcategory components / elements / utils
|
|
38
40
|
* @namespace
|
|
39
41
|
*/
|
|
40
|
-
const BlockSetting = ({ block, setProp }) => (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
);
|
|
42
|
+
const BlockSetting = ({ block, setProp }) => (
|
|
43
|
+
<div className="form-check">
|
|
44
|
+
<input
|
|
45
|
+
className="form-check-input"
|
|
46
|
+
name="block"
|
|
47
|
+
type="checkbox"
|
|
48
|
+
checked={block}
|
|
49
|
+
onChange={(e) => {
|
|
50
|
+
if (e.target) {
|
|
51
|
+
const target_value = e.target.checked;
|
|
52
|
+
setProp((prop) => (prop.block = target_value));
|
|
53
|
+
}
|
|
54
|
+
}}
|
|
55
|
+
/>
|
|
56
|
+
<label className="form-check-label">Block display</label>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
57
59
|
|
|
58
60
|
export const BlockOrInlineSetting = ({ block, inline, textStyle, setProp }) =>
|
|
59
61
|
!textStyle || !textStyle.startsWith("h") ? (
|
|
@@ -76,6 +78,18 @@ export const BlockOrInlineSetting = ({ block, inline, textStyle, setProp }) =>
|
|
|
76
78
|
</div>
|
|
77
79
|
);
|
|
78
80
|
|
|
81
|
+
export const FormulaTooltip = () => {
|
|
82
|
+
const { fields } = useContext(optionsCtx);
|
|
83
|
+
console.log(fields);
|
|
84
|
+
return <Tooltip>
|
|
85
|
+
<div>Formulae in Saltcorn are JavaScript expressions based on the current database row.</div>
|
|
86
|
+
{fields ? <Fragment> Variables in scope:
|
|
87
|
+
{fields.map((f, ix) => <Fragment><code key={ix}>{f.name}</code>{" "}</Fragment>)}</Fragment> : null}
|
|
88
|
+
|
|
89
|
+
<a className="d-block" href="https://wiki.saltcorn.com/view/ShowPage/formulas">Wiki page on formulas</a>
|
|
90
|
+
</Tooltip>
|
|
91
|
+
}
|
|
92
|
+
|
|
79
93
|
export /**
|
|
80
94
|
* @param {object} props
|
|
81
95
|
* @param {function} props.setProp
|
|
@@ -88,81 +102,83 @@ export /**
|
|
|
88
102
|
* @category saltcorn-builder
|
|
89
103
|
* @subcategory components / elements / utils
|
|
90
104
|
*/
|
|
91
|
-
const OrFormula = ({ setProp, isFormula, node, nodekey, children }) => {
|
|
92
|
-
|
|
105
|
+
const OrFormula = ({ setProp, isFormula, node, nodekey, children }) => {
|
|
106
|
+
const { mode } = useContext(optionsCtx);
|
|
93
107
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
/**
|
|
109
|
+
* @returns {void}
|
|
110
|
+
*/
|
|
111
|
+
const switchIsFml = () => {
|
|
112
|
+
const isFmlAfter = !isFormula[nodekey];
|
|
113
|
+
setProp((prop) => {
|
|
114
|
+
prop.isFormula[nodekey] = isFmlAfter;
|
|
115
|
+
if (isFmlAfter && prop[nodekey] && prop[nodekey][0] !== '"') {
|
|
116
|
+
prop[nodekey] = `"${prop[nodekey]}"`;
|
|
117
|
+
} else if (
|
|
118
|
+
!isFmlAfter &&
|
|
119
|
+
typeof prop[nodekey] === "string" &&
|
|
120
|
+
prop[nodekey][0] === '"' &&
|
|
121
|
+
prop[nodekey][prop[nodekey].length - 1] === '"'
|
|
122
|
+
) {
|
|
123
|
+
prop[nodekey] = prop[nodekey].substring(1, prop[nodekey].length - 1);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
let errorString = false;
|
|
128
|
+
if (mode === "show" && isFormula[nodekey]) {
|
|
129
|
+
try {
|
|
130
|
+
Function("return " + node[nodekey]);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
errorString = error.message;
|
|
110
133
|
}
|
|
111
|
-
});
|
|
112
|
-
};
|
|
113
|
-
let errorString = false;
|
|
114
|
-
if (mode === "show" && isFormula[nodekey]) {
|
|
115
|
-
try {
|
|
116
|
-
Function("return " + node[nodekey]);
|
|
117
|
-
} catch (error) {
|
|
118
|
-
errorString = error.message;
|
|
119
134
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
)}
|
|
135
|
+
return mode !== "show" ? (
|
|
136
|
+
children
|
|
137
|
+
) : (
|
|
138
|
+
<Fragment>
|
|
139
|
+
<div className="input-group input-group-sm w-100">
|
|
140
|
+
{isFormula[nodekey] ? (
|
|
141
|
+
<input
|
|
142
|
+
type="text"
|
|
143
|
+
className="form-control text-to-display"
|
|
144
|
+
value={node[nodekey] || ""}
|
|
145
|
+
onChange={(e) => {
|
|
146
|
+
if (e.target) {
|
|
147
|
+
const target_value = e.target.value;
|
|
148
|
+
setProp((prop) => (prop[nodekey] = target_value));
|
|
149
|
+
}
|
|
150
|
+
}}
|
|
151
|
+
/>
|
|
152
|
+
) : (
|
|
153
|
+
children
|
|
154
|
+
)}
|
|
141
155
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
</button>
|
|
152
|
-
</div>
|
|
153
|
-
{isFormula[nodekey] && (
|
|
154
|
-
<div style={{ marginTop: "-5px" }}>
|
|
155
|
-
<small className="text-muted font-monospace">FORMULA</small>
|
|
156
|
-
{errorString ? (
|
|
157
|
-
<small className="text-danger font-monospace d-block">
|
|
158
|
-
{errorString}
|
|
159
|
-
</small>
|
|
160
|
-
) : null}
|
|
156
|
+
<button
|
|
157
|
+
className={`btn activate-formula ${isFormula[nodekey] ? "btn-secondary" : "btn-outline-secondary"
|
|
158
|
+
}`}
|
|
159
|
+
title="Calculated formula"
|
|
160
|
+
type="button"
|
|
161
|
+
onClick={switchIsFml}
|
|
162
|
+
>
|
|
163
|
+
<i className="fas fa-calculator"></i>
|
|
164
|
+
</button>
|
|
161
165
|
</div>
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
+
{isFormula[nodekey] && (
|
|
167
|
+
<div style={{ marginTop: "-5px" }}>
|
|
168
|
+
<small className="text-muted font-monospace">
|
|
169
|
+
FORMULA
|
|
170
|
+
<FormulaTooltip />
|
|
171
|
+
</small>
|
|
172
|
+
{errorString ? (
|
|
173
|
+
<small className="text-danger font-monospace d-block">
|
|
174
|
+
{errorString}
|
|
175
|
+
</small>
|
|
176
|
+
) : null}
|
|
177
|
+
</div>
|
|
178
|
+
)}
|
|
179
|
+
</Fragment>
|
|
180
|
+
);
|
|
181
|
+
};
|
|
166
182
|
|
|
167
183
|
export /**
|
|
168
184
|
* @param {object} props
|
|
@@ -173,52 +189,15 @@ export /**
|
|
|
173
189
|
* @category saltcorn-builder
|
|
174
190
|
* @subcategory components / elements / utils
|
|
175
191
|
*/
|
|
176
|
-
const MinRoleSetting = ({ minRole, setProp }) => {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
<label>Minimum Role</label>
|
|
181
|
-
<select
|
|
182
|
-
className="form-control form-select"
|
|
183
|
-
value={minRole}
|
|
184
|
-
onChange={(e) => (e) => {
|
|
185
|
-
if (e.target) {
|
|
186
|
-
const target_value = e.target.value;
|
|
187
|
-
setProp((prop) => (prop.minRole = target_value));
|
|
188
|
-
}
|
|
189
|
-
}}
|
|
190
|
-
>
|
|
191
|
-
{options.roles.map((r) => (
|
|
192
|
-
<option key={r.id} value={r.id}>
|
|
193
|
-
{r.role}
|
|
194
|
-
</option>
|
|
195
|
-
))}
|
|
196
|
-
</select>
|
|
197
|
-
</div>
|
|
198
|
-
);
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
export /**
|
|
202
|
-
* @param {object} props
|
|
203
|
-
* @param {string} props.minRole
|
|
204
|
-
* @param {function} props.setProp
|
|
205
|
-
* @returns {tr}
|
|
206
|
-
* @namespace
|
|
207
|
-
* @category saltcorn-builder
|
|
208
|
-
* @subcategory components / elements / utils
|
|
209
|
-
*/
|
|
210
|
-
const MinRoleSettingRow = ({ minRole, setProp }) => {
|
|
211
|
-
const options = useContext(optionsCtx);
|
|
212
|
-
return (
|
|
213
|
-
<tr>
|
|
214
|
-
<td>
|
|
192
|
+
const MinRoleSetting = ({ minRole, setProp }) => {
|
|
193
|
+
const options = useContext(optionsCtx);
|
|
194
|
+
return (
|
|
195
|
+
<div>
|
|
215
196
|
<label>Minimum Role</label>
|
|
216
|
-
</td>
|
|
217
|
-
<td>
|
|
218
197
|
<select
|
|
219
|
-
value={minRole}
|
|
220
198
|
className="form-control form-select"
|
|
221
|
-
|
|
199
|
+
value={minRole}
|
|
200
|
+
onChange={(e) => (e) => {
|
|
222
201
|
if (e.target) {
|
|
223
202
|
const target_value = e.target.value;
|
|
224
203
|
setProp((prop) => (prop.minRole = target_value));
|
|
@@ -231,10 +210,47 @@ const MinRoleSettingRow = ({ minRole, setProp }) => {
|
|
|
231
210
|
</option>
|
|
232
211
|
))}
|
|
233
212
|
</select>
|
|
234
|
-
</
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
213
|
+
</div>
|
|
214
|
+
);
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
export /**
|
|
218
|
+
* @param {object} props
|
|
219
|
+
* @param {string} props.minRole
|
|
220
|
+
* @param {function} props.setProp
|
|
221
|
+
* @returns {tr}
|
|
222
|
+
* @namespace
|
|
223
|
+
* @category saltcorn-builder
|
|
224
|
+
* @subcategory components / elements / utils
|
|
225
|
+
*/
|
|
226
|
+
const MinRoleSettingRow = ({ minRole, setProp }) => {
|
|
227
|
+
const options = useContext(optionsCtx);
|
|
228
|
+
return (
|
|
229
|
+
<tr>
|
|
230
|
+
<td>
|
|
231
|
+
<label>Minimum Role</label>
|
|
232
|
+
</td>
|
|
233
|
+
<td>
|
|
234
|
+
<select
|
|
235
|
+
value={minRole}
|
|
236
|
+
className="form-control form-select"
|
|
237
|
+
onChange={(e) => {
|
|
238
|
+
if (e.target) {
|
|
239
|
+
const target_value = e.target.value;
|
|
240
|
+
setProp((prop) => (prop.minRole = target_value));
|
|
241
|
+
}
|
|
242
|
+
}}
|
|
243
|
+
>
|
|
244
|
+
{options.roles.map((r) => (
|
|
245
|
+
<option key={r.id} value={r.id}>
|
|
246
|
+
{r.role}
|
|
247
|
+
</option>
|
|
248
|
+
))}
|
|
249
|
+
</select>
|
|
250
|
+
</td>
|
|
251
|
+
</tr>
|
|
252
|
+
);
|
|
253
|
+
};
|
|
238
254
|
|
|
239
255
|
/**
|
|
240
256
|
* @param {object} props
|
|
@@ -283,14 +299,14 @@ export /**
|
|
|
283
299
|
* @category saltcorn-builder
|
|
284
300
|
* @subcategory components / elements / utils
|
|
285
301
|
*/
|
|
286
|
-
const TextStyleSetting = ({ textStyle, setProp }) => {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
};
|
|
302
|
+
const TextStyleSetting = ({ textStyle, setProp }) => {
|
|
303
|
+
return (
|
|
304
|
+
<div>
|
|
305
|
+
<label>Text Style</label>
|
|
306
|
+
<TextStyleSelect textStyle={textStyle} setProp={setProp} />
|
|
307
|
+
</div>
|
|
308
|
+
);
|
|
309
|
+
};
|
|
294
310
|
|
|
295
311
|
export /**
|
|
296
312
|
* @param {object} props
|
|
@@ -301,18 +317,18 @@ export /**
|
|
|
301
317
|
* @category saltcorn-builder
|
|
302
318
|
* @subcategory components / elements / utils
|
|
303
319
|
*/
|
|
304
|
-
const TextStyleRow = ({ textStyle, setProp }) => {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
};
|
|
320
|
+
const TextStyleRow = ({ textStyle, setProp }) => {
|
|
321
|
+
return (
|
|
322
|
+
<tr>
|
|
323
|
+
<td>
|
|
324
|
+
<label>Text Style</label>
|
|
325
|
+
</td>
|
|
326
|
+
<td>
|
|
327
|
+
<TextStyleSelect textStyle={textStyle} setProp={setProp} />
|
|
328
|
+
</td>
|
|
329
|
+
</tr>
|
|
330
|
+
);
|
|
331
|
+
};
|
|
316
332
|
|
|
317
333
|
export /**
|
|
318
334
|
* @param {object} props
|
|
@@ -323,36 +339,35 @@ export /**
|
|
|
323
339
|
* @subcategory components / elements / utils
|
|
324
340
|
* @namespace
|
|
325
341
|
*/
|
|
326
|
-
const Accordion = ({ titles, children }) => {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
)
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
};
|
|
342
|
+
const Accordion = ({ titles, children }) => {
|
|
343
|
+
const [currentTab, setCurrentTab] = useState(0);
|
|
344
|
+
return (
|
|
345
|
+
<Fragment>
|
|
346
|
+
{children.map((child, ix) => {
|
|
347
|
+
const isCurrent = ix === currentTab;
|
|
348
|
+
return (
|
|
349
|
+
<Fragment key={ix}>
|
|
350
|
+
<div
|
|
351
|
+
className={`bg-${isCurrent ? "primary" : "secondary"
|
|
352
|
+
} ps-1 text-white w-100 mt-1`}
|
|
353
|
+
onClick={() => setCurrentTab(ix)}
|
|
354
|
+
>
|
|
355
|
+
<span className="w-1em">
|
|
356
|
+
{isCurrent ? (
|
|
357
|
+
<FontAwesomeIcon icon={faChevronDown} />
|
|
358
|
+
) : (
|
|
359
|
+
<FontAwesomeIcon icon={faChevronRight} />
|
|
360
|
+
)}
|
|
361
|
+
</span>
|
|
362
|
+
{child.props.accordiontitle || titles[ix]}
|
|
363
|
+
</div>
|
|
364
|
+
{isCurrent ? child : null}
|
|
365
|
+
</Fragment>
|
|
366
|
+
);
|
|
367
|
+
})}
|
|
368
|
+
</Fragment>
|
|
369
|
+
);
|
|
370
|
+
};
|
|
356
371
|
|
|
357
372
|
/**
|
|
358
373
|
* @param {object} opts
|
|
@@ -402,23 +417,23 @@ const fetchPreview = ({ url, body, options, setPreviews, node_id, isView }) => {
|
|
|
402
417
|
*/
|
|
403
418
|
export const fetchFieldPreview =
|
|
404
419
|
(args = {}) =>
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
420
|
+
(changes = {}) => {
|
|
421
|
+
const { node_id, options, name, fieldview, setPreviews } = {
|
|
422
|
+
...args,
|
|
423
|
+
...changes,
|
|
424
|
+
};
|
|
425
|
+
const configuration = {
|
|
426
|
+
...(args.configuration || {}),
|
|
427
|
+
...(changes.configuration || {}),
|
|
428
|
+
};
|
|
429
|
+
fetchPreview({
|
|
430
|
+
options,
|
|
431
|
+
node_id,
|
|
432
|
+
setPreviews,
|
|
433
|
+
url: `/field/preview/${options.tableName}/${name}/${fieldview}`,
|
|
434
|
+
body: { configuration },
|
|
435
|
+
});
|
|
413
436
|
};
|
|
414
|
-
fetchPreview({
|
|
415
|
-
options,
|
|
416
|
-
node_id,
|
|
417
|
-
setPreviews,
|
|
418
|
-
url: `/field/preview/${options.tableName}/${name}/${fieldview}`,
|
|
419
|
-
body: { configuration },
|
|
420
|
-
});
|
|
421
|
-
};
|
|
422
437
|
|
|
423
438
|
/**
|
|
424
439
|
* @function
|
|
@@ -427,30 +442,30 @@ export const fetchFieldPreview =
|
|
|
427
442
|
*/
|
|
428
443
|
export const fetchViewPreview =
|
|
429
444
|
(args = {}) =>
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
445
|
+
(changes = {}) => {
|
|
446
|
+
const { node_id, options, view, setPreviews, configuration } = {
|
|
447
|
+
...args,
|
|
448
|
+
...changes,
|
|
449
|
+
};
|
|
450
|
+
let viewname,
|
|
451
|
+
body = configuration ? { ...configuration } : {};
|
|
452
|
+
if (view.includes(":")) {
|
|
453
|
+
const [reltype, rest] = view.split(":");
|
|
454
|
+
const [vnm] = rest.split(".");
|
|
455
|
+
viewname = vnm;
|
|
456
|
+
body.reltype = reltype;
|
|
457
|
+
body.path = rest;
|
|
458
|
+
} else viewname = view;
|
|
444
459
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
460
|
+
fetchPreview({
|
|
461
|
+
options,
|
|
462
|
+
node_id,
|
|
463
|
+
setPreviews,
|
|
464
|
+
url: `/view/${viewname}/preview`,
|
|
465
|
+
body,
|
|
466
|
+
isView: true,
|
|
467
|
+
});
|
|
468
|
+
};
|
|
454
469
|
|
|
455
470
|
export /**
|
|
456
471
|
* @param {object} props
|
|
@@ -462,16 +477,16 @@ export /**
|
|
|
462
477
|
* @subcategory components / elements / utils
|
|
463
478
|
* @namespace
|
|
464
479
|
*/
|
|
465
|
-
const SelectUnits = ({ vert, autoable, ...props }) => (
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
);
|
|
480
|
+
const SelectUnits = ({ vert, autoable, ...props }) => (
|
|
481
|
+
<select {...props}>
|
|
482
|
+
<option>px</option>
|
|
483
|
+
<option>%</option>
|
|
484
|
+
<option>{vert ? "vh" : "vw"}</option>
|
|
485
|
+
<option>em</option>
|
|
486
|
+
<option>rem</option>
|
|
487
|
+
{autoable && <option>auto</option>}
|
|
488
|
+
</select>
|
|
489
|
+
);
|
|
475
490
|
|
|
476
491
|
/**
|
|
477
492
|
* @function
|
|
@@ -579,36 +594,36 @@ export /**
|
|
|
579
594
|
* @subcategory components / elements / utils
|
|
580
595
|
* @namespace
|
|
581
596
|
*/
|
|
582
|
-
const ConfigForm = ({ fields, configuration, setProp, node, onChange }) => (
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
);
|
|
597
|
+
const ConfigForm = ({ fields, configuration, setProp, node, onChange }) => (
|
|
598
|
+
<div>
|
|
599
|
+
{fields.map((f, ix) => {
|
|
600
|
+
if (f.showIf && configuration) {
|
|
601
|
+
let noshow = false;
|
|
602
|
+
Object.entries(f.showIf).forEach(([nm, value]) => {
|
|
603
|
+
if (Array.isArray(value))
|
|
604
|
+
noshow = noshow || value.includes(configuration[nm]);
|
|
605
|
+
else noshow = noshow || value !== configuration[nm];
|
|
606
|
+
});
|
|
607
|
+
if (noshow) return null;
|
|
608
|
+
}
|
|
609
|
+
return (
|
|
610
|
+
<div key={ix}>
|
|
611
|
+
{!isCheckbox(f) ? <label>{f.label || f.name}</label> : null}
|
|
612
|
+
<ConfigField
|
|
613
|
+
field={f}
|
|
614
|
+
configuration={configuration}
|
|
615
|
+
setProp={setProp}
|
|
616
|
+
onChange={onChange}
|
|
617
|
+
/>
|
|
618
|
+
{f.sublabel ? (
|
|
619
|
+
<i dangerouslySetInnerHTML={{ __html: f.sublabel }}></i>
|
|
620
|
+
) : null}
|
|
621
|
+
</div>
|
|
622
|
+
);
|
|
623
|
+
})}
|
|
624
|
+
<br />
|
|
625
|
+
</div>
|
|
626
|
+
);
|
|
612
627
|
|
|
613
628
|
/**
|
|
614
629
|
* @param {object|undefined} x
|
|
@@ -630,245 +645,243 @@ export /**
|
|
|
630
645
|
* @subcategory components / elements / utils
|
|
631
646
|
* @namespace
|
|
632
647
|
*/
|
|
633
|
-
const ConfigField = ({
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
}) => {
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
648
|
+
const ConfigField = ({
|
|
649
|
+
field,
|
|
650
|
+
configuration,
|
|
651
|
+
setProp,
|
|
652
|
+
onChange,
|
|
653
|
+
props,
|
|
654
|
+
isStyle,
|
|
655
|
+
}) => {
|
|
656
|
+
/**
|
|
657
|
+
* @param {object} v
|
|
658
|
+
* @returns {void}
|
|
659
|
+
*/
|
|
660
|
+
const options = useContext(optionsCtx);
|
|
646
661
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
662
|
+
const myOnChange = (v) => {
|
|
663
|
+
setProp((prop) => {
|
|
664
|
+
if (configuration) {
|
|
665
|
+
if (!prop.configuration) prop.configuration = {};
|
|
666
|
+
prop.configuration[field.name] = v;
|
|
667
|
+
} else if (isStyle) {
|
|
668
|
+
if (!prop.style) prop.style = {};
|
|
669
|
+
prop.style[field.name] = v;
|
|
670
|
+
} else prop[field.name] = v;
|
|
671
|
+
});
|
|
672
|
+
onChange && onChange(field.name, v);
|
|
673
|
+
};
|
|
674
|
+
const value = or_if_undef(
|
|
675
|
+
configuration
|
|
676
|
+
? configuration[field.name]
|
|
677
|
+
: isStyle
|
|
678
|
+
? props.style[field.name]
|
|
679
|
+
: props[field.name],
|
|
680
|
+
field.default
|
|
681
|
+
);
|
|
682
|
+
if (field.input_type === "fromtype") field.input_type = null;
|
|
683
|
+
if (field.type && field.type.name === "String" && field.attributes.options) {
|
|
684
|
+
field.input_type = "select";
|
|
685
|
+
field.options =
|
|
686
|
+
typeof field.attributes.options === "string"
|
|
687
|
+
? field.attributes.options.split(",").map((s) => s.trim())
|
|
688
|
+
: field.attributes.options;
|
|
689
|
+
if (!field.required && field.options) field.options.unshift("");
|
|
690
|
+
}
|
|
691
|
+
const dispatch = {
|
|
692
|
+
String() {
|
|
693
|
+
if (field.attributes?.options) {
|
|
694
|
+
const options =
|
|
695
|
+
typeof field.attributes.options === "string"
|
|
696
|
+
? field.attributes.options.split(",").map((s) => s.trim())
|
|
697
|
+
: field.attributes.options;
|
|
698
|
+
return (
|
|
699
|
+
<select
|
|
700
|
+
className="form-control form-select"
|
|
701
|
+
value={value || ""}
|
|
702
|
+
onChange={(e) => e.target && myOnChange(e.target.value)}
|
|
703
|
+
>
|
|
704
|
+
{options.map((o, ix) => (
|
|
705
|
+
<option
|
|
706
|
+
key={ix}
|
|
707
|
+
value={typeof o === "string" ? o : o.value || o.name}
|
|
708
|
+
>
|
|
709
|
+
{typeof o === "string" ? o : o.label}
|
|
710
|
+
</option>
|
|
711
|
+
))}
|
|
712
|
+
</select>
|
|
713
|
+
);
|
|
714
|
+
} else
|
|
715
|
+
return (
|
|
716
|
+
<input
|
|
717
|
+
type="text"
|
|
718
|
+
className="form-control"
|
|
719
|
+
value={value || ""}
|
|
720
|
+
onChange={(e) => e.target && myOnChange(e.target.value)}
|
|
721
|
+
/>
|
|
722
|
+
);
|
|
723
|
+
},
|
|
724
|
+
Font: () => (
|
|
725
|
+
<select
|
|
726
|
+
className="form-control form-select"
|
|
727
|
+
value={value || ""}
|
|
728
|
+
onChange={(e) => e.target && myOnChange(e.target.value)}
|
|
729
|
+
>
|
|
730
|
+
<option value={""}></option>
|
|
731
|
+
{Object.entries(options.fonts || {}).map(([nm, ff], ix) => (
|
|
732
|
+
<option key={ix} value={ff}>
|
|
733
|
+
{nm}
|
|
734
|
+
</option>
|
|
735
|
+
))}
|
|
736
|
+
</select>
|
|
737
|
+
),
|
|
738
|
+
Integer: () => (
|
|
739
|
+
<input
|
|
740
|
+
type="number"
|
|
741
|
+
className="form-control"
|
|
742
|
+
step={field.step || 1}
|
|
743
|
+
min={field.min}
|
|
744
|
+
max={field.max}
|
|
745
|
+
value={value || ""}
|
|
746
|
+
onChange={(e) => e.target && myOnChange(e.target.value)}
|
|
747
|
+
/>
|
|
748
|
+
),
|
|
749
|
+
Float: () => (
|
|
750
|
+
<input
|
|
751
|
+
type="number"
|
|
752
|
+
className="form-control"
|
|
753
|
+
value={value || ""}
|
|
754
|
+
step={0.01}
|
|
755
|
+
onChange={(e) => e.target && myOnChange(e.target.value)}
|
|
756
|
+
/>
|
|
757
|
+
),
|
|
758
|
+
Color: () => <ColorInput value={value} onChange={(c) => myOnChange(c)} />,
|
|
759
|
+
Bool: () => (
|
|
760
|
+
<div className="form-check">
|
|
701
761
|
<input
|
|
702
|
-
type="
|
|
703
|
-
className="form-
|
|
704
|
-
|
|
705
|
-
onChange={(e) => e.target && myOnChange(e.target.
|
|
762
|
+
type="checkbox"
|
|
763
|
+
className="form-check-input"
|
|
764
|
+
checked={value}
|
|
765
|
+
onChange={(e) => e.target && myOnChange(e.target.checked)}
|
|
706
766
|
/>
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
<option key={ix} value={ff}>
|
|
718
|
-
{nm}
|
|
719
|
-
</option>
|
|
720
|
-
))}
|
|
721
|
-
</select>
|
|
722
|
-
),
|
|
723
|
-
Integer: () => (
|
|
724
|
-
<input
|
|
725
|
-
type="number"
|
|
726
|
-
className="form-control"
|
|
727
|
-
step={field.step || 1}
|
|
728
|
-
min={field.min}
|
|
729
|
-
max={field.max}
|
|
730
|
-
value={value || ""}
|
|
731
|
-
onChange={(e) => e.target && myOnChange(e.target.value)}
|
|
732
|
-
/>
|
|
733
|
-
),
|
|
734
|
-
Float: () => (
|
|
735
|
-
<input
|
|
736
|
-
type="number"
|
|
737
|
-
className="form-control"
|
|
738
|
-
value={value || ""}
|
|
739
|
-
step={0.01}
|
|
740
|
-
onChange={(e) => e.target && myOnChange(e.target.value)}
|
|
741
|
-
/>
|
|
742
|
-
),
|
|
743
|
-
Color: () => <ColorInput value={value} onChange={(c) => myOnChange(c)} />,
|
|
744
|
-
Bool: () => (
|
|
745
|
-
<div className="form-check">
|
|
746
|
-
<input
|
|
747
|
-
type="checkbox"
|
|
748
|
-
className="form-check-input"
|
|
749
|
-
checked={value}
|
|
750
|
-
onChange={(e) => e.target && myOnChange(e.target.checked)}
|
|
767
|
+
<label className="form-check-label">{field.label}</label>
|
|
768
|
+
</div>
|
|
769
|
+
),
|
|
770
|
+
textarea: () => (
|
|
771
|
+
<textarea
|
|
772
|
+
rows="6"
|
|
773
|
+
type="text"
|
|
774
|
+
className="form-control"
|
|
775
|
+
value={value}
|
|
776
|
+
onChange={(e) => e.target && myOnChange(e.target.value)}
|
|
751
777
|
/>
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
),
|
|
802
|
-
DimUnits: () => {
|
|
803
|
-
let styleVal, styleDim;
|
|
804
|
-
if (isStyle && value === "auto") {
|
|
805
|
-
styleVal = "";
|
|
806
|
-
styleDim = "auto";
|
|
807
|
-
} else if (isStyle && value && typeof value === "string") {
|
|
808
|
-
const matches = value.match(/^([0-9]+\.?[0-9]*)(.*)/);
|
|
809
|
-
if (matches) {
|
|
810
|
-
styleVal = matches[1];
|
|
811
|
-
styleDim = matches[2];
|
|
778
|
+
),
|
|
779
|
+
code: () => (
|
|
780
|
+
<textarea
|
|
781
|
+
rows="6"
|
|
782
|
+
type="text"
|
|
783
|
+
className="form-control"
|
|
784
|
+
value={value}
|
|
785
|
+
onChange={(e) => e.target && myOnChange(e.target.value)}
|
|
786
|
+
/>
|
|
787
|
+
),
|
|
788
|
+
select: () => (
|
|
789
|
+
<select
|
|
790
|
+
className="form-control form-select"
|
|
791
|
+
value={value || ""}
|
|
792
|
+
onChange={(e) => e.target && myOnChange(e.target.value)}
|
|
793
|
+
>
|
|
794
|
+
{field.options.map((o, ix) => (
|
|
795
|
+
<option key={ix}>{o}</option>
|
|
796
|
+
))}
|
|
797
|
+
</select>
|
|
798
|
+
),
|
|
799
|
+
btn_select: () => (
|
|
800
|
+
<div className="btn-group w-100" role="group">
|
|
801
|
+
{field.options.map((o, ix) => (
|
|
802
|
+
<button
|
|
803
|
+
key={ix}
|
|
804
|
+
title={o.title || o.value}
|
|
805
|
+
type="button"
|
|
806
|
+
style={{ width: `${Math.floor(100 / field.options.length)}%` }}
|
|
807
|
+
className={`btn btn-sm btn-${value !== o.value ? "outline-" : ""
|
|
808
|
+
}secondary ${field.btnClass || ""}`}
|
|
809
|
+
onClick={() => myOnChange(o.value)}
|
|
810
|
+
>
|
|
811
|
+
{o.label}
|
|
812
|
+
</button>
|
|
813
|
+
))}
|
|
814
|
+
</div>
|
|
815
|
+
),
|
|
816
|
+
DimUnits: () => {
|
|
817
|
+
let styleVal, styleDim;
|
|
818
|
+
if (isStyle && value === "auto") {
|
|
819
|
+
styleVal = "";
|
|
820
|
+
styleDim = "auto";
|
|
821
|
+
} else if (isStyle && value && typeof value === "string") {
|
|
822
|
+
const matches = value.match(/^([0-9]+\.?[0-9]*)(.*)/);
|
|
823
|
+
if (matches) {
|
|
824
|
+
styleVal = matches[1];
|
|
825
|
+
styleDim = matches[2];
|
|
826
|
+
}
|
|
812
827
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
/>
|
|
831
|
-
)}
|
|
832
|
-
<SelectUnits
|
|
833
|
-
value={or_if_undef(
|
|
834
|
-
configuration
|
|
835
|
-
? configuration[field.name + "Unit"]
|
|
836
|
-
: isStyle
|
|
837
|
-
? styleDim
|
|
838
|
-
: props[field.name + "Unit"],
|
|
839
|
-
"px"
|
|
828
|
+
return (
|
|
829
|
+
<Fragment>
|
|
830
|
+
{styleDim !== "auto" && (
|
|
831
|
+
<input
|
|
832
|
+
type="number"
|
|
833
|
+
value={(isStyle ? styleVal : value) || ""}
|
|
834
|
+
className="w-50 form-control-sm d-inline dimunit"
|
|
835
|
+
disabled={field.autoable && styleDim === "auto"}
|
|
836
|
+
onChange={(e) =>
|
|
837
|
+
e?.target &&
|
|
838
|
+
myOnChange(
|
|
839
|
+
isStyle
|
|
840
|
+
? `${e.target.value}${styleDim || "px"}`
|
|
841
|
+
: e.target.value
|
|
842
|
+
)
|
|
843
|
+
}
|
|
844
|
+
/>
|
|
840
845
|
)}
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
846
|
+
<SelectUnits
|
|
847
|
+
value={or_if_undef(
|
|
848
|
+
configuration
|
|
849
|
+
? configuration[field.name + "Unit"]
|
|
850
|
+
: isStyle
|
|
851
|
+
? styleDim
|
|
852
|
+
: props[field.name + "Unit"],
|
|
853
|
+
"px"
|
|
854
|
+
)}
|
|
855
|
+
autoable={field.autoable}
|
|
856
|
+
className={`w-${styleDim === "auto" ? 100 : 50
|
|
857
|
+
} form-control-sm d-inline dimunit`}
|
|
858
|
+
vert={true}
|
|
859
|
+
onChange={(e) => {
|
|
860
|
+
if (!e.target) return;
|
|
861
|
+
const target_value = e.target.value;
|
|
862
|
+
setProp((prop) => {
|
|
863
|
+
const myStyleVal =
|
|
864
|
+
target_value === "auto" && field.autoable && isStyle
|
|
865
|
+
? ""
|
|
866
|
+
: styleVal;
|
|
867
|
+
if (configuration)
|
|
868
|
+
prop.configuration[field.name + "Unit"] = target_value;
|
|
869
|
+
else if (isStyle) {
|
|
870
|
+
prop.style[field.name] = `${or_if_undef(
|
|
871
|
+
myStyleVal,
|
|
872
|
+
0
|
|
873
|
+
)}${target_value}`;
|
|
874
|
+
} else prop[field.name + "Unit"] = target_value;
|
|
875
|
+
});
|
|
876
|
+
}}
|
|
877
|
+
/>
|
|
878
|
+
</Fragment>
|
|
879
|
+
);
|
|
880
|
+
},
|
|
881
|
+
};
|
|
882
|
+
const f = dispatch[field.input_type || field.type.name || field.type];
|
|
883
|
+
return f ? f() : null;
|
|
868
884
|
};
|
|
869
|
-
const f = dispatch[field.input_type || field.type.name || field.type];
|
|
870
|
-
return f ? f() : null;
|
|
871
|
-
};
|
|
872
885
|
|
|
873
886
|
export /**
|
|
874
887
|
* @param {object[]} fields
|
|
@@ -877,30 +890,30 @@ export /**
|
|
|
877
890
|
* @namespace
|
|
878
891
|
* @returns {table}
|
|
879
892
|
*/
|
|
880
|
-
const SettingsFromFields = (fields) => () => {
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
893
|
+
const SettingsFromFields = (fields) => () => {
|
|
894
|
+
const node = useNode((node) => {
|
|
895
|
+
const ps = {};
|
|
896
|
+
fields.forEach((f) => {
|
|
897
|
+
ps[f.name] = node.data.props[f.name];
|
|
898
|
+
});
|
|
899
|
+
if (fields.some((f) => f.canBeFormula))
|
|
900
|
+
ps.isFormula = node.data.props.isFormula;
|
|
901
|
+
return ps;
|
|
885
902
|
});
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
});
|
|
890
|
-
const {
|
|
891
|
-
actions: { setProp },
|
|
892
|
-
} = node;
|
|
903
|
+
const {
|
|
904
|
+
actions: { setProp },
|
|
905
|
+
} = node;
|
|
893
906
|
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
};
|
|
907
|
+
return (
|
|
908
|
+
<table className="w-100">
|
|
909
|
+
<tbody>
|
|
910
|
+
{fields.map((f, ix) => (
|
|
911
|
+
<SettingsRow field={f} key={ix} node={node} setProp={setProp} />
|
|
912
|
+
))}
|
|
913
|
+
</tbody>
|
|
914
|
+
</table>
|
|
915
|
+
);
|
|
916
|
+
};
|
|
904
917
|
|
|
905
918
|
export /**
|
|
906
919
|
* @param {object} props
|
|
@@ -910,11 +923,11 @@ export /**
|
|
|
910
923
|
* @subcategory components / elements / utils
|
|
911
924
|
* @namespace
|
|
912
925
|
*/
|
|
913
|
-
const SettingsSectionHeaderRow = ({ title }) => (
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
);
|
|
926
|
+
const SettingsSectionHeaderRow = ({ title }) => (
|
|
927
|
+
<tr>
|
|
928
|
+
<th colSpan="2">{title}</th>
|
|
929
|
+
</tr>
|
|
930
|
+
);
|
|
918
931
|
|
|
919
932
|
export /**
|
|
920
933
|
* @param {object} props
|
|
@@ -928,49 +941,49 @@ export /**
|
|
|
928
941
|
* @subcategory components / elements / utils
|
|
929
942
|
* @namespace
|
|
930
943
|
*/
|
|
931
|
-
const SettingsRow = ({ field, node, setProp, onChange, isStyle }) => {
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
944
|
+
const SettingsRow = ({ field, node, setProp, onChange, isStyle }) => {
|
|
945
|
+
const fullWidth = ["String", "Bool", "textarea"].includes(field.type);
|
|
946
|
+
const needLabel = field.type !== "Bool";
|
|
947
|
+
const inner = field.canBeFormula ? (
|
|
948
|
+
<OrFormula
|
|
949
|
+
nodekey={field.name}
|
|
950
|
+
isFormula={node.isFormula}
|
|
951
|
+
{...{ setProp, node }}
|
|
952
|
+
>
|
|
953
|
+
<ConfigField
|
|
954
|
+
field={field}
|
|
955
|
+
props={node}
|
|
956
|
+
setProp={setProp}
|
|
957
|
+
onChange={onChange}
|
|
958
|
+
/>
|
|
959
|
+
</OrFormula>
|
|
960
|
+
) : (
|
|
940
961
|
<ConfigField
|
|
941
962
|
field={field}
|
|
942
963
|
props={node}
|
|
943
964
|
setProp={setProp}
|
|
944
965
|
onChange={onChange}
|
|
966
|
+
isStyle={isStyle}
|
|
945
967
|
/>
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
isStyle={isStyle}
|
|
954
|
-
/>
|
|
955
|
-
);
|
|
956
|
-
return (
|
|
957
|
-
<tr>
|
|
958
|
-
{fullWidth ? (
|
|
959
|
-
<td colSpan="2">
|
|
960
|
-
{needLabel && <label>{field.label}</label>}
|
|
961
|
-
{inner}
|
|
962
|
-
</td>
|
|
963
|
-
) : (
|
|
964
|
-
<Fragment>
|
|
965
|
-
<td>
|
|
966
|
-
<label>{field.label}</label>
|
|
968
|
+
);
|
|
969
|
+
return (
|
|
970
|
+
<tr>
|
|
971
|
+
{fullWidth ? (
|
|
972
|
+
<td colSpan="2">
|
|
973
|
+
{needLabel && <label>{field.label}</label>}
|
|
974
|
+
{inner}
|
|
967
975
|
</td>
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
}
|
|
976
|
+
) : (
|
|
977
|
+
<Fragment>
|
|
978
|
+
<td>
|
|
979
|
+
<label>{field.label}</label>
|
|
980
|
+
</td>
|
|
981
|
+
<td>{inner}</td>
|
|
982
|
+
</Fragment>
|
|
983
|
+
)}
|
|
984
|
+
</tr>
|
|
985
|
+
);
|
|
986
|
+
};
|
|
974
987
|
|
|
975
988
|
/**
|
|
976
989
|
* @category saltcorn-builder
|
|
@@ -1047,83 +1060,83 @@ export /**
|
|
|
1047
1060
|
* @subcategory components / elements / utils
|
|
1048
1061
|
* @namespace
|
|
1049
1062
|
*/
|
|
1050
|
-
const ButtonOrLinkSettingsRows = ({
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
}) => {
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1063
|
+
const ButtonOrLinkSettingsRows = ({
|
|
1064
|
+
setProp,
|
|
1065
|
+
btnClass = null,
|
|
1066
|
+
keyPrefix = "",
|
|
1067
|
+
values,
|
|
1068
|
+
linkFirst = false,
|
|
1069
|
+
}) => {
|
|
1070
|
+
const setAProp = setAPropGen(setProp);
|
|
1071
|
+
const addBtnClass = (s) => (btnClass ? `${btnClass} ${s}` : s);
|
|
1072
|
+
return [
|
|
1073
|
+
<tr key="btnstyle">
|
|
1074
|
+
<td>
|
|
1075
|
+
<label>Style</label>
|
|
1076
|
+
</td>
|
|
1077
|
+
<td>
|
|
1078
|
+
<select
|
|
1079
|
+
className="form-control form-select"
|
|
1080
|
+
value={values[keyPrefix + "style"]}
|
|
1081
|
+
onChange={setAProp(keyPrefix + "style")}
|
|
1082
|
+
>
|
|
1083
|
+
{linkFirst ? (
|
|
1084
|
+
<option value={addBtnClass("btn-link")}>Link</option>
|
|
1085
|
+
) : null}
|
|
1086
|
+
<option value={addBtnClass("btn-primary")}>Primary button</option>
|
|
1087
|
+
<option value={addBtnClass("btn-secondary")}>Secondary button</option>
|
|
1088
|
+
<option value={addBtnClass("btn-success")}>Success button</option>
|
|
1089
|
+
<option value={addBtnClass("btn-danger")}>Danger button</option>
|
|
1090
|
+
<option value={addBtnClass("btn-outline-primary")}>
|
|
1091
|
+
Primary outline button
|
|
1092
|
+
</option>
|
|
1093
|
+
<option value={addBtnClass("btn-outline-secondary")}>
|
|
1094
|
+
Secondary outline button
|
|
1095
|
+
</option>
|
|
1096
|
+
<option value={addBtnClass("btn-custom-color")}>
|
|
1097
|
+
Button custom color
|
|
1098
|
+
</option>
|
|
1099
|
+
{!linkFirst ? (
|
|
1100
|
+
<option value={addBtnClass("btn-link")}>Link</option>
|
|
1101
|
+
) : null}
|
|
1102
|
+
</select>
|
|
1103
|
+
</td>
|
|
1104
|
+
</tr>,
|
|
1105
|
+
<tr key="btnsz">
|
|
1106
|
+
<td>
|
|
1107
|
+
<label>Size</label>
|
|
1108
|
+
</td>
|
|
1109
|
+
<td>
|
|
1110
|
+
<select
|
|
1111
|
+
className="form-control form-select"
|
|
1112
|
+
value={values[keyPrefix + "size"]}
|
|
1113
|
+
onChange={setAProp(keyPrefix + "size")}
|
|
1114
|
+
>
|
|
1115
|
+
<option value="">Standard</option>
|
|
1116
|
+
<option value="btn-lg">Large</option>
|
|
1117
|
+
<option value="btn-sm">Small</option>
|
|
1118
|
+
<option value="btn-block">Block</option>
|
|
1119
|
+
<option value="btn-block btn-lg">Large block</option>
|
|
1120
|
+
</select>
|
|
1121
|
+
</td>
|
|
1122
|
+
</tr>,
|
|
1123
|
+
<tr key="btnicon">
|
|
1124
|
+
<td>
|
|
1125
|
+
<label>Icon</label>
|
|
1126
|
+
</td>
|
|
1127
|
+
<td>
|
|
1128
|
+
<FontIconPicker
|
|
1129
|
+
value={values[keyPrefix + "icon"]}
|
|
1130
|
+
onChange={(value) =>
|
|
1131
|
+
setProp((prop) => (prop[keyPrefix + "icon"] = value))
|
|
1132
|
+
}
|
|
1133
|
+
isMulti={false}
|
|
1134
|
+
icons={faIcons}
|
|
1135
|
+
/>
|
|
1136
|
+
</td>
|
|
1137
|
+
</tr>,
|
|
1138
|
+
...(values[keyPrefix + "style"] === addBtnClass("btn-custom-color")
|
|
1139
|
+
? [
|
|
1127
1140
|
<tr key="btnbgcol">
|
|
1128
1141
|
<td>
|
|
1129
1142
|
<label>Background</label>
|
|
@@ -1164,9 +1177,9 @@ const ButtonOrLinkSettingsRows = ({
|
|
|
1164
1177
|
</td>
|
|
1165
1178
|
</tr>,
|
|
1166
1179
|
]
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
};
|
|
1180
|
+
: []),
|
|
1181
|
+
];
|
|
1182
|
+
};
|
|
1170
1183
|
|
|
1171
1184
|
/**
|
|
1172
1185
|
* @function
|
|
@@ -1227,10 +1240,21 @@ export const isBlock = (block, inline, textStyle) =>
|
|
|
1227
1240
|
|
|
1228
1241
|
export const setAPropGen =
|
|
1229
1242
|
(setProp) =>
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1243
|
+
(key, opts = {}) =>
|
|
1244
|
+
(e) => {
|
|
1245
|
+
if (e.target) {
|
|
1246
|
+
const target_value = opts?.checked ? e.target.checked : e.target.value;
|
|
1247
|
+
setProp((prop) => (prop[key] = target_value));
|
|
1248
|
+
}
|
|
1249
|
+
};
|
|
1250
|
+
|
|
1251
|
+
const Tooltip = ({ children }) => {
|
|
1252
|
+
const [visible, setVisible] = useState(false);
|
|
1253
|
+
const show = () => setVisible(true);
|
|
1254
|
+
const hide = () => setVisible(false);
|
|
1255
|
+
return <Tippy content={children} visible={visible} onClickOutside={hide} interactive={true}>
|
|
1256
|
+
<span
|
|
1257
|
+
onClick={visible ? hide : show} className="ms-1"
|
|
1258
|
+
><FontAwesomeIcon icon={faInfoCircle} /></span>
|
|
1259
|
+
</Tippy>
|
|
1260
|
+
}
|