@embedpdf/plugin-form 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.
Files changed (47) hide show
  1. package/dist/contract/host.cjs +29 -2
  2. package/dist/contract/host.cjs.map +1 -0
  3. package/dist/contract/host.d.cts +3 -2
  4. package/dist/contract/host.d.ts +3 -2
  5. package/dist/contract/host.js +14 -2
  6. package/dist/contract/host.js.map +1 -0
  7. package/dist/contract-BwcgtCOD.d.ts +566 -0
  8. package/dist/contract-CU0jrI_D.cjs +56 -0
  9. package/dist/contract-CU0jrI_D.cjs.map +1 -0
  10. package/dist/contract-D-yQxw3H.d.cts +566 -0
  11. package/dist/contract-DcncvPcF.js +45 -0
  12. package/dist/contract-DcncvPcF.js.map +1 -0
  13. package/dist/contract.cjs +17 -6
  14. package/dist/contract.d.cts +2 -8
  15. package/dist/contract.d.ts +2 -8
  16. package/dist/contract.js +2 -7
  17. package/dist/controller-CS6tV2m1.cjs +514 -0
  18. package/dist/controller-CS6tV2m1.cjs.map +1 -0
  19. package/dist/controller-Sr5M_8G8.js +497 -0
  20. package/dist/controller-Sr5M_8G8.js.map +1 -0
  21. package/dist/host-contract-1epLfK1S.d.cts +87 -0
  22. package/dist/host-contract-BRYUbpT_.d.ts +87 -0
  23. package/dist/index.cjs +2916 -1205
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +46 -17
  26. package/dist/index.d.ts +46 -17
  27. package/dist/index.js +2895 -1206
  28. package/dist/index.js.map +1 -1
  29. package/dist/scripting.cjs +3 -484
  30. package/dist/scripting.d.cts +58 -22
  31. package/dist/scripting.d.ts +58 -22
  32. package/dist/scripting.js +1 -482
  33. package/package.json +15 -14
  34. package/dist/contract.cjs.map +0 -1
  35. package/dist/contract.js.map +0 -1
  36. package/dist/internal.cjs +0 -4
  37. package/dist/internal.d.cts +0 -3
  38. package/dist/internal.d.ts +0 -3
  39. package/dist/internal.js +0 -3
  40. package/dist/scripting.cjs.map +0 -1
  41. package/dist/scripting.js.map +0 -1
  42. package/dist/types-Bpc32Qmx.d.cts +0 -309
  43. package/dist/types-C1uIIYfn.cjs +0 -16
  44. package/dist/types-C1uIIYfn.cjs.map +0 -1
  45. package/dist/types-DRirhZKr.d.ts +0 -309
  46. package/dist/types-DkQmmcTG.js +0 -12
  47. package/dist/types-DkQmmcTG.js.map +0 -1
@@ -1,47 +1,83 @@
1
- import { r as FormCommitResult } from "./types-DRirhZKr.js";
1
+ import { R as FormUiEffect } from "./contract-BwcgtCOD.js";
2
2
  import { DocumentMeta } from "@embedpdf/core";
3
- import { DocumentHandle, FormFieldRef, FormFieldValue, PdfActionTree } from "@embedpdf/engine-core/runtime";
4
- import { ScriptBudget, ScriptTransaction } from "@embedpdf/core-acrojs";
5
- //#region src/scripting.d.ts
3
+ import { FormEffect, FormFieldRef, FormFieldValue, FormSnapshot, PdfActionTree } from "@embedpdf/engine-core/runtime";
4
+ import { ScriptBudget, ScriptDiagnostic, ScriptExecutionError, ScriptTransaction } from "@embedpdf/core-acrojs";
5
+ //#region src/scripting/controller.d.ts
6
6
  /**
7
- * The controller never owns a realm. It rides a realm PORT — this document's
7
+ * The controller never owns a realm. It rides a realm port — this document's
8
8
  * own (the actions plugin's per-document host) or a detached one minted by
9
9
  * the actions plugin for a document that is not displayed (stamp's
10
10
  * asset documents). Either way the owner disposes the realm; `dispose()`
11
11
  * here only fences further transactions.
12
12
  */
