@fabrika/annotations 0.8.1 → 0.9.0-dev.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fabrika/annotations",
3
- "version": "0.8.1",
3
+ "version": "0.9.0-dev.2",
4
4
  "type": "module",
5
5
  "description": "React annotation state, text/block/region locators, editor and feedback surface.",
6
6
  "license": "MIT",
@@ -16,28 +16,29 @@
16
16
  "index.ts",
17
17
  "src",
18
18
  "!src/**/*.test.ts",
19
- "!src/**/*.test.tsx"
19
+ "!src/**/*.test.tsx",
20
+ "types"
20
21
  ],
21
22
  "exports": {
22
23
  ".": {
23
24
  "bun": "./index.ts",
24
- "types": "./index.ts",
25
+ "types": "./types/index.d.ts",
25
26
  "default": "./index.ts"
26
27
  },
27
28
  "./runtime": {
28
29
  "bun": "./src/runtime.ts",
29
- "types": "./src/runtime.ts",
30
+ "types": "./types/src/runtime.d.ts",
30
31
  "default": "./src/runtime.ts"
31
32
  },
32
33
  "./schemas": {
33
34
  "bun": "./src/schemas.ts",
34
- "types": "./src/schemas.ts",
35
+ "types": "./types/src/schemas.d.ts",
35
36
  "default": "./src/schemas.ts"
36
37
  },
37
38
  "./styles.css": "./src/styles.css",
38
39
  "./testing/dom.ts": {
39
40
  "bun": "./src/testing/dom.ts",
40
- "types": "./src/testing/dom.ts",
41
+ "types": "./types/src/testing/dom.d.ts",
41
42
  "default": "./src/testing/dom.ts"
42
43
  }
43
44
  },
@@ -0,0 +1,27 @@
1
+ export { AnnotationCtx, AnnotationHostContext, SessionContext, useAnnotationHost, useAnnotations } from '@fabrika/annotations/runtime';
2
+ export { extractContext, formatSnippetInContext } from './src/annotationContext';
3
+ export { ANNOTATABLE_SELECTOR, ANNOTATION_TARGETS, BLOCK_SELECTOR, describeSnippet, findAnnotationElement, findSnippetElement, getBlockSnippet, restoreAnnotationTargets, } from './src/annotationDom';
4
+ export { AnnotationDraftFooter } from './src/AnnotationDraftFooter';
5
+ export type { AnnotationDraftFooterProps } from './src/AnnotationDraftFooter';
6
+ export { AnnotationEditor, AttachButton, ImageThumbnails, imageToUrl } from './src/AnnotationEditor';
7
+ export { AnnotationList } from './src/AnnotationList';
8
+ export type { AnnotationListProps } from './src/AnnotationList';
9
+ export { renderAnnotation } from './src/annotationMarkdown';
10
+ export type { RenderableAnnotation } from './src/annotationMarkdown';
11
+ export { AnnotationProvider } from './src/AnnotationProvider';
12
+ export type { AnnotationProviderProps } from './src/AnnotationProvider';
13
+ export { sealTarget } from './src/annotationTarget';
14
+ export type { AnnotationTarget, SealedAnnotationTarget, TargetAnnotation } from './src/annotationTarget';
15
+ export { blockTarget } from './src/blockTarget';
16
+ export type { BlockLocator } from './src/blockTarget';
17
+ export { renameMarkId, restoreMarks, setMarkActive, unwrapMarks, updateAllMarkStates, wrapRangeWithMark } from './src/highlightRange';
18
+ export { AnnotationCreatePopover, AnnotationEditPopover, AnnotationPopover, Popover } from './src/Popover';
19
+ export { createRegionOverlay, describeRegion, findRegionHost, isDrawableRegion, REGION_HOST_ATTR, REGION_UNITS, regionBetween, regionPointIn, regionStyle, regionTarget, } from './src/regionTarget';
20
+ export type { RegionBox, RegionLocator, RegionPoint, RegionShape } from './src/regionTarget';
21
+ export type { Annotation, AnnotationAttachment, AnnotationAuthor, AnnotationContext, AnnotationContextValue, AnnotationHost, AnnotationState, } from './src/runtime';
22
+ export { textTarget } from './src/textTarget';
23
+ export type { TextLocator } from './src/textTarget';
24
+ export { useAnnotationState } from './src/useAnnotationState';
25
+ export { useRegionAnnotation } from './src/useRegionAnnotation';
26
+ export { useTextAnnotation } from './src/useTextAnnotation';
27
+ export { autoResizeTextarea, fileAnnotationPath, generateAnnotationId, hostAcceptsUploads, RESPONSE_ANNOTATION_PATH } from './src/utils';
@@ -0,0 +1,26 @@
1
+ import type React from 'react';
2
+ /**
3
+ * The foot of a draft: the note that belongs to no one annotation, and the
4
+ * action that sends the draft off.
5
+ *
6
+ * What counts as content, and what the payload looks like, is the host's —
7
+ * hence `hasContent` and a bare `onSubmit`. The two slots are where a host
8
+ * hangs whatever else its submit step needs (a preview button, a validation
9
+ * notice) without this component learning about it.
10
+ */
11
+ export interface AnnotationDraftFooterProps {
12
+ /** Whether the draft says anything. Hosts count more than annotations and
13
+ * the general note, so they decide. */
14
+ hasContent: boolean;
15
+ onSubmit: () => void;
16
+ /** Submitting an empty draft — an explicit "nothing to say", not a no-op. */
17
+ onSubmitEmpty: () => void;
18
+ /** Sits between the note and the actions: validation, status, a warning. */
19
+ notice?: React.ReactNode;
20
+ /** Sits left of the submit button, sharing the row. */
21
+ secondaryAction?: React.ReactNode;
22
+ placeholder?: string;
23
+ submitLabel?: string;
24
+ emptyLabel?: string;
25
+ }
26
+ export declare function AnnotationDraftFooter({ hasContent, onSubmit, onSubmitEmpty, notice, secondaryAction, placeholder, submitLabel, emptyLabel, }: AnnotationDraftFooterProps): React.JSX.Element;
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ interface AnnotationEditorProps {
3
+ note: string;
4
+ onNoteChange: (note: string) => void;
5
+ images: string[];
6
+ onAddImage: (path: string) => void;
7
+ onRemoveImage: (path: string) => void;
8
+ sessionId: string;
9
+ placeholder?: string;
10
+ autoFocus?: boolean;
11
+ autoResize?: boolean;
12
+ readOnly?: boolean;
13
+ onKeyDown?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;
14
+ onTextareaClick?: (e: React.MouseEvent<HTMLTextAreaElement>) => void;
15
+ textareaRef?: React.MutableRefObject<HTMLTextAreaElement | null>;
16
+ textareaClassName?: string;
17
+ textareaStyle?: React.CSSProperties;
18
+ minHeight?: number;
19
+ /** "always" (default), "on-focus" (sidebar), or "none" (popover — use openFilePickerRef) */
20
+ attachButton?: 'always' | 'on-focus' | 'none';
21
+ /** Parent can store the open-file-picker function for external trigger */
22
+ openFilePickerRef?: React.MutableRefObject<(() => void) | null>;
23
+ }
24
+ export declare function imageToUrl(path: string): string;
25
+ export declare function AnnotationEditor({ note, onNoteChange, images, onAddImage, onRemoveImage, sessionId, placeholder, autoFocus, autoResize, readOnly, onKeyDown, onTextareaClick, textareaRef: externalRef, textareaClassName, textareaStyle, minHeight, attachButton, openFilePickerRef, }: AnnotationEditorProps): React.JSX.Element;
26
+ /** Small attach-image button — reusable in editor and popover button bar */
27
+ export declare function AttachButton({ onClick, size }: {
28
+ onClick: () => void;
29
+ size?: number;
30
+ }): React.JSX.Element;
31
+ /** Read-only image thumbnails for display in read-only annotations */
32
+ export declare function ImageThumbnails({ images }: {
33
+ images: string[];
34
+ }): React.JSX.Element | null;
35
+ export {};
@@ -0,0 +1,17 @@
1
+ import type { Annotation } from './AnnotationProvider';
2
+ export interface AnnotationListProps {
3
+ annotations: Annotation[];
4
+ /** Frozen view: notes read as text, nothing is deletable, and the list does
5
+ * not chase the active card. */
6
+ readOnly?: boolean;
7
+ /** A card just became the active one — hosts reveal what it points at here. */
8
+ onSelect?: (ann: Annotation) => void;
9
+ /** Backs the reveal button. Omit it and no button is drawn. */
10
+ onReveal?: (ann: Annotation) => void;
11
+ /** Remote annotations ticked for submission. Pass both or neither — a host
12
+ * with no notion of remote annotations passes neither and gets none of the
13
+ * remote affordances. */
14
+ includedRemoteIds?: Set<string>;
15
+ onToggleRemoteId?: (id: string) => void;
16
+ }
17
+ export declare function AnnotationList({ annotations, readOnly, onSelect, onReveal, includedRemoteIds, onToggleRemoteId, }: AnnotationListProps): import("react").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import type { Annotation, AnnotationState } from './runtime';
3
+ export { useAnnotations } from '@fabrika/annotations/runtime';
4
+ export type { Annotation, AnnotationContext, AnnotationContextValue, AnnotationState } from './runtime';
5
+ export interface AnnotationProviderProps {
6
+ scope: string;
7
+ isReadOnly?: boolean;
8
+ remoteAnnotations?: Annotation[];
9
+ loadState: (scope: string) => Promise<AnnotationState | null>;
10
+ saveState: (scope: string, state: AnnotationState) => void;
11
+ children: React.ReactNode;
12
+ }
13
+ export declare function AnnotationProvider(props: AnnotationProviderProps): React.JSX.Element;
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ interface PopoverProps {
3
+ anchorEl: HTMLElement;
4
+ scrollContainer?: HTMLElement | null;
5
+ onClose: () => void;
6
+ /** Selectors that should not trigger outside-click close */
7
+ ignoreSelector?: string;
8
+ zIndex?: string;
9
+ padding?: string;
10
+ width?: string;
11
+ children: React.ReactNode;
12
+ }
13
+ export declare function Popover({ anchorEl, scrollContainer, onClose, ignoreSelector, zIndex, padding, width, children }: PopoverProps): React.ReactPortal;
14
+ interface AnnotationPopoverProps {
15
+ anchorEl: HTMLElement;
16
+ scrollContainer?: HTMLElement | null;
17
+ snippet: string;
18
+ /** Max length for displayed snippet (default 100) */
19
+ truncateAt?: number;
20
+ /** Custom header instead of the default quoted snippet */
21
+ header?: React.ReactNode;
22
+ /** Initial note text (for edit mode) */
23
+ initialNote?: string;
24
+ /** Initial images (for edit mode) */
25
+ initialImages?: string[];
26
+ /** Called on confirm — passes note and images */
27
+ onConfirm: (note: string, images: string[]) => void;
28
+ /** Called on cancel / close without saving */
29
+ onCancel: () => void;
30
+ /** Called when annotation should be deleted (edit mode) */
31
+ onDelete?: () => void;
32
+ }
33
+ export declare function AnnotationPopover({ anchorEl, scrollContainer, snippet, truncateAt, header, initialNote, initialImages, onConfirm, onCancel, onDelete, }: AnnotationPopoverProps): React.JSX.Element;
34
+ interface AnnotationCreatePopoverProps {
35
+ anchorEl: HTMLElement;
36
+ scrollContainer?: HTMLElement | null;
37
+ snippet: string;
38
+ truncateAt?: number;
39
+ header?: React.ReactNode;
40
+ onAdd: (note: string, images?: string[]) => void;
41
+ onCancel: () => void;
42
+ }
43
+ export declare function AnnotationCreatePopover({ anchorEl, scrollContainer, snippet, truncateAt, header, onAdd, onCancel }: AnnotationCreatePopoverProps): React.JSX.Element;
44
+ interface AnnotationEditPopoverProps {
45
+ anchorEl: HTMLElement;
46
+ scrollContainer?: HTMLElement | null;
47
+ initialNote: string;
48
+ initialImages?: string[];
49
+ onUpdate: (note: string, images: string[]) => void;
50
+ onDelete: () => void;
51
+ onClose: () => void;
52
+ }
53
+ export declare function AnnotationEditPopover({ anchorEl, scrollContainer, initialNote, initialImages, onUpdate, onDelete, onClose }: AnnotationEditPopoverProps): React.JSX.Element;
54
+ export {};
@@ -0,0 +1,15 @@
1
+ import type { AnnotationContext } from './AnnotationProvider';
2
+ /**
3
+ * Extract disambiguation context from a Range:
4
+ * - surrounding text (before/after the selection)
5
+ * - hierarchy path (Section title → Task label)
6
+ */
7
+ export declare function extractContext(range: Range, planContainer: HTMLElement): AnnotationContext;
8
+ /**
9
+ * Format a snippet with surrounding context for disambiguation.
10
+ * Short snippets get before/after context.
11
+ */
12
+ export declare function formatSnippetInContext(ann: {
13
+ snippet: string;
14
+ context?: AnnotationContext;
15
+ }): string;
@@ -0,0 +1,8 @@
1
+ import { type SealedAnnotationTarget, type TargetAnnotation } from './annotationTarget';
2
+ import type { Annotation } from './runtime';
3
+ export { ANNOTATABLE_SELECTOR, BLOCK_SELECTOR, getBlockSnippet } from './blockTarget';
4
+ export declare const ANNOTATION_TARGETS: SealedAnnotationTarget[];
5
+ export declare function findSnippetElement(snippet: string, root: ParentNode): HTMLElement | null;
6
+ export declare function restoreAnnotationTargets(root: HTMLElement, annotations: readonly TargetAnnotation[]): void;
7
+ export declare function describeSnippet(snippet: string): string;
8
+ export declare function findAnnotationElement(annotation: Annotation, root?: ParentNode): HTMLElement | null;
@@ -0,0 +1,26 @@
1
+ import type { AnnotationAttachment, AnnotationContext } from './runtime';
2
+ /**
3
+ * What rendering one annotation reads off it. Every `Annotation` satisfies this,
4
+ * and so can a record that is not one: how a single annotation reads as markdown
5
+ * is the half of feedback that belongs to no particular document format.
6
+ */
7
+ export interface RenderableAnnotation {
8
+ snippet: string;
9
+ note: string;
10
+ /** Set when the annotation points into a file. With `context.lineStart` it
11
+ * switches the quote to numbered source lines. */
12
+ filePath?: string;
13
+ context?: AnnotationContext;
14
+ /** Attached images as bare paths/URLs — what the local editor writes. */
15
+ images?: string[];
16
+ /** Attached files carried on the wire — what a shared canvas sends back.
17
+ * A host may populate either field; both are rendered. */
18
+ attachments?: AnnotationAttachment[];
19
+ }
20
+ /**
21
+ * One annotation as markdown: what was annotated, quoted, then the note and any
22
+ * attachments under it. Ends on a blank line so entries stack.
23
+ *
24
+ * The caller owns everything around it — headings, grouping, ordering.
25
+ */
26
+ export declare function renderAnnotation(ann: RenderableAnnotation): string;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * How a snippet names something on the page.
3
+ *
4
+ * `Annotation.snippet` is the only field that ties an annotation to a domain —
5
+ * everything else (draft persistence, sidebar, popover, notes, attachments,
6
+ * markdown, submit) works on any annotation whatever it points at. A target is
7
+ * that one tie, pulled out as a strategy: give the kernel a new target and it
8
+ * can annotate a new kind of thing without another line changing.
9
+ */
10
+ /** What a target may read off the annotation it resolves — DOM identity, not feedback. */
11
+ export interface TargetAnnotation {
12
+ id: string;
13
+ snippet: string;
14
+ context?: {
15
+ before: string;
16
+ after: string;
17
+ hierarchy: string[];
18
+ };
19
+ }
20
+ export interface AnnotationTarget<L extends object> {
21
+ /** Names the strategy. */
22
+ readonly kind: string;
23
+ /** Read a snippet this target wrote. Null means the snippet is not its own. */
24
+ parse(snippet: string): L | null;
25
+ /** Write the locator back into the snippet key. The exact inverse of `parse`. */
26
+ format(locator: L): string;
27
+ /**
28
+ * The element the locator names, searched inside `root`. Targets whose
29
+ * annotation lives in DOM this target itself drew — an inline mark, an
30
+ * overlay box — return null here and are resolved by their annotation id
31
+ * instead; see findAnnotationElement.
32
+ */
33
+ find(locator: L, root: ParentNode): HTMLElement | null;
34
+ /**
35
+ * Put this annotation's own decoration back into `root`, if it is not there
36
+ * already. Called after every render, for every annotation, so it must be
37
+ * idempotent and cheap on a snippet it does not own.
38
+ */
39
+ restore?(locator: L, root: HTMLElement, ann: TargetAnnotation): void;
40
+ /** A one-line label a reader (or a coding agent) can act on. */
41
+ describe?(locator: L): string;
42
+ }
43
+ /** An AnnotationTarget with its locator type sealed inside, so targets whose
44
+ * locators have nothing in common can share one list. */
45
+ export interface SealedAnnotationTarget {
46
+ readonly kind: string;
47
+ owns(snippet: string): boolean;
48
+ find(snippet: string, root: ParentNode): HTMLElement | null;
49
+ restore(root: HTMLElement, ann: TargetAnnotation): void;
50
+ describe(snippet: string): string | null;
51
+ }
52
+ /** Close over the locator type, so parse and find can never be called with
53
+ * a locator the other one did not produce. */
54
+ export declare function sealTarget<L extends object>(target: AnnotationTarget<L>): SealedAnnotationTarget;
@@ -0,0 +1,15 @@
1
+ import type { AnnotationTarget } from './annotationTarget';
2
+ /**
3
+ * The blocks that can carry a block annotation — a strict subset of
4
+ * BLOCK_SELECTOR, since interactive controls are navigable but not annotatable.
5
+ */
6
+ export declare const ANNOTATABLE_SELECTOR: string;
7
+ /** Every block the keyboard arrows walk through. */
8
+ export declare const BLOCK_SELECTOR: string;
9
+ /** The snippet identifier for a block, or null if nothing can be annotated here. */
10
+ export declare function getBlockSnippet(block: HTMLElement): string | null;
11
+ /** A block is its own locator: the snippet is the text that identifies it. */
12
+ export interface BlockLocator {
13
+ snippet: string;
14
+ }
15
+ export declare const blockTarget: AnnotationTarget<BlockLocator>;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Wraps the current browser Range in <mark> elements with the given annotation ID.
3
+ * Works for multiline / cross-element selections.
4
+ */
5
+ export declare function wrapRangeWithMark(range: Range, annotationId: string): HTMLElement[];
6
+ /**
7
+ * Whether the annotation index carries this text. Line-number gutters and text
8
+ * that already belongs to another annotation are outside it. Everything that
9
+ * records a snippet or its context is matched back against that index later, so
10
+ * all of them have to skip exactly the same runs.
11
+ */
12
+ export declare function isIndexedText(node: Text): boolean;
13
+ /**
14
+ * A selection's text as the annotation index will read it back. The raw
15
+ * selection is not that: it carries the gutter and any text already inside
16
+ * another annotation, none of which the index holds — so a snippet taken from
17
+ * it names something that cannot be found again.
18
+ */
19
+ export declare function rangeIndexText(range: Range): string;
20
+ /**
21
+ * Update the visual state of marks for a given annotation ID.
22
+ */
23
+ export declare function setMarkActive(annotationId: string, active: boolean): void;
24
+ /**
25
+ * Update active state for annotation marks.
26
+ * Only touches marks for the previous and current active IDs to avoid full DOM scans.
27
+ */
28
+ export declare function updateAllMarkStates(activeId: string | null, prevActiveId?: string | null): void;
29
+ /**
30
+ * Rename annotation ID on existing marks (e.g. temp → real ID).
31
+ */
32
+ export declare function renameMarkId(oldId: string, newId: string): void;
33
+ /**
34
+ * Restore marks for persisted annotations by finding their snippet text in the DOM.
35
+ * Uses before/after context for disambiguation when the same text appears multiple times.
36
+ */
37
+ export declare function restoreMarks(container: HTMLElement, annotations: {
38
+ id: string;
39
+ snippet: string;
40
+ filePath?: string;
41
+ context?: {
42
+ before: string;
43
+ after: string;
44
+ hierarchy: string[];
45
+ };
46
+ }[]): void;
47
+ /**
48
+ * Remove the decoration for a given annotation ID, restoring the original text
49
+ * nodes an inline mark wrapped.
50
+ */
51
+ export declare function unwrapMarks(annotationId: string): void;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Read a CSS width the popover will be styled with. Only px is a width this
3
+ * placement can reason about; anything else falls back to the default rather
4
+ * than clamping against a number that means something different.
5
+ */
6
+ export declare function pxWidth(css: string): number | undefined;
7
+ /**
8
+ * Calculate popover position relative to an anchor element.
9
+ * Returns absolute position within the scroll container (or body).
10
+ */
11
+ export declare function getPopoverPosition(anchor: HTMLElement, scrollContainer?: HTMLElement | null, popoverWidth?: number): {
12
+ style: Record<string, string>;
13
+ parent: HTMLElement;
14
+ };
@@ -0,0 +1,61 @@
1
+ import type { AnnotationTarget } from './annotationTarget';
2
+ /**
3
+ * A rectangle or ellipse drawn inside an image block, so a reader can point at
4
+ * one corner of a screenshot instead of the whole picture.
5
+ *
6
+ * Coordinates are normalized against the image box, which is a uniform scale of
7
+ * the image's natural size — that is what lets a region survive a resize, a
8
+ * zoom or a different screen. They are stored on a fixed integer grid rather
9
+ * than as floats: a float printed into the snippet and read back is not
10
+ * guaranteed to be the same float, and a locator that shifts by one ulp names
11
+ * a region nobody drew.
12
+ */
13
+ /** The grid a region snaps to: hundredths of a percent of the image box. */
14
+ export declare const REGION_UNITS = 10000;
15
+ export type RegionShape = 'rect' | 'ellipse';
16
+ export interface RegionPoint {
17
+ x: number;
18
+ y: number;
19
+ }
20
+ /** Left, top, width and height, all in REGION_UNITS. */
21
+ export interface RegionBox extends RegionPoint {
22
+ w: number;
23
+ h: number;
24
+ }
25
+ export interface RegionLocator extends RegionBox {
26
+ /** The image block the region sits in — the same `src` `[Image]` is keyed by. */
27
+ src: string;
28
+ shape: RegionShape;
29
+ }
30
+ /** Marks the element a region is measured against: the image's own box, not the
31
+ * `<figure>`, which also holds the caption and would skew every percentage. */
32
+ export declare const REGION_HOST_ATTR = "data-annotation-image";
33
+ export declare function clampUnit(value: number): number;
34
+ /** Where a pointer landed inside a box, on the region grid. Null for a box with
35
+ * no extent — happy-dom and a not-yet-laid-out image both report zero. */
36
+ export declare function regionPointIn(box: {
37
+ width: number;
38
+ height: number;
39
+ }, offsetX: number, offsetY: number): RegionPoint | null;
40
+ /** The box two drag corners span, kept inside the image. */
41
+ export declare function regionBetween(a: RegionPoint, b: RegionPoint): RegionBox;
42
+ export declare function isDrawableRegion(box: RegionBox): boolean;
43
+ /** CSS geometry for the overlay. REGION_UNITS is percent × 100, so every value
44
+ * the grid holds divides out exactly. */
45
+ export declare function regionStyle(box: RegionBox): {
46
+ left: string;
47
+ top: string;
48
+ width: string;
49
+ height: string;
50
+ };
51
+ export declare function describeRegion(locator: RegionLocator): string;
52
+ /** The image box a region belongs to. Compared attribute by attribute rather
53
+ * than through a selector, because an image src is a path and may carry any
54
+ * character a selector would have to escape. */
55
+ export declare function findRegionHost(src: string, root: ParentNode): HTMLElement | null;
56
+ export declare function applyRegionStyle(el: HTMLElement, box: RegionBox): void;
57
+ /** The overlay box for one region. It carries `data-annotation-id`, so the
58
+ * hover, active-state and delete plumbing that already drives inline marks
59
+ * drives these too. */
60
+ export declare function createRegionOverlay(box: RegionBox, shape: RegionShape, annotationId: string): HTMLElement;
61
+ export declare const regionTarget: AnnotationTarget<RegionLocator>;
@@ -0,0 +1,56 @@
1
+ export interface AnnotationContext {
2
+ before: string;
3
+ after: string;
4
+ hierarchy: string[];
5
+ lineStart?: number;
6
+ lineEnd?: number;
7
+ }
8
+ export interface AnnotationAuthor {
9
+ id: string;
10
+ name: string;
11
+ }
12
+ export interface AnnotationAttachment {
13
+ url: string;
14
+ mime?: string;
15
+ }
16
+ export interface Annotation {
17
+ id: string;
18
+ snippet: string;
19
+ note: string;
20
+ createdAt: string;
21
+ filePath?: string;
22
+ canvasFile?: string;
23
+ context?: AnnotationContext;
24
+ images?: string[];
25
+ attachments?: AnnotationAttachment[];
26
+ source?: 'local' | 'remote';
27
+ author?: AnnotationAuthor;
28
+ }
29
+ export interface AnnotationState {
30
+ annotations: Annotation[];
31
+ generalNote: string;
32
+ }
33
+ export interface AnnotationContextValue extends AnnotationState {
34
+ addAnnotation: (snippet: string, note: string, filePath?: string) => void;
35
+ addAnnotationWithId: (id: string, snippet: string, note: string, filePath?: string, context?: AnnotationContext, images?: string[], canvasFile?: string) => void;
36
+ updateAnnotation: (id: string, note: string) => void;
37
+ removeAnnotation: (id: string) => void;
38
+ addAnnotationImage: (id: string, imagePath: string) => void;
39
+ removeAnnotationImage: (id: string, imagePath: string) => void;
40
+ setGeneralNote: (text: string) => void;
41
+ clearAll: () => void;
42
+ activeAnnotationId: string | null;
43
+ setActiveAnnotationId: (id: string | null) => void;
44
+ isReadOnly: boolean;
45
+ }
46
+ export interface AnnotationHost {
47
+ sessionId: string;
48
+ isShared: boolean;
49
+ fsAvailable: boolean;
50
+ uploadUrl: (() => string) | null;
51
+ }
52
+ export declare const AnnotationCtx: import("react").Context<AnnotationContextValue | null>;
53
+ export declare const SessionContext: import("react").Context<string>;
54
+ export declare const AnnotationHostContext: import("react").Context<AnnotationHost>;
55
+ export declare function useAnnotations(): AnnotationContextValue;
56
+ export declare function useAnnotationHost(): AnnotationHost;