@servicetitan/dte-pdf-editor 1.2.0 → 1.3.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.
Files changed (80) hide show
  1. package/dist/components/field-config-panel.d.ts.map +1 -1
  2. package/dist/components/field-config-panel.js +4 -2
  3. package/dist/components/field-config-panel.js.map +1 -1
  4. package/dist/components/fillable-field-type-list.d.ts.map +1 -1
  5. package/dist/components/fillable-field-type-list.js +4 -1
  6. package/dist/components/fillable-field-type-list.js.map +1 -1
  7. package/dist/components/pdf-editor.d.ts.map +1 -1
  8. package/dist/components/pdf-editor.js +9 -3
  9. package/dist/components/pdf-editor.js.map +1 -1
  10. package/dist/components/pdf-field-overlay.d.ts +10 -0
  11. package/dist/components/pdf-field-overlay.d.ts.map +1 -1
  12. package/dist/components/pdf-field-overlay.js +46 -18
  13. package/dist/components/pdf-field-overlay.js.map +1 -1
  14. package/dist/components/pdf-view-fields.d.ts +17 -0
  15. package/dist/components/pdf-view-fields.d.ts.map +1 -0
  16. package/dist/components/pdf-view-fields.js +53 -0
  17. package/dist/components/pdf-view-fields.js.map +1 -0
  18. package/dist/components/pdf-view.d.ts +19 -0
  19. package/dist/components/pdf-view.d.ts.map +1 -0
  20. package/dist/components/pdf-view.js +32 -0
  21. package/dist/components/pdf-view.js.map +1 -0
  22. package/dist/components/resize-handle.d.ts +7 -0
  23. package/dist/components/resize-handle.d.ts.map +1 -0
  24. package/dist/components/resize-handle.js +5 -0
  25. package/dist/components/resize-handle.js.map +1 -0
  26. package/dist/constants/field.constants.d.ts +7 -3
  27. package/dist/constants/field.constants.d.ts.map +1 -1
  28. package/dist/constants/field.constants.js +10 -3
  29. package/dist/constants/field.constants.js.map +1 -1
  30. package/dist/hooks/useFieldResize.d.ts +1 -1
  31. package/dist/hooks/useFieldResize.d.ts.map +1 -1
  32. package/dist/index.d.ts +1 -0
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +1 -0
  35. package/dist/index.js.map +1 -1
  36. package/dist/interface/pdf-editor.d.ts +1 -1
  37. package/dist/interface/pdf-editor.d.ts.map +1 -1
  38. package/dist/utils/generate-fillable-path.d.ts +2 -0
  39. package/dist/utils/generate-fillable-path.d.ts.map +1 -0
  40. package/dist/utils/generate-fillable-path.js +4 -0
  41. package/dist/utils/generate-fillable-path.js.map +1 -0
  42. package/dist/utils/get-field-background-color.d.ts +2 -0
  43. package/dist/utils/get-field-background-color.d.ts.map +1 -0
  44. package/dist/utils/get-field-background-color.js +4 -0
  45. package/dist/utils/get-field-background-color.js.map +1 -0
  46. package/dist/utils/get-field-placeholder-text.d.ts +3 -0
  47. package/dist/utils/get-field-placeholder-text.d.ts.map +1 -0
  48. package/dist/utils/get-field-placeholder-text.js +7 -0
  49. package/dist/utils/get-field-placeholder-text.js.map +1 -0
  50. package/dist/utils/index.d.ts +5 -0
  51. package/dist/utils/index.d.ts.map +1 -1
  52. package/dist/utils/index.js +5 -0
  53. package/dist/utils/index.js.map +1 -1
  54. package/dist/utils/parse-fillable-path.d.ts +2 -0
  55. package/dist/utils/parse-fillable-path.d.ts.map +1 -0
  56. package/dist/utils/parse-fillable-path.js +9 -0
  57. package/dist/utils/parse-fillable-path.js.map +1 -0
  58. package/dist/utils/resolve-pdf-data-values.d.ts +2 -0
  59. package/dist/utils/resolve-pdf-data-values.d.ts.map +1 -0
  60. package/dist/utils/resolve-pdf-data-values.js +27 -0
  61. package/dist/utils/resolve-pdf-data-values.js.map +1 -0
  62. package/package.json +1 -1
  63. package/src/components/field-config-panel.tsx +13 -1
  64. package/src/components/fillable-field-type-list.tsx +6 -1
  65. package/src/components/pdf-editor.tsx +8 -1
  66. package/src/components/pdf-field-overlay.tsx +147 -48
  67. package/src/components/pdf-view-fields.tsx +138 -0
  68. package/src/components/pdf-view.tsx +99 -0
  69. package/src/components/resize-handle.tsx +8 -0
  70. package/src/constants/field.constants.ts +16 -3
  71. package/src/hooks/useFieldResize.ts +1 -1
  72. package/src/index.ts +1 -0
  73. package/src/interface/pdf-editor.ts +1 -1
  74. package/src/styles/pdf-field-overlay.css +34 -9
  75. package/src/utils/generate-fillable-path.ts +3 -0
  76. package/src/utils/get-field-background-color.ts +6 -0
  77. package/src/utils/get-field-placeholder-text.ts +8 -0
  78. package/src/utils/index.ts +5 -0
  79. package/src/utils/parse-fillable-path.ts +8 -0
  80. package/src/utils/resolve-pdf-data-values.ts +34 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-fillable-path.d.ts","sourceRoot":"","sources":["../../src/utils/generate-fillable-path.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,GAAI,WAAW,MAAM,EAAE,MAAM,MAAM,KAAG,MAEtE,CAAC"}