13
13
  interface FormScriptingControllerOptions {
14
- doc: DocumentHandle;
15
- document(): DocumentMeta | null;
16
- /** The realm's transaction port ({@link ScriptTransaction}). The K/V/C/F
17
- * pipeline runs WHOLLY inside one transaction: snapshot fetch, every
18
- * pass, and the engine commit — the commit-inside-the-boundary law. */
14
+ /** What the scripts read of the document: its name, page count and pages. */
15
+ document(): Pick<DocumentMeta, 'name' | 'pageCount' | 'pages'> | null;
16
+ /** The realm's transaction port ({@link ScriptTransaction}): the realm runs one at a time. */
19
17
  transaction<T>(body: (txn: ScriptTransaction) => Promise<T>): Promise<T>;
20
18
  /** The transaction aggregate (output bytes, wall-clock across passes);
21
19
  * the realm owner hands over the same budget its runs enforce. */
22
20
  budget?: ScriptBudget;
23
21
  }
22
+ /** What the form's scripts made of one write, before anything is written. */
23
+ interface FormScriptResult {
24
+ /**
25
+ * `accepted`: write `effects`. `rejected`: a keystroke or validate script refused the value,
26
+ * so only `bootEffects` are written. `failed`: the transaction broke (a budget, a script that
27
+ * couldn't run), so nothing is.
28
+ */
29
+ readonly status: 'accepted' | 'rejected' | 'failed';
30
+ /** What the scripts changed in the form, in the order to write it (`formEffectOps`). */
31
+ readonly effects: FormEffect[];
32
+ /** What the document's open scripts changed: written even when the value is refused. */
33
+ readonly bootEffects: FormEffect[];
34
+ readonly uiEffects: FormUiEffect[];
35
+ readonly diagnostics: ScriptDiagnostic[];
36
+ readonly error?: ScriptExecutionError;
37
+ }
38
+ /** The scripts one transaction can run, each against the form it is given. */
39
+ interface FormScripts {
40
+ /**
41
+ * A field's new value through its keystroke and validate scripts, then the calculations and
42
+ * the formats. `form` is the form without the value.
43
+ */
44
+ commit(form: FormSnapshot, ref: FormFieldRef, value: FormFieldValue): Promise<FormScriptResult>;
45
+ /** One widget's activation action (`/A`, with `/Next`). Only its scripts run here. */
46
+ activate(form: FormSnapshot, ref: FormFieldRef, action: PdfActionTree<unknown>): Promise<FormScriptResult>;
47
+ /** The document's open scripts (once per realm) and the calculations, without a field change. */
48
+ recalculate(form: FormSnapshot): Promise<FormScriptResult>;
49
+ }
24
50
  declare class FormScriptingController {
25
51
  private readonly options;
26
52
  private disposed;
27
- private readonly transaction;
28
53
  private readonly transactionBudget;
29
54
  constructor(options: FormScriptingControllerOptions);
30
- /** The realm belongs to its OWNER (the actions plugin, or the caller that
55
+ /** The realm belongs to its owner (the actions plugin, or the caller that
31
56
  * minted a detached one) — this only fences further transactions. */
32
57
  dispose(): void;
33
- commit(ref: FormFieldRef, proposed: FormFieldValue): Promise<FormCommitResult>;
34
- /** Execute one originating widget's activation action (`/A`, including `/Next`). */
35
- activate(ref: FormFieldRef, action: PdfActionTree): Promise<FormCommitResult>;
36
- /** Run lazy document boot plus the `/CO` chain without a user field change.
37
- * The anchor field resolves INSIDE the transaction (undefined ref). */
38
- recalculate(): Promise<FormCommitResult>;
39
- private transact;
40
- private transactBody;
58
+ /**
59
+ * One realm transaction: `body` runs its scripts and writes what they changed before the
60
+ * next transaction starts, so that one reads the form with it.
61
+ */
62
+ transaction<T>(body: (scripts: FormScripts) => Promise<T>): Promise<T>;
63
+ /**
64
+ * Load the realm before the first write needs it: the scripts' engine starts, and the
65
+ * document's open scripts run, their effects kept for the first write as without warming.
66
+ * Nothing is written.
67
+ */
68
+ warm(form: FormSnapshot): Promise<void>;
69
+ /** {@link FormScripts.commit} in a transaction of its own. */
70
+ commit(form: FormSnapshot, ref: FormFieldRef, value: FormFieldValue): Promise<FormScriptResult>;
71
+ /** {@link FormScripts.activate} in a transaction of its own. */
72
+ activate(form: FormSnapshot, ref: FormFieldRef, action: PdfActionTree<unknown>): Promise<FormScriptResult>;
73
+ /** {@link FormScripts.recalculate} in a transaction of its own. */
74
+ recalculate(form: FormSnapshot): Promise<FormScriptResult>;
75
+ private run;
41
76
  private failed;
42
- private finishRejected;
77
+ /** The value is refused; the open scripts' effects are still written. */
78
+ private rejected;
43
79
  }
