@servicetitan/dte-pdf-editor 1.25.0 → 1.27.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 +75 -38
- package/dist/components/display-conditions/display-condition.d.ts.map +1 -1
- package/dist/components/display-conditions/display-condition.js +0 -2
- package/dist/components/display-conditions/display-condition.js.map +1 -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 +3 -2
- package/dist/components/field-config-panel/field-config-panel.js.map +1 -1
- package/dist/components/field-config-panel/table-configs.d.ts +9 -0
- package/dist/components/field-config-panel/table-configs.d.ts.map +1 -0
- package/dist/components/field-config-panel/table-configs.js +78 -0
- package/dist/components/field-config-panel/table-configs.js.map +1 -0
- package/dist/components/field-sidebar/field-menu-group.d.ts +1 -1
- package/dist/components/field-sidebar/field-menu-group.d.ts.map +1 -1
- package/dist/components/field-sidebar/field-menu-group.js +1 -5
- package/dist/components/field-sidebar/field-menu-group.js.map +1 -1
- package/dist/components/field-sidebar/field-sidebar.d.ts.map +1 -1
- package/dist/components/field-sidebar/field-sidebar.js +3 -2
- package/dist/components/field-sidebar/field-sidebar.js.map +1 -1
- package/dist/components/field-sidebar/generic-field-type-list.d.ts +9 -0
- package/dist/components/field-sidebar/generic-field-type-list.d.ts.map +1 -0
- package/dist/components/field-sidebar/generic-field-type-list.js +12 -0
- package/dist/components/field-sidebar/generic-field-type-list.js.map +1 -0
- package/dist/components/pdf-canvas/pdf-canvas.d.ts +1 -0
- package/dist/components/pdf-canvas/pdf-canvas.d.ts.map +1 -1
- package/dist/components/pdf-canvas/pdf-canvas.js +2 -2
- package/dist/components/pdf-canvas/pdf-canvas.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-fields-overlay.d.ts +1 -0
- package/dist/components/pdf-fields-overlay/pdf-fields-overlay.d.ts.map +1 -1
- package/dist/components/pdf-fields-overlay/pdf-fields-overlay.js +2 -2
- package/dist/components/pdf-fields-overlay/pdf-fields-overlay.js.map +1 -1
- package/dist/components/pdf-fields-overlay/pdf-overlay-field-generic.d.ts +9 -0
- package/dist/components/pdf-fields-overlay/pdf-overlay-field-generic.d.ts.map +1 -0
- package/dist/components/pdf-fields-overlay/pdf-overlay-field-generic.js +83 -0
- package/dist/components/pdf-fields-overlay/pdf-overlay-field-generic.js.map +1 -0
- package/dist/components/pdf-fields-overlay/pdf-overlay-field.d.ts +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 +6 -3
- package/dist/components/pdf-fields-overlay/pdf-overlay-field.js.map +1 -1
- package/dist/components/pdf-view/pdf-view-generic.d.ts +16 -0
- package/dist/components/pdf-view/pdf-view-generic.d.ts.map +1 -0
- package/dist/components/pdf-view/pdf-view-generic.js +68 -0
- package/dist/components/pdf-view/pdf-view-generic.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/components/shared/index.d.ts +2 -0
- package/dist/components/shared/index.d.ts.map +1 -0
- package/dist/components/shared/index.js +2 -0
- package/dist/components/shared/index.js.map +1 -0
- package/dist/components/shared/inline-editable.d.ts +8 -0
- package/dist/components/shared/inline-editable.d.ts.map +1 -0
- package/dist/components/shared/inline-editable.js +17 -0
- package/dist/components/shared/inline-editable.js.map +1 -0
- package/dist/constants/field.constants.d.ts +8 -1
- package/dist/constants/field.constants.d.ts.map +1 -1
- package/dist/constants/field.constants.js +23 -0
- package/dist/constants/field.constants.js.map +1 -1
- package/dist/constants/menu-group.d.ts.map +1 -1
- package/dist/constants/menu-group.js +8 -2
- package/dist/constants/menu-group.js.map +1 -1
- package/dist/hooks/useFormulaEditor.d.ts.map +1 -1
- package/dist/hooks/useFormulaEditor.js +3 -1
- package/dist/hooks/useFormulaEditor.js.map +1 -1
- package/dist/hooks/usePdfFieldDnD.d.ts.map +1 -1
- package/dist/hooks/usePdfFieldDnD.js +80 -20
- package/dist/hooks/usePdfFieldDnD.js.map +1 -1
- package/dist/interface/types.d.ts +24 -2
- package/dist/interface/types.d.ts.map +1 -1
- package/dist/interface/types.js +1 -0
- package/dist/interface/types.js.map +1 -1
- package/dist/utils/formula/validate-formula.utils.d.ts.map +1 -1
- package/dist/utils/formula/validate-formula.utils.js +9 -2
- package/dist/utils/formula/validate-formula.utils.js.map +1 -1
- package/package.json +1 -1
- package/src/components/display-conditions/display-condition.tsx +0 -3
- package/src/components/field-config-panel/field-config-panel.tsx +8 -1
- package/src/components/field-config-panel/table-configs.tsx +136 -0
- package/src/components/field-sidebar/field-menu-group.tsx +16 -27
- package/src/components/field-sidebar/field-sidebar.tsx +5 -1
- package/src/components/field-sidebar/generic-field-type-list.tsx +27 -0
- package/src/components/pdf-canvas/pdf-canvas.tsx +3 -0
- package/src/components/pdf-editor/pdf-editor.tsx +1 -0
- package/src/components/pdf-fields-overlay/pdf-fields-overlay.tsx +3 -0
- package/src/components/pdf-fields-overlay/pdf-overlay-field-generic.tsx +188 -0
- package/src/components/pdf-fields-overlay/pdf-overlay-field.tsx +11 -1
- package/src/components/pdf-view/pdf-view-generic.tsx +129 -0
- package/src/components/pdf-view/pdf-view.tsx +4 -0
- package/src/components/shared/index.ts +1 -0
- package/src/components/shared/inline-editable.tsx +47 -0
- package/src/constants/field.constants.ts +27 -0
- package/src/constants/menu-group.ts +8 -2
- package/src/hooks/useFormulaEditor.ts +4 -1
- package/src/hooks/usePdfFieldDnD.ts +97 -27
- package/src/interface/types.ts +27 -1
- package/src/styles/index.css +1 -0
- package/src/styles/inline-editable.css +20 -0
- package/src/styles/pdf-field-overlay.css +31 -0
- package/src/styles/variables.css +6 -0
- package/src/utils/formula/validate-formula.utils.ts +10 -7
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { DragEvent, RefObject, useCallback, useRef, useState } from 'react';
|
|
2
2
|
import { v4 as uuidv4 } from 'uuid';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
FIELD_CONSTANTS,
|
|
5
|
+
FILLABLE_FIELD_DEFAULT_SIZES,
|
|
6
|
+
GENERIC_FIELD_DEFAULT_SIZES,
|
|
7
|
+
GENERIC_FIELD_TABLE_ROW_HEIGHT,
|
|
8
|
+
} from '../constants';
|
|
4
9
|
import {
|
|
5
10
|
ESignFieldType,
|
|
6
11
|
FieldTypeEnum,
|
|
@@ -17,6 +22,90 @@ import {
|
|
|
17
22
|
|
|
18
23
|
const DRAG_OVER_THROTTLE_MS = 32; // ~30fps for drop effect updates
|
|
19
24
|
|
|
25
|
+
type InitializeDroppedField = (
|
|
26
|
+
baseField: PdfField,
|
|
27
|
+
option: FieldTypeOption,
|
|
28
|
+
recipientName: string,
|
|
29
|
+
) => PdfField;
|
|
30
|
+
|
|
31
|
+
const initializeDroppedFieldByType: Record<FieldTypeEnum, InitializeDroppedField> = {
|
|
32
|
+
[FieldTypeEnum.eSign]: (base, option, recipientName) => ({
|
|
33
|
+
...base,
|
|
34
|
+
recipient: recipientName,
|
|
35
|
+
path: generateESignPath(recipientName, option.subType as ESignFieldType),
|
|
36
|
+
}),
|
|
37
|
+
[FieldTypeEnum.fillable]: (base, option, recipientName) => {
|
|
38
|
+
const defaultSize = FILLABLE_FIELD_DEFAULT_SIZES[base.subType!];
|
|
39
|
+
return {
|
|
40
|
+
...base,
|
|
41
|
+
recipient: recipientName,
|
|
42
|
+
required: false,
|
|
43
|
+
path: generateFillablePath(recipientName, uuidv4()),
|
|
44
|
+
...(defaultSize && {
|
|
45
|
+
width: defaultSize.width,
|
|
46
|
+
height: defaultSize.height,
|
|
47
|
+
}),
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
[FieldTypeEnum.calculated]: base => ({
|
|
51
|
+
...base,
|
|
52
|
+
path: base.id,
|
|
53
|
+
}),
|
|
54
|
+
[FieldTypeEnum.dataModel]: base => base,
|
|
55
|
+
[FieldTypeEnum.generic]: base => {
|
|
56
|
+
const defaultSize = GENERIC_FIELD_DEFAULT_SIZES[base.subType!];
|
|
57
|
+
if (base.subType === 'text') {
|
|
58
|
+
return {
|
|
59
|
+
...base,
|
|
60
|
+
x: 0,
|
|
61
|
+
data: {
|
|
62
|
+
value: 'This is a new Text block.',
|
|
63
|
+
},
|
|
64
|
+
...(defaultSize && {
|
|
65
|
+
width: defaultSize.width,
|
|
66
|
+
height: defaultSize.height,
|
|
67
|
+
}),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
...base,
|
|
73
|
+
...(defaultSize && {
|
|
74
|
+
width: defaultSize.width,
|
|
75
|
+
height: defaultSize.height,
|
|
76
|
+
}),
|
|
77
|
+
x: 0,
|
|
78
|
+
data: {
|
|
79
|
+
showHeader: true,
|
|
80
|
+
header: {
|
|
81
|
+
height: GENERIC_FIELD_TABLE_ROW_HEIGHT,
|
|
82
|
+
cells: [
|
|
83
|
+
{
|
|
84
|
+
value: 'id',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
value: 'username',
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
body: [
|
|
92
|
+
{
|
|
93
|
+
height: GENERIC_FIELD_TABLE_ROW_HEIGHT,
|
|
94
|
+
cells: [
|
|
95
|
+
{
|
|
96
|
+
value: '124',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
value: 'test@gmail.com',
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
|
|
20
109
|
interface UsePdfFieldDnDProps {
|
|
21
110
|
fields: PdfField[];
|
|
22
111
|
recipients: RecipientInfo[];
|
|
@@ -87,7 +176,8 @@ export const usePdfFieldDnD = ({
|
|
|
87
176
|
return;
|
|
88
177
|
}
|
|
89
178
|
|
|
90
|
-
const
|
|
179
|
+
const recipientName = recipients[0]?.name ?? '';
|
|
180
|
+
const baseField: PdfField = {
|
|
91
181
|
id: uuidv4(),
|
|
92
182
|
type: draggedFieldOption.type,
|
|
93
183
|
subType: draggedFieldOption.subType,
|
|
@@ -100,31 +190,11 @@ export const usePdfFieldDnD = ({
|
|
|
100
190
|
path: draggedFieldOption.path,
|
|
101
191
|
};
|
|
102
192
|
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
recipientName,
|
|
109
|
-
draggedFieldOption.subType as ESignFieldType,
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (newField.type === FieldTypeEnum.fillable) {
|
|
114
|
-
const defaultSize = FILLABLE_FIELD_DEFAULT_SIZES[newField.subType!];
|
|
115
|
-
newField.recipient = recipientName;
|
|
116
|
-
newField.required = false;
|
|
117
|
-
newField.path = generateFillablePath(recipientName, uuidv4());
|
|
118
|
-
|
|
119
|
-
if (defaultSize) {
|
|
120
|
-
newField.width = defaultSize.width;
|
|
121
|
-
newField.height = defaultSize.height;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (newField.type === FieldTypeEnum.calculated) {
|
|
126
|
-
newField.path = newField.id;
|
|
127
|
-
}
|
|
193
|
+
const newField = initializeDroppedFieldByType[baseField.type](
|
|
194
|
+
baseField,
|
|
195
|
+
draggedFieldOption,
|
|
196
|
+
recipientName,
|
|
197
|
+
);
|
|
128
198
|
|
|
129
199
|
onFieldsChange([...fields, newField]);
|
|
130
200
|
onSelectField(newField.id);
|
package/src/interface/types.ts
CHANGED
|
@@ -3,6 +3,7 @@ export enum FieldTypeEnum {
|
|
|
3
3
|
eSign = 'eSign',
|
|
4
4
|
fillable = 'fillable',
|
|
5
5
|
calculated = 'calculated',
|
|
6
|
+
generic = 'generic',
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
export enum ESignFieldType {
|
|
@@ -14,7 +15,31 @@ export enum ESignFieldType {
|
|
|
14
15
|
|
|
15
16
|
export type FillableFieldType = 'text' | 'date' | 'checkbox' | 'radio' | 'number';
|
|
16
17
|
|
|
17
|
-
export type
|
|
18
|
+
export type GenericFieldType = 'table' | 'text';
|
|
19
|
+
|
|
20
|
+
export type PdfFieldSubType = FillableFieldType | ESignFieldType | GenericFieldType;
|
|
21
|
+
|
|
22
|
+
export interface GenericFieldTableDataType {
|
|
23
|
+
showHeader: boolean;
|
|
24
|
+
header: {
|
|
25
|
+
height: number;
|
|
26
|
+
cells: {
|
|
27
|
+
value: string;
|
|
28
|
+
}[];
|
|
29
|
+
};
|
|
30
|
+
body: {
|
|
31
|
+
height: number;
|
|
32
|
+
cells: {
|
|
33
|
+
value: string;
|
|
34
|
+
}[];
|
|
35
|
+
}[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface GenericFieldTextDataType {
|
|
39
|
+
value: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type FieldDataType = GenericFieldTableDataType | GenericFieldTextDataType;
|
|
18
43
|
|
|
19
44
|
export interface DisplayConditionState {
|
|
20
45
|
behavior: 'show' | 'hide';
|
|
@@ -49,6 +74,7 @@ export interface PdfField {
|
|
|
49
74
|
path?: string;
|
|
50
75
|
recipient?: string;
|
|
51
76
|
description?: string;
|
|
77
|
+
data?: FieldDataType;
|
|
52
78
|
formula?: StructuredFormula;
|
|
53
79
|
formulaFormat?: CalculatedFieldFormat;
|
|
54
80
|
displayCondition?: DisplayConditionState | null;
|
package/src/styles/index.css
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
.inline-editable-input {
|
|
2
|
+
width: 100%;
|
|
3
|
+
min-width: 0;
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
border: 1px solid var(--border-color);
|
|
6
|
+
padding: 2px var(--spacing-half);
|
|
7
|
+
font: inherit;
|
|
8
|
+
background: var(--bg-color);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.inline-editable-button {
|
|
12
|
+
min-height: 20px;
|
|
13
|
+
width: 100%;
|
|
14
|
+
height: inherit;
|
|
15
|
+
cursor: pointer;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.inline-editable-html-text {
|
|
19
|
+
margin: var(--spacing-0, 0);
|
|
20
|
+
}
|
|
@@ -112,3 +112,34 @@
|
|
|
112
112
|
pointer-events: none;
|
|
113
113
|
margin: var(--spacing-0, 0);
|
|
114
114
|
}
|
|
115
|
+
|
|
116
|
+
.dte-pdf-field-generic-table {
|
|
117
|
+
padding: var(--spacing-0, 0);
|
|
118
|
+
margin: var(--spacing-0, 0);
|
|
119
|
+
border-spacing: var(--spacing-0, 0);
|
|
120
|
+
width: 100%;
|
|
121
|
+
table-layout: fixed;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.dte-pdf-field-generic-table td {
|
|
125
|
+
border-top: 1px solid var(--border-color);
|
|
126
|
+
border-left: 1px solid var(--border-color);
|
|
127
|
+
padding-inline: var(--spacing-1, 8px);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.dte-pdf-field-generic-table .dte-pdf-field-generic-table-header td {
|
|
131
|
+
background-color: var(--bg-color);
|
|
132
|
+
font-weight: bold;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.dte-pdf-field-generic-table tr:not(.dte-pdf-field-generic-table-header) td {
|
|
136
|
+
background-color: var(--bg-color-light);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.dte-pdf-field-generic-table tr:last-child td {
|
|
140
|
+
border-bottom: 1px solid var(--border-color);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.dte-pdf-field-generic-table tr td:last-child {
|
|
144
|
+
border-right: 1px solid var(--border-color);
|
|
145
|
+
}
|
package/src/styles/variables.css
CHANGED
|
@@ -16,9 +16,15 @@
|
|
|
16
16
|
|
|
17
17
|
/* Colors - Neutral */
|
|
18
18
|
--color-neutral-0: var(--color-neutral-0, #ffffff);
|
|
19
|
+
--color-neutral-70: var(--color-neutral-70, #737475);
|
|
19
20
|
--color-neutral-200: var(--color-neutral-200, #6c6d70);
|
|
20
21
|
--color-neutral-300: var(--color-neutral-300, #2d2e31);
|
|
21
22
|
|
|
23
|
+
/* Background colors */
|
|
24
|
+
--bg-color-light: var(--color-neutral-0, #ffffff);
|
|
25
|
+
--bg-color: var(--color-neutral-200, #f5f5f5);
|
|
26
|
+
--bg-color-hover: #eaeaea;
|
|
27
|
+
|
|
22
28
|
/* Colors - Semantic */
|
|
23
29
|
--success: #28a745;
|
|
24
30
|
--danger: #dc3545;
|
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
FormulaToken,
|
|
3
|
-
FORMULA_OPERATORS,
|
|
4
|
-
StructuredFormula,
|
|
5
|
-
} from '../../interface/types';
|
|
1
|
+
import { FormulaToken, StructuredFormula } from '../../interface/types';
|
|
6
2
|
|
|
7
3
|
export interface FormulaValidationResult {
|
|
8
4
|
valid: boolean;
|
|
9
5
|
errors: string[];
|
|
10
6
|
}
|
|
11
7
|
|
|
12
|
-
const OPERATOR_SET = new Set<string>(FORMULA_OPERATORS);
|
|
13
|
-
|
|
14
8
|
function isOperatorToken(t: FormulaToken): t is FormulaToken & { type: 'operator' } {
|
|
15
9
|
return t.type === 'operator';
|
|
16
10
|
}
|
|
@@ -54,6 +48,9 @@ export function validateFormula(
|
|
|
54
48
|
if (prev != null && isOperatorToken(prev)) {
|
|
55
49
|
errors.push('Operand required before closing parenthesis');
|
|
56
50
|
}
|
|
51
|
+
if (next != null && (isOperandToken(next) || next.type === 'lparen')) {
|
|
52
|
+
errors.push('Operator required between expressions');
|
|
53
|
+
}
|
|
57
54
|
} else if (t.type === 'operator') {
|
|
58
55
|
if (prev == null || next == null) {
|
|
59
56
|
errors.push('Operator must be between two operands or expressions');
|
|
@@ -66,11 +63,17 @@ export function validateFormula(
|
|
|
66
63
|
if (!validPaths.has(t.path)) {
|
|
67
64
|
errors.push(`Unknown field: "${t.label}" (path: ${t.path})`);
|
|
68
65
|
}
|
|
66
|
+
if (next != null && isOperandToken(next)) {
|
|
67
|
+
errors.push('Operator required between two fields or values');
|
|
68
|
+
}
|
|
69
69
|
} else if (t.type === 'number') {
|
|
70
70
|
const num = parseFloat(t.value);
|
|
71
71
|
if (Number.isNaN(num)) {
|
|
72
72
|
errors.push(`Invalid number: "${t.value}"`);
|
|
73
73
|
}
|
|
74
|
+
if (next != null && isOperandToken(next)) {
|
|
75
|
+
errors.push('Operator required between two fields or values');
|
|
76
|
+
}
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
79
|
|