@@ -0,0 +1,4 @@
1
+ export const generateFillablePath = (recipient, name) => {
2
+ return `fillable_${recipient}_${name}`;
3
+ };
4
+ //# sourceMappingURL=generate-fillable-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-fillable-path.js","sourceRoot":"","sources":["../../src/utils/generate-fillable-path.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,SAAiB,EAAE,IAAY,EAAU,EAAE;IAC5E,OAAO,YAAY,SAAS,IAAI,IAAI,EAAE,CAAC;AAC3C,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const getFieldBackgroundColor: (recipient: string | undefined, recipientsColors: Record<string, string>) => string;
2
+ //# sourceMappingURL=get-field-background-color.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-field-background-color.d.ts","sourceRoot":"","sources":["../../src/utils/get-field-background-color.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,GAChC,WAAW,MAAM,GAAG,SAAS,EAC7B,kBAAkB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACzC,MAEF,CAAC"}
@@ -0,0 +1,4 @@
1
+ export const getFieldBackgroundColor = (recipient, recipientsColors) => {
2
+ return recipient && recipientsColors[recipient] ? recipientsColors[recipient] : 'none';
3
+ };
4
+ //# sourceMappingURL=get-field-background-color.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-field-background-color.js","sourceRoot":"","sources":["../../src/utils/get-field-background-color.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACnC,SAA6B,EAC7B,gBAAwC,EAClC,EAAE;IACR,OAAO,SAAS,IAAI,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAC3F,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { PdfField } from '../interface/pdf-editor';
2
+ export declare const getFieldPlaceholderText: (field: PdfField, prefix?: string) => string;
3
+ //# sourceMappingURL=get-field-placeholder-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-field-placeholder-text.d.ts","sourceRoot":"","sources":["../../src/utils/get-field-placeholder-text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD,eAAO,MAAM,uBAAuB,GAAI,OAAO,QAAQ,EAAE,SAAS,MAAM,KAAG,MAK1E,CAAC"}
@@ -0,0 +1,7 @@
1
+ export const getFieldPlaceholderText = (field, prefix) => {
2
+ const requiredIndicator = field.required ? '*' : '';
3
+ const label = field.label || '';
4
+ const parts = [prefix, label, requiredIndicator].filter(Boolean);
5
+ return parts.join(' ');
6
+ };
7
+ //# sourceMappingURL=get-field-placeholder-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-field-placeholder-text.js","sourceRoot":"","sources":["../../src/utils/get-field-placeholder-text.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,KAAe,EAAE,MAAe,EAAU,EAAE;IAChF,MAAM,iBAAiB,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACjE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC,CAAC"}
@@ -10,4 +10,9 @@ export * from './is-drag-over-canvas.utils';
10
10
  export * from './map-colors-to-recipients';
11
11
  export * from './pdfjs-init';
