@keboola/design 8.0.0 → 9.1.0
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/editors.cjs +366 -186
- package/dist/editors.cjs.map +1 -1
- package/dist/editors.d.cts +56 -6
- package/dist/editors.d.ts +56 -6
- package/dist/editors.js +370 -190
- package/dist/editors.js.map +1 -1
- package/dist/index.cjs +89 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -4
- package/dist/index.d.ts +29 -4
- package/dist/index.js +89 -13
- package/dist/index.js.map +1 -1
- package/dist/rjsf.cjs +394 -39
- package/dist/rjsf.cjs.map +1 -1
- package/dist/rjsf.js +396 -41
- package/dist/rjsf.js.map +1 -1
- package/package.json +5 -5
package/dist/editors.cjs
CHANGED
|
@@ -23,12 +23,11 @@ var r = require('@codemirror/legacy-modes/mode/r');
|
|
|
23
23
|
var shell = require('@codemirror/legacy-modes/mode/shell');
|
|
24
24
|
var toml = require('@codemirror/legacy-modes/mode/toml');
|
|
25
25
|
var codemirrorThemeGithub = require('@uiw/codemirror-theme-github');
|
|
26
|
-
var
|
|
26
|
+
var codemirrorLangSql = require('@keboola/codemirror-lang-sql');
|
|
27
27
|
var colors = require('@keboola/tailwind-config/colors');
|
|
28
28
|
var simpleMode = require('@codemirror/legacy-modes/mode/simple-mode');
|
|
29
|
-
var commands = require('@codemirror/commands');
|
|
30
|
-
var codemirrorLangSql = require('@keboola/codemirror-lang-sql');
|
|
31
29
|
var state = require('@codemirror/state');
|
|
30
|
+
var commands = require('@codemirror/commands');
|
|
32
31
|
|
|
33
32
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
34
33
|
|
|
@@ -297,6 +296,21 @@ Tooltip.Trigger = TooltipTrigger;
|
|
|
297
296
|
|
|
298
297
|
// src/utils/escapeStringRegexp.ts
|
|
299
298
|
var escapeStringRegexp = (string) => string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
|
|
299
|
+
|
|
300
|
+
// src/utils/isMac.ts
|
|
301
|
+
var getIsMac = () => {
|
|
302
|
+
if (typeof navigator !== "undefined" && "userAgentData" in navigator) {
|
|
303
|
+
const platform = navigator.userAgentData.platform;
|
|
304
|
+
if (typeof platform === "string") {
|
|
305
|
+
return platform.toLowerCase() === "macos";
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (typeof navigator !== "undefined" && typeof navigator.platform === "string") {
|
|
309
|
+
return navigator.platform.toUpperCase().indexOf("MAC") >= 0;
|
|
310
|
+
}
|
|
311
|
+
return false;
|
|
312
|
+
};
|
|
313
|
+
var isMac = getIsMac();
|
|
300
314
|
var helpVariants = classVarianceAuthority.cva(["tw:m-0", "tw:text-xs"], {
|
|
301
315
|
defaultVariants: {
|
|
302
316
|
state: "default"
|
|
@@ -747,8 +761,6 @@ var ButtonToolbar = ({ value, children }) => {
|
|
|
747
761
|
};
|
|
748
762
|
var COMMANDS = [
|
|
749
763
|
"run-operation",
|
|
750
|
-
"source freshness",
|
|
751
|
-
"docs generate",
|
|
752
764
|
"run",
|
|
753
765
|
"test",
|
|
754
766
|
"seed",
|
|
@@ -757,9 +769,13 @@ var COMMANDS = [
|
|
|
757
769
|
"ls",
|
|
758
770
|
"compile",
|
|
759
771
|
"build",
|
|
760
|
-
"deps"
|
|
772
|
+
"deps",
|
|
773
|
+
"docs",
|
|
774
|
+
"source"
|
|
761
775
|
];
|
|
776
|
+
var SUBCOMMANDS = { docs: ["generate"], source: ["freshness"] };
|
|
762
777
|
var ARGUMENTS = ["--select", "--exclude", "--selector", "--defer", "--resource-type", "-s"];
|
|
778
|
+
var SELECTORS = ["--select", "--exclude", "-s"];
|
|
763
779
|
var METHODS = [
|
|
764
780
|
"path:",
|
|
765
781
|
"source:",
|
|
@@ -786,13 +802,59 @@ var FLAGS = [
|
|
|
786
802
|
"--profile",
|
|
787
803
|
"--full-refresh"
|
|
788
804
|
];
|
|
789
|
-
var
|
|
790
|
-
|
|
805
|
+
var COMMAND_PHRASES = COMMANDS.flatMap((command) => {
|
|
806
|
+
const subcommands = SUBCOMMANDS[command];
|
|
807
|
+
return subcommands ? subcommands.map((subcommand) => `${command} ${subcommand}`) : [command];
|
|
808
|
+
});
|
|
809
|
+
var alternation = (list) => [...list].sort((a, b) => b.length - a.length).join("|");
|
|
810
|
+
var word = (list) => new RegExp(`^\\s+(?:${alternation(list)})\\b`, "i");
|
|
811
|
+
var prefix = (list) => new RegExp(`^\\s+(?:${alternation(list)})`, "i");
|
|
812
|
+
var WORD = /[\w:-]*$/;
|
|
813
|
+
var asOptions = (list, type) => list.map((label) => ({ label, type }));
|
|
814
|
+
var DBT = [{ label: "dbt", type: "keyword" }];
|
|
815
|
+
var COMMAND_OPTIONS = asOptions(COMMANDS, "keyword");
|
|
816
|
+
var SUBCOMMAND_OPTIONS = Object.fromEntries(
|
|
817
|
+
Object.entries(SUBCOMMANDS).map(([command, subcommands]) => [
|
|
818
|
+
command,
|
|
819
|
+
asOptions(subcommands, "keyword")
|
|
820
|
+
])
|
|
821
|
+
);
|
|
822
|
+
var ARGUMENT_OPTIONS = asOptions(ARGUMENTS, "variable");
|
|
823
|
+
var FLAG_OPTIONS = asOptions(FLAGS, "constant");
|
|
824
|
+
var METHOD_OPTIONS = asOptions(METHODS, "property");
|
|
825
|
+
var optionsAfter = (words) => {
|
|
826
|
+
const [step, command, ...rest] = words;
|
|
827
|
+
if (step === void 0) return DBT;
|
|
828
|
+
if (step.toLowerCase() !== "dbt") return [];
|
|
829
|
+
if (command === void 0) return COMMAND_OPTIONS;
|
|
830
|
+
const subcommands = SUBCOMMAND_OPTIONS[command.toLowerCase()];
|
|
831
|
+
if (subcommands && rest.length === 0) return subcommands;
|
|
832
|
+
const lastArgument = rest.filter((it) => it.startsWith("-")).at(-1);
|
|
833
|
+
const selecting = lastArgument !== void 0 && SELECTORS.includes(lastArgument.toLowerCase());
|
|
834
|
+
return selecting ? [...ARGUMENT_OPTIONS, ...FLAG_OPTIONS, ...METHOD_OPTIONS] : [...ARGUMENT_OPTIONS, ...FLAG_OPTIONS];
|
|
835
|
+
};
|
|
836
|
+
var complete = (context) => {
|
|
837
|
+
const typed = context.matchBefore(WORD);
|
|
838
|
+
if (!typed?.text && !context.explicit) return null;
|
|
839
|
+
const from = typed?.from ?? context.pos;
|
|
840
|
+
const line = context.state.doc.lineAt(from);
|
|
841
|
+
const options = optionsAfter(
|
|
842
|
+
line.text.slice(0, from - line.from).split(/\s+/).filter(Boolean)
|
|
843
|
+
);
|
|
844
|
+
return options.length > 0 ? { from, options, validFor: WORD } : null;
|
|
845
|
+
};
|
|
791
846
|
var dbt = simpleMode.simpleMode({
|
|
847
|
+
languageData: {
|
|
848
|
+
// `toggleComment` is a no-op without these, so Mod-/ silently does nothing.
|
|
849
|
+
commentTokens: { line: "--", block: { open: "/*", close: "*/" } },
|
|
850
|
+
autocomplete: complete
|
|
851
|
+
},
|
|
792
852
|
start: [
|
|
793
853
|
{ regex: /"(?:[^\\]|\\.)*?(?:"|$)/, token: "string" },
|
|
794
|
-
|
|
795
|
-
|
|
854
|
+
// Word-bounded, so `dbtX` is not a dbt step whose first word happens to
|
|
855
|
+
// colour — the same thing the completion source asks of it.
|
|
856
|
+
{ regex: /dbt\b/, token: "keyword", sol: true },
|
|
857
|
+
{ regex: word(COMMAND_PHRASES), token: "keyword" },
|
|
796
858
|
{ regex: word(ARGUMENTS), token: "variableName" },
|
|
797
859
|
{ regex: prefix(METHODS), token: "propertyName" },
|
|
798
860
|
{ regex: prefix(FLAGS), token: "attributeName" },
|
|
@@ -840,6 +902,8 @@ var KEYWORDS = {
|
|
|
840
902
|
};
|
|
841
903
|
var jsonnet = {
|
|
842
904
|
name: "jsonnet",
|
|
905
|
+
// `toggleComment` is a no-op without these, so Mod-/ silently does nothing.
|
|
906
|
+
languageData: { commentTokens: { line: "//", block: { open: "/*", close: "*/" } } },
|
|
843
907
|
startState: () => ({
|
|
844
908
|
cComment: false,
|
|
845
909
|
textBlock: false,
|
|
@@ -972,6 +1036,7 @@ var LANGUAGE_MODES = [
|
|
|
972
1036
|
"text/x-mysql",
|
|
973
1037
|
"text/x-pgsql",
|
|
974
1038
|
"text/x-mssql",
|
|
1039
|
+
// Snowflake, under a historical name — these strings are a published prop contract.
|
|
975
1040
|
"text/x-sfsql",
|
|
976
1041
|
"text/x-plsql",
|
|
977
1042
|
"text/x-rsrc",
|
|
@@ -1033,8 +1098,6 @@ var ALWAYS_OFF = {
|
|
|
1033
1098
|
var buildBasicSetup = (readOnly) => ({
|
|
1034
1099
|
...ALWAYS_OFF,
|
|
1035
1100
|
...readOnly ? {
|
|
1036
|
-
history: false,
|
|
1037
|
-
historyKeymap: false,
|
|
1038
1101
|
closeBrackets: false,
|
|
1039
1102
|
closeBracketsKeymap: false,
|
|
1040
1103
|
lintKeymap: false,
|
|
@@ -1072,7 +1135,7 @@ var getLanguageMode = (mode) => {
|
|
|
1072
1135
|
case "text/x-mssql":
|
|
1073
1136
|
return langSql.sql({ upperCaseKeywords: true, dialect: langSql.MSSQL });
|
|
1074
1137
|
case "text/x-sfsql":
|
|
1075
|
-
return
|
|
1138
|
+
return langSql.sql({ upperCaseKeywords: true, dialect: codemirrorLangSql.getSqlDialect("snowflake") });
|
|
1076
1139
|
case "text/x-plsql":
|
|
1077
1140
|
return langSql.sql({ upperCaseKeywords: true, dialect: langSql.PLSQL });
|
|
1078
1141
|
case "text/x-rsrc":
|
|
@@ -1097,6 +1160,112 @@ var getLanguageMode = (mode) => {
|
|
|
1097
1160
|
}
|
|
1098
1161
|
};
|
|
1099
1162
|
var shouldLintJson = (mode, readOnly) => mode === "application/json" && !readOnly;
|
|
1163
|
+
var setSearchEffect = state.StateEffect.define();
|
|
1164
|
+
function findMatches(doc, query) {
|
|
1165
|
+
if (!query) return [];
|
|
1166
|
+
const text = doc.toString();
|
|
1167
|
+
try {
|
|
1168
|
+
const regex = new RegExp(escapeStringRegexp(query), "gi");
|
|
1169
|
+
return Array.from(text.matchAll(regex)).map((match, index) => {
|
|
1170
|
+
const from = match.index;
|
|
1171
|
+
const to = from + match[0].length;
|
|
1172
|
+
return { from, to, text: match[0], localIndex: index };
|
|
1173
|
+
});
|
|
1174
|
+
} catch (e) {
|
|
1175
|
+
console.warn("Invalid search regex:", e);
|
|
1176
|
+
return [];
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
function createDecorations(matches, selectedLocalIndex) {
|
|
1180
|
+
const decorations = matches.map((match) => {
|
|
1181
|
+
const isSelected = match.localIndex === selectedLocalIndex;
|
|
1182
|
+
const decoration = view.Decoration.mark({
|
|
1183
|
+
class: isSelected ? "cm-searchMatch-selected" : "cm-searchMatch"
|
|
1184
|
+
});
|
|
1185
|
+
return decoration.range(match.from, match.to);
|
|
1186
|
+
});
|
|
1187
|
+
return view.Decoration.set(decorations, true);
|
|
1188
|
+
}
|
|
1189
|
+
var searchField = state.StateField.define({
|
|
1190
|
+
create() {
|
|
1191
|
+
return {
|
|
1192
|
+
query: "",
|
|
1193
|
+
selectedMatchIndex: void 0,
|
|
1194
|
+
matches: [],
|
|
1195
|
+
decorations: view.Decoration.none
|
|
1196
|
+
};
|
|
1197
|
+
},
|
|
1198
|
+
update(state, tr) {
|
|
1199
|
+
let newState = state;
|
|
1200
|
+
for (const effect of tr.effects) {
|
|
1201
|
+
if (!effect.is(setSearchEffect)) {
|
|
1202
|
+
continue;
|
|
1203
|
+
}
|
|
1204
|
+
const { query, selectedMatchIndex } = effect.value;
|
|
1205
|
+
const matches = findMatches(tr.state.doc, query);
|
|
1206
|
+
const decorations = createDecorations(matches, selectedMatchIndex);
|
|
1207
|
+
newState = {
|
|
1208
|
+
query,
|
|
1209
|
+
selectedMatchIndex,
|
|
1210
|
+
matches,
|
|
1211
|
+
decorations
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
1214
|
+
if (tr.docChanged && newState.query) {
|
|
1215
|
+
const matches = findMatches(tr.state.doc, newState.query);
|
|
1216
|
+
const decorations = createDecorations(matches, newState.selectedMatchIndex);
|
|
1217
|
+
newState = {
|
|
1218
|
+
...newState,
|
|
1219
|
+
matches,
|
|
1220
|
+
decorations
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
return newState;
|
|
1224
|
+
},
|
|
1225
|
+
provide: (field) => view.EditorView.decorations.from(field, (state) => state.decorations)
|
|
1226
|
+
});
|
|
1227
|
+
var searchViewPlugin = view.ViewPlugin.fromClass(
|
|
1228
|
+
class {
|
|
1229
|
+
lastSelectedIndex;
|
|
1230
|
+
update(update) {
|
|
1231
|
+
const state = update.state.field(searchField);
|
|
1232
|
+
if (state.selectedMatchIndex !== void 0 && state.selectedMatchIndex !== this.lastSelectedIndex) {
|
|
1233
|
+
const match = state.matches[state.selectedMatchIndex];
|
|
1234
|
+
if (match) {
|
|
1235
|
+
requestAnimationFrame(() => {
|
|
1236
|
+
update.view.dispatch({
|
|
1237
|
+
effects: view.EditorView.scrollIntoView(match.from, { y: "center" })
|
|
1238
|
+
});
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
this.lastSelectedIndex = state.selectedMatchIndex;
|
|
1242
|
+
}
|
|
1243
|
+
if (state.selectedMatchIndex === void 0) {
|
|
1244
|
+
this.lastSelectedIndex = void 0;
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
);
|
|
1249
|
+
var searchTheme = view.EditorView.baseTheme({
|
|
1250
|
+
".cm-searchMatch": {
|
|
1251
|
+
backgroundColor: colors__default.default.blue[100]
|
|
1252
|
+
},
|
|
1253
|
+
".cm-searchMatch > span": {
|
|
1254
|
+
color: `${colors__default.default.blue[600]} !important`
|
|
1255
|
+
},
|
|
1256
|
+
".cm-searchMatch-selected": {
|
|
1257
|
+
backgroundColor: colors__default.default.blue[600]
|
|
1258
|
+
},
|
|
1259
|
+
".cm-searchMatch-selected > span": {
|
|
1260
|
+
color: `${colors__default.default.white} !important`
|
|
1261
|
+
}
|
|
1262
|
+
});
|
|
1263
|
+
function searchExtension() {
|
|
1264
|
+
return [searchField, searchViewPlugin, searchTheme];
|
|
1265
|
+
}
|
|
1266
|
+
function updateSearch(view, query, selectedMatchIndex) {
|
|
1267
|
+
view.dispatch({ effects: setSearchEffect.of({ query, selectedMatchIndex }) });
|
|
1268
|
+
}
|
|
1100
1269
|
var KbdSeparator = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("span", { ...props, className: cn("tw:text-xs tw:text-muted-foreground", className) });
|
|
1101
1270
|
var KbdGroup = ({ ref, className, children, separator, ...props }) => {
|
|
1102
1271
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1156,12 +1325,79 @@ Kbd.Group = KbdGroup;
|
|
|
1156
1325
|
Kbd.Separator = KbdSeparator;
|
|
1157
1326
|
var ToggleComponentHelp = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1158
1327
|
"Use ",
|
|
1159
|
-
/* @__PURE__ */ jsxRuntime.jsx(Kbd, { children: "Ctrl+/" }),
|
|
1160
|
-
" or ",
|
|
1161
|
-
/* @__PURE__ */ jsxRuntime.jsx(Kbd, { children: "Command+/" }),
|
|
1328
|
+
/* @__PURE__ */ jsxRuntime.jsx(Kbd, { children: isMac ? "Command+/" : "Ctrl+/" }),
|
|
1162
1329
|
" to toggle comments."
|
|
1163
1330
|
] });
|
|
1164
|
-
var
|
|
1331
|
+
var establishesFixedContainingBlock = (style) => style.transform !== "none" || style.translate !== "none" || style.rotate !== "none" || style.scale !== "none" || style.perspective !== "none" || style.filter !== "none" || style.backdropFilter !== "none" || /\b(paint|layout|strict|content)\b/.test(style.contain) || /\b(transform|perspective|filter|contain)\b/.test(style.willChange);
|
|
1332
|
+
var crops = (style) => style.overflowX !== "visible" || style.overflowY !== "visible" || style.maskImage !== "none" || style.contentVisibility !== "visible" || /\b(paint|strict|content)\b/.test(style.contain);
|
|
1333
|
+
var findTooltipHost = (from) => {
|
|
1334
|
+
let outermostCropper = null;
|
|
1335
|
+
for (let node = from.parentElement; node && node !== document.body; node = node.parentElement) {
|
|
1336
|
+
const style = getComputedStyle(node);
|
|
1337
|
+
if (crops(style)) {
|
|
1338
|
+
outermostCropper = node;
|
|
1339
|
+
} else if (establishesFixedContainingBlock(style)) {
|
|
1340
|
+
return outermostCropper?.parentElement ?? node;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
return outermostCropper?.parentElement ?? null;
|
|
1344
|
+
};
|
|
1345
|
+
var tooltipsExtension = () => {
|
|
1346
|
+
const layer = new state.Compartment();
|
|
1347
|
+
return [
|
|
1348
|
+
layer.of(view.tooltips()),
|
|
1349
|
+
view.ViewPlugin.define((view$1) => {
|
|
1350
|
+
const scheduled = setTimeout(() => {
|
|
1351
|
+
if (!view$1.dom.isConnected) return;
|
|
1352
|
+
const parent = findTooltipHost(view$1.dom);
|
|
1353
|
+
if (parent) view$1.dispatch({ effects: layer.reconfigure(view.tooltips({ parent })) });
|
|
1354
|
+
});
|
|
1355
|
+
return { destroy: () => clearTimeout(scheduled) };
|
|
1356
|
+
})
|
|
1357
|
+
];
|
|
1358
|
+
};
|
|
1359
|
+
var useTooltipsExtension = () => react.useMemo(tooltipsExtension, []);
|
|
1360
|
+
|
|
1361
|
+
// src/components/CodeEditor/variableCompletion.ts
|
|
1362
|
+
var BOOST = 2e3;
|
|
1363
|
+
var NAME = String.raw`[\w-]*`;
|
|
1364
|
+
var AT_CARET = new RegExp(String.raw`(?:\{{1,2} ?)?${NAME}$`);
|
|
1365
|
+
var NAME_AT_END = new RegExp(`${NAME}$`);
|
|
1366
|
+
var OPENING = /\{{1,2} ?$/;
|
|
1367
|
+
var CLOSING = /^ ?\}{1,2}/;
|
|
1368
|
+
var completeVariables = (variables = []) => {
|
|
1369
|
+
if (variables.length === 0) return () => null;
|
|
1370
|
+
const options = variables.map(({ name, value }) => ({
|
|
1371
|
+
// The bare name: `SqlEditor` filters prefix-only while `CodeEditor` filters
|
|
1372
|
+
// fuzzily, and this is the only spelling both accept whether or not the caret
|
|
1373
|
+
// has typed the braces. The braces are `displayLabel`, which is what renders.
|
|
1374
|
+
label: name,
|
|
1375
|
+
displayLabel: `{{${name}}}`,
|
|
1376
|
+
detail: value,
|
|
1377
|
+
type: "variable",
|
|
1378
|
+
boost: BOOST,
|
|
1379
|
+
apply: (view, completion, from, to) => {
|
|
1380
|
+
const { doc } = view.state;
|
|
1381
|
+
const line = doc.lineAt(from);
|
|
1382
|
+
const insert = `{{${completion.label}}}`;
|
|
1383
|
+
const opening = OPENING.exec(doc.sliceString(line.from, from));
|
|
1384
|
+
const closing = CLOSING.exec(doc.sliceString(to, line.to));
|
|
1385
|
+
const start = opening ? from - opening[0].length : from;
|
|
1386
|
+
const end = closing ? to + closing[0].length : to;
|
|
1387
|
+
view.dispatch({
|
|
1388
|
+
changes: { from: start, to: end, insert },
|
|
1389
|
+
selection: { anchor: start + insert.length }
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
}));
|
|
1393
|
+
return (context) => {
|
|
1394
|
+
const match = context.matchBefore(AT_CARET);
|
|
1395
|
+
if (!match?.text) return null;
|
|
1396
|
+
const [name = ""] = NAME_AT_END.exec(match.text) ?? [];
|
|
1397
|
+
return { from: match.to - name.length, options };
|
|
1398
|
+
};
|
|
1399
|
+
};
|
|
1400
|
+
var useVariableCompletion = (variables = []) => useStableCallback(completeVariables(variables));
|
|
1165
1401
|
var emptyObject = {};
|
|
1166
1402
|
var CodeEditor = ({
|
|
1167
1403
|
value,
|
|
@@ -1170,8 +1406,13 @@ var CodeEditor = ({
|
|
|
1170
1406
|
mode = "application/json",
|
|
1171
1407
|
placeholder = "",
|
|
1172
1408
|
ariaLabel,
|
|
1409
|
+
searchQuery,
|
|
1410
|
+
searchMatchIndex,
|
|
1173
1411
|
readOnly = false,
|
|
1174
|
-
|
|
1412
|
+
inputLocked = false,
|
|
1413
|
+
autocompletions,
|
|
1414
|
+
completionSource,
|
|
1415
|
+
variables,
|
|
1175
1416
|
extraKeys = emptyObject,
|
|
1176
1417
|
withToggleCommentHint = false,
|
|
1177
1418
|
withAutofocus = false,
|
|
@@ -1186,49 +1427,86 @@ var CodeEditor = ({
|
|
|
1186
1427
|
className
|
|
1187
1428
|
}) => {
|
|
1188
1429
|
const handleChange = useStableCallback((next) => onChange?.(next));
|
|
1430
|
+
const withSearch = searchQuery !== void 0;
|
|
1431
|
+
const editorRef = react.useRef(null);
|
|
1432
|
+
react.useEffect(() => {
|
|
1433
|
+
const view = editorRef.current?.view;
|
|
1434
|
+
if (view && withSearch) updateSearch(view, searchQuery, searchMatchIndex);
|
|
1435
|
+
}, [withSearch, searchQuery, searchMatchIndex]);
|
|
1436
|
+
const handleCreateEditor = useStableCallback((view) => {
|
|
1437
|
+
if (searchQuery) updateSearch(view, searchQuery, searchMatchIndex);
|
|
1438
|
+
});
|
|
1439
|
+
const extraKeysRef = react.useRef(extraKeys);
|
|
1440
|
+
react.useLayoutEffect(() => {
|
|
1441
|
+
extraKeysRef.current = extraKeys;
|
|
1442
|
+
});
|
|
1443
|
+
const boundKeysSignature = Object.keys(extraKeys).join("\n");
|
|
1444
|
+
const boundKeys = react.useMemo(
|
|
1445
|
+
() => boundKeysSignature.split("\n").filter(Boolean),
|
|
1446
|
+
[boundKeysSignature]
|
|
1447
|
+
);
|
|
1448
|
+
const tooltipLayer = useTooltipsExtension();
|
|
1449
|
+
const variableCompletion = useVariableCompletion(variables);
|
|
1189
1450
|
const customTheme = useThemedExtension("editor:syntax", buildCustomTheme);
|
|
1190
1451
|
const baseTheme = useThemedExtension(
|
|
1191
1452
|
"code-editor:chrome",
|
|
1192
1453
|
() => view.EditorView.theme(buildBaseThemeStyles())
|
|
1193
1454
|
);
|
|
1194
1455
|
const commonExtensions = react.useMemo(() => {
|
|
1456
|
+
const callerCompletions = completionSource ?? (completeAny ? autocomplete.completeAnyWord : autocompletions?.length ? autocompletions : null);
|
|
1457
|
+
const completionEntries = [
|
|
1458
|
+
...callerCompletions ? [{ autocomplete: callerCompletions }] : [],
|
|
1459
|
+
{ autocomplete: variableCompletion }
|
|
1460
|
+
];
|
|
1195
1461
|
return [
|
|
1196
1462
|
getLanguageMode(mode),
|
|
1197
1463
|
shouldLintJson(mode, readOnly) ? lint.linter(langJson.jsonParseLinter()) : [],
|
|
1198
1464
|
withLineWrapping ? view.EditorView.lineWrapping : [],
|
|
1199
|
-
CodeMirror.EditorState.languageData.of(() =>
|
|
1200
|
-
{ autocomplete: completeAny ? autocomplete.completeAnyWord : autocompletions }
|
|
1201
|
-
]),
|
|
1465
|
+
CodeMirror.EditorState.languageData.of(() => completionEntries),
|
|
1202
1466
|
view.keymap.of(
|
|
1203
|
-
|
|
1467
|
+
boundKeys.map((key) => ({
|
|
1204
1468
|
key,
|
|
1205
1469
|
run: () => {
|
|
1206
|
-
|
|
1207
|
-
run();
|
|
1470
|
+
extraKeysRef.current[key]?.();
|
|
1208
1471
|
return true;
|
|
1209
1472
|
}
|
|
1210
1473
|
}))
|
|
1211
1474
|
),
|
|
1212
|
-
readOnly ? [] :
|
|
1475
|
+
readOnly ? [] : [
|
|
1476
|
+
// CodeMirror's own default. Gating it on the props hid completions the
|
|
1477
|
+
// *language* supplies — dbt's vocabulary, Snowflake's keywords — behind
|
|
1478
|
+
// a shortcut, and macOS leaves no usable one. With nothing to offer, no
|
|
1479
|
+
// popup opens anyway.
|
|
1480
|
+
autocomplete.autocompletion()
|
|
1481
|
+
],
|
|
1213
1482
|
ariaLabel ? view.EditorView.contentAttributes.of({ "aria-label": ariaLabel }) : [],
|
|
1483
|
+
withSearch ? searchExtension() : [],
|
|
1484
|
+
tooltipLayer,
|
|
1214
1485
|
baseTheme
|
|
1215
1486
|
];
|
|
1216
1487
|
}, [
|
|
1217
1488
|
autocompletions,
|
|
1489
|
+
completionSource,
|
|
1490
|
+
variableCompletion,
|
|
1218
1491
|
completeAny,
|
|
1219
|
-
|
|
1492
|
+
boundKeys,
|
|
1220
1493
|
mode,
|
|
1221
1494
|
readOnly,
|
|
1222
1495
|
withLineWrapping,
|
|
1223
1496
|
baseTheme,
|
|
1224
|
-
ariaLabel
|
|
1497
|
+
ariaLabel,
|
|
1498
|
+
withSearch,
|
|
1499
|
+
tooltipLayer
|
|
1225
1500
|
]);
|
|
1226
1501
|
const extensions = react.useMemo(() => {
|
|
1227
1502
|
return [
|
|
1228
1503
|
...commonExtensions,
|
|
1229
1504
|
view.placeholder(placeholder),
|
|
1230
1505
|
view.EditorView.editable.of(!readOnly),
|
|
1231
|
-
|
|
1506
|
+
// The lock is this facet and nothing else. `contenteditable` is what the
|
|
1507
|
+
// read-only wash keys off, and `basicSetup` is what holds the undo history,
|
|
1508
|
+
// so leaving both alone is what makes the lock invisible.
|
|
1509
|
+
CodeMirror.EditorState.readOnly.of(readOnly || inputLocked),
|
|
1232
1510
|
previousValue ? merge.unifiedMergeView({
|
|
1233
1511
|
original: previousValue,
|
|
1234
1512
|
mergeControls: false,
|
|
@@ -1236,13 +1514,16 @@ var CodeEditor = ({
|
|
|
1236
1514
|
collapseUnchanged: withCollapseUnchanged ? {} : void 0
|
|
1237
1515
|
}) : []
|
|
1238
1516
|
];
|
|
1239
|
-
}, [commonExtensions, placeholder, readOnly, previousValue, withCollapseUnchanged]);
|
|
1517
|
+
}, [commonExtensions, placeholder, readOnly, inputLocked, previousValue, withCollapseUnchanged]);
|
|
1240
1518
|
const config = react.useMemo(() => {
|
|
1241
1519
|
return {
|
|
1242
1520
|
...buildBasicSetup(readOnly),
|
|
1243
|
-
lineNumbers: withLineNumbers
|
|
1521
|
+
lineNumbers: withLineNumbers,
|
|
1522
|
+
// Mod-f opens CodeMirror's own panel, which would run a second query and a
|
|
1523
|
+
// second match count over the same document beside the caller's input.
|
|
1524
|
+
...withSearch ? { searchKeymap: false } : null
|
|
1244
1525
|
};
|
|
1245
|
-
}, [withLineNumbers, readOnly]);
|
|
1526
|
+
}, [withLineNumbers, readOnly, withSearch]);
|
|
1246
1527
|
const additionalButtons = renderAdditionalButtons?.(value);
|
|
1247
1528
|
const hasToolbar = withCopyButton && !!value || !!additionalButtons;
|
|
1248
1529
|
return (
|
|
@@ -1265,6 +1546,8 @@ var CodeEditor = ({
|
|
|
1265
1546
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1266
1547
|
CodeMirror__default.default,
|
|
1267
1548
|
{
|
|
1549
|
+
ref: editorRef,
|
|
1550
|
+
onCreateEditor: handleCreateEditor,
|
|
1268
1551
|
theme: customTheme,
|
|
1269
1552
|
value,
|
|
1270
1553
|
onChange: handleChange,
|
|
@@ -1457,8 +1740,6 @@ var activeQueryHighlight = (splitQueries) => {
|
|
|
1457
1740
|
})
|
|
1458
1741
|
];
|
|
1459
1742
|
};
|
|
1460
|
-
|
|
1461
|
-
// src/components/CodeEditor/highlighting.ts
|
|
1462
1743
|
var HighlightMarker = class extends view.GutterMarker {
|
|
1463
1744
|
toDOM() {
|
|
1464
1745
|
const marker = document.createElement("div");
|
|
@@ -1574,125 +1855,18 @@ var highlightedLinesTheme = view.EditorView.baseTheme({
|
|
|
1574
1855
|
backgroundColor: `${colors__default.default.blue[100]} !important`
|
|
1575
1856
|
}
|
|
1576
1857
|
});
|
|
1577
|
-
function highlightingExtension(
|
|
1858
|
+
function highlightingExtension() {
|
|
1578
1859
|
return [
|
|
1579
1860
|
highlightedLinesField,
|
|
1580
1861
|
highlightGutter,
|
|
1581
1862
|
errorLineDecorations,
|
|
1582
1863
|
processingLineDecorations,
|
|
1583
|
-
highlightedLinesTheme
|
|
1584
|
-
...queryParser ? activeQueryHighlight(queryParser) : []
|
|
1864
|
+
highlightedLinesTheme
|
|
1585
1865
|
];
|
|
1586
1866
|
}
|
|
1587
1867
|
function updateHighlighting(view, lines) {
|
|
1588
1868
|
view.dispatch({ effects: setHighlightedLinesEffect.of(lines ?? null) });
|
|
1589
1869
|
}
|
|
1590
|
-
var setSearchEffect = state.StateEffect.define();
|
|
1591
|
-
function findMatches(doc, query) {
|
|
1592
|
-
if (!query) return [];
|
|
1593
|
-
const text = doc.toString();
|
|
1594
|
-
try {
|
|
1595
|
-
const regex = new RegExp(escapeStringRegexp(query), "gi");
|
|
1596
|
-
return Array.from(text.matchAll(regex)).map((match, index) => {
|
|
1597
|
-
const from = match.index;
|
|
1598
|
-
const to = from + match[0].length;
|
|
1599
|
-
return { from, to, text: match[0], localIndex: index };
|
|
1600
|
-
});
|
|
1601
|
-
} catch (e) {
|
|
1602
|
-
console.warn("Invalid search regex:", e);
|
|
1603
|
-
return [];
|
|
1604
|
-
}
|
|
1605
|
-
}
|
|
1606
|
-
function createDecorations(matches, selectedLocalIndex) {
|
|
1607
|
-
const decorations = matches.map((match) => {
|
|
1608
|
-
const isSelected = match.localIndex === selectedLocalIndex;
|
|
1609
|
-
const decoration = view.Decoration.mark({
|
|
1610
|
-
class: isSelected ? "cm-searchMatch-selected" : "cm-searchMatch"
|
|
1611
|
-
});
|
|
1612
|
-
return decoration.range(match.from, match.to);
|
|
1613
|
-
});
|
|
1614
|
-
return view.Decoration.set(decorations, true);
|
|
1615
|
-
}
|
|
1616
|
-
var searchField = state.StateField.define({
|
|
1617
|
-
create() {
|
|
1618
|
-
return {
|
|
1619
|
-
query: "",
|
|
1620
|
-
selectedMatchIndex: void 0,
|
|
1621
|
-
matches: [],
|
|
1622
|
-
decorations: view.Decoration.none
|
|
1623
|
-
};
|
|
1624
|
-
},
|
|
1625
|
-
update(state, tr) {
|
|
1626
|
-
let newState = state;
|
|
1627
|
-
for (const effect of tr.effects) {
|
|
1628
|
-
if (!effect.is(setSearchEffect)) {
|
|
1629
|
-
continue;
|
|
1630
|
-
}
|
|
1631
|
-
const { query, selectedMatchIndex } = effect.value;
|
|
1632
|
-
const matches = findMatches(tr.state.doc, query);
|
|
1633
|
-
const decorations = createDecorations(matches, selectedMatchIndex);
|
|
1634
|
-
newState = {
|
|
1635
|
-
query,
|
|
1636
|
-
selectedMatchIndex,
|
|
1637
|
-
matches,
|
|
1638
|
-
decorations
|
|
1639
|
-
};
|
|
1640
|
-
}
|
|
1641
|
-
if (tr.docChanged && newState.query) {
|
|
1642
|
-
const matches = findMatches(tr.state.doc, newState.query);
|
|
1643
|
-
const decorations = createDecorations(matches, newState.selectedMatchIndex);
|
|
1644
|
-
newState = {
|
|
1645
|
-
...newState,
|
|
1646
|
-
matches,
|
|
1647
|
-
decorations
|
|
1648
|
-
};
|
|
1649
|
-
}
|
|
1650
|
-
return newState;
|
|
1651
|
-
},
|
|
1652
|
-
provide: (field) => view.EditorView.decorations.from(field, (state) => state.decorations)
|
|
1653
|
-
});
|
|
1654
|
-
var searchViewPlugin = view.ViewPlugin.fromClass(
|
|
1655
|
-
class {
|
|
1656
|
-
lastSelectedIndex;
|
|
1657
|
-
update(update) {
|
|
1658
|
-
const state = update.state.field(searchField);
|
|
1659
|
-
if (state.selectedMatchIndex !== void 0 && state.selectedMatchIndex !== this.lastSelectedIndex) {
|
|
1660
|
-
const match = state.matches[state.selectedMatchIndex];
|
|
1661
|
-
if (match) {
|
|
1662
|
-
requestAnimationFrame(() => {
|
|
1663
|
-
update.view.dispatch({
|
|
1664
|
-
effects: view.EditorView.scrollIntoView(match.from, { y: "center" })
|
|
1665
|
-
});
|
|
1666
|
-
});
|
|
1667
|
-
}
|
|
1668
|
-
this.lastSelectedIndex = state.selectedMatchIndex;
|
|
1669
|
-
}
|
|
1670
|
-
if (state.selectedMatchIndex === void 0) {
|
|
1671
|
-
this.lastSelectedIndex = void 0;
|
|
1672
|
-
}
|
|
1673
|
-
}
|
|
1674
|
-
}
|
|
1675
|
-
);
|
|
1676
|
-
var searchTheme = view.EditorView.baseTheme({
|
|
1677
|
-
".cm-searchMatch": {
|
|
1678
|
-
backgroundColor: colors__default.default.blue[100]
|
|
1679
|
-
},
|
|
1680
|
-
".cm-searchMatch > span": {
|
|
1681
|
-
color: `${colors__default.default.blue[600]} !important`
|
|
1682
|
-
},
|
|
1683
|
-
".cm-searchMatch-selected": {
|
|
1684
|
-
backgroundColor: colors__default.default.blue[600]
|
|
1685
|
-
},
|
|
1686
|
-
".cm-searchMatch-selected > span": {
|
|
1687
|
-
color: `${colors__default.default.white} !important`
|
|
1688
|
-
}
|
|
1689
|
-
});
|
|
1690
|
-
function searchExtension() {
|
|
1691
|
-
return [searchField, searchViewPlugin, searchTheme];
|
|
1692
|
-
}
|
|
1693
|
-
function updateSearch(view, query, selectedMatchIndex) {
|
|
1694
|
-
view.dispatch({ effects: setSearchEffect.of({ query, selectedMatchIndex }) });
|
|
1695
|
-
}
|
|
1696
1870
|
var OWN_KEYMAPS = {
|
|
1697
1871
|
defaultKeymap: false,
|
|
1698
1872
|
completionKeymap: false,
|
|
@@ -1708,6 +1882,7 @@ var CUSTOM_KEYMAP = [
|
|
|
1708
1882
|
}
|
|
1709
1883
|
}
|
|
1710
1884
|
];
|
|
1885
|
+
var OWN_KEYMAP_EXTENSION = CodeMirror.keymap.of([...commands.defaultKeymap, ...CUSTOM_KEYMAP]);
|
|
1711
1886
|
var buildTheme = () => ({
|
|
1712
1887
|
...buildBaseThemeStyles(),
|
|
1713
1888
|
"&.cm-editor": {
|
|
@@ -1745,7 +1920,6 @@ var SqlEditor = ({
|
|
|
1745
1920
|
searchQuery = "",
|
|
1746
1921
|
searchMatchIndex,
|
|
1747
1922
|
readOnly = false,
|
|
1748
|
-
extraKeys,
|
|
1749
1923
|
queryParser,
|
|
1750
1924
|
autoFocus = false,
|
|
1751
1925
|
lineNumbers = true,
|
|
@@ -1758,34 +1932,57 @@ var SqlEditor = ({
|
|
|
1758
1932
|
dialect
|
|
1759
1933
|
}) => {
|
|
1760
1934
|
const editorRef = react.useRef(null);
|
|
1935
|
+
const handleChange = useStableCallback((next) => onChange?.(next));
|
|
1936
|
+
const parseQueries = useStableCallback(async (sql2) => await queryParser?.(sql2) ?? []);
|
|
1937
|
+
const handleBlur = useStableCallback((view) => onBlurEditor?.(view));
|
|
1938
|
+
const handleFocus = useStableCallback((view) => onFocusEditor?.(view));
|
|
1939
|
+
const handleUpdate = useStableCallback((update) => {
|
|
1940
|
+
if (update.selectionSet) {
|
|
1941
|
+
const { main } = update.state.selection;
|
|
1942
|
+
onSelectionChange?.(update.state.sliceDoc(main.from, main.to));
|
|
1943
|
+
}
|
|
1944
|
+
});
|
|
1945
|
+
const variableCompletion = useVariableCompletion(variables);
|
|
1946
|
+
const withQueryParser = queryParser !== void 0;
|
|
1947
|
+
const tooltipLayer = useTooltipsExtension();
|
|
1761
1948
|
const customTheme = useThemedExtension("editor:syntax", buildCustomTheme);
|
|
1762
1949
|
const themeExtension = useThemedExtension(
|
|
1763
1950
|
"sql-editor:chrome",
|
|
1764
1951
|
() => CodeMirror.EditorView.theme(buildTheme())
|
|
1765
1952
|
);
|
|
1766
1953
|
const extensions = react.useMemo(() => {
|
|
1767
|
-
const baseKeymap = [...commands.defaultKeymap, ...CUSTOM_KEYMAP];
|
|
1768
1954
|
return [
|
|
1769
1955
|
CodeMirror.EditorView.lineWrapping,
|
|
1770
|
-
|
|
1771
|
-
...codemirrorLangSql.installExtensions({
|
|
1956
|
+
OWN_KEYMAP_EXTENSION,
|
|
1957
|
+
...codemirrorLangSql.installExtensions({
|
|
1958
|
+
schema,
|
|
1959
|
+
defaultDatabase,
|
|
1960
|
+
defaultSchema,
|
|
1961
|
+
variableCompletion,
|
|
1962
|
+
dialect
|
|
1963
|
+
}),
|
|
1772
1964
|
searchExtension(),
|
|
1773
|
-
highlightingExtension(
|
|
1965
|
+
highlightingExtension(),
|
|
1966
|
+
withQueryParser ? activeQueryHighlight(parseQueries) : [],
|
|
1967
|
+
tooltipLayer,
|
|
1774
1968
|
themeExtension,
|
|
1775
|
-
|
|
1776
|
-
|
|
1969
|
+
CodeMirror.EditorView.domEventHandlers({
|
|
1970
|
+
blur: (_, view) => handleBlur(view),
|
|
1971
|
+
focus: (_, view) => handleFocus(view)
|
|
1972
|
+
})
|
|
1777
1973
|
];
|
|
1778
1974
|
}, [
|
|
1779
|
-
|
|
1780
|
-
|
|
1975
|
+
withQueryParser,
|
|
1976
|
+
parseQueries,
|
|
1781
1977
|
schema,
|
|
1782
1978
|
defaultDatabase,
|
|
1783
1979
|
defaultSchema,
|
|
1784
|
-
|
|
1980
|
+
variableCompletion,
|
|
1785
1981
|
dialect,
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
themeExtension
|
|
1982
|
+
handleBlur,
|
|
1983
|
+
handleFocus,
|
|
1984
|
+
themeExtension,
|
|
1985
|
+
tooltipLayer
|
|
1789
1986
|
]);
|
|
1790
1987
|
const defaultSetup = react.useMemo(() => {
|
|
1791
1988
|
return { ...buildBasicSetup(readOnly), ...OWN_KEYMAPS, lineNumbers };
|
|
@@ -1800,34 +1997,17 @@ var SqlEditor = ({
|
|
|
1800
1997
|
updateSearch(editorRef.current.view, searchQuery, searchMatchIndex);
|
|
1801
1998
|
}
|
|
1802
1999
|
}, [searchQuery, searchMatchIndex]);
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
(
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
}
|
|
1815
|
-
if (searchQuery) {
|
|
1816
|
-
updateSearch(view, searchQuery, searchMatchIndex);
|
|
1817
|
-
}
|
|
1818
|
-
},
|
|
1819
|
-
[onCreateEditor, highlightLines, searchQuery, searchMatchIndex]
|
|
1820
|
-
);
|
|
1821
|
-
const handleOnUpdate = react.useCallback(
|
|
1822
|
-
(update) => {
|
|
1823
|
-
if (update.selectionSet) {
|
|
1824
|
-
const { main } = update.state.selection;
|
|
1825
|
-
const text = update.state.sliceDoc(main.from, main.to);
|
|
1826
|
-
onSelectionChange?.(text);
|
|
1827
|
-
}
|
|
1828
|
-
},
|
|
1829
|
-
[onSelectionChange]
|
|
1830
|
-
);
|
|
2000
|
+
const handleDestroy = useStableCallback(() => onDestroyEditor?.());
|
|
2001
|
+
react.useEffect(() => handleDestroy, [handleDestroy]);
|
|
2002
|
+
const handleCreate = useStableCallback((view, state) => {
|
|
2003
|
+
onCreateEditor?.(view, state);
|
|
2004
|
+
if (highlightLines) {
|
|
2005
|
+
updateHighlighting(view, highlightLines);
|
|
2006
|
+
}
|
|
2007
|
+
if (searchQuery) {
|
|
2008
|
+
updateSearch(view, searchQuery, searchMatchIndex);
|
|
2009
|
+
}
|
|
2010
|
+
});
|
|
1831
2011
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1832
2012
|
CodeMirror__default.default,
|
|
1833
2013
|
{
|
|
@@ -1835,9 +2015,9 @@ var SqlEditor = ({
|
|
|
1835
2015
|
theme: customTheme,
|
|
1836
2016
|
extensions,
|
|
1837
2017
|
value,
|
|
1838
|
-
onChange,
|
|
1839
|
-
onUpdate:
|
|
1840
|
-
onCreateEditor:
|
|
2018
|
+
onChange: handleChange,
|
|
2019
|
+
onUpdate: handleUpdate,
|
|
2020
|
+
onCreateEditor: handleCreate,
|
|
1841
2021
|
autoFocus,
|
|
1842
2022
|
placeholder,
|
|
1843
2023
|
className,
|