Skip to content

Commit 4c34012

Browse files
authored
Merge branch 'main' into modernize-tsconfig-setup
2 parents 0a6707a + 14c91c9 commit 4c34012

24 files changed

+790
-451
lines changed

package-lock.json

Lines changed: 515 additions & 244 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@recogito/text-annotator-monorepo",
3-
"version": "3.2.0",
3+
"version": "3.3.3",
44
"description": "Recogito Text Annotator monorepo",
55
"author": "Rainer Simon",
66
"repository": {

packages/extension-tei/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@recogito/text-annotator-tei",
3-
"version": "3.2.0",
3+
"version": "3.3.3",
44
"description": "Recogito Text Annotator TEI extension",
55
"author": "Rainer Simon",
66
"license": "BSD-3-Clause",
@@ -27,11 +27,11 @@
2727
},
2828
"devDependencies": {
2929
"CETEIcean": "^1.9.5",
30-
"typescript": "5.9.2",
30+
"typescript": "5.9.3",
3131
"vite": "^6.3.6"
3232
},
3333
"peerDependencies": {
34-
"@annotorious/core": "^3.7.7",
35-
"@recogito/text-annotator": "3.2.0"
34+
"@annotorious/core": "^3.7.11",
35+
"@recogito/text-annotator": "3.3.3"
3636
}
3737
}

