@embedpdf/react 3.0.0-next.12 → 3.0.0-next.14

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 (41) hide show
  1. package/dist/annotation.cjs +52 -15
  2. package/dist/annotation.cjs.map +1 -1
  3. package/dist/annotation.js +53 -16
  4. package/dist/annotation.js.map +1 -1
  5. package/dist/{form-D-ZSfGmB.cjs → form-BVumS7up.cjs} +91 -1
  6. package/dist/form-BVumS7up.cjs.map +1 -0
  7. package/dist/{AnnotationListSnapshot-x6tKulNV-B799rYyi.d.ts → form-Bdjk0Z3T.d.cts} +33 -42
  8. package/dist/{form-BwrLFpKN.js → form-CK3mp99m.js} +92 -2
  9. package/dist/form-CK3mp99m.js.map +1 -0
  10. package/dist/{AnnotationListSnapshot-x6tKulNV-B799rYyi.d.cts → form-CYRYgthn.d.ts} +33 -42
  11. package/dist/form.cjs +1 -1
  12. package/dist/form.d.cts +2 -34
  13. package/dist/form.d.ts +2 -34
  14. package/dist/form.js +1 -1
  15. package/dist/index.cjs +32 -2
  16. package/dist/index.d.cts +7 -3
  17. package/dist/index.d.ts +7 -3
  18. package/dist/index.js +7 -3
  19. package/dist/measurement.cjs +31 -0
  20. package/dist/measurement.cjs.map +1 -0
  21. package/dist/measurement.d.cts +12 -0
  22. package/dist/measurement.d.ts +12 -0
  23. package/dist/measurement.js +21 -0
  24. package/dist/measurement.js.map +1 -0
  25. package/dist/search.d.cts +1 -2
  26. package/dist/search.d.ts +1 -2
  27. package/dist/signature.cjs +81 -0
  28. package/dist/signature.cjs.map +1 -0
  29. package/dist/signature.d.cts +36 -0
  30. package/dist/signature.d.ts +36 -0
  31. package/dist/signature.js +67 -0
  32. package/dist/signature.js.map +1 -0
  33. package/dist/stamp.cjs +4 -2
  34. package/dist/stamp.cjs.map +1 -1
  35. package/dist/stamp.d.cts +3 -2
  36. package/dist/stamp.d.ts +3 -2
  37. package/dist/stamp.js +4 -2
  38. package/dist/stamp.js.map +1 -1
  39. package/package.json +37 -26
  40. package/dist/form-BwrLFpKN.js.map +0 -1
  41. package/dist/form-D-ZSfGmB.cjs.map +0 -1
@@ -1,4 +1,6 @@
1
- //#region ../../engine/core/dist/AnnotationListSnapshot-x6tKulNV.d.ts
1
+ import { o as AnnotationRenderer } from "./annotation-BCED_p9H.cjs";
2
+ import { FormFieldDTO } from "@embedpdf/plugin-form";
3
+ //#region ../../engine/core/dist/AnnotationListSnapshot-D9R5n2Kf.d.ts
2
4
  //#endregion
3
5
  //#region src/identity/PageObjectNumber.d.ts
4
6
  /**
@@ -467,7 +469,7 @@ interface UnknownFieldDTO extends FormFieldBase {
467
469
  * }
468
470
  * ```
469
471
  */
470
- type FormFieldDTO = TextFieldDTO | CheckboxFieldDTO | RadioFieldDTO | ComboBoxFieldDTO | ListBoxFieldDTO | PushButtonFieldDTO | SignatureFieldDTO | UnknownFieldDTO;
472
+ type FormFieldDTO$1 = TextFieldDTO | CheckboxFieldDTO | RadioFieldDTO | ComboBoxFieldDTO | ListBoxFieldDTO | PushButtonFieldDTO | SignatureFieldDTO | UnknownFieldDTO;
471
473
  //#endregion
472
474
  //#region src/forms/snapshot.d.ts
473
475
  /**
@@ -497,50 +499,39 @@ interface FormSnapshot {
497
499
  * `repair({ bakeAppearances: true })` can clear the flag document-wide.
498
500
  */
499
501
  needsAppearances: boolean;
500
- fields: FormFieldDTO[];
502
+ fields: FormFieldDTO$1[];
501
503
  /** `/AcroForm /CO` order; null preserves each malformed/unresolved slot. */
502
504
  calculationOrder: Array<FormFieldRef | null>;
503
505
  }
504
506
  //#endregion
505
- //#region src/search/types.d.ts
507
+ //#region src/form.d.ts
506
508
  /**
507
- * What to search for — THE one shape, engine → wire → plugin state →
508
- * search box. One flat object; the flags define behavior per mode instead
509
- * of the mode changing the shape:
510
- *
511
- * | flag | literal | regex |
512
- * |-------------------|------------------|--------------------------------|
513
- * | `matchCase` | fold case | `i` flag |
514
- * | `wholeWord` | boundary check | pattern is `\b(?:…)\b`-wrapped |
515
- * | `matchDiacritics` | mark fold | REJECTED (`InvalidArg`) |
516
- *
517
- * Literal queries match over FOLDED text; regex queries run the portable
518
- * dialect against the RAW page text — which is why `matchDiacritics`
519
- * cannot apply to them (diacritic folding is a property of the folded
520
- * text plane). Validate with `validateSearchQuery` for early UI feedback;
521
- * engines re-validate and reject with `EngineErrorCode.InvalidArg`.
509
+ * The form plugin's renderer entry, ready for
510
+ * `<AnnotationLayer renderers={[formWidgetRenderer]} />`. It answers for the
511
+ * PLUGIN-registered 'form-widgets' Behavior — the form plugin decides when
512
+ * widgets are fill controls vs. editable annotations, never the app.
522
513
  */
523
- interface SearchQuery {
524
- /**
525
- * The literal text — or, when `regex`, a pattern in the portable
526
- * search-regex dialect: JavaScript `u`-mode syntax MINUS backreferences
527
- * and lookaround, so every valid pattern also runs on RE2 (the
528
- * server-side engine).
529
- */
530
- text: string;
531
- /** Interpret `text` as a regex pattern. Default false (literal). */
532
- regex?: boolean;
533
- /** Exact-case matching. Default false (case-folded / `i` semantics). */
534
- matchCase?: boolean;
535
- /** Only match at word boundaries (letters/digits end the word). */
536
- wholeWord?: boolean;
537
- /**
538
- * Treat diacritics as significant ("café" ≠ "cafe"). Default false —
539
- * marks are stripped on both sides, which is what viewers ship.
540
- * LITERAL ONLY: combined with `regex` the query is rejected.
541
- */
542
- matchDiacritics?: boolean;
543
- }
514
+ declare const formWidgetRenderer: AnnotationRenderer;
515
+ /**
516
+ * Fill-mode form controls for one page, positioned from the form model's own
517
+ * widget geometry — the ANNOTATION-LESS path (a fill-only viewer whose page
518
+ * pixels come from an annotated RenderLayer raster). Active whenever the
519
+ * active tool carries the 'form-fill' tag (the built-in pointer/pan tools
520
+ * do); any other tool stands the controls down. Do not mount next to an
521
+ * AnnotationLayer wired with `formWidgetBehaviors`.
522
+ */
523
+ declare function FormLayer(): import("react/jsx-runtime").JSX.Element | null;
524
+ /** The form capability — values, interchange, design-mode verbs. */
525
+ declare function useForm(): import("@embedpdf/plugin-form").FormCapability;
526
+ /** The reconciled form snapshot (null until the first load lands),
527
+ * re-rendering on every form model change. */
528
+ declare function useFormSnapshot(): FormSnapshot | null;
529
+ /**
530
+ * The FIELD behind the currently selected widget annotation (single
531
+ * selection), or null. The design-mode join: widget selection lives in the
532
+ * annotation plane, field properties live here.
533
+ */
534
+ declare function useFormField(): FormFieldDTO | null;
544
535
  //#endregion
