@lofcz/embedpdf-plugin-actions 3.0.0-next.11

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,447 @@
1
+ import { EventHook, Unsubscribe } from "@embedpdf/core";
2
+ import { ScriptAnnotEffect, ScriptBudget, ScriptDiagnostic, ScriptExecutionError, ScriptIdentity, ScriptSandboxFactory, ScriptTransaction, ScriptUiEffect } from "@embedpdf/core-acrojs";
3
+ import { AnnotationRef, FormEffect, FormEffectsResult, FormFieldRef, FormSubmissionEntry, FormSubmissionReceipt, PageObjectNumber, PdfActionNode, PdfActionTargetRef, PdfActionTree, PdfActionType } from "@embedpdf/engine-core/runtime";
4
+ //#region src/types.d.ts
5
+ /** Why a dispatch happened. Phase 1 dispatches are all `'user'` (a real
6
+ * activation gesture); `'hover'` and `'lifecycle'` arrive with Phase 2's
7
+ * trigger sources — the policy axis ships full-shape now. */
8
+ type ActionOrigin = 'user' | 'hover' | 'lifecycle';
9
+ /** Who initiated the dispatch. Fields are REQUIRED where an executor needs
10
+ * them: the interim JavaScript executor builds `event.target` from the
11
+ * widget source's `field`. Provenance only — policy never reads it. */
12
+ type ActionSource = {
13
+ kind: 'widget';
14
+ field: FormFieldRef;
15
+ annotation: AnnotationRef;
16
+ pon: PageObjectNumber;
17
+ } | {
18
+ kind: 'link';
19
+ annotation?: AnnotationRef;
20
+ pon?: PageObjectNumber;
21
+ } |
22
+ /** A non-widget annotation's own /AA event (E/X on squares, stamps, …). */
23
+ {
24
+ kind: 'annotation';
25
+ annotation: AnnotationRef;
26
+ pon: PageObjectNumber;
27
+ } |
28
+ /** A page /AA tree (O/C) inside a page-trigger fan-out. */
29
+ {
30
+ kind: 'page';
31
+ pon: PageObjectNumber;
32
+ } |
33
+ /** The document-open sequence (openDestination / OpenAction). */
34
+ {
35
+ kind: 'document';
36
+ } | {
37
+ kind: 'api';
38
+ };
39
+ /** Trigger provenance, derived centrally beside {@link originOf} — the
40
+ * executor-visible "which event fired" (cursorEnter vs cursorExit are both
41
+ * `origin: 'hover'`; this carries the difference). */
42
+ /** The document lifecycle vocabulary: `open` (§3.9's sequence) plus the
43
+ * five catalog `/AA` verbs (ISO 32000-2 Table 200 — WC/WS/DS/WP/DP).
44
+ * Whoever owns the verb dispatches them; `runDocumentVerb` is the
45
+ * serialized door for save/print, `prepareClose` for close. */
46
+ type DocumentTriggerEvent = 'open' | 'will-save' | 'did-save' | 'will-print' | 'did-print' | 'will-close';
47
+ type ActionTriggerEvent = {
48
+ scope: 'activate';
49
+ } | {
50
+ scope: 'annotation';
51
+ name: PdfAnnotationEventKind;
52
+ } | {
53
+ scope: 'page';
54
+ name: 'open' | 'close' | 'visible' | 'invisible';
55
+ } | {
56
+ scope: 'document';
57
+ name: DocumentTriggerEvent;
58
+ };
59
+ interface ActionContext {
60
+ origin: ActionOrigin;
61
+ source: ActionSource;
62
+ event: ActionTriggerEvent;
63
+ }
64
+ /** The six annotation /AA pointer/focus events (ISO Table 197: E X D U Fo Bl).
65
+ * Page-lifecycle events (PO/PC/PV/PI) are NOT here — they fan out from page
66
+ * triggers, never from per-annotation dispatch. */
67
+ type PdfAnnotationEventKind = 'cursorEnter' | 'cursorExit' | 'mouseDown' | 'mouseUp' | 'focus' | 'blur';
68
+ /**
69
+ * Trigger vocabulary — what a feed reports; the dispatcher resolves trees,
70
+ * derives the origin ({@link originOf}), and fans out. `source` on the
71
+ * annotation-addressed arms is an optional PROVENANCE hint from first-party
72
+ * feeds (a widget feed passes its field ref so the interim JS executor can
73
+ * anchor `event.target`); policy never reads it and it cannot change origin.
74
+ */
75
+ type ActionTrigger = {
76
+ scope: 'activate';
77
+ ref: AnnotationRef;
78
+ pon: PageObjectNumber;
79
+ source?: ActionSource;
80
+ } | {
81
+ scope: 'annotation';
82
+ event: PdfAnnotationEventKind;
83
+ ref: AnnotationRef;
84
+ pon: PageObjectNumber;
85
+ source?: ActionSource;
86
+ } | {
87
+ scope: 'page';
88
+ event: 'open' | 'close' | 'visible' | 'invisible';
89
+ pon: PageObjectNumber;
90
+ } | {
91
+ scope: 'document';
92
+ event: DocumentTriggerEvent;
93
+ };
94
+ /** The one origin mapping — derived by the dispatcher, never claimed by a
95
+ * caller: a feed cannot launder a hover into a user gesture. */
96
+ declare const originOf: (trigger: ActionTrigger) => ActionOrigin;
97
+ type ActionNodeStatus = 'executed' | 'blocked' | 'no-executor' | 'inert' | 'failed' | 'skipped';
98
+ interface ActionNodeResult {
99
+ /** Node address as child indexes from the root ([] = root, [0] = root.next[0]…). */
100
+ path: number[];
101
+ type: PdfActionType;
102
+ status: ActionNodeStatus;
103
+ detail?: string;
104
+ }
105
+ interface ActionDiagnostic {
106
+ code: 'incomplete-tree' | 'blocked' | 'no-executor' | 'no-adapter' | 'no-session-sink' | 'unresolved-target' | 'duplicate-executor' | 'executor-inert' | 'executor-failed' | 'trigger-disabled' | 'no-commit-sink' | 'trigger-failed' | 'cascade-budget' | 'open-sequence-replayed' | 'no-submit-sink' | 'no-submit-resolver' | 'submit-payload-unavailable' | 'submit-entry-unsupported' | 'reentrant-print';
107
+ message: string;
108
+ }
109
+ /**
110
+ * One logical dispatch transaction's outcome. Document-lifetime work is
111
+ * NON-ROLLBACK-ATOMIC: an earlier successful reset/script write survives a
112
+ * later failure — `status: 'partial'` says so, and `nodes` carries the
113
+ * per-node truth.
114
+ */
115
+ interface ActionDispatchResult {
116
+ status: 'executed' | 'partial' | 'inert' | 'refused';
117
+ nodes: ActionNodeResult[];
118
+ diagnostics: ActionDiagnostic[];
119
+ }
120
+ interface ActionDispatchEvent {
121
+ ctx: ActionContext;
122
+ tree: PdfActionTree;
123
+ result: ActionDispatchResult;
124
+ }
125
+ /**
126
+ * One tree's execution inside a trigger: its true source, its true tree, its
127
+ * own node results — `path`s are REAL walk paths, never prefixed. `onAction`
128
+ * fires once per step with exactly this tree and a ctx built from this
129
+ * source, so the Phase-1 event contract is untouched by fan-out.
130
+ */
131
+ interface ActionStepResult {
132
+ source: ActionSource;
133
+ tree: PdfActionTree;
134
+ result: ActionDispatchResult;
135
+ }
136
+ /**
137
+ * What `dispatch(trigger)` returns: the aggregate plus per-step truth. A
138
+ * step failure NEVER skips sibling steps (a broken annotation /PC must not
139
+ * cancel the page's /C — degrade, never brick); deferred navigation/external
140
+ * effects flush per step, not per trigger.
141
+ */
142
+ interface ActionTriggerResult {
143
+ status: 'executed' | 'partial' | 'inert' | 'refused';
144
+ steps: ActionStepResult[];
145
+ /** Trigger-level diagnostics (disabled family, resolution failure);
146
+ * per-node diagnostics live inside each step's `result`. */
147
+ diagnostics: ActionDiagnostic[];
148
+ }
149
+ /**
150
+ * Stage's page-truth report (the ONE door — see the lifecycle coordinator).
151
+ * Stage stays authoritative for what page the viewer is on; the coordinator
152
+ * owns WHEN page-lifecycle triggers fire: reports are buffered behind the
153
+ * document-open barrier and diffed against the last-emitted state, so
154
+ * pre-open motion (a restored view, the openDestination reveal) never emits
155
+ * close/open churn. `cause` fuels the cascade budget: consecutive
156
+ * programmatic rounds are capped; a user-caused report resets the counter.
157
+ */
158
+ interface PageStateReport {
159
+ currentPon: PageObjectNumber | null;
160
+ visiblePons: readonly PageObjectNumber[];
161
+ /** False until layout exists; pre-placement reports are ignored. */
162
+ placed: boolean;
163
+ cause: 'user' | 'programmatic';
164
+ }
165
+ /** Per-(type × origin) decision. `allow` executes; `adapter` routes through
166
+ * the type's port (the UI adapter; for `submit-form`, the sink chain —
167
+ * embedder handler → the document's home → blocked); `report` records a
168
+ * blocked node without executing; `block` refuses.
169
+ * `launch`/`goto-remote`/`goto-embedded`/media arms are fixed `'never'`
170
+ * and not configurable. */
171
+ type ActionPolicyDecision = 'allow' | 'adapter' | 'report' | 'block';
172
+ type ActionPolicyRow = Record<ActionOrigin, ActionPolicyDecision>;
173
+ interface ActionPolicy {
174
+ goto: ActionPolicyRow;
175
+ named: ActionPolicyRow;
176
+ hide: ActionPolicyRow;
177
+ 'reset-form': ActionPolicyRow;
178
+ javascript: ActionPolicyRow;
179
+ uri: ActionPolicyRow;
180
+ /** The Named `Print` verb — owned by policy + the UI adapter, never stage.
181
+ * (An Adobe-compat extension: ISO Table 215 defines only the four page
182
+ * verbs; an unrecognized name "shall take no action".) */
183
+ print: ActionPolicyRow;
184
+ /** SubmitForm — `'adapter'` routes through the sink chain. Default: user
185
+ * origin only; hover/lifecycle submits stay blocked. */
186
+ 'submit-form': ActionPolicyRow;
187
+ }
188
+ interface ActionsPluginConfig {
189
+ /** Declarative overrides merged over the defaults (umbrella §3.5). */
190
+ policy?: Partial<ActionPolicy>;
191
+ /** Trigger-family gates, default all true. `activate` (the /A click) is
192
+ * the Phase-1 core door and is never gated. */
193
+ triggers?: {
194
+ document?: boolean;
195
+ page?: boolean;
196
+ annotation?: boolean;
197
+ };
198
+ /**
199
+ * The document-open sequence (§3.9): `'auto'` (default) fires once at the
200
+ * earliest of a UI adapter installing or the first user-origin dispatch —
201
+ * the initial page-open then comes from the stage's page-state report
202
+ * (a stage-less embedder drives page triggers itself, or declares
203
+ * headless); `'headless'` fires at bringup and falls back to the first
204
+ * page for the initial open (no stage will ever report); `'off'` never
205
+ * fires it — but still releases the page-lifecycle barrier.
206
+ */
207
+ openSequence?: 'auto' | 'headless' | 'off';
208
+ /**
209
+ * THE JavaScript switch (relocated from `formPlugin({ scripting })`).
210
+ * Default off — no VM ever loads. When enabled, the plugin owns the ONE
211
+ * per-document ScriptHost realm, registers the real `javascript` executor,
212
+ * and exposes the transaction port on the host lens (form's K/V/C/F
213
+ * pipeline rides it).
214
+ */
215
+ javascript?: {
216
+ enabled: boolean;
217
+ /** Override the lazy QuickJS factory (tests or another isolated VM). */
218
+ sandboxFactory?: ScriptSandboxFactory;
219
+ /** Embedder identity fields layered over engine/JWT identity. */
220
+ identity?: Partial<ScriptIdentity> | (() => Partial<ScriptIdentity>);
221
+ fileName?: () => string;
222
+ /** Injected deterministic transaction environment. */
223
+ now?: () => number;
224
+ utcOffsetMinutes?: () => number;
225
+ randomSeed?: () => number;
226
+ budget?: ScriptBudget;
227
+ /**
228
+ * D11's deterministic aggregate: the max JS nodes ONE dispatch may run
229
+ * (a /Next chain shares this instead of multiplying the per-run time
230
+ * budget; a wall-clock aggregate would be the flake class we banned).
231
+ * Exhausted → remaining JS nodes report inert with a budget reason.
232
+ */
233
+ maxScriptNodesPerDispatch?: number;
234
+ };
235
+ }
236
+ type ActionExecutorResult = {
237
+ status: 'executed';
238
+ } | {
239
+ status: 'inert';
240
+ reason: string;
241
+ } | {
242
+ status: 'failed';
243
+ error: string;
244
+ };
245
+ /** One node of one registered type, executed in dispatch order. Executors
246
+ * never see the tree or the capability — the anti-cascade law. */
247
+ type ActionExecutor = (node: PdfActionNode, ctx: ActionContext) => Promise<ActionExecutorResult> | ActionExecutorResult;
248
+ /** One annotation-effect commit entry. `pageObjectNumber` may be absent for
249
+ * bare Hide object-number targets — the sink resolves it from its model
250
+ * (`obj:N` is a cross-page key there); unresolvable entries fail honestly. */
251
+ interface AnnotCommitEntry {
252
+ annotObjectNumber: number;
253
+ pageObjectNumber?: number;
254
+ patch: ScriptAnnotEffect['patch'];
255
+ }
256
+ interface AnnotCommitResult {
257
+ results: Array<{
258
+ annotObjectNumber: number;
259
+ status: 'applied' | 'failed' | 'skipped';
260
+ error?: string;
261
+ }>;
262
+ }
263
+ type AnnotCommitSink = (entries: AnnotCommitEntry[]) => Promise<AnnotCommitResult>;
264
+ /** The form plugin's document commit: engine `applyEffects` + snapshot
265
+ * reconciliation (its existing commit tail, extracted). */
266
+ type FormCommitSink = (effects: FormEffect[]) => Promise<FormEffectsResult>;
267
+ /** What a script transaction surfaced besides document effects. */
268
+ interface ScriptSurfaceResult {
269
+ uiEffects: ScriptUiEffect[];
270
+ diagnostics: ScriptDiagnostic[];
271
+ error?: ScriptExecutionError;
272
+ origin: ActionOrigin;
273
+ phase: 'boot' | 'user';
274
+ }
275
+ /** Origin/phase context every script-produced UI request carries — the
276
+ * DEFAULT adapter's visibility matrix keys on it; embedder adapters receive
277
+ * everything and decide for themselves. */
278
+ interface ActionUiContext {
279
+ origin: ActionOrigin;
280
+ /** Script-model axis: `'boot'` = name-tree/document-open boot scripts. */
281
+ phase: 'boot' | 'user';
282
+ }
283
+ interface ActionUiAdapter {
284
+ openUri(uri: string, opts: {
285
+ isMap: boolean;
286
+ origin: ActionOrigin;
287
+ }): void;
288
+ /** The Named `Print` verb AND script `print()` requests (authority-gated
289
+ * upstream — `doc.print` refusals never reach the adapter). */
290
+ print(opts?: ActionUiContext): void;
291
+ /** Script `app.alert` — the ONE alert port for every script origin. */
292
+ alert?(message: string, opts: ActionUiContext & {
293
+ icon: number;
294
+ title?: string;
295
+ }): void;
296
+ /** Script `this.pageNum = n` navigation requests. */
297
+ gotoPage?(page: number, opts: ActionUiContext): void;
298
+ }
299
+ /**
300
+ * A normalized submit INTENT — one shape for both sources: a SubmitForm
301
+ * action node's extracted payload, or a script `doc.submitForm()` effect
302
+ * (include-mode names, `exclude` false). Resolution into a dataset is the
303
+ * FORM plugin's job (it owns the field plane) via the registered resolver.
304
+ */
305
+ interface SubmitIntent {
306
+ url: string | null;
307
+ /** Table-239 targets (mixed names/object numbers); `null` = the whole
308
+ * eligible form. */
309
+ fields: PdfActionTargetRef[] | null;
310
+ exclude: boolean;
311
+ includeNoValueFields: boolean;
312
+ format: 'fdf' | 'html' | 'xfdf' | 'pdf';
313
+ method: 'post' | 'get';
314
+ /** Raw ISO Table 240 word (0 for scripted submits without one). */
315
+ flagsRaw: number;
316
+ charSet?: string;
317
+ }
318
+ /**
319
+ * The resolved dataset a sink receives. Entries carry the ISO semantics
320
+ * already applied (descendants, the unconditional NoExport veto,
321
+ * push-button/unsupported exclusion — diagnosed, never silent); the
322
+ * document's declared routing survives as METADATA. The stack never
323
+ * fetches `url` — an embedder handler that chooses to must validate it
324
+ * (protocol + destination allowlists) before any network call.
325
+ */
326
+ interface ActionSubmitRequest {
327
+ url: string | null;
328
+ method: 'post' | 'get';
329
+ format: 'fdf' | 'html' | 'xfdf' | 'pdf';
330
+ flagsRaw: number;
331
+ charSet?: string;
332
+ entries: FormSubmissionEntry[];
333
+ origin: ActionOrigin;
334
+ event: ActionTriggerEvent;
335
+ }
336
+ /**
337
+ * Sink 1 of the chain: the embedder's application. Consent = installation
338
+ * (it receives nothing the embedder couldn't already compute from
339
+ * `forms.list()` under `doc.forms.read`, so no submit scope gates it).
340
+ * Contract: synchronous acceptance marks the node `executed` — "handed to
341
+ * the embedder", NOT "delivered"; a synchronous throw marks it `failed`; a
342
+ * returned promise is DETACHED and a later rejection emits a diagnostic
343
+ * only. `submitToDocumentHome` lets a handler COMPOSE with sink 2 (present
344
+ * only when the document has a submit-capable home).
345
+ */
346
+ type ActionSubmitHandler = (request: ActionSubmitRequest, ctx: {
347
+ submitToDocumentHome: (() => Promise<FormSubmissionReceipt>) | null;
348
+ }) => void | Promise<void>;
349
+ /** The form plugin's dataset resolver — registered on the host lens.
350
+ * `diagnose` is the per-entry observability channel (the honesty rule: an
351
+ * explicitly listed push-button/signature/unsupported value is DIAGNOSED
352
+ * as `submit-entry-unsupported`, never silently dropped). */
353
+ type SubmitResolver = (intent: SubmitIntent, ctx: ActionContext, diagnose: (diagnostic: ActionDiagnostic) => void) => Promise<ActionSubmitRequest>;
354
+ /** PUBLIC — embedders and chrome. Twins follow permissions.md: same name,
355
+ * same arguments, boolean, answering "would the dispatcher accept this and
356
+ * attempt execution" (per-node truth lives in the result's `nodes`). */
357
+ interface ActionsCapability {
358
+ execute(tree: PdfActionTree, ctx: ActionContext): Promise<ActionDispatchResult>;
359
+ canExecute(tree: PdfActionTree, ctx: ActionContext): boolean;
360
+ /**
361
+ * Report a trigger. Submission is SYNCHRONOUS — the queue slot is taken
362
+ * before this returns, so two dispatch calls execute in call order even
363
+ * when their resolutions race; all reads happen inside the queued
364
+ * operation. Never rejects: resolution failures come back as `refused`
365
+ * with a `trigger-failed` diagnostic, so `void dispatch(...)` is safe.
366
+ */
367
+ dispatch(trigger: ActionTrigger): Promise<ActionTriggerResult>;
368
+ canDispatch(trigger: ActionTrigger): boolean;
369
+ /** Identity-safe port install: the returned disposer clears the slot only
370
+ * while THIS adapter is still current; `null` force-clears. */
371
+ setUiAdapter(adapter: ActionUiAdapter | null): Unsubscribe;
372
+ /**
373
+ * Run one embedder-owned document verb as ONE serialized queue operation:
374
+ * open-ordering guard → before-event tree (WS/WP) → `operation()` →
375
+ * after-event tree (DS/DP). Two concurrent calls can never interleave
376
+ * their phases. Laws: a before-event failure never cancels the operation;
377
+ * `operation()` throwing skips the after-event and rethrows; the whole
378
+ * body honors `triggers.document: false` (trees skipped, operation still
379
+ * runs); print verbs hold the document-print latch, so nested
380
+ * `doc.print()` calls are suppressed with a `reentrant-print` diagnostic.
381
+ * The queue is deliberately held for the operation's duration — that IS
382
+ * the serialization (WS mutations are in the bytes a save operation
383
+ * pulls).
384
+ */
385
+ runDocumentVerb<T>(verb: 'save' | 'print', operation: () => Promise<T> | T): Promise<T>;
386
+ /**
387
+ * The cooperative WC door (D4): runs the catalog will-close tree (open
388
+ * ordering guaranteed) and resolves when its effects are committed. Call
389
+ * `documents.close()` AFTER this resolves. Scripts never run inside
390
+ * teardown — closing without this call is a named Acrobat-parity
391
+ * deviation, not an error.
392
+ */
393
+ prepareClose(): Promise<ActionTriggerResult>;
394
+ /**
395
+ * Sink 1 of the submit chain (identity-safe slot, like the UI adapter —
396
+ * but installing it does NOT arm the open-sequence latch). With no
397
+ * handler and no submit-capable document home, submits block with a
398
+ * `no-submit-sink` diagnostic.
399
+ */
400
+ setSubmitHandler(handler: ActionSubmitHandler | null): Unsubscribe;
401
+ onAction: EventHook<ActionDispatchEvent>;
402
+ onDiagnostic: EventHook<ActionDiagnostic>;
403
+ /** Script-plane observability (dispatch-driven AND K/V/C/F-driven — the
404
+ * form pipeline surfaces through the same doors). */
405
+ onScriptDiagnostic: EventHook<ScriptDiagnostic>;
406
+ onScriptError: EventHook<ScriptExecutionError>;
407
+ }
408
+ /** HOST lens — plugin-to-plugin only; import the token from
409
+ * `@embedpdf/plugin-actions/contract/host`, never from application code. */
410
+ interface ActionsHostCapability extends ActionsCapability {
411
+ /** Deterministic LAST-WINS on duplicates (a `duplicate-executor`
412
+ * diagnostic is emitted); the disposer removes the entry only while it is
413
+ * still the current one. */
414
+ registerExecutor(type: PdfActionType, executor: ActionExecutor): Unsubscribe;
415
+ registerAnnotCommitSink(sink: AnnotCommitSink): Unsubscribe;
416
+ registerFormCommitSink(sink: FormCommitSink): Unsubscribe;
417
+ /**
418
+ * The realm transaction port — present ONLY when `javascript.enabled`
419
+ * (its presence IS form's "scripting on" signal). The body must perform
420
+ * prefetch, runs, sink commits, and reconciliation before returning
421
+ * (commit-inside-the-boundary).
422
+ */
423
+ scriptTransaction?<T>(body: (txn: ScriptTransaction) => Promise<T>): Promise<T>;
424
+ /** Surface a script transaction's UI effects/diagnostics/error through the
425
+ * ONE port (adapter matrix + authority print gate + script hooks). */
426
+ surfaceScriptResult(result: ScriptSurfaceResult): void;
427
+ /** Stage's page-truth push door — see {@link PageStateReport}. */
428
+ reportPageState(report: PageStateReport): void;
429
+ /**
430
+ * The form plugin's dataset resolver (D7): both submit sources — action
431
+ * nodes and script `doc.submitForm()` effects — normalize to a
432
+ * {@link SubmitIntent} and resolve through this one door. Identity-safe;
433
+ * without it every submit blocks with `no-submit-resolver`.
434
+ */
435
+ registerSubmitResolver(resolver: SubmitResolver): Unsubscribe;
436
+ }
437
+ interface ActionsState {
438
+ /** Monotonic dispatch counter — store-visible observability. */
439
+ seq: number;
440
+ }
441
+ type ActionsAction = {
442
+ type: 'ACTIONS_DISPATCHED';
443
+ };
444
+ declare const ActionsToken: import("@embedpdf/core").CapabilityToken<ActionsCapability>;
445
+ //#endregion
446
+ export { DocumentTriggerEvent as A, ActionsHostCapability as C, AnnotCommitEntry as D, ActionsToken as E, SubmitIntent as F, SubmitResolver as I, originOf as L, PageStateReport as M, PdfAnnotationEventKind as N, AnnotCommitResult as O, ScriptSurfaceResult as P, ActionsCapability as S, ActionsState as T, ActionTrigger as _, ActionExecutor as a, ActionUiContext as b, ActionNodeStatus as c, ActionPolicyDecision as d, ActionPolicyRow as f, ActionSubmitRequest as g, ActionSubmitHandler as h, ActionDispatchResult as i, FormCommitSink as j, AnnotCommitSink as k, ActionOrigin as l, ActionStepResult as m, ActionDiagnostic as n, ActionExecutorResult as o, ActionSource as p, ActionDispatchEvent as r, ActionNodeResult as s, ActionContext as t, ActionPolicy as u, ActionTriggerResult as v, ActionsPluginConfig as w, ActionsAction as x, ActionUiAdapter as y };
447
+ //# sourceMappingURL=types-DRQReAuO.d.ts.map
@@ -0,0 +1,35 @@
1
+ import { createCapabilityToken } from "@embedpdf/core";
2
+ //#region src/types.ts
3
+ /** Trigger → provenance descriptor (the {@link ActionContext.event} axis). */
4
+ const eventOf = (trigger) => {
5
+ switch (trigger.scope) {
6
+ case "activate": return { scope: "activate" };
7
+ case "annotation": return {
8
+ scope: "annotation",
9
+ name: trigger.event
10
+ };
11
+ case "page": return {
12
+ scope: "page",
13
+ name: trigger.event
14
+ };
15
+ case "document": return {
16
+ scope: "document",
17
+ name: trigger.event
18
+ };
19
+ }
20
+ };
21
+ /** The one origin mapping — derived by the dispatcher, never claimed by a
22
+ * caller: a feed cannot launder a hover into a user gesture. */
23
+ const originOf = (trigger) => {
24
+ switch (trigger.scope) {
25
+ case "activate": return "user";
26
+ case "annotation": return trigger.event === "cursorEnter" || trigger.event === "cursorExit" ? "hover" : "user";
27
+ case "page":
28
+ case "document": return "lifecycle";
29
+ }
30
+ };
31
+ const ActionsToken = createCapabilityToken("actions", { hint: `add actionsPlugin() from '@embedpdf/plugin-actions' to your plugins list` });
32
+ //#endregion
33
+ export { eventOf as n, originOf as r, ActionsToken as t };
34
+
35
+ //# sourceMappingURL=types-DgBMy5nE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-DgBMy5nE.js","names":[],"sources":["../src/types.ts"],"sourcesContent":["import { createCapabilityToken, type EventHook, type Unsubscribe } from '@embedpdf/core';\nimport type {\n ScriptAnnotEffect,\n ScriptBudget,\n ScriptDiagnostic,\n ScriptExecutionError,\n ScriptIdentity,\n ScriptSandboxFactory,\n ScriptTransaction,\n ScriptUiEffect,\n} from '@embedpdf/core-acrojs';\nimport type {\n AnnotationRef,\n FormEffect,\n FormEffectsResult,\n FormFieldRef,\n FormSubmissionEntry,\n FormSubmissionReceipt,\n PageObjectNumber,\n PdfActionNode,\n PdfActionTargetRef,\n PdfActionTree,\n PdfActionType,\n} from '@embedpdf/engine-core/runtime';\n\n// ── the when/who axes ──────────────────────────────────────────────────────\n\n/** Why a dispatch happened. Phase 1 dispatches are all `'user'` (a real\n * activation gesture); `'hover'` and `'lifecycle'` arrive with Phase 2's\n * trigger sources — the policy axis ships full-shape now. */\nexport type ActionOrigin = 'user' | 'hover' | 'lifecycle';\n\n/** Who initiated the dispatch. Fields are REQUIRED where an executor needs\n * them: the interim JavaScript executor builds `event.target` from the\n * widget source's `field`. Provenance only — policy never reads it. */\nexport type ActionSource =\n | { kind: 'widget'; field: FormFieldRef; annotation: AnnotationRef; pon: PageObjectNumber }\n | { kind: 'link'; annotation?: AnnotationRef; pon?: PageObjectNumber }\n /** A non-widget annotation's own /AA event (E/X on squares, stamps, …). */\n | { kind: 'annotation'; annotation: AnnotationRef; pon: PageObjectNumber }\n /** A page /AA tree (O/C) inside a page-trigger fan-out. */\n | { kind: 'page'; pon: PageObjectNumber }\n /** The document-open sequence (openDestination / OpenAction). */\n | { kind: 'document' }\n | { kind: 'api' };\n\n/** Trigger provenance, derived centrally beside {@link originOf} — the\n * executor-visible \"which event fired\" (cursorEnter vs cursorExit are both\n * `origin: 'hover'`; this carries the difference). */\n/** The document lifecycle vocabulary: `open` (§3.9's sequence) plus the\n * five catalog `/AA` verbs (ISO 32000-2 Table 200 — WC/WS/DS/WP/DP).\n * Whoever owns the verb dispatches them; `runDocumentVerb` is the\n * serialized door for save/print, `prepareClose` for close. */\nexport type DocumentTriggerEvent =\n | 'open'\n | 'will-save'\n | 'did-save'\n | 'will-print'\n | 'did-print'\n | 'will-close';\n\nexport type ActionTriggerEvent =\n | { scope: 'activate' }\n | { scope: 'annotation'; name: PdfAnnotationEventKind }\n | { scope: 'page'; name: 'open' | 'close' | 'visible' | 'invisible' }\n | { scope: 'document'; name: DocumentTriggerEvent };\n\nexport interface ActionContext {\n origin: ActionOrigin;\n source: ActionSource;\n event: ActionTriggerEvent;\n}\n\n/** The six annotation /AA pointer/focus events (ISO Table 197: E X D U Fo Bl).\n * Page-lifecycle events (PO/PC/PV/PI) are NOT here — they fan out from page\n * triggers, never from per-annotation dispatch. */\nexport type PdfAnnotationEventKind =\n | 'cursorEnter'\n | 'cursorExit'\n | 'mouseDown'\n | 'mouseUp'\n | 'focus'\n | 'blur';\n\n/**\n * Trigger vocabulary — what a feed reports; the dispatcher resolves trees,\n * derives the origin ({@link originOf}), and fans out. `source` on the\n * annotation-addressed arms is an optional PROVENANCE hint from first-party\n * feeds (a widget feed passes its field ref so the interim JS executor can\n * anchor `event.target`); policy never reads it and it cannot change origin.\n */\nexport type ActionTrigger =\n | { scope: 'activate'; ref: AnnotationRef; pon: PageObjectNumber; source?: ActionSource }\n | {\n scope: 'annotation';\n event: PdfAnnotationEventKind;\n ref: AnnotationRef;\n pon: PageObjectNumber;\n source?: ActionSource;\n }\n | { scope: 'page'; event: 'open' | 'close' | 'visible' | 'invisible'; pon: PageObjectNumber }\n | { scope: 'document'; event: DocumentTriggerEvent };\n\n/** Trigger → provenance descriptor (the {@link ActionContext.event} axis). */\nexport const eventOf = (trigger: ActionTrigger): ActionTriggerEvent => {\n switch (trigger.scope) {\n case 'activate':\n return { scope: 'activate' };\n case 'annotation':\n return { scope: 'annotation', name: trigger.event };\n case 'page':\n return { scope: 'page', name: trigger.event };\n case 'document':\n return { scope: 'document', name: trigger.event };\n }\n};\n\n/** The one origin mapping — derived by the dispatcher, never claimed by a\n * caller: a feed cannot launder a hover into a user gesture. */\nexport const originOf = (trigger: ActionTrigger): ActionOrigin => {\n switch (trigger.scope) {\n case 'activate':\n return 'user';\n case 'annotation':\n return trigger.event === 'cursorEnter' || trigger.event === 'cursorExit' ? 'hover' : 'user';\n case 'page':\n case 'document':\n return 'lifecycle';\n }\n};\n\n// ── results ────────────────────────────────────────────────────────────────\n\nexport type ActionNodeStatus =\n | 'executed' // the registered executor / built-in interpreter ran\n | 'blocked' // policy said no (submit-form, origin-gated uri, …)\n | 'no-executor' // nothing registered/installed for this type\n | 'inert' // an executor was present but declined (scripting off, unknown verb)\n | 'failed' // the executor threw or reported failure\n | 'skipped'; // an earlier document-lifetime failure stopped this node\n\nexport interface ActionNodeResult {\n /** Node address as child indexes from the root ([] = root, [0] = root.next[0]…). */\n path: number[];\n type: PdfActionType;\n status: ActionNodeStatus;\n detail?: string;\n}\n\nexport interface ActionDiagnostic {\n code:\n | 'incomplete-tree'\n | 'blocked'\n | 'no-executor'\n | 'no-adapter'\n | 'no-session-sink'\n | 'unresolved-target'\n | 'duplicate-executor'\n | 'executor-inert'\n | 'executor-failed'\n | 'trigger-disabled' // config.triggers gated this family off\n | 'no-commit-sink' // a document effect had no registered owner sink\n | 'trigger-failed' // resolution threw — dispatch() never rejects\n | 'cascade-budget' // programmatic page-lifecycle rounds exceeded the cap\n | 'open-sequence-replayed' // a second document-open trigger arrived\n | 'no-submit-sink' // no handler installed and the document has no home\n | 'no-submit-resolver' // no form plugin registered a dataset resolver\n | 'submit-payload-unavailable' // older-runtime extraction: node stays inert\n | 'submit-entry-unsupported' // an explicitly included entry has no representable value\n | 'reentrant-print'; // a print request during a document print event — suppressed\n message: string;\n}\n\n/**\n * One logical dispatch transaction's outcome. Document-lifetime work is\n * NON-ROLLBACK-ATOMIC: an earlier successful reset/script write survives a\n * later failure — `status: 'partial'` says so, and `nodes` carries the\n * per-node truth.\n */\nexport interface ActionDispatchResult {\n status: 'executed' | 'partial' | 'inert' | 'refused';\n nodes: ActionNodeResult[];\n diagnostics: ActionDiagnostic[];\n}\n\nexport interface ActionDispatchEvent {\n ctx: ActionContext;\n tree: PdfActionTree;\n result: ActionDispatchResult;\n}\n\n/**\n * One tree's execution inside a trigger: its true source, its true tree, its\n * own node results — `path`s are REAL walk paths, never prefixed. `onAction`\n * fires once per step with exactly this tree and a ctx built from this\n * source, so the Phase-1 event contract is untouched by fan-out.\n */\nexport interface ActionStepResult {\n source: ActionSource;\n tree: PdfActionTree;\n result: ActionDispatchResult;\n}\n\n/**\n * What `dispatch(trigger)` returns: the aggregate plus per-step truth. A\n * step failure NEVER skips sibling steps (a broken annotation /PC must not\n * cancel the page's /C — degrade, never brick); deferred navigation/external\n * effects flush per step, not per trigger.\n */\nexport interface ActionTriggerResult {\n status: 'executed' | 'partial' | 'inert' | 'refused';\n steps: ActionStepResult[];\n /** Trigger-level diagnostics (disabled family, resolution failure);\n * per-node diagnostics live inside each step's `result`. */\n diagnostics: ActionDiagnostic[];\n}\n\n/**\n * Stage's page-truth report (the ONE door — see the lifecycle coordinator).\n * Stage stays authoritative for what page the viewer is on; the coordinator\n * owns WHEN page-lifecycle triggers fire: reports are buffered behind the\n * document-open barrier and diffed against the last-emitted state, so\n * pre-open motion (a restored view, the openDestination reveal) never emits\n * close/open churn. `cause` fuels the cascade budget: consecutive\n * programmatic rounds are capped; a user-caused report resets the counter.\n */\nexport interface PageStateReport {\n currentPon: PageObjectNumber | null;\n visiblePons: readonly PageObjectNumber[];\n /** False until layout exists; pre-placement reports are ignored. */\n placed: boolean;\n cause: 'user' | 'programmatic';\n}\n\n// ── policy ─────────────────────────────────────────────────────────────────\n\n/** Per-(type × origin) decision. `allow` executes; `adapter` routes through\n * the type's port (the UI adapter; for `submit-form`, the sink chain —\n * embedder handler → the document's home → blocked); `report` records a\n * blocked node without executing; `block` refuses.\n * `launch`/`goto-remote`/`goto-embedded`/media arms are fixed `'never'`\n * and not configurable. */\nexport type ActionPolicyDecision = 'allow' | 'adapter' | 'report' | 'block';\nexport type ActionPolicyRow = Record<ActionOrigin, ActionPolicyDecision>;\n\nexport interface ActionPolicy {\n goto: ActionPolicyRow;\n named: ActionPolicyRow;\n hide: ActionPolicyRow;\n 'reset-form': ActionPolicyRow;\n javascript: ActionPolicyRow;\n uri: ActionPolicyRow;\n /** The Named `Print` verb — owned by policy + the UI adapter, never stage.\n * (An Adobe-compat extension: ISO Table 215 defines only the four page\n * verbs; an unrecognized name \"shall take no action\".) */\n print: ActionPolicyRow;\n /** SubmitForm — `'adapter'` routes through the sink chain. Default: user\n * origin only; hover/lifecycle submits stay blocked. */\n 'submit-form': ActionPolicyRow;\n}\n\nexport interface ActionsPluginConfig {\n /** Declarative overrides merged over the defaults (umbrella §3.5). */\n policy?: Partial<ActionPolicy>;\n /** Trigger-family gates, default all true. `activate` (the /A click) is\n * the Phase-1 core door and is never gated. */\n triggers?: { document?: boolean; page?: boolean; annotation?: boolean };\n /**\n * The document-open sequence (§3.9): `'auto'` (default) fires once at the\n * earliest of a UI adapter installing or the first user-origin dispatch —\n * the initial page-open then comes from the stage's page-state report\n * (a stage-less embedder drives page triggers itself, or declares\n * headless); `'headless'` fires at bringup and falls back to the first\n * page for the initial open (no stage will ever report); `'off'` never\n * fires it — but still releases the page-lifecycle barrier.\n */\n openSequence?: 'auto' | 'headless' | 'off';\n /**\n * THE JavaScript switch (relocated from `formPlugin({ scripting })`).\n * Default off — no VM ever loads. When enabled, the plugin owns the ONE\n * per-document ScriptHost realm, registers the real `javascript` executor,\n * and exposes the transaction port on the host lens (form's K/V/C/F\n * pipeline rides it).\n */\n javascript?: {\n enabled: boolean;\n /** Override the lazy QuickJS factory (tests or another isolated VM). */\n sandboxFactory?: ScriptSandboxFactory;\n /** Embedder identity fields layered over engine/JWT identity. */\n identity?: Partial<ScriptIdentity> | (() => Partial<ScriptIdentity>);\n fileName?: () => string;\n /** Injected deterministic transaction environment. */\n now?: () => number;\n utcOffsetMinutes?: () => number;\n randomSeed?: () => number;\n budget?: ScriptBudget;\n /**\n * D11's deterministic aggregate: the max JS nodes ONE dispatch may run\n * (a /Next chain shares this instead of multiplying the per-run time\n * budget; a wall-clock aggregate would be the flake class we banned).\n * Exhausted → remaining JS nodes report inert with a budget reason.\n */\n maxScriptNodesPerDispatch?: number;\n };\n}\n\n// ── registration surfaces (host lens) ──────────────────────────────────────\n\nexport type ActionExecutorResult =\n | { status: 'executed' }\n | { status: 'inert'; reason: string }\n | { status: 'failed'; error: string };\n\n/** One node of one registered type, executed in dispatch order. Executors\n * never see the tree or the capability — the anti-cascade law. */\nexport type ActionExecutor = (\n node: PdfActionNode,\n ctx: ActionContext,\n) => Promise<ActionExecutorResult> | ActionExecutorResult;\n\n// ── owner commit sinks (D3) — full ISO: every script/Hide effect is a\n// DOCUMENT mutation committed by the plugin that owns the model, so the\n// engine write and the visible model can never diverge. Calling contract:\n// invoked from inside the actions/form serialized operations (the script\n// executor calls them while HOLDING the host transaction); a sink never\n// enqueues and never acquires the host — the proven deadlock class.\n\n/** One annotation-effect commit entry. `pageObjectNumber` may be absent for\n * bare Hide object-number targets — the sink resolves it from its model\n * (`obj:N` is a cross-page key there); unresolvable entries fail honestly. */\nexport interface AnnotCommitEntry {\n annotObjectNumber: number;\n pageObjectNumber?: number;\n patch: ScriptAnnotEffect['patch'];\n}\nexport interface AnnotCommitResult {\n results: Array<{\n annotObjectNumber: number;\n status: 'applied' | 'failed' | 'skipped';\n error?: string;\n }>;\n}\nexport type AnnotCommitSink = (entries: AnnotCommitEntry[]) => Promise<AnnotCommitResult>;\n\n/** The form plugin's document commit: engine `applyEffects` + snapshot\n * reconciliation (its existing commit tail, extracted). */\nexport type FormCommitSink = (effects: FormEffect[]) => Promise<FormEffectsResult>;\n\n/** What a script transaction surfaced besides document effects. */\nexport interface ScriptSurfaceResult {\n uiEffects: ScriptUiEffect[];\n diagnostics: ScriptDiagnostic[];\n error?: ScriptExecutionError;\n origin: ActionOrigin;\n phase: 'boot' | 'user';\n}\n\n/** Origin/phase context every script-produced UI request carries — the\n * DEFAULT adapter's visibility matrix keys on it; embedder adapters receive\n * everything and decide for themselves. */\nexport interface ActionUiContext {\n origin: ActionOrigin;\n /** Script-model axis: `'boot'` = name-tree/document-open boot scripts. */\n phase: 'boot' | 'user';\n}\n\nexport interface ActionUiAdapter {\n openUri(uri: string, opts: { isMap: boolean; origin: ActionOrigin }): void;\n /** The Named `Print` verb AND script `print()` requests (authority-gated\n * upstream — `doc.print` refusals never reach the adapter). */\n print(opts?: ActionUiContext): void;\n /** Script `app.alert` — the ONE alert port for every script origin. */\n alert?(message: string, opts: ActionUiContext & { icon: number; title?: string }): void;\n /** Script `this.pageNum = n` navigation requests. */\n gotoPage?(page: number, opts: ActionUiContext): void;\n}\n\n// ── the submit pipeline (D7: one intent, one resolver, one sink chain) ─────\n\n/**\n * A normalized submit INTENT — one shape for both sources: a SubmitForm\n * action node's extracted payload, or a script `doc.submitForm()` effect\n * (include-mode names, `exclude` false). Resolution into a dataset is the\n * FORM plugin's job (it owns the field plane) via the registered resolver.\n */\nexport interface SubmitIntent {\n url: string | null;\n /** Table-239 targets (mixed names/object numbers); `null` = the whole\n * eligible form. */\n fields: PdfActionTargetRef[] | null;\n exclude: boolean;\n includeNoValueFields: boolean;\n format: 'fdf' | 'html' | 'xfdf' | 'pdf';\n method: 'post' | 'get';\n /** Raw ISO Table 240 word (0 for scripted submits without one). */\n flagsRaw: number;\n charSet?: string;\n}\n\n/**\n * The resolved dataset a sink receives. Entries carry the ISO semantics\n * already applied (descendants, the unconditional NoExport veto,\n * push-button/unsupported exclusion — diagnosed, never silent); the\n * document's declared routing survives as METADATA. The stack never\n * fetches `url` — an embedder handler that chooses to must validate it\n * (protocol + destination allowlists) before any network call.\n */\nexport interface ActionSubmitRequest {\n url: string | null;\n method: 'post' | 'get';\n format: 'fdf' | 'html' | 'xfdf' | 'pdf';\n flagsRaw: number;\n charSet?: string;\n entries: FormSubmissionEntry[];\n origin: ActionOrigin;\n event: ActionTriggerEvent;\n}\n\n/**\n * Sink 1 of the chain: the embedder's application. Consent = installation\n * (it receives nothing the embedder couldn't already compute from\n * `forms.list()` under `doc.forms.read`, so no submit scope gates it).\n * Contract: synchronous acceptance marks the node `executed` — \"handed to\n * the embedder\", NOT \"delivered\"; a synchronous throw marks it `failed`; a\n * returned promise is DETACHED and a later rejection emits a diagnostic\n * only. `submitToDocumentHome` lets a handler COMPOSE with sink 2 (present\n * only when the document has a submit-capable home).\n */\nexport type ActionSubmitHandler = (\n request: ActionSubmitRequest,\n ctx: { submitToDocumentHome: (() => Promise<FormSubmissionReceipt>) | null },\n) => void | Promise<void>;\n\n/** The form plugin's dataset resolver — registered on the host lens.\n * `diagnose` is the per-entry observability channel (the honesty rule: an\n * explicitly listed push-button/signature/unsupported value is DIAGNOSED\n * as `submit-entry-unsupported`, never silently dropped). */\nexport type SubmitResolver = (\n intent: SubmitIntent,\n ctx: ActionContext,\n diagnose: (diagnostic: ActionDiagnostic) => void,\n) => Promise<ActionSubmitRequest>;\n\n// ── capabilities ───────────────────────────────────────────────────────────\n\n/** PUBLIC — embedders and chrome. Twins follow permissions.md: same name,\n * same arguments, boolean, answering \"would the dispatcher accept this and\n * attempt execution\" (per-node truth lives in the result's `nodes`). */\nexport interface ActionsCapability {\n execute(tree: PdfActionTree, ctx: ActionContext): Promise<ActionDispatchResult>;\n canExecute(tree: PdfActionTree, ctx: ActionContext): boolean;\n /**\n * Report a trigger. Submission is SYNCHRONOUS — the queue slot is taken\n * before this returns, so two dispatch calls execute in call order even\n * when their resolutions race; all reads happen inside the queued\n * operation. Never rejects: resolution failures come back as `refused`\n * with a `trigger-failed` diagnostic, so `void dispatch(...)` is safe.\n */\n dispatch(trigger: ActionTrigger): Promise<ActionTriggerResult>;\n canDispatch(trigger: ActionTrigger): boolean;\n /** Identity-safe port install: the returned disposer clears the slot only\n * while THIS adapter is still current; `null` force-clears. */\n setUiAdapter(adapter: ActionUiAdapter | null): Unsubscribe;\n /**\n * Run one embedder-owned document verb as ONE serialized queue operation:\n * open-ordering guard → before-event tree (WS/WP) → `operation()` →\n * after-event tree (DS/DP). Two concurrent calls can never interleave\n * their phases. Laws: a before-event failure never cancels the operation;\n * `operation()` throwing skips the after-event and rethrows; the whole\n * body honors `triggers.document: false` (trees skipped, operation still\n * runs); print verbs hold the document-print latch, so nested\n * `doc.print()` calls are suppressed with a `reentrant-print` diagnostic.\n * The queue is deliberately held for the operation's duration — that IS\n * the serialization (WS mutations are in the bytes a save operation\n * pulls).\n */\n runDocumentVerb<T>(verb: 'save' | 'print', operation: () => Promise<T> | T): Promise<T>;\n /**\n * The cooperative WC door (D4): runs the catalog will-close tree (open\n * ordering guaranteed) and resolves when its effects are committed. Call\n * `documents.close()` AFTER this resolves. Scripts never run inside\n * teardown — closing without this call is a named Acrobat-parity\n * deviation, not an error.\n */\n prepareClose(): Promise<ActionTriggerResult>;\n /**\n * Sink 1 of the submit chain (identity-safe slot, like the UI adapter —\n * but installing it does NOT arm the open-sequence latch). With no\n * handler and no submit-capable document home, submits block with a\n * `no-submit-sink` diagnostic.\n */\n setSubmitHandler(handler: ActionSubmitHandler | null): Unsubscribe;\n onAction: EventHook<ActionDispatchEvent>;\n onDiagnostic: EventHook<ActionDiagnostic>;\n /** Script-plane observability (dispatch-driven AND K/V/C/F-driven — the\n * form pipeline surfaces through the same doors). */\n onScriptDiagnostic: EventHook<ScriptDiagnostic>;\n onScriptError: EventHook<ScriptExecutionError>;\n}\n\n/** HOST lens — plugin-to-plugin only; import the token from\n * `@embedpdf/plugin-actions/contract/host`, never from application code. */\nexport interface ActionsHostCapability extends ActionsCapability {\n /** Deterministic LAST-WINS on duplicates (a `duplicate-executor`\n * diagnostic is emitted); the disposer removes the entry only while it is\n * still the current one. */\n registerExecutor(type: PdfActionType, executor: ActionExecutor): Unsubscribe;\n registerAnnotCommitSink(sink: AnnotCommitSink): Unsubscribe;\n registerFormCommitSink(sink: FormCommitSink): Unsubscribe;\n /**\n * The realm transaction port — present ONLY when `javascript.enabled`\n * (its presence IS form's \"scripting on\" signal). The body must perform\n * prefetch, runs, sink commits, and reconciliation before returning\n * (commit-inside-the-boundary).\n */\n scriptTransaction?<T>(body: (txn: ScriptTransaction) => Promise<T>): Promise<T>;\n /** Surface a script transaction's UI effects/diagnostics/error through the\n * ONE port (adapter matrix + authority print gate + script hooks). */\n surfaceScriptResult(result: ScriptSurfaceResult): void;\n /** Stage's page-truth push door — see {@link PageStateReport}. */\n reportPageState(report: PageStateReport): void;\n /**\n * The form plugin's dataset resolver (D7): both submit sources — action\n * nodes and script `doc.submitForm()` effects — normalize to a\n * {@link SubmitIntent} and resolve through this one door. Identity-safe;\n * without it every submit blocks with `no-submit-resolver`.\n */\n registerSubmitResolver(resolver: SubmitResolver): Unsubscribe;\n}\n\nexport interface ActionsState {\n /** Monotonic dispatch counter — store-visible observability. */\n seq: number;\n}\n\nexport type ActionsAction = { type: 'ACTIONS_DISPATCHED' };\n\nexport const ActionsToken = createCapabilityToken<ActionsCapability>('actions', {\n hint: `add actionsPlugin() from '@embedpdf/plugin-actions' to your plugins list`,\n});\n"],"mappings":";;;AAwGA,MAAa,WAAW,YAA+C;CACrE,QAAQ,QAAQ,OAAhB;EACE,KAAK,YACH,OAAO,EAAE,OAAO,WAAW;EAC7B,KAAK,cACH,OAAO;GAAE,OAAO;GAAc,MAAM,QAAQ;EAAM;EACpD,KAAK,QACH,OAAO;GAAE,OAAO;GAAQ,MAAM,QAAQ;EAAM;EAC9C,KAAK,YACH,OAAO;GAAE,OAAO;GAAY,MAAM,QAAQ;EAAM;CACpD;AACF;;;AAIA,MAAa,YAAY,YAAyC;CAChE,QAAQ,QAAQ,OAAhB;EACE,KAAK,YACH,OAAO;EACT,KAAK,cACH,OAAO,QAAQ,UAAU,iBAAiB,QAAQ,UAAU,eAAe,UAAU;EACvF,KAAK;EACL,KAAK,YACH,OAAO;CACX;AACF;AAwZA,MAAa,eAAe,sBAAyC,WAAW,EAC9E,MAAM,2EACR,CAAC"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@lofcz/embedpdf-plugin-actions",
3
+ "version": "3.0.0-next.11",
4
+ "private": false,
5
+ "description": "The PDF action engine: one dispatcher for extracted /A and /AA action trees (GoTo, URI, Hide, Named, ResetForm, JavaScript chains) with a per-document serialized queue, origin-aware policy, can-twins, and a registry where sibling plugins provide executors and effect sinks. JavaScript is one registered interpreter among many — Hide/ResetForm/navigation work with scripting off.",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./contract": {
16
+ "import": "./dist/contract.js",
17
+ "require": "./dist/contract.cjs"
18
+ },
19
+ "./contract/host": {
20
+ "import": "./dist/contract/host.js",
21
+ "require": "./dist/contract/host.cjs"
22
+ },
23
+ "./internal": {
24
+ "import": "./dist/internal.js",
25
+ "require": "./dist/internal.cjs"
26
+ },
27
+ "./package.json": "./package.json"
28
+ },
29
+ "files": [
30
+ "dist"
31
+ ],
32
+ "dependencies": {
33
+ "@embedpdf/core": "npm:@lofcz/embedpdf-core@3.0.0-next.11",
34
+ "@embedpdf/engine-core": "npm:@lofcz/embedpdf-engine-core@3.0.0-next.11",
35
+ "@embedpdf/core-acrojs": "npm:@lofcz/embedpdf-core-acrojs@3.0.0-next.11",
36
+ "@embedpdf/core-js-sandbox": "npm:@lofcz/embedpdf-core-js-sandbox@3.0.0-next.11"
37
+ },
38
+ "devDependencies": {
39
+ "typescript": "^5.0.0",
40
+ "vitest": "^2.1.9",
41
+ "@embedpdf/tooling-build": "npm:@lofcz/embedpdf-tooling-build@0.0.0",
42
+ "@embedpdf/engine": "npm:@lofcz/embedpdf-engine@3.0.0-next.11"
43
+ },
44
+ "license": "Apache-2.0",
45
+ "sideEffects": false,
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/lofcz/embed-pdf-viewer.git",
49
+ "directory": "packages/plugin/actions"
50
+ },
51
+ "scripts": {
52
+ "build": "epdf-build",
53
+ "clean": "rimraf dist",
54
+ "typecheck": "tsc -p tsconfig.json --noEmit",
55
+ "test": "vitest run"
56
+ }
57
+ }