@saltcorn/builder 1.6.0-alpha.0 → 1.6.0-alpha.10

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 (40) hide show
  1. package/dist/builder_bundle.js +4126 -2
  2. package/dist/builder_bundle.js.LICENSE.txt +18 -51
  3. package/package.json +31 -27
  4. package/src/components/Builder.js +334 -122
  5. package/src/components/Library.js +25 -13
  6. package/src/components/RenderNode.js +19 -8
  7. package/src/components/Toolbox.js +333 -269
  8. package/src/components/elements/Action.js +144 -29
  9. package/src/components/elements/Aggregation.js +20 -23
  10. package/src/components/elements/ArrayManager.js +7 -5
  11. package/src/components/elements/BoxModelEditor.js +19 -17
  12. package/src/components/elements/Card.js +47 -34
  13. package/src/components/elements/Clone.js +74 -2
  14. package/src/components/elements/Column.js +1 -1
  15. package/src/components/elements/Columns.js +27 -25
  16. package/src/components/elements/Container.js +170 -90
  17. package/src/components/elements/DropDownFilter.js +10 -8
  18. package/src/components/elements/DropMenu.js +18 -9
  19. package/src/components/elements/Field.js +9 -7
  20. package/src/components/elements/HTMLCode.js +3 -1
  21. package/src/components/elements/Image.js +20 -15
  22. package/src/components/elements/JoinField.js +15 -11
  23. package/src/components/elements/Link.js +18 -16
  24. package/src/components/elements/ListColumn.js +7 -3
  25. package/src/components/elements/ListColumns.js +4 -1
  26. package/src/components/elements/MonacoEditor.js +4 -2
  27. package/src/components/elements/Page.js +7 -4
  28. package/src/components/elements/RelationBadges.js +16 -11
  29. package/src/components/elements/RelationOnDemandPicker.js +18 -12
  30. package/src/components/elements/SearchBar.js +37 -10
  31. package/src/components/elements/Table.js +72 -65
  32. package/src/components/elements/Tabs.js +18 -15
  33. package/src/components/elements/Text.js +19 -14
  34. package/src/components/elements/ToggleFilter.js +28 -25
  35. package/src/components/elements/View.js +36 -18
  36. package/src/components/elements/ViewLink.js +15 -11
  37. package/src/components/elements/utils.js +224 -55
  38. package/src/components/storage.js +27 -129
  39. package/src/hooks/useTranslation.js +11 -0
  40. package/src/index.js +6 -3
@@ -6,6 +6,7 @@
6
6
 
7
7
  import React, { useMemo } from "react";
8
8
  import { useNode } from "@craftjs/core";
9
+ import useTranslation from "../../hooks/useTranslation";
9
10
  import optionsCtx from "../context";
10
11
  import relationsCtx from "../relations_context";
11
12
 
@@ -20,6 +21,8 @@ import {
20
21
  HelpTopicLink,
21
22
  initialRelation,
22
23
  buildLayers,
24
+ reactSelectStyles,
25
+ builderSelectClassName,
23
26
  } from "./utils";
24
27
 
25
28
  import { RelationBadges } from "./RelationBadges";
@@ -102,6 +105,7 @@ export /**
102
105
  * @namespace
103
106
  */
104
107
  const ViewLinkSettings = () => {
108
+ const { t } = useTranslation();
105
109
  const node = useNode((node) => ({
106
110
  name: node.data.props.name,
107
111
  relation: node.data.props.relation,
@@ -233,7 +237,7 @@ const ViewLinkSettings = () => {
233
237
  } else
234
238
  window.notifyAlert({
235
239
  type: "warning",
236
- text: `${target_value} has no relations`,
240
+ text: `${target_value} ${t("has no relations")}`,
237
241
  });
238
242
  }
239
243
  }
@@ -245,24 +249,24 @@ const ViewLinkSettings = () => {
245
249
  value: name,
246
250
  }));
247
251
  const selectedView = viewOptions.find((v) => v.value === use_view_name);
