Skip to content

Commit

Permalink
Merge branch 'main' into recogito#133-fix-not-dismissed-annotation-on…
Browse files Browse the repository at this point in the history
…-outside-click
  • Loading branch information
oleksandr-danylchenko committed Sep 26, 2024
2 parents 92e4156 + 8ad2afe commit dc27158
Show file tree
Hide file tree
Showing 19 changed files with 469 additions and 687 deletions.
1,010 changes: 393 additions & 617 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.45",
"version": "3.0.0-rc.46",
"description": "Recogito Text Annotator monorepo",
"author": "Rainer Simon",
"repository": {
Expand Down
12 changes: 6 additions & 6 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.45",
"version": "3.0.0-rc.46",
"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.5.4",
"vite": "^5.4.3",
"vite-plugin-dts": "^4.1.0"
"typescript": "5.6.2",
"vite": "^5.4.8",
"vite-plugin-dts": "^4.2.2"
},
"peerDependencies": {
"@annotorious/core": "^3.0.5",
"@recogito/text-annotator": "3.0.0-rc.45"
"@annotorious/core": "^3.0.8",
"@recogito/text-annotator": "3.0.0-rc.46"
}
}
4 changes: 2 additions & 2 deletions packages/extension-tei/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"ignoreDeprecations": "5.0",
"importsNotUsedAsValues": "error",
"incremental": false,
"isolatedModules": true,
"module": "ESNext",
Expand All @@ -14,7 +13,8 @@
"resolveJsonModule": true,
"skipLibCheck": false,
"sourceMap": true,
"target": "ESNext"
"target": "ESNext",
"verbatimModuleSyntax": true
},
"include": ["./src/**/*", "./test/**/*"],
"exclude": ["node_modules", "dist"]
Expand Down
18 changes: 9 additions & 9 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.45",
"version": "3.0.0-rc.46",
"description": "Recogito Text Annotator React bindings",
"author": "Rainer Simon",
"license": "BSD-3-Clause",
Expand Down Expand Up @@ -28,9 +28,9 @@
"@vitejs/plugin-react": "^4.3.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"typescript": "5.5.4",
"vite": "^5.4.3",
"vite-plugin-dts": "^4.1.0",
"typescript": "5.6.2",
"vite": "^5.4.6",
"vite-plugin-dts": "^4.2.1",
"vite-tsconfig-paths": "^5.0.1"
},
"peerDependencies": {
Expand All @@ -44,11 +44,11 @@
}
},
"dependencies": {
"@annotorious/core": "^3.0.5",
"@annotorious/react": "^3.0.5",
"@floating-ui/react": "^0.26.23",
"@recogito/text-annotator": "3.0.0-rc.45",
"@recogito/text-annotator-tei": "3.0.0-rc.45",
"@annotorious/core": "^3.0.8",
"@annotorious/react": "^3.0.8",
"@floating-ui/react": "^0.26.24",
"@recogito/text-annotator": "3.0.0-rc.46",
"@recogito/text-annotator-tei": "3.0.0-rc.46",
"CETEIcean": "^1.9.3"
}
}
1 change: 0 additions & 1 deletion packages/text-annotator-react/src/TextAnnotator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ 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'> {

