@fw-components/formula-editor 2.3.4-linting.1 → 2.3.4-notion-update.0

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.
@@ -5,20 +5,16 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { html, LitElement } from "lit";
8
- import { customElement, property, query, state } from "lit/decorators.js";
9
- import { getFormulaTokens } from "./utils/get-formula-tokens.js";
8
+ import { customElement, property, state, query } from "lit/decorators.js";
9
+ import "./suggestion-menu.js";
10
10
  import { Parser } from "./utils/parser.js";
11
11
  import { FormulaEditorStyles } from "./styles/editor.js";
12
+ import { getFormulaTokens } from "./utils/get-formula-tokens.js";
12
13
  let FormulaEditor = class FormulaEditor extends LitElement {
13
14
  constructor() {
14
15
  super(...arguments);
15
16
  this.recommendations = [];
16
17
  this.currentCursorPosition = 0;
17
- /**
18
- * user input event type
19
- */
20
- this.lastInputType = "";
21
- this._selectedRecommendation = "";
22
18
  this.isFocused = false;
23
19
  /**
24
20
  * Text area input value
@@ -26,14 +22,10 @@ let FormulaEditor = class FormulaEditor extends LitElement {
26
22
  this.formulaString = "";
27
23
  this.placeholder = "Type your formula...";
28
24
  this.recommendationLabels = new Map();
29
- this.label = "";
30
25
  this.variables = new Map();
31
- this.variableType = "";
32
26
  this.minSuggestionLen = 2;
33
27
  this.errorString = "";
34
- this.formulaRegex = /.*/;
35
28
  this.allowedNumbers = true;
36
- this.allowedOperators = new Set();
37
29
  }
38
30
  updated(_changedProperties) {
39
31
  if (_changedProperties.has("formulaString")) {
@@ -74,7 +66,7 @@ let FormulaEditor = class FormulaEditor extends LitElement {
74
66
  this.currentCursorPosition = this.editor.selectionStart;
75
67
  const { recommendations, errorString, formattedString, newCursorPosition } = this._parser.parseInput(this.formulaString, this.currentCursorPosition, recommendation);
76
68
  this.recommendations = recommendations;
77
- this.errorString = errorString || "";
69
+ this.errorString = errorString;
78
70
  /**
79
71
  * Don't modify the text stream manually if the text is being composed,
80
72
  * unless the user manually chooses to do so by selecting a recommendation.
@@ -100,7 +92,7 @@ let FormulaEditor = class FormulaEditor extends LitElement {
100
92
  recommendations: this.recommendations,
101
93
  formulaTokens: getFormulaTokens(this.formulaString || "", this.formulaRegex)
102
94
  },
103
- bubbles: true
95
+ bubbles: true,
104
96
  }));
105
97
  }
106
98
  formatFormula() {
@@ -139,9 +131,7 @@ let FormulaEditor = class FormulaEditor extends LitElement {
139
131
  }
140
132
  render() {
141
133
  return html `
142
- <style>
143
- ${FormulaEditorStyles}
144
- </style>
134
+ <style>${FormulaEditorStyles}</style>
145
135
 
146
136
  ${this.label ? html `<label for="fw-formula-editor" class="editor-label">${this.label}</label>` : ""}
147
137
 
@@ -165,7 +155,7 @@ let FormulaEditor = class FormulaEditor extends LitElement {
165
155
  .onRecommendationClick=${this.onRecommendationClick.bind(this)}
166
156
  .recommendationLabels=${this.recommendationLabels}
167
157
  ></suggestion-menu>`
168
- : ""}
158
+ : ''}
169
159
  `;
170
160
  }
171
161
  };
@@ -191,31 +181,31 @@ __decorate([
191
181
  property()
192
182
  ], FormulaEditor.prototype, "placeholder", void 0);
193
183
  __decorate([
194
- property({ type: Object })
184
+ property()
195
185
  ], FormulaEditor.prototype, "recommendationLabels", void 0);
196
186
  __decorate([
197
- property({ type: String })
187
+ property()
198
188
  ], FormulaEditor.prototype, "label", void 0);
199
189
  __decorate([
200
- property({ type: Object })
190
+ property()
201
191
  ], FormulaEditor.prototype, "variables", void 0);
202
192
  __decorate([
203
- property({ type: String })
193
+ property()
204
194
  ], FormulaEditor.prototype, "variableType", void 0);
205
195
  __decorate([
206
- property({ type: Number })
196
+ property()
207
197
  ], FormulaEditor.prototype, "minSuggestionLen", void 0);
208
198
  __decorate([
209
- property({ type: String })
199
+ property()
210
200
  ], FormulaEditor.prototype, "errorString", void 0);
211
201
  __decorate([
212
- property({ type: Object })
202
+ property()
213
203
  ], FormulaEditor.prototype, "formulaRegex", void 0);
214
204
  __decorate([
215
- property({ type: Boolean })
205
+ property()
216
206
  ], FormulaEditor.prototype, "allowedNumbers", void 0);
217
207
  __decorate([
218
- property({ type: Object })
208
+ property()
219
209
  ], FormulaEditor.prototype, "allowedOperators", void 0);
220
210
  __decorate([
221
211
  query("#fw-formula-editor")
@@ -45,13 +45,12 @@ let SuggestionMenu = class SuggestionMenu extends LitElement {
45
45
  }
46
46
  render() {
47
47
  return html `
48
- <style>
49
- ${SuggestionMenuStyles}
50
- </style>
48
+ <style>${SuggestionMenuStyles}</style>
51
49
  <ul class="fw-formula-suggestion-menu" @mousedown=${(e) => e.preventDefault()}>
52
- ${this.recommendations.map((recommendation, index) => html `<li class="${this._currentFocusedIndex === index ? "selected" : ""}" @click=${(e) => this.handleRecommendationSelect(index)}>
53
- ${this.recommendationLabels.get(recommendation) ?? recommendation}
54
- </li>`)}
50
+ ${this.recommendations.map((recommendation, index) => html `<li
51
+ class="${this._currentFocusedIndex === index ? "selected" : ""}"
52
+ @click=${(e) => this.handleRecommendationSelect(index)}
53
+ >${this.recommendationLabels.get(recommendation) ?? recommendation}</li>`)}
55
54
  </ul>
56
55
  `;
57
56
  }
@@ -1,10 +1,10 @@
1
- import { mathematicalOperators, operatorPrecedence, unaryOperators } from "./constants.js";
2
- import { getFormulaTokens } from "./get-formula-tokens.js";
3
- import { Queue } from "./queue.js";
1
+ import Big from "big.js";
4
2
  import { Recommender } from "./recommendor.js";
5
3
  import { Stack } from "./stack.js";
6
- import Big from "big.js";
4
+ import { Queue } from "./queue.js";
7
5
  import { Expectation } from "../types";
6
+ import { operatorPrecedence, unaryOperators, mathematicalOperators } from "./constants.js";
7
+ import { getFormulaTokens } from "./get-formula-tokens.js";
8
8
  export class Parser {
9
9
  constructor(variables, minSuggestionLen, formulaRegex = /[A-Za-z0-9_#@.]+|[-+(),*^/\s]/g, allowedNumbers = true, allowedOperators = mathematicalOperators, variableType = "") {
10
10
  this.variables = variables;
@@ -20,7 +20,7 @@ export class Parser {
20
20
  return !Number.isNaN(Number(value));
21
21
  }
22
22
  formatFormulaToken(token) {
23
- for (const existingKey of this.variables.keys()) {
23
+ for (let existingKey of this.variables.keys()) {
24
24
  if (existingKey.toLowerCase() === token.toLowerCase()) {
25
25
  return existingKey;
26
26
  }
@@ -38,7 +38,7 @@ export class Parser {
38
38
  recommendations: [],
39
39
  formattedString: "",
40
40
  newCursorPosition: prevCurPos ?? -1,
41
- errorString: null
41
+ errorString: null,
42
42
  };
43
43
  if (!formula.trim() && recommendation) {
44
44
  parseOutput.formattedString = recommendation;
@@ -73,6 +73,7 @@ export class Parser {
73
73
  recommendation = null;
74
74
  return;
75
75
  }
76
+ ;
76
77
  const updatedTokenLength = recommendation.length - token.length;
77
78
  parseOutput.newCursorPosition = Math.min(parseOutput.newCursorPosition, formula.length) + updatedTokenLength;
78
79
  token = recommendation;
@@ -83,7 +84,7 @@ export class Parser {
83
84
  /**
84
85
  * Error checks
85
86
  * skip error check if there is one already
86
- */
87
+ */
87
88
  if (expectation != Expectation.UNDEFINED) {
88
89
  /**
89
90
  * Unknown symbol/variable/word
@@ -100,37 +101,33 @@ export class Parser {
100
101
  parseOutput.errorString = "Unexpected closing bracket. Make sure all opening brackets '(' have matching closing brackets ')'.";
101
102
  expectation = Expectation.UNDEFINED;
102
103
  }
103
- else if (
104
104
  /**
105
105
  * Operator or ')' after an operator (Eg: '23 / *' or '23 / )')
106
106
  * No error for Unary `+` and `-` as they might represent a positive or negative number respectively
107
107
  */
108
- expectation === Expectation.VARIABLE &&
109
- !isNumber &&
110
- !isSpace &&
111
- token != "(" &&
112
- !(unaryOperators.includes(token) && (!parsedString.trim() || previousToken === "(" || this.allowedOperators.has(previousToken)))) {
113
- parseOutput.errorString = `Please use ${this.variableType} ${this.variableType && this.allowedNumbers ? " or " : ""} ${this.allowedNumbers ? "numbers" : ""} after '${previousToken}'.`;
108
+ else if (expectation === Expectation.VARIABLE && !isNumber && !isSpace && token != "("
109
+ && !((unaryOperators.includes(token)) && (!parsedString.trim() || previousToken === "(" || this.allowedOperators.has(previousToken)))) {
110
+ parseOutput.errorString = `Please use ${this.variableType} ${this.variableType && this.allowedNumbers ? " or " : ''} ${this.allowedNumbers ? "numbers" : ""} after '${previousToken}'.`;
114
111
  expectation = Expectation.UNDEFINED;
115
112
  }
113
+ /**
114
+ * Multiple number/variable together without operator
115
+ */
116
116
  else if (expectation === Expectation.OPERATOR && !isOperator && !isSpace && token != ")") {
117
- /**
118
- * Multiple number/variable together without operator
119
- */
120
117
  parseOutput.errorString = `Please use mathematical operators (${Array.from(this.allowedOperators).join(" ")}) after '${previousToken}'.`;
121
118
  expectation = Expectation.UNDEFINED;
122
119
  }
120
+ /**
121
+ * division by zero
122
+ */
123
123
  else if (isNumber && previousToken === "/" && (this.variables.get(token) === 0 || Number(token) === 0)) {
124
- /**
125
- * division by zero
126
- */
127
124
  parseOutput.errorString = `Division by zero is not possible.`;
128
125
  expectation = Expectation.UNDEFINED;
129
126
  }
127
+ /**
128
+ * Empty brackets
129
+ */
130
130
  else if (previousToken === "(" && token === ")") {
131
- /**
132
- * Empty brackets
133
- */
134
131
  parseOutput.errorString = `Please don't use empty brackets ().`;
135
132
  expectation = Expectation.UNDEFINED;
136
133
  }
@@ -181,7 +178,7 @@ export class Parser {
181
178
  let currentTokens = "";
182
179
  // Check if variables include unary operators `-` and `+`.
183
180
  for (const token of tokens) {
184
- if (unaryOperators.includes(token) && (!currentTokens.trim() || previousToken === "(" || this.allowedOperators.has(previousToken))) {
181
+ if ((unaryOperators.includes(token)) && (!currentTokens.trim() || previousToken === "(" || this.allowedOperators.has(previousToken))) {
185
182
  carriedToken = token;
186
183
  }
187
184
  else if (carriedToken) {
@@ -238,7 +235,7 @@ export class Parser {
238
235
  let parsedLeftExpression;
239
236
  let parsedRightExpression;
240
237
  // check if the symbol is a number or variable or unaryOperatorPreceded Variable
241
- if ((unaryOperators.includes(symbol[0]) && this.variables.has(symbol.substring(1))) ||
238
+ if (((unaryOperators.includes(symbol[0])) && this.variables.has(symbol.substring(1))) ||
242
239
  this.variables.has(symbol) ||
243
240
  (!Number.isNaN(parseFloat(symbol)) && Number.isFinite(parseFloat(symbol)))) {
244
241
  resultStack.push(symbol);
@@ -246,14 +243,21 @@ export class Parser {
246
243
  }
247
244
  // If symbol is an operator, check operatorStack, adds brackets accordingly to the result and add it to operatorStack
248
245
  else if (Object.keys(operatorPrecedence).includes(symbol)) {
249
- const [rightExpression, leftExpression, operatorA, operatorB] = [resultStack.pop(), resultStack.pop(), operatorStack.pop(), operatorStack.pop()];
250
- if (operatorPrecedence[operatorB] <= operatorPrecedence[symbol] || (operatorPrecedence[operatorB] === operatorPrecedence[symbol] && ["/", "-"].includes(symbol))) {
246
+ const [rightExpression, leftExpression, operatorA, operatorB] = [
247
+ resultStack.pop(),
248
+ resultStack.pop(),
249
+ operatorStack.pop(),
250
+ operatorStack.pop(),
251
+ ];
252
+ if ((operatorPrecedence[operatorB] <= operatorPrecedence[symbol]) ||
253
+ (operatorPrecedence[operatorB] === operatorPrecedence[symbol] && ["/", "-"].includes(symbol))) {
251
254
  parsedLeftExpression = `(${leftExpression})`;
252
255
  }
253
256
  else {
254
257
  parsedLeftExpression = leftExpression;
255
258
  }
256
- if (operatorPrecedence[operatorA] <= operatorPrecedence[symbol] || (operatorPrecedence[operatorA] === operatorPrecedence[symbol] && ["/", "-"].includes(symbol))) {
259
+ if (operatorPrecedence[operatorA] <= operatorPrecedence[symbol] ||
260
+ (operatorPrecedence[operatorA] === operatorPrecedence[symbol] && ["/", "-"].includes(symbol))) {
257
261
  parsedRightExpression = `(${rightExpression})`;
258
262
  }
259
263
  else {
@@ -273,7 +277,7 @@ export class Parser {
273
277
  const formulaRPN = this.buildRPN(formula);
274
278
  const calculationResult = {
275
279
  result: undefined,
276
- errorString: null
280
+ errorString: null,
277
281
  };
278
282
  if (!formulaRPN)
279
283
  return calculationResult;
@@ -283,7 +287,7 @@ export class Parser {
283
287
  if (!this.allowedOperators.has(frontItem)) {
284
288
  const [sign, variableKey] = /^[+-]/.test(frontItem) ? [frontItem[0], frontItem.slice(1)] : ["", frontItem];
285
289
  const operandValue = Number.parseFloat(this.variables.get(variableKey)?.toString() ?? variableKey);
286
- const number = Number.parseFloat(`${sign}1`) * operandValue;
290
+ const number = Number.parseFloat(sign + "1") * operandValue;
287
291
  calcStack.push(Big(number));
288
292
  }
289
293
  else {
@@ -317,7 +321,7 @@ export class Parser {
317
321
  }
318
322
  }
319
323
  catch (error) {
320
- calculationResult.errorString = error instanceof Error ? error.message : "Unknown error during calculation";
324
+ calculationResult.errorString = error;
321
325
  return calculationResult;
322
326
  }
323
327
  }
@@ -326,8 +330,7 @@ export class Parser {
326
330
  calculationResult.errorString = "Calculation error: Empty result stack";
327
331
  return calculationResult;
328
332
  }
329
- const topValue = calcStack.top();
330
- calculationResult.result = topValue !== undefined ? parseFloat(topValue.toString()) : undefined;
333
+ calculationResult.result = parseFloat(calcStack.top().toString());
331
334
  return calculationResult;
332
335
  }
333
336
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fw-components/formula-editor",
3
- "version": "2.3.4-linting.1",
3
+ "version": "2.3.4-notion-update.0",
4
4
  "description": "A WYSIWYG type formula editor",
5
5
  "main": "dist/formula-editor/src/formula-editor.js",
6
6
  "exports": {
@@ -13,21 +13,27 @@
13
13
  "access": "public"
14
14
  },
15
15
  "scripts": {
16
+ "start": "es-dev-server --app-index ../../index.html --node-resolve --watch --open",
16
17
  "build": "tsc --composite false",
17
18
  "dev": "tsc -w --composite false",
18
19
  "prepublishOnly": "npm run build"
19
20
  },
20
21
  "dependencies": {
21
- "@fw-components/styles": "^2.3.4-linting.0",
22
- "big.js": "^7.0.1",
23
- "lit": "^3.3.1",
24
- "match-sorter": "^8.1.0"
22
+ "@fw-components/styles": "^2.3.4-notion-update.0",
23
+ "big.js": "^6.2.1",
24
+ "lit": "^2.1.2",
25
+ "match-sorter": "^8.0.0",
26
+ "typescript": "^5.0.4"
27
+ },
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/fundwave/fw-components"
25
31
  },
26
32
  "author": "The Fundwave Authors",
27
33
  "license": "ISC",
28
34
  "devDependencies": {
29
- "@types/big.js": "^6.2.2",
30
- "typescript": "^5.9.3"
35
+ "@types/big.js": "^6.1.6",
36
+ "es-dev-server": "^2.1.0"
31
37
  },
32
- "gitHead": "7b4b36d9df7ba5ef69cb0fa7944aa2d07a6f6994"
38
+ "gitHead": "8c066ab176741959347040fdd45b9bf3906a55f8"
33
39
  }
package/tsconfig.json CHANGED
@@ -1,9 +1,20 @@
1
1
  {
2
- "extends": "../../tsconfig.json",
3
- "compilerOptions": {
4
- "rootDir": "src",
5
- "outDir": "./dist",
6
- "allowJs": true
7
- },
8
- "include": ["src"]
9
- }
2
+ "compilerOptions": {
3
+ "experimentalDecorators": true,
4
+ "useDefineForClassFields":false,
5
+ "outDir": "./dist",
6
+ "rootDir": "../",
7
+ "target": "esnext",
8
+ "module": "esnext",
9
+ "moduleResolution": "node",
10
+ "declaration": true,
11
+ "declarationDir": "./dist/types",
12
+ "composite": false,
13
+ "lib": ["esnext", "dom"],
14
+ "esModuleInterop": true,
15
+ "skipLibCheck": true,
16
+ "noEmitOnError": false
17
+ },
18
+ "include": ["src/**/*.ts"],
19
+ "exclude": ["node_modules", "dist"]
20
+ }