@annotorious/annotorious 3.0.0-rc.1 → 3.0.0-rc.11

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/dist/index.d.ts CHANGED
@@ -5,8 +5,6 @@ export * from './themes';
5
5
  export * from './annotation/tools';
6
6
  export * from './Annotorious';
7
7
  export * from './AnnotoriousOpts';
8
- export * from '@annotorious/core/src/model';
9
- export * from '@annotorious/core/src/presence';
10
- export * from '@annotorious/core/src/utils';
11
- export type { HoverState, Selection, SelectionState, Store, StoreObserver } from '@annotorious/core/src/state';
8
+ export * from './keyboardCommands';
9
+ export type { Annotation, AnnotationBody, AnnotationTarget, Annotator, AnnotatorState, Appearance, AppearanceProvider, Color, DrawingStyle, Filter, FormatAdapter, HoverState, LifecycleEvents, ParseResult, PresentUser, Purpose, Selection, SelectionState, Store, StoreChangeEvent, StoreObserver, User, W3CAnnotation, W3CAnnotationBody, W3CAnnotationTarget, W3CSelector } from '@annotorious/core';
12
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAE5C,YAAY,EACV,UAAU,EACV,SAAS,EACT,cAAc,EACd,KAAK,EACL,aAAa,EACd,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AAGnC,YAAY,EACV,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,KAAK,EACL,YAAY,EACZ,MAAM,EACN,aAAa,EACb,UAAU,EACV,eAAe,EACf,WAAW,EACX,WAAW,EACX,OAAO,EACP,SAAS,EACT,cAAc,EACd,KAAK,EACL,gBAAgB,EAChB,aAAa,EACb,IAAI,EACJ,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACZ,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { Annotation, UndoStack } from '@annotorious/core';
2
+ export declare const initKeyboardCommands: <T extends Annotation>(undoStack: UndoStack<T>, container?: Element) => {
3
+ destroy: () => void;
4
+ };
5
+ //# sourceMappingURL=keyboardCommands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboardCommands.d.ts","sourceRoot":"","sources":["../src/keyboardCommands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAI/D,eAAO,MAAM,oBAAoB,8DAEnB,OAAO;;CAuCpB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"W3CImageFormatAdapter.d.ts","sourceRoot":"","sources":["../../../src/model/w3c/W3CImageFormatAdapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEnF,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,SAAS,CAAC;AAMlE,MAAM,MAAM,qBAAqB,GAAG,aAAa,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;AAElF,eAAO,MAAM,cAAc,WACjB,MAAM,YACL,OAAO,0BAUjB,CAAA;AAED,eAAO,MAAM,uBAAuB,eACtB,aAAa,YAChB,OAAO,KACf,YAAY,eAAe,CA6B7B,CAAA;AAED,eAAO,MAAM,2BAA2B,eAC1B,eAAe,UACnB,MAAM,KACb,aAmBF,CAAC"}
1
+ {"version":3,"file":"W3CImageFormatAdapter.d.ts","sourceRoot":"","sources":["../../../src/model/w3c/W3CImageFormatAdapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEnF,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,SAAS,CAAC;AAMlE,MAAM,MAAM,qBAAqB,GAAG,aAAa,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;AAElF,eAAO,MAAM,cAAc,WACjB,MAAM,YACL,OAAO,0BAUjB,CAAA;AAED,eAAO,MAAM,uBAAuB,eACtB,aAAa,YAChB,OAAO,KACf,YAAY,eAAe,CAgC7B,CAAA;AAED,eAAO,MAAM,2BAA2B,eAC1B,eAAe,UACnB,MAAM,KACb,aAmBF,CAAC"}
@@ -1,3 +1,5 @@
1
+ import type { Theme } from '../../AnnotoriousOpts';
1
2
  export declare const sampleBrightness: (imageOrCanvas: HTMLElement) => number;
2
- export declare const setTheme: (imageOrCanvas: HTMLElement, container: HTMLElement) => void;
3
+ export declare const detectTheme: (imageOrCanvas: HTMLElement) => "dark" | "light";
4
+ export declare const setTheme: (imageOrCanvas: HTMLElement, container: HTMLElement, theme: Theme) => void;
3
5
  //# sourceMappingURL=setTheme.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"setTheme.d.ts","sourceRoot":"","sources":["../../../src/themes/smart/setTheme.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,kBAAmB,WAAW,WAmC1D,CAAA;AAED,eAAO,MAAM,QAAQ,kBAAmB,WAAW,aAAa,WAAW,SAQ1E,CAAA"}
1
+ {"version":3,"file":"setTheme.d.ts","sourceRoot":"","sources":["../../../src/themes/smart/setTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEnD,eAAO,MAAM,gBAAgB,kBAAmB,WAAW,WAmC1D,CAAA;AAED,eAAO,MAAM,WAAW,kBAAmB,WAAW,qBAOrD,CAAA;AAED,eAAO,MAAM,QAAQ,kBAAmB,WAAW,aAAa,WAAW,SAAS,KAAK,SACI,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@annotorious/annotorious",
3
- "version": "3.0.0-rc.1",
3
+ "version": "3.0.0-rc.11",
4
4
  "description": "Add image annotation functionality to any web page with a few lines of JavaScript",
5
5
  "author": "Rainer Simon",
6
6
  "license": "BSD-3-Clause",
@@ -33,9 +33,7 @@
33
33
  "require": "./dist/annotorious.js"
34
34
  },
35
35
  "./annotorious.css": "./dist/annotorious.css",
36
- "./src": "./src/index.ts",
37
- "./src/annotation": "./src/annotation/index.ts",
38
- "./src/model": "./src/model/index.ts"
36
+ "./src": "./src/index.ts"
39
37
  },
40
38
  "devDependencies": {
41
39
  "@sveltejs/vite-plugin-svelte": "^2.4.6",
@@ -48,6 +46,9 @@
48
46
  "vite-plugin-dts": "^3.6.0",
49
47
  "vitest": "^0.34.6"
50
48
  },
49
+ "peerDependencies": {
50
+ "@annotorious/core": "*"
51
+ },
51
52
  "dependencies": {
52
53
  "rbush": "^3.0.1",
53
54
  "uuid": "^9.0.1"
@@ -1,15 +1,16 @@
1
1
  import type { SvelteComponent } from 'svelte';
2
- import type { Annotator, DrawingStyle, User } from '@annotorious/core';
3
- import { createAnonymousGuest, createBaseAnnotator, createLifecyleObserver } from '@annotorious/core';
2
+ import type { Annotator, DrawingStyle, Filter, User } from '@annotorious/core';
3
+ import { createAnonymousGuest, createBaseAnnotator, createLifecyleObserver, createUndoStack } from '@annotorious/core';
4
4
  import { registerEditor } from './annotation/editors';
5
5
  import { getTool, registerTool, listDrawingTools, type DrawingTool } from './annotation/tools';
6
6
  import { SVGAnnotationLayer } from './annotation';
7
7
  import type { DrawingToolOpts, SVGAnnotationLayerPointerEvent } from './annotation';
8
8
  import type { ImageAnnotation, ShapeType } from './model';
9
9
  import { createSvelteImageAnnotatorState } from './state';
10
- import { setTheme } from './themes';
11
- import { fillDefaults } from './AnnotoriousOpts';
10
+ import { setTheme as _setTheme } from './themes';
11
+ import { fillDefaults, type Theme } from './AnnotoriousOpts';
12
12
  import type { AnnotoriousOpts } from './AnnotoriousOpts';
13
+ import { initKeyboardCommands } from './keyboardCommands';
13
14
 
14
15
  import './Annotorious.css';
15
16
  import './themes/dark/index.css';
@@ -23,10 +24,12 @@ export interface ImageAnnotator<E extends unknown = ImageAnnotation> extends Ann
23
24
 
24
25
  registerShapeEditor(shapeType: ShapeType, editor: typeof SvelteComponent): void;
25
26
 
26
- setDrawingTool(tool: DrawingTool): void;
27
+ setDrawingTool(name: DrawingTool): void;
27
28
 
28
29
  setDrawingEnabled(enabled: boolean): void;
29
30
 
31
+ setTheme(theme: Theme): void;
32
+
30
33
  }
31
34
 
32
35
  export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
@@ -44,14 +47,13 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
44
47
 
45
48
  const state = createSvelteImageAnnotatorState(opts);
46
49
 
47
- const { hover, selection, store } = state;
50
+ const { selection, store } = state;
48
51
 
49
- const lifecycle = createLifecyleObserver<ImageAnnotation, E>(
50
- store, selection, hover, undefined, opts.adapter, opts.autoSave);
52
+ const undoStack = createUndoStack(store);
51
53
 
52
- let currentUser: User = createAnonymousGuest();
53
-
54
- let style = opts.style;
54
+ const lifecycle = createLifecyleObserver<ImageAnnotation, E>(
55
+ state, undoStack, opts.adapter, opts.autoSave
56
+ );
55
57
 
56
58
  // We'll wrap the image in a container DIV.
57
59
  const container = document.createElement('DIV');
@@ -64,7 +66,11 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
64
66
  img.parentNode.insertBefore(container, img);
65
67
  container.appendChild(img);
66
68
 
67
- setTheme(img, container);
69
+ const keyboardCommands = initKeyboardCommands(undoStack);
70
+
71
+ let currentUser: User = createAnonymousGuest();
72
+
73
+ _setTheme(img, container, opts.theme);
68
74
 
69
75
  const annotationLayer = new SVGAnnotationLayer({
70
76
  target: container,
@@ -73,7 +79,7 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
73
79
  image: img,
74
80
  preferredDrawingMode: opts.drawingMode,
75
81
  state,
76
- style,
82
+ style: opts.style,
77
83
  user: currentUser
78
84
  }
79
85
  });