545
- export { SearchQuery as n, FormSnapshot as t };
546
- //# sourceMappingURL=AnnotationListSnapshot-x6tKulNV-B799rYyi.d.ts.map
536
+ export { useFormSnapshot as a, useFormField as i, formWidgetRenderer as n, useForm as r, FormLayer as t };
537
+ //# sourceMappingURL=form-Bdjk0Z3T.d.cts.map
@@ -1,9 +1,10 @@
1
- import { shallowArray, useCapability, usePage, useSelector } from "./runtime.js";
1
+ import { shallowArray, useCapability, useOptionalCapability, useOptionalSelector, usePage, useSelector } from "./runtime.js";
2
2
  import { t as useAnnotationSelected } from "./annotation-hooks-Df8EmzDO.js";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
5
5
  import { InteractionToken } from "@embedpdf/plugin-interaction/contract";
6
6
  import { FormToken } from "@embedpdf/plugin-form";
7
+ import { SignatureToken } from "@embedpdf/plugin-signature/contract";
7
8
  //#region src/form-focus-ring.tsx
8
9
  /**
9
10
  * Paint the form focus indicator above baked PDF appearances and transparent
@@ -221,8 +222,68 @@ function FormWidget({ item, page, appearance }) {
221
222
  page,
222
223
  appearance
223
224
  });
225
+ case "signature": return /* @__PURE__ */ jsx(SignatureWidget, {
226
+ fill,
227
+ item,
228
+ page,
229
+ appearance
230
+ });
224
231
  }
225
232
  }
233
+ /** The form plugin's field key → the engine ref (the inverse of `fieldKeyOf`). */
234
+ const fieldRefOfKey = (key) => key.startsWith("obj:") ? {
235
+ kind: "objectNumber",
236
+ fieldObjectNumber: Number(key.slice(4))
237
+ } : {
238
+ kind: "fqn",
239
+ name: key.slice(4)
240
+ };
241
+ /**
242
+ * A signature field's widget: the picture (the mark drawn into it, once
243
+ * there is one) with a click target on top. Unsigned → "sign here": the
244
+ * field becomes the signature plugin's TARGET, so the next mark picked
245
+ * from a signatures panel goes into it. Signed → `inspect`: the chrome shows
246
+ * what the signature says. Without the signature plugin the widget is
247
+ * picture only — the field plane has no fill control of its own here.
248
+ */
249
+ function SignatureWidget({ fill, item, page, appearance }) {
250
+ const signature = useOptionalCapability(SignatureToken);
251
+ const wrap = useIsolated();
252
+ const events = useWidgetEvents(fill.key, item.ref);
253
+ const b = viewBox(item.box, page);
254
+ const ref = fieldRefOfKey(fill.key);
255
+ const signed = useOptionalSelector(SignatureToken, (c) => c.signatureOf(ref)?.signed ?? fill.signed, fill.signed);
256
+ const actionable = signature != null && (signed || !fill.disabled);
257
+ return /* @__PURE__ */ jsxs("div", {
258
+ ref: wrap,
259
+ ...events,
260
+ style: {
261
+ position: "absolute",
262
+ left: b.left,
263
+ top: b.top,
264
+ width: b.width,
265
+ height: b.height
266
+ },
267
+ children: [/* @__PURE__ */ jsx(Picture, {
268
+ page,
269
+ appearance,
270
+ apBox: item.apBox,
271
+ frame: b
272
+ }), actionable ? /* @__PURE__ */ jsx("button", {
273
+ type: "button",
274
+ "aria-label": fill.label,
275
+ "data-signed": signed ? "" : void 0,
276
+ onClick: () => signed ? signature.inspect(ref) : signature.setTarget(ref),
277
+ style: {
278
+ ...fillControl,
279
+ padding: 0,
280
+ border: 0,
281
+ background: "transparent",
282
+ cursor: "pointer"
283
+ }
284
+ }) : null]
285
+ });
286
+ }
226
287
  function ButtonWidget({ fill, item, page, appearance }) {
227
288
  const form = useCapability(FormToken);
228
289
  const wrap = useIsolated();
@@ -738,6 +799,32 @@ function FillButton({ item, page }) {
738
799
  })
739
800
  });
740
801
  }
802
+ /** The standalone layer's signature control: the same target/inspect
803
+ * hand-off as {@link SignatureWidget}, over the page raster. */
804
+ function FillSignature({ item, page }) {
805
+ const signature = useOptionalCapability(SignatureToken);
806
+ const ref = fieldRefOfKey(item.key);
807
+ const signed = useOptionalSelector(SignatureToken, (c) => c.signatureOf(ref)?.signed ?? item.signed, item.signed);
808
+ const actionable = signature != null && (signed || !item.disabled);
809
+ return /* @__PURE__ */ jsx(FillEventBox, {
810
+ item,
811
+ page,
812
+ cursor: actionable ? "pointer" : "default",
813
+ children: actionable ? /* @__PURE__ */ jsx("button", {
814
+ type: "button",
815
+ "aria-label": item.label,
816
+ "data-signed": signed ? "" : void 0,
817
+ onClick: () => signed ? signature.inspect(ref) : signature.setTarget(ref),
818
+ style: {
819
+ ...fillControl,
820
+ padding: 0,
821
+ border: 0,
822
+ background: "transparent",
823
+ cursor: "inherit"
824
+ }
825
+ }) : null
826
+ });
827
+ }
741
828
  /**
742
829
  * Fill-mode form controls for one page, positioned from the form model's own
743
830
  * widget geometry — the ANNOTATION-LESS path (a fill-only viewer whose page
@@ -776,6 +863,9 @@ function FormLayer() {
776
863
  }, `${item.key}:${item.annotObjectNumber}`) : item.control === "button" ? /* @__PURE__ */ jsx(FillButton, {
777
864
  item,
778
865
  page
866
+ }, `${item.key}:${item.annotObjectNumber}`) : item.control === "signature" ? /* @__PURE__ */ jsx(FillSignature, {
867
+ item,
868
+ page
779
869
  }, `${item.key}:${item.annotObjectNumber}`) : null)
780
870
  });
781
871
  }
