@seljs/editor 1.0.0 → 1.0.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 (104) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/completion/completion-items.cjs +36 -0
  3. package/dist/completion/completion-items.mjs +32 -0
  4. package/dist/completion/index.cjs +1 -0
  5. package/dist/completion/index.d.mts +1 -0
  6. package/dist/completion/index.mjs +2 -0
  7. package/dist/completion/schema-completion.cjs +182 -0
  8. package/dist/completion/schema-completion.d.cts +25 -0
  9. package/dist/completion/schema-completion.d.mts +25 -0
  10. package/dist/completion/schema-completion.mjs +181 -0
  11. package/dist/completion/tree-context.cjs +108 -0
  12. package/dist/completion/tree-context.mjs +108 -0
  13. package/dist/editor/create-editor.cjs +16 -0
  14. package/dist/editor/create-editor.d.cts +7 -0
  15. package/dist/editor/create-editor.d.mts +7 -0
  16. package/dist/editor/create-editor.mjs +16 -0
  17. package/dist/editor/editor-config.cjs +49 -0
  18. package/dist/editor/editor-config.d.cts +7 -0
  19. package/dist/editor/editor-config.d.mts +7 -0
  20. package/dist/editor/editor-config.mjs +49 -0
  21. package/dist/editor/index.cjs +3 -0
  22. package/dist/editor/index.d.cts +6 -0
  23. package/dist/editor/index.d.mts +6 -0
  24. package/dist/editor/index.mjs +4 -0
  25. package/dist/editor/theme.cjs +35 -0
  26. package/dist/editor/theme.d.cts +7 -0
  27. package/dist/editor/theme.d.mts +7 -0
  28. package/dist/editor/theme.mjs +34 -0
  29. package/dist/editor/type-display.cjs +71 -0
  30. package/dist/editor/type-display.mjs +71 -0
  31. package/dist/editor/types.d.cts +31 -0
  32. package/dist/editor/types.d.mts +31 -0
  33. package/dist/index.cjs +20 -0
  34. package/dist/index.d.cts +10 -0
  35. package/dist/index.d.mts +10 -0
  36. package/dist/index.mjs +11 -0
  37. package/dist/language/semantic-highlighter.cjs +55 -0
  38. package/dist/language/semantic-highlighter.mjs +55 -0
  39. package/dist/language/tokenizer-config.cjs +9 -0
  40. package/dist/language/tokenizer-config.d.cts +12 -0
  41. package/dist/language/tokenizer-config.d.mts +12 -0
  42. package/dist/language/tokenizer-config.mjs +9 -0
  43. package/dist/linting/diagnostic-mapper.cjs +37 -0
  44. package/dist/linting/{diagnostic-mapper.d.ts → diagnostic-mapper.d.cts} +7 -6
  45. package/dist/linting/diagnostic-mapper.d.mts +29 -0
  46. package/dist/linting/diagnostic-mapper.mjs +37 -0
  47. package/dist/linting/index.cjs +2 -0
  48. package/dist/linting/index.d.mts +2 -0
  49. package/dist/linting/index.mjs +3 -0
  50. package/dist/linting/sel-linter.cjs +28 -0
  51. package/dist/linting/sel-linter.d.cts +13 -0
  52. package/dist/linting/sel-linter.d.mts +13 -0
  53. package/dist/linting/sel-linter.mjs +28 -0
  54. package/package.json +29 -22
  55. package/dist/completion/completion-items.d.ts +0 -8
  56. package/dist/completion/completion-items.d.ts.map +0 -1
  57. package/dist/completion/completion-items.js +0 -29
  58. package/dist/completion/index.d.ts +0 -2
  59. package/dist/completion/index.d.ts.map +0 -1
  60. package/dist/completion/index.js +0 -1
  61. package/dist/completion/schema-completion.d.ts +0 -22
  62. package/dist/completion/schema-completion.d.ts.map +0 -1
  63. package/dist/completion/schema-completion.js +0 -220
  64. package/dist/completion/tree-context.d.ts +0 -23
  65. package/dist/completion/tree-context.d.ts.map +0 -1
  66. package/dist/completion/tree-context.js +0 -154
  67. package/dist/editor/create-editor.d.ts +0 -4
  68. package/dist/editor/create-editor.d.ts.map +0 -1
  69. package/dist/editor/create-editor.js +0 -14
  70. package/dist/editor/editor-config.d.ts +0 -4
  71. package/dist/editor/editor-config.d.ts.map +0 -1
  72. package/dist/editor/editor-config.js +0 -64
  73. package/dist/editor/index.d.ts +0 -6
  74. package/dist/editor/index.d.ts.map +0 -1
  75. package/dist/editor/index.js +0 -3
  76. package/dist/editor/theme.d.ts +0 -3
  77. package/dist/editor/theme.d.ts.map +0 -1
  78. package/dist/editor/theme.js +0 -43
  79. package/dist/editor/type-display.d.ts +0 -4
  80. package/dist/editor/type-display.d.ts.map +0 -1
  81. package/dist/editor/type-display.js +0 -75
  82. package/dist/editor/types.d.ts +0 -28
  83. package/dist/editor/types.d.ts.map +0 -1
  84. package/dist/editor/types.js +0 -1
  85. package/dist/index.d.ts +0 -5
  86. package/dist/index.d.ts.map +0 -1
  87. package/dist/index.js +0 -4
  88. package/dist/language/index.d.ts +0 -2
  89. package/dist/language/index.d.ts.map +0 -1
  90. package/dist/language/index.js +0 -1
  91. package/dist/language/semantic-highlighter.d.ts +0 -4
  92. package/dist/language/semantic-highlighter.d.ts.map +0 -1
  93. package/dist/language/semantic-highlighter.js +0 -76
  94. package/dist/language/tokenizer-config.d.ts +0 -9
  95. package/dist/language/tokenizer-config.d.ts.map +0 -1
  96. package/dist/language/tokenizer-config.js +0 -6
  97. package/dist/linting/diagnostic-mapper.d.ts.map +0 -1
  98. package/dist/linting/diagnostic-mapper.js +0 -46
  99. package/dist/linting/index.d.ts +0 -3
  100. package/dist/linting/index.d.ts.map +0 -1
  101. package/dist/linting/index.js +0 -2
  102. package/dist/linting/sel-linter.d.ts +0 -12
  103. package/dist/linting/sel-linter.d.ts.map +0 -1
  104. package/dist/linting/sel-linter.js +0 -28
