@api-client/ui 0.5.10 → 0.5.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/build/src/elements/code-editor/internals/CodeEditor.d.ts +197 -0
  2. package/build/src/elements/code-editor/internals/CodeEditor.d.ts.map +1 -0
  3. package/build/src/elements/code-editor/internals/CodeEditor.js +612 -0
  4. package/build/src/elements/code-editor/internals/CodeEditor.js.map +1 -0
  5. package/build/src/elements/code-editor/internals/CodeEditor.styles.d.ts +3 -0
  6. package/build/src/elements/code-editor/internals/CodeEditor.styles.d.ts.map +1 -0
  7. package/build/src/elements/code-editor/internals/CodeEditor.styles.js +150 -0
  8. package/build/src/elements/code-editor/internals/CodeEditor.styles.js.map +1 -0
  9. package/build/src/elements/code-editor/internals/Linter.d.ts +5 -0
  10. package/build/src/elements/code-editor/internals/Linter.d.ts.map +1 -0
  11. package/build/src/elements/code-editor/internals/Linter.js +74 -0
  12. package/build/src/elements/code-editor/internals/Linter.js.map +1 -0
  13. package/build/src/elements/code-editor/ui-code-editor.d.ts +13 -0
  14. package/build/src/elements/code-editor/ui-code-editor.d.ts.map +1 -0
  15. package/build/src/elements/code-editor/ui-code-editor.js +28 -0
  16. package/build/src/elements/code-editor/ui-code-editor.js.map +1 -0
  17. package/build/src/index.d.ts +2 -0
  18. package/build/src/index.d.ts.map +1 -1
  19. package/build/src/index.js +2 -0
  20. package/build/src/index.js.map +1 -1
  21. package/build/src/md/chip/internals/Chip.styles.d.ts.map +1 -1
  22. package/build/src/md/chip/internals/Chip.styles.js +1 -0
  23. package/build/src/md/chip/internals/Chip.styles.js.map +1 -1
  24. package/demo/elements/code-editor/CodeEditorDemo.ts +212 -0
  25. package/demo/elements/code-editor/index.html +19 -0
  26. package/demo/elements/index.html +3 -0
  27. package/package.json +11 -3
  28. package/src/elements/code-editor/README.md +204 -0
  29. package/src/elements/code-editor/internals/CodeEditor.styles.ts +150 -0
  30. package/src/elements/code-editor/internals/CodeEditor.ts +595 -0
  31. package/src/elements/code-editor/internals/Linter.ts +87 -0
  32. package/src/elements/code-editor/ui-code-editor.ts +24 -0
  33. package/src/index.ts +10 -0
  34. package/src/md/chip/internals/Chip.styles.ts +1 -0
