@api-client/ui 0.5.14 → 0.5.16
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/build/src/elements/code-editor/internals/{PlaceholderWidget.d.ts → ChipWidget.d.ts} +1 -1
- package/build/src/elements/code-editor/internals/ChipWidget.d.ts.map +1 -0
- package/build/src/elements/code-editor/internals/{PlaceholderWidget.js → ChipWidget.js} +2 -2
- package/build/src/elements/code-editor/internals/ChipWidget.js.map +1 -0
- package/build/src/elements/code-editor/internals/CodeEditor.d.ts +8 -5
- package/build/src/elements/code-editor/internals/CodeEditor.d.ts.map +1 -1
- package/build/src/elements/code-editor/internals/CodeEditor.js +46 -46
- package/build/src/elements/code-editor/internals/CodeEditor.js.map +1 -1
- package/build/src/elements/code-editor/internals/CodeEditor.styles.d.ts.map +1 -1
- package/build/src/elements/code-editor/internals/CodeEditor.styles.js +55 -0
- package/build/src/elements/code-editor/internals/CodeEditor.styles.js.map +1 -1
- package/build/src/elements/code-editor/internals/SuggestionMatchDecorator.d.ts.map +1 -1
- package/build/src/elements/code-editor/internals/SuggestionMatchDecorator.js +4 -4
- package/build/src/elements/code-editor/internals/SuggestionMatchDecorator.js.map +1 -1
- package/demo/elements/code-editor/CodeEditorDemo.ts +52 -82
- package/package.json +1 -1
- package/src/elements/code-editor/internals/{PlaceholderWidget.ts → ChipWidget.ts} +1 -1
- package/src/elements/code-editor/internals/CodeEditor.styles.ts +55 -0
- package/src/elements/code-editor/internals/CodeEditor.ts +42 -32
- package/src/elements/code-editor/internals/SuggestionMatchDecorator.ts +4 -5
- package/build/src/elements/code-editor/internals/PlaceholderWidget.d.ts.map +0 -1
- package/build/src/elements/code-editor/internals/PlaceholderWidget.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChipWidget.d.ts","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/ChipWidget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,6BAA6B,CAAA;AAEpC;;;;;;;;GAQG;AACH,qBAAa,UAAW,SAAQ,UAAU;IACrB,UAAU,EAAE,UAAU;gBAAtB,UAAU,EAAE,UAAU;IAIhC,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO;IAIvC,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW;IAwB3B,WAAW,IAAI,OAAO;CAGhC"}
|
|
@@ -30,7 +30,7 @@ export class ChipWidget extends WidgetType {
|
|
|
30
30
|
const pos = view.posAtDOM(wrapper);
|
|
31
31
|
if (pos === null)
|
|
32
32
|
return;
|
|
33
|
-
const originalText = `{{${this.suggestion.
|
|
33
|
+
const originalText = `{{${this.suggestion.id}}}`;
|
|
34
34
|
view.dispatch({
|
|
35
35
|
changes: { from: pos, to: pos + originalText.length, insert: '' },
|
|
36
36
|
});
|
|
@@ -43,4 +43,4 @@ export class ChipWidget extends WidgetType {
|
|
|
43
43
|
return false;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
//# sourceMappingURL=
|
|
46
|
+
//# sourceMappingURL=ChipWidget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChipWidget.js","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/ChipWidget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAEzD,OAAO,6BAA6B,CAAA;AAEpC;;;;;;;;GAQG;AACH,MAAM,OAAO,UAAW,SAAQ,UAAU;IACrB;IAAnB,YAAmB,UAAsB;QACvC,KAAK,EAAE,CAAA;QADU,eAAU,GAAV,UAAU,CAAY;IAEzC,CAAC;IAEQ,EAAE,CAAC,KAAiB;QAC3B,OAAO,IAAI,CAAC,UAAU,CAAC,EAAE,IAAK,KAAoB,CAAC,UAAU,CAAC,EAAE,CAAA;IAClE,CAAC;IAED,KAAK,CAAC,IAAgB;QACpB,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;QAC9C,OAAO,CAAC,SAAS,GAAG,cAAc,CAAA;QAClC,OAAO,CAAC,YAAY,CAAC,iBAAiB,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;QAE3D,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,CAAA;QAC9C,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAClC,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;QACtC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAA;QACxC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE;YACnC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;YAClC,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAM;YAExB,MAAM,YAAY,GAAG,KAAK,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,CAAA;YAChD,IAAI,CAAC,QAAQ,CAAC;gBACZ,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;aAClE,CAAC,CAAA;YACF,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC,CAAC,CAAA;QAEF,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;QACzB,OAAO,OAAO,CAAA;IAChB,CAAC;IAEQ,WAAW;QAClB,OAAO,KAAK,CAAA;IACd,CAAC;CACF","sourcesContent":["import { EditorView, WidgetType } from '@codemirror/view'\nimport type { Suggestion } from './types.js'\nimport '../../../md/chip/ui-chip.js'\n\n/**\n * A widget that represents a placeholder in the code editor,\n * specifically for suggestions that are replaced with chips.\n *\n * This widget is used to create a visual representation of a suggestion\n * in the code editor, allowing users to see and interact with suggestions\n * as chips. When a chip is removed, the corresponding text in the editor\n * is also removed.\n */\nexport class ChipWidget extends WidgetType {\n constructor(public suggestion: Suggestion) {\n super()\n }\n\n override eq(other: WidgetType): boolean {\n return this.suggestion.id == (other as ChipWidget).suggestion.id\n }\n\n toDOM(view: EditorView): HTMLElement {\n const wrapper = document.createElement('span')\n wrapper.className = 'mention-chip'\n wrapper.setAttribute('data-mention-id', this.suggestion.id)\n\n const chip = document.createElement('ui-chip')\n chip.setAttribute('type', 'input')\n chip.setAttribute('removable', 'true')\n chip.textContent = this.suggestion.label\n chip.addEventListener('remove', () => {\n const pos = view.posAtDOM(wrapper)\n if (pos === null) return\n\n const originalText = `{{${this.suggestion.id}}}`\n view.dispatch({\n changes: { from: pos, to: pos + originalText.length, insert: '' },\n })\n view.focus()\n })\n\n wrapper.appendChild(chip)\n return wrapper\n }\n\n override ignoreEvent(): boolean {\n return false\n }\n}\n"]}
|
|
@@ -18,6 +18,7 @@ import { SuggestionMatchDecorator } from './SuggestionMatchDecorator.js';
|
|
|
18
18
|
* @fires change - When the editor loses focus and content has changed
|
|
19
19
|
*/
|
|
20
20
|
export default class CodeEditor extends LitElement {
|
|
21
|
+
#private;
|
|
21
22
|
/**
|
|
22
23
|
* Shadow root configuration for the component.
|
|
23
24
|
* Uses 'open' mode for accessibility and delegates focus to enable proper focus management.
|
|
@@ -54,7 +55,8 @@ export default class CodeEditor extends LitElement {
|
|
|
54
55
|
/**
|
|
55
56
|
* The editor content value
|
|
56
57
|
*/
|
|
57
|
-
|
|
58
|
+
get value(): string;
|
|
59
|
+
set value(newValue: string);
|
|
58
60
|
/**
|
|
59
61
|
* Available function schemas for autocomplete
|
|
60
62
|
*/
|
|
@@ -75,6 +77,10 @@ export default class CodeEditor extends LitElement {
|
|
|
75
77
|
private accessor hasContent;
|
|
76
78
|
private accessor isEditorFocus;
|
|
77
79
|
private editorView?;
|
|
80
|
+
/**
|
|
81
|
+
* A control value to track previous value of the editor.
|
|
82
|
+
* This is used to detect when change event should be dispatched.
|
|
83
|
+
*/
|
|
78
84
|
private _previousValue;
|
|
79
85
|
/**
|
|
80
86
|
* Matcher for suggestion placeholders in the editor.
|
|
@@ -84,6 +90,7 @@ export default class CodeEditor extends LitElement {
|
|
|
84
90
|
* Get all suggestions (placeholders) currently in the editor
|
|
85
91
|
*/
|
|
86
92
|
get activeSuggestions(): Suggestion[];
|
|
93
|
+
private readonlyState;
|
|
87
94
|
disconnectedCallback(): void;
|
|
88
95
|
firstUpdated(): void;
|
|
89
96
|
willUpdate(changedProperties: PropertyValues): void;
|
|
@@ -120,10 +127,6 @@ export default class CodeEditor extends LitElement {
|
|
|
120
127
|
* Update editor content when value changes
|
|
121
128
|
*/
|
|
122
129
|
private updateEditorContent;
|
|
123
|
-
/**
|
|
124
|
-
* Update editor state (e.g., disabled state)
|
|
125
|
-
*/
|
|
126
|
-
private updateEditorState;
|
|
127
130
|
/**
|
|
128
131
|
* Handle editor content change
|
|
129
132
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeEditor.d.ts","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/CodeEditor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,cAAc,EAAE,cAAc,EAAW,MAAM,KAAK,CAAA;AA0B/E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAA;AAGrE,OAAO,KAAK,EAAuB,UAAU,EAAyB,MAAM,YAAY,CAAA;AACxF,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAA;AAExE;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,UAAU
|
|
1
|
+
{"version":3,"file":"CodeEditor.d.ts","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/CodeEditor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,cAAc,EAAE,cAAc,EAAW,MAAM,KAAK,CAAA;AA0B/E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAA;AAGrE,OAAO,KAAK,EAAuB,UAAU,EAAyB,MAAM,YAAY,CAAA;AACxF,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAA;AAExE;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,UAAU;;IAChD;;;OAGG;IACH,OAAgB,iBAAiB,EAAE,cAAc,CAGhD;IAED;;OAEG;IAEH,QAAQ,CAAC,KAAK,SAAK;IAEnB;;OAEG;IAEH,QAAQ,CAAC,cAAc,SAAK;IAE5B;;OAEG;IAEH,QAAQ,CAAC,QAAQ,UAAQ;IAEzB;;OAEG;IAEH,QAAQ,CAAC,OAAO,UAAQ;IAExB;;OAEG;IAEH,QAAQ,CAAC,IAAI,SAAK;IAElB;;OAEG;IAEH,QAAQ,CAAC,QAAQ,UAAQ;IAEzB;;OAEG;IAEH,QAAQ,CAAC,WAAW,SAAK;IAOzB;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IACI,KAAK,CAAC,QAAQ,EAAE,MAAM,EAOzB;IAED;;OAEG;IAEH,QAAQ,CAAC,eAAe,EAAE,cAAc,EAAE,CAAK;IAE/C;;OAEG;IAEH,QAAQ,CAAC,WAAW,EAAE,UAAU,EAAE,CAAK;IAEvC;;OAEG;IAEH,QAAQ,CAAC,SAAS,UAAQ;IAE1B;;OAEG;IAEH,QAAQ,CAAC,QAAQ,SAAe;IAGhC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;IAGjD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;IAGnC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAQ;IAEtC,OAAO,CAAC,UAAU,CAAC,CAAY;IAC/B;;;OAGG;IACH,OAAO,CAAC,cAAc,CAAK;IAC3B;;OAEG;IACH,kBAAkB,CAAC,EAAE,wBAAwB,CAAA;IAE7C;;OAEG;IACH,IAAI,iBAAiB,IAAI,UAAU,EAAE,CAapC;IAED,OAAO,CAAC,aAAa,CAAoB;IAEhC,oBAAoB,IAAI,IAAI;IAK5B,YAAY,IAAI,IAAI;IAKpB,UAAU,CAAC,iBAAiB,EAAE,cAAc,GAAG,IAAI;IAoB5D;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqD5B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAoB/B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA0C9B,OAAO,CAAC,wBAAwB;IAmBhC,OAAO,CAAC,0BAA0B;IAmBlC;;;OAGG;IACH,OAAO,CAAC,wBAAwB,CAmB/B;IAED;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAgEjC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAiB1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAe3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IASzB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAQ9B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAQhC;;OAEG;IACM,KAAK,IAAI,IAAI;IAItB;;OAEG;IACH,YAAY,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAMnD;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAUrB,MAAM,IAAI,cAAc;CAgBlC"}
|
|
@@ -3,7 +3,7 @@ import { html, LitElement, nothing } from 'lit';
|
|
|
3
3
|
import { property, query, state } from 'lit/decorators.js';
|
|
4
4
|
import { classMap } from 'lit/directives/class-map.js';
|
|
5
5
|
import { linter } from '@codemirror/lint';
|
|
6
|
-
import { EditorState } from '@codemirror/state';
|
|
6
|
+
import { Compartment, EditorState } from '@codemirror/state';
|
|
7
7
|
import { autocompletion, } from '@codemirror/autocomplete';
|
|
8
8
|
import { javascript } from '@codemirror/lang-javascript';
|
|
9
9
|
import { syntaxHighlighting, defaultHighlightStyle } from '@codemirror/language';
|
|
@@ -16,6 +16,7 @@ import { functionLinter } from './Linter.js';
|
|
|
16
16
|
import { SuggestionMatchDecorator } from './SuggestionMatchDecorator.js';
|
|
17
17
|
let CodeEditor = (() => {
|
|
18
18
|
let _classSuper = LitElement;
|
|
19
|
+
let _instanceExtraInitializers = [];
|
|
19
20
|
let _label_decorators;
|
|
20
21
|
let _label_initializers = [];
|
|
21
22
|
let _label_extraInitializers = [];
|
|
@@ -37,9 +38,7 @@ let CodeEditor = (() => {
|
|
|
37
38
|
let _placeholder_decorators;
|
|
38
39
|
let _placeholder_initializers = [];
|
|
39
40
|
let _placeholder_extraInitializers = [];
|
|
40
|
-
let
|
|
41
|
-
let _value_initializers = [];
|
|
42
|
-
let _value_extraInitializers = [];
|
|
41
|
+
let _set_value_decorators;
|
|
43
42
|
let _functionSchemas_decorators;
|
|
44
43
|
let _functionSchemas_initializers = [];
|
|
45
44
|
let _functionSchemas_extraInitializers = [];
|
|
@@ -71,7 +70,7 @@ let CodeEditor = (() => {
|
|
|
71
70
|
_name_decorators = [property({ type: String })];
|
|
72
71
|
_required_decorators = [property({ type: Boolean })];
|
|
73
72
|
_placeholder_decorators = [property({ type: String })];
|
|
74
|
-
|
|
73
|
+
_set_value_decorators = [property({ type: String })];
|
|
75
74
|
_functionSchemas_decorators = [property({ type: Array, attribute: false })];
|
|
76
75
|
_suggestions_decorators = [property({ type: Array, attribute: false })];
|
|
77
76
|
_darkTheme_decorators = [property({ type: Boolean, attribute: 'dark-theme' })];
|
|
@@ -86,7 +85,7 @@ let CodeEditor = (() => {
|
|
|
86
85
|
__esDecorate(this, null, _name_decorators, { kind: "accessor", name: "name", static: false, private: false, access: { has: obj => "name" in obj, get: obj => obj.name, set: (obj, value) => { obj.name = value; } }, metadata: _metadata }, _name_initializers, _name_extraInitializers);
|
|
87
86
|
__esDecorate(this, null, _required_decorators, { kind: "accessor", name: "required", static: false, private: false, access: { has: obj => "required" in obj, get: obj => obj.required, set: (obj, value) => { obj.required = value; } }, metadata: _metadata }, _required_initializers, _required_extraInitializers);
|
|
88
87
|
__esDecorate(this, null, _placeholder_decorators, { kind: "accessor", name: "placeholder", static: false, private: false, access: { has: obj => "placeholder" in obj, get: obj => obj.placeholder, set: (obj, value) => { obj.placeholder = value; } }, metadata: _metadata }, _placeholder_initializers, _placeholder_extraInitializers);
|
|
89
|
-
__esDecorate(this, null,
|
|
88
|
+
__esDecorate(this, null, _set_value_decorators, { kind: "setter", name: "value", static: false, private: false, access: { has: obj => "value" in obj, set: (obj, value) => { obj.value = value; } }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
90
89
|
__esDecorate(this, null, _functionSchemas_decorators, { kind: "accessor", name: "functionSchemas", static: false, private: false, access: { has: obj => "functionSchemas" in obj, get: obj => obj.functionSchemas, set: (obj, value) => { obj.functionSchemas = value; } }, metadata: _metadata }, _functionSchemas_initializers, _functionSchemas_extraInitializers);
|
|
91
90
|
__esDecorate(this, null, _suggestions_decorators, { kind: "accessor", name: "suggestions", static: false, private: false, access: { has: obj => "suggestions" in obj, get: obj => obj.suggestions, set: (obj, value) => { obj.suggestions = value; } }, metadata: _metadata }, _suggestions_initializers, _suggestions_extraInitializers);
|
|
92
91
|
__esDecorate(this, null, _darkTheme_decorators, { kind: "accessor", name: "darkTheme", static: false, private: false, access: { has: obj => "darkTheme" in obj, get: obj => obj.darkTheme, set: (obj, value) => { obj.darkTheme = value; } }, metadata: _metadata }, _darkTheme_initializers, _darkTheme_extraInitializers);
|
|
@@ -104,11 +103,11 @@ let CodeEditor = (() => {
|
|
|
104
103
|
mode: 'open',
|
|
105
104
|
delegatesFocus: true,
|
|
106
105
|
};
|
|
107
|
-
#label_accessor_storage = __runInitializers(this, _label_initializers, ''
|
|
106
|
+
#label_accessor_storage = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _label_initializers, ''
|
|
108
107
|
/**
|
|
109
108
|
* Supporting text displayed below the editor
|
|
110
109
|
*/
|
|
111
|
-
);
|
|
110
|
+
));
|
|
112
111
|
/**
|
|
113
112
|
* The label text displayed as placeholder/floating label
|
|
114
113
|
*/
|
|
@@ -166,7 +165,7 @@ let CodeEditor = (() => {
|
|
|
166
165
|
set required(value) { this.#required_accessor_storage = value; }
|
|
167
166
|
#placeholder_accessor_storage = (__runInitializers(this, _required_extraInitializers), __runInitializers(this, _placeholder_initializers, ''
|
|
168
167
|
/**
|
|
169
|
-
*
|
|
168
|
+
* This property is used internally to set value without triggering updates.
|
|
170
169
|
*/
|
|
171
170
|
));
|
|
172
171
|
/**
|
|
@@ -174,21 +173,29 @@ let CodeEditor = (() => {
|
|
|
174
173
|
*/
|
|
175
174
|
get placeholder() { return this.#placeholder_accessor_storage; }
|
|
176
175
|
set placeholder(value) { this.#placeholder_accessor_storage = value; }
|
|
177
|
-
#value_accessor_storage = (__runInitializers(this, _placeholder_extraInitializers), __runInitializers(this, _value_initializers, ''
|
|
178
176
|
/**
|
|
179
|
-
*
|
|
177
|
+
* This property is used internally to set value without triggering updates.
|
|
180
178
|
*/
|
|
181
|
-
));
|
|
179
|
+
#value = (__runInitializers(this, _placeholder_extraInitializers), '');
|
|
182
180
|
/**
|
|
183
181
|
* The editor content value
|
|
184
182
|
*/
|
|
185
|
-
get value() {
|
|
186
|
-
|
|
187
|
-
|
|
183
|
+
get value() {
|
|
184
|
+
return this.#value;
|
|
185
|
+
}
|
|
186
|
+
set value(newValue) {
|
|
187
|
+
const oldValue = this.#value;
|
|
188
|
+
if (newValue !== oldValue) {
|
|
189
|
+
this.#value = newValue;
|
|
190
|
+
this._previousValue = newValue;
|
|
191
|
+
this.requestUpdate('value', oldValue);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
#functionSchemas_accessor_storage = __runInitializers(this, _functionSchemas_initializers, []
|
|
188
195
|
/**
|
|
189
196
|
* Available suggestions for autocomplete
|
|
190
197
|
*/
|
|
191
|
-
)
|
|
198
|
+
);
|
|
192
199
|
/**
|
|
193
200
|
* Available function schemas for autocomplete
|
|
194
201
|
*/
|
|
@@ -230,6 +237,10 @@ let CodeEditor = (() => {
|
|
|
230
237
|
get isEditorFocus() { return this.#isEditorFocus_accessor_storage; }
|
|
231
238
|
set isEditorFocus(value) { this.#isEditorFocus_accessor_storage = value; }
|
|
232
239
|
editorView = __runInitializers(this, _isEditorFocus_extraInitializers);
|
|
240
|
+
/**
|
|
241
|
+
* A control value to track previous value of the editor.
|
|
242
|
+
* This is used to detect when change event should be dispatched.
|
|
243
|
+
*/
|
|
233
244
|
_previousValue = '';
|
|
234
245
|
/**
|
|
235
246
|
* Matcher for suggestion placeholders in the editor.
|
|
@@ -240,18 +251,19 @@ let CodeEditor = (() => {
|
|
|
240
251
|
*/
|
|
241
252
|
get activeSuggestions() {
|
|
242
253
|
const suggestions = [];
|
|
243
|
-
const placeholderPattern = /\{\{(
|
|
254
|
+
const placeholderPattern = /\{\{([^}]+)\}\}/g;
|
|
244
255
|
let match;
|
|
245
256
|
while ((match = placeholderPattern.exec(this.value)) !== null) {
|
|
246
257
|
const placeholderText = match[1];
|
|
247
|
-
// Find suggestion by
|
|
248
|
-
const suggestion = this.suggestions.find((s) => s.
|
|
258
|
+
// Find suggestion by id
|
|
259
|
+
const suggestion = this.suggestions.find((s) => s.id === placeholderText);
|
|
249
260
|
if (suggestion) {
|
|
250
261
|
suggestions.push(suggestion);
|
|
251
262
|
}
|
|
252
263
|
}
|
|
253
264
|
return suggestions;
|
|
254
265
|
}
|
|
266
|
+
readonlyState = new Compartment();
|
|
255
267
|
disconnectedCallback() {
|
|
256
268
|
super.disconnectedCallback();
|
|
257
269
|
this.editorView?.destroy();
|
|
@@ -271,7 +283,9 @@ let CodeEditor = (() => {
|
|
|
271
283
|
this.updateEditorContent();
|
|
272
284
|
}
|
|
273
285
|
if (changedProperties.has('disabled')) {
|
|
274
|
-
this.
|
|
286
|
+
this.editorView?.dispatch({
|
|
287
|
+
effects: this.readonlyState.reconfigure(EditorState.readOnly.of(this.disabled)),
|
|
288
|
+
});
|
|
275
289
|
}
|
|
276
290
|
}
|
|
277
291
|
/**
|
|
@@ -297,6 +311,7 @@ let CodeEditor = (() => {
|
|
|
297
311
|
this.createPlaceholderPlugin(),
|
|
298
312
|
hoverTooltip(this.createHoverTooltipSource),
|
|
299
313
|
linter((view) => functionLinter(view, this.functionSchemas, (e) => this.dispatchEvent(e))),
|
|
314
|
+
this.readonlyState.of(EditorState.readOnly.of(this.disabled)),
|
|
300
315
|
];
|
|
301
316
|
// Add language support
|
|
302
317
|
if (this.language === 'javascript') {
|
|
@@ -326,7 +341,7 @@ let CodeEditor = (() => {
|
|
|
326
341
|
* This is created as a method to get access to the component's `suggestions`.
|
|
327
342
|
*/
|
|
328
343
|
createPlaceholderPlugin() {
|
|
329
|
-
const placeholderMatcher = new SuggestionMatchDecorator(/\{\{(
|
|
344
|
+
const placeholderMatcher = new SuggestionMatchDecorator(/\{\{([^}]+)\}\}/g, this.suggestions);
|
|
330
345
|
this.placeholderMatcher = placeholderMatcher;
|
|
331
346
|
// This class needs to be defined here to have access to the `placeholderMatcher`
|
|
332
347
|
class AtomicDecorationRange {
|
|
@@ -366,7 +381,7 @@ let CodeEditor = (() => {
|
|
|
366
381
|
}
|
|
367
382
|
}
|
|
368
383
|
// Check if we're typing a suggestion trigger (e.g., {{)
|
|
369
|
-
const suggestionMatch = textBefore.match(/\{\{(
|
|
384
|
+
const suggestionMatch = textBefore.match(/\{\{([^}]*)$/);
|
|
370
385
|
if (suggestionMatch) {
|
|
371
386
|
const prefix = suggestionMatch[1];
|
|
372
387
|
const suggestions = this.suggestions
|
|
@@ -386,6 +401,7 @@ let CodeEditor = (() => {
|
|
|
386
401
|
const result = {
|
|
387
402
|
label: schema.name,
|
|
388
403
|
detail: schema.description || '',
|
|
404
|
+
type: 'function',
|
|
389
405
|
info: () => this.createFunctionInfoElement(schema),
|
|
390
406
|
apply: (view, completion, from, to) => {
|
|
391
407
|
const functionCall = this.formatFunctionCall(schema);
|
|
@@ -403,8 +419,9 @@ let CodeEditor = (() => {
|
|
|
403
419
|
label: suggestion.label,
|
|
404
420
|
detail: suggestion.description || '',
|
|
405
421
|
info: suggestion.suffix || '',
|
|
422
|
+
type: 'variable',
|
|
406
423
|
apply: (view, completion, from, to) => {
|
|
407
|
-
const placeholderText = `{{${suggestion.
|
|
424
|
+
const placeholderText = `{{${suggestion.id}}}`;
|
|
408
425
|
view.dispatch({
|
|
409
426
|
changes: { from: from - 2, to, insert: placeholderText }, // -2 to include the {{
|
|
410
427
|
selection: { anchor: from - 2 + placeholderText.length },
|
|
@@ -524,21 +541,6 @@ let CodeEditor = (() => {
|
|
|
524
541
|
});
|
|
525
542
|
}
|
|
526
543
|
}
|
|
527
|
-
/**
|
|
528
|
-
* Update editor state (e.g., disabled state)
|
|
529
|
-
*/
|
|
530
|
-
updateEditorState() {
|
|
531
|
-
if (!this.editorView)
|
|
532
|
-
return;
|
|
533
|
-
// For now, we'll handle disabled state differently
|
|
534
|
-
// CodeMirror 6 doesn't use reconfigure for editable
|
|
535
|
-
if (this.disabled) {
|
|
536
|
-
this.editorView.contentDOM.setAttribute('contenteditable', 'false');
|
|
537
|
-
}
|
|
538
|
-
else {
|
|
539
|
-
this.editorView.contentDOM.setAttribute('contenteditable', 'true');
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
544
|
/**
|
|
543
545
|
* Handle editor content change
|
|
544
546
|
*/
|
|
@@ -546,20 +548,18 @@ let CodeEditor = (() => {
|
|
|
546
548
|
if (!this.editorView)
|
|
547
549
|
return;
|
|
548
550
|
const newValue = this.editorView.state.doc.toString();
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
this.hasContent = newValue.length > 0;
|
|
553
|
-
this.dispatchEvent(new Event('input', { bubbles: true }));
|
|
554
|
-
}
|
|
551
|
+
this.#value = newValue;
|
|
552
|
+
this.hasContent = newValue.length > 0;
|
|
553
|
+
this.dispatchEvent(new Event('input', { bubbles: true }));
|
|
555
554
|
}
|
|
556
555
|
/**
|
|
557
556
|
* Handle focus change
|
|
558
557
|
*/
|
|
559
558
|
handleFocusChange(hasFocus) {
|
|
560
559
|
this.isEditorFocus = hasFocus;
|
|
561
|
-
if (!hasFocus && this
|
|
562
|
-
this.
|
|
560
|
+
if (!hasFocus && this.#value !== this._previousValue) {
|
|
561
|
+
this._previousValue = this.#value;
|
|
562
|
+
this.dispatchEvent(new Event('change'));
|
|
563
563
|
}
|
|
564
564
|
}
|
|
565
565
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeEditor.js","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/CodeEditor.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, PropertyValues, TemplateResult, nothing } from 'lit'\nimport { property, query, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { linter } from '@codemirror/lint'\nimport { EditorState, Extension } from '@codemirror/state'\nimport {\n autocompletion,\n CompletionContext,\n type CompletionResult,\n type CompletionSource,\n type Completion,\n} from '@codemirror/autocomplete'\nimport { javascript } from '@codemirror/lang-javascript'\nimport { syntaxHighlighting, defaultHighlightStyle } from '@codemirror/language'\nimport { oneDark } from '@codemirror/theme-one-dark'\nimport { keymap } from '@codemirror/view'\nimport { defaultKeymap } from '@codemirror/commands'\nimport {\n EditorView,\n Decoration,\n DecorationSet,\n ViewPlugin,\n ViewUpdate,\n hoverTooltip,\n type Tooltip,\n} from '@codemirror/view'\nimport type { FunctionSchema } from '@pawel-up/jexl/schemas/types.js'\nimport { getTypeStringFromSchema } from '@pawel-up/jexl/schemas/utils.js'\nimport { functionLinter } from './Linter.js'\nimport type { FunctionInsertEvent, Suggestion, SuggestionInsertEvent } from './types.js'\nimport { SuggestionMatchDecorator } from './SuggestionMatchDecorator.js'\n\n/**\n * A CodeMirror 6 based editor component that supports function autocomplete and suggestion placeholders.\n *\n * Features:\n * - Dynamic function schema loading\n * - Autocomplete for functions and suggestions\n * - Suggestion placeholders with double curly braces ({{suggestion}})\n * - Keyboard navigation\n * - Accessibility support\n *\n * @fires function-insert - When a function is inserted\n * @fires suggestion-insert - When a suggestion is inserted\n * @fires input - When the editor content changes\n * @fires change - When the editor loses focus and content has changed\n */\nexport default class CodeEditor extends LitElement {\n /**\n * Shadow root configuration for the component.\n * Uses 'open' mode for accessibility and delegates focus to enable proper focus management.\n */\n static override shadowRootOptions: ShadowRootInit = {\n mode: 'open',\n delegatesFocus: true,\n }\n\n /**\n * The label text displayed as placeholder/floating label\n */\n @property({ type: String })\n accessor label = ''\n\n /**\n * Supporting text displayed below the editor\n */\n @property({ type: String, attribute: 'supporting-text' })\n accessor supportingText = ''\n\n /**\n * Whether the component is disabled\n */\n @property({ type: Boolean, reflect: true })\n accessor disabled = false\n\n /**\n * Whether the component is in an invalid state\n */\n @property({ type: Boolean, reflect: true })\n accessor invalid = false\n\n /**\n * The name attribute for form integration\n */\n @property({ type: String })\n accessor name = ''\n\n /**\n * Whether the input is required\n */\n @property({ type: Boolean })\n accessor required = false\n\n /**\n * Placeholder text shown when editor is empty\n */\n @property({ type: String })\n accessor placeholder = ''\n\n /**\n * The editor content value\n */\n @property({ type: String })\n accessor value = ''\n\n /**\n * Available function schemas for autocomplete\n */\n @property({ type: Array, attribute: false })\n accessor functionSchemas: FunctionSchema[] = []\n\n /**\n * Available suggestions for autocomplete\n */\n @property({ type: Array, attribute: false })\n accessor suggestions: Suggestion[] = []\n\n /**\n * Whether to use dark theme\n */\n @property({ type: Boolean, attribute: 'dark-theme' })\n accessor darkTheme = false\n\n /**\n * Programming language for syntax highlighting\n */\n @property({ type: String })\n accessor language = 'javascript'\n\n @query('.editor-container')\n private accessor editorContainer!: HTMLDivElement\n\n @state()\n private accessor hasContent = false\n\n @state()\n private accessor isEditorFocus = false\n\n private editorView?: EditorView\n private _previousValue = ''\n /**\n * Matcher for suggestion placeholders in the editor.\n */\n placeholderMatcher?: SuggestionMatchDecorator\n\n /**\n * Get all suggestions (placeholders) currently in the editor\n */\n get activeSuggestions(): Suggestion[] {\n const suggestions: Suggestion[] = []\n const placeholderPattern = /\\{\\{(\\w+)\\}\\}/g\n let match: RegExpExecArray | null\n while ((match = placeholderPattern.exec(this.value)) !== null) {\n const placeholderText = match[1]\n // Find suggestion by label\n const suggestion = this.suggestions.find((s) => s.label.toLowerCase() === placeholderText.toLowerCase())\n if (suggestion) {\n suggestions.push(suggestion)\n }\n }\n return suggestions\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n this.editorView?.destroy()\n }\n\n override firstUpdated(): void {\n this.initializeCodeMirror()\n this.updateEditorContent()\n }\n\n override willUpdate(changedProperties: PropertyValues): void {\n super.willUpdate(changedProperties)\n\n if (changedProperties.has('suggestions')) {\n if (this.placeholderMatcher) {\n this.placeholderMatcher.suggestions = this.suggestions || []\n }\n }\n\n if (changedProperties.has('value') && this.editorView) {\n this.updateEditorContent()\n }\n\n if (changedProperties.has('disabled')) {\n this.updateEditorState()\n }\n }\n\n /**\n * Initialize CodeMirror editor with extensions\n */\n private initializeCodeMirror(): void {\n const extensions: Extension[] = [\n keymap.of(defaultKeymap),\n syntaxHighlighting(defaultHighlightStyle),\n autocompletion({\n override: [this.createCompletionSource()],\n activateOnTyping: true,\n maxRenderedOptions: 10,\n }),\n EditorView.updateListener.of((update: ViewUpdate) => {\n if (update.docChanged) {\n this.handleEditorChange()\n }\n if (update.focusChanged) {\n this.handleFocusChange(update.view.hasFocus)\n }\n }),\n this.createPlaceholderPlugin(),\n hoverTooltip(this.createHoverTooltipSource),\n linter((view) => functionLinter(view, this.functionSchemas, (e) => this.dispatchEvent(e))),\n ]\n\n // Add language support\n if (this.language === 'javascript') {\n extensions.push(javascript())\n }\n\n // Add theme\n if (this.darkTheme) {\n extensions.push(oneDark)\n }\n\n // Add placeholder\n if (this.placeholder) {\n extensions.push(\n EditorView.contentAttributes.of({\n 'aria-placeholder': this.placeholder,\n })\n )\n }\n\n const state = EditorState.create({\n doc: this.value,\n extensions,\n })\n\n this.editorView = new EditorView({\n state,\n parent: this.editorContainer,\n })\n }\n\n /**\n * Creates the ViewPlugin for rendering suggestion placeholders.\n * This is created as a method to get access to the component's `suggestions`.\n */\n private createPlaceholderPlugin(): Extension {\n const placeholderMatcher = new SuggestionMatchDecorator(/\\{\\{(\\w+)\\}\\}/g, this.suggestions)\n this.placeholderMatcher = placeholderMatcher\n // This class needs to be defined here to have access to the `placeholderMatcher`\n class AtomicDecorationRange {\n placeholders: DecorationSet\n constructor(view: EditorView) {\n this.placeholders = placeholderMatcher.createDeco(view)\n }\n update(update: ViewUpdate) {\n this.placeholders = placeholderMatcher.updateDeco(update, this.placeholders)\n }\n }\n\n return ViewPlugin.fromClass(AtomicDecorationRange, {\n decorations: (instance) => instance.placeholders,\n provide: (plugin) => EditorView.atomicRanges.of((view) => view.plugin(plugin)?.placeholders || Decoration.none),\n })\n }\n\n /**\n * Create completion source for functions and suggestions\n */\n private createCompletionSource(): CompletionSource {\n return (context: CompletionContext): CompletionResult | null => {\n const { pos } = context\n const line = context.state.doc.lineAt(pos)\n const textBefore = line.text.slice(0, pos - line.from)\n\n // Check if we're typing a function name\n const functionMatch = textBefore.match(/(\\w+)$/)\n if (functionMatch) {\n const prefix = functionMatch[1]\n const functions = this.functionSchemas\n .filter((fn) => fn.name.toLowerCase().startsWith(prefix.toLowerCase()))\n .map((fn) => this.createFunctionCompletion(fn))\n\n if (functions.length > 0) {\n return {\n from: pos - prefix.length,\n options: functions,\n }\n }\n }\n\n // Check if we're typing a suggestion trigger (e.g., {{)\n const suggestionMatch = textBefore.match(/\\{\\{(\\w*)$/)\n if (suggestionMatch) {\n const prefix = suggestionMatch[1]\n const suggestions = this.suggestions\n .filter((suggestion) => suggestion.label.toLowerCase().startsWith(prefix.toLowerCase()))\n .map((suggestion) => this.createSuggestionCompletion(suggestion))\n\n if (suggestions.length > 0) {\n return {\n from: pos - prefix.length,\n options: suggestions,\n }\n }\n }\n\n return null\n }\n }\n\n private createFunctionCompletion(schema: FunctionSchema): Completion {\n const result: Completion = {\n label: schema.name,\n detail: schema.description || '',\n info: () => this.createFunctionInfoElement(schema),\n apply: (view: EditorView, completion: unknown, from: number, to: number) => {\n const functionCall = this.formatFunctionCall(schema)\n view.dispatch({\n changes: { from, to, insert: functionCall },\n selection: { anchor: from + functionCall.length },\n })\n this.dispatchFunctionInsert(schema, from)\n },\n }\n\n return result\n }\n\n private createSuggestionCompletion(suggestion: Suggestion): Completion {\n const result: Completion = {\n label: suggestion.label,\n detail: suggestion.description || '',\n info: suggestion.suffix || '',\n apply: (view: EditorView, completion: unknown, from: number, to: number) => {\n const placeholderText = `{{${suggestion.label}}}`\n view.dispatch({\n changes: { from: from - 2, to, insert: placeholderText }, // -2 to include the {{\n selection: { anchor: from - 2 + placeholderText.length },\n })\n this.dispatchSuggestionInsert(suggestion, from - 2)\n },\n }\n\n return result\n }\n\n /**\n * Creates the source for the hover tooltips.\n * This is an arrow function to automatically bind `this`.\n */\n private createHoverTooltipSource = (view: EditorView, pos: number): Tooltip | null => {\n const word = view.state.wordAt(pos)\n if (!word) {\n return null\n }\n\n const functionName = view.state.doc.sliceString(word.from, word.to)\n const fnSchema = this.functionSchemas.find((schema) => schema.name === functionName)\n\n if (!fnSchema) {\n return null\n }\n\n return {\n pos: word.from,\n end: word.to,\n above: true,\n create: () => ({ dom: this.createFunctionInfoElement(fnSchema) }),\n }\n }\n\n /**\n * Creates a styled HTML element to display function documentation.\n * This is used for both hover tooltips and autocomplete info panels.\n */\n private createFunctionInfoElement(fn: FunctionSchema): HTMLElement {\n const container = document.createElement('div')\n container.className = 'function-info' // for styling\n\n if (fn.description) {\n const description = document.createElement('p')\n description.className = 'description'\n description.textContent = fn.description\n container.appendChild(description)\n }\n\n if (fn.parameters && fn.parameters.length > 0) {\n const paramsContainer = document.createElement('div')\n paramsContainer.className = 'parameters'\n\n const paramsHeader = document.createElement('h4')\n paramsHeader.textContent = 'Parameters'\n paramsContainer.appendChild(paramsHeader)\n\n const paramsList = document.createElement('ul')\n fn.parameters.forEach((param) => {\n const listItem = document.createElement('li')\n\n const name = document.createElement('span')\n name.className = 'param-name'\n name.textContent = param.name\n\n const type = document.createElement('span')\n type.className = 'param-type'\n type.textContent = `: ${getTypeStringFromSchema(param.schema)}`\n\n listItem.appendChild(name)\n listItem.appendChild(type)\n\n if (param.schema.description) {\n const paramDesc = document.createElement('p')\n paramDesc.className = 'param-description'\n paramDesc.textContent = param.schema.description\n listItem.appendChild(paramDesc)\n }\n paramsList.appendChild(listItem)\n })\n paramsContainer.appendChild(paramsList)\n container.appendChild(paramsContainer)\n }\n\n if (fn.returns) {\n const returnsContainer = document.createElement('div')\n returnsContainer.className = 'returns'\n\n const returnsHeader = document.createElement('h4')\n returnsHeader.textContent = 'Returns'\n returnsContainer.appendChild(returnsHeader)\n\n const returnsDesc = document.createElement('p')\n const returnType = getTypeStringFromSchema(fn.returns)\n returnsDesc.textContent = fn.returns.description ? `${returnType}: ${fn.returns.description}` : returnType\n returnsContainer.appendChild(returnsDesc)\n container.appendChild(returnsContainer)\n }\n\n return container\n }\n\n /**\n * Format function call with parameters\n */\n private formatFunctionCall(fn: FunctionSchema): string {\n if (!fn.parameters || fn.parameters.length === 0) {\n return `${fn.name}()`\n }\n\n const params = fn.parameters\n .map((param) => {\n if (param.required) {\n return param.name\n }\n return `${param.name}?`\n })\n .join(', ')\n\n return `${fn.name}(${params})`\n }\n\n /**\n * Update editor content when value changes\n */\n private updateEditorContent(): void {\n if (!this.editorView) return\n\n const currentValue = this.editorView.state.doc.toString()\n if (currentValue !== this.value) {\n this.editorView.dispatch({\n changes: {\n from: 0,\n to: this.editorView.state.doc.length,\n insert: this.value,\n },\n })\n }\n }\n\n /**\n * Update editor state (e.g., disabled state)\n */\n private updateEditorState(): void {\n if (!this.editorView) return\n\n // For now, we'll handle disabled state differently\n // CodeMirror 6 doesn't use reconfigure for editable\n if (this.disabled) {\n this.editorView.contentDOM.setAttribute('contenteditable', 'false')\n } else {\n this.editorView.contentDOM.setAttribute('contenteditable', 'true')\n }\n }\n\n /**\n * Handle editor content change\n */\n private handleEditorChange(): void {\n if (!this.editorView) return\n\n const newValue = this.editorView.state.doc.toString()\n if (newValue !== this._previousValue) {\n this._previousValue = newValue\n this.value = newValue\n this.hasContent = newValue.length > 0\n\n this.dispatchEvent(new Event('input', { bubbles: true }))\n }\n }\n\n /**\n * Handle focus change\n */\n private handleFocusChange(hasFocus: boolean): void {\n this.isEditorFocus = hasFocus\n\n if (!hasFocus && this.value !== this._previousValue) {\n this.dispatchEvent(new Event('change', { bubbles: true }))\n }\n }\n\n /**\n * Dispatch function insert event\n */\n private dispatchFunctionInsert(functionSchema: FunctionSchema, position: number): void {\n const event = new CustomEvent<FunctionInsertEvent>('function-insert', {\n detail: { functionSchema, position },\n bubbles: true,\n })\n this.dispatchEvent(event)\n }\n\n /**\n * Dispatch suggestion insert event\n */\n private dispatchSuggestionInsert(suggestion: Suggestion, position: number): void {\n const event = new CustomEvent<SuggestionInsertEvent>('suggestion-insert', {\n detail: { suggestion, position },\n bubbles: true,\n })\n this.dispatchEvent(event)\n }\n\n /**\n * Focus the editor\n */\n override focus(): void {\n this.editorView?.focus()\n }\n\n /**\n * Get the editor's current selection\n */\n getSelection(): { from: number; to: number } | null {\n if (!this.editorView) return null\n const { from, to } = this.editorView.state.selection.main\n return { from, to }\n }\n\n /**\n * Insert text at the current cursor position\n */\n insertText(text: string): void {\n if (!this.editorView) return\n\n const { from, to } = this.editorView.state.selection.main\n this.editorView.dispatch({\n changes: { from, to, insert: text },\n selection: { anchor: from + text.length },\n })\n }\n\n override render(): TemplateResult {\n const hasLabel = !!this.label\n const hasSupportingText = !!this.supportingText\n\n return html`\n <div class=\"surface ${classMap({ 'has-focus': this.isEditorFocus, 'invalid': this.invalid })}\">\n <div class=\"content\">\n ${hasLabel ? html`<div class=\"label\">${this.label}</div>` : nothing}\n\n <div class=\"editor-container\" part=\"editor\"></div>\n </div>\n\n ${hasSupportingText ? html`<div class=\"supporting-text\">${this.supportingText}</div>` : nothing}\n </div>\n `\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"CodeEditor.js","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/CodeEditor.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, PropertyValues, TemplateResult, nothing } from 'lit'\nimport { property, query, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { linter } from '@codemirror/lint'\nimport { Compartment, EditorState, Extension } from '@codemirror/state'\nimport {\n autocompletion,\n CompletionContext,\n type CompletionResult,\n type CompletionSource,\n type Completion,\n} from '@codemirror/autocomplete'\nimport { javascript } from '@codemirror/lang-javascript'\nimport { syntaxHighlighting, defaultHighlightStyle } from '@codemirror/language'\nimport { oneDark } from '@codemirror/theme-one-dark'\nimport { keymap } from '@codemirror/view'\nimport { defaultKeymap } from '@codemirror/commands'\nimport {\n EditorView,\n Decoration,\n DecorationSet,\n ViewPlugin,\n ViewUpdate,\n hoverTooltip,\n type Tooltip,\n} from '@codemirror/view'\nimport type { FunctionSchema } from '@pawel-up/jexl/schemas/types.js'\nimport { getTypeStringFromSchema } from '@pawel-up/jexl/schemas/utils.js'\nimport { functionLinter } from './Linter.js'\nimport type { FunctionInsertEvent, Suggestion, SuggestionInsertEvent } from './types.js'\nimport { SuggestionMatchDecorator } from './SuggestionMatchDecorator.js'\n\n/**\n * A CodeMirror 6 based editor component that supports function autocomplete and suggestion placeholders.\n *\n * Features:\n * - Dynamic function schema loading\n * - Autocomplete for functions and suggestions\n * - Suggestion placeholders with double curly braces ({{suggestion}})\n * - Keyboard navigation\n * - Accessibility support\n *\n * @fires function-insert - When a function is inserted\n * @fires suggestion-insert - When a suggestion is inserted\n * @fires input - When the editor content changes\n * @fires change - When the editor loses focus and content has changed\n */\nexport default class CodeEditor extends LitElement {\n /**\n * Shadow root configuration for the component.\n * Uses 'open' mode for accessibility and delegates focus to enable proper focus management.\n */\n static override shadowRootOptions: ShadowRootInit = {\n mode: 'open',\n delegatesFocus: true,\n }\n\n /**\n * The label text displayed as placeholder/floating label\n */\n @property({ type: String })\n accessor label = ''\n\n /**\n * Supporting text displayed below the editor\n */\n @property({ type: String, attribute: 'supporting-text' })\n accessor supportingText = ''\n\n /**\n * Whether the component is disabled\n */\n @property({ type: Boolean, reflect: true })\n accessor disabled = false\n\n /**\n * Whether the component is in an invalid state\n */\n @property({ type: Boolean, reflect: true })\n accessor invalid = false\n\n /**\n * The name attribute for form integration\n */\n @property({ type: String })\n accessor name = ''\n\n /**\n * Whether the input is required\n */\n @property({ type: Boolean })\n accessor required = false\n\n /**\n * Placeholder text shown when editor is empty\n */\n @property({ type: String })\n accessor placeholder = ''\n\n /**\n * This property is used internally to set value without triggering updates.\n */\n #value = ''\n\n /**\n * The editor content value\n */\n get value(): string {\n return this.#value\n }\n\n @property({ type: String })\n set value(newValue: string) {\n const oldValue = this.#value\n if (newValue !== oldValue) {\n this.#value = newValue\n this._previousValue = newValue\n this.requestUpdate('value', oldValue)\n }\n }\n\n /**\n * Available function schemas for autocomplete\n */\n @property({ type: Array, attribute: false })\n accessor functionSchemas: FunctionSchema[] = []\n\n /**\n * Available suggestions for autocomplete\n */\n @property({ type: Array, attribute: false })\n accessor suggestions: Suggestion[] = []\n\n /**\n * Whether to use dark theme\n */\n @property({ type: Boolean, attribute: 'dark-theme' })\n accessor darkTheme = false\n\n /**\n * Programming language for syntax highlighting\n */\n @property({ type: String })\n accessor language = 'javascript'\n\n @query('.editor-container')\n private accessor editorContainer!: HTMLDivElement\n\n @state()\n private accessor hasContent = false\n\n @state()\n private accessor isEditorFocus = false\n\n private editorView?: EditorView\n /**\n * A control value to track previous value of the editor.\n * This is used to detect when change event should be dispatched.\n */\n private _previousValue = ''\n /**\n * Matcher for suggestion placeholders in the editor.\n */\n placeholderMatcher?: SuggestionMatchDecorator\n\n /**\n * Get all suggestions (placeholders) currently in the editor\n */\n get activeSuggestions(): Suggestion[] {\n const suggestions: Suggestion[] = []\n const placeholderPattern = /\\{\\{([^}]+)\\}\\}/g\n let match: RegExpExecArray | null\n while ((match = placeholderPattern.exec(this.value)) !== null) {\n const placeholderText = match[1]\n // Find suggestion by id\n const suggestion = this.suggestions.find((s) => s.id === placeholderText)\n if (suggestion) {\n suggestions.push(suggestion)\n }\n }\n return suggestions\n }\n\n private readonlyState = new Compartment()\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n this.editorView?.destroy()\n }\n\n override firstUpdated(): void {\n this.initializeCodeMirror()\n this.updateEditorContent()\n }\n\n override willUpdate(changedProperties: PropertyValues): void {\n super.willUpdate(changedProperties)\n\n if (changedProperties.has('suggestions')) {\n if (this.placeholderMatcher) {\n this.placeholderMatcher.suggestions = this.suggestions || []\n }\n }\n\n if (changedProperties.has('value') && this.editorView) {\n this.updateEditorContent()\n }\n\n if (changedProperties.has('disabled')) {\n this.editorView?.dispatch({\n effects: this.readonlyState.reconfigure(EditorState.readOnly.of(this.disabled)),\n })\n }\n }\n\n /**\n * Initialize CodeMirror editor with extensions\n */\n private initializeCodeMirror(): void {\n const extensions: Extension[] = [\n keymap.of(defaultKeymap),\n syntaxHighlighting(defaultHighlightStyle),\n autocompletion({\n override: [this.createCompletionSource()],\n activateOnTyping: true,\n maxRenderedOptions: 10,\n }),\n EditorView.updateListener.of((update: ViewUpdate) => {\n if (update.docChanged) {\n this.handleEditorChange()\n }\n if (update.focusChanged) {\n this.handleFocusChange(update.view.hasFocus)\n }\n }),\n this.createPlaceholderPlugin(),\n hoverTooltip(this.createHoverTooltipSource),\n linter((view) => functionLinter(view, this.functionSchemas, (e) => this.dispatchEvent(e))),\n this.readonlyState.of(EditorState.readOnly.of(this.disabled)),\n ]\n\n // Add language support\n if (this.language === 'javascript') {\n extensions.push(javascript())\n }\n\n // Add theme\n if (this.darkTheme) {\n extensions.push(oneDark)\n }\n\n // Add placeholder\n if (this.placeholder) {\n extensions.push(\n EditorView.contentAttributes.of({\n 'aria-placeholder': this.placeholder,\n })\n )\n }\n\n const state = EditorState.create({\n doc: this.value,\n extensions,\n })\n\n this.editorView = new EditorView({\n state,\n parent: this.editorContainer,\n })\n }\n\n /**\n * Creates the ViewPlugin for rendering suggestion placeholders.\n * This is created as a method to get access to the component's `suggestions`.\n */\n private createPlaceholderPlugin(): Extension {\n const placeholderMatcher = new SuggestionMatchDecorator(/\\{\\{([^}]+)\\}\\}/g, this.suggestions)\n this.placeholderMatcher = placeholderMatcher\n // This class needs to be defined here to have access to the `placeholderMatcher`\n class AtomicDecorationRange {\n placeholders: DecorationSet\n constructor(view: EditorView) {\n this.placeholders = placeholderMatcher.createDeco(view)\n }\n update(update: ViewUpdate) {\n this.placeholders = placeholderMatcher.updateDeco(update, this.placeholders)\n }\n }\n\n return ViewPlugin.fromClass(AtomicDecorationRange, {\n decorations: (instance) => instance.placeholders,\n provide: (plugin) => EditorView.atomicRanges.of((view) => view.plugin(plugin)?.placeholders || Decoration.none),\n })\n }\n\n /**\n * Create completion source for functions and suggestions\n */\n private createCompletionSource(): CompletionSource {\n return (context: CompletionContext): CompletionResult | null => {\n const { pos } = context\n const line = context.state.doc.lineAt(pos)\n const textBefore = line.text.slice(0, pos - line.from)\n\n // Check if we're typing a function name\n const functionMatch = textBefore.match(/(\\w+)$/)\n if (functionMatch) {\n const prefix = functionMatch[1]\n const functions = this.functionSchemas\n .filter((fn) => fn.name.toLowerCase().startsWith(prefix.toLowerCase()))\n .map((fn) => this.createFunctionCompletion(fn))\n\n if (functions.length > 0) {\n return {\n from: pos - prefix.length,\n options: functions,\n }\n }\n }\n\n // Check if we're typing a suggestion trigger (e.g., {{)\n const suggestionMatch = textBefore.match(/\\{\\{([^}]*)$/)\n if (suggestionMatch) {\n const prefix = suggestionMatch[1]\n const suggestions = this.suggestions\n .filter((suggestion) => suggestion.label.toLowerCase().startsWith(prefix.toLowerCase()))\n .map((suggestion) => this.createSuggestionCompletion(suggestion))\n\n if (suggestions.length > 0) {\n return {\n from: pos - prefix.length,\n options: suggestions,\n }\n }\n }\n\n return null\n }\n }\n\n private createFunctionCompletion(schema: FunctionSchema): Completion {\n const result: Completion = {\n label: schema.name,\n detail: schema.description || '',\n type: 'function',\n info: () => this.createFunctionInfoElement(schema),\n apply: (view: EditorView, completion: unknown, from: number, to: number) => {\n const functionCall = this.formatFunctionCall(schema)\n view.dispatch({\n changes: { from, to, insert: functionCall },\n selection: { anchor: from + functionCall.length },\n })\n this.dispatchFunctionInsert(schema, from)\n },\n }\n\n return result\n }\n\n private createSuggestionCompletion(suggestion: Suggestion): Completion {\n const result: Completion = {\n label: suggestion.label,\n detail: suggestion.description || '',\n info: suggestion.suffix || '',\n type: 'variable',\n apply: (view: EditorView, completion: unknown, from: number, to: number) => {\n const placeholderText = `{{${suggestion.id}}}`\n view.dispatch({\n changes: { from: from - 2, to, insert: placeholderText }, // -2 to include the {{\n selection: { anchor: from - 2 + placeholderText.length },\n })\n this.dispatchSuggestionInsert(suggestion, from - 2)\n },\n }\n\n return result\n }\n\n /**\n * Creates the source for the hover tooltips.\n * This is an arrow function to automatically bind `this`.\n */\n private createHoverTooltipSource = (view: EditorView, pos: number): Tooltip | null => {\n const word = view.state.wordAt(pos)\n if (!word) {\n return null\n }\n\n const functionName = view.state.doc.sliceString(word.from, word.to)\n const fnSchema = this.functionSchemas.find((schema) => schema.name === functionName)\n\n if (!fnSchema) {\n return null\n }\n\n return {\n pos: word.from,\n end: word.to,\n above: true,\n create: () => ({ dom: this.createFunctionInfoElement(fnSchema) }),\n }\n }\n\n /**\n * Creates a styled HTML element to display function documentation.\n * This is used for both hover tooltips and autocomplete info panels.\n */\n private createFunctionInfoElement(fn: FunctionSchema): HTMLElement {\n const container = document.createElement('div')\n container.className = 'function-info' // for styling\n\n if (fn.description) {\n const description = document.createElement('p')\n description.className = 'description'\n description.textContent = fn.description\n container.appendChild(description)\n }\n\n if (fn.parameters && fn.parameters.length > 0) {\n const paramsContainer = document.createElement('div')\n paramsContainer.className = 'parameters'\n\n const paramsHeader = document.createElement('h4')\n paramsHeader.textContent = 'Parameters'\n paramsContainer.appendChild(paramsHeader)\n\n const paramsList = document.createElement('ul')\n fn.parameters.forEach((param) => {\n const listItem = document.createElement('li')\n\n const name = document.createElement('span')\n name.className = 'param-name'\n name.textContent = param.name\n\n const type = document.createElement('span')\n type.className = 'param-type'\n type.textContent = `: ${getTypeStringFromSchema(param.schema)}`\n\n listItem.appendChild(name)\n listItem.appendChild(type)\n\n if (param.schema.description) {\n const paramDesc = document.createElement('p')\n paramDesc.className = 'param-description'\n paramDesc.textContent = param.schema.description\n listItem.appendChild(paramDesc)\n }\n paramsList.appendChild(listItem)\n })\n paramsContainer.appendChild(paramsList)\n container.appendChild(paramsContainer)\n }\n\n if (fn.returns) {\n const returnsContainer = document.createElement('div')\n returnsContainer.className = 'returns'\n\n const returnsHeader = document.createElement('h4')\n returnsHeader.textContent = 'Returns'\n returnsContainer.appendChild(returnsHeader)\n\n const returnsDesc = document.createElement('p')\n const returnType = getTypeStringFromSchema(fn.returns)\n returnsDesc.textContent = fn.returns.description ? `${returnType}: ${fn.returns.description}` : returnType\n returnsContainer.appendChild(returnsDesc)\n container.appendChild(returnsContainer)\n }\n\n return container\n }\n\n /**\n * Format function call with parameters\n */\n private formatFunctionCall(fn: FunctionSchema): string {\n if (!fn.parameters || fn.parameters.length === 0) {\n return `${fn.name}()`\n }\n\n const params = fn.parameters\n .map((param) => {\n if (param.required) {\n return param.name\n }\n return `${param.name}?`\n })\n .join(', ')\n\n return `${fn.name}(${params})`\n }\n\n /**\n * Update editor content when value changes\n */\n private updateEditorContent(): void {\n if (!this.editorView) return\n\n const currentValue = this.editorView.state.doc.toString()\n if (currentValue !== this.value) {\n this.editorView.dispatch({\n changes: {\n from: 0,\n to: this.editorView.state.doc.length,\n insert: this.value,\n },\n })\n }\n }\n\n /**\n * Handle editor content change\n */\n private handleEditorChange(): void {\n if (!this.editorView) return\n\n const newValue = this.editorView.state.doc.toString()\n this.#value = newValue\n this.hasContent = newValue.length > 0\n\n this.dispatchEvent(new Event('input', { bubbles: true }))\n }\n\n /**\n * Handle focus change\n */\n private handleFocusChange(hasFocus: boolean): void {\n this.isEditorFocus = hasFocus\n\n if (!hasFocus && this.#value !== this._previousValue) {\n this._previousValue = this.#value\n this.dispatchEvent(new Event('change'))\n }\n }\n\n /**\n * Dispatch function insert event\n */\n private dispatchFunctionInsert(functionSchema: FunctionSchema, position: number): void {\n const event = new CustomEvent<FunctionInsertEvent>('function-insert', {\n detail: { functionSchema, position },\n bubbles: true,\n })\n this.dispatchEvent(event)\n }\n\n /**\n * Dispatch suggestion insert event\n */\n private dispatchSuggestionInsert(suggestion: Suggestion, position: number): void {\n const event = new CustomEvent<SuggestionInsertEvent>('suggestion-insert', {\n detail: { suggestion, position },\n bubbles: true,\n })\n this.dispatchEvent(event)\n }\n\n /**\n * Focus the editor\n */\n override focus(): void {\n this.editorView?.focus()\n }\n\n /**\n * Get the editor's current selection\n */\n getSelection(): { from: number; to: number } | null {\n if (!this.editorView) return null\n const { from, to } = this.editorView.state.selection.main\n return { from, to }\n }\n\n /**\n * Insert text at the current cursor position\n */\n insertText(text: string): void {\n if (!this.editorView) return\n\n const { from, to } = this.editorView.state.selection.main\n this.editorView.dispatch({\n changes: { from, to, insert: text },\n selection: { anchor: from + text.length },\n })\n }\n\n override render(): TemplateResult {\n const hasLabel = !!this.label\n const hasSupportingText = !!this.supportingText\n\n return html`\n <div class=\"surface ${classMap({ 'has-focus': this.isEditorFocus, 'invalid': this.invalid })}\">\n <div class=\"content\">\n ${hasLabel ? html`<div class=\"label\">${this.label}</div>` : nothing}\n\n <div class=\"editor-container\" part=\"editor\"></div>\n </div>\n\n ${hasSupportingText ? html`<div class=\"supporting-text\">${this.supportingText}</div>` : nothing}\n </div>\n `\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeEditor.styles.d.ts","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/CodeEditor.styles.ts"],"names":[],"mappings":";AAEA,
|
|
1
|
+
{"version":3,"file":"CodeEditor.styles.d.ts","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/CodeEditor.styles.ts"],"names":[],"mappings":";AAEA,wBA8MC"}
|
|
@@ -128,8 +128,63 @@ export default css `
|
|
|
128
128
|
outline: none;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
.cm-tooltip-hover {
|
|
132
|
+
box-shadow: var(--md-sys-elevation-3);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.editor-container .cm-editor .cm-tooltip,
|
|
136
|
+
.cm-tooltip-lint,
|
|
137
|
+
.function-info {
|
|
138
|
+
background-color: var(--md-sys-color-surface-container-highest);
|
|
139
|
+
color: var(--md-sys-color-on-surface);
|
|
140
|
+
}
|
|
141
|
+
|
|
131
142
|
.function-info {
|
|
132
143
|
padding: 8px;
|
|
144
|
+
|
|
145
|
+
font-family: var(--md-sys-typescale-body-medium-font);
|
|
146
|
+
font-weight: var(--md-sys-typescale-body-medium-weight);
|
|
147
|
+
font-size: var(--md-sys-typescale-body-medium-size);
|
|
148
|
+
letter-spacing: var(--md-sys-typescale-body-medium-tracking);
|
|
149
|
+
line-height: var(--md-sys-typescale-body-medium-height);
|
|
150
|
+
|
|
151
|
+
h4 {
|
|
152
|
+
margin: 4px 0;
|
|
153
|
+
font-family: var(--md-sys-typescale-title-medium-font);
|
|
154
|
+
font-weight: var(--md-sys-typescale-title-medium-weight);
|
|
155
|
+
font-size: var(--md-sys-typescale-title-medium-size);
|
|
156
|
+
letter-spacing: var(--md-sys-typescale-title-medium-tracking);
|
|
157
|
+
line-height: var(--md-sys-typescale-title-medium-height);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
p {
|
|
161
|
+
margin: 0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.description {
|
|
165
|
+
font-family: var(--md-sys-typescale-body-large-font);
|
|
166
|
+
font-weight: var(--md-sys-typescale-body-large-weight);
|
|
167
|
+
font-size: var(--md-sys-typescale-body-large-size);
|
|
168
|
+
letter-spacing: var(--md-sys-typescale-body-large-tracking);
|
|
169
|
+
line-height: var(--md-sys-typescale-body-large-height);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
ul {
|
|
173
|
+
margin: 0;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.param-name,
|
|
177
|
+
.param-type {
|
|
178
|
+
font-family: var(--md-sys-typescale-label-large-font);
|
|
179
|
+
font-weight: var(--md-sys-typescale-label-large-weight);
|
|
180
|
+
font-size: var(--md-sys-typescale-label-large-size);
|
|
181
|
+
letter-spacing: var(--md-sys-typescale-label-large-tracking);
|
|
182
|
+
line-height: var(--md-sys-typescale-label-large-height);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.param-description {
|
|
186
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
187
|
+
}
|
|
133
188
|
}
|
|
134
189
|
|
|
135
190
|
/* Responsive */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeEditor.styles.js","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/CodeEditor.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,eAAe,GAAG,CAAA
|
|
1
|
+
{"version":3,"file":"CodeEditor.styles.js","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/CodeEditor.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,eAAe,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8MjB,CAAA","sourcesContent":["import { css } from 'lit'\n\nexport default css`\n :host {\n display: flex;\n flex-direction: column;\n outline: none;\n min-width: 200px;\n background-color: transparent;\n color: var(--md-sys-color-on-surface);\n\n font-family: var(--md-sys-typescale-body-large-font);\n font-size: var(--md-sys-typescale-body-large-size);\n letter-spacing: var(--md-sys-typescale-body-large-tracking);\n line-height: var(--md-sys-typescale-body-large-height);\n }\n\n .surface {\n display: flex;\n flex-direction: column;\n }\n\n .content {\n display: flex;\n flex-direction: column;\n flex: 1;\n }\n\n .label {\n font-family: var(--md-sys-typescale-label-medium-font);\n font-weight: var(--md-sys-typescale-label-medium-weight);\n font-size: var(--md-sys-typescale-label-medium-size);\n letter-spacing: var(--md-sys-typescale-label-medium-tracking);\n line-height: var(--md-sys-typescale-label-medium-height);\n color: var(--md-sys-color-on-surface-variant);\n\n padding: 8px 16px 4px 16px;\n margin: 0;\n }\n\n .has-focus .label {\n color: var(--md-sys-color-primary);\n }\n\n .editor-container {\n position: relative;\n flex: 1;\n\n border-radius: var(--md-sys-shape-corner-extra-small);\n border: 1px solid var(--md-sys-color-outline);\n outline: 0px solid var(--md-sys-color-primary);\n outline-offset: -1px;\n transition:\n border-color 150ms cubic-bezier(0.4, 0, 0.2, 1),\n outline-width 150ms cubic-bezier(0.4, 0, 0.2, 1),\n outline-offset 150ms cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .editor-container:focus-within {\n border-color: var(--md-sys-color-primary);\n outline-width: 2px;\n outline-offset: -2px;\n }\n\n .supporting-text {\n margin-top: 4px;\n padding: 0 16px;\n color: var(--md-sys-color-on-surface-variant);\n font-family: var(--md-sys-typescale-body-small-font);\n font-weight: var(--md-sys-typescale-body-small-weight);\n font-size: var(--md-sys-typescale-body-small-size);\n letter-spacing: var(--md-sys-typescale-body-small-tracking);\n line-height: var(--md-sys-typescale-body-small-height);\n }\n\n :host([disabled]) {\n pointer-events: none;\n }\n\n :host([disabled]) .editor-container {\n border-color: var(--md-sys-color-on-surface);\n }\n\n :host([disabled]) .label,\n :host([disabled]) .editor-container {\n color: var(--md-sys-color-on-surface);\n opacity: 0.38;\n }\n\n :host([invalid]) .label,\n :host([invalid]) .supporting-text {\n color: var(--md-sys-color-error);\n }\n\n :host([invalid]) .editor-container {\n border-color: var(--md-sys-color-error);\n outline-color: var(--md-sys-color-error);\n }\n\n .mention-chip {\n display: inline-flex;\n align-items: center;\n margin: 0 2px;\n vertical-align: baseline;\n user-select: none;\n }\n\n .mention-chip ui-chip {\n margin: 0;\n font-size: inherit;\n line-height: inherit;\n }\n\n .cm-gutters {\n background: var(--md-sys-color-surface-variant);\n color: var(--md-sys-color-on-surface-variant);\n border: none;\n }\n\n .cm-focused .cm-cursor {\n border-left-color: var(--md-sys-color-primary);\n }\n\n ::selection {\n background: var(--md-sys-color-surface-variant);\n }\n\n .ͼ1.cm-focused {\n outline: none;\n }\n\n .cm-tooltip-hover {\n box-shadow: var(--md-sys-elevation-3);\n }\n\n .editor-container .cm-editor .cm-tooltip,\n .cm-tooltip-lint,\n .function-info {\n background-color: var(--md-sys-color-surface-container-highest);\n color: var(--md-sys-color-on-surface);\n }\n\n .function-info {\n padding: 8px;\n\n font-family: var(--md-sys-typescale-body-medium-font);\n font-weight: var(--md-sys-typescale-body-medium-weight);\n font-size: var(--md-sys-typescale-body-medium-size);\n letter-spacing: var(--md-sys-typescale-body-medium-tracking);\n line-height: var(--md-sys-typescale-body-medium-height);\n\n h4 {\n margin: 4px 0;\n font-family: var(--md-sys-typescale-title-medium-font);\n font-weight: var(--md-sys-typescale-title-medium-weight);\n font-size: var(--md-sys-typescale-title-medium-size);\n letter-spacing: var(--md-sys-typescale-title-medium-tracking);\n line-height: var(--md-sys-typescale-title-medium-height);\n }\n\n p {\n margin: 0;\n }\n\n .description {\n font-family: var(--md-sys-typescale-body-large-font);\n font-weight: var(--md-sys-typescale-body-large-weight);\n font-size: var(--md-sys-typescale-body-large-size);\n letter-spacing: var(--md-sys-typescale-body-large-tracking);\n line-height: var(--md-sys-typescale-body-large-height);\n }\n\n ul {\n margin: 0;\n }\n\n .param-name,\n .param-type {\n font-family: var(--md-sys-typescale-label-large-font);\n font-weight: var(--md-sys-typescale-label-large-weight);\n font-size: var(--md-sys-typescale-label-large-size);\n letter-spacing: var(--md-sys-typescale-label-large-tracking);\n line-height: var(--md-sys-typescale-label-large-height);\n }\n\n .param-description {\n color: var(--md-sys-color-on-surface-variant);\n }\n }\n\n /* Responsive */\n @media (max-width: 600px) {\n :host {\n min-width: 0;\n }\n\n .label {\n padding: 6px 6px 3px 6px;\n }\n\n .editor-container {\n padding: 6px;\n }\n\n .supporting-text {\n padding: 3px 6px 6px 6px;\n }\n }\n`\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SuggestionMatchDecorator.d.ts","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/SuggestionMatchDecorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAc,MAAM,kBAAkB,CAAA;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAG5C;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,cAAc;;IASjD,WAAW,EAAE,UAAU,EAAE;IARlC;;;;;OAKG;gBAED,MAAM,EAAE,MAAM,EACP,WAAW,EAAE,UAAU,EAAE;
|
|
1
|
+
{"version":3,"file":"SuggestionMatchDecorator.d.ts","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/SuggestionMatchDecorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAc,MAAM,kBAAkB,CAAA;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAG5C;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,cAAc;;IASjD,WAAW,EAAE,UAAU,EAAE;IARlC;;;;;OAKG;gBAED,MAAM,EAAE,MAAM,EACP,WAAW,EAAE,UAAU,EAAE;CAkBnC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MatchDecorator, Decoration } from '@codemirror/view';
|
|
2
|
-
import { ChipWidget } from './
|
|
2
|
+
import { ChipWidget } from './ChipWidget.js';
|
|
3
3
|
/**
|
|
4
4
|
* A class that specializes in creating and managing decorations for suggestion matches in a code editor.
|
|
5
5
|
*/
|
|
@@ -19,10 +19,10 @@ export class SuggestionMatchDecorator extends MatchDecorator {
|
|
|
19
19
|
this.suggestions = suggestions;
|
|
20
20
|
}
|
|
21
21
|
#decoration(match) {
|
|
22
|
-
const
|
|
23
|
-
const suggestion = this.suggestions.find((s) => s.
|
|
22
|
+
const id = match[1];
|
|
23
|
+
const suggestion = this.suggestions.find((s) => s.id === id);
|
|
24
24
|
// If no suggestion is found, create a default one
|
|
25
|
-
const suggestionData = suggestion || { id
|
|
25
|
+
const suggestionData = suggestion || { id, label: id };
|
|
26
26
|
return Decoration.replace({
|
|
27
27
|
widget: new ChipWidget(suggestionData),
|
|
28
28
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SuggestionMatchDecorator.js","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/SuggestionMatchDecorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7D,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"SuggestionMatchDecorator.js","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/SuggestionMatchDecorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C;;GAEG;AACH,MAAM,OAAO,wBAAyB,SAAQ,cAAc;IASjD;IART;;;;;OAKG;IACH,YACE,MAAc,EACP,WAAyB;QAEhC,KAAK,CAAC;YACJ,MAAM;YACN,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;SAC/C,CAAC,CAAA;QALK,gBAAW,GAAX,WAAW,CAAc;IAMlC,CAAC;IAED,WAAW,CAAC,KAAsB;QAChC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;QACnB,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;QAE5D,kDAAkD;QAClD,MAAM,cAAc,GAAe,UAAU,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAA;QAClE,OAAO,UAAU,CAAC,OAAO,CAAC;YACxB,MAAM,EAAE,IAAI,UAAU,CAAC,cAAc,CAAC;SACvC,CAAC,CAAA;IACJ,CAAC;CACF","sourcesContent":["import { MatchDecorator, Decoration } from '@codemirror/view'\nimport type { Suggestion } from './types.js'\nimport { ChipWidget } from './ChipWidget.js'\n\n/**\n * A class that specializes in creating and managing decorations for suggestion matches in a code editor.\n */\nexport class SuggestionMatchDecorator extends MatchDecorator {\n /**\n * Creates a new instance of SuggestionMatchDecorator.\n * @param regexp - The regular expression used to match suggestions in the code.\n * @param suggestions - An array of suggestions that will be used to create decorations.\n * Each suggestion should have a unique `id` and a `label` that will be displayed in the editor.\n */\n constructor(\n regexp: RegExp,\n public suggestions: Suggestion[]\n ) {\n super({\n regexp,\n decoration: (match) => this.#decoration(match),\n })\n }\n\n #decoration(match: RegExpExecArray): Decoration {\n const id = match[1]\n const suggestion = this.suggestions.find((s) => s.id === id)\n\n // If no suggestion is found, create a default one\n const suggestionData: Suggestion = suggestion || { id, label: id }\n return Decoration.replace({\n widget: new ChipWidget(suggestionData),\n })\n }\n}\n"]}
|
|
@@ -8,6 +8,10 @@ import type {
|
|
|
8
8
|
SuggestionInsertEvent,
|
|
9
9
|
} from '../../../src/elements/code-editor/code-editor.js'
|
|
10
10
|
import '../../../src/elements/code-editor/code-editor.js'
|
|
11
|
+
import { stringLibrarySchema } from '@pawel-up/jexl/schemas/string.schema.js'
|
|
12
|
+
import { arrayLibrarySchema } from '@pawel-up/jexl/schemas/array.schema.js'
|
|
13
|
+
import { dateLibrarySchema } from '@pawel-up/jexl/schemas/date.schema.js'
|
|
14
|
+
import { mathLibrarySchema } from '@pawel-up/jexl/schemas/math.schema.js'
|
|
11
15
|
|
|
12
16
|
class CodeEditorDemo extends DemoPage {
|
|
13
17
|
override accessor componentName = 'Code Editor'
|
|
@@ -18,75 +22,10 @@ class CodeEditorDemo extends DemoPage {
|
|
|
18
22
|
@reactive()
|
|
19
23
|
private accessor editorValue = [
|
|
20
24
|
'// Start typing function names or {{ mentions }}',
|
|
21
|
-
'console.log("Hello, world!")',
|
|
22
25
|
'',
|
|
23
|
-
'
|
|
24
|
-
'// Example: Ask {{John}} about the API design',
|
|
25
|
-
'// Example: {{Jane}} can review the implementation',
|
|
26
|
-
'',
|
|
27
|
-
'"Hello {{John}}! Can you help with the " + getData() + " function?"',
|
|
26
|
+
'"Hello {{John}}! Can you help with the " + upper() + " function?"',
|
|
28
27
|
].join('\n')
|
|
29
28
|
|
|
30
|
-
private functionSchemas: FunctionSchema[] = [
|
|
31
|
-
{
|
|
32
|
-
name: 'getData',
|
|
33
|
-
description: 'Fetches data from the server',
|
|
34
|
-
parameters: [
|
|
35
|
-
{
|
|
36
|
-
name: 'url',
|
|
37
|
-
schema: { type: 'string', description: 'The URL to fetch data from' },
|
|
38
|
-
required: true,
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
name: 'options',
|
|
42
|
-
schema: { type: 'object', description: 'Fetch options' },
|
|
43
|
-
required: false,
|
|
44
|
-
},
|
|
45
|
-
],
|
|
46
|
-
returns: {
|
|
47
|
-
type: 'object',
|
|
48
|
-
description: 'The fetched data as an object',
|
|
49
|
-
},
|
|
50
|
-
category: 'network',
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
name: 'processData',
|
|
54
|
-
description: 'Processes raw data into a usable format',
|
|
55
|
-
parameters: [
|
|
56
|
-
{
|
|
57
|
-
name: 'data',
|
|
58
|
-
schema: { description: 'Raw data to process' },
|
|
59
|
-
required: true,
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
name: 'transformer',
|
|
63
|
-
schema: { description: 'Optional transformer function' },
|
|
64
|
-
required: false,
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
returns: {},
|
|
68
|
-
category: 'data',
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
category: 'validation',
|
|
72
|
-
name: 'validateInput',
|
|
73
|
-
description: 'Validates user input against a schema',
|
|
74
|
-
parameters: [
|
|
75
|
-
{
|
|
76
|
-
name: 'input',
|
|
77
|
-
schema: { type: 'object', description: 'The input to validate' },
|
|
78
|
-
required: true,
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
name: 'schema',
|
|
82
|
-
schema: { type: 'object', description: 'Validation schema' },
|
|
83
|
-
required: true,
|
|
84
|
-
},
|
|
85
|
-
],
|
|
86
|
-
returns: { type: 'object', description: 'Validation result' },
|
|
87
|
-
},
|
|
88
|
-
]
|
|
89
|
-
|
|
90
29
|
private suggestions: Suggestion[] = [
|
|
91
30
|
{
|
|
92
31
|
id: 'user-john',
|
|
@@ -111,6 +50,42 @@ class CodeEditorDemo extends DemoPage {
|
|
|
111
50
|
},
|
|
112
51
|
]
|
|
113
52
|
|
|
53
|
+
functions: FunctionSchema[] = []
|
|
54
|
+
|
|
55
|
+
constructor() {
|
|
56
|
+
super()
|
|
57
|
+
|
|
58
|
+
// Initialize function schemas
|
|
59
|
+
this.functions = this.createFunctionSchema()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Creates a schema for the code-editor functions.
|
|
64
|
+
* This method is responsible for defining the functions that can be used in the formula,
|
|
65
|
+
* given the current data type.
|
|
66
|
+
*/
|
|
67
|
+
createFunctionSchema(): FunctionSchema[] {
|
|
68
|
+
const result: FunctionSchema[] = []
|
|
69
|
+
|
|
70
|
+
for (const func of Object.values(stringLibrarySchema.functions)) {
|
|
71
|
+
result.push(func)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
for (const func of Object.values(arrayLibrarySchema.functions)) {
|
|
75
|
+
result.push(func)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
for (const func of Object.values(dateLibrarySchema.functions)) {
|
|
79
|
+
result.push(func)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
for (const func of Object.values(mathLibrarySchema.functions)) {
|
|
83
|
+
result.push(func)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return result
|
|
87
|
+
}
|
|
88
|
+
|
|
114
89
|
private handleFunctionInsert(event: CustomEvent<FunctionInsertEvent>): void {
|
|
115
90
|
const { functionSchema, position } = event.detail
|
|
116
91
|
this.output = `Function inserted: ${functionSchema.name} at position ${position}`
|
|
@@ -126,6 +101,12 @@ class CodeEditorDemo extends DemoPage {
|
|
|
126
101
|
this.editorValue = target.value
|
|
127
102
|
}
|
|
128
103
|
|
|
104
|
+
private handleChange(event: Event): void {
|
|
105
|
+
const target = event.target as HTMLElement & { value: string }
|
|
106
|
+
this.output = `Editor content changed: ${target.value}`
|
|
107
|
+
console.log('Editor change:', target.value)
|
|
108
|
+
}
|
|
109
|
+
|
|
129
110
|
contentTemplate() {
|
|
130
111
|
return html`
|
|
131
112
|
<a href="../">Back</a>
|
|
@@ -138,11 +119,12 @@ class CodeEditorDemo extends DemoPage {
|
|
|
138
119
|
label="Code Editor"
|
|
139
120
|
supporting-text="Type function names or {{fnName}} to see autocomplete"
|
|
140
121
|
.value=${this.editorValue}
|
|
141
|
-
.functionSchemas=${this.
|
|
122
|
+
.functionSchemas=${this.functions}
|
|
142
123
|
.suggestions=${this.suggestions}
|
|
143
124
|
@function-insert=${this.handleFunctionInsert}
|
|
144
125
|
@suggestion-insert=${this.handleSuggestionInsert}
|
|
145
126
|
@input=${this.handleInput}
|
|
127
|
+
@change=${this.handleChange}
|
|
146
128
|
></code-editor>
|
|
147
129
|
|
|
148
130
|
${this.output ? html`<p><strong>Output:</strong> ${this.output}</p>` : ''}
|
|
@@ -156,7 +138,7 @@ class CodeEditorDemo extends DemoPage {
|
|
|
156
138
|
label="Dark Theme Editor"
|
|
157
139
|
supporting-text="Dark theme variant"
|
|
158
140
|
.value=${'// Dark theme example\nconst theme = "dark"'}
|
|
159
|
-
.functionSchemas=${this.
|
|
141
|
+
.functionSchemas=${this.functions}
|
|
160
142
|
.suggestions=${this.suggestions}
|
|
161
143
|
dark-theme
|
|
162
144
|
></code-editor>
|
|
@@ -170,7 +152,7 @@ class CodeEditorDemo extends DemoPage {
|
|
|
170
152
|
label="Disabled Editor"
|
|
171
153
|
supporting-text="This editor is disabled"
|
|
172
154
|
.value=${'// This editor is disabled\nconst readOnly = true'}
|
|
173
|
-
.functionSchemas=${this.
|
|
155
|
+
.functionSchemas=${this.functions}
|
|
174
156
|
.suggestions=${this.suggestions}
|
|
175
157
|
disabled
|
|
176
158
|
></code-editor>
|
|
@@ -184,23 +166,11 @@ class CodeEditorDemo extends DemoPage {
|
|
|
184
166
|
label="Error Editor"
|
|
185
167
|
supporting-text="This editor has an error"
|
|
186
168
|
.value=${'// This editor has an error\nconst invalid = true'}
|
|
187
|
-
.functionSchemas=${this.
|
|
169
|
+
.functionSchemas=${this.functions}
|
|
188
170
|
.suggestions=${this.suggestions}
|
|
189
171
|
invalid
|
|
190
172
|
></code-editor>
|
|
191
173
|
</section>
|
|
192
|
-
|
|
193
|
-
<section class="demo-section">
|
|
194
|
-
<h2 class="display-large">Function Schemas</h2>
|
|
195
|
-
<p>Available function schemas for autocomplete:</p>
|
|
196
|
-
<pre>${JSON.stringify(this.functionSchemas, null, 2)}</pre>
|
|
197
|
-
</section>
|
|
198
|
-
|
|
199
|
-
<section class="demo-section">
|
|
200
|
-
<h2 class="display-large">Suggestions</h2>
|
|
201
|
-
<p>Available suggestions (use @mention syntax):</p>
|
|
202
|
-
<pre>${JSON.stringify(this.suggestions, null, 2)}</pre>
|
|
203
|
-
</section>
|
|
204
174
|
`
|
|
205
175
|
}
|
|
206
176
|
}
|
package/package.json
CHANGED
|
@@ -33,7 +33,7 @@ export class ChipWidget extends WidgetType {
|
|
|
33
33
|
const pos = view.posAtDOM(wrapper)
|
|
34
34
|
if (pos === null) return
|
|
35
35
|
|
|
36
|
-
const originalText = `{{${this.suggestion.
|
|
36
|
+
const originalText = `{{${this.suggestion.id}}}`
|
|
37
37
|
view.dispatch({
|
|
38
38
|
changes: { from: pos, to: pos + originalText.length, insert: '' },
|
|
39
39
|
})
|
|
@@ -129,8 +129,63 @@ export default css`
|
|
|
129
129
|
outline: none;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
.cm-tooltip-hover {
|
|
133
|
+
box-shadow: var(--md-sys-elevation-3);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.editor-container .cm-editor .cm-tooltip,
|
|
137
|
+
.cm-tooltip-lint,
|
|
138
|
+
.function-info {
|
|
139
|
+
background-color: var(--md-sys-color-surface-container-highest);
|
|
140
|
+
color: var(--md-sys-color-on-surface);
|
|
141
|
+
}
|
|
142
|
+
|
|
132
143
|
.function-info {
|
|
133
144
|
padding: 8px;
|
|
145
|
+
|
|
146
|
+
font-family: var(--md-sys-typescale-body-medium-font);
|
|
147
|
+
font-weight: var(--md-sys-typescale-body-medium-weight);
|
|
148
|
+
font-size: var(--md-sys-typescale-body-medium-size);
|
|
149
|
+
letter-spacing: var(--md-sys-typescale-body-medium-tracking);
|
|
150
|
+
line-height: var(--md-sys-typescale-body-medium-height);
|
|
151
|
+
|
|
152
|
+
h4 {
|
|
153
|
+
margin: 4px 0;
|
|
154
|
+
font-family: var(--md-sys-typescale-title-medium-font);
|
|
155
|
+
font-weight: var(--md-sys-typescale-title-medium-weight);
|
|
156
|
+
font-size: var(--md-sys-typescale-title-medium-size);
|
|
157
|
+
letter-spacing: var(--md-sys-typescale-title-medium-tracking);
|
|
158
|
+
line-height: var(--md-sys-typescale-title-medium-height);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
p {
|
|
162
|
+
margin: 0;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.description {
|
|
166
|
+
font-family: var(--md-sys-typescale-body-large-font);
|
|
167
|
+
font-weight: var(--md-sys-typescale-body-large-weight);
|
|
168
|
+
font-size: var(--md-sys-typescale-body-large-size);
|
|
169
|
+
letter-spacing: var(--md-sys-typescale-body-large-tracking);
|
|
170
|
+
line-height: var(--md-sys-typescale-body-large-height);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
ul {
|
|
174
|
+
margin: 0;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.param-name,
|
|
178
|
+
.param-type {
|
|
179
|
+
font-family: var(--md-sys-typescale-label-large-font);
|
|
180
|
+
font-weight: var(--md-sys-typescale-label-large-weight);
|
|
181
|
+
font-size: var(--md-sys-typescale-label-large-size);
|
|
182
|
+
letter-spacing: var(--md-sys-typescale-label-large-tracking);
|
|
183
|
+
line-height: var(--md-sys-typescale-label-large-height);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.param-description {
|
|
187
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
188
|
+
}
|
|
134
189
|
}
|
|
135
190
|
|
|
136
191
|
/* Responsive */
|
|
@@ -2,7 +2,7 @@ import { html, LitElement, PropertyValues, TemplateResult, nothing } from 'lit'
|
|
|
2
2
|
import { property, query, state } from 'lit/decorators.js'
|
|
3
3
|
import { classMap } from 'lit/directives/class-map.js'
|
|
4
4
|
import { linter } from '@codemirror/lint'
|
|
5
|
-
import { EditorState, Extension } from '@codemirror/state'
|
|
5
|
+
import { Compartment, EditorState, Extension } from '@codemirror/state'
|
|
6
6
|
import {
|
|
7
7
|
autocompletion,
|
|
8
8
|
CompletionContext,
|
|
@@ -97,11 +97,27 @@ export default class CodeEditor extends LitElement {
|
|
|
97
97
|
@property({ type: String })
|
|
98
98
|
accessor placeholder = ''
|
|
99
99
|
|
|
100
|
+
/**
|
|
101
|
+
* This property is used internally to set value without triggering updates.
|
|
102
|
+
*/
|
|
103
|
+
#value = ''
|
|
104
|
+
|
|
100
105
|
/**
|
|
101
106
|
* The editor content value
|
|
102
107
|
*/
|
|
108
|
+
get value(): string {
|
|
109
|
+
return this.#value
|
|
110
|
+
}
|
|
111
|
+
|
|
103
112
|
@property({ type: String })
|
|
104
|
-
|
|
113
|
+
set value(newValue: string) {
|
|
114
|
+
const oldValue = this.#value
|
|
115
|
+
if (newValue !== oldValue) {
|
|
116
|
+
this.#value = newValue
|
|
117
|
+
this._previousValue = newValue
|
|
118
|
+
this.requestUpdate('value', oldValue)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
105
121
|
|
|
106
122
|
/**
|
|
107
123
|
* Available function schemas for autocomplete
|
|
@@ -137,6 +153,10 @@ export default class CodeEditor extends LitElement {
|
|
|
137
153
|
private accessor isEditorFocus = false
|
|
138
154
|
|
|
139
155
|
private editorView?: EditorView
|
|
156
|
+
/**
|
|
157
|
+
* A control value to track previous value of the editor.
|
|
158
|
+
* This is used to detect when change event should be dispatched.
|
|
159
|
+
*/
|
|
140
160
|
private _previousValue = ''
|
|
141
161
|
/**
|
|
142
162
|
* Matcher for suggestion placeholders in the editor.
|
|
@@ -148,12 +168,12 @@ export default class CodeEditor extends LitElement {
|
|
|
148
168
|
*/
|
|
149
169
|
get activeSuggestions(): Suggestion[] {
|
|
150
170
|
const suggestions: Suggestion[] = []
|
|
151
|
-
const placeholderPattern = /\{\{(
|
|
171
|
+
const placeholderPattern = /\{\{([^}]+)\}\}/g
|
|
152
172
|
let match: RegExpExecArray | null
|
|
153
173
|
while ((match = placeholderPattern.exec(this.value)) !== null) {
|
|
154
174
|
const placeholderText = match[1]
|
|
155
|
-
// Find suggestion by
|
|
156
|
-
const suggestion = this.suggestions.find((s) => s.
|
|
175
|
+
// Find suggestion by id
|
|
176
|
+
const suggestion = this.suggestions.find((s) => s.id === placeholderText)
|
|
157
177
|
if (suggestion) {
|
|
158
178
|
suggestions.push(suggestion)
|
|
159
179
|
}
|
|
@@ -161,6 +181,8 @@ export default class CodeEditor extends LitElement {
|
|
|
161
181
|
return suggestions
|
|
162
182
|
}
|
|
163
183
|
|
|
184
|
+
private readonlyState = new Compartment()
|
|
185
|
+
|
|
164
186
|
override disconnectedCallback(): void {
|
|
165
187
|
super.disconnectedCallback()
|
|
166
188
|
this.editorView?.destroy()
|
|
@@ -185,7 +207,9 @@ export default class CodeEditor extends LitElement {
|
|
|
185
207
|
}
|
|
186
208
|
|
|
187
209
|
if (changedProperties.has('disabled')) {
|
|
188
|
-
this.
|
|
210
|
+
this.editorView?.dispatch({
|
|
211
|
+
effects: this.readonlyState.reconfigure(EditorState.readOnly.of(this.disabled)),
|
|
212
|
+
})
|
|
189
213
|
}
|
|
190
214
|
}
|
|
191
215
|
|
|
@@ -212,6 +236,7 @@ export default class CodeEditor extends LitElement {
|
|
|
212
236
|
this.createPlaceholderPlugin(),
|
|
213
237
|
hoverTooltip(this.createHoverTooltipSource),
|
|
214
238
|
linter((view) => functionLinter(view, this.functionSchemas, (e) => this.dispatchEvent(e))),
|
|
239
|
+
this.readonlyState.of(EditorState.readOnly.of(this.disabled)),
|
|
215
240
|
]
|
|
216
241
|
|
|
217
242
|
// Add language support
|
|
@@ -249,7 +274,7 @@ export default class CodeEditor extends LitElement {
|
|
|
249
274
|
* This is created as a method to get access to the component's `suggestions`.
|
|
250
275
|
*/
|
|
251
276
|
private createPlaceholderPlugin(): Extension {
|
|
252
|
-
const placeholderMatcher = new SuggestionMatchDecorator(/\{\{(
|
|
277
|
+
const placeholderMatcher = new SuggestionMatchDecorator(/\{\{([^}]+)\}\}/g, this.suggestions)
|
|
253
278
|
this.placeholderMatcher = placeholderMatcher
|
|
254
279
|
// This class needs to be defined here to have access to the `placeholderMatcher`
|
|
255
280
|
class AtomicDecorationRange {
|
|
@@ -294,7 +319,7 @@ export default class CodeEditor extends LitElement {
|
|
|
294
319
|
}
|
|
295
320
|
|
|
296
321
|
// Check if we're typing a suggestion trigger (e.g., {{)
|
|
297
|
-
const suggestionMatch = textBefore.match(/\{\{(
|
|
322
|
+
const suggestionMatch = textBefore.match(/\{\{([^}]*)$/)
|
|
298
323
|
if (suggestionMatch) {
|
|
299
324
|
const prefix = suggestionMatch[1]
|
|
300
325
|
const suggestions = this.suggestions
|
|
@@ -317,6 +342,7 @@ export default class CodeEditor extends LitElement {
|
|
|
317
342
|
const result: Completion = {
|
|
318
343
|
label: schema.name,
|
|
319
344
|
detail: schema.description || '',
|
|
345
|
+
type: 'function',
|
|
320
346
|
info: () => this.createFunctionInfoElement(schema),
|
|
321
347
|
apply: (view: EditorView, completion: unknown, from: number, to: number) => {
|
|
322
348
|
const functionCall = this.formatFunctionCall(schema)
|
|
@@ -336,8 +362,9 @@ export default class CodeEditor extends LitElement {
|
|
|
336
362
|
label: suggestion.label,
|
|
337
363
|
detail: suggestion.description || '',
|
|
338
364
|
info: suggestion.suffix || '',
|
|
365
|
+
type: 'variable',
|
|
339
366
|
apply: (view: EditorView, completion: unknown, from: number, to: number) => {
|
|
340
|
-
const placeholderText = `{{${suggestion.
|
|
367
|
+
const placeholderText = `{{${suggestion.id}}}`
|
|
341
368
|
view.dispatch({
|
|
342
369
|
changes: { from: from - 2, to, insert: placeholderText }, // -2 to include the {{
|
|
343
370
|
selection: { anchor: from - 2 + placeholderText.length },
|
|
@@ -480,21 +507,6 @@ export default class CodeEditor extends LitElement {
|
|
|
480
507
|
}
|
|
481
508
|
}
|
|
482
509
|
|
|
483
|
-
/**
|
|
484
|
-
* Update editor state (e.g., disabled state)
|
|
485
|
-
*/
|
|
486
|
-
private updateEditorState(): void {
|
|
487
|
-
if (!this.editorView) return
|
|
488
|
-
|
|
489
|
-
// For now, we'll handle disabled state differently
|
|
490
|
-
// CodeMirror 6 doesn't use reconfigure for editable
|
|
491
|
-
if (this.disabled) {
|
|
492
|
-
this.editorView.contentDOM.setAttribute('contenteditable', 'false')
|
|
493
|
-
} else {
|
|
494
|
-
this.editorView.contentDOM.setAttribute('contenteditable', 'true')
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
|
|
498
510
|
/**
|
|
499
511
|
* Handle editor content change
|
|
500
512
|
*/
|
|
@@ -502,13 +514,10 @@ export default class CodeEditor extends LitElement {
|
|
|
502
514
|
if (!this.editorView) return
|
|
503
515
|
|
|
504
516
|
const newValue = this.editorView.state.doc.toString()
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
this.value = newValue
|
|
508
|
-
this.hasContent = newValue.length > 0
|
|
517
|
+
this.#value = newValue
|
|
518
|
+
this.hasContent = newValue.length > 0
|
|
509
519
|
|
|
510
|
-
|
|
511
|
-
}
|
|
520
|
+
this.dispatchEvent(new Event('input', { bubbles: true }))
|
|
512
521
|
}
|
|
513
522
|
|
|
514
523
|
/**
|
|
@@ -517,8 +526,9 @@ export default class CodeEditor extends LitElement {
|
|
|
517
526
|
private handleFocusChange(hasFocus: boolean): void {
|
|
518
527
|
this.isEditorFocus = hasFocus
|
|
519
528
|
|
|
520
|
-
if (!hasFocus && this
|
|
521
|
-
this.
|
|
529
|
+
if (!hasFocus && this.#value !== this._previousValue) {
|
|
530
|
+
this._previousValue = this.#value
|
|
531
|
+
this.dispatchEvent(new Event('change'))
|
|
522
532
|
}
|
|
523
533
|
}
|
|
524
534
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MatchDecorator, Decoration } from '@codemirror/view'
|
|
2
2
|
import type { Suggestion } from './types.js'
|
|
3
|
-
import { ChipWidget } from './
|
|
3
|
+
import { ChipWidget } from './ChipWidget.js'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* A class that specializes in creating and managing decorations for suggestion matches in a code editor.
|
|
@@ -23,12 +23,11 @@ export class SuggestionMatchDecorator extends MatchDecorator {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
#decoration(match: RegExpExecArray): Decoration {
|
|
26
|
-
const
|
|
27
|
-
const suggestion = this.suggestions.find((s) => s.
|
|
26
|
+
const id = match[1]
|
|
27
|
+
const suggestion = this.suggestions.find((s) => s.id === id)
|
|
28
28
|
|
|
29
29
|
// If no suggestion is found, create a default one
|
|
30
|
-
const suggestionData: Suggestion = suggestion || { id
|
|
31
|
-
|
|
30
|
+
const suggestionData: Suggestion = suggestion || { id, label: id }
|
|
32
31
|
return Decoration.replace({
|
|
33
32
|
widget: new ChipWidget(suggestionData),
|
|
34
33
|
})
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PlaceholderWidget.d.ts","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/PlaceholderWidget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,6BAA6B,CAAA;AAEpC;;;;;;;;GAQG;AACH,qBAAa,UAAW,SAAQ,UAAU;IACrB,UAAU,EAAE,UAAU;gBAAtB,UAAU,EAAE,UAAU;IAIhC,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO;IAIvC,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW;IAwB3B,WAAW,IAAI,OAAO;CAGhC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PlaceholderWidget.js","sourceRoot":"","sources":["../../../../../src/elements/code-editor/internals/PlaceholderWidget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAEzD,OAAO,6BAA6B,CAAA;AAEpC;;;;;;;;GAQG;AACH,MAAM,OAAO,UAAW,SAAQ,UAAU;IACrB;IAAnB,YAAmB,UAAsB;QACvC,KAAK,EAAE,CAAA;QADU,eAAU,GAAV,UAAU,CAAY;IAEzC,CAAC;IAEQ,EAAE,CAAC,KAAiB;QAC3B,OAAO,IAAI,CAAC,UAAU,CAAC,EAAE,IAAK,KAAoB,CAAC,UAAU,CAAC,EAAE,CAAA;IAClE,CAAC;IAED,KAAK,CAAC,IAAgB;QACpB,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;QAC9C,OAAO,CAAC,SAAS,GAAG,cAAc,CAAA;QAClC,OAAO,CAAC,YAAY,CAAC,iBAAiB,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;QAE3D,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,CAAA;QAC9C,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAClC,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;QACtC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAA;QACxC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE;YACnC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;YAClC,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAM;YAExB,MAAM,YAAY,GAAG,KAAK,IAAI,CAAC,UAAU,CAAC,KAAK,IAAI,CAAA;YACnD,IAAI,CAAC,QAAQ,CAAC;gBACZ,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;aAClE,CAAC,CAAA;YACF,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC,CAAC,CAAA;QAEF,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;QACzB,OAAO,OAAO,CAAA;IAChB,CAAC;IAEQ,WAAW;QAClB,OAAO,KAAK,CAAA;IACd,CAAC;CACF","sourcesContent":["import { EditorView, WidgetType } from '@codemirror/view'\nimport type { Suggestion } from './types.js'\nimport '../../../md/chip/ui-chip.js'\n\n/**\n * A widget that represents a placeholder in the code editor,\n * specifically for suggestions that are replaced with chips.\n *\n * This widget is used to create a visual representation of a suggestion\n * in the code editor, allowing users to see and interact with suggestions\n * as chips. When a chip is removed, the corresponding text in the editor\n * is also removed.\n */\nexport class ChipWidget extends WidgetType {\n constructor(public suggestion: Suggestion) {\n super()\n }\n\n override eq(other: WidgetType): boolean {\n return this.suggestion.id == (other as ChipWidget).suggestion.id\n }\n\n toDOM(view: EditorView): HTMLElement {\n const wrapper = document.createElement('span')\n wrapper.className = 'mention-chip'\n wrapper.setAttribute('data-mention-id', this.suggestion.id)\n\n const chip = document.createElement('ui-chip')\n chip.setAttribute('type', 'input')\n chip.setAttribute('removable', 'true')\n chip.textContent = this.suggestion.label\n chip.addEventListener('remove', () => {\n const pos = view.posAtDOM(wrapper)\n if (pos === null) return\n\n const originalText = `{{${this.suggestion.label}}}`\n view.dispatch({\n changes: { from: pos, to: pos + originalText.length, insert: '' },\n })\n view.focus()\n })\n\n wrapper.appendChild(chip)\n return wrapper\n }\n\n override ignoreEvent(): boolean {\n return false\n }\n}\n"]}
|