@@ -802,4 +892,4 @@ function useFormField() {
802
892
  //#endregion
803
893
  export { useFormSnapshot as a, useFormField as i, formWidgetRenderer as n, useForm as r, FormLayer as t };
804
894
 
805
- //# sourceMappingURL=form-BwrLFpKN.js.map
895
+ //# sourceMappingURL=form-CK3mp99m.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-CK3mp99m.js","names":[],"sources":["../src/form-focus-ring.tsx","../src/form-listbox.tsx","../src/form.tsx"],"sourcesContent":["import * as React from 'react';\n\nexport interface FormFocusRingProps {\n visible: boolean;\n}\n\n/**\n * Paint the form focus indicator above baked PDF appearances and transparent\n * native controls. Putting an inset outline on the widget wrapper lets an\n * opaque child cover it, which makes rectangular checkboxes and combo boxes\n * appear unfocused even though they are active in the native Tab order.\n */\nexport function FormFocusRing({ visible }: FormFocusRingProps) {\n if (!visible) return null;\n return (\n <span\n aria-hidden=\"true\"\n data-embedpdf-form-focus-ring=\"\"\n style={{\n position: 'absolute',\n inset: 0,\n zIndex: 1,\n boxSizing: 'border-box',\n outline: '2px solid rgba(66, 133, 244, 0.8)',\n outlineOffset: -2,\n pointerEvents: 'none',\n }}\n />\n );\n}\n","import * as React from 'react';\nimport { useEffect, useRef, useState } from 'react';\n\nexport interface NativeListBoxOption {\n label: string;\n value: string;\n}\n\nexport interface NativeListBoxProps {\n ariaLabel: string;\n disabled: boolean;\n multi: boolean;\n options: NativeListBoxOption[];\n selected: string[];\n onSelect(values: string[]): void | Promise<void>;\n onFocus?: React.FocusEventHandler<HTMLSelectElement>;\n onBlur?: React.FocusEventHandler<HTMLSelectElement>;\n style?: React.CSSProperties;\n}\n\n/**\n * A PDF list box needs one owner for pixels, hit-testing, and scrolling. A\n * baked /AP picture with an invisible native select cannot provide that: the\n * browser and PDF each keep an independent top-visible row. This visible\n * native control keeps a local optimistic selection while the engine write is\n * pending and synchronizes when engine truth changes, without remounting the\n * DOM node or resetting its scroll position.\n */\nexport function NativeListBox({\n ariaLabel,\n disabled,\n multi,\n options,\n selected,\n onSelect,\n onFocus,\n onBlur,\n style,\n}: NativeListBoxProps) {\n const [draft, setDraft] = useState<string[]>(() => [...selected]);\n const controlRef = useRef<HTMLSelectElement>(null);\n const selectedRef = useRef(selected);\n selectedRef.current = selected;\n const selectedSignature = JSON.stringify(selected);\n\n useEffect(() => {\n const control = controlRef.current;\n if (!control) return;\n // The Stage's ambient wheel handler lives on an ancestor and\n // preventDefault()s to pan/zoom the page. Stop at the list box so the\n // browser can apply the same wheel event to this control's own scroll box.\n const isolateWheel = (event: WheelEvent) => event.stopPropagation();\n control.addEventListener('wheel', isolateWheel);\n return () => control.removeEventListener('wheel', isolateWheel);\n }, []);\n\n useEffect(() => {\n setDraft([...selectedRef.current]);\n }, [selectedSignature]);\n\n const rollback = () => setDraft([...selectedRef.current]);\n const choose = (values: string[]) => {\n setDraft(values);\n try {\n const result = onSelect(values);\n if (result) void result.catch(rollback);\n } catch {\n rollback();\n }\n };\n\n return (\n <select\n ref={controlRef}\n aria-label={ariaLabel}\n multiple={multi}\n size={Math.max(2, options.length)}\n disabled={disabled}\n value={multi ? draft : (draft[0] ?? '')}\n onFocus={onFocus}\n onBlur={onBlur}\n onChange={(event) =>\n choose(Array.from(event.currentTarget.selectedOptions).map((option) => option.value))\n }\n style={style}\n >\n {options.map((option, index) => (\n <option key={index} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n );\n}\n","/**\n * The React view of @embedpdf/plugin-form.\n *\n * TWO fill surfaces, one plugin:\n *\n * 1. `formWidgetRenderer` — the full-viewer path. Widgets are annotations,\n * so the fill controls plug into the annotation stack:\n * `<AnnotationLayer renderers={[formWidgetRenderer]} />` routes every\n * ENGAGED widget here with its live box and its baked /AP raster. The\n * picture IS the resting control (the engine's own rendering of value,\n * check state, borders, fonts); these components add exactly the\n * interaction skin on top:\n *\n * text → picture at rest; click swaps in an <input>/<textarea> (the\n * focused element IS the draft store — the plugin model only\n * learns a value on commit); blur/Enter commits, the engine\n * re-bakes the /AP, the refreshed picture replaces the editor.\n * toggle → the picture is the whole control; click writes the toggled\n * value; the re-baked appearance shows the new check state.\n * combo → an invisible native <select> over the picture: the browser\n * owns the dropdown, the engine owns the resting pixels.\n * list → a visible native <select>: one surface owns pixels, row\n * hit-testing, keyboard selection, and scrolling.\n * button → native keyboard/click target over the picture; activation is\n * delegated to the form plugin's isolated scripting pipeline.\n *\n * 2. `<FormLayer />` — the annotation-less path (fill-only viewers with no\n * annotation plugin): synthetic HTML controls positioned from the form\n * model's own widget geometry. Do NOT mount it next to an AnnotationLayer\n * wired with `formWidgetRenderer` — the controls would double up.\n *\n * Every control isolates its pointerdown from the interaction hub with a\n * NATIVE listener (the FreeText precedent): the Stage listens natively on an\n * ancestor, so React's synthetic events would run too late.\n */\n\n// One-line-per-feature (ADAPTERS.md): registration travels with the UI.\nexport * from '@embedpdf/plugin-form';\nimport * as React from 'react';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { PdfAnnotationEventKind } from '@embedpdf/plugin-actions/contract';\nimport type { AnnotationRef } from '@embedpdf/plugin-annotation/contract';\nimport { FormToken } from '@embedpdf/plugin-form';\nimport { SignatureToken } from '@embedpdf/plugin-signature/contract';\nimport type { FormFieldRef, FillItem, FormFieldDTO } from '@embedpdf/plugin-form';\nimport { InteractionToken } from '@embedpdf/plugin-interaction/contract';\nimport { StageToken } from '@embedpdf/plugin-stage/contract';\nimport type { Rect } from '@embedpdf/core-annotation';\n\nimport { useAnnotationSelected } from './annotation-hooks';\nimport type { AnnotationRenderer, AnnotationRendererProps } from './annotation';\nimport {\n shallowArray,\n useCapability,\n useOptionalCapability,\n useOptionalSelector,\n usePage,\n useSelector,\n} from './runtime';\nimport type { PageContextValue } from './runtime';\nimport { FormFocusRing } from './form-focus-ring';\nimport { NativeListBox } from './form-listbox';\n\n/** Content rect → a view-px box (the page wrapper's own coordinate space). */\nfunction viewBox(r: Rect, page: PageContextValue) {\n const tl = page.transform.toPixels({ x: r.x, y: r.y });\n const br = page.transform.toPixels({ x: r.x + r.width, y: r.y + r.height });\n return { left: tl.x, top: tl.y, width: br.x - tl.x, height: br.y - tl.y };\n}\n\n/**\n * Keep the interaction hub out of gestures that begin inside a fill control.\n * Native listener (not React's) so it runs during real DOM bubbling, before\n * the Stage's own native listener on an ancestor — same trick as FreeText.\n */\nfunction useIsolated<T extends HTMLElement>() {\n const ref = useRef<T>(null);\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const stop = (e: Event) => e.stopPropagation();\n el.addEventListener('pointerdown', stop);\n return () => el.removeEventListener('pointerdown', stop);\n }, []);\n return ref;\n}\n\n/**\n * The widget DOM-event feed (Phase 2): wire one widget surface's pointer and\n * focus events to `form.notifyWidgetEvent` — the `/AA` E/X/D/U/Fo/Bl trigger\n * door. Handlers live on the ALWAYS-ACTIVE event surface, never the inner\n * control: \"may edit this field\" and \"may receive PDF action events\" are\n * different rights, and a read-only session (no `doc.forms.fill`) must still\n * see hover tooltips (session Hide needs no write authority).\n */\nfunction useWidgetEvents(\n key: string,\n annotationRef: AnnotationRef | null,\n): Pick<\n React.DOMAttributes<HTMLElement>,\n 'onPointerEnter' | 'onPointerLeave' | 'onPointerDown' | 'onPointerUp' | 'onFocus' | 'onBlur'\n> {\n const form = useCapability(FormToken);\n const refBox = useRef(annotationRef);\n refBox.current = annotationRef;\n return useMemo(() => {\n const notify = (event: PdfAnnotationEventKind) => {\n const target = refBox.current;\n if (target) form.notifyWidgetEvent(key, target, event);\n };\n return {\n onPointerEnter: () => notify('cursorEnter'),\n onPointerLeave: () => notify('cursorExit'),\n onPointerDown: () => notify('mouseDown'),\n onPointerUp: () => notify('mouseUp'),\n // React focus/blur bubble (focusin semantics), so the inner control's\n // focus reaches this surface; blur fires AFTER the control's own\n // commit handler, so a /Bl script always sees the committed value.\n onFocus: () => notify('focus'),\n onBlur: () => notify('blur'),\n };\n }, [form, key]);\n}\n\n/**\n * Widget ACTIVATION: a click on ANY widget runs its `/A`. ISO puts the\n * activate action on the annotation dictionary — any subtype, any field\n * type — so activation is a WIDGET behavior, not a push-button behavior:\n * real-world producers ship \"buttons\" as read-only text fields carrying an\n * `/A` (the Test Lab's Reset/Next/Hide controls), and Acrobat runs them.\n * A widget without an `/A` resolves inert — dispatching is the cheap,\n * honest way to ask (the dispatcher owns `/A`-vs-`/AA U` precedence).\n * Push buttons keep their own gated door: `disabled` still blocks\n * activation there — unchanged shipped semantics.\n */\nfunction useWidgetActivation(key: string, annotationRef: AnnotationRef | null): () => void {\n const form = useCapability(FormToken);\n const refBox = useRef(annotationRef);\n refBox.current = annotationRef;\n return useCallback(() => {\n const target = refBox.current;\n if (target) void form.activateWidget(key, target);\n }, [form, key]);\n}\n\n/* ══════════════════════════ behavior widgets ══════════════════════════ */\n\n/** The baked /AP raster, blitted by its OWN box (exactly like BakedImage). */\nfunction Picture({\n page,\n appearance,\n apBox,\n frame,\n hidden,\n}: {\n page: PageContextValue;\n appearance: { url: string; box: Rect } | null;\n /** The item's live AP box — wins over the fetched box when present. */\n apBox?: Rect;\n /** The positioned wrapper this renders INSIDE (its view box) — the blit is\n * page-frame, so subtract the wrapper's origin. Omit when rendering\n * directly in the layer container. */\n frame?: { left: number; top: number };\n hidden?: boolean;\n}) {\n if (!appearance) return null;\n const b = viewBox(apBox ?? appearance.box, page);\n return (\n <img\n src={appearance.url}\n alt=\"\"\n draggable={false}\n style={{\n position: 'absolute',\n left: b.left - (frame?.left ?? 0),\n top: b.top - (frame?.top ?? 0),\n width: b.width,\n height: b.height,\n // Content-unit sizing; a global `img { max-width: 100% }` reset would\n // otherwise clamp it to the containing block and distort the blit.\n maxWidth: 'none',\n pointerEvents: 'none',\n visibility: hidden ? 'hidden' : 'visible',\n }}\n />\n );\n}\n\ninterface WidgetProps<C extends FillItem['control']> {\n fill: Extract<FillItem, { control: C }>;\n item: AnnotationRendererProps['item'];\n page: PageContextValue;\n appearance: AnnotationRendererProps['appearance'];\n}\n\n/**\n * Dispatch one engaged widget to its fill control. The FIELD plane (value,\n * behavior, disabled) comes from the form plugin's single-widget projection;\n * the WIDGET plane (live box, /DA font, baked raster) rides in on the\n * renderer props — no geometry is read from the form model here.\n */\nfunction FormWidget({ item, page, appearance }: AnnotationRendererProps) {\n const annot = item.ref?.kind === 'objectNumber' ? item.ref.annotObjectNumber : 0;\n // Reference-stable per model change, so the default Object.is equality holds.\n const fill = useSelector(FormToken, (c) => (annot > 0 ? c.fillItem(annot) : null));\n // Field plane not loaded (or no fill control for this family) → picture only.\n if (!fill) return <Picture page={page} appearance={appearance} apBox={item.apBox} />;\n switch (fill.control) {\n case 'text':\n return <TextWidget fill={fill} item={item} page={page} appearance={appearance} />;\n case 'toggle':\n return <ToggleWidget fill={fill} item={item} page={page} appearance={appearance} />;\n case 'choice':\n return <ChoiceWidget fill={fill} item={item} page={page} appearance={appearance} />;\n case 'button':\n return <ButtonWidget fill={fill} item={item} page={page} appearance={appearance} />;\n case 'signature':\n return <SignatureWidget fill={fill} item={item} page={page} appearance={appearance} />;\n }\n}\n\n/** The form plugin's field key → the engine ref (the inverse of `fieldKeyOf`). */\nconst fieldRefOfKey = (key: string): FormFieldRef =>\n key.startsWith('obj:')\n ? { kind: 'objectNumber', fieldObjectNumber: Number(key.slice(4)) }\n : { kind: 'fqn', name: key.slice(4) };\n\n/**\n * A signature field's widget: the picture (the mark drawn into it, once\n * there is one) with a click target on top. Unsigned → \"sign here\": the\n * field becomes the signature plugin's TARGET, so the next mark picked\n * from a signatures panel goes into it. Signed → `inspect`: the chrome shows\n * what the signature says. Without the signature plugin the widget is\n * picture only — the field plane has no fill control of its own here.\n */\nfunction SignatureWidget({ fill, item, page, appearance }: WidgetProps<'signature'>) {\n const signature = useOptionalCapability(SignatureToken);\n const wrap = useIsolated<HTMLDivElement>();\n const events = useWidgetEvents(fill.key, item.ref);\n const b = viewBox(item.box, page);\n const ref = fieldRefOfKey(fill.key);\n // The signature plugin's snapshot is the authority on signed-ness (it\n // re-reads on every new version); the field plane's /V is the fallback.\n const signed = useOptionalSelector(\n SignatureToken,\n (c) => c.signatureOf(ref)?.signed ?? fill.signed,\n fill.signed,\n );\n const actionable = signature != null && (signed || !fill.disabled);\n return (\n <div\n ref={wrap}\n {...events}\n style={{ position: 'absolute', left: b.left, top: b.top, width: b.width, height: b.height }}\n >\n <Picture page={page} appearance={appearance} apBox={item.apBox} frame={b} />\n {actionable ? (\n <button\n type=\"button\"\n aria-label={fill.label}\n data-signed={signed ? '' : undefined}\n onClick={() => (signed ? signature.inspect(ref) : signature.setTarget(ref))}\n style={{\n ...fillControl,\n padding: 0,\n border: 0,\n background: 'transparent',\n cursor: 'pointer',\n }}\n />\n ) : null}\n </div>\n );\n}\n\nfunction ButtonWidget({ fill, item, page, appearance }: WidgetProps<'button'>) {\n const form = useCapability(FormToken);\n const wrap = useIsolated<HTMLDivElement>();\n const events = useWidgetEvents(fill.key, item.ref);\n const b = viewBox(item.box, page);\n // The OUTER div is the event surface — always pointer-active so /AA hover\n // and pointer triggers fire even for a disabled/read-only button; the\n // inner button keeps `disabled` as the ACTIVATION gate only.\n return (\n <div\n ref={wrap}\n {...events}\n style={{\n position: 'absolute',\n left: b.left,\n top: b.top,\n width: b.width,\n height: b.height,\n cursor: fill.disabled ? 'default' : 'pointer',\n pointerEvents: 'auto',\n }}\n >\n <button\n type=\"button\"\n aria-label={fill.label}\n disabled={fill.disabled}\n onClick={() => {\n if (item.ref) void form.activateWidget(fill.key, item.ref);\n }}\n style={{\n position: 'absolute',\n inset: 0,\n width: '100%',\n height: '100%',\n boxSizing: 'border-box',\n padding: 0,\n border: 0,\n background: 'transparent',\n cursor: 'inherit',\n // The event surface is the wrapper; a disabled button must not\n // swallow the pointer stream before it bubbles.\n pointerEvents: fill.disabled ? 'none' : 'auto',\n }}\n >\n <Picture page={page} appearance={appearance} apBox={item.apBox} frame={b} />\n </button>\n </div>\n );\n}\n\nfunction TextWidget({ fill, item, page, appearance }: WidgetProps<'text'>) {\n const form = useCapability(FormToken);\n const wrap = useIsolated<HTMLDivElement>();\n const events = useWidgetEvents(fill.key, item.ref);\n const activate = useWidgetActivation(fill.key, item.ref);\n // The editor is ALWAYS MOUNTED (v2's pattern): transparent over the picture\n // at rest, visible while focused. That makes the DOM the focus manager —\n // native Tab order reaches every field, focus enters edit, blur commits —\n // with zero focus machinery of our own. The focused element holds the\n // draft; the plugin model only learns a value on commit (see model.ts).\n const [focused, setFocused] = useState(false);\n const [draft, setDraft] = useState(fill.value);\n const cancelled = useRef(false);\n // Adopt engine truth whenever it changes under us — but never mid-edit.\n useEffect(() => {\n if (!focused) setDraft(fill.value);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fill.value, focused]);\n\n const b = viewBox(item.box, page);\n const scale = item.box.width > 0 ? b.width / item.box.width : 1;\n\n // /DA font, scaled to view px. Size 0 means \"auto\" in PDF: approximate with\n // the box height for a single line, Acrobat's 12pt default for multiline.\n const fontSize =\n item.text && item.text.fontSize > 0\n ? item.text.fontSize * scale\n : fill.multiline\n ? 12 * scale\n : Math.max(6, b.height * 0.72);\n const editorStyle: React.CSSProperties = {\n position: 'absolute',\n inset: 0,\n width: '100%',\n height: '100%',\n boxSizing: 'border-box',\n border: 'none',\n outline: focused ? '2px solid rgba(66, 133, 244, 0.8)' : 'none',\n outlineOffset: -2,\n padding: '0 2px',\n margin: 0,\n background: item.style.interiorColor ?? '#fff',\n color: item.text?.fontColor ?? '#000',\n fontFamily: item.text?.fontFamily ?? 'Helvetica, Arial, sans-serif',\n fontSize,\n textAlign: item.text?.textAlign ?? 'left',\n resize: 'none',\n cursor: 'text',\n opacity: focused ? 1 : 0, // rest: the engine's picture IS the field\n // A DISABLED control suppresses click events entirely — it must not\n // swallow the stream before it reaches the wrapper, which owns /A\n // activation (the read-only \"fake button\" pattern) and the /AA feed.\n ...(fill.disabled ? { pointerEvents: 'none' as const } : {}),\n };\n const editorProps = {\n value: draft,\n maxLength: fill.maxLength ?? undefined,\n 'aria-label': fill.label,\n disabled: fill.disabled,\n onFocus: () => setFocused(true),\n onChange: (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) =>\n setDraft(e.target.value),\n onBlur: () => {\n setFocused(false);\n if (cancelled.current) {\n cancelled.current = false;\n setDraft(fill.value);\n return;\n }\n if (draft !== fill.value) void form.setText(fill.key, draft);\n },\n style: editorStyle,\n };\n const onKeys = (e: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n if (e.key === 'Escape') {\n cancelled.current = true;\n e.currentTarget.blur();\n }\n if (e.key === 'Enter' && !fill.multiline) e.currentTarget.blur(); // blur commits\n };\n\n return (\n <div\n ref={wrap}\n {...events}\n // ANY widget click runs its /A (see useWidgetActivation): an editable\n // field's focus click bubbles here (Acrobat runs /A on that click\n // too); a read-only field's click lands here directly (the disabled\n // editor is pointer-transparent) — the fake-button pattern.\n onClick={activate}\n style={{\n position: 'absolute',\n left: b.left,\n top: b.top,\n width: b.width,\n height: b.height,\n // Always the event surface (see useWidgetEvents); the editor's own\n // `disabled` keeps read-only fields uneditable and unfocusable.\n pointerEvents: 'auto',\n }}\n >\n <Picture page={page} appearance={appearance} apBox={item.apBox} frame={b} hidden={focused} />\n {fill.multiline ? (\n <textarea {...editorProps} onKeyDown={onKeys} />\n ) : (\n <input {...editorProps} type={fill.password ? 'password' : 'text'} onKeyDown={onKeys} />\n )}\n </div>\n );\n}\n\nfunction ToggleWidget({ fill, item, page, appearance }: WidgetProps<'toggle'>) {\n const form = useCapability(FormToken);\n const wrap = useIsolated<HTMLDivElement>();\n const events = useWidgetEvents(fill.key, item.ref);\n const activate = useWidgetActivation(fill.key, item.ref);\n const [focused, setFocused] = useState(false);\n const b = viewBox(item.box, page);\n const press = () => {\n // Checkbox: click toggles on/off (null clears). Radio: click always\n // selects its own on-state — no untoggle, per PDF/Acrobat convention.\n // Acrobat's order: the VALUE change first, THEN the /A — so an /A\n // script reads the post-toggle state. A read-only toggle still\n // activates (it just doesn't flip).\n const flipped = fill.disabled\n ? undefined\n : form.toggle(fill.key, fill.kind === 'checkbox' && fill.checked ? null : fill.onState);\n void Promise.resolve(flipped).then(activate, activate);\n };\n return (\n <div\n ref={wrap}\n role={fill.kind === 'checkbox' ? 'checkbox' : 'radio'}\n aria-checked={fill.checked}\n aria-label={fill.label}\n tabIndex={fill.disabled ? -1 : 0}\n {...events}\n onClick={press}\n onFocus={(e) => {\n setFocused(true);\n events.onFocus?.(e);\n }}\n onBlur={(e) => {\n setFocused(false);\n events.onBlur?.(e);\n }}\n onKeyDown={(e) => {\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n press();\n }\n }}\n style={{\n position: 'absolute',\n left: b.left,\n top: b.top,\n width: b.width,\n height: b.height,\n cursor: fill.disabled ? 'default' : 'pointer',\n pointerEvents: 'auto', // always the event surface; toggle() self-gates\n outline: 'none', // the top-layer FormFocusRing owns focus indication\n }}\n >\n <Picture page={page} appearance={appearance} apBox={item.apBox} frame={b} />\n <FormFocusRing visible={focused} />\n </div>\n );\n}\n\nfunction ChoiceWidget(props: WidgetProps<'choice'>) {\n return props.fill.kind === 'list' ? <ListBoxWidget {...props} /> : <ComboBoxWidget {...props} />;\n}\n\nfunction ChoiceFrame({\n fill,\n item,\n page,\n focused,\n innerRef,\n children,\n}: Pick<WidgetProps<'choice'>, 'fill' | 'item' | 'page'> & {\n focused: boolean;\n innerRef: React.RefObject<HTMLDivElement>;\n children: React.ReactNode;\n}) {\n const events = useWidgetEvents(fill.key, item.ref);\n const activate = useWidgetActivation(fill.key, item.ref);\n const b = viewBox(item.box, page);\n return (\n <div\n ref={innerRef}\n {...events}\n onClick={activate}\n style={{\n position: 'absolute',\n left: b.left,\n top: b.top,\n width: b.width,\n height: b.height,\n pointerEvents: 'auto',\n outline: 'none', // the top-layer FormFocusRing owns focus indication\n }}\n >\n {children}\n <FormFocusRing visible={focused} />\n </div>\n );\n}\n\nfunction ComboBoxWidget({ fill, item, page, appearance }: WidgetProps<'choice'>) {\n const form = useCapability(FormToken);\n const wrap = useIsolated<HTMLDivElement>();\n const [focused, setFocused] = useState(false);\n const b = viewBox(item.box, page);\n return (\n <ChoiceFrame fill={fill} item={item} page={page} focused={focused} innerRef={wrap}>\n <Picture page={page} appearance={appearance} apBox={item.apBox} frame={b} />\n {/* A combo's popup is separate from its resting box, so the baked\n appearance and transparent native trigger do not maintain competing\n in-place row geometry or scroll state. */}\n <select\n key={fill.selected.join('\\0')}\n defaultValue={fill.selected[0] ?? ''}\n aria-label={fill.label}\n disabled={fill.disabled}\n onFocus={() => setFocused(true)}\n onBlur={() => setFocused(false)}\n onChange={(e) => {\n const values = Array.from(e.currentTarget.selectedOptions).map((o) => o.value);\n void form.choose(fill.key, values);\n }}\n style={{\n position: 'absolute',\n inset: 0,\n width: '100%',\n height: '100%',\n opacity: 0,\n cursor: fill.disabled ? 'default' : 'pointer',\n // A disabled control suppresses clicks — the frame owns /A\n // activation and must still receive them.\n ...(fill.disabled ? { pointerEvents: 'none' as const } : {}),\n }}\n >\n {fill.options.map((o, i) => (\n <option key={i} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n </ChoiceFrame>\n );\n}\n\nfunction ListBoxWidget({ fill, item, page }: WidgetProps<'choice'>) {\n const form = useCapability(FormToken);\n const wrap = useIsolated<HTMLDivElement>();\n const [focused, setFocused] = useState(false);\n const b = viewBox(item.box, page);\n const scale = item.box.width > 0 ? b.width / item.box.width : 1;\n const strokeWidth = item.style.strokeWidth * scale;\n const borderStyle = item.style.border.kind === 'dashed' ? 'dashed' : 'solid';\n return (\n <ChoiceFrame fill={fill} item={item} page={page} focused={focused} innerRef={wrap}>\n <NativeListBox\n ariaLabel={fill.label}\n disabled={fill.disabled}\n multi={fill.multi}\n options={fill.options}\n selected={fill.selected}\n onFocus={() => setFocused(true)}\n onBlur={() => setFocused(false)}\n onSelect={(values) => form.choose(fill.key, values)}\n style={{\n position: 'absolute',\n inset: 0,\n width: '100%',\n height: '100%',\n boxSizing: 'border-box',\n margin: 0,\n padding: 0,\n borderWidth: strokeWidth,\n borderStyle,\n borderColor: item.style.color,\n borderRadius: 0,\n outline: 'none',\n background: item.style.interiorColor ?? '#fff',\n color: item.text?.fontColor ?? '#000',\n fontFamily: item.text?.fontFamily ?? 'Helvetica, Arial, sans-serif',\n fontSize: (item.text?.fontSize || 12) * scale,\n textAlign: item.text?.textAlign ?? 'left',\n cursor: fill.disabled ? 'default' : 'pointer',\n // A disabled control suppresses clicks — the frame owns /A\n // activation and must still receive them.\n ...(fill.disabled ? { pointerEvents: 'none' as const } : {}),\n }}\n />\n </ChoiceFrame>\n );\n}\n\n/**\n * The form plugin's renderer entry, ready for\n * `<AnnotationLayer renderers={[formWidgetRenderer]} />`. It answers for the\n * PLUGIN-registered 'form-widgets' Behavior — the form plugin decides when\n * widgets are fill controls vs. editable annotations, never the app.\n */\nexport const formWidgetRenderer: AnnotationRenderer = {\n behavior: 'form-widgets',\n component: FormWidget,\n};\n\n/* ══════════════════════ standalone layer (no annotations) ══════════════════ */\n\nconst controlBase: React.CSSProperties = {\n position: 'absolute',\n boxSizing: 'border-box',\n border: '1px solid rgba(56, 88, 233, 0.55)',\n background: 'rgba(255, 255, 255, 0.92)',\n borderRadius: 2,\n font: 'inherit',\n};\n\nconst fillBox = (item: FillItem, page: PageContextValue) => viewBox(item.box, page);\n\n/** The standalone layer's event surface: positions ONE control's box and\n * carries the /AA DOM-event feed — always pointer-active (see\n * useWidgetEvents); the control inside fills it and self-gates edits.\n * With `activate`, a click on the box runs the widget's /A (see\n * useWidgetActivation — activation is a WIDGET behavior); push buttons\n * keep their own gated inner door and do NOT set it. */\nfunction FillEventBox({\n item,\n page,\n cursor,\n activate,\n children,\n}: {\n item: FillItem;\n page: PageContextValue;\n cursor?: string;\n activate?: boolean;\n children: React.ReactNode;\n}) {\n const events = useWidgetEvents(item.key, {\n kind: 'objectNumber',\n pageObjectNumber: page.pon,\n annotObjectNumber: item.annotObjectNumber,\n });\n const onActivate = useWidgetActivation(item.key, {\n kind: 'objectNumber',\n pageObjectNumber: page.pon,\n annotObjectNumber: item.annotObjectNumber,\n });\n const css = fillBox(item, page);\n return (\n <div\n {...events}\n onClick={activate ? onActivate : undefined}\n style={{ position: 'absolute', ...css, pointerEvents: 'auto', ...(cursor ? { cursor } : {}) }}\n >\n {children}\n </div>\n );\n}\n\nconst fillControl: React.CSSProperties = {\n position: 'absolute',\n inset: 0,\n width: '100%',\n height: '100%',\n};\n\n/** Text control: keystrokes stay LOCAL (the input is the draft store);\n * the engine write happens on blur or Enter. */\nfunction FillText({\n item,\n page,\n}: {\n item: Extract<FillItem, { control: 'text' }>;\n page: PageContextValue;\n}) {\n const form = useCapability(FormToken);\n const [draft, setDraft] = useState(item.value);\n // Adopt engine truth whenever it changes under us (remote edit, reset).\n useEffect(() => setDraft(item.value), [item.value]);\n\n const css = fillBox(item, page);\n const fontSize = Math.max(9, Math.min(css.height * 0.62, 24));\n const commit = () => {\n if (draft !== item.value) void form.setText(item.key, draft).catch(() => setDraft(item.value));\n };\n const shared: React.CSSProperties = {\n ...controlBase,\n ...fillControl,\n fontSize,\n padding: '0 3px',\n ...(item.comb ? { letterSpacing: css.width / Math.max(1, item.maxLength ?? 1) / 2 } : {}),\n };\n // A disabled control suppresses clicks — the box owns /A activation and\n // must still receive them (the read-only \"fake button\" pattern).\n const editorGate = item.disabled ? ({ pointerEvents: 'none' } as const) : {};\n return (\n <FillEventBox item={item} page={page} activate>\n {item.multiline ? (\n <textarea\n aria-label={item.label}\n value={draft}\n disabled={item.disabled}\n onChange={(e) => setDraft(e.target.value)}\n onBlur={commit}\n style={{ ...shared, resize: 'none', ...editorGate }}\n />\n ) : (\n <input\n aria-label={item.label}\n type={item.password ? 'password' : 'text'}\n value={draft}\n maxLength={item.maxLength ?? undefined}\n disabled={item.disabled}\n onChange={(e) => setDraft(e.target.value)}\n onBlur={commit}\n onKeyDown={(e) => {\n if (e.key === 'Enter') (e.target as HTMLInputElement).blur();\n }}\n style={{ ...shared, ...editorGate }}\n />\n )}\n </FillEventBox>\n );\n}\n\nfunction FillToggle({\n item,\n page,\n}: {\n item: Extract<FillItem, { control: 'toggle' }>;\n page: PageContextValue;\n}) {\n const form = useCapability(FormToken);\n const activate = useWidgetActivation(item.key, {\n kind: 'objectNumber',\n pageObjectNumber: page.pon,\n annotObjectNumber: item.annotObjectNumber,\n });\n const css = fillBox(item, page);\n const glyphSize = Math.min(css.width, css.height) * 0.72;\n return (\n // `activate` covers the DISABLED path (pointer-transparent button → the\n // box click activates without toggling — a read-only toggle's /A still\n // runs); the enabled button below chains toggle-then-/A itself and\n // stops propagation so the click never double-activates.\n <FillEventBox item={item} page={page} cursor={item.disabled ? 'default' : 'pointer'} activate>\n <button\n role={item.kind}\n aria-checked={item.checked}\n aria-label={item.label}\n disabled={item.disabled}\n onClick={(e) => {\n e.stopPropagation();\n // Checkbox re-click clears; radio click always selects its state.\n // Acrobat's order: the VALUE change first, THEN the /A.\n void Promise.resolve(\n form.toggle(item.key, item.kind === 'checkbox' && item.checked ? null : item.onState),\n ).then(activate, activate);\n }}\n style={{\n ...controlBase,\n ...fillControl,\n cursor: 'inherit',\n display: 'grid',\n placeItems: 'center',\n padding: 0,\n borderRadius: item.kind === 'radio' ? '50%' : 2,\n fontSize: glyphSize,\n lineHeight: 1,\n color: '#1f2a44',\n // A disabled control suppresses clicks — the box must receive them.\n ...(item.disabled ? { pointerEvents: 'none' as const } : {}),\n }}\n >\n {item.checked ? (item.kind === 'radio' ? '●' : '✓') : ''}\n </button>\n </FillEventBox>\n );\n}\n\nfunction FillChoice({\n item,\n page,\n}: {\n item: Extract<FillItem, { control: 'choice' }>;\n page: PageContextValue;\n}) {\n const form = useCapability(FormToken);\n const css = fillBox(item, page);\n // A disabled control suppresses clicks — the box owns /A activation and\n // must still receive them.\n const controlGate = item.disabled ? ({ pointerEvents: 'none' } as const) : {};\n if (item.kind === 'list') {\n return (\n <FillEventBox item={item} page={page} activate>\n <NativeListBox\n ariaLabel={item.label}\n disabled={item.disabled}\n multi={item.multi}\n options={item.options}\n selected={item.selected}\n onSelect={(values) => form.choose(item.key, values)}\n style={{\n ...controlBase,\n ...fillControl,\n fontSize: Math.max(9, Math.min(css.height * 0.55, 18)),\n ...controlGate,\n }}\n />\n </FillEventBox>\n );\n }\n return (\n <FillEventBox item={item} page={page} activate>\n <select\n aria-label={item.label}\n disabled={item.disabled}\n value={item.selected[0] ?? ''}\n onChange={(e) => void form.choose(item.key, [e.target.value])}\n style={{\n ...controlBase,\n ...fillControl,\n fontSize: Math.max(9, Math.min(css.height * 0.55, 18)),\n ...controlGate,\n }}\n >\n {item.selected.length === 0 && <option value=\"\" />}\n {item.options.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n </FillEventBox>\n );\n}\n\nfunction FillButton({\n item,\n page,\n}: {\n item: Extract<FillItem, { control: 'button' }>;\n page: PageContextValue;\n}) {\n const form = useCapability(FormToken);\n return (\n <FillEventBox item={item} page={page} cursor={item.disabled ? 'default' : 'pointer'}>\n <button\n type=\"button\"\n aria-label={item.label}\n disabled={item.disabled}\n onClick={() =>\n void form.activateWidget(item.key, {\n kind: 'objectNumber',\n pageObjectNumber: page.pon,\n annotObjectNumber: item.annotObjectNumber,\n })\n }\n style={{\n ...controlBase,\n ...fillControl,\n padding: 0,\n border: 0,\n background: 'transparent',\n cursor: 'inherit',\n // Events live on the box; a disabled button must not swallow them.\n pointerEvents: item.disabled ? 'none' : 'auto',\n }}\n />\n </FillEventBox>\n );\n}\n\n/** The standalone layer's signature control: the same target/inspect\n * hand-off as {@link SignatureWidget}, over the page raster. */\nfunction FillSignature({\n item,\n page,\n}: {\n item: Extract<FillItem, { control: 'signature' }>;\n page: PageContextValue;\n}) {\n const signature = useOptionalCapability(SignatureToken);\n const ref = fieldRefOfKey(item.key);\n const signed = useOptionalSelector(\n SignatureToken,\n (c) => c.signatureOf(ref)?.signed ?? item.signed,\n item.signed,\n );\n const actionable = signature != null && (signed || !item.disabled);\n return (\n <FillEventBox item={item} page={page} cursor={actionable ? 'pointer' : 'default'}>\n {actionable ? (\n <button\n type=\"button\"\n aria-label={item.label}\n data-signed={signed ? '' : undefined}\n onClick={() => (signed ? signature.inspect(ref) : signature.setTarget(ref))}\n style={{\n ...fillControl,\n padding: 0,\n border: 0,\n background: 'transparent',\n cursor: 'inherit',\n }}\n />\n ) : null}\n </FillEventBox>\n );\n}\n\n/**\n * Fill-mode form controls for one page, positioned from the form model's own\n * widget geometry — the ANNOTATION-LESS path (a fill-only viewer whose page\n * pixels come from an annotated RenderLayer raster). Active whenever the\n * active tool carries the 'form-fill' tag (the built-in pointer/pan tools\n * do); any other tool stands the controls down. Do not mount next to an\n * AnnotationLayer wired with `formWidgetBehaviors`.\n */\nexport function FormLayer() {\n const page = usePage();\n const form = useCapability(FormToken);\n const active = useSelector(InteractionToken, (c) => c.activeTool().enables.has('form-fill'));\n\n useEffect(() => {\n if (active) form.ensureGeom(page.pon);\n }, [active, form, page.pon]);\n\n const items = useSelector(FormToken, (c) => c.fillItems(page.pon), shallowArray);\n if (!active) return null;\n\n return (\n <div style={{ position: 'absolute', inset: 0 }}>\n {items.map((item) =>\n item.control === 'text' ? (\n <FillText key={`${item.key}:${item.annotObjectNumber}`} item={item} page={page} />\n ) : item.control === 'toggle' ? (\n <FillToggle key={`${item.key}:${item.annotObjectNumber}`} item={item} page={page} />\n ) : item.control === 'choice' ? (\n <FillChoice key={`${item.key}:${item.annotObjectNumber}`} item={item} page={page} />\n ) : item.control === 'button' ? (\n <FillButton key={`${item.key}:${item.annotObjectNumber}`} item={item} page={page} />\n ) : item.control === 'signature' ? (\n <FillSignature key={`${item.key}:${item.annotObjectNumber}`} item={item} page={page} />\n ) : null,\n )}\n </div>\n );\n}\n\n/* ═══════════════════════════════ hooks ═══════════════════════════════ */\n\n/** The form capability — values, interchange, design-mode verbs. */\nexport function useForm() {\n return useCapability(FormToken);\n}\n\n/** The reconciled form snapshot (null until the first load lands),\n * re-rendering on every form model change. */\nexport function useFormSnapshot() {\n return useSelector(FormToken, (c) => c.snapshot());\n}\n\n/**\n * The FIELD behind the currently selected widget annotation (single\n * selection), or null. The design-mode join: widget selection lives in the\n * annotation plane, field properties live here.\n */\nexport function useFormField(): FormFieldDTO | null {\n const selected = useAnnotationSelected();\n const widget = selected.length === 1 && selected[0]!.subtype === 'widget' ? selected[0]! : null;\n const objnum = widget && widget.ref.kind === 'objectNumber' ? widget.ref.annotObjectNumber : 0;\n return useSelector(FormToken, (c) => (objnum > 0 ? c.fieldForWidget(objnum) : null));\n}\n"],"mappings":"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"}
@@ -1,4 +1,6 @@
1
- //#region ../../engine/core/dist/AnnotationListSnapshot-x6tKulNV.d.ts
1
+ import { o as AnnotationRenderer } from "./annotation-k38KDlIZ.js";
2
+ import { FormFieldDTO } from "@embedpdf/plugin-form";
3
+ //#region ../../engine/core/dist/AnnotationListSnapshot-D9R5n2Kf.d.ts
2
4
  //#endregion
3
5
  //#region src/identity/PageObjectNumber.d.ts
4
6
  /**
@@ -467,7 +469,7 @@ interface UnknownFieldDTO extends FormFieldBase {
467
469
  * }
468
470
  * ```
469
471
  */
470
- type FormFieldDTO = TextFieldDTO | CheckboxFieldDTO | RadioFieldDTO | ComboBoxFieldDTO | ListBoxFieldDTO | PushButtonFieldDTO | SignatureFieldDTO | UnknownFieldDTO;
472
+ type FormFieldDTO$1 = TextFieldDTO | CheckboxFieldDTO | RadioFieldDTO | ComboBoxFieldDTO | ListBoxFieldDTO | PushButtonFieldDTO | SignatureFieldDTO | UnknownFieldDTO;
471
473
  //#endregion
472
474
  //#region src/forms/snapshot.d.ts
473
475
  /**
@@ -497,50 +499,39 @@ interface FormSnapshot {
497
499
  * `repair({ bakeAppearances: true })` can clear the flag document-wide.
498
500
  */
499
501
  needsAppearances: boolean;
500
- fields: FormFieldDTO[];
502
+ fields: FormFieldDTO$1[];
501
503
  /** `/AcroForm /CO` order; null preserves each malformed/unresolved slot. */
502
504
  calculationOrder: Array<FormFieldRef | null>;
503
505
  }