@@ -0,0 +1,612 @@
1
+ import { __esDecorate, __runInitializers } from "tslib";
2
+ import { html, LitElement, nothing } from 'lit';
3
+ import { property, query, state } from 'lit/decorators.js';
4
+ import { classMap } from 'lit/directives/class-map.js';
5
+ import { EditorState } from '@codemirror/state';
6
+ import { autocompletion } from '@codemirror/autocomplete';
7
+ import { javascript } from '@codemirror/lang-javascript';
8
+ import { syntaxHighlighting, defaultHighlightStyle } from '@codemirror/language';
9
+ import { oneDark } from '@codemirror/theme-one-dark';
10
+ import { keymap } from '@codemirror/view';
11
+ import { defaultKeymap } from '@codemirror/commands';
12
+ import { EditorView, MatchDecorator, Decoration, ViewPlugin, WidgetType, } from '@codemirror/view';
13
+ class PlaceholderWidget extends WidgetType {
14
+ placeholderText;
15
+ constructor(placeholderText) {
16
+ super();
17
+ this.placeholderText = placeholderText;
18
+ }
19
+ eq(other) {
20
+ return this.placeholderText == other.placeholderText;
21
+ }
22
+ toDOM() {
23
+ const placeholder = document.createElement('span');
24
+ placeholder.className = 'cm-pill';
25
+ placeholder.textContent = this.placeholderText;
26
+ return placeholder;
27
+ }
28
+ ignoreEvent() {
29
+ return false;
30
+ }
31
+ }
32
+ // We do variables Salesforce style, with double curly braces.
33
+ // This decorator replaces {{variable}} with a placeholder widget.
34
+ const placeholderMatcher = new MatchDecorator({
35
+ regexp: /\{\{(\w+)\}\}/g,
36
+ decoration: (match) => Decoration.replace({
37
+ widget: new PlaceholderWidget(match[1]),
38
+ }),
39
+ });
40
+ /**
41
+ * @see https://codemirror.net/examples/decoration/
42
+ */
43
+ class AtomicDecorationRange {
44
+ placeholders;
45
+ constructor(view) {
46
+ this.placeholders = placeholderMatcher.createDeco(view);
47
+ }
48
+ update(update) {
49
+ this.placeholders = placeholderMatcher.updateDeco(update, this.placeholders);
50
+ }
51
+ }
52
+ const placeholders = ViewPlugin.fromClass(AtomicDecorationRange, {
53
+ decorations: (instance) => instance.placeholders,
54
+ provide: (plugin) => EditorView.atomicRanges.of((view) => {
55
+ return view.plugin(plugin)?.placeholders || Decoration.none;
56
+ }),
57
+ });
58
+ let CodeEditor = (() => {
59
+ let _classSuper = LitElement;
60
+ let _label_decorators;
61
+ let _label_initializers = [];
62
+ let _label_extraInitializers = [];
63
+ let _supportingText_decorators;
64
+ let _supportingText_initializers = [];
65
+ let _supportingText_extraInitializers = [];
66
+ let _disabled_decorators;
67
+ let _disabled_initializers = [];
68
+ let _disabled_extraInitializers = [];
69
+ let _invalid_decorators;
70
+ let _invalid_initializers = [];
71
+ let _invalid_extraInitializers = [];
72
+ let _name_decorators;
73
+ let _name_initializers = [];
74
+ let _name_extraInitializers = [];
75
+ let _required_decorators;
76
+ let _required_initializers = [];
77
+ let _required_extraInitializers = [];
78
+ let _placeholder_decorators;
79
+ let _placeholder_initializers = [];
80
+ let _placeholder_extraInitializers = [];
81
+ let _value_decorators;
82
+ let _value_initializers = [];
83
+ let _value_extraInitializers = [];
84
+ let _functionSchemas_decorators;
85
+ let _functionSchemas_initializers = [];
86
+ let _functionSchemas_extraInitializers = [];
87
+ let _suggestions_decorators;
88
+ let _suggestions_initializers = [];
89
+ let _suggestions_extraInitializers = [];
90
+ let _darkTheme_decorators;
91
+ let _darkTheme_initializers = [];
92
+ let _darkTheme_extraInitializers = [];
93
+ let _language_decorators;
94
+ let _language_initializers = [];
95
+ let _language_extraInitializers = [];
96
+ let _editorContainer_decorators;
97
+ let _editorContainer_initializers = [];
98
+ let _editorContainer_extraInitializers = [];
99
+ let _hasContent_decorators;
100
+ let _hasContent_initializers = [];
101
+ let _hasContent_extraInitializers = [];
102
+ let _isEditorFocus_decorators;
103
+ let _isEditorFocus_initializers = [];
104
+ let _isEditorFocus_extraInitializers = [];
105
+ return class CodeEditor extends _classSuper {
106
+ static {
107
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
108
+ _label_decorators = [property({ type: String })];
109
+ _supportingText_decorators = [property({ type: String, attribute: 'supporting-text' })];
110
+ _disabled_decorators = [property({ type: Boolean, reflect: true })];
111
+ _invalid_decorators = [property({ type: Boolean, reflect: true })];
112
+ _name_decorators = [property({ type: String })];
113
+ _required_decorators = [property({ type: Boolean })];
114
+ _placeholder_decorators = [property({ type: String })];
115
+ _value_decorators = [property({ type: String })];
116
+ _functionSchemas_decorators = [property({ type: Array, attribute: false })];
117
+ _suggestions_decorators = [property({ type: Array, attribute: false })];
118
+ _darkTheme_decorators = [property({ type: Boolean, attribute: 'dark-theme' })];
119
+ _language_decorators = [property({ type: String })];
120
+ _editorContainer_decorators = [query('.editor-container')];
121
+ _hasContent_decorators = [state()];
122
+ _isEditorFocus_decorators = [state()];
123
+ __esDecorate(this, null, _label_decorators, { kind: "accessor", name: "label", static: false, private: false, access: { has: obj => "label" in obj, get: obj => obj.label, set: (obj, value) => { obj.label = value; } }, metadata: _metadata }, _label_initializers, _label_extraInitializers);
124
+ __esDecorate(this, null, _supportingText_decorators, { kind: "accessor", name: "supportingText", static: false, private: false, access: { has: obj => "supportingText" in obj, get: obj => obj.supportingText, set: (obj, value) => { obj.supportingText = value; } }, metadata: _metadata }, _supportingText_initializers, _supportingText_extraInitializers);
125
+ __esDecorate(this, null, _disabled_decorators, { kind: "accessor", name: "disabled", static: false, private: false, access: { has: obj => "disabled" in obj, get: obj => obj.disabled, set: (obj, value) => { obj.disabled = value; } }, metadata: _metadata }, _disabled_initializers, _disabled_extraInitializers);
126
+ __esDecorate(this, null, _invalid_decorators, { kind: "accessor", name: "invalid", static: false, private: false, access: { has: obj => "invalid" in obj, get: obj => obj.invalid, set: (obj, value) => { obj.invalid = value; } }, metadata: _metadata }, _invalid_initializers, _invalid_extraInitializers);
127
+ __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);
128
+ __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);
129
+ __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);
130
+ __esDecorate(this, null, _value_decorators, { kind: "accessor", name: "value", static: false, private: false, access: { has: obj => "value" in obj, get: obj => obj.value, set: (obj, value) => { obj.value = value; } }, metadata: _metadata }, _value_initializers, _value_extraInitializers);
131
+ __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);
132
+ __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);
133
+ __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);
134
+ __esDecorate(this, null, _language_decorators, { kind: "accessor", name: "language", static: false, private: false, access: { has: obj => "language" in obj, get: obj => obj.language, set: (obj, value) => { obj.language = value; } }, metadata: _metadata }, _language_initializers, _language_extraInitializers);
135
+ __esDecorate(this, null, _editorContainer_decorators, { kind: "accessor", name: "editorContainer", static: false, private: false, access: { has: obj => "editorContainer" in obj, get: obj => obj.editorContainer, set: (obj, value) => { obj.editorContainer = value; } }, metadata: _metadata }, _editorContainer_initializers, _editorContainer_extraInitializers);
136
+ __esDecorate(this, null, _hasContent_decorators, { kind: "accessor", name: "hasContent", static: false, private: false, access: { has: obj => "hasContent" in obj, get: obj => obj.hasContent, set: (obj, value) => { obj.hasContent = value; } }, metadata: _metadata }, _hasContent_initializers, _hasContent_extraInitializers);
137
+ __esDecorate(this, null, _isEditorFocus_decorators, { kind: "accessor", name: "isEditorFocus", static: false, private: false, access: { has: obj => "isEditorFocus" in obj, get: obj => obj.isEditorFocus, set: (obj, value) => { obj.isEditorFocus = value; } }, metadata: _metadata }, _isEditorFocus_initializers, _isEditorFocus_extraInitializers);
138
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
139
+ }
140
+ /**
141
+ * Shadow root configuration for the component.
142
+ * Uses 'open' mode for accessibility and delegates focus to enable proper focus management.
143
+ */
144
+ static shadowRootOptions = {
145
+ mode: 'open',
146
+ delegatesFocus: true,
147
+ };
148
+ #label_accessor_storage = __runInitializers(this, _label_initializers, ''
149
+ /**
150
+ * Supporting text displayed below the editor
151
+ */
152
+ );
153
+ /**
154
+ * The label text displayed as placeholder/floating label
155
+ */
156
+ get label() { return this.#label_accessor_storage; }
157
+ set label(value) { this.#label_accessor_storage = value; }
158
+ #supportingText_accessor_storage = (__runInitializers(this, _label_extraInitializers), __runInitializers(this, _supportingText_initializers, ''
159
+ /**
160
+ * Whether the component is disabled
161
+ */
162
+ ));
163
+ /**
164
+ * Supporting text displayed below the editor
165
+ */
166
+ get supportingText() { return this.#supportingText_accessor_storage; }
167
+ set supportingText(value) { this.#supportingText_accessor_storage = value; }
168
+ #disabled_accessor_storage = (__runInitializers(this, _supportingText_extraInitializers), __runInitializers(this, _disabled_initializers, false
169
+ /**
170
+ * Whether the component is in an invalid state
171
+ */
172
+ ));
173
+ /**
174
+ * Whether the component is disabled
175
+ */
176
+ get disabled() { return this.#disabled_accessor_storage; }
177
+ set disabled(value) { this.#disabled_accessor_storage = value; }
178
+ #invalid_accessor_storage = (__runInitializers(this, _disabled_extraInitializers), __runInitializers(this, _invalid_initializers, false
179
+ /**
180
+ * The name attribute for form integration
181
+ */
182
+ ));
183
+ /**
184
+ * Whether the component is in an invalid state
185
+ */
186
+ get invalid() { return this.#invalid_accessor_storage; }
187
+ set invalid(value) { this.#invalid_accessor_storage = value; }
188
+ #name_accessor_storage = (__runInitializers(this, _invalid_extraInitializers), __runInitializers(this, _name_initializers, ''
189
+ /**
190
+ * Whether the input is required
191
+ */
192
+ ));
193
+ /**
194
+ * The name attribute for form integration
195
+ */
196
+ get name() { return this.#name_accessor_storage; }
197
+ set name(value) { this.#name_accessor_storage = value; }
198
+ #required_accessor_storage = (__runInitializers(this, _name_extraInitializers), __runInitializers(this, _required_initializers, false
199
+ /**
200
+ * Placeholder text shown when editor is empty
201
+ */
202
+ ));
203
+ /**
204
+ * Whether the input is required
205
+ */
206
+ get required() { return this.#required_accessor_storage; }
207
+ set required(value) { this.#required_accessor_storage = value; }
208
+ #placeholder_accessor_storage = (__runInitializers(this, _required_extraInitializers), __runInitializers(this, _placeholder_initializers, ''
209
+ /**
210
+ * The editor content value
211
+ */
212
+ ));
213
+ /**
214
+ * Placeholder text shown when editor is empty
215
+ */
216
+ get placeholder() { return this.#placeholder_accessor_storage; }
217
+ set placeholder(value) { this.#placeholder_accessor_storage = value; }
218
+ #value_accessor_storage = (__runInitializers(this, _placeholder_extraInitializers), __runInitializers(this, _value_initializers, ''
219
+ /**
220
+ * Available function schemas for autocomplete
221
+ */
222
+ ));
223
+ /**
224
+ * The editor content value
225
+ */
226
+ get value() { return this.#value_accessor_storage; }
227
+ set value(value) { this.#value_accessor_storage = value; }
228
+ #functionSchemas_accessor_storage = (__runInitializers(this, _value_extraInitializers), __runInitializers(this, _functionSchemas_initializers, []
229
+ /**
230
+ * Available suggestions for autocomplete
231
+ */
232
+ ));
233
+ /**
234
+ * Available function schemas for autocomplete
235
+ */
236
+ get functionSchemas() { return this.#functionSchemas_accessor_storage; }
237
+ set functionSchemas(value) { this.#functionSchemas_accessor_storage = value; }
238
+ #suggestions_accessor_storage = (__runInitializers(this, _functionSchemas_extraInitializers), __runInitializers(this, _suggestions_initializers, []
239
+ /**
240
+ * Whether to use dark theme
241
+ */
242
+ ));
243
+ /**
244
+ * Available suggestions for autocomplete
245
+ */
246
+ get suggestions() { return this.#suggestions_accessor_storage; }
247
+ set suggestions(value) { this.#suggestions_accessor_storage = value; }
248
+ #darkTheme_accessor_storage = (__runInitializers(this, _suggestions_extraInitializers), __runInitializers(this, _darkTheme_initializers, false
249
+ /**
250
+ * Programming language for syntax highlighting
251
+ */
252
+ ));
253
+ /**
254
+ * Whether to use dark theme
255
+ */
256
+ get darkTheme() { return this.#darkTheme_accessor_storage; }
257
+ set darkTheme(value) { this.#darkTheme_accessor_storage = value; }
258
+ #language_accessor_storage = (__runInitializers(this, _darkTheme_extraInitializers), __runInitializers(this, _language_initializers, 'javascript'));
259
+ /**
260
+ * Programming language for syntax highlighting
261
+ */
262
+ get language() { return this.#language_accessor_storage; }
263
+ set language(value) { this.#language_accessor_storage = value; }
264
+ #editorContainer_accessor_storage = (__runInitializers(this, _language_extraInitializers), __runInitializers(this, _editorContainer_initializers, void 0));
265
+ get editorContainer() { return this.#editorContainer_accessor_storage; }
266
+ set editorContainer(value) { this.#editorContainer_accessor_storage = value; }
267
+ #hasContent_accessor_storage = (__runInitializers(this, _editorContainer_extraInitializers), __runInitializers(this, _hasContent_initializers, false));
268
+ get hasContent() { return this.#hasContent_accessor_storage; }
269
+ set hasContent(value) { this.#hasContent_accessor_storage = value; }
270
+ #isEditorFocus_accessor_storage = (__runInitializers(this, _hasContent_extraInitializers), __runInitializers(this, _isEditorFocus_initializers, false));
271
+ get isEditorFocus() { return this.#isEditorFocus_accessor_storage; }
272
+ set isEditorFocus(value) { this.#isEditorFocus_accessor_storage = value; }
273
+ editorView = __runInitializers(this, _isEditorFocus_extraInitializers);
274
+ suggestionMap = new Map();
275
+ functionMap = new Map();
276
+ _previousValue = '';
277
+ /**
278
+ * Get all suggestions (placeholders) currently in the editor
279
+ */
280
+ get activeSuggestions() {
281
+ const suggestions = [];
282
+ const placeholderPattern = /\{\{(\w+)\}\}/g;
283
+ let match;
284
+ while ((match = placeholderPattern.exec(this.value)) !== null) {
285
+ const placeholderText = match[1];
286
+ // Find suggestion by label
287
+ const suggestion = this.suggestions.find((s) => s.label.toLowerCase() === placeholderText.toLowerCase());
288
+ if (suggestion) {
289
+ suggestions.push(suggestion);
290
+ }
291
+ }
292
+ return suggestions;
293
+ }
294
+ connectedCallback() {
295
+ super.connectedCallback();
296
+ this.setupSuggestionMaps();
297
+ }
298
+ disconnectedCallback() {
299
+ super.disconnectedCallback();
300
+ this.editorView?.destroy();
301
+ }
302
+ firstUpdated() {
303
+ this.initializeCodeMirror();
304
+ this.updateEditorContent();
305
+ }
306
+ willUpdate(changedProperties) {
307
+ super.willUpdate(changedProperties);
308
+ if (changedProperties.has('suggestions') || changedProperties.has('functionSchemas')) {
309
+ this.setupSuggestionMaps();
310
+ }
311
+ if (changedProperties.has('value') && this.editorView) {
312
+ this.updateEditorContent();
313
+ }
314
+ if (changedProperties.has('disabled')) {
315
+ this.updateEditorState();
316
+ }
317
+ }
318
+ /**
319
+ * Initialize CodeMirror editor with extensions
320
+ */
321
+ initializeCodeMirror() {
322
+ const extensions = [
323
+ keymap.of(defaultKeymap),
324
+ syntaxHighlighting(defaultHighlightStyle),
325
+ autocompletion({
326
+ override: [this.createCompletionSource()],
327
+ activateOnTyping: true,
328
+ maxRenderedOptions: 10,
329
+ }),
330
+ EditorView.updateListener.of((update) => {
331
+ if (update.docChanged) {
332
+ this.handleEditorChange();
333
+ }
334
+ if (update.focusChanged) {
335
+ this.handleFocusChange(update.view.hasFocus);
336
+ }
337
+ }),
338
+ placeholders,
339
+ // linter((view) => functionLinter(view as unknown as EditorView, this.functionSchemas)),
340
+ ];
341
+ // Add language support
342
+ if (this.language === 'javascript') {
343
+ extensions.push(javascript());
344
+ }
345
+ // Add theme
346
+ if (this.darkTheme) {
347
+ extensions.push(oneDark);
348
+ }
349
+ // Add placeholder
350
+ if (this.placeholder) {
351
+ extensions.push(EditorView.contentAttributes.of({
352
+ 'aria-placeholder': this.placeholder,
353
+ }));
354
+ }
355
+ const state = EditorState.create({
356
+ doc: this.value,
357
+ extensions,
358
+ });
359
+ this.editorView = new EditorView({
360
+ state,
361
+ parent: this.editorContainer,
362
+ });
363
+ }
364
+ /**
365
+ * Create completion source for functions and suggestions
366
+ */
367
+ createCompletionSource() {
368
+ return (context) => {
369
+ const { pos } = context;
370
+ const line = context.state.doc.lineAt(pos);
371
+ const textBefore = line.text.slice(0, pos - line.from);
372
+ // Check if we're typing a function name
373
+ const functionMatch = textBefore.match(/(\w+)$/);
374
+ if (functionMatch) {
375
+ const prefix = functionMatch[1];
376
+ const functions = this.functionSchemas
377
+ .filter((fn) => fn.name.toLowerCase().startsWith(prefix.toLowerCase()))
378
+ .map((fn) => ({
379
+ label: fn.name,
380
+ detail: fn.description || '',
381
+ info: this.formatFunctionInfo(fn),
382
+ apply: (view, completion, from, to) => {
383
+ const functionCall = this.formatFunctionCall(fn);
384
+ view.dispatch({
385
+ changes: { from, to, insert: functionCall },
386
+ selection: { anchor: from + functionCall.length },
387
+ });
388
+ this.dispatchFunctionInsert(fn, from);
389
+ },
390
+ }));
391
+ if (functions.length > 0) {
392
+ return {
393
+ from: pos - prefix.length,
394
+ options: functions,
395
+ };
396
+ }
397
+ }
398
+ // Check if we're typing a suggestion trigger (e.g., {{)
399
+ const suggestionMatch = textBefore.match(/\{\{(\w*)$/);
400
+ if (suggestionMatch) {
401
+ const prefix = suggestionMatch[1];
402
+ const suggestions = this.suggestions
403
+ .filter((suggestion) => suggestion.label.toLowerCase().startsWith(prefix.toLowerCase()))
404
+ .map((suggestion) => ({
405
+ label: suggestion.label,
406
+ detail: suggestion.description || '',
407
+ info: suggestion.suffix || '',
408
+ apply: (view, completion, from, to) => {
409
+ const placeholderText = `{{${suggestion.label}}}`;
410
+ view.dispatch({
411
+ changes: { from: from - 2, to, insert: placeholderText }, // -2 to include the {{
412
+ selection: { anchor: from - 2 + placeholderText.length },
413
+ });
414
+ this.dispatchSuggestionInsert(suggestion, from - 2);
415
+ },
416
+ }));
417
+ if (suggestions.length > 0) {
418
+ return {
419
+ from: pos - prefix.length,
420
+ options: suggestions,
421
+ };
422
+ }
423
+ }
424
+ return null;
425
+ };
426
+ }
427
+ /**
428
+ * Format function information for autocomplete
429
+ */
430
+ formatFunctionInfo(fn) {
431
+ let info = fn.description || '';
432
+ if (fn.parameters && fn.parameters.length > 0) {
433
+ info += '\n\nParameters:\n';
434
+ fn.parameters.forEach((param) => {
435
+ info += `• ${param.name}: ${param.type}`;
436
+ if (param.description) {
437
+ info += ` - ${param.description}`;
438
+ }
439
+ info += '\n';
440
+ });
441
+ }
442
+ if (fn.returns) {
443
+ info += `\nReturns: ${fn.returns}`;
444
+ }
445
+ return info;
446
+ }
447
+ /**
448
+ * Format function call with parameters
449
+ */
450
+ formatFunctionCall(fn) {
451
+ if (!fn.parameters || fn.parameters.length === 0) {
452
+ return `${fn.name}()`;
453
+ }
454
+ const params = fn.parameters
455
+ .map((param) => {
456
+ if (param.required) {
457
+ return param.name;
458
+ }
459
+ return `${param.name}?`;
460
+ })
461
+ .join(', ');
462
+ return `${fn.name}(${params})`;
463
+ }
464
+ /**
465
+ * Setup suggestion and function maps for quick lookup
466
+ */
467
+ setupSuggestionMaps() {
468
+ this.suggestionMap.clear();
469
+ this.functionMap.clear();
470
+ this.suggestions.forEach((suggestion) => {
471
+ this.suggestionMap.set(suggestion.id, suggestion);
472
+ });
473
+ this.functionSchemas.forEach((fn) => {
474
+ this.functionMap.set(fn.id, fn);
475
+ });
476
+ }
477
+ /**
478
+ * Update editor content when value changes
479
+ */
480
+ updateEditorContent() {
481
+ if (!this.editorView)
482
+ return;
483
+ const currentValue = this.editorView.state.doc.toString();
484
+ if (currentValue !== this.value) {
485
+ this.editorView.dispatch({
486
+ changes: {
487
+ from: 0,
488
+ to: this.editorView.state.doc.length,
489
+ insert: this.value,
490
+ },
491
+ });
492
+ }
493
+ }
494
+ /**
495
+ * Update editor state (e.g., disabled state)
496
+ */
497
+ updateEditorState() {
498
+ if (!this.editorView)
499
+ return;
500
+ // For now, we'll handle disabled state differently
501
+ // CodeMirror 6 doesn't use reconfigure for editable
502
+ if (this.disabled) {
503
+ this.editorView.contentDOM.setAttribute('contenteditable', 'false');
504
+ }
505
+ else {
506
+ this.editorView.contentDOM.setAttribute('contenteditable', 'true');
507
+ }
508
+ }
509
+ /**
510
+ * Handle editor content change
511
+ */
512
+ handleEditorChange() {
513
+ if (!this.editorView)
514
+ return;
515
+ const newValue = this.editorView.state.doc.toString();
516
+ if (newValue !== this._previousValue) {
517
+ this._previousValue = newValue;
518
+ this.value = newValue;
519
+ this.hasContent = newValue.length > 0;
520
+ this.dispatchEvent(new Event('input', { bubbles: true }));
521
+ }
522
+ }
523
+ /**
524
+ * Handle focus change
525
+ */
526
+ handleFocusChange(hasFocus) {
527
+ this.isEditorFocus = hasFocus;
528
+ if (!hasFocus && this.value !== this._previousValue) {
529
+ this.dispatchEvent(new Event('change', { bubbles: true }));
530
+ }
531
+ }
532
+ /**
533
+ * Dispatch function insert event
534
+ */
535
+ dispatchFunctionInsert(functionSchema, position) {
536
+ const event = new CustomEvent('function-insert', {
537
+ detail: { functionSchema, position },
538
+ bubbles: true,
539
+ });
540
+ this.dispatchEvent(event);
541
+ }
542
+ /**
543
+ * Dispatch suggestion insert event
544
+ */
545
+ dispatchSuggestionInsert(suggestion, position) {
546
+ const event = new CustomEvent('suggestion-insert', {
547
+ detail: { suggestion, position },
548
+ bubbles: true,
549
+ });
550
+ this.dispatchEvent(event);
551
+ }
552
+ /**
553
+ * Focus the editor
554
+ */
555
+ focus() {
556
+ this.editorView?.focus();
557
+ }
558
+ /**
559
+ * Get the editor's current selection
560
+ */
561
+ getSelection() {
562
+ if (!this.editorView)
563
+ return null;
564
+ const { from, to } = this.editorView.state.selection.main;
565
+ return { from, to };
566
+ }
567
+ /**
568
+ * Insert text at the current cursor position
569
+ */
570
+ insertText(text) {
571
+ if (!this.editorView)
572
+ return;
573
+ const { from, to } = this.editorView.state.selection.main;
574
+ this.editorView.dispatch({
575
+ changes: { from, to, insert: text },
576
+ selection: { anchor: from + text.length },
577
+ });
578
+ }
579
+ render() {
580
+ const hasLabel = !!this.label;
581
+ const hasSupportingText = !!this.supportingText;
582
+ return html `
583
+ <div class="surface ${classMap({ 'has-focus': this.isEditorFocus, 'invalid': this.invalid })}">
584
+ <div class="content">
585
+ ${hasLabel ? html `<div class="label">${this.label}</div>` : nothing}
586
+
587
+ <div class="editor-container" part="editor"></div>
588
+ </div>
589
+
590
+ ${hasSupportingText ? html `<div class="supporting-text">${this.supportingText}</div>` : nothing}
591
+ </div>
592
+ `;
593
+ }
594
+ };
595
+ })();
596
+ /**
597
+ * A CodeMirror 6 based editor component that supports function autocomplete and suggestion placeholders.
598
+ *
599
+ * Features:
600
+ * - Dynamic function schema loading
601
+ * - Autocomplete for functions and suggestions
602
+ * - Suggestion placeholders with double curly braces ({{suggestion}})
603
+ * - Keyboard navigation
604
+ * - Accessibility support
605
+ *
606
+ * @fires function-insert - When a function is inserted
607
+ * @fires suggestion-insert - When a suggestion is inserted
608
+ * @fires input - When the editor content changes
609
+ * @fires change - When the editor loses focus and content has changed
610
+ */
611
+ export default CodeEditor;
612
+ //# sourceMappingURL=CodeEditor.js.map