@inkbar/svelte 0.7.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.
Files changed (32) hide show
  1. package/README.md +7 -0
  2. package/dist/components/InkFormAlert.svelte +108 -0
  3. package/dist/components/InkFormAlert.svelte.d.ts +13 -0
  4. package/dist/components/InkFormAlert.svelte.d.ts.map +1 -0
  5. package/dist/components/InkRoot.svelte +94 -2
  6. package/dist/components/InkRoot.svelte.d.ts +22 -2
  7. package/dist/components/InkRoot.svelte.d.ts.map +1 -1
  8. package/dist/components/InkSignFieldPopover.svelte +187 -0
  9. package/dist/components/InkSignFieldPopover.svelte.d.ts +10 -0
  10. package/dist/components/InkSignFieldPopover.svelte.d.ts.map +1 -0
  11. package/dist/components/InkSignatureDialog.svelte +11 -3
  12. package/dist/components/InkSignatureDialog.svelte.d.ts +9 -3
  13. package/dist/components/InkSignatureDialog.svelte.d.ts.map +1 -1
  14. package/dist/components/InkSignatureMenu.svelte +10 -99
  15. package/dist/components/InkSignatureMenu.svelte.d.ts.map +1 -1
  16. package/dist/components/InkViewport.svelte +44 -1
  17. package/dist/components/InkViewport.svelte.d.ts.map +1 -1
  18. package/dist/components/SignatureForm.svelte +7 -2
  19. package/dist/components/SignatureForm.svelte.d.ts +2 -0
  20. package/dist/components/SignatureForm.svelte.d.ts.map +1 -1
  21. package/dist/components/SignatureMenuPanel.svelte +127 -0
  22. package/dist/components/SignatureMenuPanel.svelte.d.ts +13 -0
  23. package/dist/components/SignatureMenuPanel.svelte.d.ts.map +1 -0
  24. package/dist/context.d.ts +7 -1
  25. package/dist/context.d.ts.map +1 -1
  26. package/dist/hooks/useForm.svelte.d.ts +17 -0
  27. package/dist/hooks/useForm.svelte.d.ts.map +1 -0
  28. package/dist/hooks/useForm.svelte.js +20 -0
  29. package/dist/index.d.ts +2 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +1 -0
  32. package/package.json +5 -5
