@servicetitan/dte-pdf-editor 1.91.0 → 1.92.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/dist/components/field-sidebar/calculated-field-type-list.d.ts.map +1 -1
  2. package/dist/components/field-sidebar/calculated-field-type-list.js +1 -1
  3. package/dist/components/field-sidebar/calculated-field-type-list.js.map +1 -1
  4. package/dist/components/field-sidebar/data-model-field-type-list.d.ts +1 -12
  5. package/dist/components/field-sidebar/data-model-field-type-list.d.ts.map +1 -1
  6. package/dist/components/field-sidebar/data-model-field-type-list.js +9 -29
  7. package/dist/components/field-sidebar/data-model-field-type-list.js.map +1 -1
  8. package/dist/components/field-sidebar/e-sign-field-type-list.d.ts.map +1 -1
  9. package/dist/components/field-sidebar/e-sign-field-type-list.js +1 -1
  10. package/dist/components/field-sidebar/e-sign-field-type-list.js.map +1 -1
  11. package/dist/components/field-sidebar/field-sidebar.d.ts +0 -5
  12. package/dist/components/field-sidebar/field-sidebar.d.ts.map +1 -1
  13. package/dist/components/field-sidebar/field-sidebar.js +10 -7
  14. package/dist/components/field-sidebar/field-sidebar.js.map +1 -1
  15. package/dist/components/field-sidebar/field-type.d.ts +2 -0
  16. package/dist/components/field-sidebar/field-type.d.ts.map +1 -1
  17. package/dist/components/field-sidebar/field-type.js +2 -2
  18. package/dist/components/field-sidebar/field-type.js.map +1 -1
  19. package/dist/components/field-sidebar/fillable-field-type-list.d.ts.map +1 -1
  20. package/dist/components/field-sidebar/fillable-field-type-list.js +1 -1
  21. package/dist/components/field-sidebar/fillable-field-type-list.js.map +1 -1
  22. package/dist/components/field-sidebar/form-fields-type-list.d.ts +5 -23
  23. package/dist/components/field-sidebar/form-fields-type-list.d.ts.map +1 -1
  24. package/dist/components/field-sidebar/form-fields-type-list.js +5 -20
  25. package/dist/components/field-sidebar/form-fields-type-list.js.map +1 -1
  26. package/dist/components/field-sidebar/generic-field-type-list.d.ts.map +1 -1
  27. package/dist/components/field-sidebar/generic-field-type-list.js +1 -1
  28. package/dist/components/field-sidebar/generic-field-type-list.js.map +1 -1
  29. package/dist/components/pdf-canvas/canvas-controls.d.ts +9 -15
  30. package/dist/components/pdf-canvas/canvas-controls.d.ts.map +1 -1
  31. package/dist/components/pdf-canvas/canvas-controls.js +4 -14
  32. package/dist/components/pdf-canvas/canvas-controls.js.map +1 -1
  33. package/dist/components/pdf-canvas/pdf-canvas.d.ts +6 -2
  34. package/dist/components/pdf-canvas/pdf-canvas.d.ts.map +1 -1
  35. package/dist/components/pdf-canvas/pdf-canvas.js +11 -5
  36. package/dist/components/pdf-canvas/pdf-canvas.js.map +1 -1
  37. package/dist/components/pdf-editor/pdf-editor.d.ts +2 -0
  38. package/dist/components/pdf-editor/pdf-editor.d.ts.map +1 -1
  39. package/dist/components/pdf-editor/pdf-editor.js +2 -2
  40. package/dist/components/pdf-editor/pdf-editor.js.map +1 -1
  41. package/dist/components/pdf-fields-overlay/pdf-fields-overlay.js +4 -1
  42. package/dist/components/pdf-fields-overlay/pdf-fields-overlay.js.map +1 -1
  43. package/dist/components/pdf-fields-overlay/pdf-overlay-field-e-sign.d.ts.map +1 -1
  44. package/dist/components/pdf-fields-overlay/pdf-overlay-field-e-sign.js +3 -2
  45. package/dist/components/pdf-fields-overlay/pdf-overlay-field-e-sign.js.map +1 -1
  46. package/dist/components/pdf-fields-overlay/pdf-overlay-field.d.ts.map +1 -1
  47. package/dist/components/pdf-fields-overlay/pdf-overlay-field.js +4 -2
  48. package/dist/components/pdf-fields-overlay/pdf-overlay-field.js.map +1 -1
  49. package/dist/components/pdf-view/pdf-view-e-sign.d.ts.map +1 -1
  50. package/dist/components/pdf-view/pdf-view-e-sign.js +3 -2
  51. package/dist/components/pdf-view/pdf-view-e-sign.js.map +1 -1
  52. package/dist/components/pdf-view/pdf-view-field-container.d.ts.map +1 -1
  53. package/dist/components/pdf-view/pdf-view-field-container.js +10 -3
  54. package/dist/components/pdf-view/pdf-view-field-container.js.map +1 -1
  55. package/dist/components/pdf-view/pdf-view-fillable.js +1 -1
  56. package/dist/components/pdf-view/pdf-view-fillable.js.map +1 -1
  57. package/dist/components/pdf-view/pdf-view.d.ts +5 -0
  58. package/dist/components/pdf-view/pdf-view.d.ts.map +1 -1
  59. package/dist/components/pdf-view/pdf-view.js +51 -24
  60. package/dist/components/pdf-view/pdf-view.js.map +1 -1
  61. package/dist/constants/field.constants.d.ts.map +1 -1
  62. package/dist/constants/field.constants.js +27 -6
  63. package/dist/constants/field.constants.js.map +1 -1
  64. package/dist/constants/menu-group.d.ts +0 -5
  65. package/dist/constants/menu-group.d.ts.map +1 -1
  66. package/dist/constants/menu-group.js +2 -5
  67. package/dist/constants/menu-group.js.map +1 -1
  68. package/dist/hooks/index.d.ts +1 -0
  69. package/dist/hooks/index.d.ts.map +1 -1
  70. package/dist/hooks/index.js +1 -0
  71. package/dist/hooks/index.js.map +1 -1
  72. package/dist/hooks/usePinchZoom.d.ts +14 -0
  73. package/dist/hooks/usePinchZoom.d.ts.map +1 -0
  74. package/dist/hooks/usePinchZoom.js +58 -0
  75. package/dist/hooks/usePinchZoom.js.map +1 -0
  76. package/dist/hooks/useZoom.d.ts +2 -0
  77. package/dist/hooks/useZoom.d.ts.map +1 -1
  78. package/dist/hooks/useZoom.js +18 -6
  79. package/dist/hooks/useZoom.js.map +1 -1
  80. package/dist/interface/types.d.ts +2 -0
  81. package/dist/interface/types.d.ts.map +1 -1
  82. package/dist/interface/types.js.map +1 -1
  83. package/dist/styles/pdf-canvas.css +91 -15
  84. package/dist/styles/pdf-editor.css +1 -0
  85. package/dist/styles/pdf-field-overlay.css +109 -78
  86. package/dist/styles/variables.css +3 -0
  87. package/dist/utils/field/get-field-type-option.utils.d.ts +3 -0
  88. package/dist/utils/field/get-field-type-option.utils.d.ts.map +1 -0
  89. package/dist/utils/field/get-field-type-option.utils.js +10 -0
  90. package/dist/utils/field/get-field-type-option.utils.js.map +1 -0
  91. package/dist/utils/field/get-navigable-fields.utils.js +1 -1
  92. package/dist/utils/field/get-navigable-fields.utils.js.map +1 -1
  93. package/dist/utils/field/index.d.ts +1 -0
  94. package/dist/utils/field/index.d.ts.map +1 -1
  95. package/dist/utils/field/index.js +1 -0
  96. package/dist/utils/field/index.js.map +1 -1
  97. package/dist/utils/pdf/index.d.ts +1 -0
  98. package/dist/utils/pdf/index.d.ts.map +1 -1
  99. package/dist/utils/pdf/index.js +1 -0
  100. package/dist/utils/pdf/index.js.map +1 -1
  101. package/dist/utils/pdf/pinch-zoom.utils.d.ts +6 -0
  102. package/dist/utils/pdf/pinch-zoom.utils.d.ts.map +1 -0
  103. package/dist/utils/pdf/pinch-zoom.utils.js +18 -0
  104. package/dist/utils/pdf/pinch-zoom.utils.js.map +1 -0
  105. package/package.json +1 -1
  106. package/src/components/field-sidebar/calculated-field-type-list.tsx +1 -0
  107. package/src/components/field-sidebar/data-model-field-type-list.tsx +28 -103
  108. package/src/components/field-sidebar/e-sign-field-type-list.tsx +1 -0
  109. package/src/components/field-sidebar/field-sidebar.tsx +18 -15
  110. package/src/components/field-sidebar/field-type.tsx +13 -3
  111. package/src/components/field-sidebar/fillable-field-type-list.tsx +1 -0
  112. package/src/components/field-sidebar/form-fields-type-list.tsx +94 -109
  113. package/src/components/field-sidebar/generic-field-type-list.tsx +1 -0
  114. package/src/components/pdf-canvas/canvas-controls.tsx +30 -128
  115. package/src/components/pdf-canvas/pdf-canvas.tsx +18 -8
  116. package/src/components/pdf-editor/pdf-editor.tsx +4 -1
  117. package/src/components/pdf-fields-overlay/pdf-fields-overlay.tsx +1 -1
  118. package/src/components/pdf-fields-overlay/pdf-overlay-field-e-sign.tsx +8 -6
  119. package/src/components/pdf-fields-overlay/pdf-overlay-field.tsx +17 -1
  120. package/src/components/pdf-view/pdf-view-e-sign.tsx +8 -6
  121. package/src/components/pdf-view/pdf-view-field-container.tsx +21 -1
  122. package/src/components/pdf-view/pdf-view-fillable.tsx +1 -1
  123. package/src/components/pdf-view/pdf-view.tsx +156 -95
  124. package/src/constants/field.constants.ts +28 -6
  125. package/src/constants/menu-group.ts +2 -5
  126. package/src/hooks/index.ts +1 -0
  127. package/src/hooks/usePinchZoom.ts +86 -0
  128. package/src/hooks/useZoom.ts +20 -8
  129. package/src/interface/types.ts +3 -0
  130. package/src/styles/pdf-canvas.css +91 -15
  131. package/src/styles/pdf-editor.css +1 -0
  132. package/src/styles/pdf-field-overlay.css +109 -78
  133. package/src/styles/variables.css +3 -0
  134. package/src/utils/field/__tests__/get-field-type-option.utils.test.ts +53 -0
  135. package/src/utils/field/get-field-type-option.utils.ts +16 -0
  136. package/src/utils/field/get-navigable-fields.utils.ts +1 -1
  137. package/src/utils/field/index.ts +1 -0
  138. package/src/utils/pdf/__tests__/pinch-zoom.utils.test.ts +58 -0
  139. package/src/utils/pdf/index.ts +1 -0
  140. package/src/utils/pdf/pinch-zoom.utils.ts +30 -0
