@inkbar/svelte 0.8.0 → 0.10.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 (86) hide show
  1. package/README.md +71 -6
  2. package/dist/components/InkDownloadButton.svelte +62 -0
  3. package/dist/components/InkDownloadButton.svelte.d.ts +14 -0
  4. package/dist/components/InkDownloadButton.svelte.d.ts.map +1 -0
  5. package/dist/components/InkFindBar.svelte +18 -15
  6. package/dist/components/InkFindBar.svelte.d.ts.map +1 -1
  7. package/dist/components/InkHighlightMenu.svelte +101 -93
  8. package/dist/components/InkHighlightMenu.svelte.d.ts.map +1 -1
  9. package/dist/components/InkPanel.svelte +73 -0
  10. package/dist/components/InkPanel.svelte.d.ts +18 -0
  11. package/dist/components/InkPanel.svelte.d.ts.map +1 -0
  12. package/dist/components/InkPrintButton.svelte +57 -0
  13. package/dist/components/InkPrintButton.svelte.d.ts +12 -0
  14. package/dist/components/InkPrintButton.svelte.d.ts.map +1 -0
  15. package/dist/components/InkRecordList.svelte +91 -0
  16. package/dist/components/InkRecordList.svelte.d.ts +72 -0
  17. package/dist/components/InkRecordList.svelte.d.ts.map +1 -0
  18. package/dist/components/InkRoot.svelte +53 -5
  19. package/dist/components/InkRoot.svelte.d.ts +7 -2
  20. package/dist/components/InkRoot.svelte.d.ts.map +1 -1
  21. package/dist/components/InkSearchResults.svelte +72 -0
  22. package/dist/components/InkSearchResults.svelte.d.ts +9 -0
  23. package/dist/components/InkSearchResults.svelte.d.ts.map +1 -0
  24. package/dist/components/InkShapeMenu.svelte +89 -84
  25. package/dist/components/InkShapeMenu.svelte.d.ts.map +1 -1
  26. package/dist/components/InkSidebar.svelte +179 -0
  27. package/dist/components/InkSidebar.svelte.d.ts +22 -0
  28. package/dist/components/InkSidebar.svelte.d.ts.map +1 -0
  29. package/dist/components/InkSignatureDialog.svelte +7 -3
  30. package/dist/components/InkSignatureDialog.svelte.d.ts +4 -3
  31. package/dist/components/InkSignatureDialog.svelte.d.ts.map +1 -1
  32. package/dist/components/InkSignatureMenu.svelte +85 -77
  33. package/dist/components/InkSignatureMenu.svelte.d.ts.map +1 -1
  34. package/dist/components/InkThumbnail.svelte +74 -0
  35. package/dist/components/InkThumbnail.svelte.d.ts +19 -0
  36. package/dist/components/InkThumbnail.svelte.d.ts.map +1 -0
  37. package/dist/components/InkThumbnails.svelte +146 -0
  38. package/dist/components/InkThumbnails.svelte.d.ts +24 -0
  39. package/dist/components/InkThumbnails.svelte.d.ts.map +1 -0
  40. package/dist/components/InkToolButton.svelte +23 -24
  41. package/dist/components/InkToolButton.svelte.d.ts.map +1 -1
  42. package/dist/components/InkToolbarButton.svelte +33 -0
  43. package/dist/components/InkToolbarButton.svelte.d.ts +12 -0
  44. package/dist/components/InkToolbarButton.svelte.d.ts.map +1 -0
  45. package/dist/components/InkViewport.svelte +4 -0
  46. package/dist/components/InkViewport.svelte.d.ts.map +1 -1
  47. package/dist/components/InkZoomSelect.svelte +1 -1
  48. package/dist/components/RecordCards.svelte +173 -0
  49. package/dist/components/RecordCards.svelte.d.ts +16 -0
  50. package/dist/components/RecordCards.svelte.d.ts.map +1 -0
  51. package/dist/components/SidebarTrigger.svelte +20 -0
  52. package/dist/components/SidebarTrigger.svelte.d.ts +9 -0
  53. package/dist/components/SidebarTrigger.svelte.d.ts.map +1 -0
  54. package/dist/components/SignatureForm.svelte +9 -3
  55. package/dist/components/SignatureForm.svelte.d.ts.map +1 -1
  56. package/dist/components/body-lock.d.ts +3 -0
  57. package/dist/components/body-lock.d.ts.map +1 -0
  58. package/dist/components/body-lock.js +43 -0
  59. package/dist/components/sidebar-context.d.ts +24 -0
  60. package/dist/components/sidebar-context.d.ts.map +1 -0
  61. package/dist/components/sidebar-context.js +13 -0
  62. package/dist/context.d.ts +6 -0
  63. package/dist/context.d.ts.map +1 -1
  64. package/dist/hooks/useAnnotations.svelte.d.ts +78 -0
  65. package/dist/hooks/useAnnotations.svelte.d.ts.map +1 -1
  66. package/dist/hooks/useRecordSelection.svelte.d.ts +11 -0
  67. package/dist/hooks/useRecordSelection.svelte.d.ts.map +1 -0
  68. package/dist/hooks/useRecordSelection.svelte.js +19 -0
  69. package/dist/hooks/useRecords.svelte.d.ts +14 -0
  70. package/dist/hooks/useRecords.svelte.d.ts.map +1 -0
  71. package/dist/hooks/useRecords.svelte.js +24 -0
  72. package/dist/hooks/useRegisteredTool.svelte.d.ts +24 -0
  73. package/dist/hooks/useRegisteredTool.svelte.d.ts.map +1 -0
  74. package/dist/hooks/useRegisteredTool.svelte.js +47 -0
  75. package/dist/hooks/useSearch.svelte.d.ts.map +1 -1
  76. package/dist/hooks/useSearch.svelte.js +1 -0
  77. package/dist/hooks/useToolOptions.svelte.d.ts +8 -0
  78. package/dist/hooks/useToolOptions.svelte.d.ts.map +1 -1
  79. package/dist/hooks/useToolOptions.svelte.js +12 -2
  80. package/dist/index.d.ts +20 -0
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +11 -0
  83. package/dist/to-readable.svelte.d.ts +8 -0
  84. package/dist/to-readable.svelte.d.ts.map +1 -0
  85. package/dist/to-readable.svelte.js +15 -0
  86. package/package.json +5 -5
