@bgroup/wise-form 1.0.1

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 (319) hide show
  1. package/README.md +34 -0
  2. package/dist/components/ui/Checkbox.d.ts +14 -0
  3. package/dist/components/ui/Checkbox.d.ts.map +1 -0
  4. package/dist/components/ui/Checkbox.js +43 -0
  5. package/dist/components/ui/Checkbox.js.map +1 -0
  6. package/dist/components/ui/CheckboxGroup.d.ts +15 -0
  7. package/dist/components/ui/CheckboxGroup.d.ts.map +1 -0
  8. package/dist/components/ui/CheckboxGroup.js +33 -0
  9. package/dist/components/ui/CheckboxGroup.js.map +1 -0
  10. package/dist/components/ui/Input.d.ts +14 -0
  11. package/dist/components/ui/Input.d.ts.map +1 -0
  12. package/dist/components/ui/Input.js +49 -0
  13. package/dist/components/ui/Input.js.map +1 -0
  14. package/dist/components/ui/Radio.d.ts +14 -0
  15. package/dist/components/ui/Radio.d.ts.map +1 -0
  16. package/dist/components/ui/Radio.js +43 -0
  17. package/dist/components/ui/Radio.js.map +1 -0
  18. package/dist/components/ui/Select.d.ts +18 -0
  19. package/dist/components/ui/Select.d.ts.map +1 -0
  20. package/dist/components/ui/Select.js +44 -0
  21. package/dist/components/ui/Select.js.map +1 -0
  22. package/dist/components/ui/Textarea.d.ts +13 -0
  23. package/dist/components/ui/Textarea.d.ts.map +1 -0
  24. package/dist/components/ui/Textarea.js +42 -0
  25. package/dist/components/ui/Textarea.js.map +1 -0
  26. package/dist/components/ui/index.d.ts +13 -0
  27. package/dist/components/ui/index.d.ts.map +1 -0
  28. package/dist/components/ui/index.js +7 -0
  29. package/dist/components/ui/index.js.map +1 -0
  30. package/dist/form/index.d.ts +10 -0
  31. package/dist/form/index.d.ts.map +1 -0
  32. package/dist/form/index.js +5 -0
  33. package/dist/form/index.js.map +1 -0
  34. package/dist/form/interfaces/field-container.d.ts +8 -0
  35. package/dist/form/interfaces/field-container.d.ts.map +1 -0
  36. package/dist/form/interfaces/field-container.js +2 -0
  37. package/dist/form/interfaces/field-container.js.map +1 -0
  38. package/dist/form/interfaces/interfaces.d.ts +8 -0
  39. package/dist/form/interfaces/interfaces.d.ts.map +1 -0
  40. package/dist/form/interfaces/interfaces.js +2 -0
  41. package/dist/form/interfaces/interfaces.js.map +1 -0
  42. package/dist/form/interfaces/settings.d.ts +10 -0
  43. package/dist/form/interfaces/settings.d.ts.map +1 -0
  44. package/dist/form/interfaces/settings.js +2 -0
  45. package/dist/form/interfaces/settings.js.map +1 -0
  46. package/dist/form/interfaces/template.d.ts +6 -0
  47. package/dist/form/interfaces/template.d.ts.map +1 -0
  48. package/dist/form/interfaces/template.js +2 -0
  49. package/dist/form/interfaces/template.js.map +1 -0
  50. package/dist/form/interfaces/wise-form-specs.d.ts +9 -0
  51. package/dist/form/interfaces/wise-form-specs.d.ts.map +1 -0
  52. package/dist/form/interfaces/wise-form-specs.js +2 -0
  53. package/dist/form/interfaces/wise-form-specs.js.map +1 -0
  54. package/dist/form/view/components/containers/index.d.ts +3 -0
  55. package/dist/form/view/components/containers/index.d.ts.map +1 -0
  56. package/dist/form/view/components/containers/index.js +12 -0
  57. package/dist/form/view/components/containers/index.js.map +1 -0
  58. package/dist/form/view/components/error.d.ts +5 -0
  59. package/dist/form/view/components/error.d.ts.map +1 -0
  60. package/dist/form/view/components/error.js +8 -0
  61. package/dist/form/view/components/error.js.map +1 -0
  62. package/dist/form/view/components/field/container.d.ts +5 -0
  63. package/dist/form/view/components/field/container.d.ts.map +1 -0
  64. package/dist/form/view/components/field/container.js +5 -0
  65. package/dist/form/view/components/field/container.js.map +1 -0
  66. package/dist/form/view/components/field/index.d.ts +18 -0
  67. package/dist/form/view/components/field/index.d.ts.map +1 -0
  68. package/dist/form/view/components/field/index.js +89 -0
  69. package/dist/form/view/components/field/index.js.map +1 -0
  70. package/dist/form/view/components/field/selection.d.ts +2 -0
  71. package/dist/form/view/components/field/selection.d.ts.map +1 -0
  72. package/dist/form/view/components/field/selection.js +35 -0
  73. package/dist/form/view/components/field/selection.js.map +1 -0
  74. package/dist/form/view/components/field/use-field.d.ts +4 -0
  75. package/dist/form/view/components/field/use-field.d.ts.map +1 -0
  76. package/dist/form/view/components/field/use-field.js +41 -0
  77. package/dist/form/view/components/field/use-field.js.map +1 -0
  78. package/dist/form/view/components/rows/row-container.d.ts +18 -0
  79. package/dist/form/view/components/rows/row-container.d.ts.map +1 -0
  80. package/dist/form/view/components/rows/row-container.js +89 -0
  81. package/dist/form/view/components/rows/row-container.js.map +1 -0
  82. package/dist/form/view/components/rows/wrapper.d.ts +12 -0
  83. package/dist/form/view/components/rows/wrapper.d.ts.map +1 -0
  84. package/dist/form/view/components/rows/wrapper.js +27 -0
  85. package/dist/form/view/components/rows/wrapper.js.map +1 -0
  86. package/dist/form/view/components/wrapped-form.d.ts +6 -0
  87. package/dist/form/view/components/wrapped-form.d.ts.map +1 -0
  88. package/dist/form/view/components/wrapped-form.js +26 -0
  89. package/dist/form/view/components/wrapped-form.js.map +1 -0
  90. package/dist/form/view/context.d.ts +23 -0
  91. package/dist/form/view/context.d.ts.map +1 -0
  92. package/dist/form/view/context.js +7 -0
  93. package/dist/form/view/context.js.map +1 -0
  94. package/dist/form/view/hooks/use-model.d.ts +10 -0
  95. package/dist/form/view/hooks/use-model.d.ts.map +1 -0
  96. package/dist/form/view/hooks/use-model.js +31 -0
  97. package/dist/form/view/hooks/use-model.js.map +1 -0
  98. package/dist/form/view/hooks/use-template.d.ts +14 -0
  99. package/dist/form/view/hooks/use-template.d.ts.map +1 -0
  100. package/dist/form/view/hooks/use-template.js +57 -0
  101. package/dist/form/view/hooks/use-template.js.map +1 -0
  102. package/dist/form/view/hooks/use-types.d.ts +2 -0
  103. package/dist/form/view/hooks/use-types.d.ts.map +1 -0
  104. package/dist/form/view/hooks/use-types.js +19 -0
  105. package/dist/form/view/hooks/use-types.js.map +1 -0
  106. package/dist/form/view/index.d.ts +3 -0
  107. package/dist/form/view/index.d.ts.map +1 -0
  108. package/dist/form/view/index.js +38 -0
  109. package/dist/form/view/index.js.map +1 -0
  110. package/dist/formulas/helpers/condition-types.d.ts +5 -0
  111. package/dist/formulas/helpers/condition-types.d.ts.map +1 -0
  112. package/dist/formulas/helpers/condition-types.js +5 -0
  113. package/dist/formulas/helpers/condition-types.js.map +1 -0
  114. package/dist/formulas/helpers/evaluations.d.ts +15 -0
  115. package/dist/formulas/helpers/evaluations.d.ts.map +1 -0
  116. package/dist/formulas/helpers/evaluations.js +44 -0
  117. package/dist/formulas/helpers/evaluations.js.map +1 -0
  118. package/dist/formulas/helpers/formula.d.ts +6 -0
  119. package/dist/formulas/helpers/formula.d.ts.map +1 -0
  120. package/dist/formulas/helpers/formula.js +26 -0
  121. package/dist/formulas/helpers/formula.js.map +1 -0
  122. package/dist/formulas/helpers/lexer.d.ts +10 -0
  123. package/dist/formulas/helpers/lexer.d.ts.map +1 -0
  124. package/dist/formulas/helpers/lexer.js +73 -0
  125. package/dist/formulas/helpers/lexer.js.map +1 -0
  126. package/dist/formulas/helpers/parser.d.ts +24 -0
  127. package/dist/formulas/helpers/parser.d.ts.map +1 -0
  128. package/dist/formulas/helpers/parser.js +48 -0
  129. package/dist/formulas/helpers/parser.js.map +1 -0
  130. package/dist/formulas/helpers/token.d.ts +14 -0
  131. package/dist/formulas/helpers/token.d.ts.map +1 -0
  132. package/dist/formulas/helpers/token.js +14 -0
  133. package/dist/formulas/helpers/token.js.map +1 -0
  134. package/dist/formulas/index.d.ts +59 -0
  135. package/dist/formulas/index.d.ts.map +1 -0
  136. package/dist/formulas/index.js +186 -0
  137. package/dist/formulas/index.js.map +1 -0
  138. package/dist/formulas/types/formulas.d.ts +68 -0
  139. package/dist/formulas/types/formulas.d.ts.map +1 -0
  140. package/dist/formulas/types/formulas.js +2 -0
  141. package/dist/formulas/types/formulas.js.map +1 -0
  142. package/dist/formulas/types/index.d.ts +5 -0
  143. package/dist/formulas/types/index.d.ts.map +1 -0
  144. package/dist/formulas/types/index.js +2 -0
  145. package/dist/formulas/types/index.js.map +1 -0
  146. package/dist/formulas/variants/array-formula.d.ts +24 -0
  147. package/dist/formulas/variants/array-formula.d.ts.map +1 -0
  148. package/dist/formulas/variants/array-formula.js +142 -0
  149. package/dist/formulas/variants/array-formula.js.map +1 -0
  150. package/dist/formulas/variants/base.d.ts +6 -0
  151. package/dist/formulas/variants/base.d.ts.map +1 -0
  152. package/dist/formulas/variants/base.js +3 -0
  153. package/dist/formulas/variants/base.js.map +1 -0
  154. package/dist/formulas/variants/basic.d.ts +18 -0
  155. package/dist/formulas/variants/basic.d.ts.map +1 -0
  156. package/dist/formulas/variants/basic.js +128 -0
  157. package/dist/formulas/variants/basic.js.map +1 -0
  158. package/dist/formulas/variants/comparison.d.ts +25 -0
  159. package/dist/formulas/variants/comparison.d.ts.map +1 -0
  160. package/dist/formulas/variants/comparison.js +153 -0
  161. package/dist/formulas/variants/comparison.js.map +1 -0
  162. package/dist/formulas/variants/conditional.d.ts +18 -0
  163. package/dist/formulas/variants/conditional.d.ts.map +1 -0
  164. package/dist/formulas/variants/conditional.js +183 -0
  165. package/dist/formulas/variants/conditional.js.map +1 -0
  166. package/dist/formulas/variants/iterative-array.d.ts +20 -0
  167. package/dist/formulas/variants/iterative-array.d.ts.map +1 -0
  168. package/dist/formulas/variants/iterative-array.js +155 -0
  169. package/dist/formulas/variants/iterative-array.js.map +1 -0
  170. package/dist/formulas/variants/per-value.d.ts +20 -0
  171. package/dist/formulas/variants/per-value.d.ts.map +1 -0
  172. package/dist/formulas/variants/per-value.js +154 -0
  173. package/dist/formulas/variants/per-value.js.map +1 -0
  174. package/dist/index.d.ts +5 -0
  175. package/dist/index.d.ts.map +1 -0
  176. package/dist/index.js +6 -0
  177. package/dist/index.js.map +1 -0
  178. package/dist/models/base.d.ts +55 -0
  179. package/dist/models/base.d.ts.map +1 -0
  180. package/dist/models/base.js +146 -0
  181. package/dist/models/base.js.map +1 -0
  182. package/dist/models/callback-manager.d.ts +7 -0
  183. package/dist/models/callback-manager.d.ts.map +1 -0
  184. package/dist/models/callback-manager.js +89 -0
  185. package/dist/models/callback-manager.js.map +1 -0
  186. package/dist/models/field.d.ts +121 -0
  187. package/dist/models/field.d.ts.map +1 -0
  188. package/dist/models/field.js +374 -0
  189. package/dist/models/field.js.map +1 -0
  190. package/dist/models/index.d.ts +13 -0
  191. package/dist/models/index.d.ts.map +1 -0
  192. package/dist/models/index.js +7 -0
  193. package/dist/models/index.js.map +1 -0
  194. package/dist/models/model.d.ts +37 -0
  195. package/dist/models/model.d.ts.map +1 -0
  196. package/dist/models/model.js +245 -0
  197. package/dist/models/model.js.map +1 -0
  198. package/dist/models/plugins/base.d.ts +9 -0
  199. package/dist/models/plugins/base.d.ts.map +1 -0
  200. package/dist/models/plugins/base.js +3 -0
  201. package/dist/models/plugins/base.js.map +1 -0
  202. package/dist/models/plugins/formula.d.ts +18 -0
  203. package/dist/models/plugins/formula.d.ts.map +1 -0
  204. package/dist/models/plugins/formula.js +82 -0
  205. package/dist/models/plugins/formula.js.map +1 -0
  206. package/dist/models/plugins/index.d.ts +11 -0
  207. package/dist/models/plugins/index.d.ts.map +1 -0
  208. package/dist/models/plugins/index.js +52 -0
  209. package/dist/models/plugins/index.js.map +1 -0
  210. package/dist/models/plugins/plugins.d.ts +7 -0
  211. package/dist/models/plugins/plugins.d.ts.map +1 -0
  212. package/dist/models/plugins/plugins.js +7 -0
  213. package/dist/models/plugins/plugins.js.map +1 -0
  214. package/dist/models/types/base-wise-model.d.ts +7 -0
  215. package/dist/models/types/base-wise-model.d.ts.map +1 -0
  216. package/dist/models/types/base-wise-model.js +2 -0
  217. package/dist/models/types/base-wise-model.js.map +1 -0
  218. package/dist/models/types/callbacks.d.ts +19 -0
  219. package/dist/models/types/callbacks.d.ts.map +1 -0
  220. package/dist/models/types/callbacks.js +2 -0
  221. package/dist/models/types/callbacks.js.map +1 -0
  222. package/dist/models/types/disabled.d.ts +8 -0
  223. package/dist/models/types/disabled.d.ts.map +1 -0
  224. package/dist/models/types/disabled.js +2 -0
  225. package/dist/models/types/disabled.js.map +1 -0
  226. package/dist/models/types/form-field.d.ts +25 -0
  227. package/dist/models/types/form-field.d.ts.map +1 -0
  228. package/dist/models/types/form-field.js +2 -0
  229. package/dist/models/types/form-field.js.map +1 -0
  230. package/dist/models/types/model.d.ts +13 -0
  231. package/dist/models/types/model.d.ts.map +1 -0
  232. package/dist/models/types/model.js +2 -0
  233. package/dist/models/types/model.js.map +1 -0
  234. package/dist/models/types/plugins.d.ts +13 -0
  235. package/dist/models/types/plugins.d.ts.map +1 -0
  236. package/dist/models/types/plugins.js +2 -0
  237. package/dist/models/types/plugins.js.map +1 -0
  238. package/dist/models/types/wrapped-form-model-props.d.ts +11 -0
  239. package/dist/models/types/wrapped-form-model-props.d.ts.map +1 -0
  240. package/dist/models/types/wrapped-form-model-props.js +2 -0
  241. package/dist/models/types/wrapped-form-model-props.js.map +1 -0
  242. package/dist/models/wrapper.d.ts +30 -0
  243. package/dist/models/wrapper.d.ts.map +1 -0
  244. package/dist/models/wrapper.js +213 -0
  245. package/dist/models/wrapper.js.map +1 -0
  246. package/dist/settings/index.d.ts +7 -0
  247. package/dist/settings/index.d.ts.map +1 -0
  248. package/dist/settings/index.js +26 -0
  249. package/dist/settings/index.js.map +1 -0
  250. package/dist/utils/pending-promise.d.ts +6 -0
  251. package/dist/utils/pending-promise.d.ts.map +1 -0
  252. package/dist/utils/pending-promise.js +24 -0
  253. package/dist/utils/pending-promise.js.map +1 -0
  254. package/package.json +38 -0
  255. package/src/components/ui/Checkbox.tsx +68 -0
  256. package/src/components/ui/CheckboxGroup.tsx +60 -0
  257. package/src/components/ui/Input.tsx +72 -0
  258. package/src/components/ui/Radio.tsx +68 -0
  259. package/src/components/ui/Select.tsx +73 -0
  260. package/src/components/ui/Textarea.tsx +63 -0
  261. package/src/components/ui/index.ts +14 -0
  262. package/src/form/index.ts +11 -0
  263. package/src/form/interfaces/field-container.ts +9 -0
  264. package/src/form/interfaces/interfaces.ts +12 -0
  265. package/src/form/interfaces/settings.ts +11 -0
  266. package/src/form/interfaces/template.ts +7 -0
  267. package/src/form/interfaces/wise-form-specs.ts +10 -0
  268. package/src/form/styles.css +40 -0
  269. package/src/form/view/components/containers/index.tsx +18 -0
  270. package/src/form/view/components/error.tsx +9 -0
  271. package/src/form/view/components/field/container.tsx +6 -0
  272. package/src/form/view/components/field/index.tsx +107 -0
  273. package/src/form/view/components/field/selection.tsx +39 -0
  274. package/src/form/view/components/field/use-field.tsx +49 -0
  275. package/src/form/view/components/rows/row-container.tsx +96 -0
  276. package/src/form/view/components/rows/wrapper.tsx +28 -0
  277. package/src/form/view/components/wrapped-form.tsx +32 -0
  278. package/src/form/view/context.tsx +26 -0
  279. package/src/form/view/hooks/use-model.ts +37 -0
  280. package/src/form/view/hooks/use-template.tsx +64 -0
  281. package/src/form/view/hooks/use-types.ts +21 -0
  282. package/src/form/view/index.tsx +48 -0
  283. package/src/formulas/helpers/condition-types.ts +5 -0
  284. package/src/formulas/helpers/evaluations.ts +48 -0
  285. package/src/formulas/helpers/formula.ts +27 -0
  286. package/src/formulas/helpers/lexer.ts +82 -0
  287. package/src/formulas/helpers/parser.ts +55 -0
  288. package/src/formulas/helpers/token.ts +22 -0
  289. package/src/formulas/index.ts +198 -0
  290. package/src/formulas/types/formulas.ts +72 -0
  291. package/src/formulas/types/index.ts +5 -0
  292. package/src/formulas/variants/array-formula.ts +138 -0
  293. package/src/formulas/variants/base.ts +6 -0
  294. package/src/formulas/variants/basic.ts +141 -0
  295. package/src/formulas/variants/comparison.ts +156 -0
  296. package/src/formulas/variants/conditional.ts +208 -0
  297. package/src/formulas/variants/iterative-array.ts +152 -0
  298. package/src/formulas/variants/per-value.ts +152 -0
  299. package/src/index.ts +6 -0
  300. package/src/models/base.ts +164 -0
  301. package/src/models/callback-manager.ts +102 -0
  302. package/src/models/field.ts +426 -0
  303. package/src/models/index.ts +14 -0
  304. package/src/models/model.ts +260 -0
  305. package/src/models/plugins/base.ts +11 -0
  306. package/src/models/plugins/formula.ts +80 -0
  307. package/src/models/plugins/index.ts +48 -0
  308. package/src/models/plugins/plugins.ts +8 -0
  309. package/src/models/types/base-wise-model.ts +7 -0
  310. package/src/models/types/callbacks.ts +23 -0
  311. package/src/models/types/disabled.ts +8 -0
  312. package/src/models/types/form-field.ts +22 -0
  313. package/src/models/types/model.ts +14 -0
  314. package/src/models/types/plugins.ts +15 -0
  315. package/src/models/types/wrapped-form-model-props.ts +9 -0
  316. package/src/models/wrapper.ts +242 -0
  317. package/src/settings/index.ts +11 -0
  318. package/src/utils/pending-promise.ts +29 -0
  319. package/tsconfig.json +39 -0