@@ -91,12 +97,7 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
91
97
  /******++++++*************/
92
98
 
93
99
  // Most of the external API functions are covered in the base annotator
94
- const base = createBaseAnnotator<ImageAnnotation, E>(store, opts.adapter);
95
-
96
- const setStyle = (drawingStyle: DrawingStyle | ((annotation: ImageAnnotation) => DrawingStyle) | undefined) => {
97
- style = drawingStyle;
98
- annotationLayer.$set({ style });
99
- }
100
+ const base = createBaseAnnotator<ImageAnnotation, E>(state, undoStack, opts.adapter);
100
101
 
101
102
  const destroy = () => {
102
103
  // Destroy Svelte annotation layer
@@ -105,6 +106,10 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
105
106
  // Unwrap the image
106
107
  container.parentNode.insertBefore(img, container);
107
108
  container.parentNode.removeChild(container);
109
+
110
+ // Other cleanup actions
111
+ keyboardCommands.destroy();
112
+ undoStack.destroy();
108
113
  }
109
114
 
110
115
  const getUser = () => currentUser;
@@ -115,23 +120,27 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
115
120
  const registerShapeEditor = (shapeType: ShapeType, editor: typeof SvelteComponent) =>
116
121
  registerEditor(shapeType, editor);
117
122
 
