@embedpdf/plugin-stamp 3.0.0-next.10 → 3.0.0-next.12

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,69 @@
1
+ import { createCapabilityToken } from "@embedpdf/core";
2
+ //#region src/convention.ts
3
+ function parseStampKey(key) {
4
+ const separator = key.indexOf("=");
5
+ if (separator < 0) return {
6
+ name: key,
7
+ label: key
8
+ };
9
+ return {
10
+ name: key.slice(0, separator),
11
+ label: key.slice(separator + 1)
12
+ };
13
+ }
14
+ function stampKey(name, label) {
15
+ return `${name}=${label}`;
16
+ }
17
+ const BASE62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
18
+ /**
19
+ * A fresh identifier for a stamp authored here, in Acrobat's own shape
20
+ * (`#` + 22 base-62 characters) so a stamp created in this viewer keeps its
21
+ * identity when the library is opened and placed in Acrobat.
22
+ */
23
+ function customStampName(random = Math.random) {
24
+ let out = "#";
25
+ for (let i = 0; i < 22; i++) out += BASE62[Math.floor(random() * 62)];
26
+ return out;
27
+ }
28
+ /** Asset ids are derived, not allocated: library id + identifier. */
29
+ function assetIdFor(libraryId, name) {
30
+ return `${libraryId}:${name}`;
31
+ }
32
+ /** Catalog `/PieceInfo` application name for library-level data. */
33
+ const STAMP_LIBRARY_PIECEINFO_APP = "EMBD_StampLibrary";
34
+ /** Page `/PieceInfo` application name for per-stamp data. */
35
+ const STAMP_PIECEINFO_APP = "EMBD_Stamp";
36
+ /** The `Version` both dictionaries carry. */
37
+ const STAMP_PIECEINFO_VERSION = 2;
38
+ function stampKindToPdfName(kind) {
39
+ return kind === "signature" ? "Signature" : kind === "initials" ? "Initials" : "Stamp";
40
+ }
41
+ /** The catalog patch: library id, categories, locale. The name is `/Title`. */
42
+ function stampLibraryPieceInfo(id, opts = {}) {
43
+ return {
44
+ Version: 2,
45
+ Id: id,
46
+ Kind: { name: "StampLibrary" },
47
+ Name: null,
48
+ Categories: opts.categories ?? null,
49
+ Locale: opts.locale ?? null
50
+ };
51
+ }
52
+ /** The page patch: kind, an explicit `/Subj` override, categories. */
53
+ function stampPieceInfo(kind, opts = {}) {
54
+ return {
55
+ Version: 2,
56
+ Kind: { name: stampKindToPdfName(kind) },
57
+ Name: null,
58
+ Subject: null,
59
+ SubjectOverride: opts.subject ?? null,
60
+ Categories: opts.categories ?? null
61
+ };
62
+ }
63
+ //#endregion
64
+ //#region src/types.ts
65
+ const StampToken = createCapabilityToken("stamp");
66
+ //#endregion
67
+ export { assetIdFor as a, stampKey as c, stampPieceInfo as d, STAMP_PIECEINFO_VERSION as i, stampKindToPdfName as l, STAMP_LIBRARY_PIECEINFO_APP as n, customStampName as o, STAMP_PIECEINFO_APP as r, parseStampKey as s, StampToken as t, stampLibraryPieceInfo as u };
68
+
69
+ //# sourceMappingURL=contract-BFCBVNRX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-BFCBVNRX.js","names":[],"sources":["../src/convention.ts","../src/types.ts"],"sourcesContent":["/**\n * Acrobat's stamp-library convention, interpreted in ONE place. A library is\n * a PDF whose `/Names /Pages` registry names each stamp page with a key of\n * the form `identifier=label`:\n *\n * - `identifier` (before the first `=`) is the stamp's durable identity\n * and becomes the placed annotation's `/Name` — a standard name such as\n * `Approved`, or a custom one such as Acrobat's `#LBGiYhk8V_oAfmqAPENiwD`;\n * - `label` (after it) is what the picker shows and the placed\n * annotation's default `/Subj`.\n *\n * The engine never interprets key text; this module does. A key without\n * `=` is its own label. `#` is never stripped — it is part of the identity.\n */\nimport type { PieceInfoPatch } from '@embedpdf/engine-core/runtime';\nimport type { StampAssetKind } from './types';\n\nexport interface StampKey {\n name: string;\n label: string;\n}\n\nexport function parseStampKey(key: string): StampKey {\n const separator = key.indexOf('=');\n if (separator < 0) return { name: key, label: key };\n return { name: key.slice(0, separator), label: key.slice(separator + 1) };\n}\n\nexport function stampKey(name: string, label: string): string {\n return `${name}=${label}`;\n}\n\nconst BASE62 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n\n/**\n * A fresh identifier for a stamp authored here, in Acrobat's own shape\n * (`#` + 22 base-62 characters) so a stamp created in this viewer keeps its\n * identity when the library is opened and placed in Acrobat.\n */\nexport function customStampName(random: () => number = Math.random): string {\n let out = '#';\n for (let i = 0; i < 22; i++) out += BASE62[Math.floor(random() * BASE62.length)];\n return out;\n}\n\n/** Asset ids are derived, not allocated: library id + identifier. */\nexport function assetIdFor(libraryId: string, name: string): string {\n return `${libraryId}:${name}`;\n}\n\n// ── PieceInfo: only what has no standard home ────────────────────────────────\n//\n// The title, the registry, and the artwork are standard PDF. What remains —\n// a durable library id, categories, a locale, a stamp's kind and an explicit\n// `/Subj` override — rides `/PieceInfo` under these application names, in\n// the shape below. Exported so a library authored outside the plugin (a\n// conversion script, a build step) writes the same dictionary the plugin\n// reads.\n\n/** Catalog `/PieceInfo` application name for library-level data. */\nexport const STAMP_LIBRARY_PIECEINFO_APP = 'EMBD_StampLibrary';\n/** Page `/PieceInfo` application name for per-stamp data. */\nexport const STAMP_PIECEINFO_APP = 'EMBD_Stamp';\n/** The `Version` both dictionaries carry. */\nexport const STAMP_PIECEINFO_VERSION = 2;\n\nexport function stampKindToPdfName(kind: StampAssetKind): string {\n return kind === 'signature' ? 'Signature' : kind === 'initials' ? 'Initials' : 'Stamp';\n}\n\n/** The catalog patch: library id, categories, locale. The name is `/Title`. */\nexport function stampLibraryPieceInfo(\n id: string,\n opts: { categories?: readonly string[]; locale?: string } = {},\n): PieceInfoPatch {\n return {\n Version: STAMP_PIECEINFO_VERSION,\n Id: id,\n Kind: { name: 'StampLibrary' },\n // v2: the name is the PDF's /Title.\n Name: null,\n Categories: opts.categories ?? null,\n Locale: opts.locale ?? null,\n };\n}\n\n/** The page patch: kind, an explicit `/Subj` override, categories. */\nexport function stampPieceInfo(\n kind: StampAssetKind,\n opts: { subject?: string | null; categories?: readonly string[] } = {},\n): PieceInfoPatch {\n return {\n Version: STAMP_PIECEINFO_VERSION,\n Kind: { name: stampKindToPdfName(kind) },\n // v2: the identifier and label live in the /Names /Pages key; only an\n // explicit /Subj override has no standard home. v1 `Name`/`Subject` keys\n // are cleared so a re-imported v1 library cannot disagree with its registry.\n Name: null,\n Subject: null,\n SubjectOverride: opts.subject ?? null,\n Categories: opts.categories ?? null,\n };\n}\n","import type { BinarySource, Engine } from '@embedpdf/engine-core/runtime';\nimport { createCapabilityToken, type EventHook } from '@embedpdf/core';\nimport type { AnnotationRef, PageObjectNumber } from '@embedpdf/engine-core/runtime';\nimport type { StampPlacement } from '@embedpdf/plugin-annotation/contract';\n\n/**\n * The stamp plugin: a workspace-scoped ASSET substrate.\n *\n * The design law (\"documents have a home; assets ride the wire\"): imported\n * PDF libraries retain one canonical PDF whose catalog/page `/PieceInfo`\n * carries their metadata. Per-asset PDFs and previews are derived caches used\n * for placement. Standalone PNG/JPEG assets remain loose because the engine\n * intentionally has no raster-to-PDF-page authoring primitive.\n */\n\nexport type StampAssetKind = 'stamp' | 'signature' | 'initials';\n\n/**\n * One asset's SERIALIZABLE descriptor. The bytes and the cached preview are\n * deliberately NOT here — the reducer state stays pure/serializable (kernel\n * rule 1); binary lives in the capability and crosses only as call\n * arguments/returns, mirroring the engine's own BinarySource rule.\n */\nexport interface StampAsset {\n /** Derived and stable: `${libraryId}:${name}` (never allocated). */\n id: string;\n libraryId: string;\n kind: StampAssetKind;\n /**\n * The stamp's IDENTIFIER — the text before the first `=` in its library\n * key, and the placed annotation's `/Name`: a standard name (`Approved`)\n * or a custom one (`#LBGiYhk8V_oAfmqAPENiwD`). Not display text.\n */\n name: string;\n /** What the picker shows and the placed annotation's default `/Subj` —\n * the text after `=` in the library key (`Goedgekeurd`). */\n label: string;\n /** Intrinsic size in PDF points (the source page's crop box / image pixels 1:1). */\n size: { width: number; height: number };\n /** The library page that IS this asset. Every asset is a page: a raster\n * added to a library becomes a page carrying the image. */\n pageObjectNumber: number;\n /** An explicit `/Subj` override (PieceInfo); placements use `label` otherwise. */\n subject?: string;\n categories?: string[];\n}\n\n/**\n * A library IS a PDF: its `/Title` is the name, its `/Names /Pages` registry\n * the assets, its pages the artwork, PieceInfo only what has no standard\n * home. One imported PDF becomes one library; `exportLibrary` returns it.\n */\nexport interface StampLibrary {\n /** PieceInfo `Id` — stable while the title is editable. */\n id: string;\n name: string;\n /** PieceInfo `Locale` — the language of the labels, when the library says. */\n locale?: string;\n categories?: string[];\n /** Asset ids in display order. */\n assetIds: string[];\n}\n\nexport interface StampState {\n libraries: Record<string, StampLibrary>;\n /** Library display order (insertion order). */\n libraryOrder: string[];\n assets: Record<string, StampAsset>;\n}\n\nexport type StampAction =\n | { type: 'LIBRARY_ADDED'; library: StampLibrary }\n | { type: 'LIBRARY_REMOVED'; libraryId: string }\n | { type: 'ASSET_ADDED'; asset: StampAsset }\n | { type: 'ASSET_UPDATED'; asset: StampAsset }\n | { type: 'ASSET_REMOVED'; assetId: string };\n\n/** Why a library's canonical bytes changed — the persistence signal. */\nexport interface StampLibraryChange {\n libraryId: string;\n reason: 'created' | 'imported' | 'asset-added' | 'asset-updated' | 'asset-removed' | 'removed';\n}\n\nexport interface StampConfig {\n /**\n * The ASSET ENGINE port: any `Engine` that can open `{ kind: 'bytes' }` —\n * used only to slice an imported library PDF into per-page assets and\n * render their previews.\n *\n * Omitted → the kernel's own engine is used, which is exactly right for a\n * local deployment (same WASM instance, zero extra cost). In a CLOUD\n * deployment the kernel engine cannot open local bytes, so pass a factory —\n * it is called (and memoized) on the first import, never at viewer boot:\n *\n * ```ts\n * stampPlugin({\n * assetEngine: () => import('@embedpdf/engine').then((m) => m.createLocalEngine()),\n * })\n * ```\n */\n assetEngine?: Engine | (() => Engine | Promise<Engine>);\n /** Cached thumbnail width in device px (import-time render). Default 256. */\n previewWidth?: number;\n /**\n * Evaluate form-backed (dynamic) PDF stamp assets on arm. Default `true`.\n * Scripting itself is the workspace's ONE JavaScript switch,\n * `actionsPlugin({ javascript: { enabled } })`: stamp has no switch of its\n * own — it asks the target document's actions plugin for a DETACHED realm\n * (same identity, clock, sandbox, and budget; isolated globals), and arms\n * the template unevaluated when scripting is off or actions is absent.\n * `false` keeps templates static even with scripting on — a product\n * choice (a stamp's appearance must equal the reviewed template), not a\n * trust boundary: a detached realm can only alert and spend budget.\n */\n dynamic?: boolean;\n}\n\nexport interface ImportLibraryOptions {\n /**\n * FALLBACK library name, applied only when the PDF carries no `/Title`\n * (an Acrobat-authored or previously exported library names itself).\n * Default `'Stamps'`.\n */\n name?: string;\n /** Library categories written to catalog `/PieceInfo`. */\n categories?: string[];\n /** Kind stamped onto every imported asset. Default `'stamp'`. */\n kind?: StampAssetKind;\n /**\n * FALLBACK per-page labels for a plain PDF (no `/Names /Pages` registry):\n * every page becomes a stamp named `Stamp<n>` with this label. Ignored\n * when the PDF registers its stamps itself.\n */\n assetName?: (pageIndex: number) => string;\n}\n\nexport interface AddAssetInput {\n /** Target library; omitted → a new single-asset library named after the asset. */\n libraryId?: string;\n /** The identifier (placed `/Name`). Omit to mint an Acrobat-style `#…` one. */\n name?: string;\n /** Picker text and default `/Subj`. Defaults to `name`. */\n label?: string;\n kind?: StampAssetKind;\n subject?: string;\n categories?: string[];\n /**\n * Single-page PDF (vector) or PNG/JPEG bytes. A raster becomes a PAGE of\n * the library sized to `size` (default: its pixels as points, 1:1) with the\n * image flattened into it — so every asset is a page and every library a\n * complete PDF.\n */\n source: BinarySource;\n /** Thumbnail override for pickers (PNG/JPEG); rendered from the page otherwise. */\n preview?: BinarySource;\n /** Page size in PDF points for a RASTER source. Ignored for PDF sources (the page has one). */\n size?: { width: number; height: number };\n}\n\n/** A cached, browser-paintable render of an asset (PNG from import; raster assets as-is). */\nexport interface StampAssetPreview {\n bytes: Uint8Array;\n mimeType: string;\n}\n\nexport interface StampCapability {\n // ── selectors (pure reads over serializable state) ──\n libraries(): StampLibrary[];\n library(id: string): StampLibrary | null;\n /** Assets of one library, in library order — or every asset when omitted. */\n assets(libraryId?: string): StampAsset[];\n asset(id: string): StampAsset | null;\n // ── binary reads (capability-held, never store state) ──\n /** The asset's paintable preview, or null while none is cached. */\n assetPreview(id: string): StampAssetPreview | null;\n /** Placement bytes; derived from the canonical page for PDF-backed libraries. */\n assetBytes(id: string): Uint8Array | null;\n // ── library intents ──\n /**\n * A new, empty library: a PDF with the given title and no registered\n * stamps yet (like Acrobat, it carries one unregistered blank page so it\n * is a valid file from the start). Resolves to the library id; feed it to\n * `addAsset({ libraryId })` to fill it.\n */\n createLibrary(name: string, opts?: { id?: string; categories?: string[] }): Promise<string>;\n /**\n * Import a PDF as a stamp library: every page becomes one vector asset\n * (single-page PDF bytes + a cached preview render). Uses the asset\n * engine; in a cloud deployment without one configured this rejects with\n * an actionable error. Resolves to the new library id.\n */\n importLibraryPdf(source: BinarySource, opts?: ImportLibraryOptions): Promise<string>;\n /**\n * Add a single asset as a page of its library (a raster is flattened into\n * a fresh page first) and register it under `identifier=label`. Without\n * `libraryId`, a new library named after the label is created for it.\n */\n addAsset(input: AddAssetInput): Promise<string>;\n /**\n * Turn selected annotations of an open document into an asset: their\n * appearances are exported by the engine as ONE single-page PDF sized to\n * their union rect (vector, positions preserved — exactly what the page\n * shows) and added like any PDF asset. The identifier defaults to an\n * Acrobat-style `#…` one so the stamp keeps its identity in Acrobat.\n * Rejects when any ref is not on `pageObjectNumber`, is hidden, or has no\n * appearance (all-or-nothing: a stamp missing a part is worse than an error).\n */\n addAssetFromAnnotations(\n documentId: string,\n pageObjectNumber: PageObjectNumber,\n refs: AnnotationRef[],\n input: Omit<AddAssetInput, 'source' | 'size'>,\n ): Promise<string>;\n /** Remove an asset, deleting its canonical page before state changes when PDF-backed. */\n removeAsset(id: string): Promise<void>;\n /** Remove a library and every asset in it, ordered with in-flight library mutations. */\n removeLibrary(id: string): Promise<void>;\n /**\n * Relabel an asset (the registry key is renamed in one job), set or clear\n * its `/Subj` override, or replace its categories. The identifier never\n * changes — it is the asset's identity and every placed stamp's `/Name`.\n */\n updateAsset(\n id: string,\n patch: { label?: string; subject?: string | null; categories?: string[] },\n ): Promise<void>;\n /**\n * The library as a PDF — its title, its named pages, its artwork: the\n * complete, Acrobat-readable file. This IS the persistence format: store\n * these bytes wherever you like and `importLibraryPdf` them back.\n */\n exportLibrary(id: string): Uint8Array | null;\n /** Fires after every change to a library's canonical bytes — subscribe to persist. */\n onLibraryChanged: EventHook<StampLibraryChange>;\n // ── placement (delegates to the annotation plugin of the named document) ──\n /**\n * Arm an asset on a document: the next click on that document's pages\n * places it (and the hover ghost previews the exact placement). With\n * scripting on (the actions plugin's `javascript` switch), form-backed\n * PDFs are evaluated against that target document in a detached realm and\n * flattened first. Rides `annotation.armStamp` — bytes,\n * preview, and intrinsic size all travel along, so vector stamps keep\n * their true aspect.\n */\n armAsset(documentId: string, assetId: string, opts?: { targetWidth?: number }): Promise<void>;\n /**\n * Place an asset WITHOUT the pointer: the same materialization, name,\n * subject, fit, and page clamp a click after `armAsset` would produce —\n * one placement law, two entry points. Resolves to the new annotation.\n */\n placeAsset(\n documentId: string,\n assetId: string,\n placement: StampPlacement,\n ): Promise<AnnotationRef>;\n /** Disarm the stamp tool on a document. */\n disarm(documentId: string): void;\n}\n\nexport const StampToken = createCapabilityToken<StampCapability>('stamp');\n"],"mappings":";;AAsBA,SAAgB,cAAc,KAAuB;CACnD,MAAM,YAAY,IAAI,QAAQ,GAAG;CACjC,IAAI,YAAY,GAAG,OAAO;EAAE,MAAM;EAAK,OAAO;CAAI;CAClD,OAAO;EAAE,MAAM,IAAI,MAAM,GAAG,SAAS;EAAG,OAAO,IAAI,MAAM,YAAY,CAAC;CAAE;AAC1E;AAEA,SAAgB,SAAS,MAAc,OAAuB;CAC5D,OAAO,GAAG,KAAK,GAAG;AACpB;AAEA,MAAM,SAAS;;;;;;AAOf,SAAgB,gBAAgB,SAAuB,KAAK,QAAgB;CAC1E,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK,OAAO,OAAO,KAAK,MAAM,OAAO,IAAI,EAAa;CAC9E,OAAO;AACT;;AAGA,SAAgB,WAAW,WAAmB,MAAsB;CAClE,OAAO,GAAG,UAAU,GAAG;AACzB;;AAYA,MAAa,8BAA8B;;AAE3C,MAAa,sBAAsB;;AAEnC,MAAa,0BAA0B;AAEvC,SAAgB,mBAAmB,MAA8B;CAC/D,OAAO,SAAS,cAAc,cAAc,SAAS,aAAa,aAAa;AACjF;;AAGA,SAAgB,sBACd,IACA,OAA4D,CAAC,GAC7C;CAChB,OAAO;EACL,SAAA;EACA,IAAI;EACJ,MAAM,EAAE,MAAM,eAAe;EAE7B,MAAM;EACN,YAAY,KAAK,cAAc;EAC/B,QAAQ,KAAK,UAAU;CACzB;AACF;;AAGA,SAAgB,eACd,MACA,OAAoE,CAAC,GACrD;CAChB,OAAO;EACL,SAAA;EACA,MAAM,EAAE,MAAM,mBAAmB,IAAI,EAAE;EAIvC,MAAM;EACN,SAAS;EACT,iBAAiB,KAAK,WAAW;EACjC,YAAY,KAAK,cAAc;CACjC;AACF;;;AC6JA,MAAa,aAAa,sBAAuC,OAAO"}
@@ -0,0 +1,134 @@
1
+ let _embedpdf_core = require("@embedpdf/core");
2
+ //#region src/convention.ts
3
+ function parseStampKey(key) {
4
+ const separator = key.indexOf("=");
5
+ if (separator < 0) return {
6
+ name: key,
7
+ label: key
8
+ };
9
+ return {
10
+ name: key.slice(0, separator),
11
+ label: key.slice(separator + 1)
12
+ };
13
+ }
14
+ function stampKey(name, label) {
15
+ return `${name}=${label}`;
16
+ }
17
+ const BASE62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
18
+ /**
19
+ * A fresh identifier for a stamp authored here, in Acrobat's own shape
20
+ * (`#` + 22 base-62 characters) so a stamp created in this viewer keeps its
21
+ * identity when the library is opened and placed in Acrobat.
22
+ */
23
+ function customStampName(random = Math.random) {
24
+ let out = "#";
25
+ for (let i = 0; i < 22; i++) out += BASE62[Math.floor(random() * 62)];
26
+ return out;
27
+ }
28
+ /** Asset ids are derived, not allocated: library id + identifier. */
29
+ function assetIdFor(libraryId, name) {
30
+ return `${libraryId}:${name}`;
31
+ }
32
+ /** Catalog `/PieceInfo` application name for library-level data. */
33
+ const STAMP_LIBRARY_PIECEINFO_APP = "EMBD_StampLibrary";
34
+ /** Page `/PieceInfo` application name for per-stamp data. */
35
+ const STAMP_PIECEINFO_APP = "EMBD_Stamp";
36
+ /** The `Version` both dictionaries carry. */
37
+ const STAMP_PIECEINFO_VERSION = 2;
38
+ function stampKindToPdfName(kind) {
39
+ return kind === "signature" ? "Signature" : kind === "initials" ? "Initials" : "Stamp";
40
+ }
41
+ /** The catalog patch: library id, categories, locale. The name is `/Title`. */
42
+ function stampLibraryPieceInfo(id, opts = {}) {
43
+ return {
44
+ Version: 2,
45
+ Id: id,
46
+ Kind: { name: "StampLibrary" },
47
+ Name: null,
48
+ Categories: opts.categories ?? null,
49
+ Locale: opts.locale ?? null
50
+ };
51
+ }
52
+ /** The page patch: kind, an explicit `/Subj` override, categories. */
53
+ function stampPieceInfo(kind, opts = {}) {
54
+ return {
55
+ Version: 2,
56
+ Kind: { name: stampKindToPdfName(kind) },
57
+ Name: null,
58
+ Subject: null,
59
+ SubjectOverride: opts.subject ?? null,
60
+ Categories: opts.categories ?? null
61
+ };
62
+ }
63
+ //#endregion
64
+ //#region src/types.ts
65
+ const StampToken = (0, _embedpdf_core.createCapabilityToken)("stamp");
66
+ //#endregion
67
+ Object.defineProperty(exports, "STAMP_LIBRARY_PIECEINFO_APP", {
68
+ enumerable: true,
69
+ get: function() {
70
+ return STAMP_LIBRARY_PIECEINFO_APP;
71
+ }
72
+ });
73
+ Object.defineProperty(exports, "STAMP_PIECEINFO_APP", {
74
+ enumerable: true,
75
+ get: function() {
76
+ return STAMP_PIECEINFO_APP;
77
+ }
78
+ });
79
+ Object.defineProperty(exports, "STAMP_PIECEINFO_VERSION", {
80
+ enumerable: true,
81
+ get: function() {
82
+ return STAMP_PIECEINFO_VERSION;
83
+ }
84
+ });
85
+ Object.defineProperty(exports, "StampToken", {
86
+ enumerable: true,
87
+ get: function() {
88
+ return StampToken;
89
+ }
90
+ });
91
+ Object.defineProperty(exports, "assetIdFor", {
92
+ enumerable: true,
93
+ get: function() {
94
+ return assetIdFor;
95
+ }
96
+ });
97
+ Object.defineProperty(exports, "customStampName", {
98
+ enumerable: true,
99
+ get: function() {
100
+ return customStampName;
101
+ }
102
+ });
103
+ Object.defineProperty(exports, "parseStampKey", {
104
+ enumerable: true,
105
+ get: function() {
106
+ return parseStampKey;
107
+ }
108
+ });
109
+ Object.defineProperty(exports, "stampKey", {
110
+ enumerable: true,
111
+ get: function() {
112
+ return stampKey;
113
+ }
114
+ });
115
+ Object.defineProperty(exports, "stampKindToPdfName", {
116
+ enumerable: true,
117
+ get: function() {
118
+ return stampKindToPdfName;
119
+ }
120
+ });
121
+ Object.defineProperty(exports, "stampLibraryPieceInfo", {
122
+ enumerable: true,
123
+ get: function() {
124
+ return stampLibraryPieceInfo;
125
+ }
126
+ });
127
+ Object.defineProperty(exports, "stampPieceInfo", {
128
+ enumerable: true,
129
+ get: function() {
130
+ return stampPieceInfo;
131
+ }
132
+ });
133
+
134
+ //# sourceMappingURL=contract-C6CgKD69.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-C6CgKD69.cjs","names":[],"sources":["../src/convention.ts","../src/types.ts"],"sourcesContent":["/**\n * Acrobat's stamp-library convention, interpreted in ONE place. A library is\n * a PDF whose `/Names /Pages` registry names each stamp page with a key of\n * the form `identifier=label`:\n *\n * - `identifier` (before the first `=`) is the stamp's durable identity\n * and becomes the placed annotation's `/Name` — a standard name such as\n * `Approved`, or a custom one such as Acrobat's `#LBGiYhk8V_oAfmqAPENiwD`;\n * - `label` (after it) is what the picker shows and the placed\n * annotation's default `/Subj`.\n *\n * The engine never interprets key text; this module does. A key without\n * `=` is its own label. `#` is never stripped — it is part of the identity.\n */\nimport type { PieceInfoPatch } from '@embedpdf/engine-core/runtime';\nimport type { StampAssetKind } from './types';\n\nexport interface StampKey {\n name: string;\n label: string;\n}\n\nexport function parseStampKey(key: string): StampKey {\n const separator = key.indexOf('=');\n if (separator < 0) return { name: key, label: key };\n return { name: key.slice(0, separator), label: key.slice(separator + 1) };\n}\n\nexport function stampKey(name: string, label: string): string {\n return `${name}=${label}`;\n}\n\nconst BASE62 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n\n/**\n * A fresh identifier for a stamp authored here, in Acrobat's own shape\n * (`#` + 22 base-62 characters) so a stamp created in this viewer keeps its\n * identity when the library is opened and placed in Acrobat.\n */\nexport function customStampName(random: () => number = Math.random): string {\n let out = '#';\n for (let i = 0; i < 22; i++) out += BASE62[Math.floor(random() * BASE62.length)];\n return out;\n}\n\n/** Asset ids are derived, not allocated: library id + identifier. */\nexport function assetIdFor(libraryId: string, name: string): string {\n return `${libraryId}:${name}`;\n}\n\n// ── PieceInfo: only what has no standard home ────────────────────────────────\n//\n// The title, the registry, and the artwork are standard PDF. What remains —\n// a durable library id, categories, a locale, a stamp's kind and an explicit\n// `/Subj` override — rides `/PieceInfo` under these application names, in\n// the shape below. Exported so a library authored outside the plugin (a\n// conversion script, a build step) writes the same dictionary the plugin\n// reads.\n\n/** Catalog `/PieceInfo` application name for library-level data. */\nexport const STAMP_LIBRARY_PIECEINFO_APP = 'EMBD_StampLibrary';\n/** Page `/PieceInfo` application name for per-stamp data. */\nexport const STAMP_PIECEINFO_APP = 'EMBD_Stamp';\n/** The `Version` both dictionaries carry. */\nexport const STAMP_PIECEINFO_VERSION = 2;\n\nexport function stampKindToPdfName(kind: StampAssetKind): string {\n return kind === 'signature' ? 'Signature' : kind === 'initials' ? 'Initials' : 'Stamp';\n}\n\n/** The catalog patch: library id, categories, locale. The name is `/Title`. */\nexport function stampLibraryPieceInfo(\n id: string,\n opts: { categories?: readonly string[]; locale?: string } = {},\n): PieceInfoPatch {\n return {\n Version: STAMP_PIECEINFO_VERSION,\n Id: id,\n Kind: { name: 'StampLibrary' },\n // v2: the name is the PDF's /Title.\n Name: null,\n Categories: opts.categories ?? null,\n Locale: opts.locale ?? null,\n };\n}\n\n/** The page patch: kind, an explicit `/Subj` override, categories. */\nexport function stampPieceInfo(\n kind: StampAssetKind,\n opts: { subject?: string | null; categories?: readonly string[] } = {},\n): PieceInfoPatch {\n return {\n Version: STAMP_PIECEINFO_VERSION,\n Kind: { name: stampKindToPdfName(kind) },\n // v2: the identifier and label live in the /Names /Pages key; only an\n // explicit /Subj override has no standard home. v1 `Name`/`Subject` keys\n // are cleared so a re-imported v1 library cannot disagree with its registry.\n Name: null,\n Subject: null,\n SubjectOverride: opts.subject ?? null,\n Categories: opts.categories ?? null,\n };\n}\n","import type { BinarySource, Engine } from '@embedpdf/engine-core/runtime';\nimport { createCapabilityToken, type EventHook } from '@embedpdf/core';\nimport type { AnnotationRef, PageObjectNumber } from '@embedpdf/engine-core/runtime';\nimport type { StampPlacement } from '@embedpdf/plugin-annotation/contract';\n\n/**\n * The stamp plugin: a workspace-scoped ASSET substrate.\n *\n * The design law (\"documents have a home; assets ride the wire\"): imported\n * PDF libraries retain one canonical PDF whose catalog/page `/PieceInfo`\n * carries their metadata. Per-asset PDFs and previews are derived caches used\n * for placement. Standalone PNG/JPEG assets remain loose because the engine\n * intentionally has no raster-to-PDF-page authoring primitive.\n */\n\nexport type StampAssetKind = 'stamp' | 'signature' | 'initials';\n\n/**\n * One asset's SERIALIZABLE descriptor. The bytes and the cached preview are\n * deliberately NOT here — the reducer state stays pure/serializable (kernel\n * rule 1); binary lives in the capability and crosses only as call\n * arguments/returns, mirroring the engine's own BinarySource rule.\n */\nexport interface StampAsset {\n /** Derived and stable: `${libraryId}:${name}` (never allocated). */\n id: string;\n libraryId: string;\n kind: StampAssetKind;\n /**\n * The stamp's IDENTIFIER — the text before the first `=` in its library\n * key, and the placed annotation's `/Name`: a standard name (`Approved`)\n * or a custom one (`#LBGiYhk8V_oAfmqAPENiwD`). Not display text.\n */\n name: string;\n /** What the picker shows and the placed annotation's default `/Subj` —\n * the text after `=` in the library key (`Goedgekeurd`). */\n label: string;\n /** Intrinsic size in PDF points (the source page's crop box / image pixels 1:1). */\n size: { width: number; height: number };\n /** The library page that IS this asset. Every asset is a page: a raster\n * added to a library becomes a page carrying the image. */\n pageObjectNumber: number;\n /** An explicit `/Subj` override (PieceInfo); placements use `label` otherwise. */\n subject?: string;\n categories?: string[];\n}\n\n/**\n * A library IS a PDF: its `/Title` is the name, its `/Names /Pages` registry\n * the assets, its pages the artwork, PieceInfo only what has no standard\n * home. One imported PDF becomes one library; `exportLibrary` returns it.\n */\nexport interface StampLibrary {\n /** PieceInfo `Id` — stable while the title is editable. */\n id: string;\n name: string;\n /** PieceInfo `Locale` — the language of the labels, when the library says. */\n locale?: string;\n categories?: string[];\n /** Asset ids in display order. */\n assetIds: string[];\n}\n\nexport interface StampState {\n libraries: Record<string, StampLibrary>;\n /** Library display order (insertion order). */\n libraryOrder: string[];\n assets: Record<string, StampAsset>;\n}\n\nexport type StampAction =\n | { type: 'LIBRARY_ADDED'; library: StampLibrary }\n | { type: 'LIBRARY_REMOVED'; libraryId: string }\n | { type: 'ASSET_ADDED'; asset: StampAsset }\n | { type: 'ASSET_UPDATED'; asset: StampAsset }\n | { type: 'ASSET_REMOVED'; assetId: string };\n\n/** Why a library's canonical bytes changed — the persistence signal. */\nexport interface StampLibraryChange {\n libraryId: string;\n reason: 'created' | 'imported' | 'asset-added' | 'asset-updated' | 'asset-removed' | 'removed';\n}\n\nexport interface StampConfig {\n /**\n * The ASSET ENGINE port: any `Engine` that can open `{ kind: 'bytes' }` —\n * used only to slice an imported library PDF into per-page assets and\n * render their previews.\n *\n * Omitted → the kernel's own engine is used, which is exactly right for a\n * local deployment (same WASM instance, zero extra cost). In a CLOUD\n * deployment the kernel engine cannot open local bytes, so pass a factory —\n * it is called (and memoized) on the first import, never at viewer boot:\n *\n * ```ts\n * stampPlugin({\n * assetEngine: () => import('@embedpdf/engine').then((m) => m.createLocalEngine()),\n * })\n * ```\n */\n assetEngine?: Engine | (() => Engine | Promise<Engine>);\n /** Cached thumbnail width in device px (import-time render). Default 256. */\n previewWidth?: number;\n /**\n * Evaluate form-backed (dynamic) PDF stamp assets on arm. Default `true`.\n * Scripting itself is the workspace's ONE JavaScript switch,\n * `actionsPlugin({ javascript: { enabled } })`: stamp has no switch of its\n * own — it asks the target document's actions plugin for a DETACHED realm\n * (same identity, clock, sandbox, and budget; isolated globals), and arms\n * the template unevaluated when scripting is off or actions is absent.\n * `false` keeps templates static even with scripting on — a product\n * choice (a stamp's appearance must equal the reviewed template), not a\n * trust boundary: a detached realm can only alert and spend budget.\n */\n dynamic?: boolean;\n}\n\nexport interface ImportLibraryOptions {\n /**\n * FALLBACK library name, applied only when the PDF carries no `/Title`\n * (an Acrobat-authored or previously exported library names itself).\n * Default `'Stamps'`.\n */\n name?: string;\n /** Library categories written to catalog `/PieceInfo`. */\n categories?: string[];\n /** Kind stamped onto every imported asset. Default `'stamp'`. */\n kind?: StampAssetKind;\n /**\n * FALLBACK per-page labels for a plain PDF (no `/Names /Pages` registry):\n * every page becomes a stamp named `Stamp<n>` with this label. Ignored\n * when the PDF registers its stamps itself.\n */\n assetName?: (pageIndex: number) => string;\n}\n\nexport interface AddAssetInput {\n /** Target library; omitted → a new single-asset library named after the asset. */\n libraryId?: string;\n /** The identifier (placed `/Name`). Omit to mint an Acrobat-style `#…` one. */\n name?: string;\n /** Picker text and default `/Subj`. Defaults to `name`. */\n label?: string;\n kind?: StampAssetKind;\n subject?: string;\n categories?: string[];\n /**\n * Single-page PDF (vector) or PNG/JPEG bytes. A raster becomes a PAGE of\n * the library sized to `size` (default: its pixels as points, 1:1) with the\n * image flattened into it — so every asset is a page and every library a\n * complete PDF.\n */\n source: BinarySource;\n /** Thumbnail override for pickers (PNG/JPEG); rendered from the page otherwise. */\n preview?: BinarySource;\n /** Page size in PDF points for a RASTER source. Ignored for PDF sources (the page has one). */\n size?: { width: number; height: number };\n}\n\n/** A cached, browser-paintable render of an asset (PNG from import; raster assets as-is). */\nexport interface StampAssetPreview {\n bytes: Uint8Array;\n mimeType: string;\n}\n\nexport interface StampCapability {\n // ── selectors (pure reads over serializable state) ──\n libraries(): StampLibrary[];\n library(id: string): StampLibrary | null;\n /** Assets of one library, in library order — or every asset when omitted. */\n assets(libraryId?: string): StampAsset[];\n asset(id: string): StampAsset | null;\n // ── binary reads (capability-held, never store state) ──\n /** The asset's paintable preview, or null while none is cached. */\n assetPreview(id: string): StampAssetPreview | null;\n /** Placement bytes; derived from the canonical page for PDF-backed libraries. */\n assetBytes(id: string): Uint8Array | null;\n // ── library intents ──\n /**\n * A new, empty library: a PDF with the given title and no registered\n * stamps yet (like Acrobat, it carries one unregistered blank page so it\n * is a valid file from the start). Resolves to the library id; feed it to\n * `addAsset({ libraryId })` to fill it.\n */\n createLibrary(name: string, opts?: { id?: string; categories?: string[] }): Promise<string>;\n /**\n * Import a PDF as a stamp library: every page becomes one vector asset\n * (single-page PDF bytes + a cached preview render). Uses the asset\n * engine; in a cloud deployment without one configured this rejects with\n * an actionable error. Resolves to the new library id.\n */\n importLibraryPdf(source: BinarySource, opts?: ImportLibraryOptions): Promise<string>;\n /**\n * Add a single asset as a page of its library (a raster is flattened into\n * a fresh page first) and register it under `identifier=label`. Without\n * `libraryId`, a new library named after the label is created for it.\n */\n addAsset(input: AddAssetInput): Promise<string>;\n /**\n * Turn selected annotations of an open document into an asset: their\n * appearances are exported by the engine as ONE single-page PDF sized to\n * their union rect (vector, positions preserved — exactly what the page\n * shows) and added like any PDF asset. The identifier defaults to an\n * Acrobat-style `#…` one so the stamp keeps its identity in Acrobat.\n * Rejects when any ref is not on `pageObjectNumber`, is hidden, or has no\n * appearance (all-or-nothing: a stamp missing a part is worse than an error).\n */\n addAssetFromAnnotations(\n documentId: string,\n pageObjectNumber: PageObjectNumber,\n refs: AnnotationRef[],\n input: Omit<AddAssetInput, 'source' | 'size'>,\n ): Promise<string>;\n /** Remove an asset, deleting its canonical page before state changes when PDF-backed. */\n removeAsset(id: string): Promise<void>;\n /** Remove a library and every asset in it, ordered with in-flight library mutations. */\n removeLibrary(id: string): Promise<void>;\n /**\n * Relabel an asset (the registry key is renamed in one job), set or clear\n * its `/Subj` override, or replace its categories. The identifier never\n * changes — it is the asset's identity and every placed stamp's `/Name`.\n */\n updateAsset(\n id: string,\n patch: { label?: string; subject?: string | null; categories?: string[] },\n ): Promise<void>;\n /**\n * The library as a PDF — its title, its named pages, its artwork: the\n * complete, Acrobat-readable file. This IS the persistence format: store\n * these bytes wherever you like and `importLibraryPdf` them back.\n */\n exportLibrary(id: string): Uint8Array | null;\n /** Fires after every change to a library's canonical bytes — subscribe to persist. */\n onLibraryChanged: EventHook<StampLibraryChange>;\n // ── placement (delegates to the annotation plugin of the named document) ──\n /**\n * Arm an asset on a document: the next click on that document's pages\n * places it (and the hover ghost previews the exact placement). With\n * scripting on (the actions plugin's `javascript` switch), form-backed\n * PDFs are evaluated against that target document in a detached realm and\n * flattened first. Rides `annotation.armStamp` — bytes,\n * preview, and intrinsic size all travel along, so vector stamps keep\n * their true aspect.\n */\n armAsset(documentId: string, assetId: string, opts?: { targetWidth?: number }): Promise<void>;\n /**\n * Place an asset WITHOUT the pointer: the same materialization, name,\n * subject, fit, and page clamp a click after `armAsset` would produce —\n * one placement law, two entry points. Resolves to the new annotation.\n */\n placeAsset(\n documentId: string,\n assetId: string,\n placement: StampPlacement,\n ): Promise<AnnotationRef>;\n /** Disarm the stamp tool on a document. */\n disarm(documentId: string): void;\n}\n\nexport const StampToken = createCapabilityToken<StampCapability>('stamp');\n"],"mappings":";;AAsBA,SAAgB,cAAc,KAAuB;CACnD,MAAM,YAAY,IAAI,QAAQ,GAAG;CACjC,IAAI,YAAY,GAAG,OAAO;EAAE,MAAM;EAAK,OAAO;CAAI;CAClD,OAAO;EAAE,MAAM,IAAI,MAAM,GAAG,SAAS;EAAG,OAAO,IAAI,MAAM,YAAY,CAAC;CAAE;AAC1E;AAEA,SAAgB,SAAS,MAAc,OAAuB;CAC5D,OAAO,GAAG,KAAK,GAAG;AACpB;AAEA,MAAM,SAAS;;;;;;AAOf,SAAgB,gBAAgB,SAAuB,KAAK,QAAgB;CAC1E,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK,OAAO,OAAO,KAAK,MAAM,OAAO,IAAI,EAAa;CAC9E,OAAO;AACT;;AAGA,SAAgB,WAAW,WAAmB,MAAsB;CAClE,OAAO,GAAG,UAAU,GAAG;AACzB;;AAYA,MAAa,8BAA8B;;AAE3C,MAAa,sBAAsB;;AAEnC,MAAa,0BAA0B;AAEvC,SAAgB,mBAAmB,MAA8B;CAC/D,OAAO,SAAS,cAAc,cAAc,SAAS,aAAa,aAAa;AACjF;;AAGA,SAAgB,sBACd,IACA,OAA4D,CAAC,GAC7C;CAChB,OAAO;EACL,SAAA;EACA,IAAI;EACJ,MAAM,EAAE,MAAM,eAAe;EAE7B,MAAM;EACN,YAAY,KAAK,cAAc;EAC/B,QAAQ,KAAK,UAAU;CACzB;AACF;;AAGA,SAAgB,eACd,MACA,OAAoE,CAAC,GACrD;CAChB,OAAO;EACL,SAAA;EACA,MAAM,EAAE,MAAM,mBAAmB,IAAI,EAAE;EAIvC,MAAM;EACN,SAAS;EACT,iBAAiB,KAAK,WAAW;EACjC,YAAY,KAAK,cAAc;CACjC;AACF;;;AC6JA,MAAa,cAAA,GAAA,eAAA,sBAAA,CAAoD,OAAO"}
@@ -0,0 +1,322 @@
1
+ import { AnnotationRef, BinarySource, Engine, PageObjectNumber, PieceInfoPatch } from "@embedpdf/engine-core/runtime";
2
+ import { EventHook } from "@embedpdf/core";
3
+ import { StampPlacement } from "@embedpdf/plugin-annotation/contract";
4
+ //#region src/types.d.ts
5
+ /**
6
+ * The stamp plugin: a workspace-scoped ASSET substrate.
7
+ *
8
+ * The design law ("documents have a home; assets ride the wire"): imported
9
+ * PDF libraries retain one canonical PDF whose catalog/page `/PieceInfo`
10
+ * carries their metadata. Per-asset PDFs and previews are derived caches used
11
+ * for placement. Standalone PNG/JPEG assets remain loose because the engine
12
+ * intentionally has no raster-to-PDF-page authoring primitive.
13
+ */
14
+ type StampAssetKind = 'stamp' | 'signature' | 'initials';
15
+ /**
16
+ * One asset's SERIALIZABLE descriptor. The bytes and the cached preview are
17
+ * deliberately NOT here — the reducer state stays pure/serializable (kernel
18
+ * rule 1); binary lives in the capability and crosses only as call
19
+ * arguments/returns, mirroring the engine's own BinarySource rule.
20
+ */
21
+ interface StampAsset {
22
+ /** Derived and stable: `${libraryId}:${name}` (never allocated). */
23
+ id: string;
24
+ libraryId: string;
25
+ kind: StampAssetKind;
26
+ /**
27
+ * The stamp's IDENTIFIER — the text before the first `=` in its library
28
+ * key, and the placed annotation's `/Name`: a standard name (`Approved`)
29
+ * or a custom one (`#LBGiYhk8V_oAfmqAPENiwD`). Not display text.
30
+ */
31
+ name: string;
32
+ /** What the picker shows and the placed annotation's default `/Subj` —
33
+ * the text after `=` in the library key (`Goedgekeurd`). */
34
+ label: string;
35
+ /** Intrinsic size in PDF points (the source page's crop box / image pixels 1:1). */
36
+ size: {
37
+ width: number;
38
+ height: number;
39
+ };
40
+ /** The library page that IS this asset. Every asset is a page: a raster
41
+ * added to a library becomes a page carrying the image. */
42
+ pageObjectNumber: number;
43
+ /** An explicit `/Subj` override (PieceInfo); placements use `label` otherwise. */
44
+ subject?: string;
45
+ categories?: string[];
46
+ }
47
+ /**
48
+ * A library IS a PDF: its `/Title` is the name, its `/Names /Pages` registry
49
+ * the assets, its pages the artwork, PieceInfo only what has no standard
50
+ * home. One imported PDF becomes one library; `exportLibrary` returns it.
51
+ */
52
+ interface StampLibrary {
53
+ /** PieceInfo `Id` — stable while the title is editable. */
54
+ id: string;
55
+ name: string;
56
+ /** PieceInfo `Locale` — the language of the labels, when the library says. */
57
+ locale?: string;
58
+ categories?: string[];
59
+ /** Asset ids in display order. */
60
+ assetIds: string[];
61
+ }
62
+ interface StampState {
63
+ libraries: Record<string, StampLibrary>;
64
+ /** Library display order (insertion order). */
65
+ libraryOrder: string[];
66
+ assets: Record<string, StampAsset>;
67
+ }
68
+ type StampAction = {
69
+ type: 'LIBRARY_ADDED';
70
+ library: StampLibrary;
71
+ } | {
72
+ type: 'LIBRARY_REMOVED';
73
+ libraryId: string;
74
+ } | {
75
+ type: 'ASSET_ADDED';
76
+ asset: StampAsset;
77
+ } | {
78
+ type: 'ASSET_UPDATED';
79
+ asset: StampAsset;
80
+ } | {
81
+ type: 'ASSET_REMOVED';
82
+ assetId: string;
83
+ };
84
+ /** Why a library's canonical bytes changed — the persistence signal. */
85
+ interface StampLibraryChange {
86
+ libraryId: string;
87
+ reason: 'created' | 'imported' | 'asset-added' | 'asset-updated' | 'asset-removed' | 'removed';
88
+ }
89
+ interface StampConfig {
90
+ /**
91
+ * The ASSET ENGINE port: any `Engine` that can open `{ kind: 'bytes' }` —
92
+ * used only to slice an imported library PDF into per-page assets and
93
+ * render their previews.
94
+ *
95
+ * Omitted → the kernel's own engine is used, which is exactly right for a
96
+ * local deployment (same WASM instance, zero extra cost). In a CLOUD
97
+ * deployment the kernel engine cannot open local bytes, so pass a factory —
98
+ * it is called (and memoized) on the first import, never at viewer boot:
99
+ *
100
+ * ```ts
101
+ * stampPlugin({
102
+ * assetEngine: () => import('@embedpdf/engine').then((m) => m.createLocalEngine()),
103
+ * })
104
+ * ```
105
+ */
106
+ assetEngine?: Engine | (() => Engine | Promise<Engine>);
107
+ /** Cached thumbnail width in device px (import-time render). Default 256. */
108
+ previewWidth?: number;
109
+ /**
110
+ * Evaluate form-backed (dynamic) PDF stamp assets on arm. Default `true`.
111
+ * Scripting itself is the workspace's ONE JavaScript switch,
112
+ * `actionsPlugin({ javascript: { enabled } })`: stamp has no switch of its
113
+ * own — it asks the target document's actions plugin for a DETACHED realm
114
+ * (same identity, clock, sandbox, and budget; isolated globals), and arms
115
+ * the template unevaluated when scripting is off or actions is absent.
116
+ * `false` keeps templates static even with scripting on — a product
117
+ * choice (a stamp's appearance must equal the reviewed template), not a
118
+ * trust boundary: a detached realm can only alert and spend budget.
119
+ */
120
+ dynamic?: boolean;
121
+ }
122
+ interface ImportLibraryOptions {
123
+ /**
124
+ * FALLBACK library name, applied only when the PDF carries no `/Title`
125
+ * (an Acrobat-authored or previously exported library names itself).
126
+ * Default `'Stamps'`.
127
+ */
128
+ name?: string;
129
+ /** Library categories written to catalog `/PieceInfo`. */
130
+ categories?: string[];
131
+ /** Kind stamped onto every imported asset. Default `'stamp'`. */
132
+ kind?: StampAssetKind;
133
+ /**
134
+ * FALLBACK per-page labels for a plain PDF (no `/Names /Pages` registry):
135
+ * every page becomes a stamp named `Stamp<n>` with this label. Ignored
136
+ * when the PDF registers its stamps itself.
137
+ */
138
+ assetName?: (pageIndex: number) => string;
139
+ }
140
+ interface AddAssetInput {
141
+ /** Target library; omitted → a new single-asset library named after the asset. */
142
+ libraryId?: string;
143
+ /** The identifier (placed `/Name`). Omit to mint an Acrobat-style `#…` one. */
144
+ name?: string;
145
+ /** Picker text and default `/Subj`. Defaults to `name`. */
146
+ label?: string;
147
+ kind?: StampAssetKind;
148
+ subject?: string;
149
+ categories?: string[];
150
+ /**
151
+ * Single-page PDF (vector) or PNG/JPEG bytes. A raster becomes a PAGE of
152
+ * the library sized to `size` (default: its pixels as points, 1:1) with the
153
+ * image flattened into it — so every asset is a page and every library a
154
+ * complete PDF.
155
+ */
156
+ source: BinarySource;
157
+ /** Thumbnail override for pickers (PNG/JPEG); rendered from the page otherwise. */
158
+ preview?: BinarySource;
159
+ /** Page size in PDF points for a RASTER source. Ignored for PDF sources (the page has one). */
160
+ size?: {
161
+ width: number;
162
+ height: number;
163
+ };
164
+ }
165
+ /** A cached, browser-paintable render of an asset (PNG from import; raster assets as-is). */
166
+ interface StampAssetPreview {
167
+ bytes: Uint8Array;
168
+ mimeType: string;
169
+ }
170
+ interface StampCapability {
171
+ libraries(): StampLibrary[];
172
+ library(id: string): StampLibrary | null;
173
+ /** Assets of one library, in library order — or every asset when omitted. */
174
+ assets(libraryId?: string): StampAsset[];
175
+ asset(id: string): StampAsset | null;
176
+ /** The asset's paintable preview, or null while none is cached. */
177
+ assetPreview(id: string): StampAssetPreview | null;
178
+ /** Placement bytes; derived from the canonical page for PDF-backed libraries. */
179
+ assetBytes(id: string): Uint8Array | null;
180
+ /**
181
+ * A new, empty library: a PDF with the given title and no registered
182
+ * stamps yet (like Acrobat, it carries one unregistered blank page so it
183
+ * is a valid file from the start). Resolves to the library id; feed it to
184
+ * `addAsset({ libraryId })` to fill it.
185
+ */
186
+ createLibrary(name: string, opts?: {
187
+ id?: string;
188
+ categories?: string[];
189
+ }): Promise<string>;
190
+ /**
191
+ * Import a PDF as a stamp library: every page becomes one vector asset
192
+ * (single-page PDF bytes + a cached preview render). Uses the asset
193
+ * engine; in a cloud deployment without one configured this rejects with
194
+ * an actionable error. Resolves to the new library id.
195
+ */
196
+ importLibraryPdf(source: BinarySource, opts?: ImportLibraryOptions): Promise<string>;
197
+ /**
198
+ * Add a single asset as a page of its library (a raster is flattened into
199
+ * a fresh page first) and register it under `identifier=label`. Without
200
+ * `libraryId`, a new library named after the label is created for it.
201
+ */
202
+ addAsset(input: AddAssetInput): Promise<string>;
203
+ /**
204
+ * Turn selected annotations of an open document into an asset: their
205
+ * appearances are exported by the engine as ONE single-page PDF sized to
206
+ * their union rect (vector, positions preserved — exactly what the page
207
+ * shows) and added like any PDF asset. The identifier defaults to an
208
+ * Acrobat-style `#…` one so the stamp keeps its identity in Acrobat.
209
+ * Rejects when any ref is not on `pageObjectNumber`, is hidden, or has no
210
+ * appearance (all-or-nothing: a stamp missing a part is worse than an error).
211
+ */
212
+ addAssetFromAnnotations(documentId: string, pageObjectNumber: PageObjectNumber, refs: AnnotationRef[], input: Omit<AddAssetInput, 'source' | 'size'>): Promise<string>;
213
+ /** Remove an asset, deleting its canonical page before state changes when PDF-backed. */
214
+ removeAsset(id: string): Promise<void>;
215
+ /** Remove a library and every asset in it, ordered with in-flight library mutations. */
216
+ removeLibrary(id: string): Promise<void>;
217
+ /**
218
+ * Relabel an asset (the registry key is renamed in one job), set or clear
219
+ * its `/Subj` override, or replace its categories. The identifier never
220
+ * changes — it is the asset's identity and every placed stamp's `/Name`.
221
+ */
222
+ updateAsset(id: string, patch: {
223
+ label?: string;
224
+ subject?: string | null;
225
+ categories?: string[];
226
+ }): Promise<void>;
227
+ /**
228
+ * The library as a PDF — its title, its named pages, its artwork: the
229
+ * complete, Acrobat-readable file. This IS the persistence format: store
230
+ * these bytes wherever you like and `importLibraryPdf` them back.
231
+ */
232
+ exportLibrary(id: string): Uint8Array | null;
233
+ /** Fires after every change to a library's canonical bytes — subscribe to persist. */
234
+ onLibraryChanged: EventHook<StampLibraryChange>;
235
+ /**
236
+ * Arm an asset on a document: the next click on that document's pages
237
+ * places it (and the hover ghost previews the exact placement). With
238
+ * scripting on (the actions plugin's `javascript` switch), form-backed
239
+ * PDFs are evaluated against that target document in a detached realm and
240
+ * flattened first. Rides `annotation.armStamp` — bytes,
241
+ * preview, and intrinsic size all travel along, so vector stamps keep
242
+ * their true aspect.
243
+ */
244
+ armAsset(documentId: string, assetId: string, opts?: {
245
+ targetWidth?: number;
246
+ }): Promise<void>;
247
+ /**
248
+ * Place an asset WITHOUT the pointer: the same materialization, name,
249
+ * subject, fit, and page clamp a click after `armAsset` would produce —
250
+ * one placement law, two entry points. Resolves to the new annotation.
251
+ */
252
+ placeAsset(documentId: string, assetId: string, placement: StampPlacement): Promise<AnnotationRef>;
253
+ /** Disarm the stamp tool on a document. */
254
+ disarm(documentId: string): void;
255
+ }
256
+ declare const StampToken: import("@embedpdf/core").CapabilityToken<StampCapability>;
257
+ //#endregion
258
+ //#region src/convention.d.ts
259
+ interface StampKey {
260
+ name: string;
261
+ label: string;
262
+ }
263
+ declare function parseStampKey(key: string): StampKey;
264
+ declare function stampKey(name: string, label: string): string;
265
+ /**
266
+ * A fresh identifier for a stamp authored here, in Acrobat's own shape
267
+ * (`#` + 22 base-62 characters) so a stamp created in this viewer keeps its
268
+ * identity when the library is opened and placed in Acrobat.
269
+ */
270
+ declare function customStampName(random?: () => number): string;
271
+ /** Asset ids are derived, not allocated: library id + identifier. */
272
+ declare function assetIdFor(libraryId: string, name: string): string;
273
+ /** Catalog `/PieceInfo` application name for library-level data. */
274
+ declare const STAMP_LIBRARY_PIECEINFO_APP = "EMBD_StampLibrary";
275
+ /** Page `/PieceInfo` application name for per-stamp data. */
276
+ declare const STAMP_PIECEINFO_APP = "EMBD_Stamp";
277
+ /** The `Version` both dictionaries carry. */
278
+ declare const STAMP_PIECEINFO_VERSION = 2;
279
+ declare function stampKindToPdfName(kind: StampAssetKind): string;
280
+ /** The catalog patch: library id, categories, locale. The name is `/Title`. */
281
+ declare function stampLibraryPieceInfo(id: string, opts?: {
282
+ categories?: readonly string[];
283
+ locale?: string;
284
+ }): PieceInfoPatch;
285
+ /** The page patch: kind, an explicit `/Subj` override, categories. */
286
+ declare function stampPieceInfo(kind: StampAssetKind, opts?: {
287
+ subject?: string | null;
288
+ categories?: readonly string[];
289
+ }): PieceInfoPatch;
290
+ //#endregion
291
+ //#region src/persistence.d.ts
292
+ /** The persistence port: bytes by library id. */
293
+ interface StampLibraryStore {
294
+ list(): Promise<Array<{
295
+ id: string;
296
+ bytes: Uint8Array;
297
+ }>>;
298
+ put(id: string, bytes: Uint8Array): Promise<void>;
299
+ delete(id: string): Promise<void>;
300
+ }
301
+ /** An in-memory store — tests and SSR. */
302
+ declare function memoryStampStore(): StampLibraryStore;
303
+ /**
304
+ * Bring every stored library back: each PDF is imported as-is (its title,
305
+ * registry, and PieceInfo id come from the file — the store's key is only a
306
+ * hint). Call once at boot, before seeding defaults, so "already has
307
+ * libraries" means the user's own.
308
+ */
309
+ declare function restoreStampLibraries(stamp: StampCapability, store: StampLibraryStore): Promise<string[]>;
310
+ /**
311
+ * Keep the store in sync from now on: every canonical change writes the
312
+ * library's PDF (coalesced per library so a burst of edits saves once),
313
+ * a removal deletes it. `except` names libraries never to persist — the
314
+ * bundled default set, typically. Returns the unsubscribe.
315
+ */
316
+ declare function persistStampLibraries(stamp: StampCapability, store: StampLibraryStore, opts?: {
317
+ except?: readonly string[];
318
+ debounceMs?: number;
319
+ }): () => void;
320
+ //#endregion
321
+ export { StampConfig as C, StampToken as D, StampState as E, StampCapability as S, StampLibraryChange as T, ImportLibraryOptions as _, STAMP_LIBRARY_PIECEINFO_APP as a, StampAssetKind as b, StampKey as c, parseStampKey as d, stampKey as f, AddAssetInput as g, stampPieceInfo as h, restoreStampLibraries as i, assetIdFor as l, stampLibraryPieceInfo as m, memoryStampStore as n, STAMP_PIECEINFO_APP as o, stampKindToPdfName as p, persistStampLibraries as r, STAMP_PIECEINFO_VERSION as s, StampLibraryStore as t, customStampName as u, StampAction as v, StampLibrary as w, StampAssetPreview as x, StampAsset as y };
322
+ //# sourceMappingURL=contract-PLwYe8Zn.d.cts.map