@annotorious/annotorious 3.0.0-rc.3 → 3.0.0-rc.31

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.
Files changed (93) hide show
  1. package/dist/Annotorious.d.ts +10 -7
  2. package/dist/Annotorious.d.ts.map +1 -1
  3. package/dist/AnnotoriousOpts.d.ts +8 -6
  4. package/dist/AnnotoriousOpts.d.ts.map +1 -1
  5. package/dist/annotation/SVGAnnotationLayerPointerEvent.d.ts +4 -2
  6. package/dist/annotation/SVGAnnotationLayerPointerEvent.d.ts.map +1 -1
  7. package/dist/annotation/editors/Handle.svelte.d.ts +1 -0
  8. package/dist/annotation/editors/editorsRegistry.d.ts +4 -3
  9. package/dist/annotation/editors/editorsRegistry.d.ts.map +1 -1
  10. package/dist/annotation/editors/index.d.ts +1 -1
  11. package/dist/annotation/editors/index.d.ts.map +1 -1
  12. package/dist/annotation/tools/DrawingToolConfig.d.ts +2 -1
  13. package/dist/annotation/tools/drawingToolsRegistry.d.ts +5 -4
  14. package/dist/annotation/tools/drawingToolsRegistry.d.ts.map +1 -1
  15. package/dist/annotation/utils/responsive.d.ts +1 -1
  16. package/dist/annotation/utils/styling.d.ts +4 -3
  17. package/dist/annotation/utils/styling.d.ts.map +1 -1
  18. package/dist/annotation/utils/touch.d.ts.map +1 -1
  19. package/dist/annotorious.css +1 -1
  20. package/dist/annotorious.es.js +2540 -2178
  21. package/dist/annotorious.es.js.map +1 -1
  22. package/dist/annotorious.js +1 -1
  23. package/dist/annotorious.js.map +1 -1
  24. package/dist/index.d.ts +1 -7
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/keyboardCommands.d.ts +3 -2
  27. package/dist/keyboardCommands.d.ts.map +1 -1
  28. package/dist/model/core/ImageAnnotation.d.ts +3 -2
  29. package/dist/model/core/Shape.d.ts +2 -1
  30. package/dist/model/core/ellipse/Ellipse.d.ts +2 -1
  31. package/dist/model/core/polygon/Polygon.d.ts +2 -1
  32. package/dist/model/core/rectangle/Rectangle.d.ts +2 -1
  33. package/dist/model/core/rectangle/rectangleUtils.d.ts +3 -2
  34. package/dist/model/core/shapeUtils.d.ts +3 -5
  35. package/dist/model/core/shapeUtils.d.ts.map +1 -1
  36. package/dist/model/w3c/W3CImageAnnotation.d.ts +12 -0
  37. package/dist/model/w3c/W3CImageAnnotation.d.ts.map +1 -0
  38. package/dist/model/w3c/W3CImageFormatAdapter.d.ts +12 -6
  39. package/dist/model/w3c/W3CImageFormatAdapter.d.ts.map +1 -1
  40. package/dist/model/w3c/fragment/FragmentSelector.d.ts +3 -3
  41. package/dist/model/w3c/fragment/FragmentSelector.d.ts.map +1 -1
  42. package/dist/model/w3c/index.d.ts +1 -0
  43. package/dist/model/w3c/index.d.ts.map +1 -1
  44. package/dist/model/w3c/svg/SVG.d.ts.map +1 -1
  45. package/dist/model/w3c/svg/SVGSelector.d.ts +3 -3
  46. package/dist/model/w3c/svg/SVGSelector.d.ts.map +1 -1
  47. package/dist/state/ImageAnnotationStore.d.ts +3 -2
  48. package/dist/state/ImageAnnotatorState.d.ts +5 -4
  49. package/dist/state/ImageAnnotatorState.d.ts.map +1 -1
  50. package/dist/state/spatialTree.d.ts +3 -2
  51. package/dist/state/spatialTree.d.ts.map +1 -1
  52. package/dist/themes/smart/setTheme.d.ts +4 -1
  53. package/dist/themes/smart/setTheme.d.ts.map +1 -1
  54. package/package.json +16 -16
  55. package/src/Annotorious.css +9 -5
  56. package/src/Annotorious.ts +52 -36
  57. package/src/AnnotoriousOpts.ts +16 -15
  58. package/src/annotation/SVGAnnotationLayer.svelte +71 -36
  59. package/src/annotation/SVGAnnotationLayerPointerEvent.ts +2 -3
  60. package/src/annotation/Transform.ts +1 -1
  61. package/src/annotation/editors/Editor.svelte +10 -11
  62. package/src/annotation/editors/EditorMount.svelte +3 -3
  63. package/src/annotation/editors/Handle.svelte +66 -0
  64. package/src/annotation/editors/editorsRegistry.ts +2 -2
  65. package/src/annotation/editors/index.ts +2 -2
  66. package/src/annotation/editors/polygon/PolygonEditor.svelte +16 -16
  67. package/src/annotation/editors/rectangle/RectangleEditor.svelte +46 -43
  68. package/src/annotation/shapes/Ellipse.svelte +3 -3
  69. package/src/annotation/shapes/Polygon.svelte +3 -3
  70. package/src/annotation/shapes/Rectangle.svelte +3 -3
  71. package/src/annotation/tools/ToolMount.svelte +3 -3
  72. package/src/annotation/tools/drawingToolsRegistry.ts +2 -1
  73. package/src/annotation/tools/polygon/RubberbandPolygon.svelte +40 -13
  74. package/src/annotation/tools/rectangle/RubberbandRectangle.svelte +27 -11
  75. package/src/annotation/utils/responsive.ts +1 -1
  76. package/src/annotation/utils/styling.ts +5 -2
  77. package/src/annotation/utils/touch.ts +4 -1
  78. package/src/index.ts +22 -16
  79. package/src/keyboardCommands.ts +11 -7
  80. package/src/model/w3c/W3CImageAnnotation.ts +17 -0
  81. package/src/model/w3c/W3CImageFormatAdapter.ts +79 -31
  82. package/src/model/w3c/fragment/FragmentSelector.ts +5 -6
  83. package/src/model/w3c/index.ts +1 -0
  84. package/src/model/w3c/svg/SVG.ts +1 -2
  85. package/src/model/w3c/svg/SVGSelector.ts +11 -13
  86. package/src/state/ImageAnnotatorState.ts +4 -5
  87. package/src/state/spatialTree.ts +13 -6
  88. package/src/themes/dark/index.css +2 -2
  89. package/src/themes/light/index.css +2 -2
  90. package/src/themes/smart/setTheme.ts +10 -6
  91. package/dist/annotation/editors/Handle.d.ts +0 -14
  92. package/dist/annotation/editors/Handle.d.ts.map +0 -1
  93. package/src/annotation/editors/Handle.ts +0 -21