118
- const setDrawingTool = (t: DrawingTool) => {
119
- const { tool, opts } = getTool(t);
120
- // @ts-ignore
121
- annotationLayer.$set({ tool, opts })
123
+ const setDrawingTool = (name: DrawingTool) => {
124
+ // Validate that the tool exists
125
+ const toolSpec = getTool(name);
126
+ if (!toolSpec)
127
+ throw `No drawing tool named ${name}`;
128
+
129
+ annotationLayer.$set({ toolName: name })
122
130
  }
123
131
 
124
132
  const setDrawingEnabled = (enabled: boolean) =>
125
133
  annotationLayer.$set({ drawingEnabled: enabled });
126
-
127
- const setSelected = (arg?: string | string[]) => {
128
- if (arg) {
129
- selection.setSelected(arg);
130
- } else {
131
- selection.clear();
132
- }
134
+
135
+ const setFilter = (filter: Filter) => {
136
+ console.warn('Filter not implemented yet');
133
137
  }
134
138
 
139
+ const setStyle = (style: DrawingStyle | ((annotation: ImageAnnotation) => DrawingStyle) | undefined) =>
140
+ annotationLayer.$set({ style });
141
+
142
+ const setTheme = (theme: Theme) => _setTheme(img, container, theme);
143
+
135
144
  const setUser = (user: User) => {
136
145
  currentUser = user;
137
146
  annotationLayer.$set({ user });
@@ -139,8 +148,6 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
139
148
 
140
149
  return {
141
150
  ...base,
142
- get style() { return style },
143
- set style(s: DrawingStyle | ((annotation: ImageAnnotation) => DrawingStyle) | undefined) { setStyle(s) },
144
151
  destroy,
145
152
  getUser,
146
153
  listDrawingTools,
@@ -150,7 +157,9 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
150
157
  registerShapeEditor,
151
158
  setDrawingEnabled,
152
159
  setDrawingTool,
153
- setSelected,
160
+ setFilter,
161
+ setStyle,
162
+ setTheme,
154
163
  setUser,
155
164
  state
156
165
  }
@@ -18,10 +18,14 @@ export interface AnnotoriousOpts<I extends Annotation = ImageAnnotation, E exten
18
18
 
19
19
  style?: DrawingStyle | ((annotation: I) => DrawingStyle);
20
20
 
21
+ theme?: Theme;
22
+
21
23
  }
22
24
 
23
25
  export type DrawingMode = 'click' | 'drag';
24
26
 
27
+ export type Theme = 'dark' | 'light' | 'auto';
28
+
25
29
  export const fillDefaults = <I extends ImageAnnotation = ImageAnnotation, E extends unknown = ImageAnnotation> (
26
30
  opts: AnnotoriousOpts<I, E>
27
31
  ): AnnotoriousOpts<I, E> => {
@@ -30,7 +34,8 @@ export const fillDefaults = <I extends ImageAnnotation = ImageAnnotation, E exte
30
34
  ...opts,
31
35
  drawingEnabled: opts.drawingEnabled === undefined ? true : opts.drawingEnabled,
32
36
  drawingMode: opts.drawingMode || 'drag',
33
- pointerSelectAction: opts.pointerSelectAction || PointerSelectAction.EDIT
37
+ pointerSelectAction: opts.pointerSelectAction || PointerSelectAction.EDIT,
38
+ theme: opts.theme || 'light'
34
39
  };
35
40
 
36
41
  };
@@ -6,7 +6,7 @@
6
6
  import type { ImageAnnotation, Shape} from '../model';
7
7
  import { getEditor, EditorMount } from './editors';
8
8
  import { Ellipse, Polygon, Rectangle} from './shapes';
9
- import { getTool, ToolMount } from './tools';
9
+ import { getTool, listDrawingTools, ToolMount } from './tools';
10
10
  import { enableResponsive } from './utils';
11
11
  import { createSVGTransform } from './Transform';
12
12
  import { addEventListeners } from './SVGAnnotationLayerPointerEvent';
@@ -19,9 +19,11 @@
19
19
  export let preferredDrawingMode: DrawingMode;
20
20
  export let state: SvelteImageAnnotatorState;
21
21
  export let style: DrawingStyle | ((annotation: ImageAnnotation) => DrawingStyle) = undefined;
22
- export let { tool, opts } = getTool('rectangle');
22
+ export let toolName: string = listDrawingTools().length > 0 ? listDrawingTools()[0] : undefined;
23
23
  export let user: User;
24
24
 
25
+ $: ({ tool, opts } = getTool(toolName));
26
+
25
27
  $: drawingMode = opts?.drawingMode || preferredDrawingMode;
26
28
 
27
29
  /** Drawing tool layer **/
@@ -154,7 +156,7 @@
154
156
  {/key}
155
157
  {/each}
156
158
  {:else if (tool && drawingEnabled)}
157
- {#key tool}
159
+ {#key toolName}
158
160
  <ToolMount
159
161
  target={drawingEl}
160
162
  tool={tool}
@@ -13,11 +13,13 @@ export const IdentityTransform: Transform = {
13
13
  export const createSVGTransform = (svg: SVGSVGElement): Transform => ({
14
14
 
15
15
  elementToImage: (offsetX: number, offsetY: number) => {
16
+ const bbox = svg.getBoundingClientRect();
17
+
16
18
  const pt = svg.createSVGPoint();
17
- pt.x = offsetX;
18
- pt.y = offsetY;
19
+ pt.x = offsetX + bbox.x;
20
+ pt.y = offsetY + bbox.y;
19
21
 
20
- const { x, y } = pt.matrixTransform(svg.getCTM().inverse());
22
+ const { x, y } = pt.matrixTransform(svg.getScreenCTM().inverse());
21
23
  return [x, y];
22
24
  }
23
25
 
@@ -19,8 +19,8 @@
19
19
 
20
20
  $: computedStyle = computeStyle(annotation, style);
21
21
 
22
+ $: if (annotation) editorComponent?.$set({ shape: annotation.target.selector });
22
23
  $: if (editorComponent) editorComponent.$set({ transform });
23
-
24
24
  $: if (editorComponent) editorComponent.$set({ viewportScale });
25
25
 
26
26
  onMount(() => {
@@ -10,7 +10,7 @@
10
10
 
11
11
  $: computedStyle = computeStyle(annotation, style);
12
12
 
13
- const { x, y, w, h } = geom as RectangleGeometry;
13
+ $: ({ x, y, w, h } = geom as RectangleGeometry);
14
14
  </script>
15
15
 
16
16
  <g data-id={annotation.id}>
@@ -1,7 +1,7 @@
1
1
  <script type="ts">
2
2
  import { onMount, createEventDispatcher } from 'svelte';
3
3
  import type { DrawingMode } from '../../../AnnotoriousOpts';
4
- import { boundsFromPoints, ShapeType, type Polygon } from '../../../model';
4
+ import { boundsFromPoints, computeArea, ShapeType, type Polygon } from '../../../model';
5
5
  import { distance } from '../../utils';
6
6
  import type { Transform } from '../..';
7
7
 
@@ -13,9 +13,7 @@
13
13
  export let transform: Transform;
14
14
  export let viewportScale = 1;
15
15
 
16
- let container: SVGGElement;
17
-
18
- let lastPointerDown: number;
16
+ let lastPointerDown: { timeStamp: number, offsetX: number, offsetY: number };
19
17
 
20
18
  let points: [number, number][] = [];
21
19
 
@@ -28,7 +26,9 @@
28
26
  $: handleSize = 10 / viewportScale;
29
27
 
30
28
  const onPointerDown = (evt: PointerEvent) => {
31
- lastPointerDown = performance.now();
29
+ // Note that the event itself is ephemeral!
30
+ const { timeStamp, offsetX, offsetY } = evt;
31
+ lastPointerDown = { timeStamp, offsetX, offsetY };
32
32
 
33
33
  if (drawingMode === 'drag') {
34
34
  if (points.length === 0) {
@@ -52,14 +52,15 @@
52
52
  }
53
53
 
54
54
  const onPointerUp = (evt: PointerEvent) => {
55
- const timeDifference = performance.now() - lastPointerDown;
56
-
57
55
  if (drawingMode === 'click') {
58
- // Not a single click - ignore
59
- if (timeDifference > 300)
60
- return;
56
+ const timeDifference = evt.timeStamp - lastPointerDown.timeStamp;
61
57
 
62
- evt.stopPropagation();
58
+ const d = distance(
59
+ [lastPointerDown.offsetX, lastPointerDown.offsetY],
60
+ [evt.offsetX, evt.offsetY]);
61
+
62
+ if (timeDifference > 300 || d > 15) // Not a single click - ignore
63
+ return;
63
64
 
64
65
  if (isClosable) {
65
66
  stopDrawing();
@@ -98,22 +99,25 @@
98
99
  }
99
100
 
100
101
  const onDblClick = () => {
101
- console.log('dblclick');
102
-
102
+ // Require min 3 points (incl. cursor) and minimum
103
+ // polygon area
103
104
  const p = [...points, cursor];
104
105
 
105
106
  const shape: Polygon = {
106
- type: ShapeType.POLYGON,
107
- geometry: {
108
- bounds: boundsFromPoints(p),
109
- points: p
110
- }
107
+ type: ShapeType.POLYGON,
108
+ geometry: {
109
+ bounds: boundsFromPoints(p),
110
+ points: p
111
111
  }
112
+ }
112
113
 
114
+ const area = computeArea(shape);
115
+ if (area > 4) {
113
116
  points = [];
114
117
  cursor = null;
115
118
 
116
119
  dispatch('create', shape);
120
+ }
117
121
  }
118
122
 
119
123
  const stopDrawing = () => {
@@ -139,10 +143,7 @@
139
143
  });
140
144
  </script>
141
145
 
142
- <g
143
- bind:this={container}
144
- class="a9s-annotation a9s-rubberband">
145
-
146
+ <g class="a9s-annotation a9s-rubberband">
146
147
  {#if cursor}
147
148
  {@const coords = (isClosable ? points : [...points, cursor]).map(xy => xy.join(',')).join(' ')}
148
149
  <polygon
@@ -10,8 +10,6 @@
10
10
  export let addEventListener: (type: string, fn: EventListener, capture?: boolean) => void;
11
11
  export let drawingMode: DrawingMode;
12
12
  export let transform: Transform;
13
-
14
- let container: SVGGElement;
15
13
 
16
14
  let lastPointerDown: number;
17
15
 
@@ -109,10 +107,7 @@
109
107
  });
110
108
  </script>
111
109
 
112
- <g
113
- bind:this={container}
114
- class="a9s-annotation a9s-rubberband">
115
-
110
+ <g class="a9s-annotation a9s-rubberband">
116
111
  {#if origin}
117
112
  <rect
118
113
  class="a9s-outer"
package/src/index.ts CHANGED
@@ -5,16 +5,34 @@ export * from './themes';
5
5
  export * from './annotation/tools';
6
6
  export * from './Annotorious';
7
7
  export * from './AnnotoriousOpts';
8
+ export * from './keyboardCommands';
8
9
 
9
- // Re-export essentials from @annotorious/core utilities for convenience
10
- export * from '@annotorious/core/src/model';
11
- export * from '@annotorious/core/src/presence';
12
- export * from '@annotorious/core/src/utils';
13
-
14
- export type {
10
+ // Essential re-exports from @annotorious/core
11
+ export type {
12
+ Annotation,
13
+ AnnotationBody,
14
+ AnnotationTarget,
15
+ Annotator,
16
+ AnnotatorState,
17
+ Appearance,
18
+ AppearanceProvider,
19
+ Color,
20
+ DrawingStyle,
21
+ Filter,
22
+ FormatAdapter,
15
23
  HoverState,
24
+ LifecycleEvents,
25
+ ParseResult,
26
+ PresentUser,
27
+ Purpose,
16
28
  Selection,
17
29
  SelectionState,
18
30
  Store,
19
- StoreObserver
20
- } from '@annotorious/core/src/state';
31
+ StoreChangeEvent,
32
+ StoreObserver,
33
+ User,
34
+ W3CAnnotation,
35
+ W3CAnnotationBody,
36
+ W3CAnnotationTarget,
37
+ W3CSelector
38
+ } from '@annotorious/core';
@@ -0,0 +1,46 @@
1
+ import type { Annotation, UndoStack } from '@annotorious/core';
2
+
3
+ const isMac = navigator.userAgent.indexOf('Mac OS X') !== -1;
4
+
5
+ export const initKeyboardCommands = <T extends Annotation>(
6
+ undoStack: UndoStack<T>,
7
+ container?: Element
8
+ ) => {
9
+
10
+ const el = container || document;
11
+
12
+ const onWinKeyDown = (event: KeyboardEvent) => {
13
+ if (event.key === 'Z' && event.ctrlKey) {
14
+ undoStack.undo();
15
+ } else if (event.key === 'Y' && event.ctrlKey) {
16
+ undoStack.redo()
17
+ }
18
+ };
19
+
20
+ const onMacKeyDown = (event: KeyboardEvent) => {
21
+ if (event.key === 'z' && event.metaKey) {
22
+ if (event.shiftKey) {
23
+ undoStack.redo()
24
+ } else {
25
+ undoStack.undo();
26
+ }
27
+ }
28
+ }
29
+
30
+ const destroy = () => {
31
+ if (isMac) {
32
+ el.removeEventListener('keydown', onMacKeyDown);
33
+ } else {
34
+ el.removeEventListener('keydown', onWinKeyDown);
35
+ }
36
+ }
37
+
38
+ if (isMac)
39
+ el.addEventListener('keydown', onMacKeyDown);
40
+ else
41
+ el.addEventListener('keydown', onWinKeyDown);
42
+
43
+ return {
44
+ destroy
45
+ }
46
+ }
@@ -30,7 +30,9 @@ export const parseW3CImageAnnotation = (
30
30
  ): ParseResult<ImageAnnotation> => {
31
31
  const annotationId = annotation.id || uuidv4();
32
32
 
33
- const bodies = parseW3CBodies(annotation.body, annotationId);
33
+ const { body, ...rest } = annotation;
34
+
35
+ const bodies = parseW3CBodies(body, annotationId);
34
36
 
35
37
  const target = Array.isArray(annotation.target) ? annotation.target[0] : annotation.target;
36
38
 
@@ -44,16 +46,17 @@ export const parseW3CImageAnnotation = (
44
46
 
45
47
  return selector ? {
46
48
  parsed: {
47
- ...annotation,
49
+ ...rest,
48
50
  id: annotationId,
49
51
  bodies,
50
52
  target: {
53
+ ...rest.target,
51
54
  annotation: annotationId,
52
55
  selector
53
56
  }
54
57
  }
55
58
  } : {
56
- error: Error(`Unknown selector type: ${selector.type}`)
59
+ error: Error(`Unknown selector type: ${w3cSelector.type}`)
57
60
  };
58
61
 
59
62
  }
@@ -1,3 +1,5 @@
1
+ import type { Theme } from '../../AnnotoriousOpts';
2
+
1
3
  export const sampleBrightness = (imageOrCanvas: HTMLElement) => {
2
4
 
3
5
  let canvas: HTMLCanvasElement;
@@ -35,12 +37,14 @@ export const sampleBrightness = (imageOrCanvas: HTMLElement) => {
35
37
  return totalBrightness / 81;
36
38
  }
37
39
 
38
- export const setTheme = (imageOrCanvas: HTMLElement, container: HTMLElement) => {
40
+ export const detectTheme = (imageOrCanvas: HTMLElement) => {
39
41
  const brightness = sampleBrightness(imageOrCanvas);
40
-
41
42
  const theme = brightness > 0.6 ? 'dark' : 'light'
42
43
 
43
44
  console.log(`[Annotorious] Image brightness: ${brightness.toFixed(1)}. Setting ${theme} theme.`);
44
45
 
45
- container.setAttribute('data-theme', theme);
46
- }
46
+ return theme;
47
+ }
48
+
49
+ export const setTheme = (imageOrCanvas: HTMLElement, container: HTMLElement, theme: Theme) =>
50
+ container.setAttribute('data-theme', theme === 'auto' ? detectTheme(imageOrCanvas) : theme);