504
506
  //#endregion
505
- //#region src/search/types.d.ts
507
+ //#region src/form.d.ts
506
508
  /**
507
- * What to search for — THE one shape, engine → wire → plugin state →
508
- * search box. One flat object; the flags define behavior per mode instead
509
- * of the mode changing the shape:
510
- *
511
- * | flag | literal | regex |
512
- * |-------------------|------------------|--------------------------------|
513
- * | `matchCase` | fold case | `i` flag |
514
- * | `wholeWord` | boundary check | pattern is `\b(?:…)\b`-wrapped |
515
- * | `matchDiacritics` | mark fold | REJECTED (`InvalidArg`) |
516
- *
517
- * Literal queries match over FOLDED text; regex queries run the portable
518
- * dialect against the RAW page text — which is why `matchDiacritics`
519
- * cannot apply to them (diacritic folding is a property of the folded
520
- * text plane). Validate with `validateSearchQuery` for early UI feedback;
521
- * engines re-validate and reject with `EngineErrorCode.InvalidArg`.
509
+ * The form plugin's renderer entry, ready for
510
+ * `<AnnotationLayer renderers={[formWidgetRenderer]} />`. It answers for the
511
+ * PLUGIN-registered 'form-widgets' Behavior — the form plugin decides when
512
+ * widgets are fill controls vs. editable annotations, never the app.
522
513
  */