12
12
  export * from './generate-e-sign-path';
13
+ export * from './resolve-pdf-data-values';
14
+ export * from './generate-fillable-path';
15
+ export * from './get-field-background-color';
16
+ export * from './get-field-placeholder-text';
17
+ export * from './parse-fillable-path';
13
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +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"}
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;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC"}
@@ -10,4 +10,9 @@ export * from './is-drag-over-canvas.utils';
10
10
  export * from './map-colors-to-recipients';
11
11
  export * from './pdfjs-init';
12
12
  export * from './generate-e-sign-path';
13
+ export * from './resolve-pdf-data-values';
14
+ export * from './generate-fillable-path';
15
+ export * from './get-field-background-color';
16
+ export * from './get-field-placeholder-text';
17
+ export * from './parse-fillable-path';
13
18
  //# sourceMappingURL=index.js.map
@@ -1 +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"}
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;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const parseFillablePathName: (path: string | undefined) => string;
2
+ //# sourceMappingURL=parse-fillable-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-fillable-path.d.ts","sourceRoot":"","sources":["../../src/utils/parse-fillable-path.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,GAAG,SAAS,KAAG,MAOhE,CAAC"}
@@ -0,0 +1,9 @@
1
+ export const parseFillablePathName = (path) => {
2
+ if (!path) {
3
+ return '';
4
+ }
5
+ const parts = path.split('_');
6
+ // Path format: fillable_{recipient}_{name}
7
+ return parts.length >= 3 ? parts[2] : '';
8
+ };
9
+ //# sourceMappingURL=parse-fillable-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-fillable-path.js","sourceRoot":"","sources":["../../src/utils/parse-fillable-path.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,IAAwB,EAAU,EAAE;IACtE,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,OAAO,EAAE,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,2CAA2C;IAC3C,OAAO,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC7C,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const resolvePdfDataValues: (data: Record<string, any> | undefined, path: string | undefined) => string;
2
+ //# sourceMappingURL=resolve-pdf-data-values.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-pdf-data-values.d.ts","sourceRoot":"","sources":["../../src/utils/resolve-pdf-data-values.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,GAC7B,MAAM,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EACrC,MAAM,MAAM,GAAG,SAAS,KACzB,MA8BF,CAAC"}
@@ -0,0 +1,27 @@
1
+ export const resolvePdfDataValues = (data, path) => {
2
+ if (!data || !path) {
3
+ return '';
4
+ }
5
+ const keys = path.split('.');
6
+ let value = data;
7
+ for (const key of keys) {
8
+ if (value === null || value === undefined || typeof value !== 'object') {
9
+ return '';
10
+ }
11
+ value = value[key];
12
+ }
13
+ if (value === null || value === undefined) {
14
+ return '';
15
+ }
16
+ if (typeof value === 'object') {
17
+ if ('Amount' in value && 'Currency' in value) {
18
+ return `${value.Currency} ${value.Amount}`;
19
+ }
20
+ if ('Value' in value) {
21
+ return String(value.Value);
22
+ }
23
+ return JSON.stringify(value);
24
+ }
25
+ return String(value);
26
+ };
27
+ //# sourceMappingURL=resolve-pdf-data-values.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-pdf-data-values.js","sourceRoot":"","sources":["../../src/utils/resolve-pdf-data-values.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAChC,IAAqC,EACrC,IAAwB,EAClB,EAAE;IACR,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,EAAE,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,KAAK,GAAQ,IAAI,CAAC;IAEtB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACrE,OAAO,EAAE,CAAC;QACd,CAAC;QACD,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IAED,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxC,OAAO,EAAE,CAAC;IACd,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,IAAI,QAAQ,IAAI,KAAK,IAAI,UAAU,IAAI,KAAK,EAAE,CAAC;YAC3C,OAAO,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAC/C,CAAC;QACD,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;YACnB,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/dte-pdf-editor",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "typings": "./dist/index.d.ts",
@@ -2,7 +2,7 @@ import { Button, Checkbox, Combobox, Flex, TextField } from '@servicetitan/anvil
2
2
  import { FC, useMemo } from 'react';
3
3
  import { E_SIGN_FIELD_TYPE_OPTIONS } from '../constants';
4
4
  import { ESignFieldType, FieldTypeEnum, PdfField } from '../interface/pdf-editor';