@@ -1,15 +1,15 @@
1
- <script type="ts">
2
- import { onMount, type SvelteComponent } from 'svelte';
1
+ <script lang="ts">
2
+ import { SvelteComponent, onMount } from 'svelte';
3
3
  import { v4 as uuidv4 } from 'uuid';
4
- import type { DrawingStyle, StoreChangeEvent, User } from '@annotorious/core';
4
+ import type { DrawingStyleExpression, StoreChangeEvent, User } from '@annotorious/core';
5
5
  import { ShapeType } from '../model';
6
6
  import type { ImageAnnotation, Shape} from '../model';
7
- import { getEditor, EditorMount } from './editors';
7
+ import { getEditor as _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
- import { addEventListeners } from './SVGAnnotationLayerPointerEvent';
12
+ import { addEventListeners, getSVGPoint } from './SVGAnnotationLayerPointerEvent';
13
13
  import type { SvelteImageAnnotatorState } from 'src/state';
14
14
  import type { DrawingMode } from 'src/AnnotoriousOpts';
15
15
 
@@ -18,9 +18,12 @@
18
18
  export let image: HTMLImageElement | HTMLCanvasElement;
19
19
  export let preferredDrawingMode: DrawingMode;
20
20
  export let state: SvelteImageAnnotatorState;
21
- export let style: DrawingStyle | ((annotation: ImageAnnotation) => DrawingStyle) = undefined;
22
- export let { tool, opts } = getTool('rectangle');
21
+ export let style: DrawingStyleExpression<ImageAnnotation> | undefined = undefined;
22
+ export let toolName: string = listDrawingTools()[0];
23
23
  export let user: User;
24
+ export let visible = true;
25
+
26
+ $: ({ tool, opts } = getTool(toolName) || { tool: undefined, opts: undefined });
24
27
 
25
28
  $: drawingMode = opts?.drawingMode || preferredDrawingMode;
26
29
 
@@ -37,20 +40,21 @@
37
40
  $: transform = createSVGTransform(svgEl);
38
41
 
39
42
  /** Selection tracking */
40
- const { selection, store } = state;
43
+ const { hover, selection, store } = state;
41
44
 
42
45
  $: ({ onPointerDown, onPointerUp } = addEventListeners(svgEl, store));
43
46
 
44
- let storeObserver = null;
47
+ let storeObserver: (event: StoreChangeEvent<ImageAnnotation>) => void | undefined;
45
48
 
46
- let editableAnnotations: ImageAnnotation[] = null;
49
+ let editableAnnotations: ImageAnnotation[] | undefined;
47
50
 
48
51
  $: isEditable = (a: ImageAnnotation) => $selection.selected.find(s => s.id === a.id && s.editable);
49
52
 
50
53
  $: trackSelection($selection.selected);
51
54
 
52
55
  const trackSelection = (selected: { id: string, editable?: boolean }[]) => {
53
- store.unobserve(storeObserver);
56
+ if (storeObserver)
57
+ store.unobserve(storeObserver);
54
58
 
55
59
  // Track only editable annotations
56
60
  const editableIds =
@@ -58,17 +62,17 @@
58
62
 
59
63
  if (editableIds.length > 0) {
60
64
  // Resolve selected IDs from the store
61
- editableAnnotations = editableIds.map(id => store.getAnnotation(id));
65
+ editableAnnotations = editableIds.map(id => store.getAnnotation(id)!).filter(Boolean);
62
66
 
63
67
  // Track updates on the editable annotations
64
68
  storeObserver = (event: StoreChangeEvent<ImageAnnotation>) => {
65
69
  const { updated } = event.changes;
66
- editableAnnotations = updated.map(change => change.newValue);
70
+ editableAnnotations = updated?.map(change => change.newValue);
67
71
  }
68
72
 
69
73
  store.observe(storeObserver, { annotations: editableIds });
70
74
  } else {
71
- editableAnnotations = null;
75
+ editableAnnotations = undefined;
72
76
  }
73
77
  }
74
78
 
@@ -106,30 +110,58 @@
106
110
  ...target,
107
111
  selector: event.detail,
108
112
  created: isUpdate ? target.created : new Date(),
109
- updated: isUpdate ? new Date() : null,
110
- updatedBy: isUpdate ? user : null
113
+ updated: isUpdate ? new Date() : undefined,
114
+ updatedBy: isUpdate ? user : undefined
111
115
  });
