@fw-components/formula-editor 2.0.7-formula-editor-enhancements.12 → 2.0.7-formula-editor.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/formula-editor/src/formula-editor.js +84 -174
- package/dist/formula-editor/src/styles/{formula-editor-styles.js → editor.js} +2 -2
- package/dist/formula-editor/src/styles/suggestion-menu.js +58 -0
- package/dist/formula-editor/src/suggestion-menu.js +45 -88
- package/dist/formula-editor/src/{helpers/types.js → types/index.js} +6 -0
- package/dist/formula-editor/src/utils/constants.js +8 -0
- package/dist/formula-editor/src/{parser.js → utils/parser.js} +89 -136
- package/dist/formula-editor/src/utils/queue.js +28 -0
- package/dist/formula-editor/src/utils/recommendor.js +15 -0
- package/dist/formula-editor/src/utils/stack.js +20 -0
- package/package.json +9 -3
- package/dist/formula-editor/src/cursor.js +0 -142
- package/dist/formula-editor/src/formula-builder.js +0 -139
- package/dist/formula-editor/src/formula-creator.js +0 -83
- package/dist/formula-editor/src/helpers.js +0 -54
- package/dist/formula-editor/src/recommendor.js +0 -18
- package/dist/formula-editor/src/sub-components/operator-input.js +0 -24
- package/dist/styles/src/button-styles.js +0 -419
|
@@ -6,89 +6,41 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
6
6
|
};
|
|
7
7
|
import { html, LitElement } from "lit";
|
|
8
8
|
import { customElement, property, state, query } from "lit/decorators.js";
|
|
9
|
-
import { FormulaEditorStyles } from "./styles/formula-editor-styles.js";
|
|
10
|
-
import { Parser } from "./parser.js";
|
|
11
9
|
import "./suggestion-menu.js";
|
|
10
|
+
import { Parser } from "./utils/parser.js";
|
|
11
|
+
import { FormulaEditorStyles } from "./styles/editor.js";
|
|
12
12
|
let FormulaEditor = class FormulaEditor extends LitElement {
|
|
13
13
|
constructor() {
|
|
14
|
-
super();
|
|
14
|
+
super(...arguments);
|
|
15
|
+
this.recommendations = [];
|
|
16
|
+
this.currentCursorPosition = 0;
|
|
17
|
+
this.isFocused = false;
|
|
15
18
|
/**
|
|
16
|
-
*
|
|
17
|
-
* because TS doesn't support that.
|
|
18
|
-
* @see https://github.com/lit/lit-element/issues/414
|
|
19
|
+
* Text area input value
|
|
19
20
|
*/
|
|
20
|
-
this._formattedContent = null;
|
|
21
|
-
this._recommendations = null;
|
|
22
|
-
this._calculatedResult = undefined;
|
|
23
|
-
/**
|
|
24
|
-
* If `parseInput` is called to add a recommendation, say by clicking,
|
|
25
|
-
* browser removes focus from the input box. In that case, we have no way
|
|
26
|
-
* of knowing where the cursor previously was, other than storing it somewhere.
|
|
27
|
-
*/
|
|
28
|
-
this.currentCursorPosition = null;
|
|
29
|
-
this.currentCursorRect = undefined;
|
|
30
|
-
this.lastInputType = "";
|
|
31
|
-
this.isFocus = false;
|
|
32
21
|
this.content = "";
|
|
33
22
|
this.placeholder = "Type your formula...";
|
|
34
23
|
this.variables = new Map();
|
|
35
24
|
this.minSuggestionLen = 2;
|
|
36
|
-
this.errorString =
|
|
37
|
-
this._parser = new Parser(this.variables, this.minSuggestionLen);
|
|
25
|
+
this.errorString = "";
|
|
38
26
|
}
|
|
39
27
|
firstUpdated(_changedProperties) {
|
|
40
|
-
this._parser = new Parser(this.variables, this.minSuggestionLen);
|
|
41
|
-
let editor = this.shadowRoot?.getElementById("wysiwyg-editor");
|
|
42
28
|
const inputListener = this.handleContentUpdate.bind(this);
|
|
43
|
-
editor.addEventListener("input", inputListener);
|
|
44
|
-
editor.focus();
|
|
45
|
-
}
|
|
46
|
-
navigateRecommendations(direction) {
|
|
47
|
-
if (!this._recommendations)
|
|
48
|
-
return;
|
|
49
|
-
const currentIndex = this._recommendations.indexOf(this._selectedRecommendation);
|
|
50
|
-
const newIndex = direction === "ArrowDown"
|
|
51
|
-
? (currentIndex + 1) % this._recommendations.length
|
|
52
|
-
: direction === "ArrowUp"
|
|
53
|
-
? (currentIndex - 1 + this._recommendations.length) % this._recommendations.length
|
|
54
|
-
: currentIndex;
|
|
55
|
-
this._selectedRecommendation = this._recommendations[newIndex];
|
|
56
|
-
this.scrollToSelectedRecommendation(newIndex);
|
|
29
|
+
this.editor.addEventListener("input", inputListener);
|
|
30
|
+
this.editor.focus();
|
|
57
31
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (listItem) {
|
|
63
|
-
listItem.scrollIntoView({
|
|
64
|
-
block: "nearest",
|
|
65
|
-
inline: "nearest",
|
|
66
|
-
});
|
|
32
|
+
updated(_changedProperties) {
|
|
33
|
+
if (_changedProperties.has("content")) {
|
|
34
|
+
if (!this.content?.trim()) {
|
|
35
|
+
this.recommendations = Array.from(this.variables.keys());
|
|
67
36
|
}
|
|
37
|
+
this._adjustTextAreaHeight();
|
|
68
38
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (event.code == "Tab" && this._recommendations?.length == 1) {
|
|
72
|
-
this._selectedRecommendation = null;
|
|
73
|
-
event.preventDefault();
|
|
74
|
-
this.parseInput(this._recommendations[0]);
|
|
75
|
-
}
|
|
76
|
-
else if (event.code === "ArrowDown" || event.code === "ArrowUp") {
|
|
77
|
-
if (this._recommendations)
|
|
78
|
-
event.preventDefault();
|
|
79
|
-
this.navigateRecommendations(event.code);
|
|
80
|
-
this.requestUpdate();
|
|
81
|
-
}
|
|
82
|
-
else if (event.code === "Enter" && this._selectedRecommendation) {
|
|
83
|
-
event.preventDefault();
|
|
84
|
-
this.parseInput(this._selectedRecommendation);
|
|
85
|
-
this._selectedRecommendation = null;
|
|
39
|
+
if (_changedProperties.has("variables") && this.variables.size) {
|
|
40
|
+
this._parser = new Parser(this.variables, this.minSuggestionLen);
|
|
86
41
|
}
|
|
87
42
|
}
|
|
88
43
|
onClickRecommendation(recommendation) {
|
|
89
|
-
let editor = this.shadowRoot?.getElementById("wysiwyg-editor");
|
|
90
|
-
if (!editor)
|
|
91
|
-
return;
|
|
92
44
|
this.parseInput(recommendation);
|
|
93
45
|
}
|
|
94
46
|
handleContentUpdate(event) {
|
|
@@ -97,149 +49,116 @@ let FormulaEditor = class FormulaEditor extends LitElement {
|
|
|
97
49
|
this.content = event.target.value;
|
|
98
50
|
this.parseInput();
|
|
99
51
|
}
|
|
100
|
-
|
|
101
|
-
const editor = this.shadowRoot?.getElementById("wysiwyg-editor");
|
|
52
|
+
_adjustTextAreaHeight() {
|
|
102
53
|
if (!this.content)
|
|
103
|
-
editor.style.height = "var(--fe-height, 30px)";
|
|
104
|
-
if (editor.scrollHeight > editor.clientHeight)
|
|
105
|
-
editor.style.height = (editor.scrollHeight + 5)
|
|
54
|
+
this.editor.style.height = "var(--fe-height, 30px)";
|
|
55
|
+
if (this.editor.scrollHeight > this.editor.clientHeight)
|
|
56
|
+
this.editor.style.height = String(this.editor.scrollHeight + 5).concat("px");
|
|
106
57
|
}
|
|
107
58
|
/**
|
|
108
|
-
*
|
|
109
59
|
* @param recommendation The recommendation which needs to be inserted
|
|
110
60
|
* at the current cursor position
|
|
111
|
-
* @param manageCursor Whether or not cursor management is needed. Not
|
|
112
|
-
* needed when manual insertion of text is required (eg: during initialization)
|
|
113
61
|
* @returns void
|
|
114
62
|
*/
|
|
115
|
-
parseInput(recommendation =
|
|
116
|
-
|
|
117
|
-
if (!editor)
|
|
118
|
-
return;
|
|
119
|
-
this.currentCursorPosition = editor.selectionStart;
|
|
63
|
+
parseInput(recommendation = "") {
|
|
64
|
+
this.currentCursorPosition = this.editor.selectionStart;
|
|
120
65
|
const parseOutput = this._parser.parseInput(this.content, this.currentCursorPosition, recommendation);
|
|
121
|
-
this.
|
|
122
|
-
this._formattedContent = parseOutput.formattedContent;
|
|
66
|
+
this.recommendations = parseOutput.recommendations;
|
|
123
67
|
this.errorString = parseOutput.errorString;
|
|
124
68
|
/**
|
|
125
69
|
* Don't modify the text stream manually if the text is being composed,
|
|
126
|
-
* unless the user manually chooses to do so by selecting a
|
|
70
|
+
* unless the user manually chooses to do so by selecting a recommendation.
|
|
127
71
|
* @see https://github.com/w3c/input-events/issues/86
|
|
128
72
|
* @see https://github.com/w3c/input-events/pull/122
|
|
129
73
|
* @see https://bugs.chromium.org/p/chromium/issues/detail?id=689541
|
|
130
|
-
|
|
74
|
+
*/
|
|
131
75
|
if (this.lastInputType !== "insertCompositionText" || recommendation) {
|
|
132
|
-
|
|
133
|
-
this.content = formattedString;
|
|
76
|
+
this.content = parseOutput.formattedString;
|
|
134
77
|
}
|
|
135
|
-
if (recommendation) {
|
|
136
|
-
this.
|
|
78
|
+
if (Boolean(recommendation)) {
|
|
79
|
+
this.recommendations = [];
|
|
137
80
|
this.currentCursorPosition = parseOutput.newCursorPosition;
|
|
81
|
+
/**
|
|
82
|
+
* update cursor position in text area
|
|
83
|
+
*/
|
|
138
84
|
setTimeout(() => {
|
|
139
|
-
editor.setSelectionRange(this.currentCursorPosition, this.currentCursorPosition);
|
|
85
|
+
this.editor.setSelectionRange(this.currentCursorPosition, this.currentCursorPosition);
|
|
140
86
|
}, 0);
|
|
141
87
|
}
|
|
142
88
|
this.dispatchEvent(new CustomEvent("fw-formula-content-changed", {
|
|
143
89
|
detail: {
|
|
144
90
|
formulaString: this.content,
|
|
145
91
|
error: this.errorString,
|
|
146
|
-
recommendations: this.
|
|
92
|
+
recommendations: this.recommendations,
|
|
147
93
|
},
|
|
148
94
|
bubbles: true,
|
|
149
95
|
}));
|
|
150
|
-
editor.focus();
|
|
151
96
|
}
|
|
152
|
-
|
|
153
|
-
if (
|
|
97
|
+
formatFormula() {
|
|
98
|
+
if (!Boolean(this.content))
|
|
154
99
|
return;
|
|
155
|
-
}
|
|
156
|
-
const calculatedResult = this._parser.calculate(this.content);
|
|
157
100
|
this.content = this._parser.addParentheses(this.content) ?? this.content;
|
|
158
101
|
this.parseInput();
|
|
159
|
-
this.
|
|
160
|
-
this.errorString = calculatedResult.errorString;
|
|
161
|
-
this._recommendations = null;
|
|
162
|
-
this.requestUpdate();
|
|
102
|
+
this.recommendations = [];
|
|
163
103
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
this.content = this._parser.addParentheses(this.content) ?? this.content;
|
|
169
|
-
this.parseInput();
|
|
170
|
-
this._recommendations = null;
|
|
171
|
-
this.requestUpdate();
|
|
104
|
+
handleFocus(focus) {
|
|
105
|
+
this.isFocused = focus;
|
|
172
106
|
}
|
|
173
|
-
|
|
174
|
-
if (
|
|
175
|
-
|
|
176
|
-
|
|
107
|
+
handleKeydown(event) {
|
|
108
|
+
if (event.code === "Tab") {
|
|
109
|
+
event.preventDefault();
|
|
110
|
+
if (this.recommendations?.length === 1) {
|
|
111
|
+
this.suggestionMenu._handleRecommendationSelect();
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
const direction = event.shiftKey ? "up" : "down";
|
|
115
|
+
this.suggestionMenu.navigate(direction);
|
|
177
116
|
}
|
|
178
|
-
this._adjustInputHeight();
|
|
179
117
|
}
|
|
180
|
-
if (
|
|
181
|
-
|
|
118
|
+
else if (event.code === "ArrowDown" || event.code === "ArrowUp") {
|
|
119
|
+
event.preventDefault();
|
|
120
|
+
const direction = event.code === "ArrowDown" ? "down" : "up";
|
|
121
|
+
this.suggestionMenu.navigate(direction);
|
|
182
122
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
this._recommendations = null;
|
|
187
|
-
this.requestUpdate();
|
|
188
|
-
}
|
|
189
|
-
handleFocus(e) {
|
|
190
|
-
this.isFocus = true;
|
|
191
|
-
if (!this.content.trim()) {
|
|
192
|
-
this._recommendations = Array.from(this.variables.keys());
|
|
123
|
+
else if (event.code === "Enter") {
|
|
124
|
+
event.preventDefault();
|
|
125
|
+
this.suggestionMenu._handleRecommendationSelect();
|
|
193
126
|
}
|
|
194
127
|
}
|
|
195
128
|
render() {
|
|
196
129
|
return html `
|
|
197
|
-
<style>
|
|
198
|
-
|
|
199
|
-
</
|
|
130
|
+
<style>${FormulaEditorStyles}</style>
|
|
131
|
+
|
|
132
|
+
${this.label ? html `<label for="wysiwyg-editor" class="editor-label">${this.label}</label>` : ""}
|
|
133
|
+
|
|
134
|
+
<textarea
|
|
135
|
+
id="wysiwyg-editor"
|
|
136
|
+
class=${this.errorString?.length ? "error" : ""}
|
|
137
|
+
.value=${this.content}
|
|
138
|
+
.placeholder=${this.placeholder}
|
|
139
|
+
spellcheck="false"
|
|
140
|
+
autocomplete="off"
|
|
141
|
+
@keydown=${this.handleKeydown}
|
|
142
|
+
@blur=${() => this.handleFocus(false)}
|
|
143
|
+
@focus=${() => this.handleFocus(true)}
|
|
144
|
+
></textarea>
|
|
200
145
|
|
|
201
|
-
|
|
202
|
-
? html `<
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
placeholder=${this.placeholder}
|
|
209
|
-
id="wysiwyg-editor"
|
|
210
|
-
class=${this.errorString?.length ? "error" : ""}
|
|
211
|
-
.value=${this.content}
|
|
212
|
-
@keydown=${this.handleKeyboardEvents}
|
|
213
|
-
@blur=${this.handleFocusOut}
|
|
214
|
-
@focus=${this.handleFocus}
|
|
215
|
-
></textarea>
|
|
216
|
-
${this._recommendations && this.isFocus
|
|
217
|
-
? html ` <suggestion-menu
|
|
218
|
-
.recommendations=${this._recommendations}
|
|
219
|
-
.currentSelection=${this._selectedRecommendation}
|
|
220
|
-
.onClickRecommendation=${(e) => this.onClickRecommendation(e)}
|
|
221
|
-
@mousedown=${(e) => e.preventDefault()}
|
|
222
|
-
></suggestion-menu>`
|
|
223
|
-
: html ``}
|
|
224
|
-
<p>${this._calculatedResult}</p>
|
|
146
|
+
${this.isFocused && this.recommendations?.length
|
|
147
|
+
? html `<suggestion-menu
|
|
148
|
+
.recommendations=${this.recommendations}
|
|
149
|
+
.currentSelection=${this._selectedRecommendation}
|
|
150
|
+
.onClickRecommendation=${this.onClickRecommendation.bind(this)}
|
|
151
|
+
></suggestion-menu>`
|
|
152
|
+
: ''}
|
|
225
153
|
`;
|
|
226
154
|
}
|
|
227
155
|
};
|
|
228
156
|
__decorate([
|
|
229
157
|
state()
|
|
230
|
-
], FormulaEditor.prototype, "
|
|
231
|
-
__decorate([
|
|
232
|
-
state()
|
|
233
|
-
], FormulaEditor.prototype, "_recommendations", void 0);
|
|
234
|
-
__decorate([
|
|
235
|
-
state()
|
|
236
|
-
], FormulaEditor.prototype, "_calculatedResult", void 0);
|
|
158
|
+
], FormulaEditor.prototype, "recommendations", void 0);
|
|
237
159
|
__decorate([
|
|
238
160
|
state()
|
|
239
161
|
], FormulaEditor.prototype, "currentCursorPosition", void 0);
|
|
240
|
-
__decorate([
|
|
241
|
-
state()
|
|
242
|
-
], FormulaEditor.prototype, "currentCursorRect", void 0);
|
|
243
162
|
__decorate([
|
|
244
163
|
state()
|
|
245
164
|
], FormulaEditor.prototype, "lastInputType", void 0);
|
|
@@ -248,7 +167,7 @@ __decorate([
|
|
|
248
167
|
], FormulaEditor.prototype, "_selectedRecommendation", void 0);
|
|
249
168
|
__decorate([
|
|
250
169
|
state()
|
|
251
|
-
], FormulaEditor.prototype, "
|
|
170
|
+
], FormulaEditor.prototype, "isFocused", void 0);
|
|
252
171
|
__decorate([
|
|
253
172
|
property()
|
|
254
173
|
], FormulaEditor.prototype, "content", void 0);
|
|
@@ -259,19 +178,7 @@ __decorate([
|
|
|
259
178
|
property()
|
|
260
179
|
], FormulaEditor.prototype, "label", void 0);
|
|
261
180
|
__decorate([
|
|
262
|
-
property(
|
|
263
|
-
type: (Map),
|
|
264
|
-
converter: {
|
|
265
|
-
fromAttribute: (value) => {
|
|
266
|
-
if (value) {
|
|
267
|
-
return new Map(JSON.parse(value));
|
|
268
|
-
}
|
|
269
|
-
},
|
|
270
|
-
toAttribute: (value) => {
|
|
271
|
-
return JSON.stringify(Array.from(value.entries()));
|
|
272
|
-
},
|
|
273
|
-
},
|
|
274
|
-
})
|
|
181
|
+
property()
|
|
275
182
|
], FormulaEditor.prototype, "variables", void 0);
|
|
276
183
|
__decorate([
|
|
277
184
|
property()
|
|
@@ -280,8 +187,11 @@ __decorate([
|
|
|
280
187
|
property()
|
|
281
188
|
], FormulaEditor.prototype, "errorString", void 0);
|
|
282
189
|
__decorate([
|
|
283
|
-
query("wysiwyg-editor")
|
|
190
|
+
query("#wysiwyg-editor")
|
|
284
191
|
], FormulaEditor.prototype, "editor", void 0);
|
|
192
|
+
__decorate([
|
|
193
|
+
query("suggestion-menu")
|
|
194
|
+
], FormulaEditor.prototype, "suggestionMenu", void 0);
|
|
285
195
|
FormulaEditor = __decorate([
|
|
286
196
|
customElement("formula-editor")
|
|
287
197
|
], FormulaEditor);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { css } from "lit";
|
|
2
2
|
export const FormulaEditorStyles = css `
|
|
3
|
-
.
|
|
3
|
+
.editor-label {
|
|
4
4
|
display: block;
|
|
5
5
|
font-size: var(--fe-label-font-size, 0.8rem);
|
|
6
6
|
color: var(--fe-label-color, #515151);
|
|
@@ -13,7 +13,7 @@ export const FormulaEditorStyles = css `
|
|
|
13
13
|
padding: var(--fe-padding, 4px);
|
|
14
14
|
caret-color: var(--fe-caret-color, #fff);
|
|
15
15
|
color: var(--fe-text-color, #f7f1ff);
|
|
16
|
-
font-size: var(--fe-text-font-size,
|
|
16
|
+
font-size: var(--fe-text-font-size, 14px);
|
|
17
17
|
min-width: 100%;
|
|
18
18
|
min-height: 30px;
|
|
19
19
|
height: var(--fe-height, 30px);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { css } from "lit";
|
|
2
|
+
export const SuggestionMenuStyles = css `
|
|
3
|
+
ul {
|
|
4
|
+
position: relative;
|
|
5
|
+
border: 1px solid var(--fe-suggestion-color, white);
|
|
6
|
+
color: var(--fe-suggestion-color, #bab6c0);
|
|
7
|
+
background-color: var(--fe-suggestion-background-color, white);
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
width: var(--fe-suggestion-width, 20vw);
|
|
10
|
+
max-height: 25vh;
|
|
11
|
+
overflow-x: auto;
|
|
12
|
+
overflow-y: auto;
|
|
13
|
+
list-style-type: none;
|
|
14
|
+
padding: 0;
|
|
15
|
+
margin: 0;
|
|
16
|
+
box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.13);
|
|
17
|
+
border-radius: 5px;
|
|
18
|
+
z-index: 99999;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
li {
|
|
22
|
+
margin: 0;
|
|
23
|
+
padding: 0.5em 1rem;
|
|
24
|
+
cursor: pointer;
|
|
25
|
+
font-family: var(--theme-font);
|
|
26
|
+
font-size: var(--secondary-font-size, 16px);
|
|
27
|
+
color: var(--secondary-color, #bab6c0);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
li:hover, li:focus-visible, li.selected {
|
|
31
|
+
color: var(--fe-suggestion-focus-color, #69676c);
|
|
32
|
+
background: rgba(var(--fe-suggestion-focus-background, 86, 86, 86), 0.1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
/* Scrollbar styling */
|
|
37
|
+
::-webkit-scrollbar {
|
|
38
|
+
width: 10px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
::-webkit-scrollbar-track {
|
|
42
|
+
background: transparent;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
::-webkit-scrollbar-thumb {
|
|
46
|
+
background: #ccc;
|
|
47
|
+
border-radius: 5px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
::-webkit-scrollbar-thumb:hover {
|
|
51
|
+
background: #aaa;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Optional shadow for the dropdown */
|
|
55
|
+
.content {
|
|
56
|
+
box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.13);
|
|
57
|
+
}
|
|
58
|
+
`;
|
|
@@ -4,101 +4,52 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import {
|
|
8
|
-
import { customElement, property } from "lit/decorators.js";
|
|
7
|
+
import { html, LitElement } from "lit";
|
|
8
|
+
import { customElement, property, query, state } from "lit/decorators.js";
|
|
9
|
+
import { SuggestionMenuStyles } from "./styles/suggestion-menu";
|
|
9
10
|
let SuggestionMenu = class SuggestionMenu extends LitElement {
|
|
10
11
|
constructor() {
|
|
11
12
|
super(...arguments);
|
|
12
13
|
this.recommendations = [];
|
|
13
14
|
this.onClickRecommendation = (recommendation) => { };
|
|
14
|
-
this.
|
|
15
|
+
this._selectedRecommendationIndex = 0;
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
li:hover,
|
|
45
|
-
li:focus-visible {
|
|
46
|
-
font-weight: bold;
|
|
47
|
-
color: var(--fe-suggestion-focus-color, #69676c);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
li.selected {
|
|
51
|
-
color: var(--fe-suggestion-focus-color, #69676c);
|
|
52
|
-
font-weight: bold;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
li[focused] {
|
|
56
|
-
font-weight: bold;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/* Scrollbar styling */
|
|
60
|
-
::-webkit-scrollbar {
|
|
61
|
-
width: 10px;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
::-webkit-scrollbar-track {
|
|
65
|
-
background: transparent;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
::-webkit-scrollbar-thumb {
|
|
69
|
-
background: #ccc;
|
|
70
|
-
border-radius: 5px;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
::-webkit-scrollbar-thumb:hover {
|
|
74
|
-
background: #aaa;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/* Optional shadow for the dropdown */
|
|
78
|
-
.content {
|
|
79
|
-
box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.13);
|
|
80
|
-
}
|
|
81
|
-
`; }
|
|
82
|
-
handleKeydown(event, recommendation) {
|
|
83
|
-
if (event.code == "Enter") {
|
|
84
|
-
event.preventDefault();
|
|
85
|
-
event.stopPropagation();
|
|
86
|
-
this.onClickRecommendation(recommendation);
|
|
87
|
-
}
|
|
17
|
+
scrollToSelectedRecommendation(index) {
|
|
18
|
+
const listItem = this.suggestionList?.querySelectorAll("li")[index];
|
|
19
|
+
if (!listItem)
|
|
20
|
+
return;
|
|
21
|
+
listItem.scrollIntoView({
|
|
22
|
+
block: "nearest",
|
|
23
|
+
inline: "nearest",
|
|
24
|
+
behavior: "smooth"
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
navigate(direction) {
|
|
28
|
+
if (!this.recommendations)
|
|
29
|
+
return;
|
|
30
|
+
let newIndex = this._selectedRecommendationIndex;
|
|
31
|
+
if (direction === "down")
|
|
32
|
+
newIndex = (this._selectedRecommendationIndex + 1) % this.recommendations.length;
|
|
33
|
+
else if (direction === "up")
|
|
34
|
+
newIndex = (this._selectedRecommendationIndex - 1 + this.recommendations.length) % this.recommendations.length;
|
|
35
|
+
this._selectedRecommendationIndex = newIndex;
|
|
36
|
+
this.scrollToSelectedRecommendation(newIndex);
|
|
37
|
+
}
|
|
38
|
+
_handleRecommendationSelect(index = this._selectedRecommendationIndex) {
|
|
39
|
+
const recommendation = this.recommendations[index];
|
|
40
|
+
if (!recommendation)
|
|
41
|
+
return;
|
|
42
|
+
this.onClickRecommendation(recommendation);
|
|
43
|
+
this._selectedRecommendationIndex = -1;
|
|
88
44
|
}
|
|
89
45
|
render() {
|
|
90
46
|
return html `
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
@keydown=${(e) => this.handleKeydown(e, recommendation)}
|
|
98
|
-
>
|
|
99
|
-
${recommendation}
|
|
100
|
-
</li>`;
|
|
101
|
-
})}
|
|
47
|
+
<style>${SuggestionMenuStyles}</style>
|
|
48
|
+
<ul class="wysiwyg-suggestion-menu" @mousedown=${(e) => e.preventDefault()}>
|
|
49
|
+
${this.recommendations.map((recommendation, index) => html `<li
|
|
50
|
+
class="${this._selectedRecommendationIndex === index ? "selected" : ""}"
|
|
51
|
+
@click=${(e) => this._handleRecommendationSelect(index)}
|
|
52
|
+
>${recommendation}</li>`)}
|
|
102
53
|
</ul>
|
|
103
54
|
`;
|
|
104
55
|
}
|
|
@@ -110,8 +61,14 @@ __decorate([
|
|
|
110
61
|
property()
|
|
111
62
|
], SuggestionMenu.prototype, "onClickRecommendation", void 0);
|
|
112
63
|
__decorate([
|
|
113
|
-
|
|
114
|
-
], SuggestionMenu.prototype, "
|
|
64
|
+
state()
|
|
65
|
+
], SuggestionMenu.prototype, "_selectedRecommendationIndex", void 0);
|
|
66
|
+
__decorate([
|
|
67
|
+
state()
|
|
68
|
+
], SuggestionMenu.prototype, "abortController", void 0);
|
|
69
|
+
__decorate([
|
|
70
|
+
query(".wysiwyg-suggestion-menu")
|
|
71
|
+
], SuggestionMenu.prototype, "suggestionList", void 0);
|
|
115
72
|
SuggestionMenu = __decorate([
|
|
116
73
|
customElement("suggestion-menu")
|
|
117
74
|
], SuggestionMenu);
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
export var Expectation;
|
|
2
|
+
(function (Expectation) {
|
|
3
|
+
Expectation[Expectation["VARIABLE"] = 0] = "VARIABLE";
|
|
4
|
+
Expectation[Expectation["OPERATOR"] = 1] = "OPERATOR";
|
|
5
|
+
Expectation[Expectation["UNDEFINED"] = 2] = "UNDEFINED";
|
|
6
|
+
})(Expectation || (Expectation = {}));
|
|
1
7
|
export var Operator;
|
|
2
8
|
(function (Operator) {
|
|
3
9
|
Operator["PLUS"] = "+";
|