@embedpdf/plugin-form 2.10.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 (174) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.cjs +2 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.js +1789 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/lib/actions.d.ts +33 -0
  8. package/dist/lib/form-plugin.d.ts +59 -0
  9. package/dist/lib/handlers/checkbox.handler.d.ts +3 -0
  10. package/dist/lib/handlers/combobox.handler.d.ts +3 -0
  11. package/dist/lib/handlers/index.d.ts +5 -0
  12. package/dist/lib/handlers/listbox.handler.d.ts +3 -0
  13. package/dist/lib/handlers/radio-button.handler.d.ts +3 -0
  14. package/dist/lib/handlers/text-field.handler.d.ts +3 -0
  15. package/dist/lib/index.d.ts +10 -0
  16. package/dist/lib/manifest.d.ts +4 -0
  17. package/dist/lib/reducer.d.ts +6 -0
  18. package/dist/lib/tools.d.ts +457 -0
  19. package/dist/lib/types.d.ts +98 -0
  20. package/dist/preact/adapter.d.ts +13 -0
  21. package/dist/preact/annotation.d.ts +1 -0
  22. package/dist/preact/core.d.ts +1 -0
  23. package/dist/preact/index.cjs +2 -0
  24. package/dist/preact/index.cjs.map +1 -0
  25. package/dist/preact/index.d.ts +1 -0
  26. package/dist/preact/index.js +1359 -0
  27. package/dist/preact/index.js.map +1 -0
  28. package/dist/react/adapter.d.ts +6 -0
  29. package/dist/react/annotation.d.ts +1 -0
  30. package/dist/react/core.d.ts +1 -0
  31. package/dist/react/index.cjs +2 -0
  32. package/dist/react/index.cjs.map +1 -0
  33. package/dist/react/index.d.ts +1 -0
  34. package/dist/react/index.js +1358 -0
  35. package/dist/react/index.js.map +1 -0
  36. package/dist/shared/components/annotations/form-checkbox.d.ts +12 -0
  37. package/dist/shared/components/annotations/form-combobox.d.ts +12 -0
  38. package/dist/shared/components/annotations/form-listbox.d.ts +12 -0
  39. package/dist/shared/components/annotations/form-radio-button.d.ts +12 -0
  40. package/dist/shared/components/annotations/form-text-field.d.ts +12 -0
  41. package/dist/shared/components/fields/checkbox.d.ts +2 -0
  42. package/dist/shared/components/fields/combobox.d.ts +2 -0
  43. package/dist/shared/components/fields/listbox.d.ts +2 -0
  44. package/dist/shared/components/fields/push-button.d.ts +2 -0
  45. package/dist/shared/components/fields/radio-button.d.ts +2 -0
  46. package/dist/shared/components/fields/style.d.ts +6 -0
  47. package/dist/shared/components/fields/text.d.ts +2 -0
  48. package/dist/shared/components/fill-mode/combobox-fill-mode.d.ts +3 -0
  49. package/dist/shared/components/fill-mode/listbox-fill-mode.d.ts +3 -0
  50. package/dist/shared/components/fill-mode/push-button-fill-mode.d.ts +3 -0
  51. package/dist/shared/components/fill-mode/radio-button-fill-mode.d.ts +3 -0
  52. package/dist/shared/components/fill-mode/text-fill-mode.d.ts +3 -0
  53. package/dist/shared/components/fill-mode/toggle-fill-mode.d.ts +3 -0
  54. package/dist/shared/components/form-renderer-registration.d.ts +5 -0
  55. package/dist/shared/components/form-renderers.d.ts +9 -0
  56. package/dist/shared/components/index.d.ts +2 -0
  57. package/dist/shared/components/render-widget.d.ts +12 -0
  58. package/dist/shared/components/types.d.ts +42 -0
  59. package/dist/shared/hooks/index.d.ts +1 -0
  60. package/dist/shared/hooks/use-form-widget-state.d.ts +12 -0
  61. package/dist/shared/hooks/use-form.d.ts +16 -0
  62. package/dist/shared/index.d.ts +4 -0
  63. package/dist/shared-preact/components/annotations/form-checkbox.d.ts +12 -0
  64. package/dist/shared-preact/components/annotations/form-combobox.d.ts +12 -0
  65. package/dist/shared-preact/components/annotations/form-listbox.d.ts +12 -0
  66. package/dist/shared-preact/components/annotations/form-radio-button.d.ts +12 -0
  67. package/dist/shared-preact/components/annotations/form-text-field.d.ts +12 -0
  68. package/dist/shared-preact/components/fields/checkbox.d.ts +2 -0
  69. package/dist/shared-preact/components/fields/combobox.d.ts +2 -0
  70. package/dist/shared-preact/components/fields/listbox.d.ts +2 -0
  71. package/dist/shared-preact/components/fields/push-button.d.ts +2 -0
  72. package/dist/shared-preact/components/fields/radio-button.d.ts +2 -0
  73. package/dist/shared-preact/components/fields/style.d.ts +6 -0
  74. package/dist/shared-preact/components/fields/text.d.ts +2 -0
  75. package/dist/shared-preact/components/fill-mode/combobox-fill-mode.d.ts +3 -0
  76. package/dist/shared-preact/components/fill-mode/listbox-fill-mode.d.ts +3 -0
  77. package/dist/shared-preact/components/fill-mode/push-button-fill-mode.d.ts +3 -0
  78. package/dist/shared-preact/components/fill-mode/radio-button-fill-mode.d.ts +3 -0
  79. package/dist/shared-preact/components/fill-mode/text-fill-mode.d.ts +3 -0
  80. package/dist/shared-preact/components/fill-mode/toggle-fill-mode.d.ts +3 -0
  81. package/dist/shared-preact/components/form-renderer-registration.d.ts +5 -0
  82. package/dist/shared-preact/components/form-renderers.d.ts +9 -0
  83. package/dist/shared-preact/components/index.d.ts +2 -0
  84. package/dist/shared-preact/components/render-widget.d.ts +12 -0
  85. package/dist/shared-preact/components/types.d.ts +42 -0
  86. package/dist/shared-preact/hooks/index.d.ts +1 -0
  87. package/dist/shared-preact/hooks/use-form-widget-state.d.ts +12 -0
  88. package/dist/shared-preact/hooks/use-form.d.ts +16 -0
  89. package/dist/shared-preact/index.d.ts +4 -0
  90. package/dist/shared-react/components/annotations/form-checkbox.d.ts +12 -0
  91. package/dist/shared-react/components/annotations/form-combobox.d.ts +12 -0
  92. package/dist/shared-react/components/annotations/form-listbox.d.ts +12 -0
  93. package/dist/shared-react/components/annotations/form-radio-button.d.ts +12 -0
  94. package/dist/shared-react/components/annotations/form-text-field.d.ts +12 -0
  95. package/dist/shared-react/components/fields/checkbox.d.ts +2 -0
  96. package/dist/shared-react/components/fields/combobox.d.ts +2 -0
  97. package/dist/shared-react/components/fields/listbox.d.ts +2 -0
  98. package/dist/shared-react/components/fields/push-button.d.ts +2 -0
  99. package/dist/shared-react/components/fields/radio-button.d.ts +2 -0
  100. package/dist/shared-react/components/fields/style.d.ts +6 -0
  101. package/dist/shared-react/components/fields/text.d.ts +2 -0
  102. package/dist/shared-react/components/fill-mode/combobox-fill-mode.d.ts +3 -0
  103. package/dist/shared-react/components/fill-mode/listbox-fill-mode.d.ts +3 -0
  104. package/dist/shared-react/components/fill-mode/push-button-fill-mode.d.ts +3 -0
  105. package/dist/shared-react/components/fill-mode/radio-button-fill-mode.d.ts +3 -0
  106. package/dist/shared-react/components/fill-mode/text-fill-mode.d.ts +3 -0
  107. package/dist/shared-react/components/fill-mode/toggle-fill-mode.d.ts +3 -0
  108. package/dist/shared-react/components/form-renderer-registration.d.ts +5 -0
  109. package/dist/shared-react/components/form-renderers.d.ts +9 -0
  110. package/dist/shared-react/components/index.d.ts +2 -0
  111. package/dist/shared-react/components/render-widget.d.ts +12 -0
  112. package/dist/shared-react/components/types.d.ts +42 -0
  113. package/dist/shared-react/hooks/index.d.ts +1 -0
  114. package/dist/shared-react/hooks/use-form-widget-state.d.ts +12 -0
  115. package/dist/shared-react/hooks/use-form.d.ts +16 -0
  116. package/dist/shared-react/index.d.ts +4 -0
  117. package/dist/svelte/components/FormRendererRegistration.svelte.d.ts +18 -0
  118. package/dist/svelte/components/RenderWidget.svelte.d.ts +11 -0
  119. package/dist/svelte/components/annotations/FormCheckbox.svelte.d.ts +5 -0
  120. package/dist/svelte/components/annotations/FormCombobox.svelte.d.ts +5 -0
  121. package/dist/svelte/components/annotations/FormListbox.svelte.d.ts +5 -0
  122. package/dist/svelte/components/annotations/FormRadioButton.svelte.d.ts +5 -0
  123. package/dist/svelte/components/annotations/FormTextField.svelte.d.ts +5 -0
  124. package/dist/svelte/components/fields/ComboboxField.svelte.d.ts +4 -0
  125. package/dist/svelte/components/fields/ListboxField.svelte.d.ts +4 -0
  126. package/dist/svelte/components/fields/TextField.svelte.d.ts +4 -0
  127. package/dist/svelte/components/fill-mode/ComboboxFillMode.svelte.d.ts +5 -0
  128. package/dist/svelte/components/fill-mode/ListboxFillMode.svelte.d.ts +5 -0
  129. package/dist/svelte/components/fill-mode/RadioButtonFillMode.svelte.d.ts +5 -0
  130. package/dist/svelte/components/fill-mode/TextFillMode.svelte.d.ts +5 -0
  131. package/dist/svelte/components/fill-mode/ToggleFillMode.svelte.d.ts +5 -0
  132. package/dist/svelte/components/form-renderers.d.ts +9 -0
  133. package/dist/svelte/components/previews/CheckboxPreview.svelte.d.ts +9 -0
  134. package/dist/svelte/components/previews/ListboxPreview.svelte.d.ts +9 -0
  135. package/dist/svelte/components/previews/RadioButtonPreview.svelte.d.ts +9 -0
  136. package/dist/svelte/components/previews/TextFieldPreview.svelte.d.ts +9 -0
  137. package/dist/svelte/hooks/index.d.ts +2 -0
  138. package/dist/svelte/hooks/use-form-widget-state.svelte.d.ts +12 -0
  139. package/dist/svelte/hooks/use-form.svelte.d.ts +14 -0
  140. package/dist/svelte/index.cjs +2 -0
  141. package/dist/svelte/index.cjs.map +1 -0
  142. package/dist/svelte/index.d.ts +3 -0
  143. package/dist/svelte/index.js +1567 -0
  144. package/dist/svelte/index.js.map +1 -0
  145. package/dist/vue/components/annotations/form-checkbox.vue.d.ts +6 -0
  146. package/dist/vue/components/annotations/form-combobox.vue.d.ts +6 -0
  147. package/dist/vue/components/annotations/form-listbox.vue.d.ts +6 -0
  148. package/dist/vue/components/annotations/form-radio-button.vue.d.ts +6 -0
  149. package/dist/vue/components/annotations/form-text-field.vue.d.ts +6 -0
  150. package/dist/vue/components/fields/combobox-field.vue.d.ts +4 -0
  151. package/dist/vue/components/fields/listbox-field.vue.d.ts +4 -0
  152. package/dist/vue/components/fields/style.d.ts +6 -0
  153. package/dist/vue/components/fields/text-field.vue.d.ts +4 -0
  154. package/dist/vue/components/fill-mode/combobox-fill-mode.vue.d.ts +6 -0
  155. package/dist/vue/components/fill-mode/listbox-fill-mode.vue.d.ts +6 -0
  156. package/dist/vue/components/fill-mode/radio-button-fill-mode.vue.d.ts +6 -0
  157. package/dist/vue/components/fill-mode/text-fill-mode.vue.d.ts +6 -0
  158. package/dist/vue/components/fill-mode/toggle-fill-mode.vue.d.ts +6 -0
  159. package/dist/vue/components/form-renderer-registration.vue.d.ts +13 -0
  160. package/dist/vue/components/form-renderers.d.ts +3 -0
  161. package/dist/vue/components/previews/checkbox-preview.vue.d.ts +10 -0
  162. package/dist/vue/components/previews/listbox-preview.vue.d.ts +10 -0
  163. package/dist/vue/components/previews/radio-button-preview.vue.d.ts +10 -0
  164. package/dist/vue/components/previews/text-field-preview.vue.d.ts +10 -0
  165. package/dist/vue/components/render-widget.vue.d.ts +15 -0
  166. package/dist/vue/hooks/index.d.ts +2 -0
  167. package/dist/vue/hooks/use-form-widget-state.d.ts +12 -0
  168. package/dist/vue/hooks/use-form.d.ts +12 -0
  169. package/dist/vue/index.cjs +2 -0
  170. package/dist/vue/index.cjs.map +1 -0
  171. package/dist/vue/index.d.ts +3 -0
  172. package/dist/vue/index.js +1643 -0
  173. package/dist/vue/index.js.map +1 -0
  174. package/package.json +84 -0
