@fw-components/formula-editor 2.0.7-formula-editor.37 → 2.0.7-formula-editor.39
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 +24 -25
- package/dist/formula-editor/src/styles/editor.js +3 -3
- package/dist/formula-editor/src/styles/suggestion-menu.js +1 -6
- package/dist/formula-editor/src/suggestion-menu.js +11 -11
- package/dist/formula-editor/src/types/index.js +0 -8
- package/dist/formula-editor/src/utils/parser.js +2 -2
- package/dist/formula-editor/src/utils/queue.js +1 -4
- package/dist/formula-editor/src/utils/recommendor.js +5 -5
- package/dist/formula-editor/src/utils/stack.js +0 -3
- package/package.json +2 -2
|
@@ -19,25 +19,23 @@ let FormulaEditor = class FormulaEditor extends LitElement {
|
|
|
19
19
|
/**
|
|
20
20
|
* Text area input value
|
|
21
21
|
*/
|
|
22
|
-
this.
|
|
22
|
+
this.formulaString = "";
|
|
23
23
|
this.placeholder = "Type your formula...";
|
|
24
24
|
this.recommendationLabels = new Map();
|
|
25
25
|
this.variables = new Map();
|
|
26
26
|
this.minSuggestionLen = 2;
|
|
27
27
|
this.errorString = "";
|
|
28
|
-
this.formulaRegex = /'[^']*'|[A-Za-z0-9_#@]+|[-+(),*^/\s]/g;
|
|
29
28
|
this.allowedNumbers = true;
|
|
30
|
-
this.allowedOperators = new Set(["^", "+", "-", "*", "/"]);
|
|
31
29
|
}
|
|
32
30
|
updated(_changedProperties) {
|
|
33
|
-
if (_changedProperties.has("
|
|
34
|
-
if (!this.
|
|
31
|
+
if (_changedProperties.has("formulaString")) {
|
|
32
|
+
if (!this.formulaString?.trim()) {
|
|
35
33
|
this.recommendations = Array.from(this.variables.keys());
|
|
36
34
|
}
|
|
37
35
|
this._adjustTextAreaHeight();
|
|
38
36
|
}
|
|
39
37
|
if (_changedProperties.has("variables")) {
|
|
40
|
-
this._parser = new Parser(this.variables, this.formulaRegex, this.allowedNumbers, this.allowedOperators, this.variableType
|
|
38
|
+
this._parser = new Parser(this.variables, this.minSuggestionLen, this.formulaRegex, this.allowedNumbers, this.allowedOperators, this.variableType);
|
|
41
39
|
this.recommendations = Array.from(this.variables.keys());
|
|
42
40
|
}
|
|
43
41
|
}
|
|
@@ -47,11 +45,11 @@ let FormulaEditor = class FormulaEditor extends LitElement {
|
|
|
47
45
|
handleContentUpdate(event) {
|
|
48
46
|
event.preventDefault();
|
|
49
47
|
this.lastInputType = event.inputType;
|
|
50
|
-
this.
|
|
48
|
+
this.formulaString = event.target.value;
|
|
51
49
|
this.parseInput();
|
|
52
50
|
}
|
|
53
51
|
_adjustTextAreaHeight() {
|
|
54
|
-
if (!this.
|
|
52
|
+
if (!this.formulaString)
|
|
55
53
|
this.editor.style.height = "var(--fe-height, 30px)";
|
|
56
54
|
if (this.editor.scrollHeight > this.editor.clientHeight)
|
|
57
55
|
this.editor.style.height = String(this.editor.scrollHeight + 5).concat("px");
|
|
@@ -63,9 +61,9 @@ let FormulaEditor = class FormulaEditor extends LitElement {
|
|
|
63
61
|
*/
|
|
64
62
|
parseInput(recommendation = "") {
|
|
65
63
|
this.currentCursorPosition = this.editor.selectionStart;
|
|
66
|
-
const
|
|
67
|
-
this.recommendations =
|
|
68
|
-
this.errorString =
|
|
64
|
+
const { recommendations, errorString, formattedString, newCursorPosition } = this._parser.parseInput(this.formulaString, this.currentCursorPosition, recommendation);
|
|
65
|
+
this.recommendations = recommendations;
|
|
66
|
+
this.errorString = errorString;
|
|
69
67
|
/**
|
|
70
68
|
* Don't modify the text stream manually if the text is being composed,
|
|
71
69
|
* unless the user manually chooses to do so by selecting a recommendation.
|
|
@@ -74,11 +72,11 @@ let FormulaEditor = class FormulaEditor extends LitElement {
|
|
|
74
72
|
* @see https://bugs.chromium.org/p/chromium/issues/detail?id=689541
|
|
75
73
|
*/
|
|
76
74
|
if (this.lastInputType !== "insertCompositionText" || recommendation) {
|
|
77
|
-
this.
|
|
75
|
+
this.formulaString = formattedString;
|
|
78
76
|
}
|
|
79
77
|
if (Boolean(recommendation)) {
|
|
80
78
|
this.recommendations = [];
|
|
81
|
-
this.currentCursorPosition =
|
|
79
|
+
this.currentCursorPosition = newCursorPosition;
|
|
82
80
|
/* update cursor position in text area */
|
|
83
81
|
setTimeout(() => {
|
|
84
82
|
this.editor.setSelectionRange(this.currentCursorPosition, this.currentCursorPosition);
|
|
@@ -86,18 +84,19 @@ let FormulaEditor = class FormulaEditor extends LitElement {
|
|
|
86
84
|
}
|
|
87
85
|
this.dispatchEvent(new CustomEvent("fw-formula-content-changed", {
|
|
88
86
|
detail: {
|
|
89
|
-
formulaString: this.
|
|
87
|
+
formulaString: this.formulaString,
|
|
90
88
|
error: this.errorString,
|
|
91
89
|
recommendations: this.recommendations,
|
|
92
|
-
formulaTokens: getFormulaTokens(this.
|
|
90
|
+
formulaTokens: getFormulaTokens(this.formulaString || "", this.formulaRegex)
|
|
93
91
|
},
|
|
94
92
|
bubbles: true,
|
|
95
93
|
}));
|
|
96
94
|
}
|
|
97
95
|
formatFormula() {
|
|
98
|
-
if (!this.
|
|
96
|
+
if (!this.formulaString)
|
|
99
97
|
return;
|
|
100
|
-
|
|
98
|
+
const newContent = this._parser.addParentheses(this.formulaString);
|
|
99
|
+
this.formulaString = newContent && newContent.length ? newContent : this.formulaString;
|
|
101
100
|
this.parseInput();
|
|
102
101
|
this.recommendations = [];
|
|
103
102
|
}
|
|
@@ -131,12 +130,12 @@ let FormulaEditor = class FormulaEditor extends LitElement {
|
|
|
131
130
|
return html `
|
|
132
131
|
<style>${FormulaEditorStyles}</style>
|
|
133
132
|
|
|
134
|
-
${this.label ? html `<label for="
|
|
133
|
+
${this.label ? html `<label for="fw-formula-editor" class="editor-label">${this.label}</label>` : ""}
|
|
135
134
|
|
|
136
135
|
<textarea
|
|
137
|
-
id="
|
|
136
|
+
id="fw-formula-editor"
|
|
138
137
|
class=${this.errorString?.length ? "error" : ""}
|
|
139
|
-
.value=${this.
|
|
138
|
+
.value=${this.formulaString}
|
|
140
139
|
.placeholder=${this.placeholder}
|
|
141
140
|
spellcheck="false"
|
|
142
141
|
autocomplete="off"
|
|
@@ -174,7 +173,7 @@ __decorate([
|
|
|
174
173
|
], FormulaEditor.prototype, "isFocused", void 0);
|
|
175
174
|
__decorate([
|
|
176
175
|
property()
|
|
177
|
-
], FormulaEditor.prototype, "
|
|
176
|
+
], FormulaEditor.prototype, "formulaString", void 0);
|
|
178
177
|
__decorate([
|
|
179
178
|
property()
|
|
180
179
|
], FormulaEditor.prototype, "placeholder", void 0);
|
|
@@ -187,6 +186,9 @@ __decorate([
|
|
|
187
186
|
__decorate([
|
|
188
187
|
property()
|
|
189
188
|
], FormulaEditor.prototype, "variables", void 0);
|
|
189
|
+
__decorate([
|
|
190
|
+
property()
|
|
191
|
+
], FormulaEditor.prototype, "variableType", void 0);
|
|
190
192
|
__decorate([
|
|
191
193
|
property()
|
|
192
194
|
], FormulaEditor.prototype, "minSuggestionLen", void 0);
|
|
@@ -203,10 +205,7 @@ __decorate([
|
|
|
203
205
|
property()
|
|
204
206
|
], FormulaEditor.prototype, "allowedOperators", void 0);
|
|
205
207
|
__decorate([
|
|
206
|
-
|
|
207
|
-
], FormulaEditor.prototype, "variableType", void 0);
|
|
208
|
-
__decorate([
|
|
209
|
-
query("#wysiwyg-editor")
|
|
208
|
+
query("#fw-formula-editor")
|
|
210
209
|
], FormulaEditor.prototype, "editor", void 0);
|
|
211
210
|
__decorate([
|
|
212
211
|
query("suggestion-menu")
|
|
@@ -7,7 +7,7 @@ export const FormulaEditorStyles = css `
|
|
|
7
7
|
margin-bottom: var(--fe-label-margin-bottom, 1px);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
#
|
|
10
|
+
#fw-formula-editor {
|
|
11
11
|
display: block;
|
|
12
12
|
resize: none;
|
|
13
13
|
padding: var(--fe-padding, 4px);
|
|
@@ -26,13 +26,13 @@ export const FormulaEditorStyles = css `
|
|
|
26
26
|
line-height: 1.5;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
#
|
|
29
|
+
#fw-formula-editor:empty:before {
|
|
30
30
|
content: attr(placeholder);
|
|
31
31
|
color: var(--fe-placeholder-color, grey);
|
|
32
32
|
pointer-events: none;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
#
|
|
35
|
+
#fw-formula-editor.error {
|
|
36
36
|
text-decoration: underline;
|
|
37
37
|
-webkit-text-decoration-style: wavy;
|
|
38
38
|
text-decoration-style: wavy;
|
|
@@ -35,7 +35,7 @@ export const SuggestionMenuStyles = css `
|
|
|
35
35
|
|
|
36
36
|
/* Scrollbar styling */
|
|
37
37
|
::-webkit-scrollbar {
|
|
38
|
-
width:
|
|
38
|
+
width: 7px;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
::-webkit-scrollbar-track {
|
|
@@ -50,9 +50,4 @@ export const SuggestionMenuStyles = css `
|
|
|
50
50
|
::-webkit-scrollbar-thumb:hover {
|
|
51
51
|
background: #aaa;
|
|
52
52
|
}
|
|
53
|
-
|
|
54
|
-
/* Optional shadow for the dropdown */
|
|
55
|
-
.content {
|
|
56
|
-
box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.13);
|
|
57
|
-
}
|
|
58
53
|
`;
|
|
@@ -13,7 +13,7 @@ let SuggestionMenu = class SuggestionMenu extends LitElement {
|
|
|
13
13
|
this.recommendations = [];
|
|
14
14
|
this.recommendationLabels = new Map();
|
|
15
15
|
this.onRecommendationClick = () => { };
|
|
16
|
-
this.
|
|
16
|
+
this._currentFocusedIndex = -1;
|
|
17
17
|
}
|
|
18
18
|
scrollToSelectedRecommendation(index) {
|
|
19
19
|
const listItem = this.suggestionList?.querySelectorAll("li")[index];
|
|
@@ -28,27 +28,27 @@ let SuggestionMenu = class SuggestionMenu extends LitElement {
|
|
|
28
28
|
navigate(direction) {
|
|
29
29
|
if (!this.recommendations?.length)
|
|
30
30
|
return;
|
|
31
|
-
let newIndex = this.
|
|
31
|
+
let newIndex = this._currentFocusedIndex;
|
|
32
32
|
if (direction === "down")
|
|
33
|
-
newIndex = (this.
|
|
33
|
+
newIndex = (this._currentFocusedIndex + 1) % this.recommendations.length;
|
|
34
34
|
else if (direction === "up")
|
|
35
|
-
newIndex = (this.
|
|
36
|
-
this.
|
|
35
|
+
newIndex = (this._currentFocusedIndex - 1 + this.recommendations.length) % this.recommendations.length;
|
|
36
|
+
this._currentFocusedIndex = newIndex;
|
|
37
37
|
this.scrollToSelectedRecommendation(newIndex);
|
|
38
38
|
}
|
|
39
|
-
handleRecommendationSelect(index = this.
|
|
39
|
+
handleRecommendationSelect(index = this._currentFocusedIndex) {
|
|
40
40
|
const recommendation = this.recommendations[index];
|
|
41
41
|
if (!recommendation)
|
|
42
42
|
return;
|
|
43
43
|
this.onRecommendationClick(recommendation);
|
|
44
|
-
this.
|
|
44
|
+
this._currentFocusedIndex = -1;
|
|
45
45
|
}
|
|
46
46
|
render() {
|
|
47
47
|
return html `
|
|
48
48
|
<style>${SuggestionMenuStyles}</style>
|
|
49
|
-
<ul class="
|
|
49
|
+
<ul class="fw-formula-suggestion-menu" @mousedown=${(e) => e.preventDefault()}>
|
|
50
50
|
${this.recommendations.map((recommendation, index) => html `<li
|
|
51
|
-
class="${this.
|
|
51
|
+
class="${this._currentFocusedIndex === index ? "selected" : ""}"
|
|
52
52
|
@click=${(e) => this.handleRecommendationSelect(index)}
|
|
53
53
|
>${this.recommendationLabels.get(recommendation) ?? recommendation}</li>`)}
|
|
54
54
|
</ul>
|
|
@@ -66,9 +66,9 @@ __decorate([
|
|
|
66
66
|
], SuggestionMenu.prototype, "onRecommendationClick", void 0);
|
|
67
67
|
__decorate([
|
|
68
68
|
state()
|
|
69
|
-
], SuggestionMenu.prototype, "
|
|
69
|
+
], SuggestionMenu.prototype, "_currentFocusedIndex", void 0);
|
|
70
70
|
__decorate([
|
|
71
|
-
query(".
|
|
71
|
+
query(".fw-formula-suggestion-menu")
|
|
72
72
|
], SuggestionMenu.prototype, "suggestionList", void 0);
|
|
73
73
|
SuggestionMenu = __decorate([
|
|
74
74
|
customElement("suggestion-menu")
|
|
@@ -4,14 +4,6 @@ export var Expectation;
|
|
|
4
4
|
Expectation[Expectation["OPERATOR"] = 1] = "OPERATOR";
|
|
5
5
|
Expectation[Expectation["UNDEFINED"] = 2] = "UNDEFINED";
|
|
6
6
|
})(Expectation || (Expectation = {}));
|
|
7
|
-
export var Operator;
|
|
8
|
-
(function (Operator) {
|
|
9
|
-
Operator["PLUS"] = "+";
|
|
10
|
-
Operator["MINUS"] = "-";
|
|
11
|
-
Operator["MUL"] = "*";
|
|
12
|
-
Operator["DIV"] = "/";
|
|
13
|
-
Operator["NONE"] = "";
|
|
14
|
-
})(Operator || (Operator = {}));
|
|
15
7
|
export class Formula {
|
|
16
8
|
constructor(name, formulaString, precision = -1) {
|
|
17
9
|
this.error = null;
|
|
@@ -3,10 +3,10 @@ import { Recommender } from "./recommendor.js";
|
|
|
3
3
|
import { Stack } from "./stack.js";
|
|
4
4
|
import { Queue } from "./queue.js";
|
|
5
5
|
import { Expectation } from "../types";
|
|
6
|
-
import { operatorPrecedence, unaryOperators } from "./constants.js";
|
|
6
|
+
import { operatorPrecedence, unaryOperators, mathematicalOperators } from "./constants.js";
|
|
7
7
|
import { getFormulaTokens } from "./get-formula-tokens.js";
|
|
8
8
|
export class Parser {
|
|
9
|
-
constructor(variables, formulaRegex, allowedNumbers, allowedOperators, variableType
|
|
9
|
+
constructor(variables, minSuggestionLen, formulaRegex = /[A-Za-z0-9_#@]+|[-+(),*^/\s]/g, allowedNumbers = true, allowedOperators = mathematicalOperators, variableType = "") {
|
|
10
10
|
this.variables = variables;
|
|
11
11
|
this.formulaRegex = formulaRegex;
|
|
12
12
|
this._recommender = new Recommender(Array.from(this.variables.keys()), minSuggestionLen);
|
|
@@ -18,13 +18,10 @@ export class Queue {
|
|
|
18
18
|
}
|
|
19
19
|
peek() {
|
|
20
20
|
if (this.isEmpty())
|
|
21
|
-
|
|
21
|
+
return undefined;
|
|
22
22
|
return this._elements[this._head];
|
|
23
23
|
}
|
|
24
24
|
isEmpty() {
|
|
25
25
|
return this._head === this._tail;
|
|
26
26
|
}
|
|
27
|
-
print() {
|
|
28
|
-
console.log(this._elements);
|
|
29
|
-
}
|
|
30
27
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { matchSorter } from "match-sorter";
|
|
2
2
|
export class Recommender {
|
|
3
3
|
constructor(variables, minSuggestionLen) {
|
|
4
|
-
this.
|
|
4
|
+
this._wordLimitForSuggestions = minSuggestionLen > 0 ? minSuggestionLen : 1;
|
|
5
5
|
this.variableList = variables;
|
|
6
6
|
}
|
|
7
|
-
getRecommendations(
|
|
8
|
-
if (
|
|
7
|
+
getRecommendations(inputString) {
|
|
8
|
+
if (inputString.length < this._wordLimitForSuggestions)
|
|
9
9
|
return [];
|
|
10
|
-
const recommendations = matchSorter(this.variableList,
|
|
11
|
-
if (recommendations.length === 0
|
|
10
|
+
const recommendations = matchSorter(this.variableList, inputString);
|
|
11
|
+
if (recommendations.length === 0)
|
|
12
12
|
return [];
|
|
13
13
|
return recommendations;
|
|
14
14
|
}
|
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.39",
|
|
4
4
|
"description": "A WYSIWYG type formula editor",
|
|
5
5
|
"main": "dist/formula-editor/src/formula-editor.js",
|
|
6
6
|
"exports": {
|
|
@@ -31,5 +31,5 @@
|
|
|
31
31
|
"@types/big.js": "^6.1.6",
|
|
32
32
|
"es-dev-server": "^2.1.0"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "a3fb82b15d40e80873eaefdc8ab5b1d0ae13096c"
|
|
35
35
|
}
|