@inkbar/svelte 0.2.0 → 0.4.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 (57) hide show
  1. package/README.md +33 -11
  2. package/dist/components/InkColorMenu.svelte +242 -0
  3. package/dist/components/InkColorMenu.svelte.d.ts +33 -0
  4. package/dist/components/InkColorMenu.svelte.d.ts.map +1 -0
  5. package/dist/components/InkHighlightMenu.svelte +166 -0
  6. package/dist/components/InkHighlightMenu.svelte.d.ts +16 -0
  7. package/dist/components/InkHighlightMenu.svelte.d.ts.map +1 -0
  8. package/dist/components/InkLineStyleMenu.svelte +141 -0
  9. package/dist/components/InkLineStyleMenu.svelte.d.ts +15 -0
  10. package/dist/components/InkLineStyleMenu.svelte.d.ts.map +1 -0
  11. package/dist/components/InkRoot.svelte +77 -3
  12. package/dist/components/InkRoot.svelte.d.ts +20 -2
  13. package/dist/components/InkRoot.svelte.d.ts.map +1 -1
  14. package/dist/components/InkShapeMenu.svelte +157 -0
  15. package/dist/components/InkShapeMenu.svelte.d.ts +15 -0
  16. package/dist/components/InkShapeMenu.svelte.d.ts.map +1 -0
  17. package/dist/components/InkSignatureDialog.svelte +70 -0
  18. package/dist/components/InkSignatureDialog.svelte.d.ts +22 -0
  19. package/dist/components/InkSignatureDialog.svelte.d.ts.map +1 -0
  20. package/dist/components/InkSignatureMenu.svelte +263 -0
  21. package/dist/components/InkSignatureMenu.svelte.d.ts +18 -0
  22. package/dist/components/InkSignatureMenu.svelte.d.ts.map +1 -0
  23. package/dist/components/InkTextStyleMenu.svelte +225 -0
  24. package/dist/components/InkTextStyleMenu.svelte.d.ts +15 -0
  25. package/dist/components/InkTextStyleMenu.svelte.d.ts.map +1 -0
  26. package/dist/components/{InkNotePopover.svelte → InkThreadPopover.svelte} +38 -33
  27. package/dist/components/InkThreadPopover.svelte.d.ts +9 -0
  28. package/dist/components/InkThreadPopover.svelte.d.ts.map +1 -0
  29. package/dist/components/InkToolButton.svelte +23 -7
  30. package/dist/components/InkToolButton.svelte.d.ts.map +1 -1
  31. package/dist/components/InkViewport.svelte +7 -0
  32. package/dist/components/InkViewport.svelte.d.ts.map +1 -1
  33. package/dist/components/SignatureForm.svelte +219 -0
  34. package/dist/components/SignatureForm.svelte.d.ts +10 -0
  35. package/dist/components/SignatureForm.svelte.d.ts.map +1 -0
  36. package/dist/components/ThreadForm.svelte +4 -2
  37. package/dist/components/ThreadForm.svelte.d.ts +1 -0
  38. package/dist/components/ThreadForm.svelte.d.ts.map +1 -1
  39. package/dist/components/child-snippet.d.ts +8 -0
  40. package/dist/components/child-snippet.d.ts.map +1 -1
  41. package/dist/components/child-snippet.js +15 -0
  42. package/dist/context.d.ts +14 -2
  43. package/dist/context.d.ts.map +1 -1
  44. package/dist/hooks/useAnnotations.svelte.d.ts +1364 -146
  45. package/dist/hooks/useAnnotations.svelte.d.ts.map +1 -1
  46. package/dist/hooks/useToolOptions.svelte.d.ts +11 -0
  47. package/dist/hooks/useToolOptions.svelte.d.ts.map +1 -0
  48. package/dist/hooks/useToolOptions.svelte.js +19 -0
  49. package/dist/hooks/useToolStyle.svelte.d.ts +33 -0
  50. package/dist/hooks/useToolStyle.svelte.d.ts.map +1 -0
  51. package/dist/hooks/useToolStyle.svelte.js +33 -0
  52. package/dist/index.d.ts +20 -3
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +10 -1
  55. package/package.json +5 -5
  56. package/dist/components/InkNotePopover.svelte.d.ts +0 -9
  57. package/dist/components/InkNotePopover.svelte.d.ts.map +0 -1
