@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.
- package/dist/contract/host.cjs +29 -2
- package/dist/contract/host.cjs.map +1 -0
- package/dist/contract/host.d.cts +3 -2
- package/dist/contract/host.d.ts +3 -2
- package/dist/contract/host.js +14 -2
- package/dist/contract/host.js.map +1 -0
- package/dist/contract-BwcgtCOD.d.ts +566 -0
- package/dist/contract-CU0jrI_D.cjs +56 -0
- package/dist/contract-CU0jrI_D.cjs.map +1 -0
- package/dist/contract-D-yQxw3H.d.cts +566 -0
- package/dist/contract-DcncvPcF.js +45 -0
- package/dist/contract-DcncvPcF.js.map +1 -0
- package/dist/contract.cjs +17 -6
- package/dist/contract.d.cts +2 -8
- package/dist/contract.d.ts +2 -8
- package/dist/contract.js +2 -7
- package/dist/controller-CS6tV2m1.cjs +514 -0
- package/dist/controller-CS6tV2m1.cjs.map +1 -0
- package/dist/controller-Sr5M_8G8.js +497 -0
- package/dist/controller-Sr5M_8G8.js.map +1 -0
- package/dist/host-contract-1epLfK1S.d.cts +87 -0
- package/dist/host-contract-BRYUbpT_.d.ts +87 -0
- package/dist/index.cjs +2916 -1205
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -17
- package/dist/index.d.ts +46 -17
- package/dist/index.js +2895 -1206
- package/dist/index.js.map +1 -1
- package/dist/scripting.cjs +3 -484
- package/dist/scripting.d.cts +58 -22
- package/dist/scripting.d.ts +58 -22
- package/dist/scripting.js +1 -482
- package/package.json +15 -14
- package/dist/contract.cjs.map +0 -1
- package/dist/contract.js.map +0 -1
- package/dist/internal.cjs +0 -4
- package/dist/internal.d.cts +0 -3
- package/dist/internal.d.ts +0 -3
- package/dist/internal.js +0 -3
- package/dist/scripting.cjs.map +0 -1
- package/dist/scripting.js.map +0 -1
- package/dist/types-Bpc32Qmx.d.cts +0 -309
- package/dist/types-C1uIIYfn.cjs +0 -16
- package/dist/types-C1uIIYfn.cjs.map +0 -1
- package/dist/types-DRirhZKr.d.ts +0 -309
- package/dist/types-DkQmmcTG.js +0 -12
- package/dist/types-DkQmmcTG.js.map +0 -1
package/dist/scripting.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scripting.cjs","names":["DEFAULT_SCRIPT_BUDGET"],"sources":["../src/scripting.ts"],"sourcesContent":["import type {\n DocumentHandle,\n FormEffect,\n FormEffectsResult,\n FormFieldDTO,\n FormFieldRef,\n FormFieldValue,\n FormSnapshot,\n PdfActionTree,\n} from '@embedpdf/engine-core/runtime';\nimport {\n DEFAULT_SCRIPT_BUDGET,\n javaScriptProgramFromActionTree,\n scriptFieldsFromSnapshot,\n type ScriptBudget,\n type ScriptDiagnostic,\n type ScriptExecutionError,\n type ScriptFieldInput,\n type ScriptOutput,\n type ScriptTransaction,\n type ScriptUiEffect,\n type ScriptValue,\n type ScriptWorldInput,\n} from '@embedpdf/core-acrojs';\nimport type { DocumentMeta } from '@embedpdf/core';\n\nimport type { FormCommitResult, FormUiEffect } from './types';\n\ninterface Overlay {\n original: ScriptFieldInput[];\n fields: ScriptFieldInput[];\n resetKeys: Set<string>;\n appearances: Map<string, { ref: FormFieldRef; text: string }>;\n}\n\n/**\n * The controller never owns a realm. It rides a realm PORT — this document's\n * own (the actions plugin's per-document host) or a detached one minted by\n * the actions plugin for a document that is not displayed (stamp's\n * asset documents). Either way the owner disposes the realm; `dispose()`\n * here only fences further transactions.\n */\nexport interface FormScriptingControllerOptions {\n doc: DocumentHandle;\n document(): DocumentMeta | null;\n /** The realm's transaction port ({@link ScriptTransaction}). The K/V/C/F\n * pipeline runs WHOLLY inside one transaction: snapshot fetch, every\n * pass, and the engine commit — the commit-inside-the-boundary law. */\n transaction<T>(body: (txn: ScriptTransaction) => Promise<T>): Promise<T>;\n /** The transaction aggregate (output bytes, wall-clock across passes);\n * the realm owner hands over the same budget its runs enforce. */\n budget?: ScriptBudget;\n}\n\nconst refKey = (ref: FormFieldRef): string =>\n ref.kind === 'objectNumber' ? `obj:${ref.fieldObjectNumber}` : `fqn:${ref.name}`;\n\nconst sameRef = (left: FormFieldRef, right: FormFieldRef): boolean =>\n refKey(left) === refKey(right);\n\nconst cloneValue = (value: ScriptValue): ScriptValue => (Array.isArray(value) ? [...value] : value);\n\nconst sameValue = (left: ScriptValue, right: ScriptValue): boolean =>\n Array.isArray(left) && Array.isArray(right)\n ? left.length === right.length && left.every((value, index) => value === right[index])\n : left === right;\n\nfunction cloneFields(fields: ScriptFieldInput[]): ScriptFieldInput[] {\n return fields.map((field) => ({\n ...field,\n ref: { ...field.ref },\n value: cloneValue(field.value),\n defaultValue: cloneValue(field.defaultValue),\n ...(field.options ? { options: field.options.map((option) => ({ ...option })) } : {}),\n }));\n}\n\nfunction fieldByRef<T extends { ref: FormFieldRef }>(\n fields: T[],\n ref: FormFieldRef,\n): T | undefined {\n return fields.find((field) => sameRef(field.ref, ref));\n}\n\nfunction snapshotField(snapshot: FormSnapshot, ref: FormFieldRef): FormFieldDTO | undefined {\n return snapshot.fields.find((field) => sameRef(field.ref, ref));\n}\n\nfunction scriptValueFromFormValue(field: ScriptFieldInput, value: FormFieldValue): ScriptValue {\n if (field.family === 'text' && value.type === 'text') return value.value;\n if ((field.family === 'checkbox' || field.family === 'radio') && value.type === 'toggle') {\n return value.state ?? 'Off';\n }\n if (field.family === 'combobox' && value.type === 'choice') return value.values[0] ?? '';\n if (field.family === 'listbox' && value.type === 'choice') return [...value.values];\n throw new Error(`Form value type '${value.type}' does not match field family '${field.family}'`);\n}\n\nfunction formValueFromScriptValue(field: ScriptFieldInput): FormFieldValue | null {\n switch (field.family) {\n case 'text':\n return { type: 'text', value: String(field.value ?? '') };\n case 'checkbox':\n case 'radio':\n return {\n type: 'toggle',\n state:\n field.value === null || field.value === undefined || String(field.value) === 'Off'\n ? null\n : String(field.value),\n };\n case 'combobox':\n return {\n type: 'choice',\n values: Array.isArray(field.value) ? field.value.slice(0, 1) : [String(field.value ?? '')],\n };\n case 'listbox':\n return {\n type: 'choice',\n values: Array.isArray(field.value) ? [...field.value] : [String(field.value ?? '')],\n };\n default:\n return null;\n }\n}\n\nfunction applyEffects(overlay: Overlay, effects: FormEffect[]): void {\n for (const effect of effects) {\n if (effect.kind === 'reset') {\n for (const ref of effect.refs) {\n const field = fieldByRef(overlay.fields, ref);\n if (!field) continue;\n field.value = cloneValue(field.defaultValue);\n overlay.resetKeys.add(refKey(ref));\n }\n continue;\n }\n\n const field = fieldByRef(overlay.fields, effect.ref);\n if (!field) continue;\n const key = refKey(effect.ref);\n if (effect.kind === 'setValue') {\n field.value = scriptValueFromFormValue(field, effect.value);\n overlay.resetKeys.delete(key);\n } else if (effect.kind === 'setDisplay') {\n field.display = effect.display;\n } else {\n overlay.appearances.set(key, { ref: effect.ref, text: effect.text });\n }\n }\n}\n\nfunction canonicalEffects(overlay: Overlay): FormEffect[] {\n const effects: FormEffect[] = [];\n const resets: FormFieldRef[] = [];\n for (const field of overlay.fields) {\n const original = fieldByRef(overlay.original, field.ref);\n if (!original) continue;\n if (!sameValue(original.value, field.value)) {\n const key = refKey(field.ref);\n if (overlay.resetKeys.has(key) && sameValue(field.value, field.defaultValue)) {\n resets.push(field.ref);\n } else {\n const value = formValueFromScriptValue(field);\n if (value) effects.push({ kind: 'setValue', ref: field.ref, value });\n }\n }\n if (original.display !== field.display) {\n effects.push({ kind: 'setDisplay', ref: field.ref, display: field.display });\n }\n }\n if (resets.length > 0) effects.unshift({ kind: 'reset', refs: resets });\n effects.push(\n ...Array.from(overlay.appearances.values(), ({ ref, text }) => ({\n kind: 'setAppearanceText' as const,\n ref,\n text,\n })),\n );\n return effects;\n}\n\nfunction scriptError(message: string): ScriptExecutionError {\n return { kind: 'invalid-output', message };\n}\n\nfunction utf8Length(value: string): number {\n let length = 0;\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code < 0x80) length += 1;\n else if (code < 0x800) length += 2;\n else if (code >= 0xd800 && code <= 0xdbff && index + 1 < value.length) {\n length += 4;\n index += 1;\n } else length += 3;\n }\n return length;\n}\n\nfunction pageNumberFor(meta: DocumentMeta | null, field: FormFieldDTO): number {\n const pon = field.widgets.find((widget) => widget.pageObjectNumber > 0)?.pageObjectNumber;\n if (!meta || pon === undefined) return 0;\n const index = meta.pages.findIndex((page) => page.pageObjectNumber === pon);\n return Math.max(0, index);\n}\n\nfunction statusFromEffects(result: FormEffectsResult): FormCommitResult['status'] {\n if (result.results.some(({ status }) => status === 'failed' || status === 'skipped')) {\n return 'failed';\n }\n if (result.results.some(({ status }) => status === 'rejected')) return 'failed';\n return result.results.some(({ status }) => status === 'applied') ? 'applied' : 'unchanged';\n}\n\nexport class FormScriptingController {\n private disposed = false;\n private readonly transaction: <T>(body: (txn: ScriptTransaction) => Promise<T>) => Promise<T>;\n private readonly transactionBudget: ScriptBudget | undefined;\n\n constructor(private readonly options: FormScriptingControllerOptions) {\n this.transaction = options.transaction.bind(options);\n this.transactionBudget = options.budget;\n }\n\n /** The realm belongs to its OWNER (the actions plugin, or the caller that\n * minted a detached one) — this only fences further transactions. */\n dispose(): void {\n this.disposed = true;\n }\n\n async commit(ref: FormFieldRef, proposed: FormFieldValue): Promise<FormCommitResult> {\n return this.transact(ref, proposed);\n }\n\n /** Execute one originating widget's activation action (`/A`, including `/Next`). */\n async activate(ref: FormFieldRef, action: PdfActionTree): Promise<FormCommitResult> {\n return this.transact(ref, undefined, action);\n }\n\n /** Run lazy document boot plus the `/CO` chain without a user field change.\n * The anchor field resolves INSIDE the transaction (undefined ref). */\n async recalculate(): Promise<FormCommitResult> {\n return this.transact(undefined);\n }\n\n private async transact(\n refInput: FormFieldRef | undefined,\n proposed?: FormFieldValue,\n activation?: PdfActionTree,\n ): Promise<FormCommitResult> {\n if (this.disposed) throw new Error('Form scripting controller is disposed');\n // EVERYTHING inside the realm transaction — snapshot fetch, every pass,\n // the engine commit — so the next transaction reads post-commit truth.\n return this.transaction((txn) => this.transactBody(txn, refInput, proposed, activation));\n }\n\n private async transactBody(\n txn: ScriptTransaction,\n refInput: FormFieldRef | undefined,\n proposed?: FormFieldValue,\n activation?: PdfActionTree,\n ): Promise<FormCommitResult> {\n const snapshot = await this.options.doc.forms.list();\n // Recalculate's anchor resolves HERE (first live /CO field, else the\n // first field); a zero-field document is an honest no-op.\n const ref =\n refInput ??\n snapshot.calculationOrder.find(\n (candidate): candidate is FormFieldRef =>\n candidate !== null && snapshotField(snapshot, candidate) !== undefined,\n ) ??\n snapshot.fields[0]?.ref;\n if (!ref) {\n return {\n status: 'unchanged',\n scripted: true,\n effectsResult: null,\n uiEffects: [],\n diagnostics: [],\n };\n }\n const target = snapshotField(snapshot, ref);\n if (!target) {\n return this.failed([], [], scriptError(`Form field '${refKey(ref)}' no longer exists`));\n }\n\n const original = scriptFieldsFromSnapshot(snapshot);\n const overlay: Overlay = {\n original,\n fields: cloneFields(original),\n resetKeys: new Set(),\n appearances: new Map(),\n };\n const targetInput = fieldByRef(overlay.fields, ref);\n if (!targetInput) {\n return this.failed([], [], scriptError(`Form field '${refKey(ref)}' has no script view`));\n }\n\n const hasProposedValue = proposed !== undefined;\n let proposedValue: ScriptValue = cloneValue(targetInput.value);\n if (proposed) {\n try {\n proposedValue = scriptValueFromFormValue(targetInput, proposed);\n } catch (error) {\n return this.failed(\n [],\n [],\n scriptError(error instanceof Error ? error.message : String(error)),\n );\n }\n }\n\n const uiEffects: FormUiEffect[] = [];\n const diagnostics: ScriptDiagnostic[] = [];\n const meta = this.options.document();\n // Document/identity/environment are HOST-owned now; the world carries the\n // per-field current page for `this.pageNum`.\n const pageNumber = pageNumberFor(meta, target);\n const budget = this.transactionBudget ?? DEFAULT_SCRIPT_BUDGET;\n let executionMs = 0;\n let aggregateOutputSize = 0;\n\n const consume = (\n output: ScriptOutput,\n phase: FormUiEffect['phase'],\n ): ScriptExecutionError | null => {\n aggregateOutputSize += utf8Length(JSON.stringify(output));\n // Tag every UI request with WHO asked — embedders suppress boot-phase\n // nags (Adobe's version-check alert) but show user-phase validation.\n uiEffects.push(...output.uiEffects.map((effect) => ({ ...effect, phase })));\n diagnostics.push(...output.diagnostics);\n if (aggregateOutputSize > budget.maxOutputBytes) {\n return {\n kind: 'budget',\n message: `Form script transaction output exceeded ${budget.maxOutputBytes} bytes`,\n };\n }\n return output.error ?? null;\n };\n const remainingBudget = (): ScriptBudget | null => {\n const remaining = budget.maxExecutionMs - executionMs;\n return remaining <= 0 ? null : { ...budget, maxExecutionMs: remaining };\n };\n const world = (\n fields: ScriptFieldInput[],\n event: ScriptWorldInput['event'],\n ): ScriptWorldInput => ({\n fields,\n pageNumber,\n event,\n });\n const run = async (\n source: string,\n input: ScriptWorldInput,\n ): Promise<{ output?: ScriptOutput; error?: ScriptExecutionError }> => {\n const remaining = remainingBudget();\n if (!remaining) {\n return { error: { kind: 'budget', message: 'Form script transaction timed out' } };\n }\n let output: ScriptOutput;\n try {\n const startedAt = Date.now();\n output = await txn.run(source, input, remaining);\n executionMs += Date.now() - startedAt;\n } catch (error) {\n return {\n error: scriptError(error instanceof Error ? error.message : String(error)),\n };\n }\n const error = consume(output, 'user');\n return error ? { error } : { output };\n };\n\n {\n // Boot runs ONCE per realm (host-owned latch) and can only ever\n // degrade, never brick — a failure surfaces a diagnostic and this\n // transaction continues from pristine state.\n let boot: ScriptOutput | null = null;\n try {\n boot = await txn.boot(world(overlay.fields, { kind: 'name-tree-boot' }), budget);\n } catch (error) {\n diagnostics.push({\n code: 'script-error',\n message: `Document boot script failed (continuing without it): ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n if (boot) {\n const bootError = consume(boot, 'boot');\n if (!bootError) applyEffects(overlay, boot.formEffects);\n else {\n diagnostics.push({\n code: 'script-error',\n message: `Document boot script failed (continuing without it): ${bootError.message}`,\n });\n }\n }\n }\n\n const bootEffects = canonicalEffects(overlay);\n\n if (activation) {\n let program: string;\n try {\n program = javaScriptProgramFromActionTree(activation);\n } catch (error) {\n return this.failed(\n uiEffects,\n diagnostics,\n scriptError(error instanceof Error ? error.message : String(error)),\n );\n }\n if (program) {\n const activated = await run(\n program,\n world(overlay.fields, {\n kind: 'widget-activate',\n target: ref,\n source: ref,\n value: targetInput.value,\n }),\n );\n if (activated.error) return this.failed(uiEffects, diagnostics, activated.error);\n applyEffects(overlay, activated.output!.formEffects);\n }\n }\n\n if (!activation && hasProposedValue && target.actions?.keystroke && target.family === 'text') {\n let program: string;\n try {\n program = javaScriptProgramFromActionTree(target.actions.keystroke);\n } catch (error) {\n return this.failed(\n uiEffects,\n diagnostics,\n scriptError(error instanceof Error ? error.message : String(error)),\n );\n }\n if (program) {\n // Acrobat fires per-typing keystroke events plus one final commit\n // event. This pipeline compresses typing into ONE paste-shaped\n // replacement (Acrobat's own paste contract: the whole string rides\n // `event.change`, willCommit=false) so transform/filter scripts run,\n // then fires the Acrobat-faithful willCommit pass (the full value on\n // `event.value`, empty `change`) so AF* and commit validators see\n // what Adobe's library expects.\n const oldValue = String(targetInput.value ?? '');\n const typing = await run(\n program,\n world(overlay.fields, {\n kind: 'field-keystroke',\n target: ref,\n source: ref,\n value: oldValue,\n change: String(proposedValue ?? ''),\n selStart: 0,\n selEnd: oldValue.length,\n willCommit: false,\n }),\n );\n if (typing.error && typing.error.kind !== 'exception') {\n return this.failed(uiEffects, diagnostics, typing.error);\n }\n if (typing.error) {\n // Fault ladder: an exception is not a rejection. Keep the typed\n // value, surface a diagnostic, and let the transaction continue.\n diagnostics.push({\n code: 'script-error',\n message: `Keystroke script failed (kept the typed value): ${typing.error.message}`,\n });\n } else {\n if (!typing.output!.event.rc) {\n return this.finishRejected(bootEffects, uiEffects, diagnostics);\n }\n applyEffects(overlay, typing.output!.formEffects);\n const event = typing.output!.event;\n const base = String(event.value ?? '');\n proposedValue =\n base.slice(0, event.selStart) +\n event.change +\n base.slice(Math.max(event.selStart, event.selEnd));\n }\n const commit = await run(\n program,\n world(overlay.fields, {\n kind: 'field-keystroke',\n target: ref,\n source: ref,\n value: proposedValue,\n change: '',\n selStart: 0,\n selEnd: 0,\n willCommit: true,\n }),\n );\n if (commit.error && commit.error.kind !== 'exception') {\n return this.failed(uiEffects, diagnostics, commit.error);\n }\n if (commit.error) {\n diagnostics.push({\n code: 'script-error',\n message: `Keystroke commit script failed (kept the typed value): ${commit.error.message}`,\n });\n } else {\n if (!commit.output!.event.rc) {\n return this.finishRejected(bootEffects, uiEffects, diagnostics);\n }\n applyEffects(overlay, commit.output!.formEffects);\n proposedValue = cloneValue(commit.output!.event.value);\n }\n }\n }\n\n if (!activation && hasProposedValue) {\n targetInput.value = cloneValue(proposedValue);\n overlay.resetKeys.delete(refKey(ref));\n }\n\n if (!activation && hasProposedValue && target.actions?.validate) {\n let program: string;\n try {\n program = javaScriptProgramFromActionTree(target.actions.validate);\n } catch (error) {\n return this.failed(\n uiEffects,\n diagnostics,\n scriptError(error instanceof Error ? error.message : String(error)),\n );\n }\n if (program) {\n const validation = await run(\n program,\n world(overlay.fields, {\n kind: 'field-validate',\n target: ref,\n source: ref,\n value: proposedValue,\n willCommit: true,\n }),\n );\n if (validation.error && validation.error.kind !== 'exception') {\n return this.failed(uiEffects, diagnostics, validation.error);\n }\n if (validation.error) {\n // Fault ladder: a broken validator must not reject the value.\n diagnostics.push({\n code: 'script-error',\n message: `Validate script failed (accepted the value): ${validation.error.message}`,\n });\n } else {\n if (!validation.output!.event.rc) {\n return this.finishRejected(bootEffects, uiEffects, diagnostics);\n }\n targetInput.value = cloneValue(validation.output!.event.value);\n applyEffects(overlay, validation.output!.formEffects);\n }\n }\n }\n\n const formatRefs: FormFieldRef[] = !activation && hasProposedValue ? [ref] : [];\n for (const calculationRef of activation ? [] : snapshot.calculationOrder) {\n if (!calculationRef) continue;\n const calculated = snapshotField(snapshot, calculationRef);\n const tree = calculated?.actions?.calculate;\n if (!calculated || !tree) continue;\n let program: string;\n try {\n program = javaScriptProgramFromActionTree(tree);\n } catch (error) {\n return this.failed(\n uiEffects,\n diagnostics,\n scriptError(error instanceof Error ? error.message : String(error)),\n );\n }\n const calculatedInput = fieldByRef(overlay.fields, calculationRef);\n if (program && calculatedInput) {\n const calculation = await run(\n program,\n world(overlay.fields, {\n kind: 'field-calculate',\n target: calculationRef,\n ...(hasProposedValue ? { source: ref } : {}),\n value: calculatedInput.value,\n }),\n );\n if (calculation.error && calculation.error.kind !== 'exception') {\n return this.failed(uiEffects, diagnostics, calculation.error);\n }\n if (calculation.error) {\n // Fault ladder: this field's calculation is skipped; the /CO chain continues.\n diagnostics.push({\n code: 'script-error',\n message: `Calculate script failed (field left unchanged): ${calculation.error.message}`,\n });\n } else {\n applyEffects(overlay, calculation.output!.formEffects);\n }\n }\n if (!formatRefs.some((candidate) => sameRef(candidate, calculationRef))) {\n formatRefs.push(calculationRef);\n }\n }\n\n for (const formatRef of formatRefs) {\n const field = snapshotField(snapshot, formatRef);\n const tree = field?.actions?.format;\n const overlayField = fieldByRef(overlay.fields, formatRef);\n if (!field || !tree || !overlayField) continue;\n let program: string;\n try {\n program = javaScriptProgramFromActionTree(tree);\n } catch (error) {\n return this.failed(\n uiEffects,\n diagnostics,\n scriptError(error instanceof Error ? error.message : String(error)),\n );\n }\n if (!program) continue;\n const format = await run(\n program,\n world(overlay.fields, {\n kind: 'field-format',\n target: formatRef,\n ...(hasProposedValue ? { source: ref } : {}),\n value: overlayField.value,\n }),\n );\n if (format.error && format.error.kind !== 'exception') {\n return this.failed(uiEffects, diagnostics, format.error);\n }\n if (format.error) {\n // Fault ladder: formatting is cosmetic — skip it, keep the raw value.\n diagnostics.push({\n code: 'script-error',\n message: `Format script failed (kept the raw value): ${format.error.message}`,\n });\n continue;\n }\n applyEffects(overlay, format.output!.formEffects);\n }\n\n const effects = canonicalEffects(overlay);\n if (effects.length + uiEffects.length > budget.maxEffects) {\n return this.failed(uiEffects, diagnostics, {\n kind: 'budget',\n message: `Form script transaction exceeded ${budget.maxEffects} effects`,\n });\n }\n if (effects.length === 0) {\n return { status: 'unchanged', scripted: true, effectsResult: null, uiEffects, diagnostics };\n }\n if (!this.options.doc.forms.applyEffects) {\n return this.failed(\n uiEffects,\n diagnostics,\n scriptError('This engine does not support batched form effects'),\n );\n }\n\n const effectsResult = await this.options.doc.forms.applyEffects(effects);\n const status = statusFromEffects(effectsResult);\n return {\n status,\n scripted: true,\n effectsResult,\n uiEffects,\n diagnostics,\n ...(status === 'failed'\n ? { error: scriptError('One or more native form effects failed') }\n : {}),\n };\n }\n\n private failed(\n uiEffects: FormUiEffect[],\n diagnostics: ScriptDiagnostic[],\n error: ScriptExecutionError,\n ): FormCommitResult {\n return {\n status: 'failed',\n scripted: true,\n effectsResult: null,\n uiEffects,\n diagnostics,\n error,\n };\n }\n\n private async finishRejected(\n bootEffects: FormEffect[],\n uiEffects: FormUiEffect[],\n diagnostics: ScriptDiagnostic[],\n ): Promise<FormCommitResult> {\n if (bootEffects.length === 0) {\n return {\n status: 'rejected',\n scripted: true,\n effectsResult: null,\n uiEffects,\n diagnostics,\n };\n }\n if (!this.options.doc.forms.applyEffects) {\n return this.failed(\n uiEffects,\n diagnostics,\n scriptError('Batched form effects are unavailable'),\n );\n }\n const effectsResult = await this.options.doc.forms.applyEffects(bootEffects);\n if (statusFromEffects(effectsResult) === 'failed') {\n return this.failed(uiEffects, diagnostics, scriptError('A name-tree boot effect failed'));\n }\n return {\n status: 'rejected',\n scripted: true,\n effectsResult,\n uiEffects,\n diagnostics,\n };\n }\n}\n\nexport function createFormScriptingController(\n options: FormScriptingControllerOptions,\n): FormScriptingController {\n return new FormScriptingController(options);\n}\n"],"mappings":"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"}
|
package/dist/scripting.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scripting.js","names":[],"sources":["../src/scripting.ts"],"sourcesContent":["import type {\n DocumentHandle,\n FormEffect,\n FormEffectsResult,\n FormFieldDTO,\n FormFieldRef,\n FormFieldValue,\n FormSnapshot,\n PdfActionTree,\n} from '@embedpdf/engine-core/runtime';\nimport {\n DEFAULT_SCRIPT_BUDGET,\n javaScriptProgramFromActionTree,\n scriptFieldsFromSnapshot,\n type ScriptBudget,\n type ScriptDiagnostic,\n type ScriptExecutionError,\n type ScriptFieldInput,\n type ScriptOutput,\n type ScriptTransaction,\n type ScriptUiEffect,\n type ScriptValue,\n type ScriptWorldInput,\n} from '@embedpdf/core-acrojs';\nimport type { DocumentMeta } from '@embedpdf/core';\n\nimport type { FormCommitResult, FormUiEffect } from './types';\n\ninterface Overlay {\n original: ScriptFieldInput[];\n fields: ScriptFieldInput[];\n resetKeys: Set<string>;\n appearances: Map<string, { ref: FormFieldRef; text: string }>;\n}\n\n/**\n * The controller never owns a realm. It rides a realm PORT — this document's\n * own (the actions plugin's per-document host) or a detached one minted by\n * the actions plugin for a document that is not displayed (stamp's\n * asset documents). Either way the owner disposes the realm; `dispose()`\n * here only fences further transactions.\n */\nexport interface FormScriptingControllerOptions {\n doc: DocumentHandle;\n document(): DocumentMeta | null;\n /** The realm's transaction port ({@link ScriptTransaction}). The K/V/C/F\n * pipeline runs WHOLLY inside one transaction: snapshot fetch, every\n * pass, and the engine commit — the commit-inside-the-boundary law. */\n transaction<T>(body: (txn: ScriptTransaction) => Promise<T>): Promise<T>;\n /** The transaction aggregate (output bytes, wall-clock across passes);\n * the realm owner hands over the same budget its runs enforce. */\n budget?: ScriptBudget;\n}\n\nconst refKey = (ref: FormFieldRef): string =>\n ref.kind === 'objectNumber' ? `obj:${ref.fieldObjectNumber}` : `fqn:${ref.name}`;\n\nconst sameRef = (left: FormFieldRef, right: FormFieldRef): boolean =>\n refKey(left) === refKey(right);\n\nconst cloneValue = (value: ScriptValue): ScriptValue => (Array.isArray(value) ? [...value] : value);\n\nconst sameValue = (left: ScriptValue, right: ScriptValue): boolean =>\n Array.isArray(left) && Array.isArray(right)\n ? left.length === right.length && left.every((value, index) => value === right[index])\n : left === right;\n\nfunction cloneFields(fields: ScriptFieldInput[]): ScriptFieldInput[] {\n return fields.map((field) => ({\n ...field,\n ref: { ...field.ref },\n value: cloneValue(field.value),\n defaultValue: cloneValue(field.defaultValue),\n ...(field.options ? { options: field.options.map((option) => ({ ...option })) } : {}),\n }));\n}\n\nfunction fieldByRef<T extends { ref: FormFieldRef }>(\n fields: T[],\n ref: FormFieldRef,\n): T | undefined {\n return fields.find((field) => sameRef(field.ref, ref));\n}\n\nfunction snapshotField(snapshot: FormSnapshot, ref: FormFieldRef): FormFieldDTO | undefined {\n return snapshot.fields.find((field) => sameRef(field.ref, ref));\n}\n\nfunction scriptValueFromFormValue(field: ScriptFieldInput, value: FormFieldValue): ScriptValue {\n if (field.family === 'text' && value.type === 'text') return value.value;\n if ((field.family === 'checkbox' || field.family === 'radio') && value.type === 'toggle') {\n return value.state ?? 'Off';\n }\n if (field.family === 'combobox' && value.type === 'choice') return value.values[0] ?? '';\n if (field.family === 'listbox' && value.type === 'choice') return [...value.values];\n throw new Error(`Form value type '${value.type}' does not match field family '${field.family}'`);\n}\n\nfunction formValueFromScriptValue(field: ScriptFieldInput): FormFieldValue | null {\n switch (field.family) {\n case 'text':\n return { type: 'text', value: String(field.value ?? '') };\n case 'checkbox':\n case 'radio':\n return {\n type: 'toggle',\n state:\n field.value === null || field.value === undefined || String(field.value) === 'Off'\n ? null\n : String(field.value),\n };\n case 'combobox':\n return {\n type: 'choice',\n values: Array.isArray(field.value) ? field.value.slice(0, 1) : [String(field.value ?? '')],\n };\n case 'listbox':\n return {\n type: 'choice',\n values: Array.isArray(field.value) ? [...field.value] : [String(field.value ?? '')],\n };\n default:\n return null;\n }\n}\n\nfunction applyEffects(overlay: Overlay, effects: FormEffect[]): void {\n for (const effect of effects) {\n if (effect.kind === 'reset') {\n for (const ref of effect.refs) {\n const field = fieldByRef(overlay.fields, ref);\n if (!field) continue;\n field.value = cloneValue(field.defaultValue);\n overlay.resetKeys.add(refKey(ref));\n }\n continue;\n }\n\n const field = fieldByRef(overlay.fields, effect.ref);\n if (!field) continue;\n const key = refKey(effect.ref);\n if (effect.kind === 'setValue') {\n field.value = scriptValueFromFormValue(field, effect.value);\n overlay.resetKeys.delete(key);\n } else if (effect.kind === 'setDisplay') {\n field.display = effect.display;\n } else {\n overlay.appearances.set(key, { ref: effect.ref, text: effect.text });\n }\n }\n}\n\nfunction canonicalEffects(overlay: Overlay): FormEffect[] {\n const effects: FormEffect[] = [];\n const resets: FormFieldRef[] = [];\n for (const field of overlay.fields) {\n const original = fieldByRef(overlay.original, field.ref);\n if (!original) continue;\n if (!sameValue(original.value, field.value)) {\n const key = refKey(field.ref);\n if (overlay.resetKeys.has(key) && sameValue(field.value, field.defaultValue)) {\n resets.push(field.ref);\n } else {\n const value = formValueFromScriptValue(field);\n if (value) effects.push({ kind: 'setValue', ref: field.ref, value });\n }\n }\n if (original.display !== field.display) {\n effects.push({ kind: 'setDisplay', ref: field.ref, display: field.display });\n }\n }\n if (resets.length > 0) effects.unshift({ kind: 'reset', refs: resets });\n effects.push(\n ...Array.from(overlay.appearances.values(), ({ ref, text }) => ({\n kind: 'setAppearanceText' as const,\n ref,\n text,\n })),\n );\n return effects;\n}\n\nfunction scriptError(message: string): ScriptExecutionError {\n return { kind: 'invalid-output', message };\n}\n\nfunction utf8Length(value: string): number {\n let length = 0;\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code < 0x80) length += 1;\n else if (code < 0x800) length += 2;\n else if (code >= 0xd800 && code <= 0xdbff && index + 1 < value.length) {\n length += 4;\n index += 1;\n } else length += 3;\n }\n return length;\n}\n\nfunction pageNumberFor(meta: DocumentMeta | null, field: FormFieldDTO): number {\n const pon = field.widgets.find((widget) => widget.pageObjectNumber > 0)?.pageObjectNumber;\n if (!meta || pon === undefined) return 0;\n const index = meta.pages.findIndex((page) => page.pageObjectNumber === pon);\n return Math.max(0, index);\n}\n\nfunction statusFromEffects(result: FormEffectsResult): FormCommitResult['status'] {\n if (result.results.some(({ status }) => status === 'failed' || status === 'skipped')) {\n return 'failed';\n }\n if (result.results.some(({ status }) => status === 'rejected')) return 'failed';\n return result.results.some(({ status }) => status === 'applied') ? 'applied' : 'unchanged';\n}\n\nexport class FormScriptingController {\n private disposed = false;\n private readonly transaction: <T>(body: (txn: ScriptTransaction) => Promise<T>) => Promise<T>;\n private readonly transactionBudget: ScriptBudget | undefined;\n\n constructor(private readonly options: FormScriptingControllerOptions) {\n this.transaction = options.transaction.bind(options);\n this.transactionBudget = options.budget;\n }\n\n /** The realm belongs to its OWNER (the actions plugin, or the caller that\n * minted a detached one) — this only fences further transactions. */\n dispose(): void {\n this.disposed = true;\n }\n\n async commit(ref: FormFieldRef, proposed: FormFieldValue): Promise<FormCommitResult> {\n return this.transact(ref, proposed);\n }\n\n /** Execute one originating widget's activation action (`/A`, including `/Next`). */\n async activate(ref: FormFieldRef, action: PdfActionTree): Promise<FormCommitResult> {\n return this.transact(ref, undefined, action);\n }\n\n /** Run lazy document boot plus the `/CO` chain without a user field change.\n * The anchor field resolves INSIDE the transaction (undefined ref). */\n async recalculate(): Promise<FormCommitResult> {\n return this.transact(undefined);\n }\n\n private async transact(\n refInput: FormFieldRef | undefined,\n proposed?: FormFieldValue,\n activation?: PdfActionTree,\n ): Promise<FormCommitResult> {\n if (this.disposed) throw new Error('Form scripting controller is disposed');\n // EVERYTHING inside the realm transaction — snapshot fetch, every pass,\n // the engine commit — so the next transaction reads post-commit truth.\n return this.transaction((txn) => this.transactBody(txn, refInput, proposed, activation));\n }\n\n private async transactBody(\n txn: ScriptTransaction,\n refInput: FormFieldRef | undefined,\n proposed?: FormFieldValue,\n activation?: PdfActionTree,\n ): Promise<FormCommitResult> {\n const snapshot = await this.options.doc.forms.list();\n // Recalculate's anchor resolves HERE (first live /CO field, else the\n // first field); a zero-field document is an honest no-op.\n const ref =\n refInput ??\n snapshot.calculationOrder.find(\n (candidate): candidate is FormFieldRef =>\n candidate !== null && snapshotField(snapshot, candidate) !== undefined,\n ) ??\n snapshot.fields[0]?.ref;\n if (!ref) {\n return {\n status: 'unchanged',\n scripted: true,\n effectsResult: null,\n uiEffects: [],\n diagnostics: [],\n };\n }\n const target = snapshotField(snapshot, ref);\n if (!target) {\n return this.failed([], [], scriptError(`Form field '${refKey(ref)}' no longer exists`));\n }\n\n const original = scriptFieldsFromSnapshot(snapshot);\n const overlay: Overlay = {\n original,\n fields: cloneFields(original),\n resetKeys: new Set(),\n appearances: new Map(),\n };\n const targetInput = fieldByRef(overlay.fields, ref);\n if (!targetInput) {\n return this.failed([], [], scriptError(`Form field '${refKey(ref)}' has no script view`));\n }\n\n const hasProposedValue = proposed !== undefined;\n let proposedValue: ScriptValue = cloneValue(targetInput.value);\n if (proposed) {\n try {\n proposedValue = scriptValueFromFormValue(targetInput, proposed);\n } catch (error) {\n return this.failed(\n [],\n [],\n scriptError(error instanceof Error ? error.message : String(error)),\n );\n }\n }\n\n const uiEffects: FormUiEffect[] = [];\n const diagnostics: ScriptDiagnostic[] = [];\n const meta = this.options.document();\n // Document/identity/environment are HOST-owned now; the world carries the\n // per-field current page for `this.pageNum`.\n const pageNumber = pageNumberFor(meta, target);\n const budget = this.transactionBudget ?? DEFAULT_SCRIPT_BUDGET;\n let executionMs = 0;\n let aggregateOutputSize = 0;\n\n const consume = (\n output: ScriptOutput,\n phase: FormUiEffect['phase'],\n ): ScriptExecutionError | null => {\n aggregateOutputSize += utf8Length(JSON.stringify(output));\n // Tag every UI request with WHO asked — embedders suppress boot-phase\n // nags (Adobe's version-check alert) but show user-phase validation.\n uiEffects.push(...output.uiEffects.map((effect) => ({ ...effect, phase })));\n diagnostics.push(...output.diagnostics);\n if (aggregateOutputSize > budget.maxOutputBytes) {\n return {\n kind: 'budget',\n message: `Form script transaction output exceeded ${budget.maxOutputBytes} bytes`,\n };\n }\n return output.error ?? null;\n };\n const remainingBudget = (): ScriptBudget | null => {\n const remaining = budget.maxExecutionMs - executionMs;\n return remaining <= 0 ? null : { ...budget, maxExecutionMs: remaining };\n };\n const world = (\n fields: ScriptFieldInput[],\n event: ScriptWorldInput['event'],\n ): ScriptWorldInput => ({\n fields,\n pageNumber,\n event,\n });\n const run = async (\n source: string,\n input: ScriptWorldInput,\n ): Promise<{ output?: ScriptOutput; error?: ScriptExecutionError }> => {\n const remaining = remainingBudget();\n if (!remaining) {\n return { error: { kind: 'budget', message: 'Form script transaction timed out' } };\n }\n let output: ScriptOutput;\n try {\n const startedAt = Date.now();\n output = await txn.run(source, input, remaining);\n executionMs += Date.now() - startedAt;\n } catch (error) {\n return {\n error: scriptError(error instanceof Error ? error.message : String(error)),\n };\n }\n const error = consume(output, 'user');\n return error ? { error } : { output };\n };\n\n {\n // Boot runs ONCE per realm (host-owned latch) and can only ever\n // degrade, never brick — a failure surfaces a diagnostic and this\n // transaction continues from pristine state.\n let boot: ScriptOutput | null = null;\n try {\n boot = await txn.boot(world(overlay.fields, { kind: 'name-tree-boot' }), budget);\n } catch (error) {\n diagnostics.push({\n code: 'script-error',\n message: `Document boot script failed (continuing without it): ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n if (boot) {\n const bootError = consume(boot, 'boot');\n if (!bootError) applyEffects(overlay, boot.formEffects);\n else {\n diagnostics.push({\n code: 'script-error',\n message: `Document boot script failed (continuing without it): ${bootError.message}`,\n });\n }\n }\n }\n\n const bootEffects = canonicalEffects(overlay);\n\n if (activation) {\n let program: string;\n try {\n program = javaScriptProgramFromActionTree(activation);\n } catch (error) {\n return this.failed(\n uiEffects,\n diagnostics,\n scriptError(error instanceof Error ? error.message : String(error)),\n );\n }\n if (program) {\n const activated = await run(\n program,\n world(overlay.fields, {\n kind: 'widget-activate',\n target: ref,\n source: ref,\n value: targetInput.value,\n }),\n );\n if (activated.error) return this.failed(uiEffects, diagnostics, activated.error);\n applyEffects(overlay, activated.output!.formEffects);\n }\n }\n\n if (!activation && hasProposedValue && target.actions?.keystroke && target.family === 'text') {\n let program: string;\n try {\n program = javaScriptProgramFromActionTree(target.actions.keystroke);\n } catch (error) {\n return this.failed(\n uiEffects,\n diagnostics,\n scriptError(error instanceof Error ? error.message : String(error)),\n );\n }\n if (program) {\n // Acrobat fires per-typing keystroke events plus one final commit\n // event. This pipeline compresses typing into ONE paste-shaped\n // replacement (Acrobat's own paste contract: the whole string rides\n // `event.change`, willCommit=false) so transform/filter scripts run,\n // then fires the Acrobat-faithful willCommit pass (the full value on\n // `event.value`, empty `change`) so AF* and commit validators see\n // what Adobe's library expects.\n const oldValue = String(targetInput.value ?? '');\n const typing = await run(\n program,\n world(overlay.fields, {\n kind: 'field-keystroke',\n target: ref,\n source: ref,\n value: oldValue,\n change: String(proposedValue ?? ''),\n selStart: 0,\n selEnd: oldValue.length,\n willCommit: false,\n }),\n );\n if (typing.error && typing.error.kind !== 'exception') {\n return this.failed(uiEffects, diagnostics, typing.error);\n }\n if (typing.error) {\n // Fault ladder: an exception is not a rejection. Keep the typed\n // value, surface a diagnostic, and let the transaction continue.\n diagnostics.push({\n code: 'script-error',\n message: `Keystroke script failed (kept the typed value): ${typing.error.message}`,\n });\n } else {\n if (!typing.output!.event.rc) {\n return this.finishRejected(bootEffects, uiEffects, diagnostics);\n }\n applyEffects(overlay, typing.output!.formEffects);\n const event = typing.output!.event;\n const base = String(event.value ?? '');\n proposedValue =\n base.slice(0, event.selStart) +\n event.change +\n base.slice(Math.max(event.selStart, event.selEnd));\n }\n const commit = await run(\n program,\n world(overlay.fields, {\n kind: 'field-keystroke',\n target: ref,\n source: ref,\n value: proposedValue,\n change: '',\n selStart: 0,\n selEnd: 0,\n willCommit: true,\n }),\n );\n if (commit.error && commit.error.kind !== 'exception') {\n return this.failed(uiEffects, diagnostics, commit.error);\n }\n if (commit.error) {\n diagnostics.push({\n code: 'script-error',\n message: `Keystroke commit script failed (kept the typed value): ${commit.error.message}`,\n });\n } else {\n if (!commit.output!.event.rc) {\n return this.finishRejected(bootEffects, uiEffects, diagnostics);\n }\n applyEffects(overlay, commit.output!.formEffects);\n proposedValue = cloneValue(commit.output!.event.value);\n }\n }\n }\n\n if (!activation && hasProposedValue) {\n targetInput.value = cloneValue(proposedValue);\n overlay.resetKeys.delete(refKey(ref));\n }\n\n if (!activation && hasProposedValue && target.actions?.validate) {\n let program: string;\n try {\n program = javaScriptProgramFromActionTree(target.actions.validate);\n } catch (error) {\n return this.failed(\n uiEffects,\n diagnostics,\n scriptError(error instanceof Error ? error.message : String(error)),\n );\n }\n if (program) {\n const validation = await run(\n program,\n world(overlay.fields, {\n kind: 'field-validate',\n target: ref,\n source: ref,\n value: proposedValue,\n willCommit: true,\n }),\n );\n if (validation.error && validation.error.kind !== 'exception') {\n return this.failed(uiEffects, diagnostics, validation.error);\n }\n if (validation.error) {\n // Fault ladder: a broken validator must not reject the value.\n diagnostics.push({\n code: 'script-error',\n message: `Validate script failed (accepted the value): ${validation.error.message}`,\n });\n } else {\n if (!validation.output!.event.rc) {\n return this.finishRejected(bootEffects, uiEffects, diagnostics);\n }\n targetInput.value = cloneValue(validation.output!.event.value);\n applyEffects(overlay, validation.output!.formEffects);\n }\n }\n }\n\n const formatRefs: FormFieldRef[] = !activation && hasProposedValue ? [ref] : [];\n for (const calculationRef of activation ? [] : snapshot.calculationOrder) {\n if (!calculationRef) continue;\n const calculated = snapshotField(snapshot, calculationRef);\n const tree = calculated?.actions?.calculate;\n if (!calculated || !tree) continue;\n let program: string;\n try {\n program = javaScriptProgramFromActionTree(tree);\n } catch (error) {\n return this.failed(\n uiEffects,\n diagnostics,\n scriptError(error instanceof Error ? error.message : String(error)),\n );\n }\n const calculatedInput = fieldByRef(overlay.fields, calculationRef);\n if (program && calculatedInput) {\n const calculation = await run(\n program,\n world(overlay.fields, {\n kind: 'field-calculate',\n target: calculationRef,\n ...(hasProposedValue ? { source: ref } : {}),\n value: calculatedInput.value,\n }),\n );\n if (calculation.error && calculation.error.kind !== 'exception') {\n return this.failed(uiEffects, diagnostics, calculation.error);\n }\n if (calculation.error) {\n // Fault ladder: this field's calculation is skipped; the /CO chain continues.\n diagnostics.push({\n code: 'script-error',\n message: `Calculate script failed (field left unchanged): ${calculation.error.message}`,\n });\n } else {\n applyEffects(overlay, calculation.output!.formEffects);\n }\n }\n if (!formatRefs.some((candidate) => sameRef(candidate, calculationRef))) {\n formatRefs.push(calculationRef);\n }\n }\n\n for (const formatRef of formatRefs) {\n const field = snapshotField(snapshot, formatRef);\n const tree = field?.actions?.format;\n const overlayField = fieldByRef(overlay.fields, formatRef);\n if (!field || !tree || !overlayField) continue;\n let program: string;\n try {\n program = javaScriptProgramFromActionTree(tree);\n } catch (error) {\n return this.failed(\n uiEffects,\n diagnostics,\n scriptError(error instanceof Error ? error.message : String(error)),\n );\n }\n if (!program) continue;\n const format = await run(\n program,\n world(overlay.fields, {\n kind: 'field-format',\n target: formatRef,\n ...(hasProposedValue ? { source: ref } : {}),\n value: overlayField.value,\n }),\n );\n if (format.error && format.error.kind !== 'exception') {\n return this.failed(uiEffects, diagnostics, format.error);\n }\n if (format.error) {\n // Fault ladder: formatting is cosmetic — skip it, keep the raw value.\n diagnostics.push({\n code: 'script-error',\n message: `Format script failed (kept the raw value): ${format.error.message}`,\n });\n continue;\n }\n applyEffects(overlay, format.output!.formEffects);\n }\n\n const effects = canonicalEffects(overlay);\n if (effects.length + uiEffects.length > budget.maxEffects) {\n return this.failed(uiEffects, diagnostics, {\n kind: 'budget',\n message: `Form script transaction exceeded ${budget.maxEffects} effects`,\n });\n }\n if (effects.length === 0) {\n return { status: 'unchanged', scripted: true, effectsResult: null, uiEffects, diagnostics };\n }\n if (!this.options.doc.forms.applyEffects) {\n return this.failed(\n uiEffects,\n diagnostics,\n scriptError('This engine does not support batched form effects'),\n );\n }\n\n const effectsResult = await this.options.doc.forms.applyEffects(effects);\n const status = statusFromEffects(effectsResult);\n return {\n status,\n scripted: true,\n effectsResult,\n uiEffects,\n diagnostics,\n ...(status === 'failed'\n ? { error: scriptError('One or more native form effects failed') }\n : {}),\n };\n }\n\n private failed(\n uiEffects: FormUiEffect[],\n diagnostics: ScriptDiagnostic[],\n error: ScriptExecutionError,\n ): FormCommitResult {\n return {\n status: 'failed',\n scripted: true,\n effectsResult: null,\n uiEffects,\n diagnostics,\n error,\n };\n }\n\n private async finishRejected(\n bootEffects: FormEffect[],\n uiEffects: FormUiEffect[],\n diagnostics: ScriptDiagnostic[],\n ): Promise<FormCommitResult> {\n if (bootEffects.length === 0) {\n return {\n status: 'rejected',\n scripted: true,\n effectsResult: null,\n uiEffects,\n diagnostics,\n };\n }\n if (!this.options.doc.forms.applyEffects) {\n return this.failed(\n uiEffects,\n diagnostics,\n scriptError('Batched form effects are unavailable'),\n );\n }\n const effectsResult = await this.options.doc.forms.applyEffects(bootEffects);\n if (statusFromEffects(effectsResult) === 'failed') {\n return this.failed(uiEffects, diagnostics, scriptError('A name-tree boot effect failed'));\n }\n return {\n status: 'rejected',\n scripted: true,\n effectsResult,\n uiEffects,\n diagnostics,\n };\n }\n}\n\nexport function createFormScriptingController(\n options: FormScriptingControllerOptions,\n): FormScriptingController {\n return new FormScriptingController(options);\n}\n"],"mappings":"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"}
|
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
import { AnnotationRef, FormDataExport, FormDataFormat, FormEffect, FormEffectsResult, FormFieldDTO, FormFieldFamily, FormFieldOption, FormFieldPatch, FormFieldRef, FormFieldValue, FormImportResult, FormRepairOptions, FormRepairResult, FormSetValueResult, FormSnapshot, PdfActionTargetRef, WidgetAppearance } from "@embedpdf/engine-core/runtime";
|
|
2
|
-
import { ActionContext, ActionDiagnostic, ActionOrigin, ActionSubmitRequest, ActionTriggerResult, PdfAnnotationEventKind, SubmitIntent } from "@embedpdf/plugin-actions/contract";
|
|
3
|
-
import { ScriptDiagnostic, ScriptExecutionError, ScriptUiEffect } from "@embedpdf/core-acrojs";
|
|
4
|
-
import { AnnotationPropsPatch, ClickCreate } from "@embedpdf/plugin-annotation/contract";
|
|
5
|
-
//#region src/core/model.d.ts
|
|
6
|
-
/** A content-space box (top-left origin, y-down, PDF points). */
|
|
7
|
-
interface Box {
|
|
8
|
-
x: number;
|
|
9
|
-
y: number;
|
|
10
|
-
width: number;
|
|
11
|
-
height: number;
|
|
12
|
-
}
|
|
13
|
-
/** Stable client key for a field: object number when durable, else FQN. */
|
|
14
|
-
type FieldKey = string;
|
|
15
|
-
declare const fieldKeyOf: (field: {
|
|
16
|
-
fieldObjectNumber: number;
|
|
17
|
-
name: string;
|
|
18
|
-
}) => FieldKey;
|
|
19
|
-
interface Model {
|
|
20
|
-
/** Engine truth; replaced wholesale on refresh, patched on write-backs. */
|
|
21
|
-
snapshot: FormSnapshot | null;
|
|
22
|
-
/** fieldKey → index into snapshot.fields. */
|
|
23
|
-
byKey: Record<FieldKey, number>;
|
|
24
|
-
/** annotObjectNumber → index into snapshot.fields (widget → field join). */
|
|
25
|
-
byWidget: Record<number, number>;
|
|
26
|
-
/** Fields with an in-flight engine write (disables their controls). */
|
|
27
|
-
writing: Record<FieldKey, true>;
|
|
28
|
-
/**
|
|
29
|
-
* Widget geometry per page: annotObjectNumber → content-space box. Fed by
|
|
30
|
-
* the shell from the WIDGET plane (one annotations read per page); value
|
|
31
|
-
* writes never move widgets, so this survives snapshot refreshes and is
|
|
32
|
-
* only cleared on structural form events.
|
|
33
|
-
*/
|
|
34
|
-
geom: Record<number, Record<number, Box> | undefined>;
|
|
35
|
-
/** Bumped on every change — cheap equality for memoized projections. */
|
|
36
|
-
seq: number;
|
|
37
|
-
}
|
|
38
|
-
/** A widget hit: the annotation under the point and the field it belongs to. */
|
|
39
|
-
interface WidgetHit {
|
|
40
|
-
annotObjectNumber: number;
|
|
41
|
-
field: FormFieldDTO;
|
|
42
|
-
/** The widget's content-space box. */
|
|
43
|
-
box: Box;
|
|
44
|
-
}
|
|
45
|
-
//#endregion
|
|
46
|
-
//#region src/core/fill-items.d.ts
|
|
47
|
-
interface FillItemBase {
|
|
48
|
-
key: FieldKey;
|
|
49
|
-
/** Widget identity — joins to the annotation plane. */
|
|
50
|
-
annotObjectNumber: number;
|
|
51
|
-
box: Box;
|
|
52
|
-
/** Read-only field or write in flight: render, don't accept input. */
|
|
53
|
-
disabled: boolean;
|
|
54
|
-
/** Accessible name: /TU when present, else the fully qualified name. */
|
|
55
|
-
label: string;
|
|
56
|
-
}
|
|
57
|
-
type FillItem = FillItemBase & ({
|
|
58
|
-
control: 'text';
|
|
59
|
-
value: string;
|
|
60
|
-
multiline: boolean;
|
|
61
|
-
password: boolean;
|
|
62
|
-
maxLength: number | null;
|
|
63
|
-
comb: boolean;
|
|
64
|
-
} | {
|
|
65
|
-
control: 'toggle';
|
|
66
|
-
kind: 'checkbox' | 'radio';
|
|
67
|
-
checked: boolean;
|
|
68
|
-
onState: string;
|
|
69
|
-
} | {
|
|
70
|
-
control: 'choice';
|
|
71
|
-
kind: 'combo' | 'list';
|
|
72
|
-
edit: boolean;
|
|
73
|
-
multi: boolean;
|
|
74
|
-
options: FormFieldOption[];
|
|
75
|
-
selected: string[];
|
|
76
|
-
} | {
|
|
77
|
-
control: 'button';
|
|
78
|
-
} |
|
|
79
|
-
/**
|
|
80
|
-
* A signature field's widget. `signed` = it carries a `/V` (a signature
|
|
81
|
-
* dictionary): the field is final and its appearance sealed — the
|
|
82
|
-
* control inspects rather than signs. Unsigned: "sign here" — the
|
|
83
|
-
* signing act itself belongs to the signature plugin.
|
|
84
|
-
*/
|
|
85
|
-
{
|
|
86
|
-
control: 'signature';
|
|
87
|
-
signed: boolean;
|
|
88
|
-
});
|
|
89
|
-
//#endregion
|
|
90
|
-
//#region src/tools.d.ts
|
|
91
|
-
/** The families the palette can author (push buttons are not authorable). */
|
|
92
|
-
type AuthorableFormFamily = Exclude<FormFieldFamily, 'pushbutton' | 'unknown'>;
|
|
93
|
-
interface FormToolDef {
|
|
94
|
-
id: string;
|
|
95
|
-
/** The field family `placeField` commits (the FORM plane's vocabulary). */
|
|
96
|
-
family: AuthorableFormFamily;
|
|
97
|
-
/** The client kind the ANNOTATION registry routes on (props panel).
|
|
98
|
-
* Not a PDF subtype — every widget is PDF `widget`; this is the view. */
|
|
99
|
-
visualKind: 'widget-text' | 'widget-choice' | 'widget-toggle' | 'widget-box';
|
|
100
|
-
/** What a bare click places (box policies only — fields are boxes). */
|
|
101
|
-
clickCreate: Extract<ClickCreate, {
|
|
102
|
-
width: number;
|
|
103
|
-
}>;
|
|
104
|
-
/** Seed drawing defaults: a placed field is VISIBLE (white box, gray
|
|
105
|
-
* border) and restylable per tool through the shared style panel. */
|
|
106
|
-
defaults: AnnotationPropsPatch;
|
|
107
|
-
cursor: string;
|
|
108
|
-
}
|
|
109
|
-
declare const FORM_TOOLS: readonly FormToolDef[];
|
|
110
|
-
declare const FORM_TOOL_BY_ID: ReadonlyMap<string, FormToolDef>;
|
|
111
|
-
//#endregion
|
|
112
|
-
//#region src/types.d.ts
|
|
113
|
-
interface FormState {
|
|
114
|
-
model: Model;
|
|
115
|
-
}
|
|
116
|
-
/** The scripting switch moved to `actionsPlugin({ javascript })` (D8). */
|
|
117
|
-
interface FormPluginOptions {}
|
|
118
|
-
type FormCommitStatus = 'applied' | 'unchanged' | 'rejected' | 'failed';
|
|
119
|
-
interface FormCommitResult {
|
|
120
|
-
status: FormCommitStatus;
|
|
121
|
-
scripted: boolean;
|
|
122
|
-
effectsResult: FormEffectsResult | null;
|
|
123
|
-
uiEffects: FormUiEffect[];
|
|
124
|
-
diagnostics: ScriptDiagnostic[];
|
|
125
|
-
error?: ScriptExecutionError;
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* One DOM-free UI request produced by the curated Acrobat scripting surface.
|
|
129
|
-
* `phase` says WHO asked: `'boot'` = a document-open script (Adobe's
|
|
130
|
-
* version-check boilerplate lives here — embedders typically suppress these
|
|
131
|
-
* nags), `'user'` = a script triggered by the user's own interaction (a
|
|
132
|
-
* validation alert — show it).
|
|
133
|
-
*/
|
|
134
|
-
type FormUiEffect = ScriptUiEffect & {
|
|
135
|
-
/** WHO asked, script-model axis: `'boot'` = a name-tree/document-open boot
|
|
136
|
-
* script, `'user'` = a runtime script. */
|
|
137
|
-
phase: 'boot' | 'user';
|
|
138
|
-
/**
|
|
139
|
-
* The dispatch-origin axis (present when the script ran inside an action
|
|
140
|
-
* dispatch): a lifecycle `/OpenAction` script is NOT a name-tree boot
|
|
141
|
-
* script — the two axes are deliberately separate. Providers use this for
|
|
142
|
-
* the default visibility matrix (suppress lifecycle alerts, block
|
|
143
|
-
* non-user print); embedder handlers receive it and may decide otherwise.
|
|
144
|
-
*/
|
|
145
|
-
origin?: ActionOrigin;
|
|
146
|
-
};
|
|
147
|
-
/** Input for {@link FormCapability.placeField}. */
|
|
148
|
-
interface PlaceFieldInput {
|
|
149
|
-
family: AuthorableFormFamily;
|
|
150
|
-
pageObjectNumber: number;
|
|
151
|
-
/** Content-space LOGICAL field box (no visual padding semantics). */
|
|
152
|
-
box: Box;
|
|
153
|
-
/** Widget styling in the engine vocabulary (`WidgetAppearance`). Convert a
|
|
154
|
-
* tool's flat CSS defaults with `widgetAppearanceFromProps` from
|
|
155
|
-
* `@embedpdf/plugin-annotation`. Omitted → the engine's bare defaults. */
|
|
156
|
-
appearance?: WidgetAppearance;
|
|
157
|
-
}
|
|
158
|
-
/** What {@link FormCapability.placeField} created. */
|
|
159
|
-
interface PlacedField {
|
|
160
|
-
field: FormFieldDTO;
|
|
161
|
-
/** The widget placed on the requested page (join key to the annotation
|
|
162
|
-
* plane for auto-selection), or null when the engine reported none. */
|
|
163
|
-
widget: FormFieldDTO['widgets'][number] | null;
|
|
164
|
-
}
|
|
165
|
-
type FormAction = {
|
|
166
|
-
type: 'SET_MODEL';
|
|
167
|
-
model: Model;
|
|
168
|
-
};
|
|
169
|
-
/**
|
|
170
|
-
* The form plugin's public capability: the FIELD plane. Widgets stay
|
|
171
|
-
* annotations (geometry/appearance live there); this surface owns values,
|
|
172
|
-
* interchange, and the fill-mode projection.
|
|
173
|
-
*/
|
|
174
|
-
interface FormCapability {
|
|
175
|
-
/** The current reconciled form state (null until the first load lands). */
|
|
176
|
-
snapshot(): FormSnapshot | null;
|
|
177
|
-
/** Re-read the form from the engine (imports/repair/remote bursts). */
|
|
178
|
-
refresh(): Promise<void>;
|
|
179
|
-
/** Fill controls for one page — content-space, framework-agnostic. */
|
|
180
|
-
fillItems(pageObjectNumber: number): FillItem[];
|
|
181
|
-
/**
|
|
182
|
-
* The fill control for ONE widget, by annotation object number — the join
|
|
183
|
-
* the annotation-plane render layer uses (its RenderItem carries the live
|
|
184
|
-
* box, so this item's `box` is advisory). Reference-stable per model change.
|
|
185
|
-
* Null until the snapshot lands, or for families with no fill control.
|
|
186
|
-
*/
|
|
187
|
-
fillItem(annotObjectNumber: number): FillItem | null;
|
|
188
|
-
/** Make sure a page's widget geometry is loaded (idempotent, lazy). */
|
|
189
|
-
ensureGeom(pageObjectNumber: number): void;
|
|
190
|
-
field(key: FieldKey): FormFieldDTO | null;
|
|
191
|
-
fieldForWidget(annotObjectNumber: number): FormFieldDTO | null;
|
|
192
|
-
/**
|
|
193
|
-
* The widget under a content-space point on a page (any family), with
|
|
194
|
-
* its field — the hit test a sibling plugin runs on a pointer sample
|
|
195
|
-
* before deciding what a click means (a mark dropped over a signature
|
|
196
|
-
* field). The model's own geometry answers when it is loaded; until then
|
|
197
|
-
* the annotation plane's live boxes do, so the first click on a page
|
|
198
|
-
* already resolves. The smallest containing widget wins.
|
|
199
|
-
*/
|
|
200
|
-
widgetAt(pageObjectNumber: number, point: {
|
|
201
|
-
x: number;
|
|
202
|
-
y: number;
|
|
203
|
-
}): WidgetHit | null;
|
|
204
|
-
/** Commit a text value (call on blur/Enter — keystrokes stay local). */
|
|
205
|
-
setText(key: FieldKey, value: string): Promise<void>;
|
|
206
|
-
/** Toggle a checkbox/radio widget by its on-state; null clears the group. */
|
|
207
|
-
toggle(key: FieldKey, onState: string | null): Promise<void>;
|
|
208
|
-
/** Select choice options by export value. */
|
|
209
|
-
choose(key: FieldKey, values: string[]): Promise<void>;
|
|
210
|
-
/** Commit one originating-client value transaction, including K/V/C/F scripts when enabled. */
|
|
211
|
-
commitValue(ref: FormFieldRef, value: FormFieldValue): Promise<FormCommitResult>;
|
|
212
|
-
/**
|
|
213
|
-
* Execute one widget's `/A` activation. With the actions plugin installed
|
|
214
|
-
* the FULL tree is delegated to its dispatcher (Hide/ResetForm buttons work
|
|
215
|
-
* even with scripting off) — `kind: 'dispatched'`; without it, today's
|
|
216
|
-
* scripting-transaction path runs — `kind: 'form'`.
|
|
217
|
-
*/
|
|
218
|
-
activateWidget(key: FieldKey, annotationRef: AnnotationRef): Promise<WidgetActivationResult>;
|
|
219
|
-
/**
|
|
220
|
-
* Report one widget DOM event (pointer enter/leave, down/up, focus/blur).
|
|
221
|
-
* With the actions plugin present the matching `/AA` tree dispatches
|
|
222
|
-
* (hover rides the shared coalescing pump; `/A` shadows `/AA U` per ISO
|
|
223
|
-
* Table 197); without it — or without a tree — this is a cheap no-op.
|
|
224
|
-
* Fire-and-forget by design: results surface via the actions events.
|
|
225
|
-
*/
|
|
226
|
-
notifyWidgetEvent(key: FieldKey, ref: AnnotationRef, event: PdfAnnotationEventKind): void;
|
|
227
|
-
/** Restore a field to its /DV default. */
|
|
228
|
-
reset(key: FieldKey): Promise<void>;
|
|
229
|
-
/** Raw engine passthrough for anything the sugar above doesn't cover. */
|
|
230
|
-
setValue(ref: FormFieldRef, value: FormFieldValue): Promise<FormSetValueResult>;
|
|
231
|
-
exportData(format?: FormDataFormat): Promise<FormDataExport>;
|
|
232
|
-
importData(data: Uint8Array | ArrayBuffer, format?: FormDataFormat): Promise<FormImportResult>;
|
|
233
|
-
repair(options?: FormRepairOptions): Promise<FormRepairResult>;
|
|
234
|
-
/**
|
|
235
|
-
* Create a field of `family` with one styled widget at a content-space box
|
|
236
|
-
* — the palette tools' commit, and the programmatic authoring entry (works
|
|
237
|
-
* with NO annotation plugin: a pure `doc.forms` call). The box is clamped
|
|
238
|
-
* to the page; sizing policy (click default vs drag rect) is the caller's.
|
|
239
|
-
* The field gets a deterministic auto-name (`text_1`, …; rename in the
|
|
240
|
-
* field panel). Resolves AFTER the annotation plane (when present) has
|
|
241
|
-
* re-read the page, so the returned widget is immediately selectable.
|
|
242
|
-
*/
|
|
243
|
-
placeField(input: PlaceFieldInput): Promise<PlacedField>;
|
|
244
|
-
/** The page's content box (`{0,0,w,h}`) — page-bound placement math. */
|
|
245
|
-
pageBox(pageObjectNumber: number): Box | null;
|
|
246
|
-
/** Field-plane properties: name, required, options, default value. */
|
|
247
|
-
updateField(key: FieldKey, patch: FormFieldPatch): Promise<void>;
|
|
248
|
-
/** Delete the field and every widget of it (cascades on the page). */
|
|
249
|
-
deleteField(key: FieldKey): Promise<void>;
|
|
250
|
-
/** Unlink one widget: it stays as an inert annotation, the field survives. */
|
|
251
|
-
detachWidget(key: FieldKey, annotObjectNumber: number): Promise<void>;
|
|
252
|
-
/**
|
|
253
|
-
* The twins (permissions.md): would the family's verbs succeed now for
|
|
254
|
-
* this session? `canRead` — the form model hydrates at all (false = the
|
|
255
|
-
* hydration gate left it empty by right); `canFill` — value writes
|
|
256
|
-
* (`setText`/`toggle`/`choose`/`reset`; also fused into every
|
|
257
|
-
* `FillItem.disabled`); `canDesign` — the field-design family
|
|
258
|
-
* (`placeField`/`updateField`/`deleteField`/`detachWidget`).
|
|
259
|
-
*/
|
|
260
|
-
canRead(): boolean;
|
|
261
|
-
canFill(): boolean;
|
|
262
|
-
canDesign(): boolean;
|
|
263
|
-
}
|
|
264
|
-
/** What one widget activation did — which world handled it (see
|
|
265
|
-
* {@link FormCapability.activateWidget}). Both framework call sites ignore
|
|
266
|
-
* the value today; chrome that cares can discriminate on `kind`. */
|
|
267
|
-
type WidgetActivationResult = {
|
|
268
|
-
kind: 'form';
|
|
269
|
-
result: FormCommitResult;
|
|
270
|
-
} | {
|
|
271
|
-
kind: 'dispatched';
|
|
272
|
-
result: ActionTriggerResult;
|
|
273
|
-
};
|
|
274
|
-
/**
|
|
275
|
-
* HOST lens — plugin-to-plugin only (the actions plugin's interim
|
|
276
|
-
* `javascript` / `reset-form` executors). Import the token from
|
|
277
|
-
* `@embedpdf/plugin-form/contract/host`, never from application code.
|
|
278
|
-
*/
|
|
279
|
-
interface FormHostCapability extends FormCapability {
|
|
280
|
-
/**
|
|
281
|
-
* Execute one ResetForm action: resolve targets against the live snapshot
|
|
282
|
-
* with the shared ISO selection (`null` = every field; a parent NAME
|
|
283
|
-
* selects its descendants too; `exclude` = complement; a resolution
|
|
284
|
-
* yielding zero refs never reaches the engine), reset as ONE engine
|
|
285
|
-
* batch, refresh, then recalculate when scripting is enabled (Acrobat's
|
|
286
|
-
* behaviour). `origin` (default `'user'`) is preserved through
|
|
287
|
-
* recalculation surfacing — a lifecycle ResetForm's alerts stay lifecycle.
|
|
288
|
-
*/
|
|
289
|
-
resetFormAction(fields: PdfActionTargetRef[] | null, exclude: boolean, origin?: ActionOrigin): Promise<FormCommitResult>;
|
|
290
|
-
/**
|
|
291
|
-
* The submit dataset resolver (Phase 4, D7): fresh engine read + the pure
|
|
292
|
-
* ISO builder (`field-selection.ts`). Registered with the actions plugin
|
|
293
|
-
* as THE resolver for both action-node and script submits.
|
|
294
|
-
*/
|
|
295
|
-
resolveSubmitDataset(intent: SubmitIntent, ctx: ActionContext, diagnose: (diagnostic: ActionDiagnostic) => void): Promise<ActionSubmitRequest>;
|
|
296
|
-
/** The form DOCUMENT-commit sink (D3): engine `applyEffects` + snapshot
|
|
297
|
-
* reconciliation. Sink contract: never throws, never enqueues, never
|
|
298
|
-
* touches the script host — callable under a held host transaction. */
|
|
299
|
-
commitScriptFormEffects(effects: FormEffect[]): Promise<FormEffectsResult>;
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* The form capability token. Typed to the full {@link FormHostCapability}
|
|
303
|
-
* here (the package internals + the `/internal` entry use this view). The
|
|
304
|
-
* package root re-exports the SAME token narrowed to {@link FormCapability}.
|
|
305
|
-
*/
|
|
306
|
-
declare const FormToken: import("@embedpdf/core").CapabilityToken<FormHostCapability>;
|
|
307
|
-
//#endregion
|
|
308
|
-
export { FillItem as _, FormHostCapability as a, WidgetHit as b, FormToken as c, PlacedField as d, WidgetActivationResult as f, FormToolDef as g, FORM_TOOL_BY_ID as h, FormCommitStatus as i, FormUiEffect as l, FORM_TOOLS as m, FormCapability as n, FormPluginOptions as o, AuthorableFormFamily as p, FormCommitResult as r, FormState as s, FormAction as t, PlaceFieldInput as u, Box as v, fieldKeyOf as x, FieldKey as y };
|
|
309
|
-
//# sourceMappingURL=types-Bpc32Qmx.d.cts.map
|
package/dist/types-C1uIIYfn.cjs
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
//#region src/types.ts
|
|
2
|
-
/**
|
|
3
|
-
* The form capability token. Typed to the full {@link FormHostCapability}
|
|
4
|
-
* here (the package internals + the `/internal` entry use this view). The
|
|
5
|
-
* package root re-exports the SAME token narrowed to {@link FormCapability}.
|
|
6
|
-
*/
|
|
7
|
-
const FormToken = (0, require("@embedpdf/core").createCapabilityToken)("form");
|
|
8
|
-
//#endregion
|
|
9
|
-
Object.defineProperty(exports, "FormToken", {
|
|
10
|
-
enumerable: true,
|
|
11
|
-
get: function() {
|
|
12
|
-
return FormToken;
|
|
13
|
-
}
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
//# sourceMappingURL=types-C1uIIYfn.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types-C1uIIYfn.cjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["import type {\n AnnotationRef,\n FormDataExport,\n FormDataFormat,\n FormFieldDTO,\n FormFieldFamily,\n FormFieldPatch,\n FormFieldRef,\n FormFieldValue,\n FormImportResult,\n FormRepairOptions,\n FormRepairResult,\n FormSetValueResult,\n FormEffect,\n FormEffectsResult,\n FormSnapshot,\n PdfActionTargetRef,\n WidgetAppearance,\n} from '@embedpdf/engine-core/runtime';\nimport type {\n ActionContext,\n ActionDiagnostic,\n ActionOrigin,\n ActionSubmitRequest,\n ActionTriggerResult,\n PdfAnnotationEventKind,\n SubmitIntent,\n} from '@embedpdf/plugin-actions/contract';\nimport type { ScriptDiagnostic, ScriptExecutionError, ScriptUiEffect } from '@embedpdf/core-acrojs';\nimport { createCapabilityToken } from '@embedpdf/core';\n\nimport type { FillItem } from './core/fill-items';\nimport type { Box, FieldKey, Model, WidgetHit } from './core/model';\nimport type { AuthorableFormFamily } from './tools';\n\nexport interface FormState {\n model: Model;\n}\n\n/** The scripting switch moved to `actionsPlugin({ javascript })` (D8). */\nexport interface FormPluginOptions {}\n\nexport type FormCommitStatus = 'applied' | 'unchanged' | 'rejected' | 'failed';\n\nexport interface FormCommitResult {\n status: FormCommitStatus;\n scripted: boolean;\n effectsResult: FormEffectsResult | null;\n uiEffects: FormUiEffect[];\n diagnostics: ScriptDiagnostic[];\n error?: ScriptExecutionError;\n}\n\n/**\n * One DOM-free UI request produced by the curated Acrobat scripting surface.\n * `phase` says WHO asked: `'boot'` = a document-open script (Adobe's\n * version-check boilerplate lives here — embedders typically suppress these\n * nags), `'user'` = a script triggered by the user's own interaction (a\n * validation alert — show it).\n */\nexport type FormUiEffect = ScriptUiEffect & {\n /** WHO asked, script-model axis: `'boot'` = a name-tree/document-open boot\n * script, `'user'` = a runtime script. */\n phase: 'boot' | 'user';\n /**\n * The dispatch-origin axis (present when the script ran inside an action\n * dispatch): a lifecycle `/OpenAction` script is NOT a name-tree boot\n * script — the two axes are deliberately separate. Providers use this for\n * the default visibility matrix (suppress lifecycle alerts, block\n * non-user print); embedder handlers receive it and may decide otherwise.\n */\n origin?: ActionOrigin;\n};\n\n/** Input for {@link FormCapability.placeField}. */\nexport interface PlaceFieldInput {\n family: AuthorableFormFamily;\n pageObjectNumber: number;\n /** Content-space LOGICAL field box (no visual padding semantics). */\n box: Box;\n /** Widget styling in the engine vocabulary (`WidgetAppearance`). Convert a\n * tool's flat CSS defaults with `widgetAppearanceFromProps` from\n * `@embedpdf/plugin-annotation`. Omitted → the engine's bare defaults. */\n appearance?: WidgetAppearance;\n}\n\n/** What {@link FormCapability.placeField} created. */\nexport interface PlacedField {\n field: FormFieldDTO;\n /** The widget placed on the requested page (join key to the annotation\n * plane for auto-selection), or null when the engine reported none. */\n widget: FormFieldDTO['widgets'][number] | null;\n}\n\nexport type FormAction = { type: 'SET_MODEL'; model: Model };\n\n/**\n * The form plugin's public capability: the FIELD plane. Widgets stay\n * annotations (geometry/appearance live there); this surface owns values,\n * interchange, and the fill-mode projection.\n */\nexport interface FormCapability {\n /** The current reconciled form state (null until the first load lands). */\n snapshot(): FormSnapshot | null;\n /** Re-read the form from the engine (imports/repair/remote bursts). */\n refresh(): Promise<void>;\n\n /** Fill controls for one page — content-space, framework-agnostic. */\n fillItems(pageObjectNumber: number): FillItem[];\n /**\n * The fill control for ONE widget, by annotation object number — the join\n * the annotation-plane render layer uses (its RenderItem carries the live\n * box, so this item's `box` is advisory). Reference-stable per model change.\n * Null until the snapshot lands, or for families with no fill control.\n */\n fillItem(annotObjectNumber: number): FillItem | null;\n /** Make sure a page's widget geometry is loaded (idempotent, lazy). */\n ensureGeom(pageObjectNumber: number): void;\n\n field(key: FieldKey): FormFieldDTO | null;\n fieldForWidget(annotObjectNumber: number): FormFieldDTO | null;\n /**\n * The widget under a content-space point on a page (any family), with\n * its field — the hit test a sibling plugin runs on a pointer sample\n * before deciding what a click means (a mark dropped over a signature\n * field). The model's own geometry answers when it is loaded; until then\n * the annotation plane's live boxes do, so the first click on a page\n * already resolves. The smallest containing widget wins.\n */\n widgetAt(pageObjectNumber: number, point: { x: number; y: number }): WidgetHit | null;\n\n /** Commit a text value (call on blur/Enter — keystrokes stay local). */\n setText(key: FieldKey, value: string): Promise<void>;\n /** Toggle a checkbox/radio widget by its on-state; null clears the group. */\n toggle(key: FieldKey, onState: string | null): Promise<void>;\n /** Select choice options by export value. */\n choose(key: FieldKey, values: string[]): Promise<void>;\n /** Commit one originating-client value transaction, including K/V/C/F scripts when enabled. */\n commitValue(ref: FormFieldRef, value: FormFieldValue): Promise<FormCommitResult>;\n /**\n * Execute one widget's `/A` activation. With the actions plugin installed\n * the FULL tree is delegated to its dispatcher (Hide/ResetForm buttons work\n * even with scripting off) — `kind: 'dispatched'`; without it, today's\n * scripting-transaction path runs — `kind: 'form'`.\n */\n activateWidget(key: FieldKey, annotationRef: AnnotationRef): Promise<WidgetActivationResult>;\n /**\n * Report one widget DOM event (pointer enter/leave, down/up, focus/blur).\n * With the actions plugin present the matching `/AA` tree dispatches\n * (hover rides the shared coalescing pump; `/A` shadows `/AA U` per ISO\n * Table 197); without it — or without a tree — this is a cheap no-op.\n * Fire-and-forget by design: results surface via the actions events.\n */\n notifyWidgetEvent(key: FieldKey, ref: AnnotationRef, event: PdfAnnotationEventKind): void;\n /** Restore a field to its /DV default. */\n reset(key: FieldKey): Promise<void>;\n /** Raw engine passthrough for anything the sugar above doesn't cover. */\n setValue(ref: FormFieldRef, value: FormFieldValue): Promise<FormSetValueResult>;\n\n exportData(format?: FormDataFormat): Promise<FormDataExport>;\n importData(data: Uint8Array | ArrayBuffer, format?: FormDataFormat): Promise<FormImportResult>;\n repair(options?: FormRepairOptions): Promise<FormRepairResult>;\n\n // ── design mode (doc.forms.modify) ─────────────────────────────────────\n /**\n * Create a field of `family` with one styled widget at a content-space box\n * — the palette tools' commit, and the programmatic authoring entry (works\n * with NO annotation plugin: a pure `doc.forms` call). The box is clamped\n * to the page; sizing policy (click default vs drag rect) is the caller's.\n * The field gets a deterministic auto-name (`text_1`, …; rename in the\n * field panel). Resolves AFTER the annotation plane (when present) has\n * re-read the page, so the returned widget is immediately selectable.\n */\n placeField(input: PlaceFieldInput): Promise<PlacedField>;\n /** The page's content box (`{0,0,w,h}`) — page-bound placement math. */\n pageBox(pageObjectNumber: number): Box | null;\n /** Field-plane properties: name, required, options, default value. */\n updateField(key: FieldKey, patch: FormFieldPatch): Promise<void>;\n /** Delete the field and every widget of it (cascades on the page). */\n deleteField(key: FieldKey): Promise<void>;\n /** Unlink one widget: it stays as an inert annotation, the field survives. */\n detachWidget(key: FieldKey, annotObjectNumber: number): Promise<void>;\n\n /**\n * The twins (permissions.md): would the family's verbs succeed now for\n * this session? `canRead` — the form model hydrates at all (false = the\n * hydration gate left it empty by right); `canFill` — value writes\n * (`setText`/`toggle`/`choose`/`reset`; also fused into every\n * `FillItem.disabled`); `canDesign` — the field-design family\n * (`placeField`/`updateField`/`deleteField`/`detachWidget`).\n */\n canRead(): boolean;\n canFill(): boolean;\n canDesign(): boolean;\n}\n\n/** What one widget activation did — which world handled it (see\n * {@link FormCapability.activateWidget}). Both framework call sites ignore\n * the value today; chrome that cares can discriminate on `kind`. */\nexport type WidgetActivationResult =\n | { kind: 'form'; result: FormCommitResult }\n | { kind: 'dispatched'; result: ActionTriggerResult };\n\n/**\n * HOST lens — plugin-to-plugin only (the actions plugin's interim\n * `javascript` / `reset-form` executors). Import the token from\n * `@embedpdf/plugin-form/contract/host`, never from application code.\n */\nexport interface FormHostCapability extends FormCapability {\n /**\n * Execute one ResetForm action: resolve targets against the live snapshot\n * with the shared ISO selection (`null` = every field; a parent NAME\n * selects its descendants too; `exclude` = complement; a resolution\n * yielding zero refs never reaches the engine), reset as ONE engine\n * batch, refresh, then recalculate when scripting is enabled (Acrobat's\n * behaviour). `origin` (default `'user'`) is preserved through\n * recalculation surfacing — a lifecycle ResetForm's alerts stay lifecycle.\n */\n resetFormAction(\n fields: PdfActionTargetRef[] | null,\n exclude: boolean,\n origin?: ActionOrigin,\n ): Promise<FormCommitResult>;\n /**\n * The submit dataset resolver (Phase 4, D7): fresh engine read + the pure\n * ISO builder (`field-selection.ts`). Registered with the actions plugin\n * as THE resolver for both action-node and script submits.\n */\n resolveSubmitDataset(\n intent: SubmitIntent,\n ctx: ActionContext,\n diagnose: (diagnostic: ActionDiagnostic) => void,\n ): Promise<ActionSubmitRequest>;\n /** The form DOCUMENT-commit sink (D3): engine `applyEffects` + snapshot\n * reconciliation. Sink contract: never throws, never enqueues, never\n * touches the script host — callable under a held host transaction. */\n commitScriptFormEffects(effects: FormEffect[]): Promise<FormEffectsResult>;\n}\n\n/**\n * The form capability token. Typed to the full {@link FormHostCapability}\n * here (the package internals + the `/internal` entry use this view). The\n * package root re-exports the SAME token narrowed to {@link FormCapability}.\n */\nexport const FormToken = createCapabilityToken<FormHostCapability>('form');\n\nexport type { FillItem } from './core/fill-items';\nexport type { Box, FieldKey, WidgetHit } from './core/model';\n"],"mappings":";;;;;;AAoPA,MAAa,aAAA,2BAAA,CAAA,CAAA,sBAAA,CAAsD,MAAM"}
|