@@ -0,0 +1,57 @@
1
+ <script lang="ts" module>
2
+ import type { ChildSnippet } from './child-snippet.js'
3
+ import type { Snippet } from 'svelte'
4
+ import type { HTMLButtonAttributes } from 'svelte/elements'
5
+
6
+ export interface InkPrintButtonProps extends Omit<HTMLButtonAttributes, 'children'> {
7
+ children?: Snippet | undefined
8
+ /** Render your own button: spread `props` on it. */
9
+ child?: ChildSnippet | undefined
10
+ }
11
+ </script>
12
+
13
+ <script lang="ts">
14
+ /*
15
+ * Prints the open document's file with the browser's own PDF viewer (on iOS, in a new
16
+ * tab). Disabled until the document is ready. Today that is the file as it was opened,
17
+ * without this session's annotations.
18
+ */
19
+ import { printDocument } from '@inkbar/core/dom'
20
+ import { Printer } from '@inkbar/icons'
21
+ import { Toolbar } from 'bits-ui'
22
+
23
+ import { useInkContext } from '../context.js'
24
+
25
+ import { asBitsProps } from './child-snippet.js'
26
+ import InkIcon from './InkIcon.svelte'
27
+
28
+ let {
29
+ class: className,
30
+ children,
31
+ child,
32
+ disabled,
33
+ onclick,
34
+ ...rest
35
+ }: InkPrintButtonProps = $props()
36
+
37
+ const ctx = useInkContext('InkPrintButton')
38
+ const ready = $derived(ctx.document !== null && ctx.status.state === 'ready')
39
+ </script>
40
+
41
+ <Toolbar.Button
42
+ class={['ink-print', className]}
43
+ data-ink-print=""
44
+ aria-label="Print"
45
+ title="Print"
46
+ disabled={!ready || !!disabled}
47
+ {...child ? { child } : {}}
48
+ {...asBitsProps(rest)}
49
+ onclick={(e) => {
50
+ onclick?.(e)
51
+ const doc = ctx.document
52
+ if (e.defaultPrevented || !doc) return
53
+ void printDocument(doc).catch(() => undefined)
54
+ }}
55
+ >
56
+ {#if children}{@render children()}{:else}<InkIcon icon={Printer} />{/if}
57
+ </Toolbar.Button>
@@ -0,0 +1,12 @@
1
+ import type { ChildSnippet } from './child-snippet.js';
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLButtonAttributes } from 'svelte/elements';
4
+ export interface InkPrintButtonProps extends Omit<HTMLButtonAttributes, 'children'> {
5
+ children?: Snippet | undefined;
6
+ /** Render your own button: spread `props` on it. */
7
+ child?: ChildSnippet | undefined;
8
+ }
9
+ declare const InkPrintButton: import("svelte").Component<InkPrintButtonProps, {}, "">;
10
+ type InkPrintButton = ReturnType<typeof InkPrintButton>;
11
+ export default InkPrintButton;
12
+ //# sourceMappingURL=InkPrintButton.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkPrintButton.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkPrintButton.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAE3D,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,oBAAoB,EAAE,UAAU,CAAC;IACjF,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC9B,oDAAoD;IACpD,KAAK,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;CACjC;AAsDH,QAAA,MAAM,cAAc,yDAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
@@ -0,0 +1,91 @@
1
+ <script module lang="ts">
2
+ import type { RecordBase } from '@inkbar/core'
3
+ import type { CardSpec, RecordListSource } from '@inkbar/core/dom'
4
+ import type { Snippet } from 'svelte'
5
+ import type { HTMLAttributes } from 'svelte/elements'
6
+
7
+ export interface InkRecordListProps<
8
+ T extends RecordBase & { page: number } = RecordBase & { page: number },
9
+ > extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
10
+ /** The records to list, as `<plugin>.<name>`. */
11
+ records?: string | undefined
12
+ /**
13
+ * A host's own source, listed in place of `records` with the same controller and cards.
14
+ * `card`, `where` and `sort` do not apply to it.
15
+ */
16
+ source?: RecordListSource | undefined
17
+ /** The card each record shows. Default: its mark's card. */
18
+ card?: ((record: T) => CardSpec) | undefined
19
+ /** Which records to list. Default: those that have a mark. */
20
+ where?: ((record: T) => boolean) | undefined
21
+ /** The order. Default: reading order by the marks' rects. */
22
+ sort?: ((a: T, b: T) => number) | undefined
23
+ /** Bindable, read-only: the number listed, from once the list has mounted. */
24
+ count?: number | undefined
25
+ /** Replaces "Nothing here yet.". */
26
+ empty?: Snippet | undefined
27
+ }
28
+ </script>
29
+
30
+ <script
31
+ lang="ts"
32
+ generics="T extends RecordBase & { page: number } = RecordBase & { page: number }"
33
+ >
34
+ /*
35
+ * The records a plugin keeps under `records` (`<plugin>.<name>`) as a list of cards, the same
36
+ * cards their marks open, with the same actions: `createRecordList` on core's record list
37
+ * controller. The list, the marks and `useRecordSelection` share one selection. `card`, `where`
38
+ * and `sort` replace the marks' card, filter and reading order; a new function rebuilds the
39
+ * list, so pass functions defined once rather than inline. `bind:count` gives the number
40
+ * listed whenever it changes; the `empty` snippet replaces "Nothing here yet.". It fills its
41
+ * parent's height. Inside `InkRoot`; it renders empty on the server.
42
+ *
43
+ * In place of `records`, `source` takes a host's own `RecordListSource` and lists it with the
44
+ * same controller and cards. Give one of the two: with both, `source` wins and a development
45
+ * build warns.
46
+ */
47
+ import { recordsSource, type RecordsSourceOptions } from '@inkbar/core/dom'
48
+ import { DEV } from 'esm-env'
49
+
50
+ import { useInkContext } from '../context.js'
51
+ import { toReadable } from '../to-readable.svelte.js'
52
+
53
+ import RecordCards from './RecordCards.svelte'
54
+
55
+ let {
56
+ records,
57
+ source,
58
+ card,
59
+ where,
60
+ sort,
61
+ // Written, never read: the list reports its count to the host.
62
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
63
+ count = $bindable(),
64
+ empty,
65
+ ...rest
66
+ }: InkRecordListProps<T> = $props()
67
+
68
+ const ctx = useInkContext('InkRecordList')
69
+ const viewport = toReadable(() => ctx.viewport)
70
+
71
+ if (DEV)
72
+ $effect(() => {
73
+ if (records !== undefined && source !== undefined)
74
+ console.warn(
75
+ '[inkbar] InkRecordList takes `records` or `source`, not both: it lists `source`.'
76
+ )
77
+ })
78
+
79
+ const listed = $derived.by((): RecordListSource | null => {
80
+ if (source) return source
81
+ const pluginHost = ctx.pluginHost
82
+ if (!pluginHost || records === undefined) return null
83
+ const opts: RecordsSourceOptions<T> = {}
84
+ if (card) opts.card = card
85
+ if (where) opts.where = where
86
+ if (sort) opts.sort = sort
87
+ return recordsSource<T>({ pluginHost, viewport }, records, opts)
88
+ })
89
+ </script>
90
+
91
+ <RecordCards {...rest} source={listed} {empty} oncount={(n) => (count = n)} />
@@ -0,0 +1,72 @@
1
+ import type { RecordBase } from '@inkbar/core';
2
+ import type { CardSpec, RecordListSource } from '@inkbar/core/dom';
3
+ import type { Snippet } from 'svelte';
4
+ import type { HTMLAttributes } from 'svelte/elements';
5
+ export interface InkRecordListProps<T extends RecordBase & {
6
+ page: number;
7
+ } = RecordBase & {
8
+ page: number;
9
+ }> extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
10
+ /** The records to list, as `<plugin>.<name>`. */
11
+ records?: string | undefined;
12
+ /**
13
+ * A host's own source, listed in place of `records` with the same controller and cards.
14
+ * `card`, `where` and `sort` do not apply to it.
15
+ */
16
+ source?: RecordListSource | undefined;
17
+ /** The card each record shows. Default: its mark's card. */
18
+ card?: ((record: T) => CardSpec) | undefined;
19
+ /** Which records to list. Default: those that have a mark. */
20
+ where?: ((record: T) => boolean) | undefined;
21
+ /** The order. Default: reading order by the marks' rects. */
22
+ sort?: ((a: T, b: T) => number) | undefined;
23
+ /** Bindable, read-only: the number listed, from once the list has mounted. */
24
+ count?: number | undefined;
25
+ /** Replaces "Nothing here yet.". */
26
+ empty?: Snippet | undefined;
27
+ }
28
+ declare function $$render<T extends RecordBase & {
29
+ page: number;
30
+ } = RecordBase & {
31
+ page: number;
32
+ }>(): {
33
+ props: InkRecordListProps<T>;
34
+ exports: {};
35
+ bindings: "count";
36
+ slots: {};
37
+ events: {};
38
+ };
39
+ declare class __sveltets_Render<T extends RecordBase & {
40
+ page: number;
41
+ } = RecordBase & {
42
+ page: number;
43
+ }> {
44
+ props(): ReturnType<typeof $$render<T>>['props'];
45
+ events(): ReturnType<typeof $$render<T>>['events'];
46
+ slots(): ReturnType<typeof $$render<T>>['slots'];
47
+ bindings(): "count";
48
+ exports(): {};
49
+ }
50
+ interface $$IsomorphicComponent {
51
+ new <T extends RecordBase & {
52
+ page: number;
53
+ } = RecordBase & {
54
+ page: number;
55
+ }>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
56
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
57
+ } & ReturnType<__sveltets_Render<T>['exports']>;
58
+ <T extends RecordBase & {
59
+ page: number;
60
+ } = RecordBase & {
61
+ page: number;
62
+ }>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
63
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
64
+ }
65
+ declare const InkRecordList: $$IsomorphicComponent;
66
+ type InkRecordList<T extends RecordBase & {
67
+ page: number;
68
+ } = RecordBase & {
69
+ page: number;
70
+ }> = InstanceType<typeof InkRecordList<T>>;
71
+ export default InkRecordList;
72
+ //# sourceMappingURL=InkRecordList.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkRecordList.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkRecordList.svelte.ts"],"names":[],"mappings":"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"}
@@ -59,8 +59,13 @@
59
59
  tool?: ToolId | undefined
