@inkbar/react 0.5.0 → 0.6.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 +21 -3
- package/dist/index.d.mts +57 -6
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +179 -17
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -151,11 +151,29 @@ The highlight tool leaves `contents` free for the comment. `doc.text(page)` retu
|
|
|
151
151
|
|
|
152
152
|
`InkSignatureMenu` lists saved signatures, picks one for the `signature` tool, removes them, and opens `InkSignatureDialog` to draw, type or upload a new one. These are marks on the page, not cryptographic signatures. Pass `signatures` to `InkRoot` to keep them somewhere: `createLocalSignatureStore(key)` from `@inkbar/core` uses `localStorage`, and without it they last until reload. `signatureFonts` lists the handwriting fonts the Type tab offers; load them with `@font-face`. A placed signature keeps its aspect ratio when resized.
|
|
153
153
|
|
|
154
|
+
## Plugins
|
|
155
|
+
|
|
156
|
+
A plugin from `definePlugin` (in `@inkbar/core/dom`) adds commands, tools, decorations, page layers and its own record stores. Pass plugins to `InkRoot` once: the prop is read when the root mounts. Nothing a plugin registers shows until you place it:
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
<InkRoot src={src} assets={assets} plugins={[suggestions]}>
|
|
160
|
+
<InkToolbar>
|
|
161
|
+
<InkCommand id="sandbox.suggest" />
|
|
162
|
+
<InkToolButton tool="sandbox.stamp" />
|
|
163
|
+
</InkToolbar>
|
|
164
|
+
<InkViewport />
|
|
165
|
+
</InkRoot>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
`InkCommand` is a button named by the command's label, disabled while the command is, and its status in a live region beside it. While the command runs, the button keeps focus and has `aria-busy` and `aria-disabled`, and pressing it does nothing. It shows the command's icon, or its label as text when the command has no icon. To build your own, `useCommand(id)` returns `run`, `enabled`, `busy`, `status`, `label` and `icon`. Plugins are set up once `InkRoot` has mounted in the browser, never on the server. Until then the command is disabled and has no label, and `InkCommand` keeps its button out of the accessibility tree (`aria-hidden`). An id no plugin registered stays that way: `InkCommand` and `useCommand` log an `InkError('UnknownCommand')` to the console once, naming the id and the registered ones, and nothing throws. `InkToolButton` takes a plugin tool's own label and icon.
|
|
169
|
+
|
|
170
|
+
Plugin stores undo with annotations. In controlled mode with `history`, each undo step also snapshots the plugin stores, so accepting something and undoing it restores both.
|
|
171
|
+
|
|
154
172
|
## Custom rendering
|
|
155
173
|
|
|
156
|
-
Slots are render props. `InkViewport` takes `loading`, `empty`, `error`, `renderAnnotation` and `renderPageError`; `InkThreadPopover` takes a function as `children`; `InkToolButton` takes a node or a function of `{ active, label }`. The props each receives are typed as `AnnotationSlotProps` and `ThreadPopoverSlotProps`, the same types the Vue package exports.
|
|
174
|
+
Slots are render props. `InkViewport` takes `loading`, `empty`, `error`, `renderAnnotation` and `renderPageError`; `InkThreadPopover` takes a function as `children`; `InkToolButton` takes a node or a function of `{ active, label }`; `InkCommand` a node or a function of `{ label, busy }`. The props each receives are typed as `AnnotationSlotProps` and `ThreadPopoverSlotProps`, the same types the Vue package exports.
|
|
157
175
|
|
|
158
|
-
`InkRoot`, `InkToolbar`, `InkToolButton`, `InkUndo`, `InkRedo`, `InkPrevPage`, `InkNextPage`, `InkZoomIn` and `InkZoomOut` take `asChild` to render your own element in place of theirs, such as a button from your design system. Pass that element as the only child. The control keeps its behaviour and accessible name.
|
|
176
|
+
`InkRoot`, `InkToolbar`, `InkToolButton`, `InkCommand`, `InkUndo`, `InkRedo`, `InkPrevPage`, `InkNextPage`, `InkZoomIn` and `InkZoomOut` take `asChild` to render your own element in place of theirs, such as a button from your design system. Pass that element as the only child. The control keeps its behaviour and accessible name.
|
|
159
177
|
|
|
160
178
|
## Keyboard
|
|
161
179
|
|
|
@@ -181,7 +199,7 @@ Components carry state on data attributes, for example `[data-annotation][data-s
|
|
|
181
199
|
|
|
182
200
|
## Hooks
|
|
183
201
|
|
|
184
|
-
`useDocument`, `useAnnotations`, `useTool`, `useSelection`, `useZoom`, `usePage`, `useHistory` and `
|
|
202
|
+
`useDocument`, `useAnnotations`, `useTool`, `useSelection`, `useZoom`, `usePage`, `useHistory`, `useEmbedded` and `useCommand` read the state of the nearest `InkRoot`. Build your own toolbar or side panel from them. Tool options, such as the shape kind, last as long as `InkRoot`. The tool style that `useToolStyle` reads and sets (colours, line style, text style) belongs to the document: opening another one starts again from the theme's defaults.
|
|
185
203
|
|
|
186
204
|
## Licence
|
|
187
205
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { ComponentPropsWithoutRef, ReactNode, Ref } from "react";
|
|
2
|
-
import { Annotation, AnnotationChange, AnnotationDefaults, AnnotationDocument, AnnotationInput, AnnotationPatch, CurrentStyle, DocumentSource, ImportOptions, InkDocument, InkError, InkStatus, PageInfo, PdfAssets, Readable, SignatureLibrary, SignatureStore, SignatureTemplate, StyleGroup, StyleKey, StyleProps } from "@inkbar/core";
|
|
3
|
-
import { AnnotationDecoration, AnnotationSlotProps, AnnotationSlotProps as AnnotationSlotProps$1, AnnotationState, ColorProperty, DecorateAnnotation, DecorateAnnotation as DecorateAnnotation$1, LayoutMode, PageMount, ThreadPopoverSlotProps, ThreadPopoverSlotProps as ThreadPopoverSlotProps$1, Tool, ToolController, ToolId, ToolOptions, ToolStyle, ViewRotation, Viewport, ZoomValue } from "@inkbar/core/dom";
|
|
2
|
+
import { Annotation, AnnotationChange, AnnotationDefaults, AnnotationDocument, AnnotationInput, AnnotationPatch, CurrentStyle, DocumentSource, ImportOptions, InkDocument, InkError, InkStatus, PageInfo, PdfAssets, PluginHistory, Readable, SignatureLibrary, SignatureStore, SignatureTemplate, StyleGroup, StyleKey, StyleProps, Writable } from "@inkbar/core";
|
|
3
|
+
import { AnnotationDecoration, AnnotationSlotProps, AnnotationSlotProps as AnnotationSlotProps$1, AnnotationState, ColorProperty, DecorateAnnotation, DecorateAnnotation as DecorateAnnotation$1, InkPlugin, InkPlugin as InkPlugin$1, LayoutMode, PageMount, PluginHost, ThreadPopoverSlotProps, ThreadPopoverSlotProps as ThreadPopoverSlotProps$1, Tool, ToolController, ToolId, ToolOptions, ToolStyle, ViewRotation, Viewport, ZoomValue } from "@inkbar/core/dom";
|
|
4
4
|
import { Select } from "radix-ui";
|
|
5
5
|
import { IconNode } from "@inkbar/icons";
|
|
6
6
|
//#region src/context.d.ts
|
|
7
|
-
/**
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Undo and redo for the current document, whichever mode its annotations are in. `track` and
|
|
9
|
+
* `react` (from `PluginHistory`) reach the same history, so plugin stores undo with the edits.
|
|
10
|
+
*/
|
|
11
|
+
interface InkHistory extends PluginHistory {
|
|
9
12
|
canUndo: boolean;
|
|
10
13
|
canRedo: boolean;
|
|
11
14
|
undo: () => void;
|
|
@@ -26,6 +29,14 @@ interface InkContext {
|
|
|
26
29
|
status: InkStatus;
|
|
27
30
|
annotations: readonly Annotation[];
|
|
28
31
|
selection: readonly string[];
|
|
32
|
+
/**
|
|
33
|
+
* The plugins from InkRoot's `plugins` prop, set up once the root has mounted and kept for
|
|
34
|
+
* its life; `null` before that, and on the server. InkViewport hands it to the engine;
|
|
35
|
+
* InkCommand places its commands.
|
|
36
|
+
*/
|
|
37
|
+
pluginHost: PluginHost | null;
|
|
38
|
+
/** InkViewport's scroll element while it is mounted: the plugins' `root`. */
|
|
39
|
+
viewportEl: Writable<HTMLElement | null>;
|
|
29
40
|
/** Set by InkViewport once it has built its viewport and tool controller. */
|
|
30
41
|
viewport: Viewport | null;
|
|
31
42
|
tools: ToolController | null;
|
|
@@ -2620,6 +2631,28 @@ export declare function useEmbedded(): {
|
|
|
2620
2631
|
hasAny: boolean;
|
|
2621
2632
|
};
|
|
2622
2633
|
//#endregion
|
|
2634
|
+
//#region src/hooks/useCommand.d.ts
|
|
2635
|
+
interface CommandHandle {
|
|
2636
|
+
/** Runs the command; does nothing while it is busy or disabled. Never rejects. */
|
|
2637
|
+
run: () => Promise<void>;
|
|
2638
|
+
/** A ready document (or the plugin's own condition), and not busy. */
|
|
2639
|
+
enabled: boolean;
|
|
2640
|
+
busy: boolean;
|
|
2641
|
+
/** The command's progress or result message, `''` without one. */
|
|
2642
|
+
status: string;
|
|
2643
|
+
/** `''` until the plugins are set up. */
|
|
2644
|
+
label: string;
|
|
2645
|
+
icon: IconNode | undefined;
|
|
2646
|
+
}
|
|
2647
|
+
/**
|
|
2648
|
+
* A plugin command by its namespaced id (`sandbox.suggest`), for hosts building their own
|
|
2649
|
+
* control. Plugins are set up once InkRoot has mounted, so until then (and on the server) the
|
|
2650
|
+
* command is disabled with no label; it fills in then. Once they are set up, an id no plugin
|
|
2651
|
+
* passed to InkRoot registered stays that way, and logs `InkError('UnknownCommand')` to the
|
|
2652
|
+
* console once.
|
|
2653
|
+
*/
|
|
2654
|
+
export declare function useCommand(id: string): CommandHandle;
|
|
2655
|
+
//#endregion
|
|
2623
2656
|
//#region src/components/InkRoot.d.ts
|
|
2624
2657
|
interface InkRootHandle {
|
|
2625
2658
|
readonly document: InkDocument | null;
|
|
@@ -2649,6 +2682,12 @@ interface InkRootProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'
|
|
|
2649
2682
|
* document opens.
|
|
2650
2683
|
*/
|
|
2651
2684
|
tools?: Tool[] | undefined;
|
|
2685
|
+
/**
|
|
2686
|
+
* Plugins, set up once when the root mounts; a later change to this prop is not applied.
|
|
2687
|
+
* Their tools join `tools`, their decoration and page layers apply to every document, and
|
|
2688
|
+
* their commands are placed with `InkCommand` or `useCommand`.
|
|
2689
|
+
*/
|
|
2690
|
+
plugins?: InkPlugin$1[] | undefined;
|
|
2652
2691
|
/**
|
|
2653
2692
|
* Adds `data-*` attributes, classes and a screen-reader description to each annotation's
|
|
2654
2693
|
* element (see `DecorateAnnotation`). Decorations re-apply whenever the annotations change
|
|
@@ -2685,7 +2724,7 @@ interface InkRootProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'
|
|
|
2685
2724
|
}) => ReactNode);
|
|
2686
2725
|
ref?: Ref<InkRootHandle>;
|
|
2687
2726
|
}
|
|
2688
|
-
export declare 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, onReady, onError, onActivate, children, ref, ...rest }: InkRootProps): import("react").JSX.Element;
|
|
2727
|
+
export declare 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, onReady, onError, onActivate, children, ref, ...rest }: InkRootProps): import("react").JSX.Element;
|
|
2689
2728
|
//#endregion
|
|
2690
2729
|
//#region src/components/InkViewport.d.ts
|
|
2691
2730
|
interface InkViewportProps extends ComponentPropsWithoutRef<'div'> {
|
|
@@ -2764,6 +2803,18 @@ interface InkToolButtonProps extends Omit<ComponentPropsWithoutRef<'button'>, 'c
|
|
|
2764
2803
|
}
|
|
2765
2804
|
export declare function InkToolButton({ tool, label, asChild, className, children, onClick, ...rest }: InkToolButtonProps): import("react").JSX.Element;
|
|
2766
2805
|
//#endregion
|
|
2806
|
+
//#region src/components/InkCommand.d.ts
|
|
2807
|
+
interface InkCommandProps extends Omit<ComponentPropsWithoutRef<'button'>, 'id' | 'children'> {
|
|
2808
|
+
/** The command's namespaced id, such as `sandbox.suggest`. */
|
|
2809
|
+
id: string;
|
|
2810
|
+
asChild?: boolean;
|
|
2811
|
+
children?: ReactNode | ((props: {
|
|
2812
|
+
label: string;
|
|
2813
|
+
busy: boolean;
|
|
2814
|
+
}) => ReactNode);
|
|
2815
|
+
}
|
|
2816
|
+
export declare function InkCommand({ id, asChild, children, disabled, onClick, ...rest }: InkCommandProps): import("react").JSX.Element;
|
|
2817
|
+
//#endregion
|
|
2767
2818
|
//#region src/components/InkToolbarSeparator.d.ts
|
|
2768
2819
|
type InkToolbarSeparatorProps = ComponentPropsWithoutRef<'div'>;
|
|
2769
2820
|
/**
|
|
@@ -2898,5 +2949,5 @@ interface InkThreadPopoverProps {
|
|
|
2898
2949
|
}
|
|
2899
2950
|
export declare function InkThreadPopover({ children }: InkThreadPopoverProps): import("react").JSX.Element;
|
|
2900
2951
|
//#endregion
|
|
2901
|
-
export type { AnnotationDecoration, AnnotationSlotProps, AnnotationState, DecorateAnnotation, InkAnnotationProps, InkColorMenuProps, InkContext, InkHighlightMenuProps, InkHistory, InkHistoryButtonProps, InkIconProps, InkLineStyleMenuProps, InkPageButtonProps, InkPageInputProps, InkPageProps, InkRootHandle, InkRootProps, InkShapeMenuProps, InkSignatureDialogProps, InkSignatureMenuProps, InkStatus, InkTextStyleMenuProps, InkThreadPopoverProps, InkToolButtonProps, InkToolbarProps, InkToolbarSeparatorProps, InkViewportProps, InkZoomButtonProps, InkZoomSelectProps, ScopedToolStyleHandle, ThreadPopoverSlotProps, ToolStyleHandle };
|
|
2952
|
+
export type { AnnotationDecoration, AnnotationSlotProps, AnnotationState, CommandHandle, DecorateAnnotation, InkAnnotationProps, InkColorMenuProps, InkCommandProps, InkContext, InkHighlightMenuProps, InkHistory, InkHistoryButtonProps, InkIconProps, InkLineStyleMenuProps, InkPageButtonProps, InkPageInputProps, InkPageProps, InkPlugin, InkRootHandle, InkRootProps, InkShapeMenuProps, InkSignatureDialogProps, InkSignatureMenuProps, InkStatus, InkTextStyleMenuProps, InkThreadPopoverProps, InkToolButtonProps, InkToolbarProps, InkToolbarSeparatorProps, InkViewportProps, InkZoomButtonProps, InkZoomSelectProps, ScopedToolStyleHandle, ThreadPopoverSlotProps, ToolStyleHandle };
|
|
2902
2953
|
//# sourceMappingURL=index.d.mts.map
|
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/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/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":";;;;;;;;;;UA6BiB,mBAAmB;EAClC;EACA;EACA;EACA;EACA;;;;;;;EAOA,QAAQ;;UAGO;EACf,QAAQ;EACR,UAAU;;EAEV,QAAQ;EACR,sBAAsB;EACtB;;;;;;EAMA,YAAY;;EAEZ,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;;;;;;;;wBCpGjC,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,7 +1,7 @@
|
|
|
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, createSignatureDraft, createToolOptions, cssVariableDefaults, focusInitialMenuItem, fontFamilyValue, handleMenuKeys, handleRadioKeys, handleTabKeys, highlightMenuModel, lineStyleMenuModel, menuItems, mountViewer, observeAnnotationElement, shapeMenuModel, shouldKeepOpenOnAnnotation, signatureMenuModel, signaturePreview, textStyleMenuModel, threadDeleteLabel, threadPopoverLabel, trackToolStyle, unknownCommand } 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";
|
|
@@ -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$1 = () => 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$1, [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);
|
|
@@ -190,6 +190,40 @@ function useEmbedded() {
|
|
|
190
190
|
}), [summary]);
|
|
191
191
|
}
|
|
192
192
|
//#endregion
|
|
193
|
+
//#region src/hooks/useCommand.ts
|
|
194
|
+
/**
|
|
195
|
+
* A plugin command by its namespaced id (`sandbox.suggest`), for hosts building their own
|
|
196
|
+
* control. Plugins are set up once InkRoot has mounted, so until then (and on the server) the
|
|
197
|
+
* command is disabled with no label; it fills in then. Once they are set up, an id no plugin
|
|
198
|
+
* passed to InkRoot registered stays that way, and logs `InkError('UnknownCommand')` to the
|
|
199
|
+
* console once.
|
|
200
|
+
*/
|
|
201
|
+
function useCommand(id) {
|
|
202
|
+
const { pluginHost } = useInkContext("useCommand()");
|
|
203
|
+
const command = pluginHost?.command(id);
|
|
204
|
+
const logged = useRef(false);
|
|
205
|
+
useEffect(() => {
|
|
206
|
+
if (!pluginHost || command || logged.current) return;
|
|
207
|
+
logged.current = true;
|
|
208
|
+
console.error(unknownCommand(id, [...pluginHost.commands.keys()]));
|
|
209
|
+
}, [
|
|
210
|
+
pluginHost,
|
|
211
|
+
command,
|
|
212
|
+
id
|
|
213
|
+
]);
|
|
214
|
+
const enabled = useReadable(command?.enabled, false);
|
|
215
|
+
const busy = useReadable(command?.busy, false);
|
|
216
|
+
const status = useReadable(command?.status, "");
|
|
217
|
+
return {
|
|
218
|
+
run: useCallback(async () => command?.run(), [command]),
|
|
219
|
+
enabled,
|
|
220
|
+
busy,
|
|
221
|
+
status,
|
|
222
|
+
label: command?.label ?? "",
|
|
223
|
+
icon: command?.icon
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
//#endregion
|
|
193
227
|
//#region src/use-latest.ts
|
|
194
228
|
/**
|
|
195
229
|
* A ref that always holds the latest render's value, for callbacks that outlive a render
|
|
@@ -209,6 +243,7 @@ function useLatest(value) {
|
|
|
209
243
|
const IDLE$1 = { state: "idle" };
|
|
210
244
|
const NO_ANNOTATIONS = [];
|
|
211
245
|
const NO_IDS = [];
|
|
246
|
+
const noop = () => void 0;
|
|
212
247
|
/** Signed URLs change; the key does not. Bytes and Blobs are their own identity. */
|
|
213
248
|
function identity(src) {
|
|
214
249
|
if (src === null) return null;
|
|
@@ -226,7 +261,7 @@ function isDevelopment() {
|
|
|
226
261
|
function setTestHook(el, doc) {
|
|
227
262
|
if (el && isDevelopment()) el.__inkDocument = doc;
|
|
228
263
|
}
|
|
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 }) {
|
|
264
|
+
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
265
|
const rootElRef = useRef(null);
|
|
231
266
|
const [rootEl, setRootElState] = useState(null);
|
|
232
267
|
const setRootEl = useCallback((el) => {
|
|
@@ -240,6 +275,8 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
240
275
|
const [internalTool, setInternalTool] = useState(tool ?? "select-text");
|
|
241
276
|
const [activated, setActivatedState] = useState(null);
|
|
242
277
|
const [viewport, setViewportState] = useState(null);
|
|
278
|
+
/** The viewport as of the last `setViewport`, for the plugin host's `scrollTo`. */
|
|
279
|
+
const viewportRef = useRef(null);
|
|
243
280
|
const [tools, setToolsState] = useState(null);
|
|
244
281
|
const documentStatus = useReadable(document?.status, IDLE$1);
|
|
245
282
|
const status = override ?? documentStatus;
|
|
@@ -265,6 +302,7 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
265
302
|
onPageChange,
|
|
266
303
|
onZoomChange,
|
|
267
304
|
hostTools,
|
|
305
|
+
plugins: pluginsProp,
|
|
268
306
|
decorateAnnotation,
|
|
269
307
|
tool: internalTool,
|
|
270
308
|
tools
|
|
@@ -276,6 +314,71 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
276
314
|
useLayoutEffect(() => {
|
|
277
315
|
snapshotHistory.observe(annotations);
|
|
278
316
|
}, [annotations, snapshotHistory]);
|
|
317
|
+
/** What the plugin host follows; plain readables, so StrictMode's second render is harmless. */
|
|
318
|
+
const [plugins] = useState(() => ({
|
|
319
|
+
document: writable(null),
|
|
320
|
+
root: writable(null),
|
|
321
|
+
activated: writable(null)
|
|
322
|
+
}));
|
|
323
|
+
const setActivated = useCallback((id) => {
|
|
324
|
+
setActivatedState(id);
|
|
325
|
+
plugins.activated.set(id);
|
|
326
|
+
if (id) latest.current.onActivate?.(id);
|
|
327
|
+
}, [latest, plugins]);
|
|
328
|
+
/**
|
|
329
|
+
* The history the plugins reach, picked by the open document's mode when they call: the host
|
|
330
|
+
* reads it as soon as a document opens, before this root has rendered with that document.
|
|
331
|
+
*/
|
|
332
|
+
const pluginHistory = useMemo(() => {
|
|
333
|
+
const active = () => {
|
|
334
|
+
const doc = documentRef.current;
|
|
335
|
+
if (!doc) return void 0;
|
|
336
|
+
return doc.annotations.mode === "controlled" ? snapshotHistory : doc.history;
|
|
337
|
+
};
|
|
338
|
+
return {
|
|
339
|
+
batch: (fn) => {
|
|
340
|
+
const h = active();
|
|
341
|
+
if (h) h.batch(fn);
|
|
342
|
+
else fn();
|
|
343
|
+
},
|
|
344
|
+
track: (store) => active()?.track(store) ?? noop,
|
|
345
|
+
react: (fn) => active()?.react(fn) ?? noop
|
|
346
|
+
};
|
|
347
|
+
}, [snapshotHistory]);
|
|
348
|
+
const hostRef = useRef(null);
|
|
349
|
+
const [pluginHost, setPluginHost] = useState(null);
|
|
350
|
+
const hostMounts = useRef(0);
|
|
351
|
+
useLayoutEffect(() => {
|
|
352
|
+
hostMounts.current += 1;
|
|
353
|
+
if (!hostRef.current || hostRef.current.destroyed) {
|
|
354
|
+
const host = createPluginHost({
|
|
355
|
+
plugins: latest.current.plugins ?? [],
|
|
356
|
+
document: readonly(plugins.document),
|
|
357
|
+
history: () => pluginHistory,
|
|
358
|
+
activated: readonly(plugins.activated),
|
|
359
|
+
setActivated: (id) => {
|
|
360
|
+
if (id === null || documentRef.current?.annotations.get(id)) setActivated(id);
|
|
361
|
+
},
|
|
362
|
+
root: readonly(plugins.root),
|
|
363
|
+
decorate: () => latest.current.decorateAnnotation,
|
|
364
|
+
viewport: () => viewportRef.current
|
|
365
|
+
});
|
|
366
|
+
hostRef.current = {
|
|
367
|
+
host,
|
|
368
|
+
destroyed: false
|
|
369
|
+
};
|
|
370
|
+
setPluginHost(host);
|
|
371
|
+
}
|
|
372
|
+
return () => {
|
|
373
|
+
hostMounts.current -= 1;
|
|
374
|
+
queueMicrotask(() => {
|
|
375
|
+
const current = hostRef.current;
|
|
376
|
+
if (hostMounts.current > 0 || !current || current.destroyed) return;
|
|
377
|
+
current.destroyed = true;
|
|
378
|
+
current.host.destroy();
|
|
379
|
+
});
|
|
380
|
+
};
|
|
381
|
+
}, []);
|
|
279
382
|
const srcIdentity = identity(src);
|
|
280
383
|
useEffect(() => {
|
|
281
384
|
let cancelled = false;
|
|
@@ -287,6 +390,9 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
287
390
|
}
|
|
288
391
|
setOverride({ state: "loading" });
|
|
289
392
|
let opened = null;
|
|
393
|
+
/** The plugins told of `opened`, and the snapshot history's hold on its store. */
|
|
394
|
+
let told = null;
|
|
395
|
+
let detach = noop;
|
|
290
396
|
const run = async () => {
|
|
291
397
|
try {
|
|
292
398
|
const doc = await openDocument(source, {
|
|
@@ -316,6 +422,9 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
316
422
|
const current = latest.current.annotations;
|
|
317
423
|
if (doc.annotations.mode === "controlled" && current !== void 0) doc.annotations.setControlledValue(current);
|
|
318
424
|
documentRef.current = doc;
|
|
425
|
+
if (doc.annotations.mode === "controlled") detach = snapshotHistory.attach(doc.annotations);
|
|
426
|
+
told = plugins;
|
|
427
|
+
told.document.set(doc);
|
|
319
428
|
setDocument(doc);
|
|
320
429
|
setOverride(null);
|
|
321
430
|
setTestHook(rootElRef.current, doc);
|
|
@@ -337,6 +446,8 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
337
446
|
});
|
|
338
447
|
return () => {
|
|
339
448
|
cancelled = true;
|
|
449
|
+
told?.document.set(null);
|
|
450
|
+
detach();
|
|
340
451
|
opened?.destroy();
|
|
341
452
|
documentRef.current = null;
|
|
342
453
|
setDocument(null);
|
|
@@ -346,7 +457,8 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
346
457
|
srcIdentity,
|
|
347
458
|
password,
|
|
348
459
|
snapshotHistory,
|
|
349
|
-
latest
|
|
460
|
+
latest,
|
|
461
|
+
plugins
|
|
350
462
|
]);
|
|
351
463
|
useLayoutEffect(() => {
|
|
352
464
|
if (annotations && document?.annotations.mode === "controlled") document.annotations.setControlledValue(annotations);
|
|
@@ -360,13 +472,10 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
360
472
|
setInternalTool(id);
|
|
361
473
|
latest.current.onToolChange?.(id);
|
|
362
474
|
}, [latest]);
|
|
363
|
-
const setActivated = useCallback((id) => {
|
|
364
|
-
setActivatedState(id);
|
|
365
|
-
if (id) latest.current.onActivate?.(id);
|
|
366
|
-
}, [latest]);
|
|
367
475
|
const reportZoom = useCallback((z) => latest.current.onZoomChange?.(z), [latest]);
|
|
368
476
|
const reportPage = useCallback((p) => latest.current.onPageChange?.(p), [latest]);
|
|
369
477
|
const setViewport = useCallback((vp, tc) => {
|
|
478
|
+
viewportRef.current = vp;
|
|
370
479
|
setViewportState(vp);
|
|
371
480
|
setToolsState(tc);
|
|
372
481
|
}, []);
|
|
@@ -384,7 +493,9 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
384
493
|
if (controlled) snapshotHistory.batch(fn);
|
|
385
494
|
else if (documentRef.current) documentRef.current.history.batch(fn);
|
|
386
495
|
else fn();
|
|
387
|
-
}
|
|
496
|
+
},
|
|
497
|
+
track: (store) => pluginHistory.track(store),
|
|
498
|
+
react: (fn) => pluginHistory.react(fn)
|
|
388
499
|
}), [
|
|
389
500
|
controlled,
|
|
390
501
|
historyEnabled,
|
|
@@ -392,19 +503,21 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
392
503
|
snapCanRedo,
|
|
393
504
|
coreCanUndo,
|
|
394
505
|
coreCanRedo,
|
|
395
|
-
snapshotHistory
|
|
506
|
+
snapshotHistory,
|
|
507
|
+
pluginHistory
|
|
396
508
|
]);
|
|
397
509
|
const latestHistory = useLatest(inkHistory);
|
|
398
510
|
/** The document's tool style; it batches through `history`, whichever mode is on. */
|
|
399
511
|
const styleTracker = useMemo(() => document ? trackToolStyle({
|
|
400
512
|
store: document.annotations,
|
|
401
513
|
history: { batch: (fn) => latestHistory.current.batch(fn) },
|
|
402
|
-
tools: latest.current.hostTools,
|
|
514
|
+
tools: [...latest.current.hostTools ?? [], ...pluginHost?.tools ?? []],
|
|
403
515
|
tool: latest.current.tool
|
|
404
516
|
}) : null, [
|
|
405
517
|
document,
|
|
406
518
|
latest,
|
|
407
|
-
latestHistory
|
|
519
|
+
latestHistory,
|
|
520
|
+
pluginHost
|
|
408
521
|
]);
|
|
409
522
|
useEffect(() => {
|
|
410
523
|
styleTracker?.setTool(internalTool);
|
|
@@ -468,6 +581,8 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
468
581
|
reportPage,
|
|
469
582
|
activated,
|
|
470
583
|
setActivated,
|
|
584
|
+
pluginHost,
|
|
585
|
+
viewportEl: plugins.root,
|
|
471
586
|
history: inkHistory,
|
|
472
587
|
rootEl,
|
|
473
588
|
setViewport
|
|
@@ -495,6 +610,8 @@ function InkRoot({ src, assets, password, defaults, annotations, onAnnotationsCh
|
|
|
495
610
|
reportPage,
|
|
496
611
|
activated,
|
|
497
612
|
setActivated,
|
|
613
|
+
pluginHost,
|
|
614
|
+
plugins,
|
|
498
615
|
inkHistory,
|
|
499
616
|
rootEl,
|
|
500
617
|
setViewport
|
|
@@ -670,6 +787,7 @@ function InkViewport({ mode = "continuous", rotation = 0, gap = 16, buffer = 2,
|
|
|
670
787
|
buffer: b,
|
|
671
788
|
tool: c.tool,
|
|
672
789
|
...c.hostTools ? { tools: c.hostTools } : {},
|
|
790
|
+
...c.pluginHost ? { plugins: c.pluginHost } : {},
|
|
673
791
|
decorateAnnotation: (a) => latest.current.ctx.decorateAnnotation(a),
|
|
674
792
|
...c.toolStyle ? { toolStyle: c.toolStyle } : {},
|
|
675
793
|
toolHistory: { batch: (fn) => latest.current.ctx.history.batch(fn) },
|
|
@@ -737,8 +855,17 @@ function InkViewport({ mode = "continuous", rotation = 0, gap = 16, buffer = 2,
|
|
|
737
855
|
}, [
|
|
738
856
|
ctx.document,
|
|
739
857
|
ctx.status.state,
|
|
858
|
+
ctx.pluginHost,
|
|
740
859
|
latest
|
|
741
860
|
]);
|
|
861
|
+
const { viewportEl } = ctx;
|
|
862
|
+
useLayoutEffect(() => {
|
|
863
|
+
const el = scroll.current;
|
|
864
|
+
viewportEl.set(el);
|
|
865
|
+
return () => {
|
|
866
|
+
if (viewportEl.get() === el) viewportEl.set(null);
|
|
867
|
+
};
|
|
868
|
+
}, [viewportEl]);
|
|
742
869
|
const { onDecorateAnnotationChange } = ctx;
|
|
743
870
|
useEffect(() => onDecorateAnnotationChange(() => engine.current?.redecorate()), [onDecorateAnnotationChange]);
|
|
744
871
|
useEffect(() => {
|
|
@@ -877,10 +1004,13 @@ const ICONS = {
|
|
|
877
1004
|
signature: Signature
|
|
878
1005
|
};
|
|
879
1006
|
function InkToolButton({ tool, label, asChild = false, className, children, onClick, ...rest }) {
|
|
1007
|
+
const { hostTools, pluginHost } = useInkContext("InkToolButton");
|
|
880
1008
|
const { tool: current, setTool } = useTool();
|
|
881
1009
|
const active = current === tool;
|
|
882
|
-
|
|
883
|
-
const
|
|
1010
|
+
/** A host or plugin tool by this id, for the name and icon core has none for. */
|
|
1011
|
+
const own = [...hostTools ?? [], ...pluginHost?.tools ?? []].find((t) => t.id === tool);
|
|
1012
|
+
const name = label ?? TOOL_LABELS[tool] ?? own?.label ?? tool;
|
|
1013
|
+
const icon = ICONS[tool] ?? own?.icon;
|
|
884
1014
|
return /* @__PURE__ */ jsx(Toolbar.Button, {
|
|
885
1015
|
asChild,
|
|
886
1016
|
className: cx("ink-tool-button", className),
|
|
@@ -902,6 +1032,38 @@ function InkToolButton({ tool, label, asChild = false, className, children, onCl
|
|
|
902
1032
|
});
|
|
903
1033
|
}
|
|
904
1034
|
//#endregion
|
|
1035
|
+
//#region src/components/InkCommand.tsx
|
|
1036
|
+
function InkCommand({ id, asChild = false, children, disabled, onClick, ...rest }) {
|
|
1037
|
+
const { run, enabled, busy, status, label, icon } = useCommand(id);
|
|
1038
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1039
|
+
className: "ink-command",
|
|
1040
|
+
children: [/* @__PURE__ */ jsx(Toolbar.Button, {
|
|
1041
|
+
asChild,
|
|
1042
|
+
type: "button",
|
|
1043
|
+
"data-command": id,
|
|
1044
|
+
"aria-label": label || void 0,
|
|
1045
|
+
title: label || void 0,
|
|
1046
|
+
"aria-hidden": label ? void 0 : true,
|
|
1047
|
+
"aria-busy": busy,
|
|
1048
|
+
"aria-disabled": busy || void 0,
|
|
1049
|
+
...rest,
|
|
1050
|
+
disabled: disabled === true || !enabled && !busy,
|
|
1051
|
+
onClick: (e) => {
|
|
1052
|
+
onClick?.(e);
|
|
1053
|
+
if (!e.defaultPrevented) run();
|
|
1054
|
+
},
|
|
1055
|
+
children: typeof children === "function" ? children({
|
|
1056
|
+
label,
|
|
1057
|
+
busy
|
|
1058
|
+
}) : children ?? (icon ? /* @__PURE__ */ jsx(InkIcon, { icon }) : label)
|
|
1059
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
1060
|
+
className: "ink-command-status",
|
|
1061
|
+
role: "status",
|
|
1062
|
+
children: status
|
|
1063
|
+
})]
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
//#endregion
|
|
905
1067
|
//#region src/components/InkToolbarSeparator.tsx
|
|
906
1068
|
/**
|
|
907
1069
|
* A divider between groups of controls in a horizontal toolbar. Not focusable. A plain div
|
|
@@ -2472,6 +2634,6 @@ function ThreadForm({ editingRoot, locked, deleteLabel, onSubmit, onRemove, onCl
|
|
|
2472
2634
|
});
|
|
2473
2635
|
}
|
|
2474
2636
|
//#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 };
|
|
2637
|
+
export { InkAnnotation, InkColorMenu, InkCommand, InkHighlightMenu, InkIcon, InkLineStyleMenu, InkNextPage, InkPage, InkPageCount, InkPageInput, InkPrevPage, InkRedo, InkRoot, InkShapeMenu, InkSignatureDialog, InkSignatureMenu, InkTextStyleMenu, InkThreadPopover, InkToolButton, InkToolbar, InkToolbarSeparator, InkUndo, InkViewport, InkZoomIn, InkZoomOut, InkZoomSelect, useAnnotations, useCommand, useDocument, useEmbedded, useHistory, useInkContext, usePage, useReadable, useSelection, useTool, useToolOptions, useToolStyle, useZoom };
|
|
2476
2638
|
|
|
2477
2639
|
//# sourceMappingURL=index.mjs.map
|