5
- import { generateESignPath } from '../utils';
5
+ import { generateESignPath, generateFillablePath, parseFillablePathName } from '../utils';
6
6
  import { RecipientInfo } from './pdf-editor';
7
7
 
8
8
  interface FieldConfigPanelProps {
@@ -123,6 +123,17 @@ export const FieldConfigPanel: FC<FieldConfigPanelProps> = ({
123
123
  {field.type === FieldTypeEnum.dataModel && field.path && (
124
124
  <TextField label="Data Path" value={field.path} disabled />
125
125
  )}
126
+ {field.type === FieldTypeEnum.fillable && (
127
+ <TextField
128
+ label="Input Name"
129
+ value={parseFillablePathName(field.path)}
130
+ onChange={e =>
131
+ onFieldConfigChange({
132
+ path: generateFillablePath(field.recipient!, e.target.value),
133
+ })
134
+ }
135
+ />
136
+ )}
126
137
  {field.type === FieldTypeEnum.fillable && (
127
138
  <Checkbox
128
139
  label="Required"
@@ -134,6 +145,7 @@ export const FieldConfigPanel: FC<FieldConfigPanelProps> = ({
134
145
  }
135
146
  />
136
147
  )}
148
+
137
149
  <Button className="full-width" onClick={onDeleteField}>
138
150
  Delete Field
139
151
  </Button>
@@ -33,7 +33,12 @@ export const FillableFieldTypeList: FC<FillableFieldTypeListProps> = ({
33
33
  key={fieldOption.subType}
34
34
  label={fieldOption.label}
35
35
  onDragEnd={onDragEnd}
36
- onDragStart={() => onDragStart(fieldOption)}
36
+ onDragStart={() =>
37
+ onDragStart({
38
+ ...fieldOption,
39
+ label: '',
40
+ })
41
+ }
37
42
  />
38
43
  );
39
44
  })}
@@ -1,7 +1,7 @@
1
1
  import { Flex } from '@servicetitan/anvil2';
2
2
  import { DragEvent, FC, MouseEvent, ReactNode, useMemo, useRef, useState } from 'react';
3
3
  import { v4 as uuidv4 } from 'uuid';
4
- import { FIELD_CONSTANTS } from '../constants';
4
+ import { FIELD_CONSTANTS, FILLABLE_FIELD_DEFAULT_SIZES } from '../constants';
5
5
 
6
6
  import {
7
7
  ESignFieldType,
@@ -15,6 +15,7 @@ import {
15
15
  calculateDropCoordinates,
16
16
  extractGroupedFieldsFromDataModel,
17
17
  generateESignPath,
18
+ generateFillablePath,
18
19
  initializePdfJsWorker,
19
20
  isDragOverCanvas,
20
21
  mapColorsToRecipients,
@@ -104,8 +105,14 @@ export const PdfEditor: FC<PdfEditorProps> = ({
104
105
  );
105
106
  }
106
107
  if (draggedFieldOption.type === FieldTypeEnum.fillable) {
108
+ const defaultFieldSizes = FILLABLE_FIELD_DEFAULT_SIZES[newField.subType!];
107
109
  newField.recipient = recipients[0]?.name ?? '';
108
110
  newField.required = false;
111
+ newField.path = generateFillablePath(recipients[0]?.name ?? '', uuidv4());
112
+ if (defaultFieldSizes) {
113
+ newField.width = defaultFieldSizes.width;
114
+ newField.height = defaultFieldSizes.height;
115
+ }
109
116
  }
110
117
 
111
118
  onFieldsChange([...fields, newField]);
@@ -1,7 +1,8 @@
1
- import { FC, MouseEvent, RefObject } from 'react';
2
- import { useFieldDrag, useFieldResize } from '../hooks';
1
+ import { FC, Fragment, MouseEvent, RefObject, useMemo } from 'react';
2
+ import { useFieldDrag, useFieldResize, UseFieldResizeReturn } from '../hooks';
3
3
  import { FieldTypeEnum, PdfField } from '../interface/pdf-editor';
4
- import { getPagePosition } from '../utils';
4
+ import { getFieldBackgroundColor, getFieldPlaceholderText, getPagePosition } from '../utils';
5
+ import { ResizeHandle } from './resize-handle';
5
6
 
6
7
  interface PdfFieldOverlayProps {
7
8
  fields: PdfField[];
@@ -21,63 +22,161 @@ export const PdfFieldOverlay: FC<PdfFieldOverlayProps> = ({
21
22
  pdfWrapperRef,
22
23
  recipientsColors,
23
24
  selectedField,
25
+ }) => {
26
+ return (
27
+ <div className="dte-pdf-field-overlay skeleton-item">
28
+ {fields.map(field => (
29
+ <PdfFieldOverlayField
30
+ key={field.id}
31
+ field={field}
32
+ onFieldMove={onFieldMove}
33
+ onFieldClick={onFieldClick}
34
+ pdfWrapperRef={pdfWrapperRef}
35
+ onFieldResize={onFieldResize}
36
+ isSelected={selectedField === field.id}
37
+ recipientsColors={recipientsColors}
38
+ />
39
+ ))}
40
+ </div>
41
+ );
42
+ };
43
+
44
+ interface PdfFieldOverlayFieldProps {
45
+ field: PdfField;
46
+ isSelected: boolean;
47
+ recipientsColors: Record<string, string>;
48
+ pdfWrapperRef: RefObject<HTMLDivElement>;
49
+ onFieldClick(fieldId: string, e: MouseEvent): void;
50
+ onFieldMove(fieldId: string, newX: number, newY: number, pageNumber: number): void;
51
+ onFieldResize(fieldId: string, newWidth: number, newHeight: number, pageNumber: number): void;
52
+ }
53
+
54
+ export const PdfFieldOverlayField: FC<PdfFieldOverlayFieldProps> = ({
55
+ field,
56
+ isSelected,
57
+ onFieldClick,
58
+ onFieldMove,
59
+ onFieldResize,
60
+ pdfWrapperRef,
61
+ recipientsColors,
24
62
  }) => {
25
63
  const { draggingFieldIdRef, handleDrag, handleDragEnd, handleDragStart } = useFieldDrag({
26
64
  pdfWrapperRef,
27
65
  onFieldMove,
28
66
  });
67
+ const isDragging = draggingFieldIdRef.current === field.id;
29
68
 
30
69
  const { handleResizeStart } = useFieldResize({
31
70
  pdfWrapperRef,
32
71
  onFieldResize,
33
72
  });
34
73
 
74
+ const pagePos = useMemo(() => {
75
+ return getPagePosition(field.page, pdfWrapperRef);
76
+ }, [field.page, pdfWrapperRef]);
77
+
78
+ const style = useMemo(() => {
79
+ const bgColor = getFieldBackgroundColor(field.recipient, recipientsColors);
80
+ return {
81
+ left: pagePos.left + field.x,
82
+ top: pagePos.top + field.y,
83
+ width: field.width,
84
+ height: field.height,
85
+ backgroundColor: bgColor,
86
+ };
87
+ }, [
88
+ field.recipient,
89
+ field.x,
90
+ field.y,
91
+ field.width,
92
+ field.height,
93
+ recipientsColors,
94
+ pagePos.left,
95
+ pagePos.top,
96
+ ]);
97
+
35
98
  return (
36
- <div className="dte-pdf-field-overlay skeleton-item">
37
- {fields.map(field => {
38
- const isSelected = selectedField === field.id;
39
- const isDragging = draggingFieldIdRef.current === field.id;
40
- const pagePos = getPagePosition(field.page, pdfWrapperRef);
41
- const bgColor =
42
- field.recipient && recipientsColors[field.recipient]
43
- ? recipientsColors[field.recipient]
44
- : 'rgba(255, 255, 255, 0.8)';
45
-
46
- return (
47
- <div
48
- key={field.id}
49
- onClick={e => onFieldClick(field.id, e)}
50
- draggable
51
- onDragStart={e => handleDragStart(e, field)}
52
- onDrag={e => handleDrag(e, field)}
53
- onDragEnd={handleDragEnd}
54
- className={`dte-pdf-field ${isSelected ? 'dte-pdf-field-selected' : 'dte-pdf-field-unselected'} ${isDragging ? 'dte-pdf-field-dragging' : ''}`}
55
- style={{
56
- left: `${pagePos.left + field.x}px`,
57
- top: `${pagePos.top + field.y}px`,
58
- width: `${field.width}px`,
59
- height: `${field.height}px`,
60
- backgroundColor: bgColor,
61
- }}
62
- >
63
- <span>
64
- {(field.type === FieldTypeEnum.eSign ||
65
- field.type === FieldTypeEnum.fillable) &&
66
- `${field.label} ${field.required ? '*' : ''}`}
67
-
68
- {field.path && (
69
- <div className="dte-pdf-field-path">{`{{${field.path}}}`}</div>
70
- )}
71
- </span>
72
- {isSelected && (
73
- <div
74
- className="dte-pdf-field-resize-handle"
75
- onMouseDown={e => handleResizeStart(e, field)}
76
- />
77
- )}
78
- </div>
79
- );
80
- })}
99
+ <div
100
+ onClick={e => onFieldClick(field.id, e)}
101
+ draggable
102
+ onDragStart={e => handleDragStart(e, field)}
103
+ onDrag={e => handleDrag(e, field)}
104
+ onDragEnd={handleDragEnd}
105
+ className={`dte-pdf-field ${isSelected ? 'dte-pdf-field-selected' : 'dte-pdf-field-unselected'} ${isDragging ? 'dte-pdf-field-dragging' : ''}`}
106
+ style={style}
107
+ >
108
+ {field.type === FieldTypeEnum.eSign && <FieldEsign field={field} />}
109
+ {field.type === FieldTypeEnum.dataModel && <FieldDataModel field={field} />}
110
+ {field.type === FieldTypeEnum.fillable && (
111
+ <FieldFillable
112
+ field={field}
113
+ handleResizeStart={handleResizeStart}
114
+ isSelected={isSelected}
115
+ />
116
+ )}
81
117
  </div>
82
118
  );
83
119
  };
120
+
121
+ interface FieldProps {
122
+ field: PdfField;
123
+ }
124
+
125
+ const FieldEsign: FC<FieldProps> = ({ field }) => {
126
+ return (
127
+ <span>
128
+ {field.label} {field.required ? '*' : ''}
129
+ <div className="dte-pdf-field-value">{field.path}</div>
130
+ </span>
131
+ );
132
+ };
133
+
134
+ const FieldDataModel: FC<FieldProps> = ({ field }) => {
135
+ return (
136
+ <span>
137
+ {field.label ? field.label : field.path}
138
+ {field.required ? '*' : ''}
139
+ </span>
140
+ );
141
+ };
142
+
143
+ interface FieldFillableProps extends FieldProps {
144
+ isSelected: boolean;
145
+ handleResizeStart: UseFieldResizeReturn['handleResizeStart'];
146
+ }
147
+
148
+ const FieldFillable: FC<FieldFillableProps> = ({ field, handleResizeStart, isSelected }) => {
149
+ const placeholderText = getFieldPlaceholderText(field);
150
+
151
+ if (field.subType === 'checkbox' || field.subType === 'radio') {
152
+ return <input type={field.subType} readOnly className="dte-pdf-field-fillable" />;
153
+ }
154
+
155
+ if (field.subType === 'date') {
156
+ return (
157
+ <Fragment>
158
+ <input
159
+ type="date"
160
+ readOnly
161
+ className="dte-pdf-field-fillable"
162
+ placeholder={placeholderText}
163
+ />
164
+ {isSelected && (
165
+ <ResizeHandle handleResizeStart={e => handleResizeStart(e, field)} />
166
+ )}
167
+ </Fragment>
168
+ );
169
+ }
170
+
171
+ return (
172
+ <Fragment>
173
+ <input
174
+ type="text"
175
+ readOnly
176
+ placeholder={placeholderText}
177
+ className="dte-pdf-field-fillable"
178
+ />
179
+ {isSelected && <ResizeHandle handleResizeStart={e => handleResizeStart(e, field)} />}
180
+ </Fragment>
181
+ );
182
+ };
@@ -0,0 +1,138 @@
1
+ import { FC } from 'react';
2
+ import { PdfField } from '../interface/pdf-editor';
3
+ import { getFieldPlaceholderText, resolvePdfDataValues } from '../utils';
4
+
5
+ interface BaseFieldViewProps {
6
+ field: PdfField;
7
+ data?: Record<string, any>;
8
+ }
9
+
10
+ export const ViewDataModel: FC<BaseFieldViewProps> = ({ data, field }) => {
11
+ const resolvedValue = field.path ? resolvePdfDataValues(data, field.path) : '';
12
+ return <div className="dte-pdf-field-value">{resolvedValue ?? ''}</div>;
13
+ };
14
+
15
+ export const ViewEsign: FC<BaseFieldViewProps> = ({ data, field }) => {
16
+ const resolvedValue = field.path ? resolvePdfDataValues(data, field.path) : '';
17
+
18
+ return (
19
+ <span>
20
+ {field.label} {field.required ? '*' : ''}
21
+ <div className="dte-pdf-field-value">{resolvedValue}</div>
22
+ </span>
23
+ );
24
+ };
25
+
26
+ interface FillableFieldViewProps extends BaseFieldViewProps {
27
+ fillingBy?: string[];
28
+ onDataChange?(changedData: { [path: string]: string | boolean }): void;
29
+ }
30
+
31
+ export const FillableFieldView: FC<FillableFieldViewProps> = ({
32
+ data,
33
+ field,
34
+ fillingBy,
35
+ onDataChange,
36
+ }) => {
37
+ const resolvedValue = data?.[field.path!];
38
+ const isViewByCurrentRecipient = fillingBy?.includes(field.recipient!);
39
+ if (field.subType === 'checkbox') {
40
+ return (
41
+ <div
42
+ style={{
43
+ display: 'flex',
44
+ alignItems: 'center',
45
+ background: 'inherit',
46
+ width: 'inherit',
47
+ height: 'inherit',
48
+ }}
49
+ >
50
+ <input
51
+ style={{ width: 'inherit', height: 'inherit', margin: 0 }}
52
+ type="checkbox"
53
+ checked={resolvedValue ?? false}
54
+ disabled={!isViewByCurrentRecipient}
55
+ name={field.path}
56
+ onChange={e =>
57
+ onDataChange?.({
58
+ [field.path!]: e!.target.checked,
59
+ })
60
+ }
61
+ />
62
+ {field.label}
63
+ </div>
64
+ );
65
+ }
66
+
67
+ if (field.subType === 'radio') {
68
+ return (
69
+ <div
70
+ style={{
71
+ display: 'flex',
72
+ alignItems: 'center',
73
+ background: 'inherit',
74
+ width: 'inherit',
75
+ height: 'inherit',
76
+ }}
77
+ >
78
+ <input
79
+ style={{ width: 'inherit', height: 'inherit', margin: 0 }}
80
+ type="radio"
81
+ checked={resolvedValue ?? false}
82
+ disabled={!isViewByCurrentRecipient}
83
+ name={field.path}
84
+ onChange={e =>
85
+ onDataChange?.({
86
+ [field.path!]: e!.target.value,
87
+ })
88
+ }
89
+ />
90
+ {field.label}
91
+ </div>
92
+ );
93
+ }
94
+
95
+ if (field.subType === 'date') {
96
+ return (
97
+ <input
98
+ type="date"
99
+ style={{
100
+ background: 'inherit',
101
+ width: 'inherit',
102
+ height: 'inherit',
103
+ }}
104
+ disabled={!isViewByCurrentRecipient}
105
+ id={field.path}
106
+ name={field.path}
107
+ value={resolvedValue ?? ''}
108
+ onChange={e =>
109
+ onDataChange?.({
110
+ [field.path!]: e.target.value,
111
+ })
112
+ }
113
+ placeholder={getFieldPlaceholderText(field, 'mm/dd/yyyy')}
114
+ />
115
+ );
116
+ }
117
+
118
+ return (
119
+ <input
120
+ type="text"
121
+ style={{
122
+ background: 'inherit',
123
+ width: 'inherit',
124
+ height: 'inherit',
125
+ }}
126
+ disabled={!isViewByCurrentRecipient}
127
+ id={field.path}
128
+ name={field.path}
129
+ value={resolvedValue ?? ''}
130
+ onChange={e =>
131
+ onDataChange?.({
132
+ [field.path!]: e.target.value,
133
+ })
134
+ }
135
+ placeholder={getFieldPlaceholderText(field)}
136
+ />
137
+ );
138
+ };