60
60
  onToolChange?: ((tool: ToolId) => void) | undefined
61
61
  /**
62
- * Host tools, added to the built-ins; one with a built-in's id replaces it. Read when a
63
- * document opens.
62
+ * The creation tools, such as `allTools()` or a pick of the tool factories. `select-text`
63
+ * and `select` are always present; a tool with either id replaces it. They are read when a
64
+ * document opens: a tool added later is usable from the next open, one removed stops at
65
+ * once. When the active tool goes, the viewer switches to `select-text` and calls
66
+ * `onToolChange`. A controlled `tool` naming a missing tool is reported back as
67
+ * `select-text` and is not applied again when the tool appears later. Each mounted control
68
+ * for a missing tool logs its own `UnknownTool`.
64
69
  */
65
70
  tools?: Tool[] | undefined
66
71
  /**
@@ -125,6 +130,7 @@
125
130
  writable,
126
131
  } from '@inkbar/core'
127
132
  import {
133
+ attachFileKeys,
128
134
  attachHistoryKeys,
129
135
  createPluginHost,
130
136
  createSearchController,
@@ -136,6 +142,7 @@
136
142
  pageSelectionText,
137
143
  SIGNATURE_FONTS,
138
144
  trackToolStyle,
145
+ unknownTool,
139
146
  viewerSearchOf,
140
147
  } from '@inkbar/core/dom'
141
148
  import { DEV } from 'esm-env'
@@ -143,6 +150,7 @@
143
150
  import { createAttachmentKey } from 'svelte/attachments'
144
151
 
145
152
  import { setInkContext, type InkContext, type InkHistory } from '../context.js'
153
+ import { registeredToolIds } from '../hooks/useRegisteredTool.svelte.js'
146
154
  import { useReadable } from '../use-readable.svelte.js'
147
155
 
148
156
  import type { PluginHistory } from '@inkbar/core'
@@ -400,6 +408,11 @@
400
408
  })
401
409
 
402
410
  function setTool(id: ToolId): void {
411
+ // As the tool controller does: a missing tool is logged and nothing changes.
412
+ if (!isRegistered(id)) {
413
+ logUnknownTool(id)
414
+ return
415
+ }
403
416
  // Picking the active tool again starts it afresh, as after a one-shot tool's use.
404
417
  if (currentTool === id && tools?.active.get() === id) tools.set(id)
405
418
  tool = id
@@ -452,9 +465,12 @@
452
465
  const stopFocus = keepHistoryFocus(el, () =>
453
466
  el.querySelector<HTMLElement>('[data-ink-scroll]')
454
467
  )
468
+ // Ctrl or Cmd+P prints and +S downloads, as InkPrintButton and InkDownloadButton do.
469
+ const stopFileKeys = attachFileKeys(el, () => document)
455
470
  return () => {
456
471
  stopKeys()
457
472
  stopFocus()
473
+ stopFileKeys()
458
474
  }
459
475
  })
460
476
 
@@ -526,6 +542,32 @@
526
542
  }
527
543
  })
528
544
 
545
+ /*
546
+ * The tools are known once the plugins are set up on mount. A tool id nobody registered is
547
+ * logged as `UnknownTool`; as the active tool, from a `tool` prop or because it left `tools`,
548
+ * it falls back to `select-text`, reported through `onToolChange`. A controlled `tool` that
549
+ * stays on the missing id is not applied again.
550
+ */
551
+ /** The ids of the tools the current viewer was built with; InkViewport sets them. */
552
+ let openedToolIds = $state.raw<readonly ToolId[] | null>(null)
553
+ const toolIds = $derived(registeredToolIds(hostTools, pluginHost, openedToolIds))
554
+ const isRegistered = (id: ToolId): boolean =>
555
+ pluginHost === null || toolIds.includes(id)
556
+ /** The tool the engine and the controls see: a missing one never reaches them. */
557
+ const effectiveTool = $derived<ToolId>(
558
+ isRegistered(currentTool) ? currentTool : 'select-text'
559
+ )
560
+ const logUnknownTool = (id: ToolId): void => console.error(unknownTool(id, toolIds))
561
+ $effect(() => {
562
+ const id = currentTool
563
+ if (isRegistered(id)) return
564
+ untrack(() => {
565
+ logUnknownTool(id)
566
+ tool = 'select-text'
567
+ onToolChange?.('select-text')
568
+ })
569
+ })
570
+
529
571
  /*
530
572
  * Ctrl/Cmd+F while focus is in the root and a find bar is mounted; else the browser's. A
531
573
  * native listener: the handler reads the event's `currentTarget`, which is the root here.
@@ -551,12 +593,12 @@
551
593
  history: { batch: (fn) => inkHistory.batch(fn) },
552
594
  // The plugins' tools too, so a plugin tool's style group applies.
553
595
  tools: [...(hostTools ?? []), ...(pluginHost?.tools ?? [])],
554
- tool: currentTool,
596
+ tool: effectiveTool,
555
597
  })
556
598
  )
557
599
  })
558
600
  $effect(() => {
559
- const id = currentTool
601
+ const id = effectiveTool
560
602
  styleTracker?.setTool(id)
561
603
  })
562
604
 
@@ -590,12 +632,18 @@
590
632
  return tools
591
633
  },
592
634
  get tool() {
593
- return currentTool
635
+ return effectiveTool
594
636
  },
595
637
  setTool,
596
638
  get hostTools() {
597
639
  return hostTools
598
640
  },
641
+ get openedToolIds() {
642
+ return openedToolIds
643
+ },
644
+ setOpenedToolIds(ids) {
645
+ openedToolIds = ids
646
+ },
599
647
  get decorateAnnotation() {
600
648
  return decorateAnnotation
601
649
  },
@@ -35,8 +35,13 @@ export interface InkRootProps extends Omit<HTMLAttributes<HTMLDivElement>, 'chil
35
35
  tool?: ToolId | undefined;
36
36
  onToolChange?: ((tool: ToolId) => void) | undefined;
37
37
  /**
38
- * Host tools, added to the built-ins; one with a built-in's id replaces it. Read when a
39
- * document opens.
38
+ * The creation tools, such as `allTools()` or a pick of the tool factories. `select-text`
39
+ * and `select` are always present; a tool with either id replaces it. They are read when a
40
+ * document opens: a tool added later is usable from the next open, one removed stops at
41
+ * once. When the active tool goes, the viewer switches to `select-text` and calls
42
+ * `onToolChange`. A controlled `tool` naming a missing tool is reported back as
43
+ * `select-text` and is not applied again when the tool appears later. Each mounted control
44
+ * for a missing tool logs its own `UnknownTool`.
40
45
  */
