@annotorious/core 3.0.0-rc.21 → 3.0.0-rc.4

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 (90) hide show
  1. package/package.json +15 -18
  2. package/{dist/index.d.ts → src/index.ts} +0 -1
  3. package/src/lifecycle/Lifecycle.ts +211 -0
  4. package/src/lifecycle/LifecycleEvents.ts +21 -0
  5. package/src/lifecycle/index.ts +2 -0
  6. package/src/model/Annotation.ts +73 -0
  7. package/src/model/Annotator.ts +199 -0
  8. package/{dist/model/DrawingStyle.d.ts → src/model/DrawingStyle.ts} +14 -8
  9. package/{dist/model/Filter.d.ts → src/model/Filter.ts} +2 -2
  10. package/src/model/FormatAdapter.ts +36 -0
  11. package/src/model/User.ts +19 -0
  12. package/src/model/W3CAnnotation.ts +118 -0
  13. package/{dist/model/index.d.ts → src/model/index.ts} +1 -2
  14. package/src/presence/Appearance.ts +9 -0
  15. package/src/presence/AppearanceProvider.ts +53 -0
  16. package/src/presence/ColorPalette.ts +14 -0
  17. package/src/presence/PresenceEvents.ts +9 -0
  18. package/src/presence/PresenceProvider.ts +7 -0
  19. package/src/presence/PresenceState.ts +145 -0
  20. package/src/presence/PresentUser.ts +10 -0
  21. package/{dist/presence/index.d.ts → src/presence/index.ts} +1 -2
  22. package/src/state/Hover.ts +34 -0
  23. package/src/state/Selection.ts +113 -0
  24. package/src/state/Store.ts +344 -0
  25. package/src/state/StoreObserver.ts +194 -0
  26. package/src/state/SvelteStore.ts +54 -0
  27. package/src/state/UndoStack.ts +143 -0
  28. package/src/state/Viewport.ts +14 -0
  29. package/{dist/state/index.d.ts → src/state/index.ts} +1 -2
  30. package/src/utils/annotationUtils.ts +33 -0
  31. package/src/utils/diffAnnotations.ts +39 -0
  32. package/{dist/utils/index.d.ts → src/utils/index.ts} +1 -1
  33. package/src/vite-env.d.ts +1 -0
  34. package/dist/annotorious-core.es.js +0 -776
  35. package/dist/annotorious-core.es.js.map +0 -1
  36. package/dist/index.d.ts.map +0 -1
  37. package/dist/lifecycle/Lifecycle.d.ts +0 -10
  38. package/dist/lifecycle/Lifecycle.d.ts.map +0 -1
  39. package/dist/lifecycle/LifecycleEvents.d.ts +0 -12
  40. package/dist/lifecycle/LifecycleEvents.d.ts.map +0 -1
  41. package/dist/lifecycle/index.d.ts +0 -3
  42. package/dist/lifecycle/index.d.ts.map +0 -1
  43. package/dist/model/Annotation.d.ts +0 -32
  44. package/dist/model/Annotation.d.ts.map +0 -1
  45. package/dist/model/Annotator.d.ts +0 -63
  46. package/dist/model/Annotator.d.ts.map +0 -1
  47. package/dist/model/DrawingStyle.d.ts.map +0 -1
  48. package/dist/model/Filter.d.ts.map +0 -1
  49. package/dist/model/FormatAdapter.d.ts +0 -15
  50. package/dist/model/FormatAdapter.d.ts.map +0 -1
  51. package/dist/model/User.d.ts +0 -11
  52. package/dist/model/User.d.ts.map +0 -1
  53. package/dist/model/W3CAnnotation.d.ts +0 -41
  54. package/dist/model/W3CAnnotation.d.ts.map +0 -1
  55. package/dist/model/index.d.ts.map +0 -1
  56. package/dist/presence/Appearance.d.ts +0 -6
  57. package/dist/presence/Appearance.d.ts.map +0 -1
  58. package/dist/presence/AppearanceProvider.d.ts +0 -16
  59. package/dist/presence/AppearanceProvider.d.ts.map +0 -1
  60. package/dist/presence/ColorPalette.d.ts +0 -3
  61. package/dist/presence/ColorPalette.d.ts.map +0 -1
  62. package/dist/presence/PresenceEvents.d.ts +0 -6
  63. package/dist/presence/PresenceEvents.d.ts.map +0 -1
  64. package/dist/presence/PresenceProvider.d.ts +0 -5
  65. package/dist/presence/PresenceProvider.d.ts.map +0 -1
  66. package/dist/presence/PresenceState.d.ts +0 -18
  67. package/dist/presence/PresenceState.d.ts.map +0 -1
  68. package/dist/presence/PresentUser.d.ts +0 -7
  69. package/dist/presence/PresentUser.d.ts.map +0 -1
  70. package/dist/presence/index.d.ts.map +0 -1
  71. package/dist/state/Hover.d.ts +0 -10
  72. package/dist/state/Hover.d.ts.map +0 -1
  73. package/dist/state/Selection.d.ts +0 -31
  74. package/dist/state/Selection.d.ts.map +0 -1
  75. package/dist/state/Store.d.ts +0 -30
  76. package/dist/state/Store.d.ts.map +0 -1
  77. package/dist/state/StoreObserver.d.ts +0 -57
  78. package/dist/state/StoreObserver.d.ts.map +0 -1
  79. package/dist/state/SvelteStore.d.ts +0 -22
  80. package/dist/state/SvelteStore.d.ts.map +0 -1
  81. package/dist/state/UndoStack.d.ts +0 -18
  82. package/dist/state/UndoStack.d.ts.map +0 -1
  83. package/dist/state/Viewport.d.ts +0 -7
  84. package/dist/state/Viewport.d.ts.map +0 -1
  85. package/dist/state/index.d.ts.map +0 -1
  86. package/dist/utils/annotationUtils.d.ts +0 -11
  87. package/dist/utils/annotationUtils.d.ts.map +0 -1
  88. package/dist/utils/diffAnnotations.d.ts +0 -4
  89. package/dist/utils/diffAnnotations.d.ts.map +0 -1
  90. package/dist/utils/index.d.ts.map +0 -1