packages/extension-tei/src/crosswalk/forward.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,33 @@ const getXPath = (node: Node, path: string[] = []) => {
4747
* For the given path sgement lists, this function returns the the
4848
* start & end XPath expression pair.
4949
*/
50-
const toTEIXPaths = (startPath: string[], endPath: string[], selectedRange: Range) => {
50+
const toTEIXPaths = (container: HTMLElement, startPath: string[], endPath: string[], selectedRange: Range) => {
51+
52+
const findFirstTEIChild = (node: Node): Element | null => {
53+
const iterator = document.createNodeIterator(
54+
node,
55+
NodeFilter.SHOW_ELEMENT,
56+
(node) => {
57+
return (node as Element).nodeName.toLowerCase().startsWith('tei-')
58+
? NodeFilter.FILTER_ACCEPT
59+
: NodeFilter.FILTER_SKIP;
60+
}
61+
);
62+
63+
return iterator.nextNode() as Element | null;
64+
}
65+
5166
// For a given node, returns the closest parent that is a TEI element
5267
const getClosestTEINode = (node: Node | null) => {
5368
if (!node) return null;
5469

55-
return (node.nodeName.toLowerCase().indexOf('tei-') === 0) ?
56-
node : getClosestTEINode(node.parentNode);
70+
// Edge case: node is the container itself
71+
if (node === container) {
72+
return findFirstTEIChild(node);
73+
} else {
74+
return (node.nodeName.toLowerCase().indexOf('tei-') === 0) ?
75+
node : getClosestTEINode(node.parentNode);
76+
}
5777
};
5878

5979
// Helper to compute char offsets between end of XPath and a given reference node
@@ -85,15 +105,15 @@ const toTEIXPaths = (startPath: string[], endPath: string[], selectedRange: Rang
85105
* Using the DOM Range from a (revived!) TextSelector, this function computes
86106
* the TEIRangeSelector corresponding to that range.
87107
*/
88-
export const textToTEISelector = (selector: TextSelector): TEIRangeSelector => {
108+
export const textToTEISelector = (container: HTMLElement) => (selector: TextSelector): TEIRangeSelector => {
89109
const { range } = selector;
90110

91111
// XPath segments for Range start and end nodes as a list
92112
const startPathSegments: string[] = getXPath(range.startContainer);
93113
const endPathSegments: string[] = getXPath(range.endContainer);
94114

95115
// TEI XPath expressions
96-
const { start, end } = toTEIXPaths(startPathSegments, endPathSegments, range);
116+
const { start, end } = toTEIXPaths(container, startPathSegments, endPathSegments, range);
97117

98118
return {
99119
start: selector.start,
@@ -179,7 +199,7 @@ export const textToTEITarget = (container: HTMLElement) => (t: TextAnnotationTa
179199
const target = reviveTarget(t, container);
180200
return {
181201
...t,
182-
selector: target.selector.map(textToTEISelector)
202+
selector: target.selector.map(textToTEISelector(container))
183203
}
184204
}
185205

packages/text-annotator-react/package.json

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@recogito/react-text-annotator",
3-
"version": "3.2.0",
3+
"version": "3.3.3",
44
"description": "Recogito Text Annotator React bindings",
55
"author": "Rainer Simon",
66
"license": "BSD-3-Clause",
@@ -24,12 +24,12 @@
2424
"module": "./dist/react-text-annotator.es.js",
2525
"types": "./dist/index.d.ts",
2626
"devDependencies": {
27-
"@types/react": "^19.1.13",
28-
"@types/react-dom": "^19.1.9",
27+
"@types/react": "^19.2.2",
28+
"@types/react-dom": "^19.2.1",
2929
"@vitejs/plugin-react": "^4.7.0",
30-
"react": "^19.1.1",
31-
"react-dom": "^19.1.1",
32-
"typescript": "5.9.2",
30+
"react": "^19.2.0",
31+
"react-dom": "^19.2.0",
32+
"typescript": "5.9.3",
3333
"vite": "^6.3.6",
3434
"vite-plugin-externalize-deps": "^0.9.0",
3535
"vite-tsconfig-paths": "^5.1.4"
@@ -45,11 +45,12 @@
4545
}
4646
},
4747
"dependencies": {
48-
"@annotorious/core": "^3.7.7",
49-
"@annotorious/react": "^3.7.7",
48+
"@annotorious/core": "^3.7.11",
49+
"@annotorious/react": "^3.7.11",
5050
"@floating-ui/react": "^0.27.16",
51-
"@recogito/text-annotator": "3.2.0",
52-
"@recogito/text-annotator-tei": "3.2.0",
53-
"CETEIcean": "^1.9.5"
51+
"@recogito/text-annotator": "3.3.3",
52+
"@recogito/text-annotator-tei": "3.3.3",
53+
"CETEIcean": "^1.9.5",
54+
"debounce": "^2.2.0"
5455
}
5556
}

packages/text-annotator-react/src/TextAnnotationPopup/TextAnnotationPopup.tsx

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { ReactNode, useEffect, useMemo, useRef, useState } from 'react';
2+
import debounce from 'debounce';
23
import { useAnnotator, useSelection } from '@annotorious/react';
34
import {
4-
debounce,
55
NOT_ANNOTATABLE_CLASS,
66
TextAnnotationStore,
7+
toViewportBounds,
78
toDomRectList,
89
type TextAnnotation,
910
type TextAnnotator,
@@ -59,17 +60,11 @@ export interface TextAnnotationPopupContentProps<T extends TextAnnotation = Text
5960

6061
let cachedBounds = null;
6162

62-
const toViewportBounds = (annotationBounds: DOMRect, container: HTMLElement): DOMRect => {
63-
const { left, top, right, bottom } = annotationBounds;
64-
const containerBounds = container.getBoundingClientRect();
65-
return new DOMRect(left + containerBounds.left, top + containerBounds.top, right - left, bottom - top);
66-
}
67-
6863
const updateViewportBounds = debounce((annotationId: string, store: TextAnnotationStore, container: HTMLElement) => {
6964
requestAnimationFrame(() => {
7065
const bounds = store.getAnnotationBounds(annotationId);
7166
if (!bounds) return;
72-
cachedBounds = toViewportBounds(bounds, container);
67+
cachedBounds = toViewportBounds(bounds, container.getBoundingClientRect());
7368
});
7469
}, 250);
7570

@@ -136,13 +131,14 @@ export const TextAnnotationPopup = (props: TextAnnotationPopupProps) => {
136131
if (isOpen && annotation?.id) {
137132
refs.setPositionReference({
138133
getBoundingClientRect: () => {
139-
// Debounced!
140134
updateViewportBounds(annotation.id, r.state.store, r.element);
141135
return cachedBounds ? cachedBounds : new DOMRect();
142136
},
143137
getClientRects: () => {
144138
const rects = r.state.store.getAnnotationRects(annotation.id);
145-
const viewportRects = rects.map(rect => toViewportBounds(rect, r.element));
139+
const viewportRects = rects.map((rect) =>
140+
toViewportBounds(rect, r.element.getBoundingClientRect())
141+
);
146142
return toDomRectList(viewportRects);
147143
}
148144
});
@@ -153,7 +149,7 @@ export const TextAnnotationPopup = (props: TextAnnotationPopupProps) => {
153149

154150
useEffect(() => {
155151
if (!props.asPortal) return;
156-
152+
157153
const config: MutationObserverInit = { attributes: true, childList: true, subtree: true };
158154

159155
const mutationObserver = new MutationObserver(() => update());
@@ -180,7 +176,7 @@ export const TextAnnotationPopup = (props: TextAnnotationPopupProps) => {
180176
const onClose = () => r?.cancelSelected();
181177

182178
return isOpen && annotation ? (
183-
<FloatingPortal
179+
<FloatingPortal
184180
root={props.asPortal ? undefined : r.element}>
185181
<FloatingFocusManager
186182
context={context}

packages/text-annotator-react/src/TextAnnotator.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ export const TextAnnotator = <I extends TextAnnotation = TextAnnotation, E exten
2727
const el = useRef<HTMLDivElement>(null);
2828

2929
const { className, children, ...opts } = props;
30-
31-
const { style, filter, user } = opts;
30+
31+
const { style, filter, user, annotatingEnabled } = opts;
3232

3333
const { anno, setAnno } = useContext(AnnotoriousContext);
3434

@@ -49,10 +49,12 @@ export const TextAnnotator = <I extends TextAnnotation = TextAnnotation, E exten
4949

5050
useEffect(() => anno?.setUser(user), [anno, user]);
5151

52+
useEffect(() => anno?.setAnnotatingEnabled(annotatingEnabled), [anno, annotatingEnabled]);
53+
5254
return (
5355
<div ref={el} className={`r6o-annotatable no-focus-outline ${className}`}>
5456
{children}
5557
</div>
56-
)
58+
);
5759

5860
}

packages/text-annotator/package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@recogito/text-annotator",
3-
"version": "3.2.0",
3+
"version": "3.3.3",
44
"description": "A JavaScript text annotation library",
55
"author": "Rainer Simon",
66
"license": "BSD-3-Clause",
@@ -26,22 +26,23 @@
2626
"./dist/text-annotator.css": "./dist/text-annotator.css"
2727
},
2828
"devDependencies": {
29-
"@types/jsdom": "^21.1.7",
29+
"@types/jsdom": "^27.0.0",
3030
"@types/rbush": "^4.0.0",
3131
"jsdom": "^27.0.0",
32-
"typescript": "5.9.2",
32+
"typescript": "5.9.3",
3333
"vite": "^6.3.6",
3434
"vite-plugin-externalize-deps": "^0.9.0",
3535
"vitest": "^3.2.4"
3636
},
3737
"dependencies": {
38-
"@annotorious/core": "^3.7.7",
38+
"@annotorious/core": "^3.7.11",
3939
"colord": "^2.9.3",
40+
"debounce": "^2.2.0",
4041
"dequal": "^2.0.3",
4142
"hotkeys-js": "^3.13.15",
4243
"poll": "^3.2.2",
4344
"rbush": "^4.0.1",
44-
"ua-parser-js": "^2.0.5",
45+
"ua-parser-js": "^2.0.6",
4546
"uuid": "^13.0.0"
4647
}
4748
}

0 commit comments

Comments
 (0)