41
46
  tools?: Tool[] | undefined;
42
47
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"InkRoot.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkRoot.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,YAAY,EACZ,WAAW,EACX,UAAU,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,SAAS,EACT,cAAc,EACf,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,IAAI,EACJ,MAAM,EACN,SAAS,EACV,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD,MAAM,WAAW,YAAa,SAAQ,IAAI,CACxC,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,GAAG,UAAU,GAAG,SAAS,CACpC;IACC,GAAG,EAAE,cAAc,GAAG,IAAI,CAAA;IAC1B,MAAM,EAAE,SAAS,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,wFAAwF;IACxF,QAAQ,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAA;IACzC;;;;OAIG;IACH,WAAW,CAAC,EAAE,UAAU,EAAE,GAAG,SAAS,CAAA;IACtC,mBAAmB,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAChE,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAC3D;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;IAChC;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAChF,2FAA2F;IAC3F,YAAY,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACzD,gGAAgG;IAChG,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IACnC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACnD;;;OAGG;IACH,KAAK,CAAC,EAAE,IAAI,EAAE,GAAG,SAAS,CAAA;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,EAAE,GAAG,SAAS,CAAA;IACjC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAA;IACnD;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;IAC5B;;;;OAIG;IACH,UAAU,CAAC,EAAE,cAAc,GAAG,SAAS,CAAA;IACvC,2EAA2E;IAC3E,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;IACrC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACnD,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;IAC5B,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACtD,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC7B,OAAO,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAClD;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACjD,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAC/C,gDAAgD;IAChD,GAAG,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QAAE,MAAM,EAAE,SAAS,CAAC;QAAC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC,CAAA;IACzE;;;OAGG;IACH,KAAK,CAAC,EAAE,YAAY,CAAA;CACrB;AA8BH,OAAO,EAAkC,KAAK,UAAU,EAAE,MAAM,eAAe,CAAA;AAkiB/E,QAAA,MAAM,OAAO;;uBAhCc,WAAW,GAAG,IAAI;qBAGpB,SAAS;+DA6BmB,CAAC;AACtD,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;AAC1C,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"InkRoot.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkRoot.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,YAAY,EACZ,WAAW,EACX,UAAU,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,SAAS,EACT,cAAc,EACf,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,EACV,kBAAkB,EAClB,SAAS,EACT,IAAI,EACJ,MAAM,EACN,SAAS,EACV,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD,MAAM,WAAW,YAAa,SAAQ,IAAI,CACxC,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,GAAG,UAAU,GAAG,SAAS,CACpC;IACC,GAAG,EAAE,cAAc,GAAG,IAAI,CAAA;IAC1B,MAAM,EAAE,SAAS,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,wFAAwF;IACxF,QAAQ,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAA;IACzC;;;;OAIG;IACH,WAAW,CAAC,EAAE,UAAU,EAAE,GAAG,SAAS,CAAA;IACtC,mBAAmB,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAChE,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAC3D;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;IAChC;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAChF,2FAA2F;IAC3F,YAAY,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACzD,gGAAgG;IAChG,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IACnC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACnD;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,IAAI,EAAE,GAAG,SAAS,CAAA;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,EAAE,GAAG,SAAS,CAAA;IACjC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAA;IACnD;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;IAC5B;;;;OAIG;IACH,UAAU,CAAC,EAAE,cAAc,GAAG,SAAS,CAAA;IACvC,2EAA2E;IAC3E,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;IACrC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACnD,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;IAC5B,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACtD,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC7B,OAAO,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAClD;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IACjD,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAC/C,gDAAgD;IAChD,GAAG,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QAAE,MAAM,EAAE,SAAS,CAAC;QAAC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC,CAAA;IACzE;;;OAGG;IACH,KAAK,CAAC,EAAE,YAAY,CAAA;CACrB;AAgCH,OAAO,EAAkC,KAAK,UAAU,EAAE,MAAM,eAAe,CAAA;AA4kB/E,QAAA,MAAM,OAAO;;uBAhCc,WAAW,GAAG,IAAI;qBAGpB,SAAS;+DA6BmB,CAAC;AACtD,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;AAC1C,eAAe,OAAO,CAAC"}
@@ -0,0 +1,72 @@
1
+ <script module lang="ts">
2
+ import type { HTMLAttributes } from 'svelte/elements'
3
+
4
+ export interface InkSearchResultsProps extends Omit<
5
+ HTMLAttributes<HTMLDivElement>,
6
+ 'children'
7
+ > {
8
+ /** Show the query field. Default true; turn it off when a find bar is on the page. */
9
+ field?: boolean | undefined
10
+ }
11
+ </script>
12
+
13
+ <script lang="ts">
14
+ /*
15
+ * The search hits as a list of cards, for a sidebar panel: `createSearchResults` on core's
16
+ * record list controller over the root's search. One card per hit, with its page and the text
17
+ * around it. Choosing a card makes its hit current, as the find bar's next and previous do, and
18
+ * the current hit is the selected card. Above the cards, a query field (`field={false}`
19
+ * leaves it out when a find bar is on the page); under them, the find bar's match count.
20
+ * Field and find bar share the search state, so they never disagree. It fills its parent's
21
+ * height. Inside `InkRoot`; it renders empty on the server.
22
+ */
23
+ import {
24
+ findCountText,
25
+ handleResultsFieldKey,
26
+ isBlankQuery,
27
+ searchSource,
28
+ } from '@inkbar/core/dom'
29
+ import { Search } from '@inkbar/icons'
30
+
31
+ import { useInkContext } from '../context.js'
32
+ import { useSearch } from '../hooks/useSearch.svelte.js'
33
+
34
+ import InkIcon from './InkIcon.svelte'
35
+ import RecordCards from './RecordCards.svelte'
36
+
37
+ let { field = true, class: className, ...rest }: InkSearchResultsProps = $props()
38
+
39
+ const ctx = useInkContext('InkSearchResults')
40
+ const search = useSearch()
41
+ const source = $derived(ctx.search ? searchSource(ctx.search) : null)
42
+ // Nothing found yet is the count's to say while a query is in: "No results", or a scan.
43
+ const blank = $derived(isBlankQuery(search.state.query))
44
+ </script>
45
+
46
+ <div {...rest} class={['ink-search-results', className]} data-ink-search-results="">
47
+ {#if field}
48
+ <div class="ink-search-results-bar" role="search">
49
+ <!-- The field is the search state's: a query typed in the find bar shows here. -->
50
+ <div class="ink-input-group">
51
+ <span class="ink-input-accessory"><InkIcon icon={Search} /></span>
52
+ <input
53
+ type="text"
54
+ aria-label="Find in document"
55
+ placeholder="Search for a word or phrase"
56
+ autocomplete="off"
57
+ spellcheck={false}
58
+ value={search.state.query}
59
+ oninput={(e) => search.setQuery(e.currentTarget.value)}
60
+ onkeydown={(e) => handleResultsFieldKey(e, search)}
61
+ />
62
+ </div>
63
+ </div>
64
+ {/if}
65
+ <RecordCards {source} emptyShown={blank}>
66
+ {#snippet empty()}Search to list every match.{/snippet}
67
+ </RecordCards>
68
+ <!-- A footer under the cards, hidden while empty. -->
69
+ <div class="ink-search-results-count" data-ink-search-results-count="">
70
+ {findCountText(search.state)}
71
+ </div>
72
+ </div>
@@ -0,0 +1,9 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ export interface InkSearchResultsProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
3
+ /** Show the query field. Default true; turn it off when a find bar is on the page. */
4
+ field?: boolean | undefined;
5
+ }
6
+ declare const InkSearchResults: import("svelte").Component<InkSearchResultsProps, {}, "">;
7
+ type InkSearchResults = ReturnType<typeof InkSearchResults>;
8
+ export default InkSearchResults;
9
+ //# sourceMappingURL=InkSearchResults.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkSearchResults.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkSearchResults.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CACjD,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,CACX;IACC,sFAAsF;IACtF,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAC5B;AAqEH,QAAA,MAAM,gBAAgB,2DAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}