@annotorious/annotorious
Advanced tools
Comparing version
import { SvelteImageAnnotationStore } from '../state'; | ||
import { ImageAnnotation } from '../model'; | ||
export interface SVGAnnotationLayerPointerEvent { | ||
import { Annotation } from '@annotorious/core'; | ||
export interface SVGAnnotationLayerPointerEvent<T extends Annotation> { | ||
originalEvent: PointerEvent; | ||
annotation?: ImageAnnotation; | ||
annotation?: T; | ||
} | ||
export declare const addEventListeners: (svg: SVGSVGElement, store: SvelteImageAnnotationStore) => { | ||
export declare const addEventListeners: <T extends Annotation>(svg: SVGSVGElement, store: SvelteImageAnnotationStore<T>) => { | ||
onPointerDown: () => number; | ||
@@ -9,0 +9,0 @@ onPointerUp: (evt: PointerEvent) => void; |
import { SvelteComponent } from 'svelte'; | ||
import { Annotator } from '@annotorious/core'; | ||
import { Annotation, Annotator } from '@annotorious/core'; | ||
import { DrawingTool } from './annotation/tools'; | ||
@@ -7,3 +7,3 @@ import { DrawingToolOpts } from './annotation'; | ||
import { Theme, AnnotoriousOpts } from './AnnotoriousOpts'; | ||
export interface ImageAnnotator<E extends unknown = ImageAnnotation> extends Annotator<ImageAnnotation, E> { | ||
export interface ImageAnnotator<I extends Annotation = ImageAnnotation, E extends unknown = ImageAnnotation> extends Annotator<I, E> { | ||
element: HTMLDivElement; | ||
@@ -17,2 +17,2 @@ listDrawingTools(): string[]; | ||
} | ||
export declare const createImageAnnotator: <E extends unknown = ImageAnnotation>(image: string | HTMLImageElement | HTMLCanvasElement, options?: AnnotoriousOpts<ImageAnnotation, E>) => ImageAnnotator<E>; | ||
export declare const createImageAnnotator: <I extends Annotation = ImageAnnotation, E extends unknown = ImageAnnotation>(image: string | HTMLImageElement | HTMLCanvasElement, options?: AnnotoriousOpts<I, E>) => ImageAnnotator<I, E>; |
@@ -14,2 +14,2 @@ import { Annotation, DrawingStyleExpression, FormatAdapter, UserSelectActionExpression } from '@annotorious/core'; | ||
export type Theme = 'dark' | 'light' | 'auto'; | ||
export declare const fillDefaults: <I extends ImageAnnotation = ImageAnnotation, E extends unknown = ImageAnnotation>(opts: AnnotoriousOpts<I, E>, defaults: AnnotoriousOpts<I, E>) => AnnotoriousOpts<I, E>; | ||
export declare const fillDefaults: <I extends Annotation = ImageAnnotation, E extends unknown = ImageAnnotation>(opts: AnnotoriousOpts<I, E>, defaults: AnnotoriousOpts<I, E>) => AnnotoriousOpts<I, E>; |
@@ -9,1 +9,3 @@ import { Annotation, AnnotationTarget } from '@annotorious/core'; | ||
} | ||
export declare const isImageAnnotation: <T extends Annotation>(a: T | ImageAnnotation) => a is ImageAnnotation; | ||
export declare const isImageAnnotationTarget: <T extends AnnotationTarget>(t: T | ImageAnnotationTarget) => t is ImageAnnotationTarget; |
@@ -1,10 +0,10 @@ | ||
import { Store, SvelteAnnotatorState, SvelteStore } from '@annotorious/core'; | ||
import { Annotation, Store, SvelteAnnotatorState, SvelteStore } from '@annotorious/core'; | ||
import { ImageAnnotation } from '../model'; | ||
export type ImageAnnotationStore = Store<ImageAnnotation> & { | ||
export type ImageAnnotationStore<I extends Annotation> = Store<I> & { | ||
getAt(x: number, y: number): ImageAnnotation | undefined; | ||
getIntersecting(x: number, y: number, width: number, height: number): ImageAnnotation[]; | ||
}; | ||
export type SvelteImageAnnotationStore = SvelteStore<ImageAnnotation> & ImageAnnotationStore; | ||
export type SvelteImageAnnotatorState = SvelteAnnotatorState<ImageAnnotation> & { | ||
store: SvelteImageAnnotationStore; | ||
export type SvelteImageAnnotationStore<I extends Annotation = Annotation> = SvelteStore<I> & ImageAnnotationStore<I>; | ||
export type SvelteImageAnnotatorState<I extends Annotation = Annotation> = SvelteAnnotatorState<I> & { | ||
store: SvelteImageAnnotationStore<I>; | ||
}; |
import { ImageAnnotation } from '../model'; | ||
import { AnnotoriousOpts } from '../AnnotoriousOpts'; | ||
import { AnnotatorState, HoverState, SelectionState } from '@annotorious/core'; | ||
import { Annotation, AnnotatorState, HoverState, SelectionState } from '@annotorious/core'; | ||
import { ImageAnnotationStore, SvelteImageAnnotatorState } from './ImageAnnotationStore'; | ||
export type ImageAnnotatorState<T extends ImageAnnotationStore = ImageAnnotationStore> = AnnotatorState<ImageAnnotation> & { | ||
store: T; | ||
export type ImageAnnotatorState<I extends Annotation> = AnnotatorState<I> & { | ||
store: ImageAnnotationStore<I>; | ||
selection: SelectionState<ImageAnnotation>; | ||
hover: HoverState<ImageAnnotation>; | ||
}; | ||
export declare const createImageAnnotatorState: <E extends unknown>(opts: AnnotoriousOpts<ImageAnnotation, E>) => ImageAnnotatorState<ImageAnnotationStore>; | ||
export declare const createSvelteImageAnnotatorState: <E extends unknown>(opts: AnnotoriousOpts<ImageAnnotation, E>) => SvelteImageAnnotatorState; | ||
export declare const createImageAnnotatorState: <I extends Annotation, E extends unknown>(opts: AnnotoriousOpts<I, E>) => ImageAnnotatorState<I>; | ||
export declare const createSvelteImageAnnotatorState: <I extends Annotation, E extends unknown>(opts: AnnotoriousOpts<I, E>) => SvelteImageAnnotatorState<I>; |
import { ImageAnnotationTarget } from '../model'; | ||
import { AnnotationTarget } from '@annotorious/core'; | ||
interface IndexedTarget { | ||
@@ -14,8 +15,8 @@ minX: number; | ||
getIntersecting: (x: number, y: number, width: number, height: number) => ImageAnnotationTarget[]; | ||
insert: (target: ImageAnnotationTarget) => void; | ||
remove: (target: ImageAnnotationTarget) => void; | ||
set: (targets: ImageAnnotationTarget[], replace?: boolean) => void; | ||
insert: (target: AnnotationTarget) => void; | ||
remove: (target: AnnotationTarget) => void; | ||
set: (targets: AnnotationTarget[], replace?: boolean) => void; | ||
size: () => number; | ||
update: (previous: ImageAnnotationTarget, updated: ImageAnnotationTarget) => void; | ||
update: (previous: AnnotationTarget, updated: AnnotationTarget) => void; | ||
}; | ||
export {}; |
{ | ||
"name": "@annotorious/annotorious", | ||
"version": "3.0.0", | ||
"version": "3.0.1", | ||
"description": "Add image annotation functionality to any web page with a few lines of JavaScript", | ||
"author": "Rainer Simon", | ||
"license": "BSD-3-Clause", | ||
"homepage": "https://annotorious.github.io", | ||
"homepage": "https://annotorious.dev", | ||
"type": "module", | ||
@@ -51,3 +51,3 @@ "repository": { | ||
"dependencies": { | ||
"@annotorious/core": "3.0.0", | ||
"@annotorious/core": "3.0.1", | ||
"rbush": "^4.0.1", | ||
@@ -54,0 +54,0 @@ "uuid": "^10.0.0" |
import { createEventDispatcher } from 'svelte'; | ||
import type { SvelteImageAnnotationStore } from '../state'; | ||
import type { ImageAnnotation } from '../model'; | ||
import type { Annotation } from '@annotorious/core'; | ||
export interface SVGAnnotationLayerPointerEvent { | ||
export interface SVGAnnotationLayerPointerEvent<T extends Annotation> { | ||
originalEvent: PointerEvent; | ||
annotation?: ImageAnnotation; | ||
annotation?: T; | ||
@@ -16,4 +16,4 @@ } | ||
export const addEventListeners = (svg: SVGSVGElement, store: SvelteImageAnnotationStore) => { | ||
const dispatch = createEventDispatcher<{ click: SVGAnnotationLayerPointerEvent}>(); | ||
export const addEventListeners = <T extends Annotation>(svg: SVGSVGElement, store: SvelteImageAnnotationStore<T>) => { | ||
const dispatch = createEventDispatcher<{ click: SVGAnnotationLayerPointerEvent<T> }>(); | ||
@@ -31,3 +31,3 @@ let lastPointerDown: number; | ||
const annotation = store.getAt(x, y); | ||
const annotation = store.getAt(x, y) as T | undefined; | ||
@@ -34,0 +34,0 @@ if (annotation) |
import type { SvelteComponent } from 'svelte'; | ||
import { UserSelectAction } from '@annotorious/core'; | ||
import type { Annotator, DrawingStyleExpression, Filter, User } from '@annotorious/core'; | ||
import type { Annotation, Annotator, DrawingStyleExpression, Filter, User } from '@annotorious/core'; | ||
import { createAnonymousGuest, createBaseAnnotator, createLifecycleObserver, createUndoStack } from '@annotorious/core'; | ||
@@ -20,3 +20,3 @@ import { registerEditor } from './annotation/editors'; | ||
export interface ImageAnnotator<E extends unknown = ImageAnnotation> extends Annotator<ImageAnnotation, E> { | ||
export interface ImageAnnotator<I extends Annotation = ImageAnnotation, E extends unknown = ImageAnnotation> extends Annotator<I, E> { | ||
@@ -39,6 +39,6 @@ element: HTMLDivElement; | ||
export const createImageAnnotator = <E extends unknown = ImageAnnotation>( | ||
export const createImageAnnotator = <I extends Annotation = ImageAnnotation, E extends unknown = ImageAnnotation>( | ||
image: string | HTMLImageElement | HTMLCanvasElement, | ||
options: AnnotoriousOpts<ImageAnnotation, E> = {} | ||
): ImageAnnotator<E> => { | ||
options: AnnotoriousOpts<I, E> = {} | ||
): ImageAnnotator<I, E> => { | ||
@@ -52,3 +52,3 @@ if (!image) | ||
const opts = fillDefaults<ImageAnnotation, E>(options, { | ||
const opts = fillDefaults<I, E>(options, { | ||
drawingEnabled: true, | ||
@@ -60,3 +60,3 @@ drawingMode: 'drag', | ||
const state = createSvelteImageAnnotatorState(opts); | ||
const state = createSvelteImageAnnotatorState<I, E>(opts); | ||
@@ -67,3 +67,3 @@ const { selection, store } = state; | ||
const lifecycle = createLifecycleObserver<ImageAnnotation, E>( | ||
const lifecycle = createLifecycleObserver<I, E>( | ||
state, undoStack, opts.adapter, opts.autoSave | ||
@@ -95,3 +95,3 @@ ); | ||
preferredDrawingMode: opts.drawingMode!, | ||
state, | ||
state: state, | ||
style: opts.style, | ||
@@ -102,3 +102,3 @@ user: currentUser | ||
annotationLayer.$on('click', (evt: CustomEvent<SVGAnnotationLayerPointerEvent>) => { | ||
annotationLayer.$on('click', (evt: CustomEvent<SVGAnnotationLayerPointerEvent<I>>) => { | ||
const { originalEvent, annotation } = evt.detail; | ||
@@ -116,3 +116,3 @@ if (annotation) | ||
// Most of the external API functions are covered in the base annotator | ||
const base = createBaseAnnotator<ImageAnnotation, E>(state, undoStack, opts.adapter); | ||
const base = createBaseAnnotator<I, E>(state, undoStack, opts.adapter); | ||
@@ -157,4 +157,4 @@ const destroy = () => { | ||
const setStyle = (style: DrawingStyleExpression<ImageAnnotation> | undefined) => | ||
annotationLayer.$set({ style }); | ||
const setStyle = (style: DrawingStyleExpression<I> | undefined) => | ||
annotationLayer.$set({ style: style as DrawingStyleExpression<ImageAnnotation> }); | ||
@@ -161,0 +161,0 @@ const setTheme = (theme: Theme) => _setTheme(img, container, theme); |
@@ -28,3 +28,3 @@ import type { Annotation, DrawingStyleExpression, FormatAdapter, UserSelectActionExpression } from '@annotorious/core'; | ||
export const fillDefaults = <I extends ImageAnnotation = ImageAnnotation, E extends unknown = ImageAnnotation> ( | ||
export const fillDefaults = <I extends Annotation = ImageAnnotation, E extends unknown = ImageAnnotation> ( | ||
opts: AnnotoriousOpts<I, E>, | ||
@@ -31,0 +31,0 @@ defaults: AnnotoriousOpts<I, E> |
@@ -14,2 +14,13 @@ import type { Annotation, AnnotationTarget } from '@annotorious/core'; | ||
} | ||
} | ||
export const isImageAnnotation = <T extends Annotation>( | ||
a: T | ImageAnnotation | ||
): a is ImageAnnotation => | ||
isImageAnnotationTarget(a.target); | ||
export const isImageAnnotationTarget = <T extends AnnotationTarget>( | ||
t: T | ImageAnnotationTarget | ||
): t is ImageAnnotationTarget => | ||
t?.annotation !== undefined && | ||
(t as ImageAnnotationTarget)?.selector?.geometry?.bounds !== undefined; |
@@ -1,5 +0,5 @@ | ||
import type { Store, SvelteAnnotatorState, SvelteStore } from '@annotorious/core'; | ||
import type { Annotation, Store, SvelteAnnotatorState, SvelteStore } from '@annotorious/core'; | ||
import type { ImageAnnotation } from '../model'; | ||
export type ImageAnnotationStore = Store<ImageAnnotation> & { | ||
export type ImageAnnotationStore<I extends Annotation> = Store<I> & { | ||
@@ -12,8 +12,8 @@ getAt(x: number, y: number): ImageAnnotation | undefined; | ||
export type SvelteImageAnnotationStore = SvelteStore<ImageAnnotation> & ImageAnnotationStore; | ||
export type SvelteImageAnnotationStore<I extends Annotation = Annotation> = SvelteStore<I> & ImageAnnotationStore<I>; | ||
export type SvelteImageAnnotatorState = SvelteAnnotatorState<ImageAnnotation> & { | ||
export type SvelteImageAnnotatorState<I extends Annotation = Annotation> = SvelteAnnotatorState<I> & { | ||
store: SvelteImageAnnotationStore; | ||
store: SvelteImageAnnotationStore<I>; | ||
} |
@@ -7,2 +7,3 @@ import type { ImageAnnotation, ImageAnnotationTarget } from '../model'; | ||
toSvelteStore, | ||
type Annotation, | ||
type AnnotatorState, | ||
@@ -23,5 +24,5 @@ type HoverState, | ||
export type ImageAnnotatorState<T extends ImageAnnotationStore = ImageAnnotationStore> = AnnotatorState<ImageAnnotation> & { | ||
export type ImageAnnotatorState<I extends Annotation> = AnnotatorState<I> & { | ||
store: T; | ||
store: ImageAnnotationStore<I>; | ||
@@ -34,12 +35,11 @@ selection: SelectionState<ImageAnnotation>; | ||
export const createImageAnnotatorState = <E extends unknown>( | ||
opts: AnnotoriousOpts<ImageAnnotation, E> | ||
): ImageAnnotatorState<ImageAnnotationStore> => { | ||
export const createImageAnnotatorState = <I extends Annotation, E extends unknown> ( | ||
opts: AnnotoriousOpts<I, E> | ||
): ImageAnnotatorState<I> => { | ||
const store = createStore<ImageAnnotation>(); | ||
const store = createStore<I>(); | ||
const tree = createSpatialTree(); | ||
const selection = createSelectionState(store); | ||
selection.setUserSelectAction(opts.userSelectAction); | ||
const selection = createSelectionState<I>(store, opts.userSelectAction); | ||
@@ -55,3 +55,3 @@ const hover = createHoverState(store); | ||
(changes.updated || []).forEach(({ oldValue, newValue }) => | ||
(changes.updated || []).forEach(({ oldValue, newValue }) => | ||
tree.update(oldValue.target, newValue.target)); | ||
@@ -62,7 +62,7 @@ }); | ||
const target = tree.getAt(x, y); | ||
return target ? store.getAnnotation(target.annotation) : undefined; | ||
return target ? store.getAnnotation(target.annotation) as unknown as ImageAnnotation : undefined; | ||
} | ||
const getIntersecting = (x: number, y: number, width: number, height: number) => | ||
tree.getIntersecting(x, y, width, height).map(target => store.getAnnotation(target.annotation)); | ||
tree.getIntersecting(x, y, width, height).map(target => store.getAnnotation(target.annotation) as unknown as ImageAnnotation); | ||
@@ -74,13 +74,13 @@ return { | ||
getIntersecting | ||
} as ImageAnnotationStore, | ||
}, | ||
selection, | ||
hover, | ||
viewport | ||
} | ||
} as ImageAnnotatorState<I>; | ||
} | ||
export const createSvelteImageAnnotatorState = <E extends unknown>( | ||
opts: AnnotoriousOpts<ImageAnnotation, E> | ||
): SvelteImageAnnotatorState => { | ||
export const createSvelteImageAnnotatorState = <I extends Annotation, E extends unknown>( | ||
opts: AnnotoriousOpts<I, E> | ||
): SvelteImageAnnotatorState<I> => { | ||
@@ -91,5 +91,5 @@ const state = createImageAnnotatorState(opts); | ||
...state, | ||
store: toSvelteStore(state.store) as SvelteImageAnnotationStore | ||
store: toSvelteStore(state.store) as SvelteImageAnnotationStore<I> | ||
} | ||
} |
import RBush from 'rbush'; | ||
import { ShapeType,computeArea, intersects } from '../model'; | ||
import { ShapeType,computeArea, intersects, isImageAnnotationTarget } from '../model'; | ||
import type { ImageAnnotationTarget } from '../model'; | ||
import type { AnnotationTarget } from '@annotorious/core'; | ||
@@ -32,3 +33,5 @@ interface IndexedTarget { | ||
const insert = (target: ImageAnnotationTarget) => { | ||
const insert = (target: AnnotationTarget) => { | ||
if (!isImageAnnotationTarget(target)) return; | ||
const { minX, minY, maxX, maxY } = target.selector.geometry.bounds; | ||
@@ -42,3 +45,5 @@ | ||
const remove = (target: ImageAnnotationTarget) => { | ||
const remove = (target: AnnotationTarget) => { | ||
if (!isImageAnnotationTarget(target)) return; | ||
const item = index.get(target.annotation); | ||
@@ -50,3 +55,3 @@ if (item) | ||
const update = (previous: ImageAnnotationTarget, updated: ImageAnnotationTarget) => { | ||
const update = (previous: AnnotationTarget, updated: AnnotationTarget) => { | ||
remove(previous); | ||
@@ -56,3 +61,3 @@ insert(updated); | ||
const set = (targets: ImageAnnotationTarget[], replace: boolean = true) => { | ||
const set = (targets: AnnotationTarget[], replace: boolean = true) => { | ||
if (replace) | ||
@@ -62,7 +67,7 @@ clear(); | ||
const indexedTargets = targets.reduce<IndexedTarget[]>((all, target) => { | ||
if (target.selector?.geometry?.bounds) { | ||
if (isImageAnnotationTarget(target)) { | ||
// In case the host app injects any custom annotations, the | ||
// spatial index should simply ignore them. | ||
const { minX, minY, maxX, maxY } = target.selector.geometry.bounds; | ||
return [...all, { minX, minY, maxX, maxY, target }]; | ||
return [...all, { minX, minY, maxX, maxY, target } as IndexedTarget]; | ||
} else { | ||
@@ -69,0 +74,0 @@ return all; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
893698
0.51%6217
0.48%+ Added
- Removed
Updated