252
+
248
253
  return (
249
254
  <div>
250
255
  <table className="w-100">
251
256
  <tbody>
252
257
  <tr>
253
258
  <td colSpan="2">
254
- <label>View to link to</label>
259
+ <label>{t("View to link to")}</label>
255
260
  {options.inJestTestingMode ? null : (
256
261
  <Select
257
262
  options={viewOptions}
258
- className="react-select viewlink-selector"
263
+ className={builderSelectClassName("react-select viewlink-selector")}
264
+ classNamePrefix="builder-select"
259
265
  value={selectedView}
260
266
  onChange={set_view_name}
261
267
  onBlur={set_view_name}
262
268
  menuPortalTarget={document.body}
263
- styles={{
264
- menuPortal: (base) => ({ ...base, zIndex: 19999 }),
265
- }}
269
+ styles={reactSelectStyles()}
266
270
  ></Select>
267
271
  )}
268
272
  </td>
@@ -295,7 +299,7 @@ const ViewLinkSettings = () => {
295
299
  </tr>
296
300
  <tr>
297
301
  <td colSpan="2">
298
- <label>Label (leave blank for default)</label>
302
+ <label>{t("Label (leave blank for default)")}</label>
299
303
  <OrFormula nodekey="label" {...{ setProp, isFormula, node }}>
300
304
  <input
301
305
  type="text"
@@ -309,7 +313,7 @@ const ViewLinkSettings = () => {
309
313
  <tr>
310
314
  <td colSpan="2">
311
315
  <label>
312
- Extra state Formula
316
+ {t("Extra state Formula")}
313
317
  <HelpTopicLink topic="Extra state formula" {...helpContext} />
314
318
  </label>
315
319
  <SingleLineEditor
@@ -346,7 +350,7 @@ const ViewLinkSettings = () => {
346
350
  checked={link_target_blank}
347
351
  onChange={setAProp("link_target_blank", { checked: true })}
348
352
  />
349
- <label className="form-check-label">Open in new tab</label>
353
+ <label className="form-check-label">{t("Open in new tab")}</label>
350
354
  </div>
351
355
  <div className="form-check">
352
356
  <input
@@ -356,7 +360,7 @@ const ViewLinkSettings = () => {
356
360
  checked={inModal}
357
361
  onChange={setAProp("inModal", { checked: true })}
358
362
  />
359
- <label className="form-check-label">Open in popup modal?</label>
363
+ <label className="form-check-label">{t("Open in popup modal?")}</label>
360
364
  </div>
361
365
  <BlockSetting block={block} setProp={setProp} />
362
366
  <TextStyleSetting textStyle={textStyle} setProp={setProp} />
@@ -370,7 +374,7 @@ const ViewLinkSettings = () => {
370
374
  target="_blank"
371
375
  href={`/viewedit/config/${use_view_name}`}
372
376
  >
373
- Configure this view
377
+ {t("Configure this view")}
374
378
  </a>
375
379
  </td>
376
380
  </tr>
@@ -3,8 +3,9 @@
3
3
  * @module components/elements/utils
4
4
  * @subcategory components / elements
5
5
  */
6
- /* globals $, _sc_globalCsrf*/
6
+ /* globals $, _sc_globalCsrf, apply_showif*/
7
7
  import React, { Fragment, useState, useEffect } from "react";
8
+ import useTranslation from "../../hooks/useTranslation";
8
9
  import optionsCtx from "../context";
9
10
  import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
10
11
  import {
@@ -30,6 +31,163 @@ import { RelationType } from "@saltcorn/common-code";
30
31
  import Select from "react-select";
31
32
  import { MultiLineCodeEditor, SingleLineEditor } from "./MonacoEditor";
32
33
 
34
+ const isDarkMode = () => {
35
+ if (typeof window !== "undefined" && window._sc_lightmode) {
36
+ return window._sc_lightmode === "dark";
37
+ }
38
+ if (
39
+ typeof window !== "undefined" &&
40
+ window.matchMedia &&
41
+ window.matchMedia("(prefers-color-scheme: dark)").matches
42
+ )
43
+ return true;
44
+ return false;
45
+ };
46
+
47
+ export const builderSelectClassName = (base = "") =>
48
+ [base, isDarkMode() ? "builder-select-dark" : ""].filter(Boolean).join(" ");
49
+
50
+ export const reactSelectStyles = (overrides = {}) => {
51
+ const dark = isDarkMode();
52
+ const base = {
53
+ menuPortal: (baseStyles) => ({ ...baseStyles, zIndex: 19999 }),
54
+ };
55
+
56
+ if (!dark) {
57
+ // Light mode styles
58
+ return {
59
+ ...base,
60
+ control: (baseStyles) => ({
61
+ ...baseStyles,
62
+ backgroundColor: "#ffffff",
63
+ borderColor: "#dee2e6",
64
+ color: "#212529",
65
+ }),
66
+ valueContainer: (baseStyles) => ({
67
+ ...baseStyles,
68
+ backgroundColor: "transparent",
69
+ }),
70
+ singleValue: (baseStyles) => ({
71
+ ...baseStyles,
72
+ color: "#212529",
73
+ }),
74
+ input: (baseStyles) => ({
75
+ ...baseStyles,
76
+ color: "#212529",
77
+ }),
78
+ placeholder: (baseStyles) => ({
79
+ ...baseStyles,
80
+ color: "#6c757d",
81
+ }),
82
+ menu: (baseStyles) => ({
83
+ ...baseStyles,
84
+ backgroundColor: "#ffffff",
85
+ border: "1px solid #dee2e6",
86
+ }),
87
+ menuList: (baseStyles) => ({
88
+ ...baseStyles,
89
+ backgroundColor: "#ffffff",
90
+ }),
91
+ option: (baseStyles, state) => ({
92
+ ...baseStyles,
93
+ backgroundColor: state.isFocused
94
+ ? "#e9ecef"
95
+ : state.isSelected
96
+ ? "#0d6efd"
97
+ : "transparent",
98
+ color: state.isSelected ? "#fff" : "#212529",
99
+ }),
100
+ dropdownIndicator: (baseStyles) => ({
101
+ ...baseStyles,
102
+ color: "#6c757d",
103
+ }),
104
+ clearIndicator: (baseStyles) => ({
105
+ ...baseStyles,
106
+ color: "#6c757d",
107
+ }),
108
+ indicatorSeparator: (baseStyles) => ({
109
+ ...baseStyles,
110
+ backgroundColor: "#dee2e6",
111
+ }),
112
+ groupHeading: (baseStyles) => ({
113
+ ...baseStyles,
114
+ color: "#6c757d",
115
+ }),
116
+ menuNotice: (baseStyles) => ({
117
+ ...baseStyles,
118
+ color: "#6c757d",
119
+ }),
120
+ ...overrides,
121
+ };
122
+ }
123
+
124
+ // Dark mode styles
125
+ return {
126
+ ...base,
127
+ control: (baseStyles) => ({
128
+ ...baseStyles,
129
+ backgroundColor: "#212529",
130
+ borderColor: "#495057",
131
+ color: "#f8f9fa",
132
+ }),
133
+ valueContainer: (baseStyles) => ({
134
+ ...baseStyles,
135
+ backgroundColor: "transparent",
136
+ }),
137
+ singleValue: (baseStyles) => ({
138
+ ...baseStyles,
139
+ color: "#f8f9fa",
140
+ }),
141
+ input: (baseStyles) => ({
142
+ ...baseStyles,
143
+ color: "#f8f9fa",
144
+ }),
145
+ placeholder: (baseStyles) => ({
146
+ ...baseStyles,
147
+ color: "#adb5bd",
148
+ }),
149
+ menu: (baseStyles) => ({
150
+ ...baseStyles,
151
+ backgroundColor: "#212529",
152
+ border: "1px solid #495057",
153
+ }),
154
+ menuList: (baseStyles) => ({
155
+ ...baseStyles,
156
+ backgroundColor: "#212529",
157
+ }),
158
+ option: (baseStyles, state) => ({
159
+ ...baseStyles,
160
+ backgroundColor: state.isFocused
161
+ ? "#343a40"
162
+ : state.isSelected
163
+ ? "#0d6efd"
164
+ : "transparent",
165
+ color: state.isSelected ? "#fff" : "#f8f9fa",
166
+ }),
167
+ dropdownIndicator: (baseStyles) => ({
168
+ ...baseStyles,
169
+ color: "#adb5bd",
170
+ }),
171
+ clearIndicator: (baseStyles) => ({
172
+ ...baseStyles,
173
+ color: "#adb5bd",
174
+ }),
175
+ indicatorSeparator: (baseStyles) => ({
176
+ ...baseStyles,
177
+ backgroundColor: "#495057",
178
+ }),
179
+ groupHeading: (baseStyles) => ({
180
+ ...baseStyles,
181
+ color: "#adb5bd",
182
+ }),
183
+ menuNotice: (baseStyles) => ({
184
+ ...baseStyles,
185
+ color: "#adb5bd",
186
+ }),
187
+ ...overrides,
188
+ };
189
+ };
190
+
33
191
  export const DynamicFontAwesomeIcon = ({ icon, className }) => {
34
192
  if (!icon) return null;
35
193
  return <i className={`${icon} ${className || ""}`}></i>;
@@ -59,26 +217,30 @@ export /**
59
217
  * @subcategory components / elements / utils
60
218
  * @namespace
61
219
  */
62
- const BlockSetting = ({ block, setProp }) => (
63
- <div className="form-check">
64
- <input
65
- className="form-check-input"
66
- name="block"
67
- type="checkbox"
68
- checked={block}
69
- onChange={(e) => {
70
- if (e.target) {
71
- const target_value = e.target.checked;
72
- setProp((prop) => (prop.block = target_value));
73
- }
74
- }}
75
- />
76
- <label className="form-check-label">Block display</label>
77
- </div>
78
- );
220
+ const BlockSetting = ({ block, setProp }) => {
221
+ const { t } = useTranslation();
222
+ return (
223
+ <div className="form-check">
224
+ <input
225
+ className="form-check-input"
226
+ name="block"
227
+ type="checkbox"
228
+ checked={block}
229
+ onChange={(e) => {
230
+ if (e.target) {
231
+ const target_value = e.target.checked;
232
+ setProp((prop) => (prop.block = target_value));
233
+ }
234
+ }}
235
+ />
236
+ <label className="form-check-label">{t("Block display")}</label>
237
+ </div>
238
+ );
239
+ };
79
240
 
80
- export const BlockOrInlineSetting = ({ block, inline, textStyle, setProp }) =>
81
- !textStyle ||
241
+ export const BlockOrInlineSetting = ({ block, inline, textStyle, setProp }) => {
242
+ const { t } = useTranslation();
243
+ return !textStyle ||
82
244
  !textStyleToArray(textStyle).some((ts) => ts && ts.startsWith("h")) ? (
83
245
  <BlockSetting block={block} setProp={setProp} />
84
246
  ) : (
@@ -95,9 +257,10 @@ export const BlockOrInlineSetting = ({ block, inline, textStyle, setProp }) =>
95
257
  }
96
258
  }}
97
259
  />
98
- <label className="form-check-label">Inline display</label>
260
+ <label className="form-check-label">{t("Inline display")}</label>
99
261
  </div>
100
262
  );
263
+ };
101
264
 
102
265
  export const HelpTopicLink = ({ topic, ...context }) => {
103
266
  const { mode } = React.useContext(optionsCtx);
@@ -288,11 +451,12 @@ export /**
288
451
  * @subcategory components / elements / utils
289
452
  */
290
453
  const MinRoleSettingRow = ({ minRole, setProp }) => {
454
+ const { t } = useTranslation();
291
455
  const options = React.useContext(optionsCtx);
292
456
  return (
293
457
  <tr>
294
458
  <td>
295
- <label>Minimum Role</label>
459
+ <label>{t("Minimum role")}</label>
296
460
  </td>
297
461
  <td>
298
462
  <select
@@ -789,6 +953,7 @@ const ConfigForm = ({
789
953
  onChange,
790
954
  tableName,
791
955
  fieldName,
956
+ openPopup
792
957
  }) => (
793
958
  <div className="form-namespace">
794
959
  {fields.map((f, ix) => {
@@ -813,6 +978,7 @@ const ConfigForm = ({
813
978
  table_name={tableName}
814
979
  />
815
980
  ) : null}
981
+ {" "}{openPopup && <i class="fas fa-external-link-alt " onClick={openPopup}></i>}
816
982
  </label>
817
983
  ) : null}
818
984
  <ConfigField
@@ -918,7 +1084,7 @@ const ConfigField = ({
918
1084
  field.options =
919
1085
  typeof field.attributes?.options === "string"
920
1086
  ? field.attributes?.options.split(",").map((s) => s.trim())
921
- : [...field.attributes?.options];
1087
+ : [...(field.attributes?.options ?? [])];
922
1088
  if (!field.required && field.options) field.options.unshift("");
923
1089
  }
924
1090
  const field_type = field.input_type || field.type.name || field.type;
@@ -1098,7 +1264,8 @@ const ConfigField = ({
1098
1264
  return (
1099
1265
  <Select
1100
1266
  options={seloptions}
1101
- className="react-select selectized-field"
1267
+ className={builderSelectClassName("react-select selectized-field")}
1268
+ classNamePrefix="builder-select"
1102
1269
  value={seloptions.find((so) => value === so.value)}
1103
1270
  onChange={(e) =>
1104
1271
  (e.name && myOnChange(e.name)) ||
@@ -1112,7 +1279,7 @@ const ConfigField = ({
1112
1279
  (typeof e === "string" && myOnChange(e))
1113
1280
  }
1114
1281
  menuPortalTarget={document.body}
1115
- styles={{ menuPortal: (base) => ({ ...base, zIndex: 19999 }) }}
1282
+ styles={reactSelectStyles()}
1116
1283
  ></Select>
1117
1284
  );
1118
1285
  } else
@@ -1330,6 +1497,7 @@ const SettingsRow = ({
1330
1497
  subProp,
1331
1498
  valuePostfix,
1332
1499
  }) => {
1500
+ const { t } = useTranslation();
1333
1501
  const fullWidth = ["String", "Bool", "textarea"].includes(field.type);
1334
1502
  const needLabel = field.type !== "Bool";
1335
1503
  const inner = field.canBeFormula ? (
@@ -1470,12 +1638,13 @@ const ButtonOrLinkSettingsRows = ({
1470
1638
  allowRunOnLoad = false,
1471
1639
  faIcons = [],
1472
1640
  }) => {
1641
+ const { t } = useTranslation();
1473
1642
  const setAProp = setAPropGen(setProp);
1474
1643
  const addBtnClass = (s) => (btnClass ? `${btnClass} ${s}` : s);
1475
1644
  return [
1476
1645
  <tr key="btnstyle">
1477
1646
  <td>
1478
- <label>Style</label>
1647
+ <label>{t("Style")}</label>
1479
1648
  </td>
1480
1649
  <td>
1481
1650
  <select
@@ -1485,41 +1654,41 @@ const ButtonOrLinkSettingsRows = ({
1485
1654
  >
1486
1655
  {linkFirst ? (
1487
1656
  <option value={linkIsBlank ? "" : addBtnClass("btn-link")}>
1488
- Link
1657
+ {t("Link")}
1489
1658
  </option>
1490
1659
  ) : null}
1491
- <option value={addBtnClass("btn-primary")}>Primary button</option>
1492
- <option value={addBtnClass("btn-secondary")}>Secondary button</option>
1493
- <option value={addBtnClass("btn-success")}>Success button</option>
1494
- <option value={addBtnClass("btn-danger")}>Danger button</option>
1495
- <option value={addBtnClass("btn-warning")}>Warning button</option>
1496
- <option value={addBtnClass("btn-info")}>Info button</option>
1660
+ <option value={addBtnClass("btn-primary")}>{t("Primary button")}</option>
1661
+ <option value={addBtnClass("btn-secondary")}>{t("Secondary button")}</option>
1662
+ <option value={addBtnClass("btn-success")}>{t("Success button")}</option>
1663
+ <option value={addBtnClass("btn-danger")}>{t("Danger button")}</option>
1664
+ <option value={addBtnClass("btn-warning")}>{t("Warning button")}</option>
1665
+ <option value={addBtnClass("btn-info")}>{t("Info button")}</option>
1497
1666
  <option value={addBtnClass("btn-outline-primary")}>
1498
- Primary outline button
1667
+ {t("Primary outline button")}
1499
1668
  </option>
1500
1669
  <option value={addBtnClass("btn-outline-secondary")}>
1501
- Secondary outline button
1670
+ {t("Secondary outline button")}
1502
1671
  </option>
1503
1672
  <option value={addBtnClass("btn-outline-success")}>
1504
- Success outline button
1673
+ {t("Success outline button")}
1505
1674
  </option>
1506
1675
  <option value={addBtnClass("btn-outline-danger")}>
1507
- Danger outline button
1676
+ {t("Danger outline button")}
1508
1677
  </option>
1509
1678
  <option value={addBtnClass("btn-outline-warning")}>
1510
- Warning outline button
1679
+ {t("Warning outline button")}
1511
1680
  </option>
1512
1681
  <option value={addBtnClass("btn-outline-info")}>
1513
- Info outline button
1682
+ {t("Info outline button")}
1514
1683
  </option>
1515
1684
  <option value={addBtnClass("btn-custom-color")}>
1516
- Button custom color
1685
+ {t("Button custom color")}
1517
1686
  </option>
1518
1687
  {!linkFirst ? (
1519
- <option value={addBtnClass("btn-link")}>Link</option>
1688
+ <option value={addBtnClass("btn-link")}>{t("Link")}</option>
1520
1689
  ) : null}
1521
1690
  {!linkFirst && allowRunOnLoad ? (
1522
- <option value="on_page_load">Run on Page Load</option>
1691
+ <option value="on_page_load">{t("Run on Page Load")}</option>
1523
1692
  ) : null}
1524
1693
  </select>
1525
1694
  </td>
@@ -1527,7 +1696,7 @@ const ButtonOrLinkSettingsRows = ({
1527
1696
  values[keyPrefix + "style"] !== "on_page_load" ? (
1528
1697
  <tr key="btnsz">
1529
1698
  <td>
1530
- <label>Size</label>
1699
+ <label>{t("Size")}</label>
1531
1700
  </td>
1532
1701
  <td>
1533
1702
  <select
@@ -1535,12 +1704,12 @@ const ButtonOrLinkSettingsRows = ({
1535
1704
  value={values[keyPrefix + "size"]}
1536
1705
  onChange={setAProp(keyPrefix + "size")}
1537
1706
  >
1538
- <option value="">Standard</option>
1539
- <option value="btn-lg">Large</option>
1540
- <option value="btn-sm">Small</option>
1541
- <option value="btn-sm btn-xs">Extra Small</option>
1542
- <option value="btn-block">Block</option>
1543
- <option value="btn-block btn-lg">Large block</option>
1707
+ <option value="">{t("Standard")}</option>
1708
+ <option value="btn-lg">{t("Large")}</option>
1709
+ <option value="btn-sm">{t("Small")}</option>
1710
+ <option value="btn-sm btn-xs">{t("Extra Small")}</option>
1711
+ <option value="btn-block">{t("Block")}</option>
1712
+ <option value="btn-block btn-lg">{t("Large block")}</option>
1544
1713
  </select>
1545
1714
  </td>
1546
1715
  </tr>
@@ -1548,7 +1717,7 @@ const ButtonOrLinkSettingsRows = ({
1548
1717
  values[keyPrefix + "style"] !== "on_page_load" ? (
1549
1718
  <tr key="btnicon">
1550
1719
  <td>
1551
- <label>Icon</label>
1720
+ <label>{t("Icon")}</label>
1552
1721
  </td>
1553
1722
  <td>
1554
1723
  <FontIconPicker
@@ -1566,7 +1735,7 @@ const ButtonOrLinkSettingsRows = ({
1566
1735
  ? [
1567
1736
  <tr key="btnbgcol">
1568
1737
  <td>
1569
- <label>Background</label>
1738
+ <label>{t("Background")}</label>
1570
1739
  </td>
1571
1740
  <td>
1572
1741
  <input
@@ -1579,7 +1748,7 @@ const ButtonOrLinkSettingsRows = ({
1579
1748
  </tr>,
1580
1749
  <tr key="btnbdcol">
1581
1750
  <td>
1582
- <label>Border</label>
1751
+ <label>{t("Border")}</label>
1583
1752
  </td>
1584
1753
  <td>
1585
1754
  <input
@@ -1592,7 +1761,7 @@ const ButtonOrLinkSettingsRows = ({
1592
1761
  </tr>,
1593
1762
  <tr key="btntxtcol">
1594
1763
  <td>
1595
- <label>Text</label>
1764
+ <label>{t("Text")}</label>
1596
1765
  </td>
1597
1766
  <td>
1598
1767
  <input
@@ -1737,8 +1906,8 @@ export const buildBootstrapOptions = (values) => {
1737
1906
 
1738
1907
  export const arrayChunks = (xs, n) => {
1739
1908
  const arrayOfArrays = [];
1740
- for (var i = 0; i < bigarray.length; i += n) {
1741
- arrayOfArrays.push(bigarray.slice(i, i + n));
1909
+ for (var i = 0; i < xs.length; i += n) {
1910
+ arrayOfArrays.push(xs.slice(i, i + n));
1742
1911
  }
1743
1912
  return arrayOfArrays;
1744
1913
  };