Skip to content

Commit

Permalink
Merge branch 'main' into recogito#127-annotating-enabled-reactive
Browse files Browse the repository at this point in the history
# Conflicts:
#	packages/text-annotator/src/TextAnnotator.ts
  • Loading branch information
oleksandr-danylchenko committed Dec 16, 2024
2 parents 4249cc1 + 5b9abad commit 3ca9ab6
Show file tree
Hide file tree
Showing 21 changed files with 1,980 additions and 835 deletions.
2,523 changes: 1,807 additions & 716 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@recogito/text-annotator-monorepo",
"version": "3.0.0-rc.52",
"version": "3.0.0-rc.53",
"description": "Recogito Text Annotator monorepo",
"author": "Rainer Simon",
"repository": {
Expand Down
10 changes: 5 additions & 5 deletions packages/extension-tei/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@recogito/text-annotator-tei",
"version": "3.0.0-rc.52",
"version": "3.0.0-rc.53",
"description": "Recogito Text Annotator TEI extension",
"author": "Rainer Simon",
"license": "BSD-3-Clause",
Expand All @@ -27,12 +27,12 @@
},
"devDependencies": {
"CETEIcean": "^1.9.3",
"typescript": "5.6.3",
"vite": "^5.4.11",
"typescript": "5.7.2",
"vite": "^6.0.3",
"vite-plugin-dts": "^4.3.0"
},
"peerDependencies": {
"@annotorious/core": "^3.0.12",
"@recogito/text-annotator": "3.0.0-rc.52"
"@annotorious/core": "^3.0.14",
"@recogito/text-annotator": "3.0.0-rc.53"
}
}
6 changes: 3 additions & 3 deletions packages/extension-tei/src/crosswalk/forward.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,17 +149,17 @@ export const reviveTarget = (t: TextAnnotationTarget, container: HTMLElement) =>

