@embedpdf/plugin-form 2.15.0 → 3.0.0-next.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 (175) hide show
  1. package/LICENSE +192 -21
  2. package/dist/index.cjs +1416 -2
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +277 -0
  5. package/dist/index.d.ts +277 -1
  6. package/dist/index.js +1398 -1779
  7. package/dist/index.js.map +1 -1
  8. package/package.json +24 -61
  9. package/dist/lib/actions.d.ts +0 -33
  10. package/dist/lib/form-plugin.d.ts +0 -59
  11. package/dist/lib/handlers/checkbox.handler.d.ts +0 -3
  12. package/dist/lib/handlers/combobox.handler.d.ts +0 -3
  13. package/dist/lib/handlers/index.d.ts +0 -5
  14. package/dist/lib/handlers/listbox.handler.d.ts +0 -3
  15. package/dist/lib/handlers/radio-button.handler.d.ts +0 -3
  16. package/dist/lib/handlers/text-field.handler.d.ts +0 -3
  17. package/dist/lib/index.d.ts +0 -10
  18. package/dist/lib/manifest.d.ts +0 -4
  19. package/dist/lib/reducer.d.ts +0 -6
  20. package/dist/lib/tools.d.ts +0 -457
  21. package/dist/lib/types.d.ts +0 -98
  22. package/dist/preact/adapter.d.ts +0 -13
  23. package/dist/preact/annotation.d.ts +0 -1
  24. package/dist/preact/core.d.ts +0 -1
  25. package/dist/preact/index.cjs +0 -2
  26. package/dist/preact/index.cjs.map +0 -1
  27. package/dist/preact/index.d.ts +0 -1
  28. package/dist/preact/index.js +0 -1359
  29. package/dist/preact/index.js.map +0 -1
  30. package/dist/react/adapter.d.ts +0 -6
  31. package/dist/react/annotation.d.ts +0 -1
  32. package/dist/react/core.d.ts +0 -1
  33. package/dist/react/index.cjs +0 -2
  34. package/dist/react/index.cjs.map +0 -1
  35. package/dist/react/index.d.ts +0 -1
  36. package/dist/react/index.js +0 -1358
  37. package/dist/react/index.js.map +0 -1
  38. package/dist/shared/components/annotations/form-checkbox.d.ts +0 -12
  39. package/dist/shared/components/annotations/form-combobox.d.ts +0 -12
  40. package/dist/shared/components/annotations/form-listbox.d.ts +0 -12
  41. package/dist/shared/components/annotations/form-radio-button.d.ts +0 -12
  42. package/dist/shared/components/annotations/form-text-field.d.ts +0 -12
  43. package/dist/shared/components/fields/checkbox.d.ts +0 -2
  44. package/dist/shared/components/fields/combobox.d.ts +0 -2
  45. package/dist/shared/components/fields/listbox.d.ts +0 -2
  46. package/dist/shared/components/fields/push-button.d.ts +0 -2
  47. package/dist/shared/components/fields/radio-button.d.ts +0 -2
  48. package/dist/shared/components/fields/style.d.ts +0 -6
  49. package/dist/shared/components/fields/text.d.ts +0 -2
  50. package/dist/shared/components/fill-mode/combobox-fill-mode.d.ts +0 -3
  51. package/dist/shared/components/fill-mode/listbox-fill-mode.d.ts +0 -3
  52. package/dist/shared/components/fill-mode/push-button-fill-mode.d.ts +0 -3
  53. package/dist/shared/components/fill-mode/radio-button-fill-mode.d.ts +0 -3
  54. package/dist/shared/components/fill-mode/text-fill-mode.d.ts +0 -3
  55. package/dist/shared/components/fill-mode/toggle-fill-mode.d.ts +0 -3
  56. package/dist/shared/components/form-renderer-registration.d.ts +0 -5
  57. package/dist/shared/components/form-renderers.d.ts +0 -9
  58. package/dist/shared/components/index.d.ts +0 -2
  59. package/dist/shared/components/render-widget.d.ts +0 -12
  60. package/dist/shared/components/types.d.ts +0 -42
  61. package/dist/shared/hooks/index.d.ts +0 -1
  62. package/dist/shared/hooks/use-form-widget-state.d.ts +0 -12
  63. package/dist/shared/hooks/use-form.d.ts +0 -16
  64. package/dist/shared/index.d.ts +0 -4
  65. package/dist/shared-preact/components/annotations/form-checkbox.d.ts +0 -12
  66. package/dist/shared-preact/components/annotations/form-combobox.d.ts +0 -12
  67. package/dist/shared-preact/components/annotations/form-listbox.d.ts +0 -12
  68. package/dist/shared-preact/components/annotations/form-radio-button.d.ts +0 -12
  69. package/dist/shared-preact/components/annotations/form-text-field.d.ts +0 -12
  70. package/dist/shared-preact/components/fields/checkbox.d.ts +0 -2
  71. package/dist/shared-preact/components/fields/combobox.d.ts +0 -2
  72. package/dist/shared-preact/components/fields/listbox.d.ts +0 -2
  73. package/dist/shared-preact/components/fields/push-button.d.ts +0 -2
  74. package/dist/shared-preact/components/fields/radio-button.d.ts +0 -2
  75. package/dist/shared-preact/components/fields/style.d.ts +0 -6
  76. package/dist/shared-preact/components/fields/text.d.ts +0 -2
  77. package/dist/shared-preact/components/fill-mode/combobox-fill-mode.d.ts +0 -3
  78. package/dist/shared-preact/components/fill-mode/listbox-fill-mode.d.ts +0 -3
  79. package/dist/shared-preact/components/fill-mode/push-button-fill-mode.d.ts +0 -3
  80. package/dist/shared-preact/components/fill-mode/radio-button-fill-mode.d.ts +0 -3
  81. package/dist/shared-preact/components/fill-mode/text-fill-mode.d.ts +0 -3
  82. package/dist/shared-preact/components/fill-mode/toggle-fill-mode.d.ts +0 -3
  83. package/dist/shared-preact/components/form-renderer-registration.d.ts +0 -5
  84. package/dist/shared-preact/components/form-renderers.d.ts +0 -9
  85. package/dist/shared-preact/components/index.d.ts +0 -2
  86. package/dist/shared-preact/components/render-widget.d.ts +0 -12
  87. package/dist/shared-preact/components/types.d.ts +0 -42
  88. package/dist/shared-preact/hooks/index.d.ts +0 -1
  89. package/dist/shared-preact/hooks/use-form-widget-state.d.ts +0 -12
  90. package/dist/shared-preact/hooks/use-form.d.ts +0 -16
  91. package/dist/shared-preact/index.d.ts +0 -4
  92. package/dist/shared-react/components/annotations/form-checkbox.d.ts +0 -12
  93. package/dist/shared-react/components/annotations/form-combobox.d.ts +0 -12
  94. package/dist/shared-react/components/annotations/form-listbox.d.ts +0 -12
  95. package/dist/shared-react/components/annotations/form-radio-button.d.ts +0 -12
  96. package/dist/shared-react/components/annotations/form-text-field.d.ts +0 -12
  97. package/dist/shared-react/components/fields/checkbox.d.ts +0 -2
  98. package/dist/shared-react/components/fields/combobox.d.ts +0 -2
  99. package/dist/shared-react/components/fields/listbox.d.ts +0 -2
  100. package/dist/shared-react/components/fields/push-button.d.ts +0 -2
  101. package/dist/shared-react/components/fields/radio-button.d.ts +0 -2
  102. package/dist/shared-react/components/fields/style.d.ts +0 -6
  103. package/dist/shared-react/components/fields/text.d.ts +0 -2
  104. package/dist/shared-react/components/fill-mode/combobox-fill-mode.d.ts +0 -3
  105. package/dist/shared-react/components/fill-mode/listbox-fill-mode.d.ts +0 -3
  106. package/dist/shared-react/components/fill-mode/push-button-fill-mode.d.ts +0 -3
  107. package/dist/shared-react/components/fill-mode/radio-button-fill-mode.d.ts +0 -3
  108. package/dist/shared-react/components/fill-mode/text-fill-mode.d.ts +0 -3
  109. package/dist/shared-react/components/fill-mode/toggle-fill-mode.d.ts +0 -3
  110. package/dist/shared-react/components/form-renderer-registration.d.ts +0 -5
  111. package/dist/shared-react/components/form-renderers.d.ts +0 -9
  112. package/dist/shared-react/components/index.d.ts +0 -2
  113. package/dist/shared-react/components/render-widget.d.ts +0 -12
  114. package/dist/shared-react/components/types.d.ts +0 -42
  115. package/dist/shared-react/hooks/index.d.ts +0 -1
  116. package/dist/shared-react/hooks/use-form-widget-state.d.ts +0 -12
  117. package/dist/shared-react/hooks/use-form.d.ts +0 -16
  118. package/dist/shared-react/index.d.ts +0 -4
  119. package/dist/svelte/components/FormRendererRegistration.svelte.d.ts +0 -18
  120. package/dist/svelte/components/RenderWidget.svelte.d.ts +0 -11
  121. package/dist/svelte/components/annotations/FormCheckbox.svelte.d.ts +0 -5
  122. package/dist/svelte/components/annotations/FormCombobox.svelte.d.ts +0 -5
  123. package/dist/svelte/components/annotations/FormListbox.svelte.d.ts +0 -5
  124. package/dist/svelte/components/annotations/FormRadioButton.svelte.d.ts +0 -5
  125. package/dist/svelte/components/annotations/FormTextField.svelte.d.ts +0 -5
  126. package/dist/svelte/components/fields/ComboboxField.svelte.d.ts +0 -4
  127. package/dist/svelte/components/fields/ListboxField.svelte.d.ts +0 -4
  128. package/dist/svelte/components/fields/TextField.svelte.d.ts +0 -4
  129. package/dist/svelte/components/fill-mode/ComboboxFillMode.svelte.d.ts +0 -5
  130. package/dist/svelte/components/fill-mode/ListboxFillMode.svelte.d.ts +0 -5
  131. package/dist/svelte/components/fill-mode/RadioButtonFillMode.svelte.d.ts +0 -5
  132. package/dist/svelte/components/fill-mode/TextFillMode.svelte.d.ts +0 -5
  133. package/dist/svelte/components/fill-mode/ToggleFillMode.svelte.d.ts +0 -5
  134. package/dist/svelte/components/form-renderers.d.ts +0 -9
  135. package/dist/svelte/components/previews/CheckboxPreview.svelte.d.ts +0 -9
  136. package/dist/svelte/components/previews/ListboxPreview.svelte.d.ts +0 -9
  137. package/dist/svelte/components/previews/RadioButtonPreview.svelte.d.ts +0 -9
  138. package/dist/svelte/components/previews/TextFieldPreview.svelte.d.ts +0 -9
  139. package/dist/svelte/hooks/index.d.ts +0 -2
  140. package/dist/svelte/hooks/use-form-widget-state.svelte.d.ts +0 -12
  141. package/dist/svelte/hooks/use-form.svelte.d.ts +0 -14
  142. package/dist/svelte/index.cjs +0 -2
  143. package/dist/svelte/index.cjs.map +0 -1
  144. package/dist/svelte/index.d.ts +0 -3
  145. package/dist/svelte/index.js +0 -1592
  146. package/dist/svelte/index.js.map +0 -1
  147. package/dist/vue/components/annotations/form-checkbox.vue.d.ts +0 -6
  148. package/dist/vue/components/annotations/form-combobox.vue.d.ts +0 -6
  149. package/dist/vue/components/annotations/form-listbox.vue.d.ts +0 -6
  150. package/dist/vue/components/annotations/form-radio-button.vue.d.ts +0 -6
  151. package/dist/vue/components/annotations/form-text-field.vue.d.ts +0 -6
  152. package/dist/vue/components/fields/combobox-field.vue.d.ts +0 -4
  153. package/dist/vue/components/fields/listbox-field.vue.d.ts +0 -4
  154. package/dist/vue/components/fields/style.d.ts +0 -6
  155. package/dist/vue/components/fields/text-field.vue.d.ts +0 -4
  156. package/dist/vue/components/fill-mode/combobox-fill-mode.vue.d.ts +0 -6
  157. package/dist/vue/components/fill-mode/listbox-fill-mode.vue.d.ts +0 -6
  158. package/dist/vue/components/fill-mode/radio-button-fill-mode.vue.d.ts +0 -6
  159. package/dist/vue/components/fill-mode/text-fill-mode.vue.d.ts +0 -6
  160. package/dist/vue/components/fill-mode/toggle-fill-mode.vue.d.ts +0 -6
  161. package/dist/vue/components/form-renderer-registration.vue.d.ts +0 -13
  162. package/dist/vue/components/form-renderers.d.ts +0 -3
  163. package/dist/vue/components/previews/checkbox-preview.vue.d.ts +0 -10
  164. package/dist/vue/components/previews/listbox-preview.vue.d.ts +0 -10
  165. package/dist/vue/components/previews/radio-button-preview.vue.d.ts +0 -10
  166. package/dist/vue/components/previews/text-field-preview.vue.d.ts +0 -10
  167. package/dist/vue/components/render-widget.vue.d.ts +0 -15
  168. package/dist/vue/hooks/index.d.ts +0 -2
  169. package/dist/vue/hooks/use-form-widget-state.d.ts +0 -12
  170. package/dist/vue/hooks/use-form.d.ts +0 -12
  171. package/dist/vue/index.cjs +0 -2
  172. package/dist/vue/index.cjs.map +0 -1
  173. package/dist/vue/index.d.ts +0 -3
  174. package/dist/vue/index.js +0 -1643
  175. package/dist/vue/index.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,2 +1,1416 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/models"),o=require("@embedpdf/plugin-history"),n=require("@embedpdf/plugin-annotation"),i="form",a={id:i,name:"Form Plugin",version:"1.0.0",provides:["form"],requires:["interaction-manager"],optional:["history","annotation"],defaultConfig:{enabled:!0}},r="FORM/INIT_STATE",l="FORM/CLEANUP_STATE",s="FORM/SELECT_FIELD",d="FORM/DESELECT_FIELD";function c(e,t){return{type:s,payload:{documentId:e,annotationId:t}}}const u={selectedFieldId:null},f={documents:{}},h={annotationType:t.PdfAnnotationSubtype.WIDGET,create(o){const{pageIndex:i,onCommit:a,onPreview:r,getTool:l,pageSize:s}=o,[d,c]=n.useState(null),u=t=>({x:e.clamp(t.x,0,s.width),y:e.clamp(t.y,0,s.height)}),f=()=>{const e=l();return e?{...e.defaults,fontFamily:e.defaults.fontFamily??t.PdfStandardFont.Helvetica,fontSize:e.defaults.fontSize??12,fontColor:e.defaults.fontColor??"#000000",strokeColor:e.defaults.strokeColor??"#000000",color:e.defaults.color??"#FFFFFF",strokeWidth:e.defaults.strokeWidth??1,field:e.defaults.field}:null},h=(e,t)=>({origin:{x:Math.min(e.x,t.x),y:Math.min(e.y,t.y)},size:{width:Math.abs(e.x-t.x),height:Math.abs(e.y-t.y)}}),g=e=>{var o;const n=f(),a=`TextField_${t.uuidV4().slice(0,8)}`;return{...n,type:t.PdfAnnotationSubtype.WIDGET,id:t.uuidV4(),pageIndex:i,rect:e,created:new Date,fontFamily:n.fontFamily,fontSize:n.fontSize,fontColor:n.fontColor,strokeColor:n.strokeColor,color:n.color,strokeWidth:n.strokeWidth,field:{type:t.PDF_FORM_FIELD_TYPE.TEXTFIELD,flag:(null==(o=n.field)?void 0:o.flag)??t.PDF_FORM_FIELD_FLAG.NONE,name:a,alternateName:a,value:""}}},p=n.useClickDetector({getTool:l,onClickDetected:t=>{if(!f())return;const o=l(),n=null==o?void 0:o.clickBehavior;if(!(null==n?void 0:n.enabled))return;const{width:i,height:r}=n.defaultSize,d=e.clamp(t.x-i/2,0,s.width-i),c=e.clamp(t.y-r/2,0,s.height-r);a(g({origin:{x:d,y:c},size:{width:i,height:r}}))}}),F=e=>{const o=d();if(!o)return null;const n=f();if(!n)return null;const i=h(o,e);return{type:t.PdfAnnotationSubtype.WIDGET,bounds:i,data:{rect:i,...n}}};return{onPointerDown:(e,t)=>{var o;const n=u(e);c(n),p.onStart(n),r(F(n)),null==(o=t.setPointerCapture)||o.call(t)},onPointerMove:e=>{const t=u(e);p.onMove(t),d()&&p.hasMoved()&&r(F(t))},onPointerUp:(e,t)=>{var o;const n=d();if(!n)return;const i=u(e);if(p.hasMoved()){const e=h(n,i);e.size.width>5&&e.size.height>5&&a(g(e))}else p.onEnd(i);c(null),r(null),p.reset(),null==(o=t.releasePointerCapture)||o.call(t)},onPointerLeave:(e,t)=>{var o;c(null),r(null),p.reset(),null==(o=t.releasePointerCapture)||o.call(t)},onPointerCancel:(e,t)=>{var o;c(null),r(null),p.reset(),null==(o=t.releasePointerCapture)||o.call(t)}}}},g={annotationType:t.PdfAnnotationSubtype.WIDGET,create(o){const{pageIndex:i,onCommit:a,onPreview:r,getTool:l,pageSize:s}=o,[d,c]=n.useState(null),u=t=>({x:e.clamp(t.x,0,s.width),y:e.clamp(t.y,0,s.height)}),f=()=>{const e=l();return e?{...e.defaults,strokeColor:e.defaults.strokeColor??"#000000",color:e.defaults.color??"#FFFFFF",strokeWidth:e.defaults.strokeWidth??1,field:e.defaults.field}:null},h=(e,t)=>({origin:{x:Math.min(e.x,t.x),y:Math.min(e.y,t.y)},size:{width:Math.abs(e.x-t.x),height:Math.abs(e.y-t.y)}}),g=e=>{var o;const n=f(),a=`Checkbox_${t.uuidV4().slice(0,8)}`;return{...n,type:t.PdfAnnotationSubtype.WIDGET,id:t.uuidV4(),pageIndex:i,rect:e,created:new Date,strokeColor:n.strokeColor,color:n.color,strokeWidth:n.strokeWidth,exportValue:"Yes",field:{type:t.PDF_FORM_FIELD_TYPE.CHECKBOX,flag:(null==(o=n.field)?void 0:o.flag)??t.PDF_FORM_FIELD_FLAG.NONE,name:a,alternateName:a,value:"Off"}}},p=n.useClickDetector({getTool:l,onClickDetected:t=>{if(!f())return;const o=l(),n=null==o?void 0:o.clickBehavior;if(!(null==n?void 0:n.enabled))return;const{width:i,height:r}=n.defaultSize,d=e.clamp(t.x-i/2,0,s.width-i),c=e.clamp(t.y-r/2,0,s.height-r);a(g({origin:{x:d,y:c},size:{width:i,height:r}}))}}),F=e=>{const o=d();if(!o)return null;const n=f();if(!n)return null;const i=h(o,e);return{type:t.PdfAnnotationSubtype.WIDGET,bounds:i,data:{rect:i,...n}}};return{onPointerDown:(e,t)=>{var o;const n=u(e);c(n),p.onStart(n),r(F(n)),null==(o=t.setPointerCapture)||o.call(t)},onPointerMove:e=>{const t=u(e);p.onMove(t),d()&&p.hasMoved()&&r(F(t))},onPointerUp:(e,t)=>{var o;const n=d();if(!n)return;const i=u(e);if(p.hasMoved()){const e=h(n,i);e.size.width>5&&e.size.height>5&&a(g(e))}else p.onEnd(i);c(null),r(null),p.reset(),null==(o=t.releasePointerCapture)||o.call(t)},onPointerLeave:(e,t)=>{var o;c(null),r(null),p.reset(),null==(o=t.releasePointerCapture)||o.call(t)},onPointerCancel:(e,t)=>{var o;c(null),r(null),p.reset(),null==(o=t.releasePointerCapture)||o.call(t)}}}},p={annotationType:t.PdfAnnotationSubtype.WIDGET,create(o){const{pageIndex:i,onCommit:a,onPreview:r,getTool:l,pageSize:s}=o,[d,c]=n.useState(null),u=t=>({x:e.clamp(t.x,0,s.width),y:e.clamp(t.y,0,s.height)}),f=()=>{const e=l();return e?{...e.defaults,strokeColor:e.defaults.strokeColor??"#000000",color:e.defaults.color??"#FFFFFF",strokeWidth:e.defaults.strokeWidth??1,field:e.defaults.field}:null},h=(e,t)=>{const o=t.x-e.x,n=t.y-e.y,i=Math.max(Math.abs(o),Math.abs(n)),a=o<0?-i:i,r=n<0?-i:i;return{origin:{x:Math.min(e.x,e.x+a),y:Math.min(e.y,e.y+r)},size:{width:i,height:i}}},g=e=>{var o;const n=f(),a=`RadioButton_${t.uuidV4().slice(0,8)}`,r=t.uuidV4();return{...n,type:t.PdfAnnotationSubtype.WIDGET,id:r,pageIndex:i,rect:e,created:new Date,strokeColor:n.strokeColor,color:n.color,strokeWidth:n.strokeWidth,exportValue:r,field:{type:t.PDF_FORM_FIELD_TYPE.RADIOBUTTON,flag:(null==(o=n.field)?void 0:o.flag)??t.PDF_FORM_FIELD_FLAG.BUTTON_RADIO|t.PDF_FORM_FIELD_FLAG.BUTTON_NOTOGGLETOOFF,name:a,alternateName:a,value:"Off",options:[]}}},p=n.useClickDetector({getTool:l,onClickDetected:t=>{if(!f())return;const o=l(),n=null==o?void 0:o.clickBehavior;if(!(null==n?void 0:n.enabled))return;const{width:i,height:r}=n.defaultSize,d=e.clamp(t.x-i/2,0,s.width-i),c=e.clamp(t.y-r/2,0,s.height-r);a(g({origin:{x:d,y:c},size:{width:i,height:r}}))}}),F=e=>{const o=d();if(!o)return null;const n=f();if(!n)return null;const i=h(o,e);return{type:t.PdfAnnotationSubtype.WIDGET,bounds:i,data:{rect:i,...n}}};return{onPointerDown:(e,t)=>{var o;const n=u(e);c(n),p.onStart(n),r(F(n)),null==(o=t.setPointerCapture)||o.call(t)},onPointerMove:e=>{const t=u(e);p.onMove(t),d()&&p.hasMoved()&&r(F(t))},onPointerUp:(e,t)=>{var o;const n=d();if(!n)return;const i=u(e);if(p.hasMoved()){const e=h(n,i);e.size.width>5&&e.size.height>5&&a(g(e))}else p.onEnd(i);c(null),r(null),p.reset(),null==(o=t.releasePointerCapture)||o.call(t)},onPointerLeave:(e,t)=>{var o;c(null),r(null),p.reset(),null==(o=t.releasePointerCapture)||o.call(t)},onPointerCancel:(e,t)=>{var o;c(null),r(null),p.reset(),null==(o=t.releasePointerCapture)||o.call(t)}}}},F={annotationType:t.PdfAnnotationSubtype.WIDGET,create(o){const{pageIndex:i,onCommit:a,onPreview:r,getTool:l,pageSize:s}=o,[d,c]=n.useState(null),u=t=>({x:e.clamp(t.x,0,s.width),y:e.clamp(t.y,0,s.height)}),f=()=>{const e=l();return e?{...e.defaults,fontFamily:e.defaults.fontFamily??t.PdfStandardFont.Helvetica,fontSize:e.defaults.fontSize??12,fontColor:e.defaults.fontColor??"#000000",strokeColor:e.defaults.strokeColor??"#000000",color:e.defaults.color??"#FFFFFF",strokeWidth:e.defaults.strokeWidth??1,field:e.defaults.field}:null},h=(e,t)=>({origin:{x:Math.min(e.x,t.x),y:Math.min(e.y,t.y)},size:{width:Math.abs(e.x-t.x),height:Math.abs(e.y-t.y)}}),g=e=>{var o;const n=f(),a=`Combobox_${t.uuidV4().slice(0,8)}`;return{...n,type:t.PdfAnnotationSubtype.WIDGET,id:t.uuidV4(),pageIndex:i,rect:e,created:new Date,fontFamily:n.fontFamily,fontSize:n.fontSize,fontColor:n.fontColor,strokeColor:n.strokeColor,color:n.color,strokeWidth:n.strokeWidth,field:{type:t.PDF_FORM_FIELD_TYPE.COMBOBOX,flag:(null==(o=n.field)?void 0:o.flag)??t.PDF_FORM_FIELD_FLAG.NONE,name:a,alternateName:a,value:"",options:[{label:"Option 1",isSelected:!0},{label:"Option 2",isSelected:!1},{label:"Option 3",isSelected:!1}]}}},p=n.useClickDetector({getTool:l,onClickDetected:t=>{if(!f())return;const o=l(),n=null==o?void 0:o.clickBehavior;if(!(null==n?void 0:n.enabled))return;const{width:i,height:r}=n.defaultSize,d=e.clamp(t.x-i/2,0,s.width-i),c=e.clamp(t.y-r/2,0,s.height-r);a(g({origin:{x:d,y:c},size:{width:i,height:r}}))}}),F=e=>{const o=d();if(!o)return null;const n=f();if(!n)return null;const i=h(o,e);return{type:t.PdfAnnotationSubtype.WIDGET,bounds:i,data:{rect:i,...n}}};return{onPointerDown:(e,t)=>{var o;const n=u(e);c(n),p.onStart(n),r(F(n)),null==(o=t.setPointerCapture)||o.call(t)},onPointerMove:e=>{const t=u(e);p.onMove(t),d()&&p.hasMoved()&&r(F(t))},onPointerUp:(e,t)=>{var o;const n=d();if(!n)return;const i=u(e);if(p.hasMoved()){const e=h(n,i);e.size.width>5&&e.size.height>5&&a(g(e))}else p.onEnd(i);c(null),r(null),p.reset(),null==(o=t.releasePointerCapture)||o.call(t)},onPointerLeave:(e,t)=>{var o;c(null),r(null),p.reset(),null==(o=t.releasePointerCapture)||o.call(t)},onPointerCancel:(e,t)=>{var o;c(null),r(null),p.reset(),null==(o=t.releasePointerCapture)||o.call(t)}}}},m={annotationType:t.PdfAnnotationSubtype.WIDGET,create(o){const{pageIndex:i,onCommit:a,onPreview:r,getTool:l,pageSize:s}=o,[d,c]=n.useState(null),u=t=>({x:e.clamp(t.x,0,s.width),y:e.clamp(t.y,0,s.height)}),f=()=>{const e=l();return e?{...e.defaults,fontFamily:e.defaults.fontFamily??t.PdfStandardFont.Helvetica,fontSize:e.defaults.fontSize??12,fontColor:e.defaults.fontColor??"#000000",strokeColor:e.defaults.strokeColor??"#000000",color:e.defaults.color??"#FFFFFF",strokeWidth:e.defaults.strokeWidth??1,field:e.defaults.field}:null},h=(e,t)=>({origin:{x:Math.min(e.x,t.x),y:Math.min(e.y,t.y)},size:{width:Math.abs(e.x-t.x),height:Math.abs(e.y-t.y)}}),g=e=>{var o;const n=f(),a=`Listbox_${t.uuidV4().slice(0,8)}`;return{...n,type:t.PdfAnnotationSubtype.WIDGET,id:t.uuidV4(),pageIndex:i,rect:e,created:new Date,fontFamily:n.fontFamily,fontSize:n.fontSize,fontColor:n.fontColor,strokeColor:n.strokeColor,color:n.color,strokeWidth:n.strokeWidth,field:{type:t.PDF_FORM_FIELD_TYPE.LISTBOX,flag:(null==(o=n.field)?void 0:o.flag)??t.PDF_FORM_FIELD_FLAG.NONE,name:a,alternateName:a,value:"",options:[{label:"Option 1",isSelected:!0},{label:"Option 2",isSelected:!1},{label:"Option 3",isSelected:!1}]}}},p=n.useClickDetector({getTool:l,onClickDetected:t=>{if(!f())return;const o=l(),n=null==o?void 0:o.clickBehavior;if(!(null==n?void 0:n.enabled))return;const{width:i,height:r}=n.defaultSize,d=e.clamp(t.x-i/2,0,s.width-i),c=e.clamp(t.y-r/2,0,s.height-r);a(g({origin:{x:d,y:c},size:{width:i,height:r}}))}}),F=e=>{const o=d();if(!o)return null;const n=f();if(!n)return null;const i=h(o,e);return{type:t.PdfAnnotationSubtype.WIDGET,bounds:i,data:{rect:i,...n}}};return{onPointerDown:(e,t)=>{var o;const n=u(e);c(n),p.onStart(n),r(F(n)),null==(o=t.setPointerCapture)||o.call(t)},onPointerMove:e=>{const t=u(e);p.onMove(t),d()&&p.hasMoved()&&r(F(t))},onPointerUp:(e,t)=>{var o;const n=d();if(!n)return;const i=u(e);if(p.hasMoved()){const e=h(n,i);e.size.width>5&&e.size.height>5&&a(g(e))}else p.onEnd(i);c(null),r(null),p.reset(),null==(o=t.releasePointerCapture)||o.call(t)},onPointerLeave:(e,t)=>{var o;c(null),r(null),p.reset(),null==(o=t.releasePointerCapture)||o.call(t)},onPointerCancel:(e,t)=>{var o;c(null),r(null),p.reset(),null==(o=t.releasePointerCapture)||o.call(t)}}}},y=n.defineAnnotationTool({id:"formTextField",name:"Text Field",labelKey:"form.textfield",categories:["annotation","form"],matchScore:e=>{var o;if(e.type!==t.PdfAnnotationSubtype.WIDGET)return 0;return(null==(o=e.field)?void 0:o.type)===t.PDF_FORM_FIELD_TYPE.TEXTFIELD?10:0},interaction:{exclusive:!1,cursor:"crosshair",isDraggable:!0,isResizable:!0,isRotatable:!1,isGroupDraggable:!0,isGroupResizable:!1,isGroupRotatable:!1},defaults:{type:t.PdfAnnotationSubtype.WIDGET,fontFamily:t.PdfStandardFont.Helvetica,fontSize:12,fontColor:"#000000",strokeColor:"#000000",color:"#FFFFFF",strokeWidth:1,field:{flag:t.PDF_FORM_FIELD_FLAG.NONE,name:"TextField",alternateName:"TextField",value:"",type:t.PDF_FORM_FIELD_TYPE.TEXTFIELD}},behavior:{useAppearanceStream:!1},clickBehavior:{enabled:!0,defaultSize:{width:150,height:24}},pointerHandler:h}),I=n.defineAnnotationTool({id:"formCheckbox",name:"Checkbox",labelKey:"form.checkbox",categories:["annotation","form"],matchScore:e=>{var o;if(e.type!==t.PdfAnnotationSubtype.WIDGET)return 0;return(null==(o=e.field)?void 0:o.type)===t.PDF_FORM_FIELD_TYPE.CHECKBOX?10:0},interaction:{exclusive:!1,cursor:"crosshair",isDraggable:!0,isResizable:!0,isRotatable:!1,isGroupDraggable:!0,isGroupResizable:!1,isGroupRotatable:!1},defaults:{type:t.PdfAnnotationSubtype.WIDGET,strokeColor:"#000000",color:"#FFFFFF",strokeWidth:1,field:{flag:t.PDF_FORM_FIELD_FLAG.NONE,name:"Checkbox",alternateName:"Checkbox",value:"Off",type:t.PDF_FORM_FIELD_TYPE.CHECKBOX}},behavior:{useAppearanceStream:!1},clickBehavior:{enabled:!0,defaultSize:{width:20,height:20}},pointerHandler:g}),P=n.defineAnnotationTool({id:"formRadioButton",name:"Radio Button",labelKey:"form.radiobutton",categories:["annotation","form"],matchScore:e=>{var o;if(e.type!==t.PdfAnnotationSubtype.WIDGET)return 0;return(null==(o=e.field)?void 0:o.type)===t.PDF_FORM_FIELD_TYPE.RADIOBUTTON?10:0},interaction:{exclusive:!1,cursor:"crosshair",isDraggable:!0,isResizable:!0,isRotatable:!1,lockAspectRatio:!0,isGroupDraggable:!0,isGroupResizable:!1,isGroupRotatable:!1},defaults:{type:t.PdfAnnotationSubtype.WIDGET,strokeColor:"#000000",color:"#FFFFFF",strokeWidth:1,field:{flag:t.PDF_FORM_FIELD_FLAG.BUTTON_RADIO|t.PDF_FORM_FIELD_FLAG.BUTTON_NOTOGGLETOOFF,name:"RadioButton",alternateName:"RadioButton",value:"Off",type:t.PDF_FORM_FIELD_TYPE.RADIOBUTTON,options:[]}},behavior:{useAppearanceStream:!1},clickBehavior:{enabled:!0,defaultSize:{width:20,height:20}},pointerHandler:p}),D=n.defineAnnotationTool({id:"formCombobox",name:"Combo Box",labelKey:"form.combobox",categories:["annotation","form"],matchScore:e=>{var o;if(e.type!==t.PdfAnnotationSubtype.WIDGET)return 0;return(null==(o=e.field)?void 0:o.type)===t.PDF_FORM_FIELD_TYPE.COMBOBOX?10:0},interaction:{exclusive:!1,cursor:"crosshair",isDraggable:!0,isResizable:!0,isRotatable:!1,isGroupDraggable:!0,isGroupResizable:!1,isGroupRotatable:!1},defaults:{type:t.PdfAnnotationSubtype.WIDGET,fontFamily:t.PdfStandardFont.Helvetica,fontSize:12,fontColor:"#000000",strokeColor:"#000000",color:"#FFFFFF",strokeWidth:1,field:{flag:t.PDF_FORM_FIELD_FLAG.NONE,name:"ComboBox",alternateName:"ComboBox",value:"",type:t.PDF_FORM_FIELD_TYPE.COMBOBOX,options:[{label:"Option 1",isSelected:!0},{label:"Option 2",isSelected:!1},{label:"Option 3",isSelected:!1}]}},behavior:{useAppearanceStream:!1},clickBehavior:{enabled:!0,defaultSize:{width:200,height:40}},pointerHandler:F}),b=n.defineAnnotationTool({id:"formListbox",name:"List Box",labelKey:"form.listbox",categories:["annotation","form"],matchScore:e=>{var o;if(e.type!==t.PdfAnnotationSubtype.WIDGET)return 0;return(null==(o=e.field)?void 0:o.type)===t.PDF_FORM_FIELD_TYPE.LISTBOX?10:0},interaction:{exclusive:!1,cursor:"crosshair",isDraggable:!0,isResizable:!0,isRotatable:!1,isGroupDraggable:!0,isGroupResizable:!1,isGroupRotatable:!1},defaults:{type:t.PdfAnnotationSubtype.WIDGET,fontFamily:t.PdfStandardFont.Helvetica,fontSize:12,fontColor:"#000000",strokeColor:"#000000",color:"#FFFFFF",strokeWidth:1,field:{flag:t.PDF_FORM_FIELD_FLAG.NONE,name:"ListBox",alternateName:"ListBox",value:"",type:t.PDF_FORM_FIELD_TYPE.LISTBOX,options:[{label:"Option 1",isSelected:!0},{label:"Option 2",isSelected:!1},{label:"Option 3",isSelected:!1}]}},behavior:{useAppearanceStream:!1},clickBehavior:{enabled:!0,defaultSize:{width:150,height:150}},pointerHandler:m}),v=[y,I,P,D,b],x=class extends e.BasePlugin{constructor(t,n,i){var a,r;if(super(t,n),this.FORM_HISTORY_TOPIC="form-fields",this.annotation=null,this.history=null,this.state$=e.createScopedEmitter((e,t)=>({documentId:e,state:t})),this.fieldValueChange$=e.createScopedEmitter((e,t)=>t,{cache:!1}),this.formReady$=e.createScopedEmitter((e,t)=>({documentId:e,fields:t}),{cache:!1}),this.fieldGroupIndex=new Map,this.fieldNameIndex=new Map,this.orderedFieldIndex=new Map,this.propagationInProgress=new Set,this.annotation=(null==(a=n.getPlugin("annotation"))?void 0:a.provides())??null,this.history=(null==(r=n.getPlugin(o.HistoryPlugin.id))?void 0:r.provides())??null,this.annotation){for(const e of v)this.annotation.addTool(e);this.annotation.onAnnotationEvent(e=>this.handleAnnotationEvent(e))}}async initialize(){}onDocumentLoadingStarted(e){this.dispatch(function(e,t){return{type:r,payload:{documentId:e,state:t}}}(e,{...u}))}onDocumentClosed(e){this.dispatch(function(e){return{type:l,payload:e}}(e)),this.fieldGroupIndex.delete(e),this.fieldNameIndex.delete(e),this.orderedFieldIndex.delete(e),this.state$.clearScope(e),this.fieldValueChange$.clearScope(e),this.formReady$.clearScope(e)}onStoreUpdated(e,t){for(const o in t.documents){const n=e.documents[o],i=t.documents[o];n!==i&&this.state$.emit(o,i)}}buildCapability(){return{getPageFormAnnoWidgets:(e,t)=>this.getPageFormAnnoWidgets(e,t),setFormFieldValues:(e,t,o,n)=>this.setFormFieldValues(e,t,o,n),renameField:(e,t,o)=>this.renameFieldMethod(e,t,o),shareField:(e,t,o)=>this.shareFieldMethod(e,t,o),renderWidget:(e,t)=>this.renderWidget(e,t),selectField:(e,t)=>this.selectFieldMethod(e,t),deselectField:e=>this.deselectFieldMethod(e),getSelectedFieldId:e=>this.getSelectedFieldId(e),selectNextField:e=>this.selectNextFieldMethod(e),selectPreviousField:e=>this.selectPreviousFieldMethod(e),activateField:e=>this.activateFieldMethod(e),getState:e=>this.getDocumentState(e),getFieldGroup:(e,t)=>this.getFieldGroup(e,t),getFieldSiblings:(e,t)=>this.getFieldSiblings(e,t),getFormValues:e=>this.getFormValuesMethod(e),getFormFields:e=>this.getFormFieldsMethod(e),setFormValues:(e,t)=>this.setFormValuesMethod(e,t),forDocument:e=>this.createFormScope(e),onStateChange:this.state$.onGlobal,onFieldValueChange:this.fieldValueChange$.onGlobal,onFormReady:this.formReady$.onGlobal}}createFormScope(e){return{getPageFormAnnoWidgets:t=>this.getPageFormAnnoWidgets(t,e),setFormFieldValues:(t,o,n)=>this.setFormFieldValues(t,o,n,e),renameField:(t,o)=>this.renameFieldMethod(t,o,e),shareField:(t,o)=>this.shareFieldMethod(t,o,e),renderWidget:t=>this.renderWidget(t,e),selectField:t=>this.selectFieldMethod(t,e),deselectField:()=>this.deselectFieldMethod(e),getSelectedFieldId:()=>this.getSelectedFieldId(e),selectNextField:()=>this.selectNextFieldMethod(e),selectPreviousField:()=>this.selectPreviousFieldMethod(e),activateField:()=>this.activateFieldMethod(e),getState:()=>this.getDocumentState(e),getFieldGroup:t=>this.getFieldGroup(t,e),getFieldSiblings:t=>this.getFieldSiblings(t,e),getFormValues:()=>this.getFormValuesMethod(e),getFormFields:()=>this.getFormFieldsMethod(e),setFormValues:t=>this.setFormValuesMethod(t,e),onStateChange:this.state$.forScope(e),onFieldValueChange:this.fieldValueChange$.forScope(e),onFormReady:this.formReady$.forScope(e)}}handleAnnotationEvent(e){switch(e.type){case"loaded":this.buildFieldGroupIndex(e.documentId),this.formReady$.emit(e.documentId,this.getFormFieldsMethod(e.documentId));break;case"create":case"delete":if(e.annotation.type!==t.PdfAnnotationSubtype.WIDGET)break;this.buildFieldGroupIndex(e.documentId);break;case"update":{if(!e.committed)break;const o=e.annotation;if(o.type!==t.PdfAnnotationSubtype.WIDGET)break;if(this.propagationInProgress.has(o.id)){this.propagationInProgress.delete(o.id);break}const n=e.patch;this.buildFieldGroupIndex(e.documentId),this.propagateFieldLevelChanges(e.documentId,o,n);break}}}propagateFieldLevelChanges(e,t,o){if(!this.annotation||!o.field)return;const n=o.field,i=this.getFieldSiblings(t.id,e);if(0===i.length)return;const a=[];for(const r of i)this.propagationInProgress.add(r.annotationId),a.push({pageIndex:r.pageIndex,id:r.annotationId,patch:{field:{...n}}});this.annotation.forDocument(e).updateAnnotations(a)}buildFieldGroupIndex(e){if(!this.annotation)return;const o=this.annotation.forDocument(e).getState();if(!o)return;const n=new Map,i=[];for(const[l,s]of Object.entries(o.pages)){const e=Number(l);for(const a of s){const r=o.byUid[a];if(!r||r.object.type!==t.PdfAnnotationSubtype.WIDGET)continue;const l=r.object,s={annotationId:a,pageIndex:e};i.push({entry:s,widget:l});const d=this.getFieldKey(l.field);if(!d)continue;const c=n.get(d)??[];c.push(s),n.set(d,c)}}this.fieldGroupIndex.set(e,n);const a=new Map;for(const{entry:t,widget:l}of i){const e=l.field.name.trim();if(!e)continue;const o=a.get(e)??[];o.push(t),a.set(e,o)}this.fieldNameIndex.set(e,a);const r=i.filter(({widget:e})=>!(e.field.flag&t.PDF_FORM_FIELD_FLAG.READONLY));this.orderedFieldIndex.set(e,r.map(({entry:e})=>e))}getDocumentState(e){const t=e??this.getActiveDocumentId();return this.state.documents[t]??{...u}}getDocIndex(e){let t=this.fieldGroupIndex.get(e);return t||(t=new Map,this.fieldGroupIndex.set(e,t)),t}getFieldKey(e){if("number"==typeof e.fieldObjectId&&e.fieldObjectId>0)return`field:${e.fieldObjectId}`;const t=e.name.trim();return t?`legacy:${e.type}:${t}`:null}resolveWidgetAnnotation(e,o){if(!this.annotation)return null;const n=this.annotation.forDocument(o).getState(),i=null==n?void 0:n.byUid[e];return i&&i.object.type===t.PdfAnnotationSubtype.WIDGET?i.object:null}getFieldGroup(e,t){const o=t??this.getActiveDocumentId(),n=this.resolveWidgetAnnotation(e,o);if(!n)return[];const i=this.getFieldKey(n.field);return i?this.getDocIndex(o).get(i)??[{annotationId:n.id,pageIndex:n.pageIndex}]:[{annotationId:n.id,pageIndex:n.pageIndex}]}getFieldSiblings(e,t){return this.getFieldGroup(e,t).filter(t=>t.annotationId!==e)}getFormValuesMethod(e){const t=e??this.getActiveDocumentId(),o=this.fieldNameIndex.get(t);if(!o)return{};const n={};for(const[i,a]of o){const e=this.resolveWidgetAnnotation(a[0].annotationId,t);e&&(n[i]=e.field.value)}return n}getFormFieldsMethod(e){const o=e??this.getActiveDocumentId(),n=this.fieldNameIndex.get(o);if(!n)return[];const i=[];for(const[a,r]of n){const e=this.resolveWidgetAnnotation(r[0].annotationId,o);e&&i.push({name:a,type:e.field.type,value:e.field.value,readOnly:!!(e.field.flag&t.PDF_FORM_FIELD_FLAG.READONLY),..."options"in e.field&&e.field.options?{options:e.field.options}:{}})}return i}setFormValuesMethod(e,o){const n=o??this.getActiveDocumentId(),i=this.fieldNameIndex.get(n);if(!i)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"no form fields indexed for this document"});const a=Object.entries(e);if(0===a.length)return t.PdfTaskHelper.resolve(!0);const r=new t.Task;let l=a.length,s=!1;const d=()=>{l--,0!==l||s||r.resolve(!0)};for(const[c,u]of a){const e=i.get(c);if(!e||0===e.length){d();continue}let o=e[0],a=this.resolveWidgetAnnotation(o.annotationId,n);if(a){if(a.field.type===t.PDF_FORM_FIELD_TYPE.RADIOBUTTON||a.field.type===t.PDF_FORM_FIELD_TYPE.CHECKBOX)for(const t of e){const e=this.resolveWidgetAnnotation(t.annotationId,n);if(e&&e.exportValue===u){a=e,o=t;break}}this.setFormFieldValues(o.pageIndex,a,this.buildImportField(a,u),n).wait(()=>d(),e=>{return t=e.reason,void(s||(s=!0,r.reject(t)));var t})}else d()}return r}buildImportField(e,o){const n=e.field;if((n.type===t.PDF_FORM_FIELD_TYPE.COMBOBOX||n.type===t.PDF_FORM_FIELD_TYPE.LISTBOX)&&"options"in n)return{...n,value:o,options:n.options.map(e=>({...e,isSelected:e.label===o}))};if(n.type===t.PDF_FORM_FIELD_TYPE.CHECKBOX){const t="Off"===o?"Off":e.exportValue??"Yes";return{...n,value:t}}return{...n,value:o}}isToggleField(e){return e.type===t.PDF_FORM_FIELD_TYPE.CHECKBOX||e.type===t.PDF_FORM_FIELD_TYPE.RADIOBUTTON}shouldRegenerateWidgetAppearances(e){return!this.isToggleField(e)}getFieldBatchTarget(e){const o=[...e.values()];return o.find(e=>this.isToggleField(e.widget.field)&&t.isWidgetChecked(e.widget))??o[0]}async readFieldWidgets(e,t,o,n){const i=new Set(t.map(e=>e.pageIndex)),a=new Set(t.map(e=>e.annotationId)),r=new Map;for(const l of i){const i=e.pages.find(e=>e.index===l);if(!i)continue;const s=t.filter(e=>e.pageIndex===l).map(e=>e.annotationId);n&&await o.run(()=>this.engine.regenerateWidgetAppearances(e,i,s));const d=await o.run(()=>this.engine.getPageAnnoWidgets(e,i));for(const e of d)a.has(e.id)&&r.set(e.id,{widget:e,pageIndex:l})}return r}syncFieldBatch(e,t,o={}){if(this.annotation){for(const[n,{widget:i,pageIndex:a}]of t)this.annotation.syncAnnotationObject(n,i,e),this.annotation.invalidatePageAppearances(a,e),o.emitFieldValueChanges&&this.fieldValueChange$.emit(e,{documentId:e,pageIndex:a,annotationId:n,widget:i});this.buildFieldGroupIndex(e)}}resolveWidgetPage(e,t,o){const n=this.resolveWidgetAnnotation(e,t);if(!n)return null;const i=o.pages.find(e=>e.index===n.pageIndex);return i?{widget:n,page:i}:null}getPageFormAnnoWidgets(e,o){const n=this.getCoreDocumentOrThrow(o).document;if(!n)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.DocNotOpen,message:"document is not open"});const i=n.pages.find(t=>t.index===e);return i?this.engine.getPageAnnoWidgets(n,i):t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"page does not exist"})}setFormFieldValues(e,o,n,i){const a=i??this.getActiveDocumentId(),r=this.getCoreDocumentOrThrow(a).document;if(!r)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.DocNotOpen,message:"document is not open"});const l=r.pages.find(t=>t.index===e);if(!l)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"page does not exist"});const s=new t.Task,d=new t.TaskSequence(s);return d.execute(async()=>{const e=this.getFieldGroup(o.id,a),t=await this.readFieldWidgets(r,e,d,!1);await d.run(()=>this.engine.setFormFieldState(r,l,o,n));const i=await this.readFieldWidgets(r,e,d,this.shouldRegenerateWidgetAppearances(n));let c=!0;const u=async e=>{const t=this.getFieldBatchTarget(e);if(!t)return;const o=r.pages.find(e=>e.index===t.pageIndex);if(o&&(await new Promise(e=>{this.engine.setFormFieldState(r,o,t.widget,t.widget.field).wait(()=>e(),()=>e())}),this.shouldRegenerateWidgetAppearances(t.widget.field)))for(const n of new Set([...e.values()].map(e=>e.pageIndex))){const t=r.pages.find(e=>e.index===n);if(!t)continue;const o=[...e.entries()].filter(([,e])=>e.pageIndex===n).map(([e])=>e);await new Promise(e=>{this.engine.regenerateWidgetAppearances(r,t,o).wait(()=>e(),()=>e())})}},f={execute:()=>{const e=c;c=!1,e?this.syncFieldBatch(a,i,{emitFieldValueChanges:!0}):u(i).then(()=>this.syncFieldBatch(a,i,{emitFieldValueChanges:!0}))},undo:()=>{u(t).then(()=>this.syncFieldBatch(a,t,{emitFieldValueChanges:!0}))}};this.history?this.history.forDocument(a).register(f,this.FORM_HISTORY_TOPIC):f.execute(),s.resolve(!0)},e=>({code:t.PdfErrorCode.Unknown,message:String(e)})),s}findConflictingFieldGroups(e,o,n){const i=new Map;if(!this.annotation)return i;const a=this.annotation.forDocument(n).getState();if(!a)return i;const r=(()=>{const e=this.resolveWidgetAnnotation(o,n);return e?this.getFieldKey(e.field):null})();for(const[l,s]of Object.entries(a.pages)){const o=Number(l);for(const n of s){const l=a.byUid[n];if(!l||l.object.type!==t.PdfAnnotationSubtype.WIDGET)continue;const s=l.object;if(s.field.name.trim()!==e)continue;const d=this.getFieldKey(s.field);d&&d!==r&&(i.has(d)||i.set(d,{entries:[],widget:s}),i.get(d).entries.push({annotationId:n,pageIndex:o}))}}return i}renameFieldMethod(e,o,n){const i=n??this.getActiveDocumentId(),a=o.trim();if(!a)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.Unknown,message:"Field name must not be empty."});const r=this.getCoreDocumentOrThrow(i).document;if(!r)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.DocNotOpen,message:"document is not open"});const l=this.resolveWidgetPage(e,i,r);if(!l)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"widget annotation not found"});if(l.widget.field.name.trim()===a)return t.PdfTaskHelper.resolve({outcome:"no-op"});const s=this.findConflictingFieldGroups(a,e,i);if(s.size>0){if(s.size>1)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.Unknown,message:"That field name is used by multiple fields. Choose a unique name."});const[,e]=[...s.entries()][0];return e.widget.field.type!==l.widget.field.type?t.PdfTaskHelper.reject({code:t.PdfErrorCode.Unknown,message:"That field name is already used by a different widget type."}):t.PdfTaskHelper.resolve({outcome:"conflict",targetAnnotationId:e.entries[0].annotationId,fieldName:a})}const d=new t.Task,c=new t.TaskSequence(d);return c.execute(async()=>{const t=this.getFieldGroup(e,i);await c.run(()=>this.engine.renameWidgetField(r,l.page,l.widget,a));const o=await this.readFieldWidgets(r,t,c,!1);this.syncFieldBatch(i,o),d.resolve({outcome:"renamed"})},e=>({code:t.PdfErrorCode.Unknown,message:String(e)})),d}shareFieldMethod(e,o,n){const i=n??this.getActiveDocumentId();if(e===o)return t.PdfTaskHelper.resolve(!0);const a=this.getCoreDocumentOrThrow(i).document;if(!a)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.DocNotOpen,message:"document is not open"});const r=this.resolveWidgetPage(e,i,a),l=this.resolveWidgetPage(o,i,a);if(!r||!l)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"widget annotation not found"});if(r.widget.field.type!==l.widget.field.type)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.Unknown,message:"cannot share fields with different widget types"});if(r.widget.field.fieldObjectId&&l.widget.field.fieldObjectId&&r.widget.field.fieldObjectId===l.widget.field.fieldObjectId)return t.PdfTaskHelper.resolve(!0);const s=new Map;for(const t of this.getFieldGroup(e,i))s.set(t.annotationId,t);for(const t of this.getFieldGroup(o,i))s.set(t.annotationId,t);const d=[...s.values()],c=new t.Task,u=new t.TaskSequence(c);return u.execute(async()=>{await u.run(()=>this.engine.shareWidgetField(a,r.page,r.widget,l.page,l.widget));const e=await this.readFieldWidgets(a,d,u,this.shouldRegenerateWidgetAppearances(l.widget.field));this.syncFieldBatch(i,e),c.resolve(!0)},e=>({code:t.PdfErrorCode.Unknown,message:String(e)})),c}selectFieldMethod(e,t){const o=t??this.getActiveDocumentId();this.dispatch(c(o,e))}deselectFieldMethod(e){const t=e??this.getActiveDocumentId();this.dispatch(function(e){return{type:d,payload:e}}(t))}getSelectedFieldId(e){return this.getDocumentState(e).selectedFieldId}selectNextFieldMethod(e){const t=e??this.getActiveDocumentId(),o=this.orderedFieldIndex.get(t);if(!o||0===o.length)return;const n=this.getSelectedFieldId(t);let i=0;if(n){const e=o.findIndex(e=>e.annotationId===n);i=e>=0?(e+1)%o.length:0}const a=o[i];this.dispatch(c(t,a.annotationId))}selectPreviousFieldMethod(e){const t=e??this.getActiveDocumentId(),o=this.orderedFieldIndex.get(t);if(!o||0===o.length)return;const n=this.getSelectedFieldId(t);let i=o.length-1;if(n){const e=o.findIndex(e=>e.annotationId===n);i=e>=0?(e-1+o.length)%o.length:o.length-1}const a=o[i];this.dispatch(c(t,a.annotationId))}activateFieldMethod(e){const o=e??this.getActiveDocumentId(),n=this.getSelectedFieldId(o);if(!n)return;const i=this.resolveWidgetAnnotation(n,o);if(!i)return;const a=i.field;if(a.type===t.PDF_FORM_FIELD_TYPE.CHECKBOX){const e=t.isWidgetChecked(i)?"Off":i.exportValue??"Yes";this.setFormFieldValues(i.pageIndex,i,{...a,value:e},o)}else a.type===t.PDF_FORM_FIELD_TYPE.RADIOBUTTON&&!t.isWidgetChecked(i)&&i.exportValue&&this.setFormFieldValues(i.pageIndex,i,{...a,value:i.exportValue},o)}renderWidget(e,o){if(!this.annotation)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"annotation plugin not found"});const n=o??this.getActiveDocumentId();return this.annotation.forDocument(n).renderAnnotation(e)}async destroy(){this.state$.clear(),this.fieldValueChange$.clear(),this.formReady$.clear(),super.destroy()}};x.id="form";let T=x;const S={manifest:a,create:(e,t)=>new T(i,e,t),reducer:(e=f,t)=>{switch(t.type){case r:return{...e,documents:{...e.documents,[t.payload.documentId]:t.payload.state}};case l:{const o=t.payload,{[o]:n,...i}=e.documents;return{...e,documents:i}}case s:{const{documentId:o,annotationId:n}=t.payload,i=e.documents[o];return i?{...e,documents:{...e.documents,[o]:{...i,selectedFieldId:n}}}:e}case d:{const o=t.payload,n=e.documents[o];return n?{...e,documents:{...e.documents,[o]:{...n,selectedFieldId:null}}}:e}default:return e}},initialState:f};exports.FORM_PLUGIN_ID=i,exports.FormPlugin=T,exports.FormPluginPackage=S,exports.formCheckboxTool=I,exports.formComboboxTool=D,exports.formListboxTool=b,exports.formRadioButtonTool=P,exports.formTextFieldTool=y,exports.formTools=v,exports.initialDocumentState=u,exports.initialState=f,exports.manifest=a;
