@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,305 @@
1
+ /**
2
+ * @category saltcorn-builder
3
+ * @module components/elements/Link
4
+ * @subcategory components / elements
5
+ */
6
+
7
+ import React, { Fragment, useContext } from "react";
8
+ import { useNode } from "@craftjs/core";
9
+ import {
10
+ blockProps,
11
+ BlockSetting,
12
+ TextStyleSetting,
13
+ OrFormula,
14
+ ButtonOrLinkSettingsRows,
15
+ DynamicFontAwesomeIcon,
16
+ } from "./utils";
17
+ import optionsCtx from "../context";
18
+
19
+ export /**
20
+ * @param {object} props
21
+ * @param {string} props.text
22
+ * @param {boolean} props.block
23
+ * @param {object} props.isFormula
24
+ * @param {string} props.textStyle
25
+ * @param {string} props.link_style
26
+ * @param {string} props.link_size
27
+ * @param {string} [props.link_icon]
28
+ * @param {string} [props.link_bgcol]
29
+ * @param {string} [props.link_bordercol]
30
+ * @param {string} [props.link_textcol]
31
+ * @returns {Fragment}
32
+ * @namespace
33
+ * @category saltcorn-builder
34
+ * @subcategory components
35
+ */
36
+ const Link = ({
37
+ text,
38
+ block,
39
+ isFormula,
40
+ textStyle,
41
+ link_style,
42
+ link_size,
43
+ link_icon,
44
+ link_bgcol,
45
+ link_bordercol,
46
+ link_textcol,
47
+ }) => {
48
+ const {
49
+ selected,
50
+ connectors: { connect, drag },
51
+ } = useNode((node) => ({ selected: node.events.selected }));
52
+ return (
53
+ <span
54
+ className={`${textStyle} is-builder-link ${
55
+ selected ? "selected-node" : ""
56
+ } ${isFormula?.text ? "font-monospace" : ""} ${link_style} ${link_size}`}
57
+ {...blockProps(block)}
58
+ ref={(dom) => connect(drag(dom))}
59
+ style={
60
+ link_style === "btn btn-custom-color"
61
+ ? {
62
+ backgroundColor: link_bgcol || "#000000",
63
+ borderColor: link_bordercol || "#000000",
64
+ color: link_textcol || "#000000",
65
+ }
66
+ : {}
67
+ }
68
+ >
69
+ <DynamicFontAwesomeIcon icon={link_icon} className="me-1" />
70
+ {isFormula?.text ? `=${text}` : text}
71
+ </span>
72
+ );
73
+ };
74
+
75
+ export /**
76
+ * @returns {div}
77
+ * @namespace
78
+ * @category saltcorn-builder
79
+ * @subcategory components
80
+ */
81
+ const LinkSettings = () => {
82
+ const node = useNode((node) => ({
83
+ text: node.data.props.text,
84
+ url: node.data.props.url,
85
+ block: node.data.props.block,
86
+ isFormula: node.data.props.isFormula,
87
+ textStyle: node.data.props.textStyle,
88
+ nofollow: node.data.props.nofollow,
89
+ in_modal: node.data.props.in_modal,
90
+ link_src: node.data.props.link_src,
91
+ target_blank: node.data.props.target_blank,
92
+ link_style: node.data.props.link_style,
93
+ link_size: node.data.props.link_size,
94
+ link_icon: node.data.props.link_icon,
95
+ link_bgcol: node.data.props.link_bgcol,
96
+ link_bordercol: node.data.props.link_bordercol,
97
+ link_textcol: node.data.props.link_textcol,
98
+ }));
99
+ const {
100
+ actions: { setProp },
101
+ text,
102
+ url,
103
+ block,
104
+ isFormula,
105
+ textStyle,
106
+ nofollow,
107
+ target_blank,
108
+ link_src,
109
+ in_modal,
110
+ } = node;
111
+ const options = useContext(optionsCtx);
112
+ const setAProp = (key) => (e) => {
113
+ if (e.target) {
114
+ const target_value = e.target.value;
115
+ setProp((prop) => (prop[key] = target_value));
116
+ }
117
+ };
118
+ return (
119
+ <div>
120
+ <table className="w-100">
121
+ <tbody>
122
+ <tr>
123
+ <td>
124
+ <label>Text to display</label>
125
+ </td>
126
+ <td>
127
+ <OrFormula nodekey="text" {...{ setProp, isFormula, node }}>
128
+ <input
129
+ type="text"
130
+ className="form-control text-to-display"
131
+ value={text}
132
+ onChange={setAProp("text")}
133
+ />
134
+ </OrFormula>
135
+ </td>
136
+ </tr>
137
+ <tr>
138
+ <td>
139
+ <label>Link source</label>
140
+ </td>
141
+ <td>
142
+ <select
143
+ value={link_src}
144
+ className="form-control form-select"
145
+ onChange={(e) =>
146
+ setProp((prop) => {
147
+ prop.link_src = e.target.value;
148
+ if (e.target.value !== "URL") {
149
+ prop.isFormula.url = false;
150
+ }
151
+ })
152
+ }
153
+ >
154
+ <option>URL</option>
155
+ {(options.pages || []).length > 0 && <option>Page</option>}
156
+ {(options.views || []).length > 0 &&
157
+ options.mode === "page" && <option>View</option>}
158
+ </select>
159
+ </td>
160
+ </tr>
161
+ {link_src === "URL" && (
162
+ <tr>
163
+ <td>
164
+ <label>URL</label>
165
+ </td>
166
+ <td>
167
+ <OrFormula nodekey="url" {...{ setProp, isFormula, node }}>
168
+ <input
169
+ type="text"
170
+ className="form-control "
171
+ value={url}
172
+ onChange={setAProp("url")}
173
+ />
174
+ </OrFormula>
175
+ </td>
176
+ </tr>
177
+ )}
178
+ {link_src === "Page" && (
179
+ <tr>
180
+ <td>
181
+ <label>Page</label>
182
+ </td>
183
+ <td>
184
+ <select
185
+ value={url}
186
+ className="form-control form-select"
187
+ onChange={setAProp("url")}
188
+ >
189
+ <option></option>
190
+ {(options.pages || []).map((p) => (
191
+ <option value={`/page/${p.name}`}>{p.name}</option>
192
+ ))}
193
+ </select>
194
+ </td>
195
+ </tr>
196
+ )}
197
+ {link_src === "View" && (
198
+ <tr>
199
+ <td>
200
+ <label>View</label>
201
+ </td>
202
+ <td>
203
+ <select
204
+ value={url}
205
+ className="form-control form-select"
206
+ onChange={setAProp("url")}
207
+ >
208
+ <option></option>
209
+ {(options.views || []).map((p) => (
210
+ <option value={`/view/${p.name}`}>
211
+ {p.name} [{p.viewtemplate}]
212
+ </option>
213
+ ))}
214
+ </select>
215
+ </td>
216
+ </tr>
217
+ )}
218
+ <ButtonOrLinkSettingsRows
219
+ setProp={setProp}
220
+ keyPrefix="link_"
221
+ btnClass="btn"
222
+ values={node}
223
+ linkFirst={true}
224
+ />
225
+ </tbody>
226
+ </table>
227
+
228
+ <div className="form-check">
229
+ <input
230
+ className="form-check-input"
231
+ name="block"
232
+ type="checkbox"
233
+ checked={nofollow}
234
+ onChange={(e) =>
235
+ setProp((prop) => (prop.nofollow = e.target.checked))
236
+ }
237
+ />
238
+ <label className="form-check-label">Nofollow</label>
239
+ </div>
240
+ <div className="form-check">
241
+ <input
242
+ className="form-check-input"
243
+ name="block"
244
+ type="checkbox"
245
+ checked={target_blank}
246
+ onChange={(e) =>
247
+ setProp((prop) => (prop.target_blank = e.target.checked))
248
+ }
249
+ />
250
+ <label className="form-check-label">Open in new tab</label>
251
+ </div>
252
+ <div className="form-check">
253
+ <input
254
+ className="form-check-input"
255
+ name="block"
256
+ type="checkbox"
257
+ checked={in_modal}
258
+ onChange={(e) =>
259
+ setProp((prop) => (prop.in_modal = e.target.checked))
260
+ }
261
+ />
262
+ <label className="form-check-label">Open in popup modal?</label>
263
+ </div>
264
+ <BlockSetting block={block} setProp={setProp} />
265
+ <TextStyleSetting textStyle={textStyle} setProp={setProp} />
266
+ </div>
267
+ );
268
+ };
269
+
270
+ /**
271
+ * @type {object}
272
+ */
273
+ Link.craft = {
274
+ defaultProps: {
275
+ text: "Click here",
276
+ url: "https://saltcorn.com/",
277
+ block: false,
278
+ nofollow: false,
279
+ target_blank: false,
280
+ isFormula: {},
281
+ textStyle: "",
282
+ link_src: "URL",
283
+ },
284
+ displayName: "Link",
285
+ related: {
286
+ settings: LinkSettings,
287
+ segment_type: "link",
288
+ fields: [
289
+ { name: "text", canBeFormula: true },
290
+ { name: "url", canBeFormula: true },
291
+ { name: "link_src", default: "URL" },
292
+ "block",
293
+ "nofollow",
294
+ "target_blank",
295
+ "textStyle",
296
+ "link_size",
297
+ "link_icon",
298
+ "link_style",
299
+ "link_bgcol",
300
+ "link_bordercol",
301
+ "link_textcol",
302
+ "in_modal",
303
+ ],
304
+ },
305
+ };
@@ -0,0 +1,141 @@
1
+ /**
2
+ * @category saltcorn-builder
3
+ * @module components/elements/SearchBar
4
+ * @subcategory components / elements
5
+ */
6
+
7
+ import React, { Fragment, useState } from "react";
8
+ import { Element, useNode } from "@craftjs/core";
9
+ import { Column } from "./Column";
10
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
11
+ import { faCaretDown } from "@fortawesome/free-solid-svg-icons";
12
+
13
+ export /**
14
+ * @param {object} props
15
+ * @param {boolean} props.has_dropdown
16
+ * @param {string} props.children
17
+ * @param {boolean} props.show_badges
18
+ * @returns {div}
19
+ * @namespace
20
+ * @category saltcorn-builder
21
+ * @subcategory components
22
+ */
23
+ const SearchBar = ({ has_dropdown, children, show_badges }) => {
24
+ const {
25
+ selected,
26
+ connectors: { connect, drag },
27
+ } = useNode((node) => ({ selected: node.events.selected }));
28
+ const [showDropdown, setDropdown] = useState(false);
29
+ const [dropWidth, setDropWidth] = useState(200);
30
+ return (
31
+ <div
32
+ className={`input-group ${selected ? "selected-node" : ""}`}
33
+ ref={(dom) => {
34
+ if (dom && dom.getBoundingClientRect) {
35
+ //console.log(dom.getBoundingClientRect());
36
+ const elwidth = dom.getBoundingClientRect().width;
37
+ if (elwidth !== dropWidth) setDropWidth(elwidth);
38
+ }
39
+ connect(drag(dom));
40
+ }}
41
+ >
42
+ <button className="btn btn-outline-secondary" disabled>
43
+ <i className="fas fa-search"></i>
44
+ </button>
45
+
46
+ <input
47
+ type="text"
48
+ className="form-control bg-light"
49
+ placeholder="Search..."
50
+ disabled
51
+ />
52
+
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>
73
+ </div>
74
+ </Fragment>
75
+ )}
76
+ </div>
77
+ );
78
+ };
79
+
80
+ export /**
81
+ * @returns {div}
82
+ * @namespace
83
+ * @category saltcorn-builder
84
+ * @subcategory components
85
+ */
86
+ const SearchBarSettings = () => {
87
+ const {
88
+ actions: { setProp },
89
+ has_dropdown,
90
+ show_badges,
91
+ } = useNode((node) => ({
92
+ has_dropdown: node.data.props.has_dropdown,
93
+ show_badges: node.data.props.show_badges,
94
+ }));
95
+
96
+ return (
97
+ <div>
98
+ <div className="form-check">
99
+ <input
100
+ className="form-check-input"
101
+ name="block"
102
+ type="checkbox"
103
+ checked={has_dropdown}
104
+ onChange={(e) =>
105
+ setProp((prop) => (prop.has_dropdown = e.target.checked))
106
+ }
107
+ />
108
+ <label className="form-check-label">Has Dropdown</label>
109
+ </div>
110
+ <div className="form-check">
111
+ <input
112
+ className="form-check-input"
113
+ name="block"
114
+ type="checkbox"
115
+ checked={show_badges}
116
+ onChange={(e) =>
117
+ setProp((prop) => (prop.show_badges = e.target.checked))
118
+ }
119
+ />
120
+ <label className="form-check-label">Show current state badges</label>
121
+ </div>
122
+ </div>
123
+ );
124
+ };
125
+
126
+ /**
127
+ * @type {object}
128
+ */
129
+ SearchBar.craft = {
130
+ displayName: "SearchBar",
131
+ props: {
132
+ has_dropdown: false,
133
+ show_badges: false,
134
+ },
135
+ related: {
136
+ settings: SearchBarSettings,
137
+ segment_type: "search_bar",
138
+ hasContents: true,
139
+ fields: ["has_dropdown", "show_badges"],
140
+ },
141
+ };