// Helper
const reanchorIfNeeded = (parent: Node, offset: number) => {
if (parent.firstChild.toString().length >= offset) {
if (parent.firstChild instanceof Text && parent.firstChild.length >= offset) {
return { node: parent.firstChild, offset };
} else {
return reanchor(parent.firstChild, parent, offset);
}
}

const reanchoredStart = reanchorIfNeeded(startNode, startOffset);
const reanchoredEnd = reanchorIfNeeded(endNode, endOffset);

range.setStart(reanchoredStart.node, reanchoredStart.offset);

const reanchoredEnd = reanchorIfNeeded(endNode, endOffset);
range.setEnd(reanchoredEnd.node, reanchoredEnd.offset);

const textSelector = rangeToSelector(range, container);
Expand Down
22 changes: 11 additions & 11 deletions packages/text-annotator-react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@recogito/react-text-annotator",
"version": "3.0.0-rc.52",
"version": "3.0.0-rc.53",
"description": "Recogito Text Annotator React bindings",
"author": "Rainer Simon",
"license": "BSD-3-Clause",
Expand All @@ -24,14 +24,14 @@
"module": "./dist/react-text-annotator.es.js",
"types": "./dist/index.d.ts",
"devDependencies": {
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.3",
"@types/react-dom": "^18.3.5",
"@vitejs/plugin-react": "^4.3.4",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"typescript": "5.6.3",
"vite": "^5.4.11",
"typescript": "5.7.2",
"vite": "^6.0.3",
"vite-plugin-dts": "^4.3.0",
"vite-tsconfig-paths": "^5.1.2"
"vite-tsconfig-paths": "^5.1.4"
},
"peerDependencies": {
"openseadragon": "^3.0.0 || ^4.0.0 || ^5.0.0",
Expand All @@ -44,11 +44,11 @@
}
},
"dependencies": {
"@annotorious/core": "^3.0.12",
"@annotorious/react": "^3.0.12",
"@floating-ui/react": "^0.26.27",
"@recogito/text-annotator": "3.0.0-rc.52",
"@recogito/text-annotator-tei": "3.0.0-rc.52",
"@annotorious/core": "^3.0.14",
"@annotorious/react": "^3.0.14",
"@floating-ui/react": "^0.27.1",
"@recogito/text-annotator": "3.0.0-rc.53",
"@recogito/text-annotator-tei": "3.0.0-rc.53",
"CETEIcean": "^1.9.3"
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { ReactNode, useEffect, useMemo, useRef, useState } from 'react';
import { useAnnotator, useSelection } from '@annotorious/react';
import { isRevived, NOT_ANNOTATABLE_CLASS, TextAnnotation, TextAnnotator } from '@recogito/text-annotator';
import {
NOT_ANNOTATABLE_CLASS,
toDomRectList,
type TextAnnotation,
type TextAnnotator,
} from '@recogito/text-annotator';

import { isMobile } from './isMobile';
import {
arrow,
Expand Down Expand Up @@ -43,6 +49,12 @@ export interface TextAnnotationPopupContentProps {

}

const toViewportBounds = (annotationBounds: DOMRect, container: HTMLElement): DOMRect => {
const { left, top, right, bottom } = annotationBounds;
const containerBounds = container.getBoundingClientRect();
return new DOMRect(left + containerBounds.left, top + containerBounds.top, right - left, bottom - top);
}

export const TextAnnotationPopup = (props: TextAnnotationPopupProps) => {

const r = useAnnotator<TextAnnotator>();
Expand All @@ -55,20 +67,6 @@ export const TextAnnotationPopup = (props: TextAnnotationPopupProps) => {

const arrowRef = useRef(null);

// Conditional floating-ui middleware
const middleware = useMemo(() => {
const m = [
inline(),
offset(10),
flip({ crossAxis: true }),
shift({ crossAxis: true, padding: 10 })
];

return props.arrow
? [...m, arrow({ element: arrowRef }) ]
: m;
}, [props.arrow]);

const { refs, floatingStyles, update, context } = useFloating({
placement: isMobile() ? 'bottom' : 'top',
open: isOpen,
Expand All @@ -78,7 +76,13 @@ export const TextAnnotationPopup = (props: TextAnnotationPopupProps) => {
r?.cancelSelected();
}
},
middleware,
middleware: [
inline(),
offset(10),
flip({ crossAxis: true }),
shift({ crossAxis: true, padding: 10 }),
arrow({ element: arrowRef })
],
whileElementsMounted: autoUpdate
});

Expand All @@ -89,26 +93,36 @@ export const TextAnnotationPopup = (props: TextAnnotationPopupProps) => {
const { getFloatingProps } = useInteractions([dismiss, role]);

useEffect(() => {
const annotationSelector = annotation?.target.selector;
setOpen(annotationSelector?.length > 0 ? isRevived(annotationSelector) : false);
}, [annotation]);
if (annotation?.id) {
const bounds = r?.state.store.getAnnotationBounds(annotation.id);
setOpen(Boolean(bounds));
} else {
setOpen(false);
}
}, [annotation?.id, r?.state.store]);

useEffect(() => {
if (isOpen && annotation) {
const {
target: {
selector: [{ range }]
}
} = annotation;
if (!r) return;

if (isOpen && annotation?.id) {
refs.setPositionReference({
getBoundingClientRect: () => range.getBoundingClientRect(),
getClientRects: () => range.getClientRects()
getBoundingClientRect: () => {
// Annotation bounds are relative to the document element
const bounds = r.state.store.getAnnotationBounds(annotation.id);
return bounds
? toViewportBounds(bounds, r.element)
: new DOMRect();
},
getClientRects: () => {
const rects = r.state.store.getAnnotationRects(annotation.id);
const viewportRects = rects.map(rect => toViewportBounds(rect, r.element));
return toDomRectList(viewportRects);
}
});
} else {
refs.setPositionReference(null);
}
}, [isOpen, annotation, refs]);
}, [isOpen, annotation?.id, annotation?.target, r]);

useEffect(() => {
const config: MutationObserverInit = { attributes: true, childList: true, subtree: true };
Expand Down Expand Up @@ -151,9 +165,9 @@ export const TextAnnotationPopup = (props: TextAnnotationPopupProps) => {
})}

{props.arrow && (
<FloatingArrow
<FloatingArrow
ref={arrowRef}
context={context}
context={context}
{...(props.arrowProps || {})} />
)}

Expand Down
10 changes: 6 additions & 4 deletions packages/text-annotator-react/src/TextAnnotator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,23 @@ import { createTextAnnotator } from '@recogito/text-annotator';

import '@recogito/text-annotator/dist/text-annotator.css';

export interface TextAnnotatorProps<E extends unknown> extends Omit<TextAnnotatorOptions<TextAnnotation, E>, 'adapter'> {
export interface TextAnnotatorProps<I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation> extends Omit<TextAnnotatorOptions<I, E>, 'adapter'> {

children?: ReactNode | JSX.Element;

adapter?: FormatAdapter<TextAnnotation, E> | ((container: HTMLElement) => FormatAdapter<TextAnnotation, E>) | null;
adapter?: FormatAdapter<I, E> | ((container: HTMLElement) => FormatAdapter<I, E>) | null;

filter?: Filter;
filter?: Filter<I>;

style?: HighlightStyleExpression;

className?: string;

}

export const TextAnnotator = <E extends unknown>(props: TextAnnotatorProps<E>) => {
export const TextAnnotator = <I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation>(
props: TextAnnotatorProps<I, E>
) => {

const el = useRef<HTMLDivElement>(null);

Expand Down
10 changes: 8 additions & 2 deletions packages/text-annotator-react/src/tei/CETEIcean.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import CETEI from 'CETEIcean';

interface CETEIceanProps {

initArgs?: any;

tei?: string;

onLoad?(element: Element): void;
Expand Down Expand Up @@ -55,7 +57,7 @@ export const CETEIcean = (props: CETEIceanProps) => {

useEffect(() => {
if (props.tei) {
const ceteicean = new CETEI();
const ceteicean = new CETEI(props.initArgs);

ceteicean.addBehaviors({
...PRESET_BEHAVIORS,
Expand All @@ -71,7 +73,11 @@ export const CETEIcean = (props: CETEIceanProps) => {
props.onLoad(el.current);
});
}
}, [props.tei]);

return () => {
el.current.innerHTML = '';
}
}, [props.tei, JSON.stringify(props.initArgs), props.onLoad]);

return (
<div
Expand Down
6 changes: 3 additions & 3 deletions packages/text-annotator-react/src/tei/TEIAnnotator.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Children, ReactElement, ReactNode, cloneElement, useContext, useEffect } from 'react';
import { Children, ReactElement, ReactNode, cloneElement, useCallback, useContext, useEffect } from 'react';
import { AnnotoriousContext, Filter } from '@annotorious/react';
import { TEIPlugin } from '@recogito/text-annotator-tei';
import { createTextAnnotator, HighlightStyleExpression } from '@recogito/text-annotator';
Expand All @@ -22,10 +22,10 @@ export const TEIAnnotator = (props: TEIAnnotatorProps) => {

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

const onLoad = (element: HTMLElement) => {
const onLoad = useCallback((element: HTMLElement) => {
const anno = TEIPlugin(createTextAnnotator(element, opts));
setAnno(anno);
}
}, []);

useEffect(() => {
if (!anno)
Expand Down
13 changes: 8 additions & 5 deletions packages/text-annotator-react/test/tei/App.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import React, { FC, useEffect, useRef, useState } from 'react';

import { AnnotationBody, Annotorious, useAnnotationStore, useAnnotator } from '@annotorious/react';
import { TextAnnotation, TextAnnotator as VanillaTextAnnotator } from '@recogito/text-annotator';

import { TEIAnnotator, CETEIcean, TextAnnotatorPopup, type TextAnnotationPopupContentProps } from '../../src';
import {
TEIAnnotator,
CETEIcean,
type TextAnnotationPopupContentProps,
TextAnnotationPopup
} from '../../src';

const TestPopup: FC<TextAnnotationPopupContentProps> = (props) => {

Expand All @@ -22,7 +25,7 @@ const TestPopup: FC<TextAnnotationPopupContentProps> = (props) => {
};

const onClick = () => {
store.addBody(body);
store?.addBody(body);
r.cancelSelected();
};

Expand Down Expand Up @@ -78,7 +81,7 @@ export const App: FC = () => {
<TEIAnnotator>
<CETEIcean tei={tei} />

<TextAnnotatorPopup
<TextAnnotationPopup
popup={props => (
<TestPopup {...props} />
)}
Expand Down
10 changes: 7 additions & 3 deletions packages/text-annotator-react/test/tei/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import React, { createRoot } from 'react-dom/client';
import React from 'react';
import ReactDOM from 'react-dom/client';

import { App } from './App';

const root = createRoot(document.getElementById('root') as Element);
const root = ReactDOM.createRoot(document.getElementById('root') as Element);
root.render(
<App />
<React.StrictMode>
<App />
</React.StrictMode>
)
12 changes: 6 additions & 6 deletions packages/text-annotator/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@recogito/text-annotator",
"version": "3.0.0-rc.52",
"version": "3.0.0-rc.53",
"description": "A JavaScript text annotation library",
"author": "Rainer Simon",
"license": "BSD-3-Clause",
Expand Down Expand Up @@ -29,17 +29,17 @@
"@types/jsdom": "^21.1.7",
"@types/rbush": "^4.0.0",
"jsdom": "^25.0.1",
"typescript": "5.6.3",
"vite": "^5.4.11",
"typescript": "5.7.2",
"vite": "^6.0.3",
"vite-plugin-dts": "^4.3.0",
"vitest": "^2.1.4"
"vitest": "^2.1.8"
},
"dependencies": {
"@annotorious/core": "^3.0.12",
"@annotorious/core": "^3.0.14",
"colord": "^2.9.3",
"debounce": "^2.1.1",
"dequal": "^2.0.3",
"hotkeys-js": "^3.13.7",
"hotkeys-js": "^3.13.9",
"rbush": "^4.0.1",
"uuid": "^11.0.3"
}
Expand Down
Loading

0 comments on commit 3ca9ab6

Please sign in to comment.