@@ -0,0 +1,143 @@
1
+ import { createNanoEvents, type Unsubscribe } from 'nanoevents';
2
+ import type { Annotation } from '../model';
3
+ import type { Store } from './Store';
4
+ import { Origin } from './StoreObserver';
5
+ import { mergeChanges, type ChangeSet, type StoreChangeEvent, type Update } from './StoreObserver';
6
+
7
+ // Duration with fast successive changes get merged
8
+ // with the last event in the stack, rather than getting stacked
9
+ // as a new undo/redo step.
10
+ const DEBOUNCE = 250;
11
+
12
+ export interface UndoStack <T extends Annotation> {
13
+
14
+ canRedo(): boolean;
15
+
16
+ canUndo(): boolean;
17
+
18
+ destroy(): void;
19
+
20
+ on<E extends keyof UndoStackEvents<T>>(event: E, callback: UndoStackEvents<T>[E]): Unsubscribe;
21
+
22
+ undo(): void;
23
+
24
+ redo(): void;
25
+
26
+ }
27
+
28
+ export interface UndoStackEvents <T extends Annotation> {
29
+
30
+ redo(change: ChangeSet<T>): void;
31
+
32
+ undo(change: ChangeSet<T>): void;
33
+
34
+ }
35
+
36
+ export const createUndoStack = <T extends Annotation>(store: Store<T>): UndoStack<T> => {
37
+
38
+ const emitter = createNanoEvents<UndoStackEvents<T>>();
39
+
40
+ const changeStack: ChangeSet<T>[] = [];
41
+
42
+ let pointer = -1;
43
+
44
+ let muteEvents = false;
45
+
46
+ let lastEvent = 0;
47
+
48
+ const onChange = (event: StoreChangeEvent<T>) => {
49
+ if (!muteEvents) {
50
+ const { changes } = event;
51
+
52
+ const now = performance.now();
53
+
54
+ if (now - lastEvent > DEBOUNCE) {
55
+ // Put this change on the stack...
56
+ changeStack.splice(pointer + 1);
57
+ changeStack.push(changes);
58
+
59
+ // ...and update the pointer
60
+ pointer = changeStack.length - 1;
61
+ } else {
62
+ // Merge this change with the last in the stack
63
+ const last = changeStack.length - 1;
64
+ changeStack[last] = mergeChanges(changeStack[last], changes);
65
+ }
66
+
67
+ lastEvent = now;
68
+ }
69
+
70
+ muteEvents = false;
71
+ }
72
+
73
+ store.observe(onChange, { origin: Origin.LOCAL });
74
+
75
+ const undoCreated = (created: T[]) =>
76
+ created?.length > 0 && store.bulkDeleteAnnotation(created);
77
+
78
+ const redoCreated = (created: T[]) =>
79
+ created?.length > 0 && store.bulkAddAnnotation(created, false);
80
+
81
+ const undoUpdated = (updated: Update<T>[]) =>
82
+ updated?.length > 0 && store.bulkUpdateAnnotation(updated.map(({ oldValue }) => oldValue));
83
+
84
+ const redoUpdated = (updated: Update<T>[]) =>
85
+ updated?.length > 0 && store.bulkUpdateAnnotation(updated.map(({ newValue }) => newValue));
86
+
87
+ const undoDeleted = (deleted: T[]) =>
88
+ deleted?.length > 0 && store.bulkAddAnnotation(deleted, false);
89
+
90
+ const redoDeleted = (deleted: T[]) =>
91
+ deleted?.length > 0 && store.bulkDeleteAnnotation(deleted);
92
+
93
+ const undo = () => {
94
+ if (pointer > -1) {
95
+ muteEvents = true;
96
+
97
+ const { created, updated, deleted } = changeStack[pointer];
98
+
99
+ undoCreated(created);
100
+ undoUpdated(updated);
101
+ undoDeleted(deleted);
102
+
103
+ emitter.emit('undo', changeStack[pointer]);
104
+
105
+ pointer -= 1;
106
+ }
107
+ }
108
+
109
+ const canUndo = () => pointer > -1;
110
+
111
+ const redo = () => {
112
+ if (changeStack.length - 1 > pointer) {
113
+ muteEvents = true;
114
+
115
+ const { created, updated, deleted } = changeStack[pointer + 1];
116
+
117
+ redoCreated(created);
118
+ redoUpdated(updated);
119
+ redoDeleted(deleted);
120
+
121
+ emitter.emit('redo', changeStack[pointer + 1]);
122
+
123
+ pointer += 1;
124
+ }
125
+ }
126
+
127
+ const canRedo = () => changeStack.length - 1 > pointer;
128
+
129
+ const destroy = () => store.unobserve(onChange);
130
+
131
+ const on = <E extends keyof UndoStackEvents<T>>(event: E, callback: UndoStackEvents<T>[E]) =>
132
+ emitter.on(event, callback);
133
+
134
+ return {
135
+ canRedo,
136
+ canUndo,
137
+ destroy,
138
+ on,
139
+ redo,
140
+ undo
141
+ }
142
+
143
+ }
@@ -0,0 +1,14 @@
1
+ import { writable } from 'svelte/store';
2
+
3
+ export type ViewportState = ReturnType<typeof createViewportState>;
4
+
5
+ export const createViewportState = () => {
6
+
7
+ const { subscribe, set } = writable<string[]>([]);
8
+
9
+ return {
10
+ subscribe,
11
+ set
12
+ };
13
+
14
+ }
@@ -4,5 +4,4 @@ export * from './Store';
4
4
  export * from './StoreObserver';
