@inkbar/react 0.2.0 → 0.3.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 +19 -3
- package/dist/index.d.mts +98 -98
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ Annotations are plain typed objects. Control them from your own state, or let In
|
|
|
30
30
|
pnpm add @inkbar/react @inkbar/core @inkbar/theme
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
React 19
|
|
33
|
+
React 19 and React DOM 19 are peer dependencies. Add the Vite plugin from `@inkbar/core/vite` so PDF.js can load its worker and fonts; the [`@inkbar/core` README](https://github.com/inkbar/inkbar/tree/main/packages/core#serving-pdfjs-assets) covers it. The package is marked `'use client'`, so a React Server Components app can import it from a server component.
|
|
34
34
|
|
|
35
35
|
## Usage
|
|
36
36
|
|
|
@@ -72,6 +72,7 @@ export function Review({
|
|
|
72
72
|
onAnnotationsChange={setAnnotations}
|
|
73
73
|
>
|
|
74
74
|
<InkToolbar>
|
|
75
|
+
<InkToolButton tool="view" />
|
|
75
76
|
<InkToolButton tool="select" />
|
|
76
77
|
<InkToolButton tool="highlight" />
|
|
77
78
|
<InkToolButton tool="redact-area" />
|
|
@@ -144,15 +145,30 @@ Inside `InkRoot`, `useHistory()` returns the same object. Its `batch(fn)` runs `
|
|
|
144
145
|
|
|
145
146
|
`InkNotePopover` opens the thread of the activated note. A new note has no text yet, so the form first writes the note's own text (labelled "Comment"); after that it adds replies.
|
|
146
147
|
|
|
147
|
-
A root note with no text and no replies is removed when its popover closes, or when activation moves to another annotation, so abandoned notes do not stay on the page. Locked notes are never removed. If you add notes yourself (`add({ type: '
|
|
148
|
+
A root note with no text and no replies is removed when its popover closes, or when activation moves to another annotation, so abandoned notes do not stay on the page. Locked notes are never removed. If you add notes yourself (`add({ type: 'text', ... })`), give them `contents`, or they will be removed the first time someone opens and closes them.
|
|
148
149
|
|
|
149
150
|
## Custom rendering
|
|
150
151
|
|
|
151
152
|
Slots are render props. `InkViewport` takes `loading`, `empty`, `error`, `renderAnnotation` and `renderPageError`; `InkNotePopover` and `InkSuggestionCard` take a function as `children`; `InkToolButton` takes a node or a function of `{ active, label }`. The props each receives are typed as `AnnotationSlotProps`, `NotePopoverSlotProps` and `SuggestionCardSlotProps`, the same types the Vue package exports.
|
|
152
153
|
|
|
154
|
+
`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.
|
|
155
|
+
|
|
153
156
|
## Keyboard
|
|
154
157
|
|
|
155
|
-
The scroll
|
|
158
|
+
The scroll area takes focus. From there:
|
|
159
|
+
|
|
160
|
+
- With the `highlight` or `redact-area` tool active, `Enter` turns the text selection into a mark.
|
|
161
|
+
- With the `note` tool active, `Enter` places a note at the centre of the current page and opens it.
|
|
162
|
+
|
|
163
|
+
On a focused annotation:
|
|
164
|
+
|
|
165
|
+
- `Enter` or `Space` selects and activates it. A note opens its thread and a suggested redaction its card; other types are only selected.
|
|
166
|
+
- `ArrowUp` and `ArrowDown` move to the previous or next annotation on the page.
|
|
167
|
+
- `Shift` + arrow moves it by 1 pt, or by 10 pt with `Alt` as well.
|
|
168
|
+
- `Ctrl` or `Cmd` + `Shift` + arrow resizes an area redaction, text box or shape.
|
|
169
|
+
- `Delete` or `Backspace` removes it.
|
|
170
|
+
|
|
171
|
+
The full table, with the zoom and page keys, is in the [`@inkbar/core` README](https://github.com/inkbar/inkbar/tree/main/packages/core#tools-and-keyboard).
|
|
156
172
|
|
|
157
173
|
## Styling
|
|
158
174
|
|
package/dist/index.d.mts
CHANGED
|
@@ -124,8 +124,8 @@ export declare function useAnnotations(): {
|
|
|
124
124
|
createdAt: string;
|
|
125
125
|
modifiedAt: string;
|
|
126
126
|
source: "session" | "pdf";
|
|
127
|
-
type: "
|
|
128
|
-
icon: "
|
|
127
|
+
type: "text";
|
|
128
|
+
icon: "comment" | "note" | "help" | "insert" | "key" | "paragraph";
|
|
129
129
|
author?: string | undefined;
|
|
130
130
|
contents?: string | undefined;
|
|
131
131
|
inReplyTo?: string | undefined;
|
|
@@ -145,13 +145,12 @@ export declare function useAnnotations(): {
|
|
|
145
145
|
createdAt: string;
|
|
146
146
|
modifiedAt: string;
|
|
147
147
|
source: "session" | "pdf";
|
|
148
|
-
type: "
|
|
149
|
-
|
|
148
|
+
type: "freetext";
|
|
149
|
+
contents: string;
|
|
150
150
|
fontSize: number;
|
|
151
151
|
fontFamily: string;
|
|
152
152
|
align: "left" | "center" | "right";
|
|
153
153
|
author?: string | undefined;
|
|
154
|
-
contents?: string | undefined;
|
|
155
154
|
inReplyTo?: string | undefined;
|
|
156
155
|
locked?: boolean | undefined;
|
|
157
156
|
custom?: Record<string, unknown> | undefined;
|
|
@@ -174,13 +173,13 @@ export declare function useAnnotations(): {
|
|
|
174
173
|
modifiedAt: string;
|
|
175
174
|
source: "session" | "pdf";
|
|
176
175
|
type: "square" | "circle";
|
|
177
|
-
|
|
176
|
+
width: number;
|
|
178
177
|
author?: string | undefined;
|
|
179
178
|
contents?: string | undefined;
|
|
180
179
|
inReplyTo?: string | undefined;
|
|
181
180
|
locked?: boolean | undefined;
|
|
182
181
|
custom?: Record<string, unknown> | undefined;
|
|
183
|
-
|
|
182
|
+
interiorColor?: string | undefined;
|
|
184
183
|
} | {
|
|
185
184
|
id: string;
|
|
186
185
|
page: number;
|
|
@@ -204,13 +203,14 @@ export declare function useAnnotations(): {
|
|
|
204
203
|
x: number;
|
|
205
204
|
y: number;
|
|
206
205
|
};
|
|
207
|
-
|
|
206
|
+
width: number;
|
|
208
207
|
author?: string | undefined;
|
|
209
208
|
contents?: string | undefined;
|
|
210
209
|
inReplyTo?: string | undefined;
|
|
211
210
|
locked?: boolean | undefined;
|
|
212
211
|
custom?: Record<string, unknown> | undefined;
|
|
213
|
-
|
|
212
|
+
head?: "square" | "circle" | "none" | "openArrow" | "closedArrow" | "diamond" | "butt" | "slash" | undefined;
|
|
213
|
+
tail?: "square" | "circle" | "none" | "openArrow" | "closedArrow" | "diamond" | "butt" | "slash" | undefined;
|
|
214
214
|
} | {
|
|
215
215
|
id: string;
|
|
216
216
|
page: number;
|
|
@@ -230,13 +230,13 @@ export declare function useAnnotations(): {
|
|
|
230
230
|
x: number;
|
|
231
231
|
y: number;
|
|
232
232
|
}[];
|
|
233
|
-
|
|
233
|
+
width: number;
|
|
234
234
|
author?: string | undefined;
|
|
235
235
|
contents?: string | undefined;
|
|
236
236
|
inReplyTo?: string | undefined;
|
|
237
237
|
locked?: boolean | undefined;
|
|
238
238
|
custom?: Record<string, unknown> | undefined;
|
|
239
|
-
|
|
239
|
+
interiorColor?: string | undefined;
|
|
240
240
|
} | {
|
|
241
241
|
id: string;
|
|
242
242
|
page: number;
|
|
@@ -252,11 +252,11 @@ export declare function useAnnotations(): {
|
|
|
252
252
|
modifiedAt: string;
|
|
253
253
|
source: "session" | "pdf";
|
|
254
254
|
type: "ink";
|
|
255
|
-
|
|
255
|
+
inklist: {
|
|
256
256
|
x: number;
|
|
257
257
|
y: number;
|
|
258
258
|
}[][];
|
|
259
|
-
|
|
259
|
+
width: number;
|
|
260
260
|
author?: string | undefined;
|
|
261
261
|
contents?: string | undefined;
|
|
262
262
|
inReplyTo?: string | undefined;
|
|
@@ -278,7 +278,7 @@ export declare function useAnnotations(): {
|
|
|
278
278
|
source: "session" | "pdf";
|
|
279
279
|
type: "redact";
|
|
280
280
|
origin: "user" | "suggested";
|
|
281
|
-
|
|
281
|
+
interiorColor: string;
|
|
282
282
|
author?: string | undefined;
|
|
283
283
|
contents?: string | undefined;
|
|
284
284
|
inReplyTo?: string | undefined;
|
|
@@ -363,8 +363,8 @@ export declare function useAnnotations(): {
|
|
|
363
363
|
createdAt: string;
|
|
364
364
|
modifiedAt: string;
|
|
365
365
|
source: "session" | "pdf";
|
|
366
|
-
type: "
|
|
367
|
-
icon: "
|
|
366
|
+
type: "text";
|
|
367
|
+
icon: "comment" | "note" | "help" | "insert" | "key" | "paragraph";
|
|
368
368
|
author?: string | undefined;
|
|
369
369
|
contents?: string | undefined;
|
|
370
370
|
inReplyTo?: string | undefined;
|
|
@@ -384,13 +384,12 @@ export declare function useAnnotations(): {
|
|
|
384
384
|
createdAt: string;
|
|
385
385
|
modifiedAt: string;
|
|
386
386
|
source: "session" | "pdf";
|
|
387
|
-
type: "
|
|
388
|
-
|
|
387
|
+
type: "freetext";
|
|
388
|
+
contents: string;
|
|
389
389
|
fontSize: number;
|
|
390
390
|
fontFamily: string;
|
|
391
391
|
align: "left" | "center" | "right";
|
|
392
392
|
author?: string | undefined;
|
|
393
|
-
contents?: string | undefined;
|
|
394
393
|
inReplyTo?: string | undefined;
|
|
395
394
|
locked?: boolean | undefined;
|
|
396
395
|
custom?: Record<string, unknown> | undefined;
|
|
@@ -413,13 +412,13 @@ export declare function useAnnotations(): {
|
|
|
413
412
|
modifiedAt: string;
|
|
414
413
|
source: "session" | "pdf";
|
|
415
414
|
type: "square" | "circle";
|
|
416
|
-
|
|
415
|
+
width: number;
|
|
417
416
|
author?: string | undefined;
|
|
418
417
|
contents?: string | undefined;
|
|
419
418
|
inReplyTo?: string | undefined;
|
|
420
419
|
locked?: boolean | undefined;
|
|
421
420
|
custom?: Record<string, unknown> | undefined;
|
|
422
|
-
|
|
421
|
+
interiorColor?: string | undefined;
|
|
423
422
|
} | {
|
|
424
423
|
id: string;
|
|
425
424
|
page: number;
|
|
@@ -443,13 +442,14 @@ export declare function useAnnotations(): {
|
|
|
443
442
|
x: number;
|
|
444
443
|
y: number;
|
|
445
444
|
};
|
|
446
|
-
|
|
445
|
+
width: number;
|
|
447
446
|
author?: string | undefined;
|
|
448
447
|
contents?: string | undefined;
|
|
449
448
|
inReplyTo?: string | undefined;
|
|
450
449
|
locked?: boolean | undefined;
|
|
451
450
|
custom?: Record<string, unknown> | undefined;
|
|
452
|
-
|
|
451
|
+
head?: "square" | "circle" | "none" | "openArrow" | "closedArrow" | "diamond" | "butt" | "slash" | undefined;
|
|
452
|
+
tail?: "square" | "circle" | "none" | "openArrow" | "closedArrow" | "diamond" | "butt" | "slash" | undefined;
|
|
453
453
|
} | {
|
|
454
454
|
id: string;
|
|
455
455
|
page: number;
|
|
@@ -469,13 +469,13 @@ export declare function useAnnotations(): {
|
|
|
469
469
|
x: number;
|
|
470
470
|
y: number;
|
|
471
471
|
}[];
|
|
472
|
-
|
|
472
|
+
width: number;
|
|
473
473
|
author?: string | undefined;
|
|
474
474
|
contents?: string | undefined;
|
|
475
475
|
inReplyTo?: string | undefined;
|
|
476
476
|
locked?: boolean | undefined;
|
|
477
477
|
custom?: Record<string, unknown> | undefined;
|
|
478
|
-
|
|
478
|
+
interiorColor?: string | undefined;
|
|
479
479
|
} | {
|
|
480
480
|
id: string;
|
|
481
481
|
page: number;
|
|
@@ -491,11 +491,11 @@ export declare function useAnnotations(): {
|
|
|
491
491
|
modifiedAt: string;
|
|
492
492
|
source: "session" | "pdf";
|
|
493
493
|
type: "ink";
|
|
494
|
-
|
|
494
|
+
inklist: {
|
|
495
495
|
x: number;
|
|
496
496
|
y: number;
|
|
497
497
|
}[][];
|
|
498
|
-
|
|
498
|
+
width: number;
|
|
499
499
|
author?: string | undefined;
|
|
500
500
|
contents?: string | undefined;
|
|
501
501
|
inReplyTo?: string | undefined;
|
|
@@ -517,7 +517,7 @@ export declare function useAnnotations(): {
|
|
|
517
517
|
source: "session" | "pdf";
|
|
518
518
|
type: "redact";
|
|
519
519
|
origin: "user" | "suggested";
|
|
520
|
-
|
|
520
|
+
interiorColor: string;
|
|
521
521
|
author?: string | undefined;
|
|
522
522
|
contents?: string | undefined;
|
|
523
523
|
inReplyTo?: string | undefined;
|
|
@@ -605,8 +605,8 @@ export declare function useAnnotations(): {
|
|
|
605
605
|
createdAt: string;
|
|
606
606
|
modifiedAt: string;
|
|
607
607
|
source: "session" | "pdf";
|
|
608
|
-
type: "
|
|
609
|
-
icon: "
|
|
608
|
+
type: "text";
|
|
609
|
+
icon: "comment" | "note" | "help" | "insert" | "key" | "paragraph";
|
|
610
610
|
author?: string | undefined;
|
|
611
611
|
contents?: string | undefined;
|
|
612
612
|
inReplyTo?: string | undefined;
|
|
@@ -626,13 +626,12 @@ export declare function useAnnotations(): {
|
|
|
626
626
|
createdAt: string;
|
|
627
627
|
modifiedAt: string;
|
|
628
628
|
source: "session" | "pdf";
|
|
629
|
-
type: "
|
|
630
|
-
|
|
629
|
+
type: "freetext";
|
|
630
|
+
contents: string;
|
|
631
631
|
fontSize: number;
|
|
632
632
|
fontFamily: string;
|
|
633
633
|
align: "left" | "center" | "right";
|
|
634
634
|
author?: string | undefined;
|
|
635
|
-
contents?: string | undefined;
|
|
636
635
|
inReplyTo?: string | undefined;
|
|
637
636
|
locked?: boolean | undefined;
|
|
638
637
|
custom?: Record<string, unknown> | undefined;
|
|
@@ -655,13 +654,13 @@ export declare function useAnnotations(): {
|
|
|
655
654
|
modifiedAt: string;
|
|
656
655
|
source: "session" | "pdf";
|
|
657
656
|
type: "square" | "circle";
|
|
658
|
-
|
|
657
|
+
width: number;
|
|
659
658
|
author?: string | undefined;
|
|
660
659
|
contents?: string | undefined;
|
|
661
660
|
inReplyTo?: string | undefined;
|
|
662
661
|
locked?: boolean | undefined;
|
|
663
662
|
custom?: Record<string, unknown> | undefined;
|
|
664
|
-
|
|
663
|
+
interiorColor?: string | undefined;
|
|
665
664
|
} | {
|
|
666
665
|
id: string;
|
|
667
666
|
page: number;
|
|
@@ -685,13 +684,14 @@ export declare function useAnnotations(): {
|
|
|
685
684
|
x: number;
|
|
686
685
|
y: number;
|
|
687
686
|
};
|
|
688
|
-
|
|
687
|
+
width: number;
|
|
689
688
|
author?: string | undefined;
|
|
690
689
|
contents?: string | undefined;
|
|
691
690
|
inReplyTo?: string | undefined;
|
|
692
691
|
locked?: boolean | undefined;
|
|
693
692
|
custom?: Record<string, unknown> | undefined;
|
|
694
|
-
|
|
693
|
+
head?: "square" | "circle" | "none" | "openArrow" | "closedArrow" | "diamond" | "butt" | "slash" | undefined;
|
|
694
|
+
tail?: "square" | "circle" | "none" | "openArrow" | "closedArrow" | "diamond" | "butt" | "slash" | undefined;
|
|
695
695
|
} | {
|
|
696
696
|
id: string;
|
|
697
697
|
page: number;
|
|
@@ -711,13 +711,13 @@ export declare function useAnnotations(): {
|
|
|
711
711
|
x: number;
|
|
712
712
|
y: number;
|
|
713
713
|
}[];
|
|
714
|
-
|
|
714
|
+
width: number;
|
|
715
715
|
author?: string | undefined;
|
|
716
716
|
contents?: string | undefined;
|
|
717
717
|
inReplyTo?: string | undefined;
|
|
718
718
|
locked?: boolean | undefined;
|
|
719
719
|
custom?: Record<string, unknown> | undefined;
|
|
720
|
-
|
|
720
|
+
interiorColor?: string | undefined;
|
|
721
721
|
} | {
|
|
722
722
|
id: string;
|
|
723
723
|
page: number;
|
|
@@ -733,11 +733,11 @@ export declare function useAnnotations(): {
|
|
|
733
733
|
modifiedAt: string;
|
|
734
734
|
source: "session" | "pdf";
|
|
735
735
|
type: "ink";
|
|
736
|
-
|
|
736
|
+
inklist: {
|
|
737
737
|
x: number;
|
|
738
738
|
y: number;
|
|
739
739
|
}[][];
|
|
740
|
-
|
|
740
|
+
width: number;
|
|
741
741
|
author?: string | undefined;
|
|
742
742
|
contents?: string | undefined;
|
|
743
743
|
inReplyTo?: string | undefined;
|
|
@@ -759,7 +759,7 @@ export declare function useAnnotations(): {
|
|
|
759
759
|
source: "session" | "pdf";
|
|
760
760
|
type: "redact";
|
|
761
761
|
origin: "user" | "suggested";
|
|
762
|
-
|
|
762
|
+
interiorColor: string;
|
|
763
763
|
author?: string | undefined;
|
|
764
764
|
contents?: string | undefined;
|
|
765
765
|
inReplyTo?: string | undefined;
|
|
@@ -845,8 +845,8 @@ export declare function useAnnotations(): {
|
|
|
845
845
|
createdAt: string;
|
|
846
846
|
modifiedAt: string;
|
|
847
847
|
source: "session" | "pdf";
|
|
848
|
-
type: "
|
|
849
|
-
icon: "
|
|
848
|
+
type: "text";
|
|
849
|
+
icon: "comment" | "note" | "help" | "insert" | "key" | "paragraph";
|
|
850
850
|
author?: string | undefined;
|
|
851
851
|
contents?: string | undefined;
|
|
852
852
|
inReplyTo?: string | undefined;
|
|
@@ -866,13 +866,12 @@ export declare function useAnnotations(): {
|
|
|
866
866
|
createdAt: string;
|
|
867
867
|
modifiedAt: string;
|
|
868
868
|
source: "session" | "pdf";
|
|
869
|
-
type: "
|
|
870
|
-
|
|
869
|
+
type: "freetext";
|
|
870
|
+
contents: string;
|
|
871
871
|
fontSize: number;
|
|
872
872
|
fontFamily: string;
|
|
873
873
|
align: "left" | "center" | "right";
|
|
874
874
|
author?: string | undefined;
|
|
875
|
-
contents?: string | undefined;
|
|
876
875
|
inReplyTo?: string | undefined;
|
|
877
876
|
locked?: boolean | undefined;
|
|
878
877
|
custom?: Record<string, unknown> | undefined;
|
|
@@ -895,13 +894,13 @@ export declare function useAnnotations(): {
|
|
|
895
894
|
modifiedAt: string;
|
|
896
895
|
source: "session" | "pdf";
|
|
897
896
|
type: "square" | "circle";
|
|
898
|
-
|
|
897
|
+
width: number;
|
|
899
898
|
author?: string | undefined;
|
|
900
899
|
contents?: string | undefined;
|
|
901
900
|
inReplyTo?: string | undefined;
|
|
902
901
|
locked?: boolean | undefined;
|
|
903
902
|
custom?: Record<string, unknown> | undefined;
|
|
904
|
-
|
|
903
|
+
interiorColor?: string | undefined;
|
|
905
904
|
} | {
|
|
906
905
|
id: string;
|
|
907
906
|
page: number;
|
|
@@ -925,13 +924,14 @@ export declare function useAnnotations(): {
|
|
|
925
924
|
x: number;
|
|
926
925
|
y: number;
|
|
927
926
|
};
|
|
928
|
-
|
|
927
|
+
width: number;
|
|
929
928
|
author?: string | undefined;
|
|
930
929
|
contents?: string | undefined;
|
|
931
930
|
inReplyTo?: string | undefined;
|
|
932
931
|
locked?: boolean | undefined;
|
|
933
932
|
custom?: Record<string, unknown> | undefined;
|
|
934
|
-
|
|
933
|
+
head?: "square" | "circle" | "none" | "openArrow" | "closedArrow" | "diamond" | "butt" | "slash" | undefined;
|
|
934
|
+
tail?: "square" | "circle" | "none" | "openArrow" | "closedArrow" | "diamond" | "butt" | "slash" | undefined;
|
|
935
935
|
} | {
|
|
936
936
|
id: string;
|
|
937
937
|
page: number;
|
|
@@ -951,13 +951,13 @@ export declare function useAnnotations(): {
|
|
|
951
951
|
x: number;
|
|
952
952
|
y: number;
|
|
953
953
|
}[];
|
|
954
|
-
|
|
954
|
+
width: number;
|
|
955
955
|
author?: string | undefined;
|
|
956
956
|
contents?: string | undefined;
|
|
957
957
|
inReplyTo?: string | undefined;
|
|
958
958
|
locked?: boolean | undefined;
|
|
959
959
|
custom?: Record<string, unknown> | undefined;
|
|
960
|
-
|
|
960
|
+
interiorColor?: string | undefined;
|
|
961
961
|
} | {
|
|
962
962
|
id: string;
|
|
963
963
|
page: number;
|
|
@@ -973,11 +973,11 @@ export declare function useAnnotations(): {
|
|
|
973
973
|
modifiedAt: string;
|
|
974
974
|
source: "session" | "pdf";
|
|
975
975
|
type: "ink";
|
|
976
|
-
|
|
976
|
+
inklist: {
|
|
977
977
|
x: number;
|
|
978
978
|
y: number;
|
|
979
979
|
}[][];
|
|
980
|
-
|
|
980
|
+
width: number;
|
|
981
981
|
author?: string | undefined;
|
|
982
982
|
contents?: string | undefined;
|
|
983
983
|
inReplyTo?: string | undefined;
|
|
@@ -999,7 +999,7 @@ export declare function useAnnotations(): {
|
|
|
999
999
|
source: "session" | "pdf";
|
|
1000
1000
|
type: "redact";
|
|
1001
1001
|
origin: "user" | "suggested";
|
|
1002
|
-
|
|
1002
|
+
interiorColor: string;
|
|
1003
1003
|
author?: string | undefined;
|
|
1004
1004
|
contents?: string | undefined;
|
|
1005
1005
|
inReplyTo?: string | undefined;
|
|
@@ -1085,8 +1085,8 @@ export declare function useAnnotations(): {
|
|
|
1085
1085
|
createdAt: string;
|
|
1086
1086
|
modifiedAt: string;
|
|
1087
1087
|
source: "session" | "pdf";
|
|
1088
|
-
type: "
|
|
1089
|
-
icon: "
|
|
1088
|
+
type: "text";
|
|
1089
|
+
icon: "comment" | "note" | "help" | "insert" | "key" | "paragraph";
|
|
1090
1090
|
author?: string | undefined;
|
|
1091
1091
|
contents?: string | undefined;
|
|
1092
1092
|
inReplyTo?: string | undefined;
|
|
@@ -1106,13 +1106,12 @@ export declare function useAnnotations(): {
|
|
|
1106
1106
|
createdAt: string;
|
|
1107
1107
|
modifiedAt: string;
|
|
1108
1108
|
source: "session" | "pdf";
|
|
1109
|
-
type: "
|
|
1110
|
-
|
|
1109
|
+
type: "freetext";
|
|
1110
|
+
contents: string;
|
|
1111
1111
|
fontSize: number;
|
|
1112
1112
|
fontFamily: string;
|
|
1113
1113
|
align: "left" | "center" | "right";
|
|
1114
1114
|
author?: string | undefined;
|
|
1115
|
-
contents?: string | undefined;
|
|
1116
1115
|
inReplyTo?: string | undefined;
|
|
1117
1116
|
locked?: boolean | undefined;
|
|
1118
1117
|
custom?: Record<string, unknown> | undefined;
|
|
@@ -1135,13 +1134,13 @@ export declare function useAnnotations(): {
|
|
|
1135
1134
|
modifiedAt: string;
|
|
1136
1135
|
source: "session" | "pdf";
|
|
1137
1136
|
type: "square" | "circle";
|
|
1138
|
-
|
|
1137
|
+
width: number;
|
|
1139
1138
|
author?: string | undefined;
|
|
1140
1139
|
contents?: string | undefined;
|
|
1141
1140
|
inReplyTo?: string | undefined;
|
|
1142
1141
|
locked?: boolean | undefined;
|
|
1143
1142
|
custom?: Record<string, unknown> | undefined;
|
|
1144
|
-
|
|
1143
|
+
interiorColor?: string | undefined;
|
|
1145
1144
|
} | {
|
|
1146
1145
|
id: string;
|
|
1147
1146
|
page: number;
|
|
@@ -1165,13 +1164,14 @@ export declare function useAnnotations(): {
|
|
|
1165
1164
|
x: number;
|
|
1166
1165
|
y: number;
|
|
1167
1166
|
};
|
|
1168
|
-
|
|
1167
|
+
width: number;
|
|
1169
1168
|
author?: string | undefined;
|
|
1170
1169
|
contents?: string | undefined;
|
|
1171
1170
|
inReplyTo?: string | undefined;
|
|
1172
1171
|
locked?: boolean | undefined;
|
|
1173
1172
|
custom?: Record<string, unknown> | undefined;
|
|
1174
|
-
|
|
1173
|
+
head?: "square" | "circle" | "none" | "openArrow" | "closedArrow" | "diamond" | "butt" | "slash" | undefined;
|
|
1174
|
+
tail?: "square" | "circle" | "none" | "openArrow" | "closedArrow" | "diamond" | "butt" | "slash" | undefined;
|
|
1175
1175
|
} | {
|
|
1176
1176
|
id: string;
|
|
1177
1177
|
page: number;
|
|
@@ -1191,13 +1191,13 @@ export declare function useAnnotations(): {
|
|
|
1191
1191
|
x: number;
|
|
1192
1192
|
y: number;
|
|
1193
1193
|
}[];
|
|
1194
|
-
|
|
1194
|
+
width: number;
|
|
1195
1195
|
author?: string | undefined;
|
|
1196
1196
|
contents?: string | undefined;
|
|
1197
1197
|
inReplyTo?: string | undefined;
|
|
1198
1198
|
locked?: boolean | undefined;
|
|
1199
1199
|
custom?: Record<string, unknown> | undefined;
|
|
1200
|
-
|
|
1200
|
+
interiorColor?: string | undefined;
|
|
1201
1201
|
} | {
|
|
1202
1202
|
id: string;
|
|
1203
1203
|
page: number;
|
|
@@ -1213,11 +1213,11 @@ export declare function useAnnotations(): {
|
|
|
1213
1213
|
modifiedAt: string;
|
|
1214
1214
|
source: "session" | "pdf";
|
|
1215
1215
|
type: "ink";
|
|
1216
|
-
|
|
1216
|
+
inklist: {
|
|
1217
1217
|
x: number;
|
|
1218
1218
|
y: number;
|
|
1219
1219
|
}[][];
|
|
1220
|
-
|
|
1220
|
+
width: number;
|
|
1221
1221
|
author?: string | undefined;
|
|
1222
1222
|
contents?: string | undefined;
|
|
1223
1223
|
inReplyTo?: string | undefined;
|
|
@@ -1239,7 +1239,7 @@ export declare function useAnnotations(): {
|
|
|
1239
1239
|
source: "session" | "pdf";
|
|
1240
1240
|
type: "redact";
|
|
1241
1241
|
origin: "user" | "suggested";
|
|
1242
|
-
|
|
1242
|
+
interiorColor: string;
|
|
1243
1243
|
author?: string | undefined;
|
|
1244
1244
|
contents?: string | undefined;
|
|
1245
1245
|
inReplyTo?: string | undefined;
|
|
@@ -1324,8 +1324,8 @@ export declare function useAnnotations(): {
|
|
|
1324
1324
|
createdAt: string;
|
|
1325
1325
|
modifiedAt: string;
|
|
1326
1326
|
source: "session" | "pdf";
|
|
1327
|
-
type: "
|
|
1328
|
-
icon: "
|
|
1327
|
+
type: "text";
|
|
1328
|
+
icon: "comment" | "note" | "help" | "insert" | "key" | "paragraph";
|
|
1329
1329
|
author?: string | undefined;
|
|
1330
1330
|
contents?: string | undefined;
|
|
1331
1331
|
inReplyTo?: string | undefined;
|
|
@@ -1345,13 +1345,12 @@ export declare function useAnnotations(): {
|
|
|
1345
1345
|
createdAt: string;
|
|
1346
1346
|
modifiedAt: string;
|
|
1347
1347
|
source: "session" | "pdf";
|
|
1348
|
-
type: "
|
|
1349
|
-
|
|
1348
|
+
type: "freetext";
|
|
1349
|
+
contents: string;
|
|
1350
1350
|
fontSize: number;
|
|
1351
1351
|
fontFamily: string;
|
|
1352
1352
|
align: "left" | "center" | "right";
|
|
1353
1353
|
author?: string | undefined;
|
|
1354
|
-
contents?: string | undefined;
|
|
1355
1354
|
inReplyTo?: string | undefined;
|
|
1356
1355
|
locked?: boolean | undefined;
|
|
1357
1356
|
custom?: Record<string, unknown> | undefined;
|
|
@@ -1374,13 +1373,13 @@ export declare function useAnnotations(): {
|
|
|
1374
1373
|
modifiedAt: string;
|
|
1375
1374
|
source: "session" | "pdf";
|
|
1376
1375
|
type: "square" | "circle";
|
|
1377
|
-
|
|
1376
|
+
width: number;
|
|
1378
1377
|
author?: string | undefined;
|
|
1379
1378
|
contents?: string | undefined;
|
|
1380
1379
|
inReplyTo?: string | undefined;
|
|
1381
1380
|
locked?: boolean | undefined;
|
|
1382
1381
|
custom?: Record<string, unknown> | undefined;
|
|
1383
|
-
|
|
1382
|
+
interiorColor?: string | undefined;
|
|
1384
1383
|
} | {
|
|
1385
1384
|
id: string;
|
|
1386
1385
|
page: number;
|
|
@@ -1404,13 +1403,14 @@ export declare function useAnnotations(): {
|
|
|
1404
1403
|
x: number;
|
|
1405
1404
|
y: number;
|
|
1406
1405
|
};
|
|
1407
|
-
|
|
1406
|
+
width: number;
|
|
1408
1407
|
author?: string | undefined;
|
|
1409
1408
|
contents?: string | undefined;
|
|
1410
1409
|
inReplyTo?: string | undefined;
|
|
1411
1410
|
locked?: boolean | undefined;
|
|
1412
1411
|
custom?: Record<string, unknown> | undefined;
|
|
1413
|
-
|
|
1412
|
+
head?: "square" | "circle" | "none" | "openArrow" | "closedArrow" | "diamond" | "butt" | "slash" | undefined;
|
|
1413
|
+
tail?: "square" | "circle" | "none" | "openArrow" | "closedArrow" | "diamond" | "butt" | "slash" | undefined;
|
|
1414
1414
|
} | {
|
|
1415
1415
|
id: string;
|
|
1416
1416
|
page: number;
|
|
@@ -1430,13 +1430,13 @@ export declare function useAnnotations(): {
|
|
|
1430
1430
|
x: number;
|
|
1431
1431
|
y: number;
|
|
1432
1432
|
}[];
|
|
1433
|
-
|
|
1433
|
+
width: number;
|
|
1434
1434
|
author?: string | undefined;
|
|
1435
1435
|
contents?: string | undefined;
|
|
1436
1436
|
inReplyTo?: string | undefined;
|
|
1437
1437
|
locked?: boolean | undefined;
|
|
1438
1438
|
custom?: Record<string, unknown> | undefined;
|
|
1439
|
-
|
|
1439
|
+
interiorColor?: string | undefined;
|
|
1440
1440
|
} | {
|
|
1441
1441
|
id: string;
|
|
1442
1442
|
page: number;
|
|
@@ -1452,11 +1452,11 @@ export declare function useAnnotations(): {
|
|
|
1452
1452
|
modifiedAt: string;
|
|
1453
1453
|
source: "session" | "pdf";
|
|
1454
1454
|
type: "ink";
|
|
1455
|
-
|
|
1455
|
+
inklist: {
|
|
1456
1456
|
x: number;
|
|
1457
1457
|
y: number;
|
|
1458
1458
|
}[][];
|
|
1459
|
-
|
|
1459
|
+
width: number;
|
|
1460
1460
|
author?: string | undefined;
|
|
1461
1461
|
contents?: string | undefined;
|
|
1462
1462
|
inReplyTo?: string | undefined;
|
|
@@ -1478,7 +1478,7 @@ export declare function useAnnotations(): {
|
|
|
1478
1478
|
source: "session" | "pdf";
|
|
1479
1479
|
type: "redact";
|
|
1480
1480
|
origin: "user" | "suggested";
|
|
1481
|
-
|
|
1481
|
+
interiorColor: string;
|
|
1482
1482
|
author?: string | undefined;
|
|
1483
1483
|
contents?: string | undefined;
|
|
1484
1484
|
inReplyTo?: string | undefined;
|
|
@@ -1564,8 +1564,8 @@ export declare function useAnnotations(): {
|
|
|
1564
1564
|
createdAt: string;
|
|
1565
1565
|
modifiedAt: string;
|
|
1566
1566
|
source: "session" | "pdf";
|
|
1567
|
-
type: "
|
|
1568
|
-
icon: "
|
|
1567
|
+
type: "text";
|
|
1568
|
+
icon: "comment" | "note" | "help" | "insert" | "key" | "paragraph";
|
|
1569
1569
|
author?: string | undefined;
|
|
1570
1570
|
contents?: string | undefined;
|
|
1571
1571
|
inReplyTo?: string | undefined;
|
|
@@ -1585,13 +1585,12 @@ export declare function useAnnotations(): {
|
|
|
1585
1585
|
createdAt: string;
|
|
1586
1586
|
modifiedAt: string;
|
|
1587
1587
|
source: "session" | "pdf";
|
|
1588
|
-
type: "
|
|
1589
|
-
|
|
1588
|
+
type: "freetext";
|
|
1589
|
+
contents: string;
|
|
1590
1590
|
fontSize: number;
|
|
1591
1591
|
fontFamily: string;
|
|
1592
1592
|
align: "left" | "center" | "right";
|
|
1593
1593
|
author?: string | undefined;
|
|
1594
|
-
contents?: string | undefined;
|
|
1595
1594
|
inReplyTo?: string | undefined;
|
|
1596
1595
|
locked?: boolean | undefined;
|
|
1597
1596
|
custom?: Record<string, unknown> | undefined;
|
|
@@ -1614,13 +1613,13 @@ export declare function useAnnotations(): {
|
|
|
1614
1613
|
modifiedAt: string;
|
|
1615
1614
|
source: "session" | "pdf";
|
|
1616
1615
|
type: "square" | "circle";
|
|
1617
|
-
|
|
1616
|
+
width: number;
|
|
1618
1617
|
author?: string | undefined;
|
|
1619
1618
|
contents?: string | undefined;
|
|
1620
1619
|
inReplyTo?: string | undefined;
|
|
1621
1620
|
locked?: boolean | undefined;
|
|
1622
1621
|
custom?: Record<string, unknown> | undefined;
|
|
1623
|
-
|
|
1622
|
+
interiorColor?: string | undefined;
|
|
1624
1623
|
} | {
|
|
1625
1624
|
id: string;
|
|
1626
1625
|
page: number;
|
|
@@ -1644,13 +1643,14 @@ export declare function useAnnotations(): {
|
|
|
1644
1643
|
x: number;
|
|
1645
1644
|
y: number;
|
|
1646
1645
|
};
|
|
1647
|
-
|
|
1646
|
+
width: number;
|
|
1648
1647
|
author?: string | undefined;
|
|
1649
1648
|
contents?: string | undefined;
|
|
1650
1649
|
inReplyTo?: string | undefined;
|
|
1651
1650
|
locked?: boolean | undefined;
|
|
1652
1651
|
custom?: Record<string, unknown> | undefined;
|
|
1653
|
-
|
|
1652
|
+
head?: "square" | "circle" | "none" | "openArrow" | "closedArrow" | "diamond" | "butt" | "slash" | undefined;
|
|
1653
|
+
tail?: "square" | "circle" | "none" | "openArrow" | "closedArrow" | "diamond" | "butt" | "slash" | undefined;
|
|
1654
1654
|
} | {
|
|
1655
1655
|
id: string;
|
|
1656
1656
|
page: number;
|
|
@@ -1670,13 +1670,13 @@ export declare function useAnnotations(): {
|
|
|
1670
1670
|
x: number;
|
|
1671
1671
|
y: number;
|
|
1672
1672
|
}[];
|
|
1673
|
-
|
|
1673
|
+
width: number;
|
|
1674
1674
|
author?: string | undefined;
|
|
1675
1675
|
contents?: string | undefined;
|
|
1676
1676
|
inReplyTo?: string | undefined;
|
|
1677
1677
|
locked?: boolean | undefined;
|
|
1678
1678
|
custom?: Record<string, unknown> | undefined;
|
|
1679
|
-
|
|
1679
|
+
interiorColor?: string | undefined;
|
|
1680
1680
|
} | {
|
|
1681
1681
|
id: string;
|
|
1682
1682
|
page: number;
|
|
@@ -1692,11 +1692,11 @@ export declare function useAnnotations(): {
|
|
|
1692
1692
|
modifiedAt: string;
|
|
1693
1693
|
source: "session" | "pdf";
|
|
1694
1694
|
type: "ink";
|
|
1695
|
-
|
|
1695
|
+
inklist: {
|
|
1696
1696
|
x: number;
|
|
1697
1697
|
y: number;
|
|
1698
1698
|
}[][];
|
|
1699
|
-
|
|
1699
|
+
width: number;
|
|
1700
1700
|
author?: string | undefined;
|
|
1701
1701
|
contents?: string | undefined;
|
|
1702
1702
|
inReplyTo?: string | undefined;
|
|
@@ -1718,7 +1718,7 @@ export declare function useAnnotations(): {
|
|
|
1718
1718
|
source: "session" | "pdf";
|
|
1719
1719
|
type: "redact";
|
|
1720
1720
|
origin: "user" | "suggested";
|
|
1721
|
-
|
|
1721
|
+
interiorColor: string;
|
|
1722
1722
|
author?: string | undefined;
|
|
1723
1723
|
contents?: string | undefined;
|
|
1724
1724
|
inReplyTo?: string | undefined;
|
package/dist/index.mjs
CHANGED
|
@@ -1106,7 +1106,7 @@ function InkNotePopover({ children }) {
|
|
|
1106
1106
|
const { annotations, add, update, remove } = useAnnotations();
|
|
1107
1107
|
const note = useMemo(() => {
|
|
1108
1108
|
const a = ctx.activated ? annotations.find((x) => x.id === ctx.activated) : void 0;
|
|
1109
|
-
return a?.type === "
|
|
1109
|
+
return a?.type === "text" ? threadRoot(annotations, a) : null;
|
|
1110
1110
|
}, [annotations, ctx.activated]);
|
|
1111
1111
|
const anchor = useAnnotationElement(ctx.rootEl, note?.id ?? null);
|
|
1112
1112
|
const anchorRef = useMemo(() => ({ current: anchor }), [anchor]);
|
|
@@ -1148,7 +1148,7 @@ function InkNotePopover({ children }) {
|
|
|
1148
1148
|
if (!root || !contents) return;
|
|
1149
1149
|
written.current.add(root.id);
|
|
1150
1150
|
add({
|
|
1151
|
-
type: "
|
|
1151
|
+
type: "text",
|
|
1152
1152
|
page: root.page,
|
|
1153
1153
|
rect: root.rect,
|
|
1154
1154
|
contents,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/context.ts","../src/use-readable.ts","../src/hooks/useDocument.ts","../src/hooks/useAnnotations.ts","../src/hooks/useTool.ts","../src/hooks/useSelection.ts","../src/hooks/useZoom.ts","../src/hooks/usePage.ts","../src/hooks/useHistory.ts","../src/hooks/useEmbedded.ts","../src/use-latest.ts","../src/components/InkRoot.tsx","../src/class-names.ts","../src/components/InkAnnotation.tsx","../src/components/InkPage.tsx","../src/components/InkViewport.tsx","../src/components/InkToolbar.tsx","../src/components/InkIcon.tsx","../src/components/InkToolButton.tsx","../src/components/InkToolbarSeparator.tsx","../src/components/InkUndo.tsx","../src/components/InkRedo.tsx","../src/components/InkZoomIn.tsx","../src/components/InkZoomOut.tsx","../src/components/InkZoomSelect.tsx","../src/components/InkPageInput.tsx","../src/components/InkPageCount.tsx","../src/components/InkPrevPage.tsx","../src/components/InkNextPage.tsx","../src/components/annotation-element.ts","../src/components/popover-focus.ts","../src/components/InkNotePopover.tsx","../src/components/InkSuggestionCard.tsx"],"sourcesContent":["import { createContext, useContext } from 'react'\n\nimport type { Annotation, InkDocument, InkStatus, PdfAssets } from '@inkbar/core'\nimport type { ToolController, ToolId, Viewport, ZoomValue } from '@inkbar/core/dom'\n\nexport type { InkStatus }\n\n/** Undo and redo for the current document, whichever mode its annotations are in. */\nexport interface InkHistory {\n canUndo: boolean\n canRedo: boolean\n undo: () => void\n redo: () => void\n clear: () => void\n /**\n * Runs `fn` and records what it changes as one undo step. The host still receives one change\n * per add. Controlled, the history groups the resulting list changes into one step, and\n * `canUndo` updates once the current task ends. Any other change the host applies in that\n * same window joins the step.\n */\n batch: (fn: () => void) => void\n}\n\nexport interface InkContext {\n assets: PdfAssets\n document: InkDocument | null\n /** `loading` from the moment a document starts opening, then the document's own status. */\n status: InkStatus\n annotations: readonly Annotation[]\n selection: readonly string[]\n /** Set by InkViewport once it has built its viewport and tool controller. */\n viewport: Viewport | null\n tools: ToolController | null\n /** Desired tool; InkViewport applies it to the controller. */\n tool: ToolId\n setTool: (id: ToolId) => void\n /** Desired zoom and page from the host's props; InkViewport applies and reports back. */\n zoomModel: ZoomValue | undefined\n pageModel: number | undefined\n reportZoom: (z: ZoomValue) => void\n reportPage: (p: number) => void\n /** Last activated annotation (Enter, click with the note tool, etc.). Popovers key off this. */\n activated: string | null\n setActivated: (id: string | null) => void\n history: InkHistory\n rootEl: HTMLElement | null\n setViewport: (viewport: Viewport | null, tools: ToolController | null) => void\n}\n\nexport const InkContextObject = createContext<InkContext | null>(null)\n\n/**\n * The context for hooks: throws a readable error when called outside a component rendered\n * inside `InkRoot`.\n */\nexport function useInkContext(consumer: string): InkContext {\n const ctx = useContext(InkContextObject)\n if (!ctx)\n throw new Error(\n `[inkbar] ${consumer} must be called in a component inside <InkRoot>.`\n )\n return ctx\n}\n","import { useCallback, useSyncExternalStore } from 'react'\n\nimport type { Readable } from '@inkbar/core'\n\nconst noop = (): void => undefined\n\n/**\n * Mirrors a core `Readable` into React. A missing readable yields `fallback`, which must be a\n * stable reference (a module constant): `useSyncExternalStore` compares snapshots by identity\n * and loops on a fresh value. On the server the fallback is rendered.\n */\nexport function useReadable<T>(readable: Readable<T> | null | undefined, fallback: T): T {\n const subscribe = useCallback(\n (onChange: () => void) => (readable ? readable.subscribe(() => onChange()) : noop),\n [readable]\n )\n const get = useCallback(\n () => (readable ? readable.get() : fallback),\n [readable, fallback]\n )\n const server = useCallback(() => fallback, [fallback])\n return useSyncExternalStore(subscribe, get, server)\n}\n","import { useMemo } from 'react'\n\nimport { useInkContext } from '../context'\n\nimport type { AnnotationDocument, ImportOptions, PageInfo } from '@inkbar/core'\n\nconst NO_PAGES: readonly PageInfo[] = []\n\nexport function useDocument() {\n const ctx = useInkContext('useDocument()')\n const { document, status } = ctx\n return useMemo(\n () => ({\n document,\n status,\n isReady: status.state === 'ready',\n error: status.state === 'error' ? status.error : null,\n pages: document?.pages ?? NO_PAGES,\n info: document?.info ?? null,\n exportAnnotations: () => document?.exportAnnotations('json'),\n importAnnotations: (data: AnnotationDocument | string, opts?: ImportOptions) =>\n document?.importAnnotations(data, opts),\n }),\n [document, status]\n )\n}\n","import { acceptSuggestion, repliesTo } from '@inkbar/core'\nimport { useMemo } from 'react'\n\nimport { useInkContext } from '../context'\n\nimport type { Annotation, AnnotationInput } from '@inkbar/core'\n\nexport function useAnnotations() {\n const ctx = useInkContext('useAnnotations()')\n const { annotations, selection, document } = ctx\n const store = document?.annotations\n const selected = useMemo(\n () =>\n selection\n .map((id) => annotations.find((a) => a.id === id))\n .filter((a): a is Annotation => !!a),\n [annotations, selection]\n )\n // Stable for the life of the document, so hosts can pass them as props or effect deps.\n const actions = useMemo(\n () => ({\n add: (input: AnnotationInput) => store?.add(input),\n update: (id: string, patch: Partial<Annotation>) => store?.update(id, patch),\n remove: (id: string) => store?.remove(id) ?? false,\n select: (ids: string[]) => store?.select(ids),\n /** Keeps a suggested redaction as the user's own, in the default redaction colour. */\n accept: (id: string) => (store ? acceptSuggestion(store, id) : undefined),\n dismiss: (id: string) => store?.remove(id) ?? false,\n }),\n [store]\n )\n return useMemo(\n () => ({\n annotations,\n selection,\n selected,\n byPage: (page: number) => annotations.filter((a) => a.page === page),\n /** Replies in creation order for a note id. */\n replies: (id: string) => repliesTo(annotations, id),\n ...actions,\n }),\n [annotations, selection, selected, actions]\n )\n}\n","import { useMemo } from 'react'\n\nimport { useInkContext } from '../context'\n\nexport function useTool() {\n const ctx = useInkContext('useTool()')\n const { tool, setTool } = ctx\n return useMemo(() => ({ tool, setTool }), [tool, setTool])\n}\n","import { useMemo } from 'react'\n\nimport { useInkContext } from '../context'\n\nexport function useSelection() {\n const ctx = useInkContext('useSelection()')\n const { selection, document } = ctx\n const store = document?.annotations\n return useMemo(\n () => ({\n selection,\n select: (ids: string[]) => store?.select(ids),\n clear: () => store?.select([]),\n }),\n [selection, store]\n )\n}\n","import { useMemo } from 'react'\n\nimport { useInkContext } from '../context'\nimport { useReadable } from '../use-readable'\n\nimport type { ZoomValue } from '@inkbar/core/dom'\n\nexport function useZoom() {\n const ctx = useInkContext('useZoom()')\n const { viewport } = ctx\n const zoom = useReadable<ZoomValue>(viewport?.zoom, 'fit-width')\n const scale = useReadable<number>(viewport?.scale, 1)\n return useMemo(\n () => ({\n zoom,\n scale,\n setZoom: (z: ZoomValue) => viewport?.setZoom(z),\n zoomIn: () => viewport?.zoomBy(1.25),\n zoomOut: () => viewport?.zoomBy(0.8),\n }),\n [viewport, zoom, scale]\n )\n}\n","import { useMemo } from 'react'\n\nimport { useInkContext } from '../context'\nimport { useReadable } from '../use-readable'\n\nexport function usePage() {\n const ctx = useInkContext('usePage()')\n const { viewport, document } = ctx\n const current = useReadable<number>(viewport?.currentPage, 0)\n return useMemo(\n () => ({\n /** 0-based. */\n current,\n count: document?.pages.length ?? 0,\n goTo: (index: number) => viewport?.scrollToPage(index),\n // Read the live page, so these stay the same functions as the reader scrolls.\n next: () => viewport?.scrollToPage(viewport.currentPage.get() + 1),\n previous: () => viewport?.scrollToPage(viewport.currentPage.get() - 1),\n scrollToAnnotation(id: string) {\n const a = document?.annotations.get(id)\n if (a) viewport?.scrollToRect(a.page, a.rect)\n },\n }),\n [viewport, document, current]\n )\n}\n","import { useInkContext, type InkHistory } from '../context'\n\n/**\n * Undo and redo. Uncontrolled documents use the core history; controlled hosts that pass\n * `history` to InkRoot get a snapshot stack over their own list, applied through\n * `onAnnotationsChange`.\n */\nexport function useHistory(): InkHistory {\n return useInkContext('useHistory()').history\n}\n","import { useMemo } from 'react'\n\nimport { useInkContext } from '../context'\n\nconst NONE: readonly never[] = []\n\nexport function useEmbedded() {\n const ctx = useInkContext('useEmbedded()')\n const summary = ctx.document?.embedded ?? NONE\n return useMemo(\n () => ({\n summary,\n total: summary.reduce((n, s) => n + s.count, 0),\n hasAny: summary.length > 0,\n }),\n [summary]\n )\n}\n","import { useLayoutEffect, useRef, type RefObject } from 'react'\n\n/**\n * A ref that always holds the latest render's value, for callbacks that outlive a render\n * (core's `onChange`, effects keyed on something else). Updated in a layout effect, so it is\n * current before the parent's own layout and passive effects and before any callback fired\n * after commit; declare it before the effects that read it.\n */\nexport function useLatest<T>(value: T): RefObject<T> {\n const ref = useRef(value)\n useLayoutEffect(() => {\n ref.current = value\n })\n return ref\n}\n","import { createSnapshotHistory, InkError, openDocument } from '@inkbar/core'\nimport { cssVariableDefaults } from '@inkbar/core/dom'\nimport { Slot } from 'radix-ui'\nimport {\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type ReactNode,\n type Ref,\n} from 'react'\nimport { flushSync } from 'react-dom'\n\nimport {\n InkContextObject,\n type InkContext,\n type InkHistory,\n type InkStatus,\n} from '../context'\nimport { useLatest } from '../use-latest'\nimport { useReadable } from '../use-readable'\n\nimport type {\n Annotation,\n AnnotationChange,\n AnnotationDefaults,\n DocumentSource,\n InkDocument,\n PdfAssets,\n} from '@inkbar/core'\nimport type { ToolController, ToolId, Viewport, ZoomValue } from '@inkbar/core/dom'\n\nexport interface InkRootHandle {\n readonly document: InkDocument | null\n readonly status: InkStatus\n readonly rootEl: HTMLElement | null\n /** What `useHistory()` returns inside the root. A controlled host calls `clear()` after loading its saved list. */\n readonly history: InkHistory\n}\n\nexport interface InkRootProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'children' | 'onChange' | 'onError'\n> {\n src: DocumentSource | null\n assets: PdfAssets\n password?: string | undefined\n /** Colour defaults. Without it, the theme's CSS variables on the root element apply. */\n defaults?: AnnotationDefaults | undefined\n /**\n * Pass (with `onAnnotationsChange`) to put annotations under the host's control. The mode\n * is fixed when a document opens: passing or dropping this prop later takes effect on the\n * next open.\n */\n annotations?: Annotation[] | undefined\n onAnnotationsChange?: ((next: Annotation[]) => void) | undefined\n onChange?: ((change: AnnotationChange) => void) | undefined\n tool?: ToolId | undefined\n onToolChange?: ((tool: ToolId) => void) | undefined\n page?: number | undefined\n onPageChange?: ((page: number) => void) | undefined\n zoom?: ZoomValue | undefined\n onZoomChange?: ((zoom: ZoomValue) => void) | undefined\n /** Undo history. Defaults to on for uncontrolled, off for controlled. */\n history?: boolean | undefined\n asChild?: boolean | undefined\n onReady?: ((doc: InkDocument) => void) | undefined\n onError?: ((error: InkError) => void) | undefined\n onActivate?: ((id: string) => void) | undefined\n children?:\n | ReactNode\n | ((props: { status: InkStatus; document: InkDocument | null }) => ReactNode)\n ref?: Ref<InkRootHandle>\n}\n\ntype TestHookElement = HTMLElement & { __inkDocument?: InkDocument | undefined }\n\nconst IDLE: InkStatus = { state: 'idle' }\nconst NO_ANNOTATIONS: readonly Annotation[] = []\nconst NO_IDS: readonly string[] = []\n\n/** Signed URLs change; the key does not. Bytes and Blobs are their own identity. */\nfunction identity(src: DocumentSource | null): unknown {\n if (src === null) return null\n if (typeof src === 'string') return src\n if ('key' in src) return src.key\n return src\n}\n\nfunction isDevelopment(): boolean {\n // Bundlers replace the expression with a literal; raw browser ESM has no `process`.\n try {\n return process.env.NODE_ENV !== 'production'\n } catch {\n return false\n }\n}\n\nfunction setTestHook(el: HTMLElement | null, doc: InkDocument | undefined): void {\n if (el && isDevelopment()) (el as TestHookElement).__inkDocument = doc\n}\n\nexport function InkRoot({\n src,\n assets,\n password,\n defaults,\n annotations,\n onAnnotationsChange,\n onChange,\n tool,\n onToolChange,\n page,\n onPageChange,\n zoom,\n onZoomChange,\n history,\n asChild = false,\n onReady,\n onError,\n onActivate,\n children,\n ref,\n ...rest\n}: InkRootProps) {\n const rootElRef = useRef<HTMLElement | null>(null)\n const [rootEl, setRootElState] = useState<HTMLElement | null>(null)\n const setRootEl = useCallback((el: HTMLElement | null) => {\n rootElRef.current = el\n setRootElState(el)\n }, [])\n\n const documentRef = useRef<InkDocument | null>(null)\n const [document, setDocument] = useState<InkDocument | null>(null)\n /** Overrides the document's status while opening, and when opening itself failed. */\n const [override, setOverride] = useState<InkStatus | null>(null)\n const [internalTool, setInternalTool] = useState<ToolId>(tool ?? 'view')\n const [activated, setActivatedState] = useState<string | null>(null)\n const [viewport, setViewportState] = useState<Viewport | null>(null)\n const [tools, setToolsState] = useState<ToolController | null>(null)\n\n const documentStatus = useReadable<InkStatus>(document?.status, IDLE)\n const status = override ?? documentStatus\n const annotationList = useReadable(document?.annotations.list, NO_ANNOTATIONS)\n const selection = useReadable(document?.annotations.selection, NO_IDS)\n\n // What the next open will do follows the prop; the open document's mode is fixed.\n const controlledProp = annotations !== undefined\n const controlled = document\n ? document.annotations.mode === 'controlled'\n : controlledProp\n const historyEnabled = controlled && history === true\n // Callbacks and options read later than the render that passed them.\n const latest = useLatest({\n src,\n assets,\n defaults,\n annotations,\n controlled: controlledProp,\n history,\n historyEnabled,\n onAnnotationsChange,\n onChange,\n onReady,\n onError,\n onActivate,\n onToolChange,\n onPageChange,\n onZoomChange,\n })\n\n const snapshotHistory = useMemo(\n () =>\n createSnapshotHistory({\n apply: (list) => documentRef.current?.annotations.replaceAll(list, 'history'),\n enabled: () => latest.current.historyEnabled,\n }),\n [latest]\n )\n useEffect(() => {\n snapshotHistory.observe(annotations)\n }, [annotations, snapshotHistory])\n\n const srcIdentity = identity(src)\n useEffect(() => {\n let cancelled = false\n snapshotHistory.clear()\n const source = latest.current.src\n if (source === null) {\n setOverride(null)\n return\n }\n setOverride({ state: 'loading' })\n let opened: InkDocument | null = null\n const run = async () => {\n try {\n const doc = await openDocument(source, {\n assets: latest.current.assets,\n password,\n defaults:\n latest.current.defaults ??\n (rootElRef.current ? cssVariableDefaults(rootElRef.current) : undefined),\n // Controlled hosts get the snapshot history below; core's own stack stays off.\n history: latest.current.controlled ? false : (latest.current.history ?? true),\n annotations: latest.current.controlled\n ? {\n mode: 'controlled',\n initial: latest.current.annotations ?? [],\n onChange: (next, change) => {\n // Apply the host's state update, its render and the layout effect that pushes\n // the list back before core's development check expires. The microtask\n // leaves React's render, commit and passive-effect contexts, where a host\n // may call the store, so `flushSync` is always legal; the host sees the\n // proposal one microtask after the store returned. A proposal made in the\n // tick this root unmounts or reopens never reaches the host.\n queueMicrotask(() => {\n if (cancelled) return\n flushSync(() => {\n latest.current.onAnnotationsChange?.(next)\n latest.current.onChange?.(change)\n })\n })\n },\n }\n : { mode: 'uncontrolled' },\n })\n if (cancelled) {\n doc.destroy()\n return\n }\n opened = doc\n // The prop may have changed while the file loaded, when there was no store to apply it to.\n const current = latest.current.annotations\n if (doc.annotations.mode === 'controlled' && current !== undefined)\n doc.annotations.setControlledValue(current)\n documentRef.current = doc\n setDocument(doc)\n setOverride(null)\n setTestHook(rootElRef.current, doc)\n const s = doc.status.get()\n if (s.state === 'ready') latest.current.onReady?.(doc)\n else if (s.state === 'error') latest.current.onError?.(s.error)\n } catch (cause) {\n if (cancelled) return\n const error =\n cause instanceof InkError\n ? cause\n : new InkError(\n 'InvalidPdf',\n cause instanceof Error ? cause.message : String(cause),\n {},\n cause\n )\n setOverride({ state: 'error', error })\n latest.current.onError?.(error)\n }\n }\n // StrictMode's simulated cleanup runs synchronously in the same commit, so deferring one\n // microtask means the discarded first attempt never starts a fetch.\n void Promise.resolve().then(() => {\n if (!cancelled) return run()\n })\n return () => {\n cancelled = true\n opened?.destroy()\n documentRef.current = null\n setDocument(null)\n setTestHook(rootElRef.current, undefined)\n }\n // `srcIdentity` stands in for `src`: a new URL with the same key is the same document.\n }, [srcIdentity, password, snapshotHistory, latest])\n\n useLayoutEffect(() => {\n if (annotations && document?.annotations.mode === 'controlled')\n document.annotations.setControlledValue(annotations)\n }, [annotations, document])\n\n useEffect(() => {\n if (tool) setInternalTool(tool)\n }, [tool])\n\n const setTool = useCallback(\n (id: ToolId) => {\n setInternalTool(id)\n latest.current.onToolChange?.(id)\n },\n [latest]\n )\n const setActivated = useCallback(\n (id: string | null) => {\n setActivatedState(id)\n if (id) latest.current.onActivate?.(id)\n },\n [latest]\n )\n const reportZoom = useCallback(\n (z: ZoomValue) => latest.current.onZoomChange?.(z),\n [latest]\n )\n const reportPage = useCallback(\n (p: number) => latest.current.onPageChange?.(p),\n [latest]\n )\n const setViewport = useCallback((vp: Viewport | null, tc: ToolController | null) => {\n setViewportState(vp)\n setToolsState(tc)\n }, [])\n\n const snapCanUndo = useReadable(snapshotHistory.canUndo, false)\n const snapCanRedo = useReadable(snapshotHistory.canRedo, false)\n const coreCanUndo = useReadable(document?.history.canUndo, false)\n const coreCanRedo = useReadable(document?.history.canRedo, false)\n const inkHistory = useMemo<InkHistory>(\n () => ({\n canUndo: controlled ? historyEnabled && snapCanUndo : coreCanUndo,\n canRedo: controlled ? historyEnabled && snapCanRedo : coreCanRedo,\n undo: () =>\n controlled ? snapshotHistory.undo() : documentRef.current?.history.undo(),\n redo: () =>\n controlled ? snapshotHistory.redo() : documentRef.current?.history.redo(),\n clear: () =>\n controlled ? snapshotHistory.clear() : documentRef.current?.history.clear(),\n batch: (fn) => {\n if (controlled) snapshotHistory.batch(fn)\n else if (documentRef.current) documentRef.current.history.batch(fn)\n else fn()\n },\n }),\n [\n controlled,\n historyEnabled,\n snapCanUndo,\n snapCanRedo,\n coreCanUndo,\n coreCanRedo,\n snapshotHistory,\n ]\n )\n\n useImperativeHandle(ref, () => ({ document, status, rootEl, history: inkHistory }), [\n document,\n status,\n rootEl,\n inkHistory,\n ])\n\n const ctx = useMemo<InkContext>(\n () => ({\n assets,\n document,\n status,\n annotations: annotationList,\n selection,\n viewport,\n tools,\n tool: internalTool,\n setTool,\n zoomModel: zoom,\n pageModel: page,\n reportZoom,\n reportPage,\n activated,\n setActivated,\n history: inkHistory,\n rootEl,\n setViewport,\n }),\n [\n assets,\n document,\n status,\n annotationList,\n selection,\n viewport,\n tools,\n internalTool,\n setTool,\n zoom,\n page,\n reportZoom,\n reportPage,\n activated,\n setActivated,\n inkHistory,\n rootEl,\n setViewport,\n ]\n )\n\n const Comp = asChild ? Slot.Root : 'div'\n return (\n <InkContextObject.Provider value={ctx}>\n <Comp ref={setRootEl} data-ink-root=\"\" data-state={status.state} {...rest}>\n {typeof children === 'function' ? children({ status, document }) : children}\n </Comp>\n </InkContextObject.Provider>\n )\n}\n","/** Joins class names, dropping empties. */\nexport function cx(...parts: (string | undefined | false)[]): string | undefined {\n const out = parts.filter(Boolean).join(' ')\n return out === '' ? undefined : out\n}\n","/*\n * Slot props for one annotation. It renders only its children: the overlay already draws the\n * default visual for every annotation that is not custom, so this never draws a second one.\n * InkPage portals it into the annotation's overlay element.\n */\nimport { acceptSuggestion } from '@inkbar/core'\nimport { useEffect, useMemo, useState, type ReactNode } from 'react'\n\nimport { useInkContext } from '../context'\n\nimport type { Annotation } from '@inkbar/core'\nimport type { AnnotationSlotProps, AnnotationState } from '@inkbar/core/dom'\n\nexport interface InkAnnotationProps {\n annotation: Annotation\n /** The overlay element; its `data-state` (which includes hover) drives `state`. */\n element?: HTMLElement | undefined\n children: (props: AnnotationSlotProps) => ReactNode\n}\n\nfunction readState(el: HTMLElement): AnnotationState | null {\n const s = el.dataset.state\n return s === 'idle' || s === 'hover' || s === 'selected' ? s : null\n}\n\nexport function InkAnnotation({ annotation, element, children }: InkAnnotationProps) {\n const ctx = useInkContext('InkAnnotation')\n const [observed, setObserved] = useState<AnnotationState | null>(() =>\n element ? readState(element) : null\n )\n useEffect(() => {\n if (!element) {\n setObserved(null)\n return\n }\n setObserved(readState(element))\n const observer = new MutationObserver(() => setObserved(readState(element)))\n observer.observe(element, { attributes: true, attributeFilter: ['data-state'] })\n return () => observer.disconnect()\n }, [element])\n\n const { id } = annotation\n const isSuggestion = annotation.type === 'redact' && annotation.origin === 'suggested'\n const locked = annotation.locked === true\n const selected = ctx.selection.includes(id)\n const store = ctx.document?.annotations\n const slotProps = useMemo<AnnotationSlotProps>(\n () => ({\n annotation,\n state: observed ?? (selected ? 'selected' : 'idle'),\n locked,\n select: () => store?.select([id]),\n remove: () => void store?.remove(id),\n accept: () => {\n if (store && isSuggestion) acceptSuggestion(store, id)\n },\n dismiss: () => {\n if (isSuggestion) store?.remove(id)\n },\n }),\n [annotation, observed, selected, locked, store, id, isSuggestion]\n )\n return <>{children(slotProps)}</>\n}\n","/*\n * One page the viewer engine mounted. Renders nothing in place; portals go into the host\n * (page error) and into each annotation's overlay element (custom annotations).\n *\n * The overlay creates and removes those elements as the annotation list changes, outside\n * React. So the portal targets come from a list read after every overlay render: this\n * component subscribes to the store after the overlay does (the engine created the mount\n * first), and core notifies subscribers in order, so the elements already exist when the list\n * arrives here.\n *\n * The engine tracks page errors and sets `data-state=\"error\"` on the host; this component\n * portals the page-error slot into it while `error` is set.\n */\nimport { useEffect, useState, type ReactNode } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { useInkContext } from '../context'\n\nimport { InkAnnotation } from './InkAnnotation'\n\nimport type { Annotation, InkError } from '@inkbar/core'\nimport type { AnnotationSlotProps, PageMount } from '@inkbar/core/dom'\n\nexport interface InkPageProps {\n page: number\n host: HTMLElement\n /** The engine's page mount in `host`. */\n mount: PageMount\n /** The engine's error for this page, `null` while it renders. */\n error: InkError | null\n /** Fixed for the life of the mount: the engine rebuilds when it changes. */\n customAnnotations?: boolean\n renderAnnotation?: ((props: AnnotationSlotProps) => ReactNode) | undefined\n renderPageError?: ((props: { error: InkError; page: number }) => ReactNode) | undefined\n}\n\ninterface Target {\n annotation: Annotation\n el: HTMLElement\n}\n\nfunction sameTargets(a: readonly Target[], b: readonly Target[]): boolean {\n return (\n a.length === b.length &&\n a.every((t, i) => t.annotation === b[i]!.annotation && t.el === b[i]!.el)\n )\n}\n\nexport function InkPage({\n page,\n host,\n mount,\n error,\n customAnnotations = false,\n renderAnnotation,\n renderPageError,\n}: InkPageProps) {\n const doc = useInkContext('InkPage').document\n const [targets, setTargets] = useState<Target[]>([])\n\n useEffect(() => {\n if (!doc || !customAnnotations) return\n const read = (): void => {\n const next = doc.annotations.byPage(page).flatMap((annotation) => {\n const el = mount.overlay.elementFor(annotation.id)\n return el ? [{ annotation, el }] : []\n })\n // A change elsewhere in the document leaves this page's targets as they were.\n setTargets((prev) => (sameTargets(prev, next) ? prev : next))\n }\n const stop = doc.annotations.list.subscribe(read)\n read()\n return () => {\n stop()\n setTargets([])\n }\n }, [doc, page, mount, customAnnotations])\n\n return (\n <>\n {error\n ? createPortal(\n <div className=\"ink-page-error\" data-ink-page-error=\"\" role=\"alert\">\n {renderPageError ? (\n renderPageError({ error, page })\n ) : (\n <>\n <p>Page {page + 1} could not be shown.</p>\n <code className=\"ink-error-code\">{error.code}</code>\n </>\n )}\n </div>,\n host\n )\n : null}\n {renderAnnotation\n ? targets.map((t) =>\n createPortal(\n <InkAnnotation annotation={t.annotation} element={t.el}>\n {renderAnnotation}\n </InkAnnotation>,\n t.el,\n t.annotation.id\n )\n )\n : null}\n </>\n )\n}\n","/*\n * The scroll element is handed to core's `mountViewer`, which builds the viewport, the page\n * layers, the tool controller and the keyboard shortcuts in it; React never renders children\n * into it. The engine reports each page host it mounts, and InkPage components rendered here\n * portal the page-error and custom-annotation slots into them.\n *\n * Two-way zoom and page: the viewport's own changes are reported through the context, and\n * the host's props are applied only when they differ from the viewport's state, so the echo\n * of a reported value does nothing.\n */\nimport { mountViewer } from '@inkbar/core/dom'\nimport {\n useEffect,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type ReactNode,\n} from 'react'\n\nimport { cx } from '../class-names'\nimport { useInkContext } from '../context'\nimport { useLatest } from '../use-latest'\n\nimport { InkPage } from './InkPage'\n\nimport type { InkError } from '@inkbar/core'\nimport type {\n AnnotationSlotProps,\n LayoutMode,\n PageMount,\n ViewerEngine,\n ViewRotation,\n ZoomValue,\n} from '@inkbar/core/dom'\n\nexport interface InkViewportProps extends ComponentPropsWithoutRef<'div'> {\n mode?: LayoutMode\n rotation?: ViewRotation\n /** Gap between pages, CSS px. */\n gap?: number\n /** Pages kept mounted either side of the visible ones. */\n buffer?: number\n loading?: ReactNode\n empty?: ReactNode\n error?: ReactNode | ((props: { error: InkError }) => ReactNode)\n renderAnnotation?: ((props: AnnotationSlotProps) => ReactNode) | undefined\n /** Shown inside a page that failed to render. The rest of the document stays usable. */\n renderPageError?: ((props: { error: InkError; page: number }) => ReactNode) | undefined\n}\n\ninterface MountedPage {\n /** The engine build the host belongs to; part of the InkPage key. */\n build: number\n page: number\n host: HTMLElement\n mount: PageMount\n error: InkError | null\n /** Whether the build that mounted the page renders the annotation slot. */\n custom: boolean\n}\n\nexport function InkViewport({\n mode = 'continuous',\n rotation = 0,\n gap = 16,\n buffer = 2,\n loading,\n empty,\n error,\n renderAnnotation,\n renderPageError,\n className,\n ...rest\n}: InkViewportProps) {\n const ctx = useInkContext('InkViewport')\n const scroll = useRef<HTMLDivElement>(null)\n const custom = !!renderAnnotation\n const latest = useLatest({ ctx, mode, rotation, gap, buffer, custom })\n\n const engine = useRef<ViewerEngine | null>(null)\n /** Page hosts, mounts and errors the engine reported; InkPage renders portals for them. */\n const [pages, setPages] = useState<MountedPage[]>([])\n /**\n * Numbered before each build starts, so the pages a build mounts carry its own number. A\n * rebuild gives each page a new host and mount, so pages from an earlier build must remount,\n * not be reused.\n */\n const buildCount = useRef(0)\n /** The construction options the engine was last built with, so a rebuild runs only on a change. */\n const builtWith = useRef<{ gap: number; buffer: number; custom: boolean } | null>(null)\n /** The zoom and page last reported to the host. */\n const lastReportedZoom = useRef<ZoomValue | undefined>(undefined)\n const lastReportedPage = useRef<number | undefined>(undefined)\n\n // Build for a new document or status; tear down on the next change and on unmount.\n useEffect(() => {\n const { ctx: c, mode: m, rotation: r, gap: g, buffer: b, custom: cu } = latest.current\n const doc = c.document\n const el = scroll.current\n lastReportedZoom.current = undefined\n lastReportedPage.current = undefined\n if (!doc || !el || c.status.state !== 'ready') return\n let first = true\n let stops: (() => void)[] = []\n buildCount.current += 1\n builtWith.current = { gap: g, buffer: b, custom: cu }\n const e = mountViewer({\n container: el,\n document: doc,\n zoom: c.zoomModel ?? 'fit-width',\n ...(c.pageModel === undefined ? {} : { page: c.pageModel }),\n mode: m,\n rotation: r,\n gap: g,\n buffer: b,\n tool: c.tool,\n customAnnotations: cu,\n onActivate: (id) => latest.current.ctx.setActivated(id),\n onBuild: (vp, tc) => {\n latest.current.ctx.setViewport(vp, tc)\n if (first) {\n // A new document starts from where the viewport opens (its zoom, on the first page);\n // only later changes are reported, the restored page among them.\n first = false\n lastReportedZoom.current = vp.zoom.get()\n lastReportedPage.current = 0\n }\n for (const stop of stops) stop()\n const reportZoom = (z: ZoomValue): void => {\n if (z === lastReportedZoom.current) return\n lastReportedZoom.current = z\n latest.current.ctx.reportZoom(z)\n }\n const reportPage = (p: number): void => {\n if (p === lastReportedPage.current) return\n lastReportedPage.current = p\n latest.current.ctx.reportPage(p)\n }\n stops = [vp.zoom.subscribe(reportZoom), vp.currentPage.subscribe(reportPage)]\n // Whatever the build restored is reported once; nothing is when it matched.\n reportZoom(vp.zoom.get())\n reportPage(vp.currentPage.get())\n },\n onPageMount: (page, mount, host) => {\n // `buildCount` and `builtWith` belong to the build in progress: both are set before it starts.\n const build = buildCount.current\n const custom = builtWith.current?.custom ?? false\n setPages((prev) => [...prev, { build, page, host, mount, error: null, custom }])\n },\n onPageUnmount: (page) => setPages((prev) => prev.filter((p) => p.page !== page)),\n onPageError: (page, err) =>\n setPages((prev) => prev.map((p) => (p.page === page ? { ...p, error: err } : p))),\n })\n engine.current = e\n return () => {\n for (const stop of stops) stop()\n e.destroy()\n engine.current = null\n builtWith.current = null\n c.setViewport(null, null)\n setPages((prev) => (prev.length === 0 ? prev : []))\n }\n }, [ctx.document, ctx.status.state, latest])\n\n // Construction-only options rebuild the engine for the same document, keeping zoom and page.\n useEffect(() => {\n const built = builtWith.current\n if (!engine.current || !built) return\n if (built.gap === gap && built.buffer === buffer && built.custom === custom) return\n buildCount.current += 1\n builtWith.current = { gap, buffer, custom }\n engine.current.rebuild({ gap, buffer, customAnnotations: custom })\n }, [gap, buffer, custom])\n\n useEffect(() => {\n const vp = engine.current?.viewport\n const z = ctx.zoomModel\n if (vp && z !== undefined && z !== vp.zoom.get()) vp.setZoom(z)\n }, [ctx.zoomModel])\n useEffect(() => {\n const vp = engine.current?.viewport\n const p = ctx.pageModel\n if (!vp || p === undefined || p === lastReportedPage.current) return\n if (p !== vp.currentPage.get()) vp.scrollToPage(p)\n }, [ctx.pageModel])\n useEffect(() => {\n const tc = engine.current?.tools\n if (tc && tc.active.get() !== ctx.tool) tc.set(ctx.tool)\n }, [ctx.tool])\n // The build applied both; these only act on a later change, not on mount.\n useEffect(() => {\n const vp = engine.current?.viewport\n if (vp && vp.mode.get() !== mode) vp.setMode(mode)\n }, [mode])\n useEffect(() => {\n const vp = engine.current?.viewport\n if (vp && vp.rotation.get() !== rotation) vp.setRotation(rotation)\n }, [rotation])\n\n const state = ctx.status.state\n const err = ctx.status.state === 'error' ? ctx.status.error : null\n\n return (\n <div\n {...rest}\n className={cx('ink-viewport-root', className)}\n data-ink-viewport-root=\"\"\n data-state={state}\n >\n {state === 'loading' ? (\n <div className=\"ink-status\" role=\"status\" aria-live=\"polite\">\n {loading === undefined ? 'Loading document…' : loading}\n </div>\n ) : err ? (\n <div className=\"ink-status ink-error\" role=\"alert\">\n {typeof error === 'function' ? (\n error({ error: err })\n ) : error !== undefined ? (\n error\n ) : (\n <>\n <p className=\"ink-error-title\">This document could not be opened.</p>\n {/* The message comes from the PDF engine and is not written for readers: it stays\n off the page, on the code's tooltip. */}\n <p>\n <code className=\"ink-error-code\" title={err.message}>\n {err.code}\n </code>\n </p>\n </>\n )}\n </div>\n ) : state === 'idle' ? (\n <div className=\"ink-status ink-empty\">{empty}</div>\n ) : null}\n <div\n ref={scroll}\n className=\"ink-scroll\"\n data-ink-scroll=\"\"\n tabIndex={0}\n role=\"document\"\n aria-label=\"Document\"\n />\n {pages.map((p) => (\n <InkPage\n key={`${p.build}:${p.page}`}\n page={p.page}\n host={p.host}\n mount={p.mount}\n error={p.error}\n customAnnotations={p.custom}\n renderAnnotation={renderAnnotation}\n renderPageError={renderPageError}\n />\n ))}\n </div>\n )\n}\n","import { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\n\nimport type { ComponentPropsWithoutRef } from 'react'\n\nexport interface InkToolbarProps extends Omit<ComponentPropsWithoutRef<'div'>, 'dir'> {\n /** Radix narrows text direction to these two values. */\n dir?: 'ltr' | 'rtl'\n label?: string\n asChild?: boolean\n}\n\nexport function InkToolbar({\n label = 'Document tools',\n asChild = false,\n className,\n children,\n ...rest\n}: InkToolbarProps) {\n return (\n <Toolbar.Root\n asChild={asChild}\n orientation=\"horizontal\"\n aria-label={label}\n data-ink-toolbar=\"\"\n className={cx('ink-toolbar', className)}\n {...rest}\n >\n {children}\n </Toolbar.Root>\n )\n}\n","/*\n * An icon from `@inkbar/icons`, hidden from assistive technology: the control it sits in\n * carries the name. The theme sizes it with `--ink-icon-size`.\n */\nimport { ICON_ATTRIBUTES } from '@inkbar/icons'\nimport { createElement, type SVGProps } from 'react'\n\nimport type { IconNode } from '@inkbar/icons'\n\nexport interface InkIconProps {\n icon: IconNode\n size?: number\n}\n\n/** `stroke-width` to `strokeWidth`: React names SVG attributes in camelCase. */\nconst camel = (name: string) =>\n name.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase())\n\nconst SVG_ATTRIBUTES = Object.fromEntries(\n Object.entries(ICON_ATTRIBUTES).map(([k, v]) => [camel(k), v])\n) as SVGProps<SVGSVGElement>\n\nexport function InkIcon({ icon, size = 18 }: InkIconProps) {\n return (\n <svg\n {...SVG_ATTRIBUTES}\n width={size}\n height={size}\n className=\"ink-icon\"\n aria-hidden=\"true\"\n >\n {icon.map(([tag, attrs], i) => createElement(tag, { key: i, ...attrs }))}\n </svg>\n )\n}\n","import { TOOL_LABELS, type ToolId } from '@inkbar/core/dom'\nimport { Hand, Highlighter, MessageSquare, MousePointer2, Square } from '@inkbar/icons'\nimport { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { useTool } from '../hooks/useTool'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { IconNode } from '@inkbar/icons'\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react'\n\nconst ICONS: Readonly<Record<ToolId, IconNode>> = {\n view: Hand,\n select: MousePointer2,\n highlight: Highlighter,\n 'redact-area': Square,\n note: MessageSquare,\n}\n\nexport interface InkToolButtonProps extends Omit<\n ComponentPropsWithoutRef<'button'>,\n 'children'\n> {\n tool: ToolId\n label?: string | undefined\n asChild?: boolean\n children?: ReactNode | ((props: { active: boolean; label: string }) => ReactNode)\n}\n\nexport function InkToolButton({\n tool,\n label,\n asChild = false,\n className,\n children,\n onClick,\n ...rest\n}: InkToolButtonProps) {\n const { tool: current, setTool } = useTool()\n const active = current === tool\n const name = label ?? TOOL_LABELS[tool]\n return (\n <Toolbar.Button\n asChild={asChild}\n className={cx('ink-tool-button', className)}\n data-ink-tool-button=\"\"\n data-tool={tool}\n data-state={active ? 'on' : 'off'}\n aria-pressed={active}\n aria-label={name}\n title={name}\n onClick={(e) => {\n onClick?.(e)\n if (!e.defaultPrevented) setTool(tool)\n }}\n {...rest}\n >\n {typeof children === 'function'\n ? children({ active, label: name })\n : (children ?? <InkIcon icon={ICONS[tool]} />)}\n </Toolbar.Button>\n )\n}\n","import { cx } from '../class-names'\n\nimport type { ComponentPropsWithoutRef } from 'react'\n\nexport type InkToolbarSeparatorProps = ComponentPropsWithoutRef<'div'>\n\n/**\n * A divider between groups of controls in a horizontal toolbar. Not focusable. A plain div\n * rather than Radix's separator, which reads as horizontal inside a horizontal toolbar.\n */\nexport function InkToolbarSeparator({ className, ...rest }: InkToolbarSeparatorProps) {\n return (\n <div\n role=\"separator\"\n aria-orientation=\"vertical\"\n className={cx('ink-toolbar-separator', className)}\n data-ink-toolbar-separator=\"\"\n {...rest}\n />\n )\n}\n","import { Undo2 } from '@inkbar/icons'\nimport { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { useHistory } from '../hooks/useHistory'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { InkHistoryButtonProps } from './history-button'\n\nexport function InkUndo({\n asChild = false,\n className,\n children,\n disabled,\n onClick,\n ...rest\n}: InkHistoryButtonProps) {\n const { canUndo, undo } = useHistory()\n return (\n <Toolbar.Button\n asChild={asChild}\n className={cx('ink-undo', className)}\n data-ink-undo=\"\"\n aria-label=\"Undo\"\n title=\"Undo\"\n {...rest}\n disabled={disabled === true || !canUndo}\n onClick={(e) => {\n onClick?.(e)\n if (!e.defaultPrevented) undo()\n }}\n >\n {children ?? <InkIcon icon={Undo2} />}\n </Toolbar.Button>\n )\n}\n","import { Redo2 } from '@inkbar/icons'\nimport { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { useHistory } from '../hooks/useHistory'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { InkHistoryButtonProps } from './history-button'\n\nexport function InkRedo({\n asChild = false,\n className,\n children,\n disabled,\n onClick,\n ...rest\n}: InkHistoryButtonProps) {\n const { canRedo, redo } = useHistory()\n return (\n <Toolbar.Button\n asChild={asChild}\n className={cx('ink-redo', className)}\n data-ink-redo=\"\"\n aria-label=\"Redo\"\n title=\"Redo\"\n {...rest}\n disabled={disabled === true || !canRedo}\n onClick={(e) => {\n onClick?.(e)\n if (!e.defaultPrevented) redo()\n }}\n >\n {children ?? <InkIcon icon={Redo2} />}\n </Toolbar.Button>\n )\n}\n","import { ZoomIn } from '@inkbar/icons'\nimport { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { useZoom } from '../hooks/useZoom'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { InkZoomButtonProps } from './zoom-button'\n\nexport function InkZoomIn({\n asChild = false,\n className,\n children,\n onClick,\n ...rest\n}: InkZoomButtonProps) {\n const { zoomIn } = useZoom()\n return (\n <Toolbar.Button\n asChild={asChild}\n className={cx('ink-zoom-in', className)}\n data-ink-zoom-in=\"\"\n aria-label=\"Zoom in\"\n title=\"Zoom in\"\n {...rest}\n onClick={(e) => {\n onClick?.(e)\n if (!e.defaultPrevented) zoomIn()\n }}\n >\n {children ?? <InkIcon icon={ZoomIn} />}\n </Toolbar.Button>\n )\n}\n","import { ZoomOut } from '@inkbar/icons'\nimport { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { useZoom } from '../hooks/useZoom'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { InkZoomButtonProps } from './zoom-button'\n\nexport function InkZoomOut({\n asChild = false,\n className,\n children,\n onClick,\n ...rest\n}: InkZoomButtonProps) {\n const { zoomOut } = useZoom()\n return (\n <Toolbar.Button\n asChild={asChild}\n className={cx('ink-zoom-out', className)}\n data-ink-zoom-out=\"\"\n aria-label=\"Zoom out\"\n title=\"Zoom out\"\n {...rest}\n onClick={(e) => {\n onClick?.(e)\n if (!e.defaultPrevented) zoomOut()\n }}\n >\n {children ?? <InkIcon icon={ZoomOut} />}\n </Toolbar.Button>\n )\n}\n","import { ZOOM_LEVELS, type ZoomValue } from '@inkbar/core/dom'\nimport { Check, ChevronDown } from '@inkbar/icons'\nimport { Select } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { useZoom } from '../hooks/useZoom'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { ComponentPropsWithoutRef } from 'react'\n\nconst CUSTOM = 'custom:'\nconst level = (z: number) => ZOOM_LEVELS.find((l) => Math.abs(l - z) < 0.001)\nconst percent = (z: number) => `${Math.round(z * 100)}%`\n\nconst FITS = [\n { value: 'fit-width', label: 'Fit width' },\n { value: 'fit-page', label: 'Fit page' },\n]\n\n/** Props of the select's trigger button; the options come from the zoom levels. */\nexport type InkZoomSelectProps = Omit<\n ComponentPropsWithoutRef<typeof Select.Trigger>,\n 'children' | 'asChild'\n>\n\nfunction Item({ value, label }: { value: string; label: string }) {\n return (\n <Select.Item value={value} className=\"ink-select-item\" data-ink-select-item=\"\">\n <Select.ItemText>{label}</Select.ItemText>\n <Select.ItemIndicator className=\"ink-select-indicator\">\n <InkIcon icon={Check} size={16} />\n </Select.ItemIndicator>\n </Select.Item>\n )\n}\n\nexport function InkZoomSelect({ className, ...rest }: InkZoomSelectProps) {\n const { zoom, scale, setZoom } = useZoom()\n /** A numeric zoom that is not one of the levels (zoom in and out multiply). */\n const custom = typeof zoom === 'number' && level(zoom) === undefined ? zoom : null\n const value =\n typeof zoom !== 'number'\n ? zoom\n : custom === null\n ? String(level(zoom))\n : `${CUSTOM}${zoom}`\n /** The levels, with a custom zoom in its place among them. */\n const levels = ZOOM_LEVELS.map((l) => ({ z: l, value: String(l), label: percent(l) }))\n if (custom !== null)\n levels.push({ z: custom, value: `${CUSTOM}${custom}`, label: percent(scale) })\n levels.sort((a, b) => a.z - b.z)\n\n function onValueChange(v: string): void {\n if (v === value) return\n const next: ZoomValue =\n v === 'fit-width' || v === 'fit-page' ? v : Number(v.replace(CUSTOM, ''))\n setZoom(next)\n }\n return (\n <Select.Root value={value} onValueChange={onValueChange}>\n <Select.Trigger\n className={cx('ink-zoom-select ink-select-trigger', className)}\n data-ink-zoom-select=\"\"\n aria-label=\"Zoom\"\n {...rest}\n >\n <Select.Value className=\"ink-select-value\" />\n <Select.Icon className=\"ink-select-icon\">\n <InkIcon icon={ChevronDown} size={16} />\n </Select.Icon>\n </Select.Trigger>\n <Select.Portal>\n <Select.Content\n className=\"ink-select-content\"\n data-ink-select-content=\"\"\n position=\"popper\"\n side=\"top\"\n sideOffset={4}\n >\n <Select.Viewport>\n {FITS.map((o) => (\n <Item key={o.value} value={o.value} label={o.label} />\n ))}\n <Select.Separator className=\"ink-select-separator\" />\n {levels.map((o) => (\n <Item key={o.value} value={o.value} label={o.label} />\n ))}\n </Select.Viewport>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n )\n}\n","import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type KeyboardEvent,\n} from 'react'\n\nimport { cx } from '../class-names'\nimport { usePage } from '../hooks/usePage'\nimport { useLatest } from '../use-latest'\n\nexport type InkPageInputProps = Omit<\n ComponentPropsWithoutRef<'input'>,\n 'value' | 'onChange' | 'type' | 'min' | 'max'\n>\n\nexport function InkPageInput({\n className,\n onKeyDown: onKeyDownProp,\n ...rest\n}: InkPageInputProps) {\n const { current, count, goTo } = usePage()\n const [draft, setDraft] = useState(String(current + 1))\n useEffect(() => {\n setDraft(String(current + 1))\n }, [current])\n const input = useRef<HTMLInputElement>(null)\n const latest = useLatest({ current, count, goTo })\n\n /** 1-based in the input, 0-based in the viewport. Out of range resets to the current page. */\n const commit = useCallback(\n (value: string) => {\n const { current: page, count: total, goTo: go } = latest.current\n const n = Number(value)\n if (Number.isInteger(n) && n >= 1 && n <= total) {\n if (n - 1 !== page) go(n - 1)\n } else setDraft(String(page + 1))\n },\n [latest]\n )\n // The native `change` event fires when an edit is committed: on blur after typing, and on\n // each step of the spinner or the arrow keys. React's `onChange` is the `input` event, which\n // fires for every keystroke, so the commit listens to the DOM event itself.\n useEffect(() => {\n const el = input.current\n if (!el) return\n const onNativeChange = (): void => commit(el.value)\n el.addEventListener('change', onNativeChange)\n return () => el.removeEventListener('change', onNativeChange)\n }, [commit])\n\n function onKeyDown(e: KeyboardEvent<HTMLInputElement>): void {\n onKeyDownProp?.(e)\n if (e.defaultPrevented || e.key !== 'Enter') return\n e.preventDefault()\n commit(draft)\n }\n return (\n <input\n ref={input}\n className={cx('ink-page-input', className)}\n data-ink-page-input=\"\"\n type=\"number\"\n inputMode=\"numeric\"\n aria-label=\"Page\"\n min={1}\n max={count}\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={onKeyDown}\n {...rest}\n />\n )\n}\n","import { cx } from '../class-names'\nimport { usePage } from '../hooks/usePage'\n\nimport type { ComponentPropsWithoutRef } from 'react'\n\nexport function InkPageCount({ className, ...rest }: ComponentPropsWithoutRef<'span'>) {\n const { count } = usePage()\n return (\n <span\n className={cx('ink-page-count', className)}\n data-ink-page-count=\"\"\n aria-live=\"polite\"\n {...rest}\n >\n {`of ${count}`}\n </span>\n )\n}\n","import { ChevronLeft } from '@inkbar/icons'\nimport { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { usePage } from '../hooks/usePage'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { InkPageButtonProps } from './page-button'\n\nexport function InkPrevPage({\n asChild = false,\n className,\n children,\n disabled,\n onClick,\n ...rest\n}: InkPageButtonProps) {\n const { current, previous } = usePage()\n return (\n <Toolbar.Button\n asChild={asChild}\n className={cx('ink-prev-page', className)}\n data-ink-prev-page=\"\"\n aria-label=\"Previous page\"\n title=\"Previous page\"\n disabled={disabled === true || current <= 0}\n {...rest}\n onClick={(e) => {\n onClick?.(e)\n if (!e.defaultPrevented) previous()\n }}\n >\n {children ?? <InkIcon icon={ChevronLeft} />}\n </Toolbar.Button>\n )\n}\n","import { ChevronRight } from '@inkbar/icons'\nimport { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { usePage } from '../hooks/usePage'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { InkPageButtonProps } from './page-button'\n\nexport function InkNextPage({\n asChild = false,\n className,\n children,\n disabled,\n onClick,\n ...rest\n}: InkPageButtonProps) {\n const { current, count, next } = usePage()\n return (\n <Toolbar.Button\n asChild={asChild}\n className={cx('ink-next-page', className)}\n data-ink-next-page=\"\"\n aria-label=\"Next page\"\n title=\"Next page\"\n disabled={disabled === true || current >= count - 1}\n {...rest}\n onClick={(e) => {\n onClick?.(e)\n if (!e.defaultPrevented) next()\n }}\n >\n {children ?? <InkIcon icon={ChevronRight} />}\n </Toolbar.Button>\n )\n}\n","import { observeAnnotationElement } from '@inkbar/core/dom'\nimport { useEffect, useState } from 'react'\n\n/**\n * The overlay element core draws for an annotation, for anchoring a popover to it. Core\n * creates and removes these elements outside React, so this follows the root's subtree while\n * an id is wanted.\n */\nexport function useAnnotationElement(\n root: HTMLElement | null,\n id: string | null\n): HTMLElement | null {\n const [element, setElement] = useState<HTMLElement | null>(null)\n useEffect(() => {\n if (!root || !id) {\n setElement(null)\n return\n }\n return observeAnnotationElement(root, id, setElement)\n }, [root, id])\n return element\n}\n","import {\n createFocusReturn,\n shouldKeepOpenOnAnnotation,\n type FocusReturn,\n} from '@inkbar/core/dom'\nimport { useMemo } from 'react'\n\nimport { useLatest } from '../use-latest'\n\nimport type { InkContext } from '../context'\n\nexport type { FocusReturn }\n\n/** Radix's `onInteractOutside` handler: a press that will activate an annotation keeps the popover open. */\nexport function keepOpenOnAnnotation(event: CustomEvent<{ originalEvent: Event }>): void {\n if (shouldKeepOpenOnAnnotation(event.detail.originalEvent.target))\n event.preventDefault()\n}\n\nexport function useFocusReturn(ctx: InkContext): FocusReturn {\n const latest = useLatest(ctx)\n return useMemo(\n () =>\n createFocusReturn({\n root: () => latest.current.rootEl,\n activated: () => latest.current.activated,\n }),\n [latest]\n )\n}\n","/*\n * The thread for the activated note, anchored to the note's overlay element. Activating a\n * reply opens the whole thread from its root. Closing (Close, Escape, a press outside) clears\n * `activated`.\n *\n * A new note has no text. While its root is empty (and unlocked) the default form writes the\n * root's own `contents`, labelled \"Comment\", and the thread list stays hidden until there is\n * something in it; after that the form adds replies. Closing a root that is still empty and\n * has no replies removes it, so an abandoned note does not stay on the page.\n */\nimport { isAbandonedNote, threadOf, threadRoot } from '@inkbar/core'\nimport { Popover } from 'radix-ui'\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n type FormEvent,\n type ReactNode,\n} from 'react'\n\nimport { useInkContext } from '../context'\nimport { useAnnotations } from '../hooks/useAnnotations'\nimport { useLatest } from '../use-latest'\n\nimport { useAnnotationElement } from './annotation-element'\nimport { keepOpenOnAnnotation, useFocusReturn } from './popover-focus'\n\nimport type { Annotation, NoteAnnotation } from '@inkbar/core'\nimport type { NotePopoverSlotProps } from '@inkbar/core/dom'\n\nexport interface InkNotePopoverProps {\n children?: ((props: NotePopoverSlotProps) => ReactNode) | undefined\n}\n\nexport function InkNotePopover({ children }: InkNotePopoverProps) {\n const ctx = useInkContext('InkNotePopover')\n const { annotations, add, update, remove } = useAnnotations()\n\n const note = useMemo<NoteAnnotation | null>(() => {\n const a = ctx.activated ? annotations.find((x) => x.id === ctx.activated) : undefined\n return a?.type === 'note' ? threadRoot(annotations, a) : null\n }, [annotations, ctx.activated])\n const anchor = useAnnotationElement(ctx.rootEl, note?.id ?? null)\n const anchorRef = useMemo(() => ({ current: anchor }), [anchor])\n const focusReturn = useFocusReturn(ctx)\n const open = note !== null && anchor !== null\n /** The root, then every reply below it, depth first, each level in creation order. */\n const thread = useMemo<Annotation[]>(\n () => (note ? threadOf(annotations, note) : []),\n [annotations, note]\n )\n /** True while the default form writes the root note's own text rather than a reply. */\n const editingRoot = note !== null && !note.locked && !note.contents?.trim()\n\n /**\n * Notes this popover wrote text or a reply for. In controlled mode the write is a proposal\n * the host may not have applied yet, so the applied list still shows the note empty; these\n * are never dropped as abandoned.\n */\n const written = useRef(new Set<string>())\n /** Notes this popover has already asked to remove, so a slow host is asked once. */\n const dropped = useRef(new Set<string>())\n const latest = useLatest({ annotations, remove })\n\n function dropIfEmpty(id: string): boolean {\n if (\n dropped.current.has(id) ||\n written.current.has(id) ||\n !isAbandonedNote(latest.current.annotations, id)\n )\n return false\n dropped.current.add(id)\n latest.current.remove(id)\n return true\n }\n\n // Activation moved on from a note that never got any text: drop it.\n const noteId = note?.id\n const previousId = useRef<string | undefined>(undefined)\n useEffect(() => {\n const previous = previousId.current\n if (previous === noteId) return\n previousId.current = noteId\n if (previous !== undefined) dropIfEmpty(previous)\n // dropIfEmpty reads through `latest`; it is stable for the effect's purposes.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [noteId])\n\n function reply(text: string): void {\n const root = note\n const contents = text.trim()\n if (!root || !contents) return\n written.current.add(root.id)\n add({ type: 'note', page: root.page, rect: root.rect, contents, inReplyTo: root.id })\n }\n function isEmptyRoot(root: NoteAnnotation): boolean {\n return (\n !written.current.has(root.id) &&\n !root.locked &&\n !root.contents?.trim() &&\n thread.length === 1\n )\n }\n function close(): void {\n const root = note\n if (root && annotations.some((a) => a.id === root.id) && isEmptyRoot(root)) {\n focusReturn.beforeRemove(anchor)\n dropIfEmpty(root.id)\n }\n ctx.setActivated(null)\n }\n function updateContents(contents: string): void {\n if (!note || note.locked) return\n if (contents.trim()) written.current.add(note.id)\n update(note.id, { contents })\n }\n /** Locked notes cannot be removed: removing one does nothing and keeps the popover. */\n function removeThread(): void {\n const root = note\n if (!root || root.locked) return\n focusReturn.beforeRemove(anchor)\n // Under a slow controlled host the note stays listed for a while; it is not asked for again.\n dropped.current.add(root.id)\n remove(root.id)\n ctx.setActivated(null)\n }\n\n return (\n <Popover.Root open={open} onOpenChange={(next) => !next && close()}>\n <Popover.Anchor virtualRef={anchorRef} />\n <Popover.Portal>\n {note && anchor ? (\n <Popover.Content\n className=\"ink-note-popover\"\n data-ink-note-popover=\"\"\n side=\"right\"\n sideOffset={8}\n collisionPadding={8}\n aria-label=\"Note thread\"\n onInteractOutside={keepOpenOnAnnotation}\n onCloseAutoFocus={(e) => focusReturn.onCloseAutoFocus(e, anchor)}\n >\n {children ? (\n children({\n note,\n replies: thread.slice(1),\n reply,\n update: updateContents,\n remove: removeThread,\n close,\n })\n ) : (\n <>\n {!editingRoot || thread.length > 1 ? (\n <ol className=\"ink-thread\" data-ink-thread=\"\">\n {thread.map((item) => (\n <li\n key={item.id}\n className=\"ink-thread-item\"\n data-ink-thread-item=\"\"\n data-reply={item.inReplyTo ? '' : undefined}\n >\n <span className=\"ink-thread-author\">\n {item.author ?? 'Anonymous'}\n </span>\n <time className=\"ink-thread-time\" dateTime={item.createdAt}>\n {new Date(item.createdAt).toLocaleString()}\n </time>\n <p className=\"ink-thread-text\">{item.contents}</p>\n </li>\n ))}\n </ol>\n ) : null}\n <ThreadForm\n // Keyed by note: moving to another note starts with an empty draft at once.\n key={note.id}\n editingRoot={editingRoot}\n locked={!!note.locked}\n onSubmit={(text) => (editingRoot ? updateContents(text) : reply(text))}\n onRemove={removeThread}\n onClose={close}\n />\n </>\n )}\n </Popover.Content>\n ) : null}\n </Popover.Portal>\n </Popover.Root>\n )\n}\n\n/** The default form: the root note's own text while it is empty, replies after that. */\nfunction ThreadForm({\n editingRoot,\n locked,\n onSubmit,\n onRemove,\n onClose,\n}: {\n editingRoot: boolean\n locked: boolean\n onSubmit: (text: string) => void\n onRemove: () => void\n onClose: () => void\n}) {\n const [draft, setDraft] = useState('')\n function submit(e: FormEvent): void {\n e.preventDefault()\n const text = draft.trim()\n if (!text) return\n onSubmit(text)\n setDraft('')\n }\n return (\n <form className=\"ink-thread-reply\" data-ink-thread-reply=\"\" onSubmit={submit}>\n <textarea\n aria-label={editingRoot ? 'Comment' : 'Reply'}\n rows={2}\n placeholder={editingRoot ? 'Comment' : 'Reply'}\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n />\n <div className=\"ink-thread-actions\">\n <button type=\"submit\" disabled={!draft.trim()}>\n {editingRoot ? 'Comment' : 'Reply'}\n </button>\n {!locked ? (\n <button type=\"button\" onClick={onRemove}>\n Delete\n </button>\n ) : null}\n <button type=\"button\" onClick={onClose}>\n Close\n </button>\n </div>\n </form>\n )\n}\n","/*\n * Review card for a suggested redaction: opens when the activated annotation, or the only\n * selected one, is a redaction with `origin: 'suggested'`. Locked suggestions cannot be\n * dismissed, so they get no Dismiss button. A press on the overlay selects and activates, so a\n * click opens it whatever the tool. Closing clears `activated` and the selection.\n */\nimport { confidenceBucket } from '@inkbar/core'\nimport { Popover } from 'radix-ui'\nimport { useMemo, type ReactNode } from 'react'\n\nimport { useInkContext } from '../context'\nimport { useAnnotations } from '../hooks/useAnnotations'\n\nimport { useAnnotationElement } from './annotation-element'\nimport { keepOpenOnAnnotation, useFocusReturn } from './popover-focus'\n\nimport type { ConfidenceBucket, RedactAnnotation } from '@inkbar/core'\nimport type { SuggestionCardSlotProps } from '@inkbar/core/dom'\n\nexport interface InkSuggestionCardProps {\n children?: ((props: SuggestionCardSlotProps) => ReactNode) | undefined\n}\n\nexport function InkSuggestionCard({ children }: InkSuggestionCardProps) {\n const ctx = useInkContext('InkSuggestionCard')\n const {\n annotations,\n selection,\n accept: acceptId,\n dismiss: dismissId,\n select,\n } = useAnnotations()\n\n function suggestion(id: string | null | undefined): RedactAnnotation | null {\n const a = id ? annotations.find((x) => x.id === id) : undefined\n return a?.type === 'redact' && a.origin === 'suggested' ? a : null\n }\n // The activated annotation when it is a suggestion; otherwise the only selected one (a\n // marquee selects without activating).\n const target =\n suggestion(ctx.activated) ??\n (selection.length === 1 ? suggestion(selection[0]) : null)\n const anchor = useAnnotationElement(ctx.rootEl, target?.id ?? null)\n const anchorRef = useMemo(() => ({ current: anchor }), [anchor])\n const focusReturn = useFocusReturn(ctx)\n const open = target !== null && anchor !== null\n const bucket: ConfidenceBucket | undefined = target?.suggestion\n ? confidenceBucket(target.suggestion.confidence)\n : undefined\n\n function close(): void {\n ctx.setActivated(null)\n select([])\n }\n function accept(): void {\n if (target) acceptId(target.id)\n close()\n }\n /** Locked annotations cannot be removed: dismissing one does nothing and keeps the card. */\n function dismiss(): void {\n if (!target || target.locked) return\n focusReturn.beforeRemove(anchor, '[data-origin=\"suggested\"]')\n dismissId(target.id)\n close()\n }\n\n return (\n <Popover.Root open={open} onOpenChange={(next) => !next && close()}>\n <Popover.Anchor virtualRef={anchorRef} />\n <Popover.Portal>\n {target && anchor ? (\n <Popover.Content\n className=\"ink-suggestion-card\"\n data-ink-suggestion-card=\"\"\n side=\"bottom\"\n sideOffset={6}\n collisionPadding={8}\n aria-label=\"Suggested redaction\"\n onInteractOutside={keepOpenOnAnnotation}\n onCloseAutoFocus={(e) => focusReturn.onCloseAutoFocus(e, anchor)}\n >\n {children ? (\n children({\n annotation: target,\n suggestion: target.suggestion,\n bucket,\n accept,\n dismiss,\n close,\n })\n ) : (\n <>\n <p className=\"ink-suggestion-reason\">\n <strong>{target.suggestion?.reason ?? 'Suggested redaction'}</strong>\n {bucket ? (\n <span className=\"ink-suggestion-confidence\" data-confidence={bucket}>\n {bucket} confidence\n </span>\n ) : null}\n </p>\n {target.suggestion?.explanation ? (\n <p className=\"ink-suggestion-explanation\">\n {target.suggestion.explanation}\n </p>\n ) : null}\n <div className=\"ink-suggestion-actions\">\n <button type=\"button\" onClick={accept}>\n Accept\n </button>\n {!target.locked ? (\n <button type=\"button\" onClick={dismiss}>\n Dismiss\n </button>\n ) : null}\n </div>\n </>\n )}\n </Popover.Content>\n ) : null}\n </Popover.Portal>\n </Popover.Root>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/context.ts","../src/use-readable.ts","../src/hooks/useDocument.ts","../src/hooks/useAnnotations.ts","../src/hooks/useTool.ts","../src/hooks/useSelection.ts","../src/hooks/useZoom.ts","../src/hooks/usePage.ts","../src/hooks/useHistory.ts","../src/hooks/useEmbedded.ts","../src/use-latest.ts","../src/components/InkRoot.tsx","../src/class-names.ts","../src/components/InkAnnotation.tsx","../src/components/InkPage.tsx","../src/components/InkViewport.tsx","../src/components/InkToolbar.tsx","../src/components/InkIcon.tsx","../src/components/InkToolButton.tsx","../src/components/InkToolbarSeparator.tsx","../src/components/InkUndo.tsx","../src/components/InkRedo.tsx","../src/components/InkZoomIn.tsx","../src/components/InkZoomOut.tsx","../src/components/InkZoomSelect.tsx","../src/components/InkPageInput.tsx","../src/components/InkPageCount.tsx","../src/components/InkPrevPage.tsx","../src/components/InkNextPage.tsx","../src/components/annotation-element.ts","../src/components/popover-focus.ts","../src/components/InkNotePopover.tsx","../src/components/InkSuggestionCard.tsx"],"sourcesContent":["import { createContext, useContext } from 'react'\n\nimport type { Annotation, InkDocument, InkStatus, PdfAssets } from '@inkbar/core'\nimport type { ToolController, ToolId, Viewport, ZoomValue } from '@inkbar/core/dom'\n\nexport type { InkStatus }\n\n/** Undo and redo for the current document, whichever mode its annotations are in. */\nexport interface InkHistory {\n canUndo: boolean\n canRedo: boolean\n undo: () => void\n redo: () => void\n clear: () => void\n /**\n * Runs `fn` and records what it changes as one undo step. The host still receives one change\n * per add. Controlled, the history groups the resulting list changes into one step, and\n * `canUndo` updates once the current task ends. Any other change the host applies in that\n * same window joins the step.\n */\n batch: (fn: () => void) => void\n}\n\nexport interface InkContext {\n assets: PdfAssets\n document: InkDocument | null\n /** `loading` from the moment a document starts opening, then the document's own status. */\n status: InkStatus\n annotations: readonly Annotation[]\n selection: readonly string[]\n /** Set by InkViewport once it has built its viewport and tool controller. */\n viewport: Viewport | null\n tools: ToolController | null\n /** Desired tool; InkViewport applies it to the controller. */\n tool: ToolId\n setTool: (id: ToolId) => void\n /** Desired zoom and page from the host's props; InkViewport applies and reports back. */\n zoomModel: ZoomValue | undefined\n pageModel: number | undefined\n reportZoom: (z: ZoomValue) => void\n reportPage: (p: number) => void\n /** Last activated annotation (Enter, click with the note tool, etc.). Popovers key off this. */\n activated: string | null\n setActivated: (id: string | null) => void\n history: InkHistory\n rootEl: HTMLElement | null\n setViewport: (viewport: Viewport | null, tools: ToolController | null) => void\n}\n\nexport const InkContextObject = createContext<InkContext | null>(null)\n\n/**\n * The context for hooks: throws a readable error when called outside a component rendered\n * inside `InkRoot`.\n */\nexport function useInkContext(consumer: string): InkContext {\n const ctx = useContext(InkContextObject)\n if (!ctx)\n throw new Error(\n `[inkbar] ${consumer} must be called in a component inside <InkRoot>.`\n )\n return ctx\n}\n","import { useCallback, useSyncExternalStore } from 'react'\n\nimport type { Readable } from '@inkbar/core'\n\nconst noop = (): void => undefined\n\n/**\n * Mirrors a core `Readable` into React. A missing readable yields `fallback`, which must be a\n * stable reference (a module constant): `useSyncExternalStore` compares snapshots by identity\n * and loops on a fresh value. On the server the fallback is rendered.\n */\nexport function useReadable<T>(readable: Readable<T> | null | undefined, fallback: T): T {\n const subscribe = useCallback(\n (onChange: () => void) => (readable ? readable.subscribe(() => onChange()) : noop),\n [readable]\n )\n const get = useCallback(\n () => (readable ? readable.get() : fallback),\n [readable, fallback]\n )\n const server = useCallback(() => fallback, [fallback])\n return useSyncExternalStore(subscribe, get, server)\n}\n","import { useMemo } from 'react'\n\nimport { useInkContext } from '../context'\n\nimport type { AnnotationDocument, ImportOptions, PageInfo } from '@inkbar/core'\n\nconst NO_PAGES: readonly PageInfo[] = []\n\nexport function useDocument() {\n const ctx = useInkContext('useDocument()')\n const { document, status } = ctx\n return useMemo(\n () => ({\n document,\n status,\n isReady: status.state === 'ready',\n error: status.state === 'error' ? status.error : null,\n pages: document?.pages ?? NO_PAGES,\n info: document?.info ?? null,\n exportAnnotations: () => document?.exportAnnotations('json'),\n importAnnotations: (data: AnnotationDocument | string, opts?: ImportOptions) =>\n document?.importAnnotations(data, opts),\n }),\n [document, status]\n )\n}\n","import { acceptSuggestion, repliesTo } from '@inkbar/core'\nimport { useMemo } from 'react'\n\nimport { useInkContext } from '../context'\n\nimport type { Annotation, AnnotationInput } from '@inkbar/core'\n\nexport function useAnnotations() {\n const ctx = useInkContext('useAnnotations()')\n const { annotations, selection, document } = ctx\n const store = document?.annotations\n const selected = useMemo(\n () =>\n selection\n .map((id) => annotations.find((a) => a.id === id))\n .filter((a): a is Annotation => !!a),\n [annotations, selection]\n )\n // Stable for the life of the document, so hosts can pass them as props or effect deps.\n const actions = useMemo(\n () => ({\n add: (input: AnnotationInput) => store?.add(input),\n update: (id: string, patch: Partial<Annotation>) => store?.update(id, patch),\n remove: (id: string) => store?.remove(id) ?? false,\n select: (ids: string[]) => store?.select(ids),\n /** Keeps a suggested redaction as the user's own, in the default redaction colour. */\n accept: (id: string) => (store ? acceptSuggestion(store, id) : undefined),\n dismiss: (id: string) => store?.remove(id) ?? false,\n }),\n [store]\n )\n return useMemo(\n () => ({\n annotations,\n selection,\n selected,\n byPage: (page: number) => annotations.filter((a) => a.page === page),\n /** Replies in creation order for a note id. */\n replies: (id: string) => repliesTo(annotations, id),\n ...actions,\n }),\n [annotations, selection, selected, actions]\n )\n}\n","import { useMemo } from 'react'\n\nimport { useInkContext } from '../context'\n\nexport function useTool() {\n const ctx = useInkContext('useTool()')\n const { tool, setTool } = ctx\n return useMemo(() => ({ tool, setTool }), [tool, setTool])\n}\n","import { useMemo } from 'react'\n\nimport { useInkContext } from '../context'\n\nexport function useSelection() {\n const ctx = useInkContext('useSelection()')\n const { selection, document } = ctx\n const store = document?.annotations\n return useMemo(\n () => ({\n selection,\n select: (ids: string[]) => store?.select(ids),\n clear: () => store?.select([]),\n }),\n [selection, store]\n )\n}\n","import { useMemo } from 'react'\n\nimport { useInkContext } from '../context'\nimport { useReadable } from '../use-readable'\n\nimport type { ZoomValue } from '@inkbar/core/dom'\n\nexport function useZoom() {\n const ctx = useInkContext('useZoom()')\n const { viewport } = ctx\n const zoom = useReadable<ZoomValue>(viewport?.zoom, 'fit-width')\n const scale = useReadable<number>(viewport?.scale, 1)\n return useMemo(\n () => ({\n zoom,\n scale,\n setZoom: (z: ZoomValue) => viewport?.setZoom(z),\n zoomIn: () => viewport?.zoomBy(1.25),\n zoomOut: () => viewport?.zoomBy(0.8),\n }),\n [viewport, zoom, scale]\n )\n}\n","import { useMemo } from 'react'\n\nimport { useInkContext } from '../context'\nimport { useReadable } from '../use-readable'\n\nexport function usePage() {\n const ctx = useInkContext('usePage()')\n const { viewport, document } = ctx\n const current = useReadable<number>(viewport?.currentPage, 0)\n return useMemo(\n () => ({\n /** 0-based. */\n current,\n count: document?.pages.length ?? 0,\n goTo: (index: number) => viewport?.scrollToPage(index),\n // Read the live page, so these stay the same functions as the reader scrolls.\n next: () => viewport?.scrollToPage(viewport.currentPage.get() + 1),\n previous: () => viewport?.scrollToPage(viewport.currentPage.get() - 1),\n scrollToAnnotation(id: string) {\n const a = document?.annotations.get(id)\n if (a) viewport?.scrollToRect(a.page, a.rect)\n },\n }),\n [viewport, document, current]\n )\n}\n","import { useInkContext, type InkHistory } from '../context'\n\n/**\n * Undo and redo. Uncontrolled documents use the core history; controlled hosts that pass\n * `history` to InkRoot get a snapshot stack over their own list, applied through\n * `onAnnotationsChange`.\n */\nexport function useHistory(): InkHistory {\n return useInkContext('useHistory()').history\n}\n","import { useMemo } from 'react'\n\nimport { useInkContext } from '../context'\n\nconst NONE: readonly never[] = []\n\nexport function useEmbedded() {\n const ctx = useInkContext('useEmbedded()')\n const summary = ctx.document?.embedded ?? NONE\n return useMemo(\n () => ({\n summary,\n total: summary.reduce((n, s) => n + s.count, 0),\n hasAny: summary.length > 0,\n }),\n [summary]\n )\n}\n","import { useLayoutEffect, useRef, type RefObject } from 'react'\n\n/**\n * A ref that always holds the latest render's value, for callbacks that outlive a render\n * (core's `onChange`, effects keyed on something else). Updated in a layout effect, so it is\n * current before the parent's own layout and passive effects and before any callback fired\n * after commit; declare it before the effects that read it.\n */\nexport function useLatest<T>(value: T): RefObject<T> {\n const ref = useRef(value)\n useLayoutEffect(() => {\n ref.current = value\n })\n return ref\n}\n","import { createSnapshotHistory, InkError, openDocument } from '@inkbar/core'\nimport { cssVariableDefaults } from '@inkbar/core/dom'\nimport { Slot } from 'radix-ui'\nimport {\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type ReactNode,\n type Ref,\n} from 'react'\nimport { flushSync } from 'react-dom'\n\nimport {\n InkContextObject,\n type InkContext,\n type InkHistory,\n type InkStatus,\n} from '../context'\nimport { useLatest } from '../use-latest'\nimport { useReadable } from '../use-readable'\n\nimport type {\n Annotation,\n AnnotationChange,\n AnnotationDefaults,\n DocumentSource,\n InkDocument,\n PdfAssets,\n} from '@inkbar/core'\nimport type { ToolController, ToolId, Viewport, ZoomValue } from '@inkbar/core/dom'\n\nexport interface InkRootHandle {\n readonly document: InkDocument | null\n readonly status: InkStatus\n readonly rootEl: HTMLElement | null\n /** What `useHistory()` returns inside the root. A controlled host calls `clear()` after loading its saved list. */\n readonly history: InkHistory\n}\n\nexport interface InkRootProps extends Omit<\n ComponentPropsWithoutRef<'div'>,\n 'children' | 'onChange' | 'onError'\n> {\n src: DocumentSource | null\n assets: PdfAssets\n password?: string | undefined\n /** Colour defaults. Without it, the theme's CSS variables on the root element apply. */\n defaults?: AnnotationDefaults | undefined\n /**\n * Pass (with `onAnnotationsChange`) to put annotations under the host's control. The mode\n * is fixed when a document opens: passing or dropping this prop later takes effect on the\n * next open.\n */\n annotations?: Annotation[] | undefined\n onAnnotationsChange?: ((next: Annotation[]) => void) | undefined\n onChange?: ((change: AnnotationChange) => void) | undefined\n tool?: ToolId | undefined\n onToolChange?: ((tool: ToolId) => void) | undefined\n page?: number | undefined\n onPageChange?: ((page: number) => void) | undefined\n zoom?: ZoomValue | undefined\n onZoomChange?: ((zoom: ZoomValue) => void) | undefined\n /** Undo history. Defaults to on for uncontrolled, off for controlled. */\n history?: boolean | undefined\n asChild?: boolean | undefined\n onReady?: ((doc: InkDocument) => void) | undefined\n onError?: ((error: InkError) => void) | undefined\n onActivate?: ((id: string) => void) | undefined\n children?:\n | ReactNode\n | ((props: { status: InkStatus; document: InkDocument | null }) => ReactNode)\n ref?: Ref<InkRootHandle>\n}\n\ntype TestHookElement = HTMLElement & { __inkDocument?: InkDocument | undefined }\n\nconst IDLE: InkStatus = { state: 'idle' }\nconst NO_ANNOTATIONS: readonly Annotation[] = []\nconst NO_IDS: readonly string[] = []\n\n/** Signed URLs change; the key does not. Bytes and Blobs are their own identity. */\nfunction identity(src: DocumentSource | null): unknown {\n if (src === null) return null\n if (typeof src === 'string') return src\n if ('key' in src) return src.key\n return src\n}\n\nfunction isDevelopment(): boolean {\n // Bundlers replace the expression with a literal; raw browser ESM has no `process`.\n try {\n return process.env.NODE_ENV !== 'production'\n } catch {\n return false\n }\n}\n\nfunction setTestHook(el: HTMLElement | null, doc: InkDocument | undefined): void {\n if (el && isDevelopment()) (el as TestHookElement).__inkDocument = doc\n}\n\nexport function InkRoot({\n src,\n assets,\n password,\n defaults,\n annotations,\n onAnnotationsChange,\n onChange,\n tool,\n onToolChange,\n page,\n onPageChange,\n zoom,\n onZoomChange,\n history,\n asChild = false,\n onReady,\n onError,\n onActivate,\n children,\n ref,\n ...rest\n}: InkRootProps) {\n const rootElRef = useRef<HTMLElement | null>(null)\n const [rootEl, setRootElState] = useState<HTMLElement | null>(null)\n const setRootEl = useCallback((el: HTMLElement | null) => {\n rootElRef.current = el\n setRootElState(el)\n }, [])\n\n const documentRef = useRef<InkDocument | null>(null)\n const [document, setDocument] = useState<InkDocument | null>(null)\n /** Overrides the document's status while opening, and when opening itself failed. */\n const [override, setOverride] = useState<InkStatus | null>(null)\n const [internalTool, setInternalTool] = useState<ToolId>(tool ?? 'view')\n const [activated, setActivatedState] = useState<string | null>(null)\n const [viewport, setViewportState] = useState<Viewport | null>(null)\n const [tools, setToolsState] = useState<ToolController | null>(null)\n\n const documentStatus = useReadable<InkStatus>(document?.status, IDLE)\n const status = override ?? documentStatus\n const annotationList = useReadable(document?.annotations.list, NO_ANNOTATIONS)\n const selection = useReadable(document?.annotations.selection, NO_IDS)\n\n // What the next open will do follows the prop; the open document's mode is fixed.\n const controlledProp = annotations !== undefined\n const controlled = document\n ? document.annotations.mode === 'controlled'\n : controlledProp\n const historyEnabled = controlled && history === true\n // Callbacks and options read later than the render that passed them.\n const latest = useLatest({\n src,\n assets,\n defaults,\n annotations,\n controlled: controlledProp,\n history,\n historyEnabled,\n onAnnotationsChange,\n onChange,\n onReady,\n onError,\n onActivate,\n onToolChange,\n onPageChange,\n onZoomChange,\n })\n\n const snapshotHistory = useMemo(\n () =>\n createSnapshotHistory({\n apply: (list) => documentRef.current?.annotations.replaceAll(list, 'history'),\n enabled: () => latest.current.historyEnabled,\n }),\n [latest]\n )\n useEffect(() => {\n snapshotHistory.observe(annotations)\n }, [annotations, snapshotHistory])\n\n const srcIdentity = identity(src)\n useEffect(() => {\n let cancelled = false\n snapshotHistory.clear()\n const source = latest.current.src\n if (source === null) {\n setOverride(null)\n return\n }\n setOverride({ state: 'loading' })\n let opened: InkDocument | null = null\n const run = async () => {\n try {\n const doc = await openDocument(source, {\n assets: latest.current.assets,\n password,\n defaults:\n latest.current.defaults ??\n (rootElRef.current ? cssVariableDefaults(rootElRef.current) : undefined),\n // Controlled hosts get the snapshot history below; core's own stack stays off.\n history: latest.current.controlled ? false : (latest.current.history ?? true),\n annotations: latest.current.controlled\n ? {\n mode: 'controlled',\n initial: latest.current.annotations ?? [],\n onChange: (next, change) => {\n // Apply the host's state update, its render and the layout effect that pushes\n // the list back before core's development check expires. The microtask\n // leaves React's render, commit and passive-effect contexts, where a host\n // may call the store, so `flushSync` is always legal; the host sees the\n // proposal one microtask after the store returned. A proposal made in the\n // tick this root unmounts or reopens never reaches the host.\n queueMicrotask(() => {\n if (cancelled) return\n flushSync(() => {\n latest.current.onAnnotationsChange?.(next)\n latest.current.onChange?.(change)\n })\n })\n },\n }\n : { mode: 'uncontrolled' },\n })\n if (cancelled) {\n doc.destroy()\n return\n }\n opened = doc\n // The prop may have changed while the file loaded, when there was no store to apply it to.\n const current = latest.current.annotations\n if (doc.annotations.mode === 'controlled' && current !== undefined)\n doc.annotations.setControlledValue(current)\n documentRef.current = doc\n setDocument(doc)\n setOverride(null)\n setTestHook(rootElRef.current, doc)\n const s = doc.status.get()\n if (s.state === 'ready') latest.current.onReady?.(doc)\n else if (s.state === 'error') latest.current.onError?.(s.error)\n } catch (cause) {\n if (cancelled) return\n const error =\n cause instanceof InkError\n ? cause\n : new InkError(\n 'InvalidPdf',\n cause instanceof Error ? cause.message : String(cause),\n {},\n cause\n )\n setOverride({ state: 'error', error })\n latest.current.onError?.(error)\n }\n }\n // StrictMode's simulated cleanup runs synchronously in the same commit, so deferring one\n // microtask means the discarded first attempt never starts a fetch.\n void Promise.resolve().then(() => {\n if (!cancelled) return run()\n })\n return () => {\n cancelled = true\n opened?.destroy()\n documentRef.current = null\n setDocument(null)\n setTestHook(rootElRef.current, undefined)\n }\n // `srcIdentity` stands in for `src`: a new URL with the same key is the same document.\n }, [srcIdentity, password, snapshotHistory, latest])\n\n useLayoutEffect(() => {\n if (annotations && document?.annotations.mode === 'controlled')\n document.annotations.setControlledValue(annotations)\n }, [annotations, document])\n\n useEffect(() => {\n if (tool) setInternalTool(tool)\n }, [tool])\n\n const setTool = useCallback(\n (id: ToolId) => {\n setInternalTool(id)\n latest.current.onToolChange?.(id)\n },\n [latest]\n )\n const setActivated = useCallback(\n (id: string | null) => {\n setActivatedState(id)\n if (id) latest.current.onActivate?.(id)\n },\n [latest]\n )\n const reportZoom = useCallback(\n (z: ZoomValue) => latest.current.onZoomChange?.(z),\n [latest]\n )\n const reportPage = useCallback(\n (p: number) => latest.current.onPageChange?.(p),\n [latest]\n )\n const setViewport = useCallback((vp: Viewport | null, tc: ToolController | null) => {\n setViewportState(vp)\n setToolsState(tc)\n }, [])\n\n const snapCanUndo = useReadable(snapshotHistory.canUndo, false)\n const snapCanRedo = useReadable(snapshotHistory.canRedo, false)\n const coreCanUndo = useReadable(document?.history.canUndo, false)\n const coreCanRedo = useReadable(document?.history.canRedo, false)\n const inkHistory = useMemo<InkHistory>(\n () => ({\n canUndo: controlled ? historyEnabled && snapCanUndo : coreCanUndo,\n canRedo: controlled ? historyEnabled && snapCanRedo : coreCanRedo,\n undo: () =>\n controlled ? snapshotHistory.undo() : documentRef.current?.history.undo(),\n redo: () =>\n controlled ? snapshotHistory.redo() : documentRef.current?.history.redo(),\n clear: () =>\n controlled ? snapshotHistory.clear() : documentRef.current?.history.clear(),\n batch: (fn) => {\n if (controlled) snapshotHistory.batch(fn)\n else if (documentRef.current) documentRef.current.history.batch(fn)\n else fn()\n },\n }),\n [\n controlled,\n historyEnabled,\n snapCanUndo,\n snapCanRedo,\n coreCanUndo,\n coreCanRedo,\n snapshotHistory,\n ]\n )\n\n useImperativeHandle(ref, () => ({ document, status, rootEl, history: inkHistory }), [\n document,\n status,\n rootEl,\n inkHistory,\n ])\n\n const ctx = useMemo<InkContext>(\n () => ({\n assets,\n document,\n status,\n annotations: annotationList,\n selection,\n viewport,\n tools,\n tool: internalTool,\n setTool,\n zoomModel: zoom,\n pageModel: page,\n reportZoom,\n reportPage,\n activated,\n setActivated,\n history: inkHistory,\n rootEl,\n setViewport,\n }),\n [\n assets,\n document,\n status,\n annotationList,\n selection,\n viewport,\n tools,\n internalTool,\n setTool,\n zoom,\n page,\n reportZoom,\n reportPage,\n activated,\n setActivated,\n inkHistory,\n rootEl,\n setViewport,\n ]\n )\n\n const Comp = asChild ? Slot.Root : 'div'\n return (\n <InkContextObject.Provider value={ctx}>\n <Comp ref={setRootEl} data-ink-root=\"\" data-state={status.state} {...rest}>\n {typeof children === 'function' ? children({ status, document }) : children}\n </Comp>\n </InkContextObject.Provider>\n )\n}\n","/** Joins class names, dropping empties. */\nexport function cx(...parts: (string | undefined | false)[]): string | undefined {\n const out = parts.filter(Boolean).join(' ')\n return out === '' ? undefined : out\n}\n","/*\n * Slot props for one annotation. It renders only its children: the overlay already draws the\n * default visual for every annotation that is not custom, so this never draws a second one.\n * InkPage portals it into the annotation's overlay element.\n */\nimport { acceptSuggestion } from '@inkbar/core'\nimport { useEffect, useMemo, useState, type ReactNode } from 'react'\n\nimport { useInkContext } from '../context'\n\nimport type { Annotation } from '@inkbar/core'\nimport type { AnnotationSlotProps, AnnotationState } from '@inkbar/core/dom'\n\nexport interface InkAnnotationProps {\n annotation: Annotation\n /** The overlay element; its `data-state` (which includes hover) drives `state`. */\n element?: HTMLElement | undefined\n children: (props: AnnotationSlotProps) => ReactNode\n}\n\nfunction readState(el: HTMLElement): AnnotationState | null {\n const s = el.dataset.state\n return s === 'idle' || s === 'hover' || s === 'selected' ? s : null\n}\n\nexport function InkAnnotation({ annotation, element, children }: InkAnnotationProps) {\n const ctx = useInkContext('InkAnnotation')\n const [observed, setObserved] = useState<AnnotationState | null>(() =>\n element ? readState(element) : null\n )\n useEffect(() => {\n if (!element) {\n setObserved(null)\n return\n }\n setObserved(readState(element))\n const observer = new MutationObserver(() => setObserved(readState(element)))\n observer.observe(element, { attributes: true, attributeFilter: ['data-state'] })\n return () => observer.disconnect()\n }, [element])\n\n const { id } = annotation\n const isSuggestion = annotation.type === 'redact' && annotation.origin === 'suggested'\n const locked = annotation.locked === true\n const selected = ctx.selection.includes(id)\n const store = ctx.document?.annotations\n const slotProps = useMemo<AnnotationSlotProps>(\n () => ({\n annotation,\n state: observed ?? (selected ? 'selected' : 'idle'),\n locked,\n select: () => store?.select([id]),\n remove: () => void store?.remove(id),\n accept: () => {\n if (store && isSuggestion) acceptSuggestion(store, id)\n },\n dismiss: () => {\n if (isSuggestion) store?.remove(id)\n },\n }),\n [annotation, observed, selected, locked, store, id, isSuggestion]\n )\n return <>{children(slotProps)}</>\n}\n","/*\n * One page the viewer engine mounted. Renders nothing in place; portals go into the host\n * (page error) and into each annotation's overlay element (custom annotations).\n *\n * The overlay creates and removes those elements as the annotation list changes, outside\n * React. So the portal targets come from a list read after every overlay render: this\n * component subscribes to the store after the overlay does (the engine created the mount\n * first), and core notifies subscribers in order, so the elements already exist when the list\n * arrives here.\n *\n * The engine tracks page errors and sets `data-state=\"error\"` on the host; this component\n * portals the page-error slot into it while `error` is set.\n */\nimport { useEffect, useState, type ReactNode } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { useInkContext } from '../context'\n\nimport { InkAnnotation } from './InkAnnotation'\n\nimport type { Annotation, InkError } from '@inkbar/core'\nimport type { AnnotationSlotProps, PageMount } from '@inkbar/core/dom'\n\nexport interface InkPageProps {\n page: number\n host: HTMLElement\n /** The engine's page mount in `host`. */\n mount: PageMount\n /** The engine's error for this page, `null` while it renders. */\n error: InkError | null\n /** Fixed for the life of the mount: the engine rebuilds when it changes. */\n customAnnotations?: boolean\n renderAnnotation?: ((props: AnnotationSlotProps) => ReactNode) | undefined\n renderPageError?: ((props: { error: InkError; page: number }) => ReactNode) | undefined\n}\n\ninterface Target {\n annotation: Annotation\n el: HTMLElement\n}\n\nfunction sameTargets(a: readonly Target[], b: readonly Target[]): boolean {\n return (\n a.length === b.length &&\n a.every((t, i) => t.annotation === b[i]!.annotation && t.el === b[i]!.el)\n )\n}\n\nexport function InkPage({\n page,\n host,\n mount,\n error,\n customAnnotations = false,\n renderAnnotation,\n renderPageError,\n}: InkPageProps) {\n const doc = useInkContext('InkPage').document\n const [targets, setTargets] = useState<Target[]>([])\n\n useEffect(() => {\n if (!doc || !customAnnotations) return\n const read = (): void => {\n const next = doc.annotations.byPage(page).flatMap((annotation) => {\n const el = mount.overlay.elementFor(annotation.id)\n return el ? [{ annotation, el }] : []\n })\n // A change elsewhere in the document leaves this page's targets as they were.\n setTargets((prev) => (sameTargets(prev, next) ? prev : next))\n }\n const stop = doc.annotations.list.subscribe(read)\n read()\n return () => {\n stop()\n setTargets([])\n }\n }, [doc, page, mount, customAnnotations])\n\n return (\n <>\n {error\n ? createPortal(\n <div className=\"ink-page-error\" data-ink-page-error=\"\" role=\"alert\">\n {renderPageError ? (\n renderPageError({ error, page })\n ) : (\n <>\n <p>Page {page + 1} could not be shown.</p>\n <code className=\"ink-error-code\">{error.code}</code>\n </>\n )}\n </div>,\n host\n )\n : null}\n {renderAnnotation\n ? targets.map((t) =>\n createPortal(\n <InkAnnotation annotation={t.annotation} element={t.el}>\n {renderAnnotation}\n </InkAnnotation>,\n t.el,\n t.annotation.id\n )\n )\n : null}\n </>\n )\n}\n","/*\n * The scroll element is handed to core's `mountViewer`, which builds the viewport, the page\n * layers, the tool controller and the keyboard shortcuts in it; React never renders children\n * into it. The engine reports each page host it mounts, and InkPage components rendered here\n * portal the page-error and custom-annotation slots into them.\n *\n * Two-way zoom and page: the viewport's own changes are reported through the context, and\n * the host's props are applied only when they differ from the viewport's state, so the echo\n * of a reported value does nothing.\n */\nimport { mountViewer } from '@inkbar/core/dom'\nimport {\n useEffect,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type ReactNode,\n} from 'react'\n\nimport { cx } from '../class-names'\nimport { useInkContext } from '../context'\nimport { useLatest } from '../use-latest'\n\nimport { InkPage } from './InkPage'\n\nimport type { InkError } from '@inkbar/core'\nimport type {\n AnnotationSlotProps,\n LayoutMode,\n PageMount,\n ViewerEngine,\n ViewRotation,\n ZoomValue,\n} from '@inkbar/core/dom'\n\nexport interface InkViewportProps extends ComponentPropsWithoutRef<'div'> {\n mode?: LayoutMode\n rotation?: ViewRotation\n /** Gap between pages, CSS px. */\n gap?: number\n /** Pages kept mounted either side of the visible ones. */\n buffer?: number\n loading?: ReactNode\n empty?: ReactNode\n error?: ReactNode | ((props: { error: InkError }) => ReactNode)\n renderAnnotation?: ((props: AnnotationSlotProps) => ReactNode) | undefined\n /** Shown inside a page that failed to render. The rest of the document stays usable. */\n renderPageError?: ((props: { error: InkError; page: number }) => ReactNode) | undefined\n}\n\ninterface MountedPage {\n /** The engine build the host belongs to; part of the InkPage key. */\n build: number\n page: number\n host: HTMLElement\n mount: PageMount\n error: InkError | null\n /** Whether the build that mounted the page renders the annotation slot. */\n custom: boolean\n}\n\nexport function InkViewport({\n mode = 'continuous',\n rotation = 0,\n gap = 16,\n buffer = 2,\n loading,\n empty,\n error,\n renderAnnotation,\n renderPageError,\n className,\n ...rest\n}: InkViewportProps) {\n const ctx = useInkContext('InkViewport')\n const scroll = useRef<HTMLDivElement>(null)\n const custom = !!renderAnnotation\n const latest = useLatest({ ctx, mode, rotation, gap, buffer, custom })\n\n const engine = useRef<ViewerEngine | null>(null)\n /** Page hosts, mounts and errors the engine reported; InkPage renders portals for them. */\n const [pages, setPages] = useState<MountedPage[]>([])\n /**\n * Numbered before each build starts, so the pages a build mounts carry its own number. A\n * rebuild gives each page a new host and mount, so pages from an earlier build must remount,\n * not be reused.\n */\n const buildCount = useRef(0)\n /** The construction options the engine was last built with, so a rebuild runs only on a change. */\n const builtWith = useRef<{ gap: number; buffer: number; custom: boolean } | null>(null)\n /** The zoom and page last reported to the host. */\n const lastReportedZoom = useRef<ZoomValue | undefined>(undefined)\n const lastReportedPage = useRef<number | undefined>(undefined)\n\n // Build for a new document or status; tear down on the next change and on unmount.\n useEffect(() => {\n const { ctx: c, mode: m, rotation: r, gap: g, buffer: b, custom: cu } = latest.current\n const doc = c.document\n const el = scroll.current\n lastReportedZoom.current = undefined\n lastReportedPage.current = undefined\n if (!doc || !el || c.status.state !== 'ready') return\n let first = true\n let stops: (() => void)[] = []\n buildCount.current += 1\n builtWith.current = { gap: g, buffer: b, custom: cu }\n const e = mountViewer({\n container: el,\n document: doc,\n zoom: c.zoomModel ?? 'fit-width',\n ...(c.pageModel === undefined ? {} : { page: c.pageModel }),\n mode: m,\n rotation: r,\n gap: g,\n buffer: b,\n tool: c.tool,\n customAnnotations: cu,\n onActivate: (id) => latest.current.ctx.setActivated(id),\n onBuild: (vp, tc) => {\n latest.current.ctx.setViewport(vp, tc)\n if (first) {\n // A new document starts from where the viewport opens (its zoom, on the first page);\n // only later changes are reported, the restored page among them.\n first = false\n lastReportedZoom.current = vp.zoom.get()\n lastReportedPage.current = 0\n }\n for (const stop of stops) stop()\n const reportZoom = (z: ZoomValue): void => {\n if (z === lastReportedZoom.current) return\n lastReportedZoom.current = z\n latest.current.ctx.reportZoom(z)\n }\n const reportPage = (p: number): void => {\n if (p === lastReportedPage.current) return\n lastReportedPage.current = p\n latest.current.ctx.reportPage(p)\n }\n stops = [vp.zoom.subscribe(reportZoom), vp.currentPage.subscribe(reportPage)]\n // Whatever the build restored is reported once; nothing is when it matched.\n reportZoom(vp.zoom.get())\n reportPage(vp.currentPage.get())\n },\n onPageMount: (page, mount, host) => {\n // `buildCount` and `builtWith` belong to the build in progress: both are set before it starts.\n const build = buildCount.current\n const custom = builtWith.current?.custom ?? false\n setPages((prev) => [...prev, { build, page, host, mount, error: null, custom }])\n },\n onPageUnmount: (page) => setPages((prev) => prev.filter((p) => p.page !== page)),\n onPageError: (page, err) =>\n setPages((prev) => prev.map((p) => (p.page === page ? { ...p, error: err } : p))),\n })\n engine.current = e\n return () => {\n for (const stop of stops) stop()\n e.destroy()\n engine.current = null\n builtWith.current = null\n c.setViewport(null, null)\n setPages((prev) => (prev.length === 0 ? prev : []))\n }\n }, [ctx.document, ctx.status.state, latest])\n\n // Construction-only options rebuild the engine for the same document, keeping zoom and page.\n useEffect(() => {\n const built = builtWith.current\n if (!engine.current || !built) return\n if (built.gap === gap && built.buffer === buffer && built.custom === custom) return\n buildCount.current += 1\n builtWith.current = { gap, buffer, custom }\n engine.current.rebuild({ gap, buffer, customAnnotations: custom })\n }, [gap, buffer, custom])\n\n useEffect(() => {\n const vp = engine.current?.viewport\n const z = ctx.zoomModel\n if (vp && z !== undefined && z !== vp.zoom.get()) vp.setZoom(z)\n }, [ctx.zoomModel])\n useEffect(() => {\n const vp = engine.current?.viewport\n const p = ctx.pageModel\n if (!vp || p === undefined || p === lastReportedPage.current) return\n if (p !== vp.currentPage.get()) vp.scrollToPage(p)\n }, [ctx.pageModel])\n useEffect(() => {\n const tc = engine.current?.tools\n if (tc && tc.active.get() !== ctx.tool) tc.set(ctx.tool)\n }, [ctx.tool])\n // The build applied both; these only act on a later change, not on mount.\n useEffect(() => {\n const vp = engine.current?.viewport\n if (vp && vp.mode.get() !== mode) vp.setMode(mode)\n }, [mode])\n useEffect(() => {\n const vp = engine.current?.viewport\n if (vp && vp.rotation.get() !== rotation) vp.setRotation(rotation)\n }, [rotation])\n\n const state = ctx.status.state\n const err = ctx.status.state === 'error' ? ctx.status.error : null\n\n return (\n <div\n {...rest}\n className={cx('ink-viewport-root', className)}\n data-ink-viewport-root=\"\"\n data-state={state}\n >\n {state === 'loading' ? (\n <div className=\"ink-status\" role=\"status\" aria-live=\"polite\">\n {loading === undefined ? 'Loading document…' : loading}\n </div>\n ) : err ? (\n <div className=\"ink-status ink-error\" role=\"alert\">\n {typeof error === 'function' ? (\n error({ error: err })\n ) : error !== undefined ? (\n error\n ) : (\n <>\n <p className=\"ink-error-title\">This document could not be opened.</p>\n {/* The message comes from the PDF engine and is not written for readers: it stays\n off the page, on the code's tooltip. */}\n <p>\n <code className=\"ink-error-code\" title={err.message}>\n {err.code}\n </code>\n </p>\n </>\n )}\n </div>\n ) : state === 'idle' ? (\n <div className=\"ink-status ink-empty\">{empty}</div>\n ) : null}\n <div\n ref={scroll}\n className=\"ink-scroll\"\n data-ink-scroll=\"\"\n tabIndex={0}\n role=\"document\"\n aria-label=\"Document\"\n />\n {pages.map((p) => (\n <InkPage\n key={`${p.build}:${p.page}`}\n page={p.page}\n host={p.host}\n mount={p.mount}\n error={p.error}\n customAnnotations={p.custom}\n renderAnnotation={renderAnnotation}\n renderPageError={renderPageError}\n />\n ))}\n </div>\n )\n}\n","import { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\n\nimport type { ComponentPropsWithoutRef } from 'react'\n\nexport interface InkToolbarProps extends Omit<ComponentPropsWithoutRef<'div'>, 'dir'> {\n /** Radix narrows text direction to these two values. */\n dir?: 'ltr' | 'rtl'\n label?: string\n asChild?: boolean\n}\n\nexport function InkToolbar({\n label = 'Document tools',\n asChild = false,\n className,\n children,\n ...rest\n}: InkToolbarProps) {\n return (\n <Toolbar.Root\n asChild={asChild}\n orientation=\"horizontal\"\n aria-label={label}\n data-ink-toolbar=\"\"\n className={cx('ink-toolbar', className)}\n {...rest}\n >\n {children}\n </Toolbar.Root>\n )\n}\n","/*\n * An icon from `@inkbar/icons`, hidden from assistive technology: the control it sits in\n * carries the name. The theme sizes it with `--ink-icon-size`.\n */\nimport { ICON_ATTRIBUTES } from '@inkbar/icons'\nimport { createElement, type SVGProps } from 'react'\n\nimport type { IconNode } from '@inkbar/icons'\n\nexport interface InkIconProps {\n icon: IconNode\n size?: number\n}\n\n/** `stroke-width` to `strokeWidth`: React names SVG attributes in camelCase. */\nconst camel = (name: string) =>\n name.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase())\n\nconst SVG_ATTRIBUTES = Object.fromEntries(\n Object.entries(ICON_ATTRIBUTES).map(([k, v]) => [camel(k), v])\n) as SVGProps<SVGSVGElement>\n\nexport function InkIcon({ icon, size = 18 }: InkIconProps) {\n return (\n <svg\n {...SVG_ATTRIBUTES}\n width={size}\n height={size}\n className=\"ink-icon\"\n aria-hidden=\"true\"\n >\n {icon.map(([tag, attrs], i) => createElement(tag, { key: i, ...attrs }))}\n </svg>\n )\n}\n","import { TOOL_LABELS, type ToolId } from '@inkbar/core/dom'\nimport { Hand, Highlighter, MessageSquare, MousePointer2, Square } from '@inkbar/icons'\nimport { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { useTool } from '../hooks/useTool'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { IconNode } from '@inkbar/icons'\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react'\n\nconst ICONS: Readonly<Record<ToolId, IconNode>> = {\n view: Hand,\n select: MousePointer2,\n highlight: Highlighter,\n 'redact-area': Square,\n note: MessageSquare,\n}\n\nexport interface InkToolButtonProps extends Omit<\n ComponentPropsWithoutRef<'button'>,\n 'children'\n> {\n tool: ToolId\n label?: string | undefined\n asChild?: boolean\n children?: ReactNode | ((props: { active: boolean; label: string }) => ReactNode)\n}\n\nexport function InkToolButton({\n tool,\n label,\n asChild = false,\n className,\n children,\n onClick,\n ...rest\n}: InkToolButtonProps) {\n const { tool: current, setTool } = useTool()\n const active = current === tool\n const name = label ?? TOOL_LABELS[tool]\n return (\n <Toolbar.Button\n asChild={asChild}\n className={cx('ink-tool-button', className)}\n data-ink-tool-button=\"\"\n data-tool={tool}\n data-state={active ? 'on' : 'off'}\n aria-pressed={active}\n aria-label={name}\n title={name}\n onClick={(e) => {\n onClick?.(e)\n if (!e.defaultPrevented) setTool(tool)\n }}\n {...rest}\n >\n {typeof children === 'function'\n ? children({ active, label: name })\n : (children ?? <InkIcon icon={ICONS[tool]} />)}\n </Toolbar.Button>\n )\n}\n","import { cx } from '../class-names'\n\nimport type { ComponentPropsWithoutRef } from 'react'\n\nexport type InkToolbarSeparatorProps = ComponentPropsWithoutRef<'div'>\n\n/**\n * A divider between groups of controls in a horizontal toolbar. Not focusable. A plain div\n * rather than Radix's separator, which reads as horizontal inside a horizontal toolbar.\n */\nexport function InkToolbarSeparator({ className, ...rest }: InkToolbarSeparatorProps) {\n return (\n <div\n role=\"separator\"\n aria-orientation=\"vertical\"\n className={cx('ink-toolbar-separator', className)}\n data-ink-toolbar-separator=\"\"\n {...rest}\n />\n )\n}\n","import { Undo2 } from '@inkbar/icons'\nimport { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { useHistory } from '../hooks/useHistory'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { InkHistoryButtonProps } from './history-button'\n\nexport function InkUndo({\n asChild = false,\n className,\n children,\n disabled,\n onClick,\n ...rest\n}: InkHistoryButtonProps) {\n const { canUndo, undo } = useHistory()\n return (\n <Toolbar.Button\n asChild={asChild}\n className={cx('ink-undo', className)}\n data-ink-undo=\"\"\n aria-label=\"Undo\"\n title=\"Undo\"\n {...rest}\n disabled={disabled === true || !canUndo}\n onClick={(e) => {\n onClick?.(e)\n if (!e.defaultPrevented) undo()\n }}\n >\n {children ?? <InkIcon icon={Undo2} />}\n </Toolbar.Button>\n )\n}\n","import { Redo2 } from '@inkbar/icons'\nimport { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { useHistory } from '../hooks/useHistory'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { InkHistoryButtonProps } from './history-button'\n\nexport function InkRedo({\n asChild = false,\n className,\n children,\n disabled,\n onClick,\n ...rest\n}: InkHistoryButtonProps) {\n const { canRedo, redo } = useHistory()\n return (\n <Toolbar.Button\n asChild={asChild}\n className={cx('ink-redo', className)}\n data-ink-redo=\"\"\n aria-label=\"Redo\"\n title=\"Redo\"\n {...rest}\n disabled={disabled === true || !canRedo}\n onClick={(e) => {\n onClick?.(e)\n if (!e.defaultPrevented) redo()\n }}\n >\n {children ?? <InkIcon icon={Redo2} />}\n </Toolbar.Button>\n )\n}\n","import { ZoomIn } from '@inkbar/icons'\nimport { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { useZoom } from '../hooks/useZoom'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { InkZoomButtonProps } from './zoom-button'\n\nexport function InkZoomIn({\n asChild = false,\n className,\n children,\n onClick,\n ...rest\n}: InkZoomButtonProps) {\n const { zoomIn } = useZoom()\n return (\n <Toolbar.Button\n asChild={asChild}\n className={cx('ink-zoom-in', className)}\n data-ink-zoom-in=\"\"\n aria-label=\"Zoom in\"\n title=\"Zoom in\"\n {...rest}\n onClick={(e) => {\n onClick?.(e)\n if (!e.defaultPrevented) zoomIn()\n }}\n >\n {children ?? <InkIcon icon={ZoomIn} />}\n </Toolbar.Button>\n )\n}\n","import { ZoomOut } from '@inkbar/icons'\nimport { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { useZoom } from '../hooks/useZoom'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { InkZoomButtonProps } from './zoom-button'\n\nexport function InkZoomOut({\n asChild = false,\n className,\n children,\n onClick,\n ...rest\n}: InkZoomButtonProps) {\n const { zoomOut } = useZoom()\n return (\n <Toolbar.Button\n asChild={asChild}\n className={cx('ink-zoom-out', className)}\n data-ink-zoom-out=\"\"\n aria-label=\"Zoom out\"\n title=\"Zoom out\"\n {...rest}\n onClick={(e) => {\n onClick?.(e)\n if (!e.defaultPrevented) zoomOut()\n }}\n >\n {children ?? <InkIcon icon={ZoomOut} />}\n </Toolbar.Button>\n )\n}\n","import { ZOOM_LEVELS, type ZoomValue } from '@inkbar/core/dom'\nimport { Check, ChevronDown } from '@inkbar/icons'\nimport { Select } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { useZoom } from '../hooks/useZoom'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { ComponentPropsWithoutRef } from 'react'\n\nconst CUSTOM = 'custom:'\nconst level = (z: number) => ZOOM_LEVELS.find((l) => Math.abs(l - z) < 0.001)\nconst percent = (z: number) => `${Math.round(z * 100)}%`\n\nconst FITS = [\n { value: 'fit-width', label: 'Fit width' },\n { value: 'fit-page', label: 'Fit page' },\n]\n\n/** Props of the select's trigger button; the options come from the zoom levels. */\nexport type InkZoomSelectProps = Omit<\n ComponentPropsWithoutRef<typeof Select.Trigger>,\n 'children' | 'asChild'\n>\n\nfunction Item({ value, label }: { value: string; label: string }) {\n return (\n <Select.Item value={value} className=\"ink-select-item\" data-ink-select-item=\"\">\n <Select.ItemText>{label}</Select.ItemText>\n <Select.ItemIndicator className=\"ink-select-indicator\">\n <InkIcon icon={Check} size={16} />\n </Select.ItemIndicator>\n </Select.Item>\n )\n}\n\nexport function InkZoomSelect({ className, ...rest }: InkZoomSelectProps) {\n const { zoom, scale, setZoom } = useZoom()\n /** A numeric zoom that is not one of the levels (zoom in and out multiply). */\n const custom = typeof zoom === 'number' && level(zoom) === undefined ? zoom : null\n const value =\n typeof zoom !== 'number'\n ? zoom\n : custom === null\n ? String(level(zoom))\n : `${CUSTOM}${zoom}`\n /** The levels, with a custom zoom in its place among them. */\n const levels = ZOOM_LEVELS.map((l) => ({ z: l, value: String(l), label: percent(l) }))\n if (custom !== null)\n levels.push({ z: custom, value: `${CUSTOM}${custom}`, label: percent(scale) })\n levels.sort((a, b) => a.z - b.z)\n\n function onValueChange(v: string): void {\n if (v === value) return\n const next: ZoomValue =\n v === 'fit-width' || v === 'fit-page' ? v : Number(v.replace(CUSTOM, ''))\n setZoom(next)\n }\n return (\n <Select.Root value={value} onValueChange={onValueChange}>\n <Select.Trigger\n className={cx('ink-zoom-select ink-select-trigger', className)}\n data-ink-zoom-select=\"\"\n aria-label=\"Zoom\"\n {...rest}\n >\n <Select.Value className=\"ink-select-value\" />\n <Select.Icon className=\"ink-select-icon\">\n <InkIcon icon={ChevronDown} size={16} />\n </Select.Icon>\n </Select.Trigger>\n <Select.Portal>\n <Select.Content\n className=\"ink-select-content\"\n data-ink-select-content=\"\"\n position=\"popper\"\n side=\"top\"\n sideOffset={4}\n >\n <Select.Viewport>\n {FITS.map((o) => (\n <Item key={o.value} value={o.value} label={o.label} />\n ))}\n <Select.Separator className=\"ink-select-separator\" />\n {levels.map((o) => (\n <Item key={o.value} value={o.value} label={o.label} />\n ))}\n </Select.Viewport>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n )\n}\n","import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type KeyboardEvent,\n} from 'react'\n\nimport { cx } from '../class-names'\nimport { usePage } from '../hooks/usePage'\nimport { useLatest } from '../use-latest'\n\nexport type InkPageInputProps = Omit<\n ComponentPropsWithoutRef<'input'>,\n 'value' | 'onChange' | 'type' | 'min' | 'max'\n>\n\nexport function InkPageInput({\n className,\n onKeyDown: onKeyDownProp,\n ...rest\n}: InkPageInputProps) {\n const { current, count, goTo } = usePage()\n const [draft, setDraft] = useState(String(current + 1))\n useEffect(() => {\n setDraft(String(current + 1))\n }, [current])\n const input = useRef<HTMLInputElement>(null)\n const latest = useLatest({ current, count, goTo })\n\n /** 1-based in the input, 0-based in the viewport. Out of range resets to the current page. */\n const commit = useCallback(\n (value: string) => {\n const { current: page, count: total, goTo: go } = latest.current\n const n = Number(value)\n if (Number.isInteger(n) && n >= 1 && n <= total) {\n if (n - 1 !== page) go(n - 1)\n } else setDraft(String(page + 1))\n },\n [latest]\n )\n // The native `change` event fires when an edit is committed: on blur after typing, and on\n // each step of the spinner or the arrow keys. React's `onChange` is the `input` event, which\n // fires for every keystroke, so the commit listens to the DOM event itself.\n useEffect(() => {\n const el = input.current\n if (!el) return\n const onNativeChange = (): void => commit(el.value)\n el.addEventListener('change', onNativeChange)\n return () => el.removeEventListener('change', onNativeChange)\n }, [commit])\n\n function onKeyDown(e: KeyboardEvent<HTMLInputElement>): void {\n onKeyDownProp?.(e)\n if (e.defaultPrevented || e.key !== 'Enter') return\n e.preventDefault()\n commit(draft)\n }\n return (\n <input\n ref={input}\n className={cx('ink-page-input', className)}\n data-ink-page-input=\"\"\n type=\"number\"\n inputMode=\"numeric\"\n aria-label=\"Page\"\n min={1}\n max={count}\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={onKeyDown}\n {...rest}\n />\n )\n}\n","import { cx } from '../class-names'\nimport { usePage } from '../hooks/usePage'\n\nimport type { ComponentPropsWithoutRef } from 'react'\n\nexport function InkPageCount({ className, ...rest }: ComponentPropsWithoutRef<'span'>) {\n const { count } = usePage()\n return (\n <span\n className={cx('ink-page-count', className)}\n data-ink-page-count=\"\"\n aria-live=\"polite\"\n {...rest}\n >\n {`of ${count}`}\n </span>\n )\n}\n","import { ChevronLeft } from '@inkbar/icons'\nimport { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { usePage } from '../hooks/usePage'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { InkPageButtonProps } from './page-button'\n\nexport function InkPrevPage({\n asChild = false,\n className,\n children,\n disabled,\n onClick,\n ...rest\n}: InkPageButtonProps) {\n const { current, previous } = usePage()\n return (\n <Toolbar.Button\n asChild={asChild}\n className={cx('ink-prev-page', className)}\n data-ink-prev-page=\"\"\n aria-label=\"Previous page\"\n title=\"Previous page\"\n disabled={disabled === true || current <= 0}\n {...rest}\n onClick={(e) => {\n onClick?.(e)\n if (!e.defaultPrevented) previous()\n }}\n >\n {children ?? <InkIcon icon={ChevronLeft} />}\n </Toolbar.Button>\n )\n}\n","import { ChevronRight } from '@inkbar/icons'\nimport { Toolbar } from 'radix-ui'\n\nimport { cx } from '../class-names'\nimport { usePage } from '../hooks/usePage'\n\nimport { InkIcon } from './InkIcon'\n\nimport type { InkPageButtonProps } from './page-button'\n\nexport function InkNextPage({\n asChild = false,\n className,\n children,\n disabled,\n onClick,\n ...rest\n}: InkPageButtonProps) {\n const { current, count, next } = usePage()\n return (\n <Toolbar.Button\n asChild={asChild}\n className={cx('ink-next-page', className)}\n data-ink-next-page=\"\"\n aria-label=\"Next page\"\n title=\"Next page\"\n disabled={disabled === true || current >= count - 1}\n {...rest}\n onClick={(e) => {\n onClick?.(e)\n if (!e.defaultPrevented) next()\n }}\n >\n {children ?? <InkIcon icon={ChevronRight} />}\n </Toolbar.Button>\n )\n}\n","import { observeAnnotationElement } from '@inkbar/core/dom'\nimport { useEffect, useState } from 'react'\n\n/**\n * The overlay element core draws for an annotation, for anchoring a popover to it. Core\n * creates and removes these elements outside React, so this follows the root's subtree while\n * an id is wanted.\n */\nexport function useAnnotationElement(\n root: HTMLElement | null,\n id: string | null\n): HTMLElement | null {\n const [element, setElement] = useState<HTMLElement | null>(null)\n useEffect(() => {\n if (!root || !id) {\n setElement(null)\n return\n }\n return observeAnnotationElement(root, id, setElement)\n }, [root, id])\n return element\n}\n","import {\n createFocusReturn,\n shouldKeepOpenOnAnnotation,\n type FocusReturn,\n} from '@inkbar/core/dom'\nimport { useMemo } from 'react'\n\nimport { useLatest } from '../use-latest'\n\nimport type { InkContext } from '../context'\n\nexport type { FocusReturn }\n\n/** Radix's `onInteractOutside` handler: a press that will activate an annotation keeps the popover open. */\nexport function keepOpenOnAnnotation(event: CustomEvent<{ originalEvent: Event }>): void {\n if (shouldKeepOpenOnAnnotation(event.detail.originalEvent.target))\n event.preventDefault()\n}\n\nexport function useFocusReturn(ctx: InkContext): FocusReturn {\n const latest = useLatest(ctx)\n return useMemo(\n () =>\n createFocusReturn({\n root: () => latest.current.rootEl,\n activated: () => latest.current.activated,\n }),\n [latest]\n )\n}\n","/*\n * The thread for the activated note, anchored to the note's overlay element. Activating a\n * reply opens the whole thread from its root. Closing (Close, Escape, a press outside) clears\n * `activated`.\n *\n * A new note has no text. While its root is empty (and unlocked) the default form writes the\n * root's own `contents`, labelled \"Comment\", and the thread list stays hidden until there is\n * something in it; after that the form adds replies. Closing a root that is still empty and\n * has no replies removes it, so an abandoned note does not stay on the page.\n */\nimport { isAbandonedNote, threadOf, threadRoot } from '@inkbar/core'\nimport { Popover } from 'radix-ui'\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n type FormEvent,\n type ReactNode,\n} from 'react'\n\nimport { useInkContext } from '../context'\nimport { useAnnotations } from '../hooks/useAnnotations'\nimport { useLatest } from '../use-latest'\n\nimport { useAnnotationElement } from './annotation-element'\nimport { keepOpenOnAnnotation, useFocusReturn } from './popover-focus'\n\nimport type { Annotation, NoteAnnotation } from '@inkbar/core'\nimport type { NotePopoverSlotProps } from '@inkbar/core/dom'\n\nexport interface InkNotePopoverProps {\n children?: ((props: NotePopoverSlotProps) => ReactNode) | undefined\n}\n\nexport function InkNotePopover({ children }: InkNotePopoverProps) {\n const ctx = useInkContext('InkNotePopover')\n const { annotations, add, update, remove } = useAnnotations()\n\n const note = useMemo<NoteAnnotation | null>(() => {\n const a = ctx.activated ? annotations.find((x) => x.id === ctx.activated) : undefined\n return a?.type === 'text' ? threadRoot(annotations, a) : null\n }, [annotations, ctx.activated])\n const anchor = useAnnotationElement(ctx.rootEl, note?.id ?? null)\n const anchorRef = useMemo(() => ({ current: anchor }), [anchor])\n const focusReturn = useFocusReturn(ctx)\n const open = note !== null && anchor !== null\n /** The root, then every reply below it, depth first, each level in creation order. */\n const thread = useMemo<Annotation[]>(\n () => (note ? threadOf(annotations, note) : []),\n [annotations, note]\n )\n /** True while the default form writes the root note's own text rather than a reply. */\n const editingRoot = note !== null && !note.locked && !note.contents?.trim()\n\n /**\n * Notes this popover wrote text or a reply for. In controlled mode the write is a proposal\n * the host may not have applied yet, so the applied list still shows the note empty; these\n * are never dropped as abandoned.\n */\n const written = useRef(new Set<string>())\n /** Notes this popover has already asked to remove, so a slow host is asked once. */\n const dropped = useRef(new Set<string>())\n const latest = useLatest({ annotations, remove })\n\n function dropIfEmpty(id: string): boolean {\n if (\n dropped.current.has(id) ||\n written.current.has(id) ||\n !isAbandonedNote(latest.current.annotations, id)\n )\n return false\n dropped.current.add(id)\n latest.current.remove(id)\n return true\n }\n\n // Activation moved on from a note that never got any text: drop it.\n const noteId = note?.id\n const previousId = useRef<string | undefined>(undefined)\n useEffect(() => {\n const previous = previousId.current\n if (previous === noteId) return\n previousId.current = noteId\n if (previous !== undefined) dropIfEmpty(previous)\n // dropIfEmpty reads through `latest`; it is stable for the effect's purposes.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [noteId])\n\n function reply(text: string): void {\n const root = note\n const contents = text.trim()\n if (!root || !contents) return\n written.current.add(root.id)\n add({ type: 'text', page: root.page, rect: root.rect, contents, inReplyTo: root.id })\n }\n function isEmptyRoot(root: NoteAnnotation): boolean {\n return (\n !written.current.has(root.id) &&\n !root.locked &&\n !root.contents?.trim() &&\n thread.length === 1\n )\n }\n function close(): void {\n const root = note\n if (root && annotations.some((a) => a.id === root.id) && isEmptyRoot(root)) {\n focusReturn.beforeRemove(anchor)\n dropIfEmpty(root.id)\n }\n ctx.setActivated(null)\n }\n function updateContents(contents: string): void {\n if (!note || note.locked) return\n if (contents.trim()) written.current.add(note.id)\n update(note.id, { contents })\n }\n /** Locked notes cannot be removed: removing one does nothing and keeps the popover. */\n function removeThread(): void {\n const root = note\n if (!root || root.locked) return\n focusReturn.beforeRemove(anchor)\n // Under a slow controlled host the note stays listed for a while; it is not asked for again.\n dropped.current.add(root.id)\n remove(root.id)\n ctx.setActivated(null)\n }\n\n return (\n <Popover.Root open={open} onOpenChange={(next) => !next && close()}>\n <Popover.Anchor virtualRef={anchorRef} />\n <Popover.Portal>\n {note && anchor ? (\n <Popover.Content\n className=\"ink-note-popover\"\n data-ink-note-popover=\"\"\n side=\"right\"\n sideOffset={8}\n collisionPadding={8}\n aria-label=\"Note thread\"\n onInteractOutside={keepOpenOnAnnotation}\n onCloseAutoFocus={(e) => focusReturn.onCloseAutoFocus(e, anchor)}\n >\n {children ? (\n children({\n note,\n replies: thread.slice(1),\n reply,\n update: updateContents,\n remove: removeThread,\n close,\n })\n ) : (\n <>\n {!editingRoot || thread.length > 1 ? (\n <ol className=\"ink-thread\" data-ink-thread=\"\">\n {thread.map((item) => (\n <li\n key={item.id}\n className=\"ink-thread-item\"\n data-ink-thread-item=\"\"\n data-reply={item.inReplyTo ? '' : undefined}\n >\n <span className=\"ink-thread-author\">\n {item.author ?? 'Anonymous'}\n </span>\n <time className=\"ink-thread-time\" dateTime={item.createdAt}>\n {new Date(item.createdAt).toLocaleString()}\n </time>\n <p className=\"ink-thread-text\">{item.contents}</p>\n </li>\n ))}\n </ol>\n ) : null}\n <ThreadForm\n // Keyed by note: moving to another note starts with an empty draft at once.\n key={note.id}\n editingRoot={editingRoot}\n locked={!!note.locked}\n onSubmit={(text) => (editingRoot ? updateContents(text) : reply(text))}\n onRemove={removeThread}\n onClose={close}\n />\n </>\n )}\n </Popover.Content>\n ) : null}\n </Popover.Portal>\n </Popover.Root>\n )\n}\n\n/** The default form: the root note's own text while it is empty, replies after that. */\nfunction ThreadForm({\n editingRoot,\n locked,\n onSubmit,\n onRemove,\n onClose,\n}: {\n editingRoot: boolean\n locked: boolean\n onSubmit: (text: string) => void\n onRemove: () => void\n onClose: () => void\n}) {\n const [draft, setDraft] = useState('')\n function submit(e: FormEvent): void {\n e.preventDefault()\n const text = draft.trim()\n if (!text) return\n onSubmit(text)\n setDraft('')\n }\n return (\n <form className=\"ink-thread-reply\" data-ink-thread-reply=\"\" onSubmit={submit}>\n <textarea\n aria-label={editingRoot ? 'Comment' : 'Reply'}\n rows={2}\n placeholder={editingRoot ? 'Comment' : 'Reply'}\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n />\n <div className=\"ink-thread-actions\">\n <button type=\"submit\" disabled={!draft.trim()}>\n {editingRoot ? 'Comment' : 'Reply'}\n </button>\n {!locked ? (\n <button type=\"button\" onClick={onRemove}>\n Delete\n </button>\n ) : null}\n <button type=\"button\" onClick={onClose}>\n Close\n </button>\n </div>\n </form>\n )\n}\n","/*\n * Review card for a suggested redaction: opens when the activated annotation, or the only\n * selected one, is a redaction with `origin: 'suggested'`. Locked suggestions cannot be\n * dismissed, so they get no Dismiss button. A press on the overlay selects and activates, so a\n * click opens it whatever the tool. Closing clears `activated` and the selection.\n */\nimport { confidenceBucket } from '@inkbar/core'\nimport { Popover } from 'radix-ui'\nimport { useMemo, type ReactNode } from 'react'\n\nimport { useInkContext } from '../context'\nimport { useAnnotations } from '../hooks/useAnnotations'\n\nimport { useAnnotationElement } from './annotation-element'\nimport { keepOpenOnAnnotation, useFocusReturn } from './popover-focus'\n\nimport type { ConfidenceBucket, RedactAnnotation } from '@inkbar/core'\nimport type { SuggestionCardSlotProps } from '@inkbar/core/dom'\n\nexport interface InkSuggestionCardProps {\n children?: ((props: SuggestionCardSlotProps) => ReactNode) | undefined\n}\n\nexport function InkSuggestionCard({ children }: InkSuggestionCardProps) {\n const ctx = useInkContext('InkSuggestionCard')\n const {\n annotations,\n selection,\n accept: acceptId,\n dismiss: dismissId,\n select,\n } = useAnnotations()\n\n function suggestion(id: string | null | undefined): RedactAnnotation | null {\n const a = id ? annotations.find((x) => x.id === id) : undefined\n return a?.type === 'redact' && a.origin === 'suggested' ? a : null\n }\n // The activated annotation when it is a suggestion; otherwise the only selected one (a\n // marquee selects without activating).\n const target =\n suggestion(ctx.activated) ??\n (selection.length === 1 ? suggestion(selection[0]) : null)\n const anchor = useAnnotationElement(ctx.rootEl, target?.id ?? null)\n const anchorRef = useMemo(() => ({ current: anchor }), [anchor])\n const focusReturn = useFocusReturn(ctx)\n const open = target !== null && anchor !== null\n const bucket: ConfidenceBucket | undefined = target?.suggestion\n ? confidenceBucket(target.suggestion.confidence)\n : undefined\n\n function close(): void {\n ctx.setActivated(null)\n select([])\n }\n function accept(): void {\n if (target) acceptId(target.id)\n close()\n }\n /** Locked annotations cannot be removed: dismissing one does nothing and keeps the card. */\n function dismiss(): void {\n if (!target || target.locked) return\n focusReturn.beforeRemove(anchor, '[data-origin=\"suggested\"]')\n dismissId(target.id)\n close()\n }\n\n return (\n <Popover.Root open={open} onOpenChange={(next) => !next && close()}>\n <Popover.Anchor virtualRef={anchorRef} />\n <Popover.Portal>\n {target && anchor ? (\n <Popover.Content\n className=\"ink-suggestion-card\"\n data-ink-suggestion-card=\"\"\n side=\"bottom\"\n sideOffset={6}\n collisionPadding={8}\n aria-label=\"Suggested redaction\"\n onInteractOutside={keepOpenOnAnnotation}\n onCloseAutoFocus={(e) => focusReturn.onCloseAutoFocus(e, anchor)}\n >\n {children ? (\n children({\n annotation: target,\n suggestion: target.suggestion,\n bucket,\n accept,\n dismiss,\n close,\n })\n ) : (\n <>\n <p className=\"ink-suggestion-reason\">\n <strong>{target.suggestion?.reason ?? 'Suggested redaction'}</strong>\n {bucket ? (\n <span className=\"ink-suggestion-confidence\" data-confidence={bucket}>\n {bucket} confidence\n </span>\n ) : null}\n </p>\n {target.suggestion?.explanation ? (\n <p className=\"ink-suggestion-explanation\">\n {target.suggestion.explanation}\n </p>\n ) : null}\n <div className=\"ink-suggestion-actions\">\n <button type=\"button\" onClick={accept}>\n Accept\n </button>\n {!target.locked ? (\n <button type=\"button\" onClick={dismiss}>\n Dismiss\n </button>\n ) : null}\n </div>\n </>\n )}\n </Popover.Content>\n ) : null}\n </Popover.Portal>\n </Popover.Root>\n )\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inkbar/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "React components and hooks for Inkbar, the browser PDF viewer and editor.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://inkbar.dev",
|
|
@@ -24,18 +24,18 @@
|
|
|
24
24
|
"./package.json": "./package.json"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@inkbar/icons": "^0.
|
|
27
|
+
"@inkbar/icons": "^0.3.0",
|
|
28
28
|
"radix-ui": "^1.8.1"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@inkbar/core": "^0.
|
|
31
|
+
"@inkbar/core": "^0.3.0",
|
|
32
32
|
"react": "^19.0.0",
|
|
33
33
|
"react-dom": "^19.0.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@inkbar/core": "0.
|
|
36
|
+
"@inkbar/core": "0.3.0",
|
|
37
37
|
"@inkbar/fixtures": "0.0.0",
|
|
38
|
-
"@inkbar/theme": "0.
|
|
38
|
+
"@inkbar/theme": "0.3.0",
|
|
39
39
|
"@playwright/experimental-ct-react": "1.62.1",
|
|
40
40
|
"@playwright/test": "1.62.1",
|
|
41
41
|
"@types/react": "^19.3.0",
|