@embedpdf/react 3.0.0-next.11 → 3.0.0-next.13

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.
@@ -0,0 +1,36 @@
1
+ import { DocumentProtection, FormFieldRef, SignatureCapability, SignatureChange, SignatureSnapshot, SignatureVerdict } from "@embedpdf/plugin-signature";
2
+ import { StampAsset, StampLibrary } from "@embedpdf/plugin-stamp/contract";
3
+ export * from "@embedpdf/plugin-signature";
4
+ //#region src/signature.d.ts
5
+ /** The signature capability for the surrounding document. */
6
+ declare function useSignature(): SignatureCapability;
7
+ /** The last signature snapshot (null until the first read lands). */
8
+ declare function useSignatureSnapshot(): SignatureSnapshot | null;
9
+ /** The last validation (null until one ran). */
10
+ declare function useSignatureVerdicts(): SignatureVerdict[] | null;
11
+ /** What the document's signatures forbid (null when nothing is signed or not yet read). */
12
+ declare function useDocumentProtection(): DocumentProtection | null;
13
+ /** The field the next picked mark goes to, and whether a sign/fill is in flight. */
14
+ declare function useSignatureTarget(): {
15
+ target: FormFieldRef | null;
16
+ busy: boolean;
17
+ };
18
+ /** Subscribe to the plugin's change events (signed / filled / ask / inspect / target / validated …). */
19
+ declare function useSignatureEvent(handler: (event: SignatureChange) => void): void;
20
+ /** One person: a library of kind `signatures` with its marks split by role. */
21
+ interface SignerRow {
22
+ libraryId: string;
23
+ name: string;
24
+ library: StampLibrary;
25
+ signatures: StampAsset[];
26
+ initials: StampAsset | null;
27
+ }
28
+ /**
29
+ * The people whose marks this browser holds — one row per library of kind
30
+ * `signatures`. Purely derived from the stamp plugin: rename, delete, and
31
+ * export are the library verbs; nothing is stored beyond the file.
32
+ */
33
+ declare function useSignerRows(): SignerRow[];
34
+ //#endregion
35
+ export { SignerRow, useDocumentProtection, useSignature, useSignatureEvent, useSignatureSnapshot, useSignatureTarget, useSignatureVerdicts, useSignerRows };
36
+ //# sourceMappingURL=signature.d.cts.map
@@ -0,0 +1,36 @@
1
+ import { DocumentProtection, FormFieldRef, SignatureCapability, SignatureChange, SignatureSnapshot, SignatureVerdict } from "@embedpdf/plugin-signature";
2
+ import { StampAsset, StampLibrary } from "@embedpdf/plugin-stamp/contract";
3
+ export * from "@embedpdf/plugin-signature";
4
+ //#region src/signature.d.ts
5
+ /** The signature capability for the surrounding document. */
6
+ declare function useSignature(): SignatureCapability;
7
+ /** The last signature snapshot (null until the first read lands). */
8
+ declare function useSignatureSnapshot(): SignatureSnapshot | null;
9
+ /** The last validation (null until one ran). */
10
+ declare function useSignatureVerdicts(): SignatureVerdict[] | null;
11
+ /** What the document's signatures forbid (null when nothing is signed or not yet read). */
12
+ declare function useDocumentProtection(): DocumentProtection | null;
13
+ /** The field the next picked mark goes to, and whether a sign/fill is in flight. */
14
+ declare function useSignatureTarget(): {
15
+ target: FormFieldRef | null;
16
+ busy: boolean;
17
+ };
18
+ /** Subscribe to the plugin's change events (signed / filled / ask / inspect / target / validated …). */
19
+ declare function useSignatureEvent(handler: (event: SignatureChange) => void): void;
20
+ /** One person: a library of kind `signatures` with its marks split by role. */
21
+ interface SignerRow {
22
+ libraryId: string;
23
+ name: string;
24
+ library: StampLibrary;
25
+ signatures: StampAsset[];
26
+ initials: StampAsset | null;
27
+ }
28
+ /**
29
+ * The people whose marks this browser holds — one row per library of kind
30
+ * `signatures`. Purely derived from the stamp plugin: rename, delete, and
31
+ * export are the library verbs; nothing is stored beyond the file.
32
+ */
33
+ declare function useSignerRows(): SignerRow[];
34
+ //#endregion
35
+ export { SignerRow, useDocumentProtection, useSignature, useSignatureEvent, useSignatureSnapshot, useSignatureTarget, useSignatureVerdicts, useSignerRows };
36
+ //# sourceMappingURL=signature.d.ts.map
@@ -0,0 +1,67 @@
1
+ import "./rolldown-runtime-BBjsoOtd.js";
2
+ import { shallowArray, useCapability, useCapabilityEvent, useSelector } from "./runtime.js";
3
+ import { useStampLibraries } from "./stamp.js";
4
+ import { useMemo } from "react";
5
+ import { SIGNATURES_LIBRARY_KIND, SignatureToken, markRoleOf } from "@embedpdf/plugin-signature";
6
+ import { StampToken } from "@embedpdf/plugin-stamp/contract";
7
+ export * from "@embedpdf/plugin-signature";
8
+ //#region src/signature.tsx
9
+ /**
10
+ * The React view of @embedpdf/plugin-signature: the act of signing for the
11
+ * surrounding `DocumentScope`, its live facts (snapshot, verdicts,
12
+ * protection, target), and the one derivation a signatures panel needs —
13
+ * the people (libraries of kind `signatures`) with their marks.
14
+ *
15
+ * const signature = useSignature();
16
+ * await signature.placeMark({ assetId }, { field: target }); // sign / fill / ask, by mode
17
+ */
18
+ /** The signature capability for the surrounding document. */
19
+ function useSignature() {
20
+ return useCapability(SignatureToken);
21
+ }
22
+ /** The last signature snapshot (null until the first read lands). */
23
+ function useSignatureSnapshot() {
24
+ return useSelector(SignatureToken, (c) => c.snapshot());
25
+ }
26
+ /** The last validation (null until one ran). */
27
+ function useSignatureVerdicts() {
28
+ return useSelector(SignatureToken, (c) => c.verdicts());
29
+ }
30
+ /** What the document's signatures forbid (null when nothing is signed or not yet read). */
31
+ function useDocumentProtection() {
32
+ return useSelector(SignatureToken, (c) => c.protection());
33
+ }
34
+ /** The field the next picked mark goes to, and whether a sign/fill is in flight. */
35
+ function useSignatureTarget() {
36
+ return {
37
+ target: useSelector(SignatureToken, (c) => c.target()),
38
+ busy: useSelector(SignatureToken, (c) => c.busy())
39
+ };
40
+ }
41
+ /** Subscribe to the plugin's change events (signed / filled / ask / inspect / target / validated …). */
42
+ function useSignatureEvent(handler) {
43
+ useCapabilityEvent(SignatureToken, (c) => c.onChanged, handler);
44
+ }
45
+ /**
46
+ * The people whose marks this browser holds — one row per library of kind
47
+ * `signatures`. Purely derived from the stamp plugin: rename, delete, and
48
+ * export are the library verbs; nothing is stored beyond the file.
49
+ */
50
+ function useSignerRows() {
51
+ const libraries = useStampLibraries({ kind: SIGNATURES_LIBRARY_KIND });
52
+ const assets = useSelector(StampToken, (c) => c.assets(), shallowArray);
53
+ return useMemo(() => libraries.map((library) => {
54
+ const own = assets.filter((asset) => asset.libraryId === library.id);
55
+ return {
56
+ libraryId: library.id,
57
+ name: library.name,
58
+ library,
59
+ signatures: own.filter((asset) => markRoleOf(asset) === "signature"),
60
+ initials: own.find((asset) => markRoleOf(asset) === "initials") ?? null
61
+ };
62
+ }), [libraries, assets]);
63
+ }
64
+ //#endregion
65
+ export { useDocumentProtection, useSignature, useSignatureEvent, useSignatureSnapshot, useSignatureTarget, useSignatureVerdicts, useSignerRows };
66
+
67
+ //# sourceMappingURL=signature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.js","names":[],"sources":["../src/signature.tsx"],"sourcesContent":["/**\n * The React view of @embedpdf/plugin-signature: the act of signing for the\n * surrounding `DocumentScope`, its live facts (snapshot, verdicts,\n * protection, target), and the one derivation a signatures panel needs —\n * the people (libraries of kind `signatures`) with their marks.\n *\n * const signature = useSignature();\n * await signature.placeMark({ assetId }, { field: target }); // sign / fill / ask, by mode\n */\nimport { useMemo } from 'react';\nimport {\n markRoleOf,\n SIGNATURES_LIBRARY_KIND,\n SignatureToken,\n type DocumentProtection,\n type FormFieldRef,\n type SignatureCapability,\n type SignatureChange,\n type SignatureSnapshot,\n type SignatureVerdict,\n} from '@embedpdf/plugin-signature';\nimport { StampToken, type StampAsset, type StampLibrary } from '@embedpdf/plugin-stamp/contract';\n\nimport { shallowArray, useCapability, useCapabilityEvent, useSelector } from './runtime';\nimport { useStampLibraries } from './stamp';\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-signature';\n\n/** The signature capability for the surrounding document. */\nexport function useSignature(): SignatureCapability {\n return useCapability(SignatureToken);\n}\n\n/** The last signature snapshot (null until the first read lands). */\nexport function useSignatureSnapshot(): SignatureSnapshot | null {\n return useSelector(SignatureToken, (c) => c.snapshot());\n}\n\n/** The last validation (null until one ran). */\nexport function useSignatureVerdicts(): SignatureVerdict[] | null {\n return useSelector(SignatureToken, (c) => c.verdicts());\n}\n\n/** What the document's signatures forbid (null when nothing is signed or not yet read). */\nexport function useDocumentProtection(): DocumentProtection | null {\n return useSelector(SignatureToken, (c) => c.protection());\n}\n\n/** The field the next picked mark goes to, and whether a sign/fill is in flight. */\nexport function useSignatureTarget(): { target: FormFieldRef | null; busy: boolean } {\n const target = useSelector(SignatureToken, (c) => c.target());\n const busy = useSelector(SignatureToken, (c) => c.busy());\n return { target, busy };\n}\n\n/** Subscribe to the plugin's change events (signed / filled / ask / inspect / target / validated …). */\nexport function useSignatureEvent(handler: (event: SignatureChange) => void): void {\n useCapabilityEvent(SignatureToken, (c) => c.onChanged, handler);\n}\n\n/** One person: a library of kind `signatures` with its marks split by role. */\nexport interface SignerRow {\n libraryId: string;\n name: string;\n library: StampLibrary;\n signatures: StampAsset[];\n initials: StampAsset | null;\n}\n\n/**\n * The people whose marks this browser holds — one row per library of kind\n * `signatures`. Purely derived from the stamp plugin: rename, delete, and\n * export are the library verbs; nothing is stored beyond the file.\n */\nexport function useSignerRows(): SignerRow[] {\n const libraries = useStampLibraries({ kind: SIGNATURES_LIBRARY_KIND });\n const assets = useSelector(StampToken, (c) => c.assets(), shallowArray);\n return useMemo(\n () =>\n libraries.map((library) => {\n const own = assets.filter((asset) => asset.libraryId === library.id);\n return {\n libraryId: library.id,\n name: library.name,\n library,\n signatures: own.filter((asset) => markRoleOf(asset) === 'signature'),\n initials: own.find((asset) => markRoleOf(asset) === 'initials') ?? null,\n };\n }),\n [libraries, assets],\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA8BA,SAAgB,eAAoC;CAClD,OAAO,cAAc,cAAc;AACrC;;AAGA,SAAgB,uBAAiD;CAC/D,OAAO,YAAY,iBAAiB,MAAM,EAAE,SAAS,CAAC;AACxD;;AAGA,SAAgB,uBAAkD;CAChE,OAAO,YAAY,iBAAiB,MAAM,EAAE,SAAS,CAAC;AACxD;;AAGA,SAAgB,wBAAmD;CACjE,OAAO,YAAY,iBAAiB,MAAM,EAAE,WAAW,CAAC;AAC1D;;AAGA,SAAgB,qBAAqE;CAGnF,OAAO;EAAE,QAFM,YAAY,iBAAiB,MAAM,EAAE,OAAO,CAE7C;EAAG,MADJ,YAAY,iBAAiB,MAAM,EAAE,KAAK,CACnC;CAAE;AACxB;;AAGA,SAAgB,kBAAkB,SAAiD;CACjF,mBAAmB,iBAAiB,MAAM,EAAE,WAAW,OAAO;AAChE;;;;;;AAgBA,SAAgB,gBAA6B;CAC3C,MAAM,YAAY,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;CACrE,MAAM,SAAS,YAAY,aAAa,MAAM,EAAE,OAAO,GAAG,YAAY;CACtE,OAAO,cAEH,UAAU,KAAK,YAAY;EACzB,MAAM,MAAM,OAAO,QAAQ,UAAU,MAAM,cAAc,QAAQ,EAAE;EACnE,OAAO;GACL,WAAW,QAAQ;GACnB,MAAM,QAAQ;GACd;GACA,YAAY,IAAI,QAAQ,UAAU,WAAW,KAAK,MAAM,WAAW;GACnE,UAAU,IAAI,MAAM,UAAU,WAAW,KAAK,MAAM,UAAU,KAAK;EACrE;CACF,CAAC,GACH,CAAC,WAAW,MAAM,CACpB;AACF"}
package/dist/stamp.cjs CHANGED
@@ -2,14 +2,17 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("./rolldown-runtime-DDXJien1.cjs");
3
3
  const require_runtime = require("./runtime.cjs");