@@ -0,0 +1,1358 @@
1
+ import { createPluginPackage } from "@embedpdf/core";
2
+ import { initialDocumentState, FormPlugin, FormPluginPackage as FormPluginPackage$1 } from "@embedpdf/plugin-form";
3
+ export * from "@embedpdf/plugin-form";
4
+ import { useIOSZoomPrevention, createRenderer, useRegisterRenderers } from "@embedpdf/plugin-annotation/react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { PDF_FORM_FIELD_TYPE, PDF_FORM_FIELD_FLAG, standardFontCssProperties, isWidgetChecked, ignore, PdfErrorCode, PdfAnnotationSubtype } from "@embedpdf/models";
7
+ import { useState, useEffect, useMemo, useCallback, useRef, Fragment } from "react";
8
+ import { useCapability, usePlugin } from "@embedpdf/core/react";
9
+ const selectProps = (isMultiple, selectedValues) => ({
10
+ value: isMultiple ? selectedValues : selectedValues[0] || ""
11
+ });
12
+ const optionProps = (isMultiple, selectedValues, optionValue) => ({
13
+ // React doesn't need any extra props for options in multi-select
14
+ });
15
+ function FormTextField({
16
+ annotation,
17
+ isSelected,
18
+ scale,
19
+ onClick,
20
+ style
21
+ }) {
22
+ const [isHovered, setIsHovered] = useState(false);
23
+ const { object } = annotation;
24
+ const field = object.field;
25
+ const isTextField = field.type === PDF_FORM_FIELD_TYPE.TEXTFIELD;
26
+ const value = isTextField ? field.value : "";
27
+ const isComb = isTextField && !!(field.flag & PDF_FORM_FIELD_FLAG.TEXT_COMB) && !!field.maxLen;
28
+ const isMultiline = isTextField && !!(field.flag & PDF_FORM_FIELD_FLAG.TEXT_MULTIPLINE);
29
+ const maxLen = isTextField ? field.maxLen : void 0;
30
+ const borderWidth = (object.strokeWidth ?? 1) * scale;
31
+ const fontStyle = {
32
+ fontSize: (object.fontSize ?? 12) * scale,
33
+ ...standardFontCssProperties(object.fontFamily),
34
+ color: object.fontColor ?? "#000000",
35
+ lineHeight: 1.2
36
+ };
37
+ return /* @__PURE__ */ jsx(
38
+ "div",
39
+ {
40
+ onPointerDown: !isSelected ? onClick : void 0,
41
+ onMouseEnter: () => setIsHovered(true),
42
+ onMouseLeave: () => setIsHovered(false),
43
+ style: {
44
+ position: "absolute",
45
+ inset: 0,
46
+ background: object.color ?? "rgba(255, 255, 255, 0.9)",
47
+ border: `${borderWidth}px solid ${object.strokeColor ?? "rgba(0, 0, 0, 0.2)"}`,
48
+ outline: isHovered || isSelected ? "1px solid rgba(66, 133, 244, 0.5)" : "none",
49
+ outlineOffset: -1,
50
+ boxSizing: "border-box",
51
+ pointerEvents: "auto",
52
+ cursor: isSelected ? "move" : "pointer",
53
+ display: "flex",
54
+ alignItems: isMultiline ? "flex-start" : "center",
55
+ overflow: "hidden",
56
+ ...!isComb ? { padding: `${borderWidth}px ${borderWidth}px` } : {},
57
+ ...style
58
+ },
59
+ children: isComb && maxLen ? /* @__PURE__ */ jsx(
60
+ CombPreview,
61
+ {
62
+ value: value ?? "",
63
+ maxLen,
64
+ scale,
65
+ width: object.rect.size.width,
66
+ fontStyle,
67
+ strokeColor: object.strokeColor ?? "rgba(0, 0, 0, 0.2)"
68
+ }
69
+ ) : /* @__PURE__ */ jsx(
70
+ "span",
71
+ {
72
+ style: {
73
+ ...fontStyle,
74
+ display: "block",
75
+ width: "100%",
76
+ whiteSpace: isMultiline ? "pre-wrap" : "nowrap",
77
+ wordBreak: isMultiline ? "break-word" : "normal",
78
+ overflowWrap: isMultiline ? "break-word" : "normal",
79
+ overflow: "hidden",
80
+ textOverflow: isMultiline ? "clip" : "ellipsis"
81
+ },
82
+ children: value
83
+ }
84
+ )
85
+ }
86
+ );
87
+ }
88
+ function CombPreview({
89
+ value,
90
+ maxLen,
91
+ scale,
92
+ width,
93
+ fontStyle,
94
+ strokeColor
95
+ }) {
96
+ const cellWidth = width * scale / maxLen;
97
+ const chars = value.split("");
98
+ return /* @__PURE__ */ jsx("div", { style: { position: "relative", width: "100%", height: "100%" }, children: Array.from({ length: maxLen }).map((_, i) => /* @__PURE__ */ jsx(
99
+ "span",
100
+ {
101
+ style: {
102
+ position: "absolute",
103
+ top: 0,
104
+ left: i * cellWidth,
105
+ width: cellWidth,
106
+ height: "100%",
107
+ display: "flex",
108
+ alignItems: "center",
109
+ justifyContent: "center",
110
+ borderRight: i < maxLen - 1 ? `1px solid ${strokeColor}` : "none",
111
+ boxSizing: "border-box",
112
+ ...fontStyle
113
+ },
114
+ children: chars[i] || ""
115
+ },
116
+ i
117
+ )) });
118
+ }
119
+ function FormCheckbox({ annotation, isSelected, scale, onClick, style }) {
120
+ const [isHovered, setIsHovered] = useState(false);
121
+ const { object } = annotation;
122
+ const isChecked = isWidgetChecked(object);
123
+ return /* @__PURE__ */ jsx(
124
+ "div",
125
+ {
126
+ onPointerDown: !isSelected ? onClick : void 0,
127
+ onMouseEnter: () => setIsHovered(true),
128
+ onMouseLeave: () => setIsHovered(false),
129
+ style: {
130
+ position: "absolute",
131
+ inset: 0,
132
+ background: object.color ?? "#FFFFFF",
133
+ border: `${(object.strokeWidth ?? 1) * scale}px solid ${object.strokeColor ?? "#000000"}`,
134
+ outline: isHovered || isSelected ? "1px solid rgba(66, 133, 244, 0.5)" : "none",
135
+ outlineOffset: -1,
136
+ boxSizing: "border-box",
137
+ pointerEvents: "auto",
138
+ cursor: isSelected ? "move" : "pointer",
139
+ display: "flex",
140
+ alignItems: "center",
141
+ justifyContent: "center",
142
+ ...style
143
+ },
144
+ children: isChecked && /* @__PURE__ */ jsx(
145
+ "svg",
146
+ {
147
+ viewBox: "0 0 100 100",
148
+ style: {
149
+ width: "100%",
150
+ height: "100%"
151
+ },
152
+ children: /* @__PURE__ */ jsx(
153
+ "path",
154
+ {
155
+ d: "M28 48C27.45 50.21 29.45 63.13 30 67C30.55 69.21 34.58 72 39 72C44.52 71.45 76.55 32.55 76 32C77.1 31.45 76 25 76 25C74.34 22.24 68 25.45 68 26C68 26 43.55 53 43 53C41.34 53 40.55 41.1 40 40C33.37 36.69 29.1 45.79 28 48Z",
156
+ fill: "#000000"
157
+ }
158
+ )
159
+ }
160
+ )
161
+ }
162
+ );
163
+ }
164
+ function FormRadioButton({
165
+ annotation,
166
+ isSelected,
167
+ scale,
168
+ onClick,
169
+ style
170
+ }) {
171
+ const [isHovered, setIsHovered] = useState(false);
172
+ const { object } = annotation;
173
+ const isChecked = isWidgetChecked(object);
174
+ return /* @__PURE__ */ jsx(
175
+ "div",
176
+ {
177
+ onPointerDown: !isSelected ? onClick : void 0,
178
+ onMouseEnter: () => setIsHovered(true),
179
+ onMouseLeave: () => setIsHovered(false),
180
+ style: {
181
+ position: "absolute",
182
+ inset: 0,
183
+ background: object.color ?? "#FFFFFF",
184
+ border: `${(object.strokeWidth ?? 1) * scale}px solid ${object.strokeColor ?? "#000000"}`,
185
+ borderRadius: "50%",
186
+ outline: isHovered || isSelected ? "1px solid rgba(66, 133, 244, 0.5)" : "none",
187
+ outlineOffset: -1,
188
+ boxSizing: "border-box",
189
+ pointerEvents: "auto",
190
+ cursor: isSelected ? "move" : "pointer",
191
+ display: "flex",
192
+ alignItems: "center",
193
+ justifyContent: "center",
194
+ ...style
195
+ },
196
+ children: isChecked && /* @__PURE__ */ jsx(
197
+ "div",
198
+ {
199
+ style: {
200
+ width: "50%",
201
+ height: "50%",
202
+ borderRadius: "50%",
203
+ background: "#000000"
204
+ }
205
+ }
206
+ )
207
+ }
208
+ );
209
+ }
210
+ function FormCombobox({ annotation, isSelected, scale, onClick, style }) {
211
+ var _a;
212
+ const [isHovered, setIsHovered] = useState(false);
213
+ const { object } = annotation;
214
+ const field = object.field;
215
+ const options = field.type === PDF_FORM_FIELD_TYPE.COMBOBOX ? field.options : [];
216
+ const selectedLabel = ((_a = options.find((o) => o.isSelected)) == null ? void 0 : _a.label) ?? "";
217
+ const borderWidth = (object.strokeWidth ?? 1) * scale;
218
+ const fontSize = (object.fontSize ?? 12) * scale;
219
+ return /* @__PURE__ */ jsxs(
220
+ "div",
221
+ {
222
+ onPointerDown: !isSelected ? onClick : void 0,
223
+ onMouseEnter: () => setIsHovered(true),
224
+ onMouseLeave: () => setIsHovered(false),
225
+ style: {
226
+ position: "absolute",
227
+ inset: 0,
228
+ background: object.color ?? "#FFFFFF",
229
+ border: `${borderWidth}px solid ${object.strokeColor ?? "#000000"}`,
230
+ outline: isHovered || isSelected ? "1px solid rgba(66, 133, 244, 0.5)" : "none",
231
+ outlineOffset: -1,
232
+ boxSizing: "border-box",
233
+ pointerEvents: "auto",
234
+ cursor: isSelected ? "move" : "pointer",
235
+ display: "flex",
236
+ alignItems: "center",
237
+ overflow: "hidden",
238
+ ...style
239
+ },
240
+ children: [
241
+ /* @__PURE__ */ jsx(
242
+ "span",
243
+ {
244
+ style: {
245
+ flex: 1,
246
+ padding: `0 ${4 * scale}px`,
247
+ fontSize,
248
+ ...standardFontCssProperties(object.fontFamily),
249
+ color: object.fontColor ?? "#000000",
250
+ whiteSpace: "nowrap",
251
+ overflow: "hidden",
252
+ textOverflow: "ellipsis"
253
+ },
254
+ children: selectedLabel
255
+ }
256
+ ),
257
+ /* @__PURE__ */ jsx(
258
+ "div",
259
+ {
260
+ style: {
261
+ width: 13 * scale,
262
+ minWidth: 13 * scale,
263
+ height: "100%",
264
+ display: "flex",
265
+ alignItems: "center",
266
+ justifyContent: "center",
267
+ borderLeft: `1px solid ${object.strokeColor ?? "#000000"}`
268
+ },
269
+ children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 10 6", style: { width: 8 * scale, height: 5 * scale }, fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M0 0 L5 6 L10 0 Z" }) })
270
+ }
271
+ )
272
+ ]
273
+ }
274
+ );
275
+ }
276
+ function FormListbox({ annotation, isSelected, scale, onClick, style }) {
277
+ const [isHovered, setIsHovered] = useState(false);
278
+ const { object } = annotation;
279
+ const field = object.field;
280
+ const options = field.type === PDF_FORM_FIELD_TYPE.LISTBOX ? field.options : [];
281
+ const borderWidth = (object.strokeWidth ?? 1) * scale;
282
+ const fontSize = (object.fontSize ?? 12) * scale;
283
+ const lineHeight = fontSize * 1.2;
284
+ return /* @__PURE__ */ jsx(
285
+ "div",
286
+ {
287
+ onPointerDown: !isSelected ? onClick : void 0,
288
+ onMouseEnter: () => setIsHovered(true),
289
+ onMouseLeave: () => setIsHovered(false),
290
+ style: {
291
+ position: "absolute",
292
+ inset: 0,
293
+ background: object.color ?? "#FFFFFF",
294
+ border: `${borderWidth}px solid ${object.strokeColor ?? "#000000"}`,
295
+ outline: isHovered || isSelected ? "1px solid rgba(66, 133, 244, 0.5)" : "none",
296
+ outlineOffset: -1,
297
+ boxSizing: "border-box",
298
+ pointerEvents: "auto",
299
+ cursor: isSelected ? "move" : "pointer",
300
+ overflow: "hidden",
301
+ display: "flex",
302
+ flexDirection: "column",
303
+ ...style
304
+ },
305
+ children: options.map((opt, i) => /* @__PURE__ */ jsx(
306
+ "div",
307
+ {
308
+ style: {
309
+ padding: `0 ${4 * scale}px`,
310
+ fontSize,
311
+ lineHeight: `${lineHeight}px`,
312
+ ...standardFontCssProperties(object.fontFamily),
313
+ color: opt.isSelected ? "#FFFFFF" : object.fontColor ?? "#000000",
314
+ background: opt.isSelected ? "rgba(0, 51, 113, 1)" : "transparent",
315
+ whiteSpace: "nowrap",
316
+ overflow: "hidden",
317
+ textOverflow: "ellipsis"
318
+ },
319
+ children: opt.label
320
+ },
321
+ i
322
+ ))
323
+ }
324
+ );
325
+ }
326
+ const useFormPlugin = () => usePlugin(FormPlugin.id);
327
+ const useFormCapability = () => useCapability(FormPlugin.id);
328
+ const useFormDocumentState = (documentId) => {
329
+ var _a;
330
+ const { provides } = useFormCapability();
331
+ const [state, setState] = useState(
332
+ ((_a = provides == null ? void 0 : provides.forDocument(documentId)) == null ? void 0 : _a.getState()) ?? { ...initialDocumentState }
333
+ );
334
+ useEffect(() => {
335
+ if (!provides) return;
336
+ const scope = provides.forDocument(documentId);
337
+ setState(scope.getState());
338
+ return scope.onStateChange((newState) => {
339
+ setState(newState);
340
+ });
341
+ }, [provides, documentId]);
342
+ return state;
343
+ };
344
+ function useFormWidgetState(props) {
345
+ const { currentObject: annotation, scale, pageIndex } = props;
346
+ const field = annotation.field;
347
+ const { provides: formProvides } = useFormCapability();
348
+ const [renderKey, setRenderKey] = useState(0);
349
+ const isReadOnly = !!(field.flag & PDF_FORM_FIELD_FLAG.READONLY);
350
+ const scope = useMemo(
351
+ () => formProvides == null ? void 0 : formProvides.forDocument(props.documentId),
352
+ [formProvides, props.documentId]
353
+ );
354
+ useEffect(() => {
355
+ if (!scope) return;
356
+ return scope.onFieldValueChange((event) => {
357
+ if (event.annotationId === annotation.id) {
358
+ setRenderKey((k) => k + 1);
359
+ }
360
+ });
361
+ }, [scope, annotation.id]);
362
+ const handleChangeField = useCallback(
363
+ (newField) => {
364
+ if (!scope) return;
365
+ scope.setFormFieldValues(pageIndex, annotation, newField);
366
+ },
367
+ [scope, pageIndex, annotation]
368
+ );
369
+ return { annotation, field, scale, pageIndex, scope, handleChangeField, renderKey, isReadOnly };
370
+ }
371
+ function RenderWidget({
372
+ pageIndex,
373
+ annotation,
374
+ scaleFactor = 1,
375
+ renderKey = 0,
376
+ style,
377
+ ...props
378
+ }) {
379
+ const { provides: formProvides } = useFormCapability();
380
+ const [imageUrl, setImageUrl] = useState(null);
381
+ const urlRef = useRef(null);
382
+ const { width, height } = annotation.rect.size;
383
+ useEffect(() => {
384
+ if (!formProvides) return;
385
+ const task = formProvides.renderWidget({
386
+ pageIndex,
387
+ annotation,
388
+ options: {
389
+ scaleFactor,
390
+ dpr: window.devicePixelRatio
391
+ }
392
+ });
393
+ task.wait((blob) => {
394
+ const url = URL.createObjectURL(blob);
395
+ if (urlRef.current) {
396
+ URL.revokeObjectURL(urlRef.current);
397
+ }
398
+ urlRef.current = url;
399
+ setImageUrl(url);
400
+ }, ignore);
401
+ return () => {
402
+ task.abort({
403
+ code: PdfErrorCode.Cancelled,
404
+ message: "canceled render task"
405
+ });
406
+ };
407
+ }, [pageIndex, scaleFactor, formProvides, annotation.id, width, height, renderKey]);
408
+ useEffect(() => {
409
+ return () => {
410
+ if (urlRef.current) {
411
+ URL.revokeObjectURL(urlRef.current);
412
+ urlRef.current = null;
413
+ }
414
+ };
415
+ }, []);
416
+ return /* @__PURE__ */ jsx(Fragment, { children: imageUrl && /* @__PURE__ */ jsx(
417
+ "img",
418
+ {
419
+ src: imageUrl,
420
+ ...props,
421
+ style: {
422
+ width: "100%",
423
+ height: "100%",
424
+ display: "block",
425
+ ...style || {}
426
+ }
427
+ }
428
+ ) });
429
+ }
430
+ const baseStyle = {
431
+ position: "absolute",
432
+ top: 0,
433
+ left: 0,
434
+ padding: 0,
435
+ margin: 0,
436
+ width: "100%",
437
+ height: "100%"
438
+ };
439
+ const baseInputStyle = {
440
+ ...baseStyle,
441
+ borderRadius: 0,
442
+ outline: "none",
443
+ boxSizing: "border-box"
444
+ };
445
+ const inputStyle = baseInputStyle;
446
+ const selectStyle = {
447
+ ...baseInputStyle,
448
+ cursor: "inherit"
449
+ };
450
+ const textareaStyle = {
451
+ ...baseInputStyle,
452
+ resize: "none",
453
+ lineHeight: 1.14
454
+ };
455
+ const combContainerStyle = {
456
+ position: "relative",
457
+ width: "100%",
458
+ height: "100%",
459
+ borderRadius: 0,
460
+ boxSizing: "border-box"
461
+ };
462
+ const combHiddenInputStyle = {
463
+ position: "absolute",
464
+ top: 0,
465
+ left: 0,
466
+ width: "100%",
467
+ height: "100%",
468
+ opacity: 0,
469
+ padding: 0,
470
+ margin: 0,
471
+ border: "none",
472
+ zIndex: 1
473
+ };
474
+ const combCellStyle = {
475
+ position: "absolute",
476
+ top: 0,
477
+ height: "100%",
478
+ display: "flex",
479
+ alignItems: "center",
480
+ justifyContent: "center",
481
+ pointerEvents: "none"
482
+ };
483
+ const combCaretStyle = {
484
+ position: "absolute",
485
+ top: "15%",
486
+ height: "70%",
487
+ width: 1,
488
+ backgroundColor: "black",
489
+ pointerEvents: "none"
490
+ };
491
+ function CombField(props) {
492
+ const {
493
+ inputRef,
494
+ required,
495
+ disabled,
496
+ password,
497
+ name,
498
+ value,
499
+ maxLen,
500
+ cellWidth,
501
+ chars,
502
+ caretIndex,
503
+ containerStyle,
504
+ cellFontStyle,
505
+ onFocus,
506
+ onChange,
507
+ onBlur
508
+ } = props;
509
+ const [caretVisible, setCaretVisible] = useState(true);
510
+ useEffect(() => {
511
+ setCaretVisible(true);
512
+ const id = setInterval(() => setCaretVisible((v) => !v), 530);
513
+ return () => clearInterval(id);
514
+ }, [caretIndex]);
515
+ const showCaret = caretIndex < maxLen;
516
+ return /* @__PURE__ */ jsxs("div", { style: containerStyle, children: [
517
+ /* @__PURE__ */ jsx(
518
+ "input",
519
+ {
520
+ ref: inputRef,
521
+ required,
522
+ disabled,
523
+ type: password ? "password" : "text",
524
+ name,
525
+ "aria-label": name,
526
+ value,
527
+ maxLength: maxLen,
528
+ onFocus,
529
+ onChange,
530
+ onBlur,
531
+ style: combHiddenInputStyle
532
+ }
533
+ ),
534
+ Array.from({ length: maxLen }).map((_, i) => /* @__PURE__ */ jsx(
535
+ "span",
536
+ {
537
+ style: {
538
+ ...combCellStyle,
539
+ ...cellFontStyle,
540
+ left: i * cellWidth,
541
+ width: cellWidth
542
+ },
543
+ children: chars[i] || ""
544
+ },
545
+ i
546
+ )),
547
+ showCaret && /* @__PURE__ */ jsx(
548
+ "span",
549
+ {
550
+ style: {
551
+ ...combCaretStyle,
552
+ left: caretIndex * cellWidth + cellWidth / 2,
553
+ opacity: caretVisible ? 1 : 0
554
+ }
555
+ }
556
+ )
557
+ ] });
558
+ }
559
+ function TextField(props) {
560
+ const {
561
+ annotation,
562
+ isEditable,
563
+ onChangeField,
564
+ onFocus,
565
+ onBlur,
566
+ inputRef,
567
+ scale,
568
+ syncExternalValue = true
569
+ } = props;
570
+ const field = annotation.field;
571
+ const { flag } = field;
572
+ const name = field.name;
573
+ const value = field.value;
574
+ const [localValue, setLocalValue] = useState(value);
575
+ useEffect(() => {
576
+ if (!syncExternalValue) return;
577
+ setLocalValue(value);
578
+ }, [value, syncExternalValue]);
579
+ const changeValue = useCallback(
580
+ (evt) => {
581
+ const newValue = evt.target.value;
582
+ setLocalValue(newValue);
583
+ onChangeField == null ? void 0 : onChangeField({ ...field, value: newValue });
584
+ },
585
+ [onChangeField, field]
586
+ );
587
+ const bw = (annotation.strokeWidth ?? 0) * scale;
588
+ const fontCss = standardFontCssProperties(annotation.fontFamily);
589
+ const { adjustedFontPx, wrapperStyle } = useIOSZoomPrevention(annotation.fontSize * scale, true);
590
+ const visualStyle = useMemo(
591
+ () => ({
592
+ backgroundColor: annotation.color ?? "transparent",
593
+ borderStyle: "solid",
594
+ borderColor: annotation.strokeColor ?? "transparent",
595
+ borderWidth: bw,
596
+ color: annotation.fontColor,
597
+ ...fontCss,
598
+ fontSize: adjustedFontPx,
599
+ padding: `${bw}px ${bw}px`
600
+ }),
601
+ [annotation.color, annotation.strokeColor, annotation.fontColor, adjustedFontPx, bw, fontCss]
602
+ );
603
+ const isDisabled = !isEditable || !!(flag & PDF_FORM_FIELD_FLAG.READONLY);
604
+ const isRequired = !!(flag & PDF_FORM_FIELD_FLAG.REQUIRED);
605
+ const isPassword = !!(flag & PDF_FORM_FIELD_FLAG.TEXT_PASSWORD);
606
+ const isMultipleLine = !!(flag & PDF_FORM_FIELD_FLAG.TEXT_MULTIPLINE);
607
+ const isComb = !!(flag & PDF_FORM_FIELD_FLAG.TEXT_COMB);
608
+ const maxLen = field.maxLen;
609
+ if (isComb && maxLen) {
610
+ const cellWidth = annotation.rect.size.width * scale / maxLen;
611
+ const chars = (localValue || "").split("");
612
+ const caretIndex = chars.length;
613
+ const combContainer = {
614
+ ...combContainerStyle,
615
+ backgroundColor: annotation.color ?? "transparent",
616
+ borderStyle: "solid",
617
+ borderColor: annotation.strokeColor ?? "transparent",
618
+ borderWidth: bw
619
+ };
620
+ const cellFont = {
621
+ color: annotation.fontColor,
622
+ ...fontCss,
623
+ fontSize: adjustedFontPx
624
+ };
625
+ const combContent = /* @__PURE__ */ jsx(
626
+ CombField,
627
+ {
628
+ inputRef,
629
+ required: isRequired,
630
+ disabled: isDisabled,
631
+ password: isPassword,
632
+ name,
633
+ value: localValue,
634
+ maxLen,
635
+ cellWidth,
636
+ chars,
637
+ caretIndex,
638
+ containerStyle: combContainer,
639
+ cellFontStyle: cellFont,
640
+ onFocus,
641
+ onChange: changeValue,
642
+ onBlur
643
+ }
644
+ );
645
+ return wrapperStyle ? /* @__PURE__ */ jsx("div", { style: wrapperStyle, children: combContent }) : combContent;
646
+ }
647
+ const inputContent = isMultipleLine ? /* @__PURE__ */ jsx(
648
+ "textarea",
649
+ {
650
+ ref: inputRef,
651
+ required: isRequired,
652
+ disabled: isDisabled,
653
+ name,
654
+ "aria-label": name,
655
+ value: localValue,
656
+ maxLength: maxLen,
657
+ onFocus,
658
+ onChange: changeValue,
659
+ onBlur,
660
+ style: { ...textareaStyle, ...visualStyle }
661
+ }
662
+ ) : /* @__PURE__ */ jsx(
663
+ "input",
664
+ {
665
+ ref: inputRef,
666
+ required: isRequired,
667
+ disabled: isDisabled,
668
+ type: isPassword ? "password" : "text",
669
+ name,
670
+ "aria-label": name,
671
+ value: localValue,
672
+ maxLength: maxLen,
673
+ onFocus,
674
+ onChange: changeValue,
675
+ onBlur,
676
+ style: { ...inputStyle, ...visualStyle }
677
+ }
678
+ );
679
+ return wrapperStyle ? /* @__PURE__ */ jsx("div", { style: wrapperStyle, children: inputContent }) : inputContent;
680
+ }
681
+ function TextFillMode(props) {
682
+ const { annotation, scale, pageIndex, scope, handleChangeField, renderKey, isReadOnly } = useFormWidgetState(props);
683
+ const formState = useFormDocumentState(props.documentId);
684
+ const [editing, setEditing] = useState(false);
685
+ const inputRef = useRef(null);
686
+ const isFocused = formState.selectedFieldId === annotation.id;
687
+ useEffect(() => {
688
+ if (isFocused && inputRef.current && document.activeElement !== inputRef.current) {
689
+ inputRef.current.focus();
690
+ }
691
+ }, [isFocused]);
692
+ const handleFocus = useCallback(() => {
693
+ if (isReadOnly) return;
694
+ scope == null ? void 0 : scope.selectField(annotation.id);
695
+ setEditing(true);
696
+ }, [isReadOnly, scope, annotation.id]);
697
+ const handleBlur = useCallback(() => {
698
+ setEditing(false);
699
+ if ((scope == null ? void 0 : scope.getSelectedFieldId()) === annotation.id) {
700
+ scope == null ? void 0 : scope.deselectField();
701
+ }
702
+ }, [scope, annotation.id]);
703
+ const handleInputRef = useCallback((el) => {
704
+ inputRef.current = el;
705
+ }, []);
706
+ return /* @__PURE__ */ jsxs(
707
+ "div",
708
+ {
709
+ style: {
710
+ width: "100%",
711
+ height: "100%",
712
+ overflow: "hidden",
713
+ position: "relative",
714
+ pointerEvents: "auto",
715
+ outline: "none"
716
+ },
717
+ children: [
718
+ /* @__PURE__ */ jsx(
719
+ RenderWidget,
720
+ {
721
+ pageIndex,
722
+ annotation,
723
+ scaleFactor: scale,
724
+ renderKey,
725
+ style: {
726
+ position: "absolute",
727
+ inset: 0,
728
+ pointerEvents: "none",
729
+ visibility: editing ? "hidden" : "visible"
730
+ }
731
+ }
732
+ ),
733
+ /* @__PURE__ */ jsx(
734
+ "div",
735
+ {
736
+ style: {
737
+ position: "absolute",
738
+ inset: 0,
739
+ zIndex: 1,
740
+ opacity: editing ? 1 : 0
741
+ },
742
+ children: /* @__PURE__ */ jsx(
743
+ TextField,
744
+ {
745
+ annotation,
746
+ scale,
747
+ pageIndex,
748
+ isEditable: true,
749
+ onChangeField: handleChangeField,
750
+ syncExternalValue: !editing,
751
+ onFocus: handleFocus,
752
+ onBlur: handleBlur,
753
+ inputRef: handleInputRef
754
+ }
755
+ )
756
+ }
757
+ )
758
+ ]
759
+ }
760
+ );
761
+ }
762
+ function ToggleFillMode(props) {
763
+ const { annotation, field, scale, pageIndex, scope, handleChangeField, renderKey, isReadOnly } = useFormWidgetState(props);
764
+ const formState = useFormDocumentState(props.documentId);
765
+ const wrapperRef = useRef(null);
766
+ const isFocused = formState.selectedFieldId === annotation.id;
767
+ useEffect(() => {
768
+ if (isFocused && wrapperRef.current && document.activeElement !== wrapperRef.current) {
769
+ wrapperRef.current.focus();
770
+ }
771
+ }, [isFocused]);
772
+ const toggle = useCallback(() => {
773
+ if (isReadOnly) return;
774
+ const checked = isWidgetChecked(annotation);
775
+ const newValue = checked ? "Off" : annotation.exportValue ?? "Yes";
776
+ handleChangeField({ ...field, value: newValue });
777
+ }, [isReadOnly, annotation, field, handleChangeField]);
778
+ const handleClick = useCallback(() => {
779
+ if (isReadOnly) return;
780
+ scope == null ? void 0 : scope.selectField(annotation.id);
781
+ toggle();
782
+ }, [isReadOnly, scope, annotation.id, toggle]);
783
+ const handleFocus = useCallback(() => {
784
+ if (isReadOnly) return;
785
+ scope == null ? void 0 : scope.selectField(annotation.id);
786
+ }, [isReadOnly, scope, annotation.id]);
787
+ const handleBlur = useCallback(() => {
788
+ if ((scope == null ? void 0 : scope.getSelectedFieldId()) === annotation.id) {
789
+ scope == null ? void 0 : scope.deselectField();
790
+ }
791
+ }, [scope, annotation.id]);
792
+ const handleKeyDown = useCallback(
793
+ (e) => {
794
+ if (e.key === " " || e.key === "Enter") {
795
+ e.preventDefault();
796
+ toggle();
797
+ }
798
+ },
799
+ [toggle]
800
+ );
801
+ return /* @__PURE__ */ jsx(
802
+ "div",
803
+ {
804
+ ref: wrapperRef,
805
+ tabIndex: isReadOnly ? -1 : 0,
806
+ onClick: handleClick,
807
+ onFocus: handleFocus,
808
+ onBlur: handleBlur,
809
+ onKeyDown: handleKeyDown,
810
+ style: {
811
+ width: "100%",
812
+ height: "100%",
813
+ overflow: "hidden",
814
+ cursor: isReadOnly ? "default" : "pointer",
815
+ pointerEvents: "auto",
816
+ outline: isFocused ? "2px solid rgba(66, 133, 244, 0.8)" : "none",
817
+ outlineOffset: -2
818
+ },
819
+ children: /* @__PURE__ */ jsx(
820
+ RenderWidget,
821
+ {
822
+ pageIndex,
823
+ annotation,
824
+ scaleFactor: scale,
825
+ renderKey,
826
+ style: { pointerEvents: "none" }
827
+ }
828
+ )
829
+ }
830
+ );
831
+ }
832
+ function RadioButtonFillMode(props) {
833
+ const { annotation, field, scale, pageIndex, scope, handleChangeField, renderKey, isReadOnly } = useFormWidgetState(props);
834
+ const formState = useFormDocumentState(props.documentId);
835
+ const wrapperRef = useRef(null);
836
+ const isFocused = formState.selectedFieldId === annotation.id;
837
+ useEffect(() => {
838
+ if (isFocused && wrapperRef.current && document.activeElement !== wrapperRef.current) {
839
+ wrapperRef.current.focus();
840
+ }
841
+ }, [isFocused]);
842
+ const selectRadio = useCallback(() => {
843
+ if (isReadOnly) return;
844
+ if (!isWidgetChecked(annotation) && annotation.exportValue) {
845
+ handleChangeField({ ...field, value: annotation.exportValue });
846
+ }
847
+ }, [isReadOnly, annotation, field, handleChangeField]);
848
+ const handleClick = useCallback(() => {
849
+ if (isReadOnly) return;
850
+ scope == null ? void 0 : scope.selectField(annotation.id);
851
+ selectRadio();
852
+ }, [isReadOnly, scope, annotation.id, selectRadio]);
853
+ const handleFocus = useCallback(() => {
854
+ if (isReadOnly) return;
855
+ scope == null ? void 0 : scope.selectField(annotation.id);
856
+ }, [isReadOnly, scope, annotation.id]);
857
+ const handleBlur = useCallback(() => {
858
+ if ((scope == null ? void 0 : scope.getSelectedFieldId()) === annotation.id) {
859
+ scope == null ? void 0 : scope.deselectField();
860
+ }
861
+ }, [scope, annotation.id]);
862
+ const handleKeyDown = useCallback(
863
+ (e) => {
864
+ if (e.key === " " || e.key === "Enter") {
865
+ e.preventDefault();
866
+ selectRadio();
867
+ }
868
+ },
869
+ [selectRadio]
870
+ );
871
+ return /* @__PURE__ */ jsx(
872
+ "div",
873
+ {
874
+ ref: wrapperRef,
875
+ tabIndex: isReadOnly ? -1 : 0,
876
+ onClick: handleClick,
877
+ onFocus: handleFocus,
878
+ onBlur: handleBlur,
879
+ onKeyDown: handleKeyDown,
880
+ style: {
881
+ width: "100%",
882
+ height: "100%",
883
+ overflow: "hidden",
884
+ cursor: isReadOnly ? "default" : "pointer",
885
+ pointerEvents: "auto",
886
+ outline: isFocused ? "2px solid rgba(66, 133, 244, 0.8)" : "none",
887
+ outlineOffset: -2
888
+ },
889
+ children: /* @__PURE__ */ jsx(
890
+ RenderWidget,
891
+ {
892
+ pageIndex,
893
+ annotation,
894
+ scaleFactor: scale,
895
+ renderKey,
896
+ style: { pointerEvents: "none" }
897
+ }
898
+ )
899
+ }
900
+ );
901
+ }
902
+ function ComboboxField(props) {
903
+ const { annotation, isEditable, onChangeField, onBlur, inputRef } = props;
904
+ const field = annotation.field;
905
+ const { flag, options } = field;
906
+ const name = field.alternateName || field.name;
907
+ const isDisabled = !isEditable || !!(flag & PDF_FORM_FIELD_FLAG.READONLY);
908
+ const isRequired = !!(flag & PDF_FORM_FIELD_FLAG.REQUIRED);
909
+ const handleChange = useCallback(
910
+ (evt) => {
911
+ const select = evt.target;
912
+ const updatedOptions = options.map((opt, i) => ({
913
+ ...opt,
914
+ isSelected: i === select.selectedIndex
915
+ }));
916
+ onChangeField == null ? void 0 : onChangeField({ ...field, options: updatedOptions });
917
+ },
918
+ [onChangeField, field, options]
919
+ );
920
+ const selectedTexts = options.filter((opt) => opt.isSelected).map((opt) => opt.label);
921
+ return /* @__PURE__ */ jsx(
922
+ "select",
923
+ {
924
+ ref: inputRef,
925
+ required: isRequired,
926
+ disabled: isDisabled,
927
+ name,
928
+ "aria-label": name,
929
+ ...selectProps(false, selectedTexts),
930
+ onChange: handleChange,
931
+ onBlur,
932
+ style: { ...selectStyle, opacity: 0 },
933
+ children: options.map((option, index) => {
934
+ return /* @__PURE__ */ jsx(
935
+ "option",
936
+ {
937
+ value: option.label,
938
+ ...optionProps(false, selectedTexts, option.label),
939
+ children: option.label
940
+ },
941
+ index
942
+ );
943
+ })
944
+ }
945
+ );
946
+ }
947
+ function ComboboxFillMode(props) {
948
+ const { annotation, scale, pageIndex, scope, handleChangeField, renderKey, isReadOnly } = useFormWidgetState(props);
949
+ const formState = useFormDocumentState(props.documentId);
950
+ const wrapperRef = useRef(null);
951
+ const selectElRef = useRef(null);
952
+ const isFocused = formState.selectedFieldId === annotation.id;
953
+ useEffect(() => {
954
+ if (isFocused && wrapperRef.current && !wrapperRef.current.contains(document.activeElement)) {
955
+ (selectElRef.current ?? wrapperRef.current).focus();
956
+ }
957
+ }, [isFocused]);
958
+ const handleFocus = useCallback(() => {
959
+ scope == null ? void 0 : scope.selectField(annotation.id);
960
+ }, [scope, annotation.id]);
961
+ const handleBlur = useCallback(() => {
962
+ requestAnimationFrame(() => {
963
+ var _a;
964
+ if ((_a = wrapperRef.current) == null ? void 0 : _a.contains(document.activeElement)) return;
965
+ if ((scope == null ? void 0 : scope.getSelectedFieldId()) === annotation.id) {
966
+ scope == null ? void 0 : scope.deselectField();
967
+ }
968
+ });
969
+ }, [scope, annotation.id]);
970
+ const selectInputRef = useCallback((el) => {
971
+ selectElRef.current = el;
972
+ }, []);
973
+ return /* @__PURE__ */ jsxs(
974
+ "div",
975
+ {
976
+ ref: wrapperRef,
977
+ onFocus: handleFocus,
978
+ onBlur: handleBlur,
979
+ style: {
980
+ width: "100%",
981
+ height: "100%",
982
+ overflow: "hidden",
983
+ cursor: isReadOnly ? "default" : "pointer",
984
+ pointerEvents: "auto",
985
+ outline: isFocused ? "2px solid rgba(66, 133, 244, 0.8)" : "none",
986
+ outlineOffset: -2
987
+ },
988
+ children: [
989
+ /* @__PURE__ */ jsx(
990
+ RenderWidget,
991
+ {
992
+ pageIndex,
993
+ annotation,
994
+ scaleFactor: scale,
995
+ renderKey,
996
+ style: { pointerEvents: "none" }
997
+ }
998
+ ),
999
+ /* @__PURE__ */ jsx(
1000
+ ComboboxField,
1001
+ {
1002
+ annotation,
1003
+ scale,
1004
+ pageIndex,
1005
+ isEditable: true,
1006
+ onChangeField: handleChangeField,
1007
+ inputRef: selectInputRef
1008
+ }
1009
+ )
1010
+ ]
1011
+ }
1012
+ );
1013
+ }
1014
+ function ListboxField(props) {
1015
+ const { annotation, isEditable, onChangeField, onBlur, inputRef, scale } = props;
1016
+ const field = annotation.field;
1017
+ const { flag, options } = field;
1018
+ const isDisabled = !isEditable || !!(flag & PDF_FORM_FIELD_FLAG.READONLY);
1019
+ const isMultipleChoice = !!(flag & PDF_FORM_FIELD_FLAG.CHOICE_MULTL_SELECT);
1020
+ const bw = (annotation.strokeWidth ?? 0) * scale;
1021
+ const fontSize = (annotation.fontSize ?? 12) * scale;
1022
+ const lineHeight = fontSize * 1.2;
1023
+ const fontCss = standardFontCssProperties(annotation.fontFamily);
1024
+ const containerStyle = useMemo(
1025
+ () => ({
1026
+ position: "absolute",
1027
+ top: 0,
1028
+ left: 0,
1029
+ width: "100%",
1030
+ height: "100%",
1031
+ background: annotation.color ?? "#FFFFFF",
1032
+ borderStyle: "solid",
1033
+ borderColor: annotation.strokeColor ?? "#000000",
1034
+ borderWidth: bw,
1035
+ boxSizing: "border-box",
1036
+ overflow: "auto",
1037
+ display: "flex",
1038
+ flexDirection: "column",
1039
+ outline: "none"
1040
+ }),
1041
+ [annotation.color, annotation.strokeColor, bw]
1042
+ );
1043
+ const handleOptionClick = useCallback(
1044
+ (clickedIndex) => {
1045
+ if (isDisabled) return;
1046
+ const updatedOptions = options.map((opt, i) => ({
1047
+ ...opt,
1048
+ isSelected: isMultipleChoice ? i === clickedIndex ? !opt.isSelected : opt.isSelected : i === clickedIndex
1049
+ }));
1050
+ onChangeField == null ? void 0 : onChangeField({ ...field, options: updatedOptions });
1051
+ },
1052
+ [isDisabled, isMultipleChoice, options, field, onChangeField]
1053
+ );
1054
+ return /* @__PURE__ */ jsx(
1055
+ "div",
1056
+ {
1057
+ ref: inputRef,
1058
+ onBlur,
1059
+ style: containerStyle,
1060
+ children: options.map((opt, i) => /* @__PURE__ */ jsx(
1061
+ "div",
1062
+ {
1063
+ onClick: () => handleOptionClick(i),
1064
+ style: {
1065
+ padding: `0 ${4 * scale}px`,
1066
+ fontSize,
1067
+ lineHeight: `${lineHeight}px`,
1068
+ ...fontCss,
1069
+ color: opt.isSelected ? "#FFFFFF" : annotation.fontColor ?? "#000000",
1070
+ background: opt.isSelected ? "rgba(0, 51, 113, 1)" : "transparent",
1071
+ whiteSpace: "nowrap",
1072
+ overflow: "hidden",
1073
+ textOverflow: "ellipsis",
1074
+ cursor: isDisabled ? "default" : "pointer"
1075
+ },
1076
+ children: opt.label
1077
+ },
1078
+ i
1079
+ ))
1080
+ }
1081
+ );
1082
+ }
1083
+ function ListboxFillMode(props) {
1084
+ const { annotation, scale, pageIndex, scope, handleChangeField, renderKey, isReadOnly } = useFormWidgetState(props);
1085
+ const formState = useFormDocumentState(props.documentId);
1086
+ const [editing, setEditing] = useState(false);
1087
+ const wrapperRef = useRef(null);
1088
+ const isFocused = formState.selectedFieldId === annotation.id;
1089
+ useEffect(() => {
1090
+ if (isFocused && wrapperRef.current && !wrapperRef.current.contains(document.activeElement)) {
1091
+ wrapperRef.current.focus();
1092
+ }
1093
+ }, [isFocused]);
1094
+ const handleFocus = useCallback(() => {
1095
+ if (isReadOnly) return;
1096
+ scope == null ? void 0 : scope.selectField(annotation.id);
1097
+ setEditing(true);
1098
+ }, [isReadOnly, scope, annotation.id]);
1099
+ const handleBlur = useCallback(() => {
1100
+ requestAnimationFrame(() => {
1101
+ var _a;
1102
+ if ((_a = wrapperRef.current) == null ? void 0 : _a.contains(document.activeElement)) return;
1103
+ setEditing(false);
1104
+ if ((scope == null ? void 0 : scope.getSelectedFieldId()) === annotation.id) {
1105
+ scope == null ? void 0 : scope.deselectField();
1106
+ }
1107
+ });
1108
+ }, [scope, annotation.id]);
1109
+ return /* @__PURE__ */ jsxs(
1110
+ "div",
1111
+ {
1112
+ ref: wrapperRef,
1113
+ tabIndex: isReadOnly ? -1 : 0,
1114
+ onFocus: handleFocus,
1115
+ onBlur: handleBlur,
1116
+ style: {
1117
+ width: "100%",
1118
+ height: "100%",
1119
+ overflow: "hidden",
1120
+ cursor: isReadOnly ? "default" : "pointer",
1121
+ pointerEvents: "auto",
1122
+ outline: isFocused && !editing ? "2px solid rgba(66, 133, 244, 0.8)" : "none",
1123
+ outlineOffset: -2
1124
+ },
1125
+ children: [
1126
+ /* @__PURE__ */ jsx(
1127
+ ListboxField,
1128
+ {
1129
+ annotation,
1130
+ scale,
1131
+ pageIndex,
1132
+ isEditable: true,
1133
+ onChangeField: handleChangeField
1134
+ }
1135
+ ),
1136
+ !editing && /* @__PURE__ */ jsx(
1137
+ RenderWidget,
1138
+ {
1139
+ pageIndex,
1140
+ annotation,
1141
+ scaleFactor: scale,
1142
+ renderKey,
1143
+ style: { pointerEvents: "none" }
1144
+ }
1145
+ )
1146
+ ]
1147
+ }
1148
+ );
1149
+ }
1150
+ const formRenderers = [
1151
+ createRenderer({
1152
+ id: "formTextField",
1153
+ matches: (a) => {
1154
+ var _a;
1155
+ return a.type === PdfAnnotationSubtype.WIDGET && ((_a = a.field) == null ? void 0 : _a.type) === PDF_FORM_FIELD_TYPE.TEXTFIELD;
1156
+ },
1157
+ render: ({ annotation, isSelected, scale, pageIndex, onClick }) => /* @__PURE__ */ jsx(
1158
+ FormTextField,
1159
+ {
1160
+ annotation,
1161
+ isSelected,
1162
+ scale,
1163
+ pageIndex,
1164
+ onClick
1165
+ }
1166
+ ),
1167
+ renderPreview: ({ bounds, scale }) => /* @__PURE__ */ jsx(
1168
+ "div",
1169
+ {
1170
+ style: {
1171
+ position: "absolute",
1172
+ left: 0,
1173
+ top: 0,
1174
+ width: bounds.size.width * scale,
1175
+ height: bounds.size.height * scale,
1176
+ border: "1px dashed rgba(66, 133, 244, 0.6)",
1177
+ backgroundColor: "rgba(255, 255, 255, 0.9)",
1178
+ boxSizing: "border-box",
1179
+ display: "flex",
1180
+ alignItems: "center",
1181
+ padding: `0 ${2 * scale}px`,
1182
+ overflow: "hidden"
1183
+ }
1184
+ }
1185
+ ),
1186
+ interactionDefaults: { isDraggable: false, isResizable: true, isRotatable: false },
1187
+ useAppearanceStream: false,
1188
+ renderLocked: (props) => /* @__PURE__ */ jsx(TextFillMode, { ...props })
1189
+ }),
1190
+ createRenderer({
1191
+ id: "formCheckbox",
1192
+ matches: (a) => {
1193
+ var _a;
1194
+ return a.type === PdfAnnotationSubtype.WIDGET && ((_a = a.field) == null ? void 0 : _a.type) === PDF_FORM_FIELD_TYPE.CHECKBOX;
1195
+ },
1196
+ render: ({ annotation, isSelected, scale, pageIndex, onClick }) => /* @__PURE__ */ jsx(
1197
+ FormCheckbox,
1198
+ {
1199
+ annotation,
1200
+ isSelected,
1201
+ scale,
1202
+ pageIndex,
1203
+ onClick
1204
+ }
1205
+ ),
1206
+ renderPreview: ({ bounds, scale }) => /* @__PURE__ */ jsx(
1207
+ "div",
1208
+ {
1209
+ style: {
1210
+ position: "absolute",
1211
+ left: 0,
1212
+ top: 0,
1213
+ width: bounds.size.width * scale,
1214
+ height: bounds.size.height * scale,
1215
+ border: "1px dashed rgba(66, 133, 244, 0.6)",
1216
+ backgroundColor: "rgba(255, 255, 255, 0.9)",
1217
+ boxSizing: "border-box",
1218
+ display: "flex",
1219
+ alignItems: "center",
1220
+ justifyContent: "center"
1221
+ }
1222
+ }
1223
+ ),
1224
+ interactionDefaults: { isDraggable: false, isResizable: true, isRotatable: false },
1225
+ useAppearanceStream: false,
1226
+ renderLocked: (props) => /* @__PURE__ */ jsx(ToggleFillMode, { ...props })
1227
+ }),
1228
+ createRenderer({
1229
+ id: "formRadioButton",
1230
+ matches: (a) => {
1231
+ var _a;
1232
+ return a.type === PdfAnnotationSubtype.WIDGET && ((_a = a.field) == null ? void 0 : _a.type) === PDF_FORM_FIELD_TYPE.RADIOBUTTON;
1233
+ },
1234
+ render: ({ annotation, isSelected, scale, pageIndex, onClick }) => /* @__PURE__ */ jsx(
1235
+ FormRadioButton,
1236
+ {
1237
+ annotation,
1238
+ isSelected,
1239
+ scale,
1240
+ pageIndex,
1241
+ onClick
1242
+ }
1243
+ ),
1244
+ renderPreview: ({ bounds, scale }) => /* @__PURE__ */ jsx(
1245
+ "div",
1246
+ {
1247
+ style: {
1248
+ position: "absolute",
1249
+ left: 0,
1250
+ top: 0,
1251
+ width: bounds.size.width * scale,
1252
+ height: bounds.size.height * scale,
1253
+ border: "1px dashed rgba(66, 133, 244, 0.6)",
1254
+ backgroundColor: "rgba(255, 255, 255, 0.9)",
1255
+ borderRadius: "50%",
1256
+ boxSizing: "border-box",
1257
+ display: "flex",
1258
+ alignItems: "center",
1259
+ justifyContent: "center"
1260
+ }
1261
+ }
1262
+ ),
1263
+ interactionDefaults: { isDraggable: false, isResizable: true, isRotatable: false },
1264
+ useAppearanceStream: false,
1265
+ renderLocked: (props) => /* @__PURE__ */ jsx(RadioButtonFillMode, { ...props })
1266
+ }),
1267
+ createRenderer({
1268
+ id: "formCombobox",
1269
+ matches: (a) => {
1270
+ var _a;
1271
+ return a.type === PdfAnnotationSubtype.WIDGET && ((_a = a.field) == null ? void 0 : _a.type) === PDF_FORM_FIELD_TYPE.COMBOBOX;
1272
+ },
1273
+ render: ({ annotation, isSelected, scale, pageIndex, onClick }) => /* @__PURE__ */ jsx(
1274
+ FormCombobox,
1275
+ {
1276
+ annotation,
1277
+ isSelected,
1278
+ scale,
1279
+ pageIndex,
1280
+ onClick
1281
+ }
1282
+ ),
1283
+ renderPreview: ({ bounds, scale }) => /* @__PURE__ */ jsx(
1284
+ "div",
1285
+ {
1286
+ style: {
1287
+ position: "absolute",
1288
+ left: 0,
1289
+ top: 0,
1290
+ width: bounds.size.width * scale,
1291
+ height: bounds.size.height * scale,
1292
+ border: "1px dashed rgba(66, 133, 244, 0.6)",
1293
+ backgroundColor: "rgba(255, 255, 255, 0.9)",
1294
+ boxSizing: "border-box",
1295
+ display: "flex",
1296
+ alignItems: "center",
1297
+ padding: `0 ${2 * scale}px`,
1298
+ overflow: "hidden"
1299
+ }
1300
+ }
1301
+ ),
1302
+ interactionDefaults: { isDraggable: false, isResizable: true, isRotatable: false },
1303
+ useAppearanceStream: false,
1304
+ renderLocked: (props) => /* @__PURE__ */ jsx(ComboboxFillMode, { ...props })
1305
+ }),
1306
+ createRenderer({
1307
+ id: "formListbox",
1308
+ matches: (a) => {
1309
+ var _a;
1310
+ return a.type === PdfAnnotationSubtype.WIDGET && ((_a = a.field) == null ? void 0 : _a.type) === PDF_FORM_FIELD_TYPE.LISTBOX;
1311
+ },
1312
+ render: ({ annotation, isSelected, scale, pageIndex, onClick }) => /* @__PURE__ */ jsx(
1313
+ FormListbox,
1314
+ {
1315
+ annotation,
1316
+ isSelected,
1317
+ scale,
1318
+ pageIndex,
1319
+ onClick
1320
+ }
1321
+ ),
1322
+ renderPreview: ({ bounds, scale }) => /* @__PURE__ */ jsx(
1323
+ "div",
1324
+ {
1325
+ style: {
1326
+ position: "absolute",
1327
+ left: 0,
1328
+ top: 0,
1329
+ width: bounds.size.width * scale,
1330
+ height: bounds.size.height * scale,
1331
+ border: "1px dashed rgba(66, 133, 244, 0.6)",
1332
+ backgroundColor: "rgba(255, 255, 255, 0.9)",
1333
+ boxSizing: "border-box",
1334
+ display: "flex",
1335
+ flexDirection: "column",
1336
+ overflow: "hidden"
1337
+ }
1338
+ }
1339
+ ),
1340
+ interactionDefaults: { isDraggable: false, isResizable: true, isRotatable: false },
1341
+ useAppearanceStream: false,
1342
+ renderLocked: (props) => /* @__PURE__ */ jsx(ListboxFillMode, { ...props })
1343
+ })
1344
+ ];
1345
+ function FormRendererRegistration() {
1346
+ useRegisterRenderers(formRenderers);
1347
+ return null;
1348
+ }
1349
+ const FormPluginPackage = createPluginPackage(FormPluginPackage$1).addUtility(FormRendererRegistration).build();
1350
+ export {
1351
+ FormPluginPackage,
1352
+ FormRendererRegistration,
1353
+ formRenderers,
1354
+ useFormCapability,
1355
+ useFormDocumentState,
1356
+ useFormPlugin
1357
+ };
1358
+ //# sourceMappingURL=index.js.map