523
- interface SearchQuery {
524
- /**
525
- * The literal text — or, when `regex`, a pattern in the portable
526
- * search-regex dialect: JavaScript `u`-mode syntax MINUS backreferences
527
- * and lookaround, so every valid pattern also runs on RE2 (the
528
- * server-side engine).
529
- */
530
- text: string;
531
- /** Interpret `text` as a regex pattern. Default false (literal). */
532
- regex?: boolean;
533
- /** Exact-case matching. Default false (case-folded / `i` semantics). */
534
- matchCase?: boolean;
535
- /** Only match at word boundaries (letters/digits end the word). */
536
- wholeWord?: boolean;
537
- /**
538
- * Treat diacritics as significant ("café" ≠ "cafe"). Default false —
539
- * marks are stripped on both sides, which is what viewers ship.
540
- * LITERAL ONLY: combined with `regex` the query is rejected.
541
- */
542
- matchDiacritics?: boolean;
543
- }
514
+ declare const formWidgetRenderer: AnnotationRenderer;
515
+ /**
516
+ * Fill-mode form controls for one page, positioned from the form model's own
517
+ * widget geometry — the ANNOTATION-LESS path (a fill-only viewer whose page
518
+ * pixels come from an annotated RenderLayer raster). Active whenever the
519
+ * active tool carries the 'form-fill' tag (the built-in pointer/pan tools
520
+ * do); any other tool stands the controls down. Do not mount next to an
521
+ * AnnotationLayer wired with `formWidgetBehaviors`.
522
+ */
523
+ declare function FormLayer(): import("react/jsx-runtime").JSX.Element | null;
524
+ /** The form capability — values, interchange, design-mode verbs. */
525
+ declare function useForm(): import("@embedpdf/plugin-form").FormCapability;
526
+ /** The reconciled form snapshot (null until the first load lands),
527
+ * re-rendering on every form model change. */
528
+ declare function useFormSnapshot(): FormSnapshot | null;
529
+ /**
530
+ * The FIELD behind the currently selected widget annotation (single
531
+ * selection), or null. The design-mode join: widget selection lives in the
532
+ * annotation plane, field properties live here.
533
+ */
534
+ declare function useFormField(): FormFieldDTO | null;
544
535
  //#endregion