@@ -1,25 +1,37 @@
1
1
  import { useCallback, useState } from 'react';
2
- import { ZOOM_DEFAULT, ZOOM_MAX, ZOOM_MIN, ZOOM_STEP } from '../constants';
2
+ import { ZOOM_DEFAULT, ZOOM_STEP } from '../constants';
3
+ import { clampZoom } from '../utils';
3
4
 
4
5
  export interface UseZoomReturn {
5
6
  zoom: number;
6
7
  zoomIn(): void;
7
8
  zoomOut(): void;
8
9
  resetZoom(): void;
10
+ setZoomValue(value: number): void;
11
+ zoomByFactor(factor: number): void;
9
12
  }
10
13
 
11
- const clampZoom = (value: number) =>
12
- Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, Math.round(value * 100) / 100));
13
-
14
14
  /**
15
15
  * Manages a page zoom factor (1 = 100%), clamped to [ZOOM_MIN, ZOOM_MAX] in ZOOM_STEP increments.
16
16
  */
17
17
  export const useZoom = (initialZoom: number = ZOOM_DEFAULT): UseZoomReturn => {
18
18
  const [zoom, setZoom] = useState<number>(initialZoom);
19
19
 
20
- const zoomIn = useCallback(() => setZoom(prev => clampZoom(prev + ZOOM_STEP)), []);
21
- const zoomOut = useCallback(() => setZoom(prev => clampZoom(prev - ZOOM_STEP)), []);
22
- const resetZoom = useCallback(() => setZoom(ZOOM_DEFAULT), []);
20
+ const zoomIn = useCallback(() => {
21
+ setZoom(prev => clampZoom(prev + ZOOM_STEP));
22
+ }, []);
23
+ const zoomOut = useCallback(() => {
24
+ setZoom(prev => clampZoom(prev - ZOOM_STEP));
25
+ }, []);
26
+ const resetZoom = useCallback(() => {
27
+ setZoom(ZOOM_DEFAULT);
28
+ }, []);
29
+ const setZoomValue = useCallback((value: number) => {
30
+ setZoom(clampZoom(value));
31
+ }, []);
32
+ const zoomByFactor = useCallback((factor: number) => {
33
+ setZoom(prev => clampZoom(prev * factor));
34
+ }, []);
23
35
 
24
- return { zoom, zoomIn, zoomOut, resetZoom };
36
+ return { resetZoom, setZoomValue, zoom, zoomByFactor, zoomIn, zoomOut };
25
37
  };
