@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,9 @@
1
+ /**
2
+ * @category saltcorn-builder
3
+ * @module components/preview_context
4
+ * @subcategory components
5
+ */
6
+
7
+ import { createContext } from "react";
8
+
9
+ export default createContext({});
@@ -0,0 +1,506 @@
1
+ /**
2
+ * @category saltcorn-builder
3
+ * @module components/storage
4
+ * @subcategory components
5
+ */
6
+
7
+ import React, { Fragment } from "react";
8
+ import { Element } from "@craftjs/core";
9
+ import { Text } from "./elements/Text";
10
+ import { Field } from "./elements/Field";
11
+ import { Empty } from "./elements/Empty";
12
+ import { Columns, ntimes, sum } from "./elements/Columns";
13
+ import { JoinField } from "./elements/JoinField";
14
+ import { Tabs } from "./elements/Tabs";
15
+ import { Aggregation } from "./elements/Aggregation";
16
+ import { LineBreak } from "./elements/LineBreak";
17
+ import { ViewLink } from "./elements/ViewLink";
18
+ import { Action } from "./elements/Action";
19
+ import { HTMLCode } from "./elements/HTMLCode";
20
+ import { Card } from "./elements/Card";
21
+ import { Image } from "./elements/Image";
22
+ import { Link } from "./elements/Link";
23
+ import { View } from "./elements/View";
24
+ import { SearchBar } from "./elements/SearchBar";
25
+ import { Container } from "./elements/Container";
26
+ import { DropDownFilter } from "./elements/DropDownFilter";
27
+ import { ToggleFilter } from "./elements/ToggleFilter";
28
+ import { DropMenu } from "./elements/DropMenu";
29
+
30
+ /**
31
+ * @param {object} segment
32
+ * @returns {number}
33
+ */
34
+ const getColWidths = (segment) => {
35
+ if (!segment.widths)
36
+ return ntimes(
37
+ segment.besides.length - 1,
38
+ () => 12 / segment.besides.length
39
+ );
40
+
41
+ var widths = [...segment.widths];
42
+ widths.pop();
43
+ return widths;
44
+ };
45
+
46
+ /**
47
+ * @param {object} segment
48
+ * @returns {object[]}
49
+ */
50
+ const default_breakpoints = (segment) =>
51
+ ntimes(segment.besides.length, () => segment.breakpoint || "");
52
+
53
+ const allElements = [
54
+ Text,
55
+ Empty,
56
+ Columns,
57
+ JoinField,
58
+ Field,
59
+ ViewLink,
60
+ Action,
61
+ HTMLCode,
62
+ LineBreak,
63
+ Aggregation,
64
+ Card,
65
+ Image,
66
+ Link,
67
+ View,
68
+ SearchBar,
69
+ Container,
70
+ DropDownFilter,
71
+ Tabs,
72
+ ToggleFilter,
73
+ DropMenu,
74
+ ];
75
+
76
+ export /**
77
+ * @param {object} layout
78
+ * @param {object} query
79
+ * @param {object} actions
80
+ * @param {string} [parent = "ROOT"]
81
+ * @returns {Text|View|Action|Element|Tabs|Columns}
82
+ * @category saltcorn-builder
83
+ * @subcategory components
84
+ * @namespace
85
+ */
86
+ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
87
+ //console.log("layoutToNodes", JSON.stringify(layout));
88
+ /**
89
+ * @param {object} segment
90
+ * @param {string} ix
91
+ * @returns {Element|Text|View|Action|Tabs|Columns}
92
+ */
93
+ function toTag(segment, ix) {
94
+ if (!segment) return <Empty key={ix} />;
95
+
96
+ const MatchElement = allElements.find(
97
+ (e) =>
98
+ e.craft.related &&
99
+ e.craft.related.fields &&
100
+ e.craft.related.segment_type &&
101
+ e.craft.related.segment_type == segment.type &&
102
+ (!e.craft.related.segment_match ||
103
+ e.craft.related.segment_match(segment))
104
+ );
105
+ if (MatchElement) {
106
+ const related = MatchElement.craft.related;
107
+ const props = {};
108
+ related.fields.forEach((f) => {
109
+ const v = segment[f.segment_name || f.name || f];
110
+ props[f.name || f] = typeof v === "undefined" ? f.default : v;
111
+ });
112
+ if (related.fields.some((f) => f.canBeFormula))
113
+ props.isFormula = segment.isFormula;
114
+ if (related.hasContents)
115
+ return (
116
+ <Element key={ix} canvas {...props} is={MatchElement}>
117
+ {toTag(segment.contents)}
118
+ </Element>
119
+ );
120
+ else return <MatchElement key={ix} {...props} />;
121
+ }
122
+
123
+ if (segment.type === "blank") {
124
+ return (
125
+ <Text
126
+ key={ix}
127
+ text={segment.contents}
128
+ isFormula={segment.isFormula || {}}
129
+ block={segment.block || false}
130
+ inline={segment.inline || false}
131
+ textStyle={segment.textStyle || ""}
132
+ labelFor={segment.labelFor || ""}
133
+ style={segment.style || {}}
134
+ icon={segment.icon}
135
+ font={segment.font || ""}
136
+ />
137
+ );
138
+ } else if (segment.type === "view") {
139
+ return (
140
+ <View
141
+ key={ix}
142
+ view={segment.view}
143
+ name={segment.name}
144
+ state={segment.state}
145
+ extra_state_fml={segment.extra_state_fml}
146
+ configuration={segment.configuration || {}}
147
+ />
148
+ );
149
+ } else if (segment.type === "action") {
150
+ return (
151
+ <Action
152
+ key={ix}
153
+ name={segment.action_name}
154
+ rndid={segment.rndid || "not_assigned"}
155
+ action_label={segment.action_label || ""}
156
+ action_style={segment.action_style || "btn-primary"}
157
+ action_size={segment.action_size || ""}
158
+ action_icon={segment.action_icon || ""}
159
+ action_bgcol={segment.action_bgcol || ""}
160
+ action_bordercol={segment.action_bordercol || ""}
161
+ action_textcol={segment.action_textcol || ""}
162
+ confirm={segment.confirm}
163
+ configuration={segment.configuration || {}}
164
+ block={segment.block || false}
165
+ minRole={segment.minRole || 10}
166
+ isFormula={segment.isFormula || {}}
167
+ />
168
+ );
169
+ } else if (segment.type === "container") {
170
+ return (
171
+ <Element
172
+ key={ix}
173
+ canvas
174
+ gradStartColor={segment.gradStartColor}
175
+ gradEndColor={segment.gradEndColor}
176
+ gradDirection={segment.gradDirection}
177
+ rotate={segment.rotate || 0}
178
+ customClass={segment.customClass}
179
+ customCSS={segment.customCSS}
180
+ overflow={segment.overflow}
181
+ margin={segment.margin || [0, 0, 0, 0]}
182
+ padding={segment.padding || [0, 0, 0, 0]}
183
+ minHeight={segment.minHeight}
184
+ height={segment.height}
185
+ width={segment.width}
186
+ url={segment.url}
187
+ hoverColor={segment.hoverColor}
188
+ minHeightUnit={segment.minHeightUnit || "px"}
189
+ heightUnit={segment.heightUnit || "px"}
190
+ widthUnit={segment.widthUnit || "px"}
191
+ vAlign={segment.vAlign}
192
+ hAlign={segment.hAlign}
193
+ htmlElement={segment.htmlElement || "div"}
194
+ display={
195
+ segment.display ||
196
+ (segment.block === true
197
+ ? "block"
198
+ : segment.block === false
199
+ ? "inline-block"
200
+ : "block")
201
+ }
202
+ fullPageWidth={
203
+ typeof segment.fullPageWidth === "undefined"
204
+ ? false
205
+ : segment.fullPageWidth
206
+ }
207
+ bgFileId={segment.bgFileId}
208
+ imageSize={segment.imageSize || "contain"}
209
+ imgResponsiveWidths={segment.imgResponsiveWidths}
210
+ bgType={segment.bgType || "None"}
211
+ style={segment.style || {}}
212
+ bgColor={segment.bgColor || "#ffffff"}
213
+ setTextColor={!!segment.setTextColor}
214
+ textColor={segment.textColor || "#000000"}
215
+ isFormula={segment.isFormula || {}}
216
+ showIfFormula={segment.showIfFormula || ""}
217
+ showForRole={segment.showForRole || []}
218
+ minScreenWidth={segment.minScreenWidth || ""}
219
+ maxScreenWidth={segment.maxScreenWidth || ""}
220
+ show_for_owner={!!segment.show_for_owner}
221
+ is={Container}
222
+ >
223
+ {toTag(segment.contents)}
224
+ </Element>
225
+ );
226
+ } else if (segment.type === "tabs") {
227
+ let contentsArray = segment.contents.map(toTag);
228
+ let contents;
229
+ if (segment.tabsStyle === "Value switch") {
230
+ contents = {};
231
+ segment.titles.forEach(({ label, value }, ix) => {
232
+ contents[value] = contentsArray[ix];
233
+ });
234
+ } else contents = contentsArray;
235
+ return (
236
+ <Tabs
237
+ key={ix}
238
+ titles={segment.titles}
239
+ ntabs={segment.ntabs}
240
+ independent={segment.independent}
241
+ deeplink={segment.deeplink}
242
+ field={segment.field}
243
+ tabsStyle={segment.tabsStyle}
244
+ contents={contents}
245
+ />
246
+ );
247
+ } else if (segment.besides) {
248
+ return (
249
+ <Columns
250
+ key={ix}
251
+ breakpoints={segment.breakpoints || default_breakpoints(segment)}
252
+ ncols={segment.besides.length}
253
+ widths={getColWidths(segment)}
254
+ style={segment.style || {}}
255
+ contents={segment.besides.map(toTag)}
256
+ />
257
+ );
258
+ } else if (segment.above) {
259
+ return segment.above.map((e, ix) => toTag(e, ix));
260
+ }
261
+ }
262
+
263
+ /**
264
+ * @param {object} segment
265
+ * @param {object} parent
266
+ * @returns {void}
267
+ */
268
+ function go(segment, parent) {
269
+ if (!segment) return;
270
+ if (segment.above) {
271
+ segment.above.forEach((child) => {
272
+ if (child) go(child, parent);
273
+ });
274
+ } else if (segment.besides) {
275
+ const node = query
276
+ .parseReactElement(
277
+ <Columns
278
+ widths={getColWidths(segment)}
279
+ breakpoints={segment.breakpoints || default_breakpoints(segment)}
280
+ ncols={segment.besides.length}
281
+ style={segment.style || {}}
282
+ contents={segment.besides.map(toTag)}
283
+ />
284
+ )
285
+ .toNodeTree();
286
+ actions.addNodeTree(node, parent);
287
+ } else {
288
+ const tag = toTag(segment);
289
+ if (tag) {
290
+ const node = query.parseReactElement(tag).toNodeTree();
291
+ //console.log("other", node);
292
+ actions.addNodeTree(node, parent);
293
+ }
294
+ }
295
+ }
296
+ //const node1 = query.createNode(toTag(layout));
297
+ //actions.add(node1, );
298
+ go(layout, parent);
299
+ };
300
+
301
+ /**
302
+ * @returns {number}
303
+ */
304
+ const rand_ident = () => Math.floor(Math.random() * 16777215).toString(16);
305
+
306
+ export /**
307
+ * @param {object[]} nodes
308
+ * @param {string} [startFrom = "ROOT" ]
309
+ * @returns {object}
310
+ * @category saltcorn-builder
311
+ * @subcategory components
312
+ * @namespace
313
+ */
314
+ const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
315
+ //console.log(JSON.stringify(nodes, null, 2));
316
+ var columns = [];
317
+
318
+ /**
319
+ * @param {object} node
320
+ * @returns {void|object}
321
+ */
322
+ const get_nodes = (node) => {
323
+ if (!node.nodes || node.nodes.length == 0) return;
324
+ else if (node.nodes.length == 1) return go(nodes[node.nodes[0]]);
325
+ else return { above: node.nodes.map((nm) => go(nodes[nm])) };
326
+ };
327
+
328
+ /**
329
+ * @param {object} node
330
+ * @returns {object}
331
+ */
332
+ const go = (node) => {
333
+ if (!node) return;
334
+ const matchElement = allElements.find(
335
+ (e) =>
336
+ e.craft.related &&
337
+ node.displayName === e.craft.displayName &&
338
+ e.craft.related.fields &&
339
+ e.craft.related.segment_type
340
+ );
341
+ if (matchElement) {
342
+ const related = matchElement.craft.related;
343
+ const s = { type: related.segment_type };
344
+ if (related.hasContents) s.contents = get_nodes(node);
345
+ related.fields.forEach((f) => {
346
+ s[f.segment_name || f.name || f] = node.props[f.name || f];
347
+ });
348
+ if (related.fields.some((f) => f.canBeFormula))
349
+ s.isFormula = node.props.isFormula;
350
+ if (related.segment_vars) Object.assign(s, related.segment_vars);
351
+ if (related.column_type) {
352
+ const c = { type: related.column_type };
353
+ related.fields.forEach((f) => {
354
+ c[f.column_name || f.name || f] = node.props[f.name || f];
355
+ });
356
+ columns.push(c);
357
+ }
358
+ return s;
359
+ }
360
+ if (node.isCanvas) {
361
+ if (node.displayName === Container.craft.displayName)
362
+ return {
363
+ contents: get_nodes(node),
364
+ type: "container",
365
+ customCSS: node.props.customCSS,
366
+ customClass: node.props.customClass,
367
+ minHeight: node.props.minHeight,
368
+ height: node.props.height,
369
+ width: node.props.width,
370
+ url: node.props.url,
371
+ hoverColor: node.props.hoverColor,
372
+ minHeightUnit: node.props.minHeightUnit,
373
+ heightUnit: node.props.heightUnit,
374
+ widthUnit: node.props.widthUnit,
375
+ vAlign: node.props.vAlign,
376
+ hAlign: node.props.hAlign,
377
+ htmlElement: node.props.htmlElement,
378
+ margin: node.props.margin,
379
+ padding: node.props.padding,
380
+ overflow: node.props.overflow,
381
+ display: node.props.display,
382
+ fullPageWidth: node.props.fullPageWidth || false,
383
+ bgFileId: node.props.bgFileId,
384
+ bgType: node.props.bgType,
385
+ imageSize: node.props.imageSize,
386
+ imgResponsiveWidths: node.props.imgResponsiveWidths,
387
+ bgColor: node.props.bgColor,
388
+ setTextColor: node.props.setTextColor,
389
+ textColor: node.props.textColor,
390
+ isFormula: node.props.isFormula,
391
+ showIfFormula: node.props.showIfFormula,
392
+ showForRole: node.props.showForRole,
393
+ minScreenWidth: node.props.minScreenWidth,
394
+ maxScreenWidth: node.props.maxScreenWidth,
395
+ show_for_owner: node.props.show_for_owner,
396
+ gradStartColor: node.props.gradStartColor,
397
+ gradEndColor: node.props.gradEndColor,
398
+ gradDirection: node.props.gradDirection,
399
+ rotate: node.props.rotate,
400
+ style: node.props.style,
401
+ };
402
+ else return get_nodes(node);
403
+ }
404
+
405
+ if (node.displayName === Text.craft.displayName) {
406
+ return {
407
+ type: "blank",
408
+ contents: node.props.text,
409
+ block: node.props.block,
410
+ inline: node.props.inline,
411
+ textStyle: node.props.textStyle,
412
+ isFormula: node.props.isFormula,
413
+ labelFor: node.props.labelFor,
414
+ style: node.props.style,
415
+ icon: node.props.icon,
416
+ font: node.props.font,
417
+ };
418
+ }
419
+
420
+ if (node.displayName === Columns.craft.displayName) {
421
+ const widths = [...node.props.widths, 12 - sum(node.props.widths)];
422
+ return {
423
+ besides: widths.map((w, ix) => go(nodes[node.linkedNodes["Col" + ix]])),
424
+ breakpoints: node.props.breakpoints,
425
+ style: node.props.style,
426
+ widths,
427
+ };
428
+ }
429
+ if (node.displayName === Tabs.craft.displayName) {
430
+ let contents;
431
+ if (node.props.tabsStyle === "Value switch") {
432
+ contents = node.props.titles.map(({ value }, ix) => {
433
+ const useIx = typeof value === "undefined" ? ix : value;
434
+ return go(nodes[node.linkedNodes["Tab" + useIx]]);
435
+ });
436
+ } else
437
+ contents = ntimes(node.props.ntabs, (ix) =>
438
+ go(nodes[node.linkedNodes["Tab" + ix]])
439
+ );
440
+ return {
441
+ type: "tabs",
442
+ contents,
443
+ titles: node.props.titles,
444
+ tabsStyle: node.props.tabsStyle,
445
+ field: node.props.field,
446
+ independent: node.props.independent,
447
+ deeplink: node.props.deeplink,
448
+ ntabs: node.props.ntabs,
449
+ };
450
+ }
451
+
452
+ if (node.displayName === View.craft.displayName) {
453
+ return {
454
+ type: "view",
455
+ view: node.props.view,
456
+ name:
457
+ node.props.name === "not_assigned" ? rand_ident() : node.props.name,
458
+ state: node.props.state,
459
+ configuration: node.props.configuration,
460
+ extra_state_fml: node.props.extra_state_fml,
461
+ };
462
+ }
463
+
464
+ if (node.displayName === Action.craft.displayName) {
465
+ const newid = rand_ident();
466
+ columns.push({
467
+ type: "Action",
468
+ action_name: node.props.name,
469
+ action_label: node.props.action_label,
470
+ action_style: node.props.action_style,
471
+ action_size: node.props.action_size,
472
+ action_icon: node.props.action_icon,
473
+ action_bgcol: node.props.action_bgcol,
474
+ action_bordercol: node.props.action_bordercol,
475
+ action_textcol: node.props.action_textcol,
476
+ minRole: node.props.minRole,
477
+ confirm: node.props.confirm,
478
+ configuration: node.props.configuration,
479
+ isFormula: node.props.isFormula,
480
+ rndid: node.props.rndid === "not_assigned" ? newid : node.props.rndid,
481
+ });
482
+ return {
483
+ type: "action",
484
+ block: node.props.block,
485
+ configuration: node.props.configuration,
486
+ confirm: node.props.confirm,
487
+ action_name: node.props.name,
488
+ action_label: node.props.action_label,
489
+ action_style: node.props.action_style,
490
+ action_size: node.props.action_size,
491
+ action_icon: node.props.action_icon,
492
+ action_bgcol: node.props.action_bgcol,
493
+ action_bordercol: node.props.action_bordercol,
494
+ action_textcol: node.props.action_textcol,
495
+ minRole: node.props.minRole,
496
+ isFormula: node.props.isFormula,
497
+ rndid: node.props.rndid === "not_assigned" ? newid : node.props.rndid,
498
+ };
499
+ }
500
+ };
501
+ const layout = go(nodes[startFrom]) || { type: "blank", contents: "" };
502
+ /*console.log("nodes", JSON.stringify(nodes));
503
+ console.log("cols", JSON.stringify(columns));
504
+ console.log("layout", JSON.stringify(layout));*/
505
+ return { columns, layout };
506
+ };
package/src/index.js ADDED
@@ -0,0 +1,73 @@
1
+ /**
2
+ * @category saltcorn-builder
3
+ * @module saltcorn-builder/index
4
+ */
5
+
6
+ /**
7
+ * All files in the saltcorn-builder package.
8
+ * @namespace saltcorn-builder_overview
9
+ * @property {module:components/Builder} Builder
10
+ * @property {module:components/context} context
11
+ * @property {module:components/Library} Library
12
+ * @property {module:components/preview_context} preview_context
13
+ * @property {module:components/RenderNode} RenderNode
14
+ * @property {module:components/storage} storage
15
+ * @property {module:components/Toolbox} Toolbox
16
+ *
17
+ * @category saltcorn-builder
18
+ */
19
+
20
+ /**
21
+ * All files in the elements folder.
22
+ * @namespace saltcorn-builder_overview/elements
23
+ * @memberof module:saltcorn-builder/index~saltcorn-builder_overview
24
+ * @property {module:components/elements/Action} Action
25
+ * @property {module:components/elements/Aggregation} Aggregation
26
+ * @property {module:components/elements/BoxModelEditor} BoxModelEditor
27
+ * @property {module:components/elements/Card} Card
28
+ * @property {module:components/elements/Column} Column
29
+ * @property {module:components/elements/Columns} Columns
30
+ * @property {module:components/elements/Container} Container
31
+ * @property {module:components/elements/DropDownFilter} DropDownFilter
32
+ * @property {module:components/elements/Empty} Empty
33
+ * @property {module:components/elements/faicons} faicons
34
+ * @property {module:components/elements/Field} Field
35
+ * @property {module:components/elements/HTMLCode} HTMLCode
36
+ * @property {module:components/elements/Image} Image
37
+ * @property {module:components/elements/JoinField} JoinField
38
+ * @property {module:components/elements/LineBreak} LineBreak
39
+ * @property {module:components/elements/Link} Link
40
+ * @property {module:components/elements/SearchBar} SearchBar
41
+ * @property {module:components/elements/Tabs} Tabs
42
+ * @property {module:components/elements/Text} Text
43
+ * @property {module:components/elements/ToggleFilter} ToggleFilter
44
+ * @property {module:components/elements/utils} utils
45
+ * @property {module:components/elements/View} View
46
+ * @property {module:components/elements/ViewLink} ViewLink
47
+ *
48
+ * @category saltcorn-builder
49
+ */
50
+
51
+ import React from "react";
52
+ import Builder from "./components/Builder";
53
+ import ReactDOM from "react-dom";
54
+
55
+ /**
56
+ *
57
+ * @param {object} id
58
+ * @param {object} options
59
+ * @param {object} layout
60
+ * @param {string} mode
61
+ */
62
+ function renderBuilder(id, options, layout, mode) {
63
+ ReactDOM.render(
64
+ <Builder
65
+ options={JSON.parse(decodeURIComponent(options))}
66
+ layout={JSON.parse(decodeURIComponent(layout))}
67
+ mode={mode}
68
+ />,
69
+ document.getElementById(id)
70
+ );
71
+ }
72
+
73
+ export { renderBuilder };
@@ -0,0 +1,21 @@
1
+ const path = require("path");
2
+
3
+ module.exports = {
4
+ module: {
5
+ rules: [
6
+ {
7
+ test: /\.(js|jsx)$/,
8
+ exclude: /node_modules/,
9
+ use: {
10
+ loader: "babel-loader",
11
+ },
12
+ },
13
+ ],
14
+ },
15
+ output: {
16
+ filename: "builder_bundle.js",
17
+ library: "builder",
18
+ //libraryTarget: 'window',
19
+ //libraryExport: 'default'
20
+ },
21
+ };