545
- export { SearchQuery as n, FormSnapshot as t };
546
- //# sourceMappingURL=AnnotationListSnapshot-x6tKulNV-B799rYyi.d.cts.map
536
+ export { useFormSnapshot as a, useFormField as i, formWidgetRenderer as n, useForm as r, FormLayer as t };
537
+ //# sourceMappingURL=form-CYRYgthn.d.ts.map
package/dist/form.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("./runtime.cjs");
3
- const require_form = require("./form-D-ZSfGmB.cjs");
3
+ const require_form = require("./form-BVumS7up.cjs");
4
4
  exports.FormLayer = require_form.FormLayer;
5
5
  exports.formWidgetRenderer = require_form.formWidgetRenderer;
6
6
  exports.useForm = require_form.useForm;
package/dist/form.d.cts CHANGED
@@ -1,35 +1,3 @@
1
- import { o as AnnotationRenderer } from "./annotation-BCED_p9H.cjs";
2
- import { t as FormSnapshot } from "./AnnotationListSnapshot-x6tKulNV-B799rYyi.cjs";
3
- import { FormFieldDTO } from "@embedpdf/plugin-form";
1
+ import { a as useFormSnapshot, i as useFormField, n as formWidgetRenderer, r as useForm, t as FormLayer } from "./form-Bdjk0Z3T.cjs";
4
2
  export * from "@embedpdf/plugin-form";