5
5
  export * from './SvelteStore';
6
6
  export * from './UndoStack';
7
- export * from './Viewport';
8
- //# sourceMappingURL=index.d.ts.map
7
+ export * from './Viewport';
@@ -0,0 +1,33 @@
1
+ import { v4 as uuidv4 } from 'uuid';
2
+ import type { Annotation, AnnotationBody, User } from '../model';
3
+
4
+ /**
5
+ * Returns all users listed as creators or updaters in any parts of this
6
+ * annotation.
7
+ */
8
+ export const getContributors = (annotation: Annotation): User[] => {
9
+ const { creator, updatedBy } = annotation.target;
10
+
11
+ const bodyCollaborators = annotation.bodies.reduce((users, body) => (
12
+ [...users, body.creator, body.updatedBy]
13
+ ), [] as User[]);
14
+
15
+ return [
16
+ creator,
17
+ updatedBy,
18
+ ...bodyCollaborators
19
+ ].filter(u => u); // Remove undefined
20
+ }
21
+
22
+ export const createBody = (
23
+ annotation: Annotation,
24
+ payload: { [key: string]: any },
25
+ created?: Date,
26
+ creator?: User
27
+ ): AnnotationBody => ({
28
+ id: uuidv4(),
29
+ annotation: annotation.id,
30
+ created: created || new Date(),
31
+ creator,
32
+ ...payload
33
+ });
@@ -0,0 +1,39 @@
1
+ import { dequal } from 'dequal/lite';
2
+ import type { Update } from '../state';
3
+ import type { Annotation } from '../model';
4
+
5
+ const getAddedBodies = (oldValue: Annotation, newValue: Annotation) => {
6
+ const oldBodyIds = new Set(oldValue.bodies.map(b => b.id));
7
+ return newValue.bodies.filter(b => !oldBodyIds.has(b.id));
8
+ }
9
+
10
+ const getRemovedBodies = (oldValue: Annotation, newValue: Annotation) => {
11
+ const newBodyIds = new Set(newValue.bodies.map(b => b.id));
12
+ return oldValue.bodies.filter(b => !newBodyIds.has(b.id));
13
+ }
14
+
15
+ const getChangedBodies = (oldValue: Annotation, newValue: Annotation) =>
16
+ newValue.bodies
17
+ .map(newBody => {
18
+ const oldBody = oldValue.bodies.find(b => b.id === newBody.id);
19
+ return { newBody, oldBody: oldBody && !dequal(oldBody, newBody) ? oldBody : undefined }
20
+ })
21
+ .filter(({ oldBody }) => oldBody);
22
+
23
+ const hasTargetChanged = (oldValue: Annotation, newValue: Annotation) =>
24
+ !dequal(oldValue.target, newValue.target);
25
+
26
+ export const diffAnnotations = <T extends Annotation = Annotation>(oldValue: T, newValue: T): Update<T> => {
27
+ const bodiesCreated = getAddedBodies(oldValue, newValue);
28
+ const bodiesDeleted = getRemovedBodies(oldValue, newValue);
29
+ const bodiesUpdated = getChangedBodies(oldValue, newValue);
30
+
31
+ return {
32
+ oldValue,
33
+ newValue,
34
+ bodiesCreated: bodiesCreated.length > 0 ? bodiesCreated : undefined,
35
+ bodiesDeleted: bodiesDeleted.length > 0 ? bodiesDeleted : undefined,
36
+ bodiesUpdated: bodiesUpdated.length > 0 ? bodiesUpdated : undefined,
37
+ targetUpdated: hasTargetChanged(oldValue, newValue) ? { oldTarget: oldValue.target, newTarget: newValue.target } : undefined
38
+ }
39
+ }
@@ -1,3 +1,3 @@
1
1
  export * from './annotationUtils';
2
2
  export * from './diffAnnotations';
3
- //# sourceMappingURL=index.d.ts.map
3
+
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />