@inkbar/react 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/index.d.mts +178 -85
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +412 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -5
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":["DecorateAnnotation","DecorateAnnotation","AnnotationSlotProps","AnnotationSlotProps","AnnotationSlotProps","ThreadPopoverSlotProps"],"sources":["../src/context.ts","../src/use-readable.ts","../src/hooks/useDocument.ts","../src/hooks/useAnnotations.ts","../src/hooks/useTool.ts","../src/hooks/useToolStyle.ts","../src/hooks/useToolOptions.ts","../src/hooks/useSelection.ts","../src/hooks/useZoom.ts","../src/hooks/usePage.ts","../src/hooks/useHistory.ts","../src/hooks/useEmbedded.ts","../src/components/InkRoot.tsx","../src/components/InkViewport.tsx","../src/components/InkPage.tsx","../src/components/InkAnnotation.tsx","../src/components/InkToolbar.tsx","../src/components/InkIcon.tsx","../src/components/InkToolButton.tsx","../src/components/InkToolbarSeparator.tsx","../src/components/history-button.ts","../src/components/InkUndo.tsx","../src/components/InkRedo.tsx","../src/components/zoom-button.ts","../src/components/InkZoomIn.tsx","../src/components/InkZoomOut.tsx","../src/components/InkZoomSelect.tsx","../src/components/InkPageInput.tsx","../src/components/InkPageCount.tsx","../src/components/page-button.ts","../src/components/InkPrevPage.tsx","../src/components/InkNextPage.tsx","../src/components/InkColorMenu.tsx","../src/components/InkShapeMenu.tsx","../src/components/InkSignatureMenu.tsx","../src/components/InkSignatureDialog.tsx","../src/components/InkHighlightMenu.tsx","../src/components/InkTextStyleMenu.tsx","../src/components/InkLineStyleMenu.tsx","../src/components/InkThreadPopover.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":["DecorateAnnotation","InkPlugin","DecorateAnnotation","AnnotationSlotProps","AnnotationSlotProps","AnnotationSlotProps","ThreadPopoverSlotProps"],"sources":["../src/context.ts","../src/use-readable.ts","../src/hooks/useDocument.ts","../src/hooks/useAnnotations.ts","../src/hooks/useTool.ts","../src/hooks/useToolStyle.ts","../src/hooks/useToolOptions.ts","../src/hooks/useSelection.ts","../src/hooks/useZoom.ts","../src/hooks/useSearch.ts","../src/hooks/usePage.ts","../src/hooks/useHistory.ts","../src/hooks/useEmbedded.ts","../src/hooks/useCommand.ts","../src/components/InkRoot.tsx","../src/components/InkViewport.tsx","../src/components/InkPage.tsx","../src/components/InkAnnotation.tsx","../src/components/InkToolbar.tsx","../src/components/InkIcon.tsx","../src/components/InkToolButton.tsx","../src/components/InkCommand.tsx","../src/components/InkToolbarSeparator.tsx","../src/components/history-button.ts","../src/components/InkUndo.tsx","../src/components/InkRedo.tsx","../src/components/InkSearchButton.tsx","../src/components/InkFindBar.tsx","../src/components/zoom-button.ts","../src/components/InkZoomIn.tsx","../src/components/InkZoomOut.tsx","../src/components/InkZoomSelect.tsx","../src/components/InkPageInput.tsx","../src/components/InkPageCount.tsx","../src/components/page-button.ts","../src/components/InkPrevPage.tsx","../src/components/InkNextPage.tsx","../src/components/InkColorMenu.tsx","../src/components/InkShapeMenu.tsx","../src/components/InkSignatureMenu.tsx","../src/components/InkSignatureDialog.tsx","../src/components/InkHighlightMenu.tsx","../src/components/InkTextStyleMenu.tsx","../src/components/InkLineStyleMenu.tsx","../src/components/InkThreadPopover.tsx"],"mappings":";;;;;;;;;;UA8BiB,mBAAmB;EAClC;EACA;EACA;EACA;EACA;;;;;;;EAOA,QAAQ;;UAGO;EACf,QAAQ;EACR,UAAU;;EAEV,QAAQ;EACR,sBAAsB;EACtB;;;;;;EAMA,YAAY;;;;;;EAMZ,QAAQ;;EAER,YAAY,SAAS;;EAErB,UAAU;EACV,OAAO;;EAEP,MAAM;EACN,UAAU,IAAI;;EAEd,WAAW;;;;;EAKX,oBAAoBA;;;;;EAKpB,6BAA6B;;EAE7B;;EAEA,aAAa;;EAEb,YAAY;;EAEZ;;EAEA,WAAW;;EAEX,WAAW;EACX;EACA,aAAa,GAAG;EAChB,aAAa;;EAEb;;;;;;EAMA,eAAe;EACf,SAAS;EACT,QAAQ;EACR,cAAc,UAAU,iBAAiB,OAAO;;;;;;wBASlC,cAAc,mBAAmB;;;;;;;;wBC3GjC,YAAY,GAAG,UAAU,SAAS,uBAAuB,UAAU,IAAI;;;wBCHvE;;;;;;;;EAYgB,oBAAA,MAAA,6BAA2B,OAAS,yCAAa;;;;wBCbjE;EAcG,MAAA,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EACA,SAAA,YAAM,OAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EACf,SAAA;EACC,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASC,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, createContext, createElement, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
3
|
-
import { InkError, createMemorySignatureStore, createSignatureLibrary, createSnapshotHistory, isAbandonedNote, openDocument, repliesTo, threadOf, threadRoot } from "@inkbar/core";
|
|
4
|
-
import { COLOR_COLUMNS, FONT_FAMILIES, MARKUP_ICONS, MARKUP_KINDS, SHAPE_COLUMNS, SHAPE_ICONS, SHAPE_KINDS, SIGNATURE_FONTS, SIGNATURE_LABELS, SIGNATURE_TABS, TOOL_LABELS, ZOOM_LEVELS, colorMenuModel, createFocusReturn, createSignatureDraft, createToolOptions, cssVariableDefaults, focusInitialMenuItem, fontFamilyValue, handleMenuKeys, handleRadioKeys, handleTabKeys, highlightMenuModel, lineStyleMenuModel, menuItems, mountViewer, observeAnnotationElement, shapeMenuModel, shouldKeepOpenOnAnnotation, signatureMenuModel, signaturePreview, textStyleMenuModel, threadDeleteLabel, threadPopoverLabel, trackToolStyle } from "@inkbar/core/dom";
|
|
3
|
+
import { InkError, createMemorySignatureStore, createSignatureLibrary, createSnapshotHistory, isAbandonedNote, openDocument, readonly, repliesTo, threadOf, threadRoot, writable } from "@inkbar/core";
|
|
4
|
+
import { COLOR_COLUMNS, FONT_FAMILIES, MARKUP_ICONS, MARKUP_KINDS, SHAPE_COLUMNS, SHAPE_ICONS, SHAPE_KINDS, SIGNATURE_FONTS, SIGNATURE_LABELS, SIGNATURE_TABS, TOOL_LABELS, ZOOM_LEVELS, colorMenuModel, createFocusReturn, createPluginHost, createSearchController, createSignatureDraft, createToolOptions, cssVariableDefaults, findAnnouncer, findCountText, focusInitialMenuItem, fontFamilyValue, handleFindKey, handleMenuKeys, handleRadioKeys, handleTabKeys, highlightMenuModel, lineStyleMenuModel, menuItems, mountViewer, observeAnnotationElement, pageSelectionText, shapeMenuModel, shouldKeepOpenOnAnnotation, signatureMenuModel, signaturePreview, textStyleMenuModel, threadDeleteLabel, threadPopoverLabel, trackToolStyle, unknownCommand, viewerSearchOf } from "@inkbar/core/dom";
|
|
5
5
|
import { Dialog, Popover, Select, Slot, Toolbar } from "radix-ui";
|
|
6
6
|
import { createPortal, flushSync } from "react-dom";
|
|
7
7
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
-
import { ALargeSmall, AlignCenter, AlignJustify, AlignLeft, AlignRight, Bold, Check, ChevronDown, ChevronLeft, ChevronRight, Highlighter, ICON_ATTRIBUTES, Italic, MessageSquare, Minus, PenLine, PenTool, Plus, Redo2, Signature, Square, SquareDashedMousePointer, TextCursor, Trash2, Type, Underline, Undo2, ZoomIn, ZoomOut } from "@inkbar/icons";
|
|
8
|
+
import { ALargeSmall, AlignCenter, AlignJustify, AlignLeft, AlignRight, Bold, CaseSensitive, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Highlighter, ICON_ATTRIBUTES, Italic, MessageSquare, Minus, PenLine, PenTool, Plus, Redo2, Search, Signature, Square, SquareDashedMousePointer, TextCursor, Trash2, Type, Underline, Undo2, X, ZoomIn, ZoomOut } from "@inkbar/icons";
|
|
9
9
|
//#region src/context.ts
|
|
10
10
|
const InkContextObject = createContext(null);
|
|
11
11
|
/**
|
|
@@ -19,14 +19,14 @@ function useInkContext(consumer) {
|
|
|
19
19
|
}
|
|
20
20
|
//#endregion
|
|
21
21
|
//#region src/use-readable.ts
|
|
22
|
-
const noop = () => void 0;
|
|
22
|
+
const noop$2 = () => void 0;
|
|
23
23
|
/**
|
|
24
24
|
* Mirrors a core `Readable` into React. A missing readable yields `fallback`, which must be a
|
|
25
25
|
* stable reference (a module constant): `useSyncExternalStore` compares snapshots by identity
|
|
26
26
|
* and loops on a fresh value. On the server the fallback is rendered.
|
|
27
27
|
*/
|
|
28
28
|
function useReadable(readable, fallback) {
|
|
29
|
-
const subscribe = useCallback((onChange) => readable ? readable.subscribe(() => onChange()) : noop, [readable]);
|
|
29
|
+
const subscribe = useCallback((onChange) => readable ? readable.subscribe(() => onChange()) : noop$2, [readable]);
|
|
30
30
|
const get = useCallback(() => readable ? readable.get() : fallback, [readable, fallback]);
|
|
31
31
|
const server = useCallback(() => fallback, [fallback]);
|
|
32
32
|
return useSyncExternalStore(subscribe, get, server);
|
|
@@ -147,6 +147,35 @@ function useZoom() {
|
|
|
147
147
|
]);
|
|
148
148
|
}
|
|
149
149
|
//#endregion
|
|
150
|
+
//#region src/hooks/useSearch.ts
|
|
151
|
+
const CLOSED = {
|
|
152
|
+
open: false,
|
|
153
|
+
query: "",
|
|
154
|
+
matchCase: false,
|
|
155
|
+
hits: [],
|
|
156
|
+
current: -1,
|
|
157
|
+
scanning: false
|
|
158
|
+
};
|
|
159
|
+
const noop$1 = () => void 0;
|
|
160
|
+
/**
|
|
161
|
+
* The document search for hosts building their own control: the state, and the actions the
|
|
162
|
+
* find bar uses. Search is set up once InkRoot has mounted, so until then (and on the server)
|
|
163
|
+
* the state is closed and the actions do nothing. `open()` runs the search and draws the
|
|
164
|
+
* highlights even when no find bar is mounted.
|
|
165
|
+
*/
|
|
166
|
+
function useSearch() {
|
|
167
|
+
const search = useInkContext("useSearch()").search;
|
|
168
|
+
return {
|
|
169
|
+
state: useReadable(search?.state, CLOSED),
|
|
170
|
+
open: search ? (query) => search.open(query) : noop$1,
|
|
171
|
+
setQuery: search ? (query) => search.setQuery(query) : noop$1,
|
|
172
|
+
setMatchCase: search ? (on) => search.setMatchCase(on) : noop$1,
|
|
173
|
+
next: search ? () => search.next() : noop$1,
|
|
174
|
+
previous: search ? () => search.previous() : noop$1,
|
|
175
|
+
close: search ? () => search.close() : noop$1
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
//#endregion
|
|
150
179
|
//#region src/hooks/usePage.ts
|
|
151
180
|
function usePage() {
|
|
152
181
|
const { viewport, document } = useInkContext("usePage()");
|
|
@@ -190,6 +219,40 @@ function useEmbedded() {
|
|
|
190
219
|
}), [summary]);
|
|
191
220
|
}
|
|
192
221
|
//#endregion
|
|
222
|
+
//#region src/hooks/useCommand.ts
|
|
223
|
+
/**
|
|
224
|
+
* A plugin command by its namespaced id (`sandbox.suggest`), for hosts building their own
|
|
225
|
+
* control. Plugins are set up once InkRoot has mounted, so until then (and on the server) the
|
|
226
|
+
* command is disabled with no label; it fills in then. Once they are set up, an id no plugin
|
|
227
|
+
* passed to InkRoot registered stays that way, and logs `InkError('UnknownCommand')` to the
|
|
228
|
+
* console once.
|
|
229
|
+
*/
|
|
230
|
+
function useCommand(id) {
|
|
231
|
+
const { pluginHost } = useInkContext("useCommand()");
|
|
232
|
+
const command = pluginHost?.command(id);
|
|
233
|
+
const logged = useRef(false);
|
|
234
|
+
useEffect(() => {
|
|
235
|
+
if (!pluginHost || command || logged.current) return;
|
|
236
|
+
logged.current = true;
|
|
237
|
+
console.error(unknownCommand(id, [...pluginHost.commands.keys()]));
|
|
238
|
+
}, [
|
|
239
|
+
pluginHost,
|
|
240
|
+
command,
|
|
241
|
+
id
|
|
242
|
+
]);
|
|
243
|
+
const enabled = useReadable(command?.enabled, false);
|
|
244
|
+
const busy = useReadable(command?.busy, false);
|
|
245
|
+
const status = useReadable(command?.status, "");
|
|
246
|
+
return {
|
|
247
|
+
run: useCallback(async () => command?.run(), [command]),
|
|
248
|
+
enabled,
|
|
249
|
+
busy,
|
|
250
|
+
status,
|
|
251
|
+
label: command?.label ?? "",
|
|
252
|
+
icon: command?.icon
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
//#endregion
|
|
193
256
|
//#region src/use-latest.ts
|
|
194
257
|
/**
|
|
195
258
|
* A ref that always holds the latest render's value, for callbacks that outlive a render
|
|
@@ -209,6 +272,7 @@ function useLatest(value) {
|
|
|
209
272
|
const IDLE$1 = { state: "idle" };
|
|
210
273
|
const NO_ANNOTATIONS = [];
|
|
211
274
|
const NO_IDS = [];
|
|
275
|
+
const noop = () => void 0;
|
|
212
276
|
/** Signed URLs change; the key does not. Bytes and Blobs are their own identity. */
|
|
213
277
|
function identity(src) {
|
|
214
278
|
if (src === null) return null;
|
|
@@ -226,7 +290,7 @@ function isDevelopment() {
|
|
|
226
290
|
function setTestHook(el, doc) {
|
|
227
291
|
if (el && isDevelopment()) el.__inkDocument = doc;
|
|
228
292
|
}
|
|
229
|
-
function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsChange, onChange, tool, onToolChange, tools: hostTools, decorateAnnotation, fonts: fontsProp, signatures: signatureStore, signatureFonts: signatureFontsProp, page, onPageChange, zoom, onZoomChange, history, asChild = false, onReady, onError, onActivate, children, ref, ...rest }) {
|
|
293
|
+
function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsChange, onChange, tool, onToolChange, tools: hostTools, plugins: pluginsProp, decorateAnnotation, fonts: fontsProp, signatures: signatureStore, signatureFonts: signatureFontsProp, page, onPageChange, zoom, onZoomChange, history, asChild = false, onReady, onError, onActivate, children, ref, ...rest }) {
|
|
230
294
|
const rootElRef = useRef(null);
|
|
231
295
|
const [rootEl, setRootElState] = useState(null);
|
|
232
296
|
const setRootEl = useCallback((el) => {
|
|
@@ -240,6 +304,8 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
240
304
|
const [internalTool, setInternalTool] = useState(tool ?? "select-text");
|
|
241
305
|
const [activated, setActivatedState] = useState(null);
|
|
242
306
|
const [viewport, setViewportState] = useState(null);
|
|
307
|
+
/** The viewport as of the last `setViewport`, for the plugin host's `scrollTo`. */
|
|
308
|
+
const viewportRef = useRef(null);
|
|
243
309
|
const [tools, setToolsState] = useState(null);
|
|
244
310
|
const documentStatus = useReadable(document?.status, IDLE$1);
|
|
245
311
|
const status = override ?? documentStatus;
|
|
@@ -265,6 +331,7 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
265
331
|
onPageChange,
|
|
266
332
|
onZoomChange,
|
|
267
333
|
hostTools,
|
|
334
|
+
plugins: pluginsProp,
|
|
268
335
|
decorateAnnotation,
|
|
269
336
|
tool: internalTool,
|
|
270
337
|
tools
|
|
@@ -276,6 +343,80 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
276
343
|
useLayoutEffect(() => {
|
|
277
344
|
snapshotHistory.observe(annotations);
|
|
278
345
|
}, [annotations, snapshotHistory]);
|
|
346
|
+
/** What the plugin host follows; plain readables, so StrictMode's second render is harmless. */
|
|
347
|
+
const [plugins] = useState(() => ({
|
|
348
|
+
document: writable(null),
|
|
349
|
+
root: writable(null),
|
|
350
|
+
activated: writable(null)
|
|
351
|
+
}));
|
|
352
|
+
const setActivated = useCallback((id) => {
|
|
353
|
+
setActivatedState(id);
|
|
354
|
+
plugins.activated.set(id);
|
|
355
|
+
if (id) latest.current.onActivate?.(id);
|
|
356
|
+
}, [latest, plugins]);
|
|
357
|
+
/**
|
|
358
|
+
* The history the plugins reach, picked by the open document's mode when they call: the host
|
|
359
|
+
* reads it as soon as a document opens, before this root has rendered with that document.
|
|
360
|
+
*/
|
|
361
|
+
const pluginHistory = useMemo(() => {
|
|
362
|
+
const active = () => {
|
|
363
|
+
const doc = documentRef.current;
|
|
364
|
+
if (!doc) return void 0;
|
|
365
|
+
return doc.annotations.mode === "controlled" ? snapshotHistory : doc.history;
|
|
366
|
+
};
|
|
367
|
+
return {
|
|
368
|
+
batch: (fn) => {
|
|
369
|
+
const h = active();
|
|
370
|
+
if (h) h.batch(fn);
|
|
371
|
+
else fn();
|
|
372
|
+
},
|
|
373
|
+
track: (store) => active()?.track(store) ?? noop,
|
|
374
|
+
react: (fn) => active()?.react(fn) ?? noop
|
|
375
|
+
};
|
|
376
|
+
}, [snapshotHistory]);
|
|
377
|
+
const hostRef = useRef(null);
|
|
378
|
+
const [pluginHost, setPluginHost] = useState(null);
|
|
379
|
+
const [search, setSearch] = useState(null);
|
|
380
|
+
const hostMounts = useRef(0);
|
|
381
|
+
useLayoutEffect(() => {
|
|
382
|
+
hostMounts.current += 1;
|
|
383
|
+
if (!hostRef.current || hostRef.current.destroyed) {
|
|
384
|
+
const search = createSearchController({
|
|
385
|
+
document: readonly(plugins.document),
|
|
386
|
+
viewport: () => viewportRef.current
|
|
387
|
+
});
|
|
388
|
+
const host = createPluginHost({
|
|
389
|
+
plugins: latest.current.plugins ?? [],
|
|
390
|
+
document: readonly(plugins.document),
|
|
391
|
+
history: () => pluginHistory,
|
|
392
|
+
activated: readonly(plugins.activated),
|
|
393
|
+
setActivated: (id) => {
|
|
394
|
+
if (id === null || documentRef.current?.annotations.get(id)) setActivated(id);
|
|
395
|
+
},
|
|
396
|
+
root: readonly(plugins.root),
|
|
397
|
+
decorate: () => latest.current.decorateAnnotation,
|
|
398
|
+
viewport: () => viewportRef.current,
|
|
399
|
+
search: viewerSearchOf(search)
|
|
400
|
+
});
|
|
401
|
+
hostRef.current = {
|
|
402
|
+
host,
|
|
403
|
+
search,
|
|
404
|
+
destroyed: false
|
|
405
|
+
};
|
|
406
|
+
setPluginHost(host);
|
|
407
|
+
setSearch(search);
|
|
408
|
+
}
|
|
409
|
+
return () => {
|
|
410
|
+
hostMounts.current -= 1;
|
|
411
|
+
queueMicrotask(() => {
|
|
412
|
+
const current = hostRef.current;
|
|
413
|
+
if (hostMounts.current > 0 || !current || current.destroyed) return;
|
|
414
|
+
current.destroyed = true;
|
|
415
|
+
current.host.destroy();
|
|
416
|
+
current.search.destroy();
|
|
417
|
+
});
|
|
418
|
+
};
|
|
419
|
+
}, []);
|
|
279
420
|
const srcIdentity = identity(src);
|
|
280
421
|
useEffect(() => {
|
|
281
422
|
let cancelled = false;
|
|
@@ -287,6 +428,9 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
287
428
|
}
|
|
288
429
|
setOverride({ state: "loading" });
|
|
289
430
|
let opened = null;
|
|
431
|
+
/** The plugins told of `opened`, and the snapshot history's hold on its store. */
|
|
432
|
+
let told = null;
|
|
433
|
+
let detach = noop;
|
|
290
434
|
const run = async () => {
|
|
291
435
|
try {
|
|
292
436
|
const doc = await openDocument(source, {
|
|
@@ -316,6 +460,9 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
316
460
|
const current = latest.current.annotations;
|
|
317
461
|
if (doc.annotations.mode === "controlled" && current !== void 0) doc.annotations.setControlledValue(current);
|
|
318
462
|
documentRef.current = doc;
|
|
463
|
+
if (doc.annotations.mode === "controlled") detach = snapshotHistory.attach(doc.annotations);
|
|
464
|
+
told = plugins;
|
|
465
|
+
told.document.set(doc);
|
|
319
466
|
setDocument(doc);
|
|
320
467
|
setOverride(null);
|
|
321
468
|
setTestHook(rootElRef.current, doc);
|
|
@@ -337,6 +484,8 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
337
484
|
});
|
|
338
485
|
return () => {
|
|
339
486
|
cancelled = true;
|
|
487
|
+
told?.document.set(null);
|
|
488
|
+
detach();
|
|
340
489
|
opened?.destroy();
|
|
341
490
|
documentRef.current = null;
|
|
342
491
|
setDocument(null);
|
|
@@ -346,7 +495,8 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
346
495
|
srcIdentity,
|
|
347
496
|
password,
|
|
348
497
|
snapshotHistory,
|
|
349
|
-
latest
|
|
498
|
+
latest,
|
|
499
|
+
plugins
|
|
350
500
|
]);
|
|
351
501
|
useLayoutEffect(() => {
|
|
352
502
|
if (annotations && document?.annotations.mode === "controlled") document.annotations.setControlledValue(annotations);
|
|
@@ -360,13 +510,10 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
360
510
|
setInternalTool(id);
|
|
361
511
|
latest.current.onToolChange?.(id);
|
|
362
512
|
}, [latest]);
|
|
363
|
-
const setActivated = useCallback((id) => {
|
|
364
|
-
setActivatedState(id);
|
|
365
|
-
if (id) latest.current.onActivate?.(id);
|
|
366
|
-
}, [latest]);
|
|
367
513
|
const reportZoom = useCallback((z) => latest.current.onZoomChange?.(z), [latest]);
|
|
368
514
|
const reportPage = useCallback((p) => latest.current.onPageChange?.(p), [latest]);
|
|
369
515
|
const setViewport = useCallback((vp, tc) => {
|
|
516
|
+
viewportRef.current = vp;
|
|
370
517
|
setViewportState(vp);
|
|
371
518
|
setToolsState(tc);
|
|
372
519
|
}, []);
|
|
@@ -384,7 +531,9 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
384
531
|
if (controlled) snapshotHistory.batch(fn);
|
|
385
532
|
else if (documentRef.current) documentRef.current.history.batch(fn);
|
|
386
533
|
else fn();
|
|
387
|
-
}
|
|
534
|
+
},
|
|
535
|
+
track: (store) => pluginHistory.track(store),
|
|
536
|
+
react: (fn) => pluginHistory.react(fn)
|
|
388
537
|
}), [
|
|
389
538
|
controlled,
|
|
390
539
|
historyEnabled,
|
|
@@ -392,19 +541,21 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
392
541
|
snapCanRedo,
|
|
393
542
|
coreCanUndo,
|
|
394
543
|
coreCanRedo,
|
|
395
|
-
snapshotHistory
|
|
544
|
+
snapshotHistory,
|
|
545
|
+
pluginHistory
|
|
396
546
|
]);
|
|
397
547
|
const latestHistory = useLatest(inkHistory);
|
|
398
548
|
/** The document's tool style; it batches through `history`, whichever mode is on. */
|
|
399
549
|
const styleTracker = useMemo(() => document ? trackToolStyle({
|
|
400
550
|
store: document.annotations,
|
|
401
551
|
history: { batch: (fn) => latestHistory.current.batch(fn) },
|
|
402
|
-
tools: latest.current.hostTools,
|
|
552
|
+
tools: [...latest.current.hostTools ?? [], ...pluginHost?.tools ?? []],
|
|
403
553
|
tool: latest.current.tool
|
|
404
554
|
}) : null, [
|
|
405
555
|
document,
|
|
406
556
|
latest,
|
|
407
|
-
latestHistory
|
|
557
|
+
latestHistory,
|
|
558
|
+
pluginHost
|
|
408
559
|
]);
|
|
409
560
|
useEffect(() => {
|
|
410
561
|
styleTracker?.setTool(internalTool);
|
|
@@ -468,6 +619,9 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
468
619
|
reportPage,
|
|
469
620
|
activated,
|
|
470
621
|
setActivated,
|
|
622
|
+
pluginHost,
|
|
623
|
+
search,
|
|
624
|
+
viewportEl: plugins.root,
|
|
471
625
|
history: inkHistory,
|
|
472
626
|
rootEl,
|
|
473
627
|
setViewport
|
|
@@ -495,10 +649,21 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
495
649
|
reportPage,
|
|
496
650
|
activated,
|
|
497
651
|
setActivated,
|
|
652
|
+
pluginHost,
|
|
653
|
+
search,
|
|
654
|
+
plugins,
|
|
498
655
|
inkHistory,
|
|
499
656
|
rootEl,
|
|
500
657
|
setViewport
|
|
501
658
|
]);
|
|
659
|
+
useEffect(() => {
|
|
660
|
+
if (!rootEl || !search) return;
|
|
661
|
+
const onKeyDown = (e) => {
|
|
662
|
+
handleFindKey(e, search, () => pageSelectionText(rootEl));
|
|
663
|
+
};
|
|
664
|
+
rootEl.addEventListener("keydown", onKeyDown);
|
|
665
|
+
return () => rootEl.removeEventListener("keydown", onKeyDown);
|
|
666
|
+
}, [rootEl, search]);
|
|
502
667
|
const Comp = asChild ? Slot.Root : "div";
|
|
503
668
|
return /* @__PURE__ */ jsx(InkContextObject.Provider, {
|
|
504
669
|
value: ctx,
|
|
@@ -670,6 +835,8 @@ function InkViewport({ mode = "continuous", rotation = 0, gap = 16, buffer = 2,
|
|
|
670
835
|
buffer: b,
|
|
671
836
|
tool: c.tool,
|
|
672
837
|
...c.hostTools ? { tools: c.hostTools } : {},
|
|
838
|
+
...c.pluginHost ? { plugins: c.pluginHost } : {},
|
|
839
|
+
...c.search ? { search: c.search } : {},
|
|
673
840
|
decorateAnnotation: (a) => latest.current.ctx.decorateAnnotation(a),
|
|
674
841
|
...c.toolStyle ? { toolStyle: c.toolStyle } : {},
|
|
675
842
|
toolHistory: { batch: (fn) => latest.current.ctx.history.batch(fn) },
|
|
@@ -737,8 +904,18 @@ function InkViewport({ mode = "continuous", rotation = 0, gap = 16, buffer = 2,
|
|
|
737
904
|
}, [
|
|
738
905
|
ctx.document,
|
|
739
906
|
ctx.status.state,
|
|
907
|
+
ctx.pluginHost,
|
|
908
|
+
ctx.search,
|
|
740
909
|
latest
|
|
741
910
|
]);
|
|
911
|
+
const { viewportEl } = ctx;
|
|
912
|
+
useLayoutEffect(() => {
|
|
913
|
+
const el = scroll.current;
|
|
914
|
+
viewportEl.set(el);
|
|
915
|
+
return () => {
|
|
916
|
+
if (viewportEl.get() === el) viewportEl.set(null);
|
|
917
|
+
};
|
|
918
|
+
}, [viewportEl]);
|
|
742
919
|
const { onDecorateAnnotationChange } = ctx;
|
|
743
920
|
useEffect(() => onDecorateAnnotationChange(() => engine.current?.redecorate()), [onDecorateAnnotationChange]);
|
|
744
921
|
useEffect(() => {
|
|
@@ -877,10 +1054,13 @@ const ICONS = {
|
|
|
877
1054
|
signature: Signature
|
|
878
1055
|
};
|
|
879
1056
|
function InkToolButton({ tool, label, asChild = false, className, children, onClick, ...rest }) {
|
|
1057
|
+
const { hostTools, pluginHost } = useInkContext("InkToolButton");
|
|
880
1058
|
const { tool: current, setTool } = useTool();
|
|
881
1059
|
const active = current === tool;
|
|
882
|
-
|
|
883
|
-
const
|
|
1060
|
+
/** A host or plugin tool by this id, for the name and icon core has none for. */
|
|
1061
|
+
const own = [...hostTools ?? [], ...pluginHost?.tools ?? []].find((t) => t.id === tool);
|
|
1062
|
+
const name = label ?? TOOL_LABELS[tool] ?? own?.label ?? tool;
|
|
1063
|
+
const icon = ICONS[tool] ?? own?.icon;
|
|
884
1064
|
return /* @__PURE__ */ jsx(Toolbar.Button, {
|
|
885
1065
|
asChild,
|
|
886
1066
|
className: cx("ink-tool-button", className),
|
|
@@ -902,6 +1082,38 @@ function InkToolButton({ tool, label, asChild = false, className, children, onCl
|
|
|
902
1082
|
});
|
|
903
1083
|
}
|
|
904
1084
|
//#endregion
|
|
1085
|
+
//#region src/components/InkCommand.tsx
|
|
1086
|
+
function InkCommand({ id, asChild = false, children, disabled, onClick, ...rest }) {
|
|
1087
|
+
const { run, enabled, busy, status, label, icon } = useCommand(id);
|
|
1088
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1089
|
+
className: "ink-command",
|
|
1090
|
+
children: [/* @__PURE__ */ jsx(Toolbar.Button, {
|
|
1091
|
+
asChild,
|
|
1092
|
+
type: "button",
|
|
1093
|
+
"data-command": id,
|
|
1094
|
+
"aria-label": label || void 0,
|
|
1095
|
+
title: label || void 0,
|
|
1096
|
+
"aria-hidden": label ? void 0 : true,
|
|
1097
|
+
"aria-busy": busy,
|
|
1098
|
+
"aria-disabled": busy || void 0,
|
|
1099
|
+
...rest,
|
|
1100
|
+
disabled: disabled === true || !enabled && !busy,
|
|
1101
|
+
onClick: (e) => {
|
|
1102
|
+
onClick?.(e);
|
|
1103
|
+
if (!e.defaultPrevented) run();
|
|
1104
|
+
},
|
|
1105
|
+
children: typeof children === "function" ? children({
|
|
1106
|
+
label,
|
|
1107
|
+
busy
|
|
1108
|
+
}) : children ?? (icon ? /* @__PURE__ */ jsx(InkIcon, { icon }) : label)
|
|
1109
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
1110
|
+
className: "ink-command-status",
|
|
1111
|
+
role: "status",
|
|
1112
|
+
children: status
|
|
1113
|
+
})]
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1116
|
+
//#endregion
|
|
905
1117
|
//#region src/components/InkToolbarSeparator.tsx
|
|
906
1118
|
/**
|
|
907
1119
|
* A divider between groups of controls in a horizontal toolbar. Not focusable. A plain div
|
|
@@ -955,6 +1167,188 @@ function InkRedo({ asChild = false, className, children, disabled, onClick, ...r
|
|
|
955
1167
|
});
|
|
956
1168
|
}
|
|
957
1169
|
//#endregion
|
|
1170
|
+
//#region src/components/InkSearchButton.tsx
|
|
1171
|
+
/**
|
|
1172
|
+
* Opens the find bar; pressed while it is open. Pressing it again focuses the field. Place it
|
|
1173
|
+
* in a toolbar next to `InkFindBar`, which it needs for the field to focus. Disabled until a
|
|
1174
|
+
* document is open.
|
|
1175
|
+
*/
|
|
1176
|
+
function InkSearchButton({ asChild = false, className, children, disabled, onClick, ...rest }) {
|
|
1177
|
+
const { rootEl } = useInkContext("InkSearchButton");
|
|
1178
|
+
const { state, open } = useSearch();
|
|
1179
|
+
const { isReady } = useDocument();
|
|
1180
|
+
return /* @__PURE__ */ jsx(Toolbar.Button, {
|
|
1181
|
+
...rest,
|
|
1182
|
+
asChild,
|
|
1183
|
+
className: cx("ink-search-button", className),
|
|
1184
|
+
"data-ink-search-button": "",
|
|
1185
|
+
"aria-label": "Find",
|
|
1186
|
+
title: "Find",
|
|
1187
|
+
"aria-pressed": state.open,
|
|
1188
|
+
"data-state": state.open ? "on" : "off",
|
|
1189
|
+
disabled: !isReady || !!disabled,
|
|
1190
|
+
onClick: (e) => {
|
|
1191
|
+
onClick?.(e);
|
|
1192
|
+
if (e.defaultPrevented) return;
|
|
1193
|
+
flushSync(() => open());
|
|
1194
|
+
const field = rootEl?.querySelector("[data-ink-find-bar] input");
|
|
1195
|
+
field?.focus();
|
|
1196
|
+
field?.select();
|
|
1197
|
+
},
|
|
1198
|
+
children: children ?? /* @__PURE__ */ jsx(InkIcon, { icon: Search })
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
//#endregion
|
|
1202
|
+
//#region src/components/InkFindBar.tsx
|
|
1203
|
+
/**
|
|
1204
|
+
* The find bar: a field, the match count, previous and next, a match-case toggle and close,
|
|
1205
|
+
* a view of the root's search state. Place it anywhere inside `InkRoot`: it portals itself
|
|
1206
|
+
* into `[data-ink-viewport-root]`, the positioned ancestor the theme floats it from over the
|
|
1207
|
+
* top-right of the pages (as `InkThreadPopover` anchors to the root's overlay rather than
|
|
1208
|
+
* where it is written). It renders nothing until `InkViewport` has mounted, and is hidden
|
|
1209
|
+
* while the search is closed. While it is mounted it registers with the search controller,
|
|
1210
|
+
* which is what lets Ctrl/Cmd+F open it.
|
|
1211
|
+
*
|
|
1212
|
+
* Enter in the field steps to the next match, Shift+Enter to the previous, Escape closes.
|
|
1213
|
+
* Closing returns focus to where it was before the bar opened, else to the document.
|
|
1214
|
+
*/
|
|
1215
|
+
function InkFindBar({ className, ...rest }) {
|
|
1216
|
+
const ctx = useInkContext("InkFindBar");
|
|
1217
|
+
const { state, setQuery, setMatchCase, next, previous, close } = useSearch();
|
|
1218
|
+
const scroll = useReadable(ctx.viewportEl, null);
|
|
1219
|
+
/** The viewport root: the scroll element's parent, once InkViewport has mounted. */
|
|
1220
|
+
const target = scroll?.parentElement ?? null;
|
|
1221
|
+
const bar = useRef(null);
|
|
1222
|
+
const field = useRef(null);
|
|
1223
|
+
const live = useRef(null);
|
|
1224
|
+
/** Where focus was when the bar opened, and whether it was open on the last pass. */
|
|
1225
|
+
const before = useRef(null);
|
|
1226
|
+
const wasOpen = useRef(false);
|
|
1227
|
+
useLayoutEffect(() => {
|
|
1228
|
+
const el = bar.current;
|
|
1229
|
+
const input = field.current;
|
|
1230
|
+
if (!el || !input) return;
|
|
1231
|
+
if (state.open !== wasOpen.current) {
|
|
1232
|
+
wasOpen.current = state.open;
|
|
1233
|
+
const doc = el.ownerDocument;
|
|
1234
|
+
if (state.open) {
|
|
1235
|
+
const active = doc.activeElement;
|
|
1236
|
+
before.current = active instanceof HTMLElement && active !== doc.body && !el.contains(active) ? active : null;
|
|
1237
|
+
input.focus();
|
|
1238
|
+
input.select();
|
|
1239
|
+
} else {
|
|
1240
|
+
if (el.contains(doc.activeElement) || doc.activeElement === doc.body) (before.current?.isConnected && !el.contains(before.current) ? before.current : scroll)?.focus({ preventScroll: true });
|
|
1241
|
+
before.current = null;
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
if (input.value !== state.query) {
|
|
1245
|
+
input.value = state.query;
|
|
1246
|
+
if (el.ownerDocument.activeElement === input) input.select();
|
|
1247
|
+
}
|
|
1248
|
+
}, [
|
|
1249
|
+
state.open,
|
|
1250
|
+
state.query,
|
|
1251
|
+
scroll
|
|
1252
|
+
]);
|
|
1253
|
+
const { search } = ctx;
|
|
1254
|
+
useEffect(() => {
|
|
1255
|
+
if (!search || !target) return;
|
|
1256
|
+
return search.attachBar();
|
|
1257
|
+
}, [search, target]);
|
|
1258
|
+
useEffect(() => {
|
|
1259
|
+
const el = live.current;
|
|
1260
|
+
if (!search || !el) return;
|
|
1261
|
+
const announce = findAnnouncer();
|
|
1262
|
+
const say = (s) => {
|
|
1263
|
+
const text = announce(s);
|
|
1264
|
+
if (el.textContent !== text) el.textContent = text;
|
|
1265
|
+
};
|
|
1266
|
+
say(search.state.get());
|
|
1267
|
+
return search.state.subscribe(say);
|
|
1268
|
+
}, [search, target]);
|
|
1269
|
+
useEffect(() => {
|
|
1270
|
+
const el = bar.current;
|
|
1271
|
+
if (!search || !el) return;
|
|
1272
|
+
const onKeyDown = (e) => {
|
|
1273
|
+
if (e.key !== "Escape" || e.defaultPrevented || e.isComposing) return;
|
|
1274
|
+
e.preventDefault();
|
|
1275
|
+
e.stopPropagation();
|
|
1276
|
+
search.close();
|
|
1277
|
+
};
|
|
1278
|
+
el.addEventListener("keydown", onKeyDown);
|
|
1279
|
+
return () => el.removeEventListener("keydown", onKeyDown);
|
|
1280
|
+
}, [search, target]);
|
|
1281
|
+
if (!target) return null;
|
|
1282
|
+
return createPortal(/* @__PURE__ */ jsxs("div", {
|
|
1283
|
+
...rest,
|
|
1284
|
+
ref: bar,
|
|
1285
|
+
className: cx("ink-find-bar", className),
|
|
1286
|
+
"data-ink-find-bar": "",
|
|
1287
|
+
role: "search",
|
|
1288
|
+
hidden: !state.open,
|
|
1289
|
+
children: [
|
|
1290
|
+
/* @__PURE__ */ jsx("input", {
|
|
1291
|
+
ref: field,
|
|
1292
|
+
type: "text",
|
|
1293
|
+
"aria-label": "Find in document",
|
|
1294
|
+
autoComplete: "off",
|
|
1295
|
+
spellCheck: false,
|
|
1296
|
+
onInput: (e) => setQuery(e.currentTarget.value),
|
|
1297
|
+
onKeyDown: (e) => {
|
|
1298
|
+
if (e.key !== "Enter" || e.nativeEvent.isComposing) return;
|
|
1299
|
+
e.preventDefault();
|
|
1300
|
+
if (e.shiftKey) previous();
|
|
1301
|
+
else next();
|
|
1302
|
+
}
|
|
1303
|
+
}),
|
|
1304
|
+
/* @__PURE__ */ jsx("span", {
|
|
1305
|
+
className: "ink-find-count",
|
|
1306
|
+
"data-ink-find-count": "",
|
|
1307
|
+
children: findCountText(state)
|
|
1308
|
+
}),
|
|
1309
|
+
/* @__PURE__ */ jsx("button", {
|
|
1310
|
+
type: "button",
|
|
1311
|
+
"data-ink-find-previous": "",
|
|
1312
|
+
"aria-label": "Previous match",
|
|
1313
|
+
title: "Previous match",
|
|
1314
|
+
onClick: () => previous(),
|
|
1315
|
+
children: /* @__PURE__ */ jsx(InkIcon, { icon: ChevronUp })
|
|
1316
|
+
}),
|
|
1317
|
+
/* @__PURE__ */ jsx("button", {
|
|
1318
|
+
type: "button",
|
|
1319
|
+
"data-ink-find-next": "",
|
|
1320
|
+
"aria-label": "Next match",
|
|
1321
|
+
title: "Next match",
|
|
1322
|
+
onClick: () => next(),
|
|
1323
|
+
children: /* @__PURE__ */ jsx(InkIcon, { icon: ChevronDown })
|
|
1324
|
+
}),
|
|
1325
|
+
/* @__PURE__ */ jsx("button", {
|
|
1326
|
+
type: "button",
|
|
1327
|
+
"data-ink-find-match-case": "",
|
|
1328
|
+
"aria-label": "Match case",
|
|
1329
|
+
title: "Match case",
|
|
1330
|
+
"aria-pressed": state.matchCase,
|
|
1331
|
+
onClick: () => setMatchCase(!state.matchCase),
|
|
1332
|
+
children: /* @__PURE__ */ jsx(InkIcon, { icon: CaseSensitive })
|
|
1333
|
+
}),
|
|
1334
|
+
/* @__PURE__ */ jsx("button", {
|
|
1335
|
+
type: "button",
|
|
1336
|
+
"data-ink-find-close": "",
|
|
1337
|
+
"aria-label": "Close find",
|
|
1338
|
+
title: "Close find",
|
|
1339
|
+
onClick: () => close(),
|
|
1340
|
+
children: /* @__PURE__ */ jsx(InkIcon, { icon: X })
|
|
1341
|
+
}),
|
|
1342
|
+
/* @__PURE__ */ jsx("div", {
|
|
1343
|
+
ref: live,
|
|
1344
|
+
className: "ink-visually-hidden",
|
|
1345
|
+
"data-ink-find-status": "",
|
|
1346
|
+
"aria-live": "polite"
|
|
1347
|
+
})
|
|
1348
|
+
]
|
|
1349
|
+
}), target);
|
|
1350
|
+
}
|
|
1351
|
+
//#endregion
|
|
958
1352
|
//#region src/components/InkZoomIn.tsx
|
|
959
1353
|
function InkZoomIn({ asChild = false, className, children, onClick, ...rest }) {
|
|
960
1354
|
const { zoomIn } = useZoom();
|
|
@@ -2472,6 +2866,6 @@ function ThreadForm({ editingRoot, locked, deleteLabel, onSubmit, onRemove, onCl
|
|
|
2472
2866
|
});
|
|
2473
2867
|
}
|
|
2474
2868
|
//#endregion
|
|
2475
|
-
export { InkAnnotation, InkColorMenu, InkHighlightMenu, InkIcon, InkLineStyleMenu, InkNextPage, InkPage, InkPageCount, InkPageInput, InkPrevPage, InkRedo, InkRoot, InkShapeMenu, InkSignatureDialog, InkSignatureMenu, InkTextStyleMenu, InkThreadPopover, InkToolButton, InkToolbar, InkToolbarSeparator, InkUndo, InkViewport, InkZoomIn, InkZoomOut, InkZoomSelect, useAnnotations, useDocument, useEmbedded, useHistory, useInkContext, usePage, useReadable, useSelection, useTool, useToolOptions, useToolStyle, useZoom };
|
|
2869
|
+
export { InkAnnotation, InkColorMenu, InkCommand, InkFindBar, InkHighlightMenu, InkIcon, InkLineStyleMenu, InkNextPage, InkPage, InkPageCount, InkPageInput, InkPrevPage, InkRedo, InkRoot, InkSearchButton, InkShapeMenu, InkSignatureDialog, InkSignatureMenu, InkTextStyleMenu, InkThreadPopover, InkToolButton, InkToolbar, InkToolbarSeparator, InkUndo, InkViewport, InkZoomIn, InkZoomOut, InkZoomSelect, useAnnotations, useCommand, useDocument, useEmbedded, useHistory, useInkContext, usePage, useReadable, useSearch, useSelection, useTool, useToolOptions, useToolStyle, useZoom };
|
|
2476
2870
|
|
|
2477
2871
|
//# sourceMappingURL=index.mjs.map
|