box-annotations 5.2.1-beta.7 → 5.2.1-beta.8
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.
- package/dist/annotations.css +1 -1
- package/dist/annotations.js +1 -1
- package/package.json +1 -1
- package/src/common/BaseAnnotator.scss +2 -1
- package/src/common/BaseAnnotator.ts +14 -0
- package/src/common/DeselectListener.tsx +3 -1
- package/src/components/Popups/PopupV2.scss +4 -1
- package/src/components/Popups/PopupV2.tsx +11 -5
- package/src/document/DocumentAnnotator.ts +5 -2
- package/src/image/ImageAnnotator.ts +1 -1
- package/src/media/MediaAnnotator.ts +1 -1
- package/src/popup/PopupContainer.tsx +8 -1
- package/src/popup/PopupLayer.tsx +4 -0
- package/src/popup/PopupManager.tsx +21 -3
package/package.json
CHANGED
|
@@ -49,6 +49,7 @@ export type Options = {
|
|
|
49
49
|
|
|
50
50
|
export const CSS_CONTAINER_CLASS = 'ba';
|
|
51
51
|
export const CSS_LOADED_CLASS = 'ba-annotations-loaded';
|
|
52
|
+
export const CSS_POPUP_PORTAL_CLASS = 'ba-PopupPortal';
|
|
52
53
|
export const ANNOTATION_CLASSES: { [M in store.Mode]?: string } = {
|
|
53
54
|
[store.Mode.HIGHLIGHT]: 'ba-is-create--highlight',
|
|
54
55
|
[store.Mode.REGION]: 'ba-is-create--region',
|
|
@@ -59,6 +60,8 @@ export default class BaseAnnotator extends EventEmitter {
|
|
|
59
60
|
|
|
60
61
|
containerEl?: HTMLElement | null;
|
|
61
62
|
|
|
63
|
+
popupPortalEl?: HTMLElement | null;
|
|
64
|
+
|
|
62
65
|
container: Container;
|
|
63
66
|
|
|
64
67
|
deselectManager: DeselectManager | null = null;
|
|
@@ -132,6 +135,11 @@ export default class BaseAnnotator extends EventEmitter {
|
|
|
132
135
|
this.containerEl.classList.remove(CSS_CONTAINER_CLASS);
|
|
133
136
|
}
|
|
134
137
|
|
|
138
|
+
if (this.popupPortalEl) {
|
|
139
|
+
this.popupPortalEl.remove();
|
|
140
|
+
this.popupPortalEl = null;
|
|
141
|
+
}
|
|
142
|
+
|
|
135
143
|
if (this.annotatedEl) {
|
|
136
144
|
this.annotatedEl.classList.remove(CSS_LOADED_CLASS);
|
|
137
145
|
}
|
|
@@ -166,6 +174,12 @@ export default class BaseAnnotator extends EventEmitter {
|
|
|
166
174
|
this.annotatedEl.classList.add(CSS_LOADED_CLASS);
|
|
167
175
|
this.containerEl.classList.add(CSS_CONTAINER_CLASS);
|
|
168
176
|
|
|
177
|
+
if (!this.popupPortalEl) {
|
|
178
|
+
this.popupPortalEl = this.containerEl.ownerDocument.createElement('div');
|
|
179
|
+
this.popupPortalEl.classList.add(CSS_POPUP_PORTAL_CLASS);
|
|
180
|
+
this.containerEl.appendChild(this.popupPortalEl);
|
|
181
|
+
}
|
|
182
|
+
|
|
169
183
|
// Defer to the child class to render annotations
|
|
170
184
|
this.render();
|
|
171
185
|
|
|
@@ -6,7 +6,9 @@ export default function DeselectListener(): null {
|
|
|
6
6
|
const dispatch = useDispatch();
|
|
7
7
|
|
|
8
8
|
React.useEffect(() => {
|
|
9
|
-
const handleMouseDown = (): void => {
|
|
9
|
+
const handleMouseDown = (event: MouseEvent): void => {
|
|
10
|
+
// Popup is portaled outside .ba-Layer; native mousedown still bubbles here.
|
|
11
|
+
if ((event.target as Element | null)?.closest?.('.ba-PopupV2')) return;
|
|
10
12
|
dispatch(setActiveAnnotationIdAction(null));
|
|
11
13
|
};
|
|
12
14
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import noop from 'lodash/noop';
|
|
3
|
-
import
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import ReactDOM from 'react-dom';
|
|
4
4
|
import { useIntl } from 'react-intl';
|
|
5
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
6
|
+
|
|
5
7
|
import { BlueprintModernizationProvider } from '@box/blueprint-web';
|
|
6
8
|
import {
|
|
7
9
|
MentionContextProvider,
|
|
@@ -35,6 +37,7 @@ import './PopupV2.scss';
|
|
|
35
37
|
export type Props = {
|
|
36
38
|
annotationId?: string;
|
|
37
39
|
onSubmit: (text: string) => void;
|
|
40
|
+
popupPortalEl?: HTMLElement | null;
|
|
38
41
|
reference: PopupReference;
|
|
39
42
|
};
|
|
40
43
|
|
|
@@ -74,7 +77,7 @@ const fetchAvatarBlob = async (apiHost: string, token: string, userId: string):
|
|
|
74
77
|
}
|
|
75
78
|
};
|
|
76
79
|
|
|
77
|
-
const PopupV2 = ({ annotationId, onSubmit, reference }: Props): JSX.Element => {
|
|
80
|
+
const PopupV2 = ({ annotationId, onSubmit, popupPortalEl, reference }: Props): JSX.Element | null => {
|
|
78
81
|
const intl = useIntl();
|
|
79
82
|
const dispatch = useDispatch<AppThunkDispatch>();
|
|
80
83
|
const popupRef = React.useRef<HTMLDivElement>(null);
|
|
@@ -260,7 +263,9 @@ const PopupV2 = ({ annotationId, onSubmit, reference }: Props): JSX.Element => {
|
|
|
260
263
|
[annotationId, dispatch],
|
|
261
264
|
);
|
|
262
265
|
|
|
263
|
-
return
|
|
266
|
+
if (!popupPortalEl) return null;
|
|
267
|
+
|
|
268
|
+
return ReactDOM.createPortal(
|
|
264
269
|
<FocusTrap>
|
|
265
270
|
<div
|
|
266
271
|
ref={popupRef}
|
|
@@ -307,7 +312,8 @@ const PopupV2 = ({ annotationId, onSubmit, reference }: Props): JSX.Element => {
|
|
|
307
312
|
</BlueprintModernizationProvider>
|
|
308
313
|
<div data-threaded-annotations-portal />
|
|
309
314
|
</div>
|
|
310
|
-
</FocusTrap
|
|
315
|
+
</FocusTrap>,
|
|
316
|
+
popupPortalEl,
|
|
311
317
|
);
|
|
312
318
|
};
|
|
313
319
|
|
|
@@ -24,6 +24,9 @@ import type { ViewMode } from '../store/options/types';
|
|
|
24
24
|
// Pdf.js textLayer enhancement requires waiting for 300ms (they hardcode this magic number)
|
|
25
25
|
const TEXT_LAYER_ENHANCEMENT = 300;
|
|
26
26
|
|
|
27
|
+
// Vertical padding on each page element as provided by Preview SDK (see DocumentAnnotator.scss)
|
|
28
|
+
const PAGE_PADDING = 15;
|
|
29
|
+
|
|
27
30
|
export default class DocumentAnnotator extends BaseAnnotator {
|
|
28
31
|
annotatedEl?: HTMLElement;
|
|
29
32
|
|
|
@@ -99,7 +102,7 @@ export default class DocumentAnnotator extends BaseAnnotator {
|
|
|
99
102
|
}
|
|
100
103
|
|
|
101
104
|
// Annotations mode
|
|
102
|
-
managers.add(new PopupManager({ location: pageNumber, referenceEl: pageReferenceEl, resinTags }));
|
|
105
|
+
managers.add(new PopupManager({ location: pageNumber, popupPortalEl: this.popupPortalEl, referenceEl: pageReferenceEl, resinTags }));
|
|
103
106
|
managers.add(new DrawingManager({ location: pageNumber, referenceEl: pageReferenceEl, resinTags }));
|
|
104
107
|
|
|
105
108
|
const textLayer = pageEl.querySelector('.textLayer') as HTMLElement;
|
|
@@ -200,7 +203,7 @@ export default class DocumentAnnotator extends BaseAnnotator {
|
|
|
200
203
|
|
|
201
204
|
// Calculate original (unrotated) page dimensions for annotation layer sizing
|
|
202
205
|
const pageWidth = pageEl.clientWidth;
|
|
203
|
-
const pageHeight = pageEl.clientHeight;
|
|
206
|
+
const pageHeight = pageEl.clientHeight - PAGE_PADDING * 2;
|
|
204
207
|
const isOrthogonal = rotation % 180 !== 0;
|
|
205
208
|
const origWidth = isOrthogonal ? pageHeight : pageWidth;
|
|
206
209
|
const origHeight = isOrthogonal ? pageWidth : pageHeight;
|
|
@@ -73,7 +73,7 @@ export default class ImageAnnotator extends BaseAnnotator {
|
|
|
73
73
|
return this.managers;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
this.managers.add(new PopupManager({ referenceEl, resinTags }));
|
|
76
|
+
this.managers.add(new PopupManager({ popupPortalEl: this.popupPortalEl, referenceEl, resinTags }));
|
|
77
77
|
this.managers.add(new DrawingManager({ referenceEl, resinTags }));
|
|
78
78
|
this.managers.add(new RegionManager({ referenceEl, resinTags }));
|
|
79
79
|
this.managers.add(new RegionCreationManager({ referenceEl, resinTags }));
|
|
@@ -46,7 +46,7 @@ export default class MediaAnnotator extends BaseAnnotator {
|
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
addManagers(referenceEl: HTMLVideoElement, resinTags: { fileid: string|null; iscurrent: boolean }): void {
|
|
49
|
-
this.managers.add(new PopupManager({ location: MEDIA_LOCATION_INDEX, referenceEl, resinTags, targetType: TARGET_TYPE.FRAME }));
|
|
49
|
+
this.managers.add(new PopupManager({ location: MEDIA_LOCATION_INDEX, popupPortalEl: this.popupPortalEl, referenceEl, resinTags, targetType: TARGET_TYPE.FRAME }));
|
|
50
50
|
this.managers.add(new DrawingManager({ location: MEDIA_LOCATION_INDEX, referenceEl, resinTags, targetType: TARGET_TYPE.FRAME }));
|
|
51
51
|
this.managers.add(new RegionManager({ location: MEDIA_LOCATION_INDEX, referenceEl, resinTags, targetType: TARGET_TYPE.FRAME }));
|
|
52
52
|
this.managers.add(new RegionCreationManager({ location: MEDIA_LOCATION_INDEX, referenceEl, resinTags, targetType: TARGET_TYPE.FRAME }));
|
|
@@ -20,6 +20,13 @@ import { isFeatureEnabled } from '../store/options';
|
|
|
20
20
|
import { createDrawingAction } from '../drawing/actions';
|
|
21
21
|
import { createHighlightAction } from '../highlight/actions';
|
|
22
22
|
import { createRegionAction } from '../region';
|
|
23
|
+
import { TARGET_TYPE } from '../constants';
|
|
24
|
+
|
|
25
|
+
export type OwnProps = {
|
|
26
|
+
location: number;
|
|
27
|
+
popupPortalEl?: HTMLElement | null;
|
|
28
|
+
targetType?: TARGET_TYPE;
|
|
29
|
+
};
|
|
23
30
|
|
|
24
31
|
export type Props = {
|
|
25
32
|
activeAnnotationId: string | null;
|
|
@@ -32,7 +39,7 @@ export type Props = {
|
|
|
32
39
|
status: CreatorStatus;
|
|
33
40
|
};
|
|
34
41
|
|
|
35
|
-
export const mapStateToProps = (state: AppState, { location }:
|
|
42
|
+
export const mapStateToProps = (state: AppState, { location }: OwnProps): Props => {
|
|
36
43
|
return {
|
|
37
44
|
activeAnnotationId: getActiveAnnotationId(state),
|
|
38
45
|
isPromoting: getIsPromoting(state),
|
package/src/popup/PopupLayer.tsx
CHANGED
|
@@ -29,6 +29,7 @@ export type Props = {
|
|
|
29
29
|
location: number;
|
|
30
30
|
message: string;
|
|
31
31
|
mode: Mode;
|
|
32
|
+
popupPortalEl?: HTMLElement | null;
|
|
32
33
|
referenceId: string | null;
|
|
33
34
|
resetCreator: () => void;
|
|
34
35
|
setMessage: (message: string) => void;
|
|
@@ -53,6 +54,7 @@ const PopupLayer = (props: Props): JSX.Element | null => {
|
|
|
53
54
|
isThreadedAnnotation = false,
|
|
54
55
|
message,
|
|
55
56
|
mode,
|
|
57
|
+
popupPortalEl,
|
|
56
58
|
referenceId,
|
|
57
59
|
resetCreator,
|
|
58
60
|
setMessage,
|
|
@@ -111,6 +113,7 @@ const PopupLayer = (props: Props): JSX.Element | null => {
|
|
|
111
113
|
<div className="ba-PopupLayer-popup">
|
|
112
114
|
<PopupV2
|
|
113
115
|
onSubmit={handleSubmit}
|
|
116
|
+
popupPortalEl={popupPortalEl}
|
|
114
117
|
reference={reference}
|
|
115
118
|
/>
|
|
116
119
|
</div>
|
|
@@ -138,6 +141,7 @@ const PopupLayer = (props: Props): JSX.Element | null => {
|
|
|
138
141
|
<PopupV2
|
|
139
142
|
annotationId={activeAnnotationId}
|
|
140
143
|
onSubmit={handleSubmit}
|
|
144
|
+
popupPortalEl={popupPortalEl}
|
|
141
145
|
reference={activeReference}
|
|
142
146
|
/>
|
|
143
147
|
</div>
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import * as ReactDOM from 'react-dom/client';
|
|
3
|
-
import BaseManager, { Props } from '../common/BaseManager';
|
|
3
|
+
import BaseManager, { Options as BaseOptions, Props } from '../common/BaseManager';
|
|
4
4
|
import PopupContainer from './PopupContainer';
|
|
5
5
|
|
|
6
|
+
export type Options = BaseOptions & {
|
|
7
|
+
popupPortalEl?: HTMLElement | null;
|
|
8
|
+
};
|
|
9
|
+
|
|
6
10
|
export default class PopupManager extends BaseManager {
|
|
11
|
+
popupPortalEl?: HTMLElement | null;
|
|
12
|
+
|
|
13
|
+
constructor({ popupPortalEl, ...options }: Options) {
|
|
14
|
+
super(options);
|
|
15
|
+
this.popupPortalEl = popupPortalEl;
|
|
16
|
+
}
|
|
17
|
+
|
|
7
18
|
decorate(): void {
|
|
8
19
|
this.reactEl.classList.add('ba-Layer--popup');
|
|
9
20
|
this.reactEl.dataset.testid = 'ba-Layer--popup';
|
|
@@ -13,7 +24,14 @@ export default class PopupManager extends BaseManager {
|
|
|
13
24
|
if (!this.root) {
|
|
14
25
|
this.root = ReactDOM.createRoot(this.reactEl);
|
|
15
26
|
}
|
|
16
|
-
|
|
17
|
-
this.root.render(
|
|
27
|
+
|
|
28
|
+
this.root.render(
|
|
29
|
+
<PopupContainer
|
|
30
|
+
location={this.location}
|
|
31
|
+
{...props}
|
|
32
|
+
popupPortalEl={this.popupPortalEl}
|
|
33
|
+
targetType={this.targetType}
|
|
34
|
+
/>,
|
|
35
|
+
);
|
|
18
36
|
}
|
|
19
37
|
}
|