4
4
  let react = require("react");
5
+ let _embedpdf_web = require("@embedpdf/web");
5
6
  let _embedpdf_plugin_stamp = require("@embedpdf/plugin-stamp");
6
7
  //#region src/stamp.tsx
7
8
  /** The stamp capability (workspace-scoped: one library set for every document). */
8
9
  function useStamp() {
9
10
  return require_runtime.useCapability(_embedpdf_plugin_stamp.StampToken);
10
11
  }
11
- function useStampLibraries() {
12
- return require_runtime.useSelector(_embedpdf_plugin_stamp.StampToken, (c) => c.libraries(), require_runtime.shallowArray);
12
+ /** Libraries, optionally of one kind or several (`{ kind: 'stamps' }`, `{ kind: ['stamps', 'toolbar'] }`). */
13
+ function useStampLibraries(query) {
14
+ const kinds = query?.kind === void 0 ? void 0 : [].concat(query.kind).join("\0");
15
+ return require_runtime.useSelector(_embedpdf_plugin_stamp.StampToken, (c) => c.libraries(kinds === void 0 ? void 0 : { kind: kinds.split("\0") }), require_runtime.shallowArray);
13
16
  }
14
17
  /** Assets of one library, or every asset when `libraryId` is omitted. */
15
18
  function useStampAssets(libraryId) {
@@ -59,6 +62,12 @@ function useArmStampAsset() {
59
62
  };
60
63
  }
61
64
  //#endregion
65
+ Object.defineProperty(exports, "indexedDbByteStore", {
66
+ enumerable: true,
67
+ get: function() {
68
+ return _embedpdf_web.indexedDbByteStore;
69
+ }
70
+ });
62
71
  exports.useArmStampAsset = useArmStampAsset;
63
72
  exports.useStamp = useStamp;
64
73
  exports.useStampAssetPreviewUrl = useStampAssetPreviewUrl;
@@ -1 +1 @@
1
- {"version":3,"file":"stamp.cjs","names":["useCapability","StampToken","useSelector","shallowArray","useDocumentId"],"sources":["../src/stamp.tsx"],"sourcesContent":["/**\n * The React view of @embedpdf/plugin-stamp.\n *\n * Thin by design: the plugin owns the store (libraries/assets) and the binary\n * sidecar (bytes + cached previews); this file only exposes hooks and owns the\n * DOM-side object-URL lifetime for gallery thumbnails. Placement UI needs no\n * component here — arming rides the annotation plugin, whose `<AnnotationLayer>`\n * already renders the hover ghost.\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-stamp';\nimport { useEffect, useState } from 'react';\nimport { StampToken, type StampAsset, type StampLibrary } from '@embedpdf/plugin-stamp';\nimport { shallowArray, useCapability, useDocumentId, useSelector } from './runtime';\n\n/** The stamp capability (workspace-scoped: one library set for every document). */\nexport function useStamp() {\n return useCapability(StampToken);\n}\n\nexport function useStampLibraries(): StampLibrary[] {\n return useSelector(StampToken, (c) => c.libraries(), shallowArray);\n}\n\n/** Assets of one library, or every asset when `libraryId` is omitted. */\nexport function useStampAssets(libraryId?: string): StampAsset[] {\n return useSelector(StampToken, (c) => c.assets(libraryId), shallowArray);\n}\n\n/**\n * Object URL for an asset's cached preview (gallery thumbnails). The plugin\n * holds the preview BYTES; the URL — a DOM resource — is created here and\n * revoked on unmount/asset change, mirroring `<AnnotationLayer>`'s rule that\n * object-URL lifetime belongs to the framework layer.\n */\nexport function useStampAssetPreviewUrl(assetId: string | null): string | null {\n const stamp = useCapability(StampToken);\n const [url, setUrl] = useState<string | null>(null);\n useEffect(() => {\n const preview = assetId ? stamp.assetPreview(assetId) : null;\n if (!preview) {\n setUrl(null);\n return;\n }\n // Copy into an EXACT ArrayBuffer (the engine idiom) before Blob-wrapping.\n const body = new ArrayBuffer(preview.bytes.byteLength);\n new Uint8Array(body).set(preview.bytes);\n const obj = URL.createObjectURL(new Blob([body], { type: preview.mimeType }));\n setUrl(obj);\n return () => {\n URL.revokeObjectURL(obj);\n setUrl(null);\n };\n }, [stamp, assetId]);\n return url;\n}\n\n/**\n * Arm/disarm assets against the nearest `<DocumentScope>` (or the active\n * document) — the one-liner a gallery item's onClick needs.\n */\nexport function useArmStampAsset(): {\n armAsset: (assetId: string, opts?: { targetWidth?: number }) => Promise<void>;\n disarm: () => void;\n} {\n const stamp = useCapability(StampToken);\n const documentId = useDocumentId();\n return {\n armAsset: (assetId, opts) => {\n if (!documentId) return Promise.reject(new Error('[stamp] no document in scope'));\n return stamp.armAsset(documentId, assetId, opts);\n },\n disarm: () => {\n if (documentId) stamp.disarm(documentId);\n },\n };\n}\n"],"mappings":";;;;;;;AAiBA,SAAgB,WAAW;CACzB,OAAOA,gBAAAA,cAAcC,uBAAAA,UAAU;AACjC;AAEA,SAAgB,oBAAoC;CAClD,OAAOC,gBAAAA,YAAYD,uBAAAA,aAAa,MAAM,EAAE,UAAU,GAAGE,gBAAAA,YAAY;AACnE;;AAGA,SAAgB,eAAe,WAAkC;CAC/D,OAAOD,gBAAAA,YAAYD,uBAAAA,aAAa,MAAM,EAAE,OAAO,SAAS,GAAGE,gBAAAA,YAAY;AACzE;;;;;;;AAQA,SAAgB,wBAAwB,SAAuC;CAC7E,MAAM,QAAQH,gBAAAA,cAAcC,uBAAAA,UAAU;CACtC,MAAM,CAAC,KAAK,WAAA,GAAA,MAAA,SAAA,CAAkC,IAAI;CAClD,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,MAAM,UAAU,UAAU,MAAM,aAAa,OAAO,IAAI;EACxD,IAAI,CAAC,SAAS;GACZ,OAAO,IAAI;GACX;EACF;EAEA,MAAM,OAAO,IAAI,YAAY,QAAQ,MAAM,UAAU;EACrD,IAAI,WAAW,IAAI,CAAC,CAAC,IAAI,QAAQ,KAAK;EACtC,MAAM,MAAM,IAAI,gBAAgB,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,MAAM,QAAQ,SAAS,CAAC,CAAC;EAC5E,OAAO,GAAG;EACV,aAAa;GACX,IAAI,gBAAgB,GAAG;GACvB,OAAO,IAAI;EACb;CACF,GAAG,CAAC,OAAO,OAAO,CAAC;CACnB,OAAO;AACT;;;;;AAMA,SAAgB,mBAGd;CACA,MAAM,QAAQD,gBAAAA,cAAcC,uBAAAA,UAAU;CACtC,MAAM,aAAaG,gBAAAA,cAAc;CACjC,OAAO;EACL,WAAW,SAAS,SAAS;GAC3B,IAAI,CAAC,YAAY,OAAO,QAAQ,uBAAO,IAAI,MAAM,8BAA8B,CAAC;GAChF,OAAO,MAAM,SAAS,YAAY,SAAS,IAAI;EACjD;EACA,cAAc;GACZ,IAAI,YAAY,MAAM,OAAO,UAAU;EACzC;CACF;AACF"}
1
+ {"version":3,"file":"stamp.cjs","names":["useCapability","StampToken","useSelector","shallowArray","useDocumentId"],"sources":["../src/stamp.tsx"],"sourcesContent":["/**\n * The React view of @embedpdf/plugin-stamp.\n *\n * Thin by design: the plugin owns the store (libraries/assets) and the binary\n * sidecar (bytes + cached previews); this file only exposes hooks and owns the\n * DOM-side object-URL lifetime for gallery thumbnails. Placement UI needs no\n * component here — arming rides the annotation plugin, whose `<AnnotationLayer>`\n * already renders the hover ghost.\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-stamp';\n// The browser store for `persistStampLibraries` / `restoreStampLibraries`\n// (structurally the plugin's `StampLibraryStore`), written once in `@embedpdf/web`.\nexport { indexedDbByteStore } from '@embedpdf/web';\nexport type { ByteStore } from '@embedpdf/web';\nimport { useEffect, useState } from 'react';\nimport {\n StampToken,\n type StampAsset,\n type StampLibrary,\n type StampLibraryQuery,\n} from '@embedpdf/plugin-stamp';\nimport { shallowArray, useCapability, useDocumentId, useSelector } from './runtime';\n\n/** The stamp capability (workspace-scoped: one library set for every document). */\nexport function useStamp() {\n return useCapability(StampToken);\n}\n\n/** Libraries, optionally of one kind or several (`{ kind: 'stamps' }`, `{ kind: ['stamps', 'toolbar'] }`). */\nexport function useStampLibraries(query?: StampLibraryQuery): StampLibrary[] {\n const kinds = query?.kind === undefined ? undefined : ([] as string[]).concat(query.kind).join('\\u0000');\n return useSelector(\n StampToken,\n (c) => c.libraries(kinds === undefined ? undefined : { kind: kinds.split('\\u0000') }),\n shallowArray,\n );\n}\n\n/** Assets of one library, or every asset when `libraryId` is omitted. */\nexport function useStampAssets(libraryId?: string): StampAsset[] {\n return useSelector(StampToken, (c) => c.assets(libraryId), shallowArray);\n}\n\n/**\n * Object URL for an asset's cached preview (gallery thumbnails). The plugin\n * holds the preview BYTES; the URL — a DOM resource — is created here and\n * revoked on unmount/asset change, mirroring `<AnnotationLayer>`'s rule that\n * object-URL lifetime belongs to the framework layer.\n */\nexport function useStampAssetPreviewUrl(assetId: string | null): string | null {\n const stamp = useCapability(StampToken);\n const [url, setUrl] = useState<string | null>(null);\n useEffect(() => {\n const preview = assetId ? stamp.assetPreview(assetId) : null;\n if (!preview) {\n setUrl(null);\n return;\n }\n // Copy into an EXACT ArrayBuffer (the engine idiom) before Blob-wrapping.\n const body = new ArrayBuffer(preview.bytes.byteLength);\n new Uint8Array(body).set(preview.bytes);\n const obj = URL.createObjectURL(new Blob([body], { type: preview.mimeType }));\n setUrl(obj);\n return () => {\n URL.revokeObjectURL(obj);\n setUrl(null);\n };\n }, [stamp, assetId]);\n return url;\n}\n\n/**\n * Arm/disarm assets against the nearest `<DocumentScope>` (or the active\n * document) — the one-liner a gallery item's onClick needs.\n */\nexport function useArmStampAsset(): {\n armAsset: (assetId: string, opts?: { targetWidth?: number }) => Promise<void>;\n disarm: () => void;\n} {\n const stamp = useCapability(StampToken);\n const documentId = useDocumentId();\n return {\n armAsset: (assetId, opts) => {\n if (!documentId) return Promise.reject(new Error('[stamp] no document in scope'));\n return stamp.armAsset(documentId, assetId, opts);\n },\n disarm: () => {\n if (documentId) stamp.disarm(documentId);\n },\n };\n}\n"],"mappings":";;;;;;;;AA0BA,SAAgB,WAAW;CACzB,OAAOA,gBAAAA,cAAcC,uBAAAA,UAAU;AACjC;;AAGA,SAAgB,kBAAkB,OAA2C;CAC3E,MAAM,QAAQ,OAAO,SAAS,KAAA,IAAY,KAAA,IAAa,CAAC,CAAC,CAAc,OAAO,MAAM,IAAI,CAAC,CAAC,KAAK,IAAQ;CACvG,OAAOC,gBAAAA,YACLD,uBAAAA,aACC,MAAM,EAAE,UAAU,UAAU,KAAA,IAAY,KAAA,IAAY,EAAE,MAAM,MAAM,MAAM,IAAQ,EAAE,CAAC,GACpFE,gBAAAA,YACF;AACF;;AAGA,SAAgB,eAAe,WAAkC;CAC/D,OAAOD,gBAAAA,YAAYD,uBAAAA,aAAa,MAAM,EAAE,OAAO,SAAS,GAAGE,gBAAAA,YAAY;AACzE;;;;;;;AAQA,SAAgB,wBAAwB,SAAuC;CAC7E,MAAM,QAAQH,gBAAAA,cAAcC,uBAAAA,UAAU;CACtC,MAAM,CAAC,KAAK,WAAA,GAAA,MAAA,SAAA,CAAkC,IAAI;CAClD,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,MAAM,UAAU,UAAU,MAAM,aAAa,OAAO,IAAI;EACxD,IAAI,CAAC,SAAS;GACZ,OAAO,IAAI;GACX;EACF;EAEA,MAAM,OAAO,IAAI,YAAY,QAAQ,MAAM,UAAU;EACrD,IAAI,WAAW,IAAI,CAAC,CAAC,IAAI,QAAQ,KAAK;EACtC,MAAM,MAAM,IAAI,gBAAgB,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,MAAM,QAAQ,SAAS,CAAC,CAAC;EAC5E,OAAO,GAAG;EACV,aAAa;GACX,IAAI,gBAAgB,GAAG;GACvB,OAAO,IAAI;EACb;CACF,GAAG,CAAC,OAAO,OAAO,CAAC;CACnB,OAAO;AACT;;;;;AAMA,SAAgB,mBAGd;CACA,MAAM,QAAQD,gBAAAA,cAAcC,uBAAAA,UAAU;CACtC,MAAM,aAAaG,gBAAAA,cAAc;CACjC,OAAO;EACL,WAAW,SAAS,SAAS;GAC3B,IAAI,CAAC,YAAY,OAAO,QAAQ,uBAAO,IAAI,MAAM,8BAA8B,CAAC;GAChF,OAAO,MAAM,SAAS,YAAY,SAAS,IAAI;EACjD;EACA,cAAc;GACZ,IAAI,YAAY,MAAM,OAAO,UAAU;EACzC;CACF;AACF"}
package/dist/stamp.d.cts CHANGED
@@ -1,9 +1,11 @@
1
- import { StampAsset, StampLibrary } from "@embedpdf/plugin-stamp";
1
+ import { ByteStore, indexedDbByteStore } from "@embedpdf/web";
2
+ import { StampAsset, StampLibrary, StampLibraryQuery } from "@embedpdf/plugin-stamp";
2
3
  export * from "@embedpdf/plugin-stamp";
3
4
  //#region src/stamp.d.ts
4
5
  /** The stamp capability (workspace-scoped: one library set for every document). */
5
6
  declare function useStamp(): import("@embedpdf/plugin-stamp").StampCapability;
6
- declare function useStampLibraries(): StampLibrary[];
7
+ /** Libraries, optionally of one kind or several (`{ kind: 'stamps' }`, `{ kind: ['stamps', 'toolbar'] }`). */
8
+ declare function useStampLibraries(query?: StampLibraryQuery): StampLibrary[];
7
9
  /** Assets of one library, or every asset when `libraryId` is omitted. */
8
10
  declare function useStampAssets(libraryId?: string): StampAsset[];
9
11
  /**
@@ -24,5 +26,5 @@ declare function useArmStampAsset(): {
24
26
  disarm: () => void;
25
27
  };
26
28
  //#endregion
27
- export { useArmStampAsset, useStamp, useStampAssetPreviewUrl, useStampAssets, useStampLibraries };
29
+ export { type ByteStore, indexedDbByteStore, useArmStampAsset, useStamp, useStampAssetPreviewUrl, useStampAssets, useStampLibraries };
28
30
  //# sourceMappingURL=stamp.d.cts.map
package/dist/stamp.d.ts CHANGED
@@ -1,9 +1,11 @@
1
- import { StampAsset, StampLibrary } from "@embedpdf/plugin-stamp";
1
+ import { ByteStore, indexedDbByteStore } from "@embedpdf/web";
2
+ import { StampAsset, StampLibrary, StampLibraryQuery } from "@embedpdf/plugin-stamp";
2
3
  export * from "@embedpdf/plugin-stamp";
3
4
  //#region src/stamp.d.ts
4
5
  /** The stamp capability (workspace-scoped: one library set for every document). */
5
6
  declare function useStamp(): import("@embedpdf/plugin-stamp").StampCapability;
6
- declare function useStampLibraries(): StampLibrary[];
7
+ /** Libraries, optionally of one kind or several (`{ kind: 'stamps' }`, `{ kind: ['stamps', 'toolbar'] }`). */
8
+ declare function useStampLibraries(query?: StampLibraryQuery): StampLibrary[];
7
9
  /** Assets of one library, or every asset when `libraryId` is omitted. */
8
10
  declare function useStampAssets(libraryId?: string): StampAsset[];
9
11
  /**
@@ -24,5 +26,5 @@ declare function useArmStampAsset(): {
24
26
  disarm: () => void;
25
27
  };
26
28
  //#endregion
27
- export { useArmStampAsset, useStamp, useStampAssetPreviewUrl, useStampAssets, useStampLibraries };
29
+ export { type ByteStore, indexedDbByteStore, useArmStampAsset, useStamp, useStampAssetPreviewUrl, useStampAssets, useStampLibraries };
28
30
  //# sourceMappingURL=stamp.d.ts.map
package/dist/stamp.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import "./rolldown-runtime-BBjsoOtd.js";
2
2
  import { shallowArray, useCapability, useDocumentId, useSelector } from "./runtime.js";
3
3
  import { useEffect, useState } from "react";
4
+ import { indexedDbByteStore } from "@embedpdf/web";
4
5
  import { StampToken } from "@embedpdf/plugin-stamp";
5
6
  export * from "@embedpdf/plugin-stamp";
6
7
  //#region src/stamp.tsx
@@ -8,8 +9,10 @@ export * from "@embedpdf/plugin-stamp";
8
9
  function useStamp() {
9
10
  return useCapability(StampToken);
10
11
  }
11
- function useStampLibraries() {
12
- return useSelector(StampToken, (c) => c.libraries(), shallowArray);
12
+ /** Libraries, optionally of one kind or several (`{ kind: 'stamps' }`, `{ kind: ['stamps', 'toolbar'] }`). */
13
+ function useStampLibraries(query) {
14
+ const kinds = query?.kind === void 0 ? void 0 : [].concat(query.kind).join("\0");
15
+ return useSelector(StampToken, (c) => c.libraries(kinds === void 0 ? void 0 : { kind: kinds.split("\0") }), shallowArray);
13
16
  }
14
17
  /** Assets of one library, or every asset when `libraryId` is omitted. */
15
18
  function useStampAssets(libraryId) {
@@ -59,6 +62,6 @@ function useArmStampAsset() {
59
62
  };
60
63
  }
61
64
  //#endregion
62
- export { useArmStampAsset, useStamp, useStampAssetPreviewUrl, useStampAssets, useStampLibraries };
65
+ export { indexedDbByteStore, useArmStampAsset, useStamp, useStampAssetPreviewUrl, useStampAssets, useStampLibraries };
63
66
 
64
67
  //# sourceMappingURL=stamp.js.map
package/dist/stamp.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"stamp.js","names":[],"sources":["../src/stamp.tsx"],"sourcesContent":["/**\n * The React view of @embedpdf/plugin-stamp.\n *\n * Thin by design: the plugin owns the store (libraries/assets) and the binary\n * sidecar (bytes + cached previews); this file only exposes hooks and owns the\n * DOM-side object-URL lifetime for gallery thumbnails. Placement UI needs no\n * component here — arming rides the annotation plugin, whose `<AnnotationLayer>`\n * already renders the hover ghost.\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-stamp';\nimport { useEffect, useState } from 'react';\nimport { StampToken, type StampAsset, type StampLibrary } from '@embedpdf/plugin-stamp';\nimport { shallowArray, useCapability, useDocumentId, useSelector } from './runtime';\n\n/** The stamp capability (workspace-scoped: one library set for every document). */\nexport function useStamp() {\n return useCapability(StampToken);\n}\n\nexport function useStampLibraries(): StampLibrary[] {\n return useSelector(StampToken, (c) => c.libraries(), shallowArray);\n}\n\n/** Assets of one library, or every asset when `libraryId` is omitted. */\nexport function useStampAssets(libraryId?: string): StampAsset[] {\n return useSelector(StampToken, (c) => c.assets(libraryId), shallowArray);\n}\n\n/**\n * Object URL for an asset's cached preview (gallery thumbnails). The plugin\n * holds the preview BYTES; the URL — a DOM resource — is created here and\n * revoked on unmount/asset change, mirroring `<AnnotationLayer>`'s rule that\n * object-URL lifetime belongs to the framework layer.\n */\nexport function useStampAssetPreviewUrl(assetId: string | null): string | null {\n const stamp = useCapability(StampToken);\n const [url, setUrl] = useState<string | null>(null);\n useEffect(() => {\n const preview = assetId ? stamp.assetPreview(assetId) : null;\n if (!preview) {\n setUrl(null);\n return;\n }\n // Copy into an EXACT ArrayBuffer (the engine idiom) before Blob-wrapping.\n const body = new ArrayBuffer(preview.bytes.byteLength);\n new Uint8Array(body).set(preview.bytes);\n const obj = URL.createObjectURL(new Blob([body], { type: preview.mimeType }));\n setUrl(obj);\n return () => {\n URL.revokeObjectURL(obj);\n setUrl(null);\n };\n }, [stamp, assetId]);\n return url;\n}\n\n/**\n * Arm/disarm assets against the nearest `<DocumentScope>` (or the active\n * document) — the one-liner a gallery item's onClick needs.\n */\nexport function useArmStampAsset(): {\n armAsset: (assetId: string, opts?: { targetWidth?: number }) => Promise<void>;\n disarm: () => void;\n} {\n const stamp = useCapability(StampToken);\n const documentId = useDocumentId();\n return {\n armAsset: (assetId, opts) => {\n if (!documentId) return Promise.reject(new Error('[stamp] no document in scope'));\n return stamp.armAsset(documentId, assetId, opts);\n },\n disarm: () => {\n if (documentId) stamp.disarm(documentId);\n },\n };\n}\n"],"mappings":";;;;;;;AAiBA,SAAgB,WAAW;CACzB,OAAO,cAAc,UAAU;AACjC;AAEA,SAAgB,oBAAoC;CAClD,OAAO,YAAY,aAAa,MAAM,EAAE,UAAU,GAAG,YAAY;AACnE;;AAGA,SAAgB,eAAe,WAAkC;CAC/D,OAAO,YAAY,aAAa,MAAM,EAAE,OAAO,SAAS,GAAG,YAAY;AACzE;;;;;;;AAQA,SAAgB,wBAAwB,SAAuC;CAC7E,MAAM,QAAQ,cAAc,UAAU;CACtC,MAAM,CAAC,KAAK,UAAU,SAAwB,IAAI;CAClD,gBAAgB;EACd,MAAM,UAAU,UAAU,MAAM,aAAa,OAAO,IAAI;EACxD,IAAI,CAAC,SAAS;GACZ,OAAO,IAAI;GACX;EACF;EAEA,MAAM,OAAO,IAAI,YAAY,QAAQ,MAAM,UAAU;EACrD,IAAI,WAAW,IAAI,CAAC,CAAC,IAAI,QAAQ,KAAK;EACtC,MAAM,MAAM,IAAI,gBAAgB,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,MAAM,QAAQ,SAAS,CAAC,CAAC;EAC5E,OAAO,GAAG;EACV,aAAa;GACX,IAAI,gBAAgB,GAAG;GACvB,OAAO,IAAI;EACb;CACF,GAAG,CAAC,OAAO,OAAO,CAAC;CACnB,OAAO;AACT;;;;;AAMA,SAAgB,mBAGd;CACA,MAAM,QAAQ,cAAc,UAAU;CACtC,MAAM,aAAa,cAAc;CACjC,OAAO;EACL,WAAW,SAAS,SAAS;GAC3B,IAAI,CAAC,YAAY,OAAO,QAAQ,uBAAO,IAAI,MAAM,8BAA8B,CAAC;GAChF,OAAO,MAAM,SAAS,YAAY,SAAS,IAAI;EACjD;EACA,cAAc;GACZ,IAAI,YAAY,MAAM,OAAO,UAAU;EACzC;CACF;AACF"}
1
+ {"version":3,"file":"stamp.js","names":[],"sources":["../src/stamp.tsx"],"sourcesContent":["/**\n * The React view of @embedpdf/plugin-stamp.\n *\n * Thin by design: the plugin owns the store (libraries/assets) and the binary\n * sidecar (bytes + cached previews); this file only exposes hooks and owns the\n * DOM-side object-URL lifetime for gallery thumbnails. Placement UI needs no\n * component here — arming rides the annotation plugin, whose `<AnnotationLayer>`\n * already renders the hover ghost.\n */\n\n// One-line-per-feature: registration travels with the UI.\nexport * from '@embedpdf/plugin-stamp';\n// The browser store for `persistStampLibraries` / `restoreStampLibraries`\n// (structurally the plugin's `StampLibraryStore`), written once in `@embedpdf/web`.\nexport { indexedDbByteStore } from '@embedpdf/web';\nexport type { ByteStore } from '@embedpdf/web';\nimport { useEffect, useState } from 'react';\nimport {\n StampToken,\n type StampAsset,\n type StampLibrary,\n type StampLibraryQuery,\n} from '@embedpdf/plugin-stamp';\nimport { shallowArray, useCapability, useDocumentId, useSelector } from './runtime';\n\n/** The stamp capability (workspace-scoped: one library set for every document). */\nexport function useStamp() {\n return useCapability(StampToken);\n}\n\n/** Libraries, optionally of one kind or several (`{ kind: 'stamps' }`, `{ kind: ['stamps', 'toolbar'] }`). */\nexport function useStampLibraries(query?: StampLibraryQuery): StampLibrary[] {\n const kinds = query?.kind === undefined ? undefined : ([] as string[]).concat(query.kind).join('\\u0000');\n return useSelector(\n StampToken,\n (c) => c.libraries(kinds === undefined ? undefined : { kind: kinds.split('\\u0000') }),\n shallowArray,\n );\n}\n\n/** Assets of one library, or every asset when `libraryId` is omitted. */\nexport function useStampAssets(libraryId?: string): StampAsset[] {\n return useSelector(StampToken, (c) => c.assets(libraryId), shallowArray);\n}\n\n/**\n * Object URL for an asset's cached preview (gallery thumbnails). The plugin\n * holds the preview BYTES; the URL — a DOM resource — is created here and\n * revoked on unmount/asset change, mirroring `<AnnotationLayer>`'s rule that\n * object-URL lifetime belongs to the framework layer.\n */\nexport function useStampAssetPreviewUrl(assetId: string | null): string | null {\n const stamp = useCapability(StampToken);\n const [url, setUrl] = useState<string | null>(null);\n useEffect(() => {\n const preview = assetId ? stamp.assetPreview(assetId) : null;\n if (!preview) {\n setUrl(null);\n return;\n }\n // Copy into an EXACT ArrayBuffer (the engine idiom) before Blob-wrapping.\n const body = new ArrayBuffer(preview.bytes.byteLength);\n new Uint8Array(body).set(preview.bytes);\n const obj = URL.createObjectURL(new Blob([body], { type: preview.mimeType }));\n setUrl(obj);\n return () => {\n URL.revokeObjectURL(obj);\n setUrl(null);\n };\n }, [stamp, assetId]);\n return url;\n}\n\n/**\n * Arm/disarm assets against the nearest `<DocumentScope>` (or the active\n * document) — the one-liner a gallery item's onClick needs.\n */\nexport function useArmStampAsset(): {\n armAsset: (assetId: string, opts?: { targetWidth?: number }) => Promise<void>;\n disarm: () => void;\n} {\n const stamp = useCapability(StampToken);\n const documentId = useDocumentId();\n return {\n armAsset: (assetId, opts) => {\n if (!documentId) return Promise.reject(new Error('[stamp] no document in scope'));\n return stamp.armAsset(documentId, assetId, opts);\n },\n disarm: () => {\n if (documentId) stamp.disarm(documentId);\n },\n };\n}\n"],"mappings":";;;;;;;;AA0BA,SAAgB,WAAW;CACzB,OAAO,cAAc,UAAU;AACjC;;AAGA,SAAgB,kBAAkB,OAA2C;CAC3E,MAAM,QAAQ,OAAO,SAAS,KAAA,IAAY,KAAA,IAAa,CAAC,CAAC,CAAc,OAAO,MAAM,IAAI,CAAC,CAAC,KAAK,IAAQ;CACvG,OAAO,YACL,aACC,MAAM,EAAE,UAAU,UAAU,KAAA,IAAY,KAAA,IAAY,EAAE,MAAM,MAAM,MAAM,IAAQ,EAAE,CAAC,GACpF,YACF;AACF;;AAGA,SAAgB,eAAe,WAAkC;CAC/D,OAAO,YAAY,aAAa,MAAM,EAAE,OAAO,SAAS,GAAG,YAAY;AACzE;;;;;;;AAQA,SAAgB,wBAAwB,SAAuC;CAC7E,MAAM,QAAQ,cAAc,UAAU;CACtC,MAAM,CAAC,KAAK,UAAU,SAAwB,IAAI;CAClD,gBAAgB;EACd,MAAM,UAAU,UAAU,MAAM,aAAa,OAAO,IAAI;EACxD,IAAI,CAAC,SAAS;GACZ,OAAO,IAAI;GACX;EACF;EAEA,MAAM,OAAO,IAAI,YAAY,QAAQ,MAAM,UAAU;EACrD,IAAI,WAAW,IAAI,CAAC,CAAC,IAAI,QAAQ,KAAK;EACtC,MAAM,MAAM,IAAI,gBAAgB,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,MAAM,QAAQ,SAAS,CAAC,CAAC;EAC5E,OAAO,GAAG;EACV,aAAa;GACX,IAAI,gBAAgB,GAAG;GACvB,OAAO,IAAI;EACb;CACF,GAAG,CAAC,OAAO,OAAO,CAAC;CACnB,OAAO;AACT;;;;;AAMA,SAAgB,mBAGd;CACA,MAAM,QAAQ,cAAc,UAAU;CACtC,MAAM,aAAa,cAAc;CACjC,OAAO;EACL,WAAW,SAAS,SAAS;GAC3B,IAAI,CAAC,YAAY,OAAO,QAAQ,uBAAO,IAAI,MAAM,8BAA8B,CAAC;GAChF,OAAO,MAAM,SAAS,YAAY,SAAS,IAAI;EACjD;EACA,cAAc;GACZ,IAAI,YAAY,MAAM,OAAO,UAAU;EACzC;CACF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embedpdf/react",
3
- "version": "3.0.0-next.11",
3
+ "version": "3.0.0-next.13",
4
4
  "private": false,
5
5
  "description": "React adapter for EmbedPDF v3: one generic reactive binding + structural components (Viewer, Stage, PageView) + headless layers & hooks. The whole framework surface.",
6
6
  "type": "module",
@@ -89,6 +89,10 @@
89
89
  "import": "./dist/shell.js",
90
90
  "require": "./dist/shell.cjs"
91
91
  },
