@saltcorn/builder 0.0.1-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.
Files changed (38) hide show
  1. package/.babelrc +3 -0
  2. package/CHANGELOG.md +8 -0
  3. package/dist/builder_bundle.js +80 -0
  4. package/package.json +47 -0
  5. package/src/components/Builder.js +477 -0
  6. package/src/components/Library.js +224 -0
  7. package/src/components/RenderNode.js +203 -0
  8. package/src/components/Toolbox.js +688 -0
  9. package/src/components/context.js +9 -0
  10. package/src/components/elements/Action.js +204 -0
  11. package/src/components/elements/Aggregation.js +179 -0
  12. package/src/components/elements/BoxModelEditor.js +398 -0
  13. package/src/components/elements/Card.js +152 -0
  14. package/src/components/elements/Column.js +63 -0
  15. package/src/components/elements/Columns.js +201 -0
  16. package/src/components/elements/Container.js +947 -0
  17. package/src/components/elements/DropDownFilter.js +154 -0
  18. package/src/components/elements/DropMenu.js +156 -0
  19. package/src/components/elements/Empty.js +30 -0
  20. package/src/components/elements/Field.js +239 -0
  21. package/src/components/elements/HTMLCode.js +61 -0
  22. package/src/components/elements/Image.js +320 -0
  23. package/src/components/elements/JoinField.js +206 -0
  24. package/src/components/elements/LineBreak.js +46 -0
  25. package/src/components/elements/Link.js +305 -0
  26. package/src/components/elements/SearchBar.js +141 -0
  27. package/src/components/elements/Tabs.js +347 -0
  28. package/src/components/elements/Text.js +330 -0
  29. package/src/components/elements/ToggleFilter.js +243 -0
  30. package/src/components/elements/View.js +189 -0
  31. package/src/components/elements/ViewLink.js +225 -0
  32. package/src/components/elements/boxmodel.html +253 -0
  33. package/src/components/elements/faicons.js +1643 -0
  34. package/src/components/elements/utils.js +1217 -0
  35. package/src/components/preview_context.js +9 -0
  36. package/src/components/storage.js +506 -0
  37. package/src/index.js +73 -0
  38. package/webpack.config.js +21 -0
@@ -0,0 +1,398 @@
1
+ /**
2
+ * @category saltcorn-builder
3
+ * @module components/elements/BoxModelEditor
4
+ * @subcategory components / elements
5
+ */
6
+
7
+ import React, { useContext, Fragment, useState } from "react";
8
+ import { SettingsRow, SettingsSectionHeaderRow, bstyleopt } from "./utils";
9
+ /*
10
+ Contains code from https://github.com/tpaksu/boxmodel
11
+ Copyright (c) 2017 Taha Paksu
12
+ */
13
+
14
+ export /**
15
+ *
16
+ * @param {object} props
17
+ * @param {function} props.setProp
18
+ * @param {object} props.node
19
+ * @returns {Fragment}
20
+ * @category saltcorn-builder
21
+ * @subcategory components
22
+ * @namespace
23
+ */
24
+ const BoxModelEditor = ({ setProp, node, sizeWithStyle }) => {
25
+ const [selectedCategory, setSelectedCategory] = useState(false);
26
+ const [selectedDirection, setSelectedDirection] = useState(false);
27
+ const selectedProperty = !selectedCategory
28
+ ? false
29
+ : selectedDirection
30
+ ? `${selectedCategory}-${selectedDirection}`
31
+ : selectedCategory;
32
+ const setCatAndDir = (c, d) => {
33
+ setSelectedCategory(c);
34
+ setSelectedDirection(d);
35
+ };
36
+ //console.log(node.style);
37
+ const style = node.style;
38
+ return (
39
+ <Fragment>
40
+ <div className="w-100 text-center">
41
+ <div className="boxmodel-container boxmodel-chrome-skin mt-2 mx-auto text-center">
42
+ <div className="boxmodel-container">
43
+ <div className="boxmodel-margin">
44
+ <span
45
+ className="boxmodel-text boxmodel-header"
46
+ onClick={() => setCatAndDir("margin", null)}
47
+ >
48
+ Margin
49
+ </span>
50
+ <span
51
+ className="boxmodel-input-container boxmodel-input-direction-left"
52
+ onClick={() => setCatAndDir("margin", "left")}
53
+ >
54
+ <div className="rotate dim-display">
55
+ {style["margin-left"] || style["margin"] || ""}
56
+ </div>
57
+ </span>
58
+ <div className="flex-row">
59
+ <span
60
+ className="boxmodel-input-container boxmodel-input-direction-top"
61
+ onClick={() => setCatAndDir("margin", "top")}
62
+ >
63
+ <input
64
+ disabled
65
+ type="text"
66
+ autoComplete="off"
67
+ name="boxmodel-ex-1_top_margin"
68
+ size="3"
69
+ value={style["margin-top"] || style["margin"] || ""}
70
+ />
71
+ </span>
72
+ <div className="boxmodel-border">
73
+ <span
74
+ className="boxmodel-text boxmodel-header"
75
+ onClick={() => setCatAndDir("border", null)}
76
+ >
77
+ Border
78
+ </span>
79
+ <span
80
+ className="boxmodel-input-container boxmodel-input-direction-left"
81
+ onClick={() => setCatAndDir("border", "left")}
82
+ >
83
+ <div className="rotate dim-display">
84
+ {style["border-left-width"] ||
85
+ style["border-width"] ||
86
+ ""}
87
+ </div>
88
+ </span>
89
+ <div className="flex-row">
90
+ <span
91
+ className="boxmodel-input-container boxmodel-input-direction-top"
92
+ onClick={() => setCatAndDir("border", "top")}
93
+ >
94
+ <input
95
+ disabled
96
+ type="text"
97
+ autoComplete="off"
98
+ name="boxmodel-ex-1_top_border"
99
+ value={
100
+ style["border-top-width"] ||
101
+ style["border-width"] ||
102
+ ""
103
+ }
104
+ size="3"
105
+ />
106
+ </span>
107
+ <div className="boxmodel-padding">
108
+ <span
109
+ className="boxmodel-text boxmodel-header"
110
+ onClick={() => setCatAndDir("padding", null)}
111
+ >
112
+ Padding
113
+ </span>
114
+ <span
115
+ className="boxmodel-input-container boxmodel-input-direction-left"
116
+ onClick={() => setCatAndDir("padding", "left")}
117
+ >
118
+ <div className="rotate dim-display-padding">
119
+ {style["padding-left"] || style["padding"] || ""}
120
+ </div>
121
+ </span>
122
+ <div className="flex-row">
123
+ <span
124
+ className="boxmodel-input-container boxmodel-input-direction-top"
125
+ onClick={() => setCatAndDir("padding", "top")}
126
+ >
127
+ <input
128
+ disabled
129
+ type="text"
130
+ autoComplete="off"
131
+ name="boxmodel-ex-1_top_padding"
132
+ value={
133
+ style["padding-top"] || style["padding"] || ""
134
+ }
135
+ size="3"
136
+ />
137
+ </span>
138
+ <div
139
+ className="boxmodel-content"
140
+ onClick={() => setSelectedCategory("size")}
141
+ >
142
+ <input
143
+ disabled
144
+ type="text"
145
+ autoComplete="off"
146
+ name="boxmodel-ex-1_width"
147
+ size="3"
148
+ value={
149
+ sizeWithStyle
150
+ ? style["width"]
151
+ : node.width
152
+ ? `${node.width}${node.widthUnits || "px"}`
153
+ : ""
154
+ }
155
+ />
156
+ x
157
+ <input
158
+ disabled
159
+ type="text"
160
+ autoComplete="off"
161
+ name="boxmodel-ex-1_height"
162
+ size="3"
163
+ value={
164
+ sizeWithStyle
165
+ ? style["height"]
166
+ : node.height
167
+ ? `${node.height}${node.heightUnits || "px"}`
168
+ : ""
169
+ }
170
+ />
171
+ </div>
172
+ <span
173
+ className="boxmodel-input-container boxmodel-input-direction-bottom"
174
+ onClick={() => setCatAndDir("padding", "bottom")}
175
+ >
176
+ <input
177
+ disabled
178
+ type="text"
179
+ autoComplete="off"
180
+ name="boxmodel-ex-1_bottom_padding"
181
+ size="3"
182
+ value={
183
+ style["padding-bottom"] || style["padding"] || ""
184
+ }
185
+ />
186
+ </span>
187
+ </div>
188
+ <span
189
+ className="boxmodel-input-container boxmodel-input-direction-right"
190
+ onClick={() => setCatAndDir("padding", "right")}
191
+ >
192
+ <div className="rotate dim-display-padding">
193
+ {style["padding-right"] || style["padding"] || ""}
194
+ </div>
195
+ </span>
196
+ </div>
197
+ <span
198
+ className="boxmodel-input-container boxmodel-input-direction-bottom"
199
+ onClick={() => setCatAndDir("border", "bottom")}
200
+ >
201
+ <input
202
+ disabled
203
+ type="text"
204
+ autoComplete="off"
205
+ name="boxmodel-ex-1_bottom_border"
206
+ size="3"
207
+ value={
208
+ style["border-bottom-width"] ||
209
+ style["border-width"] ||
210
+ ""
211
+ }
212
+ />
213
+ </span>
214
+ </div>
215
+ <span
216
+ className="boxmodel-input-container boxmodel-input-direction-right"
217
+ onClick={() => setCatAndDir("border", "right")}
218
+ >
219
+ <div className="rotate dim-display">
220
+ {style["border-right-width"] ||
221
+ style["border-width"] ||
222
+ ""}
223
+ </div>
224
+ </span>
225
+ </div>
226
+ <span
227
+ className="boxmodel-input-container boxmodel-input-direction-bottom"
228
+ onClick={() => setCatAndDir("margin", "bottom")}
229
+ >
230
+ <input
231
+ disabled
232
+ type="text"
233
+ autoComplete="off"
234
+ name="boxmodel-ex-1_bottom_margin"
235
+ size="3"
236
+ value={style["margin-bottom"] || style["margin"] || ""}
237
+ />
238
+ </span>
239
+ </div>
240
+ <span
241
+ className="boxmodel-input-container boxmodel-input-direction-right"
242
+ onClick={() => setCatAndDir("margin", "right")}
243
+ >
244
+ <div className="rotate dim-display">
245
+ {style["margin-right"] || style["margin"] || ""}
246
+ </div>
247
+ </span>
248
+ </div>
249
+ </div>
250
+ </div>
251
+ </div>
252
+ <table className="w-100 mt-2">
253
+ <tbody>
254
+ <tr>
255
+ <td width="45%"></td>
256
+ <td></td>
257
+ </tr>
258
+ {selectedProperty &&
259
+ ["margin", "padding"].includes(selectedCategory) && (
260
+ <SettingsRow
261
+ field={{
262
+ name: selectedProperty,
263
+ label: selectedProperty,
264
+ type: "DimUnits",
265
+ autoable: selectedCategory === "margin",
266
+ }}
267
+ node={node}
268
+ setProp={setProp}
269
+ isStyle={true}
270
+ />
271
+ )}
272
+ {selectedCategory === "size" && (
273
+ <Fragment>
274
+ <SettingsRow
275
+ field={{ name: "width", label: "width", type: "DimUnits" }}
276
+ node={node}
277
+ setProp={setProp}
278
+ isStyle={!!sizeWithStyle}
279
+ />
280
+ <SettingsRow
281
+ field={{ name: "height", label: "height", type: "DimUnits" }}
282
+ node={node}
283
+ setProp={setProp}
284
+ isStyle={!!sizeWithStyle}
285
+ />
286
+ <SettingsRow
287
+ field={{
288
+ name: sizeWithStyle ? "min-height" : "minHeight",
289
+ label: "min height",
290
+ type: "DimUnits",
291
+ }}
292
+ node={node}
293
+ setProp={setProp}
294
+ isStyle={!!sizeWithStyle}
295
+ />
296
+ </Fragment>
297
+ )}
298
+ {selectedCategory === "border" && (
299
+ <Fragment>
300
+ <SettingsSectionHeaderRow title={selectedProperty} />
301
+ <SettingsRow
302
+ field={{
303
+ name: selectedProperty + "-width",
304
+ label: "width",
305
+ type: "DimUnits",
306
+ }}
307
+ node={node}
308
+ setProp={setProp}
309
+ isStyle={true}
310
+ />
311
+ <SettingsRow
312
+ field={{
313
+ name: selectedProperty + "-style",
314
+ label: "style",
315
+ type: "btn_select",
316
+ btnClass: "btnstylesel",
317
+ options: [
318
+ "solid",
319
+ "dotted",
320
+ "dashed",
321
+ "double",
322
+ "groove",
323
+ "ridge",
324
+ "inset",
325
+ "outset",
326
+ ].map(bstyleopt),
327
+ }}
328
+ node={node}
329
+ isStyle={true}
330
+ setProp={setProp}
331
+ />
332
+ <SettingsRow
333
+ field={{
334
+ name: selectedProperty + "-color",
335
+ label: "color",
336
+ type: "Color",
337
+ }}
338
+ node={node}
339
+ isStyle={true}
340
+ setProp={setProp}
341
+ />
342
+ {!selectedDirection && (
343
+ <SettingsRow
344
+ field={{
345
+ name: selectedProperty + "-radius",
346
+ label: "radius",
347
+ type: "DimUnits",
348
+ }}
349
+ node={node}
350
+ setProp={setProp}
351
+ isStyle={true}
352
+ />
353
+ )}
354
+ {selectedDirection &&
355
+ radiusCornerDirections[selectedDirection].map((corner, ix) => (
356
+ <SettingsRow
357
+ key={ix}
358
+ field={{
359
+ name: `border-${corner}-radius`,
360
+ label: corner.replace("-", " ") + " radius",
361
+ type: "DimUnits",
362
+ }}
363
+ node={node}
364
+ setProp={setProp}
365
+ isStyle={true}
366
+ />
367
+ ))}
368
+ </Fragment>
369
+ )}
370
+ {!selectedProperty && (
371
+ <tr>
372
+ <td colSpan={2}>
373
+ <div>Click above to select a property to adjust.</div>
374
+ <div>
375
+ <small>
376
+ Click a label (margin, border, padding) to adjust all edges.
377
+ </small>
378
+ </div>
379
+ <div>
380
+ <small>Click an edge to adjust that edge.</small>
381
+ </div>
382
+ <div>
383
+ <small>Click center to adjust height and width</small>
384
+ </div>
385
+ </td>
386
+ </tr>
387
+ )}
388
+ </tbody>
389
+ </table>
390
+ </Fragment>
391
+ );
392
+ };
393
+ const radiusCornerDirections = {
394
+ left: ["bottom-left", "top-left"],
395
+ right: ["bottom-right", "top-right"],
396
+ top: ["top-left", "top-right"],
397
+ bottom: ["bottom-left", "bottom-right"],
398
+ };
@@ -0,0 +1,152 @@
1
+ /**
2
+ * @category saltcorn-builder
3
+ * @module components/elements/Card
4
+ * @subcategory components / elements
5
+ */
6
+
7
+ import React, { Fragment } from "react";
8
+ import { Text } from "./Text";
9
+ import { OrFormula, SettingsRow, Accordion, reactifyStyles } from "./utils";
10
+
11
+ import { Element, useNode } from "@craftjs/core";
12
+ import { BoxModelEditor } from "./BoxModelEditor";
13
+ import { bstyleopt } from "./utils";
14
+
15
+ export /**
16
+ * @param {object} props
17
+ * @param {string} props.children
18
+ * @param {object} props.isFormula
19
+ * @param {string} [props.title]
20
+ * @param {string} props.shadow
21
+ * @param {boolean} props.noPadding
22
+ * @param {object} props.style
23
+ * @returns {div}
24
+ * @category saltcorn-builder
25
+ * @subcategory components
26
+ * @namespace
27
+ */
28
+ const Card = ({ children, isFormula, title, shadow, noPadding, style }) => {
29
+ const {
30
+ selected,
31
+ connectors: { connect, drag },
32
+ } = useNode((node) => ({ selected: node.events.selected }));
33
+
34
+ return (
35
+ <div
36
+ className={`card ${shadow ? "shadow" : ""} builder ${
37
+ selected ? "selected-node" : ""
38
+ }`}
39
+ style={reactifyStyles(style)}
40
+ ref={(dom) => connect(drag(dom))}
41
+ >
42
+ {title && title.length > 0 && (
43
+ <div className="card-header">
44
+ {isFormula?.title ? (
45
+ <span className="font-monospace">={title}</span>
46
+ ) : (
47
+ title
48
+ )}
49
+ </div>
50
+ )}
51
+ <div className={`card-body ${noPadding ? "p-0" : ""}`}>
52
+ <div className="canvas">{children}</div>
53
+ </div>
54
+ </div>
55
+ );
56
+ };
57
+
58
+ export /**
59
+ * @returns {Accordion}
60
+ * @category saltcorn-builder
61
+ * @subcategory components
62
+ * @namespace
63
+ */
64
+ const CardSettings = () => {
65
+ const node = useNode((node) => {
66
+ const ps = {};
67
+ fields.forEach((f) => {
68
+ ps[f.name] = node.data.props[f.name];
69
+ });
70
+ if (fields.some((f) => f.canBeFormula))
71
+ ps.isFormula = node.data.props.isFormula;
72
+ return ps;
73
+ });
74
+ const {
75
+ actions: { setProp },
76
+ } = node;
77
+
78
+ return (
79
+ <Accordion>
80
+ <table className="w-100" accordiontitle="Card properties">
81
+ <tbody>
82
+ <SettingsRow
83
+ field={{
84
+ label: "Card title",
85
+ name: "title",
86
+ type: "String",
87
+ canBeFormula: true,
88
+ }}
89
+ node={node}
90
+ setProp={setProp}
91
+ />
92
+ <SettingsRow
93
+ field={{
94
+ label: "URL",
95
+ name: "url",
96
+ type: "String",
97
+ canBeFormula: true,
98
+ }}
99
+ node={node}
100
+ setProp={setProp}
101
+ />
102
+ <SettingsRow
103
+ field={{ label: "Shadow", name: "shadow", type: "Bool" }}
104
+ node={node}
105
+ setProp={setProp}
106
+ />
107
+ <SettingsRow
108
+ field={{ label: "No padding", name: "noPadding", type: "Bool" }}
109
+ node={node}
110
+ setProp={setProp}
111
+ />
112
+ </tbody>
113
+ </table>
114
+ <div accordiontitle="Box" className="w-100">
115
+ <BoxModelEditor setProp={setProp} node={node} sizeWithStyle={true} />
116
+ </div>
117
+ </Accordion>
118
+ );
119
+ };
120
+
121
+ const fields = [
122
+ {
123
+ label: "Card title",
124
+ name: "title",
125
+ type: "String",
126
+ canBeFormula: true,
127
+ },
128
+ { label: "URL", name: "url", type: "String", canBeFormula: true },
129
+ { label: "Shadow", name: "shadow", type: "Bool" },
130
+ { label: "No padding", name: "noPadding", type: "Bool" },
131
+ { name: "style", default: {} },
132
+ ];
133
+
134
+ /**
135
+ * @type {object}
136
+ */
137
+ Card.craft = {
138
+ props: {
139
+ title: "",
140
+ url: "",
141
+ shadow: true,
142
+ isFormula: {},
143
+ style: {},
144
+ },
145
+ displayName: "Card",
146
+ related: {
147
+ settings: CardSettings,
148
+ segment_type: "card",
149
+ hasContents: true,
150
+ fields,
151
+ },
152
+ };
@@ -0,0 +1,63 @@
1
+ /**
2
+ * @category saltcorn-builder
3
+ * @module components/elements/Column
4
+ * @subcategory components / elements
5
+ */
6
+
7
+ import React, { useContext, Fragment } from "react";
8
+
9
+ import { Element, useNode } from "@craftjs/core";
10
+ import optionsCtx from "../context";
11
+
12
+ export /**
13
+ *
14
+ * @param {object} props
15
+ * @param {string} props.children
16
+ * @param {*} props.align
17
+ * @returns {div}
18
+ * @category saltcorn-builder
19
+ * @subcategory components
20
+ * @namespace
21
+ */
22
+ const Column = ({ children, align }) => {
23
+ const {
24
+ selected,
25
+ id,
26
+ connectors: { connect, drag },
27
+ } = useNode((node) => ({ selected: node.events.selected }));
28
+ return (
29
+ <div
30
+ className={selected ? "selected-node" : ""}
31
+ ref={(dom) => connect(drag(dom))}
32
+ >
33
+ <div className={`canvas ${id === "ROOT" ? "root-canvas" : ""}`}>
34
+ {children}
35
+ </div>
36
+ </div>
37
+ );
38
+ };
39
+
40
+ export /**
41
+ * @returns {div}
42
+ * @category saltcorn-builder
43
+ * @subcategory components
44
+ * @namespace
45
+ */
46
+ const ColumnSettings = () => {
47
+ const {} = useNode((node) => ({}));
48
+ return <div></div>;
49
+ };
50
+
51
+ /**
52
+ * @type {object}
53
+ */
54
+ Column.craft = {
55
+ displayName: "Column",
56
+ props: {},
57
+ rules: {
58
+ canDrag: () => true,
59
+ },
60
+ related: {
61
+ settings: ColumnSettings,
62
+ },
63
+ };