@inkbar/svelte 0.5.0 → 0.7.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.
- package/README.md +27 -3
- package/dist/components/InkColorMenu.svelte +7 -18
- package/dist/components/InkColorMenu.svelte.d.ts.map +1 -1
- package/dist/components/InkCommand.svelte +63 -0
- package/dist/components/InkCommand.svelte.d.ts +17 -0
- package/dist/components/InkCommand.svelte.d.ts.map +1 -0
- package/dist/components/InkFindBar.svelte +213 -0
- package/dist/components/InkFindBar.svelte.d.ts +6 -0
- package/dist/components/InkFindBar.svelte.d.ts.map +1 -0
- package/dist/components/InkHighlightMenu.svelte +6 -13
- package/dist/components/InkHighlightMenu.svelte.d.ts.map +1 -1
- package/dist/components/InkLineStyleMenu.svelte +7 -17
- package/dist/components/InkLineStyleMenu.svelte.d.ts.map +1 -1
- package/dist/components/InkRoot.svelte +138 -3
- package/dist/components/InkRoot.svelte.d.ts +7 -1
- package/dist/components/InkRoot.svelte.d.ts.map +1 -1
- package/dist/components/InkSearchButton.svelte +56 -0
- package/dist/components/InkSearchButton.svelte.d.ts +5 -0
- package/dist/components/InkSearchButton.svelte.d.ts.map +1 -0
- package/dist/components/InkShapeMenu.svelte +6 -13
- package/dist/components/InkShapeMenu.svelte.d.ts.map +1 -1
- package/dist/components/InkSignatureMenu.svelte +6 -13
- package/dist/components/InkSignatureMenu.svelte.d.ts.map +1 -1
- package/dist/components/InkToolButton.svelte +11 -3
- package/dist/components/InkToolButton.svelte.d.ts.map +1 -1
- package/dist/components/InkViewport.svelte +15 -0
- package/dist/components/InkViewport.svelte.d.ts.map +1 -1
- package/dist/components/menu-open-focus.d.ts +12 -0
- package/dist/components/menu-open-focus.d.ts.map +1 -0
- package/dist/components/menu-open-focus.js +35 -0
- package/dist/components/search-button.d.ts +10 -0
- package/dist/components/search-button.d.ts.map +1 -0
- package/dist/components/search-button.js +1 -0
- package/dist/context.d.ts +21 -4
- package/dist/context.d.ts.map +1 -1
- package/dist/hooks/useCommand.svelte.d.ts +23 -0
- package/dist/hooks/useCommand.svelte.d.ts.map +1 -0
- package/dist/hooks/useCommand.svelte.js +44 -0
- package/dist/hooks/useSearch.svelte.d.ts +11 -0
- package/dist/hooks/useSearch.svelte.d.ts.map +1 -0
- package/dist/hooks/useSearch.svelte.js +31 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/package.json +6 -5
|
@@ -11,7 +11,13 @@
|
|
|
11
11
|
PdfAssets,
|
|
12
12
|
SignatureStore,
|
|
13
13
|
} from '@inkbar/core'
|
|
14
|
-
import type {
|
|
14
|
+
import type {
|
|
15
|
+
DecorateAnnotation,
|
|
16
|
+
InkPlugin,
|
|
17
|
+
Tool,
|
|
18
|
+
ToolId,
|
|
19
|
+
ZoomValue,
|
|
20
|
+
} from '@inkbar/core/dom'
|
|
15
21
|
import type { Snippet } from 'svelte'
|
|
16
22
|
import type { HTMLAttributes } from 'svelte/elements'
|
|
17
23
|
|
|
@@ -39,6 +45,12 @@
|
|
|
39
45
|
* document opens.
|
|
40
46
|
*/
|
|
41
47
|
tools?: Tool[] | undefined
|
|
48
|
+
/**
|
|
49
|
+
* Plugins, set up once when the root is created; a later change to this prop is not
|
|
50
|
+
* applied. Their tools join `tools`, their decoration and page layers apply to every
|
|
51
|
+
* document, and their commands are placed with `InkCommand` or `useCommand`.
|
|
52
|
+
*/
|
|
53
|
+
plugins?: InkPlugin[] | undefined
|
|
42
54
|
/**
|
|
43
55
|
* Adds `data-*` attributes, classes and a screen-reader description to each annotation's
|
|
44
56
|
* element (see `DecorateAnnotation`). Decorations re-apply whenever the annotations change
|
|
@@ -86,13 +98,20 @@
|
|
|
86
98
|
createSnapshotHistory,
|
|
87
99
|
InkError as InkErrorClass,
|
|
88
100
|
openDocument,
|
|
101
|
+
readonly,
|
|
102
|
+
writable,
|
|
89
103
|
} from '@inkbar/core'
|
|
90
104
|
import {
|
|
105
|
+
createPluginHost,
|
|
106
|
+
createSearchController,
|
|
91
107
|
createToolOptions,
|
|
92
108
|
cssVariableDefaults,
|
|
93
109
|
FONT_FAMILIES,
|
|
110
|
+
handleFindKey,
|
|
111
|
+
pageSelectionText,
|
|
94
112
|
SIGNATURE_FONTS,
|
|
95
113
|
trackToolStyle,
|
|
114
|
+
viewerSearchOf,
|
|
96
115
|
} from '@inkbar/core/dom'
|
|
97
116
|
import { DEV } from 'esm-env'
|
|
98
117
|
import { untrack } from 'svelte'
|
|
@@ -101,7 +120,13 @@
|
|
|
101
120
|
import { setInkContext, type InkContext, type InkHistory } from '../context.js'
|
|
102
121
|
import { useReadable } from '../use-readable.svelte.js'
|
|
103
122
|
|
|
104
|
-
import type {
|
|
123
|
+
import type { PluginHistory } from '@inkbar/core'
|
|
124
|
+
import type {
|
|
125
|
+
PluginHost,
|
|
126
|
+
SearchController,
|
|
127
|
+
ToolController,
|
|
128
|
+
Viewport,
|
|
129
|
+
} from '@inkbar/core/dom'
|
|
105
130
|
|
|
106
131
|
let {
|
|
107
132
|
src,
|
|
@@ -114,6 +139,7 @@
|
|
|
114
139
|
tool = $bindable(),
|
|
115
140
|
onToolChange,
|
|
116
141
|
tools: hostTools,
|
|
142
|
+
plugins,
|
|
117
143
|
decorateAnnotation,
|
|
118
144
|
fonts,
|
|
119
145
|
signatures: signatureStore,
|
|
@@ -146,6 +172,7 @@
|
|
|
146
172
|
const IDLE: InkStatus = { state: 'idle' }
|
|
147
173
|
const NO_ANNOTATIONS: readonly Annotation[] = []
|
|
148
174
|
const NO_IDS: readonly string[] = []
|
|
175
|
+
const noop = (): void => undefined
|
|
149
176
|
|
|
150
177
|
/** Signed URLs change; the key does not. Bytes and Blobs are their own identity. */
|
|
151
178
|
function identity(source: DocumentSource | null): unknown {
|
|
@@ -160,6 +187,8 @@
|
|
|
160
187
|
}
|
|
161
188
|
|
|
162
189
|
let document = $state.raw<InkDocument | null>(null)
|
|
190
|
+
/** The same document outside the reactive graph, for the plugins' history. */
|
|
191
|
+
let documentNow: InkDocument | null = null
|
|
163
192
|
/** Overrides the document's status while opening, and when opening itself failed. */
|
|
164
193
|
let override = $state.raw<InkStatus | null>(null)
|
|
165
194
|
let activated = $state<string | null>(null)
|
|
@@ -206,6 +235,8 @@
|
|
|
206
235
|
const pw = sourcePassword
|
|
207
236
|
let cancelled = false
|
|
208
237
|
let opened: InkDocument | null = null
|
|
238
|
+
/** The snapshot history's hold on a controlled document's store. */
|
|
239
|
+
let detach: () => void = noop
|
|
209
240
|
untrack(() => snapshotHistory.clear())
|
|
210
241
|
const source = untrack(() => src)
|
|
211
242
|
if (source === null) {
|
|
@@ -249,7 +280,13 @@
|
|
|
249
280
|
const current = untrack(() => annotations)
|
|
250
281
|
if (doc.annotations.mode === 'controlled' && current !== undefined)
|
|
251
282
|
doc.annotations.setControlledValue(current)
|
|
283
|
+
documentNow = doc
|
|
252
284
|
document = doc
|
|
285
|
+
// Controlled edits run the plugins' reactions inside their own snapshot step.
|
|
286
|
+
if (doc.annotations.mode === 'controlled')
|
|
287
|
+
detach = snapshotHistory.attach(doc.annotations)
|
|
288
|
+
// The document is current, so the host reads its history when it hears of it.
|
|
289
|
+
hostDocument.set(doc)
|
|
253
290
|
override = null
|
|
254
291
|
setTestHook(ref, doc)
|
|
255
292
|
const s = doc.status.get()
|
|
@@ -272,7 +309,11 @@
|
|
|
272
309
|
})()
|
|
273
310
|
return () => {
|
|
274
311
|
cancelled = true
|
|
312
|
+
// Cleared first, so the plugins close their stores while the document is still alive.
|
|
313
|
+
hostDocument.set(null)
|
|
314
|
+
detach()
|
|
275
315
|
opened?.destroy()
|
|
316
|
+
documentNow = null
|
|
276
317
|
document = null
|
|
277
318
|
setTestHook(ref, undefined)
|
|
278
319
|
}
|
|
@@ -295,6 +336,7 @@
|
|
|
295
336
|
function setActivated(id: string | null): void {
|
|
296
337
|
activated = id
|
|
297
338
|
activatedNow = id
|
|
339
|
+
hostActivated.set(id)
|
|
298
340
|
if (id) onActivate?.(id)
|
|
299
341
|
}
|
|
300
342
|
function reportZoom(z: ZoomValue): void {
|
|
@@ -325,8 +367,93 @@
|
|
|
325
367
|
else if (document) document.history.batch(fn)
|
|
326
368
|
else fn()
|
|
327
369
|
},
|
|
370
|
+
track: (store) => pluginHistory.track(store),
|
|
371
|
+
react: (fn) => pluginHistory.react(fn),
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* The history the plugins reach, picked by the open document's mode when they call. The host
|
|
376
|
+
* reads it as soon as a document opens, so it goes by `documentNow`, which is set by then.
|
|
377
|
+
*/
|
|
378
|
+
const activeHistory = (): PluginHistory | undefined => {
|
|
379
|
+
const doc = documentNow
|
|
380
|
+
if (!doc) return undefined
|
|
381
|
+
return doc.annotations.mode === 'controlled' ? snapshotHistory : doc.history
|
|
382
|
+
}
|
|
383
|
+
const pluginHistory: PluginHistory = {
|
|
384
|
+
batch: (fn) => {
|
|
385
|
+
const h = activeHistory()
|
|
386
|
+
if (h) h.batch(fn)
|
|
387
|
+
else fn()
|
|
388
|
+
},
|
|
389
|
+
track: (store) => activeHistory()?.track(store) ?? noop,
|
|
390
|
+
react: (fn) => activeHistory()?.react(fn) ?? noop,
|
|
328
391
|
}
|
|
329
392
|
|
|
393
|
+
/*
|
|
394
|
+
* One plugin host for the root's life, built in an effect so that no `setup` runs on the
|
|
395
|
+
* server, where effects never run and nothing would clean it up. Until then `pluginHost` is
|
|
396
|
+
* null and InkCommand renders its command disabled. The open effect above runs first, but
|
|
397
|
+
* the document it opens arrives after an await, so the host is in place by then. It follows
|
|
398
|
+
* these writables rather than the root's state: the open effect sets `hostDocument` once
|
|
399
|
+
* `documentNow` is current.
|
|
400
|
+
*/
|
|
401
|
+
const hostDocument = writable<InkDocument | null>(null)
|
|
402
|
+
const hostActivated = writable<string | null>(null)
|
|
403
|
+
const viewportEl = writable<HTMLElement | null>(null)
|
|
404
|
+
let pluginHost = $state.raw<PluginHost | null>(null)
|
|
405
|
+
/** One search controller for the root's life, built with the plugin host that shares it. */
|
|
406
|
+
let search = $state.raw<SearchController | null>(null)
|
|
407
|
+
$effect(() => {
|
|
408
|
+
const controller = untrack(() =>
|
|
409
|
+
createSearchController({
|
|
410
|
+
document: readonly(hostDocument),
|
|
411
|
+
viewport: () => viewport,
|
|
412
|
+
})
|
|
413
|
+
)
|
|
414
|
+
const host = untrack(() =>
|
|
415
|
+
createPluginHost({
|
|
416
|
+
// Read once, as documented on the prop.
|
|
417
|
+
plugins: plugins ?? [],
|
|
418
|
+
document: readonly(hostDocument),
|
|
419
|
+
history: () => pluginHistory,
|
|
420
|
+
activated: readonly(hostActivated),
|
|
421
|
+
// As in `createViewer`: an id not in the open document is ignored.
|
|
422
|
+
setActivated: (id) => {
|
|
423
|
+
if (id === null || documentNow?.annotations.get(id)) setActivated(id)
|
|
424
|
+
},
|
|
425
|
+
root: readonly(viewportEl),
|
|
426
|
+
decorate: () => decorateAnnotation,
|
|
427
|
+
viewport: () => viewport,
|
|
428
|
+
search: viewerSearchOf(controller),
|
|
429
|
+
})
|
|
430
|
+
)
|
|
431
|
+
search = controller
|
|
432
|
+
pluginHost = host
|
|
433
|
+
// Destroyed after InkViewport's engine and its plugin layers, as in `createViewer`: Svelte
|
|
434
|
+
// creates a component's effects after its template and tears them down in creation order,
|
|
435
|
+
// so the children's teardowns run first.
|
|
436
|
+
return () => {
|
|
437
|
+
host.destroy()
|
|
438
|
+
controller.destroy()
|
|
439
|
+
}
|
|
440
|
+
})
|
|
441
|
+
|
|
442
|
+
/*
|
|
443
|
+
* Ctrl/Cmd+F while focus is in the root and a find bar is mounted; else the browser's. A
|
|
444
|
+
* native listener: the handler reads the event's `currentTarget`, which is the root here.
|
|
445
|
+
*/
|
|
446
|
+
$effect(() => {
|
|
447
|
+
const el = ref
|
|
448
|
+
const controller = search
|
|
449
|
+
if (!el || !controller) return
|
|
450
|
+
const onKeydown = (e: KeyboardEvent): void => {
|
|
451
|
+
handleFindKey(e, controller, () => pageSelectionText(el))
|
|
452
|
+
}
|
|
453
|
+
el.addEventListener('keydown', onKeydown)
|
|
454
|
+
return () => el.removeEventListener('keydown', onKeydown)
|
|
455
|
+
})
|
|
456
|
+
|
|
330
457
|
/** The document's tool style; it batches through `inkHistory`, whichever mode is on. */
|
|
331
458
|
const styleTracker = $derived.by(() => {
|
|
332
459
|
const doc = document
|
|
@@ -335,7 +462,8 @@
|
|
|
335
462
|
trackToolStyle({
|
|
336
463
|
store: doc.annotations,
|
|
337
464
|
history: { batch: (fn) => inkHistory.batch(fn) },
|
|
338
|
-
tools
|
|
465
|
+
// The plugins' tools too, so a plugin tool's style group applies.
|
|
466
|
+
tools: [...(hostTools ?? []), ...(pluginHost?.tools ?? [])],
|
|
339
467
|
tool: currentTool,
|
|
340
468
|
})
|
|
341
469
|
)
|
|
@@ -361,6 +489,13 @@
|
|
|
361
489
|
get selection() {
|
|
362
490
|
return selection.current
|
|
363
491
|
},
|
|
492
|
+
get pluginHost() {
|
|
493
|
+
return pluginHost
|
|
494
|
+
},
|
|
495
|
+
get search() {
|
|
496
|
+
return search
|
|
497
|
+
},
|
|
498
|
+
viewportEl,
|
|
364
499
|
get viewport() {
|
|
365
500
|
return viewport
|
|
366
501
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ChildSnippet } from './child-snippet.js';
|
|
2
2
|
import type { Annotation, AnnotationChange, AnnotationDefaults, DocumentSource, InkDocument, InkError, InkStatus, PdfAssets, SignatureStore } from '@inkbar/core';
|
|
3
|
-
import type { DecorateAnnotation, Tool, ToolId, ZoomValue } from '@inkbar/core/dom';
|
|
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';
|
|
6
6
|
export interface InkRootProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'onchange' | 'onerror'> {
|
|
@@ -24,6 +24,12 @@ export interface InkRootProps extends Omit<HTMLAttributes<HTMLDivElement>, 'chil
|
|
|
24
24
|
* document opens.
|
|
25
25
|
*/
|
|
26
26
|
tools?: Tool[] | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Plugins, set up once when the root is created; a later change to this prop is not
|
|
29
|
+
* applied. Their tools join `tools`, their decoration and page layers apply to every
|
|
30
|
+
* document, and their commands are placed with `InkCommand` or `useCommand`.
|
|
31
|
+
*/
|
|
32
|
+
plugins?: InkPlugin[] | undefined;
|
|
27
33
|
/**
|
|
28
34
|
* Adds `data-*` attributes, classes and a screen-reader description to each annotation's
|
|
29
35
|
* element (see `DecorateAnnotation`). Decorations re-apply whenever the annotations change
|
|
@@ -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,WAAW,EACX,QAAQ,EACR,SAAS,EACT,SAAS,EACT,cAAc,EACf,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,
|
|
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,56 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/*
|
|
3
|
+
* Opens the find bar; pressed while it is open. Pressing it again focuses the field. Place
|
|
4
|
+
* it in a toolbar next to `InkFindBar`, which it needs for the field to focus. Disabled until
|
|
5
|
+
* a document is open.
|
|
6
|
+
*/
|
|
7
|
+
import { Search } from '@inkbar/icons'
|
|
8
|
+
import { Toolbar } from 'bits-ui'
|
|
9
|
+
import { tick } from 'svelte'
|
|
10
|
+
|
|
11
|
+
import { useInkContext } from '../context.js'
|
|
12
|
+
import { useDocument } from '../hooks/useDocument.svelte.js'
|
|
13
|
+
import { useSearch } from '../hooks/useSearch.svelte.js'
|
|
14
|
+
|
|
15
|
+
import { asBitsProps } from './child-snippet.js'
|
|
16
|
+
import InkIcon from './InkIcon.svelte'
|
|
17
|
+
|
|
18
|
+
import type { InkSearchButtonProps } from './search-button.js'
|
|
19
|
+
|
|
20
|
+
let {
|
|
21
|
+
class: className,
|
|
22
|
+
children,
|
|
23
|
+
child,
|
|
24
|
+
disabled,
|
|
25
|
+
onclick,
|
|
26
|
+
...rest
|
|
27
|
+
}: InkSearchButtonProps = $props()
|
|
28
|
+
|
|
29
|
+
const ctx = useInkContext('InkSearchButton')
|
|
30
|
+
const search = useSearch()
|
|
31
|
+
const doc = useDocument()
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<Toolbar.Button
|
|
35
|
+
{...asBitsProps(rest)}
|
|
36
|
+
class={['ink-search-button', className]}
|
|
37
|
+
data-ink-search-button=""
|
|
38
|
+
aria-label="Find"
|
|
39
|
+
title="Find"
|
|
40
|
+
aria-pressed={search.state.open}
|
|
41
|
+
data-state={search.state.open ? 'on' : 'off'}
|
|
42
|
+
disabled={!doc.isReady || !!disabled}
|
|
43
|
+
{...child ? { child } : {}}
|
|
44
|
+
onclick={async (e) => {
|
|
45
|
+
onclick?.(e)
|
|
46
|
+
if (e.defaultPrevented) return
|
|
47
|
+
search.open()
|
|
48
|
+
// The bar shows once this update lands; its field takes focus then.
|
|
49
|
+
await tick()
|
|
50
|
+
const field = ctx.rootEl?.querySelector<HTMLInputElement>('[data-ink-find-bar] input')
|
|
51
|
+
field?.focus()
|
|
52
|
+
field?.select()
|
|
53
|
+
}}
|
|
54
|
+
>
|
|
55
|
+
{#if children}{@render children()}{:else}<InkIcon icon={Search} />{/if}
|
|
56
|
+
</Toolbar.Button>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { InkSearchButtonProps } from './search-button.js';
|
|
2
|
+
declare const InkSearchButton: import("svelte").Component<InkSearchButtonProps, {}, "">;
|
|
3
|
+
type InkSearchButton = ReturnType<typeof InkSearchButton>;
|
|
4
|
+
export default InkSearchButton;
|
|
5
|
+
//# sourceMappingURL=InkSearchButton.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InkSearchButton.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkSearchButton.svelte.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AA8C/D,QAAA,MAAM,eAAe,0DAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
|
|
@@ -18,9 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
<script lang="ts">
|
|
20
20
|
import {
|
|
21
|
-
focusInitialMenuItem,
|
|
22
21
|
handleMenuKeys,
|
|
23
|
-
menuItems,
|
|
24
22
|
SHAPE_COLUMNS,
|
|
25
23
|
SHAPE_ICONS,
|
|
26
24
|
SHAPE_KINDS,
|
|
@@ -35,6 +33,7 @@
|
|
|
35
33
|
import { useToolOptions } from '../hooks/useToolOptions.svelte.js'
|
|
36
34
|
|
|
37
35
|
import InkIcon from './InkIcon.svelte'
|
|
36
|
+
import { createMenuOpenFocus } from './menu-open-focus.js'
|
|
38
37
|
|
|
39
38
|
let { class: className, children, ...rest }: InkShapeMenuProps = $props()
|
|
40
39
|
|
|
@@ -50,15 +49,14 @@
|
|
|
50
49
|
let menu = $state<HTMLElement | null>(null)
|
|
51
50
|
|
|
52
51
|
/** ArrowDown opens on the first item; a click opens on the checked one. */
|
|
53
|
-
|
|
54
|
-
// Bits runs the open-focus callback more than once, so the flag outlives it; reset on close.
|
|
52
|
+
const openFocus = createMenuOpenFocus()
|
|
55
53
|
$effect(() => {
|
|
56
|
-
if (!open)
|
|
54
|
+
if (!open) openFocus.reset()
|
|
57
55
|
})
|
|
58
56
|
function onTriggerKeydown(e: KeyboardEvent): void {
|
|
59
57
|
if (e.key !== 'ArrowDown' || e.defaultPrevented || open) return
|
|
60
58
|
e.preventDefault()
|
|
61
|
-
|
|
59
|
+
openFocus.first()
|
|
62
60
|
open = true
|
|
63
61
|
}
|
|
64
62
|
|
|
@@ -123,13 +121,8 @@
|
|
|
123
121
|
align="start"
|
|
124
122
|
sideOffset={4}
|
|
125
123
|
collisionPadding={8}
|
|
126
|
-
onOpenAutoFocus={(e) =>
|
|
127
|
-
|
|
128
|
-
if (menu) {
|
|
129
|
-
if (focusFirst) menuItems(menu)[0]?.focus({ preventScroll: true })
|
|
130
|
-
else focusInitialMenuItem(menu)
|
|
131
|
-
}
|
|
132
|
-
}}
|
|
124
|
+
onOpenAutoFocus={(e) => openFocus.onOpenAutoFocus(e, menu)}
|
|
125
|
+
onfocusin={openFocus.onfocusin}
|
|
133
126
|
onkeydown={(e) => menu && handleMenuKeys(e, menu)}
|
|
134
127
|
>
|
|
135
128
|
<div
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InkShapeMenu.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkShapeMenu.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAC7C,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,CACX;IACC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAC/B;
|
|
1
|
+
{"version":3,"file":"InkShapeMenu.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/InkShapeMenu.svelte.ts"],"names":[],"mappings":"AAGE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAC7C,cAAc,CAAC,cAAc,CAAC,EAC9B,UAAU,CACX;IACC,uCAAuC;IACvC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAC/B;AA+FH,QAAA,MAAM,YAAY,uDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -21,9 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
<script lang="ts">
|
|
23
23
|
import {
|
|
24
|
-
focusInitialMenuItem,
|
|
25
24
|
handleMenuKeys,
|
|
26
|
-
menuItems,
|
|
27
25
|
SIGNATURE_LABELS,
|
|
28
26
|
signatureMenuModel,
|
|
29
27
|
signaturePreview,
|
|
@@ -39,6 +37,7 @@
|
|
|
39
37
|
|
|
40
38
|
import InkIcon from './InkIcon.svelte'
|
|
41
39
|
import InkSignatureDialog from './InkSignatureDialog.svelte'
|
|
40
|
+
import { createMenuOpenFocus } from './menu-open-focus.js'
|
|
42
41
|
|
|
43
42
|
import type { SignatureOptions, SignatureTemplate } from '@inkbar/core'
|
|
44
43
|
|
|
@@ -65,10 +64,9 @@
|
|
|
65
64
|
let main = $state<HTMLElement | null>(null)
|
|
66
65
|
|
|
67
66
|
/** ArrowDown opens on the first item; a click opens on the checked one. */
|
|
68
|
-
|
|
69
|
-
// Bits runs the open-focus callback more than once, so the flag outlives it; reset on close.
|
|
67
|
+
const openFocus = createMenuOpenFocus()
|
|
70
68
|
$effect(() => {
|
|
71
|
-
if (!open)
|
|
69
|
+
if (!open) openFocus.reset()
|
|
72
70
|
})
|
|
73
71
|
/** Set while the menu closes for the dialog, which takes focus instead of the trigger. */
|
|
74
72
|
let toDialog = false
|
|
@@ -76,7 +74,7 @@
|
|
|
76
74
|
function onTriggerKeydown(e: KeyboardEvent): void {
|
|
77
75
|
if (e.key !== 'ArrowDown' || e.defaultPrevented || open) return
|
|
78
76
|
e.preventDefault()
|
|
79
|
-
|
|
77
|
+
openFocus.first()
|
|
80
78
|
open = true
|
|
81
79
|
}
|
|
82
80
|
|
|
@@ -168,13 +166,8 @@
|
|
|
168
166
|
align="start"
|
|
169
167
|
sideOffset={4}
|
|
170
168
|
collisionPadding={8}
|
|
171
|
-
onOpenAutoFocus={(e) =>
|
|
172
|
-
|
|
173
|
-
if (menu) {
|
|
174
|
-
if (focusFirst) menuItems(menu)[0]?.focus({ preventScroll: true })
|
|
175
|
-
else focusInitialMenuItem(menu)
|
|
176
|
-
}
|
|
177
|
-
}}
|
|
169
|
+
onOpenAutoFocus={(e) => openFocus.onOpenAutoFocus(e, menu)}
|
|
170
|
+
onfocusin={openFocus.onfocusin}
|
|
178
171
|
onCloseAutoFocus={(e) => {
|
|
179
172
|
if (toDialog) e.preventDefault()
|
|
180
173
|
toDialog = false
|
|
@@ -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;
|
|
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"}
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
} from '@inkbar/icons'
|
|
28
28
|
import { Toolbar } from 'bits-ui'
|
|
29
29
|
|
|
30
|
+
import { useInkContext } from '../context.js'
|
|
30
31
|
import { useTool } from '../hooks/useTool.svelte.js'
|
|
31
32
|
|
|
32
33
|
import { asBitsProps } from './child-snippet.js'
|
|
@@ -56,11 +57,18 @@
|
|
|
56
57
|
...rest
|
|
57
58
|
}: InkToolButtonProps = $props()
|
|
58
59
|
|
|
60
|
+
const ctx = useInkContext('InkToolButton')
|
|
59
61
|
const current = useTool()
|
|
60
62
|
const active = $derived(current.tool === tool)
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
63
|
+
/** A host or plugin tool by this id, for the name and icon core has none for. */
|
|
64
|
+
const own = $derived(
|
|
65
|
+
[...(ctx.hostTools ?? []), ...(ctx.pluginHost?.tools ?? [])].find(
|
|
66
|
+
(t) => t.id === tool
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
// `label` and `children` win; then core's name and icon; then the tool's own.
|
|
70
|
+
const name = $derived(label ?? TOOL_LABELS[tool] ?? own?.label ?? tool)
|
|
71
|
+
const icon = $derived(ICONS[tool] ?? own?.icon)
|
|
64
72
|
</script>
|
|
65
73
|
|
|
66
74
|
<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;
|
|
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;AAqFH,QAAA,MAAM,aAAa,wDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
|
|
@@ -126,6 +126,11 @@
|
|
|
126
126
|
buffer,
|
|
127
127
|
tool: ctx.tool,
|
|
128
128
|
...(ctx.hostTools ? { tools: ctx.hostTools } : {}),
|
|
129
|
+
// The engine adds the plugins' tools and layers, and decorates through the host, which
|
|
130
|
+
// reads `decorateAnnotation` first.
|
|
131
|
+
...(ctx.pluginHost ? { plugins: ctx.pluginHost } : {}),
|
|
132
|
+
// The highlights draw from the shared search.
|
|
133
|
+
...(ctx.search ? { search: ctx.search } : {}),
|
|
129
134
|
// Read through, so the effect below can re-apply a new function without a rebuild.
|
|
130
135
|
decorateAnnotation: (a) => ctx.decorateAnnotation?.(a),
|
|
131
136
|
...(ctx.toolStyle ? { toolStyle: ctx.toolStyle } : {}),
|
|
@@ -191,6 +196,16 @@
|
|
|
191
196
|
})
|
|
192
197
|
}
|
|
193
198
|
|
|
199
|
+
// The plugins' `root`. Before the build below, so it is set when the engine mounts.
|
|
200
|
+
$effect(() => {
|
|
201
|
+
const el = scroll
|
|
202
|
+
const { viewportEl } = ctx
|
|
203
|
+
viewportEl.set(el)
|
|
204
|
+
return () => {
|
|
205
|
+
if (viewportEl.get() === el) viewportEl.set(null)
|
|
206
|
+
}
|
|
207
|
+
})
|
|
208
|
+
|
|
194
209
|
// Build for a new document or status; tear down on the next change and on unmount. Only the
|
|
195
210
|
// values read before `untrack` are dependencies, each through a derived, which notifies only
|
|
196
211
|
// when the value changes: the status is a new object on every engine report.
|
|
@@ -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;
|
|
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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface MenuOpenFocus {
|
|
2
|
+
/** Makes the next open start on the first item (ArrowDown on the trigger). */
|
|
3
|
+
first: () => void;
|
|
4
|
+
/** For the content's `onOpenAutoFocus`. */
|
|
5
|
+
onOpenAutoFocus: (e: Event, menu: HTMLElement | null) => void;
|
|
6
|
+
/** For the content's `onfocusin`: remembers where the user is. */
|
|
7
|
+
onfocusin: (e: FocusEvent) => void;
|
|
8
|
+
/** Call when the menu closes. */
|
|
9
|
+
reset: () => void;
|
|
10
|
+
}
|
|
11
|
+
export declare function createMenuOpenFocus(): MenuOpenFocus;
|
|
12
|
+
//# sourceMappingURL=menu-open-focus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menu-open-focus.d.ts","sourceRoot":"","sources":["../../src/lib/components/menu-open-focus.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,2CAA2C;IAC3C,eAAe,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAA;IAC7D,kEAAkE;IAClE,SAAS,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;IAClC,iCAAiC;IACjC,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAED,wBAAgB,mBAAmB,IAAI,aAAa,CAsBnD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Where a toolbar menu puts focus as it opens: the first item when ArrowDown opened it, else the
|
|
3
|
+
* checked one. Bits can remount a popover's focus scope just after it opens, which sends focus
|
|
4
|
+
* to the trigger and runs the open-focus callback again; by then the user may have moved on, so
|
|
5
|
+
* a repeat run goes back to the item they last focused.
|
|
6
|
+
*/
|
|
7
|
+
import { focusInitialMenuItem, menuItems } from '@inkbar/core/dom';
|
|
8
|
+
export function createMenuOpenFocus() {
|
|
9
|
+
let first = false;
|
|
10
|
+
let last = null;
|
|
11
|
+
return {
|
|
12
|
+
first: () => {
|
|
13
|
+
first = true;
|
|
14
|
+
},
|
|
15
|
+
onOpenAutoFocus: (e, menu) => {
|
|
16
|
+
e.preventDefault();
|
|
17
|
+
if (!menu)
|
|
18
|
+
return;
|
|
19
|
+
if (last && menu.contains(last))
|
|
20
|
+
last.focus({ preventScroll: true });
|
|
21
|
+
else if (first)
|
|
22
|
+
menuItems(menu)[0]?.focus({ preventScroll: true });
|
|
23
|
+
else
|
|
24
|
+
focusInitialMenuItem(menu);
|
|
25
|
+
},
|
|
26
|
+
onfocusin: (e) => {
|
|
27
|
+
if (e.target instanceof HTMLElement)
|
|
28
|
+
last = e.target;
|
|
29
|
+
},
|
|
30
|
+
reset: () => {
|
|
31
|
+
first = false;
|
|
32
|
+
last = null;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ChildSnippet } from './child-snippet.js';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
4
|
+
/** Props of `InkSearchButton`: a toolbar button that may render through `child`. */
|
|
5
|
+
export interface InkSearchButtonProps extends Omit<HTMLButtonAttributes, 'children'> {
|
|
6
|
+
children?: Snippet | undefined;
|
|
7
|
+
/** Render your own button: spread `props` on it. */
|
|
8
|
+
child?: ChildSnippet | undefined;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=search-button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-button.d.ts","sourceRoot":"","sources":["../../src/lib/components/search-button.ts"],"names":[],"mappings":"AAAA,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,oFAAoF;AACpF,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,oBAAoB,EAAE,UAAU,CAAC;IAClF,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC9B,oDAAoD;IACpD,KAAK,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;CACjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/context.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import type { Annotation, InkDocument, InkStatus, PdfAssets, SignatureLibrary } from '@inkbar/core';
|
|
2
|
-
import type { DecorateAnnotation, Tool, ToolController, ToolId, ToolOptions, ToolStyle, Viewport, ZoomValue } from '@inkbar/core/dom';
|
|
1
|
+
import type { Annotation, InkDocument, InkStatus, PdfAssets, PluginHistory, SignatureLibrary, Writable } from '@inkbar/core';
|
|
2
|
+
import type { DecorateAnnotation, PluginHost, SearchController, Tool, ToolController, ToolId, ToolOptions, ToolStyle, Viewport, ZoomValue } from '@inkbar/core/dom';
|
|
3
3
|
export type { InkStatus };
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Undo and redo for the current document, whichever mode its annotations are in. `track` and
|
|
6
|
+
* `react` (from `PluginHistory`) reach the same history, so plugin stores undo with the edits.
|
|
7
|
+
*/
|
|
8
|
+
export interface InkHistory extends PluginHistory {
|
|
6
9
|
readonly canUndo: boolean;
|
|
7
10
|
readonly canRedo: boolean;
|
|
8
11
|
undo(): void;
|
|
@@ -27,6 +30,20 @@ export interface InkContext {
|
|
|
27
30
|
readonly status: InkStatus;
|
|
28
31
|
readonly annotations: readonly Annotation[];
|
|
29
32
|
readonly selection: readonly string[];
|
|
33
|
+
/**
|
|
34
|
+
* The plugins from InkRoot's `plugins` prop, set up once the root has mounted and kept for
|
|
35
|
+
* its life; `null` before that, and on the server. InkViewport hands it to the engine;
|
|
36
|
+
* InkCommand places its commands.
|
|
37
|
+
*/
|
|
38
|
+
readonly pluginHost: PluginHost | null;
|
|
39
|
+
/**
|
|
40
|
+
* The root's search controller, built with the plugin host and kept for its life; `null`
|
|
41
|
+
* before the root has mounted, and on the server. InkViewport hands it to the engine, which
|
|
42
|
+
* draws the highlights; `useSearch` and the find bar read it.
|
|
43
|
+
*/
|
|
44
|
+
readonly search: SearchController | null;
|
|
45
|
+
/** InkViewport's scroll element while it is mounted: the plugins' `root`. */
|
|
46
|
+
readonly viewportEl: Writable<HTMLElement | null>;
|
|
30
47
|
/** Set by InkViewport once it has built its viewport and tool controller. */
|
|
31
48
|
readonly viewport: Viewport | null;
|
|
32
49
|
readonly tools: ToolController | null;
|