5
- //#region src/form.d.ts
6
- /**
7
- * The form plugin's renderer entry, ready for
8
- * `<AnnotationLayer renderers={[formWidgetRenderer]} />`. It answers for the
9
- * PLUGIN-registered 'form-widgets' Behavior — the form plugin decides when
10
- * widgets are fill controls vs. editable annotations, never the app.
11
- */
12
- declare const formWidgetRenderer: AnnotationRenderer;
13
- /**
14
- * Fill-mode form controls for one page, positioned from the form model's own
15
- * widget geometry — the ANNOTATION-LESS path (a fill-only viewer whose page
16
- * pixels come from an annotated RenderLayer raster). Active whenever the
17
- * active tool carries the 'form-fill' tag (the built-in pointer/pan tools
18
- * do); any other tool stands the controls down. Do not mount next to an
19
- * AnnotationLayer wired with `formWidgetBehaviors`.
20
- */
21
- declare function FormLayer(): import("react/jsx-runtime").JSX.Element | null;
22
- /** The form capability — values, interchange, design-mode verbs. */
23
- declare function useForm(): import("@embedpdf/plugin-form").FormCapability;
24
- /** The reconciled form snapshot (null until the first load lands),
25
- * re-rendering on every form model change. */
26
- declare function useFormSnapshot(): FormSnapshot | null;
27
- /**
28
- * The FIELD behind the currently selected widget annotation (single
29
- * selection), or null. The design-mode join: widget selection lives in the
30
- * annotation plane, field properties live here.
31
- */
32
- declare function useFormField(): FormFieldDTO | null;
33
- //#endregion
34
- export { FormLayer, formWidgetRenderer, useForm, useFormField, useFormSnapshot };
35
- //# sourceMappingURL=form.d.cts.map
3
+ export { FormLayer, formWidgetRenderer, useForm, useFormField, useFormSnapshot };
package/dist/form.d.ts CHANGED
@@ -1,35 +1,3 @@
1
- import { o as AnnotationRenderer } from "./annotation-k38KDlIZ.js";
2
- import { t as FormSnapshot } from "./AnnotationListSnapshot-x6tKulNV-B799rYyi.js";
3
- import { FormFieldDTO } from "@embedpdf/plugin-form";
1
+ import { a as useFormSnapshot, i as useFormField, n as formWidgetRenderer, r as useForm, t as FormLayer } from "./form-CYRYgthn.js";
4
2
  export * from "@embedpdf/plugin-form";