44
80
  declare function createFormScriptingController(options: FormScriptingControllerOptions): FormScriptingController;
45
81
  //#endregion
46
- export { FormScriptingController, FormScriptingControllerOptions, createFormScriptingController };
82
+ export { FormScriptResult, FormScriptingController, FormScriptingControllerOptions, FormScripts, createFormScriptingController };
47
83
  //# sourceMappingURL=scripting.d.ts.map
package/dist/scripting.js CHANGED
@@ -1,483 +1,2 @@
1
- import { DEFAULT_SCRIPT_BUDGET, javaScriptProgramFromActionTree, scriptFieldsFromSnapshot } from "@embedpdf/core-acrojs";
2
- //#region src/scripting.ts
3
- const refKey = (ref) => ref.kind === "objectNumber" ? `obj:${ref.fieldObjectNumber}` : `fqn:${ref.name}`;
4
- const sameRef = (left, right) => refKey(left) === refKey(right);
5
- const cloneValue = (value) => Array.isArray(value) ? [...value] : value;
6
- const sameValue = (left, right) => Array.isArray(left) && Array.isArray(right) ? left.length === right.length && left.every((value, index) => value === right[index]) : left === right;
7
- function cloneFields(fields) {
8
- return fields.map((field) => ({
9
- ...field,
10
- ref: { ...field.ref },
11
- value: cloneValue(field.value),
12
- defaultValue: cloneValue(field.defaultValue),
13
- ...field.options ? { options: field.options.map((option) => ({ ...option })) } : {}
14
- }));
15
- }
16
- function fieldByRef(fields, ref) {
17
- return fields.find((field) => sameRef(field.ref, ref));
18
- }
19
- function snapshotField(snapshot, ref) {
20
- return snapshot.fields.find((field) => sameRef(field.ref, ref));
21
- }
22
- function scriptValueFromFormValue(field, value) {
23
- if (field.family === "text" && value.type === "text") return value.value;
24
- if ((field.family === "checkbox" || field.family === "radio") && value.type === "toggle") return value.state ?? "Off";
25
- if (field.family === "combobox" && value.type === "choice") return value.values[0] ?? "";
26
- if (field.family === "listbox" && value.type === "choice") return [...value.values];
27
- throw new Error(`Form value type '${value.type}' does not match field family '${field.family}'`);
28
- }
29
- function formValueFromScriptValue(field) {
30
- switch (field.family) {
31
- case "text": return {
32
- type: "text",
33
- value: String(field.value ?? "")
34
- };
35
- case "checkbox":
36
- case "radio": return {
37
- type: "toggle",
38
- state: field.value === null || field.value === void 0 || String(field.value) === "Off" ? null : String(field.value)
39
- };
40
- case "combobox": return {
41
- type: "choice",
42
- values: Array.isArray(field.value) ? field.value.slice(0, 1) : [String(field.value ?? "")]
43
- };
44
- case "listbox": return {
45
- type: "choice",
46
- values: Array.isArray(field.value) ? [...field.value] : [String(field.value ?? "")]
47
- };
48
- default: return null;
49
- }
50
- }
51
- function applyEffects(overlay, effects) {
52
- for (const effect of effects) {
53
- if (effect.kind === "reset") {
54
- for (const ref of effect.refs) {
55
- const field = fieldByRef(overlay.fields, ref);
56
- if (!field) continue;
57
- field.value = cloneValue(field.defaultValue);
58
- overlay.resetKeys.add(refKey(ref));
59
- }
60
- continue;
61
- }
62
- const field = fieldByRef(overlay.fields, effect.ref);
63
- if (!field) continue;
64
- const key = refKey(effect.ref);
65
- if (effect.kind === "setValue") {
66
- field.value = scriptValueFromFormValue(field, effect.value);
67
- overlay.resetKeys.delete(key);
68
- } else if (effect.kind === "setDisplay") field.display = effect.display;
69
- else overlay.appearances.set(key, {
70
- ref: effect.ref,
71
- text: effect.text
72
- });
73
- }
74
- }
75
- function canonicalEffects(overlay) {
76
- const effects = [];
77
- const resets = [];
78
- for (const field of overlay.fields) {
79
- const original = fieldByRef(overlay.original, field.ref);
80
- if (!original) continue;
81
- if (!sameValue(original.value, field.value)) {
82
- const key = refKey(field.ref);
83
- if (overlay.resetKeys.has(key) && sameValue(field.value, field.defaultValue)) resets.push(field.ref);
84
- else {
85
- const value = formValueFromScriptValue(field);
86
- if (value) effects.push({
87
- kind: "setValue",
88
- ref: field.ref,
89
- value
90
- });
91
- }
92
- }
93
- if (original.display !== field.display) effects.push({
94
- kind: "setDisplay",
95
- ref: field.ref,
96
- display: field.display
97
- });
98
- }
99
- if (resets.length > 0) effects.unshift({
100
- kind: "reset",
101
- refs: resets
102
- });
103
- effects.push(...Array.from(overlay.appearances.values(), ({ ref, text }) => ({
104
- kind: "setAppearanceText",
105
- ref,
106
- text
107
- })));
108
- return effects;
109
- }
110
- function scriptError(message) {
111
- return {
112
- kind: "invalid-output",
113
- message
114
- };
115
- }
116
- function utf8Length(value) {
117
- let length = 0;
118
- for (let index = 0; index < value.length; index += 1) {
119
- const code = value.charCodeAt(index);
120
- if (code < 128) length += 1;
121
- else if (code < 2048) length += 2;
122
- else if (code >= 55296 && code <= 56319 && index + 1 < value.length) {
123
- length += 4;
124
- index += 1;
125
- } else length += 3;
126
- }
127
- return length;
128
- }
129
- function pageNumberFor(meta, field) {
130
- const pon = field.widgets.find((widget) => widget.pageObjectNumber > 0)?.pageObjectNumber;
131
- if (!meta || pon === void 0) return 0;
132
- const index = meta.pages.findIndex((page) => page.pageObjectNumber === pon);
133
- return Math.max(0, index);
134
- }
135
- function statusFromEffects(result) {
136
- if (result.results.some(({ status }) => status === "failed" || status === "skipped")) return "failed";
137
- if (result.results.some(({ status }) => status === "rejected")) return "failed";
138
- return result.results.some(({ status }) => status === "applied") ? "applied" : "unchanged";
139
- }
140
- var FormScriptingController = class {
141
- constructor(options) {
142
- this.options = options;
143
- this.disposed = false;
144
- this.transaction = options.transaction.bind(options);
145
- this.transactionBudget = options.budget;
146
- }
147
- /** The realm belongs to its OWNER (the actions plugin, or the caller that
148
- * minted a detached one) — this only fences further transactions. */
149
- dispose() {
150
- this.disposed = true;
151
- }
152
- async commit(ref, proposed) {
153
- return this.transact(ref, proposed);
154
- }
155
- /** Execute one originating widget's activation action (`/A`, including `/Next`). */
156
- async activate(ref, action) {
157
- return this.transact(ref, void 0, action);
158
- }
159
- /** Run lazy document boot plus the `/CO` chain without a user field change.
160
- * The anchor field resolves INSIDE the transaction (undefined ref). */
161
- async recalculate() {
162
- return this.transact(void 0);
163
- }
164
- async transact(refInput, proposed, activation) {
165
- if (this.disposed) throw new Error("Form scripting controller is disposed");
166
- return this.transaction((txn) => this.transactBody(txn, refInput, proposed, activation));
167
- }
168
- async transactBody(txn, refInput, proposed, activation) {
169
- const snapshot = await this.options.doc.forms.list();
170
- const ref = refInput ?? snapshot.calculationOrder.find((candidate) => candidate !== null && snapshotField(snapshot, candidate) !== void 0) ?? snapshot.fields[0]?.ref;
171
- if (!ref) return {
172
- status: "unchanged",
173
- scripted: true,
174
- effectsResult: null,
175
- uiEffects: [],
176
- diagnostics: []
177
- };
178
- const target = snapshotField(snapshot, ref);
179
- if (!target) return this.failed([], [], scriptError(`Form field '${refKey(ref)}' no longer exists`));
180
- const original = scriptFieldsFromSnapshot(snapshot);
181
- const overlay = {
182
- original,
183
- fields: cloneFields(original),
184
- resetKeys: /* @__PURE__ */ new Set(),
185
- appearances: /* @__PURE__ */ new Map()
186
- };
187
- const targetInput = fieldByRef(overlay.fields, ref);
188
- if (!targetInput) return this.failed([], [], scriptError(`Form field '${refKey(ref)}' has no script view`));
189
- const hasProposedValue = proposed !== void 0;
190
- let proposedValue = cloneValue(targetInput.value);
191
- if (proposed) try {
192
- proposedValue = scriptValueFromFormValue(targetInput, proposed);
193
- } catch (error) {
194
- return this.failed([], [], scriptError(error instanceof Error ? error.message : String(error)));
195
- }
196
- const uiEffects = [];
197
- const diagnostics = [];
198
- const pageNumber = pageNumberFor(this.options.document(), target);
199
- const budget = this.transactionBudget ?? DEFAULT_SCRIPT_BUDGET;
200
- let executionMs = 0;
201
- let aggregateOutputSize = 0;
202
- const consume = (output, phase) => {
203
- aggregateOutputSize += utf8Length(JSON.stringify(output));
204
- uiEffects.push(...output.uiEffects.map((effect) => ({
205
- ...effect,
206
- phase
207
- })));
208
- diagnostics.push(...output.diagnostics);
209
- if (aggregateOutputSize > budget.maxOutputBytes) return {
210
- kind: "budget",
211
- message: `Form script transaction output exceeded ${budget.maxOutputBytes} bytes`
212
- };
213
- return output.error ?? null;
214
- };
215
- const remainingBudget = () => {
216
- const remaining = budget.maxExecutionMs - executionMs;
217
- return remaining <= 0 ? null : {
218
- ...budget,
219
- maxExecutionMs: remaining
220
- };
221
- };
222
- const world = (fields, event) => ({
223
- fields,
224
- pageNumber,
225
- event
226
- });
227
- const run = async (source, input) => {
228
- const remaining = remainingBudget();
229
- if (!remaining) return { error: {
230
- kind: "budget",
231
- message: "Form script transaction timed out"
232
- } };
233
- let output;
234
- try {
235
- const startedAt = Date.now();
236
- output = await txn.run(source, input, remaining);
237
- executionMs += Date.now() - startedAt;
238
- } catch (error) {
239
- return { error: scriptError(error instanceof Error ? error.message : String(error)) };
240
- }
241
- const error = consume(output, "user");
242
- return error ? { error } : { output };
243
- };
244
- {
245
- let boot = null;
246
- try {
247
- boot = await txn.boot(world(overlay.fields, { kind: "name-tree-boot" }), budget);
248
- } catch (error) {
249
- diagnostics.push({
250
- code: "script-error",
251
- message: `Document boot script failed (continuing without it): ${error instanceof Error ? error.message : String(error)}`
252
- });
253
- }
254
- if (boot) {
255
- const bootError = consume(boot, "boot");
256
- if (!bootError) applyEffects(overlay, boot.formEffects);
257
- else diagnostics.push({
258
- code: "script-error",
259
- message: `Document boot script failed (continuing without it): ${bootError.message}`
260
- });
261
- }
262
- }
263
- const bootEffects = canonicalEffects(overlay);
264
- if (activation) {
265
- let program;
266
- try {
267
- program = javaScriptProgramFromActionTree(activation);
268
- } catch (error) {
269
- return this.failed(uiEffects, diagnostics, scriptError(error instanceof Error ? error.message : String(error)));
270
- }
271
- if (program) {
272
- const activated = await run(program, world(overlay.fields, {
273
- kind: "widget-activate",
274
- target: ref,
275
- source: ref,
276
- value: targetInput.value
277
- }));
278
- if (activated.error) return this.failed(uiEffects, diagnostics, activated.error);
279
- applyEffects(overlay, activated.output.formEffects);
280
- }
281
- }
282
- if (!activation && hasProposedValue && target.actions?.keystroke && target.family === "text") {
283
- let program;
284
- try {
285
- program = javaScriptProgramFromActionTree(target.actions.keystroke);
286
- } catch (error) {
287
- return this.failed(uiEffects, diagnostics, scriptError(error instanceof Error ? error.message : String(error)));
288
- }
289
- if (program) {
290
- const oldValue = String(targetInput.value ?? "");
291
- const typing = await run(program, world(overlay.fields, {
292
- kind: "field-keystroke",
293
- target: ref,
294
- source: ref,
295
- value: oldValue,
296
- change: String(proposedValue ?? ""),
297
- selStart: 0,
298
- selEnd: oldValue.length,
299
- willCommit: false
300
- }));
301
- if (typing.error && typing.error.kind !== "exception") return this.failed(uiEffects, diagnostics, typing.error);
302
- if (typing.error) diagnostics.push({
303
- code: "script-error",
304
- message: `Keystroke script failed (kept the typed value): ${typing.error.message}`
305
- });
306
- else {
307
- if (!typing.output.event.rc) return this.finishRejected(bootEffects, uiEffects, diagnostics);
308
- applyEffects(overlay, typing.output.formEffects);
309
- const event = typing.output.event;
310
- const base = String(event.value ?? "");
311
- proposedValue = base.slice(0, event.selStart) + event.change + base.slice(Math.max(event.selStart, event.selEnd));
312
- }
313
- const commit = await run(program, world(overlay.fields, {
314
- kind: "field-keystroke",
315
- target: ref,
316
- source: ref,
317
- value: proposedValue,
318
- change: "",
319
- selStart: 0,
320
- selEnd: 0,
321
- willCommit: true
322
- }));
323
- if (commit.error && commit.error.kind !== "exception") return this.failed(uiEffects, diagnostics, commit.error);
324
- if (commit.error) diagnostics.push({
325
- code: "script-error",
326
- message: `Keystroke commit script failed (kept the typed value): ${commit.error.message}`
327
- });
328
- else {
329
- if (!commit.output.event.rc) return this.finishRejected(bootEffects, uiEffects, diagnostics);
330
- applyEffects(overlay, commit.output.formEffects);
331
- proposedValue = cloneValue(commit.output.event.value);
332
- }
333
- }
334
- }
335
- if (!activation && hasProposedValue) {
336
- targetInput.value = cloneValue(proposedValue);
337
- overlay.resetKeys.delete(refKey(ref));
338
- }
339
- if (!activation && hasProposedValue && target.actions?.validate) {
340
- let program;
341
- try {
342
- program = javaScriptProgramFromActionTree(target.actions.validate);
343
- } catch (error) {
344
- return this.failed(uiEffects, diagnostics, scriptError(error instanceof Error ? error.message : String(error)));
345
- }
346
- if (program) {
347
- const validation = await run(program, world(overlay.fields, {
348
- kind: "field-validate",
349
- target: ref,
350
- source: ref,
351
- value: proposedValue,
352
- willCommit: true
353
- }));
354
- if (validation.error && validation.error.kind !== "exception") return this.failed(uiEffects, diagnostics, validation.error);
355
- if (validation.error) diagnostics.push({
356
- code: "script-error",
357
- message: `Validate script failed (accepted the value): ${validation.error.message}`
358
- });
359
- else {
360
- if (!validation.output.event.rc) return this.finishRejected(bootEffects, uiEffects, diagnostics);
361
- targetInput.value = cloneValue(validation.output.event.value);
362
- applyEffects(overlay, validation.output.formEffects);
363
- }
364
- }
365
- }
366
- const formatRefs = !activation && hasProposedValue ? [ref] : [];
367
- for (const calculationRef of activation ? [] : snapshot.calculationOrder) {
368
- if (!calculationRef) continue;
369
- const calculated = snapshotField(snapshot, calculationRef);
370
- const tree = calculated?.actions?.calculate;
371
- if (!calculated || !tree) continue;
372
- let program;
373
- try {
374
- program = javaScriptProgramFromActionTree(tree);
375
- } catch (error) {
376
- return this.failed(uiEffects, diagnostics, scriptError(error instanceof Error ? error.message : String(error)));
377
- }
378
- const calculatedInput = fieldByRef(overlay.fields, calculationRef);
379
- if (program && calculatedInput) {
380
- const calculation = await run(program, world(overlay.fields, {
381
- kind: "field-calculate",
382
- target: calculationRef,
383
- ...hasProposedValue ? { source: ref } : {},
384
- value: calculatedInput.value
385
- }));
386
- if (calculation.error && calculation.error.kind !== "exception") return this.failed(uiEffects, diagnostics, calculation.error);
387
- if (calculation.error) diagnostics.push({
388
- code: "script-error",
389
- message: `Calculate script failed (field left unchanged): ${calculation.error.message}`
390
- });
391
- else applyEffects(overlay, calculation.output.formEffects);
392
- }
393
- if (!formatRefs.some((candidate) => sameRef(candidate, calculationRef))) formatRefs.push(calculationRef);
394
- }
395
- for (const formatRef of formatRefs) {
396
- const field = snapshotField(snapshot, formatRef);
397
- const tree = field?.actions?.format;
398
- const overlayField = fieldByRef(overlay.fields, formatRef);
399
- if (!field || !tree || !overlayField) continue;
400
- let program;
401
- try {
402
- program = javaScriptProgramFromActionTree(tree);
403
- } catch (error) {
404
- return this.failed(uiEffects, diagnostics, scriptError(error instanceof Error ? error.message : String(error)));
405
- }
406
- if (!program) continue;
407
- const format = await run(program, world(overlay.fields, {
408
- kind: "field-format",
409
- target: formatRef,
410
- ...hasProposedValue ? { source: ref } : {},
411
- value: overlayField.value
412
- }));
413
- if (format.error && format.error.kind !== "exception") return this.failed(uiEffects, diagnostics, format.error);
414
- if (format.error) {
415
- diagnostics.push({
416
- code: "script-error",
417
- message: `Format script failed (kept the raw value): ${format.error.message}`
418
- });
419
- continue;
420
- }
421
- applyEffects(overlay, format.output.formEffects);
422
- }
423
- const effects = canonicalEffects(overlay);
424
- if (effects.length + uiEffects.length > budget.maxEffects) return this.failed(uiEffects, diagnostics, {
425
- kind: "budget",
426
- message: `Form script transaction exceeded ${budget.maxEffects} effects`
427
- });
428
- if (effects.length === 0) return {
429
- status: "unchanged",
430
- scripted: true,
431
- effectsResult: null,
432
- uiEffects,
433
- diagnostics
434
- };
435
- if (!this.options.doc.forms.applyEffects) return this.failed(uiEffects, diagnostics, scriptError("This engine does not support batched form effects"));
436
- const effectsResult = await this.options.doc.forms.applyEffects(effects);
437
- const status = statusFromEffects(effectsResult);
438
- return {
439
- status,
440
- scripted: true,
441
- effectsResult,
442
- uiEffects,
443
- diagnostics,
444
- ...status === "failed" ? { error: scriptError("One or more native form effects failed") } : {}
445
- };
446
- }
447
- failed(uiEffects, diagnostics, error) {
448
- return {
449
- status: "failed",
450
- scripted: true,
451
- effectsResult: null,
452
- uiEffects,
453
- diagnostics,
454
- error
455
- };
456
- }
457
- async finishRejected(bootEffects, uiEffects, diagnostics) {
458
- if (bootEffects.length === 0) return {
459
- status: "rejected",
460
- scripted: true,
461
- effectsResult: null,
462
- uiEffects,
463
- diagnostics
464
- };
465
- if (!this.options.doc.forms.applyEffects) return this.failed(uiEffects, diagnostics, scriptError("Batched form effects are unavailable"));
466
- const effectsResult = await this.options.doc.forms.applyEffects(bootEffects);
467
- if (statusFromEffects(effectsResult) === "failed") return this.failed(uiEffects, diagnostics, scriptError("A name-tree boot effect failed"));
468
- return {
469
- status: "rejected",
470
- scripted: true,
471
- effectsResult,
472
- uiEffects,
473
- diagnostics
474
- };
475
- }
476
- };
477
- function createFormScriptingController(options) {
478
- return new FormScriptingController(options);
479
- }
480
- //#endregion
1
+ import { n as createFormScriptingController, t as FormScriptingController } from "./controller-Sr5M_8G8.js";
481
2
  export { FormScriptingController, createFormScriptingController };