92
+ "./signature": {
93
+ "import": "./dist/signature.js",
94
+ "require": "./dist/signature.cjs"
95
+ },
92
96
  "./stage": {
93
97
  "import": "./dist/stage.js",
94
98
  "require": "./dist/stage.cjs"
@@ -111,29 +115,31 @@
111
115
  "dist"
112
116
  ],
113
117
  "dependencies": {
114
- "@embedpdf/core-annotation": "3.0.0-next.11",
115
- "@embedpdf/core": "3.0.0-next.11",
116
- "@embedpdf/plugin-annotation": "3.0.0-next.11",
117
- "@embedpdf/core-geometry": "3.0.0-next.11",
118
- "@embedpdf/plugin-commands": "3.0.0-next.11",
119
- "@embedpdf/plugin-form": "3.0.0-next.11",
120
- "@embedpdf/plugin-link": "3.0.0-next.11",
121
- "@embedpdf/plugin-interaction": "3.0.0-next.11",
122
- "@embedpdf/plugin-metadata": "3.0.0-next.11",
123
- "@embedpdf/plugin-redaction": "3.0.0-next.11",
124
- "@embedpdf/plugin-page-edit": "3.0.0-next.11",
125
- "@embedpdf/plugin-render": "3.0.0-next.11",
126
- "@embedpdf/plugin-search": "3.0.0-next.11",
127
- "@embedpdf/plugin-selection": "3.0.0-next.11",
128
- "@embedpdf/plugin-shell": "3.0.0-next.11",
129
- "@embedpdf/plugin-stage": "3.0.0-next.11",
130
- "@embedpdf/plugin-stamp": "3.0.0-next.11",
131
- "@embedpdf/plugin-view-manager": "3.0.0-next.11",
132
- "@embedpdf/plugin-i18n": "3.0.0-next.11",
133
- "@embedpdf/core-stage": "3.0.0-next.11",
134
- "@embedpdf/web": "3.0.0-next.11",
135
- "@embedpdf/plugin-actions": "3.0.0-next.11",
136
- "@embedpdf/core-ui": "3.0.0-next.11"
118
+ "@embedpdf/core-annotation": "3.0.0-next.13",
119
+ "@embedpdf/core-geometry": "3.0.0-next.13",
120
+ "@embedpdf/core": "3.0.0-next.13",
121
+ "@embedpdf/plugin-annotation": "3.0.0-next.13",
122
+ "@embedpdf/plugin-form": "3.0.0-next.13",
123
+ "@embedpdf/plugin-i18n": "3.0.0-next.13",
124
+ "@embedpdf/plugin-interaction": "3.0.0-next.13",
125
+ "@embedpdf/plugin-commands": "3.0.0-next.13",
126
+ "@embedpdf/plugin-link": "3.0.0-next.13",
127
+ "@embedpdf/plugin-page-edit": "3.0.0-next.13",
128
+ "@embedpdf/plugin-redaction": "3.0.0-next.13",
129
+ "@embedpdf/plugin-metadata": "3.0.0-next.13",
130
+ "@embedpdf/plugin-render": "3.0.0-next.13",
131
+ "@embedpdf/plugin-selection": "3.0.0-next.13",
132
+ "@embedpdf/plugin-search": "3.0.0-next.13",
133
+ "@embedpdf/plugin-shell": "3.0.0-next.13",
134
+ "@embedpdf/plugin-signature": "3.0.0-next.13",
135
+ "@embedpdf/plugin-stage": "3.0.0-next.13",
136
+ "@embedpdf/core-signature": "3.0.0-next.13",
137
+ "@embedpdf/plugin-stamp": "3.0.0-next.13",
138
+ "@embedpdf/plugin-view-manager": "3.0.0-next.13",
139
+ "@embedpdf/core-stage": "3.0.0-next.13",
140
+ "@embedpdf/core-ui": "3.0.0-next.13",
141
+ "@embedpdf/web": "3.0.0-next.13",
142
+ "@embedpdf/plugin-actions": "3.0.0-next.13"
137
143
  },
138
144
  "peerDependencies": {
139
145
  "react": ">=18",
@@ -147,7 +153,7 @@
147
153
  "happy-dom": "^20.11.0",
148
154
  "typescript": "^5.0.0",
149
155
  "vitest": "^2.1.9",
150
- "@embedpdf/engine": "3.0.0-next.11",
156
+ "@embedpdf/engine": "3.0.0-next.13",
151
157
  "@embedpdf/tooling-build": "0.0.0"
152
158
  },
153
159
  "license": "Apache-2.0",
@@ -1 +0,0 @@
1
- {"version":3,"file":"form-BwrLFpKN.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 type {\n FillItem,\n FormFieldDTO,\n} 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 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\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 }\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/**\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 ) : 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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"}