@api-client/ui 0.5.11 → 0.5.13

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