package/README.md CHANGED
@@ -145,6 +145,12 @@ Inside `InkRoot`, `useHistory()` returns the same object. Its `batch(fn)` runs `
145
145
 
146
146
  `key` identifies the document. Reuse the same key when only the signed URL changes and the document is not reloaded.
147
147
 
148
+ ## Forms
149
+
150
+ `InkViewport` fills the PDF's form fields and runs the form's scripts. `useForm()` returns the fields, their values, and `set` and `reset`. Use `bind:fields` to hold the values in your own state. The form never submits, opens a link, sends mail or prints: `onformaction` hands each request to you. `formHighlight={false}` turns off the field tint, and a change applies to the open document in place.
151
+
152
+ The [forms guide](https://inkbar.dev/docs/guides/forms/) covers controlled fields, form actions, scripts, signature fields and saving values as Gloss.
153
+
148
154
  ## Thread popover
149
155
 
150
156
  `InkThreadPopover` opens the comment thread of the activated note or text markup (a highlight, underline, strikeout or squiggly). A new note or highlight has no text yet, so the form first writes its own `contents` (labelled "Comment"); after that it adds replies. A highlight with a comment shows a small marker at its end. Replies show in the thread only; the page draws just the note or highlight they answer.
@@ -202,6 +208,7 @@ The scroll area takes focus. From there:
202
208
  - With the `highlight` or `redact-area` tool active, `Enter` turns the text selection into a mark.
203
209
  - With the `note` tool active, `Enter` places a note at the centre of the current page and opens it.
204
210
  - With the `signature` tool active, `Enter` places the chosen signature at the centre of the current page.
211
+ - `Ctrl` or `Cmd` + `Z` undoes. `Ctrl` or `Cmd` + `Shift` + `Z`, or `Ctrl` + `Y`, redoes. `Ctrl` and `Cmd` both work on every platform. The keys do what `InkUndo` and `InkRedo` do, from anywhere in `InkRoot`, toolbars included, and act only while that button is enabled. In a text field or editable content the keys stay with the element, so a field keeps its own text undo. In a `<select>` they are left to the browser, which does nothing with them.
205
212
 
206
213
  On a focused annotation:
207
214
 
@@ -0,0 +1,108 @@
1
+ <script lang="ts">
2
+ /*
3
+ * A form script's `app.alert`: the message and OK, shown without blocking (no overlay, not
4
+ * modal), so the form stays usable around it. InkViewport mounts it; hosts compose nothing.
5
+ * OK, or Escape while focus is in the alert, closes it, and focus goes back where it was. A
6
+ * press outside leaves it open, and Escape anywhere else stays with the viewer. A new message
7
+ * replaces the one shown.
8
+ *
9
+ * The markup is core's `createFormAlert`, portalled to `<body>`. It is not a Bits UI dialog:
10
+ * Bits UI's escape layer takes every Escape on the page while it is open (it prevents the
11
+ * key's default), which would end the viewer's own use of the key.
12
+ */
13
+ import { FORM_LABELS } from '@inkbar/core/dom'
14
+ import { Portal } from 'bits-ui'
15
+ import { untrack } from 'svelte'
16
+
17
+ let {
18
+ message,
19
+ shown,
20
+ fallback,
21
+ onClose,
22
+ }: {
23
+ /** The message to show (text, not markup); `null` while none is. */
24
+ message: string | null
25
+ /** Counts the times a message was shown, so the same text shown again takes focus again. */
26
+ shown: number
27
+ /** Where focus goes when nothing it can return to is left. */
28
+ fallback: () => HTMLElement | null
29
+ onClose: () => void
30
+ } = $props()
31
+
32
+ const uid = $props.id()
33
+ let panel = $state<HTMLElement | null>(null)
34
+ let ok = $state<HTMLButtonElement | null>(null)
35
+ /** Where focus was when the alert opened. */
36
+ let returnTo: HTMLElement | null = null
37
+ let wasOpen = false
38
+ const open = $derived(message !== null)
39
+
40
+ // After the alert renders, before anything else moves focus: where focus was is read first.
41
+ $effect(() => {
42
+ const showing = open
43
+ void shown
44
+ const button = ok
45
+ if (!showing) {
46
+ wasOpen = false
47
+ return
48
+ }
49
+ if (!button) return
50
+ untrack(() => {
51
+ if (!wasOpen) {
52
+ wasOpen = true
53
+ const active = document.activeElement
54
+ returnTo =
55
+ active instanceof HTMLElement && active !== document.body ? active : null
56
+ }
57
+ button.focus({ preventScroll: true })
58
+ })
59
+ })
60
+
61
+ function close(): void {
62
+ // Focus that moved elsewhere while the alert showed stays there.
63
+ const hadFocus = !!panel?.contains(document.activeElement)
64
+ const back = returnTo?.isConnected === true ? returnTo : fallback()
65
+ onClose()
66
+ if (hadFocus) back?.focus({ preventScroll: true })
67
+ }
68
+
69
+ function onkeydown(e: KeyboardEvent): void {
70
+ if (e.key !== 'Escape' || e.defaultPrevented) return
71
+ e.preventDefault()
72
+ e.stopPropagation()
73
+ close()
74
+ }
75
+ </script>
76
+
77
+ {#if message !== null}
78
+ <Portal>
79
+ <div
80
+ bind:this={panel}
81
+ role="alertdialog"
82
+ aria-labelledby="{uid}-title"
83
+ aria-describedby="{uid}-message"
84
+ class="ink-dialog ink-form-alert"
85
+ data-ink-form-alert=""
86
+ data-state="open"
87
+ tabindex="-1"
88
+ {onkeydown}
89
+ >
90
+ <h2 id="{uid}-title" class="ink-dialog-title">{FORM_LABELS.alert}</h2>
91
+ <p id="{uid}-message" class="ink-form-alert-message" data-ink-form-alert-message="">
92
+ {message}
93
+ </p>
94
+ <div class="ink-dialog-actions">
95
+ <button
96
+ bind:this={ok}
97
+ type="button"
98
+ class="ink-button"
99
+ data-variant="primary"
100
+ data-ink-form-alert-ok=""
101
+ onclick={close}
102
+ >
103
+ {FORM_LABELS.ok}
104
+ </button>
105
+ </div>
106
+ </div>
107
+ </Portal>
108
+ {/if}
@@ -0,0 +1,13 @@
1
+ type $$ComponentProps = {
2
+ /** The message to show (text, not markup); `null` while none is. */
3
+ message: string | null;
4
+ /** Counts the times a message was shown, so the same text shown again takes focus again. */
5
+ shown: number;
6
+ /** Where focus goes when nothing it can return to is left. */
7
+ fallback: () => HTMLElement | null;
8
+ onClose: () => void;
9
+ };
10
+ declare const InkFormAlert: import("svelte").Component<$$ComponentProps, {}, "">;
11
+ type InkFormAlert = ReturnType<typeof InkFormAlert>;
12
+ export default InkFormAlert;
13
+ //# sourceMappingURL=InkFormAlert.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkFormAlert.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkFormAlert.svelte.ts"],"names":[],"mappings":"AAkBC,KAAK,gBAAgB,GAAI;IACtB,oEAAoE;IACpE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,4FAA4F;IAC5F,KAAK,EAAE,MAAM,CAAA;IACb,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,WAAW,GAAG,IAAI,CAAA;IAClC,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CAAC;AA6EJ,QAAA,MAAM,YAAY,sDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
@@ -5,6 +5,9 @@
5
5
  AnnotationChange,
6
6
  AnnotationDefaults,
7
7
  DocumentSource,
8
+ FieldsChange,
9
+ FieldValues,
10
+ FormAction,
8
11
  InkDocument,
9
12
  InkError,
10
13
  InkStatus,
@@ -38,6 +41,21 @@
38
41
  annotations?: Annotation[] | undefined
39
42
  onAnnotationsChange?: ((next: Annotation[]) => void) | undefined
40
43
  onChange?: ((change: AnnotationChange) => void) | undefined
44
+ /**
45
+ * Pass (with `bind:`) to put the form's field values under the host's control. A commit
46
+ * shows at once and is reported after; the host's push wins. The mode is fixed when a
47
+ * document opens, as for `annotations`.
48
+ */
49
+ fields?: FieldValues | undefined
50
+ /**
51
+ * Committed field values, in full, with what changed them. Called only while the fields
52
+ * are controlled, after the bound value is written.
53
+ */
54
+ onFieldsChange?: ((next: FieldValues, change: FieldsChange) => void) | undefined
55
+ /** The form asked to submit, open a link, send mail, print or prompt. Inkbar does none. */
56
+ onformaction?: ((action: FormAction) => void) | undefined
57
+ /** Tints fillable form fields. Default true. A change applies to the open document in place. */
58
+ formHighlight?: boolean | undefined
41
59
  tool?: ToolId | undefined
42
60
  onToolChange?: ((tool: ToolId) => void) | undefined
43
61
  /**
@@ -78,6 +96,11 @@
78
96
  /** Undo history. Defaults to on for uncontrolled, off for controlled. */
79
97
  history?: boolean | undefined
80
98
  onReady?: ((doc: InkDocument) => void) | undefined
99
+ /**
100
+ * Opening failed, or later: a form script failed (`FormScriptError`; the form stays
101
+ * fillable), or a signature field refused its signing (`FieldSigned`, `FieldReadOnly`).
102
+ * An error from while the document opened comes after `onReady`.
103
+ */
81
104
  onError?: ((error: InkError) => void) | undefined
82
105
  onActivate?: ((id: string) => void) | undefined
83
106
  /** The root element, for hosts that bind it. */
@@ -102,12 +125,14 @@
102
125
  writable,
103
126
  } from '@inkbar/core'
104
127
  import {
128
+ attachHistoryKeys,
105
129
  createPluginHost,
106
130
  createSearchController,
107
131
  createToolOptions,
108
132
  cssVariableDefaults,
109
133
  FONT_FAMILIES,
110
134
  handleFindKey,
135
+ keepHistoryFocus,
111
136
  pageSelectionText,
112
137
  SIGNATURE_FONTS,
113
138
  trackToolStyle,
@@ -136,6 +161,10 @@
136
161
  annotations = $bindable(),
137
162
  onAnnotationsChange,
138
163
  onChange,
164
+ fields = $bindable(),
165
+ onFieldsChange,
166
+ onformaction,
167
+ formHighlight,
139
168
  tool = $bindable(),
140
169
  onToolChange,
141
170
  tools: hostTools,
@@ -237,6 +266,7 @@
237
266
  let opened: InkDocument | null = null
238
267
  /** The snapshot history's hold on a controlled document's store. */
239
268
  let detach: () => void = noop
269
+ let stopFormErrors: () => void = noop
240
270
  untrack(() => snapshotHistory.clear())
241
271
  const source = untrack(() => src)
242
272
  if (source === null) {
@@ -269,6 +299,20 @@
269
299
  },
270
300
  }
271
301
  : { mode: 'uncontrolled' as const },
302
+ fields:
303
+ fields !== undefined
304
+ ? {
305
+ mode: 'controlled' as const,
306
+ initial: fields,
307
+ onChange: (next: FieldValues, change: FieldsChange) => {
308
+ // As for annotations: a commit made in the tick this root unmounts or
309
+ // reopens never reaches the host.
310
+ if (cancelled) return
311
+ fields = next
312
+ onFieldsChange?.(next, change)
313
+ },
314
+ }
315
+ : { mode: 'uncontrolled' as const },
272
316
  }))
273
317
  )
274
318
  if (cancelled) {
@@ -280,6 +324,17 @@
280
324
  const current = untrack(() => annotations)
281
325
  if (doc.annotations.mode === 'controlled' && current !== undefined)
282
326
  doc.annotations.setControlledValue(current)
327
+ // The same for the fields; a document whose fields opened uncontrolled ignores the push.
328
+ const currentFields = untrack(() => fields)
329
+ if (currentFields !== undefined) doc.form.setControlledValue(currentFields)
330
+ // A form script that fails leaves the form fillable; the failure goes to `onError`.
331
+ // Subscribed before anyone hears of the document, so the form replays the errors from
332
+ // while it opened here; they are held until `onReady` has run.
333
+ let held: InkError[] | undefined = []
334
+ stopFormErrors = doc.form.on('error', (e) => {
335
+ if (held) held.push(e)
336
+ else onError?.(e)
337
+ })
283
338
  documentNow = doc
284
339
  document = doc
285
340
  // Controlled edits run the plugins' reactions inside their own snapshot step.
@@ -290,8 +345,15 @@
290
345
  override = null
291
346
  setTestHook(ref, doc)
292
347
  const s = doc.status.get()
293
- if (s.state === 'ready') onReady?.(doc)
294
- else if (s.state === 'error') onError?.(s.error)
348
+ try {
349
+ if (s.state === 'ready') onReady?.(doc)
350
+ else if (s.state === 'error') onError?.(s.error)
351
+ } finally {
352
+ // A host whose `onReady` throws still hears the held errors and every later one.
353
+ const early = held
354
+ held = undefined
355
+ if (!cancelled) for (const e of early) onError?.(e)
356
+ }
295
357
  } catch (cause) {
296
358
  if (cancelled) return
297
359
  const error =
@@ -312,6 +374,7 @@
312
374
  // Cleared first, so the plugins close their stores while the document is still alive.
313
375
  hostDocument.set(null)
314
376
  detach()
377
+ stopFormErrors()
315
378
  opened?.destroy()
316
379
  documentNow = null
317
380
  document = null
@@ -327,6 +390,15 @@
327
390
  untrack(() => doc.annotations.setControlledValue(list))
328
391
  })
329
392
 
393
+ // The host's field values reach the form; the echo of a commit it applied changes nothing.
394
+ // Read through a derived, so a host that spreads its props pushes only a new value.
395
+ const pushedFields = $derived(fields)
396
+ $effect(() => {
397
+ const values = pushedFields
398
+ const doc = document
399
+ if (values && doc) untrack(() => doc.form.setControlledValue(values))
400
+ })
401
+
330
402
  function setTool(id: ToolId): void {
331
403
  // Picking the active tool again starts it afresh, as after a one-shot tool's use.
332
404
  if (currentTool === id && tools?.active.get() === id) tools.set(id)
@@ -371,6 +443,21 @@
371
443
  react: (fn) => pluginHistory.react(fn),
372
444
  }
373
445
 
446
+ // The undo and redo keys anywhere in the root do what InkUndo and InkRedo do. When either
447
+ // button undoes or redoes the last step and disables itself, focus goes back to the document.
448
+ $effect(() => {
449
+ const el = ref
450
+ if (!el) return
451
+ const stopKeys = attachHistoryKeys(el, () => inkHistory)
452
+ const stopFocus = keepHistoryFocus(el, () =>
453
+ el.querySelector<HTMLElement>('[data-ink-scroll]')
454
+ )
455
+ return () => {
456
+ stopKeys()
457
+ stopFocus()
458
+ }
459
+ })
460
+
374
461
  /**
375
462
  * The history the plugins reach, picked by the open document's mode when they call. The host
376
463
  * reads it as soon as a document opens, so it goes by `documentNow`, which is set by then.
@@ -545,6 +632,11 @@
545
632
  viewport = vp
546
633
  tools = tc
547
634
  },
635
+ get formHighlight() {
636
+ return formHighlight
637
+ },
638
+ reportFormAction: (a) => onformaction?.(a),
639
+ reportError: (e) => onError?.(e),
548
640
  }
549
641
  setInkContext(context, () => activatedNow)
550
642
 
@@ -1,5 +1,5 @@
1
1
  import type { ChildSnippet } from './child-snippet.js';
2
- import type { Annotation, AnnotationChange, AnnotationDefaults, DocumentSource, InkDocument, InkError, InkStatus, PdfAssets, SignatureStore } from '@inkbar/core';
2
+ import type { Annotation, AnnotationChange, AnnotationDefaults, DocumentSource, FieldsChange, FieldValues, FormAction, InkDocument, InkError, InkStatus, PdfAssets, SignatureStore } from '@inkbar/core';
3
3
  import type { DecorateAnnotation, InkPlugin, Tool, ToolId, ZoomValue } from '@inkbar/core/dom';
4
4
  import type { Snippet } from 'svelte';
5
5
  import type { HTMLAttributes } from 'svelte/elements';
@@ -17,6 +17,21 @@ export interface InkRootProps extends Omit<HTMLAttributes<HTMLDivElement>, 'chil
17
17
  annotations?: Annotation[] | undefined;
18
18
  onAnnotationsChange?: ((next: Annotation[]) => void) | undefined;
19
19
  onChange?: ((change: AnnotationChange) => void) | undefined;
20
+ /**
21
+ * Pass (with `bind:`) to put the form's field values under the host's control. A commit
22
+ * shows at once and is reported after; the host's push wins. The mode is fixed when a
23
+ * document opens, as for `annotations`.
24
+ */
25
+ fields?: FieldValues | undefined;
26
+ /**
27
+ * Committed field values, in full, with what changed them. Called only while the fields
28
+ * are controlled, after the bound value is written.
29
+ */
30
+ onFieldsChange?: ((next: FieldValues, change: FieldsChange) => void) | undefined;
31
+ /** The form asked to submit, open a link, send mail, print or prompt. Inkbar does none. */
32
+ onformaction?: ((action: FormAction) => void) | undefined;
33
+ /** Tints fillable form fields. Default true. A change applies to the open document in place. */
34
+ formHighlight?: boolean | undefined;
20
35
  tool?: ToolId | undefined;
21
36
  onToolChange?: ((tool: ToolId) => void) | undefined;
22
37
  /**
@@ -57,6 +72,11 @@ export interface InkRootProps extends Omit<HTMLAttributes<HTMLDivElement>, 'chil
57
72
  /** Undo history. Defaults to on for uncontrolled, off for controlled. */
58
73
  history?: boolean | undefined;
59
74
  onReady?: ((doc: InkDocument) => void) | undefined;
75
+ /**
76
+ * Opening failed, or later: a form script failed (`FormScriptError`; the form stays
77
+ * fillable), or a signature field refused its signing (`FieldSigned`, `FieldReadOnly`).
78
+ * An error from while the document opened comes after `onReady`.
79
+ */
60
80
  onError?: ((error: InkError) => void) | undefined;
61
81
  onActivate?: ((id: string) => void) | undefined;
62
82
  /** The root element, for hosts that bind it. */
@@ -76,7 +96,7 @@ declare const InkRoot: import("svelte").Component<InkRootProps, {
76
96
  history: InkHistory;
77
97
  getDocument: () => InkDocument | null;
78
98
  getStatus: () => InkStatus;
79
- }, "page" | "annotations" | "tool" | "zoom" | "ref">;
99
+ }, "page" | "annotations" | "fields" | "tool" | "zoom" | "ref">;
80
100
  type InkRoot = ReturnType<typeof InkRoot>;
81
101
  export default InkRoot;
82
102
  //# sourceMappingURL=InkRoot.svelte.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"InkRoot.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkRoot.svelte.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"InkRoot.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkRoot.svelte.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,187 @@
1
+ <script lang="ts">
2
+ /*
3
+ * The signature menu for a signature field, opened from the field's "Sign" button and
4
+ * anchored to its box. It lists the saved signatures and "Create signature", as
5
+ * `InkSignatureMenu` does. Picking one signs the field with it (`signField`); a signature
6
+ * made in `InkSignatureDialog` signs the field once saved, without picking the signature
7
+ * tool. Focus returns to the field. InkViewport mounts it, one per document; hosts compose
8
+ * nothing.
9
+ */
10
+ import { InkError, signField } from '@inkbar/core'
11
+ import {
12
+ handleMenuKeys,
13
+ SIGNATURE_LABELS,
14
+ signatureMenuModel,
15
+ watchDetached,
16
+ } from '@inkbar/core/dom'
17
+ import { Popover } from 'bits-ui'
18
+ import { untrack } from 'svelte'
19
+
20
+ import { useInkContext } from '../context.js'
21
+ import { useReadable } from '../use-readable.svelte.js'
22
+
23
+ import InkSignatureDialog from './InkSignatureDialog.svelte'
24
+ import { createMenuOpenFocus } from './menu-open-focus.js'
25
+ import SignatureMenuPanel from './SignatureMenuPanel.svelte'
26
+
27
+ import type { InkDocument, SignatureTemplate } from '@inkbar/core'
28
+ import type { SignFieldRequest } from '@inkbar/core/dom'
29
+
30
+ let {
31
+ request,
32
+ onClose,
33
+ }: {
34
+ /** The field to sign; `null` while the menu is closed. */
35
+ request: SignFieldRequest | null
36
+ onClose: () => void
37
+ } = $props()
38
+
39
+ const NO_TEMPLATES: readonly SignatureTemplate[] = []
40
+
41
+ const ctx = useInkContext('InkSignFieldPopover')
42
+ const templates = useReadable(() => ctx.signatures.templates, NO_TEMPLATES)
43
+ // No signature is "chosen" here: each signing picks its own.
44
+ const model = $derived(signatureMenuModel(templates.current, {}))
45
+ const open = $derived(request !== null)
46
+ let menu = $state<HTMLElement | null>(null)
47
+ /** The field the dialog signs once its signature is saved, and the document it is in. */
48
+ let creatingFor = $state.raw<{ req: SignFieldRequest; doc: InkDocument } | null>(null)
49
+ /**
50
+ * The request the menu last opened for, kept to return focus once it closes. Untracked:
51
+ * Bits UI reports the close from an effect teardown, where a reactive read of `request`
52
+ * returns the value from before the close.
53
+ */
54
+ let last: SignFieldRequest | null = null
55
+ /** Set while the menu closes for the dialog, which takes focus instead of the field. */
56
+ let toDialog = false
57
+ /** Cleared on destroy, so a dialog save that settles after the document went signs nothing. */
58
+ let alive = true
59
+ $effect(() => () => {
60
+ alive = false
61
+ })
62
+
63
+ $effect(() => {
64
+ if (request) last = request
65
+ })
66
+ // The field's box went (its page unmounted, its layer rebuilt): the menu has nothing to
67
+ // stand by.
68
+ $effect(() => {
69
+ const req = request
70
+ if (!req) return
71
+ return watchDetached(req.anchor, () => untrack(onClose))
72
+ })
73
+ // An old removal error is not news when the menu opens again.
74
+ $effect(() => {
75
+ if (open) untrack(() => ctx.signatures.clearRemoveError())
76
+ })
77
+ const openFocus = createMenuOpenFocus()
78
+ $effect(() => {
79
+ if (!open) openFocus.reset()
80
+ })
81
+
82
+ /** The field's own button, which focus returns to. */
83
+ const control = (req: SignFieldRequest | null): HTMLElement | null =>
84
+ req?.anchor.querySelector<HTMLElement>('button.ink-form-control') ?? null
85
+
86
+ /** Focus goes back to the field's button, or to the scroll element once the field's box has gone. */
87
+ function returnFocus(req: SignFieldRequest | null): void {
88
+ const c = control(req)
89
+ ;(c?.isConnected ? c : ctx.viewportEl.get())?.focus({ preventScroll: true })
90
+ }
91
+
92
+ /** Signs the request's field with `t`; a refusal (signed, read-only by now) goes to `onError`. */
93
+ function sign(req: SignFieldRequest, doc: InkDocument, t: SignatureTemplate): void {
94
+ // The document the request came from is still the open one.
95
+ if (!alive || ctx.document !== doc) return
96
+ try {
97
+ signField(doc, req.field, req.widget, t)
98
+ } catch (e) {
99
+ if (!(e instanceof InkError)) throw e
100
+ ctx.reportError(e)
101
+ }
102
+ }
103
+
104
+ function choose(t: SignatureTemplate): void {
105
+ const req = request
106
+ const doc = ctx.document
107
+ onClose()
108
+ if (req && doc) sign(req, doc, t)
109
+ }
110
+
111
+ function create(): void {
112
+ const req = request
113
+ const doc = ctx.document
114
+ if (!req || !doc) return
115
+ toDialog = true
116
+ creatingFor = { req, doc }
117
+ onClose()
118
+ }
119
+
120
+ function onInteractOutside(e: PointerEvent): void {
121
+ // A press on this field's own button toggles the menu through the engine; it must not
122
+ // also close it here first, or the click would open it again.
123
+ const target = e.target
124
+ if (target instanceof Node && request?.anchor.contains(target)) e.preventDefault()
125
+ }
126
+ </script>
127
+
128
+ <Popover.Root
129
+ bind:open={
130
+ () => open,
131
+ (next) => {
132
+ if (!next) onClose()
133
+ }
134
+ }
135
+ >
136
+ <Popover.Portal>
137
+ {#if request}
138
+ <Popover.Content
139
+ bind:ref={menu}
140
+ role="menu"
141
+ aria-label={SIGNATURE_LABELS.menu}
142
+ class="ink-select-content ink-menu-content"
143
+ data-ink-select-content=""
144
+ data-ink-menu="signature"
145
+ data-ink-sign-field-menu={request.field}
146
+ customAnchor={request.anchor}
147
+ side="bottom"
148
+ align="start"
149
+ sideOffset={4}
150
+ collisionPadding={8}
151
+ onOpenAutoFocus={(e) => openFocus.onOpenAutoFocus(e, menu)}
152
+ onfocusin={openFocus.onfocusin}
153
+ onCloseAutoFocus={(e) => {
154
+ e.preventDefault()
155
+ if (!toDialog) returnFocus(last)
156
+ toDialog = false
157
+ }}
158
+ {onInteractOutside}
159
+ onkeydown={(e) => menu && handleMenuKeys(e, menu)}
160
+ >
161
+ <SignatureMenuPanel
162
+ items={model.items}
163
+ menu={() => menu}
164
+ onChoose={choose}
165
+ onCreate={create}
166
+ />
167
+ </Popover.Content>
168
+ {/if}
169
+ </Popover.Portal>
170
+ </Popover.Root>
171
+ <InkSignatureDialog
172
+ bind:open={
173
+ () => creatingFor !== null,
174
+ (next) => {
175
+ if (!next) creatingFor = null
176
+ }
177
+ }
178
+ select={false}
179
+ onSave={(t) => {
180
+ const c = creatingFor
181
+ if (c) sign(c.req, c.doc, t)
182
+ }}
183
+ onCloseAutoFocus={(e) => {
184
+ e.preventDefault()
185
+ returnFocus(last)
186
+ }}
187
+ />
@@ -0,0 +1,10 @@
1
+ import type { SignFieldRequest } from '@inkbar/core/dom';
2
+ type $$ComponentProps = {
3
+ /** The field to sign; `null` while the menu is closed. */
4
+ request: SignFieldRequest | null;
5
+ onClose: () => void;
6
+ };
7
+ declare const InkSignFieldPopover: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type InkSignFieldPopover = ReturnType<typeof InkSignFieldPopover>;
9
+ export default InkSignFieldPopover;
10
+ //# sourceMappingURL=InkSignFieldPopover.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkSignFieldPopover.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkSignFieldPopover.svelte.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAExD,KAAK,gBAAgB,GAAI;IACtB,0DAA0D;IAC1D,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAChC,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CAAC;AA2IJ,QAAA,MAAM,mBAAmB,sDAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
@@ -4,15 +4,21 @@
4
4
  /**
5
5
  * "Create signature": a modal with Draw, Type and Image tabs. Draw is a pad with the draw
6
6
  * tool's renderer; Type sets a name in one of the host's handwriting fonts; Image takes a PNG
7
- * or JPEG scan. Save stores the template through InkRoot's signature store and selects it
8
- * for the `signature` tool. Escape, Cancel or a press outside closes it.
7
+ * or JPEG scan. Save stores the template through InkRoot's signature store and, unless
8
+ * `select` is false, selects it for the `signature` tool. Escape, Cancel or a press outside
9
+ * closes it.
9
10
  */
10
11
  export interface InkSignatureDialogProps {
11
12
  open?: boolean
12
13
  onOpenChange?: ((open: boolean) => void) | undefined
13
14
  /** The fonts the Type tab offers. Default: InkRoot's `signatureFonts`. */
14
15
  fonts?: readonly string[] | undefined
15
- /** Called with the new template once it is saved and selected. */
16
+ /**
17
+ * Whether saving selects the new signature for the `signature` tool. Default true. False
18
+ * leaves the tool alone, for a dialog that signs a field with it through `onSave`.
19
+ */
20
+ select?: boolean | undefined
21
+ /** Called with the new template once it is saved (and selected, with `select`). */
16
22
  onSave?: ((template: SignatureTemplate) => void) | undefined
17
23
  /** Where focus goes on close; by default, back to what had it before. */
18
24
  onCloseAutoFocus?: ((event: Event) => void) | undefined
@@ -30,6 +36,7 @@
30
36
  open = $bindable(false),
31
37
  onOpenChange,
32
38
  fonts,
39
+ select = true,
33
40
  onSave,
34
41
  onCloseAutoFocus,
35
42
  class: className,
@@ -62,6 +69,7 @@
62
69
  <Dialog.Title class="ink-dialog-title">{SIGNATURE_LABELS.dialog}</Dialog.Title>
63
70
  <SignatureForm
64
71
  {fonts}
72
+ {select}
65
73
  onSaved={(t) => onSave?.(t)}
66
74
  onClose={() => setOpen(false)}
67
75
  />
@@ -2,15 +2,21 @@ import type { SignatureTemplate } from '@inkbar/core';
2
2
  /**
3
3
  * "Create signature": a modal with Draw, Type and Image tabs. Draw is a pad with the draw
4
4
  * tool's renderer; Type sets a name in one of the host's handwriting fonts; Image takes a PNG
5
- * or JPEG scan. Save stores the template through InkRoot's signature store and selects it
6
- * for the `signature` tool. Escape, Cancel or a press outside closes it.
5
+ * or JPEG scan. Save stores the template through InkRoot's signature store and, unless
6
+ * `select` is false, selects it for the `signature` tool. Escape, Cancel or a press outside
7
+ * closes it.
7
8
  */
8
9
  export interface InkSignatureDialogProps {
9
10
  open?: boolean;
10
11
  onOpenChange?: ((open: boolean) => void) | undefined;
11
12
  /** The fonts the Type tab offers. Default: InkRoot's `signatureFonts`. */
12
13
  fonts?: readonly string[] | undefined;
13
- /** Called with the new template once it is saved and selected. */
14
+ /**
15
+ * Whether saving selects the new signature for the `signature` tool. Default true. False
16
+ * leaves the tool alone, for a dialog that signs a field with it through `onSave`.
17
+ */
18
+ select?: boolean | undefined;
19
+ /** Called with the new template once it is saved (and selected, with `select`). */
14
20
  onSave?: ((template: SignatureTemplate) => void) | undefined;
15
21
  /** Where focus goes on close; by default, back to what had it before. */
16
22
  onCloseAutoFocus?: ((event: Event) => void) | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"InkSignatureDialog.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkSignatureDialog.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAErD;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACpD,0EAA0E;IAC1E,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;IACrC,kEAAkE;IAClE,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAC5D,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACvD,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC3B;AAkDH,QAAA,MAAM,kBAAkB,iEAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"InkSignatureDialog.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkSignatureDialog.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAErD;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACpD,0EAA0E;IAC1E,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;IACrC;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC5B,mFAAmF;IACnF,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAC5D,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACvD,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC3B;AAmDH,QAAA,MAAM,kBAAkB,iEAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
@@ -20,15 +20,10 @@
20
20
  </script>
21
21
 
22
22
  <script lang="ts">
23
- import {
24
- handleMenuKeys,
25
- SIGNATURE_LABELS,
26
- signatureMenuModel,
27
- signaturePreview,
28
- } from '@inkbar/core/dom'
29
- import { ChevronDown, Plus, Signature, Trash2 } from '@inkbar/icons'
23
+ import { handleMenuKeys, SIGNATURE_LABELS, signatureMenuModel } from '@inkbar/core/dom'
24
+ import { ChevronDown, Signature } from '@inkbar/icons'
30
25
  import { Popover, Toolbar } from 'bits-ui'
31
- import { tick, untrack } from 'svelte'
26
+ import { untrack } from 'svelte'
32
27
 
33
28
  import { useInkContext } from '../context.js'
34
29
  import { useTool } from '../hooks/useTool.svelte.js'
@@ -38,6 +33,7 @@
38
33
  import InkIcon from './InkIcon.svelte'
39
34
  import InkSignatureDialog from './InkSignatureDialog.svelte'
40
35
  import { createMenuOpenFocus } from './menu-open-focus.js'
36
+ import SignatureMenuPanel from './SignatureMenuPanel.svelte'
41
37
 
42
38
  import type { SignatureOptions, SignatureTemplate } from '@inkbar/core'
43
39
 
@@ -49,7 +45,6 @@
49
45
  const current = useTool()
50
46
  const signature = useToolOptions<SignatureOptions>('signature')
51
47
  const templates = useReadable(() => ctx.signatures.templates, NO_TEMPLATES)
52
- const removeError = useReadable(() => ctx.signatures.removeError, undefined)
53
48
  // An old removal error is not news when the menu opens again.
54
49
  $effect(() => {
55
50
  if (open) untrack(() => ctx.signatures.clearRemoveError())
@@ -89,24 +84,6 @@
89
84
  open = false
90
85
  }
91
86
 
92
- /** Removes a template; focus moves to the signature now in its row, else "Create signature". */
93
- function remove(id: string, row: number): void {
94
- ctx.signatures.remove(id).then(
95
- async () => {
96
- await tick()
97
- if (!menu) return
98
- const rows = menu.querySelectorAll<HTMLElement>('.ink-signature-item')
99
- const next =
100
- rows[Math.min(row, rows.length - 1)] ??
101
- menu.querySelector<HTMLElement>('[data-ink-signature-create]')
102
- next?.focus({ preventScroll: true })
103
- },
104
- () => {
105
- // The host's store refused: the signature stays.
106
- }
107
- )
108
- }
109
-
110
87
  function create(): void {
111
88
  toDialog = true
112
89
  open = false
@@ -174,78 +151,12 @@
174
151
  }}
175
152
  onkeydown={(e) => menu && handleMenuKeys(e, menu)}
176
153
  >
177
- {#if model.items.length > 0}
178
- <div
179
- role="group"
180
- aria-label={SIGNATURE_LABELS.saved}
181
- class="ink-signature-list"
182
- data-ink-menu-columns="2"
183
- >
184
- {#each model.items as item, row (item.id)}
185
- {@const preview =
186
- item.template.kind === 'ink' ? signaturePreview(item.template) : null}
187
- <button
188
- type="button"
189
- role="menuitemradio"
190
- aria-checked={item.checked}
191
- aria-label={item.label}
192
- tabindex={-1}
193
- class="ink-select-item ink-menu-item ink-signature-item"
194
- data-ink-select-item=""
195
- data-key={item.id}
196
- data-state={item.checked ? 'checked' : 'unchecked'}
197
- onclick={() => choose(item.id)}
198
- >
199
- <span class="ink-signature-preview" data-kind={item.template.kind}>
200
- {#if item.template.kind === 'image'}
201
- <img src={item.template.imagedata} alt="" draggable="false" />
202
- {:else if preview}
203
- <svg viewBox={preview.viewBox} aria-hidden="true">
204
- {#each preview.paths as d, i (i)}
205
- <path {d} fill="currentColor" />
206
- {/each}
207
- </svg>
208
- {/if}
209
- </span>
210
- </button>
211
- <button
212
- type="button"
213
- role="menuitem"
214
- aria-label={item.removeLabel}
215
- title={item.removeLabel}
216
- tabindex={-1}
217
- class="ink-menu-item ink-signature-remove"
218
- data-ink-signature-remove=""
219
- data-key={item.id}
220
- onclick={() => remove(item.id, row)}
221
- >
222
- <InkIcon icon={Trash2} size={16} />
223
- </button>
224
- {/each}
225
- </div>
226
- <div role="separator" class="ink-select-separator"></div>
227
- {/if}
228
- <button
229
- type="button"
230
- role="menuitem"
231
- tabindex={-1}
232
- class="ink-select-item ink-menu-item ink-signature-create"
233
- data-ink-select-item=""
234
- data-ink-signature-create=""
235
- onclick={create}
236
- >
237
- <InkIcon icon={Plus} size={16} />
238
- {SIGNATURE_LABELS.create}
239
- </button>
240
- {#if removeError.current}
241
- <p
242
- class="ink-field-error ink-signature-remove-error"
243
- role="alert"
244
- data-ink-signature-remove-error=""
245
- >
246
- {removeError.current}
247
- </p>
248
- {/if}
154
+ <SignatureMenuPanel
155
+ items={model.items}
156
+ menu={() => menu}
157
+ onChoose={(t) => choose(t.id)}
158
+ onCreate={create}
159
+ />
249
160
  </Popover.Content>
250
161
  </Popover.Portal>
251
162
  </Popover.Root>
@@ -1 +1 @@
1
- {"version":3,"file":"InkSignatureMenu.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkSignatureMenu.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD;;;;;GAKG;AACH,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CACjD,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,CACX;IACC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC9B,mFAAmF;IACnF,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;CACtC;AAkLH,QAAA,MAAM,gBAAgB,2DAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"InkSignatureMenu.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkSignatureMenu.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD;;;;;GAKG;AACH,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CACjD,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,CACX;IACC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC9B,mFAAmF;IACnF,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;CACtC;AA2HH,QAAA,MAAM,gBAAgB,2DAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
@@ -34,16 +34,28 @@
34
34
  * Two-way zoom and page: the viewport's own changes are reported through the context, and
35
35
  * the host's props are applied only when they differ from the viewport's state, so the echo
36
36
  * of a reported value does nothing.
37
+ *
38
+ * Form fields render in the engine's form layer. A signature field's "Sign" opens
39
+ * `InkSignFieldPopover`, and a form script's alert shows in `InkFormAlert`; both are mounted
40
+ * here, so hosts compose nothing for them.
37
41
  */
38
42
  import { mountViewer } from '@inkbar/core/dom'
39
43
  import { untrack } from 'svelte'
40
44
 
41
45
  import { useInkContext } from '../context.js'
42
46
 
47
+ import InkFormAlert from './InkFormAlert.svelte'
43
48
  import InkPage from './InkPage.svelte'
49
+ import InkSignFieldPopover from './InkSignFieldPopover.svelte'
44
50
 
45
51
  import type { InkDocument, InkStatus } from '@inkbar/core'
46
- import type { PageMount, ToolId, ViewerEngine, ZoomValue } from '@inkbar/core/dom'
52
+ import type {
53
+ PageMount,
54
+ SignFieldRequest,
55
+ ToolId,
56
+ ViewerEngine,
57
+ ZoomValue,
58
+ } from '@inkbar/core/dom'
47
59
 
48
60
  let {
49
61
  mode = 'continuous',
@@ -74,6 +86,10 @@
74
86
  let scroll = $state<HTMLDivElement | null>(null)
75
87
  /** Page hosts, mounts and errors the engine reported; InkPage renders portals for them. */
76
88
  let pages = $state.raw<MountedPage[]>([])
89
+ /** The signature field whose menu is open. */
90
+ let signRequest = $state.raw<SignFieldRequest | null>(null)
91
+ /** The form script's message on show, and how many have been shown. */
92
+ let alert = $state.raw<{ message: string; shown: number } | null>(null)
77
93
 
78
94
  let engine: ViewerEngine | null = null
79
95
  /**
@@ -101,6 +117,9 @@
101
117
  builtWith = null
102
118
  ctx.setViewport(null, null)
103
119
  if (pages.length > 0) pages = []
120
+ // Their fields and the document they came from are gone.
121
+ signRequest = null
122
+ alert = null
104
123
  }
105
124
 
106
125
  function setup(
@@ -140,6 +159,15 @@
140
159
  // Read through, so a new `signatures` store reaches the tool as well as the menus.
141
160
  signatureLibrary: () => ctx.signatures,
142
161
  customAnnotations: custom,
162
+ ...(ctx.formHighlight === undefined ? {} : { formHighlight: ctx.formHighlight }),
163
+ // The field's own button again, while its menu is open, closes the menu.
164
+ onSignField: (req) => {
165
+ signRequest = signRequest?.widget === req.widget ? null : req
166
+ },
167
+ onFormAction: (a) => ctx.reportFormAction(a),
168
+ onFormAlert: (message) => {
169
+ alert = { message, shown: (alert?.shown ?? 0) + 1 }
170
+ },
143
171
  onActivate: (id) => ctx.setActivated(id),
144
172
  onBuild: (vp, tc) => {
145
173
  ctx.setViewport(vp, tc)
@@ -280,6 +308,11 @@
280
308
  const tc = engine?.tools
281
309
  if (tc && tc.active.get() !== t) untrack(() => tc.set(t))
282
310
  })
311
+ // The tint follows `formHighlight` in place, without a new document.
312
+ $effect(() => {
313
+ const on = ctx.formHighlight ?? true
314
+ untrack(() => engine?.setFormHighlight(on))
315
+ })
283
316
  // The build applied both; these only act on a later change, not on mount.
284
317
  $effect(() => {
285
318
  const m = mode
@@ -342,4 +375,14 @@
342
375
  {pageError}
343
376
  />
344
377
  {/each}
378
+ <!-- Keyed by document, so the menu and its dialog start afresh for each one. -->
379
+ {#key buildDocument}
380
+ <InkSignFieldPopover request={signRequest} onClose={() => (signRequest = null)} />
381
+ {/key}
382
+ <InkFormAlert
383
+ message={alert?.message ?? null}
384
+ shown={alert?.shown ?? 0}
385
+ fallback={() => scroll}
386
+ onClose={() => (alert = null)}
387
+ />
345
388
  </div>
@@ -1 +1 @@
1
- {"version":3,"file":"InkViewport.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkViewport.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACrF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAC5C,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,CACX;IACC,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC7B,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;QAAE,KAAK,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC,GAAG,SAAS,CAAA;IAClD,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC,mBAAmB,CAAC,CAAC,GAAG,SAAS,CAAA;IACvD,wFAAwF;IACxF,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;QAAE,KAAK,EAAE,QAAQ,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,GAAG,SAAS,CAAA;CACrE;AA8TH,QAAA,MAAM,WAAW,sDAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"InkViewport.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkViewport.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACrF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAC5C,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,CACX;IACC,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC7B,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;QAAE,KAAK,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC,GAAG,SAAS,CAAA;IAClD,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC,mBAAmB,CAAC,CAAC,GAAG,SAAS,CAAA;IACvD,wFAAwF;IACxF,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;QAAE,KAAK,EAAE,QAAQ,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,GAAG,SAAS,CAAA;CACrE;AAsWH,QAAA,MAAM,WAAW,sDAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -24,10 +24,13 @@
24
24
 
25
25
  let {
26
26
  fonts,
27
+ select,
27
28
  onSaved,
28
29
  onClose,
29
30
  }: {
30
31
  fonts: readonly string[] | undefined
32
+ /** Whether saving selects the new signature for the `signature` tool. */
33
+ select: boolean
31
34
  onSaved: (t: SignatureTemplate) => void
32
35
  onClose: () => void
33
36
  } = $props()
@@ -54,8 +57,10 @@
54
57
  draft.save(ctx.signatures).then(
55
58
  (t) => {
56
59
  if (!t) return
57
- signature.setOptions({ templateId: t.id })
58
- current.setTool('signature')
60
+ if (select) {
61
+ signature.setOptions({ templateId: t.id })
62
+ current.setTool('signature')
63
+ }
59
64
  onSaved(t)
60
65
  onClose()
61
66
  },
@@ -1,6 +1,8 @@
1
1
  import type { SignatureTemplate } from '@inkbar/core';
2
2
  type $$ComponentProps = {
3
3
  fonts: readonly string[] | undefined;
4
+ /** Whether saving selects the new signature for the `signature` tool. */
5
+ select: boolean;
4
6
  onSaved: (t: SignatureTemplate) => void;
5
7
  onClose: () => void;
6
8
  };
@@ -1 +1 @@
1
- {"version":3,"file":"SignatureForm.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/SignatureForm.svelte.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAoB,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEvE,KAAK,gBAAgB,GAAI;IACtB,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;IACpC,OAAO,EAAE,CAAC,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACvC,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CAAC;AAuHJ,QAAA,MAAM,aAAa,sDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"SignatureForm.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/SignatureForm.svelte.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAoB,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEvE,KAAK,gBAAgB,GAAI;IACtB,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;IACpC,yEAAyE;IACzE,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,CAAC,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACvC,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CAAC;AA0HJ,QAAA,MAAM,aAAa,sDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
@@ -0,0 +1,127 @@
1
+ <script lang="ts">
2
+ /*
3
+ * The signature menu's items: the saved signatures as previews, each with a remove button,
4
+ * then "Create signature", and the store's removal error. The toolbar's `InkSignatureMenu`
5
+ * and a signature field's `InkSignFieldPopover` both render it inside their `role="menu"`
6
+ * content, which `menu` returns.
7
+ */
8
+ import { SIGNATURE_LABELS, signaturePreview } from '@inkbar/core/dom'
9
+ import { Plus, Trash2 } from '@inkbar/icons'
10
+ import { tick } from 'svelte'
11
+
12
+ import { useInkContext } from '../context.js'
13
+ import { useReadable } from '../use-readable.svelte.js'
14
+
15
+ import InkIcon from './InkIcon.svelte'
16
+
17
+ import type { SignatureTemplate } from '@inkbar/core'
18
+ import type { SignatureMenuItem } from '@inkbar/core/dom'
19
+
20
+ let {
21
+ items,
22
+ menu,
23
+ onChoose,
24
+ onCreate,
25
+ }: {
26
+ items: readonly SignatureMenuItem[]
27
+ /** The menu element the items sit in, for moving focus after a removal. */
28
+ menu: () => HTMLElement | null
29
+ onChoose: (template: SignatureTemplate) => void
30
+ onCreate: () => void
31
+ } = $props()
32
+
33
+ const ctx = useInkContext('SignatureMenuPanel')
34
+ const removeError = useReadable(() => ctx.signatures.removeError, undefined)
35
+
36
+ /** Removes a template; focus moves to the signature now in its row, else "Create signature". */
37
+ function remove(id: string, row: number): void {
38
+ ctx.signatures.remove(id).then(
39
+ async () => {
40
+ await tick()
41
+ const panel = menu()
42
+ if (!panel) return
43
+ const rows = panel.querySelectorAll<HTMLElement>('.ink-signature-item')
44
+ const next =
45
+ rows[Math.min(row, rows.length - 1)] ??
46
+ panel.querySelector<HTMLElement>('[data-ink-signature-create]')
47
+ next?.focus({ preventScroll: true })
48
+ },
49
+ () => {
50
+ // The host's store refused: the signature stays.
51
+ }
52
+ )
53
+ }
54
+ </script>
55
+
56
+ {#if items.length > 0}
57
+ <div
58
+ role="group"
59
+ aria-label={SIGNATURE_LABELS.saved}
60
+ class="ink-signature-list"
61
+ data-ink-menu-columns="2"
62
+ >
63
+ {#each items as item, row (item.id)}
64
+ {@const preview =
65
+ item.template.kind === 'ink' ? signaturePreview(item.template) : null}
66
+ <button
67
+ type="button"
68
+ role="menuitemradio"
69
+ aria-checked={item.checked}
70
+ aria-label={item.label}
71
+ tabindex={-1}
72
+ class="ink-select-item ink-menu-item ink-signature-item"
73
+ data-ink-select-item=""
74
+ data-key={item.id}
75
+ data-state={item.checked ? 'checked' : 'unchecked'}
76
+ onclick={() => onChoose(item.template)}
77
+ >
78
+ <span class="ink-signature-preview" data-kind={item.template.kind}>
79
+ {#if item.template.kind === 'image'}
80
+ <img src={item.template.imagedata} alt="" draggable="false" />
81
+ {:else if preview}
82
+ <svg viewBox={preview.viewBox} aria-hidden="true">
83
+ {#each preview.paths as d, i (i)}
84
+ <path {d} fill="currentColor" />
85
+ {/each}
86
+ </svg>
87
+ {/if}
88
+ </span>
89
+ </button>
90
+ <button
91
+ type="button"
92
+ role="menuitem"
93
+ aria-label={item.removeLabel}
94
+ title={item.removeLabel}
95
+ tabindex={-1}
96
+ class="ink-menu-item ink-signature-remove"
97
+ data-ink-signature-remove=""
98
+ data-key={item.id}
99
+ onclick={() => remove(item.id, row)}
100
+ >
101
+ <InkIcon icon={Trash2} size={16} />
102
+ </button>
103
+ {/each}
104
+ </div>
105
+ <div role="separator" class="ink-select-separator"></div>
106
+ {/if}
107
+ <button
108
+ type="button"
109
+ role="menuitem"
110
+ tabindex={-1}
111
+ class="ink-select-item ink-menu-item ink-signature-create"
112
+ data-ink-select-item=""
113
+ data-ink-signature-create=""
114
+ onclick={onCreate}
115
+ >
116
+ <InkIcon icon={Plus} size={16} />
117
+ {SIGNATURE_LABELS.create}
118
+ </button>
119
+ {#if removeError.current}
120
+ <p
121
+ class="ink-field-error ink-signature-remove-error"
122
+ role="alert"
123
+ data-ink-signature-remove-error=""
124
+ >
125
+ {removeError.current}
126
+ </p>
127
+ {/if}
@@ -0,0 +1,13 @@
1
+ import type { SignatureTemplate } from '@inkbar/core';
2
+ import type { SignatureMenuItem } from '@inkbar/core/dom';
3
+ type $$ComponentProps = {
4
+ items: readonly SignatureMenuItem[];
5
+ /** The menu element the items sit in, for moving focus after a removal. */
6
+ menu: () => HTMLElement | null;
7
+ onChoose: (template: SignatureTemplate) => void;
8
+ onCreate: () => void;
9
+ };
10
+ declare const SignatureMenuPanel: import("svelte").Component<$$ComponentProps, {}, "">;
11
+ type SignatureMenuPanel = ReturnType<typeof SignatureMenuPanel>;
12
+ export default SignatureMenuPanel;
13
+ //# sourceMappingURL=SignatureMenuPanel.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SignatureMenuPanel.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/SignatureMenuPanel.svelte.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,KAAK,gBAAgB,GAAI;IACtB,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAA;IACnC,2EAA2E;IAC3E,IAAI,EAAE,MAAM,WAAW,GAAG,IAAI,CAAA;IAC9B,QAAQ,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAA;IAC/C,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB,CAAC;AAkFJ,QAAA,MAAM,kBAAkB,sDAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
package/dist/context.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Annotation, InkDocument, InkStatus, PdfAssets, PluginHistory, SignatureLibrary, Writable } from '@inkbar/core';
1
+ import type { Annotation, FormAction, InkDocument, InkError, InkStatus, PdfAssets, PluginHistory, SignatureLibrary, Writable } from '@inkbar/core';
2
2
  import type { DecorateAnnotation, PluginHost, SearchController, Tool, ToolController, ToolId, ToolOptions, ToolStyle, Viewport, ZoomValue } from '@inkbar/core/dom';
3
3
  export type { InkStatus };
4
4
  /**
@@ -80,6 +80,12 @@ export interface InkContext {
80
80
  readonly history: InkHistory;
81
81
  readonly rootEl: HTMLElement | null;
82
82
  setViewport(viewport: Viewport | null, tools: ToolController | null): void;
83
+ /** InkRoot's `formHighlight`; InkViewport reads it when it builds the viewer. */
84
+ readonly formHighlight: boolean | undefined;
85
+ /** Calls InkRoot's `onformaction`. */
86
+ reportFormAction(action: FormAction): void;
87
+ /** Calls InkRoot's `onError`, for failures after the document opened (a refused signing). */
88
+ reportError(error: InkError): void;
83
89
  }
84
90
  /** Called once by InkRoot during its initialisation. */
85
91
  export declare function setInkContext(ctx: InkContext, peekActivated: () => string | null): void;
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/lib/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/lib/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { FieldValues, FormField, FormSetResult } from '@inkbar/core';
2
+ export interface FormHandle {
3
+ /** The open document's form fields; empty while none is open or it has none. */
4
+ readonly fields: readonly FormField[];
5
+ /** What the fields hold now, keyed by full name. */
6
+ readonly values: FieldValues;
7
+ /**
8
+ * Commits values as a person would: scripts run, and the call is one undo step. Returns the
9
+ * names applied and rejected, or `undefined` while no document is open.
10
+ */
11
+ set: (values: FieldValues) => FormSetResult | undefined;
12
+ /** Restores the PDF's default values of `names`, or of every field. */
13
+ reset: (names?: string[]) => void;
14
+ }
15
+ /** The open document's form: its fields, their values, and `set` and `reset`. */
16
+ export declare function useForm(): FormHandle;
17
+ //# sourceMappingURL=useForm.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useForm.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/hooks/useForm.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAKzE,MAAM,WAAW,UAAU;IACzB,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAA;IACrC,oDAAoD;IACpD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B;;;OAGG;IACH,GAAG,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,aAAa,GAAG,SAAS,CAAA;IACvD,uEAAuE;IACvE,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;CAClC;AAED,iFAAiF;AACjF,wBAAgB,OAAO,IAAI,UAAU,CAcpC"}
@@ -0,0 +1,20 @@
1
+ import { useInkContext } from '../context.js';
2
+ import { useReadable } from '../use-readable.svelte.js';
3
+ const NO_FIELDS = [];
4
+ const NO_VALUES = Object.freeze({});
5
+ /** The open document's form: its fields, their values, and `set` and `reset`. */
6
+ export function useForm() {
7
+ const ctx = useInkContext('useForm()');
8
+ const fields = useReadable(() => ctx.document?.form.fields, NO_FIELDS);
9
+ const values = useReadable(() => ctx.document?.form.values, NO_VALUES);
10
+ return {
11
+ get fields() {
12
+ return fields.current;
13
+ },
14
+ get values() {
15
+ return values.current;
16
+ },
17
+ set: (v) => ctx.document?.form.set(v),
18
+ reset: (names) => ctx.document?.form.reset(names),
19
+ };
20
+ }
package/dist/index.d.ts CHANGED
@@ -18,6 +18,8 @@ export { useHistory } from './hooks/useHistory.svelte.js';
18
18
  export { useSearch } from './hooks/useSearch.svelte.js';
19
19
  export { useEmbedded } from './hooks/useEmbedded.svelte.js';
20
20
  export { useCommand } from './hooks/useCommand.svelte.js';
21
+ export { useForm } from './hooks/useForm.svelte.js';
22
+ export type { FormHandle } from './hooks/useForm.svelte.js';
21
23
  export type { CommandHandle } from './hooks/useCommand.svelte.js';
22
24
  export { default as InkRoot } from './components/InkRoot.svelte';
23
25
  export type { InkRootProps } from './components/InkRoot.svelte';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -12,6 +12,7 @@ export { useHistory } from './hooks/useHistory.svelte.js';
12
12
  export { useSearch } from './hooks/useSearch.svelte.js';
13
13
  export { useEmbedded } from './hooks/useEmbedded.svelte.js';
14
14
  export { useCommand } from './hooks/useCommand.svelte.js';
15
+ export { useForm } from './hooks/useForm.svelte.js';
15
16
  export { default as InkRoot } from './components/InkRoot.svelte';
16
17
  export { default as InkViewport } from './components/InkViewport.svelte';
17
18
  export { default as InkPage } from './components/InkPage.svelte';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkbar/svelte",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Svelte 5 components and hooks for Inkbar, the browser PDF viewer and editor.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://inkbar.dev",
@@ -26,19 +26,19 @@
26
26
  "./package.json": "./package.json"
27
27
  },
28
28
  "dependencies": {
29
- "@inkbar/icons": "^0.7.0",
29
+ "@inkbar/icons": "^0.8.0",
30
30
  "@internationalized/date": "^3.12.4",
31
31
  "bits-ui": "^2.19.5",
32
32
  "esm-env": "^1.2.0"
33
33
  },
34
34
  "peerDependencies": {
35
- "@inkbar/core": "^0.7.0",
35
+ "@inkbar/core": "^0.8.0",
36
36
  "svelte": "^5.46.4"
37
37
  },
38
38
  "devDependencies": {
39
- "@inkbar/core": "0.7.0",
39
+ "@inkbar/core": "0.8.0",
40
40
  "@inkbar/fixtures": "0.0.0",
41
- "@inkbar/theme": "0.7.0",
41
+ "@inkbar/theme": "0.8.0",
42
42
  "@sveltejs/package": "^3.0.0",
43
43
  "@sveltejs/vite-plugin-svelte": "^7.3.1",
44
44
  "@vitest/browser-playwright": "^5.0.4",