@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.
- package/README.md +34 -0
- package/dist/components/ui/Checkbox.d.ts +14 -0
- package/dist/components/ui/Checkbox.d.ts.map +1 -0
- package/dist/components/ui/Checkbox.js +43 -0
- package/dist/components/ui/Checkbox.js.map +1 -0
- package/dist/components/ui/CheckboxGroup.d.ts +15 -0
- package/dist/components/ui/CheckboxGroup.d.ts.map +1 -0
- package/dist/components/ui/CheckboxGroup.js +33 -0
- package/dist/components/ui/CheckboxGroup.js.map +1 -0
- package/dist/components/ui/Input.d.ts +14 -0
- package/dist/components/ui/Input.d.ts.map +1 -0
- package/dist/components/ui/Input.js +49 -0
- package/dist/components/ui/Input.js.map +1 -0
- package/dist/components/ui/Radio.d.ts +14 -0
- package/dist/components/ui/Radio.d.ts.map +1 -0
- package/dist/components/ui/Radio.js +43 -0
- package/dist/components/ui/Radio.js.map +1 -0
- package/dist/components/ui/Select.d.ts +18 -0
- package/dist/components/ui/Select.d.ts.map +1 -0
- package/dist/components/ui/Select.js +44 -0
- package/dist/components/ui/Select.js.map +1 -0
- package/dist/components/ui/Textarea.d.ts +13 -0
- package/dist/components/ui/Textarea.d.ts.map +1 -0
- package/dist/components/ui/Textarea.js +42 -0
- package/dist/components/ui/Textarea.js.map +1 -0
- package/dist/components/ui/index.d.ts +13 -0
- package/dist/components/ui/index.d.ts.map +1 -0
- package/dist/components/ui/index.js +7 -0
- package/dist/components/ui/index.js.map +1 -0
- package/dist/form/index.d.ts +10 -0
- package/dist/form/index.d.ts.map +1 -0
- package/dist/form/index.js +5 -0
- package/dist/form/index.js.map +1 -0
- package/dist/form/interfaces/field-container.d.ts +8 -0
- package/dist/form/interfaces/field-container.d.ts.map +1 -0
- package/dist/form/interfaces/field-container.js +2 -0
- package/dist/form/interfaces/field-container.js.map +1 -0
- package/dist/form/interfaces/interfaces.d.ts +8 -0
- package/dist/form/interfaces/interfaces.d.ts.map +1 -0
- package/dist/form/interfaces/interfaces.js +2 -0
- package/dist/form/interfaces/interfaces.js.map +1 -0
- package/dist/form/interfaces/settings.d.ts +10 -0
- package/dist/form/interfaces/settings.d.ts.map +1 -0
- package/dist/form/interfaces/settings.js +2 -0
- package/dist/form/interfaces/settings.js.map +1 -0
- package/dist/form/interfaces/template.d.ts +6 -0
- package/dist/form/interfaces/template.d.ts.map +1 -0
- package/dist/form/interfaces/template.js +2 -0
- package/dist/form/interfaces/template.js.map +1 -0
- package/dist/form/interfaces/wise-form-specs.d.ts +9 -0
- package/dist/form/interfaces/wise-form-specs.d.ts.map +1 -0
- package/dist/form/interfaces/wise-form-specs.js +2 -0
- package/dist/form/interfaces/wise-form-specs.js.map +1 -0
- package/dist/form/view/components/containers/index.d.ts +3 -0
- package/dist/form/view/components/containers/index.d.ts.map +1 -0
- package/dist/form/view/components/containers/index.js +12 -0
- package/dist/form/view/components/containers/index.js.map +1 -0
- package/dist/form/view/components/error.d.ts +5 -0
- package/dist/form/view/components/error.d.ts.map +1 -0
- package/dist/form/view/components/error.js +8 -0
- package/dist/form/view/components/error.js.map +1 -0
- package/dist/form/view/components/field/container.d.ts +5 -0
- package/dist/form/view/components/field/container.d.ts.map +1 -0
- package/dist/form/view/components/field/container.js +5 -0
- package/dist/form/view/components/field/container.js.map +1 -0
- package/dist/form/view/components/field/index.d.ts +18 -0
- package/dist/form/view/components/field/index.d.ts.map +1 -0
- package/dist/form/view/components/field/index.js +89 -0
- package/dist/form/view/components/field/index.js.map +1 -0
- package/dist/form/view/components/field/selection.d.ts +2 -0
- package/dist/form/view/components/field/selection.d.ts.map +1 -0
- package/dist/form/view/components/field/selection.js +35 -0
- package/dist/form/view/components/field/selection.js.map +1 -0
- package/dist/form/view/components/field/use-field.d.ts +4 -0
- package/dist/form/view/components/field/use-field.d.ts.map +1 -0
- package/dist/form/view/components/field/use-field.js +41 -0
- package/dist/form/view/components/field/use-field.js.map +1 -0
- package/dist/form/view/components/rows/row-container.d.ts +18 -0
- package/dist/form/view/components/rows/row-container.d.ts.map +1 -0
- package/dist/form/view/components/rows/row-container.js +89 -0
- package/dist/form/view/components/rows/row-container.js.map +1 -0
- package/dist/form/view/components/rows/wrapper.d.ts +12 -0
- package/dist/form/view/components/rows/wrapper.d.ts.map +1 -0
- package/dist/form/view/components/rows/wrapper.js +27 -0
- package/dist/form/view/components/rows/wrapper.js.map +1 -0
- package/dist/form/view/components/wrapped-form.d.ts +6 -0
- package/dist/form/view/components/wrapped-form.d.ts.map +1 -0
- package/dist/form/view/components/wrapped-form.js +26 -0
- package/dist/form/view/components/wrapped-form.js.map +1 -0
- package/dist/form/view/context.d.ts +23 -0
- package/dist/form/view/context.d.ts.map +1 -0
- package/dist/form/view/context.js +7 -0
- package/dist/form/view/context.js.map +1 -0
- package/dist/form/view/hooks/use-model.d.ts +10 -0
- package/dist/form/view/hooks/use-model.d.ts.map +1 -0
- package/dist/form/view/hooks/use-model.js +31 -0
- package/dist/form/view/hooks/use-model.js.map +1 -0
- package/dist/form/view/hooks/use-template.d.ts +14 -0
- package/dist/form/view/hooks/use-template.d.ts.map +1 -0
- package/dist/form/view/hooks/use-template.js +57 -0
- package/dist/form/view/hooks/use-template.js.map +1 -0
- package/dist/form/view/hooks/use-types.d.ts +2 -0
- package/dist/form/view/hooks/use-types.d.ts.map +1 -0
- package/dist/form/view/hooks/use-types.js +19 -0
- package/dist/form/view/hooks/use-types.js.map +1 -0
- package/dist/form/view/index.d.ts +3 -0
- package/dist/form/view/index.d.ts.map +1 -0
- package/dist/form/view/index.js +38 -0
- package/dist/form/view/index.js.map +1 -0
- package/dist/formulas/helpers/condition-types.d.ts +5 -0
- package/dist/formulas/helpers/condition-types.d.ts.map +1 -0
- package/dist/formulas/helpers/condition-types.js +5 -0
- package/dist/formulas/helpers/condition-types.js.map +1 -0
- package/dist/formulas/helpers/evaluations.d.ts +15 -0
- package/dist/formulas/helpers/evaluations.d.ts.map +1 -0
- package/dist/formulas/helpers/evaluations.js +44 -0
- package/dist/formulas/helpers/evaluations.js.map +1 -0
- package/dist/formulas/helpers/formula.d.ts +6 -0
- package/dist/formulas/helpers/formula.d.ts.map +1 -0
- package/dist/formulas/helpers/formula.js +26 -0
- package/dist/formulas/helpers/formula.js.map +1 -0
- package/dist/formulas/helpers/lexer.d.ts +10 -0
- package/dist/formulas/helpers/lexer.d.ts.map +1 -0
- package/dist/formulas/helpers/lexer.js +73 -0
- package/dist/formulas/helpers/lexer.js.map +1 -0
- package/dist/formulas/helpers/parser.d.ts +24 -0
- package/dist/formulas/helpers/parser.d.ts.map +1 -0
- package/dist/formulas/helpers/parser.js +48 -0
- package/dist/formulas/helpers/parser.js.map +1 -0
- package/dist/formulas/helpers/token.d.ts +14 -0
- package/dist/formulas/helpers/token.d.ts.map +1 -0
- package/dist/formulas/helpers/token.js +14 -0
- package/dist/formulas/helpers/token.js.map +1 -0
- package/dist/formulas/index.d.ts +59 -0
- package/dist/formulas/index.d.ts.map +1 -0
- package/dist/formulas/index.js +186 -0
- package/dist/formulas/index.js.map +1 -0
- package/dist/formulas/types/formulas.d.ts +68 -0
- package/dist/formulas/types/formulas.d.ts.map +1 -0
- package/dist/formulas/types/formulas.js +2 -0
- package/dist/formulas/types/formulas.js.map +1 -0
- package/dist/formulas/types/index.d.ts +5 -0
- package/dist/formulas/types/index.d.ts.map +1 -0
- package/dist/formulas/types/index.js +2 -0
- package/dist/formulas/types/index.js.map +1 -0
- package/dist/formulas/variants/array-formula.d.ts +24 -0
- package/dist/formulas/variants/array-formula.d.ts.map +1 -0
- package/dist/formulas/variants/array-formula.js +142 -0
- package/dist/formulas/variants/array-formula.js.map +1 -0
- package/dist/formulas/variants/base.d.ts +6 -0
- package/dist/formulas/variants/base.d.ts.map +1 -0
- package/dist/formulas/variants/base.js +3 -0
- package/dist/formulas/variants/base.js.map +1 -0
- package/dist/formulas/variants/basic.d.ts +18 -0
- package/dist/formulas/variants/basic.d.ts.map +1 -0
- package/dist/formulas/variants/basic.js +128 -0
- package/dist/formulas/variants/basic.js.map +1 -0
- package/dist/formulas/variants/comparison.d.ts +25 -0
- package/dist/formulas/variants/comparison.d.ts.map +1 -0
- package/dist/formulas/variants/comparison.js +153 -0
- package/dist/formulas/variants/comparison.js.map +1 -0
- package/dist/formulas/variants/conditional.d.ts +18 -0
- package/dist/formulas/variants/conditional.d.ts.map +1 -0
- package/dist/formulas/variants/conditional.js +183 -0
- package/dist/formulas/variants/conditional.js.map +1 -0
- package/dist/formulas/variants/iterative-array.d.ts +20 -0
- package/dist/formulas/variants/iterative-array.d.ts.map +1 -0
- package/dist/formulas/variants/iterative-array.js +155 -0
- package/dist/formulas/variants/iterative-array.js.map +1 -0
- package/dist/formulas/variants/per-value.d.ts +20 -0
- package/dist/formulas/variants/per-value.d.ts.map +1 -0
- package/dist/formulas/variants/per-value.js +154 -0
- package/dist/formulas/variants/per-value.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/models/base.d.ts +55 -0
- package/dist/models/base.d.ts.map +1 -0
- package/dist/models/base.js +146 -0
- package/dist/models/base.js.map +1 -0
- package/dist/models/callback-manager.d.ts +7 -0
- package/dist/models/callback-manager.d.ts.map +1 -0
- package/dist/models/callback-manager.js +89 -0
- package/dist/models/callback-manager.js.map +1 -0
- package/dist/models/field.d.ts +121 -0
- package/dist/models/field.d.ts.map +1 -0
- package/dist/models/field.js +374 -0
- package/dist/models/field.js.map +1 -0
- package/dist/models/index.d.ts +13 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +7 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/model.d.ts +37 -0
- package/dist/models/model.d.ts.map +1 -0
- package/dist/models/model.js +245 -0
- package/dist/models/model.js.map +1 -0
- package/dist/models/plugins/base.d.ts +9 -0
- package/dist/models/plugins/base.d.ts.map +1 -0
- package/dist/models/plugins/base.js +3 -0
- package/dist/models/plugins/base.js.map +1 -0
- package/dist/models/plugins/formula.d.ts +18 -0
- package/dist/models/plugins/formula.d.ts.map +1 -0
- package/dist/models/plugins/formula.js +82 -0
- package/dist/models/plugins/formula.js.map +1 -0
- package/dist/models/plugins/index.d.ts +11 -0
- package/dist/models/plugins/index.d.ts.map +1 -0
- package/dist/models/plugins/index.js +52 -0
- package/dist/models/plugins/index.js.map +1 -0
- package/dist/models/plugins/plugins.d.ts +7 -0
- package/dist/models/plugins/plugins.d.ts.map +1 -0
- package/dist/models/plugins/plugins.js +7 -0
- package/dist/models/plugins/plugins.js.map +1 -0
- package/dist/models/types/base-wise-model.d.ts +7 -0
- package/dist/models/types/base-wise-model.d.ts.map +1 -0
- package/dist/models/types/base-wise-model.js +2 -0
- package/dist/models/types/base-wise-model.js.map +1 -0
- package/dist/models/types/callbacks.d.ts +19 -0
- package/dist/models/types/callbacks.d.ts.map +1 -0
- package/dist/models/types/callbacks.js +2 -0
- package/dist/models/types/callbacks.js.map +1 -0
- package/dist/models/types/disabled.d.ts +8 -0
- package/dist/models/types/disabled.d.ts.map +1 -0
- package/dist/models/types/disabled.js +2 -0
- package/dist/models/types/disabled.js.map +1 -0
- package/dist/models/types/form-field.d.ts +25 -0
- package/dist/models/types/form-field.d.ts.map +1 -0
- package/dist/models/types/form-field.js +2 -0
- package/dist/models/types/form-field.js.map +1 -0
- package/dist/models/types/model.d.ts +13 -0
- package/dist/models/types/model.d.ts.map +1 -0
- package/dist/models/types/model.js +2 -0
- package/dist/models/types/model.js.map +1 -0
- package/dist/models/types/plugins.d.ts +13 -0
- package/dist/models/types/plugins.d.ts.map +1 -0
- package/dist/models/types/plugins.js +2 -0
- package/dist/models/types/plugins.js.map +1 -0
- package/dist/models/types/wrapped-form-model-props.d.ts +11 -0
- package/dist/models/types/wrapped-form-model-props.d.ts.map +1 -0
- package/dist/models/types/wrapped-form-model-props.js +2 -0
- package/dist/models/types/wrapped-form-model-props.js.map +1 -0
- package/dist/models/wrapper.d.ts +30 -0
- package/dist/models/wrapper.d.ts.map +1 -0
- package/dist/models/wrapper.js +213 -0
- package/dist/models/wrapper.js.map +1 -0
- package/dist/settings/index.d.ts +7 -0
- package/dist/settings/index.d.ts.map +1 -0
- package/dist/settings/index.js +26 -0
- package/dist/settings/index.js.map +1 -0
- package/dist/utils/pending-promise.d.ts +6 -0
- package/dist/utils/pending-promise.d.ts.map +1 -0
- package/dist/utils/pending-promise.js +24 -0
- package/dist/utils/pending-promise.js.map +1 -0
- package/package.json +38 -0
- package/src/components/ui/Checkbox.tsx +68 -0
- package/src/components/ui/CheckboxGroup.tsx +60 -0
- package/src/components/ui/Input.tsx +72 -0
- package/src/components/ui/Radio.tsx +68 -0
- package/src/components/ui/Select.tsx +73 -0
- package/src/components/ui/Textarea.tsx +63 -0
- package/src/components/ui/index.ts +14 -0
- package/src/form/index.ts +11 -0
- package/src/form/interfaces/field-container.ts +9 -0
- package/src/form/interfaces/interfaces.ts +12 -0
- package/src/form/interfaces/settings.ts +11 -0
- package/src/form/interfaces/template.ts +7 -0
- package/src/form/interfaces/wise-form-specs.ts +10 -0
- package/src/form/styles.css +40 -0
- package/src/form/view/components/containers/index.tsx +18 -0
- package/src/form/view/components/error.tsx +9 -0
- package/src/form/view/components/field/container.tsx +6 -0
- package/src/form/view/components/field/index.tsx +107 -0
- package/src/form/view/components/field/selection.tsx +39 -0
- package/src/form/view/components/field/use-field.tsx +49 -0
- package/src/form/view/components/rows/row-container.tsx +96 -0
- package/src/form/view/components/rows/wrapper.tsx +28 -0
- package/src/form/view/components/wrapped-form.tsx +32 -0
- package/src/form/view/context.tsx +26 -0
- package/src/form/view/hooks/use-model.ts +37 -0
- package/src/form/view/hooks/use-template.tsx +64 -0
- package/src/form/view/hooks/use-types.ts +21 -0
- package/src/form/view/index.tsx +48 -0
- package/src/formulas/helpers/condition-types.ts +5 -0
- package/src/formulas/helpers/evaluations.ts +48 -0
- package/src/formulas/helpers/formula.ts +27 -0
- package/src/formulas/helpers/lexer.ts +82 -0
- package/src/formulas/helpers/parser.ts +55 -0
- package/src/formulas/helpers/token.ts +22 -0
- package/src/formulas/index.ts +198 -0
- package/src/formulas/types/formulas.ts +72 -0
- package/src/formulas/types/index.ts +5 -0
- package/src/formulas/variants/array-formula.ts +138 -0
- package/src/formulas/variants/base.ts +6 -0
- package/src/formulas/variants/basic.ts +141 -0
- package/src/formulas/variants/comparison.ts +156 -0
- package/src/formulas/variants/conditional.ts +208 -0
- package/src/formulas/variants/iterative-array.ts +152 -0
- package/src/formulas/variants/per-value.ts +152 -0
- package/src/index.ts +6 -0
- package/src/models/base.ts +164 -0
- package/src/models/callback-manager.ts +102 -0
- package/src/models/field.ts +426 -0
- package/src/models/index.ts +14 -0
- package/src/models/model.ts +260 -0
- package/src/models/plugins/base.ts +11 -0
- package/src/models/plugins/formula.ts +80 -0
- package/src/models/plugins/index.ts +48 -0
- package/src/models/plugins/plugins.ts +8 -0
- package/src/models/types/base-wise-model.ts +7 -0
- package/src/models/types/callbacks.ts +23 -0
- package/src/models/types/disabled.ts +8 -0
- package/src/models/types/form-field.ts +22 -0
- package/src/models/types/model.ts +14 -0
- package/src/models/types/plugins.ts +15 -0
- package/src/models/types/wrapped-form-model-props.ts +9 -0
- package/src/models/wrapper.ts +242 -0
- package/src/settings/index.ts +11 -0
- package/src/utils/pending-promise.ts +29 -0
- package/tsconfig.json +39 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Control } from "../field";
|
|
3
|
+
import { FormSectionWrapper } from "./wrapper";
|
|
4
|
+
import { IFieldContainer } from "../../../interfaces/field-container";
|
|
5
|
+
import type { FormField, WrappedFormModel } from "../../../../models";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Represents a container for form fields within a row, organizing them according to a specified grid style.
|
|
9
|
+
* This component is used to group form fields dynamically based on the `template` property, allowing for
|
|
10
|
+
* a flexible layout structure within the form. It supports wrapping fields in a div with a CSS grid layout
|
|
11
|
+
* to align items as specified by the `template` and `styles` provided.
|
|
12
|
+
*
|
|
13
|
+
* @param {Object} props The properties passed to the RowFieldContainer component.
|
|
14
|
+
* @param {[number, string]} props.template A tuple where the first element is the total number of fields in the row,
|
|
15
|
+
* and the second element is a string representing the CSS grid template for the layout of these fields.
|
|
16
|
+
* @param {WiseFormField[]} props.items An array of form field configurations that will be rendered within this row.
|
|
17
|
+
* @param {any} [props.styles] Optional styles to be applied to the row container, allowing for further customization.
|
|
18
|
+
* @param
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
export function RowFieldContainer({ template: [totalFields, gridStyle], items, styles, model }: IFieldContainer) {
|
|
22
|
+
// Estado para rastrear los valores de hidden de cada campo de forma reactiva
|
|
23
|
+
const [fieldHiddenStates, setFieldHiddenStates] = React.useState<Record<string, boolean>>(() => {
|
|
24
|
+
const initialStates: Record<string, boolean> = {};
|
|
25
|
+
items.forEach((field) => {
|
|
26
|
+
const fieldItem = field as any; // Using any to access dynamic properties
|
|
27
|
+
const fieldName = fieldItem?.name;
|
|
28
|
+
if (fieldName) {
|
|
29
|
+
const fieldModel = model.getField(fieldName);
|
|
30
|
+
if (fieldModel) {
|
|
31
|
+
const properties = (fieldModel as FormField).getProperties();
|
|
32
|
+
initialStates[fieldName] = (properties as any).hidden ?? false;
|
|
33
|
+
} else {
|
|
34
|
+
initialStates[fieldName] = (fieldItem as any).hidden ?? false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
return initialStates;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Suscribirse a los cambios de cada campo
|
|
42
|
+
React.useEffect(() => {
|
|
43
|
+
const listeners: Array<() => void> = [];
|
|
44
|
+
|
|
45
|
+
items.forEach((field) => {
|
|
46
|
+
const fieldItem = field as any; // Using any to access dynamic properties
|
|
47
|
+
const fieldName = fieldItem?.name;
|
|
48
|
+
const fieldType = fieldItem?.type;
|
|
49
|
+
if (!fieldName || fieldType === "wrapper") return;
|
|
50
|
+
|
|
51
|
+
const fieldModel = model.getField(fieldName);
|
|
52
|
+
if (!fieldModel) return;
|
|
53
|
+
|
|
54
|
+
const onChange = () => {
|
|
55
|
+
const properties = (fieldModel as FormField).getProperties();
|
|
56
|
+
setFieldHiddenStates((prev) => ({
|
|
57
|
+
...prev,
|
|
58
|
+
[fieldName]: (properties as any).hidden ?? false,
|
|
59
|
+
}));
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
fieldModel.on('change', onChange);
|
|
63
|
+
listeners.push(() => fieldModel.off('change', onChange));
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return () => {
|
|
67
|
+
listeners.forEach((cleanup) => cleanup());
|
|
68
|
+
};
|
|
69
|
+
}, [items, model]);
|
|
70
|
+
|
|
71
|
+
let hidden = false;
|
|
72
|
+
const output = items.reduce((acc: React.ReactElement[], field, index) => {
|
|
73
|
+
const fieldItem = field as any; // Using any to access dynamic properties
|
|
74
|
+
const fieldType = fieldItem?.type;
|
|
75
|
+
if (fieldType === "wrapper") {
|
|
76
|
+
const fieldModel = model.getField(fieldItem?.name);
|
|
77
|
+
const wrapperHidden = fieldModel ? ((fieldModel as WrappedFormModel).getProperties() as any).hidden ?? false : false;
|
|
78
|
+
if (wrapperHidden) hidden = true;
|
|
79
|
+
acc.push(<FormSectionWrapper key={`rf-row__item--${index}`} data={fieldItem} model={model} />);
|
|
80
|
+
return acc;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const fieldName = fieldItem?.name;
|
|
84
|
+
const isHidden = fieldName ? (fieldHiddenStates[fieldName] ?? (fieldItem as any).hidden ?? false) : false;
|
|
85
|
+
if (!isHidden) {
|
|
86
|
+
acc.push(<Control index={index} model={model} field={fieldItem} key={`rf-row__item--${index}`} hidden={isHidden} />);
|
|
87
|
+
}
|
|
88
|
+
return acc;
|
|
89
|
+
}, []);
|
|
90
|
+
|
|
91
|
+
const attrs = { className: `rf-fields-container`, style: {} };
|
|
92
|
+
attrs.style = { gridTemplateColumns: `${gridStyle}`, ...styles };
|
|
93
|
+
if (hidden) return null;
|
|
94
|
+
return <div {...attrs}>{output}</div>;
|
|
95
|
+
}
|
|
96
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {useWiseFormContext} from "../../context";
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param data {WrappedFormModel}
|
|
6
|
+
* @param model {FormModel} parent.
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
export function FormSectionWrapper({data, model}) {
|
|
10
|
+
const {formTypes} = useWiseFormContext();
|
|
11
|
+
|
|
12
|
+
const types = {
|
|
13
|
+
...formTypes,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
if (!data.control) throw new Error("Wrapper must have a control");
|
|
17
|
+
if (!data.name) {
|
|
18
|
+
console.error("Wrapper must have a name", data);
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
if (data?.hidden) return null;
|
|
22
|
+
|
|
23
|
+
const wrapperModel = model?.getField(data.name);
|
|
24
|
+
const Control = types[data.control];
|
|
25
|
+
// data = wrapperModel ? { ...data, ...wrapperModel.getProperties() } : data;
|
|
26
|
+
return <Control model={wrapperModel} />;
|
|
27
|
+
}
|
|
28
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { WrappedWiseFormContext, useWiseFormContext } from '../context';
|
|
3
|
+
import { RowFieldContainer } from './rows/row-container';
|
|
4
|
+
import { useTemplate } from '../hooks/use-template';
|
|
5
|
+
|
|
6
|
+
export function WrappedForm({ children, name, types }): JSX.Element {
|
|
7
|
+
const { model: parent } = useWiseFormContext();
|
|
8
|
+
const wrapper = parent.wrappers.get(name);
|
|
9
|
+
const model = wrapper;
|
|
10
|
+
const template = useTemplate(model.settings);
|
|
11
|
+
const fields = [...model.settings.fields];
|
|
12
|
+
const Containers = template.items.map((num, index) => {
|
|
13
|
+
const items = fields.splice(0, num[0]);
|
|
14
|
+
return <RowFieldContainer template={num} model={model} items={items} key={`rf-row--${index}.${num}`} />;
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const value = {
|
|
18
|
+
model,
|
|
19
|
+
name,
|
|
20
|
+
template,
|
|
21
|
+
formTypes: types ?? {},
|
|
22
|
+
parent,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<WrappedWiseFormContext.Provider value={value}>
|
|
27
|
+
{Containers}
|
|
28
|
+
{children}
|
|
29
|
+
</WrappedWiseFormContext.Provider>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { FormModel, WrappedFormModel } from '@bgroup/wise-form/models';
|
|
3
|
+
export interface IFormContext {
|
|
4
|
+
model?: FormModel | WrappedFormModel;
|
|
5
|
+
name?: string;
|
|
6
|
+
values?: Record<string, any>;
|
|
7
|
+
items?: any;
|
|
8
|
+
rows?: [number, string][];
|
|
9
|
+
template?: {
|
|
10
|
+
type: string;
|
|
11
|
+
styles: any;
|
|
12
|
+
items: any[];
|
|
13
|
+
};
|
|
14
|
+
formTypes?: Record<string, React.ElementType>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface IWrappedFormContext extends IFormContext {
|
|
18
|
+
parent: IFormContext;
|
|
19
|
+
}
|
|
20
|
+
const value: IFormContext = {};
|
|
21
|
+
export const WiseFormContext = React.createContext(value);
|
|
22
|
+
export const useWiseFormContext = () => React.useContext(WiseFormContext);
|
|
23
|
+
|
|
24
|
+
export const WrappedWiseFormContext = React.createContext(value);
|
|
25
|
+
export const useWrappedWiseFormContext = () => React.useContext(WrappedWiseFormContext);
|
|
26
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FormModel } from '@bgroup/wise-form/models';
|
|
3
|
+
import { useTemplate } from './use-template';
|
|
4
|
+
|
|
5
|
+
export function useModel(settings, form?: FormModel) {
|
|
6
|
+
const [model, setModel] = React.useState(form);
|
|
7
|
+
const [ready, setReady] = React.useState(false);
|
|
8
|
+
const [values, setValues] = React.useState(form?.values || {});
|
|
9
|
+
const templateSpecs = settings ? settings : form;
|
|
10
|
+
const { type, styles, items } = useTemplate(templateSpecs, templateSpecs.gap);
|
|
11
|
+
const startup = () => {
|
|
12
|
+
setReady(false);
|
|
13
|
+
const onChange = () => {
|
|
14
|
+
setReady(form.ready);
|
|
15
|
+
setValues({ ...form.values });
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
if (!form) {
|
|
19
|
+
const properties = settings.fields.map(item => item.name);
|
|
20
|
+
const values = settings.values || {};
|
|
21
|
+
form = new FormModel(settings, { properties, ...values });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
setModel(form);
|
|
25
|
+
form.on('change', onChange);
|
|
26
|
+
|
|
27
|
+
onChange();
|
|
28
|
+
|
|
29
|
+
return () => {
|
|
30
|
+
form.off('change', onChange);
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
React.useEffect(startup, [form?.name]);
|
|
35
|
+
|
|
36
|
+
return { ready, model, values, type, styles, items };
|
|
37
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { IFormTemplate } from '../../interfaces/template';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Applies a template to create a structured layout, optionally using a gap between elements.
|
|
5
|
+
*
|
|
6
|
+
* @param template - The template to be applied. Can be an array or an object conforming to the IFormTemplate interface.
|
|
7
|
+
* @param gap - Specifies the gap between elements.
|
|
8
|
+
* The `gap` parameter is deprecated and will be removed in a future version. Use the gap property within the template object instead.
|
|
9
|
+
* @returns An object representing the structured layout with type, styles, and items.
|
|
10
|
+
*/
|
|
11
|
+
export function useTemplate(settings, gap = undefined) {
|
|
12
|
+
if (!settings?.template) throw new Error(`${settings?.name} Doesn't have a template`);
|
|
13
|
+
|
|
14
|
+
let template = settings?.template;
|
|
15
|
+
let structure = template;
|
|
16
|
+
let styles = {};
|
|
17
|
+
|
|
18
|
+
if (!template) {
|
|
19
|
+
return {
|
|
20
|
+
type: 'grid',
|
|
21
|
+
styles: {},
|
|
22
|
+
items: settings.fields.map(item => [1, '1fr']),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (gap) {
|
|
27
|
+
template = { structure: template, gap: gap } as IFormTemplate;
|
|
28
|
+
}
|
|
29
|
+
const isArray = Array.isArray(template);
|
|
30
|
+
|
|
31
|
+
if (!isArray) {
|
|
32
|
+
if (typeof template !== 'object' || !template.structure || !Array.isArray(template.structure)) {
|
|
33
|
+
throw new Error('Template must be an array or an object');
|
|
34
|
+
}
|
|
35
|
+
structure = template.structure;
|
|
36
|
+
|
|
37
|
+
styles = template.gap ? { gap: template.gap } : {};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const processString = str => {
|
|
41
|
+
if (typeof str === 'number') return [1, '1fr'];
|
|
42
|
+
const [num, times] = str.split('x').map(Number);
|
|
43
|
+
|
|
44
|
+
const tpl = times
|
|
45
|
+
? [
|
|
46
|
+
times,
|
|
47
|
+
Array(times)
|
|
48
|
+
.fill(num)
|
|
49
|
+
.reduce((acc, v) => `${acc} 1fr`, ''),
|
|
50
|
+
]
|
|
51
|
+
: [1, '1fr'];
|
|
52
|
+
return tpl;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
type: 'grid',
|
|
57
|
+
styles: styles,
|
|
58
|
+
items: structure.map(item => {
|
|
59
|
+
if (!Array.isArray(item)) return processString(item);
|
|
60
|
+
return item;
|
|
61
|
+
}),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { WFSettings } from '../../../settings';
|
|
3
|
+
import { SelectionField } from '../components/field/selection';
|
|
4
|
+
import { Input, Textarea } from '../../../components/ui';
|
|
5
|
+
|
|
6
|
+
export function useTypes(types) {
|
|
7
|
+
return React.useMemo(() => {
|
|
8
|
+
const defaultTypes = {
|
|
9
|
+
checkbox: SelectionField,
|
|
10
|
+
radio: SelectionField,
|
|
11
|
+
select: SelectionField,
|
|
12
|
+
textarea: Textarea,
|
|
13
|
+
text: Input,
|
|
14
|
+
password: Input,
|
|
15
|
+
default: Input,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
return { ...defaultTypes, ...WFSettings.types, ...types };
|
|
19
|
+
}, [types]);
|
|
20
|
+
}
|
|
21
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useModel } from './hooks/use-model';
|
|
3
|
+
import { WiseFormContext } from './context';
|
|
4
|
+
import { useTypes } from './hooks/use-types';
|
|
5
|
+
|
|
6
|
+
import { IWiseFormSpecs } from '../interfaces/wise-form-specs';
|
|
7
|
+
import { Containers } from './components/containers';
|
|
8
|
+
|
|
9
|
+
export function WiseForm({ children, settings, types, model }: IWiseFormSpecs): JSX.Element {
|
|
10
|
+
const { ready, model: instance, type, styles, items } = useModel(settings, model);
|
|
11
|
+
const formTypes = useTypes(types);
|
|
12
|
+
|
|
13
|
+
if (!ready) return null;
|
|
14
|
+
|
|
15
|
+
if (!settings && !model) {
|
|
16
|
+
console.error('the form does not have settings or model defined', settings);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const onSubmit = (event: React.FormEvent) => {
|
|
20
|
+
event.preventDefault();
|
|
21
|
+
// Form submission can be handled via callbacks or custom handlers
|
|
22
|
+
if (instance.callbacks?.onSubmit) {
|
|
23
|
+
instance.callbacks.onSubmit({ form: instance, event });
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const value = {
|
|
28
|
+
model: instance,
|
|
29
|
+
items,
|
|
30
|
+
rows: items,
|
|
31
|
+
values: instance.values,
|
|
32
|
+
name: instance.name,
|
|
33
|
+
template: { type, styles, items },
|
|
34
|
+
formTypes,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<WiseFormContext.Provider value={value}>
|
|
39
|
+
<form onKeyDown={(e) => {
|
|
40
|
+
if (e.key === 'Enter') e.preventDefault();
|
|
41
|
+
}} className="reactive-form-container" onSubmit={onSubmit}>
|
|
42
|
+
<Containers />
|
|
43
|
+
{children}
|
|
44
|
+
</form>
|
|
45
|
+
</WiseFormContext.Provider>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export class EvaluationsManager {
|
|
2
|
+
private static evaluations: Record<string, (value: any, comparisonValue?: any) => boolean> = {
|
|
3
|
+
equal: (value, comparisonValue) => value == comparisonValue,
|
|
4
|
+
lower: (value, comparisonValue) => Number(value) < Number(comparisonValue),
|
|
5
|
+
upper: (value, comparisonValue) => Number(value) > Number(comparisonValue),
|
|
6
|
+
between: (value, [min, max]) => {
|
|
7
|
+
const numValue = Number(value);
|
|
8
|
+
return numValue >= Number(min) && numValue <= Number(max);
|
|
9
|
+
},
|
|
10
|
+
different: (value, comparisonValue) => value != comparisonValue,
|
|
11
|
+
hasValue: value => ![undefined, null, '', false].includes(value),
|
|
12
|
+
empty: value => [undefined, null, '',].includes(value),
|
|
13
|
+
lessOrEqual: (value, comparisonValue) => Number(value) <= Number(comparisonValue),
|
|
14
|
+
greaterOrEqual: (value, comparisonValue) => Number(value) >= Number(comparisonValue),
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
static validate(identifier: string, value: any, comparisonValue?: any): boolean {
|
|
18
|
+
if (!this.evaluations[identifier]) {
|
|
19
|
+
throw new Error(`Evaluation identifier "${identifier}" not recognized.`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const result = this.evaluations[identifier](value, comparisonValue);
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Evalúa un arreglo de valores para ver si alguno cumple con la condición especificada.
|
|
28
|
+
* Retorna true si al menos uno de los valores cumple con la condición.
|
|
29
|
+
*/
|
|
30
|
+
static validateAny(identifier: string, values: any[], comparisonValue?: any): boolean {
|
|
31
|
+
if (!this.evaluations[identifier]) {
|
|
32
|
+
throw new Error(`Evaluation identifier "${identifier}" not recognized.`);
|
|
33
|
+
}
|
|
34
|
+
return values.some(value => this.evaluations[identifier](value, comparisonValue));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Evalúa un arreglo de valores para ver si todos cumplen con la condición especificada.
|
|
39
|
+
* Retorna true solo si todos los valores cumplen con la condición.
|
|
40
|
+
*/
|
|
41
|
+
static validateAll(identifier: string, values: any[], comparisonValue?: any): boolean {
|
|
42
|
+
if (!this.evaluations[identifier]) {
|
|
43
|
+
throw new Error(`Evaluation identifier "${identifier}" not recognized.`);
|
|
44
|
+
}
|
|
45
|
+
return values.every(value => this.evaluations[identifier](value, comparisonValue));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Lexer } from './lexer';
|
|
2
|
+
import { Parser } from './parser';
|
|
3
|
+
import { Token } from './token';
|
|
4
|
+
|
|
5
|
+
type ParserData = {
|
|
6
|
+
parser: Parser;
|
|
7
|
+
tokens: Token[];
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export class Formula {
|
|
12
|
+
#lexer = new Lexer();
|
|
13
|
+
#parsers: Map<string, ParserData> = new Map();
|
|
14
|
+
#tokens: Token[];
|
|
15
|
+
constructor(data) {
|
|
16
|
+
if (!data.formula) throw new Error('To get a parser you must provide a formula');
|
|
17
|
+
// if (this.#parsers.has(data.formula)) return this.#parsers.get(data.formula);
|
|
18
|
+
const tokens = this.#lexer.tokenize(data.formula);
|
|
19
|
+
const parser = new Parser(tokens);
|
|
20
|
+
const result = { tokens, parser, ...data };
|
|
21
|
+
this.#parsers.set(data.formula, result);
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
initialize() {}
|
|
26
|
+
}
|
|
27
|
+
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Token } from './token';
|
|
2
|
+
import { TokenType } from '../types';
|
|
3
|
+
|
|
4
|
+
export class Lexer {
|
|
5
|
+
private tokenRegex: RegExp = /\s*(\(|\)|\+|\-|\*|\/|\d+\.\d+|\d+|[A-Za-z_][A-Za-z0-9_]*)\s*/g;
|
|
6
|
+
private flattenTokens: boolean;
|
|
7
|
+
|
|
8
|
+
constructor(flattenTokens: boolean = false) {
|
|
9
|
+
this.flattenTokens = flattenTokens;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
tokenize(formula: string): Token[] {
|
|
13
|
+
this.tokenRegex.lastIndex = 0;
|
|
14
|
+
const tokens: Token[] = [];
|
|
15
|
+
const stack: Array<Token[]> = [tokens]; // Stack to manage nested token lists
|
|
16
|
+
let match: RegExpExecArray | null;
|
|
17
|
+
|
|
18
|
+
while ((match = this.tokenRegex.exec(formula)) !== null) {
|
|
19
|
+
const tokenValue = match[1];
|
|
20
|
+
let tokenType: TokenType = this.determineTokenType(tokenValue);
|
|
21
|
+
|
|
22
|
+
if (tokenType === 'parenthesis') {
|
|
23
|
+
if (tokenValue === '(') {
|
|
24
|
+
if (!this.flattenTokens) {
|
|
25
|
+
// Start a new scope for tokens
|
|
26
|
+
stack.push([]);
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
if (!this.flattenTokens) {
|
|
30
|
+
// End the current scope
|
|
31
|
+
const subTokens = stack.pop();
|
|
32
|
+
if (!subTokens) {
|
|
33
|
+
throw new Error('Mismatched parentheses in the formula');
|
|
34
|
+
}
|
|
35
|
+
// Create a parenthesis token with these subtokens as children
|
|
36
|
+
const parentTokens = stack[stack.length - 1];
|
|
37
|
+
parentTokens.push(new Token('parenthesis', '()', null, subTokens));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
// Add this token to the current scope
|
|
42
|
+
stack[stack.length - 1].push(new Token(tokenType, tokenValue));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (stack.length !== 1) {
|
|
47
|
+
throw new Error('Mismatched parentheses in the formula');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// If flattenTokens is true, flatten all tokens into a single array
|
|
51
|
+
if (this.flattenTokens) {
|
|
52
|
+
return this.flatten(tokens);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return tokens; // Return the outermost list of tokens
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private determineTokenType(value: string): TokenType {
|
|
59
|
+
const operators = {
|
|
60
|
+
'+': 'operator',
|
|
61
|
+
'-': 'operator',
|
|
62
|
+
'*': 'operator',
|
|
63
|
+
'/': 'operator',
|
|
64
|
+
'(': 'parenthesis',
|
|
65
|
+
')': 'parenthesis',
|
|
66
|
+
};
|
|
67
|
+
return operators[value] || (!isNaN(parseFloat(value)) ? 'number' : 'variable');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private flatten(tokens: Token[]): Token[] {
|
|
71
|
+
const flatList: Token[] = [];
|
|
72
|
+
for (const token of tokens) {
|
|
73
|
+
if (token.type === 'parenthesis' && token.children) {
|
|
74
|
+
flatList.push(...this.flatten(token.children)); // Flatten nested tokens
|
|
75
|
+
} else {
|
|
76
|
+
flatList.push(token);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return flatList;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Token } from './token';
|
|
2
|
+
|
|
3
|
+
type TokenType = 'variable' | 'number' | 'operator';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The Parser class is responsible for parsing a sequence of tokens into an abstract syntax tree (AST).
|
|
7
|
+
* The tokens should be an array of objects with `type` and `value` properties.
|
|
8
|
+
*
|
|
9
|
+
* The Parser handles mathematical expressions and ensures that the tokens are in the correct order
|
|
10
|
+
* for later evaluation. It understands variables, numbers, and parentheses, and is extendable to support
|
|
11
|
+
* additional operations and precedence rules.
|
|
12
|
+
*
|
|
13
|
+
* Example usage:
|
|
14
|
+
* ```
|
|
15
|
+
* const tokens: Token[] = [...];
|
|
16
|
+
* const parser = new Parser(tokens);
|
|
17
|
+
* const ast = parser.parse();
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export class Parser {
|
|
21
|
+
private tokens: Token[];
|
|
22
|
+
private currentTokenIndex: number;
|
|
23
|
+
|
|
24
|
+
constructor(tokens: Token[]) {
|
|
25
|
+
this.tokens = tokens;
|
|
26
|
+
this.currentTokenIndex = 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public parse(): Token | undefined {
|
|
30
|
+
return this.parseExpression();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private parseExpression(): Token | undefined {
|
|
34
|
+
let token = this.tokens[this.currentTokenIndex];
|
|
35
|
+
if (token && token.type === 'variable') {
|
|
36
|
+
this.currentTokenIndex++;
|
|
37
|
+
return token;
|
|
38
|
+
} else if (token && token.type === 'number') {
|
|
39
|
+
this.currentTokenIndex++;
|
|
40
|
+
return token;
|
|
41
|
+
} else if (token && token.value === '(') {
|
|
42
|
+
this.currentTokenIndex++; // Skip '('
|
|
43
|
+
let expr = this.parseExpression(); // Parse subexpression
|
|
44
|
+
if (this.tokens[this.currentTokenIndex] && this.tokens[this.currentTokenIndex].value === ')') {
|
|
45
|
+
this.currentTokenIndex++; // Skip ')'
|
|
46
|
+
return expr;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// TODO: Add cases for parsing different operations (like addition, multiplication etc.)
|
|
50
|
+
// TODO: Implement precedence handling for different operations
|
|
51
|
+
// This function should be extended to fully construct the AST.
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { TokenType } from '../types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The Token class now includes a stringValue property for storing the original string value
|
|
5
|
+
* of the expression inside the parentheses and an optional parent property for storing the parent token.
|
|
6
|
+
*/
|
|
7
|
+
export class Token {
|
|
8
|
+
type: TokenType;
|
|
9
|
+
value: string;
|
|
10
|
+
stringValue?: string;
|
|
11
|
+
children?: Token[];
|
|
12
|
+
parent?: Token;
|
|
13
|
+
|
|
14
|
+
constructor(type: TokenType, value: string, stringValue?: string, children?: Token[], parent?: Token) {
|
|
15
|
+
this.type = type;
|
|
16
|
+
this.value = value;
|
|
17
|
+
this.stringValue = stringValue;
|
|
18
|
+
this.children = children;
|
|
19
|
+
this.parent = parent;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|