@servicetitan/dte-pdf-editor 1.0.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 +356 -0
- package/dist/components/data-model-field-type-list.d.ts +11 -0
- package/dist/components/data-model-field-type-list.d.ts.map +1 -0
- package/dist/components/data-model-field-type-list.js +23 -0
- package/dist/components/data-model-field-type-list.js.map +1 -0
- package/dist/components/e-sign-field-type-list.d.ts +9 -0
- package/dist/components/e-sign-field-type-list.d.ts.map +1 -0
- package/dist/components/e-sign-field-type-list.js +12 -0
- package/dist/components/e-sign-field-type-list.js.map +1 -0
- package/dist/components/field-config-panel-overlay.d.ts +13 -0
- package/dist/components/field-config-panel-overlay.d.ts.map +1 -0
- package/dist/components/field-config-panel-overlay.js +8 -0
- package/dist/components/field-config-panel-overlay.js.map +1 -0
- package/dist/components/field-config-panel.d.ts +12 -0
- package/dist/components/field-config-panel.d.ts.map +1 -0
- package/dist/components/field-config-panel.js +38 -0
- package/dist/components/field-config-panel.js.map +1 -0
- package/dist/components/field-sidebar.d.ts +10 -0
- package/dist/components/field-sidebar.d.ts.map +1 -0
- package/dist/components/field-sidebar.js +25 -0
- package/dist/components/field-sidebar.js.map +1 -0
- package/dist/components/field-type.d.ts +9 -0
- package/dist/components/field-type.d.ts.map +1 -0
- package/dist/components/field-type.js +12 -0
- package/dist/components/field-type.js.map +1 -0
- package/dist/components/fillable-field-type-list.d.ts +10 -0
- package/dist/components/fillable-field-type-list.d.ts.map +1 -0
- package/dist/components/fillable-field-type-list.js +17 -0
- package/dist/components/fillable-field-type-list.js.map +1 -0
- package/dist/components/pdf-canvas.d.ts +22 -0
- package/dist/components/pdf-canvas.d.ts.map +1 -0
- package/dist/components/pdf-canvas.js +14 -0
- package/dist/components/pdf-canvas.js.map +1 -0
- package/dist/components/pdf-document-renderer.d.ts +16 -0
- package/dist/components/pdf-document-renderer.d.ts.map +1 -0
- package/dist/components/pdf-document-renderer.js +28 -0
- package/dist/components/pdf-document-renderer.js.map +1 -0
- package/dist/components/pdf-editor.d.ts +21 -0
- package/dist/components/pdf-editor.d.ts.map +1 -0
- package/dist/components/pdf-editor.js +108 -0
- package/dist/components/pdf-editor.js.map +1 -0
- package/dist/components/pdf-field-overlay.d.ts +14 -0
- package/dist/components/pdf-field-overlay.d.ts.map +1 -0
- package/dist/components/pdf-field-overlay.js +32 -0
- package/dist/components/pdf-field-overlay.js.map +1 -0
- package/dist/constants/field.constants.d.ts +16 -0
- package/dist/constants/field.constants.d.ts.map +1 -0
- package/dist/constants/field.constants.js +28 -0
- package/dist/constants/field.constants.js.map +1 -0
- package/dist/constants/index.d.ts +3 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js +3 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/constants/pdf-editor.constants.d.ts +2 -0
- package/dist/constants/pdf-editor.constants.d.ts.map +1 -0
- package/dist/constants/pdf-editor.constants.js +2 -0
- package/dist/constants/pdf-editor.constants.js.map +1 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/useFieldDrag.d.ts +24 -0
- package/dist/hooks/useFieldDrag.d.ts.map +1 -0
- package/dist/hooks/useFieldDrag.js +34 -0
- package/dist/hooks/useFieldDrag.js.map +1 -0
- package/dist/hooks/useFieldResize.d.ts +17 -0
- package/dist/hooks/useFieldResize.d.ts.map +1 -0
- package/dist/hooks/useFieldResize.js +58 -0
- package/dist/hooks/useFieldResize.js.map +1 -0
- package/dist/hooks/usePdfDocumentRenderer.d.ts +9 -0
- package/dist/hooks/usePdfDocumentRenderer.d.ts.map +1 -0
- package/dist/hooks/usePdfDocumentRenderer.js +13 -0
- package/dist/hooks/usePdfDocumentRenderer.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/interface/pdf-editor.d.ts +64 -0
- package/dist/interface/pdf-editor.d.ts.map +1 -0
- package/dist/interface/pdf-editor.js +14 -0
- package/dist/interface/pdf-editor.js.map +1 -0
- package/dist/utils/calculate-drop-coordinates.utils.d.ts +15 -0
- package/dist/utils/calculate-drop-coordinates.utils.d.ts.map +1 -0
- package/dist/utils/calculate-drop-coordinates.utils.js +48 -0
- package/dist/utils/calculate-drop-coordinates.utils.js.map +1 -0
- package/dist/utils/extract-grouped-fields-from-data-model.utils.d.ts +7 -0
- package/dist/utils/extract-grouped-fields-from-data-model.utils.d.ts.map +1 -0
- package/dist/utils/extract-grouped-fields-from-data-model.utils.js +57 -0
- package/dist/utils/extract-grouped-fields-from-data-model.utils.js.map +1 -0
- package/dist/utils/generate-e-sign-path.d.ts +3 -0
- package/dist/utils/generate-e-sign-path.d.ts.map +1 -0
- package/dist/utils/generate-e-sign-path.js +4 -0
- package/dist/utils/generate-e-sign-path.js.map +1 -0
- package/dist/utils/get-page-dimensions.utils.d.ts +12 -0
- package/dist/utils/get-page-dimensions.utils.d.ts.map +1 -0
- package/dist/utils/get-page-dimensions.utils.js +31 -0
- package/dist/utils/get-page-dimensions.utils.js.map +1 -0
- package/dist/utils/get-page-number-from-client-y.utils.d.ts +9 -0
- package/dist/utils/get-page-number-from-client-y.utils.d.ts.map +1 -0
- package/dist/utils/get-page-number-from-client-y.utils.js +24 -0
- package/dist/utils/get-page-number-from-client-y.utils.js.map +1 -0
- package/dist/utils/get-page-position.utils.d.ts +12 -0
- package/dist/utils/get-page-position.utils.d.ts.map +1 -0
- package/dist/utils/get-page-position.utils.js +22 -0
- package/dist/utils/get-page-position.utils.js.map +1 -0
- package/dist/utils/handle-field-drag-start.utils.d.ts +16 -0
- package/dist/utils/handle-field-drag-start.utils.d.ts.map +1 -0
- package/dist/utils/handle-field-drag-start.utils.js +41 -0
- package/dist/utils/handle-field-drag-start.utils.js.map +1 -0
- package/dist/utils/handle-field-drag.utils.d.ts +19 -0
- package/dist/utils/handle-field-drag.utils.d.ts.map +1 -0
- package/dist/utils/handle-field-drag.utils.js +36 -0
- package/dist/utils/handle-field-drag.utils.js.map +1 -0
- package/dist/utils/handle-field-resize.utils.d.ts +35 -0
- package/dist/utils/handle-field-resize.utils.d.ts.map +1 -0
- package/dist/utils/handle-field-resize.utils.js +66 -0
- package/dist/utils/handle-field-resize.utils.js.map +1 -0
- package/dist/utils/index.d.ts +13 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +13 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/is-drag-over-canvas.utils.d.ts +9 -0
- package/dist/utils/is-drag-over-canvas.utils.d.ts.map +1 -0
- package/dist/utils/is-drag-over-canvas.utils.js +26 -0
- package/dist/utils/is-drag-over-canvas.utils.js.map +1 -0
- package/dist/utils/map-colors-to-recipients.d.ts +3 -0
- package/dist/utils/map-colors-to-recipients.d.ts.map +1 -0
- package/dist/utils/map-colors-to-recipients.js +35 -0
- package/dist/utils/map-colors-to-recipients.js.map +1 -0
- package/dist/utils/pdfjs-init.d.ts +6 -0
- package/dist/utils/pdfjs-init.d.ts.map +1 -0
- package/dist/utils/pdfjs-init.js +25 -0
- package/dist/utils/pdfjs-init.js.map +1 -0
- package/package.json +28 -0
- package/src/components/data-model-field-type-list.tsx +58 -0
- package/src/components/e-sign-field-type-list.tsx +27 -0
- package/src/components/field-config-panel-overlay.tsx +51 -0
- package/src/components/field-config-panel.tsx +142 -0
- package/src/components/field-sidebar.tsx +93 -0
- package/src/components/field-type.tsx +28 -0
- package/src/components/fillable-field-type-list.tsx +42 -0
- package/src/components/pdf-canvas.tsx +81 -0
- package/src/components/pdf-document-renderer.tsx +78 -0
- package/src/components/pdf-editor.tsx +216 -0
- package/src/components/pdf-field-overlay.tsx +83 -0
- package/src/constants/field.constants.ts +31 -0
- package/src/constants/index.ts +2 -0
- package/src/constants/pdf-editor.constants.ts +1 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useFieldDrag.ts +56 -0
- package/src/hooks/useFieldResize.ts +95 -0
- package/src/hooks/usePdfDocumentRenderer.ts +21 -0
- package/src/index.ts +2 -0
- package/src/interface/pdf-editor.ts +74 -0
- package/src/styles/field-config-panel-overlay.css +33 -0
- package/src/styles/field-sidebar.css +31 -0
- package/src/styles/field-type-list.css +8 -0
- package/src/styles/field-type.css +10 -0
- package/src/styles/generic.css +3 -0
- package/src/styles/index.css +10 -0
- package/src/styles/pdf-canvas.css +9 -0
- package/src/styles/pdf-document-renderer.css +4 -0
- package/src/styles/pdf-editor.css +14 -0
- package/src/styles/pdf-field-overlay.css +54 -0
- package/src/styles/variables.css +26 -0
- package/src/utils/calculate-drop-coordinates.utils.ts +68 -0
- package/src/utils/extract-grouped-fields-from-data-model.utils.ts +73 -0
- package/src/utils/generate-e-sign-path.ts +5 -0
- package/src/utils/get-page-dimensions.utils.ts +39 -0
- package/src/utils/get-page-number-from-client-y.utils.ts +31 -0
- package/src/utils/get-page-position.utils.ts +30 -0
- package/src/utils/handle-field-drag-start.utils.ts +52 -0
- package/src/utils/handle-field-drag.utils.ts +55 -0
- package/src/utils/handle-field-resize.utils.ts +102 -0
- package/src/utils/index.ts +12 -0
- package/src/utils/is-drag-over-canvas.utils.ts +35 -0
- package/src/utils/map-colors-to-recipients.ts +37 -0
- package/src/utils/pdfjs-init.ts +27 -0
- package/src/vite-env.d.ts +16 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { FIELD_CONSTANTS } from '../constants';
|
|
2
|
+
import { getPageDimensions } from './get-page-dimensions.utils';
|
|
3
|
+
import { getPagePosition } from './get-page-position.utils';
|
|
4
|
+
/**
|
|
5
|
+
* Calculates the initial resize data when user starts resizing
|
|
6
|
+
* @param e - Mouse event
|
|
7
|
+
* @param field - The field being resized
|
|
8
|
+
* @param pdfWrapperRef - Reference to the PDF wrapper element
|
|
9
|
+
* @returns Resize start data or null if calculation fails
|
|
10
|
+
*/
|
|
11
|
+
export const handleFieldResizeStart = (e, field, pdfWrapperRef) => {
|
|
12
|
+
if (!pdfWrapperRef.current) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const pagePos = getPagePosition(field.page, pdfWrapperRef);
|
|
16
|
+
const wrapperRect = pdfWrapperRef.current.getBoundingClientRect();
|
|
17
|
+
// Calculate mouse position relative to the page
|
|
18
|
+
const startX = e.clientX - wrapperRect.left - pagePos.left;
|
|
19
|
+
const startY = e.clientY - wrapperRect.top - pagePos.top;
|
|
20
|
+
return {
|
|
21
|
+
startX,
|
|
22
|
+
startY,
|
|
23
|
+
startWidth: field.width,
|
|
24
|
+
startHeight: field.height,
|
|
25
|
+
page: field.page,
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Handles the resize event for a PDF field from bottom-right corner
|
|
30
|
+
* Only changes width and height, keeping x and y coordinates unchanged
|
|
31
|
+
* @param e - Mouse event
|
|
32
|
+
* @param field - The field being resized
|
|
33
|
+
* @param resizeStartData - Data from resize start
|
|
34
|
+
* @param pdfWrapperRef - Reference to the PDF wrapper element
|
|
35
|
+
* @param onFieldResize - Callback to update field dimensions
|
|
36
|
+
*/
|
|
37
|
+
export const handleFieldResize = (e, field, resizeStartData, pdfWrapperRef, onFieldResize) => {
|
|
38
|
+
if (!pdfWrapperRef.current) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const pageDimensions = getPageDimensions(resizeStartData.page, pdfWrapperRef);
|
|
42
|
+
const pagePos = getPagePosition(resizeStartData.page, pdfWrapperRef);
|
|
43
|
+
const wrapperRect = pdfWrapperRef.current.getBoundingClientRect();
|
|
44
|
+
// Calculate mouse position relative to the page
|
|
45
|
+
const mouseX = e.clientX - wrapperRect.left - pagePos.left;
|
|
46
|
+
const mouseY = e.clientY - wrapperRect.top - pagePos.top;
|
|
47
|
+
// Calculate delta from the start position
|
|
48
|
+
const deltaX = mouseX - resizeStartData.startX;
|
|
49
|
+
const deltaY = mouseY - resizeStartData.startY;
|
|
50
|
+
/*
|
|
51
|
+
* Calculate new width and height based on which handle is being used
|
|
52
|
+
* x and y always stay the same
|
|
53
|
+
*/
|
|
54
|
+
let newWidth = resizeStartData.startWidth + deltaX;
|
|
55
|
+
let newHeight = resizeStartData.startHeight + deltaY;
|
|
56
|
+
// Clamp to minimum dimensions
|
|
57
|
+
newWidth = Math.max(FIELD_CONSTANTS.minWidth, newWidth);
|
|
58
|
+
newHeight = Math.max(FIELD_CONSTANTS.minHeight, newHeight);
|
|
59
|
+
// Clamp to page boundaries (ensure the field doesn't go outside the page)
|
|
60
|
+
const maxWidth = pageDimensions.width - field.x;
|
|
61
|
+
const maxHeight = pageDimensions.height - field.y;
|
|
62
|
+
newWidth = Math.min(newWidth, maxWidth);
|
|
63
|
+
newHeight = Math.min(newHeight, maxHeight);
|
|
64
|
+
onFieldResize(field.id, newWidth, newHeight, resizeStartData.page);
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=handle-field-resize.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handle-field-resize.utils.js","sourceRoot":"","sources":["../../src/utils/handle-field-resize.utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAU5D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAClC,CAAuC,EACvC,KAAe,EACf,aAAwC,EAClB,EAAE;IACxB,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAC3D,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAElE,gDAAgD;IAChD,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,GAAG,WAAW,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC3D,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,GAAG,WAAW,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAEzD,OAAO;QACH,MAAM;QACN,MAAM;QACN,UAAU,EAAE,KAAK,CAAC,KAAK;QACvB,WAAW,EAAE,KAAK,CAAC,MAAM;QACzB,IAAI,EAAE,KAAK,CAAC,IAAI;KACnB,CAAC;AACN,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC7B,CAAuC,EACvC,KAAe,EACf,eAAgC,EAChC,aAAwC,EACxC,aAKS,EACL,EAAE;IACN,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;QACzB,OAAO;IACX,CAAC;IAED,MAAM,cAAc,GAAG,iBAAiB,CAAC,eAAe,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAC9E,MAAM,OAAO,GAAG,eAAe,CAAC,eAAe,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IACrE,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC;IAElE,gDAAgD;IAChD,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,GAAG,WAAW,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC3D,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,GAAG,WAAW,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAEzD,0CAA0C;IAC1C,MAAM,MAAM,GAAG,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC;IAC/C,MAAM,MAAM,GAAG,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC;IAE/C;;;OAGG;IACH,IAAI,QAAQ,GAAG,eAAe,CAAC,UAAU,GAAG,MAAM,CAAC;IACnD,IAAI,SAAS,GAAG,eAAe,CAAC,WAAW,GAAG,MAAM,CAAC;IAErD,8BAA8B;IAC9B,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACxD,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAE3D,0EAA0E;IAC1E,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC;IAClD,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACxC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAE3C,aAAa,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,CAAC,IAAI,CAAC,CAAC;AACvE,CAAC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './calculate-drop-coordinates.utils';
|
|
2
|
+
export * from './extract-grouped-fields-from-data-model.utils';
|
|
3
|
+
export * from './get-page-dimensions.utils';
|
|
4
|
+
export * from './get-page-number-from-client-y.utils';
|
|
5
|
+
export * from './get-page-position.utils';
|
|
6
|
+
export * from './handle-field-drag.utils';
|
|
7
|
+
export * from './handle-field-drag-start.utils';
|
|
8
|
+
export * from './handle-field-resize.utils';
|
|
9
|
+
export * from './is-drag-over-canvas.utils';
|
|
10
|
+
export * from './map-colors-to-recipients';
|
|
11
|
+
export * from './pdfjs-init';
|
|
12
|
+
export * from './generate-e-sign-path';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAC;AACnD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uCAAuC,CAAC;AACtD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './calculate-drop-coordinates.utils';
|
|
2
|
+
export * from './extract-grouped-fields-from-data-model.utils';
|
|
3
|
+
export * from './get-page-dimensions.utils';
|
|
4
|
+
export * from './get-page-number-from-client-y.utils';
|
|
5
|
+
export * from './get-page-position.utils';
|
|
6
|
+
export * from './handle-field-drag.utils';
|
|
7
|
+
export * from './handle-field-drag-start.utils';
|
|
8
|
+
export * from './handle-field-resize.utils';
|
|
9
|
+
export * from './is-drag-over-canvas.utils';
|
|
10
|
+
export * from './map-colors-to-recipients';
|
|
11
|
+
export * from './pdfjs-init';
|
|
12
|
+
export * from './generate-e-sign-path';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAC;AACnD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uCAAuC,CAAC;AACtD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DragEvent, RefObject } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Checks if a drag event is over any PDF canvas within the wrapper
|
|
4
|
+
* @param e - The drag event
|
|
5
|
+
* @param pdfWrapperRef - Reference to the PDF wrapper element
|
|
6
|
+
* @returns true if the drag is over a canvas, false otherwise
|
|
7
|
+
*/
|
|
8
|
+
export declare const isDragOverCanvas: (e: DragEvent<HTMLDivElement>, pdfWrapperRef: RefObject<HTMLDivElement>) => boolean;
|
|
9
|
+
//# sourceMappingURL=is-drag-over-canvas.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-drag-over-canvas.utils.d.ts","sourceRoot":"","sources":["../../src/utils/is-drag-over-canvas.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GACzB,GAAG,SAAS,CAAC,cAAc,CAAC,EAC5B,eAAe,SAAS,CAAC,cAAc,CAAC,KACzC,OAuBF,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if a drag event is over any PDF canvas within the wrapper
|
|
3
|
+
* @param e - The drag event
|
|
4
|
+
* @param pdfWrapperRef - Reference to the PDF wrapper element
|
|
5
|
+
* @returns true if the drag is over a canvas, false otherwise
|
|
6
|
+
*/
|
|
7
|
+
export const isDragOverCanvas = (e, pdfWrapperRef) => {
|
|
8
|
+
if (!pdfWrapperRef.current) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
const pageElements = pdfWrapperRef.current.querySelectorAll('[data-page-number]');
|
|
12
|
+
for (const pageElement of pageElements) {
|
|
13
|
+
const canvas = pageElement.querySelector('canvas');
|
|
14
|
+
if (canvas) {
|
|
15
|
+
const canvasRect = canvas.getBoundingClientRect();
|
|
16
|
+
if (e.clientX >= canvasRect.left &&
|
|
17
|
+
e.clientX <= canvasRect.right &&
|
|
18
|
+
e.clientY >= canvasRect.top &&
|
|
19
|
+
e.clientY <= canvasRect.bottom) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=is-drag-over-canvas.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-drag-over-canvas.utils.js","sourceRoot":"","sources":["../../src/utils/is-drag-over-canvas.utils.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC5B,CAA4B,EAC5B,aAAwC,EACjC,EAAE;IACT,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,MAAM,YAAY,GAAG,aAAa,CAAC,OAAO,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,CAAC;IAElF,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,WAAW,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,MAAM,EAAE,CAAC;YACT,MAAM,UAAU,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAC;YAClD,IACI,CAAC,CAAC,OAAO,IAAI,UAAU,CAAC,IAAI;gBAC5B,CAAC,CAAC,OAAO,IAAI,UAAU,CAAC,KAAK;gBAC7B,CAAC,CAAC,OAAO,IAAI,UAAU,CAAC,GAAG;gBAC3B,CAAC,CAAC,OAAO,IAAI,UAAU,CAAC,MAAM,EAChC,CAAC;gBACC,OAAO,IAAI,CAAC;YAChB,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-colors-to-recipients.d.ts","sourceRoot":"","sources":["../../src/utils/map-colors-to-recipients.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AA4BzD,eAAO,MAAM,qBAAqB,GAAI,aAAa,aAAa,EAAE,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAQzF,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const colors = [
|
|
2
|
+
'#1F77B41f',
|
|
3
|
+
'#FF7F0E1f',
|
|
4
|
+
'#2CA02C1f',
|
|
5
|
+
'#9467BD1f',
|
|
6
|
+
'#8C564B1f',
|
|
7
|
+
'#E377C21f',
|
|
8
|
+
'#7F7F7F1f',
|
|
9
|
+
'#BCBD221f',
|
|
10
|
+
'#17BECF1f',
|
|
11
|
+
'#D627281f',
|
|
12
|
+
'#98DF8A1f',
|
|
13
|
+
'#FFBB781f',
|
|
14
|
+
'#C5B0D51f',
|
|
15
|
+
'#C49C941f',
|
|
16
|
+
'#F7B6D21f',
|
|
17
|
+
'#C7C7C71f',
|
|
18
|
+
'#DBDB8D1f',
|
|
19
|
+
'#9EDAE51f',
|
|
20
|
+
'#E5E5E51f',
|
|
21
|
+
'#393B791f',
|
|
22
|
+
'#5254A31f',
|
|
23
|
+
'#6B6EBD1f',
|
|
24
|
+
'#9C9EDA1f',
|
|
25
|
+
];
|
|
26
|
+
export const mapColorsToRecipients = (recipients) => {
|
|
27
|
+
if (!recipients) {
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
return recipients.reduce((acc, curr, i) => {
|
|
31
|
+
acc[curr.name] = colors[i];
|
|
32
|
+
return acc;
|
|
33
|
+
}, {});
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=map-colors-to-recipients.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-colors-to-recipients.js","sourceRoot":"","sources":["../../src/utils/map-colors-to-recipients.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,GAAG;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;CACd,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,UAA4B,EAA0B,EAAE;IAC1F,IAAI,CAAC,UAAU,EAAE,CAAC;QACd,OAAO,EAAE,CAAC;IACd,CAAC;IACD,OAAO,UAAU,CAAC,MAAM,CAAyB,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE;QAC9D,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAC3B,OAAO,GAAG,CAAC;IACf,CAAC,EAAE,EAAE,CAAC,CAAC;AACX,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdfjs-init.d.ts","sourceRoot":"","sources":["../../src/utils/pdfjs-init.ts"],"names":[],"mappings":"AASA;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAO,IAWxC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Initialize PDF.js worker - centralized configuration
|
|
3
|
+
* This ensures the worker is configured once and can be imported by any component
|
|
4
|
+
*/
|
|
5
|
+
import * as pdfjsLib from 'pdfjs-dist';
|
|
6
|
+
import workerSrc from 'pdfjs-dist/build/pdf.worker.min.js?url';
|
|
7
|
+
let isInitialized = false;
|
|
8
|
+
/**
|
|
9
|
+
* Initializes PDF.js worker if not already initialized
|
|
10
|
+
* Safe to call multiple times - will only initialize once
|
|
11
|
+
*/
|
|
12
|
+
export const initializePdfJsWorker = () => {
|
|
13
|
+
if (isInitialized || typeof window === 'undefined') {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc;
|
|
18
|
+
isInitialized = true;
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
throw new Error('Failed to initialize PDF.js worker:' + error.message);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
initializePdfJsWorker();
|
|
25
|
+
//# sourceMappingURL=pdfjs-init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdfjs-init.js","sourceRoot":"","sources":["../../src/utils/pdfjs-init.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAC;AACvC,OAAO,SAAS,MAAM,wCAAwC,CAAC;AAE/D,IAAI,aAAa,GAAG,KAAK,CAAC;AAE1B;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAS,EAAE;IAC5C,IAAI,aAAa,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QACjD,OAAO;IACX,CAAC;IAED,IAAI,CAAC;QACD,QAAQ,CAAC,mBAAmB,CAAC,SAAS,GAAG,SAAS,CAAC;QACnD,aAAa,GAAG,IAAI,CAAC;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAI,KAAe,CAAC,OAAO,CAAC,CAAC;IACtF,CAAC;AACL,CAAC,CAAC;AAEF,qBAAqB,EAAE,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@servicetitan/dte-pdf-editor",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"typings": "./dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"src"
|
|
10
|
+
],
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public",
|
|
13
|
+
"registry": "https://registry.npmjs.org"
|
|
14
|
+
},
|
|
15
|
+
"cli": {
|
|
16
|
+
"webpack": false
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"pdfjs-dist": "^3.11.0",
|
|
20
|
+
"react-pdf": "^7.5.0",
|
|
21
|
+
"uuid": "^9.0.0"
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"@servicetitan/anvil2": "^1.46.9",
|
|
25
|
+
"react": "~18.3.1",
|
|
26
|
+
"react-dom": "~18.3.1"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Flex, Text } from '@servicetitan/anvil2';
|
|
2
|
+
import { FC, Fragment, useMemo } from 'react';
|
|
3
|
+
import { DataModelFieldGroup, FieldTypeOption } from '../interface/pdf-editor';
|
|
4
|
+
import { FieldType } from './field-type';
|
|
5
|
+
|
|
6
|
+
interface DataModelFieldTypeListProps {
|
|
7
|
+
searchText?: string;
|
|
8
|
+
dataModelGroups?: DataModelFieldGroup[];
|
|
9
|
+
onDragStart(fieldOption: FieldTypeOption): void;
|
|
10
|
+
onDragEnd(): void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const DataModelFieldTypeList: FC<DataModelFieldTypeListProps> = ({
|
|
14
|
+
dataModelGroups = [],
|
|
15
|
+
onDragEnd,
|
|
16
|
+
onDragStart,
|
|
17
|
+
searchText,
|
|
18
|
+
}) => {
|
|
19
|
+
const searchedFieldGroups = useMemo(() => {
|
|
20
|
+
if (!searchText) {
|
|
21
|
+
return dataModelGroups;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const searchLower = searchText.toLowerCase();
|
|
25
|
+
return dataModelGroups
|
|
26
|
+
.map(group => ({
|
|
27
|
+
...group,
|
|
28
|
+
fieldTypes: group.fields.filter(({ label }) =>
|
|
29
|
+
label.toLowerCase().includes(searchLower),
|
|
30
|
+
),
|
|
31
|
+
}))
|
|
32
|
+
.filter(group => group.fieldTypes.length > 0);
|
|
33
|
+
}, [dataModelGroups, searchText]);
|
|
34
|
+
return (
|
|
35
|
+
<Fragment>
|
|
36
|
+
{searchedFieldGroups.map(group => (
|
|
37
|
+
<div key={group.groupName} className="dte-field-type-group m-t-1">
|
|
38
|
+
<Flex alignItems="center" gap={1} className="dte-field-type-group-header">
|
|
39
|
+
<Text variant="headline" el="h6" size="small">
|
|
40
|
+
{group.groupName}
|
|
41
|
+
</Text>
|
|
42
|
+
</Flex>
|
|
43
|
+
{group.fields.map(fieldOption => {
|
|
44
|
+
const key = `${fieldOption.type}-${group.groupName}-${fieldOption.path}`;
|
|
45
|
+
return (
|
|
46
|
+
<FieldType
|
|
47
|
+
key={key}
|
|
48
|
+
label={fieldOption.label}
|
|
49
|
+
onDragEnd={onDragEnd}
|
|
50
|
+
onDragStart={() => onDragStart(fieldOption)}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
})}
|
|
54
|
+
</div>
|
|
55
|
+
))}
|
|
56
|
+
</Fragment>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { FC, Fragment } from 'react';
|
|
2
|
+
import { E_SIGN_FIELD_TYPES } from '../constants';
|
|
3
|
+
import { FieldTypeOption } from '../interface/pdf-editor';
|
|
4
|
+
import { FieldType } from './field-type';
|
|
5
|
+
|
|
6
|
+
interface ESignFieldTypeListProps {
|
|
7
|
+
onDragStart(fieldOption: FieldTypeOption): void;
|
|
8
|
+
onDragEnd(): void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const ESignFieldTypeList: FC<ESignFieldTypeListProps> = ({ onDragEnd, onDragStart }) => {
|
|
12
|
+
return (
|
|
13
|
+
<Fragment>
|
|
14
|
+
{E_SIGN_FIELD_TYPES.map(fieldOption => {
|
|
15
|
+
const key = `${fieldOption.type}-${fieldOption.path ?? fieldOption.label}`;
|
|
16
|
+
return (
|
|
17
|
+
<FieldType
|
|
18
|
+
key={key}
|
|
19
|
+
label={fieldOption.label}
|
|
20
|
+
onDragEnd={onDragEnd}
|
|
21
|
+
onDragStart={() => onDragStart(fieldOption)}
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
24
|
+
})}
|
|
25
|
+
</Fragment>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Button, Flex, Text } from '@servicetitan/anvil2';
|
|
2
|
+
import IconClose from '@servicetitan/anvil2/assets/icons/material/round/close.svg';
|
|
3
|
+
import { FC } from 'react';
|
|
4
|
+
import { PdfField } from '../interface/pdf-editor';
|
|
5
|
+
import { FieldConfigPanel } from './field-config-panel';
|
|
6
|
+
import { RecipientInfo } from './pdf-editor';
|
|
7
|
+
|
|
8
|
+
interface FieldConfigPanelOverlayProps {
|
|
9
|
+
selectedField: PdfField;
|
|
10
|
+
recipients?: RecipientInfo[];
|
|
11
|
+
onFieldConfigChange(updates: Partial<PdfField>): void;
|
|
12
|
+
onDeleteField(): void;
|
|
13
|
+
onDeselectField?(): void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const FieldConfigPanelOverlay: FC<FieldConfigPanelOverlayProps> = ({
|
|
17
|
+
onDeleteField,
|
|
18
|
+
onDeselectField,
|
|
19
|
+
onFieldConfigChange,
|
|
20
|
+
recipients,
|
|
21
|
+
selectedField,
|
|
22
|
+
}) => {
|
|
23
|
+
return (
|
|
24
|
+
<Flex className="dte-field-config-panel-overlay" onClick={e => e.stopPropagation()}>
|
|
25
|
+
<Flex
|
|
26
|
+
className="dte-field-config-panel-header"
|
|
27
|
+
alignItems="center"
|
|
28
|
+
justifyContent="space-between"
|
|
29
|
+
>
|
|
30
|
+
<Text variant="headline" el="h6" size="small">
|
|
31
|
+
Field Configuration
|
|
32
|
+
</Text>
|
|
33
|
+
<Button
|
|
34
|
+
appearance="ghost"
|
|
35
|
+
size="small"
|
|
36
|
+
onClick={onDeselectField}
|
|
37
|
+
aria-label="Close"
|
|
38
|
+
icon={IconClose}
|
|
39
|
+
/>
|
|
40
|
+
</Flex>
|
|
41
|
+
<div className="dte-field-config-panel-content">
|
|
42
|
+
<FieldConfigPanel
|
|
43
|
+
field={selectedField}
|
|
44
|
+
recipients={recipients}
|
|
45
|
+
onFieldConfigChange={onFieldConfigChange}
|
|
46
|
+
onDeleteField={onDeleteField}
|
|
47
|
+
/>
|
|
48
|
+
</div>
|
|
49
|
+
</Flex>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { Button, Checkbox, Combobox, Flex, TextField } from '@servicetitan/anvil2';
|
|
2
|
+
import { FC, useMemo } from 'react';
|
|
3
|
+
import { E_SIGN_FIELD_TYPE_OPTIONS } from '../constants';
|
|
4
|
+
import { ESignFieldType, FieldTypeEnum, PdfField } from '../interface/pdf-editor';
|
|
5
|
+
import { generateESignPath } from '../utils';
|
|
6
|
+
import { RecipientInfo } from './pdf-editor';
|
|
7
|
+
|
|
8
|
+
interface FieldConfigPanelProps {
|
|
9
|
+
field: PdfField;
|
|
10
|
+
recipients?: RecipientInfo[];
|
|
11
|
+
onDeleteField(): void;
|
|
12
|
+
onFieldConfigChange(updates: Partial<PdfField>): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const FieldConfigPanel: FC<FieldConfigPanelProps> = ({
|
|
16
|
+
field,
|
|
17
|
+
onDeleteField,
|
|
18
|
+
onFieldConfigChange,
|
|
19
|
+
recipients = [],
|
|
20
|
+
}) => {
|
|
21
|
+
const recipientOptions = useMemo(
|
|
22
|
+
() =>
|
|
23
|
+
recipients.map(recipient => ({
|
|
24
|
+
id: recipient.name,
|
|
25
|
+
name: recipient.displayName,
|
|
26
|
+
})),
|
|
27
|
+
[recipients],
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const selectedRecipient = useMemo(
|
|
31
|
+
() => recipientOptions.find(option => option.id === field.recipient) ?? null,
|
|
32
|
+
[recipientOptions, field.recipient],
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const handleRecipientChange = (item: { id: string; name: string } | null) => {
|
|
36
|
+
if (item) {
|
|
37
|
+
onFieldConfigChange({
|
|
38
|
+
recipient: item.id,
|
|
39
|
+
path:
|
|
40
|
+
field.type === FieldTypeEnum.eSign
|
|
41
|
+
? generateESignPath(item.id, field.subType as ESignFieldType)
|
|
42
|
+
: field.path,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const selectedESignFieldType = useMemo(
|
|
48
|
+
() => E_SIGN_FIELD_TYPE_OPTIONS.find(option => option.id === field.subType) ?? null,
|
|
49
|
+
[field],
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const handleESignFieldTypeChange = (item: { id: ESignFieldType; name: string } | null) => {
|
|
53
|
+
if (item) {
|
|
54
|
+
onFieldConfigChange({
|
|
55
|
+
subType: item.id,
|
|
56
|
+
path: generateESignPath(field.recipient!, item.id),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<Flex direction="column" gap="4">
|
|
63
|
+
{(field.type === FieldTypeEnum.fillable || field.type === FieldTypeEnum.eSign) && (
|
|
64
|
+
<TextField
|
|
65
|
+
label="Label"
|
|
66
|
+
value={field.label}
|
|
67
|
+
onChange={e =>
|
|
68
|
+
onFieldConfigChange({
|
|
69
|
+
label: e.target.value,
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
/>
|
|
73
|
+
)}
|
|
74
|
+
|
|
75
|
+
{(field.type === FieldTypeEnum.fillable || field.type === FieldTypeEnum.eSign) && (
|
|
76
|
+
<Combobox
|
|
77
|
+
items={recipientOptions}
|
|
78
|
+
itemToString={item => item?.name ?? ''}
|
|
79
|
+
onChange={handleRecipientChange}
|
|
80
|
+
selectedItem={selectedRecipient}
|
|
81
|
+
>
|
|
82
|
+
<Combobox.SearchField
|
|
83
|
+
placeholder=""
|
|
84
|
+
label="Recipient"
|
|
85
|
+
labelProps={{ required: true }}
|
|
86
|
+
/>
|
|
87
|
+
<Combobox.Content>
|
|
88
|
+
{({ items }) => (
|
|
89
|
+
<Combobox.List>
|
|
90
|
+
{items.map((item, i) => (
|
|
91
|
+
<Combobox.Item key={item.id} item={item} index={i}>
|
|
92
|
+
{item.name}
|
|
93
|
+
</Combobox.Item>
|
|
94
|
+
))}
|
|
95
|
+
</Combobox.List>
|
|
96
|
+
)}
|
|
97
|
+
</Combobox.Content>
|
|
98
|
+
</Combobox>
|
|
99
|
+
)}
|
|
100
|
+
|
|
101
|
+
{field.type === FieldTypeEnum.eSign && (
|
|
102
|
+
<Combobox
|
|
103
|
+
items={E_SIGN_FIELD_TYPE_OPTIONS}
|
|
104
|
+
itemToString={item => item?.name ?? ''}
|
|
105
|
+
onChange={handleESignFieldTypeChange}
|
|
106
|
+
selectedItem={selectedESignFieldType}
|
|
107
|
+
>
|
|
108
|
+
<Combobox.SearchField label="Field Type" labelProps={{ required: true }} />
|
|
109
|
+
<Combobox.Content>
|
|
110
|
+
{({ items }) => (
|
|
111
|
+
<Combobox.List>
|
|
112
|
+
{items.map((item, i) => (
|
|
113
|
+
<Combobox.Item key={item.id} item={item} index={i}>
|
|
114
|
+
{item.name}
|
|
115
|
+
</Combobox.Item>
|
|
116
|
+
))}
|
|
117
|
+
</Combobox.List>
|
|
118
|
+
)}
|
|
119
|
+
</Combobox.Content>
|
|
120
|
+
</Combobox>
|
|
121
|
+
)}
|
|
122
|
+
|
|
123
|
+
{field.type === FieldTypeEnum.dataModel && field.path && (
|
|
124
|
+
<TextField label="Data Path" value={field.path} disabled />
|
|
125
|
+
)}
|
|
126
|
+
{field.type === FieldTypeEnum.fillable && (
|
|
127
|
+
<Checkbox
|
|
128
|
+
label="Required"
|
|
129
|
+
checked={field.required}
|
|
130
|
+
onChange={() =>
|
|
131
|
+
onFieldConfigChange({
|
|
132
|
+
required: !field.required,
|
|
133
|
+
})
|
|
134
|
+
}
|
|
135
|
+
/>
|
|
136
|
+
)}
|
|
137
|
+
<Button className="full-width" onClick={onDeleteField}>
|
|
138
|
+
Delete Field
|
|
139
|
+
</Button>
|
|
140
|
+
</Flex>
|
|
141
|
+
);
|
|
142
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { Flex, Icon, SearchField, Text } from '@servicetitan/anvil2';
|
|
2
|
+
import IconBorderColor from '@servicetitan/anvil2/assets/icons/material/round/border_color.svg';
|
|
3
|
+
import IconPhotoSizeSelectSmall from '@servicetitan/anvil2/assets/icons/material/round/photo_size_select_small.svg';
|
|
4
|
+
import IconEstimate from '@servicetitan/anvil2/assets/icons/st/estimate.svg';
|
|
5
|
+
|
|
6
|
+
import { FC, useState } from 'react';
|
|
7
|
+
import { DataModelFieldGroup, FieldTypeEnum, FieldTypeOption } from '../interface/pdf-editor';
|
|
8
|
+
import { DataModelFieldTypeList } from './data-model-field-type-list';
|
|
9
|
+
import { ESignFieldTypeList } from './e-sign-field-type-list';
|
|
10
|
+
import { FillableFieldTypeList } from './fillable-field-type-list';
|
|
11
|
+
|
|
12
|
+
interface FieldSidebarProps {
|
|
13
|
+
dataModelGroups?: DataModelFieldGroup[];
|
|
14
|
+
onDragEnd(): void;
|
|
15
|
+
onDragStart(fieldOption: FieldTypeOption): void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const menuGroups: { svgIcon: any; label: string; key: FieldTypeEnum }[] = [
|
|
19
|
+
{ svgIcon: IconEstimate, label: 'Merge Tags', key: FieldTypeEnum.dataModel },
|
|
20
|
+
{ svgIcon: IconBorderColor, label: 'E-Sign', key: FieldTypeEnum.eSign },
|
|
21
|
+
{
|
|
22
|
+
svgIcon: IconPhotoSizeSelectSmall,
|
|
23
|
+
label: 'Fillable Fields',
|
|
24
|
+
key: FieldTypeEnum.fillable,
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
export const FieldSidebar: FC<FieldSidebarProps> = ({
|
|
29
|
+
dataModelGroups = [],
|
|
30
|
+
onDragEnd,
|
|
31
|
+
onDragStart,
|
|
32
|
+
}) => {
|
|
33
|
+
const [activeFieldType, setActiveFieldType] = useState<FieldTypeEnum>(FieldTypeEnum.dataModel);
|
|
34
|
+
const [searchText, setSearchText] = useState('');
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<Flex className="dte-field-sidebar-container skeleton-item">
|
|
38
|
+
<Flex className="dte-field-sidebar-menu" shrink={0} direction="column" gap="3">
|
|
39
|
+
{menuGroups.map(({ key, label, svgIcon }) => (
|
|
40
|
+
<Flex
|
|
41
|
+
key={key}
|
|
42
|
+
alignItems="center"
|
|
43
|
+
justifyContent="center"
|
|
44
|
+
direction="column"
|
|
45
|
+
className="dte-field-sidebar-menu-item cursor-pointer"
|
|
46
|
+
onClick={() => setActiveFieldType(key)}
|
|
47
|
+
>
|
|
48
|
+
<Icon svg={svgIcon} size="large" />
|
|
49
|
+
<Text
|
|
50
|
+
variant="body"
|
|
51
|
+
size="small"
|
|
52
|
+
className="dte-field-sidebar-menu-item-text"
|
|
53
|
+
>
|
|
54
|
+
{label}
|
|
55
|
+
</Text>
|
|
56
|
+
</Flex>
|
|
57
|
+
))}
|
|
58
|
+
</Flex>
|
|
59
|
+
<Flex className="dte-field-sidebar-content skeleton-item" shrink={0}>
|
|
60
|
+
<Text variant="headline" el="h1" size="medium">
|
|
61
|
+
Merge Tags
|
|
62
|
+
</Text>
|
|
63
|
+
|
|
64
|
+
{activeFieldType !== FieldTypeEnum.eSign && (
|
|
65
|
+
<SearchField
|
|
66
|
+
placeholder="Search"
|
|
67
|
+
size="small"
|
|
68
|
+
className="dte-field-sidebar-search"
|
|
69
|
+
onChange={e => setSearchText(e.target.value ?? '')}
|
|
70
|
+
/>
|
|
71
|
+
)}
|
|
72
|
+
{activeFieldType === FieldTypeEnum.fillable && (
|
|
73
|
+
<FillableFieldTypeList
|
|
74
|
+
searchText={searchText}
|
|
75
|
+
onDragStart={onDragStart}
|
|
76
|
+
onDragEnd={onDragEnd}
|
|
77
|
+
/>
|
|
78
|
+
)}
|
|
79
|
+
{activeFieldType === FieldTypeEnum.eSign && (
|
|
80
|
+
<ESignFieldTypeList onDragEnd={onDragEnd} onDragStart={onDragStart} />
|
|
81
|
+
)}
|
|
82
|
+
{activeFieldType === FieldTypeEnum.dataModel && (
|
|
83
|
+
<DataModelFieldTypeList
|
|
84
|
+
searchText={searchText}
|
|
85
|
+
dataModelGroups={dataModelGroups}
|
|
86
|
+
onDragStart={onDragStart}
|
|
87
|
+
onDragEnd={onDragEnd}
|
|
88
|
+
/>
|
|
89
|
+
)}
|
|
90
|
+
</Flex>
|
|
91
|
+
</Flex>
|
|
92
|
+
);
|
|
93
|
+
};
|