@inkbar/core 0.6.0 → 0.8.0

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.
@@ -76,9 +76,6 @@ interface PdfjsAnnotationData {
76
76
  name?: string;
77
77
  /** The intent (`/IT`), a PDF name. PDF.js 6.4 does not pass FreeText `/CL`, `/RD` or `/LE`. */
78
78
  it?: string;
79
- borderStyle?: {
80
- width: number;
81
- } | null;
82
79
  lineCoordinates?: [number, number, number, number];
83
80
  vertices?: Float32Array | number[];
84
81
  inkLists?: Array<Float32Array | number[]>;
@@ -95,6 +92,55 @@ interface PdfjsAnnotationData {
95
92
  hasAppearance?: boolean;
96
93
  hidden?: boolean;
97
94
  noView?: boolean;
95
+ /** `/F`, the annotation flags. */
96
+ annotationFlags?: number;
97
+ fieldName?: string;
98
+ fieldType?: string | null;
99
+ fieldValue?: string | string[] | null;
100
+ defaultFieldValue?: string | string[] | null;
101
+ fieldFlags?: number;
102
+ checkBox?: boolean;
103
+ radioButton?: boolean;
104
+ pushButton?: boolean;
105
+ /** A checkbox's on value, mapped through `/Opt`. */
106
+ exportValue?: string | null;
107
+ /** A radio widget's on value, mapped through `/Opt`. */
108
+ buttonValue?: string | null;
109
+ options?: {
110
+ exportValue: string;
111
+ displayValue: string;
112
+ }[];
113
+ combo?: boolean;
114
+ multiSelect?: boolean;
115
+ multiLine?: boolean;
116
+ password?: boolean;
117
+ comb?: boolean;
118
+ maxLen?: number | null;
119
+ /** `/Q`: 0 left, 1 centre, 2 right. */
120
+ textAlignment?: number | null;
121
+ borderStyle?: {
122
+ width: number;
123
+ style?: number;
124
+ } | null;
125
+ borderColor?: Uint8ClampedArray | null;
126
+ backgroundColor?: Uint8ClampedArray | null;
127
+ /** `/TU`. */
128
+ alternativeText?: string;
129
+ /** `/MK /R`. */
130
+ rotation?: number;
131
+ /** JavaScript actions by event name; null when there are none. */
132
+ actions?: Map<string, string[]> | Record<string, string[]> | null;
133
+ resetForm?: {
134
+ fields: string[];
135
+ refs: string[];
136
+ include: boolean;
137
+ };
138
+ url?: string;
139
+ /** `app.launchURL`'s second argument, for a `url` PDF.js read out of a JavaScript `/A`. */
140
+ newWindow?: boolean;
141
+ /** A Named action's name. */
142
+ action?: string;
143
+ dest?: string | unknown[];
98
144
  }
99
145
  interface PdfAssets {
100
146
  /** URL (or file path in Node) of `pdf.worker(.min).mjs`. */
@@ -142,6 +188,250 @@ declare function writable<T>(initial: T): Writable<T>;
142
188
  declare function derived<T, U>(source: Readable<T>, fn: (value: T) => U): Readable<U>;
143
189
  declare function readonly<T>(w: Writable<T>): Readable<T>;
144
190
  //#endregion
191
+ //#region src/model/form/types.d.ts
192
+ /**
193
+ * A field's value: a string (text, combo, single-select list, and the appearance-state name of a
194
+ * checkbox or radio, `"Off"` included), the selected options of a multi-select list in option
195
+ * order, or the id of the annotation that visually signs a signature field.
196
+ */
197
+ type FieldValue = string | readonly string[] | {
198
+ readonly signature: string;
199
+ };
200
+ /** Values keyed by full field name (`/T` parts joined with `.`). */
201
+ type FieldValues = Readonly<Record<string, FieldValue>>;
202
+ type FormFieldType = 'text' | 'checkbox' | 'radio' | 'combo' | 'list' | 'button' | 'signature';
203
+ /** `/Ff` bits, each false where it does not apply to the field's type. */
204
+ interface FieldFlags {
205
+ readOnly: boolean;
206
+ required: boolean;
207
+ noExport: boolean;
208
+ multiline: boolean;
209
+ password: boolean;
210
+ comb: boolean;
211
+ fileSelect: boolean;
212
+ doNotSpellCheck: boolean;
213
+ doNotScroll: boolean;
214
+ multiSelect: boolean;
215
+ editable: boolean;
216
+ radiosInUnison: boolean;
217
+ }
218
+ /**
219
+ * For a choice field, `value` is the export value and `label` the display text. For a checkbox
220
+ * or radio, `value` is a widget's appearance-state name and `label` its export value.
221
+ */
222
+ interface FieldOption {
223
+ value: string;
224
+ label: string;
225
+ }
226
+ interface WidgetAppearance {
227
+ font?: {
228
+ family: string;
229
+ fontWeight?: 'bold';
230
+ fontStyle?: 'italic';
231
+ };
232
+ /** Points; 0 means auto size. */
233
+ fontSize: number;
234
+ /** Upper-case `#RRGGBB`, as `pdfColorToHex` gives it. */
235
+ color?: string;
236
+ align: 'left' | 'center' | 'right';
237
+ border?: {
238
+ /** Upper-case `#RRGGBB`. */
239
+ color?: string;
240
+ width: number;
241
+ style: 'solid' | 'dashed' | 'beveled' | 'inset' | 'underline';
242
+ };
243
+ /** Upper-case `#RRGGBB`. */
244
+ background?: string;
245
+ /** A push button's `/MK /CA`. */
246
+ caption?: string;
247
+ /** A checkbox or radio's `/MK /CA`: the ZapfDingbats character drawn when on. */
248
+ checkStyle?: string;
249
+ /** A checkbox or radio widget has its own on appearance: `/AP /N` holds its on state. */
250
+ onAppearance?: boolean;
251
+ /** A checkbox or radio widget has its own off appearance: `/AP /N` holds `Off`. */
252
+ offAppearance?: boolean;
253
+ /**
254
+ * The file has an `/AP /N` appearance for the widget (a checkbox or radio: for its current
255
+ * `/AS`). Without one, PDF.js draws nothing for it unless it makes one from the value.
256
+ */
257
+ fileAppearance?: boolean;
258
+ }
259
+ type WidgetAction = {
260
+ kind: 'reset';
261
+ fields: string[];
262
+ include: boolean;
263
+ } | {
264
+ kind: 'submit';
265
+ url: string;
266
+ fields: string[];
267
+ include: boolean;
268
+ format: 'fdf' | 'xfdf' | 'html' | 'pdf';
269
+ method?: 'GET' | 'POST';
270
+ } | {
271
+ kind: 'uri';
272
+ url: string;
273
+ newWindow?: boolean;
274
+ } | {
275
+ kind: 'named';
276
+ name: string;
277
+ } | {
278
+ kind: 'goto';
279
+ page: number;
280
+ };
281
+ /**
282
+ * A page's `/Tabs`: rows, columns, structure, widgets first (PDF 2.0; Inkbar's fields come
283
+ * before annotations anyway) or annotation array order (PDF 2.0).
284
+ */
285
+ type TabsOrder = 'R' | 'C' | 'S' | 'W' | 'A';
286
+ interface FormWidget {
287
+ /** The PDF.js annotation id, such as `12R`. */
288
+ id: string;
289
+ page: number;
290
+ /**
291
+ * Its place among the page's widgets in the page's `/Annots`, from 0. Widgets paint in this
292
+ * order, and Tab follows it unless the page's `/Tabs` reads rows or columns.
293
+ */
294
+ order?: number;
295
+ /** User space, before the page's /Rotate. */
296
+ rect: Rect$1;
297
+ /** `/MK /R`. */
298
+ rotation: 0 | 90 | 180 | 270;
299
+ /** A checkbox or radio widget's on appearance state. */
300
+ onState?: string;
301
+ /** Not drawn on screen: `/F` Hidden or NoView, or a barcode field Inkbar cannot draw. */
302
+ hidden: boolean;
303
+ /** `/F` NoView with Print: drawn only when printed. Such a widget is also `hidden`. */
304
+ printOnly: boolean;
305
+ appearance: WidgetAppearance;
306
+ action?: WidgetAction;
307
+ /**
308
+ * The URL a JavaScript `/A`'s `app.launchURL` opens, as PDF.js reads it out of the script.
309
+ * Followed on Action only when the form runs no scripts, such as when the sandbox failed to
310
+ * load; with scripts running, the script opens it itself.
311
+ */
312
+ fallback?: WidgetAction;
313
+ /**
314
+ * The GoTo, URI, Named, ResetForm and SubmitForm actions in the `/A`'s `/Next` chain, in
315
+ * order. They run on Action after the widget's scripts and its own action, whether or not
316
+ * scripts run, in the same undo step. JavaScript anywhere in the chain runs first, with the
317
+ * widget's other Action scripts (PDF.js collects them into one), so its position in the
318
+ * chain is not kept: a GoTo whose `/Next` is JavaScript runs the script, then the GoTo.
319
+ */
320
+ next?: readonly WidgetAction[];
321
+ hasScripts: boolean;
322
+ }
323
+ interface FormField {
324
+ /** Full name: `/T` parts joined with `.`. */
325
+ name: string;
326
+ type: FormFieldType;
327
+ flags: FieldFlags;
328
+ maxLength?: number;
329
+ options: readonly FieldOption[];
330
+ defaultValue?: FieldValue;
331
+ value?: FieldValue;
332
+ /** `/TU`. */
333
+ tooltip?: string;
334
+ /** In page order, as the file lists them. */
335
+ widgets: readonly FormWidget[];
336
+ signed?: 'certificate';
337
+ /** Nothing may change the value: certificate-signed, locked by a signature, or unsupported. */
338
+ locked: boolean;
339
+ }
340
+ /** Script-driven state for one widget. Absent keys leave the PDF's own state. */
341
+ interface WidgetOverride {
342
+ hidden?: boolean;
343
+ readOnly?: boolean;
344
+ required?: boolean;
345
+ /** Lower-case `#rrggbb`, or `transparent` for none. */
346
+ textColor?: string;
347
+ fillColor?: string;
348
+ strokeColor?: string;
349
+ /** Points; 0 means auto size. */
350
+ textSize?: number;
351
+ }
352
+ /** An event the form layer sends a widget's scripts. */
353
+ interface FormEvent {
354
+ widget: string;
355
+ name: 'Keystroke' | 'Format' | 'Validate' | 'Focus' | 'Blur' | 'Mouse Enter' | 'Mouse Exit' | 'Mouse Down' | 'Mouse Up' | 'Action';
356
+ value?: string | string[];
357
+ change?: string;
358
+ selStart?: number;
359
+ selEnd?: number;
360
+ willCommit?: boolean;
361
+ commitKey?: number;
362
+ }
363
+ /** Something a form asks the host to do. Inkbar itself never sends, opens, mails or prints. */
364
+ type FormAction = {
365
+ kind: 'submit';
366
+ url: string;
367
+ fields: FieldValues;
368
+ format: 'fdf' | 'xfdf' | 'html' | 'pdf';
369
+ method?: 'GET' | 'POST';
370
+ } | {
371
+ kind: 'open-url';
372
+ url: string;
373
+ newWindow: boolean;
374
+ } | {
375
+ kind: 'mail';
376
+ to?: string;
377
+ cc?: string;
378
+ bcc?: string;
379
+ subject?: string;
380
+ body?: string;
381
+ withData: boolean;
382
+ } | {
383
+ kind: 'print';
384
+ } | {
385
+ kind: 'prompt';
386
+ message: string;
387
+ };
388
+ /**
389
+ * What changed the values reported to a controlled host, and the fields it changed. Undo
390
+ * history needs uncontrolled fields and annotations, so a controlled host never hears of an
391
+ * undo or redo, and no change has a `history` kind.
392
+ *
393
+ * - `commit`: a person, `set` or a signature committed values; `names` lists the fields
394
+ * committed, including fields a calculation changed.
395
+ * - `reset`: a reset (the API's or a reset button's) restored defaults, with what it
396
+ * calculated.
397
+ * - `import`: a Gloss import set values, with what it calculated.
398
+ * - `calculate`: a script set values outside a commit or reset (a timer, a page's open or close
399
+ * script, a widget's event script), or calculated after a host's push.
400
+ */
401
+ type FieldsChange = {
402
+ kind: 'commit';
403
+ names: string[];
404
+ } | {
405
+ kind: 'reset';
406
+ names: string[];
407
+ } | {
408
+ kind: 'import';
409
+ names: string[];
410
+ } | {
411
+ kind: 'calculate';
412
+ names: string[];
413
+ };
414
+ /**
415
+ * Defaults to uncontrolled, starting from the PDF's values with `initial` over them. In
416
+ * controlled mode a change applies at once and is then reported with the full map; the host's
417
+ * push wins.
418
+ */
419
+ type FieldsMode = {
420
+ mode: 'uncontrolled';
421
+ initial?: FieldValues;
422
+ } | {
423
+ mode: 'controlled';
424
+ initial: FieldValues;
425
+ onChange(next: FieldValues, change: FieldsChange): void;
426
+ };
427
+ interface FormSetResult {
428
+ applied: string[];
429
+ rejected: {
430
+ name: string;
431
+ reason: 'unknown' | 'readOnly' | 'invalid' | 'script';
432
+ }[];
433
+ }
434
+ //#endregion
145
435
  //#region src/model/annotations/types.d.ts
146
436
  declare const PointSchema: z.ZodObject<{
147
437
  x: z.ZodNumber;
@@ -1729,6 +2019,7 @@ declare const AnnotationDocumentSchema: z.ZodObject<{
1729
2019
  version: z.ZodLiteral<1>;
1730
2020
  documentKey: z.ZodOptional<z.ZodString>;
1731
2021
  annotations: z.ZodArray<z.ZodUnknown>;
2022
+ fields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1732
2023
  }, z.core.$strip>;
1733
2024
  /**
1734
2025
  * An item whose `type` this version does not know, such as one from a newer writer. It is kept
@@ -1741,6 +2032,8 @@ interface AnnotationDocument {
1741
2032
  version: GlossDocument['version'];
1742
2033
  documentKey?: string;
1743
2034
  annotations: Array<Annotation | ForeignAnnotation>;
2035
+ /** Form field values by full name: each field that has one and is not no-export. */
2036
+ fields?: Record<string, FieldValue>;
1744
2037
  }
1745
2038
  //#endregion
1746
2039
  //#region src/model/annotations/defaults.d.ts
@@ -1776,6 +2069,7 @@ interface EmbeddedSummary {
1776
2069
  count: number;
1777
2070
  supported: boolean;
1778
2071
  }
2072
+ /** An RGB colour in 0–255 as upper-case `#RRGGBB`; `fallback` when it has fewer than three parts. */
1779
2073
  declare function pdfColorToHex(c: ArrayLike<number> | null | undefined, fallback: string): string;
1780
2074
  /**
1781
2075
  * Imported ids are `pdf:<page>:<pdfjsId>` (page is 0-based, pdfjsId is the annotation's object
@@ -1966,6 +2260,17 @@ interface AnnotationStore {
1966
2260
  * not applied yet: the list `update` and `remove` build on.
1967
2261
  */
1968
2262
  _getProposed(id: string): Annotation$1 | undefined;
2263
+ /**
2264
+ * @internal Pins annotations to what they fill (a signature to its signature field): a
2265
+ * pinned annotation takes patches only to `contents` and to `custom` outside its `inkbar`
2266
+ * key, and refuses any other (no move, resize, restyle, new image or new author), while
2267
+ * `remove` still works. Replaces the whole set.
2268
+ */
2269
+ _setPinned(ids: ReadonlySet<string>): void;
2270
+ /** @internal Whether `_setPinned` pinned `id`. */
2271
+ _isPinned(id: string): boolean;
2272
+ /** @internal The pinned ids, for the overlay. */
2273
+ readonly _pinned: Readable<ReadonlySet<string>>;
1969
2274
  completeInput(input: AnnotationInput): Annotation$1;
1970
2275
  on(event: 'change', fn: (change: AnnotationChange) => void): () => void;
1971
2276
  /**
@@ -1991,8 +2296,8 @@ interface PluginHistory {
1991
2296
  batch(fn: () => void): void;
1992
2297
  /**
1993
2298
  * Makes the store's changes undo steps: on their own, or joining the open batch or edit. The
1994
- * returned function stops tracking; existing entries keep their snapshot of the store but undo
1995
- * and redo no longer replay it.
2299
+ * returned function stops tracking: existing entries forget the store, so undo and redo never
2300
+ * replay it again, even once it is tracked again, and an entry left with nothing is dropped.
1996
2301
  */
1997
2302
  track(store: RecordStore<RecordBase>): () => void;
1998
2303
  /**
@@ -2018,6 +2323,14 @@ interface History extends PluginHistory {
2018
2323
  * history this only runs `fn`, and a history destroyed inside `fn` records nothing.
2019
2324
  */
2020
2325
  batch(fn: () => void): void;
2326
+ /**
2327
+ * Runs `fn` and records none of what it changes in the tracked record stores: each changed
2328
+ * record becomes part of the baseline, written into every step on both stacks (and the open
2329
+ * step), so undo and redo leave it as `fn` left it. A step left with nothing else to replay is
2330
+ * dropped. Nested calls, and calls inside a batch, work the same way. Annotation changes inside
2331
+ * `fn` are recorded as usual. On a controlled or destroyed history this only runs `fn`.
2332
+ */
2333
+ baseline(fn: () => void): void;
2021
2334
  /** Unsubscribes from the store and empties both stacks; undo and redo become no-ops. */
2022
2335
  destroy(): void;
2023
2336
  }
@@ -2032,6 +2345,13 @@ declare function createHistory(store: AnnotationStore, opts?: {
2032
2345
  limit?: number;
2033
2346
  }): History;
2034
2347
  //#endregion
2348
+ //#region src/model/form/gloss.d.ts
2349
+ /** A Gloss value the form could not apply. No script runs on one, so none is `script`. */
2350
+ interface GlossRejection {
2351
+ name: string;
2352
+ reason: 'unknown' | 'readOnly' | 'invalid';
2353
+ }
2354
+ //#endregion
2035
2355
  //#region src/model/annotations/json.d.ts
2036
2356
  interface ImportResult {
2037
2357
  imported: number;
@@ -2044,6 +2364,11 @@ interface ImportResult {
2044
2364
  index: number;
2045
2365
  issues: string[];
2046
2366
  }[];
2367
+ /** The document's `fields` names that were applied, and the ones that were not, with why. */
2368
+ fields: {
2369
+ applied: string[];
2370
+ rejected: GlossRejection[];
2371
+ };
2047
2372
  }
2048
2373
  interface ImportOptions {
2049
2374
  /** `replace` drops every session annotation first; `merge` overwrites by id and keeps the rest. */
@@ -2061,19 +2386,22 @@ interface ImportOptions {
2061
2386
  * under `custom.inkbar`, with loupes and masks as the circle or square they draw. Every other key
2062
2387
  * under `custom` goes out as it is.
2063
2388
  *
2389
+ * `fields`, when given and not empty, goes out as the document's `fields` (see `fieldsToGloss`).
2390
+ *
2064
2391
  * The result validates against the Gloss schema (`gloss-format/schema.json`). Foreign items
2065
2392
  * validate as unknown annotations while their type is one Gloss does not define.
2066
2393
  */
2067
- declare function exportAnnotations(store: AnnotationStore, preserved?: readonly ForeignAnnotation[], documentKey?: string): AnnotationDocument;
2394
+ declare function exportAnnotations(store: AnnotationStore, preserved?: readonly ForeignAnnotation[], documentKey?: string, fields?: Readonly<Record<string, FieldValue>>): AnnotationDocument;
2068
2395
  /**
2069
2396
  * Validates the envelope (throws a TypeError when it is not a gloss v1 document),
2070
2397
  * then each item on its own. Embedded annotations are never touched; imported items become
2071
- * session annotations.
2398
+ * session annotations. With no form to apply them to, every `fields` name is reported as
2399
+ * unknown; `InkDocument.importAnnotations` applies them to the document's form.
2072
2400
  */
2073
2401
  declare function importAnnotations(store: AnnotationStore, data: AnnotationDocument | string, opts: ImportOptions): ImportResult;
2074
2402
  //#endregion
2075
2403
  //#region src/model/errors.d.ts
2076
- type InkErrorCode = 'PasswordRequired' | 'InvalidPdf' | 'SourceFetchFailed' | 'AssetConfigMissing' | 'AssetLoadFailed' | 'EngineUnavailable' | 'ControlledMutationIgnored' | 'DocumentDestroyed' | 'PageOutOfRange' | 'DuplicateId' | 'DuplicatePlugin' | 'InvalidPluginId' | 'InvalidCommandLabel' | 'UnknownCommand';
2404
+ type InkErrorCode = 'PasswordRequired' | 'InvalidPdf' | 'SourceFetchFailed' | 'AssetConfigMissing' | 'AssetLoadFailed' | 'EngineUnavailable' | 'ControlledMutationIgnored' | 'DocumentDestroyed' | 'PageOutOfRange' | 'DuplicateId' | 'DuplicatePlugin' | 'InvalidPluginId' | 'InvalidCommandLabel' | 'UnknownCommand' | 'FormScriptError' | 'UnknownField' | 'NotSignatureField' | 'FieldReadOnly' | 'FieldSigned';
2077
2405
  declare class InkError extends Error {
2078
2406
  readonly name = "InkError";
2079
2407
  readonly code: InkErrorCode;
@@ -2082,14 +2410,187 @@ declare class InkError extends Error {
2082
2410
  }
2083
2411
  declare function isInkError(value: unknown): value is InkError;
2084
2412
  //#endregion
2085
- //#region src/model/source.d.ts
2086
- type DocumentSource = ArrayBuffer | Uint8Array | Blob | string | {
2087
- url: string;
2088
- key: string;
2089
- } | {
2090
- data: ArrayBuffer | Uint8Array;
2091
- key: string;
2092
- };
2413
+ //#region src/model/form/controller.d.ts
2414
+ interface FieldRecord {
2415
+ readonly id: string;
2416
+ readonly value: FieldValue;
2417
+ }
2418
+ interface FormController {
2419
+ /** Structure, read once on load. */
2420
+ readonly fields: Readable<readonly FormField[]>;
2421
+ /** What the screen and the sandbox hold, keyed by full name. */
2422
+ readonly values: Readable<FieldValues>;
2423
+ /** Formatted text per field, for display when not focused; set by scripts. */
2424
+ readonly formatted: Readable<Readonly<Record<string, string>>>;
2425
+ /** Script-driven widget state: hidden, readOnly, required, colours, by widget id. */
2426
+ readonly widgetState: Readable<Readonly<Record<string, WidgetOverride>>>;
2427
+ /**
2428
+ * Whether the form has JavaScript: a widget's scripts, or document-level or page scripts
2429
+ * running in the sandbox.
2430
+ */
2431
+ readonly hasScripts: boolean;
2432
+ get(name: string): FieldValue | undefined;
2433
+ /**
2434
+ * Commits `values` as a person would: each runs its validate and calculate scripts, and the
2435
+ * whole call is one undo step. A value that is unknown, read-only, invalid for the field or
2436
+ * rejected by a script is left out and listed in `rejected`. In controlled mode the full map
2437
+ * is reported once afterwards, as a `commit` naming the fields set and the fields a
2438
+ * calculation changed.
2439
+ */
2440
+ set(values: FieldValues): FormSetResult;
2441
+ /**
2442
+ * Restores the PDF's default values of `names`, or of every field. Read-only fields reset
2443
+ * too, as in Acrobat; locked fields keep theirs.
2444
+ */
2445
+ reset(names?: readonly string[]): void;
2446
+ /**
2447
+ * Controlled mode only: the host pushes its values. Names it leaves out keep their value.
2448
+ * Pushing what the form already holds does nothing; otherwise calculate scripts run, and a
2449
+ * calculation that changes more is reported once. Before the fields load, the push waits for
2450
+ * them.
2451
+ */
2452
+ setControlledValue(next: FieldValues): void;
2453
+ on(event: 'action', fn: (a: FormAction) => void): () => void;
2454
+ on(event: 'alert', fn: (message: string) => void): () => void;
2455
+ /**
2456
+ * A script failed. The document keeps working; the form layer shows or logs it. Errors from
2457
+ * before the first listener (a sandbox that failed to start while the document opened) go to
2458
+ * that listener once, as it subscribes.
2459
+ */
2460
+ on(event: 'error', fn: (e: InkError) => void): () => void;
2461
+ /** A script asked to move focus to this widget (by id). */
2462
+ on(event: 'focus', fn: (widgetId: string) => void): () => void;
2463
+ /** A widget's `/GoTo` action ran: show this page (zero-based). */
2464
+ on(event: 'goto', fn: (page: number) => void): () => void;
2465
+ /** @internal The scripting seam and the form layer. */
2466
+ readonly _store: RecordStore<FieldRecord>;
2467
+ _attachScripting(s: FormScripting): void;
2468
+ _emitAction(a: FormAction): void;
2469
+ /**
2470
+ * Runs the widget's scripts for `event`, and on `Action` its non-script action (reset,
2471
+ * submit, URI, named Print, GoTo). A Blur drops the widget's uncommitted text.
2472
+ */
2473
+ _dispatch(event: FormEvent): void;
2474
+ /**
2475
+ * @internal Runs `fn` as one undo step, so a widget's activation (its new value, its Mouse Up
2476
+ * and its Action, with the scripts and reset they run) undoes at once.
2477
+ */
2478
+ _step(fn: () => void): void;
2479
+ /**
2480
+ * Applies a keystroke to the widget's text as typed so far (its uncommitted text, else the
2481
+ * field's value as shown: a combo's option label for its export value). Without scripting it
2482
+ * accepts every keystroke. The uncommitted text is dropped when the field's value changes or
2483
+ * the widget blurs.
2484
+ */
2485
+ _keystroke(widget: string, change: string, selStart: number, selEnd: number): KeystrokeResult;
2486
+ /**
2487
+ * @internal Drops the widget's uncommitted text (Escape in a text field), and the sandbox,
2488
+ * which saw each keystroke, goes back to the stored value. Its next keystroke builds on that.
2489
+ */
2490
+ _revert(widget: string): void;
2491
+ /**
2492
+ * @internal The viewer's current page became `page` (`PageOpen`) or another (`PageClose`):
2493
+ * runs the page's open or close scripts. Resolves once they ran; nothing runs without scripts.
2494
+ */
2495
+ _pageEvent(page: number, name: PageEventName): Promise<void>;
2496
+ /** @internal Sets a field's formatted text; `undefined` clears it. */
2497
+ _setFormatted(name: string, text: string | undefined): void;
2498
+ /** @internal Merges into a widget's override; `undefined` clears it. */
2499
+ _setWidgetState(widgetId: string, override: WidgetOverride | undefined): void;
2500
+ /** @internal Reports a script error to `onError` and the `error` listeners. */
2501
+ _error(e: InkError): void;
2502
+ /** @internal A script's `app.alert`. */
2503
+ _alert(message: string): void;
2504
+ /** @internal A script moved focus to a widget. */
2505
+ _focus(widgetId: string): void;
2506
+ /**
2507
+ * @internal Values a script set (a calculation, or a script assigning a field). Read-only
2508
+ * fields take them; locked fields and values that do not suit the field are skipped. Inside
2509
+ * a commit, reset or widget event they join its undo step. Outside one (a timer, a page's
2510
+ * open or close script, a keystroke script) they are no undo step: they become the history's
2511
+ * baseline, so undo never rewinds them. A controlled host hears of them as `calculate`.
2512
+ */
2513
+ _scriptValues(values: FieldValues): void;
2514
+ /** @internal Each page's `/Tabs`, for pages that set one; set with the fields. */
2515
+ readonly _tabs: ReadonlyMap<number, TabsOrder>;
2516
+ /**
2517
+ * @internal For each page whose `/Tabs` is `S`, its annotation ids in structure-tree order;
2518
+ * set with the fields.
2519
+ */
2520
+ readonly _structure: ReadonlyMap<number, readonly string[]>;
2521
+ /** @internal Sets the structure once the file's fields are read, applying any waiting push. */
2522
+ _load(fields: readonly FormField[], tabs?: ReadonlyMap<number, TabsOrder>, structure?: ReadonlyMap<number, readonly string[]>): void;
2523
+ /**
2524
+ * @internal Applies values already checked by `fieldsFromGloss`, as an import: neither the
2525
+ * values nor what they calculate are an undo step. A controlled host hears of both as one
2526
+ * `import`.
2527
+ */
2528
+ _import(values: FieldValues): void;
2529
+ /**
2530
+ * @internal Keeps signature fields and the annotations that sign them in step, from now
2531
+ * until `_destroy`. Each signing annotation is pinned in the store. Removing one (by a person,
2532
+ * an import, a controlled host that drops it, or undo) clears its field, and clearing the
2533
+ * field (a reset, a host's push of another value, an import) removes the annotation.
2534
+ */
2535
+ _linkAnnotations(link: SignatureLink): void;
2536
+ /**
2537
+ * @internal Signs signature field `name` with annotation `id`, reported to a controlled
2538
+ * host as a `commit`. When the annotation is not in the list yet (a controlled host has it
2539
+ * proposed), the field is signed once it arrives, and stays empty if the host drops it.
2540
+ */
2541
+ _signWith(name: string, id: string): void;
2542
+ /**
2543
+ * @internal Whether `name` waits for a signature a controlled host has proposed and not
2544
+ * applied or dropped yet.
2545
+ */
2546
+ _awaitingSignature(name: string): boolean;
2547
+ /**
2548
+ * @internal `set` or `reset` gave these fields a value, whether or not it differs from the
2549
+ * one they held. The form layer clears a refused commit's mark on them. A host's push is not
2550
+ * reported: it clears a mark only where it changes the value.
2551
+ */
2552
+ _onPut(fn: (names: readonly string[]) => void): () => void;
2553
+ /** @internal Destroys the scripting and drops every listener. */
2554
+ _destroy(): void;
2555
+ }
2556
+ /** What `_linkAnnotations` needs from the document. */
2557
+ interface SignatureLink {
2558
+ store: AnnotationStore;
2559
+ /** The history's `react`: runs inside a person's edit, so the field clears in the same step. */
2560
+ react(fn: (edit: AnnotationEdit) => void): () => void;
2561
+ /**
2562
+ * True when undo and redo replay the field values together with the annotations, so an
2563
+ * annotation replay leaves the fields to theirs.
2564
+ */
2565
+ replays: boolean;
2566
+ }
2567
+ /** A page event a page's scripts may handle. */
2568
+ type PageEventName = 'PageOpen' | 'PageClose';
2569
+ interface KeystrokeResult {
2570
+ accepted: boolean;
2571
+ value: string;
2572
+ selStart: number;
2573
+ selEnd: number;
2574
+ }
2575
+ interface FormScripting {
2576
+ /**
2577
+ * Runs validate for `name` with `value`, then calculate. Synchronous. Returns the value to
2578
+ * store (a script may change it), or `undefined` when a script rejected it.
2579
+ */
2580
+ commit(name: string, value: FieldValue): FieldValue | undefined;
2581
+ /** After values change without a user commit (host push, import, reset, undo). */
2582
+ sync(values: FieldValues, calculate: boolean): void;
2583
+ /** Runs a widget event's scripts. Synchronous. */
2584
+ dispatch(event: FormEvent): void;
2585
+ /**
2586
+ * Runs the widget's keystroke scripts on `text`, the text typed so far. `undefined` when the
2587
+ * widget has no field in the sandbox.
2588
+ */
2589
+ keystroke(widget: string, text: string, change: string, selStart: number, selEnd: number): KeystrokeResult | undefined;
2590
+ /** Runs `page`'s (zero-based) open or close scripts; resolves once they ran. */
2591
+ pageEvent(page: number, name: PageEventName): Promise<void>;
2592
+ destroy(): void;
2593
+ }
2093
2594
  //#endregion
2094
2595
  //#region src/model/text.d.ts
2095
2596
  interface TextItem {
@@ -2102,12 +2603,69 @@ interface TextItem {
2102
2603
  quad: Quad;
2103
2604
  /** Axis-aligned bounds of `quad`. */
2104
2605
  rect: Rect$1;
2606
+ /**
2607
+ * How far along the run each character boundary lies, as a fraction of its width: `str.length + 1`
2608
+ * entries, from 0 to 1 or a little past it. Taken from where the page draws each glyph when the
2609
+ * glyphs can be matched to the run, else measured in the run's fallback font. Absent when neither
2610
+ * works, in which case every character takes an equal share.
2611
+ */
2612
+ advances?: readonly number[];
2613
+ /**
2614
+ * Where each character's glyph ends, as a fraction of the run's width: `str.length` entries, set
2615
+ * with `advances` when they come from the page's glyphs. Kerning can pull the next character
2616
+ * back over the end of a glyph, so a glyph may end past the next boundary.
2617
+ */
2618
+ glyphEnds?: readonly number[];
2105
2619
  }
2106
2620
  interface TextContent {
2107
2621
  page: number;
2108
2622
  items: TextItem[];
2109
2623
  }
2110
2624
  //#endregion
2625
+ //#region src/model/search.d.ts
2626
+ interface SearchOptions {
2627
+ /** Defaults to false. Ignored for a `RegExp`, whose own `i` flag rules. */
2628
+ matchCase?: boolean;
2629
+ /** Requires a hit to have no letter, digit or underscore next to it. */
2630
+ wholeWord?: boolean;
2631
+ /** Page indices to search, in the order given. Defaults to every page in order. */
2632
+ pages?: readonly number[];
2633
+ signal?: AbortSignal;
2634
+ }
2635
+ interface SearchHit {
2636
+ page: number;
2637
+ /** Offsets into `pageText(page)`. */
2638
+ start: number;
2639
+ end: number;
2640
+ /** The page text the hit covers. */
2641
+ text: string;
2642
+ /** One quad per run of text the hit touches. */
2643
+ quads: Quad[];
2644
+ rect: Rect$1;
2645
+ /**
2646
+ * True when every quad is cut where the page draws its glyphs. False when some text could not
2647
+ * be matched to the page's glyphs (right-to-left or vertical text, or an unusual file) and its
2648
+ * quad is cut at estimated widths, which can fall short of the glyphs; pad those before
2649
+ * covering text with them.
2650
+ */
2651
+ exact: boolean;
2652
+ /** Up to `CONTEXT_CHARS` of page text either side of the hit, whitespace collapsed. */
2653
+ before: string;
2654
+ after: string;
2655
+ }
2656
+ interface SearchResults extends AsyncIterable<SearchHit> {
2657
+ all(): Promise<SearchHit[]>;
2658
+ }
2659
+ //#endregion
2660
+ //#region src/model/source.d.ts
2661
+ type DocumentSource = ArrayBuffer | Uint8Array | Blob | string | {
2662
+ url: string;
2663
+ key: string;
2664
+ } | {
2665
+ data: ArrayBuffer | Uint8Array;
2666
+ key: string;
2667
+ };
2668
+ //#endregion
2111
2669
  //#region src/model/document.d.ts
2112
2670
  type DocumentStatus = {
2113
2671
  state: 'loading';
@@ -2137,11 +2695,17 @@ interface OpenOptions {
2137
2695
  * in `list` whatever the host pushes back.
2138
2696
  */
2139
2697
  annotations?: StoreMode | undefined;
2698
+ /**
2699
+ * Form field values; defaults to uncontrolled, starting from the PDF's. In controlled mode a
2700
+ * commit applies at once and is reported with the full map, and the host's push wins.
2701
+ */
2702
+ fields?: FieldsMode | undefined;
2140
2703
  /** Colour defaults. Pass `cssVariableDefaults(element)` from the DOM layer to read theme variables. */
2141
2704
  defaults?: AnnotationDefaults | undefined;
2142
2705
  /**
2143
2706
  * Undo history, on by default. `false` disables it. In controlled mode history is always
2144
- * inert: the host owns the list, so it owns undo too.
2707
+ * inert: the host owns the list, so it owns undo too. Field values join it only while both
2708
+ * annotations and fields are uncontrolled.
2145
2709
  */
2146
2710
  history?: boolean | {
2147
2711
  limit?: number | undefined;
@@ -2157,8 +2721,13 @@ interface InkDocument {
2157
2721
  readonly pages: readonly PageInfo[];
2158
2722
  readonly info: DocumentInfo;
2159
2723
  text(page: number): Promise<TextContent>;
2160
- /** The page's text items joined with a single space. */
2724
+ /** The page's text as search sees it: items joined the way the page reads. */
2161
2725
  pageText(page: number): Promise<string>;
2726
+ /**
2727
+ * Finds `query` in the document's text, a page at a time. A string matches ignoring case,
2728
+ * accents and quote style; a `RegExp` runs on the same normalised text.
2729
+ */
2730
+ search(query: string | RegExp, opts?: SearchOptions): SearchResults;
2162
2731
  /**
2163
2732
  * Annotations embedded in the file arrive here as `source: 'pdf'`, `locked: true` before
2164
2733
  * `ready` resolves. They stay in `list` in both modes and cannot be removed; in controlled
@@ -2170,9 +2739,17 @@ interface InkDocument {
2170
2739
  /** What the file contained, by PDF subtype, including subtypes Inkbar does not show. */
2171
2740
  readonly embedded: readonly EmbeddedSummary[];
2172
2741
  readonly history: History;
2173
- /** Session annotations only, plus unknown-type items kept from earlier imports. */
2742
+ /** The form's fields and values; empty when the file has no fields. */
2743
+ readonly form: FormController;
2744
+ /**
2745
+ * Session annotations only, plus unknown-type items kept from earlier imports, and `fields`
2746
+ * with every field value that is not no-export.
2747
+ */
2174
2748
  exportAnnotations(format: 'json'): AnnotationDocument;
2175
- /** Defaults to `{ mode: 'replace' }`. Embedded annotations are never touched. */
2749
+ /**
2750
+ * Defaults to `{ mode: 'replace' }`. Embedded annotations are never touched. `fields`, when
2751
+ * present, sets the values it names and leaves the rest; that is not an undo step.
2752
+ */
2176
2753
  importAnnotations(data: AnnotationDocument | string, opts?: ImportOptions): ImportResult;
2177
2754
  /** Writes the document with its annotations. Needs @inkbar/engine; rejects with EngineUnavailable otherwise. */
2178
2755
  save(): Promise<Uint8Array>;
@@ -2236,7 +2813,7 @@ interface ToolStyle {
2236
2813
  * Updates the active tool's group, or under a select tool (no active group) the group that
2237
2814
  * owns each prop on each selected annotation (a speech bubble's outline is `shape`'s, its
2238
2815
  * text `text`'s). With `apply` it also updates every selected, unlocked annotation that has
2239
- * the props, in one history step. `apply` defaults to true under a select tool, and to
2816
+ * the props, in one history step; a pinned one keeps its style. `apply` defaults to true under a select tool, and to
2240
2817
  * whether the selection is wholly in the group otherwise. `group` names the group explicitly.
2241
2818
  */
2242
2819
  set(patch: StyleProps, opts?: {
@@ -2362,5 +2939,21 @@ interface SignatureLibrary {
2362
2939
  }
2363
2940
  declare function createSignatureLibrary(store: SignatureStore): SignatureLibrary;
2364
2941
  //#endregion
2365
- export { createRecordStore as $, QuadSchema as $t, TextItem as A, rectContainsPoint as An, GLOSS_FORMAT$1 as At, PluginHistory as B, LineSchema as Bt, DocumentInfo as C, approxEqual as Cn, ExportedAnnotation as Ct, OpenOptions as D, quadFromRect as Dn, FreeTextSchema as Dt, InkStatus as E, pointsFromFlat as En, FreeTextAnnotation as Et, ImportOptions as F, translateQuad as Fn, InkAnnotation as Ft, StoreMode as G, NoteAnnotation as Gt, AnnotationChange as H, LoupeSchema as Ht, ImportResult as I, translateRect as In, InkSchema as It, deriveRect as J, PointSchema as Jt, StoreOptions as K, NoteIconSchema as Kt, exportAnnotations as L, unionRects as Ln, LineAnnotation as Lt, InkError as M, rectFromQuad as Mn, GLOSS_SCHEMA_ID as Mt, InkErrorCode as N, rectFromQuads as Nn, GLOSS_VERSION$1 as Nt, openDocument as O, quadsFromFlat as On, FreeTextStyle$1 as Ot, isInkError as P, rectsIntersect as Pn, IMAGE_DATA_URL as Pt, RecordStoreOptions as Q, PolylineSchema as Qt, importAnnotations as R, LineEnding$1 as Rt, createToolStyle as S, applyMatrix as Sn, CircleSchema as St, InkDocument as T, multiplyMatrix as Tn, ForeignAnnotation as Tt, AnnotationEdit as U, MaskAnnotation as Ut, createHistory as V, LoupeAnnotation as Vt, AnnotationStore as W, MaskSchema as Wt, RecordChange as X, PolySchema as Xt, RecordBase as Y, PolyAnnotation as Yt, RecordStore as Z, PolygonSchema as Zt, StyleGroup as _, PdfAssets as _n, AnnotationInput as _t, SignatureStore as a, SquareSchema as an, importedId as at, ToolStyle as b, Quad as bn, AnnotationSchema as bt, createInkTemplate as c, TextMarkupAnnotation as cn, Fringe$1 as ct, createSignatureLibrary as d, Writable as dn, cssVariableDefaults as dt, RectSchema as en, EmbeddedFieldPatch as et, normaliseInk as f, derived as fn, normalizeColor as ft, ScopedToolStyle as g, PageRotation as gn, AnnotationDocumentSchema as gt, STYLE_GROUPS as h, PageInfo as hn, AnnotationDocument as ht, SignatureOptions as i, ShapeSchema as in, importEmbeddedPage as it, DocumentSource as j, rectFromPoints as jn, GLOSS_MEDIA_TYPE as jt, TextContent as k, quadsFromRect as kn, FreeTextStyleSchema as kt, createLocalSignatureStore as l, TextMarkupSchema as ln, FringeSchema as lt, CurrentStyle as m, writable as mn, Annotation$1 as mt, SIGNATURE_INK_WIDTH as n, RedactSchema as nn, EmbeddedTarget as nt, SignatureTemplate as o, StampAnnotation as on, pdfColorToHex as ot, placeSignature as p, readonly as pn, staticDefaults as pt, createAnnotationStore as q, NoteSchema as qt, SignatureLibrary as r, ShapeAnnotation as rn, SUPPORTED_SUBTYPES as rt, createImageTemplate as s, StampSchema as sn, summarise as st, DEFAULT_SIGNATURE_WIDTH as t, RedactAnnotation as tn, EmbeddedSummary as tt, createMemorySignatureStore as u, Readable as un, AnnotationDefaults as ut, StyleKey as v, Matrix as vn, AnnotationOfType as vt, DocumentStatus as w, invertMatrix as wn, ExportedAnnotationSchema as wt, ToolStyleDeps as x, Rect$1 as xn, AnnotationType as xt, StyleProps as y, Point$1 as yn, AnnotationPatch as yt, History as z, LineEndingSchema as zt };
2366
- //# sourceMappingURL=signatures-By4B40DP.d.mts.map
2942
+ //#region src/model/form/sign.d.ts
2943
+ /**
2944
+ * Signs signature field `field` on its widget `widget` with template `t`, and returns the new
2945
+ * annotation's id. The signature (ink for a drawn one, a stamp for an image, `subject:
2946
+ * 'Signature'`) is fitted and centred in the widget's rect, upright as the page's `/Rotate`
2947
+ * shows it, and the field's value becomes `{ signature: id }`: one undo step, and in controlled
2948
+ * mode one change of each. A controlled host gets the annotation proposed, and the field is
2949
+ * signed once the host applies it.
2950
+ *
2951
+ * The signature is pinned to the field: it can be deleted, which clears the field, but not
2952
+ * moved or resized. Throws an `InkError`: `UnknownField` for a field or widget the form does
2953
+ * not have, `NotSignatureField` for another type, `FieldReadOnly` for a read-only or locked
2954
+ * field (one signed with a certificate included), and `FieldSigned` when it is already signed.
2955
+ */
2956
+ declare function signField(doc: InkDocument, field: string, widget: string, t: SignatureTemplate): string;
2957
+ //#endregion
2958
+ export { createAnnotationStore as $, rectFromQuad as $n, NoteSchema as $t, DocumentSource as A, WidgetOverride as An, ExportedAnnotationSchema as At, isInkError as B, Point$1 as Bn, IMAGE_DATA_URL as Bt, createToolStyle as C, FormEvent as Cn, AnnotationInput as Ct, InkStatus as D, FormWidget as Dn, AnnotationType as Dt, InkDocument as E, FormSetResult as En, AnnotationSchema as Et, TextItem as F, writable as Fn, FreeTextStyleSchema as Ft, History as G, invertMatrix as Gn, LineEndingSchema as Gt, ImportResult as H, Rect$1 as Hn, InkSchema as Ht, FormController as I, PageInfo as In, GLOSS_FORMAT$1 as It, AnnotationChange as J, quadFromRect as Jn, LoupeSchema as Jt, PluginHistory as K, multiplyMatrix as Kn, LineSchema as Kt, FormScripting as L, PageRotation as Ln, GLOSS_MEDIA_TYPE as Lt, SearchOptions as M, Writable as Mn, FreeTextAnnotation as Mt, SearchResults as N, derived as Nn, FreeTextSchema as Nt, OpenOptions as O, WidgetAction as On, CircleSchema as Ot, TextContent as P, readonly as Pn, FreeTextStyle$1 as Pt, StoreOptions as Q, rectFromPoints as Qn, NoteIconSchema as Qt, InkError as R, PdfAssets as Rn, GLOSS_SCHEMA_ID as Rt, ToolStyleDeps as S, FormAction as Sn, AnnotationDocumentSchema as St, DocumentStatus as T, FormFieldType as Tn, AnnotationPatch as Tt, exportAnnotations as U, applyMatrix as Un, LineAnnotation as Ut, ImportOptions as V, Quad as Vn, InkAnnotation as Vt, importAnnotations as W, approxEqual as Wn, LineEnding$1 as Wt, AnnotationStore as X, quadsFromRect as Xn, MaskSchema as Xt, AnnotationEdit as Y, quadsFromFlat as Yn, MaskAnnotation as Yt, StoreMode as Z, rectContainsPoint as Zn, NoteAnnotation as Zt, ScopedToolStyle as _, FieldOption as _n, cssVariableDefaults as _t, SignatureOptions as a, QuadSchema as an, createRecordStore as at, StyleProps as b, FieldsChange as bn, Annotation$1 as bt, createImageTemplate as c, RedactSchema as cn, EmbeddedTarget as ct, createMemorySignatureStore as d, SquareSchema as dn, importedId as dt, PointSchema as en, rectFromQuads as er, deriveRect as et, createSignatureLibrary as f, StampAnnotation as fn, pdfColorToHex as ft, STYLE_GROUPS as g, FieldFlags as gn, AnnotationDefaults as gt, CurrentStyle as h, TextMarkupSchema as hn, FringeSchema as ht, SignatureLibrary as i, PolylineSchema as in, unionRects as ir, RecordStoreOptions as it, SearchHit as j, Readable as jn, ForeignAnnotation as jt, openDocument as k, WidgetAppearance as kn, ExportedAnnotation as kt, createInkTemplate as l, ShapeAnnotation as ln, SUPPORTED_SUBTYPES as lt, placeSignature as m, TextMarkupAnnotation as mn, Fringe$1 as mt, DEFAULT_SIGNATURE_WIDTH as n, PolySchema as nn, translateQuad as nr, RecordChange as nt, SignatureStore as o, RectSchema as on, EmbeddedFieldPatch as ot, normaliseInk as p, StampSchema as pn, summarise as pt, createHistory as q, pointsFromFlat as qn, LoupeAnnotation as qt, SIGNATURE_INK_WIDTH as r, PolygonSchema as rn, translateRect as rr, RecordStore as rt, SignatureTemplate as s, RedactAnnotation as sn, EmbeddedSummary as st, signField as t, PolyAnnotation as tn, rectsIntersect as tr, RecordBase as tt, createLocalSignatureStore as u, ShapeSchema as un, importEmbeddedPage as ut, StyleGroup as v, FieldValue as vn, normalizeColor as vt, DocumentInfo as w, FormField as wn, AnnotationOfType as wt, ToolStyle as x, FieldsMode as xn, AnnotationDocument as xt, StyleKey as y, FieldValues as yn, staticDefaults as yt, InkErrorCode as z, Matrix as zn, GLOSS_VERSION$1 as zt };
2959
+ //# sourceMappingURL=sign-47QLNaqQ.d.mts.map