@@ -0,0 +1,108 @@
1
+ import { syntaxTree } from "@codemirror/language";
2
+ //#region src/completion/tree-context.ts
3
+ /**
4
+ * Walk up the tree looking for a MemberExpression ancestor.
5
+ * A MemberExpression has two Identifier children (or child nodes) separated by ".".
6
+ * The dot position is: firstChild.to + 1 (the "." character is between them).
7
+ * We are in dot-access context when pos >= dotPos.
8
+ */
9
+ const findDotAccess = (state, node, pos) => {
10
+ let current = node;
11
+ while (current) {
12
+ if (current.name === "ArgList") break;
13
+ if (current.name === "MemberExpression" || current.name === "OptionalExpression") {
14
+ const firstChild = current.firstChild;
15
+ if (firstChild) {
16
+ const dotPos = firstChild.to + 1;
17
+ if (pos >= dotPos) return {
18
+ kind: "dot-access",
19
+ receiverText: state.doc.sliceString(current.from, firstChild.to),
20
+ from: dotPos
21
+ };
22
+ }
23
+ }
24
+ current = current.parent;
25
+ }
26
+ };
27
+ /**
28
+ * Count commas in ArgList text that appear before pos.
29
+ * Commas are anonymous tokens not exposed as named children,
30
+ * so we scan the raw source text.
31
+ */
32
+ const countCommasBefore = (argList, state, pos) => {
33
+ const open = argList.from + 1;
34
+ const end = Math.min(pos, argList.to);
35
+ const text = state.doc.sliceString(open, end);
36
+ let count = 0;
37
+ for (const ch of text) if (ch === ",") count++;
38
+ return count;
39
+ };
40
+ /**
41
+ * Extract function name and optional receiver name from a CallExpression node.
42
+ *
43
+ * Tree shapes:
44
+ * foo(...) → CallExpression > Identifier, ArgList
45
+ * erc20.foo(...) → CallExpression > MemberExpression(Identifier "erc20", Identifier "foo"), ArgList
46
+ */
47
+ const extractCallInfo = (state, callExpr) => {
48
+ const callee = callExpr.firstChild;
49
+ if (!callee) return;
50
+ if (callee.name === "Identifier") return { functionName: state.doc.sliceString(callee.from, callee.to) };
51
+ if (callee.name === "MemberExpression") {
52
+ const lastChild = callee.lastChild;
53
+ if (lastChild?.name === "Identifier") {
54
+ const functionName = state.doc.sliceString(lastChild.from, lastChild.to);
55
+ const receiverNode = callee.firstChild;
56
+ return {
57
+ functionName,
58
+ receiverName: receiverNode?.name === "Identifier" ? state.doc.sliceString(receiverNode.from, receiverNode.to) : void 0
59
+ };
60
+ }
61
+ }
62
+ };
63
+ const findWordStart = (state, pos) => {
64
+ const text = state.doc.sliceString(0, pos);
65
+ const match = /\w+$/.exec(text);
66
+ return match ? pos - match[0].length : pos;
67
+ };
68
+ /**
69
+ * Walk up the tree looking for an ArgList ancestor.
70
+ * When found, count commas before pos to get paramIndex,
71
+ * then extract function name and optional receiver from the CallExpression.
72
+ */
73
+ const findCallArg = (state, node, pos) => {
74
+ let current = node;
75
+ while (current) {
76
+ if (current.name === "ArgList") {
77
+ const paramIndex = countCommasBefore(current, state, pos);
78
+ const callExpr = current.parent;
79
+ if (callExpr?.name === "CallExpression") {
80
+ const info = extractCallInfo(state, callExpr);
81
+ if (info) return {
82
+ kind: "call-arg",
83
+ functionName: info.functionName,
84
+ receiverName: info.receiverName,
85
+ paramIndex,
86
+ from: pos
87
+ };
88
+ }
89
+ }
90
+ current = current.parent;
91
+ }
92
+ };
93
+ /**
94
+ * Extract completion context from the Lezer syntax tree at the given position.
95
+ */
96
+ const getCompletionContext = (state, pos) => {
97
+ const node = syntaxTree(state).resolveInner(pos, -1);
98
+ const dotAccess = findDotAccess(state, node, pos);
99
+ if (dotAccess) return dotAccess;
100
+ const callArg = findCallArg(state, node, pos);
101
+ if (callArg) return callArg;
102
+ return {
103
+ kind: "top-level",
104
+ from: findWordStart(state, pos)
105
+ };
106
+ };
107
+ //#endregion
108
+ export { getCompletionContext };
@@ -0,0 +1,16 @@
1
+ const require_editor_config = require("./editor-config.cjs");
2
+ let _codemirror_state = require("@codemirror/state");
3
+ let _codemirror_view = require("@codemirror/view");
4
+ //#region src/editor/create-editor.ts
5
+ function createSELEditor(config) {
6
+ const extensions = require_editor_config.buildExtensions(config);
7
+ return new _codemirror_view.EditorView({
8
+ state: _codemirror_state.EditorState.create({
9
+ doc: config.value ?? "",
10
+ extensions
11
+ }),
12
+ parent: config.parent
13
+ });
14
+ }
15
+ //#endregion
16
+ exports.createSELEditor = createSELEditor;
@@ -0,0 +1,7 @@
1
+ import { SELEditorConfig } from "./types.cjs";
2
+ import { EditorView } from "@codemirror/view";
3
+
4
+ //#region src/editor/create-editor.d.ts
5
+ declare function createSELEditor(config: SELEditorConfig): EditorView;
6
+ //#endregion
7
+ export { createSELEditor };
@@ -0,0 +1,7 @@
1
+ import { SELEditorConfig } from "./types.mjs";
2
+ import { EditorView } from "@codemirror/view";
3
+
4
+ //#region src/editor/create-editor.d.ts
5
+ declare function createSELEditor(config: SELEditorConfig): EditorView;
6
+ //#endregion
7
+ export { createSELEditor };
@@ -0,0 +1,16 @@
1
+ import { buildExtensions } from "./editor-config.mjs";
2
+ import { EditorState } from "@codemirror/state";
3
+ import { EditorView } from "@codemirror/view";
4
+ //#region src/editor/create-editor.ts
5
+ function createSELEditor(config) {
6
+ const extensions = buildExtensions(config);
7
+ return new EditorView({
8
+ state: EditorState.create({
9
+ doc: config.value ?? "",
10
+ extensions
11
+ }),
12
+ parent: config.parent
13
+ });
14
+ }
15
+ //#endregion
16
+ export { createSELEditor };
@@ -0,0 +1,49 @@
1
+ const require_tokenizer_config = require("../language/tokenizer-config.cjs");
2
+ const require_schema_completion = require("../completion/schema-completion.cjs");
3
+ const require_sel_linter = require("../linting/sel-linter.cjs");
4
+ const require_theme = require("./theme.cjs");
5
+ const require_type_display = require("./type-display.cjs");
6
+ const require_semantic_highlighter = require("../language/semantic-highlighter.cjs");
7
+ let _codemirror_autocomplete = require("@codemirror/autocomplete");
8
+ let _seljs_checker = require("@seljs/checker");
9
+ let _codemirror_language = require("@codemirror/language");
10
+ let _codemirror_state = require("@codemirror/state");
11
+ let _codemirror_view = require("@codemirror/view");
12
+ let _codemirror_commands = require("@codemirror/commands");
13
+ let _seljs_cel_lezer = require("@seljs/cel-lezer");
14
+ //#region src/editor/editor-config.ts
15
+ const buildExtensions = (config) => {
16
+ const checker = new _seljs_checker.SELChecker(config.schema, { rules: [..._seljs_checker.rules.builtIn] });
17
+ const extensions = [];
18
+ extensions.push((0, _seljs_cel_lezer.celLanguageSupport)(config.dark));
19
+ extensions.push((0, _codemirror_language.bracketMatching)());
20
+ const tokenizerConfig = require_tokenizer_config.createTokenizerConfig(config.schema);
21
+ extensions.push(require_semantic_highlighter.createSemanticHighlighter(tokenizerConfig, config.dark));
22
+ extensions.push(require_schema_completion.createSchemaCompletion(config.schema, checker));
23
+ extensions.push((0, _codemirror_autocomplete.closeBrackets)());
24
+ extensions.push(_codemirror_view.keymap.of([
25
+ ..._codemirror_autocomplete.closeBracketsKeymap,
26
+ ..._codemirror_commands.defaultKeymap,
27
+ ..._codemirror_commands.historyKeymap
28
+ ]));
29
+ extensions.push((0, _codemirror_commands.history)());
30
+ extensions.push(config.dark ? require_theme.selDarkTheme : require_theme.selLightTheme);
31
+ const validate = config.validate ?? ((expression) => checker.check(expression).diagnostics);
32
+ extensions.push(require_sel_linter.createSELLinter({
33
+ validate,
34
+ delay: config.validateDelay
35
+ }));
36
+ if (config.onChange) {
37
+ const onChange = config.onChange;
38
+ extensions.push(_codemirror_view.EditorView.updateListener.of((update) => {
39
+ if (update.docChanged) onChange(update.state.doc.toString());
40
+ }));
41
+ }
42
+ if (config.readOnly) extensions.push(_codemirror_state.EditorState.readOnly.of(true));
43
+ if (config.placeholder) extensions.push((0, _codemirror_view.placeholder)(config.placeholder));
44
+ if (config.showType) extensions.push(require_type_display.createTypeDisplay(checker, config.dark ?? false));
45
+ if (config.extensions) extensions.push(...config.extensions);
46
+ return extensions;
47
+ };
48
+ //#endregion
49
+ exports.buildExtensions = buildExtensions;
@@ -0,0 +1,7 @@
1
+ import { SELEditorConfig } from "./types.cjs";
2
+ import { Extension } from "@codemirror/state";
3
+
4
+ //#region src/editor/editor-config.d.ts
5
+ declare const buildExtensions: (config: SELEditorConfig) => Extension[];
6
+ //#endregion
7
+ export { buildExtensions };
@@ -0,0 +1,7 @@
1
+ import { SELEditorConfig } from "./types.mjs";
2
+ import { Extension } from "@codemirror/state";
3
+
4
+ //#region src/editor/editor-config.d.ts
5
+ declare const buildExtensions: (config: SELEditorConfig) => Extension[];
6
+ //#endregion
7
+ export { buildExtensions };
@@ -0,0 +1,49 @@
1
+ import { createTokenizerConfig } from "../language/tokenizer-config.mjs";
2
+ import { createSchemaCompletion } from "../completion/schema-completion.mjs";
3
+ import { createSELLinter } from "../linting/sel-linter.mjs";
4
+ import { selDarkTheme, selLightTheme } from "./theme.mjs";
5
+ import { createTypeDisplay } from "./type-display.mjs";
6
+ import { createSemanticHighlighter } from "../language/semantic-highlighter.mjs";
7
+ import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
8
+ import { SELChecker, rules } from "@seljs/checker";
9
+ import { bracketMatching } from "@codemirror/language";
10
+ import { EditorState } from "@codemirror/state";
11
+ import { EditorView, keymap, placeholder } from "@codemirror/view";
12
+ import { defaultKeymap, history, historyKeymap } from "@codemirror/commands";
13
+ import { celLanguageSupport } from "@seljs/cel-lezer";
14
+ //#region src/editor/editor-config.ts
15
+ const buildExtensions = (config) => {
16
+ const checker = new SELChecker(config.schema, { rules: [...rules.builtIn] });
17
+ const extensions = [];
18
+ extensions.push(celLanguageSupport(config.dark));
19
+ extensions.push(bracketMatching());
20
+ const tokenizerConfig = createTokenizerConfig(config.schema);
21
+ extensions.push(createSemanticHighlighter(tokenizerConfig, config.dark));
22
+ extensions.push(createSchemaCompletion(config.schema, checker));
23
+ extensions.push(closeBrackets());
24
+ extensions.push(keymap.of([
25
+ ...closeBracketsKeymap,
26
+ ...defaultKeymap,
27
+ ...historyKeymap
28
+ ]));
29
+ extensions.push(history());
30
+ extensions.push(config.dark ? selDarkTheme : selLightTheme);
31
+ const validate = config.validate ?? ((expression) => checker.check(expression).diagnostics);
32
+ extensions.push(createSELLinter({
33
+ validate,
34
+ delay: config.validateDelay
35
+ }));
36
+ if (config.onChange) {
37
+ const onChange = config.onChange;
38
+ extensions.push(EditorView.updateListener.of((update) => {
39
+ if (update.docChanged) onChange(update.state.doc.toString());
40
+ }));
41
+ }
42
+ if (config.readOnly) extensions.push(EditorState.readOnly.of(true));
43
+ if (config.placeholder) extensions.push(placeholder(config.placeholder));
44
+ if (config.showType) extensions.push(createTypeDisplay(checker, config.dark ?? false));
45
+ if (config.extensions) extensions.push(...config.extensions);
46
+ return extensions;
47
+ };
48
+ //#endregion
49
+ export { buildExtensions };
@@ -0,0 +1,3 @@
1
+ require("./theme.cjs");
2
+ require("./editor-config.cjs");
3
+ require("./create-editor.cjs");
@@ -0,0 +1,6 @@
1
+ import { SELEditorConfig } from "./types.cjs";
2
+ import { createSELEditor } from "./create-editor.cjs";
3
+ import { buildExtensions } from "./editor-config.cjs";
4
+ import { selDarkTheme, selLightTheme } from "./theme.cjs";
5
+ import { EditorView as EditorView$1 } from "@codemirror/view";
6
+ export { type EditorView$1 as EditorView };
@@ -0,0 +1,6 @@
1
+ import { SELEditorConfig } from "./types.mjs";
2
+ import { createSELEditor } from "./create-editor.mjs";
3
+ import { buildExtensions } from "./editor-config.mjs";
4
+ import { selDarkTheme, selLightTheme } from "./theme.mjs";
5
+ import { EditorView as EditorView$1 } from "@codemirror/view";
6
+ export { type EditorView$1 as EditorView };
@@ -0,0 +1,4 @@
1
+ import "./theme.mjs";
2
+ import "./editor-config.mjs";
3
+ import "./create-editor.mjs";
4
+ export {};
@@ -0,0 +1,35 @@
1
+ let _codemirror_view = require("@codemirror/view");
2
+ //#region src/editor/theme.ts
3
+ const selLightTheme = _codemirror_view.EditorView.theme({
4
+ "&": {
5
+ fontSize: "14px",
6
+ backgroundColor: "#ffffff",
7
+ color: "#1e1e1e"
8
+ },
9
+ ".cm-content": {
10
+ caretColor: "#000000",
11
+ fontFamily: "'JetBrains Mono', 'Fira Code', 'Consolas', monospace",
12
+ padding: "4px 0"
13
+ },
14
+ "&.cm-focused .cm-cursor": { borderLeftColor: "#000000" },
15
+ "&.cm-focused .cm-selectionBackground, .cm-selectionBackground": { backgroundColor: "#d7d4f0" },
16
+ ".cm-gutters": { display: "none" }
17
+ });
18
+ const selDarkTheme = _codemirror_view.EditorView.theme({
19
+ "&": {
20
+ fontSize: "14px",
21
+ backgroundColor: "#1e1e1e",
22
+ color: "#d4d4d4"
23
+ },
24
+ ".cm-content": {
25
+ caretColor: "#ffffff",
26
+ fontFamily: "'JetBrains Mono', 'Fira Code', 'Consolas', monospace",
27
+ padding: "4px 0"
28
+ },
29
+ "&.cm-focused .cm-cursor": { borderLeftColor: "#ffffff" },
30
+ "&.cm-focused .cm-selectionBackground, .cm-selectionBackground": { backgroundColor: "#264f78" },
31
+ ".cm-gutters": { display: "none" }
32
+ }, { dark: true });
33
+ //#endregion
34
+ exports.selDarkTheme = selDarkTheme;
35
+ exports.selLightTheme = selLightTheme;
@@ -0,0 +1,7 @@
1
+ import * as _codemirror_state0 from "@codemirror/state";
2
+
3
+ //#region src/editor/theme.d.ts
4
+ declare const selLightTheme: _codemirror_state0.Extension;
5
+ declare const selDarkTheme: _codemirror_state0.Extension;
6
+ //#endregion
7
+ export { selDarkTheme, selLightTheme };
@@ -0,0 +1,7 @@
1
+ import * as _codemirror_state0 from "@codemirror/state";
2
+
3
+ //#region src/editor/theme.d.ts
4
+ declare const selLightTheme: _codemirror_state0.Extension;
5
+ declare const selDarkTheme: _codemirror_state0.Extension;
6
+ //#endregion
7
+ export { selDarkTheme, selLightTheme };
@@ -0,0 +1,34 @@
1
+ import { EditorView } from "@codemirror/view";
2
+ //#region src/editor/theme.ts
3
+ const selLightTheme = EditorView.theme({
4
+ "&": {
5
+ fontSize: "14px",
6
+ backgroundColor: "#ffffff",
7
+ color: "#1e1e1e"
8
+ },
9
+ ".cm-content": {
10
+ caretColor: "#000000",
11
+ fontFamily: "'JetBrains Mono', 'Fira Code', 'Consolas', monospace",
12
+ padding: "4px 0"
13
+ },
14
+ "&.cm-focused .cm-cursor": { borderLeftColor: "#000000" },
15
+ "&.cm-focused .cm-selectionBackground, .cm-selectionBackground": { backgroundColor: "#d7d4f0" },
16
+ ".cm-gutters": { display: "none" }
17
+ });
18
+ const selDarkTheme = EditorView.theme({
19
+ "&": {
20
+ fontSize: "14px",
21
+ backgroundColor: "#1e1e1e",
22
+ color: "#d4d4d4"
23
+ },
24
+ ".cm-content": {
25
+ caretColor: "#ffffff",
26
+ fontFamily: "'JetBrains Mono', 'Fira Code', 'Consolas', monospace",
27
+ padding: "4px 0"
28
+ },
29
+ "&.cm-focused .cm-cursor": { borderLeftColor: "#ffffff" },
30
+ "&.cm-focused .cm-selectionBackground, .cm-selectionBackground": { backgroundColor: "#264f78" },
31
+ ".cm-gutters": { display: "none" }
32
+ }, { dark: true });
33
+ //#endregion
34
+ export { selDarkTheme, selLightTheme };
@@ -0,0 +1,71 @@
1
+ let _codemirror_state = require("@codemirror/state");
2
+ let _codemirror_view = require("@codemirror/view");
3
+ //#region src/editor/type-display.ts
4
+ const setType = _codemirror_state.StateEffect.define();
5
+ const typeField = _codemirror_state.StateField.define({
6
+ create: () => null,
7
+ update(value, tr) {
8
+ for (const e of tr.effects) if (e.is(setType)) return e.value;
9
+ return value;
10
+ }
11
+ });
12
+ function createTypePanel(dark) {
13
+ return (view) => {
14
+ const dom = document.createElement("div");
15
+ dom.className = "sel-type-display";
16
+ dom.style.cssText = [
17
+ "display: flex",
18
+ "align-items: center",
19
+ "gap: 6px",
20
+ `padding: 3px 8px`,
21
+ "font-size: 12px",
22
+ `font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace`,
23
+ `color: ${dark ? "#9ca3af" : "#6b7280"}`,
24
+ `background: ${dark ? "#262626" : "#f9fafb"}`,
25
+ `border-top: 1px solid ${dark ? "#374151" : "#e5e7eb"}`
26
+ ].join("; ");
27
+ const update = () => {
28
+ const type = view.state.field(typeField);
29
+ dom.textContent = "";
30
+ if (type) {
31
+ const label = document.createElement("span");
32
+ label.style.color = dark ? "#6b7280" : "#9ca3af";
33
+ label.textContent = "output";
34
+ const typeSpan = document.createElement("span");
35
+ typeSpan.style.color = dark ? "#93c5fd" : "#2563eb";
36
+ typeSpan.style.fontWeight = "500";
37
+ typeSpan.textContent = type;
38
+ dom.append(label, " ", typeSpan);
39
+ }
40
+ };
41
+ update();
42
+ return {
43
+ dom,
44
+ update: () => {
45
+ update();
46
+ }
47
+ };
48
+ };
49
+ }
50
+ function createTypeDisplay(checker, dark) {
51
+ let debounceTimer;
52
+ return [
53
+ typeField,
54
+ _codemirror_view.EditorView.updateListener.of((update) => {
55
+ if (!update.docChanged && !update.startState.field(typeField, false)) return;
56
+ if (debounceTimer) clearTimeout(debounceTimer);
57
+ debounceTimer = setTimeout(() => {
58
+ const doc = update.state.doc.toString().trim();
59
+ if (!doc) {
60
+ update.view.dispatch({ effects: setType.of(null) });
61
+ return;
62
+ }
63
+ const result = checker.check(doc);
64
+ update.view.dispatch({ effects: setType.of(result.valid ? result.type ?? null : null) });
65
+ }, 200);
66
+ }),
67
+ _codemirror_view.showPanel.of(createTypePanel(dark))
68
+ ];
69
+ }
70
+ //#endregion
71
+ exports.createTypeDisplay = createTypeDisplay;
@@ -0,0 +1,71 @@
1
+ import { StateEffect, StateField } from "@codemirror/state";
2
+ import { EditorView, showPanel } from "@codemirror/view";
3
+ //#region src/editor/type-display.ts
4
+ const setType = StateEffect.define();
5
+ const typeField = StateField.define({
6
+ create: () => null,
7
+ update(value, tr) {
8
+ for (const e of tr.effects) if (e.is(setType)) return e.value;
9
+ return value;
10
+ }
11
+ });
12
+ function createTypePanel(dark) {
13
+ return (view) => {
14
+ const dom = document.createElement("div");
15
+ dom.className = "sel-type-display";
16
+ dom.style.cssText = [
17
+ "display: flex",
18
+ "align-items: center",
19
+ "gap: 6px",
20
+ `padding: 3px 8px`,
21
+ "font-size: 12px",
22
+ `font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace`,
23
+ `color: ${dark ? "#9ca3af" : "#6b7280"}`,
24
+ `background: ${dark ? "#262626" : "#f9fafb"}`,
25
+ `border-top: 1px solid ${dark ? "#374151" : "#e5e7eb"}`
26
+ ].join("; ");
27
+ const update = () => {
28
+ const type = view.state.field(typeField);
29
+ dom.textContent = "";
30
+ if (type) {
31
+ const label = document.createElement("span");
32
+ label.style.color = dark ? "#6b7280" : "#9ca3af";
33
+ label.textContent = "output";
34
+ const typeSpan = document.createElement("span");
35
+ typeSpan.style.color = dark ? "#93c5fd" : "#2563eb";
36
+ typeSpan.style.fontWeight = "500";
37
+ typeSpan.textContent = type;
38
+ dom.append(label, " ", typeSpan);
39
+ }
40
+ };
41
+ update();
42
+ return {
43
+ dom,
44
+ update: () => {
45
+ update();
46
+ }
47
+ };
48
+ };
49
+ }
50
+ function createTypeDisplay(checker, dark) {
51
+ let debounceTimer;
52
+ return [
53
+ typeField,
54
+ EditorView.updateListener.of((update) => {
55
+ if (!update.docChanged && !update.startState.field(typeField, false)) return;
56
+ if (debounceTimer) clearTimeout(debounceTimer);
57
+ debounceTimer = setTimeout(() => {
58
+ const doc = update.state.doc.toString().trim();
59
+ if (!doc) {
60
+ update.view.dispatch({ effects: setType.of(null) });
61
+ return;
62
+ }
63
+ const result = checker.check(doc);
64
+ update.view.dispatch({ effects: setType.of(result.valid ? result.type ?? null : null) });
65
+ }, 200);
66
+ }),
67
+ showPanel.of(createTypePanel(dark))
68
+ ];
69
+ }
70
+ //#endregion
71
+ export { createTypeDisplay };
@@ -0,0 +1,31 @@
1
+ import { SELDiagnostic } from "../linting/diagnostic-mapper.cjs";
2
+ import { SELSchema } from "@seljs/schema";
3
+ import { Extension } from "@codemirror/state";
4
+
5
+ //#region src/editor/types.d.ts
6
+ interface SELEditorConfig {
7
+ /** Container element to mount into */
8
+ parent: HTMLElement;
9
+ /** Schema driving autocomplete and syntax highlighting */
10
+ schema: SELSchema;
11
+ /** Initial expression value */
12
+ value?: string;
13
+ /** Called on every expression change */
14
+ onChange?: (value: string) => void;
15
+ /** Validation function for error highlighting */
16
+ validate?: (expression: string) => SELDiagnostic[] | Promise<SELDiagnostic[]>;
17
+ /** Debounce delay for validation (default: 300ms) */
18
+ validateDelay?: number;
19
+ /** Dark mode */
20
+ dark?: boolean;
21
+ /** Whether the editor is read-only */
22
+ readOnly?: boolean;
23
+ /** Placeholder text */
24
+ placeholder?: string;
25
+ /** Show inferred output type below the editor */
26
+ showType?: boolean;
27
+ /** Additional CodeMirror extensions */
28
+ extensions?: Extension[];
29
+ }
30
+ //#endregion
31
+ export { SELEditorConfig };
@@ -0,0 +1,31 @@
1
+ import { SELDiagnostic } from "../linting/diagnostic-mapper.mjs";
2
+ import { Extension } from "@codemirror/state";
3
+ import { SELSchema } from "@seljs/schema";
4
+
5
+ //#region src/editor/types.d.ts
6
+ interface SELEditorConfig {
7
+ /** Container element to mount into */
8
+ parent: HTMLElement;
9
+ /** Schema driving autocomplete and syntax highlighting */
10
+ schema: SELSchema;
11
+ /** Initial expression value */
12
+ value?: string;
13
+ /** Called on every expression change */
14
+ onChange?: (value: string) => void;
15
+ /** Validation function for error highlighting */
16
+ validate?: (expression: string) => SELDiagnostic[] | Promise<SELDiagnostic[]>;
17
+ /** Debounce delay for validation (default: 300ms) */
18
+ validateDelay?: number;
19
+ /** Dark mode */
20
+ dark?: boolean;
21
+ /** Whether the editor is read-only */
22
+ readOnly?: boolean;
23
+ /** Placeholder text */
24
+ placeholder?: string;
25
+ /** Show inferred output type below the editor */
26
+ showType?: boolean;
27
+ /** Additional CodeMirror extensions */
28
+ extensions?: Extension[];
29
+ }
30
+ //#endregion
31
+ export { SELEditorConfig };
package/dist/index.cjs ADDED
@@ -0,0 +1,20 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_tokenizer_config = require("./language/tokenizer-config.cjs");
3
+ const require_schema_completion = require("./completion/schema-completion.cjs");
4
+ require("./completion/index.cjs");
5
+ const require_sel_linter = require("./linting/sel-linter.cjs");
6
+ const require_diagnostic_mapper = require("./linting/diagnostic-mapper.cjs");
7
+ require("./linting/index.cjs");
8
+ const require_theme = require("./editor/theme.cjs");
9
+ const require_editor_config = require("./editor/editor-config.cjs");
10
+ const require_create_editor = require("./editor/create-editor.cjs");
11
+ require("./editor/index.cjs");
12
+ exports.SchemaCompletionProvider = require_schema_completion.SchemaCompletionProvider;
13
+ exports.buildExtensions = require_editor_config.buildExtensions;
14
+ exports.createSELEditor = require_create_editor.createSELEditor;
15
+ exports.createSELLinter = require_sel_linter.createSELLinter;
16
+ exports.createSchemaCompletion = require_schema_completion.createSchemaCompletion;
17
+ exports.createTokenizerConfig = require_tokenizer_config.createTokenizerConfig;
18
+ exports.mapCheckResult = require_diagnostic_mapper.mapCheckResult;
19
+ exports.selDarkTheme = require_theme.selDarkTheme;
20
+ exports.selLightTheme = require_theme.selLightTheme;
@@ -0,0 +1,10 @@
1
+ import { TokenizerConfig, createTokenizerConfig } from "./language/tokenizer-config.cjs";
2
+ import { SchemaCompletionProvider, createSchemaCompletion } from "./completion/schema-completion.cjs";
3
+ import { SELDiagnostic, mapCheckResult } from "./linting/diagnostic-mapper.cjs";
4
+ import { SELLinterOptions, createSELLinter } from "./linting/sel-linter.cjs";
5
+ import { SELEditorConfig } from "./editor/types.cjs";
6
+ import { createSELEditor } from "./editor/create-editor.cjs";
7
+ import { buildExtensions } from "./editor/editor-config.cjs";
8
+ import { selDarkTheme, selLightTheme } from "./editor/theme.cjs";
9
+ import { EditorView } from "./editor/index.cjs";
10
+ export { EditorView, SELDiagnostic, SELEditorConfig, SELLinterOptions, SchemaCompletionProvider, TokenizerConfig, buildExtensions, createSELEditor, createSELLinter, createSchemaCompletion, createTokenizerConfig, mapCheckResult, selDarkTheme, selLightTheme };
@@ -0,0 +1,10 @@
1
+ import { TokenizerConfig, createTokenizerConfig } from "./language/tokenizer-config.mjs";
2
+ import { SchemaCompletionProvider, createSchemaCompletion } from "./completion/schema-completion.mjs";
3
+ import { SELDiagnostic, mapCheckResult } from "./linting/diagnostic-mapper.mjs";
4
+ import { SELLinterOptions, createSELLinter } from "./linting/sel-linter.mjs";
5
+ import { SELEditorConfig } from "./editor/types.mjs";
6
+ import { createSELEditor } from "./editor/create-editor.mjs";
7
+ import { buildExtensions } from "./editor/editor-config.mjs";
8
+ import { selDarkTheme, selLightTheme } from "./editor/theme.mjs";
9
+ import { EditorView } from "./editor/index.mjs";
10
+ export { EditorView, SELDiagnostic, SELEditorConfig, SELLinterOptions, SchemaCompletionProvider, TokenizerConfig, buildExtensions, createSELEditor, createSELLinter, createSchemaCompletion, createTokenizerConfig, mapCheckResult, selDarkTheme, selLightTheme };
package/dist/index.mjs ADDED
@@ -0,0 +1,11 @@
1
+ import { createTokenizerConfig } from "./language/tokenizer-config.mjs";
2
+ import { SchemaCompletionProvider, createSchemaCompletion } from "./completion/schema-completion.mjs";
3
+ import "./completion/index.mjs";
4
+ import { createSELLinter } from "./linting/sel-linter.mjs";
5
+ import { mapCheckResult } from "./linting/diagnostic-mapper.mjs";
6
+ import "./linting/index.mjs";
7
+ import { selDarkTheme, selLightTheme } from "./editor/theme.mjs";
8
+ import { buildExtensions } from "./editor/editor-config.mjs";
9
+ import { createSELEditor } from "./editor/create-editor.mjs";
10
+ import "./editor/index.mjs";
11
+ export { SchemaCompletionProvider, buildExtensions, createSELEditor, createSELLinter, createSchemaCompletion, createTokenizerConfig, mapCheckResult, selDarkTheme, selLightTheme };