@saltcorn/builder 1.5.0-beta.12 → 1.5.0-beta.13
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.
- package/dist/builder_bundle.js +1 -1
- package/dist/builder_bundle.js.LICENSE.txt +2 -0
- package/package.json +5 -3
- package/src/components/elements/Card.js +319 -8
- package/src/components/elements/Columns.js +6 -1
- package/src/components/elements/Container.js +11 -2
- package/src/components/elements/Image.js +12 -2
- package/src/components/elements/MonacoEditor.js +182 -0
- package/src/components/elements/Text.js +2 -7
- package/src/components/elements/ViewLink.js +10 -0
- package/src/components/elements/utils.js +31 -23
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import React, { Fragment, useState, useEffect, useRef } from "react";
|
|
2
|
+
import optionsCtx from "../context";
|
|
3
|
+
|
|
4
|
+
import Editor, { useMonaco } from "@monaco-editor/react";
|
|
5
|
+
|
|
6
|
+
const setMonacoLanguage = async (monaco, options, isStatements) => {
|
|
7
|
+
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
|
|
8
|
+
noLib: true,
|
|
9
|
+
allowNonTsExtensions: true,
|
|
10
|
+
});
|
|
11
|
+
if (options.setMonaco) return;
|
|
12
|
+
|
|
13
|
+
options.setMonaco = true;
|
|
14
|
+
const tsres = await fetch(
|
|
15
|
+
`/admin/ts-declares?${options.tableName ? `table=${options.tableName}` : ""}&user=yes`
|
|
16
|
+
);
|
|
17
|
+
const tsds = await tsres.text();
|
|
18
|
+
|
|
19
|
+
monaco.languages.typescript.typescriptDefaults.addExtraLib(tsds);
|
|
20
|
+
// for code ending in return: https://github.com/microsoft/monaco-editor/issues/1661
|
|
21
|
+
// codes for await ignore are shown by hover card
|
|
22
|
+
if (isStatements)
|
|
23
|
+
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
|
|
24
|
+
//noSemanticValidation: false,
|
|
25
|
+
//noSyntaxValidation: false,
|
|
26
|
+
diagnosticCodesToIgnore: [1108, 1378, 1375, 7044, 2580, 80005],
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const SingleLineEditor = ({
|
|
31
|
+
setProp,
|
|
32
|
+
value,
|
|
33
|
+
propKey,
|
|
34
|
+
onChange,
|
|
35
|
+
className,
|
|
36
|
+
}) => {
|
|
37
|
+
const options = React.useContext(optionsCtx);
|
|
38
|
+
|
|
39
|
+
const handleEditorWillMount = (monaco) => {
|
|
40
|
+
setMonacoLanguage(monaco, options, false);
|
|
41
|
+
};
|
|
42
|
+
return (
|
|
43
|
+
<div className="form-control p-0 pt-1">
|
|
44
|
+
<Editor
|
|
45
|
+
className={className || ""}
|
|
46
|
+
height="22px"
|
|
47
|
+
value={value}
|
|
48
|
+
onChange={(value) => {
|
|
49
|
+
onChange && onChange(value);
|
|
50
|
+
setProp && propKey && setProp((prop) => (prop[propKey] = value));
|
|
51
|
+
}}
|
|
52
|
+
defaultLanguage="typescript"
|
|
53
|
+
//onMount={handleEditorDidMount}
|
|
54
|
+
//beforeMount={handleEditorWillMount}
|
|
55
|
+
options={singleLineEditorOptions}
|
|
56
|
+
//theme="myCoolTheme"
|
|
57
|
+
beforeMount={handleEditorWillMount}
|
|
58
|
+
/>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const MultiLineCodeEditor = ({ setProp, value, onChange }) => {
|
|
64
|
+
const options = React.useContext(optionsCtx);
|
|
65
|
+
|
|
66
|
+
const handleEditorWillMount = (monaco) => {
|
|
67
|
+
setMonacoLanguage(monaco, options, true);
|
|
68
|
+
};
|
|
69
|
+
return (
|
|
70
|
+
<div className="form-control p-0 pt-2">
|
|
71
|
+
<Editor
|
|
72
|
+
height="150px"
|
|
73
|
+
value={value}
|
|
74
|
+
onChange={onChange}
|
|
75
|
+
defaultLanguage="typescript"
|
|
76
|
+
//onMount={handleEditorDidMount}
|
|
77
|
+
//beforeMount={handleEditorWillMount}
|
|
78
|
+
options={multiLineEditorOptions}
|
|
79
|
+
//theme="myCoolTheme"
|
|
80
|
+
beforeMount={handleEditorWillMount}
|
|
81
|
+
/>
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const multiLineEditorOptions = {
|
|
87
|
+
fontSize: "14px",
|
|
88
|
+
fontWeight: "normal",
|
|
89
|
+
wordWrap: "off",
|
|
90
|
+
lineNumbers: "off",
|
|
91
|
+
lineNumbersMinChars: 0,
|
|
92
|
+
overviewRulerLanes: 0,
|
|
93
|
+
overviewRulerBorder: false,
|
|
94
|
+
hideCursorInOverviewRuler: true,
|
|
95
|
+
lineDecorationsWidth: 10,
|
|
96
|
+
glyphMargin: false,
|
|
97
|
+
folding: false,
|
|
98
|
+
// disable `Find`
|
|
99
|
+
find: {
|
|
100
|
+
addExtraSpaceOnTop: false,
|
|
101
|
+
autoFindInSelection: "never",
|
|
102
|
+
seedSearchStringFromSelection: false,
|
|
103
|
+
},
|
|
104
|
+
minimap: { enabled: false },
|
|
105
|
+
// see: https://github.com/microsoft/monaco-editor/issues/1746
|
|
106
|
+
wordBasedSuggestions: false,
|
|
107
|
+
// avoid links underline
|
|
108
|
+
links: false,
|
|
109
|
+
// avoid highlight hover word
|
|
110
|
+
occurrencesHighlight: false,
|
|
111
|
+
cursorStyle: "line-thin",
|
|
112
|
+
// hide current row highlight grey border
|
|
113
|
+
// see: https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.ieditoroptions.html#renderlinehighlight
|
|
114
|
+
renderLineHighlight: "none",
|
|
115
|
+
contextmenu: false,
|
|
116
|
+
// default selection is rounded
|
|
117
|
+
roundedSelection: false,
|
|
118
|
+
hover: {
|
|
119
|
+
// unit: ms
|
|
120
|
+
// default: 300
|
|
121
|
+
delay: 100,
|
|
122
|
+
},
|
|
123
|
+
acceptSuggestionOnEnter: "on",
|
|
124
|
+
// auto adjust width and height to parent
|
|
125
|
+
// see: https://github.com/Microsoft/monaco-editor/issues/543#issuecomment-321767059
|
|
126
|
+
automaticLayout: true,
|
|
127
|
+
// if monaco is inside a table, hover tips or completion may casue table body scroll
|
|
128
|
+
fixedOverflowWidgets: true,
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
//https://codesandbox.io/p/sandbox/react-monaco-single-line-forked-nsmhp6?file=%2Fsrc%2FApp.js%3A28%2C31
|
|
132
|
+
const singleLineEditorOptions = {
|
|
133
|
+
fontSize: "14px",
|
|
134
|
+
fontWeight: "normal",
|
|
135
|
+
wordWrap: "off",
|
|
136
|
+
lineNumbers: "off",
|
|
137
|
+
lineNumbersMinChars: 0,
|
|
138
|
+
overviewRulerLanes: 0,
|
|
139
|
+
overviewRulerBorder: false,
|
|
140
|
+
hideCursorInOverviewRuler: true,
|
|
141
|
+
lineDecorationsWidth: 10,
|
|
142
|
+
glyphMargin: false,
|
|
143
|
+
folding: false,
|
|
144
|
+
scrollBeyondLastColumn: 0,
|
|
145
|
+
scrollbar: {
|
|
146
|
+
horizontal: "hidden",
|
|
147
|
+
vertical: "hidden",
|
|
148
|
+
// avoid can not scroll page when hover monaco
|
|
149
|
+
alwaysConsumeMouseWheel: false,
|
|
150
|
+
},
|
|
151
|
+
// disable `Find`
|
|
152
|
+
find: {
|
|
153
|
+
addExtraSpaceOnTop: false,
|
|
154
|
+
autoFindInSelection: "never",
|
|
155
|
+
seedSearchStringFromSelection: false,
|
|
156
|
+
},
|
|
157
|
+
minimap: { enabled: false },
|
|
158
|
+
// see: https://github.com/microsoft/monaco-editor/issues/1746
|
|
159
|
+
wordBasedSuggestions: false,
|
|
160
|
+
// avoid links underline
|
|
161
|
+
links: false,
|
|
162
|
+
// avoid highlight hover word
|
|
163
|
+
occurrencesHighlight: false,
|
|
164
|
+
cursorStyle: "line-thin",
|
|
165
|
+
// hide current row highlight grey border
|
|
166
|
+
// see: https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.ieditoroptions.html#renderlinehighlight
|
|
167
|
+
renderLineHighlight: "none",
|
|
168
|
+
contextmenu: false,
|
|
169
|
+
// default selection is rounded
|
|
170
|
+
roundedSelection: false,
|
|
171
|
+
hover: {
|
|
172
|
+
// unit: ms
|
|
173
|
+
// default: 300
|
|
174
|
+
delay: 100,
|
|
175
|
+
},
|
|
176
|
+
acceptSuggestionOnEnter: "on",
|
|
177
|
+
// auto adjust width and height to parent
|
|
178
|
+
// see: https://github.com/Microsoft/monaco-editor/issues/543#issuecomment-321767059
|
|
179
|
+
automaticLayout: true,
|
|
180
|
+
// if monaco is inside a table, hover tips or completion may casue table body scroll
|
|
181
|
+
fixedOverflowWidgets: true,
|
|
182
|
+
};
|
|
@@ -26,6 +26,7 @@ import FontIconPicker from "@fonticonpicker/react-fonticonpicker";
|
|
|
26
26
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
27
27
|
import fas from "@fortawesome/free-solid-svg-icons";
|
|
28
28
|
import far from "@fortawesome/free-regular-svg-icons";
|
|
29
|
+
import { SingleLineEditor } from "./MonacoEditor";
|
|
29
30
|
const ckConfig = {
|
|
30
31
|
toolbarGroups: [
|
|
31
32
|
{ name: "document", groups: ["mode", "document", "doctools"] },
|
|
@@ -202,13 +203,7 @@ const TextSettings = () => {
|
|
|
202
203
|
)}
|
|
203
204
|
<label>Text to display</label>
|
|
204
205
|
{allowFormula && isFormula.text ? (
|
|
205
|
-
<
|
|
206
|
-
type="text"
|
|
207
|
-
className="text-to-display form-control"
|
|
208
|
-
value={text}
|
|
209
|
-
onChange={setAProp("text")}
|
|
210
|
-
spellCheck={false}
|
|
211
|
-
/>
|
|
206
|
+
<SingleLineEditor setProp={setProp} value={text} propKey="text" />
|
|
212
207
|
) : (
|
|
213
208
|
<ErrorBoundary>
|
|
214
209
|
<div className="border">
|
|
@@ -31,6 +31,16 @@ import {
|
|
|
31
31
|
Relation,
|
|
32
32
|
buildTableCaches,
|
|
33
33
|
} from "@saltcorn/common-code";
|
|
34
|
+
import { SingleLineEditor } from "./MonacoEditor";
|
|
35
|
+
|
|
36
|
+
/*
|
|
37
|
+
<SingleLineEditor
|
|
38
|
+
setProp={setProp}
|
|
39
|
+
value={extra_state_fml}
|
|
40
|
+
propKey="extra_state_fml"
|
|
41
|
+
/>
|
|
42
|
+
|
|
43
|
+
*/
|
|
34
44
|
|
|
35
45
|
export /**
|
|
36
46
|
* @param {object} props
|
|
@@ -28,6 +28,7 @@ import FontIconPicker from "@fonticonpicker/react-fonticonpicker";
|
|
|
28
28
|
import Tippy from "@tippyjs/react";
|
|
29
29
|
import { RelationType } from "@saltcorn/common-code";
|
|
30
30
|
import Select from "react-select";
|
|
31
|
+
import { MultiLineCodeEditor, SingleLineEditor } from "./MonacoEditor";
|
|
31
32
|
|
|
32
33
|
export const DynamicFontAwesomeIcon = ({ icon, className }) => {
|
|
33
34
|
if (!icon) return null;
|
|
@@ -204,17 +205,12 @@ const OrFormula = ({ setProp, isFormula, node, nodekey, children }) => {
|
|
|
204
205
|
<Fragment>
|
|
205
206
|
<div className="input-group input-group-sm w-100">
|
|
206
207
|
{isFormula[nodekey] ? (
|
|
207
|
-
<
|
|
208
|
-
type="text"
|
|
209
|
-
className="form-control text-to-display"
|
|
208
|
+
<SingleLineEditor
|
|
210
209
|
value={node[nodekey] || ""}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if (e.target) {
|
|
214
|
-
const target_value = e.target.value;
|
|
215
|
-
setProp((prop) => (prop[nodekey] = target_value));
|
|
216
|
-
}
|
|
210
|
+
onChange={(target_value) => {
|
|
211
|
+
setProp((prop) => (prop[nodekey] = target_value));
|
|
217
212
|
}}
|
|
213
|
+
className="text-to-display"
|
|
218
214
|
/>
|
|
219
215
|
) : (
|
|
220
216
|
children
|
|
@@ -487,8 +483,12 @@ export /**
|
|
|
487
483
|
* @subcategory components / elements / utils
|
|
488
484
|
* @namespace
|
|
489
485
|
*/
|
|
490
|
-
const Accordion = ({ titles, children }) => {
|
|
491
|
-
const [currentTab, setCurrentTab] = useState(0);
|
|
486
|
+
const Accordion = ({ titles, children, value, onChange }) => {
|
|
487
|
+
const [currentTab, setCurrentTab] = useState(value || 0);
|
|
488
|
+
const setTab = (ix) => {
|
|
489
|
+
setCurrentTab(ix);
|
|
490
|
+
onChange && onChange(ix);
|
|
491
|
+
};
|
|
492
492
|
return (
|
|
493
493
|
<Fragment>
|
|
494
494
|
{children.map((child, ix) => {
|
|
@@ -499,7 +499,7 @@ const Accordion = ({ titles, children }) => {
|
|
|
499
499
|
className={`bg-${
|
|
500
500
|
isCurrent ? "primary" : "secondary"
|
|
501
501
|
} ps-1 text-white w-100 mt-1`}
|
|
502
|
-
onClick={() =>
|
|
502
|
+
onClick={() => setTab(ix)}
|
|
503
503
|
>
|
|
504
504
|
<span className="w-1em">
|
|
505
505
|
{isCurrent ? (
|
|
@@ -1067,17 +1067,25 @@ const ConfigField = ({
|
|
|
1067
1067
|
onChange={(e) => e.target && myOnChange(e.target.value)}
|
|
1068
1068
|
/>
|
|
1069
1069
|
),
|
|
1070
|
-
code: () =>
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1070
|
+
code: () =>
|
|
1071
|
+
field?.attributes?.expression_type === "row" ||
|
|
1072
|
+
field?.attributes?.expression_type === "query" ? (
|
|
1073
|
+
<textarea
|
|
1074
|
+
rows="6"
|
|
1075
|
+
type="text"
|
|
1076
|
+
className={`field-${field?.name} form-control`}
|
|
1077
|
+
value={value}
|
|
1078
|
+
name={field?.name}
|
|
1079
|
+
onChange={(e) => e.target && myOnChange(e.target.value)}
|
|
1080
|
+
spellCheck={false}
|
|
1081
|
+
/>
|
|
1082
|
+
) : (
|
|
1083
|
+
<MultiLineCodeEditor
|
|
1084
|
+
setProp={setProp}
|
|
1085
|
+
value={value}
|
|
1086
|
+
onChange={myOnChange}
|
|
1087
|
+
/>
|
|
1088
|
+
),
|
|
1081
1089
|
select: () => {
|
|
1082
1090
|
if (field.class?.includes?.("selectizable")) {
|
|
1083
1091
|
const seloptions = field.options.map((o, ix) =>
|