@fw-components/formula-editor 2.0.7-formula-editor.0 → 2.0.7-formula-editor.2
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.
|
@@ -56,6 +56,19 @@ let FormulaEditor = class FormulaEditor extends LitElement {
|
|
|
56
56
|
? (currentIndex - 1 + this._recommendations.length) % this._recommendations.length
|
|
57
57
|
: currentIndex;
|
|
58
58
|
this._selectedRecommendation = this._recommendations[newIndex];
|
|
59
|
+
this.scrollToSelectedRecommendation(newIndex);
|
|
60
|
+
}
|
|
61
|
+
scrollToSelectedRecommendation(index) {
|
|
62
|
+
const suggestionMenu = this.shadowRoot?.querySelector("suggestion-menu");
|
|
63
|
+
if (suggestionMenu) {
|
|
64
|
+
const listItem = suggestionMenu.shadowRoot?.querySelectorAll("li")[index];
|
|
65
|
+
if (listItem) {
|
|
66
|
+
listItem.scrollIntoView({
|
|
67
|
+
block: "nearest",
|
|
68
|
+
inline: "nearest",
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
59
72
|
}
|
|
60
73
|
handleKeyboardEvents(event) {
|
|
61
74
|
if (event.code == "Tab" && this._recommendations?.length == 1) {
|
|
@@ -146,6 +159,9 @@ let FormulaEditor = class FormulaEditor extends LitElement {
|
|
|
146
159
|
this.requestUpdate();
|
|
147
160
|
}
|
|
148
161
|
requestFormat() {
|
|
162
|
+
if (!Boolean(this.content)) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
149
165
|
this.content = this._parser.addParentheses(this.content) ?? this.content;
|
|
150
166
|
this.parseInput();
|
|
151
167
|
this._recommendations = null;
|
|
@@ -156,14 +172,14 @@ let FormulaEditor = class FormulaEditor extends LitElement {
|
|
|
156
172
|
<style>
|
|
157
173
|
${FormulaEditorStyles}
|
|
158
174
|
</style>
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
175
|
+
<div
|
|
176
|
+
contenteditable
|
|
177
|
+
id="wysiwyg-editor"
|
|
178
|
+
spellcheck="false"
|
|
179
|
+
autocomplete="off"
|
|
180
|
+
@input=${this.handleChange}
|
|
181
|
+
@keydown=${this.handleKeyboardEvents}
|
|
182
|
+
></div>
|
|
167
183
|
${this._recommendations
|
|
168
184
|
? html ` <suggestion-menu
|
|
169
185
|
style="
|
|
@@ -176,10 +192,10 @@ let FormulaEditor = class FormulaEditor extends LitElement {
|
|
|
176
192
|
window.scrollY +
|
|
177
193
|
"px"};
|
|
178
194
|
"
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
195
|
+
.recommendations=${this._recommendations}
|
|
196
|
+
.currentSelection=${this._selectedRecommendation}
|
|
197
|
+
.onClickRecommendation=${(e) => this.onClickRecommendation(e)}
|
|
198
|
+
></suggestion-menu>`
|
|
183
199
|
: html ``}
|
|
184
200
|
<p>${this._calculatedResult}</p>
|
|
185
201
|
`;
|
|
@@ -75,7 +75,6 @@ export class Parser {
|
|
|
75
75
|
// Fetch recommendations nonetheless.
|
|
76
76
|
parseOutput.recommendations =
|
|
77
77
|
this._recommender.getRecommendation(token);
|
|
78
|
-
console.log(parseOutput.recommendations);
|
|
79
78
|
}
|
|
80
79
|
let tokenClassName = "";
|
|
81
80
|
// Don't check for errors if an error has already been encountered.
|
|
@@ -1,67 +1,20 @@
|
|
|
1
|
+
import { Fzf } from 'fzf';
|
|
1
2
|
export class Recommender {
|
|
2
3
|
constructor(variables, minSuggestionLen) {
|
|
3
|
-
this.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
this.insert(variable[0]);
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
insert(word, position = -1, node = undefined) {
|
|
10
|
-
if (position == -1) {
|
|
11
|
-
this.insert(word, 0, this._trie);
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
if (position == word.length) {
|
|
15
|
-
node?.addChild("\0");
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
if (!node.getChild(word[position])) {
|
|
19
|
-
node?.addChild(word[position]);
|
|
20
|
-
}
|
|
21
|
-
this.insert(word, position + 1, node.getChild(word[position]));
|
|
4
|
+
this._minimumSuggestionLength = minSuggestionLen > 0 ? minSuggestionLen : 1;
|
|
5
|
+
const variableList = Array.from(variables.keys());
|
|
6
|
+
this._fzf = new Fzf(variableList);
|
|
22
7
|
}
|
|
23
8
|
getRecommendation(word) {
|
|
24
|
-
if (word.length < this.
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
let recommendations = [];
|
|
28
|
-
let currentPosition = 0;
|
|
29
|
-
let currentNode = this._trie;
|
|
30
|
-
while (currentNode && currentPosition < word.length) {
|
|
31
|
-
currentNode = currentNode.getChild(word[currentPosition]);
|
|
32
|
-
currentPosition++;
|
|
33
|
-
}
|
|
34
|
-
if (!currentNode) {
|
|
9
|
+
if (word.length < this._minimumSuggestionLength) {
|
|
35
10
|
return null;
|
|
36
11
|
}
|
|
37
|
-
this.
|
|
38
|
-
|
|
39
|
-
|
|
12
|
+
const entries = this._fzf.find(word);
|
|
13
|
+
const recommendations = entries.map(entry => entry.item);
|
|
14
|
+
if (recommendations.length === 0 ||
|
|
15
|
+
(recommendations.length === 1 && recommendations[0] === word)) {
|
|
40
16
|
return null;
|
|
41
17
|
}
|
|
42
18
|
return recommendations;
|
|
43
19
|
}
|
|
44
|
-
_traverseAndGet(recommendations, node, word, currentString = "") {
|
|
45
|
-
for (let child of node.children) {
|
|
46
|
-
if (child[0] == "\0") {
|
|
47
|
-
recommendations.push(word + currentString);
|
|
48
|
-
// return;
|
|
49
|
-
}
|
|
50
|
-
this._traverseAndGet(recommendations, child[1], word, currentString + child[0]);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
class TrieNode {
|
|
55
|
-
constructor() {
|
|
56
|
-
this._children = new Map();
|
|
57
|
-
}
|
|
58
|
-
get children() {
|
|
59
|
-
return this._children;
|
|
60
|
-
}
|
|
61
|
-
getChild(char) {
|
|
62
|
-
return this._children.get(char);
|
|
63
|
-
}
|
|
64
|
-
addChild(char) {
|
|
65
|
-
this._children.set(char, new TrieNode());
|
|
66
|
-
}
|
|
67
20
|
}
|
|
@@ -14,35 +14,69 @@ let SuggestionMenu = class SuggestionMenu extends LitElement {
|
|
|
14
14
|
this.currentSelection = "";
|
|
15
15
|
}
|
|
16
16
|
static { this.styles = css `
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
17
|
+
ul {
|
|
18
|
+
border: 1px solid var(--fe-suggestion-color, white);
|
|
19
|
+
color: var(--fe-suggestion-color, #bab6c0);
|
|
20
|
+
background-color: var(--fe-suggestion-background-color, white);
|
|
21
|
+
box-sizing: border-box;
|
|
22
|
+
width: 20vw;
|
|
23
|
+
max-height: 25vh;
|
|
24
|
+
overflow-x: auto;
|
|
25
|
+
overflow-y: auto;
|
|
26
|
+
list-style-type: none;
|
|
27
|
+
padding: 0;
|
|
28
|
+
margin: 0;
|
|
29
|
+
box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.13);
|
|
30
|
+
border-radius: 5px;
|
|
31
|
+
}
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
li {
|
|
34
|
+
margin: 0;
|
|
35
|
+
padding: 0.5em 1rem;
|
|
36
|
+
cursor: pointer;
|
|
37
|
+
font-family: var(--theme-font);
|
|
38
|
+
font-size: var(--secondary-font-size, 16px);
|
|
39
|
+
color: var(--secondary-color, #bab6c0);
|
|
40
|
+
}
|
|
33
41
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
42
|
+
li:hover,
|
|
43
|
+
li:focus-visible {
|
|
44
|
+
font-weight: bold;
|
|
45
|
+
color: var(--fe-suggestion-focus-color, #69676c);
|
|
46
|
+
}
|
|
38
47
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
li.selected {
|
|
49
|
+
color: var(--fe-suggestion-focus-color, #69676c);
|
|
50
|
+
font-weight: bold;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
li[focused] {
|
|
54
|
+
font-weight: bold;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Scrollbar styling */
|
|
58
|
+
::-webkit-scrollbar {
|
|
59
|
+
width: 10px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
::-webkit-scrollbar-track {
|
|
63
|
+
background: transparent;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
::-webkit-scrollbar-thumb {
|
|
67
|
+
background: #ccc;
|
|
68
|
+
border-radius: 5px;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
::-webkit-scrollbar-thumb:hover {
|
|
72
|
+
background: #aaa;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* Optional shadow for the dropdown */
|
|
76
|
+
.content {
|
|
77
|
+
box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.13);
|
|
78
|
+
}
|
|
79
|
+
`; }
|
|
46
80
|
handleKeydown(event, recommendation) {
|
|
47
81
|
if (event.code == "Enter") {
|
|
48
82
|
event.preventDefault();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fw-components/formula-editor",
|
|
3
|
-
"version": "2.0.7-formula-editor.
|
|
3
|
+
"version": "2.0.7-formula-editor.2",
|
|
4
4
|
"description": "A WYSIWYG type formula editor",
|
|
5
5
|
"main": "dist/formula-editor/src/formula-builder.js",
|
|
6
6
|
"publishConfig": {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@fw-components/styles": "^2.0.7-formula-editor.0",
|
|
17
17
|
"big.js": "^6.2.1",
|
|
18
|
+
"fzf": "^0.5.2",
|
|
18
19
|
"lit": "^2.1.2",
|
|
19
20
|
"typescript": "^5.0.4"
|
|
20
21
|
},
|
|
@@ -24,5 +25,5 @@
|
|
|
24
25
|
"@types/big.js": "^6.1.6",
|
|
25
26
|
"es-dev-server": "^2.1.0"
|
|
26
27
|
},
|
|
27
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "dd5507965a60cb53b241d974d5e3c74d5388263b"
|
|
28
29
|
}
|