@@ -0,0 +1,156 @@
1
+ import type { FormulaManager } from "..";
2
+ import { EvaluationsManager } from "../helpers/evaluations";
3
+
4
+ import { Token } from "../helpers/token";
5
+ import { FormulaObserver, IComplexCondition, IConditionalField } from "../types/formulas";
6
+ import { number, parse } from "mathjs";
7
+
8
+ export class FormulaComparison {
9
+ #plugin: any;
10
+ #specs: FormulaObserver;
11
+ #emptyValue: undefined;
12
+ #tokens: Token[];
13
+ get formula() {
14
+ return this.#specs.formula;
15
+ }
16
+ get base() {
17
+ const formula = <IComplexCondition>this.#specs.formula;
18
+ return formula.base;
19
+ }
20
+ #value: string | number | undefined | 0;
21
+ get value() {
22
+ return this.#value;
23
+ }
24
+ get name() {
25
+ return this.#specs.name;
26
+ }
27
+ /**
28
+ * Represents the fields defined in the plugin settings
29
+ */
30
+ get fields() {
31
+ const formula = <IComplexCondition>this.formula;
32
+ return typeof formula?.fields === "string" ? [formula?.fields] : formula?.fields;
33
+ }
34
+
35
+ get conditions() {
36
+ if (typeof this.#specs.formula === "string") return;
37
+ const formula = this.#specs.formula as IComplexCondition;
38
+ return formula.conditions;
39
+ }
40
+
41
+ #variables: string[] = [];
42
+ get variables() {
43
+ return this.#variables;
44
+ };
45
+
46
+ #observers: string[];
47
+ get observers() {
48
+ return this.#observers;
49
+ }
50
+
51
+ #isNotListenToChanges = false
52
+
53
+ #parent: FormulaManager;
54
+ constructor(parent, plugin, specs) {
55
+ this.#parent = parent;
56
+ this.#plugin = plugin;
57
+ this.#specs = specs;
58
+ this.#isNotListenToChanges = specs.isNotListenToChanges;
59
+ this.#observers = specs.formula.observers;
60
+ }
61
+
62
+ initialize() {
63
+ if (!Array.isArray(this.#specs.fields)) {
64
+ throw new Error("The fields property must be an array");
65
+ }
66
+ if (!this.#isNotListenToChanges && this.#observers && Array.isArray(this.#observers) && !!this.#observers.length) {
67
+ const fields = this.#parent.getModels(this.#observers);
68
+ fields.forEach(field => {
69
+ if (!field) return;
70
+ field.on('change', this.calculate.bind(this));
71
+ });
72
+ }
73
+ const models = this.#parent.getModels(this.#specs.fields);
74
+ if (!this.#isNotListenToChanges) models.forEach(model => model.on("change", this.calculate.bind(this)));
75
+ }
76
+
77
+
78
+ start() { }
79
+
80
+ evaluate() {
81
+ const formula = <IComplexCondition>this.#specs.formula;
82
+
83
+ if (typeof formula === "string" || !formula.conditions) {
84
+ console.error("Invalid formula configuration");
85
+ return null;
86
+ }
87
+ const models = this.#parent.getModels(this.#specs.fields);
88
+ let fieldValues = models.map(fieldModel => {
89
+ if (!fieldModel) return;
90
+ return { name: fieldModel.name, value: fieldModel ? fieldModel.value : null };
91
+ });
92
+
93
+ // Utilizar reduce para comparar cada par de valores consecutivos y determinar cuál cumple la condición
94
+ const resultField = fieldValues.reduce((prevField, currentField) => {
95
+ if (!prevField) return currentField;
96
+
97
+ // Si el campo previo cumple la condición con respecto al actual, se mantiene como el campo elegido
98
+ if (EvaluationsManager.validate(formula.condition, prevField.value, currentField.value)) {
99
+ return prevField;
100
+ }
101
+ // De lo contrario, el campo actual se convierte en el nuevo campo elegido
102
+ return currentField;
103
+ }, null);
104
+
105
+ if (resultField) {
106
+ // Ajustar según la lógica específica deseada, como devolver una fórmula particular basada en el resultado
107
+ return resultField;
108
+ } else {
109
+ // Manejar el caso de que ninguno cumpla la condición
110
+ return null;
111
+ }
112
+ }
113
+
114
+ async calculate() {
115
+ let applied = this.evaluate();
116
+
117
+ if (!applied || !applied?.value) {
118
+ // any formula apply, so we need to reset the value
119
+ this.#value = 0;
120
+ return;
121
+ }
122
+ /**
123
+ * Get the formula analyzer
124
+ */
125
+
126
+ const specsFormula = this.#specs.formula as IComplexCondition;
127
+ const formulaString = specsFormula.conditions[applied.name];
128
+ const formula = this.#parent.getParser({ formula: formulaString });
129
+ const variables = formula.tokens.filter(token => token.type === "variable").map(item => item.value);
130
+ const params = await this.#parent.getParams(variables);
131
+
132
+ try {
133
+ const keys = Object.keys(params);
134
+ const result = keys.length === 1 ? params[keys[0]] : parse(this.formula as string).evaluate(params);
135
+
136
+ this.#value = [-Infinity, Infinity, undefined, null, NaN].includes(result)
137
+ ? this.#emptyValue
138
+ : Number(result.toFixed(2));
139
+ this.#parent.trigger("change");
140
+ return this.#value;
141
+ } catch (e) {
142
+ console.log("formula", this.name, this.formula, params);
143
+ throw new Error("Error calculating the formula");
144
+ }
145
+ }
146
+
147
+ calculateUpper(models) {
148
+ let glue;
149
+ models.forEach(item => {
150
+ if (Number(item.value) > Number(glue?.value ?? 0)) glue = item;
151
+ });
152
+
153
+ return glue;
154
+ }
155
+ }
156
+
@@ -0,0 +1,208 @@
1
+ import type { FormulaManager } from '..';
2
+ import { conditionsTypes } from '../helpers/condition-types';
3
+ import { EvaluationsManager } from '../helpers/evaluations';
4
+ import {
5
+ EvaluatedFormula,
6
+ FormulaObserver,
7
+ IComplexCondition,
8
+ IConditionalField,
9
+ } from '../types/formulas';
10
+ import { parse } from 'mathjs';
11
+
12
+ export class FormulaConditional {
13
+ #plugin: any;
14
+ #specs: FormulaObserver;
15
+ #emptyValue: undefined;
16
+ get formula() {
17
+ return this.#specs.formula;
18
+ }
19
+ get base() {
20
+ const formula = <IComplexCondition>this.#specs.formula;
21
+ return formula.base;
22
+ }
23
+ #value: string | number | undefined | 0;
24
+ get value() {
25
+ return this.#value;
26
+ }
27
+ get name() {
28
+ return this.#specs.name;
29
+ }
30
+ /**
31
+ * Represents the fields defined in the plugin settings
32
+ */
33
+ get fields() {
34
+ const formula = <IComplexCondition>this.formula;
35
+ return typeof formula?.fields === 'string'
36
+ ? [formula?.fields]
37
+ : formula?.fields;
38
+ }
39
+
40
+ get conditions() {
41
+ if (typeof this.#specs.formula === 'string') return;
42
+ const formula = this.#specs.formula as IComplexCondition;
43
+ return formula.conditions;
44
+ }
45
+
46
+ /**
47
+ * FormField type
48
+ */
49
+ #fields: any;
50
+
51
+ #parent: FormulaManager;
52
+ #ceil: boolean;
53
+ #round: boolean;
54
+ #isNotListenToChanges = false;
55
+ constructor(parent, plugin, specs) {
56
+ this.#parent = parent;
57
+ this.#plugin = plugin;
58
+ this.#specs = specs;
59
+ this.#round = specs.round;
60
+ this.#ceil = specs.ceil;
61
+ this.#emptyValue = specs.emptyValue;
62
+
63
+ if (specs.isNotListenToChanges)
64
+ this.#isNotListenToChanges = specs.isNotListenToChanges;
65
+ }
66
+
67
+ initialize() {
68
+ try {
69
+ const { form } = this.#plugin;
70
+
71
+ if (!this.fields) {
72
+ throw new Error(`Fields not found in formula ${this.name}`);
73
+ }
74
+ const fields = this.fields.map((name) => {
75
+ const formula = this.#plugin.formulas.get(name);
76
+ if (formula) return formula;
77
+ const field = form.getField(name);
78
+ return field;
79
+ });
80
+ this.#fields = fields;
81
+ if (this.name === 'costoTotalGrafico') {
82
+ console.log('fields', fields);
83
+ }
84
+ if (!this.#isNotListenToChanges)
85
+ fields.forEach((field) => {
86
+ if (!field) {
87
+ throw new Error(
88
+ `Field ${this.name} not found in form ${form.name}`
89
+ );
90
+ }
91
+ field.on('change', this.calculate.bind(this));
92
+ });
93
+ } catch (e) {}
94
+ }
95
+
96
+ evaluate() {
97
+ const formula = <IComplexCondition>this.#specs.formula;
98
+ let evaluatedFormula: any = { formula: formula.base }; // Use the base formula by default
99
+ if (formula.conditions) {
100
+ const conditionsArray = Array.isArray(formula.conditions) ? formula.conditions : [formula.conditions];
101
+ for (const condition of conditionsArray) {
102
+ let conditionMet = false;
103
+ if (condition.conditions) {
104
+ // If there are nested conditions, all must be met
105
+ conditionMet = condition.conditions.every(
106
+ (subCondition) => {
107
+ const fieldValues = subCondition.fields.map(
108
+ (fieldName) => {
109
+ const field = this.#fields.find(
110
+ (f) => f.name === fieldName
111
+ );
112
+ return field
113
+ ? field.value
114
+ : this.#emptyValue;
115
+ }
116
+ );
117
+ return EvaluationsManager.validateAll(
118
+ subCondition.condition,
119
+ fieldValues,
120
+ subCondition.value
121
+ );
122
+ }
123
+ );
124
+ } else {
125
+ const fieldValues = condition.fields.map((fieldName) => {
126
+ const field = this.#fields.find(
127
+ (f) => f.name === fieldName
128
+ );
129
+ return field ? field.value : this.#emptyValue;
130
+ });
131
+ const conditionType =
132
+ !!condition.type && conditionsTypes[condition.type]
133
+ ? conditionsTypes[condition.type]
134
+ : conditionsTypes.some;
135
+ // Check if any of the specified fields meet the condition
136
+ conditionMet = EvaluationsManager[conditionType](
137
+ condition.condition,
138
+ fieldValues,
139
+ condition.value
140
+ );
141
+ }
142
+
143
+ if (conditionMet) {
144
+ evaluatedFormula.formula = condition.formula;
145
+ evaluatedFormula.fi = condition;
146
+ break;
147
+ }
148
+ }
149
+ }
150
+ return evaluatedFormula;
151
+ }
152
+
153
+ async calculate() {
154
+ /**
155
+ * the formula is taken from the evaluate method since the conditions are evaluated there and
156
+ * can change the formula to be applied
157
+ */
158
+ const model = this.#plugin.form.getField(this.name);
159
+ const formula = this.evaluate();
160
+
161
+ if (!formula.formula) {
162
+ this.#value =
163
+ this.#emptyValue !== undefined ? this.#emptyValue : '';
164
+ model && model.set({ value: this.#value });
165
+ this.#parent.trigger('change');
166
+ return this.#value;
167
+ }
168
+ // todo: Review if this section can be replaced by formulaManager.variables property.
169
+ const { tokens } = this.#parent.getParser(formula);
170
+ const variables = tokens
171
+ .filter((token) => token.type === 'variable')
172
+ .map((item) => item.value);
173
+
174
+ const params = await this.#parent.getParams(variables);
175
+
176
+ try {
177
+ const keys = Object.keys(params);
178
+ let result =
179
+ keys.length === 1
180
+ ? params[keys[0]]
181
+ : parse(formula.formula as string).evaluate(params);
182
+
183
+ const isInvalidResult = [
184
+ -Infinity,
185
+ Infinity,
186
+ undefined,
187
+ null,
188
+ NaN,
189
+ ].includes(result);
190
+ if (this.#round && !isInvalidResult) result = Math.round(result);
191
+ if (this.#ceil && !isInvalidResult) result = Math.ceil(result);
192
+ this.#value =
193
+ isInvalidResult || typeof result === 'object'
194
+ ? this.#emptyValue
195
+ : Number(result.toFixed(2));
196
+
197
+ this.#parent.trigger('change');
198
+
199
+ model && model.set({ value: this.#value });
200
+ return this.#value;
201
+ } catch (e) {
202
+ console.log('formula', this.name, formula.formula, params);
203
+ console.error(e);
204
+ throw new Error('Error calculating the formula');
205
+ }
206
+ }
207
+ }
208
+
@@ -0,0 +1,152 @@
1
+ import type { FormulaManager } from '..';
2
+ import { EvaluationsManager } from '../helpers/evaluations';
3
+ import { Token } from '../helpers/token';
4
+ import { FormulaObserver, IComplexCondition } from '../types/formulas';
5
+ import { parse } from 'mathjs';
6
+
7
+ export class IterativeArrayFormula {
8
+ #plugin: any;
9
+ #specs: FormulaObserver;
10
+ #tokens: Token[];
11
+ get formula() {
12
+ return this.#specs.formula;
13
+ }
14
+ get base() {
15
+ const formula = <IComplexCondition>this.#specs.formula;
16
+ return formula.base;
17
+ }
18
+ #value: string | number | undefined | 0;
19
+ get value() {
20
+ return this.#value;
21
+ }
22
+ get name() {
23
+ return this.#specs.name;
24
+ }
25
+ /**
26
+ * Represents the fields defined in the plugin settings
27
+ */
28
+ get fields() {
29
+ const formula = <IComplexCondition>this.formula;
30
+ return typeof formula?.fields === 'string' ? [formula?.fields] : formula?.fields;
31
+ }
32
+
33
+ get conditions() {
34
+ if (typeof this.#specs.formula === 'string') return;
35
+ const formula = this.#specs.formula as IComplexCondition;
36
+ return formula.conditions;
37
+ }
38
+
39
+ #emptyValue: string | number;
40
+ #variables: string[] = [];
41
+ get variables() {
42
+ return this.#variables;
43
+ }
44
+
45
+ #round: boolean;
46
+ #ceil: boolean
47
+
48
+ #parent: FormulaManager;
49
+
50
+ #isNotListenToChanges = false
51
+ constructor(parent, plugin, specs) {
52
+ this.#parent = parent;
53
+ this.#plugin = plugin;
54
+ this.#specs = specs;
55
+ this.#round = specs.round;
56
+ this.#ceil = specs.ceil;
57
+ this.#emptyValue = this.#specs.emptyValue;
58
+ this.#isNotListenToChanges = specs.isNotListenToChanges
59
+ }
60
+
61
+ initialize() {
62
+ const fieldArray = this.#plugin.form.getField(this.#specs.arrayFieldName);
63
+ if (!fieldArray) {
64
+ console.error(`Field ${this.#specs.arrayFieldName} does NOT exist.`);
65
+ return;
66
+ }
67
+ fieldArray.on('change', this.calculate.bind(this));
68
+ }
69
+
70
+ async calculate() {
71
+
72
+ const formulaField = this.#plugin.form.getField(this.name);
73
+
74
+ const fieldArray = this.#plugin.form.getField(this.#specs.arrayFieldName);
75
+
76
+ if (!fieldArray) {
77
+ console.error(`Field ${this.#specs.arrayFieldName} does NOT exist.`);
78
+ return;
79
+ }
80
+
81
+ const entries = fieldArray[this.#specs.arrayFieldProperty];
82
+
83
+ if (!Array.isArray(entries)) {
84
+ console.error(`Property ${this.#specs.arrayFieldProperty} is not an array.`);
85
+ return;
86
+ }
87
+
88
+ const empty = !entries.length;
89
+ const formula: any = this.#specs.formula;
90
+ let formulaEvaluate = formula?.formula || formula
91
+ if (empty) {
92
+ // If all models are empty, set the input to empty if exists.
93
+ if (formulaField) formulaField.set({ value: this.#emptyValue !== undefined ? this.#emptyValue : '' });
94
+ this.#value = undefined;
95
+ this.#parent.trigger('change');
96
+ return;
97
+ }
98
+
99
+ try {
100
+ let totalResult: string | number = 0;
101
+ for (let item of entries) {
102
+ if (formula.conditions) {
103
+ for (const condition of formula.conditions) {
104
+ const comparisonValue = item[condition.property]
105
+ let conditionMet = EvaluationsManager.validate(condition.condition, comparisonValue, condition.value);
106
+ if (conditionMet) {
107
+ formulaEvaluate = condition.formula;
108
+ break
109
+ } else {
110
+ formulaEvaluate = formula.base
111
+ }
112
+ }
113
+ }
114
+ const attrs = this.sanitizeData(item);
115
+ let result = parse(formulaEvaluate as string).evaluate(attrs);
116
+ const isInvalidResult = [-Infinity, Infinity, undefined, null, NaN].includes(result);
117
+ if (this.#round && !isInvalidResult) result = Math.round(result);
118
+ if (this.#ceil && !isInvalidResult) result = Math.ceil(result);
119
+ totalResult = isInvalidResult ? totalResult : Number(totalResult) + Number(result.toFixed(2))
120
+ }
121
+ const isInvalidResult = [-Infinity, Infinity, undefined, null, NaN, ''].includes(totalResult);
122
+ this.#value = isInvalidResult ? this.#emptyValue : totalResult
123
+ if (formulaField) formulaField.set({ value: this.#value });
124
+ this.#parent.trigger('change');
125
+ } catch (e) {
126
+ console.log('formula', this.name, this.formula);
127
+ console.trace(e);
128
+ throw new Error(`Error calculating the formula: ${e.message} ${this.name}`);
129
+ }
130
+ };
131
+
132
+ private sanitizeData(data: any): any {
133
+ if (Array.isArray(data)) {
134
+ return data.map(item => this.sanitizeData(item));
135
+ } else if (typeof data === 'object' && data !== null) {
136
+ const sanitizedData: any = {};
137
+ for (const key in data) {
138
+ if (data.hasOwnProperty(key)) {
139
+ sanitizedData[key] = this.sanitizeData(data[key]);
140
+ }
141
+ }
142
+ return sanitizedData;
143
+ } else {
144
+ return this.sanitizeValue(data);
145
+ }
146
+ }
147
+
148
+ private sanitizeValue(value: any, defaultValue: number = 0): number {
149
+ return (value === null || value === undefined || isNaN(value)) ? defaultValue : Number(value);
150
+ }
151
+ }
152
+
@@ -0,0 +1,152 @@
1
+ import type { FormulaManager } from '../';
2
+ import { EvaluationsManager } from '../helpers/evaluations';
3
+ import { Parser } from '../helpers/parser';
4
+ import { FormulaObserver, IComplexCondition, ParserData } from '../types/formulas';
5
+ import { filter, parse } from 'mathjs';
6
+
7
+ export class FormulaPerValue {
8
+ #plugin: any;
9
+ #emptyValue: undefined;
10
+ #specs: FormulaObserver;
11
+ get formula() {
12
+ return this.#specs.formula;
13
+ }
14
+ #value: string | number | undefined | 0;
15
+ get value() {
16
+ return this.#value;
17
+ }
18
+ get name() {
19
+ return this.#specs.name;
20
+ }
21
+
22
+ #observers: string[];
23
+ get observers() {
24
+ return this.#observers;
25
+ }
26
+ /**
27
+ * Represents the fields defined in the plugin settings
28
+ */
29
+ get fields() {
30
+ const formula = <IComplexCondition>this.formula;
31
+ return typeof formula?.fields === 'string' ? [formula?.fields] : formula?.fields;
32
+ }
33
+
34
+ get conditions() {
35
+ if (typeof this.#specs.formula === 'string') return;
36
+ const formula = this.#specs.formula as IComplexCondition;
37
+ return formula.conditions;
38
+ }
39
+
40
+ #parent: FormulaManager;
41
+ #parsers: ParserData[];
42
+ #mainFields: any[];
43
+ #isNotListenToChanges = false
44
+ constructor(parent, plugin, specs) {
45
+ this.#parent = parent;
46
+ this.#plugin = plugin;
47
+ this.#specs = specs;
48
+ this.#observers = specs.formula.observers;
49
+ this.#isNotListenToChanges = specs.isNotListenToChanges
50
+ }
51
+
52
+ initialize() {
53
+ const { form } = this.#plugin;
54
+ const fields = new Set<string>();
55
+
56
+ this.#mainFields = this.#parent.getModels(this.fields);
57
+
58
+ /**
59
+ * The method will iterate over the conditions to get the parser for each value
60
+ * and get access to the fields that are part of the formula and be able to evaluate it
61
+ * changes.
62
+ */
63
+ const conditionsArray = Array.isArray(this.conditions) ? this.conditions : [];
64
+ conditionsArray.forEach(condition => {
65
+ if (!condition.condition) {
66
+ throw new Error('the formula per value must contain a condition property in the condition`s item');
67
+ }
68
+ if (!condition.values) {
69
+ throw new Error('the formula per value must contain a values property in the condition`s item');
70
+ }
71
+
72
+ const parsers = condition.values.map(item => this.#parent.getParser(item));
73
+ this.#parsers = parsers;
74
+ parsers.forEach(parser => {
75
+ parser.tokens.filter(token => token.type === 'variable').forEach(token => fields.add(token.value));
76
+ });
77
+ });
78
+
79
+ fields.forEach(field => {
80
+ const model = form.getField(field);
81
+ if (model) model.on('change', this.listenConditionals.bind(this));
82
+ });
83
+
84
+ this.listenConditionals();
85
+ if (!this.#isNotListenToChanges) this.#mainFields.forEach(item => item.on('change', this.calculate.bind(this)));
86
+ if (!this.#isNotListenToChanges) if (this.#observers && Array.isArray(this.#observers) && !!this.#observers.length) {
87
+ const fields = this.#parent.getModels(this.#observers);
88
+ fields.forEach(field => {
89
+ if (!field) return;
90
+ field.on('change', this.calculateAll.bind(this));
91
+ });
92
+ }
93
+ }
94
+
95
+ calculateAll() {
96
+ this.#mainFields.forEach(field => this.calculate(field));
97
+ }
98
+ listenConditionals() {
99
+ this.#mainFields.forEach(field => {
100
+ if (!field) return;
101
+ field.on('change', this.calculate.bind(this));
102
+ });
103
+ }
104
+
105
+ async calculate(field) {
106
+ if (!field) return;
107
+ const { form } = this.#plugin;
108
+ const formula = this.evaluate(field.value);
109
+
110
+ if (!formula) return;
111
+
112
+ const variables = formula.tokens.filter(token => token.type === 'variable').map(item => item.value);
113
+ const params = await this.#parent.getParams(variables);
114
+ const formulaField = form.getField(this.name);
115
+
116
+ try {
117
+ const keys = Object.keys(params);
118
+ const result = keys.length === 1 ? params[keys[0]] : parse(formula.formula as string).evaluate(params);
119
+ this.#value = [-Infinity, Infinity, undefined, null, NaN].includes(result)
120
+ ? this.#emptyValue
121
+ : Number(result.toFixed(2));
122
+ formulaField && formulaField.set({ value: this.#value });
123
+ this.#parent.trigger('change');
124
+ } catch (e) {
125
+ console.log(e);
126
+ throw new Error('Error calculating the formula');
127
+ }
128
+ }
129
+
130
+ evaluate(value) {
131
+ let formula = undefined;
132
+ if ([null, undefined].includes(value)) {
133
+ return;
134
+ }
135
+ const conditionsArray = Array.isArray(this.conditions) ? this.conditions : [];
136
+ conditionsArray.forEach(item => {
137
+ const { condition, values } = item;
138
+ if (!condition) {
139
+ throw new Error('the formula per value must contain a condition property in the condition`s item');
140
+ }
141
+ if (!values) {
142
+ throw new Error('the formula per value must contain a values property in the condition`s item');
143
+ }
144
+ const index = values.findIndex(item => EvaluationsManager.validate(condition, value, item.value));
145
+
146
+ if (index > -1) formula = this.#parent.getParser(values[index]);
147
+ });
148
+
149
+ return formula;
150
+ }
151
+ }
152
+
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ // Main entry point - export all modules
2
+ export * from './form';
3
+ export * from './formulas';
4
+ export * from './models';
5
+ export * from './settings';
6
+