112
116
  }
117
+
118
+ const onPointerMove = (evt: PointerEvent) => {
119
+ const { x, y } = getSVGPoint(evt, svgEl);
120
+
121
+ const hit = store.getAt(x, y);
122
+ if (hit) {
123
+ if ($hover !== hit.id) {
124
+ hover.set(hit.id);
125
+ }
126
+ } else {
127
+ hover.set(undefined);
128
+ }
129
+ }
130
+
131
+ // To get around lack of TypeScript support in Svelte markup
132
+ const getEditor = (shape: Shape): typeof SvelteComponent => _getEditor(shape)!;
113
133
  </script>
114
134
 
115
135
  <svg
116
136
  bind:this={svgEl}
117
137
  class="a9s-annotationlayer"
118
138
  class:drawing={tool}
139
+ class:hidden={!visible}
140
+ class:hover={$hover}
119
141
  on:pointerup={onPointerUp}
120
- on:pointerdown={onPointerDown}>
142
+ on:pointerdown={onPointerDown}
143
+ on:pointermove={onPointerMove}>
121
144
 
122
145
  <g>
123
146
  {#each $store as annotation}
124
147
  {#if !isEditable(annotation)}
125
148
  {@const selector = annotation.target.selector}
126
149
  {#key annotation.id}
127
- {#if (selector.type === ShapeType.ELLIPSE)}
128
- <Ellipse annotation={annotation} geom={selector.geometry} style={style} />
129
- {:else if (selector.type === ShapeType.RECTANGLE)}
130
- <Rectangle annotation={annotation} geom={selector.geometry} style={style} />
131
- {:else if (selector.type === ShapeType.POLYGON)}
132
- <Polygon annotation={annotation} geom={selector.geometry} style={style} />
150
+ {#if (selector?.type === ShapeType.ELLIPSE)}
151
+ <Ellipse
152
+ annotation={annotation}
153
+ geom={selector?.geometry}
154
+ style={style} />
155
+ {:else if (selector?.type === ShapeType.RECTANGLE)}
156
+ <Rectangle
157
+ annotation={annotation}
158
+ geom={selector.geometry}
159
+ style={style} />
160
+ {:else if (selector?.type === ShapeType.POLYGON)}
161
+ <Polygon
162
+ annotation={annotation}
163
+ geom={selector.geometry}
164
+ style={style} />
133
165
  {/if}
134
166
  {/key}
135
167
  {/if}
@@ -142,19 +174,22 @@
142
174
  {#if drawingEl}
143
175
  {#if editableAnnotations}
144
176
  {#each editableAnnotations as editable}
145
- {#key editable.id}
146
- <EditorMount
147
- target={drawingEl}
148
- editor={getEditor(editable.target.selector)}
149
- annotation={editable}
150
- style={style}
151
- transform={transform}
152
- viewportScale={$scale}
153
- on:change={onChangeSelected(editable)} />
154
- {/key}
177
+ {@const editor = getEditor(editable.target.selector)}
178
+ {#if editor}
179
+ {#key editable.id}
180
+ <EditorMount
181
+ target={drawingEl}
182
+ editor={getEditor(editable.target.selector)}
183
+ annotation={editable}
184
+ style={style}
185
+ transform={transform}
186
+ viewportScale={$scale}
187
+ on:change={onChangeSelected(editable)} />
188
+ {/key}
189
+ {/if}
155
190
  {/each}
156
191
  {:else if (tool && drawingEnabled)}
157
- {#key tool}
192
+ {#key toolName}
158
193
  <ToolMount
159
194
  target={drawingEl}
160
195
  tool={tool}
@@ -166,4 +201,4 @@
166
201
  {/if}
167
202
  {/if}
168
203
  </g>
169
- </svg>
204
+ </svg>
@@ -1,7 +1,6 @@
1
1
  import { createEventDispatcher } from 'svelte';
2
2
  import type { SvelteImageAnnotationStore } from '../state';
3
3
  import type { ImageAnnotation } from '../model';
4
- import { isTouch } from './utils';
5
4
 
6
5
  export interface SVGAnnotationLayerPointerEvent {
7
6
 
@@ -40,7 +39,7 @@ export const addEventListeners = (svg: SVGSVGElement, store: SvelteImageAnnotati
40
39
  return { onPointerDown, onPointerUp };
41
40
  }
42
41
 
43
- const getSVGPoint = (evt: PointerEvent, svg: SVGSVGElement) => {
42
+ export const getSVGPoint = (evt: PointerEvent, svg: SVGSVGElement) => {
44
43
  const pt = svg.createSVGPoint();
45
44
  const bbox = svg.getBoundingClientRect();
46
45
 
@@ -51,5 +50,5 @@ const getSVGPoint = (evt: PointerEvent, svg: SVGSVGElement) => {
51
50
  pt.x = x + left;
52
51
  pt.y = y + top;
53
52
 
54
- return pt.matrixTransform(svg.getScreenCTM().inverse());
53
+ return pt.matrixTransform(svg.getScreenCTM()!.inverse());
55
54
  }
@@ -19,7 +19,7 @@ export const createSVGTransform = (svg: SVGSVGElement): Transform => ({
19
19
  pt.x = offsetX + bbox.x;
20
20
  pt.y = offsetY + bbox.y;
21
21
 
22
- const { x, y } = pt.matrixTransform(svg.getScreenCTM().inverse());
22
+ const { x, y } = pt.matrixTransform(svg.getScreenCTM()!.inverse());
23
23
  return [x, y];
24
24
  }
25
25
 
@@ -1,23 +1,22 @@
1
- <script type="ts">
1
+ <script lang="ts">
2
2
  import { createEventDispatcher } from 'svelte';
3
3
  import type { Shape } from '../../model';
4
- import type { Handle } from './Handle';
5
4
  import type { Transform } from '../Transform';
6
5
 
7
- const dispatch = createEventDispatcher<{ grab: undefined, release: undefined, change: Shape }>();
6
+ const dispatch = createEventDispatcher<{ grab: PointerEvent, release: PointerEvent, change: Shape }>();
8
7
 
9
8
  /** Props */
10
9
  export let shape: Shape;
11
- export let editor: (shape: Shape, handle: Handle, delta: [number, number]) => Shape;
10
+ export let editor: (shape: Shape, handle: string, delta: [number, number]) => Shape;
12
11
  export let transform: Transform;
13
12
 
14
- let grabbedHandle: Handle = null;
13
+ let grabbedHandle: string | undefined;
15
14
 
16
15
  let origin: [number, number];
17
16
 
18
- let initialShape: Shape = null;
17
+ let initialShape: Shape | undefined;
19
18
 
20
- const onGrab = (handle: Handle) => (evt: PointerEvent) => {
19
+ const onGrab = (handle: string) => (evt: PointerEvent) => {
21
20
  grabbedHandle = handle;
22
21
  origin = transform.elementToImage(evt.offsetX, evt.offsetY);
23
22
  initialShape = shape;
@@ -25,7 +24,7 @@
25
24
  const target = evt.target as Element;
26
25
  target.setPointerCapture(evt.pointerId);
27
26
 
28
- dispatch('grab');
27
+ dispatch('grab', evt);
29
28
  }
30
29
 
31
30
  const onPointerMove = (evt: PointerEvent) => {
@@ -34,7 +33,7 @@
34
33
 
35
34
  const delta: [number, number] = [x - origin[0], y - origin[1]];
36
35
 
37
- shape = editor(initialShape, grabbedHandle, delta);
36
+ shape = editor(initialShape!, grabbedHandle, delta);
38
37
 
39
38
  dispatch('change', shape);
40
39
  }
@@ -44,11 +43,11 @@
44
43
  const target = evt.target as Element;
45
44
  target.releasePointerCapture(evt.pointerId);
46
45
 
47
- grabbedHandle = null;
46
+ grabbedHandle = undefined;
48
47
 
49
48
  initialShape = shape;
50
49
 
51
- dispatch('release');
50
+ dispatch('release', evt);
52
51
  }
53
52
  </script>
54
53
 
@@ -1,16 +1,16 @@
1
1
  <script lang="ts">
2
- import type { DrawingStyle } from '@annotorious/core';
2
+ import type { DrawingStyleExpression } from '@annotorious/core';
3
3
  import { createEventDispatcher, onMount, type SvelteComponent } from 'svelte';
4
4
  import type { ImageAnnotation, Shape } from '../../model';
5
5
  import { computeStyle } from '../utils/styling';
6
6
  import type { Transform } from '../Transform';
7
7
 
8
- const dispatch = createEventDispatcher<{ grab: undefined, release: undefined, change: Shape }>();
8
+ const dispatch = createEventDispatcher<{ grab: PointerEvent, release: PointerEvent, change: Shape }>();
9
9
 
10
10
  /** Props */
11
11
  export let annotation: ImageAnnotation;
12
12
  export let editor: typeof SvelteComponent;
13
- export let style: DrawingStyle | ((annotation: ImageAnnotation) => DrawingStyle) = undefined;
13
+ export let style: DrawingStyleExpression<ImageAnnotation> | undefined;
14
14
  export let target: SVGGElement;
15
15
  export let transform: Transform;
16
16
  export let viewportScale: number;
@@ -0,0 +1,66 @@
1
+ <script lang="ts">
2
+ import { isTouch } from '../utils';
3
+
4
+ /** props **/
5
+ export let x: number;
6
+ export let y: number;
7
+ export let scale: number;
8
+ export let radius: number = 30;
9
+
10
+ let touched = false;
11
+
12
+ const onPointerDown = (event: PointerEvent) => {
13
+ if (event.pointerType === 'touch')
14
+ touched = true;
15
+ }
16
+
17
+ const onPointerUp = () =>
18
+ touched = false;
19
+
20
+ $: handleSize = 10 / scale;
21
+ </script>
22
+
23
+ {#if isTouch}
24
+ <g class="a9s-touch-handle">
25
+ <circle
26
+ cx={x}
27
+ cy={y}
28
+ r={radius / scale}
29
+ class="a9s-touch-halo"
30
+ class:touched={touched}
31
+ on:pointerdown
32
+ on:pointerdown={onPointerDown}
33
+ on:pointerup={onPointerUp} />
34
+
35
+ <rect
36
+ class={`a9s-handle ${$$props.class || ''}`.trim()}
37
+ x={x - handleSize / 2}
38
+ y={y - handleSize / 2}
39
+ width={handleSize}
40
+ height={handleSize}
41
+ on:pointerdown
42
+ on:pointerdown={onPointerDown}
43
+ on:pointerup={onPointerUp} />
44
+ </g>
45
+ {:else}
46
+ <rect
47
+ class={`a9s-handle ${$$props.class || ''}`.trim()}
48
+ x={x - handleSize / 2}
49
+ y={y - handleSize / 2}
50
+ width={handleSize}
51
+ height={handleSize}
52
+ on:pointerdown />
53
+ {/if}
54
+
55
+ <style>
56
+ .a9s-touch-halo {
57
+ fill: transparent;
58
+ stroke-width: 0;
59
+ }
60
+
61
+ .a9s-touch-halo.touched {
62
+ fill: rgba(255, 255, 255, 0.25);
63
+ }
64
+
65
+
66
+ </style>
@@ -4,8 +4,8 @@ import { PolygonEditor } from './polygon';
4
4
  import { RectangleEditor } from './rectangle';
5
5
 
6
6
  const REGISTERED = new Map<ShapeType, typeof SvelteComponent>([
7
- [ShapeType.RECTANGLE, RectangleEditor],
8
- [ShapeType.POLYGON, PolygonEditor]
7
+ [ShapeType.RECTANGLE, RectangleEditor as typeof SvelteComponent],
8
+ [ShapeType.POLYGON, PolygonEditor as typeof SvelteComponent]
9
9
  ]);
10
10
 
11
11
  export const getEditor = (shape: Shape) => REGISTERED.get(shape.type);
@@ -1,7 +1,7 @@
1
1
  export * from './polygon';
2
2
  export * from './rectangle';
3
3
  export * from './editorsRegistry';
4
- export * from './Handle';
5
4
 
6
5
  export { default as Editor } from './Editor.svelte';
7
- export { default as EditorMount } from './EditorMount.svelte';
6
+ export { default as EditorMount } from './EditorMount.svelte';
7
+ export { default as Handle } from './Handle.svelte';
@@ -1,27 +1,27 @@
1
- <script type="ts">
1
+ <script lang="ts">
2
2
  import { boundsFromPoints } from '../../../model';
3
- import type { Polygon } from '../../../model';
3
+ import type { Polygon, PolygonGeometry, Shape } from '../../../model';
4
4
  import type { Transform } from '../../Transform';
5
5
  import { Editor, Handle } from '..';
6
6
 
7
7
  /** Props */
8
8
  export let shape: Polygon;
9
- export let computedStyle: string = undefined;
9
+ export let computedStyle: string | undefined;
10
10
  export let transform: Transform;
11
11
  export let viewportScale: number = 1;
12
12
 
13
13
  $: geom = shape.geometry;
14
14
 
15
- $: handleSize = 10 / viewportScale;
16
-
17
- const editor = (polygon: Polygon, handle: Handle, delta: [number, number]) => {
15
+ const editor = (polygon: Shape, handle: string, delta: [number, number]) => {
18
16
  let points: [number, number][];
19
17
 
20
- if (handle === Handle.SHAPE) {
21
- points = polygon.geometry.points.map(([x, y]) => [x + delta[0], y + delta[1]]);
18
+ const geom = (polygon.geometry) as PolygonGeometry;
19
+
20
+ if (handle === 'SHAPE') {
21
+ points = geom.points.map(([x, y]) => [x + delta[0], y + delta[1]]);
22
22
  } else {
23
- points = polygon.geometry.points.map(([x, y], idx) =>
24
- handle === Handle(idx) ? [x + delta[0], y + delta[1]] : [x, y]
23
+ points = geom.points.map(([x, y], idx) =>
24
+ handle === `HANDLE-${idx}` ? [x + delta[0], y + delta[1]] : [x, y]
25
25
  );
26
26
  }
27
27
 
@@ -46,19 +46,19 @@
46
46
  <polygon
47
47
  class="a9s-outer"
48
48
  style={computedStyle ? 'display:none;' : undefined}
49
- on:pointerdown={grab(Handle.SHAPE)}
49
+ on:pointerdown={grab('SHAPE')}
50
50
  points={geom.points.map(xy => xy.join(',')).join(' ')} />
51
51
 
52
52
  <polygon
53
53
  class="a9s-inner a9s-shape-handle"
54
54
  style={computedStyle}
55
- on:pointerdown={grab(Handle.SHAPE)}
55
+ on:pointerdown={grab('SHAPE')}
56
56
  points={geom.points.map(xy => xy.join(',')).join(' ')} />
57
57
 
58
58
  {#each geom.points as point, idx}
59
- <rect
60
- class="a9s-corner-handle"
61
- on:pointerdown={grab(Handle(idx))}
62
- x={point[0] - handleSize / 2} y={point[1] - handleSize / 2} height={handleSize} width={handleSize} />
59
+ <Handle
60
+ on:pointerdown={grab(`HANDLE-${idx}`)}
61
+ x={point[0]} y={point[1]}
62
+ scale={viewportScale} />
63
63
  {/each}
64
64
  </Editor>
@@ -1,19 +1,18 @@
1
- <script type="ts">
2
- import type { Rectangle } from '../../../model';
1
+ <script lang="ts">
2
+ import Handle from '../Handle.svelte';
3
+ import type { Rectangle, Shape } from '../../../model';
3
4
  import type { Transform } from '../../Transform';
4
- import { Editor, Handle } from '..';
5
+ import { Editor } from '..';
5
6
 
6
7
  /** Props */
7
8
  export let shape: Rectangle;
8
- export let computedStyle: string = undefined;
9
+ export let computedStyle: string | undefined;
9
10
  export let transform: Transform;
10
11
  export let viewportScale: number = 1;
11
12
 
12
13
  $: geom = shape.geometry;
13
14
 
14
- $: handleSize = 10 / viewportScale;
15
-
16
- const editor = (rectangle: Rectangle, handle: Handle, delta: [number, number]) => {
15
+ const editor = (rectangle: Shape, handle: string, delta: [number, number]) => {
17
16
  const initialBounds = rectangle.geometry.bounds;
18
17
 
19
18
  let [x0, y0] = [initialBounds.minX, initialBounds.minY];
@@ -21,39 +20,39 @@
21
20
 
22
21
  const [dx, dy] = delta;
23
22
 
24
- if (handle === Handle.SHAPE) {
23
+ if (handle === 'SHAPE') {
25
24
  x0 += dx;
26
25
  x1 += dx;
27
26
  y0 += dy;
28
27
  y1 += dy;
29
28
  } else {
30
29
  switch (handle) {
31
- case Handle.TOP:
32
- case Handle.TOP_LEFT:
33
- case Handle.TOP_RIGHT: {
30
+ case 'TOP':
31
+ case 'TOP_LEFT':
32
+ case 'TOP_RIGHT': {
34
33
  y0 += dy;
35
34
  break;
36
35
  }
37
36
 
38
- case Handle.BOTTOM:
39
- case Handle.BOTTOM_LEFT:
40
- case Handle.BOTTOM_RIGHT: {
37
+ case 'BOTTOM':
38
+ case 'BOTTOM_LEFT':
39
+ case 'BOTTOM_RIGHT': {
41
40
  y1 += dy;
42
41
  break;
43
42
  }
44
43
  }
45
44
 
46
45
  switch (handle) {
47
- case Handle.LEFT:
48
- case Handle.TOP_LEFT:
49
- case Handle.BOTTOM_LEFT: {
46
+ case 'LEFT':
47
+ case 'TOP_LEFT':
48
+ case 'BOTTOM_LEFT': {
50
49
  x0 += dx;
51
50
  break;
52
51
  }
53
52
 
54
- case Handle.RIGHT:
55
- case Handle.TOP_RIGHT:
56
- case Handle.BOTTOM_RIGHT: {
53
+ case 'RIGHT':
54
+ case 'TOP_RIGHT':
55
+ case 'BOTTOM_RIGHT': {
57
56
  x1 += dx;
58
57
  break;
59
58
  }
@@ -92,52 +91,56 @@
92
91
  <rect
93
92
  class="a9s-outer"
94
93
  style={computedStyle ? 'display:none;' : undefined}
95
- on:pointerdown={grab(Handle.SHAPE)}
94
+ on:pointerdown={grab('SHAPE')}
96
95
  x={geom.x} y={geom.y} width={geom.w} height={geom.h} />
97
96
 
98
97
  <rect
99
98
  class="a9s-inner a9s-shape-handle"
100
99
  style={computedStyle}
101
- on:pointerdown={grab(Handle.SHAPE)}
100
+ on:pointerdown={grab('SHAPE')}
102
101
  x={geom.x} y={geom.y} width={geom.w} height={geom.h} />
103
102
 
104
103
  <rect
105
104
  class="a9s-edge-handle a9s-edge-handle-top"
106
- on:pointerdown={grab(Handle.TOP)}
105
+ on:pointerdown={grab('TOP')}
107
106
  x={geom.x} y={geom.y} height={1} width={geom.w} />
108
107
 
109
108
  <rect
110
109
  class="a9s-edge-handle a9s-edge-handle-right"
111
- on:pointerdown={grab(Handle.RIGHT)}
110
+ on:pointerdown={grab('RIGHT')}
112
111
  x={geom.x + geom.w} y={geom.y} height={geom.h} width={1}/>
113
112
 
114
113
  <rect
115
114
  class="a9s-edge-handle a9s-edge-handle-bottom"
116
- on:pointerdown={grab(Handle.BOTTOM)}
115
+ on:pointerdown={grab('BOTTOM')}
117
116
  x={geom.x} y={geom.y + geom.h} height={1} width={geom.w} />
118
117
 
119
118
  <rect
120
119
  class="a9s-edge-handle a9s-edge-handle-left"
121
- on:pointerdown={grab(Handle.LEFT)}
120
+ on:pointerdown={grab('LEFT')}
122
121
  x={geom.x} y={geom.y} height={geom.h} width={1} />
123
122
 
124
- <rect
125
- class="a9s-corner-handle a9s-corner-handle-topleft"
126
- on:pointerdown={grab(Handle.TOP_LEFT)}
127
- x={geom.x - handleSize / 2} y={geom.y - handleSize / 2} height={handleSize} width={handleSize} />
128
-
129
- <rect
130
- class="a9s-corner-handle a9s-corner-handle-topright"
131
- on:pointerdown={grab(Handle.TOP_RIGHT)}
132
- x={geom.x + geom.w - handleSize / 2} y={geom.y - handleSize / 2} height={handleSize} width={handleSize} />
123
+ <Handle
124
+ class="a9s-corner-handle-topleft"
125
+ on:pointerdown={grab('TOP_LEFT')}
126
+ x={geom.x} y={geom.y}
127
+ scale={viewportScale} />
128
+
129
+ <Handle
130
+ class="a9s-corner-handle-topright"
131
+ on:pointerdown={grab('TOP_RIGHT')}
132
+ x={geom.x + geom.w} y={geom.y}
133
+ scale={viewportScale} />
133
134
 
134
- <rect
135
- class="a9s-corner-handle a9s-corner-handle-bottomright"
136
- on:pointerdown={grab(Handle.BOTTOM_RIGHT)}
137
- x={geom.x + geom.w - handleSize / 2} y={geom.y + geom.h - handleSize / 2} height={handleSize} width={handleSize} />
135
+ <Handle
136
+ class="a9s-corner-handle-bottomright"
137
+ on:pointerdown={grab('BOTTOM_RIGHT')}
138
+ x={geom.x + geom.w} y={geom.y + geom.h}
139
+ scale={viewportScale} />
138
140
 
139
- <rect
140
- class="a9s-corner-handle a9s-corner-handle-bottomleft"
141
- on:pointerdown={grab(Handle.BOTTOM_LEFT)}
142
- x={geom.x - handleSize / 2} y={geom.y + geom.h - handleSize / 2} height={handleSize} width={handleSize} />
141
+ <Handle
142
+ class="a9s-corner-handle-bottomleft"
143
+ on:pointerdown={grab('BOTTOM_LEFT')}
144
+ x={geom.x} y={geom.y + geom.h}
145
+ scale={viewportScale} />
143
146
  </Editor>
@@ -1,12 +1,12 @@
1
- <script type="ts">
2
- import type { DrawingStyle } from '@annotorious/core';
1
+ <script lang="ts">
2
+ import type { DrawingStyleExpression } from '@annotorious/core';
3
3
  import type { Geometry, EllipseGeometry, ImageAnnotation } from '../../model';
4
4
  import { computeStyle } from '../utils/styling';
5
5
 
6
6
  /** Props */
7
7
  export let annotation: ImageAnnotation;
8
8
  export let geom: Geometry;
9
- export let style: DrawingStyle | ((annotation: ImageAnnotation) => DrawingStyle) = undefined;
9
+ export let style: DrawingStyleExpression<ImageAnnotation> | undefined;
10
10
 
11
11
  $: computedStyle = computeStyle(annotation, style);
12
12
 
@@ -1,12 +1,12 @@
1
- <script type="ts">
2
- import type { DrawingStyle } from '@annotorious/core';
1
+ <script lang="ts">
2
+ import type { DrawingStyleExpression } from '@annotorious/core';
3
3
  import type { Geometry, ImageAnnotation, PolygonGeometry } from '../../model';
4
4
  import { computeStyle } from '../utils/styling';
5
5
 
6
6
  /** Props **/
7
7
  export let annotation: ImageAnnotation;
8
8
  export let geom: Geometry;
9
- export let style: DrawingStyle | ((annotation: ImageAnnotation) => DrawingStyle) = undefined;
9
+ export let style: DrawingStyleExpression<ImageAnnotation> | undefined;
10
10
 
11
11
  $: computedStyle = computeStyle(annotation, style);
12
12