482
-
483
- //# sourceMappingURL=scripting.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embedpdf/plugin-form",
3
- "version": "3.0.0-next.13",
3
+ "version": "3.0.0-next.15",
4
4
  "private": false,
5
5
  "description": "Document-scoped interactive forms: reactive field state over doc.forms, fill-mode controls (FillItem projection), and form-data interchange. Widgets stay annotations; this plugin owns the field plane.",
6
6
  "type": "module",
@@ -20,10 +20,6 @@
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
  "./scripting": {
28
24
  "import": "./dist/scripting.js",
29
25
  "require": "./dist/scripting.cjs"
@@ -34,19 +30,24 @@
34
30
  "dist"
35
31
  ],
36
32
  "dependencies": {
37
- "@embedpdf/core-acrojs": "3.0.0-next.13",
38
- "@embedpdf/core-js-sandbox": "3.0.0-next.13",
39
- "@embedpdf/core": "3.0.0-next.13",
40
- "@embedpdf/plugin-interaction": "3.0.0-next.13",
41
- "@embedpdf/engine-core": "3.0.0-next.13",
42
- "@embedpdf/plugin-annotation": "3.0.0-next.13",
43
- "@embedpdf/plugin-actions": "3.0.0-next.13"
33
+ "@embedpdf/core": "3.0.0-next.15",
34
+ "@embedpdf/core-acrojs": "3.0.0-next.15",
35
+ "@embedpdf/core-form": "3.0.0-next.15",
36
+ "@embedpdf/core-annotation": "3.0.0-next.15",
37
+ "@embedpdf/core-geometry": "3.0.0-next.15",
38
+ "@embedpdf/plugin-actions": "3.0.0-next.15",
39
+ "@embedpdf/engine-core": "3.0.0-next.15",
40
+ "@embedpdf/plugin-annotation": "3.0.0-next.15",
41
+ "@embedpdf/core-js-sandbox": "3.0.0-next.15",
42
+ "@embedpdf/plugin-interaction": "3.0.0-next.15",
43
+ "@embedpdf/plugin-render": "3.0.0-next.15"
44
44
  },