@@ -1,24 +1,26 @@
1
1
  <script module lang="ts">
2
- import type { NotePopoverSlotProps } from '@inkbar/core/dom'
2
+ import type { ThreadPopoverSlotProps } from '@inkbar/core/dom'
3
3
  import type { Snippet } from 'svelte'
4
4
 
5
- export interface InkNotePopoverProps {
6
- children?: Snippet<[NotePopoverSlotProps]> | undefined
5
+ export interface InkThreadPopoverProps {
6
+ children?: Snippet<[ThreadPopoverSlotProps]> | undefined
7
7
  }
8
8
  </script>
9
9
 
10
10
  <script lang="ts">
11
11
  /*
12
- * The thread for the activated note, anchored to the note's overlay element. Activating a
13
- * reply opens the whole thread from its root. Closing (Close, Escape, a press outside) clears
14
- * `activated`.
12
+ * The thread for the activated note or text markup, anchored to the root's overlay
13
+ * element. Activating a reply opens the whole thread from its root. Closing (Close, Escape,
14
+ * a press outside) clears `activated`.
15
15
  *
16
- * A new note has no text. While its root is empty (and unlocked) the default form writes the
17
- * root's own `contents`, labelled "Comment", and the thread list stays hidden until there is
18
- * something in it; after that the form adds replies. Closing a root that is still empty and
19
- * has no replies removes it, so an abandoned note does not stay on the page.
16
+ * A new note, or a highlight, has no text. While its root is empty (and unlocked) the
17
+ * default form writes the root's own `contents`, labelled "Comment", and the thread list
18
+ * stays hidden until there is something in it; after that the form adds replies. Closing a
19
+ * note that is still empty and has no replies removes it, so an abandoned note does not stay
20
+ * on the page. Markup stays: the mark is the point.
20
21
  */
21
22
  import { isAbandonedNote, threadOf, threadRoot } from '@inkbar/core'
23
+ import { threadDeleteLabel, threadPopoverLabel } from '@inkbar/core/dom'
22
24
  import { Popover } from 'bits-ui'
23
25
  import { untrack } from 'svelte'
24
26
 
@@ -29,18 +31,18 @@
29
31
  import { keepOpenOnAnnotation, useFocusReturn } from './popover-focus.js'
30
32
  import ThreadForm from './ThreadForm.svelte'
31
33
 
32
- import type { Annotation, NoteAnnotation } from '@inkbar/core'
34
+ import type { Annotation, ThreadRoot } from '@inkbar/core'
33
35
 
34
- let { children }: InkNotePopoverProps = $props()
36
+ let { children }: InkThreadPopoverProps = $props()
35
37
 
36
- const ctx = useInkContext('InkNotePopover')
38
+ const ctx = useInkContext('InkThreadPopover')
37
39
  const store = useAnnotations()
38
40
 
39
- const note = $derived.by<NoteAnnotation | null>(() => {
41
+ const note = $derived.by<ThreadRoot | null>(() => {
40
42
  const a = ctx.activated
41
43
  ? store.annotations.find((x) => x.id === ctx.activated)
42
44
  : undefined
43
- return a?.type === 'note' ? threadRoot(store.annotations, a) : null
45
+ return a ? threadRoot(store.annotations, a) : null
44
46
  })
45
47
  const anchorRef = useAnnotationElement(
46
48
  () => ctx.rootEl,
@@ -51,11 +53,11 @@
51
53
  const open = $derived(note !== null && anchor !== null)
52
54
  /** The root, then every reply below it, depth first, each level in creation order. */
53
55
  const thread = $derived<Annotation[]>(note ? threadOf(store.annotations, note) : [])
54
- /** True while the default form writes the root note's own text rather than a reply. */
56
+ /** True while the default form writes the root's own text rather than a reply. */
55
57
  const editingRoot = $derived(note !== null && !note.locked && !note.contents?.trim())
56
58
 
57
59
  /**
58
- * Notes this popover wrote text or a reply for. In controlled mode the write is a proposal
60
+ * Roots this popover wrote text or a reply for. In controlled mode the write is a proposal
59
61
  * the host may not have applied yet, so the applied list still shows the note empty; these
60
62
  * are never dropped as abandoned. Bookkeeping only: nothing renders from it.
61
63
  */
@@ -67,7 +69,13 @@
67
69
 
68
70
  /** Removes an unlocked root note with no text and no replies. True when it did. */
69
71
  function dropIfEmpty(id: string): boolean {
70
- if (dropped.has(id) || written.has(id) || !isAbandonedNote(store.annotations, id))
72
+ const a = store.annotations.find((x) => x.id === id)
73
+ if (
74
+ !a ||
75
+ dropped.has(id) ||
76
+ written.has(id) ||
77
+ !isAbandonedNote(a, store.annotations)
78
+ )
71
79
  return false
72
80
  dropped.add(id)
73
81
  store.remove(id)
@@ -90,20 +98,16 @@
90
98
  if (!root || !contents) return
91
99
  written.add(root.id)
92
100
  store.add({
93
- type: 'note',
101
+ type: 'text',
94
102
  page: root.page,
95
103
  rect: root.rect,
96
104
  contents,
97
105
  inReplyTo: root.id,
98
106
  })
99
107
  }
100
- function isEmptyRoot(root: NoteAnnotation): boolean {
101
- return (
102
- !written.has(root.id) &&
103
- !root.locked &&
104
- !root.contents?.trim() &&
105
- thread.length === 1
106
- )
108
+ /** A note that closing now would remove. */
109
+ function isEmptyRoot(root: ThreadRoot): boolean {
110
+ return !written.has(root.id) && isAbandonedNote(root, store.annotations)
107
111
  }
108
112
  function close(): void {
109
113
  const root = note
@@ -118,12 +122,12 @@
118
122
  if (contents.trim()) written.add(note.id)
119
123
  store.update(note.id, { contents })
120
124
  }
121
- /** Locked notes cannot be removed: removing one does nothing and keeps the popover. */
125
+ /** Locked roots cannot be removed: removing one does nothing and keeps the popover. */
122
126
  function removeThread(): void {
123
127
  const root = note
124
128
  if (!root || root.locked) return
125
129
  focusReturn.beforeRemove(anchor)
126
- // Under a slow controlled host the note stays listed for a while; it is not asked for again.
130
+ // Under a slow controlled host the root stays listed for a while; it is not asked for again.
127
131
  dropped.add(root.id)
128
132
  store.remove(root.id)
129
133
  ctx.setActivated(null)
@@ -137,13 +141,13 @@
137
141
  <Popover.Portal>
138
142
  {#if note && anchor}
139
143
  <Popover.Content
140
- class="ink-note-popover"
141
- data-ink-note-popover=""
144
+ class="ink-thread-popover"
145
+ data-ink-thread-popover=""
142
146
  role="dialog"
143
147
  side="right"
144
148
  sideOffset={8}
145
149
  collisionPadding={8}
146
- aria-label="Note thread"
150
+ aria-label={threadPopoverLabel(note)}
147
151
  customAnchor={anchor}
148
152
  onInteractOutside={keepOpenOnAnnotation}
149
153
  onOpenAutoFocus={focusReturn.onOpenAutoFocus}
@@ -151,7 +155,7 @@
151
155
  >
152
156
  {#if children}
153
157
  {@render children({
154
- note,
158
+ root: note,
155
159
  replies: thread.slice(1),
156
160
  reply,
157
161
  update: updateContents,
@@ -176,11 +180,12 @@
176
180
  {/each}
177
181
  </ol>
178
182
  {/if}
179
- <!-- Keyed by note: moving to another note starts with an empty draft at once. -->
183
+ <!-- Keyed by root: moving to another thread starts with an empty draft at once. -->
180
184
  {#key note.id}
181
185
  <ThreadForm
182
186
  {editingRoot}
183
187
  locked={!!note.locked}
188
+ deleteLabel={threadDeleteLabel(note)}
184
189
  onSubmit={(text) => (editingRoot ? updateContents(text) : reply(text))}
185
190
  onRemove={removeThread}
186
191
  onClose={close}
@@ -0,0 +1,9 @@
1
+ import type { ThreadPopoverSlotProps } from '@inkbar/core/dom';
2
+ import type { Snippet } from 'svelte';
3
+ export interface InkThreadPopoverProps {
4
+ children?: Snippet<[ThreadPopoverSlotProps]> | undefined;
5
+ }
6
+ declare const InkThreadPopover: import("svelte").Component<InkThreadPopoverProps, {}, "">;
7
+ type InkThreadPopover = ReturnType<typeof InkThreadPopover>;
8
+ export default InkThreadPopover;
9
+ //# sourceMappingURL=InkThreadPopover.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkThreadPopover.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkThreadPopover.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAErC,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,sBAAsB,CAAC,CAAC,GAAG,SAAS,CAAA;CACzD;AA6LH,QAAA,MAAM,gBAAgB,2DAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
@@ -14,7 +14,17 @@
14
14
 
15
15
  <script lang="ts">
16
16
  import { TOOL_LABELS } from '@inkbar/core/dom'
17
- import { Hand, Highlighter, MessageSquare, MousePointer2, Square } from '@inkbar/icons'
17
+ import {
18
+ Highlighter,
19
+ MessageSquare,
20
+ PenLine,
21
+ PenTool,
22
+ Signature,
23
+ Square,
24
+ SquareDashedMousePointer,
25
+ TextCursor,
26
+ Type,
27
+ } from '@inkbar/icons'
18
28
  import { Toolbar } from 'bits-ui'
19
29
 
20
30
  import { useTool } from '../hooks/useTool.svelte.js'
@@ -24,12 +34,16 @@
24
34
 
25
35
  import type { IconNode } from '@inkbar/icons'
26
36
 
27
- const ICONS: Readonly<Record<ToolId, IconNode>> = {
28
- view: Hand,
29
- select: MousePointer2,
37
+ const ICONS: Readonly<Partial<Record<ToolId, IconNode>>> = {
38
+ 'select-text': TextCursor,
39
+ select: SquareDashedMousePointer,
30
40
  highlight: Highlighter,
31
41
  'redact-area': Square,
42
+ sketch: PenTool,
43
+ draw: PenLine,
32
44
  note: MessageSquare,
45
+ freetext: Type,
46
+ signature: Signature,
33
47
  }
34
48
 
35
49
  let {
@@ -44,7 +58,9 @@
44
58
 
45
59
  const current = useTool()
46
60
  const active = $derived(current.tool === tool)
47
- const name = $derived(label ?? TOOL_LABELS[tool])
61
+ // A host tool has no built-in name or icon: `label` and `children` supply them.
62
+ const name = $derived(label ?? TOOL_LABELS[tool] ?? tool)
63
+ const icon = $derived(ICONS[tool])
48
64
  </script>
49
65
 
50
66
  <Toolbar.Button
@@ -62,7 +78,7 @@
62
78
  if (!e.defaultPrevented) current.setTool(tool)
63
79
  }}
64
80
  >
65
- {#if children}{@render children({ active, label: name })}{:else}<InkIcon
66
- icon={ICONS[tool]}
81
+ {#if children}{@render children({ active, label: name })}{:else if icon}<InkIcon
82
+ {icon}
67
83
  />{/if}
68
84
  </Toolbar.Button>
@@ -1 +1 @@
1
- {"version":3,"file":"InkToolButton.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkToolButton.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAE3D,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,oBAAoB,EAAE,UAAU,CAAC;IAChF,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,GAAG,SAAS,CAAA;IACpE,KAAK,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;CACjC;AA4DH,QAAA,MAAM,aAAa,wDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"InkToolButton.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkToolButton.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAE3D,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,oBAAoB,EAAE,UAAU,CAAC;IAChF,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,GAAG,SAAS,CAAA;IACpE,KAAK,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;CACjC;AA4EH,QAAA,MAAM,aAAa,wDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
@@ -125,6 +125,13 @@
125
125
  gap,
126
126
  buffer,
127
127
  tool: ctx.tool,
128
+ ...(ctx.hostTools ? { tools: ctx.hostTools } : {}),
129
+ ...(ctx.toolStyle ? { toolStyle: ctx.toolStyle } : {}),
130
+ toolHistory: { batch: (fn) => ctx.history.batch(fn) },
131
+ toolOptions: ctx.toolOptions,
132
+ fonts: [...ctx.fonts],
133
+ // Read through, so a new `signatures` store reaches the tool as well as the menus.
134
+ signatureLibrary: () => ctx.signatures,
128
135
  customAnnotations: custom,
129
136
  onActivate: (id) => ctx.setActivated(id),
130
137
  onBuild: (vp, tc) => {
@@ -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;AAuRH,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;AA8RH,QAAA,MAAM,WAAW,sDAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -0,0 +1,219 @@
1
+ <script lang="ts">
2
+ /*
3
+ * The body of `InkSignatureDialog`, mounted while it is open: one draft per opening. Draw,
4
+ * Type and Image tabs, then Cancel and Save.
5
+ */
6
+ import {
7
+ createSignatureDraft,
8
+ fontFamilyValue,
9
+ handleRadioKeys,
10
+ handleTabKeys,
11
+ SIGNATURE_LABELS,
12
+ SIGNATURE_TABS,
13
+ type SignatureTab,
14
+ } from '@inkbar/core/dom'
15
+ import { Dialog } from 'bits-ui'
16
+ import { untrack } from 'svelte'
17
+
18
+ import { useInkContext } from '../context.js'
19
+ import { useTool } from '../hooks/useTool.svelte.js'
20
+ import { useToolOptions } from '../hooks/useToolOptions.svelte.js'
21
+ import { useReadable } from '../use-readable.svelte.js'
22
+
23
+ import type { SignatureOptions, SignatureTemplate } from '@inkbar/core'
24
+
25
+ let {
26
+ fonts,
27
+ onSaved,
28
+ onClose,
29
+ }: {
30
+ fonts: readonly string[] | undefined
31
+ onSaved: (t: SignatureTemplate) => void
32
+ onClose: () => void
33
+ } = $props()
34
+
35
+ const ctx = useInkContext('InkSignatureDialog')
36
+ const current = useTool()
37
+ const signature = useToolOptions<SignatureOptions>('signature')
38
+ // One draft per opening: the fonts are read once.
39
+ const draft = untrack(() =>
40
+ createSignatureDraft({ fonts: fonts ?? ctx.signatureFonts })
41
+ )
42
+ const draftState = useReadable(() => draft.state, draft.state.get())
43
+ const s = $derived(draftState.current)
44
+ const uid = $props.id()
45
+ let padHost = $state<HTMLDivElement | null>(null)
46
+
47
+ $effect(() => {
48
+ if (!padHost) return
49
+ return draft.attachPad(padHost)
50
+ })
51
+ $effect(() => () => draft.destroy())
52
+
53
+ function save(): void {
54
+ draft.save(ctx.signatures).then(
55
+ (t) => {
56
+ if (!t) return
57
+ signature.setOptions({ templateId: t.id })
58
+ current.setTool('signature')
59
+ onSaved(t)
60
+ onClose()
61
+ },
62
+ () => {
63
+ // The host's store refused it: the dialog stays open to try again.
64
+ }
65
+ )
66
+ }
67
+
68
+ const tabId = (tab: SignatureTab) => `${uid}-tab-${tab}`
69
+ const panelId = (tab: SignatureTab) => `${uid}-panel-${tab}`
70
+ const shown = $derived(s.name.trim() || SIGNATURE_LABELS.namePlaceholder)
71
+ </script>
72
+
73
+ <div
74
+ role="tablist"
75
+ tabindex="-1"
76
+ aria-label={SIGNATURE_LABELS.tabs}
77
+ class="ink-tabs"
78
+ onkeydown={(e) => handleTabKeys(e, e.currentTarget)}
79
+ >
80
+ {#each SIGNATURE_TABS as tab (tab)}
81
+ <button
82
+ type="button"
83
+ role="tab"
84
+ id={tabId(tab)}
85
+ aria-controls={panelId(tab)}
86
+ aria-selected={s.tab === tab}
87
+ tabindex={s.tab === tab ? 0 : -1}
88
+ class="ink-tab"
89
+ data-key={tab}
90
+ data-state={s.tab === tab ? 'active' : 'inactive'}
91
+ onclick={() => draft.setTab(tab)}
92
+ >
93
+ {SIGNATURE_LABELS[tab]}
94
+ </button>
95
+ {/each}
96
+ </div>
97
+ <div
98
+ role="tabpanel"
99
+ id={panelId('draw')}
100
+ aria-labelledby={tabId('draw')}
101
+ class="ink-tab-panel"
102
+ data-key="draw"
103
+ hidden={s.tab !== 'draw'}
104
+ >
105
+ <div
106
+ bind:this={padHost}
107
+ class="ink-signature-pad-host"
108
+ data-ink-signature-pad-host=""
109
+ role="img"
110
+ aria-label={SIGNATURE_LABELS.pad}
111
+ ></div>
112
+ <div class="ink-dialog-row">
113
+ <button
114
+ type="button"
115
+ class="ink-button"
116
+ data-ink-signature-clear=""
117
+ disabled={s.padEmpty}
118
+ onclick={() => draft.clearPad()}
119
+ >
120
+ {SIGNATURE_LABELS.clear}
121
+ </button>
122
+ </div>
123
+ </div>
124
+ <div
125
+ role="tabpanel"
126
+ id={panelId('type')}
127
+ aria-labelledby={tabId('type')}
128
+ class="ink-tab-panel"
129
+ data-key="type"
130
+ hidden={s.tab !== 'type'}
131
+ >
132
+ <label class="ink-field">
133
+ <span>{SIGNATURE_LABELS.name}</span>
134
+ <input
135
+ type="text"
136
+ class="ink-input"
137
+ data-ink-signature-name=""
138
+ autocomplete="name"
139
+ placeholder={SIGNATURE_LABELS.namePlaceholder}
140
+ value={s.name}
141
+ oninput={(e) => draft.setName(e.currentTarget.value)}
142
+ />
143
+ </label>
144
+ <div
145
+ role="radiogroup"
146
+ tabindex="-1"
147
+ aria-label={SIGNATURE_LABELS.fonts}
148
+ class="ink-signature-fonts"
149
+ onkeydown={(e) => handleRadioKeys(e, e.currentTarget)}
150
+ >
151
+ {#each draft.fonts as font (font)}
152
+ <button
153
+ type="button"
154
+ role="radio"
155
+ aria-checked={s.font === font}
156
+ aria-label={font}
157
+ tabindex={s.font === font ? 0 : -1}
158
+ class="ink-signature-font"
159
+ data-key={font}
160
+ data-state={s.font === font ? 'checked' : 'unchecked'}
161
+ onclick={() => draft.setFont(font)}
162
+ >
163
+ <!-- The font is the option itself, so it is set here, not left to the theme. -->
164
+ <span class="ink-signature-font-sample" style:font-family={fontFamilyValue(font)}
165
+ >{shown}</span
166
+ >
167
+ </button>
168
+ {/each}
169
+ </div>
170
+ </div>
171
+ <div
172
+ role="tabpanel"
173
+ id={panelId('image')}
174
+ aria-labelledby={tabId('image')}
175
+ class="ink-tab-panel"
176
+ data-key="image"
177
+ hidden={s.tab !== 'image'}
178
+ >
179
+ <label class="ink-field">
180
+ <span>{SIGNATURE_LABELS.file}</span>
181
+ <input
182
+ type="file"
183
+ accept="image/png,image/jpeg"
184
+ class="ink-input"
185
+ data-ink-signature-file=""
186
+ onchange={(e) => void draft.chooseFile(e.currentTarget.files?.[0])}
187
+ />
188
+ </label>
189
+ {#if s.image?.kind === 'image'}
190
+ <img class="ink-signature-image" src={s.image.imagedata} alt="" />
191
+ {/if}
192
+ {#if s.imageError}
193
+ <p class="ink-field-error" role="alert">{s.imageError}</p>
194
+ {/if}
195
+ </div>
196
+ {#if s.saveError}
197
+ <p class="ink-field-error" role="alert" data-ink-signature-save-error="">
198
+ {s.saveError}
199
+ </p>
200
+ {/if}
201
+ <div class="ink-dialog-actions">
202
+ <Dialog.Close>
203
+ {#snippet child({ props })}
204
+ <button {...props} type="button" class="ink-button" data-ink-signature-cancel="">
205
+ {SIGNATURE_LABELS.cancel}
206
+ </button>
207
+ {/snippet}
208
+ </Dialog.Close>
209
+ <button
210
+ type="button"
211
+ class="ink-button"
212
+ data-variant="primary"
213
+ data-ink-signature-save=""
214
+ disabled={!s.canSave}
215
+ onclick={save}
216
+ >
217
+ {SIGNATURE_LABELS.save}
218
+ </button>
219
+ </div>
@@ -0,0 +1,10 @@
1
+ import type { SignatureTemplate } from '@inkbar/core';
2
+ type $$ComponentProps = {
3
+ fonts: readonly string[] | undefined;
4
+ onSaved: (t: SignatureTemplate) => void;
5
+ onClose: () => void;
6
+ };
7
+ declare const SignatureForm: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type SignatureForm = ReturnType<typeof SignatureForm>;
9
+ export default SignatureForm;
10
+ //# sourceMappingURL=SignatureForm.svelte.d.ts.map
@@ -0,0 +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,14 +1,16 @@
1
1
  <script lang="ts">
2
- /** The default form: the root note's own text while it is empty, replies after that. */
2
+ /** The default form: the root's own text while it is empty, replies after that. */
3
3
  let {
4
4
  editingRoot,
5
5
  locked,
6
+ deleteLabel,
6
7
  onSubmit,
7
8
  onRemove,
8
9
  onClose,
9
10
  }: {
10
11
  editingRoot: boolean
11
12
  locked: boolean
13
+ deleteLabel: string
12
14
  onSubmit: (text: string) => void
13
15
  onRemove: () => void
14
16
  onClose: () => void
@@ -35,7 +37,7 @@
35
37
  >{editingRoot ? 'Comment' : 'Reply'}</button
36
38
  >
37
39
  {#if !locked}
38
- <button type="button" onclick={onRemove}>Delete</button>
40
+ <button type="button" onclick={onRemove}>{deleteLabel}</button>
39
41
  {/if}
40
42
  <button type="button" onclick={onClose}>Close</button>
41
43
  </div>
@@ -1,6 +1,7 @@
1
1
  type $$ComponentProps = {
2
2
  editingRoot: boolean;
3
3
  locked: boolean;
4
+ deleteLabel: string;
4
5
  onSubmit: (text: string) => void;
5
6
  onRemove: () => void;
6
7
  onClose: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"ThreadForm.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/ThreadForm.svelte.ts"],"names":[],"mappings":"AAGC,KAAK,gBAAgB,GAAI;IACtB,WAAW,EAAE,OAAO,CAAA;IACpB,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CAAC;AAkCJ,QAAA,MAAM,UAAU,sDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"ThreadForm.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/ThreadForm.svelte.ts"],"names":[],"mappings":"AAGC,KAAK,gBAAgB,GAAI;IACtB,WAAW,EAAE,OAAO,CAAA;IACpB,MAAM,EAAE,OAAO,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CAAC;AAmCJ,QAAA,MAAM,UAAU,sDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
@@ -19,4 +19,12 @@ export type BitsProps<T> = {
19
19
  * `loop`) receives the explicit `null` or `undefined`. This is the one place the cast lives.
20
20
  */
21
21
  export declare function asBitsProps<T extends object>(rest: T): BitsProps<T>;
22
+ type Handler<E> = ((e: E) => unknown) | null | undefined;
23
+ /**
24
+ * One handler for an element both the host and the component listen on: the host's first,
25
+ * then each of `inner` in turn unless the host (or an earlier one) prevented the default.
26
+ * `inner` takes Bits UI's own handler from its `props`, typed `unknown` there.
27
+ */
28
+ export declare function composeHandlers<E extends Event>(host: Handler<E>, ...inner: unknown[]): (e: E) => void;
29
+ export {};
22
30
  //# sourceMappingURL=child-snippet.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"child-snippet.d.ts","sourceRoot":"","sources":["../../src/lib/components/child-snippet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAErC,qEAAqE;AACrE,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAAC,CAAA;AAExE,6FAA6F;AAC7F,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;CAAE,CAAA;AAE9E;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAEnE"}
1
+ {"version":3,"file":"child-snippet.d.ts","sourceRoot":"","sources":["../../src/lib/components/child-snippet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAErC,qEAAqE;AACrE,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAAC,CAAA;AAExE,6FAA6F;AAC7F,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;CAAE,CAAA;AAE9E;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAEnE;AAED,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,CAAA;AAExD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,KAAK,EAC7C,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAChB,GAAG,KAAK,EAAE,OAAO,EAAE,GAClB,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,CAQhB"}
@@ -12,3 +12,18 @@
12
12
  export function asBitsProps(rest) {
13
13
  return rest;
14
14
  }
15
+ /**
16
+ * One handler for an element both the host and the component listen on: the host's first,
17
+ * then each of `inner` in turn unless the host (or an earlier one) prevented the default.
18
+ * `inner` takes Bits UI's own handler from its `props`, typed `unknown` there.
19
+ */
20
+ export function composeHandlers(host, ...inner) {
21
+ return (e) => {
22
+ host?.(e);
23
+ for (const fn of inner) {
24
+ if (e.defaultPrevented)
25
+ return;
26
+ fn?.(e);
27
+ }
28
+ };
29
+ }
package/dist/context.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { Annotation, InkDocument, InkStatus, PdfAssets } from '@inkbar/core';
2
- import type { ToolController, ToolId, Viewport, ZoomValue } from '@inkbar/core/dom';
1
+ import type { Annotation, InkDocument, InkStatus, PdfAssets, SignatureLibrary } from '@inkbar/core';
2
+ import type { Tool, ToolController, ToolId, ToolOptions, ToolStyle, Viewport, ZoomValue } from '@inkbar/core/dom';
3
3
  export type { InkStatus };
4
4
  /** Undo and redo for the current document, whichever mode its annotations are in. */
5
5
  export interface InkHistory {
@@ -33,6 +33,18 @@ export interface InkContext {
33
33
  /** Desired tool; InkViewport applies it to the controller. */
34
34
  readonly tool: ToolId;
35
35
  setTool(id: ToolId): void;
36
+ /** Host tools from InkRoot's `tools` prop; InkViewport registers them. */
37
+ readonly hostTools: Tool[] | undefined;
38
+ /** The font families text boxes offer: InkRoot's `fonts`, else `FONT_FAMILIES`. */
39
+ readonly fonts: readonly string[];
40
+ /** The tools' options for InkRoot's life, so they persist across documents. */
41
+ readonly toolOptions: ToolOptions;
42
+ /** The saved signatures, from InkRoot's `signatures` store (memory by default). */
43
+ readonly signatures: SignatureLibrary;
44
+ /** The fonts a typed signature offers: InkRoot's `signatureFonts`, else `SIGNATURE_FONTS`. */
45
+ readonly signatureFonts: readonly string[];
46
+ /** The open document's tool style; `null` while no document is open. */
47
+ readonly toolStyle: ToolStyle | null;
36
48
  /** Desired zoom and page from the host's props; InkViewport applies and reports back. */
37
49
  readonly zoomModel: ZoomValue | undefined;
38
50
  readonly pageModel: number | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/lib/context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAEnF,YAAY,EAAE,SAAS,EAAE,CAAA;AAEzB,qFAAqF;AACrF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,IAAI,IAAI,IAAI,CAAA;IACZ,IAAI,IAAI,IAAI,CAAA;IACZ,KAAK,IAAI,IAAI,CAAA;IACb;;;;;OAKG;IACH,KAAK,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAAA;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;IAC1B,QAAQ,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAA;IACrC,2FAA2F;IAC3F,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;IAC1B,QAAQ,CAAC,WAAW,EAAE,SAAS,UAAU,EAAE,CAAA;IAC3C,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAA;IACrC,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,yFAAyF;IACzF,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,CAAA;IACzC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,UAAU,CAAC,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAC9B,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,gGAAgG;IAChG,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAA;IACrC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;IAC5B,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;IACnC,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,EAAE,KAAK,EAAE,cAAc,GAAG,IAAI,GAAG,IAAI,CAAA;CAC3E;AAWD,wDAAwD;AACxD,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,CAGvF;AAED,4FAA4F;AAC5F,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAG5D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAY1D"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/lib/context.ts"],"names":[],"mappings":"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"}