@servicetitan/dte-pdf-editor 1.16.0 → 1.18.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.
- package/README.md +35 -7
- package/dist/components/field-config-panel/advanced-settings.d.ts +9 -0
- package/dist/components/field-config-panel/advanced-settings.d.ts.map +1 -0
- package/dist/components/field-config-panel/advanced-settings.js +17 -0
- package/dist/components/field-config-panel/advanced-settings.js.map +1 -0
- package/dist/components/field-config-panel/field-config-panel-overlay.d.ts +4 -1
- package/dist/components/field-config-panel/field-config-panel-overlay.d.ts.map +1 -1
- package/dist/components/field-config-panel/field-config-panel-overlay.js +2 -2
- package/dist/components/field-config-panel/field-config-panel-overlay.js.map +1 -1
- package/dist/components/field-config-panel/field-config-panel.d.ts +4 -1
- package/dist/components/field-config-panel/field-config-panel.d.ts.map +1 -1
- package/dist/components/field-config-panel/field-config-panel.js +11 -5
- package/dist/components/field-config-panel/field-config-panel.js.map +1 -1
- package/dist/components/field-config-panel/field-sidebar.d.ts +13 -0
- package/dist/components/field-config-panel/field-sidebar.d.ts.map +1 -0
- package/dist/components/field-config-panel/field-sidebar.js +20 -0
- package/dist/components/field-config-panel/field-sidebar.js.map +1 -0
- package/dist/components/field-config-panel/formula-generator.d.ts +11 -0
- package/dist/components/field-config-panel/formula-generator.d.ts.map +1 -0
- package/dist/components/field-config-panel/formula-generator.js +51 -0
- package/dist/components/field-config-panel/formula-generator.js.map +1 -0
- package/dist/components/field-config-panel/formula-modal.d.ts +12 -0
- package/dist/components/field-config-panel/formula-modal.d.ts.map +1 -0
- package/dist/components/field-config-panel/formula-modal.js +99 -0
- package/dist/components/field-config-panel/formula-modal.js.map +1 -0
- package/dist/components/field-config-panel/formula-workspace.d.ts +23 -0
- package/dist/components/field-config-panel/formula-workspace.d.ts.map +1 -0
- package/dist/components/field-config-panel/formula-workspace.js +28 -0
- package/dist/components/field-config-panel/formula-workspace.js.map +1 -0
- package/dist/components/field-config-panel/result-type-selector.d.ts +9 -0
- package/dist/components/field-config-panel/result-type-selector.d.ts.map +1 -0
- package/dist/components/field-config-panel/result-type-selector.js +10 -0
- package/dist/components/field-config-panel/result-type-selector.js.map +1 -0
- package/dist/components/field-sidebar/calculated-field-type-list.d.ts +9 -0
- package/dist/components/field-sidebar/calculated-field-type-list.d.ts.map +1 -0
- package/dist/components/field-sidebar/calculated-field-type-list.js +12 -0
- package/dist/components/field-sidebar/calculated-field-type-list.js.map +1 -0
- package/dist/components/field-sidebar/data-model-field-type-list.d.ts +0 -1
- package/dist/components/field-sidebar/data-model-field-type-list.d.ts.map +1 -1
- package/dist/components/field-sidebar/data-model-field-type-list.js +8 -7
- package/dist/components/field-sidebar/data-model-field-type-list.js.map +1 -1
- package/dist/components/field-sidebar/field-menu-group.d.ts +11 -0
- package/dist/components/field-sidebar/field-menu-group.d.ts.map +1 -0
- package/dist/components/field-sidebar/field-menu-group.js +6 -0
- package/dist/components/field-sidebar/field-menu-group.js.map +1 -0
- package/dist/components/field-sidebar/field-sidebar.d.ts.map +1 -1
- package/dist/components/field-sidebar/field-sidebar.js +6 -15
- package/dist/components/field-sidebar/field-sidebar.js.map +1 -1
- package/dist/components/field-sidebar/fillable-field-type-list.d.ts +0 -1
- package/dist/components/field-sidebar/fillable-field-type-list.d.ts.map +1 -1
- package/dist/components/field-sidebar/fillable-field-type-list.js +8 -9
- package/dist/components/field-sidebar/fillable-field-type-list.js.map +1 -1
- package/dist/components/pdf-editor/pdf-editor.d.ts.map +1 -1
- package/dist/components/pdf-editor/pdf-editor.js +1 -1
- package/dist/components/pdf-editor/pdf-editor.js.map +1 -1
- package/dist/components/pdf-fields-overlay/pdf-overlay-field-calculated.d.ts +8 -0
- package/dist/components/pdf-fields-overlay/pdf-overlay-field-calculated.d.ts.map +1 -0
- package/dist/components/pdf-fields-overlay/pdf-overlay-field-calculated.js +5 -0
- package/dist/components/pdf-fields-overlay/pdf-overlay-field-calculated.js.map +1 -0
- package/dist/components/pdf-fields-overlay/pdf-overlay-field.d.ts.map +1 -1
- package/dist/components/pdf-fields-overlay/pdf-overlay-field.js +11 -6
- package/dist/components/pdf-fields-overlay/pdf-overlay-field.js.map +1 -1
- package/dist/components/pdf-view/pdf-view-calculated.d.ts +9 -0
- package/dist/components/pdf-view/pdf-view-calculated.d.ts.map +1 -0
- package/dist/components/pdf-view/pdf-view-calculated.js +18 -0
- package/dist/components/pdf-view/pdf-view-calculated.js.map +1 -0
- package/dist/components/pdf-view/pdf-view.d.ts.map +1 -1
- package/dist/components/pdf-view/pdf-view.js +2 -1
- package/dist/components/pdf-view/pdf-view.js.map +1 -1
- package/dist/constants/field.constants.d.ts +3 -2
- package/dist/constants/field.constants.d.ts.map +1 -1
- package/dist/constants/field.constants.js +6 -0
- package/dist/constants/field.constants.js.map +1 -1
- package/dist/constants/menu-group.d.ts +8 -0
- package/dist/constants/menu-group.d.ts.map +1 -0
- package/dist/constants/menu-group.js +20 -0
- package/dist/constants/menu-group.js.map +1 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/useFieldDrag.d.ts +9 -2
- package/dist/hooks/useFieldDrag.d.ts.map +1 -1
- package/dist/hooks/useFieldDrag.js +60 -8
- package/dist/hooks/useFieldDrag.js.map +1 -1
- package/dist/hooks/useFormulaEditor.d.ts +22 -0
- package/dist/hooks/useFormulaEditor.d.ts.map +1 -0
- package/dist/hooks/useFormulaEditor.js +290 -0
- package/dist/hooks/useFormulaEditor.js.map +1 -0
- package/dist/hooks/usePdfFieldDnD.d.ts.map +1 -1
- package/dist/hooks/usePdfFieldDnD.js +19 -3
- package/dist/hooks/usePdfFieldDnD.js.map +1 -1
- package/dist/interface/types.d.ts +45 -3
- package/dist/interface/types.d.ts.map +1 -1
- package/dist/interface/types.js +3 -0
- package/dist/interface/types.js.map +1 -1
- package/dist/utils/data-model/extract-fields.utils.d.ts +5 -5
- package/dist/utils/data-model/extract-fields.utils.d.ts.map +1 -1
- package/dist/utils/data-model/extract-fields.utils.js +42 -8
- package/dist/utils/data-model/extract-fields.utils.js.map +1 -1
- package/dist/utils/formula/caret.utils.d.ts +3 -0
- package/dist/utils/formula/caret.utils.d.ts.map +1 -0
- package/dist/utils/formula/caret.utils.js +123 -0
- package/dist/utils/formula/caret.utils.js.map +1 -0
- package/dist/utils/formula/dom.utils.d.ts +4 -0
- package/dist/utils/formula/dom.utils.d.ts.map +1 -0
- package/dist/utils/formula/dom.utils.js +34 -0
- package/dist/utils/formula/dom.utils.js.map +1 -0
- package/dist/utils/formula/evaluate-formula.utils.d.ts +13 -0
- package/dist/utils/formula/evaluate-formula.utils.d.ts.map +1 -0
- package/dist/utils/formula/evaluate-formula.utils.js +134 -0
- package/dist/utils/formula/evaluate-formula.utils.js.map +1 -0
- package/dist/utils/formula/expression.utils.d.ts +18 -0
- package/dist/utils/formula/expression.utils.d.ts.map +1 -0
- package/dist/utils/formula/expression.utils.js +84 -0
- package/dist/utils/formula/expression.utils.js.map +1 -0
- package/dist/utils/formula/format-calculated-result.utils.d.ts +7 -0
- package/dist/utils/formula/format-calculated-result.utils.d.ts.map +1 -0
- package/dist/utils/formula/format-calculated-result.utils.js +50 -0
- package/dist/utils/formula/format-calculated-result.utils.js.map +1 -0
- package/dist/utils/formula/formula-types.d.ts +3 -0
- package/dist/utils/formula/formula-types.d.ts.map +1 -0
- package/dist/utils/formula/formula-types.js +2 -0
- package/dist/utils/formula/formula-types.js.map +1 -0
- package/dist/utils/formula/index.d.ts +11 -0
- package/dist/utils/formula/index.d.ts.map +1 -0
- package/dist/utils/formula/index.js +11 -0
- package/dist/utils/formula/index.js.map +1 -0
- package/dist/utils/formula/referenced-paths.utils.d.ts +7 -0
- package/dist/utils/formula/referenced-paths.utils.d.ts.map +1 -0
- package/dist/utils/formula/referenced-paths.utils.js +18 -0
- package/dist/utils/formula/referenced-paths.utils.js.map +1 -0
- package/dist/utils/formula/render-formula.utils.d.ts +8 -0
- package/dist/utils/formula/render-formula.utils.d.ts.map +1 -0
- package/dist/utils/formula/render-formula.utils.js +39 -0
- package/dist/utils/formula/render-formula.utils.js.map +1 -0
- package/dist/utils/formula/serialize-formula.utils.d.ts +14 -0
- package/dist/utils/formula/serialize-formula.utils.d.ts.map +1 -0
- package/dist/utils/formula/serialize-formula.utils.js +33 -0
- package/dist/utils/formula/serialize-formula.utils.js.map +1 -0
- package/dist/utils/formula/validate-formula.utils.d.ts +11 -0
- package/dist/utils/formula/validate-formula.utils.d.ts.map +1 -0
- package/dist/utils/formula/validate-formula.utils.js +79 -0
- package/dist/utils/formula/validate-formula.utils.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/field-config-panel/advanced-settings.tsx +113 -0
- package/src/components/field-config-panel/field-config-panel-overlay.tsx +8 -1
- package/src/components/field-config-panel/field-config-panel.tsx +43 -15
- package/src/components/field-config-panel/field-sidebar.tsx +91 -0
- package/src/components/field-config-panel/formula-generator.tsx +122 -0
- package/src/components/field-config-panel/formula-modal.tsx +229 -0
- package/src/components/field-config-panel/formula-workspace.tsx +116 -0
- package/src/components/field-config-panel/result-type-selector.tsx +34 -0
- package/src/components/field-sidebar/calculated-field-type-list.tsx +29 -0
- package/src/components/field-sidebar/data-model-field-type-list.tsx +10 -4
- package/src/components/field-sidebar/field-menu-group.tsx +36 -0
- package/src/components/field-sidebar/field-sidebar.tsx +14 -55
- package/src/components/field-sidebar/fillable-field-type-list.tsx +11 -9
- package/src/components/pdf-editor/pdf-editor.tsx +2 -0
- package/src/components/pdf-fields-overlay/pdf-overlay-field-calculated.tsx +15 -0
- package/src/components/pdf-fields-overlay/pdf-overlay-field.tsx +10 -5
- package/src/components/pdf-view/pdf-view-calculated.tsx +23 -0
- package/src/components/pdf-view/pdf-view.tsx +4 -0
- package/src/constants/field.constants.ts +9 -2
- package/src/constants/menu-group.ts +26 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useFieldDrag.ts +84 -8
- package/src/hooks/useFormulaEditor.ts +336 -0
- package/src/hooks/usePdfFieldDnD.ts +36 -14
- package/src/interface/types.ts +38 -2
- package/src/styles/formula-modal.css +307 -0
- package/src/styles/index.css +1 -0
- package/src/styles/pdf-field-overlay.css +1 -0
- package/src/utils/data-model/extract-fields.utils.ts +65 -7
- package/src/utils/formula/caret.utils.ts +125 -0
- package/src/utils/formula/dom.utils.ts +35 -0
- package/src/utils/formula/evaluate-formula.utils.ts +159 -0
- package/src/utils/formula/expression.utils.ts +99 -0
- package/src/utils/formula/format-calculated-result.utils.ts +79 -0
- package/src/utils/formula/formula-types.ts +2 -0
- package/src/utils/formula/index.ts +10 -0
- package/src/utils/formula/referenced-paths.utils.ts +18 -0
- package/src/utils/formula/render-formula.utils.ts +40 -0
- package/src/utils/formula/serialize-formula.utils.ts +40 -0
- package/src/utils/formula/validate-formula.utils.ts +94 -0
- package/src/utils/index.ts +1 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert StructuredFormula tokens to an editable expression string.
|
|
3
|
+
* Uses field path as the identifier so parsing is unambiguous.
|
|
4
|
+
*/
|
|
5
|
+
export function tokensToExpression(formula) {
|
|
6
|
+
var _a;
|
|
7
|
+
if (!((_a = formula === null || formula === void 0 ? void 0 : formula.tokens) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
8
|
+
return '';
|
|
9
|
+
}
|
|
10
|
+
return formula.tokens
|
|
11
|
+
.map(t => {
|
|
12
|
+
if (t.type === 'field') {
|
|
13
|
+
return t.path;
|
|
14
|
+
}
|
|
15
|
+
return t.value;
|
|
16
|
+
})
|
|
17
|
+
.join(' ')
|
|
18
|
+
.replace(/\s+/g, ' ')
|
|
19
|
+
.trim();
|
|
20
|
+
}
|
|
21
|
+
// Field paths may contain hyphens (e.g. fillable_recipient_uuid with UUIDs)
|
|
22
|
+
const EXPRESSION_REGEX = /[A-Za-z_][A-Za-z0-9_.-]*|\d+(?:\.\d+)?|[()+\-*/]|\s+|./g;
|
|
23
|
+
export function tokenizeExpression(expression) {
|
|
24
|
+
const tokens = [];
|
|
25
|
+
let match;
|
|
26
|
+
while ((match = EXPRESSION_REGEX.exec(expression)) !== null) {
|
|
27
|
+
const value = match[0];
|
|
28
|
+
if (/^[A-Za-z_]/.test(value)) {
|
|
29
|
+
tokens.push({ type: 'field', value });
|
|
30
|
+
}
|
|
31
|
+
else if (/^\d/.test(value)) {
|
|
32
|
+
tokens.push({ type: 'number', value });
|
|
33
|
+
}
|
|
34
|
+
else if (/^[()+\-*/]$/.test(value)) {
|
|
35
|
+
tokens.push({ type: value === '(' || value === ')' ? 'paren' : 'operator', value });
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
tokens.push({ type: 'text', value });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return tokens;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Parse an expression string into FormulaToken[] using valid paths and path->label map.
|
|
45
|
+
* Invalid or unknown identifiers are skipped (or could be left as placeholder); only known paths become field tokens.
|
|
46
|
+
*/
|
|
47
|
+
export function parseExpression(expression, validPaths, pathToLabel) {
|
|
48
|
+
var _a;
|
|
49
|
+
const parts = tokenizeExpression(expression).filter(p => p.type !== 'text' || p.value.trim() !== '');
|
|
50
|
+
const tokens = [];
|
|
51
|
+
for (const part of parts) {
|
|
52
|
+
if (part.type === 'text') {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (part.type === 'field') {
|
|
56
|
+
if (validPaths.has(part.value)) {
|
|
57
|
+
tokens.push({
|
|
58
|
+
type: 'field',
|
|
59
|
+
path: part.value,
|
|
60
|
+
label: (_a = pathToLabel.get(part.value)) !== null && _a !== void 0 ? _a : part.value,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (part.type === 'number') {
|
|
66
|
+
tokens.push({ type: 'number', value: part.value });
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (part.type === 'operator') {
|
|
70
|
+
tokens.push({
|
|
71
|
+
type: 'operator',
|
|
72
|
+
value: part.value,
|
|
73
|
+
});
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (part.type === 'paren') {
|
|
77
|
+
tokens.push(part.value === '('
|
|
78
|
+
? { type: 'lparen', value: '(' }
|
|
79
|
+
: { type: 'rparen', value: ')' });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return tokens;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=expression.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression.utils.js","sourceRoot":"","sources":["../../../src/utils/formula/expression.utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CalculatedFieldFormat } from '../../interface/types';
|
|
2
|
+
/**
|
|
3
|
+
* Format a calculated formula result for display using advanced settings.
|
|
4
|
+
* Applies rounding, decimal places, thousands/decimal separators, result type (number/currency/percent), and prefix/postfix.
|
|
5
|
+
*/
|
|
6
|
+
export declare function formatCalculatedResult(value: number, format: CalculatedFieldFormat | undefined): string;
|
|
7
|
+
//# sourceMappingURL=format-calculated-result.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-calculated-result.utils.d.ts","sourceRoot":"","sources":["../../../src/utils/formula/format-calculated-result.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAsC9D;;;GAGG;AACH,wBAAgB,sBAAsB,CAClC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,qBAAqB,GAAG,SAAS,GAC1C,MAAM,CAiCR"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
function roundValue(value, decimals, mode) {
|
|
2
|
+
const factor = 10 ** decimals;
|
|
3
|
+
const scaled = value * factor;
|
|
4
|
+
switch (mode) {
|
|
5
|
+
case 'floor':
|
|
6
|
+
return Math.floor(scaled) / factor;
|
|
7
|
+
case 'ceil':
|
|
8
|
+
return Math.ceil(scaled) / factor;
|
|
9
|
+
default:
|
|
10
|
+
return Math.round(scaled) / factor;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function formatIntegerPart(s, thousandsSeparator, decimalSeparator) {
|
|
14
|
+
if (!thousandsSeparator) {
|
|
15
|
+
return s;
|
|
16
|
+
}
|
|
17
|
+
const sep = decimalSeparator === ',' ? '.' : ','; // opposite for thousands
|
|
18
|
+
const parts = [];
|
|
19
|
+
let i = s.length;
|
|
20
|
+
while (i > 0) {
|
|
21
|
+
const start = Math.max(0, i - 3);
|
|
22
|
+
parts.unshift(s.slice(start, i));
|
|
23
|
+
i = start;
|
|
24
|
+
}
|
|
25
|
+
return parts.join(sep);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Format a calculated formula result for display using advanced settings.
|
|
29
|
+
* Applies rounding, decimal places, thousands/decimal separators, result type (number/currency/percent), and prefix/postfix.
|
|
30
|
+
*/
|
|
31
|
+
export function formatCalculatedResult(value, format) {
|
|
32
|
+
if (format == null) {
|
|
33
|
+
return String(value);
|
|
34
|
+
}
|
|
35
|
+
const { decimalSeparator, decimalSeparatorEnabled, decimals, postfixText, prefixText, resultType, roundingMode, thousandsSeparator, } = format;
|
|
36
|
+
let num = value;
|
|
37
|
+
if (resultType === 'percent') {
|
|
38
|
+
num = value * 100;
|
|
39
|
+
}
|
|
40
|
+
const rounded = roundValue(num, decimals, roundingMode);
|
|
41
|
+
const fixed = rounded.toFixed(decimals);
|
|
42
|
+
const [intPart, decPart] = fixed.split('.');
|
|
43
|
+
const decimalSep = decimalSeparatorEnabled ? decimalSeparator : '.';
|
|
44
|
+
const intFormatted = formatIntegerPart(intPart, thousandsSeparator, decimalSep);
|
|
45
|
+
const decSuffix = decimals > 0 ? decimalSep + (decPart !== null && decPart !== void 0 ? decPart : '') : '';
|
|
46
|
+
const numberStr = intFormatted + decSuffix;
|
|
47
|
+
const suffix = resultType === 'percent' ? '%' : '';
|
|
48
|
+
return `${prefixText}${numberStr}${suffix}${postfixText}`;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=format-calculated-result.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-calculated-result.utils.js","sourceRoot":"","sources":["../../../src/utils/formula/format-calculated-result.utils.ts"],"names":[],"mappings":"AAEA,SAAS,UAAU,CACf,KAAa,EACb,QAAgB,EAChB,IAA2C;IAE3C,MAAM,MAAM,GAAG,EAAE,IAAI,QAAQ,CAAC;IAC9B,MAAM,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;IAC9B,QAAQ,IAAI,EAAE,CAAC;QACX,KAAK,OAAO;YACR,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;QACvC,KAAK,MAAM;YACP,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;QACtC;YACI,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAC3C,CAAC;AACL,CAAC;AAED,SAAS,iBAAiB,CACtB,CAAS,EACT,kBAA2B,EAC3B,gBAA2B;IAE3B,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACtB,OAAO,CAAC,CAAC;IACb,CAAC;IACD,MAAM,GAAG,GAAG,gBAAgB,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,yBAAyB;IAC3E,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;IACjB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACjC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC,GAAG,KAAK,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAClC,KAAa,EACb,MAAyC;IAEzC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;QACjB,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,EACF,gBAAgB,EAChB,uBAAuB,EACvB,QAAQ,EACR,WAAW,EACX,UAAU,EACV,UAAU,EACV,YAAY,EACZ,kBAAkB,GACrB,GAAG,MAAM,CAAC;IAEX,IAAI,GAAG,GAAG,KAAK,CAAC;IAChB,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC3B,GAAG,GAAG,KAAK,GAAG,GAAG,CAAC;IACtB,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE5C,MAAM,UAAU,GAAG,uBAAuB,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC;IACpE,MAAM,YAAY,GAAG,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,EAAE,UAAU,CAAC,CAAC;IAChF,MAAM,SAAS,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEnE,MAAM,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;IAC3C,MAAM,MAAM,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAEnD,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,WAAW,EAAE,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formula-types.d.ts","sourceRoot":"","sources":["../../../src/utils/formula/formula-types.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC9F,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formula-types.js","sourceRoot":"","sources":["../../../src/utils/formula/formula-types.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './caret.utils';
|
|
2
|
+
export * from './dom.utils';
|
|
3
|
+
export * from './evaluate-formula.utils';
|
|
4
|
+
export * from './expression.utils';
|
|
5
|
+
export * from './format-calculated-result.utils';
|
|
6
|
+
export * from './formula-types';
|
|
7
|
+
export * from './referenced-paths.utils';
|
|
8
|
+
export * from './render-formula.utils';
|
|
9
|
+
export * from './serialize-formula.utils';
|
|
10
|
+
export * from './validate-formula.utils';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/formula/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kCAAkC,CAAC;AACjD,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './caret.utils';
|
|
2
|
+
export * from './dom.utils';
|
|
3
|
+
export * from './evaluate-formula.utils';
|
|
4
|
+
export * from './expression.utils';
|
|
5
|
+
export * from './format-calculated-result.utils';
|
|
6
|
+
export * from './formula-types';
|
|
7
|
+
export * from './referenced-paths.utils';
|
|
8
|
+
export * from './render-formula.utils';
|
|
9
|
+
export * from './serialize-formula.utils';
|
|
10
|
+
export * from './validate-formula.utils';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/formula/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kCAAkC,CAAC;AACjD,cAAc,iBAAiB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { StructuredFormula } from '../../interface/types';
|
|
2
|
+
/**
|
|
3
|
+
* Returns the set of data model field paths referenced in the formula.
|
|
4
|
+
* Used for recalculation scope: only these fields should trigger formula updates.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getReferencedPaths(formula: StructuredFormula | undefined | null): string[];
|
|
7
|
+
//# sourceMappingURL=referenced-paths.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"referenced-paths.utils.d.ts","sourceRoot":"","sources":["../../../src/utils/formula/referenced-paths.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,EAAE,CAW1F"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the set of data model field paths referenced in the formula.
|
|
3
|
+
* Used for recalculation scope: only these fields should trigger formula updates.
|
|
4
|
+
*/
|
|
5
|
+
export function getReferencedPaths(formula) {
|
|
6
|
+
var _a;
|
|
7
|
+
if (!((_a = formula === null || formula === void 0 ? void 0 : formula.tokens) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
const paths = [];
|
|
11
|
+
for (const token of formula.tokens) {
|
|
12
|
+
if (token.type === 'field') {
|
|
13
|
+
paths.push(token.path);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return paths;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=referenced-paths.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"referenced-paths.utils.js","sourceRoot":"","sources":["../../../src/utils/formula/referenced-paths.utils.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAA6C;;IAC5E,IAAI,CAAC,CAAA,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,0CAAE,MAAM,CAAA,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACjC,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FormulaToken } from '../../interface/types';
|
|
2
|
+
/**
|
|
3
|
+
* Renders formula tokens to HTML for the read-only preview (e.g. formula box).
|
|
4
|
+
* Uses the same token classes as the modal (dte-formula-token, dte-formula-token-field, etc.).
|
|
5
|
+
*/
|
|
6
|
+
export declare function renderFormulaPreviewHtml(tokens: FormulaToken[]): string;
|
|
7
|
+
export declare function renderFormulaHtml(expression: string, labelMap: Map<string, string>): string;
|
|
8
|
+
//# sourceMappingURL=render-formula.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-formula.utils.d.ts","sourceRoot":"","sources":["../../../src/utils/formula/render-formula.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAIrD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,CAYvE;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAiB3F"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { escapeHtml } from './dom.utils';
|
|
2
|
+
import { tokenizeExpression } from './expression.utils';
|
|
3
|
+
/**
|
|
4
|
+
* Renders formula tokens to HTML for the read-only preview (e.g. formula box).
|
|
5
|
+
* Uses the same token classes as the modal (dte-formula-token, dte-formula-token-field, etc.).
|
|
6
|
+
*/
|
|
7
|
+
export function renderFormulaPreviewHtml(tokens) {
|
|
8
|
+
if (!(tokens === null || tokens === void 0 ? void 0 : tokens.length)) {
|
|
9
|
+
return '';
|
|
10
|
+
}
|
|
11
|
+
return tokens
|
|
12
|
+
.map(token => {
|
|
13
|
+
const type = token.type;
|
|
14
|
+
const text = type === 'field' ? token.label : token.value;
|
|
15
|
+
const escaped = escapeHtml(text).replace(/ /g, ' ');
|
|
16
|
+
return `<span class="dte-formula-token dte-formula-token-${type}">${escaped}</span>`;
|
|
17
|
+
})
|
|
18
|
+
.join('');
|
|
19
|
+
}
|
|
20
|
+
export function renderFormulaHtml(expression, labelMap) {
|
|
21
|
+
if (!expression.trim()) {
|
|
22
|
+
return '';
|
|
23
|
+
}
|
|
24
|
+
const parts = tokenizeExpression(expression);
|
|
25
|
+
let fieldIndex = 0;
|
|
26
|
+
return parts
|
|
27
|
+
.map(part => {
|
|
28
|
+
var _a;
|
|
29
|
+
if (part.type === 'field') {
|
|
30
|
+
const displayValue = (_a = labelMap.get(part.value)) !== null && _a !== void 0 ? _a : part.value;
|
|
31
|
+
const currentIndex = fieldIndex;
|
|
32
|
+
fieldIndex += 1;
|
|
33
|
+
return `<span class="dte-formula-chip" contenteditable="false" data-field="${escapeHtml(part.value)}" data-field-index="${currentIndex}" draggable="true"><span class="dte-formula-chip-label">${escapeHtml(displayValue)}</span><span class="dte-formula-chip-remove" data-field-remove="true" role="button" aria-label="Remove field">×</span></span>`;
|
|
34
|
+
}
|
|
35
|
+
return `<span>${escapeHtml(part.value).replace(/ /g, ' ')}</span>`;
|
|
36
|
+
})
|
|
37
|
+
.join('');
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=render-formula.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-formula.utils.js","sourceRoot":"","sources":["../../../src/utils/formula/render-formula.utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAsB;IAC3D,IAAI,CAAC,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,MAAM,CAAA,EAAE,CAAC;QAClB,OAAO,EAAE,CAAC;IACd,CAAC;IACD,OAAO,MAAM;SACR,GAAG,CAAC,KAAK,CAAC,EAAE;QACT,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACxB,MAAM,IAAI,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAE,KAA2B,CAAC,KAAK,CAAC;QACjF,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACzD,OAAO,oDAAoD,IAAI,KAAK,OAAO,SAAS,CAAC;IACzF,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,UAAkB,EAAE,QAA6B;IAC/E,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;QACrB,OAAO,EAAE,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAC7C,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,OAAO,KAAK;SACP,GAAG,CAAC,IAAI,CAAC,EAAE;;QACR,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACxB,MAAM,YAAY,GAAG,MAAA,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,mCAAI,IAAI,CAAC,KAAK,CAAC;YAC5D,MAAM,YAAY,GAAG,UAAU,CAAC;YAChC,UAAU,IAAI,CAAC,CAAC;YAChB,OAAO,sEAAsE,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,uBAAuB,YAAY,2DAA2D,UAAU,CAAC,YAAY,CAAC,qIAAqI,CAAC;QACnW,CAAC;QACD,OAAO,SAAS,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAC;IAC5E,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { StructuredFormula } from '../../interface/types';
|
|
2
|
+
export interface SerializedFormula {
|
|
3
|
+
v: number;
|
|
4
|
+
tokens: StructuredFormula['tokens'];
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Serialize structured formula for persistence (e.g. to JSON in store).
|
|
8
|
+
*/
|
|
9
|
+
export declare function serializeFormula(formula: StructuredFormula): string;
|
|
10
|
+
/**
|
|
11
|
+
* Deserialize formula from persisted string. Returns null if invalid.
|
|
12
|
+
*/
|
|
13
|
+
export declare function deserializeFormula(json: string): StructuredFormula | null;
|
|
14
|
+
//# sourceMappingURL=serialize-formula.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize-formula.utils.d.ts","sourceRoot":"","sources":["../../../src/utils/formula/serialize-formula.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAI1D,MAAM,WAAW,iBAAiB;IAC9B,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC;CACvC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAMnE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAgBzE"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const SERIALIZATION_VERSION = 1;
|
|
2
|
+
/**
|
|
3
|
+
* Serialize structured formula for persistence (e.g. to JSON in store).
|
|
4
|
+
*/
|
|
5
|
+
export function serializeFormula(formula) {
|
|
6
|
+
const payload = {
|
|
7
|
+
v: SERIALIZATION_VERSION,
|
|
8
|
+
tokens: formula.tokens,
|
|
9
|
+
};
|
|
10
|
+
return JSON.stringify(payload);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Deserialize formula from persisted string. Returns null if invalid.
|
|
14
|
+
*/
|
|
15
|
+
export function deserializeFormula(json) {
|
|
16
|
+
if (!json || typeof json !== 'string') {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
const payload = JSON.parse(json);
|
|
21
|
+
if ((payload === null || payload === void 0 ? void 0 : payload.v) !== SERIALIZATION_VERSION || !Array.isArray(payload.tokens)) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
if (payload.tokens.length === 0) {
|
|
25
|
+
return { tokens: [] };
|
|
26
|
+
}
|
|
27
|
+
return { tokens: payload.tokens };
|
|
28
|
+
}
|
|
29
|
+
catch (_a) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=serialize-formula.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize-formula.utils.js","sourceRoot":"","sources":["../../../src/utils/formula/serialize-formula.utils.ts"],"names":[],"mappings":"AAEA,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAOhC;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAA0B;IACvD,MAAM,OAAO,GAAsB;QAC/B,CAAC,EAAE,qBAAqB;QACxB,MAAM,EAAE,OAAO,CAAC,MAAM;KACzB,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC3C,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAsB,CAAC;QACtD,IAAI,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,CAAC,MAAK,qBAAqB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACzE,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QAC1B,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;IACtC,CAAC;IAAC,WAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { StructuredFormula } from '../../interface/types';
|
|
2
|
+
export interface FormulaValidationResult {
|
|
3
|
+
valid: boolean;
|
|
4
|
+
errors: string[];
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Validates a structured formula.
|
|
8
|
+
* Rules: not empty, valid operator placement, balanced parentheses, supported operators only, all field paths exist.
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateFormula(formula: StructuredFormula | undefined | null, validPaths: Set<string>): FormulaValidationResult;
|
|
11
|
+
//# sourceMappingURL=validate-formula.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-formula.utils.d.ts","sourceRoot":"","sources":["../../../src/utils/formula/validate-formula.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,iBAAiB,EACpB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,uBAAuB;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CACpB;AAYD;;;GAGG;AACH,wBAAgB,eAAe,CAC3B,OAAO,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI,EAC7C,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,GACxB,uBAAuB,CAiEzB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { FORMULA_OPERATORS, } from '../../interface/types';
|
|
2
|
+
const OPERATOR_SET = new Set(FORMULA_OPERATORS);
|
|
3
|
+
function isOperatorToken(t) {
|
|
4
|
+
return t.type === 'operator';
|
|
5
|
+
}
|
|
6
|
+
function isOperandToken(t) {
|
|
7
|
+
return t.type === 'number' || t.type === 'field';
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Validates a structured formula.
|
|
11
|
+
* Rules: not empty, valid operator placement, balanced parentheses, supported operators only, all field paths exist.
|
|
12
|
+
*/
|
|
13
|
+
export function validateFormula(formula, validPaths) {
|
|
14
|
+
var _a;
|
|
15
|
+
const errors = [];
|
|
16
|
+
if (!((_a = formula === null || formula === void 0 ? void 0 : formula.tokens) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
17
|
+
return { valid: false, errors: ['Formula cannot be empty'] };
|
|
18
|
+
}
|
|
19
|
+
const tokens = formula.tokens;
|
|
20
|
+
let parenBalance = 0;
|
|
21
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
22
|
+
const t = tokens[i];
|
|
23
|
+
const prev = tokens[i - 1];
|
|
24
|
+
const next = tokens[i + 1];
|
|
25
|
+
if (t.type === 'lparen') {
|
|
26
|
+
parenBalance++;
|
|
27
|
+
if (prev != null && isOperandToken(prev)) {
|
|
28
|
+
errors.push('Operator required before opening parenthesis');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else if (t.type === 'rparen') {
|
|
32
|
+
parenBalance--;
|
|
33
|
+
if (parenBalance < 0) {
|
|
34
|
+
errors.push('Unbalanced parentheses');
|
|
35
|
+
}
|
|
36
|
+
if (prev != null && isOperatorToken(prev)) {
|
|
37
|
+
errors.push('Operand required before closing parenthesis');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (t.type === 'operator') {
|
|
41
|
+
if (prev == null || next == null) {
|
|
42
|
+
errors.push('Operator must be between two operands or expressions');
|
|
43
|
+
}
|
|
44
|
+
else if (prev.type === 'operator' || prev.type === 'lparen') {
|
|
45
|
+
errors.push('Operand required before operator');
|
|
46
|
+
}
|
|
47
|
+
else if (next.type === 'operator' || next.type === 'rparen') {
|
|
48
|
+
errors.push('Operand required after operator');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else if (t.type === 'field') {
|
|
52
|
+
if (!validPaths.has(t.path)) {
|
|
53
|
+
errors.push(`Unknown field: "${t.label}" (path: ${t.path})`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else if (t.type === 'number') {
|
|
57
|
+
const num = parseFloat(t.value);
|
|
58
|
+
if (Number.isNaN(num)) {
|
|
59
|
+
errors.push(`Invalid number: "${t.value}"`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (parenBalance !== 0) {
|
|
64
|
+
errors.push('Unbalanced parentheses');
|
|
65
|
+
}
|
|
66
|
+
const first = tokens[0];
|
|
67
|
+
const last = tokens[tokens.length - 1];
|
|
68
|
+
if (first && (first.type === 'operator' || first.type === 'rparen')) {
|
|
69
|
+
errors.push('Formula must start with an operand or opening parenthesis');
|
|
70
|
+
}
|
|
71
|
+
if (last && (last.type === 'operator' || last.type === 'lparen')) {
|
|
72
|
+
errors.push('Formula must end with an operand or closing parenthesis');
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
valid: errors.length === 0,
|
|
76
|
+
errors,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=validate-formula.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-formula.utils.js","sourceRoot":"","sources":["../../../src/utils/formula/validate-formula.utils.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC;AACtB,cAAc,cAAc,CAAC;AAC7B,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC;AACtB,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC"}
|
package/dist/utils/index.js
CHANGED
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC;AACtB,cAAc,cAAc,CAAC;AAC7B,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC;AACtB,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@servicetitan/dte-pdf-editor",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.18.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"typings": "./dist/index.d.ts",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"uuid": "^9.0.0"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
-
"@servicetitan/anvil2": "^
|
|
24
|
+
"@servicetitan/anvil2": "^2.0.2",
|
|
25
25
|
"react": "~18.3.1",
|
|
26
26
|
"react-dom": "~18.3.1"
|
|
27
27
|
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Button, Flex, Text } from '@servicetitan/anvil2';
|
|
2
|
+
import { Dispatch, FC, SetStateAction } from 'react';
|
|
3
|
+
import { CalculatedFieldFormat } from '../../interface/types';
|
|
4
|
+
|
|
5
|
+
interface AdvancedSettingsProps {
|
|
6
|
+
format: CalculatedFieldFormat;
|
|
7
|
+
setFormat: Dispatch<SetStateAction<CalculatedFieldFormat>>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const ROUNDING_OPTIONS: { label: string; value: CalculatedFieldFormat['roundingMode'] }[] = [
|
|
11
|
+
{ label: 'Round', value: 'round' },
|
|
12
|
+
{ label: 'Floor', value: 'floor' },
|
|
13
|
+
{ label: 'Ceil', value: 'ceil' },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
export const AdvancedSettings: FC<AdvancedSettingsProps> = ({ format, setFormat }) => (
|
|
17
|
+
<div className="dte-formula-advanced">
|
|
18
|
+
<Text variant="body" size="small">
|
|
19
|
+
Rounding mode
|
|
20
|
+
</Text>
|
|
21
|
+
<Flex gap={1}>
|
|
22
|
+
{ROUNDING_OPTIONS.map(({ label, value }) => (
|
|
23
|
+
<Button
|
|
24
|
+
key={value}
|
|
25
|
+
appearance={format.roundingMode === value ? 'primary' : 'secondary'}
|
|
26
|
+
size="small"
|
|
27
|
+
onClick={() => setFormat(prev => ({ ...prev, roundingMode: value }))}
|
|
28
|
+
>
|
|
29
|
+
{label}
|
|
30
|
+
</Button>
|
|
31
|
+
))}
|
|
32
|
+
</Flex>
|
|
33
|
+
<Flex
|
|
34
|
+
alignItems="center"
|
|
35
|
+
justifyContent="space-between"
|
|
36
|
+
className="dte-formula-advanced-row"
|
|
37
|
+
>
|
|
38
|
+
<Text variant="body" size="small">
|
|
39
|
+
Decimal places
|
|
40
|
+
</Text>
|
|
41
|
+
<Text variant="body" size="small" className="dte-formula-advanced-value">
|
|
42
|
+
{format.decimals}
|
|
43
|
+
</Text>
|
|
44
|
+
</Flex>
|
|
45
|
+
<input
|
|
46
|
+
type="range"
|
|
47
|
+
className="dte-formula-advanced-range"
|
|
48
|
+
min={0}
|
|
49
|
+
max={10}
|
|
50
|
+
value={format.decimals}
|
|
51
|
+
onChange={e =>
|
|
52
|
+
setFormat(prev => ({
|
|
53
|
+
...prev,
|
|
54
|
+
decimals: Number(e.target.value),
|
|
55
|
+
}))
|
|
56
|
+
}
|
|
57
|
+
/>
|
|
58
|
+
<label className="dte-formula-advanced-checkbox">
|
|
59
|
+
<input
|
|
60
|
+
type="checkbox"
|
|
61
|
+
checked={format.thousandsSeparator}
|
|
62
|
+
onChange={e =>
|
|
63
|
+
setFormat(prev => ({
|
|
64
|
+
...prev,
|
|
65
|
+
thousandsSeparator: e.target.checked,
|
|
66
|
+
decimalSeparatorEnabled: e.target.checked,
|
|
67
|
+
decimalSeparator: e.target.checked ? prev.decimalSeparator : '.',
|
|
68
|
+
}))
|
|
69
|
+
}
|
|
70
|
+
/>
|
|
71
|
+
<Text variant="body" size="small">
|
|
72
|
+
Thousands separator
|
|
73
|
+
</Text>
|
|
74
|
+
</label>
|
|
75
|
+
{format.thousandsSeparator && (
|
|
76
|
+
<Flex gap={2}>
|
|
77
|
+
{(['.', ','] as const).map(sep => (
|
|
78
|
+
<Button
|
|
79
|
+
key={sep}
|
|
80
|
+
appearance={format.decimalSeparator === sep ? 'primary' : 'secondary'}
|
|
81
|
+
size="small"
|
|
82
|
+
onClick={() => setFormat(prev => ({ ...prev, decimalSeparator: sep }))}
|
|
83
|
+
>
|
|
84
|
+
{sep}
|
|
85
|
+
</Button>
|
|
86
|
+
))}
|
|
87
|
+
</Flex>
|
|
88
|
+
)}
|
|
89
|
+
<Text variant="body" size="small">
|
|
90
|
+
Result affixes
|
|
91
|
+
</Text>
|
|
92
|
+
<Flex gap="2" alignItems="center">
|
|
93
|
+
<Text variant="body" size="small">
|
|
94
|
+
Prefix
|
|
95
|
+
</Text>
|
|
96
|
+
<input
|
|
97
|
+
type="text"
|
|
98
|
+
className="dte-formula-advanced-input"
|
|
99
|
+
value={format.prefixText}
|
|
100
|
+
onChange={e => setFormat(prev => ({ ...prev, prefixText: e.target.value }))}
|
|
101
|
+
/>
|
|
102
|
+
<Text variant="body" size="small">
|
|
103
|
+
Postfix
|
|
104
|
+
</Text>
|
|
105
|
+
<input
|
|
106
|
+
type="text"
|
|
107
|
+
className="dte-formula-advanced-input"
|
|
108
|
+
value={format.postfixText}
|
|
109
|
+
onChange={e => setFormat(prev => ({ ...prev, postfixText: e.target.value }))}
|
|
110
|
+
/>
|
|
111
|
+
</Flex>
|
|
112
|
+
</div>
|
|
113
|
+
);
|