5
- //#region src/form.d.ts
6
- /**
7
- * The form plugin's renderer entry, ready for
8
- * `<AnnotationLayer renderers={[formWidgetRenderer]} />`. It answers for the
9
- * PLUGIN-registered 'form-widgets' Behavior — the form plugin decides when
10
- * widgets are fill controls vs. editable annotations, never the app.
11
- */
12
- declare const formWidgetRenderer: AnnotationRenderer;
13
- /**
14
- * Fill-mode form controls for one page, positioned from the form model's own
15
- * widget geometry — the ANNOTATION-LESS path (a fill-only viewer whose page
16
- * pixels come from an annotated RenderLayer raster). Active whenever the
17
- * active tool carries the 'form-fill' tag (the built-in pointer/pan tools
18
- * do); any other tool stands the controls down. Do not mount next to an
19
- * AnnotationLayer wired with `formWidgetBehaviors`.
20
- */
21
- declare function FormLayer(): import("react/jsx-runtime").JSX.Element | null;
22
- /** The form capability — values, interchange, design-mode verbs. */
23
- declare function useForm(): import("@embedpdf/plugin-form").FormCapability;
24
- /** The reconciled form snapshot (null until the first load lands),
25
- * re-rendering on every form model change. */
26
- declare function useFormSnapshot(): FormSnapshot | null;
27
- /**
28
- * The FIELD behind the currently selected widget annotation (single
29
- * selection), or null. The design-mode join: widget selection lives in the
30
- * annotation plane, field properties live here.
31
- */
32
- declare function useFormField(): FormFieldDTO | null;
33
- //#endregion
34
- export { FormLayer, formWidgetRenderer, useForm, useFormField, useFormSnapshot };
35
- //# sourceMappingURL=form.d.ts.map
3
+ export { FormLayer, formWidgetRenderer, useForm, useFormField, useFormSnapshot };
package/dist/form.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import "./runtime.js";
2
- import { a as useFormSnapshot, i as useFormField, n as formWidgetRenderer, r as useForm, t as FormLayer } from "./form-BwrLFpKN.js";
2
+ import { a as useFormSnapshot, i as useFormField, n as formWidgetRenderer, r as useForm, t as FormLayer } from "./form-CK3mp99m.js";
3
3
  export * from "@embedpdf/plugin-form";
4
4
  export { FormLayer, formWidgetRenderer, useForm, useFormField, useFormSnapshot };