45
45
  "devDependencies": {
46
46
  "typescript": "^5.0.0",
47
47
  "vitest": "^2.1.9",
48
- "@embedpdf/engine": "3.0.0-next.13",
49
- "@embedpdf/tooling-build": "0.0.0"
48
+ "@embedpdf/tooling-build": "0.0.0",
49
+ "@embedpdf/engine": "3.0.0-next.15",
50
+ "@embedpdf/plugin-history": "3.0.0-next.15"
50
51
  },
51
52
  "license": "Apache-2.0",
52
53
  "sideEffects": false,
@@ -1 +0,0 @@
1
- {"version":3,"file":"contract.cjs","names":["FormHostToken"],"sources":["../src/contract.ts"],"sourcesContent":["/** Public form capability protocol without the form engine implementation. */\nimport type { CapabilityToken } from '@embedpdf/core';\n\nimport { FormToken as FormHostToken } from './types';\nimport type { FormCapability } from './types';\n\nexport const FormToken = FormHostToken as unknown as CapabilityToken<FormCapability>;\nexport type {\n Box,\n FieldKey,\n FillItem,\n FormAction,\n FormCapability,\n FormCommitResult,\n FormCommitStatus,\n FormPluginOptions,\n FormState,\n FormUiEffect,\n PlacedField,\n PlaceFieldInput,\n WidgetActivationResult,\n WidgetHit,\n} from './types';\nexport type {\n FormFieldDTO,\n FormFieldPatch,\n FormFieldRef,\n WidgetAppearance,\n} from '@embedpdf/engine-core/runtime';\n"],"mappings":";;AAMA,MAAa,0CAAYA,CAAAA,CAAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"contract.js","names":["FormHostToken"],"sources":["../src/contract.ts"],"sourcesContent":["/** Public form capability protocol without the form engine implementation. */\nimport type { CapabilityToken } from '@embedpdf/core';\n\nimport { FormToken as FormHostToken } from './types';\nimport type { FormCapability } from './types';\n\nexport const FormToken = FormHostToken as unknown as CapabilityToken<FormCapability>;\nexport type {\n Box,\n FieldKey,\n FillItem,\n FormAction,\n FormCapability,\n FormCommitResult,\n FormCommitStatus,\n FormPluginOptions,\n FormState,\n FormUiEffect,\n PlacedField,\n PlaceFieldInput,\n WidgetActivationResult,\n WidgetHit,\n} from './types';\nexport type {\n FormFieldDTO,\n FormFieldPatch,\n FormFieldRef,\n WidgetAppearance,\n} from '@embedpdf/engine-core/runtime';\n"],"mappings":";;AAMA,MAAa,YAAYA"}
package/dist/internal.cjs DELETED
@@ -1,4 +0,0 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_types = require("./types-C1uIIYfn.cjs");
3
- require("./contract/host.cjs");
4
- exports.FormToken = require_types.FormToken;
@@ -1,3 +0,0 @@
1
- import { a as FormHostCapability, c as FormToken } from "./types-Bpc32Qmx.cjs";
2
- import "./contract/host.cjs";
3
- export { type FormHostCapability, FormToken };
@@ -1,3 +0,0 @@
1
- import { a as FormHostCapability, c as FormToken } from "./types-DRirhZKr.js";
2
- import "./contract/host.js";
3
- export { type FormHostCapability, FormToken };
package/dist/internal.js DELETED
@@ -1,3 +0,0 @@
1
- import { t as FormToken } from "./types-DkQmmcTG.js";
2
- import "./contract/host.js";
3
- export { FormToken };