@@ -1,3 +1,5 @@
1
+ import { Svg } from '@servicetitan/anvil2';
2
+
1
3
  export enum FieldTypeEnum {
2
4
  dataModel = 'dataModel',
3
5
  forms = 'forms',
@@ -164,6 +166,7 @@ export interface FieldTypeOption {
164
166
  fieldType?: SchemaFieldType;
165
167
  formSnapshot?: FormulaFieldFormSnapshot;
166
168
  sampleData?: unknown;
169
+ icon?: Svg;
167
170
  }
168
171
 
169
172
  export interface DataModelFieldGroup {
@@ -5,14 +5,8 @@
5
5
  margin-inline-end: auto;
6
6
  }
7
7
 
8
- .dte-pdf-canvas-controls {
9
- z-index: 1;
10
- position: sticky;
11
- top: 0;
12
- left: 0;
13
- background: var(--bg-color-main, #fafafa);
14
- box-shadow: 0 2px 4px rgb(0 0 0 / 15%);
15
- padding: var(--spacing-half) var(--spacing-1);
8
+ .dte-pdf-canvas-container {
9
+ touch-action: pan-x pan-y;
16
10
  }
17
11
 
18
12
  .dte-pdf-zoom-controls-value {
@@ -22,13 +16,95 @@
22
16
  user-select: none;
23
17
  }
24
18
 
25
- .dte-pdf-zoom-controls,
26
- .dte-pdf-field-navigation-controls {
27
- border-radius: var(--radius-1, 4px);
28
- padding: var(--spacing-half);
29
- background-color: var(--bg-color-secondary, #eeeeee);
19
+ .dte-pdf-zoom-controls {
20
+ background-color: var(--bg-color-light, #ffffff);
21
+ border: 1px solid var(--border-color, #e0e0e0);
22
+ border-radius: var(--radius-2, 8px);
23
+ position: fixed;
24
+ z-index: 2;
25
+
26
+ &.--vertical {
27
+ flex-direction: column;
28
+ }
29
+
30
+ &.--right-center {
31
+ right: 24px;
32
+ top: 50%;
33
+ transform: translateY(-50%);
34
+ }
35
+
36
+ &.--right-bottom {
37
+ right: 24px;
38
+ bottom: 24px;
39
+ }
40
+ }
41
+
42
+ .dte-pdf-field-next-controls-button {
43
+ background-color: #0365dd;
44
+ cursor: pointer;
45
+ color: var(--color-neutral-0, #ffffff);
46
+ border-radius: var(--border-radius-2, 6px);
47
+ font-size: var(--typescale-1, 12px);
48
+ font-family: 'Nunito Sans';
49
+ font-weight: var(--font-weight-semibold, 600);
50
+ font-stretch: 100%;
51
+
52
+ &.--started {
53
+ &:after {
54
+ content: '';
55
+ position: absolute;
56
+ right: -1em;
57
+ height: 100%;
58
+ width: 1.3em;
59
+ background-color: inherit;
60
+ clip-path: polygon(0% 0%, 100% 50%, 0% 100%);
61
+ }
62
+ }
63
+
64
+ &.--disabled {
65
+ background-color: var(--color-neutral-300, #e0e0e0);
66
+ cursor: not-allowed;
67
+ }
68
+
69
+ > span {
70
+ position: relative;
71
+ padding: 5px var(--spacing-1);
72
+ display: inline-block;
73
+ }
74
+ }
75
+
76
+ .dte-pdf-canvas-controls {
77
+ z-index: 1;
78
+ position: sticky;
79
+ top: 0;
80
+ left: 0;
81
+ background: var(--bg-color-highlited, #0265dc);
82
+ padding: var(--spacing-2, 16px);
83
+
84
+ .dte-pdf-field-next-controls-button:after {
85
+ display: none;
86
+ }
87
+ }
88
+
89
+ .dte-pdf-movable-next-button-wrapper {
90
+ top: 50px;
91
+ transform: translateX(-100%);
92
+ position: absolute;
93
+ z-index: 2;
94
+ }
95
+
96
+ @media (max-width: 1000px) {
97
+ .dte-pdf-movable-next-button-wrapper {
98
+ display: none;
99
+ }
100
+
101
+ .dte-pdf-zoom-controls {
102
+ display: none !important;
103
+ }
30
104
  }
31
105
 
32
- .dte-pdf-field-view.--eSign:focus {
33
- outline: 2px solid var(--border-color-active);
106
+ @media (min-width: 1001px) {
107
+ .dte-pdf-editor-theme > .dte-pdf-canvas-controls {
108
+ display: none;
109
+ }
34
110
  }
@@ -14,6 +14,7 @@
14
14
  min-width: 0;
15
15
  overflow: auto;
16
16
  overscroll-behavior: none;
17
+ touch-action: pan-x pan-y;
17
18
  background-color: var(--bg-color-main, #eeeeee);
18
19
  width: 100%;
19
20
 
@@ -5,10 +5,10 @@
5
5
  width: 100%;
6
6
  height: 100%;
7
7
  pointer-events: none;
8
- }
9
8
 
10
- .dte-pdf-field-overlay.--view-mode {
11
- pointer-events: auto;
9
+ &.--view-mode {
10
+ pointer-events: auto;
11
+ }
12
12
  }
13
13
 
14
14
  /* Editor-only chrome. Layout metrics come from getFieldBoundsStyle. */
@@ -17,33 +17,34 @@
17
17
  outline-offset: 0;
18
18
  border: none;
19
19
  pointer-events: auto;
20
- }
20
+ border-radius: 4px;
21
21
 
22
- .dte-pdf-field-editor.fillable-radio.--edit-mode {
23
- overflow: unset !important;
24
- }
22
+ &.--edit-mode {
23
+ overflow: unset !important;
24
+ }
25
25
 
26
- .dte-pdf-field-editor.--selected {
27
- outline: 2px solid var(--border-color-active);
28
- cursor: move;
29
- }
26
+ &.--selected {
27
+ outline: 2px solid var(--border-color-active);
28
+ cursor: move;
29
+ }
30
30
 
31
- .dte-pdf-field-editor.--unselected {
32
- cursor: pointer;
33
- }
31
+ &.--unselected {
32
+ cursor: pointer;
33
+ }
34
34
 
35
- .dte-pdf-field-editor.--dragging {
36
- opacity: 0.5;
37
- }
35
+ &.--dragging {
36
+ opacity: 0.5;
37
+ }
38
38
 
39
- .dte-pdf-field-editor.--colored:not(.--selected) {
40
- outline-color: var(--border-color-active) !important;
41
- box-shadow: 0 0 2px 0 var(--border-color-active);
42
- }
39
+ &.--colored:not(.--selected) {
40
+ outline-color: var(--border-color-active) !important;
41
+ box-shadow: 0 0 2px 0 var(--border-color-active);
42
+ }
43
43
 
44
- .dte-pdf-field-editor.--error {
45
- outline-color: var(--danger) !important;
46
- box-shadow: 0 0 4px 0 var(--danger);
44
+ &.--error {
45
+ outline-color: var(--danger) !important;
46
+ box-shadow: 0 0 4px 0 var(--danger);
47
+ }
47
48
  }
48
49
 
49
50
  .dte-pdf-field-error-message {
@@ -52,7 +53,26 @@
52
53
  position: absolute;
53
54
  margin-top: var(--spacing-half, 4px);
54
55
  color: var(--danger);
55
- font-size: var(--typescale-1, 12px);
56
+ font-size: var(--typescale-small, 10px);
57
+ }
58
+
59
+ .dte-pdf-field-label {
60
+ position: absolute;
61
+ display: flex;
62
+ align-items: center;
63
+ gap: var(--spacing-half, 4px);
64
+ background-color: var(--color-neutral-0, #ffffff);
65
+ border-radius: 4px;
66
+ padding: 1px var(--spacing-half, 4px);
67
+ top: -10px;
68
+ left: 3px;
69
+ font-size: var(--typescale-small, 10px);
70
+ line-height: 1;
71
+ white-space: nowrap;
72
+ color: var(--menu-active-color, #2270ee);
73
+ border-width: 1px;
74
+ border-style: solid;
75
+ border-color: inherit;
56
76
  }
57
77
 
58
78
  .dte-pdf-field-resize-handle {
@@ -65,10 +85,10 @@
65
85
  cursor: nwse-resize;
66
86
  z-index: 10;
67
87
  box-sizing: border-box;
68
- }
69
88
 
70
- .dte-pdf-field-resize-handle:hover {
71
- border-color: var(--border-color-active);
89
+ &:hover {
90
+ border-color: var(--border-color-active);
91
+ }
72
92
  }
73
93
 
74
94
  .dte-add-field-button {
@@ -80,10 +100,10 @@
80
100
  padding: var(--spacing-0, 0);
81
101
  width: 20px;
82
102
  height: 20px;
83
- }
84
103
 
85
- .dte-pdf-field-editor:hover .dte-add-field-button {
86
- display: block;
104
+ .dte-pdf-field-editor:hover & {
105
+ display: block;
106
+ }
87
107
  }
88
108
 
89
109
  .dte-pdf-field-view {
@@ -91,6 +111,17 @@
91
111
  outline: none;
92
112
  cursor: default;
93
113
  pointer-events: auto;
114
+
115
+ &.--fillable,
116
+ &.--eSign {
117
+ border-style: dashed;
118
+ border-width: 1px;
119
+ border-radius: 4px;
120
+
121
+ &:focus {
122
+ outline: 2px solid var(--border-color-active);
123
+ }
124
+ }
94
125
  }
95
126
 
96
127
  .dte-pdf-field-content {
@@ -99,15 +130,15 @@
99
130
  min-height: 0;
100
131
  overflow: hidden;
101
132
  line-height: 1;
102
- }
103
133
 
104
- .dte-pdf-field-content input[type='checkbox']:focus,
105
- .dte-pdf-field-content input[type='checkbox']:active,
106
- .dte-pdf-field-content input[type='radio']:active,
107
- .dte-pdf-field-content input[type='radio']:focus {
108
- box-shadow:
109
- 0 0 0 2px var(--border-color-active, #2270ee) inset,
110
- 0 0 0 3px var(--color-neutral-0, #ffffff) inset;
134
+ input[type='checkbox']:focus,
135
+ input[type='checkbox']:active,
136
+ input[type='radio']:active,
137
+ input[type='radio']:focus {
138
+ box-shadow:
139
+ 0 0 0 2px var(--border-color-active, #2270ee) inset,
140
+ 0 0 0 3px var(--color-neutral-0, #ffffff) inset;
141
+ }
111
142
  }
112
143
 
113
144
  /*
@@ -150,37 +181,37 @@
150
181
  min-width: 0;
151
182
  min-height: 0;
152
183
  box-sizing: border-box;
153
- background: inherit;
184
+ background: transparent;
154
185
  border: none;
155
186
  padding: var(--spacing-0);
156
187
  margin: var(--spacing-0);
157
188
  line-height: 1;
158
189
  font-size: inherit;
159
- }
160
190
 
161
- .dte-pdf-field-editor .dte-pdf-field-fillable {
162
- pointer-events: none;
163
- }
191
+ &.dte-pdf-field-text--single-line {
192
+ white-space: nowrap;
193
+ overflow: hidden;
194
+ }
164
195
 
165
- .dte-pdf-field-view .dte-pdf-field-fillable {
166
- pointer-events: auto;
167
- }
196
+ &.dte-pdf-field-text--multiline {
197
+ white-space: pre-wrap;
198
+ overflow-wrap: break-word;
199
+ overflow: hidden;
200
+ resize: none;
201
+ }
168
202
 
169
- .dte-pdf-field-fillable.dte-pdf-field-text--single-line {
170
- white-space: nowrap;
171
- overflow: hidden;
172
- }
203
+ &:focus {
204
+ outline: 2px solid var(--border-color-active, #2270ee);
205
+ outline-offset: 2px;
206
+ }
173
207
 
174
- .dte-pdf-field-fillable.dte-pdf-field-text--multiline {
175
- white-space: pre-wrap;
176
- overflow-wrap: break-word;
177
- overflow: hidden;
178
- resize: none;
179
- }
208
+ .dte-pdf-field-editor & {
209
+ pointer-events: none;
210
+ }
180
211
 
181
- .dte-pdf-field-fillable:focus {
182
- outline: 2px solid var(--border-color-active, #2270ee);
183
- outline-offset: 2px;
212
+ .dte-pdf-field-view & {
213
+ pointer-events: auto;
214
+ }
184
215
  }
185
216
 
186
217
  .dte-pdf-field-generic-table {
@@ -189,27 +220,27 @@
189
220
  border-spacing: var(--spacing-0, 0);
190
221
  width: 100%;
191
222
  table-layout: fixed;
192
- }
193
223
 
194
- .dte-pdf-field-generic-table td {
195
- border-top: 1px solid var(--border-color);
196
- border-left: 1px solid var(--border-color);
197
- padding-inline: var(--spacing-1, 8px);
198
- }
224
+ td {
225
+ border-top: 1px solid var(--border-color);
226
+ border-left: 1px solid var(--border-color);
227
+ padding-inline: var(--spacing-1, 8px);
228
+ }
199
229
 
200
- .dte-pdf-field-generic-table .dte-pdf-field-generic-table-header td {
201
- background-color: var(--bg-color);
202
- font-weight: bold;
203
- }
230
+ .dte-pdf-field-generic-table-header td {
231
+ background-color: var(--bg-color);
232
+ font-weight: bold;
233
+ }
204
234
 
205
- .dte-pdf-field-generic-table tr:not(.dte-pdf-field-generic-table-header) td {
206
- background-color: var(--bg-color-light);
207
- }
235
+ tr:not(.dte-pdf-field-generic-table-header) td {
236
+ background-color: var(--bg-color-light);
237
+ }
208
238
 
209
- .dte-pdf-field-generic-table tr:last-child td {
210
- border-bottom: 1px solid var(--border-color);
211
- }
239
+ tr:last-child td {
240
+ border-bottom: 1px solid var(--border-color);
241
+ }
212
242
 
213
- .dte-pdf-field-generic-table tr td:last-child {
214
- border-right: 1px solid var(--border-color);
243
+ tr td:last-child {
244
+ border-right: 1px solid var(--border-color);
245
+ }
215
246
  }
@@ -6,6 +6,7 @@
6
6
  --menu-hover-color: var(--color-neutral-100, #606162);
7
7
 
8
8
  /* Typography */
9
+ --typescale-small: 10px;
9
10
  --typescale-0: var(--typescale-1, 12px);
10
11
  --typescale-1: var(--typescale-1, 14px);
11
12
 
@@ -20,6 +21,7 @@
20
21
  --radius-0: 0;
21
22
  --radius-1: 4px;
22
23
  --radius-2: 8px;
24
+ --radius-3: 16px;
23
25
 
24
26
  /* Colors - Neutral */
25
27
  --color-neutral-0: var(--color-neutral-0, #ffffff);
@@ -31,6 +33,7 @@
31
33
  --color-blue-100: var(--color-blue-100, #fafcff);
32
34
 
33
35
  /* Background colors */
36
+ --bg-color-highlited: var(--color-blue-400);
34
37
  --bg-color-light: var(--color-neutral-0, #ffffff);
35
38
  --bg-color-main: var(--color-neutral-20, #fafafa);
36
39
  --bg-color-secondary: var(--color-neutral-50, #eeeeee);
@@ -0,0 +1,53 @@
1
+ import { E_SIGN_FIELD_TYPES, FILLABLE_FIELD_TYPES } from '../../../constants';
2
+ import { ESignFieldType, FieldTypeEnum, type PdfField } from '../../../interface/types';
3
+ import { getFieldTypeOption } from '../get-field-type-option.utils';
4
+
5
+ const buildField = (overrides: Partial<PdfField> = {}): PdfField => ({
6
+ id: 'field-1',
7
+ type: FieldTypeEnum.fillable,
8
+ subType: 'text',
9
+ x: 0,
10
+ y: 0,
11
+ page: 1,
12
+ label: 'Label',
13
+ width: 200,
14
+ height: 25,
15
+ ...overrides,
16
+ });
17
+
18
+ describe('getFieldTypeOption', () => {
19
+ const subject = (field: Pick<PdfField, 'type' | 'subType'>) => getFieldTypeOption(field);
20
+
21
+ test.each(
22
+ [...FILLABLE_FIELD_TYPES, ...E_SIGN_FIELD_TYPES].filter(
23
+ option => option.subType !== 'checkbox' && option.subType !== 'radio',
24
+ ),
25
+ )('returns $label for $type $subType', option => {
26
+ expect(subject(buildField({ type: option.type, subType: option.subType }))).toBe(option);
27
+ });
28
+
29
+ test.each(['checkbox', 'radio'] as const)('returns undefined for fillable %s', subType => {
30
+ expect(subject(buildField({ type: FieldTypeEnum.fillable, subType }))).toBeUndefined();
31
+ });
32
+
33
+ test.each([
34
+ FieldTypeEnum.calculated,
35
+ FieldTypeEnum.generic,
36
+ FieldTypeEnum.dataModel,
37
+ FieldTypeEnum.forms,
38
+ ])('returns undefined for %s fields', type => {
39
+ const subType = type === FieldTypeEnum.generic ? 'text' : undefined;
40
+ expect(subject(buildField({ type, subType }))).toBeUndefined();
41
+ });
42
+
43
+ test('returns undefined for unknown e-sign subtype', () => {
44
+ expect(
45
+ subject(
46
+ buildField({
47
+ type: FieldTypeEnum.eSign,
48
+ subType: 'unknown' as ESignFieldType,
49
+ }),
50
+ ),
51
+ ).toBeUndefined();
52
+ });
53
+ });
@@ -0,0 +1,16 @@
1
+ import { E_SIGN_FIELD_TYPES, FILLABLE_FIELD_TYPES } from '../../constants';
2
+ import { type PdfField } from '../../interface/types';
3
+
4
+ const HIDDEN_OVERLAY_LABEL_SUBTYPES = new Set(['checkbox', 'radio']);
5
+
6
+ const FIELD_TYPE_OPTIONS = [...FILLABLE_FIELD_TYPES, ...E_SIGN_FIELD_TYPES];
7
+
8
+ export const getFieldTypeOption = (field: Pick<PdfField, 'type' | 'subType'>) => {
9
+ if (field.subType && HIDDEN_OVERLAY_LABEL_SUBTYPES.has(field.subType)) {
10
+ return undefined;
11
+ }
12
+
13
+ return FIELD_TYPE_OPTIONS.find(
14
+ option => option.type === field.type && option.subType === field.subType,
15
+ );
16
+ };
@@ -1,7 +1,7 @@
1
1
  import { type DataModelValues, FieldTypeEnum, PdfField } from '../../interface/types';
2
2
  import { evaluateDisplayCondition } from '../conditions';
3
3
 
4
- const navigableFields = [FieldTypeEnum.fillable, FieldTypeEnum.eSign];
4
+ const navigableFields = [FieldTypeEnum.fillable];
5
5
 
6
6
  export const getNavigableFieldsUtils = (
7
7
  fields: PdfField[],
@@ -8,5 +8,6 @@ export * from './field-resize.utils';
8
8
  export * from './get-field-bounds-style.utils';
9
9
  export * from './get-field-font-size.utils';
10
10
  export * from './get-field-text-clip.utils';
11
+ export * from './get-field-type-option.utils';
11
12
  export * from './get-field-typography.utils';
12
13
  export * from './get-navigable-fields.utils';
@@ -0,0 +1,58 @@
1
+ import { ZOOM_MAX, ZOOM_MIN } from '../../../constants';
2
+ import {
3
+ clampZoom,
4
+ getPinchZoomValue,
5
+ getTouchDistance,
6
+ getWheelZoomFactor,
7
+ } from '../pinch-zoom.utils';
8
+
9
+ describe('clampZoom', () => {
10
+ const subject = (value: number) => clampZoom(value);
11
+
12
+ test('returns the value when inside the range', () => {
13
+ expect(subject(1)).toBe(1);
14
+ expect(subject(1.25)).toBe(1.25);
15
+ });
16
+
17
+ test('clamps to the minimum and maximum', () => {
18
+ expect(subject(ZOOM_MIN - 0.5)).toBe(ZOOM_MIN);
19
+ expect(subject(ZOOM_MAX + 0.5)).toBe(ZOOM_MAX);
20
+ });
21
+ });
22
+
23
+ describe('getWheelZoomFactor', () => {
24
+ const subject = (deltaY: number) => getWheelZoomFactor(deltaY);
25
+
26
+ test('zooms out for a positive delta', () => {
27
+ expect(subject(20)).toBeLessThan(1);
28
+ });
29
+
30
+ test('zooms in for a negative delta', () => {
31
+ expect(subject(-20)).toBeGreaterThan(1);
32
+ });
33
+ });
34
+
35
+ describe('getTouchDistance', () => {
36
+ const subject = (
37
+ first: Pick<Touch, 'clientX' | 'clientY'>,
38
+ second: Pick<Touch, 'clientX' | 'clientY'>,
39
+ ) => getTouchDistance(first, second);
40
+
41
+ test('returns the distance between two points', () => {
42
+ expect(subject({ clientX: 0, clientY: 0 }, { clientX: 3, clientY: 4 })).toBe(5);
43
+ });
44
+ });
45
+
46
+ describe('getPinchZoomValue', () => {
47
+ const subject = (startZoom: number, startDistance: number, currentDistance: number) =>
48
+ getPinchZoomValue(startZoom, startDistance, currentDistance);
49
+
50
+ test('scales zoom by the pinch distance ratio', () => {
51
+ expect(subject(1, 100, 150)).toBe(1.5);
52
+ expect(subject(1, 100, 50)).toBe(0.5);
53
+ });
54
+
55
+ test('returns the start zoom when the start distance is invalid', () => {
56
+ expect(subject(1.2, 0, 80)).toBe(1.2);
57
+ });
58
+ });
@@ -1,2 +1,3 @@
1
1
  export * from './pdf-rendering.utils';
2
+ export * from './pinch-zoom.utils';
2
3
  export * from './unit-conversion.utils';
@@ -0,0 +1,30 @@
1
+ import { ZOOM_MAX, ZOOM_MIN } from '../../constants';
2
+
3
+ export const WHEEL_ZOOM_SENSITIVITY = 0.01;
4
+
5
+ export const clampZoom = (value: number) => {
6
+ return Math.min(ZOOM_MAX, Math.max(ZOOM_MIN, Math.round(value * 100) / 100));
7
+ };
8
+
9
+ export const getWheelZoomFactor = (deltaY: number) => {
10
+ return Math.exp(-deltaY * WHEEL_ZOOM_SENSITIVITY);
11
+ };
12
+
13
+ export const getTouchDistance = (
14
+ first: Pick<Touch, 'clientX' | 'clientY'>,
15
+ second: Pick<Touch, 'clientX' | 'clientY'>,
16
+ ) => {
17
+ return Math.hypot(first.clientX - second.clientX, first.clientY - second.clientY);
18
+ };
19
+
20
+ export const getPinchZoomValue = (
21
+ startZoom: number,
22
+ startDistance: number,
23
+ currentDistance: number,
24
+ ) => {
25
+ if (startDistance <= 0) {
26
+ return startZoom;
27
+ }
28
+
29
+ return startZoom * (currentDistance / startDistance);
30
+ };