@embedpdf/plugin-actions 3.0.0-next.13 → 3.0.0-next.15
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.
- package/dist/contract/host.cjs +13 -1
- package/dist/contract/host.cjs.map +1 -1
- package/dist/contract/host.d.cts +3 -7
- package/dist/contract/host.d.ts +3 -7
- package/dist/contract/host.js +10 -3
- package/dist/contract/host.js.map +1 -1
- package/dist/contract-CNKZHb6w.d.ts +547 -0
- package/dist/contract-CwN3NAXU.js +175 -0
- package/dist/contract-CwN3NAXU.js.map +1 -0
- package/dist/contract-DSQysTqU.d.cts +547 -0
- package/dist/contract-_HB_UliT.cjs +210 -0
- package/dist/contract-_HB_UliT.cjs.map +1 -0
- package/dist/contract.cjs +5 -4
- package/dist/contract.d.cts +2 -3
- package/dist/contract.d.ts +2 -3
- package/dist/contract.js +2 -3
- package/dist/host-contract-CRNO2oZN.d.ts +165 -0
- package/dist/host-contract-DJ8TqDr3.d.cts +165 -0
- package/dist/index.cjs +1524 -1076
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -9
- package/dist/index.d.ts +11 -9
- package/dist/index.js +1522 -1076
- package/dist/index.js.map +1 -1
- package/package.json +6 -10
- package/dist/contract-C1K3H4RP.cjs +0 -89
- package/dist/contract-C1K3H4RP.cjs.map +0 -1
- package/dist/contract-COk-w3Fo.d.ts +0 -50
- package/dist/contract-DAem-EST.js +0 -78
- package/dist/contract-DAem-EST.js.map +0 -1
- package/dist/contract-Os5y4NaD.d.cts +0 -50
- package/dist/internal.cjs +0 -3
- package/dist/internal.d.cts +0 -3
- package/dist/internal.d.ts +0 -3
- package/dist/internal.js +0 -2
- package/dist/types-BXJLAKXi.cjs +0 -52
- package/dist/types-BXJLAKXi.cjs.map +0 -1
- package/dist/types-D-DoiESj.d.cts +0 -504
- package/dist/types-D-DoiESj.d.ts +0 -504
- package/dist/types-DgBMy5nE.js +0 -35
- package/dist/types-DgBMy5nE.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embedpdf/plugin-actions",
|
|
3
|
-
"version": "3.0.0-next.
|
|
3
|
+
"version": "3.0.0-next.15",
|
|
4
4
|
"private": false,
|
|
5
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
6
|
"type": "module",
|
|
@@ -20,26 +20,22 @@
|
|
|
20
20
|
"import": "./dist/contract/host.js",
|
|
21
21
|
"require": "./dist/contract/host.cjs"
|
|
22
22
|
},
|
|
23
|
-
"./internal": {
|
|
24
|
-
"import": "./dist/internal.js",
|
|
25
|
-
"require": "./dist/internal.cjs"
|
|
26
|
-
},
|
|
27
23
|
"./package.json": "./package.json"
|
|
28
24
|
},
|
|
29
25
|
"files": [
|
|
30
26
|
"dist"
|
|
31
27
|
],
|
|
32
28
|
"dependencies": {
|
|
33
|
-
"@embedpdf/core": "3.0.0-next.
|
|
34
|
-
"@embedpdf/core-acrojs": "3.0.0-next.
|
|
35
|
-
"@embedpdf/core
|
|
36
|
-
"@embedpdf/
|
|
29
|
+
"@embedpdf/engine-core": "3.0.0-next.15",
|
|
30
|
+
"@embedpdf/core-acrojs": "3.0.0-next.15",
|
|
31
|
+
"@embedpdf/core": "3.0.0-next.15",
|
|
32
|
+
"@embedpdf/core-js-sandbox": "3.0.0-next.15"
|
|
37
33
|
},
|
|
38
34
|
"devDependencies": {
|
|
39
35
|
"typescript": "^5.0.0",
|
|
40
36
|
"vitest": "^2.1.9",
|
|
41
37
|
"@embedpdf/tooling-build": "0.0.0",
|
|
42
|
-
"@embedpdf/engine": "3.0.0-next.
|
|
38
|
+
"@embedpdf/engine": "3.0.0-next.15"
|
|
43
39
|
},
|
|
44
40
|
"license": "Apache-2.0",
|
|
45
41
|
"sideEffects": false,
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
//#region src/hover-pump.ts
|
|
2
|
-
const sameTarget = (a, b) => {
|
|
3
|
-
if (a === null || b === null) return a === b;
|
|
4
|
-
if (a.ref.kind !== b.ref.kind || a.pon !== b.pon) return false;
|
|
5
|
-
if (a.ref.kind === "objectNumber" && b.ref.kind === "objectNumber") return a.ref.annotObjectNumber === b.ref.annotObjectNumber;
|
|
6
|
-
if (a.ref.kind === "nm" && b.ref.kind === "nm") return a.ref.nm === b.ref.nm;
|
|
7
|
-
if (a.ref.kind === "index" && b.ref.kind === "index") return a.ref.index === b.ref.index && a.ref.revision === b.ref.revision;
|
|
8
|
-
return false;
|
|
9
|
-
};
|
|
10
|
-
/**
|
|
11
|
-
* The ONE hover state machine every event plane shares (D8): per pointer
|
|
12
|
-
* feed, `{ delivered, desired, inFlight }`. On each settle it delivers the
|
|
13
|
-
* transition `delivered → desired` as `Exit(delivered)` then
|
|
14
|
-
* `Enter(desired)`, SUBMITTED BACK-TO-BACK SYNCHRONOUSLY — dispatch takes
|
|
15
|
-
* its queue slot before returning, so the ordered pair can never be split by
|
|
16
|
-
* a slow resolution (the per-annotation-tail reordering the review caught).
|
|
17
|
-
* Under pressure intermediate targets are skipped by design: the pointer
|
|
18
|
-
* sweeping A→B→C while A's exit is in flight delivers `Exit(A) → Enter(C)`,
|
|
19
|
-
* never a stale `Enter(B)`.
|
|
20
|
-
*/
|
|
21
|
-
function createHoverPump(dispatch) {
|
|
22
|
-
let delivered = null;
|
|
23
|
-
let desired = null;
|
|
24
|
-
let inFlight = false;
|
|
25
|
-
const pump = () => {
|
|
26
|
-
if (inFlight || sameTarget(delivered, desired)) return;
|
|
27
|
-
inFlight = true;
|
|
28
|
-
const from = delivered;
|
|
29
|
-
const to = desired;
|
|
30
|
-
delivered = to;
|
|
31
|
-
const submissions = [];
|
|
32
|
-
if (from && from.events?.exit !== false) submissions.push(dispatch({
|
|
33
|
-
scope: "annotation",
|
|
34
|
-
event: "cursorExit",
|
|
35
|
-
ref: from.ref,
|
|
36
|
-
pon: from.pon,
|
|
37
|
-
...from.source ? { source: from.source } : {}
|
|
38
|
-
}));
|
|
39
|
-
if (to && to.events?.enter !== false) submissions.push(dispatch({
|
|
40
|
-
scope: "annotation",
|
|
41
|
-
event: "cursorEnter",
|
|
42
|
-
ref: to.ref,
|
|
43
|
-
pon: to.pon,
|
|
44
|
-
...to.source ? { source: to.source } : {}
|
|
45
|
-
}));
|
|
46
|
-
Promise.allSettled(submissions).then(() => {
|
|
47
|
-
inFlight = false;
|
|
48
|
-
pump();
|
|
49
|
-
});
|
|
50
|
-
};
|
|
51
|
-
return {
|
|
52
|
-
hover(target) {
|
|
53
|
-
desired = target;
|
|
54
|
-
pump();
|
|
55
|
-
},
|
|
56
|
-
reset() {
|
|
57
|
-
delivered = null;
|
|
58
|
-
desired = null;
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
//#endregion
|
|
63
|
-
//#region src/submit-encoding.ts
|
|
64
|
-
/**
|
|
65
|
-
* Encode a resolved submission dataset as `application/x-www-form-urlencoded`
|
|
66
|
-
* (UTF-8 — the one encoding this helper speaks; a `/CharSet` other than
|
|
67
|
-
* utf-8 is the handler's problem). A name-only entry (`value === null`, the
|
|
68
|
-
* IncludeNoValueFields shape) encodes as a bare name; a multi-select list
|
|
69
|
-
* box repeats the name per value, the HTML-form convention.
|
|
70
|
-
*
|
|
71
|
-
* Pure and dependency-free on purpose: a convenience for embedder handlers,
|
|
72
|
-
* never called by the plugin itself (the plugin never touches a network).
|
|
73
|
-
*/
|
|
74
|
-
const submitEntriesToUrlEncoded = (entries) => entries.flatMap(({ name, value }) => value === null ? [encodeURIComponent(name)] : Array.isArray(value) ? value.map((item) => `${encodeURIComponent(name)}=${encodeURIComponent(item)}`) : [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`]).join("&");
|
|
75
|
-
//#endregion
|
|
76
|
-
Object.defineProperty(exports, "createHoverPump", {
|
|
77
|
-
enumerable: true,
|
|
78
|
-
get: function() {
|
|
79
|
-
return createHoverPump;
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
Object.defineProperty(exports, "submitEntriesToUrlEncoded", {
|
|
83
|
-
enumerable: true,
|
|
84
|
-
get: function() {
|
|
85
|
-
return submitEntriesToUrlEncoded;
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
//# sourceMappingURL=contract-C1K3H4RP.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"contract-C1K3H4RP.cjs","names":[],"sources":["../src/hover-pump.ts","../src/submit-encoding.ts"],"sourcesContent":["import type { AnnotationRef, PageObjectNumber } from '@embedpdf/engine-core/runtime';\n\nimport type { ActionSource, ActionTrigger, ActionTriggerResult } from './types';\n\n/** One hoverable target, as a feed sees it. `events` lets a feed that KNOWS\n * tree presence (folded model, fill item) skip the inert half of a pair —\n * omitted flags default to true. */\nexport interface HoverTarget {\n ref: AnnotationRef;\n pon: PageObjectNumber;\n /** Optional provenance hint forwarded on the trigger (widget/link feeds). */\n source?: ActionSource;\n events?: { enter?: boolean; exit?: boolean };\n}\n\nexport interface HoverPump {\n /** Report where the pointer is now (null = nowhere interesting). */\n hover(target: HoverTarget | null): void;\n /** Forget everything without dispatching (teardown; document switch). */\n reset(): void;\n}\n\nconst sameTarget = (a: HoverTarget | null, b: HoverTarget | null): boolean => {\n if (a === null || b === null) return a === b;\n if (a.ref.kind !== b.ref.kind || a.pon !== b.pon) return false;\n if (a.ref.kind === 'objectNumber' && b.ref.kind === 'objectNumber') {\n return a.ref.annotObjectNumber === b.ref.annotObjectNumber;\n }\n if (a.ref.kind === 'nm' && b.ref.kind === 'nm') return a.ref.nm === b.ref.nm;\n if (a.ref.kind === 'index' && b.ref.kind === 'index') {\n return a.ref.index === b.ref.index && a.ref.revision === b.ref.revision;\n }\n return false;\n};\n\n/**\n * The ONE hover state machine every event plane shares (D8): per pointer\n * feed, `{ delivered, desired, inFlight }`. On each settle it delivers the\n * transition `delivered → desired` as `Exit(delivered)` then\n * `Enter(desired)`, SUBMITTED BACK-TO-BACK SYNCHRONOUSLY — dispatch takes\n * its queue slot before returning, so the ordered pair can never be split by\n * a slow resolution (the per-annotation-tail reordering the review caught).\n * Under pressure intermediate targets are skipped by design: the pointer\n * sweeping A→B→C while A's exit is in flight delivers `Exit(A) → Enter(C)`,\n * never a stale `Enter(B)`.\n */\nexport function createHoverPump(\n dispatch: (trigger: ActionTrigger) => Promise<ActionTriggerResult>,\n): HoverPump {\n let delivered: HoverTarget | null = null;\n let desired: HoverTarget | null = null;\n let inFlight = false;\n\n const pump = (): void => {\n if (inFlight || sameTarget(delivered, desired)) return;\n inFlight = true;\n const from = delivered;\n const to = desired;\n delivered = to;\n const submissions: Array<Promise<unknown>> = [];\n if (from && from.events?.exit !== false) {\n submissions.push(\n dispatch({\n scope: 'annotation',\n event: 'cursorExit',\n ref: from.ref,\n pon: from.pon,\n ...(from.source ? { source: from.source } : {}),\n }),\n );\n }\n if (to && to.events?.enter !== false) {\n submissions.push(\n dispatch({\n scope: 'annotation',\n event: 'cursorEnter',\n ref: to.ref,\n pon: to.pon,\n ...(to.source ? { source: to.source } : {}),\n }),\n );\n }\n void Promise.allSettled(submissions).then(() => {\n inFlight = false;\n pump(); // the pointer may have moved on — deliver the latest transition\n });\n };\n\n return {\n hover(target) {\n desired = target;\n pump();\n },\n reset() {\n delivered = null;\n desired = null;\n },\n };\n}\n","import type { FormSubmissionEntry } from '@embedpdf/engine-core/runtime';\n\n/**\n * Encode a resolved submission dataset as `application/x-www-form-urlencoded`\n * (UTF-8 — the one encoding this helper speaks; a `/CharSet` other than\n * utf-8 is the handler's problem). A name-only entry (`value === null`, the\n * IncludeNoValueFields shape) encodes as a bare name; a multi-select list\n * box repeats the name per value, the HTML-form convention.\n *\n * Pure and dependency-free on purpose: a convenience for embedder handlers,\n * never called by the plugin itself (the plugin never touches a network).\n */\nexport const submitEntriesToUrlEncoded = (entries: FormSubmissionEntry[]): string =>\n entries\n .flatMap(({ name, value }) =>\n value === null\n ? [encodeURIComponent(name)]\n : Array.isArray(value)\n ? value.map((item) => `${encodeURIComponent(name)}=${encodeURIComponent(item)}`)\n : [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`],\n )\n .join('&');\n"],"mappings":";AAsBA,MAAM,cAAc,GAAuB,MAAmC;CAC5E,IAAI,MAAM,QAAQ,MAAM,MAAM,OAAO,MAAM;CAC3C,IAAI,EAAE,IAAI,SAAS,EAAE,IAAI,QAAQ,EAAE,QAAQ,EAAE,KAAK,OAAO;CACzD,IAAI,EAAE,IAAI,SAAS,kBAAkB,EAAE,IAAI,SAAS,gBAClD,OAAO,EAAE,IAAI,sBAAsB,EAAE,IAAI;CAE3C,IAAI,EAAE,IAAI,SAAS,QAAQ,EAAE,IAAI,SAAS,MAAM,OAAO,EAAE,IAAI,OAAO,EAAE,IAAI;CAC1E,IAAI,EAAE,IAAI,SAAS,WAAW,EAAE,IAAI,SAAS,SAC3C,OAAO,EAAE,IAAI,UAAU,EAAE,IAAI,SAAS,EAAE,IAAI,aAAa,EAAE,IAAI;CAEjE,OAAO;AACT;;;;;;;;;;;;AAaA,SAAgB,gBACd,UACW;CACX,IAAI,YAAgC;CACpC,IAAI,UAA8B;CAClC,IAAI,WAAW;CAEf,MAAM,aAAmB;EACvB,IAAI,YAAY,WAAW,WAAW,OAAO,GAAG;EAChD,WAAW;EACX,MAAM,OAAO;EACb,MAAM,KAAK;EACX,YAAY;EACZ,MAAM,cAAuC,CAAC;EAC9C,IAAI,QAAQ,KAAK,QAAQ,SAAS,OAChC,YAAY,KACV,SAAS;GACP,OAAO;GACP,OAAO;GACP,KAAK,KAAK;GACV,KAAK,KAAK;GACV,GAAI,KAAK,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;EAC/C,CAAC,CACH;EAEF,IAAI,MAAM,GAAG,QAAQ,UAAU,OAC7B,YAAY,KACV,SAAS;GACP,OAAO;GACP,OAAO;GACP,KAAK,GAAG;GACR,KAAK,GAAG;GACR,GAAI,GAAG,SAAS,EAAE,QAAQ,GAAG,OAAO,IAAI,CAAC;EAC3C,CAAC,CACH;EAEF,QAAa,WAAW,WAAW,CAAC,CAAC,WAAW;GAC9C,WAAW;GACX,KAAK;EACP,CAAC;CACH;CAEA,OAAO;EACL,MAAM,QAAQ;GACZ,UAAU;GACV,KAAK;EACP;EACA,QAAQ;GACN,YAAY;GACZ,UAAU;EACZ;CACF;AACF;;;;;;;;;;;;;ACtFA,MAAa,6BAA6B,YACxC,QACG,SAAS,EAAE,MAAM,YAChB,UAAU,OACN,CAAC,mBAAmB,IAAI,CAAC,IACzB,MAAM,QAAQ,KAAK,IACjB,MAAM,KAAK,SAAS,GAAG,mBAAmB,IAAI,EAAE,GAAG,mBAAmB,IAAI,GAAG,IAC7E,CAAC,GAAG,mBAAmB,IAAI,EAAE,GAAG,mBAAmB,KAAK,GAAG,CACnE,CAAC,CACA,KAAK,GAAG"}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { _ as ActionTrigger, p as ActionSource, v as ActionTriggerResult } from "./types-D-DoiESj.js";
|
|
2
|
-
import { AnnotationRef, FormSubmissionEntry, PageObjectNumber } from "@embedpdf/engine-core/runtime";
|
|
3
|
-
//#region src/hover-pump.d.ts
|
|
4
|
-
/** One hoverable target, as a feed sees it. `events` lets a feed that KNOWS
|
|
5
|
-
* tree presence (folded model, fill item) skip the inert half of a pair —
|
|
6
|
-
* omitted flags default to true. */
|
|
7
|
-
interface HoverTarget {
|
|
8
|
-
ref: AnnotationRef;
|
|
9
|
-
pon: PageObjectNumber;
|
|
10
|
-
/** Optional provenance hint forwarded on the trigger (widget/link feeds). */
|
|
11
|
-
source?: ActionSource;
|
|
12
|
-
events?: {
|
|
13
|
-
enter?: boolean;
|
|
14
|
-
exit?: boolean;
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
interface HoverPump {
|
|
18
|
-
/** Report where the pointer is now (null = nowhere interesting). */
|
|
19
|
-
hover(target: HoverTarget | null): void;
|
|
20
|
-
/** Forget everything without dispatching (teardown; document switch). */
|
|
21
|
-
reset(): void;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* The ONE hover state machine every event plane shares (D8): per pointer
|
|
25
|
-
* feed, `{ delivered, desired, inFlight }`. On each settle it delivers the
|
|
26
|
-
* transition `delivered → desired` as `Exit(delivered)` then
|
|
27
|
-
* `Enter(desired)`, SUBMITTED BACK-TO-BACK SYNCHRONOUSLY — dispatch takes
|
|
28
|
-
* its queue slot before returning, so the ordered pair can never be split by
|
|
29
|
-
* a slow resolution (the per-annotation-tail reordering the review caught).
|
|
30
|
-
* Under pressure intermediate targets are skipped by design: the pointer
|
|
31
|
-
* sweeping A→B→C while A's exit is in flight delivers `Exit(A) → Enter(C)`,
|
|
32
|
-
* never a stale `Enter(B)`.
|
|
33
|
-
*/
|
|
34
|
-
declare function createHoverPump(dispatch: (trigger: ActionTrigger) => Promise<ActionTriggerResult>): HoverPump;
|
|
35
|
-
//#endregion
|
|
36
|
-
//#region src/submit-encoding.d.ts
|
|
37
|
-
/**
|
|
38
|
-
* Encode a resolved submission dataset as `application/x-www-form-urlencoded`
|
|
39
|
-
* (UTF-8 — the one encoding this helper speaks; a `/CharSet` other than
|
|
40
|
-
* utf-8 is the handler's problem). A name-only entry (`value === null`, the
|
|
41
|
-
* IncludeNoValueFields shape) encodes as a bare name; a multi-select list
|
|
42
|
-
* box repeats the name per value, the HTML-form convention.
|
|
43
|
-
*
|
|
44
|
-
* Pure and dependency-free on purpose: a convenience for embedder handlers,
|
|
45
|
-
* never called by the plugin itself (the plugin never touches a network).
|
|
46
|
-
*/
|
|
47
|
-
declare const submitEntriesToUrlEncoded: (entries: FormSubmissionEntry[]) => string;
|
|
48
|
-
//#endregion
|
|
49
|
-
export { createHoverPump as i, HoverPump as n, HoverTarget as r, submitEntriesToUrlEncoded as t };
|
|
50
|
-
//# sourceMappingURL=contract-COk-w3Fo.d.ts.map
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
//#region src/hover-pump.ts
|
|
2
|
-
const sameTarget = (a, b) => {
|
|
3
|
-
if (a === null || b === null) return a === b;
|
|
4
|
-
if (a.ref.kind !== b.ref.kind || a.pon !== b.pon) return false;
|
|
5
|
-
if (a.ref.kind === "objectNumber" && b.ref.kind === "objectNumber") return a.ref.annotObjectNumber === b.ref.annotObjectNumber;
|
|
6
|
-
if (a.ref.kind === "nm" && b.ref.kind === "nm") return a.ref.nm === b.ref.nm;
|
|
7
|
-
if (a.ref.kind === "index" && b.ref.kind === "index") return a.ref.index === b.ref.index && a.ref.revision === b.ref.revision;
|
|
8
|
-
return false;
|
|
9
|
-
};
|
|
10
|
-
/**
|
|
11
|
-
* The ONE hover state machine every event plane shares (D8): per pointer
|
|
12
|
-
* feed, `{ delivered, desired, inFlight }`. On each settle it delivers the
|
|
13
|
-
* transition `delivered → desired` as `Exit(delivered)` then
|
|
14
|
-
* `Enter(desired)`, SUBMITTED BACK-TO-BACK SYNCHRONOUSLY — dispatch takes
|
|
15
|
-
* its queue slot before returning, so the ordered pair can never be split by
|
|
16
|
-
* a slow resolution (the per-annotation-tail reordering the review caught).
|
|
17
|
-
* Under pressure intermediate targets are skipped by design: the pointer
|
|
18
|
-
* sweeping A→B→C while A's exit is in flight delivers `Exit(A) → Enter(C)`,
|
|
19
|
-
* never a stale `Enter(B)`.
|
|
20
|
-
*/
|
|
21
|
-
function createHoverPump(dispatch) {
|
|
22
|
-
let delivered = null;
|
|
23
|
-
let desired = null;
|
|
24
|
-
let inFlight = false;
|
|
25
|
-
const pump = () => {
|
|
26
|
-
if (inFlight || sameTarget(delivered, desired)) return;
|
|
27
|
-
inFlight = true;
|
|
28
|
-
const from = delivered;
|
|
29
|
-
const to = desired;
|
|
30
|
-
delivered = to;
|
|
31
|
-
const submissions = [];
|
|
32
|
-
if (from && from.events?.exit !== false) submissions.push(dispatch({
|
|
33
|
-
scope: "annotation",
|
|
34
|
-
event: "cursorExit",
|
|
35
|
-
ref: from.ref,
|
|
36
|
-
pon: from.pon,
|
|
37
|
-
...from.source ? { source: from.source } : {}
|
|
38
|
-
}));
|
|
39
|
-
if (to && to.events?.enter !== false) submissions.push(dispatch({
|
|
40
|
-
scope: "annotation",
|
|
41
|
-
event: "cursorEnter",
|
|
42
|
-
ref: to.ref,
|
|
43
|
-
pon: to.pon,
|
|
44
|
-
...to.source ? { source: to.source } : {}
|
|
45
|
-
}));
|
|
46
|
-
Promise.allSettled(submissions).then(() => {
|
|
47
|
-
inFlight = false;
|
|
48
|
-
pump();
|
|
49
|
-
});
|
|
50
|
-
};
|
|
51
|
-
return {
|
|
52
|
-
hover(target) {
|
|
53
|
-
desired = target;
|
|
54
|
-
pump();
|
|
55
|
-
},
|
|
56
|
-
reset() {
|
|
57
|
-
delivered = null;
|
|
58
|
-
desired = null;
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
//#endregion
|
|
63
|
-
//#region src/submit-encoding.ts
|
|
64
|
-
/**
|
|
65
|
-
* Encode a resolved submission dataset as `application/x-www-form-urlencoded`
|
|
66
|
-
* (UTF-8 — the one encoding this helper speaks; a `/CharSet` other than
|
|
67
|
-
* utf-8 is the handler's problem). A name-only entry (`value === null`, the
|
|
68
|
-
* IncludeNoValueFields shape) encodes as a bare name; a multi-select list
|
|
69
|
-
* box repeats the name per value, the HTML-form convention.
|
|
70
|
-
*
|
|
71
|
-
* Pure and dependency-free on purpose: a convenience for embedder handlers,
|
|
72
|
-
* never called by the plugin itself (the plugin never touches a network).
|
|
73
|
-
*/
|
|
74
|
-
const submitEntriesToUrlEncoded = (entries) => entries.flatMap(({ name, value }) => value === null ? [encodeURIComponent(name)] : Array.isArray(value) ? value.map((item) => `${encodeURIComponent(name)}=${encodeURIComponent(item)}`) : [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`]).join("&");
|
|
75
|
-
//#endregion
|
|
76
|
-
export { createHoverPump as n, submitEntriesToUrlEncoded as t };
|
|
77
|
-
|
|
78
|
-
//# sourceMappingURL=contract-DAem-EST.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"contract-DAem-EST.js","names":[],"sources":["../src/hover-pump.ts","../src/submit-encoding.ts"],"sourcesContent":["import type { AnnotationRef, PageObjectNumber } from '@embedpdf/engine-core/runtime';\n\nimport type { ActionSource, ActionTrigger, ActionTriggerResult } from './types';\n\n/** One hoverable target, as a feed sees it. `events` lets a feed that KNOWS\n * tree presence (folded model, fill item) skip the inert half of a pair —\n * omitted flags default to true. */\nexport interface HoverTarget {\n ref: AnnotationRef;\n pon: PageObjectNumber;\n /** Optional provenance hint forwarded on the trigger (widget/link feeds). */\n source?: ActionSource;\n events?: { enter?: boolean; exit?: boolean };\n}\n\nexport interface HoverPump {\n /** Report where the pointer is now (null = nowhere interesting). */\n hover(target: HoverTarget | null): void;\n /** Forget everything without dispatching (teardown; document switch). */\n reset(): void;\n}\n\nconst sameTarget = (a: HoverTarget | null, b: HoverTarget | null): boolean => {\n if (a === null || b === null) return a === b;\n if (a.ref.kind !== b.ref.kind || a.pon !== b.pon) return false;\n if (a.ref.kind === 'objectNumber' && b.ref.kind === 'objectNumber') {\n return a.ref.annotObjectNumber === b.ref.annotObjectNumber;\n }\n if (a.ref.kind === 'nm' && b.ref.kind === 'nm') return a.ref.nm === b.ref.nm;\n if (a.ref.kind === 'index' && b.ref.kind === 'index') {\n return a.ref.index === b.ref.index && a.ref.revision === b.ref.revision;\n }\n return false;\n};\n\n/**\n * The ONE hover state machine every event plane shares (D8): per pointer\n * feed, `{ delivered, desired, inFlight }`. On each settle it delivers the\n * transition `delivered → desired` as `Exit(delivered)` then\n * `Enter(desired)`, SUBMITTED BACK-TO-BACK SYNCHRONOUSLY — dispatch takes\n * its queue slot before returning, so the ordered pair can never be split by\n * a slow resolution (the per-annotation-tail reordering the review caught).\n * Under pressure intermediate targets are skipped by design: the pointer\n * sweeping A→B→C while A's exit is in flight delivers `Exit(A) → Enter(C)`,\n * never a stale `Enter(B)`.\n */\nexport function createHoverPump(\n dispatch: (trigger: ActionTrigger) => Promise<ActionTriggerResult>,\n): HoverPump {\n let delivered: HoverTarget | null = null;\n let desired: HoverTarget | null = null;\n let inFlight = false;\n\n const pump = (): void => {\n if (inFlight || sameTarget(delivered, desired)) return;\n inFlight = true;\n const from = delivered;\n const to = desired;\n delivered = to;\n const submissions: Array<Promise<unknown>> = [];\n if (from && from.events?.exit !== false) {\n submissions.push(\n dispatch({\n scope: 'annotation',\n event: 'cursorExit',\n ref: from.ref,\n pon: from.pon,\n ...(from.source ? { source: from.source } : {}),\n }),\n );\n }\n if (to && to.events?.enter !== false) {\n submissions.push(\n dispatch({\n scope: 'annotation',\n event: 'cursorEnter',\n ref: to.ref,\n pon: to.pon,\n ...(to.source ? { source: to.source } : {}),\n }),\n );\n }\n void Promise.allSettled(submissions).then(() => {\n inFlight = false;\n pump(); // the pointer may have moved on — deliver the latest transition\n });\n };\n\n return {\n hover(target) {\n desired = target;\n pump();\n },\n reset() {\n delivered = null;\n desired = null;\n },\n };\n}\n","import type { FormSubmissionEntry } from '@embedpdf/engine-core/runtime';\n\n/**\n * Encode a resolved submission dataset as `application/x-www-form-urlencoded`\n * (UTF-8 — the one encoding this helper speaks; a `/CharSet` other than\n * utf-8 is the handler's problem). A name-only entry (`value === null`, the\n * IncludeNoValueFields shape) encodes as a bare name; a multi-select list\n * box repeats the name per value, the HTML-form convention.\n *\n * Pure and dependency-free on purpose: a convenience for embedder handlers,\n * never called by the plugin itself (the plugin never touches a network).\n */\nexport const submitEntriesToUrlEncoded = (entries: FormSubmissionEntry[]): string =>\n entries\n .flatMap(({ name, value }) =>\n value === null\n ? [encodeURIComponent(name)]\n : Array.isArray(value)\n ? value.map((item) => `${encodeURIComponent(name)}=${encodeURIComponent(item)}`)\n : [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`],\n )\n .join('&');\n"],"mappings":";AAsBA,MAAM,cAAc,GAAuB,MAAmC;CAC5E,IAAI,MAAM,QAAQ,MAAM,MAAM,OAAO,MAAM;CAC3C,IAAI,EAAE,IAAI,SAAS,EAAE,IAAI,QAAQ,EAAE,QAAQ,EAAE,KAAK,OAAO;CACzD,IAAI,EAAE,IAAI,SAAS,kBAAkB,EAAE,IAAI,SAAS,gBAClD,OAAO,EAAE,IAAI,sBAAsB,EAAE,IAAI;CAE3C,IAAI,EAAE,IAAI,SAAS,QAAQ,EAAE,IAAI,SAAS,MAAM,OAAO,EAAE,IAAI,OAAO,EAAE,IAAI;CAC1E,IAAI,EAAE,IAAI,SAAS,WAAW,EAAE,IAAI,SAAS,SAC3C,OAAO,EAAE,IAAI,UAAU,EAAE,IAAI,SAAS,EAAE,IAAI,aAAa,EAAE,IAAI;CAEjE,OAAO;AACT;;;;;;;;;;;;AAaA,SAAgB,gBACd,UACW;CACX,IAAI,YAAgC;CACpC,IAAI,UAA8B;CAClC,IAAI,WAAW;CAEf,MAAM,aAAmB;EACvB,IAAI,YAAY,WAAW,WAAW,OAAO,GAAG;EAChD,WAAW;EACX,MAAM,OAAO;EACb,MAAM,KAAK;EACX,YAAY;EACZ,MAAM,cAAuC,CAAC;EAC9C,IAAI,QAAQ,KAAK,QAAQ,SAAS,OAChC,YAAY,KACV,SAAS;GACP,OAAO;GACP,OAAO;GACP,KAAK,KAAK;GACV,KAAK,KAAK;GACV,GAAI,KAAK,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;EAC/C,CAAC,CACH;EAEF,IAAI,MAAM,GAAG,QAAQ,UAAU,OAC7B,YAAY,KACV,SAAS;GACP,OAAO;GACP,OAAO;GACP,KAAK,GAAG;GACR,KAAK,GAAG;GACR,GAAI,GAAG,SAAS,EAAE,QAAQ,GAAG,OAAO,IAAI,CAAC;EAC3C,CAAC,CACH;EAEF,QAAa,WAAW,WAAW,CAAC,CAAC,WAAW;GAC9C,WAAW;GACX,KAAK;EACP,CAAC;CACH;CAEA,OAAO;EACL,MAAM,QAAQ;GACZ,UAAU;GACV,KAAK;EACP;EACA,QAAQ;GACN,YAAY;GACZ,UAAU;EACZ;CACF;AACF;;;;;;;;;;;;;ACtFA,MAAa,6BAA6B,YACxC,QACG,SAAS,EAAE,MAAM,YAChB,UAAU,OACN,CAAC,mBAAmB,IAAI,CAAC,IACzB,MAAM,QAAQ,KAAK,IACjB,MAAM,KAAK,SAAS,GAAG,mBAAmB,IAAI,EAAE,GAAG,mBAAmB,IAAI,GAAG,IAC7E,CAAC,GAAG,mBAAmB,IAAI,EAAE,GAAG,mBAAmB,KAAK,GAAG,CACnE,CAAC,CACA,KAAK,GAAG"}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { _ as ActionTrigger, p as ActionSource, v as ActionTriggerResult } from "./types-D-DoiESj.cjs";
|
|
2
|
-
import { AnnotationRef, FormSubmissionEntry, PageObjectNumber } from "@embedpdf/engine-core/runtime";
|
|
3
|
-
//#region src/hover-pump.d.ts
|
|
4
|
-
/** One hoverable target, as a feed sees it. `events` lets a feed that KNOWS
|
|
5
|
-
* tree presence (folded model, fill item) skip the inert half of a pair —
|
|
6
|
-
* omitted flags default to true. */
|
|
7
|
-
interface HoverTarget {
|
|
8
|
-
ref: AnnotationRef;
|
|
9
|
-
pon: PageObjectNumber;
|
|
10
|
-
/** Optional provenance hint forwarded on the trigger (widget/link feeds). */
|
|
11
|
-
source?: ActionSource;
|
|
12
|
-
events?: {
|
|
13
|
-
enter?: boolean;
|
|
14
|
-
exit?: boolean;
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
interface HoverPump {
|
|
18
|
-
/** Report where the pointer is now (null = nowhere interesting). */
|
|
19
|
-
hover(target: HoverTarget | null): void;
|
|
20
|
-
/** Forget everything without dispatching (teardown; document switch). */
|
|
21
|
-
reset(): void;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* The ONE hover state machine every event plane shares (D8): per pointer
|
|
25
|
-
* feed, `{ delivered, desired, inFlight }`. On each settle it delivers the
|
|
26
|
-
* transition `delivered → desired` as `Exit(delivered)` then
|
|
27
|
-
* `Enter(desired)`, SUBMITTED BACK-TO-BACK SYNCHRONOUSLY — dispatch takes
|
|
28
|
-
* its queue slot before returning, so the ordered pair can never be split by
|
|
29
|
-
* a slow resolution (the per-annotation-tail reordering the review caught).
|
|
30
|
-
* Under pressure intermediate targets are skipped by design: the pointer
|
|
31
|
-
* sweeping A→B→C while A's exit is in flight delivers `Exit(A) → Enter(C)`,
|
|
32
|
-
* never a stale `Enter(B)`.
|
|
33
|
-
*/
|
|
34
|
-
declare function createHoverPump(dispatch: (trigger: ActionTrigger) => Promise<ActionTriggerResult>): HoverPump;
|
|
35
|
-
//#endregion
|
|
36
|
-
//#region src/submit-encoding.d.ts
|
|
37
|
-
/**
|
|
38
|
-
* Encode a resolved submission dataset as `application/x-www-form-urlencoded`
|
|
39
|
-
* (UTF-8 — the one encoding this helper speaks; a `/CharSet` other than
|
|
40
|
-
* utf-8 is the handler's problem). A name-only entry (`value === null`, the
|
|
41
|
-
* IncludeNoValueFields shape) encodes as a bare name; a multi-select list
|
|
42
|
-
* box repeats the name per value, the HTML-form convention.
|
|
43
|
-
*
|
|
44
|
-
* Pure and dependency-free on purpose: a convenience for embedder handlers,
|
|
45
|
-
* never called by the plugin itself (the plugin never touches a network).
|
|
46
|
-
*/
|
|
47
|
-
declare const submitEntriesToUrlEncoded: (entries: FormSubmissionEntry[]) => string;
|
|
48
|
-
//#endregion
|
|
49
|
-
export { createHoverPump as i, HoverPump as n, HoverTarget as r, submitEntriesToUrlEncoded as t };
|
|
50
|
-
//# sourceMappingURL=contract-Os5y4NaD.d.cts.map
|
package/dist/internal.cjs
DELETED
package/dist/internal.d.cts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { A as DetachedScriptRealm, B as SubmitIntent, C as ActionsHostCapability, D as AnnotCommitEntry, F as ScriptCommitSurface, I as ScriptRealmKind, L as ScriptRealmPort, M as FormCommitSink, N as PageStateReport, O as AnnotCommitResult, R as ScriptRealmTarget, V as SubmitResolver, a as ActionExecutor, g as ActionSubmitRequest, k as AnnotCommitSink, o as ActionExecutorResult, z as ScriptSurfaceResult } from "./types-D-DoiESj.cjs";
|
|
2
|
-
import { ActionsToken } from "./contract/host.cjs";
|
|
3
|
-
export { type ActionExecutor, type ActionExecutorResult, type ActionSubmitRequest, type ActionsHostCapability, ActionsToken, type AnnotCommitEntry, type AnnotCommitResult, type AnnotCommitSink, type DetachedScriptRealm, type FormCommitSink, type PageStateReport, type ScriptCommitSurface, type ScriptRealmKind, type ScriptRealmPort, type ScriptRealmTarget, type ScriptSurfaceResult, type SubmitIntent, type SubmitResolver };
|
package/dist/internal.d.ts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { A as DetachedScriptRealm, B as SubmitIntent, C as ActionsHostCapability, D as AnnotCommitEntry, F as ScriptCommitSurface, I as ScriptRealmKind, L as ScriptRealmPort, M as FormCommitSink, N as PageStateReport, O as AnnotCommitResult, R as ScriptRealmTarget, V as SubmitResolver, a as ActionExecutor, g as ActionSubmitRequest, k as AnnotCommitSink, o as ActionExecutorResult, z as ScriptSurfaceResult } from "./types-D-DoiESj.js";
|
|
2
|
-
import { ActionsToken } from "./contract/host.js";
|
|
3
|
-
export { type ActionExecutor, type ActionExecutorResult, type ActionSubmitRequest, type ActionsHostCapability, ActionsToken, type AnnotCommitEntry, type AnnotCommitResult, type AnnotCommitSink, type DetachedScriptRealm, type FormCommitSink, type PageStateReport, type ScriptCommitSurface, type ScriptRealmKind, type ScriptRealmPort, type ScriptRealmTarget, type ScriptSurfaceResult, type SubmitIntent, type SubmitResolver };
|
package/dist/internal.js
DELETED
package/dist/types-BXJLAKXi.cjs
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
let _embedpdf_core = require("@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 = (0, _embedpdf_core.createCapabilityToken)("actions", { hint: `add actionsPlugin() from '@embedpdf/plugin-actions' to your plugins list` });
|
|
32
|
-
//#endregion
|
|
33
|
-
Object.defineProperty(exports, "ActionsToken", {
|
|
34
|
-
enumerable: true,
|
|
35
|
-
get: function() {
|
|
36
|
-
return ActionsToken;
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
Object.defineProperty(exports, "eventOf", {
|
|
40
|
-
enumerable: true,
|
|
41
|
-
get: function() {
|
|
42
|
-
return eventOf;
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
Object.defineProperty(exports, "originOf", {
|
|
46
|
-
enumerable: true,
|
|
47
|
-
get: function() {
|
|
48
|
-
return originOf;
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
//# sourceMappingURL=types-BXJLAKXi.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types-BXJLAKXi.cjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["import {\n createCapabilityToken,\n type DocumentMeta,\n type EventHook,\n type Unsubscribe,\n} 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 DocumentHandle,\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. */\n/**\n * Which realm produced a script result. `'document'` = this document's own\n * realm: every effect targets the viewer document. `'detached'` = a realm\n * minted for a document that is NOT displayed (a stamp asset): it has no\n * document surface, so only alerts reach the adapter — print, page\n * navigation, and submit are suppressed with a diagnostic rather than\n * acting on the wrong document.\n */\nexport type ScriptRealmKind = 'document' | 'detached';\n\nexport interface ScriptSurfaceResult {\n uiEffects: ScriptUiEffect[];\n diagnostics: ScriptDiagnostic[];\n error?: ScriptExecutionError;\n origin: ActionOrigin;\n phase: 'boot' | 'user';\n realm: ScriptRealmKind;\n}\n\n/** A K/V/C/F transaction's result as the form controller reports it: effects\n * carry their own phase (boot effects belong to the first transaction that\n * lazily booted the realm). Structurally `FormCommitResult`'s surface half —\n * typed here so the actions plane never imports the form package. */\nexport interface ScriptCommitSurface {\n uiEffects: Array<ScriptUiEffect & { phase: 'boot' | 'user' }>;\n diagnostics: ScriptDiagnostic[];\n error?: ScriptExecutionError;\n}\n\n// ── script realms (host lens) ───────────────────────────────────────────────\n\n/** What a realm is minted FOR. `doc` is the document the scripts operate on\n * (the viewer document, or a detached asset); `document()` is the metadata\n * scripts observe (`this.documentFileName` …) — for a detached stamp that is\n * the TARGET document's, by Acrobat's dynamic-stamp contract. */\nexport interface ScriptRealmTarget {\n doc: DocumentHandle;\n document(): DocumentMeta | null;\n /** Name-tree programs, fetched lazily once per realm build. */\n bootSources(): Promise<string[]>;\n}\n\n/** The realm transaction port plus the budget consumers apply as their\n * transaction aggregate — the same shape whether the realm is this\n * document's own (owned by actions) or a detached one (owned by the caller). */\nexport interface ScriptRealmPort {\n /** The body must perform prefetch, runs, sink commits, and reconciliation\n * before returning (commit-inside-the-boundary). */\n transaction<T>(body: (txn: ScriptTransaction) => Promise<T>): Promise<T>;\n budget: ScriptBudget;\n}\n\n/** A detached realm: the caller OWNS its lifetime. */\nexport interface DetachedScriptRealm extends ScriptRealmPort {\n dispose(): void;\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 * THIS document's realm — present ONLY when `javascript.enabled` (its\n * presence IS form's \"scripting on\" signal).\n */\n scriptRealm?: ScriptRealmPort;\n /**\n * Mint a realm for a DETACHED document under this document's policy and\n * environment (same sandbox factory, identity, clock, budget; a fresh\n * sandbox, so isolated globals). Present ONLY when `javascript.enabled`,\n * like `scriptRealm`. The caller owns the returned realm's lifetime and\n * surfaces its results with `realm: 'detached'`.\n */\n createDetachedScriptRealm?(target: ScriptRealmTarget): DetachedScriptRealm;\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 /** Surface a K/V/C/F commit result: splits boot-phase and user-phase\n * effects into their own surfaces (diagnostics and the error ride the\n * user phase) — the one place that split lives. */\n surfaceScriptCommit(\n commit: ScriptCommitSurface,\n context: { origin: ActionOrigin; realm: ScriptRealmKind },\n ): 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":";;;AA8GA,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;AAsdA,MAAa,gBAAA,GAAA,eAAA,sBAAA,CAAwD,WAAW,EAC9E,MAAM,2EACR,CAAC"}
|