2
- //# sourceMappingURL=index.cjs.map
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _embedpdf_core = require("@embedpdf/core");
3
+ let _embedpdf_plugin_annotation = require("@embedpdf/plugin-annotation");
4
+ let _embedpdf_plugin_annotation_internal = require("@embedpdf/plugin-annotation/internal");
5
+ let _embedpdf_plugin_interaction = require("@embedpdf/plugin-interaction");
6
+ let _embedpdf_core_acrojs = require("@embedpdf/core-acrojs");
7
+ //#region src/core/model.ts
8
+ const fieldKeyOf = (field) => field.fieldObjectNumber > 0 ? `obj:${field.fieldObjectNumber}` : `fqn:${field.name}`;
9
+ const initialModel = () => ({
10
+ snapshot: null,
11
+ byKey: {},
12
+ byWidget: {},
13
+ writing: {},
14
+ geom: {},
15
+ seq: 0
16
+ });
17
+ function index(snapshot) {
18
+ const byKey = {};
19
+ const byWidget = {};
20
+ snapshot.fields.forEach((field, i) => {
21
+ byKey[fieldKeyOf(field)] = i;
22
+ for (const w of field.widgets) if (w.annotObjectNumber > 0) byWidget[w.annotObjectNumber] = i;
23
+ });
24
+ return {
25
+ byKey,
26
+ byWidget
27
+ };
28
+ }
29
+ function update(model, msg) {
30
+ switch (msg.t) {
31
+ case "snapshot": return {
32
+ ...model,
33
+ snapshot: msg.snapshot,
34
+ ...index(msg.snapshot),
35
+ writing: {},
36
+ seq: model.seq + 1
37
+ };
38
+ case "writeStart": return {
39
+ ...model,
40
+ writing: {
41
+ ...model.writing,
42
+ [msg.key]: true
43
+ },
44
+ seq: model.seq + 1
45
+ };
46
+ case "writeDone": {
47
+ if (!model.snapshot) return model;
48
+ const i = model.byKey[msg.key];
49
+ if (i === void 0) return model;
50
+ const fields = model.snapshot.fields.slice();
51
+ fields[i] = msg.field;
52
+ const { [msg.key]: _done, ...writing } = model.writing;
53
+ const snapshot = {
54
+ ...model.snapshot,
55
+ fields
56
+ };
57
+ return {
58
+ ...model,
59
+ snapshot,
60
+ ...index(snapshot),
61
+ writing,
62
+ seq: model.seq + 1
63
+ };
64
+ }
65
+ case "writeFailed": {
66
+ const { [msg.key]: _failed, ...writing } = model.writing;
67
+ return {
68
+ ...model,
69
+ writing,
70
+ seq: model.seq + 1
71
+ };
72
+ }
73
+ case "pageGeom": return {
74
+ ...model,
75
+ geom: {
76
+ ...model.geom,
77
+ [msg.pageObjectNumber]: msg.boxes
78
+ },
79
+ seq: model.seq + 1
80
+ };
81
+ case "clearGeom": {
82
+ if (msg.pageObjectNumber === void 0) return {
83
+ ...model,
84
+ geom: {},
85
+ seq: model.seq + 1
86
+ };
87
+ const geom = { ...model.geom };
88
+ delete geom[msg.pageObjectNumber];
89
+ return {
90
+ ...model,
91
+ geom,
92
+ seq: model.seq + 1
93
+ };
94
+ }
95
+ }
96
+ }
97
+ const fieldByKey = (model, key) => {
98
+ const i = model.byKey[key];
99
+ return i === void 0 ? null : model.snapshot?.fields[i] ?? null;
100
+ };
101
+ const fieldForWidget = (model, annotObjectNumber) => {
102
+ const i = model.byWidget[annotObjectNumber];
103
+ return i === void 0 ? null : model.snapshot?.fields[i] ?? null;
104
+ };
105
+ //#endregion
106
+ //#region src/core/fill-items.ts
107
+ const ZERO_BOX = {
108
+ x: 0,
109
+ y: 0,
110
+ width: 0,
111
+ height: 0
112
+ };
113
+ /**
114
+ * Project ONE widget of a field into a fill control. `box` is supplied by the
115
+ * caller: the page projection reads the model's widget geometry; a consumer
116
+ * that already owns a live box (the annotation plane's RenderItem) passes it —
117
+ * or nothing, when only the semantics matter. Null for families with no fill
118
+ * control (signature/unknown: rendered by the annotation plane only).
119
+ */
120
+ function projectWidget(model, field, annotObjectNumber, box = ZERO_BOX) {
121
+ const key = fieldKeyOf(field);
122
+ const base = {
123
+ key,
124
+ annotObjectNumber,
125
+ box,
126
+ disabled: field.flags.readOnly || model.writing[key] === true,
127
+ label: field.alternateName ?? field.name
128
+ };
129
+ switch (field.family) {
130
+ case "text": return {
131
+ ...base,
132
+ control: "text",
133
+ value: field.value,
134
+ multiline: field.multiline,
135
+ password: field.password,
136
+ maxLength: field.maxLength,
137
+ comb: field.comb
138
+ };
139
+ case "checkbox": {
140
+ const toggle = field.widgets.find((w) => w.annotObjectNumber === annotObjectNumber);
141
+ return {
142
+ ...base,
143
+ control: "toggle",
144
+ kind: "checkbox",
145
+ checked: field.checked,
146
+ onState: toggle && "onState" in toggle ? toggle.onState : "Yes"
147
+ };
148
+ }
149
+ case "radio": {
150
+ const toggle = field.widgets.find((w) => w.annotObjectNumber === annotObjectNumber);
151
+ return {
152
+ ...base,
153
+ control: "toggle",
154
+ kind: "radio",
155
+ checked: toggle && "checked" in toggle ? toggle.checked : false,
156
+ onState: toggle && "onState" in toggle ? toggle.onState : ""
157
+ };
158
+ }
159
+ case "combobox": return {
160
+ ...base,
161
+ control: "choice",
162
+ kind: "combo",
163
+ edit: field.edit,
164
+ multi: false,
165
+ options: field.options,
166
+ selected: field.value === "" ? [] : [field.value]
167
+ };
168
+ case "listbox": return {
169
+ ...base,
170
+ control: "choice",
171
+ kind: "list",
172
+ edit: false,
173
+ multi: field.multiSelect,
174
+ options: field.options,
175
+ selected: field.selectedValues
176
+ };
177
+ case "pushbutton": return {
178
+ ...base,
179
+ control: "button"
180
+ };
181
+ default: return null;
182
+ }
183
+ }
184
+ /**
185
+ * Project one page's widgets into fill controls. Widgets whose geometry has
186
+ * not arrived yet (or that are direct objects with no join key) are skipped —
187
+ * the shell re-runs the projection when `pageGeom` lands.
188
+ */
189
+ function fillItems(model, pageObjectNumber) {
190
+ const snapshot = model.snapshot;
191
+ const geom = model.geom[pageObjectNumber];
192
+ if (!snapshot || !geom) return [];
193
+ const items = [];
194
+ for (const field of snapshot.fields) for (const widget of field.widgets) {
195
+ if (widget.pageObjectNumber !== pageObjectNumber) continue;
196
+ const box = geom[widget.annotObjectNumber];
197
+ if (!box) continue;
198
+ const item = projectWidget(model, field, widget.annotObjectNumber, box);
199
+ if (item) items.push(item);
200
+ }
201
+ return items;
202
+ }
203
+ /**
204
+ * Project a SINGLE widget by its annotation object number — the join the
205
+ * annotation-plane render layer uses (it owns a live box already, so the
206
+ * model's cached geometry is used only when it happens to be loaded; the
207
+ * item's semantics never depend on it). Null while the snapshot hasn't
208
+ * landed, or for families with no fill control.
209
+ */
210
+ function fillItemForWidget(model, annotObjectNumber) {
211
+ const field = fieldForWidget(model, annotObjectNumber);
212
+ if (!field) return null;
213
+ const widget = field.widgets.find((w) => w.annotObjectNumber === annotObjectNumber);
214
+ if (!widget) return null;
215
+ const box = model.geom[widget.pageObjectNumber]?.[annotObjectNumber];
216
+ return projectWidget(model, field, annotObjectNumber, box);
217
+ }
218
+ //#endregion
219
+ //#region src/mutationQueue.ts
220
+ /** Small promise-tail queue: failures never poison later mutations. */
221
+ function createSerialMutationQueue() {
222
+ let tail = Promise.resolve();
223
+ return (operation) => {
224
+ const result = tail.then(operation, operation);
225
+ tail = result.then(() => void 0, () => void 0);
226
+ return result;
227
+ };
228
+ }
229
+ //#endregion
230
+ //#region src/scripting.ts
231
+ const refKey = (ref) => ref.kind === "objectNumber" ? `obj:${ref.fieldObjectNumber}` : `fqn:${ref.name}`;
232
+ const sameRef = (left, right) => refKey(left) === refKey(right);
233
+ const cloneValue = (value) => Array.isArray(value) ? [...value] : value;
234
+ const sameValue = (left, right) => Array.isArray(left) && Array.isArray(right) ? left.length === right.length && left.every((value, index) => value === right[index]) : left === right;
235
+ function cloneFields(fields) {
236
+ return fields.map((field) => ({
237
+ ...field,
238
+ ref: { ...field.ref },
239
+ value: cloneValue(field.value),
240
+ defaultValue: cloneValue(field.defaultValue),
241
+ ...field.options ? { options: field.options.map((option) => ({ ...option })) } : {}
242
+ }));
243
+ }
244
+ function fieldByRef(fields, ref) {
245
+ return fields.find((field) => sameRef(field.ref, ref));
246
+ }
247
+ function snapshotField(snapshot, ref) {
248
+ return snapshot.fields.find((field) => sameRef(field.ref, ref));
249
+ }
250
+ function scriptValueFromFormValue(field, value) {
251
+ if (field.family === "text" && value.type === "text") return value.value;
252
+ if ((field.family === "checkbox" || field.family === "radio") && value.type === "toggle") return value.state ?? "Off";
253
+ if (field.family === "combobox" && value.type === "choice") return value.values[0] ?? "";
254
+ if (field.family === "listbox" && value.type === "choice") return [...value.values];
255
+ throw new Error(`Form value type '${value.type}' does not match field family '${field.family}'`);
256
+ }
257
+ function formValueFromScriptValue(field) {
258
+ switch (field.family) {
259
+ case "text": return {
260
+ type: "text",
261
+ value: String(field.value ?? "")
262
+ };
263
+ case "checkbox":
264
+ case "radio": return {
265
+ type: "toggle",
266
+ state: field.value === null || field.value === void 0 || String(field.value) === "Off" ? null : String(field.value)
267
+ };
268
+ case "combobox": return {
269
+ type: "choice",
270
+ values: Array.isArray(field.value) ? field.value.slice(0, 1) : [String(field.value ?? "")]
271
+ };
272
+ case "listbox": return {
273
+ type: "choice",
274
+ values: Array.isArray(field.value) ? [...field.value] : [String(field.value ?? "")]
275
+ };
276
+ default: return null;
277
+ }
278
+ }
279
+ function applyEffects(overlay, effects) {
280
+ for (const effect of effects) {
281
+ if (effect.kind === "reset") {
282
+ for (const ref of effect.refs) {
283
+ const field = fieldByRef(overlay.fields, ref);
284
+ if (!field) continue;
285
+ field.value = cloneValue(field.defaultValue);
286
+ overlay.resetKeys.add(refKey(ref));
287
+ }
288
+ continue;
289
+ }
290
+ const field = fieldByRef(overlay.fields, effect.ref);
291
+ if (!field) continue;
292
+ const key = refKey(effect.ref);
293
+ if (effect.kind === "setValue") {
294
+ field.value = scriptValueFromFormValue(field, effect.value);
295
+ overlay.resetKeys.delete(key);
296
+ } else if (effect.kind === "setDisplay") field.display = effect.display;
297
+ else overlay.appearances.set(key, {
298
+ ref: effect.ref,
299
+ text: effect.text
300
+ });
301
+ }
302
+ }
303
+ function canonicalEffects(overlay) {
304
+ const effects = [];
305
+ const resets = [];
306
+ for (const field of overlay.fields) {
307
+ const original = fieldByRef(overlay.original, field.ref);
308
+ if (!original) continue;
309
+ if (!sameValue(original.value, field.value)) {
310
+ const key = refKey(field.ref);
311
+ if (overlay.resetKeys.has(key) && sameValue(field.value, field.defaultValue)) resets.push(field.ref);
312
+ else {
313
+ const value = formValueFromScriptValue(field);
314
+ if (value) effects.push({
315
+ kind: "setValue",
316
+ ref: field.ref,
317
+ value
318
+ });
319
+ }
320
+ }
321
+ if (original.display !== field.display) effects.push({
322
+ kind: "setDisplay",
323
+ ref: field.ref,
324
+ display: field.display
325
+ });
326
+ }
327
+ if (resets.length > 0) effects.unshift({
328
+ kind: "reset",
329
+ refs: resets
330
+ });
331
+ effects.push(...Array.from(overlay.appearances.values(), ({ ref, text }) => ({
332
+ kind: "setAppearanceText",
333
+ ref,
334
+ text
335
+ })));
336
+ return effects;
337
+ }
338
+ function scriptError(message) {
339
+ return {
340
+ kind: "invalid-output",
341
+ message
342
+ };
343
+ }
344
+ function utf8Length(value) {
345
+ let length = 0;
346
+ for (let index = 0; index < value.length; index += 1) {
347
+ const code = value.charCodeAt(index);
348
+ if (code < 128) length += 1;
349
+ else if (code < 2048) length += 2;
350
+ else if (code >= 55296 && code <= 56319 && index + 1 < value.length) {
351
+ length += 4;
352
+ index += 1;
353
+ } else length += 3;
354
+ }
355
+ return length;
356
+ }
357
+ function seedFrom(documentId, sequence) {
358
+ let hash = 2166136261;
359
+ for (const char of `${documentId}:${sequence}`) {
360
+ hash ^= char.charCodeAt(0);
361
+ hash = Math.imul(hash, 16777619);
362
+ }
363
+ return hash >>> 0;
364
+ }
365
+ function resolvedIdentity(doc, config) {
366
+ const claims = doc.security.identity;
367
+ const supplied = typeof config.identity === "function" ? config.identity() : config.identity ?? {};
368
+ return {
369
+ name: supplied.name ?? claims?.display_name ?? claims?.user_id ?? "",
370
+ loginName: supplied.loginName ?? claims?.user_id ?? "",
371
+ corporation: supplied.corporation ?? claims?.group_id ?? "",
372
+ email: supplied.email ?? ""
373
+ };
374
+ }
375
+ function pageNumberFor(meta, field) {
376
+ const pon = field.widgets.find((widget) => widget.pageObjectNumber > 0)?.pageObjectNumber;
377
+ if (!meta || pon === void 0) return 0;
378
+ const index = meta.pages.findIndex((page) => page.pageObjectNumber === pon);
379
+ return Math.max(0, index);
380
+ }
381
+ function statusFromEffects(result) {
382
+ if (result.results.some(({ status }) => status === "failed" || status === "skipped")) return "failed";
383
+ if (result.results.some(({ status }) => status === "rejected")) return "failed";
384
+ return result.results.some(({ status }) => status === "applied") ? "applied" : "unchanged";
385
+ }
386
+ var FormScriptingController = class {
387
+ constructor(options) {
388
+ this.options = options;
389
+ this.sandboxPromise = null;
390
+ this.booted = false;
391
+ this.disposed = false;
392
+ this.sequence = 0;
393
+ }
394
+ dispose() {
395
+ if (this.disposed) return;
396
+ this.disposed = true;
397
+ this.sandboxPromise?.then((sandbox) => sandbox.dispose()).catch(() => void 0);
398
+ }
399
+ async commit(snapshot, ref, proposed) {
400
+ return this.transact(snapshot, ref, proposed);
401
+ }
402
+ /** Execute one originating widget's activation action (`/A`, including `/Next`). */
403
+ async activate(snapshot, ref, action) {
404
+ return this.transact(snapshot, ref, void 0, action);
405
+ }
406
+ /** Run lazy document boot plus the `/CO` chain without a user field change. */
407
+ async recalculate(snapshot) {
408
+ const target = snapshot.calculationOrder.find((ref) => ref !== null && snapshotField(snapshot, ref) !== void 0) ?? snapshot.fields[0]?.ref;
409
+ if (!target) return {
410
+ status: "unchanged",
411
+ scripted: true,
412
+ effectsResult: null,
413
+ uiEffects: [],
414
+ diagnostics: []
415
+ };
416
+ return this.transact(snapshot, target);
417
+ }
418
+ async transact(snapshot, ref, proposed, activation) {
419
+ if (this.disposed) throw new Error("Form scripting controller is disposed");
420
+ const target = snapshotField(snapshot, ref);
421
+ if (!target) return this.failed([], [], scriptError(`Form field '${refKey(ref)}' no longer exists`));
422
+ const original = (0, _embedpdf_core_acrojs.scriptFieldsFromSnapshot)(snapshot);
423
+ const overlay = {
424
+ original,
425
+ fields: cloneFields(original),
426
+ resetKeys: /* @__PURE__ */ new Set(),
427
+ appearances: /* @__PURE__ */ new Map()
428
+ };
429
+ const targetInput = fieldByRef(overlay.fields, ref);
430
+ if (!targetInput) return this.failed([], [], scriptError(`Form field '${refKey(ref)}' has no script view`));
431
+ const hasProposedValue = proposed !== void 0;
432
+ let proposedValue = cloneValue(targetInput.value);
433
+ if (proposed) try {
434
+ proposedValue = scriptValueFromFormValue(targetInput, proposed);
435
+ } catch (error) {
436
+ return this.failed([], [], scriptError(error instanceof Error ? error.message : String(error)));
437
+ }
438
+ const uiEffects = [];
439
+ const diagnostics = [];
440
+ const meta = this.options.document();
441
+ const nowMs = this.options.config.now?.() ?? Date.now();
442
+ const inputBase = {
443
+ document: {
444
+ id: this.options.doc.id,
445
+ fileName: this.options.config.fileName?.() ?? meta?.name ?? this.options.doc.id,
446
+ pageCount: meta?.pageCount ?? 0,
447
+ pageNumber: pageNumberFor(meta, target)
448
+ },
449
+ identity: resolvedIdentity(this.options.doc, this.options.config),
450
+ environment: {
451
+ nowMs,
452
+ utcOffsetMinutes: this.options.config.utcOffsetMinutes?.() ?? -new Date(nowMs).getTimezoneOffset(),
453
+ randomSeed: this.options.config.randomSeed?.() ?? seedFrom(this.options.doc.id, this.sequence++)
454
+ }
455
+ };
456
+ const budget = this.options.config.budget ?? _embedpdf_core_acrojs.DEFAULT_SCRIPT_BUDGET;
457
+ let executionMs = 0;
458
+ let aggregateOutputSize = 0;
459
+ const consume = (output, phase) => {
460
+ aggregateOutputSize += utf8Length(JSON.stringify(output));
461
+ uiEffects.push(...output.uiEffects.map((effect) => ({
462
+ ...effect,
463
+ phase
464
+ })));
465
+ diagnostics.push(...output.diagnostics);
466
+ if (aggregateOutputSize > budget.maxOutputBytes) return {
467
+ kind: "budget",
468
+ message: `Form script transaction output exceeded ${budget.maxOutputBytes} bytes`
469
+ };
470
+ return output.error ?? null;
471
+ };
472
+ const remainingBudget = () => {
473
+ const remaining = budget.maxExecutionMs - executionMs;
474
+ return remaining <= 0 ? null : {
475
+ ...budget,
476
+ maxExecutionMs: remaining
477
+ };
478
+ };
479
+ const run = async (kind, source, input) => {
480
+ const remaining = remainingBudget();
481
+ if (!remaining) return { error: {
482
+ kind: "budget",
483
+ message: "Form script transaction timed out"
484
+ } };
485
+ let output;
486
+ try {
487
+ const sandbox = await this.sandbox();
488
+ const startedAt = Date.now();
489
+ output = kind === "boot" ? sandbox.boot(source, input, remaining) : sandbox.run(source, input, remaining);
490
+ executionMs += Date.now() - startedAt;
491
+ } catch (error) {
492
+ return { error: scriptError(error instanceof Error ? error.message : String(error)) };
493
+ }
494
+ const error = consume(output, kind === "boot" ? "boot" : "user");
495
+ return error ? { error } : { output };
496
+ };
497
+ if (!this.booted) {
498
+ this.booted = true;
499
+ let sources = [];
500
+ let bootError = null;
501
+ try {
502
+ sources = (this.options.doc.actions ? await this.options.doc.actions.read() : null)?.nameTreeScripts.map(({ action }) => (0, _embedpdf_core_acrojs.javaScriptProgramFromActionTree)(action)) ?? [];
503
+ } catch (error) {
504
+ bootError = scriptError(error instanceof Error ? error.message : String(error));
505
+ }
506
+ if (!bootError && sources.length > 0) {
507
+ const boot = await run("boot", sources, {
508
+ ...inputBase,
509
+ fields: overlay.fields,
510
+ event: { kind: "name-tree-boot" }
511
+ });
512
+ if (boot.error) bootError = boot.error;
513
+ else applyEffects(overlay, boot.output.formEffects);
514
+ }
515
+ if (bootError) diagnostics.push({
516
+ code: "script-error",
517
+ message: `Document boot script failed (continuing without it): ${bootError.message}`
518
+ });
519
+ }
520
+ const bootEffects = canonicalEffects(overlay);
521
+ if (activation) {
522
+ let program;
523
+ try {
524
+ program = (0, _embedpdf_core_acrojs.javaScriptProgramFromActionTree)(activation);
525
+ } catch (error) {
526
+ return this.failed(uiEffects, diagnostics, scriptError(error instanceof Error ? error.message : String(error)));
527
+ }
528
+ if (program) {
529
+ const activated = await run("run", program, {
530
+ ...inputBase,
531
+ fields: overlay.fields,
532
+ event: {
533
+ kind: "widget-activate",
534
+ target: ref,
535
+ source: ref,
536
+ value: targetInput.value
537
+ }
538
+ });
539
+ if (activated.error) return this.failed(uiEffects, diagnostics, activated.error);
540
+ applyEffects(overlay, activated.output.formEffects);
541
+ }
542
+ }
543
+ if (!activation && hasProposedValue && target.actions?.keystroke && target.family === "text") {
544
+ let program;
545
+ try {
546
+ program = (0, _embedpdf_core_acrojs.javaScriptProgramFromActionTree)(target.actions.keystroke);
547
+ } catch (error) {
548
+ return this.failed(uiEffects, diagnostics, scriptError(error instanceof Error ? error.message : String(error)));
549
+ }
550
+ if (program) {
551
+ const oldValue = String(targetInput.value ?? "");
552
+ const key = await run("run", program, {
553
+ ...inputBase,
554
+ fields: overlay.fields,
555
+ event: {
556
+ kind: "field-keystroke",
557
+ target: ref,
558
+ source: ref,
559
+ value: oldValue,
560
+ change: String(proposedValue ?? ""),
561
+ selStart: 0,
562
+ selEnd: oldValue.length,
563
+ willCommit: true
564
+ }
565
+ });
566
+ if (key.error) return this.failed(uiEffects, diagnostics, key.error);
567
+ if (!key.output.event.rc) return this.finishRejected(bootEffects, uiEffects, diagnostics);
568
+ applyEffects(overlay, key.output.formEffects);
569
+ const event = key.output.event;
570
+ const base = String(event.value ?? "");
571
+ proposedValue = base.slice(0, event.selStart) + event.change + base.slice(Math.max(event.selStart, event.selEnd));
572
+ }
573
+ }
574
+ if (!activation && hasProposedValue) {
575
+ targetInput.value = cloneValue(proposedValue);
576
+ overlay.resetKeys.delete(refKey(ref));
577
+ }
578
+ if (!activation && hasProposedValue && target.actions?.validate) {
579
+ let program;
580
+ try {
581
+ program = (0, _embedpdf_core_acrojs.javaScriptProgramFromActionTree)(target.actions.validate);
582
+ } catch (error) {
583
+ return this.failed(uiEffects, diagnostics, scriptError(error instanceof Error ? error.message : String(error)));
584
+ }
585
+ if (program) {
586
+ const validation = await run("run", program, {
587
+ ...inputBase,
588
+ fields: overlay.fields,
589
+ event: {
590
+ kind: "field-validate",
591
+ target: ref,
592
+ source: ref,
593
+ value: proposedValue,
594
+ willCommit: true
595
+ }
596
+ });
597
+ if (validation.error) return this.failed(uiEffects, diagnostics, validation.error);
598
+ if (!validation.output.event.rc) return this.finishRejected(bootEffects, uiEffects, diagnostics);
599
+ targetInput.value = cloneValue(validation.output.event.value);
600
+ applyEffects(overlay, validation.output.formEffects);
601
+ }
602
+ }
603
+ const formatRefs = !activation && hasProposedValue ? [ref] : [];
604
+ for (const calculationRef of activation ? [] : snapshot.calculationOrder) {
605
+ if (!calculationRef) continue;
606
+ const calculated = snapshotField(snapshot, calculationRef);
607
+ const tree = calculated?.actions?.calculate;
608
+ if (!calculated || !tree) continue;
609
+ let program;
610
+ try {
611
+ program = (0, _embedpdf_core_acrojs.javaScriptProgramFromActionTree)(tree);
612
+ } catch (error) {
613
+ return this.failed(uiEffects, diagnostics, scriptError(error instanceof Error ? error.message : String(error)));
614
+ }
615
+ const calculatedInput = fieldByRef(overlay.fields, calculationRef);
616
+ if (program && calculatedInput) {
617
+ const calculation = await run("run", program, {
618
+ ...inputBase,
619
+ fields: overlay.fields,
620
+ event: {
621
+ kind: "field-calculate",
622
+ target: calculationRef,
623
+ ...hasProposedValue ? { source: ref } : {},
624
+ value: calculatedInput.value
625
+ }
626
+ });
627
+ if (calculation.error) return this.failed(uiEffects, diagnostics, calculation.error);
628
+ applyEffects(overlay, calculation.output.formEffects);
629
+ }
630
+ if (!formatRefs.some((candidate) => sameRef(candidate, calculationRef))) formatRefs.push(calculationRef);
631
+ }
632
+ for (const formatRef of formatRefs) {
633
+ const field = snapshotField(snapshot, formatRef);
634
+ const tree = field?.actions?.format;
635
+ const overlayField = fieldByRef(overlay.fields, formatRef);
636
+ if (!field || !tree || !overlayField) continue;
637
+ let program;
638
+ try {
639
+ program = (0, _embedpdf_core_acrojs.javaScriptProgramFromActionTree)(tree);
640
+ } catch (error) {
641
+ return this.failed(uiEffects, diagnostics, scriptError(error instanceof Error ? error.message : String(error)));
642
+ }
643
+ if (!program) continue;
644
+ const format = await run("run", program, {
645
+ ...inputBase,
646
+ fields: overlay.fields,
647
+ event: {
648
+ kind: "field-format",
649
+ target: formatRef,
650
+ ...hasProposedValue ? { source: ref } : {},
651
+ value: overlayField.value
652
+ }
653
+ });
654
+ if (format.error) return this.failed(uiEffects, diagnostics, format.error);
655
+ applyEffects(overlay, format.output.formEffects);
656
+ }
657
+ const effects = canonicalEffects(overlay);
658
+ if (effects.length + uiEffects.length > budget.maxEffects) return this.failed(uiEffects, diagnostics, {
659
+ kind: "budget",
660
+ message: `Form script transaction exceeded ${budget.maxEffects} effects`
661
+ });
662
+ if (effects.length === 0) return {
663
+ status: "unchanged",
664
+ scripted: true,
665
+ effectsResult: null,
666
+ uiEffects,
667
+ diagnostics
668
+ };
669
+ if (!this.options.doc.forms.applyEffects) return this.failed(uiEffects, diagnostics, scriptError("This engine does not support batched form effects"));
670
+ const effectsResult = await this.options.doc.forms.applyEffects(effects);
671
+ const status = statusFromEffects(effectsResult);
672
+ return {
673
+ status,
674
+ scripted: true,
675
+ effectsResult,
676
+ uiEffects,
677
+ diagnostics,
678
+ ...status === "failed" ? { error: scriptError("One or more native form effects failed") } : {}
679
+ };
680
+ }
681
+ async sandbox() {
682
+ this.sandboxPromise ?? (this.sandboxPromise = this.options.sandboxFactory().then((sandbox) => {
683
+ if (this.disposed) sandbox.dispose();
684
+ return sandbox;
685
+ }));
686
+ return this.sandboxPromise;
687
+ }
688
+ failed(uiEffects, diagnostics, error) {
689
+ return {
690
+ status: "failed",
691
+ scripted: true,
692
+ effectsResult: null,
693
+ uiEffects,
694
+ diagnostics,
695
+ error
696
+ };
697
+ }
698
+ async finishRejected(bootEffects, uiEffects, diagnostics) {
699
+ if (bootEffects.length === 0) return {
700
+ status: "rejected",
701
+ scripted: true,
702
+ effectsResult: null,
703
+ uiEffects,
704
+ diagnostics
705
+ };
706
+ if (!this.options.doc.forms.applyEffects) return this.failed(uiEffects, diagnostics, scriptError("Batched form effects are unavailable"));
707
+ const effectsResult = await this.options.doc.forms.applyEffects(bootEffects);
708
+ if (statusFromEffects(effectsResult) === "failed") return this.failed(uiEffects, diagnostics, scriptError("A name-tree boot effect failed"));
709
+ return {
710
+ status: "rejected",
711
+ scripted: true,
712
+ effectsResult,
713
+ uiEffects,
714
+ diagnostics
715
+ };
716
+ }
717
+ };
718
+ function createFormScriptingController(options) {
719
+ return new FormScriptingController(options);
720
+ }
721
+ //#endregion
722
+ //#region src/capability.ts
723
+ /** PDF user-space rect (y-up) → content-space box (y-down, crop-relative). */
724
+ const toBox = (rect, crop) => ({
725
+ x: rect.left - crop.left,
726
+ y: crop.top - rect.top,
727
+ width: rect.right - rect.left,
728
+ height: rect.top - rect.bottom
729
+ });
730
+ const sameAnnotationRef = (left, right) => {
731
+ if (left.kind !== right.kind || left.pageObjectNumber !== right.pageObjectNumber) return false;
732
+ if (left.kind === "objectNumber" && right.kind === "objectNumber") return left.annotObjectNumber === right.annotObjectNumber;
733
+ if (left.kind === "nm" && right.kind === "nm") return left.nm === right.nm;
734
+ return left.kind === "index" && right.kind === "index" && left.index === right.index && left.revision === right.revision;
735
+ };
736
+ /**
737
+ * The form shell. Pure `update` runs here; the resulting model is dispatched
738
+ * to the store; engine calls happen around it. Every read the frameworks do
739
+ * goes through memoized projections keyed on `model.seq`.
740
+ */
741
+ function createFormCapability(ctx, options = {}) {
742
+ const model = () => ctx.getState().model;
743
+ const apply = (msg) => {
744
+ ctx.dispatch({
745
+ type: "SET_MODEL",
746
+ model: update(model(), msg)
747
+ });
748
+ };
749
+ const refKeyOf = (key) => {
750
+ if (key.startsWith("obj:")) return {
751
+ kind: "objectNumber",
752
+ fieldObjectNumber: Number(key.slice(4))
753
+ };
754
+ return {
755
+ kind: "fqn",
756
+ name: key.slice(4)
757
+ };
758
+ };
759
+ const enqueueMutation = createSerialMutationQueue();
760
+ const scripting = options.scripting?.enabled && ctx.doc ? createFormScriptingController({
761
+ doc: ctx.doc,
762
+ document: () => ctx.document(),
763
+ config: options.scripting,
764
+ sandboxFactory: options.scripting.sandboxFactory ?? (() => import("@embedpdf/core-js-sandbox").then(({ createQuickJsSandbox }) => createQuickJsSandbox()))
765
+ }) : null;
766
+ if (scripting) ctx.cleanup(() => scripting.dispose());
767
+ let uiEffectProvider = null;
768
+ const surfaceScriptingResult = (result) => {
769
+ const observe = (callback) => {
770
+ if (!callback) return;
771
+ try {
772
+ callback();
773
+ } catch (error) {
774
+ globalThis.console?.error("[form] scripting observer failed:", error);
775
+ }
776
+ };
777
+ for (const effect of result.uiEffects) {
778
+ observe(options.scripting?.onUiEffect ? () => options.scripting.onUiEffect(effect) : void 0);
779
+ observe(uiEffectProvider ? () => uiEffectProvider(effect) : void 0);
780
+ }
781
+ for (const diagnostic of result.diagnostics) observe(options.scripting?.onDiagnostic ? () => options.scripting.onDiagnostic(diagnostic) : void 0);
782
+ if (result.error) observe(options.scripting?.onError ? () => options.scripting.onError(result.error) : void 0);
783
+ };
784
+ let refreshPromise = null;
785
+ const refresh = async (force = false) => {
786
+ const doc = ctx.doc;
787
+ if (!doc) return;
788
+ if (refreshPromise) {
789
+ await refreshPromise;
790
+ if (!force) return;
791
+ }
792
+ refreshPromise = doc.forms.list().then((snapshot) => apply({
793
+ t: "snapshot",
794
+ snapshot
795
+ })).finally(() => {
796
+ refreshPromise = null;
797
+ });
798
+ return refreshPromise;
799
+ };
800
+ const geomLoading = /* @__PURE__ */ new Set();
801
+ const ensureGeom = (pon) => {
802
+ const doc = ctx.doc;
803
+ if (!doc || geomLoading.has(pon) || model().geom[pon]) return;
804
+ const crop = ctx.document()?.pages.find((p) => p.pageObjectNumber === pon)?.boxes.crop;
805
+ if (!crop) return;
806
+ geomLoading.add(pon);
807
+ doc.page(pon).annotations.list().then(({ annotations }) => {
808
+ const boxes = {};
809
+ for (const dto of annotations) {
810
+ if (dto.subtype !== "widget") continue;
811
+ const objectNumber = dto.ref.kind === "objectNumber" ? dto.ref.annotObjectNumber : 0;
812
+ if (objectNumber > 0) boxes[objectNumber] = toBox(dto.rect, crop);
813
+ }
814
+ apply({
815
+ t: "pageGeom",
816
+ pageObjectNumber: pon,
817
+ boxes
818
+ });
819
+ }).finally(() => {
820
+ geomLoading.delete(pon);
821
+ });
822
+ };
823
+ const fillCache = /* @__PURE__ */ new Map();
824
+ const fillItems$1 = (pon) => {
825
+ const m = model();
826
+ const hit = fillCache.get(pon);
827
+ if (hit && hit.seq === m.seq) return hit.items;
828
+ const items = fillItems(m, pon);
829
+ fillCache.set(pon, {
830
+ seq: m.seq,
831
+ items
832
+ });
833
+ return items;
834
+ };
835
+ const fillItemCache = /* @__PURE__ */ new Map();
836
+ const fillItem = (annotObjectNumber) => {
837
+ const m = model();
838
+ const hit = fillItemCache.get(annotObjectNumber);
839
+ if (hit && hit.seq === m.seq) return hit.item;
840
+ const item = fillItemForWidget(m, annotObjectNumber);
841
+ fillItemCache.set(annotObjectNumber, {
842
+ seq: m.seq,
843
+ item
844
+ });
845
+ return item;
846
+ };
847
+ const commitValueNow = async (ref, value) => {
848
+ const doc = ctx.doc;
849
+ if (!doc) throw new Error("no document");
850
+ if (scripting) {
851
+ const result = await scripting.commit(await doc.forms.list(), ref, value);
852
+ surfaceScriptingResult(result);
853
+ if (result.effectsResult !== null) await refresh(true);
854
+ return result;
855
+ }
856
+ const result = await doc.forms.setValue(ref, value);
857
+ await refresh(true);
858
+ return {
859
+ status: result.changedWidgets.length > 0 ? "applied" : "unchanged",
860
+ scripted: false,
861
+ effectsResult: null,
862
+ uiEffects: [],
863
+ diagnostics: []
864
+ };
865
+ };
866
+ const write = (key, value) => enqueueMutation(async () => {
867
+ if (!ctx.doc) return;
868
+ apply({
869
+ t: "writeStart",
870
+ key
871
+ });
872
+ try {
873
+ const result = await commitValueNow(refKeyOf(key), value);
874
+ if (result.status === "rejected" || result.status === "failed") apply({
875
+ t: "writeFailed",
876
+ key
877
+ });
878
+ else if (result.effectsResult === null && result.scripted) apply({
879
+ t: "writeFailed",
880
+ key
881
+ });
882
+ } catch (err) {
883
+ apply({
884
+ t: "writeFailed",
885
+ key
886
+ });
887
+ throw err;
888
+ }
889
+ });
890
+ const can = (cap) => ctx.doc?.security.allows(cap) ?? false;
891
+ const annotationHost = ctx.tryGet(_embedpdf_plugin_annotation_internal.AnnotationToken);
892
+ const annotationActivation = async (ref) => {
893
+ const doc = ctx.doc;
894
+ if (!doc) return null;
895
+ const loaded = annotationHost?.get(ref);
896
+ if (loaded?.subtype === "widget") return loaded.actions?.activate ?? null;
897
+ const { annotations } = await doc.page(ref.pageObjectNumber).annotations.list();
898
+ const annotation = annotations.find((candidate) => sameAnnotationRef(candidate.ref, ref));
899
+ return annotation?.subtype === "widget" ? annotation.actions?.activate ?? null : null;
900
+ };
901
+ const activateWidgetNow = async (key, annotationRef) => {
902
+ const doc = ctx.doc;
903
+ if (!doc) throw new Error("no document");
904
+ if (!scripting) return {
905
+ status: "unchanged",
906
+ scripted: false,
907
+ effectsResult: null,
908
+ uiEffects: [],
909
+ diagnostics: []
910
+ };
911
+ const action = await annotationActivation(annotationRef);
912
+ if (!action) return {
913
+ status: "unchanged",
914
+ scripted: true,
915
+ effectsResult: null,
916
+ uiEffects: [],
917
+ diagnostics: []
918
+ };
919
+ const result = await scripting.activate(await doc.forms.list(), refKeyOf(key), action);
920
+ surfaceScriptingResult(result);
921
+ if (result.effectsResult !== null) await refresh(true);
922
+ return result;
923
+ };
924
+ const nudgeAnnotations = (pons) => {
925
+ if (!annotationHost) return;
926
+ for (const pon of new Set(pons)) annotationHost.reloadPage(pon);
927
+ };
928
+ /** Content-space box → PDF rect (inverse of `toBox`). */
929
+ const toPdfRect = (box, crop) => ({
930
+ left: box.x + crop.left,
931
+ top: crop.top - box.y,
932
+ right: box.x + crop.left + box.width,
933
+ bottom: crop.top - box.y - box.height
934
+ });
935
+ /** The page's content box (`{0,0,w,h}`), for page-bound placement math. */
936
+ const pageBox = (pon) => {
937
+ const crop = ctx.document()?.pages.find((p) => p.pageObjectNumber === pon)?.boxes.crop;
938
+ return crop ? {
939
+ x: 0,
940
+ y: 0,
941
+ width: crop.right - crop.left,
942
+ height: crop.top - crop.bottom
943
+ } : null;
944
+ };
945
+ /** Deterministic, collision-free auto-name: `text_1`, `text_2`, … counted
946
+ * against the CURRENT snapshot (rename in the field panel). */
947
+ const autoName = (family) => {
948
+ const names = new Set((model().snapshot?.fields ?? []).map((f) => f.name));
949
+ let n = 1;
950
+ while (names.has(`${family}_${n}`)) n++;
951
+ return `${family}_${n}`;
952
+ };
953
+ const placeFieldNow = async (input) => {
954
+ const doc = ctx.doc;
955
+ const pon = input.pageObjectNumber;
956
+ const crop = ctx.document()?.pages.find((p) => p.pageObjectNumber === pon)?.boxes.crop;
957
+ if (!doc || !crop) throw new Error("[form] placeField: document/page not ready");
958
+ const page = pageBox(pon);
959
+ const x = Math.max(page.x, Math.min(input.box.x, page.width));
960
+ const y = Math.max(page.y, Math.min(input.box.y, page.height));
961
+ const box = {
962
+ x,
963
+ y,
964
+ width: Math.max(0, Math.min(input.box.x + input.box.width, page.width) - x),
965
+ height: Math.max(0, Math.min(input.box.y + input.box.height, page.height) - y)
966
+ };
967
+ if (box.width < 1 || box.height < 1) throw new Error("[form] placeField: degenerate box (size the box before placing)");
968
+ const { family, appearance } = input;
969
+ const name = autoName(family);
970
+ const placement = {
971
+ pageObjectNumber: pon,
972
+ rect: toPdfRect(box, crop),
973
+ ...appearance ? { appearance } : {}
974
+ };
975
+ const draft = family === "radio" ? {
976
+ family,
977
+ name,
978
+ widgets: [{
979
+ ...placement,
980
+ onState: "option1"
981
+ }]
982
+ } : family === "combobox" || family === "listbox" ? {
983
+ family,
984
+ name,
985
+ widget: placement,
986
+ options: [{
987
+ label: "Option 1",
988
+ value: "Option 1"
989
+ }, {
990
+ label: "Option 2",
991
+ value: "Option 2"
992
+ }]
993
+ } : {
994
+ family,
995
+ name,
996
+ widget: placement
997
+ };
998
+ const result = await doc.forms.createField(draft);
999
+ await refresh(true);
1000
+ apply({
1001
+ t: "clearGeom",
1002
+ pageObjectNumber: pon
1003
+ });
1004
+ if (annotationHost) await annotationHost.reloadPage(pon);
1005
+ const widget = result.field.widgets.find((w) => w.pageObjectNumber === pon) ?? null;
1006
+ return {
1007
+ field: result.field,
1008
+ widget
1009
+ };
1010
+ };
1011
+ const updateFieldNow = async (key, patch) => {
1012
+ const doc = ctx.doc;
1013
+ if (!doc) return;
1014
+ await doc.forms.updateField(refKeyOf(key), patch);
1015
+ await refresh(true);
1016
+ };
1017
+ const deleteFieldNow = async (key) => {
1018
+ const doc = ctx.doc;
1019
+ if (!doc) return;
1020
+ const pons = fieldByKey(model(), key)?.widgets.map((w) => w.pageObjectNumber).filter((p) => p > 0) ?? [];
1021
+ await doc.forms.deleteField(refKeyOf(key));
1022
+ await refresh(true);
1023
+ for (const pon of new Set(pons)) apply({
1024
+ t: "clearGeom",
1025
+ pageObjectNumber: pon
1026
+ });
1027
+ nudgeAnnotations(pons);
1028
+ };
1029
+ const detachWidgetNow = async (key, annotObjectNumber) => {
1030
+ const doc = ctx.doc;
1031
+ if (!doc) return;
1032
+ const widget = fieldByKey(model(), key)?.widgets.find((w) => w.annotObjectNumber === annotObjectNumber);
1033
+ await doc.forms.detachWidget(refKeyOf(key), {
1034
+ annotObjectNumber,
1035
+ pageObjectNumber: widget?.pageObjectNumber ?? 0
1036
+ });
1037
+ await refresh(true);
1038
+ if (widget && widget.pageObjectNumber > 0) {
1039
+ apply({
1040
+ t: "clearGeom",
1041
+ pageObjectNumber: widget.pageObjectNumber
1042
+ });
1043
+ nudgeAnnotations([widget.pageObjectNumber]);
1044
+ }
1045
+ };
1046
+ refresh();
1047
+ return {
1048
+ snapshot: () => model().snapshot,
1049
+ refresh,
1050
+ fillItems: fillItems$1,
1051
+ fillItem,
1052
+ ensureGeom,
1053
+ field: (key) => fieldByKey(model(), key),
1054
+ fieldForWidget: (annotObjectNumber) => fieldForWidget(model(), annotObjectNumber),
1055
+ setText: (key, value) => write(key, {
1056
+ type: "text",
1057
+ value
1058
+ }),
1059
+ toggle: (key, onState) => write(key, {
1060
+ type: "toggle",
1061
+ state: onState
1062
+ }),
1063
+ choose: (key, values) => write(key, {
1064
+ type: "choice",
1065
+ values
1066
+ }),
1067
+ reset: (key) => enqueueMutation(async () => {
1068
+ const doc = ctx.doc;
1069
+ if (!doc) return;
1070
+ apply({
1071
+ t: "writeStart",
1072
+ key
1073
+ });
1074
+ try {
1075
+ const result = await doc.forms.reset(refKeyOf(key));
1076
+ apply({
1077
+ t: "writeDone",
1078
+ key,
1079
+ field: result.field
1080
+ });
1081
+ } catch (err) {
1082
+ apply({
1083
+ t: "writeFailed",
1084
+ key
1085
+ });
1086
+ throw err;
1087
+ }
1088
+ }),
1089
+ commitValue: (ref, value) => enqueueMutation(() => commitValueNow(ref, value)),
1090
+ activateWidget: (key, annotationRef) => enqueueMutation(() => activateWidgetNow(key, annotationRef)),
1091
+ setUiEffectProvider: (provider) => {
1092
+ uiEffectProvider = provider;
1093
+ },
1094
+ setValue: (ref, value) => enqueueMutation(async () => {
1095
+ const doc = ctx.doc;
1096
+ if (!doc) throw new Error("no document");
1097
+ const result = await doc.forms.setValue(ref, value);
1098
+ await refresh(true);
1099
+ return result;
1100
+ }),
1101
+ exportData: async (format = "xfdf") => {
1102
+ const doc = ctx.doc;
1103
+ if (!doc) throw new Error("no document");
1104
+ return doc.forms.exportData(format);
1105
+ },
1106
+ importData: (data, format) => enqueueMutation(async () => {
1107
+ const doc = ctx.doc;
1108
+ if (!doc) throw new Error("no document");
1109
+ const result = await doc.forms.importData(data, format);
1110
+ apply({
1111
+ t: "snapshot",
1112
+ snapshot: result.snapshot
1113
+ });
1114
+ return result;
1115
+ }),
1116
+ repair: (repairOptions) => enqueueMutation(async () => {
1117
+ const doc = ctx.doc;
1118
+ if (!doc) throw new Error("no document");
1119
+ const result = await doc.forms.repair(repairOptions);
1120
+ await refresh(true);
1121
+ return result;
1122
+ }),
1123
+ placeField: (input) => enqueueMutation(() => placeFieldNow(input)),
1124
+ pageBox,
1125
+ updateField: (key, patch) => enqueueMutation(() => updateFieldNow(key, patch)),
1126
+ deleteField: (key) => enqueueMutation(() => deleteFieldNow(key)),
1127
+ detachWidget: (key, annotObjectNumber) => enqueueMutation(() => detachWidgetNow(key, annotObjectNumber)),
1128
+ canFill: () => can("doc.forms.fill"),
1129
+ canModify: () => can("doc.forms.modify")
1130
+ };
1131
+ }
1132
+ //#endregion
1133
+ //#region src/effects.ts
1134
+ const STRUCTURAL = /* @__PURE__ */ new Set([
1135
+ "form.fieldCreated",
1136
+ "form.fieldUpdated",
1137
+ "form.fieldDeleted",
1138
+ "form.widgetAttached",
1139
+ "form.widgetDetached",
1140
+ "form.repaired"
1141
+ ]);
1142
+ function registerFormEffects(ctx) {
1143
+ const doc = ctx.doc;
1144
+ if (!doc) return;
1145
+ let refreshing = false;
1146
+ const refresh = async () => {
1147
+ if (refreshing) return;
1148
+ refreshing = true;
1149
+ try {
1150
+ const snapshot = await doc.forms.list();
1151
+ ctx.dispatch({
1152
+ type: "SET_MODEL",
1153
+ model: update(ctx.getState().model, {
1154
+ t: "snapshot",
1155
+ snapshot
1156
+ })
1157
+ });
1158
+ } finally {
1159
+ refreshing = false;
1160
+ }
1161
+ };
1162
+ const unsubscribe = doc.events.subscribe((event) => {
1163
+ if (!event.type.startsWith("form.")) return;
1164
+ const structural = STRUCTURAL.has(event.type);
1165
+ if (event.origin.kind !== "remote" && !structural) return;
1166
+ if (structural) ctx.dispatch({
1167
+ type: "SET_MODEL",
1168
+ model: update(ctx.getState().model, { t: "clearGeom" })
1169
+ });
1170
+ refresh();
1171
+ });
1172
+ ctx.cleanup(unsubscribe);
1173
+ }
1174
+ //#endregion
1175
+ //#region src/tools.ts
1176
+ /** Palette tools keep widgets editable right after placement. */
1177
+ const PLACE_TAGS = ["form-place", "annotation-edit"];
1178
+ const FIELD_CHROME = {
1179
+ interiorColor: "#ffffff",
1180
+ color: "#6b7280",
1181
+ strokeWidth: 1
1182
+ };
1183
+ const FORM_TOOLS = [
1184
+ {
1185
+ id: "form-text",
1186
+ family: "text",
1187
+ visualKind: "widget-text",
1188
+ clickCreate: {
1189
+ width: 160,
1190
+ height: 24
1191
+ },
1192
+ defaults: {
1193
+ ...FIELD_CHROME,
1194
+ fontSize: 12
1195
+ },
1196
+ cursor: "crosshair"
1197
+ },
1198
+ {
1199
+ id: "form-checkbox",
1200
+ family: "checkbox",
1201
+ visualKind: "widget-toggle",
1202
+ clickCreate: {
1203
+ width: 18,
1204
+ height: 18
1205
+ },
1206
+ defaults: FIELD_CHROME,
1207
+ cursor: "crosshair"
1208
+ },
1209
+ {
1210
+ id: "form-radio",
1211
+ family: "radio",
1212
+ visualKind: "widget-toggle",
1213
+ clickCreate: {
1214
+ width: 18,
1215
+ height: 18
1216
+ },
1217
+ defaults: FIELD_CHROME,
1218
+ cursor: "crosshair"
1219
+ },
1220
+ {
1221
+ id: "form-combobox",
1222
+ family: "combobox",
1223
+ visualKind: "widget-choice",
1224
+ clickCreate: {
1225
+ width: 140,
1226
+ height: 24
1227
+ },
1228
+ defaults: {
1229
+ ...FIELD_CHROME,
1230
+ fontSize: 12
1231
+ },
1232
+ cursor: "crosshair"
1233
+ },
1234
+ {
1235
+ id: "form-listbox",
1236
+ family: "listbox",
1237
+ visualKind: "widget-choice",
1238
+ clickCreate: {
1239
+ width: 140,
1240
+ height: 72
1241
+ },
1242
+ defaults: {
1243
+ ...FIELD_CHROME,
1244
+ fontSize: 12
1245
+ },
1246
+ cursor: "crosshair"
1247
+ }
1248
+ ];
1249
+ const FORM_TOOL_BY_ID = new Map(FORM_TOOLS.map((t) => [t.id, t]));
1250
+ //#endregion
1251
+ //#region src/handler.ts
1252
+ const rectFrom = (a, b) => ({
1253
+ x: Math.min(a.x, b.x),
1254
+ y: Math.min(a.y, b.y),
1255
+ width: Math.abs(b.x - a.x),
1256
+ height: Math.abs(b.y - a.y)
1257
+ });
1258
+ /**
1259
+ * Draw-to-place: drag a box (live placement preview through the annotation
1260
+ * plane's ghost pipeline) or just click (the tool's `clickCreate` policy,
1261
+ * resolved by the SAME `resolveClickPlacement` the annotation core uses) —
1262
+ * the commit creates field + widget through `doc.forms.placeField`, styled
1263
+ * from the tool's live defaults. The tool stays active for repeat placement
1264
+ * (v2 rubber-stamp feel) and the fresh widget is auto-selected.
1265
+ *
1266
+ * Gesture rules match the annotation handlers: page-anchored via the sample
1267
+ * projection (the box keeps sizing along the edge when the cursor overshoots
1268
+ * or crosses a gap), the UP sample is the final point, and a CLICK means
1269
+ * width AND height under the shared threshold — a thin 100×2 drag is a drag.
1270
+ */
1271
+ function createPlaceHandler(form, interaction, annotation) {
1272
+ let origin = null;
1273
+ return {
1274
+ id: "form-place",
1275
+ priority: 95,
1276
+ enabledFor: (t) => t.enables.has("form-place"),
1277
+ onDown: (s) => {
1278
+ if (!s.page || !FORM_TOOL_BY_ID.has(interaction.activeToolId())) return false;
1279
+ if (!form.canModify()) return false;
1280
+ origin = {
1281
+ pon: s.page.pon,
1282
+ start: s.page.point,
1283
+ last: s.page.point
1284
+ };
1285
+ return true;
1286
+ },
1287
+ onMove: (s) => {
1288
+ if (!origin) return;
1289
+ const point = (0, _embedpdf_plugin_interaction.samplePointOn)(s, origin.pon);
1290
+ if (!point) return;
1291
+ origin.last = point;
1292
+ const box = rectFrom(origin.start, point);
1293
+ if (annotation) if (Math.max(box.width, box.height) >= _embedpdf_plugin_annotation.MIN_DRAG) annotation.setPlacementPreview(interaction.activeToolId(), origin.pon, box);
1294
+ else annotation.clearPlacementPreview();
1295
+ },
1296
+ onUp: (s) => {
1297
+ if (!origin) return;
1298
+ const o = origin;
1299
+ origin = null;
1300
+ annotation?.clearPlacementPreview();
1301
+ const toolId = interaction.activeToolId();
1302
+ const tool = FORM_TOOL_BY_ID.get(toolId);
1303
+ if (!tool) return;
1304
+ const end = (0, _embedpdf_plugin_interaction.samplePointOn)(s, o.pon) ?? o.last;
1305
+ const dragged = rectFrom(o.start, end);
1306
+ const isClick = dragged.width < _embedpdf_plugin_annotation.MIN_DRAG && dragged.height < _embedpdf_plugin_annotation.MIN_DRAG;
1307
+ const pageBox = form.pageBox(o.pon);
1308
+ const box = isClick ? boxOfClick(o.start, tool.clickCreate, pageBox) : dragged;
1309
+ form.placeField({
1310
+ family: tool.family,
1311
+ pageObjectNumber: o.pon,
1312
+ box,
1313
+ appearance: (0, _embedpdf_plugin_annotation.widgetAppearanceFromProps)(annotation ? annotation.currentDefaults(toolId) : tool.defaults)
1314
+ }).then((placed) => {
1315
+ if (!annotation || interaction.activeToolId() !== toolId) return;
1316
+ const widget = placed.widget;
1317
+ if (!widget || widget.annotObjectNumber <= 0) return;
1318
+ annotation.select({
1319
+ kind: "objectNumber",
1320
+ annotObjectNumber: widget.annotObjectNumber,
1321
+ pageObjectNumber: o.pon
1322
+ });
1323
+ }).catch((err) => {
1324
+ globalThis.console?.error("[form] placeField failed:", err);
1325
+ });
1326
+ }
1327
+ };
1328
+ }
1329
+ /** The click-create box through the SHARED placement layer (fields are boxes;
1330
+ * the policy anchor + page clamp are exactly the annotation click's). */
1331
+ function boxOfClick(point, policy, pageBox) {
1332
+ const placement = (0, _embedpdf_plugin_annotation.resolveClickPlacement)(point, policy, { pageBox: pageBox ?? void 0 });
1333
+ return placement.kind === "box" ? placement.rect : {
1334
+ x: point.x,
1335
+ y: point.y,
1336
+ width: policy.width,
1337
+ height: policy.height
1338
+ };
1339
+ }
1340
+ //#endregion
1341
+ //#region src/reducer.ts
1342
+ const initialFormState = () => ({ model: initialModel() });
1343
+ /** Dumb store: the pure core computes the next model; the shell dispatches it. */
1344
+ const formReducer = (state, action) => action.type === "SET_MODEL" ? { model: action.model } : state;
1345
+ //#endregion
1346
+ //#region src/types.ts
1347
+ const FormToken = (0, _embedpdf_core.createCapabilityToken)("form");
1348
+ //#endregion
1349
+ //#region src/form.plugin.ts
1350
+ /**
1351
+ * The form plugin: the FIELD plane. Document-scoped; requires the
1352
+ * interaction hub. Fill mode works with no annotation plugin at all —
1353
+ * geometry is read from the engine's widget DTOs. When the annotation
1354
+ * plugin IS present, a Behavior keeps widgets geometry-inert while the
1355
+ * active tool carries 'form-fill' (the built-in pointer/pan tools do, so
1356
+ * filling is the resting state) and stands the fill controls down under
1357
+ * every other tool — the single-active-tool hub IS the mode switch.
1358
+ * Design mode = the 'form-edit' / palette tools: no 'form-fill' tag, so
1359
+ * widgets become ordinary editable annotations.
1360
+ */
1361
+ const formPlugin = (options = {}) => (0, _embedpdf_core.definePlugin)({
1362
+ id: "form",
1363
+ token: FormToken,
1364
+ scope: "document",
1365
+ requires: [_embedpdf_plugin_interaction.InteractionToken],
1366
+ optional: [_embedpdf_plugin_annotation.AnnotationToken],
1367
+ initialState: initialFormState,
1368
+ reduce: formReducer,
1369
+ capability: (ctx) => createFormCapability(ctx, options),
1370
+ effects: registerFormEffects,
1371
+ init: (ctx) => {
1372
+ const interaction = ctx.get(_embedpdf_plugin_interaction.InteractionToken);
1373
+ const form = ctx.get(FormToken);
1374
+ interaction.registerTool({
1375
+ id: "form-fill",
1376
+ cursor: "default",
1377
+ enables: /* @__PURE__ */ new Set(["form-fill", "link-nav"])
1378
+ });
1379
+ interaction.registerTool({
1380
+ id: "form-edit",
1381
+ cursor: "default",
1382
+ enables: /* @__PURE__ */ new Set(["annotation-edit", "annotation-marquee"])
1383
+ });
1384
+ const annotation = ctx.tryGet(_embedpdf_plugin_annotation_internal.AnnotationToken);
1385
+ for (const t of FORM_TOOLS) if (annotation) annotation.registerTool({
1386
+ id: t.id,
1387
+ subtype: t.visualKind,
1388
+ cursor: t.cursor,
1389
+ enables: [...PLACE_TAGS],
1390
+ clickCreate: t.clickCreate,
1391
+ defaults: t.defaults
1392
+ });
1393
+ else interaction.registerTool({
1394
+ id: t.id,
1395
+ cursor: t.cursor,
1396
+ enables: new Set(PLACE_TAGS)
1397
+ });
1398
+ interaction.registerHandler(createPlaceHandler(form, interaction, annotation));
1399
+ if (annotation) annotation.registerBehavior({
1400
+ id: "form-widgets",
1401
+ matches: (a) => a.subtype.startsWith("widget"),
1402
+ engaged: () => interaction.activeTool()?.enables.has("form-fill") ?? false
1403
+ });
1404
+ }
1405
+ });
1406
+ //#endregion
1407
+ exports.FORM_TOOLS = FORM_TOOLS;
1408
+ exports.FORM_TOOL_BY_ID = FORM_TOOL_BY_ID;
1409
+ exports.FormScriptingController = FormScriptingController;
1410
+ exports.FormToken = FormToken;
1411
+ exports.createFormScriptingController = createFormScriptingController;
1412
+ exports.createSerialMutationQueue = createSerialMutationQueue;
1413
+ exports.fieldKeyOf = fieldKeyOf;
1414
+ exports.formPlugin = formPlugin;
1415
+
1416
+ //# sourceMappingURL=index.cjs.map