children?: ReactNode | JSX.Element;
Expand Down
3 changes: 1 addition & 2 deletions packages/text-annotator-react/src/TextAnnotatorPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,8 @@ export const TextAnnotatorPopup = (props: TextAnnotationPopupProps) => {

useEffect(() => {
// Ignore all selection changes except those accompanied by a pointer event.
if (event) {
if (event)
setOpen(selected.length > 0 && event.type === 'pointerup');
}
}, [event?.type, selectedKey]);

useEffect(() => {
Expand Down
14 changes: 7 additions & 7 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.45",
"version": "3.0.0-rc.46",
"description": "A JavaScript text annotation library",
"author": "Rainer Simon",
"license": "BSD-3-Clause",
Expand Down Expand Up @@ -29,15 +29,15 @@
"@types/jsdom": "^21.1.7",
"@types/rbush": "^3.0.4",
"@types/uuid": "^10.0.0",
"jsdom": "^25.0.0",
"jsdom": "^25.0.1",
"svelte": "^4.2.19",
"typescript": "5.5.4",
"vite": "^5.4.3",
"vite-plugin-dts": "^4.1.0",
"vitest": "^2.0.5"
"typescript": "5.6.2",
"vite": "^5.4.8",
"vite-plugin-dts": "^4.2.2",
"vitest": "^2.1.1"
},
"dependencies": {
"@annotorious/core": "^3.0.5",
"@annotorious/core": "^3.0.8",
"colord": "^2.9.3",
"dequal": "^2.0.3",
"rbush": "^4.0.1",
Expand Down
6 changes: 3 additions & 3 deletions packages/text-annotator/src/SelectionHandler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Filter, Origin, type User } from '@annotorious/core';
import { type Filter, Origin, type User } from '@annotorious/core';
import { v4 as uuidv4 } from 'uuid';
import type { TextAnnotatorState } from './state';
import type { TextAnnotationTarget } from './model';
import type { TextAnnotation, TextAnnotationTarget } from './model';
import {
debounce,
splitAnnotatableRanges,
Expand All @@ -13,7 +13,7 @@ import {

export const SelectionHandler = (
container: HTMLElement,
state: TextAnnotatorState,
state: TextAnnotatorState<TextAnnotation, unknown>,
annotatingEnabled: boolean,
offsetReferenceSelector?: string
) => {
Expand Down
14 changes: 8 additions & 6 deletions packages/text-annotator/src/TextAnnotator.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { createAnonymousGuest, createLifecycleObserver, createBaseAnnotator, Filter, createUndoStack } from '@annotorious/core';
import { createAnonymousGuest, createLifecycleObserver, createBaseAnnotator, createUndoStack } from '@annotorious/core';
import type { Filter } from '@annotorious/core';
import type { Annotator, User, PresenceProvider } from '@annotorious/core';
import { createCanvasRenderer, createHighlightsRenderer, createSpansRenderer, type HighlightStyleExpression } from './highlight';
import { createPresencePainter } from './presence';
import { scrollIntoView } from './api';
import { TextAnnotationStore, TextAnnotatorState, createTextAnnotatorState } from './state';
import { type TextAnnotationStore, type TextAnnotatorState, createTextAnnotatorState } from './state';
import type { TextAnnotation } from './model';
import { cancelSingleClickEvents } from './utils';
import { fillDefaults, type RendererType, type TextAnnotatorOptions } from './TextAnnotatorOptions';
Expand All @@ -13,16 +14,16 @@ import './TextAnnotator.css';

const USE_DEFAULT_RENDERER: RendererType = 'SPANS';

export interface TextAnnotator<I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation> extends Annotator<TextAnnotation, E> {
export interface TextAnnotator<I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation> extends Annotator<I, E> {

element: HTMLElement;

setStyle(style: HighlightStyleExpression | undefined): void;

// Returns true if successful (or false if the annotation is not currently rendered)
scrollIntoView(annotation: I): boolean;
scrollIntoView(annotationOrId: I | string): boolean;

state: TextAnnotatorState<I>;
state: TextAnnotatorState<I, E>;

}

Expand All @@ -38,7 +39,8 @@ export const createTextAnnotator = <E extends unknown = TextAnnotation>(
user: createAnonymousGuest()
});

const state: TextAnnotatorState = createTextAnnotatorState(container, opts.userSelectAction);
const state: TextAnnotatorState<TextAnnotation, E> =
createTextAnnotatorState<TextAnnotation, E>(container, opts.userSelectAction);

const { selection, viewport } = state;

Expand Down
2 changes: 1 addition & 1 deletion packages/text-annotator/src/TextAnnotatorOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export interface TextAnnotatorOptions<I extends TextAnnotation = TextAnnotation,

offsetReferenceSelector?: string;

userSelectAction?: UserSelectActionExpression<TextAnnotation>,
userSelectAction?: UserSelectActionExpression<E>,

presence?: PresencePainterOptions;

Expand Down
2 changes: 1 addition & 1 deletion packages/text-annotator/src/highlight/baseRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Filter, ViewportState } from '@annotorious/core';
import type { TextAnnotatorState } from '../state';
import { debounce } from '../utils';
import { ViewportBounds, getViewportBounds, trackViewport } from './viewport';
import { type ViewportBounds, getViewportBounds, trackViewport } from './viewport';
import type { HighlightPainter } from './HighlightPainter';
import type { Highlight } from './Highlight';
import type { HighlightStyleExpression } from './HighlightStyle';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import type { TextAnnotatorState } from '../../state';
import { debounce } from '../../utils';
import type { ViewportBounds } from '../viewport';
import type { HighlightStyle } from '../HighlightStyle';
import { DEFAULT_SELECTED_STYLE, DEFAULT_STYLE, HighlightStyleExpression } from '../HighlightStyle';
import { DEFAULT_SELECTED_STYLE, DEFAULT_STYLE, type HighlightStyleExpression } from '../HighlightStyle';
import type { HighlightPainter } from '../HighlightPainter';
import { createBaseRenderer, type RendererImplementation } from '../baseRenderer';
import type { Highlight } from '../Highlight';
import type { TextAnnotation } from 'src/model';

import './canvasRenderer.css';

Expand Down Expand Up @@ -142,6 +143,6 @@ const createRenderer = (container: HTMLElement): RendererImplementation => {

export const createCanvasRenderer = (
container: HTMLElement,
state: TextAnnotatorState,
state: TextAnnotatorState<TextAnnotation, unknown>,
viewport: ViewportState
) => createBaseRenderer(container, state, viewport, createRenderer(container));
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { colord } from 'colord';
import type { HighlightPainter } from '../HighlightPainter';
import type { TextAnnotatorState } from 'src/state';
import type { ViewportBounds } from '../viewport';
import { DEFAULT_SELECTED_STYLE, DEFAULT_STYLE, HighlightStyle, HighlightStyleExpression } from '../HighlightStyle';
import { RendererImplementation, createBaseRenderer } from '../baseRenderer';
import { DEFAULT_SELECTED_STYLE, DEFAULT_STYLE } from '../HighlightStyle';
import type { HighlightStyle, HighlightStyleExpression } from '../HighlightStyle';
import { type RendererImplementation, createBaseRenderer } from '../baseRenderer';
import type { Highlight } from '../Highlight';
import type { TextAnnotation } from 'src/model';

const toCSS = (s?: HighlightStyle) => {
const backgroundColor = colord(s?.fill || DEFAULT_STYLE.fill)
Expand Down Expand Up @@ -106,6 +108,6 @@ export const createRenderer = (): RendererImplementation => {

export const createHighlightsRenderer = (
container: HTMLElement,
state: TextAnnotatorState,
state: TextAnnotatorState<TextAnnotation, unknown>,
viewport: ViewportState
) => createBaseRenderer(container, state, viewport, createRenderer());
5 changes: 3 additions & 2 deletions packages/text-annotator/src/highlight/span/spansRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { ViewportBounds } from '../viewport';
import { createBaseRenderer, type RendererImplementation } from '../baseRenderer';
import type { Highlight } from '../Highlight';
import { DEFAULT_STYLE, type HighlightStyleExpression } from '../HighlightStyle';
import type { TextAnnotation } from 'src/model';

import './spansRenderer.css';

Expand Down Expand Up @@ -127,8 +128,8 @@ const createRenderer = (container: HTMLElement): RendererImplementation => {

}

export const createSpansRenderer = <T extends TextAnnotatorState = TextAnnotatorState> (
export const createSpansRenderer = (
container: HTMLElement,
state: T,
state: TextAnnotatorState<TextAnnotation, unknown>,
viewport: ViewportState
) => createBaseRenderer(container, state, viewport, createRenderer(container));
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { v4 as uuidv4 } from 'uuid';
import {
type FormatAdapter,
ParseResult,
type ParseResult,
parseW3CBodies,
parseW3CUser,
serializeW3CBodies
Expand Down
40 changes: 21 additions & 19 deletions packages/text-annotator/src/state/TextAnnotatorState.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,52 @@
import type { Filter, Store, ViewportState, UserSelectActionExpression } from '@annotorious/core';
import type { Filter, Store, ViewportState, UserSelectActionExpression, Annotation } from '@annotorious/core';
import {
createHoverState,
createSelectionState,
createStore,
Origin,
createViewportState
} from '@annotorious/core';
import type {
AnnotatorState,
SelectionState,
HoverState,
Origin,
createViewportState
} from '@annotorious/core';
import { createSpatialTree } from './spatialTree';
import type { TextAnnotation, TextAnnotationTarget } from '../model';
import type { TextAnnotationStore } from './TextAnnotationStore';
import { isRevived, reviveAnnotation, reviveTarget } from '../utils';

export interface TextAnnotatorState<T extends TextAnnotation = TextAnnotation> extends AnnotatorState<T> {
export interface TextAnnotatorState<I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation> extends AnnotatorState<I, E> {

store: TextAnnotationStore<T>;
store: TextAnnotationStore<I>;

selection: SelectionState<T>;
selection: SelectionState<I, E>;

hover: HoverState<T>;
hover: HoverState<I>;

viewport: ViewportState;

}

export const createTextAnnotatorState = <T extends TextAnnotation>(
export const createTextAnnotatorState = <I extends TextAnnotation = TextAnnotation, E extends unknown = TextAnnotation>(
container: HTMLElement,
defaultUserSelectAction?: UserSelectActionExpression<TextAnnotation>
): TextAnnotatorState<T> => {
defaultUserSelectAction?: UserSelectActionExpression<E>
): TextAnnotatorState<I, E> => {

const store: Store<T> = createStore<T>();
const store: Store<I> = createStore<I>();

const tree = createSpatialTree(store, container);

// Temporary
const selection = createSelectionState<TextAnnotation>(store)
const selection = createSelectionState<I, E>(store)
selection.setUserSelectAction(defaultUserSelectAction);

const hover = createHoverState(store);

const viewport = createViewportState();

// Wrap store interface to intercept annotations and revive DOM ranges, if needed
const addAnnotation = (annotation: T, origin = Origin.LOCAL): boolean => {
const addAnnotation = (annotation: I, origin = Origin.LOCAL): boolean => {
const revived = reviveAnnotation(annotation, container);

const isValid = isRevived(revived.target.selector);
Expand All @@ -55,11 +57,11 @@ export const createTextAnnotatorState = <T extends TextAnnotation>(
}

const bulkAddAnnotation = (
annotations: T[],
annotations: I[],
replace = true,
origin = Origin.LOCAL
): T[] => {
const revived = annotations.map(a => reviveAnnotation(a, container));
): I[] => {
const revived = annotations.map(a => reviveAnnotation<I>(a, container));

// Initial page load might take some time. Retry for more robustness.
const couldNotRevive = revived.filter(a => !isRevived(a.target.selector));
Expand All @@ -79,9 +81,9 @@ export const createTextAnnotatorState = <T extends TextAnnotation>(
}

const bulkUpsertAnnotations = (
annotations: T[],
annotations: I[],
origin = Origin.LOCAL
): T[] => {
): I[] => {
const revived = annotations.map(a => reviveAnnotation(a, container));

// Initial page load might take some time. Retry for more robustness.
Expand Down Expand Up @@ -109,7 +111,7 @@ export const createTextAnnotatorState = <T extends TextAnnotation>(
store.bulkUpdateTargets(revived, origin);
}

const getAt = (x: number, y: number, filter?: Filter): T | undefined => {
const getAt = (x: number, y: number, filter?: Filter): I | undefined => {
const annotations = tree.getAt(x, y, Boolean(filter)).map(id => store.getAnnotation(id));
const filtered = filter ? annotations.filter(filter) : annotations;
return filtered.length > 0 ? filtered[0] : undefined;
Expand Down
Loading

0 comments on commit dc27158

Please sign in to comment.