box-annotations 5.2.1-beta.8 → 5.3.1-beta.0

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 (121) hide show
  1. package/dist/annotations.css +1 -1
  2. package/dist/annotations.js +1 -1
  3. package/dist/annotations.js.LICENSE.txt +1 -10
  4. package/i18n/bn-IN.js +6 -0
  5. package/i18n/bn-IN.properties +12 -0
  6. package/i18n/da-DK.js +6 -0
  7. package/i18n/da-DK.properties +12 -0
  8. package/i18n/de-DE.js +6 -0
  9. package/i18n/de-DE.properties +12 -0
  10. package/i18n/en-AU.js +6 -0
  11. package/i18n/en-AU.properties +12 -0
  12. package/i18n/en-CA.js +6 -0
  13. package/i18n/en-CA.properties +12 -0
  14. package/i18n/en-GB.js +6 -0
  15. package/i18n/en-GB.properties +12 -0
  16. package/i18n/es-419.js +6 -0
  17. package/i18n/es-419.properties +12 -0
  18. package/i18n/es-ES.js +6 -0
  19. package/i18n/es-ES.properties +12 -0
  20. package/i18n/fi-FI.js +6 -0
  21. package/i18n/fi-FI.properties +12 -0
  22. package/i18n/fr-CA.js +6 -0
  23. package/i18n/fr-CA.properties +12 -0
  24. package/i18n/fr-FR.js +6 -0
  25. package/i18n/fr-FR.properties +12 -0
  26. package/i18n/hi-IN.js +6 -0
  27. package/i18n/hi-IN.properties +12 -0
  28. package/i18n/it-IT.js +6 -0
  29. package/i18n/it-IT.properties +12 -0
  30. package/i18n/ja-JP.js +7 -1
  31. package/i18n/ja-JP.properties +13 -1
  32. package/i18n/ko-KR.js +6 -0
  33. package/i18n/ko-KR.properties +12 -0
  34. package/i18n/nb-NO.js +6 -0
  35. package/i18n/nb-NO.properties +12 -0
  36. package/i18n/nl-NL.js +6 -0
  37. package/i18n/nl-NL.properties +12 -0
  38. package/i18n/pl-PL.js +6 -0
  39. package/i18n/pl-PL.properties +12 -0
  40. package/i18n/pt-BR.js +6 -0
  41. package/i18n/pt-BR.properties +12 -0
  42. package/i18n/ru-RU.js +6 -0
  43. package/i18n/ru-RU.properties +12 -0
  44. package/i18n/sv-SE.js +6 -0
  45. package/i18n/sv-SE.properties +12 -0
  46. package/i18n/tr-TR.js +6 -0
  47. package/i18n/tr-TR.properties +12 -0
  48. package/i18n/zh-CN.js +6 -0
  49. package/i18n/zh-CN.properties +12 -0
  50. package/i18n/zh-TW.js +6 -0
  51. package/i18n/zh-TW.properties +12 -0
  52. package/index.js +1 -1
  53. package/package.json +54 -42
  54. package/src/@types/api.ts +3 -2
  55. package/src/@types/events.ts +27 -10
  56. package/src/@types/global.ts +0 -9
  57. package/src/@types/model.ts +9 -0
  58. package/src/BoxAnnotations.ts +6 -2
  59. package/src/adapters/threadedAnnotationsAdapters.ts +49 -28
  60. package/src/api/APIFactory.ts +6 -1
  61. package/src/api/types.ts +23 -1
  62. package/src/boundingBoxHighlight/BoundingBoxHighlightContainer.tsx +4 -1
  63. package/src/common/AnnotationCallbacksContext.ts +7 -0
  64. package/src/common/BaseAnnotator.scss +12 -0
  65. package/src/common/BaseAnnotator.ts +32 -2
  66. package/src/common/BaseManager.ts +2 -0
  67. package/src/common/DeselectListener.tsx +1 -1
  68. package/src/common/withProviders.tsx +6 -2
  69. package/src/components/BoundingBoxHighlight/BoundingBoxHighlightNav.scss +3 -3
  70. package/src/components/BoundingBoxHighlight/BoundingBoxHighlightRect.scss +11 -6
  71. package/src/components/Popups/PopupBase.scss +2 -2
  72. package/src/components/Popups/PopupDrawingToolbar.scss +4 -4
  73. package/src/components/Popups/PopupDrawingToolbar.tsx +0 -7
  74. package/src/components/Popups/PopupList.scss +1 -1
  75. package/src/components/Popups/PopupV2.scss +2 -2
  76. package/src/components/Popups/PopupV2.tsx +128 -72
  77. package/src/components/ReplyForm/ReplyForm.tsx +1 -8
  78. package/src/constants.ts +2 -3
  79. package/src/document/DocumentAnnotator.ts +29 -5
  80. package/src/document/docUtil.ts +8 -1
  81. package/src/drawing/DrawingAnnotations.tsx +30 -21
  82. package/src/drawing/DrawingAnnotationsContainer.tsx +3 -0
  83. package/src/drawing/DrawingCreator.tsx +9 -16
  84. package/src/drawing/DrawingCursor.ts +2 -1
  85. package/src/drawing/DrawingManager.tsx +21 -2
  86. package/src/highlight/HighlightAnnotations.tsx +28 -14
  87. package/src/highlight/HighlightContainer.tsx +3 -0
  88. package/src/highlight/HighlightCreator.scss +9 -2
  89. package/src/highlight/HighlightCreatorManager.ts +8 -5
  90. package/src/highlight/HighlightListener.ts +4 -2
  91. package/src/highlight/HighlightManager.tsx +13 -2
  92. package/src/image/ImageAnnotator.ts +2 -1
  93. package/src/media/MediaAnnotator.ts +39 -16
  94. package/src/popup/PopupLayer.tsx +38 -11
  95. package/src/popup/PopupManager.tsx +4 -2
  96. package/src/region/RegionAnnotations.tsx +2 -3
  97. package/src/region/RegionCreation.tsx +15 -9
  98. package/src/region/RegionCreationContainer.tsx +2 -2
  99. package/src/region/RegionCreationManager.tsx +8 -1
  100. package/src/region/RegionCreator.scss +9 -3
  101. package/src/region/RegionCreator.tsx +9 -17
  102. package/src/region/RegionManager.tsx +8 -1
  103. package/src/region/RegionRect.scss +17 -9
  104. package/src/store/annotations/actions.ts +104 -33
  105. package/src/store/annotations/reducer.ts +49 -1
  106. package/src/store/creator/selectors.ts +6 -6
  107. package/src/store/eventing/create.ts +6 -4
  108. package/src/store/eventing/delete.ts +26 -0
  109. package/src/store/eventing/middleware.ts +53 -15
  110. package/src/store/eventing/replyCreate.ts +30 -0
  111. package/src/store/eventing/replyDelete.ts +31 -0
  112. package/src/store/eventing/replyUpdate.ts +35 -0
  113. package/src/store/eventing/types.ts +4 -4
  114. package/src/store/eventing/update.ts +28 -0
  115. package/src/store/highlight/actions.ts +50 -19
  116. package/src/store/highlight/types.ts +1 -0
  117. package/src/store/options/selectors.ts +2 -2
  118. package/src/store/options/types.ts +2 -2
  119. package/src/test-utils/videoAnnotations.tsx +11 -11
  120. package/src/utils/rotate.ts +43 -0
  121. package/src/utils/useVideoTiming.ts +9 -13
@@ -1,4 +1,11 @@
1
- import type { DocumentNodeV2, MentionNodeV2, ParagraphNodeV2, TextMessageTypeV2, TextNodeV2 } from '@box/threaded-annotations';
1
+ import type {
2
+ DocumentNodeV2,
3
+ MentionNodeV2,
4
+ ParagraphNodeV2,
5
+ TextMessageTypeV2,
6
+ TextNodeV2,
7
+ } from '@box/threaded-annotations';
8
+ import { parseMessageMarkdown } from '@box/threaded-annotations';
2
9
 
3
10
  import type { Annotation, Collaborator, Reply, UserMini } from '../@types';
4
11
 
@@ -69,10 +76,27 @@ export const deserializeMentionMarkup = (text: string): DocumentNodeV2 => {
69
76
  return { type: 'doc', content };
70
77
  };
71
78
 
79
+ const toDocumentNode = (text: string, isRichTextEnabled = false): DocumentNodeV2 =>
80
+ isRichTextEnabled ? (parseMessageMarkdown(text) as DocumentNodeV2) : deserializeMentionMarkup(text);
81
+
82
+ /**
83
+ * Returns the edit timestamp consumers use to render an edited indicator.
84
+ * Compares parsed instants, not raw strings, so equivalent ISO formats
85
+ * (Z vs +00:00, fractional precision) are treated as unedited.
86
+ */
87
+ const toUpdatedAt = (createdAt: string, modifiedAt: string | undefined): number | undefined => {
88
+ if (!modifiedAt) return undefined;
89
+ const modifiedMs = new Date(modifiedAt).getTime();
90
+ if (Number.isNaN(modifiedMs)) return undefined;
91
+ const createdMs = new Date(createdAt).getTime();
92
+ if (modifiedMs === createdMs) return undefined;
93
+ return modifiedMs;
94
+ };
95
+
72
96
  /**
73
97
  * Converts a box-annotations Reply to a threaded-annotations TextMessageType.
74
98
  */
75
- export const replyToTextMessage = (reply: Reply): TextMessageTypeV2 => ({
99
+ export const replyToTextMessage = (reply: Reply, isRichTextEnabled = false): TextMessageTypeV2 => ({
76
100
  author: {
77
101
  email: reply.created_by?.login ?? '',
78
102
  id: parseInt(reply.created_by?.id ?? '0', 10),
@@ -80,55 +104,50 @@ export const replyToTextMessage = (reply: Reply): TextMessageTypeV2 => ({
80
104
  },
81
105
  createdAt: new Date(reply.created_at).getTime(),
82
106
  id: reply.id,
83
- message: deserializeMentionMarkup(reply.message),
107
+ message: toDocumentNode(reply.message, isRichTextEnabled),
84
108
  permissions: {
85
- canDelete: false,
86
- canEdit: false,
87
- canReply: true,
88
- canResolve: false,
109
+ canDelete: reply.permissions?.can_delete ?? false,
110
+ canEdit: reply.permissions?.can_edit ?? false,
111
+ canReply: reply.permissions?.can_reply ?? false,
112
+ canResolve: reply.permissions?.can_resolve ?? false,
89
113
  },
114
+ updatedAt: toUpdatedAt(reply.created_at, reply.modified_at),
90
115
  });
91
116
 
92
- /**
93
- * Converts an Annotation's description (root message) to a TextMessageType.
94
- * The root message gets resolve permission from the annotation's permissions.
95
- * Falls back to annotation-level fields when the description object is sparse
96
- * (the list endpoint returns description with only { message }).
97
- */
98
- const descriptionToTextMessage = (
99
- annotation: Annotation,
100
- reply: Reply,
101
- ): TextMessageTypeV2 => ({
117
+ // The root message shares the annotation's author and permissions; description
118
+ // comes back sparse ({ message } only) from the list endpoint.
119
+ const descriptionToTextMessage = (annotation: Annotation, isRichTextEnabled = false): TextMessageTypeV2 => ({
102
120
  author: {
103
- email: (reply.created_by ?? annotation.created_by)?.login ?? '',
104
- id: parseInt((reply.created_by ?? annotation.created_by)?.id ?? '0', 10),
105
- name: (reply.created_by ?? annotation.created_by)?.name ?? '',
121
+ email: annotation.created_by?.login ?? '',
122
+ id: parseInt(annotation.created_by?.id ?? '0', 10),
123
+ name: annotation.created_by?.name ?? '',
106
124
  },
107
- createdAt: new Date(reply.created_at ?? annotation.created_at).getTime(),
108
- id: reply.id ?? annotation.id,
109
- message: deserializeMentionMarkup(reply.message),
125
+ createdAt: new Date(annotation.created_at).getTime(),
126
+ id: annotation.id,
127
+ message: toDocumentNode(annotation.description?.message ?? '', isRichTextEnabled),
110
128
  permissions: {
111
129
  canDelete: annotation.permissions?.can_delete ?? false,
112
130
  canEdit: annotation.permissions?.can_edit ?? false,
113
- canReply: true,
131
+ canReply: annotation.permissions?.can_reply ?? false,
114
132
  canResolve: annotation.permissions?.can_resolve ?? false,
115
133
  },
134
+ updatedAt: toUpdatedAt(annotation.created_at, annotation.modified_at),
116
135
  });
117
136
 
118
137
  /**
119
138
  * Maps a full Annotation (description + replies) to an array of TextMessageType
120
139
  * suitable for ThreadedAnnotationsV2.
121
140
  */
122
- export const annotationToMessages = (annotation: Annotation): TextMessageTypeV2[] => {
141
+ export const annotationToMessages = (annotation: Annotation, isRichTextEnabled = false): TextMessageTypeV2[] => {
123
142
  const messages: TextMessageTypeV2[] = [];
124
143
 
125
144
  if (annotation.description) {
126
- messages.push(descriptionToTextMessage(annotation, annotation.description));
145
+ messages.push(descriptionToTextMessage(annotation, isRichTextEnabled));
127
146
  }
128
147
 
129
148
  if (annotation.replies) {
130
149
  annotation.replies.forEach(reply => {
131
- messages.push(replyToTextMessage(reply));
150
+ messages.push(replyToTextMessage(reply, isRichTextEnabled));
132
151
  });
133
152
  }
134
153
 
@@ -138,7 +157,9 @@ export const annotationToMessages = (annotation: Annotation): TextMessageTypeV2[
138
157
  /**
139
158
  * Converts a box-annotations Collaborator to a @box/user-selector UserContactType.
140
159
  */
141
- export const collaboratorToUserContact = (collaborator: Collaborator): {
160
+ export const collaboratorToUserContact = (
161
+ collaborator: Collaborator,
162
+ ): {
142
163
  email: string;
143
164
  id: number;
144
165
  name: string;
@@ -1,7 +1,8 @@
1
1
  import Annotations from 'box-ui-elements/es/api/Annotations';
2
2
  import FileCollaborators from 'box-ui-elements/es/api/FileCollaborators';
3
+ import ThreadedComments from 'box-ui-elements/es/api/ThreadedComments';
3
4
  import { DEFAULT_HOSTNAME_API } from 'box-ui-elements/es/constants';
4
- import { AnnotationsAPI, CollaboratorsAPI, APIOptions } from './types';
5
+ import { AnnotationsAPI, CollaboratorsAPI, APIOptions, ThreadedCommentsAPI } from './types';
5
6
 
6
7
  export default class APIFactory {
7
8
  options: APIOptions;
@@ -21,4 +22,8 @@ export default class APIFactory {
21
22
  getCollaboratorsAPI(): CollaboratorsAPI {
22
23
  return new FileCollaborators(this.options);
23
24
  }
25
+
26
+ getThreadedCommentsAPI(): ThreadedCommentsAPI {
27
+ return new ThreadedComments(this.options);
28
+ }
24
29
  }
package/src/api/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Annotation, Collaborator, NewAnnotation, Permissions, Reply, Token } from '../@types';
1
+ import { Annotation, Collaborator, NewAnnotation, Permissions, Reply, ReplyPermissions, Token } from '../@types';
2
2
 
3
3
  export type APICollection<R> = {
4
4
  entries: R[];
@@ -73,6 +73,28 @@ export interface AnnotationsAPI {
73
73
  destroy(): void;
74
74
  }
75
75
 
76
+ export interface ThreadedCommentsAPI {
77
+ deleteComment(args: {
78
+ commentId: string;
79
+ errorCallback: (error: APIError) => void;
80
+ fileId: string | null;
81
+ permissions: ReplyPermissions;
82
+ successCallback: () => void;
83
+ }): void;
84
+
85
+ updateComment(args: {
86
+ commentId: string;
87
+ errorCallback: (error: APIError) => void;
88
+ fileId: string | null;
89
+ message?: string;
90
+ permissions: ReplyPermissions;
91
+ status?: string;
92
+ successCallback: (reply: Reply) => void;
93
+ }): void;
94
+
95
+ destroy(): void;
96
+ }
97
+
76
98
  export interface CollaboratorsAPI {
77
99
  getFileCollaborators(
78
100
  fileId: string | null,
@@ -15,7 +15,10 @@ export type Props = {
15
15
  location: number;
16
16
  };
17
17
 
18
- const mapStateToProps = (state: AppState, { location }: Props): {
18
+ const mapStateToProps = (
19
+ state: AppState,
20
+ { location }: Props,
21
+ ): {
19
22
  allBoundingBoxes: BoundingBox[];
20
23
  boundingBoxes: BoundingBox[];
21
24
  selectedId: string | null;
@@ -0,0 +1,7 @@
1
+ import { createContext } from 'react';
2
+
3
+ export type AnnotationCallbacks = {
4
+ onCopyLink?: (params: { annotationId: string; fileVersionId: string }) => void;
5
+ };
6
+
7
+ export default createContext<AnnotationCallbacks>({});
@@ -28,3 +28,15 @@
28
28
  .ba-Layer--popup {
29
29
  z-index: 4;
30
30
  }
31
+
32
+ .ba-PopupPortal {
33
+ position: relative;
34
+ z-index: 10;
35
+ pointer-events: none;
36
+
37
+ .ba-Popup,
38
+ .ba-PopupAnnotation {
39
+ z-index: 150;
40
+ pointer-events: auto;
41
+ }
42
+ }
@@ -6,7 +6,7 @@ import DeselectManager from './DeselectManager';
6
6
  import EventEmitter from './EventEmitter';
7
7
  import i18n from '../utils/i18n';
8
8
  import messages from '../messages';
9
- import { Event, IntlOptions, LegacyEvent, Permissions } from '../@types';
9
+ import { Event, IntlOptions, LegacyEvent, Permissions, SidebarEvent, Token } from '../@types';
10
10
  import { BoundingBox, getBoundingBoxHighlights } from '../store/boundingBoxHighlights';
11
11
  import { ViewMode } from '../store/options/types';
12
12
  import { Features } from '../BoxAnnotations';
@@ -44,7 +44,8 @@ export type Options = {
44
44
  initialViewMode?: ViewMode;
45
45
  intl: IntlOptions;
46
46
  locale?: string;
47
- token: string;
47
+ onCopyLink?: (params: { annotationId: string; fileVersionId: string }) => void;
48
+ token: Token;
48
49
  };
49
50
 
50
51
  export const CSS_CONTAINER_CLASS = 'ba';
@@ -70,6 +71,8 @@ export default class BaseAnnotator extends EventEmitter {
70
71
 
71
72
  intl: IntlShape;
72
73
 
74
+ onCopyLink?: (params: { annotationId: string; fileVersionId: string }) => void;
75
+
73
76
  store: store.AppStore;
74
77
 
75
78
  constructor({
@@ -82,6 +85,7 @@ export default class BaseAnnotator extends EventEmitter {
82
85
  initialMode,
83
86
  initialViewMode = 'annotations',
84
87
  intl,
88
+ onCopyLink,
85
89
  token,
86
90
  }: Options) {
87
91
  super();
@@ -111,6 +115,7 @@ export default class BaseAnnotator extends EventEmitter {
111
115
  this.container = container;
112
116
  this.features = features;
113
117
  this.intl = i18n.createIntlProvider(intl);
118
+ this.onCopyLink = onCopyLink;
114
119
  this.store = store.createStore(initialState, {
115
120
  api: new API({ apiHost, token }),
116
121
  });
@@ -126,6 +131,11 @@ export default class BaseAnnotator extends EventEmitter {
126
131
  this.addListener(Event.BOUNDING_BOX_HIGHLIGHT_SELECT, this.handleSelectBoundingBoxHighlight);
127
132
  this.addListener(Event.VIEW_MODE_SET, this.handleSetViewMode);
128
133
 
134
+ this.addListener(SidebarEvent.SIDEBAR_ANNOTATION_UPDATE, this.handleSidebarAnnotationUpdate);
135
+ this.addListener(SidebarEvent.SIDEBAR_REPLY_CREATE, this.handleSidebarReplyCreate);
136
+ this.addListener(SidebarEvent.SIDEBAR_REPLY_UPDATE, this.handleSidebarReplyUpdate);
137
+ this.addListener(SidebarEvent.SIDEBAR_REPLY_DELETE, this.handleSidebarReplyDelete);
138
+
129
139
  // Load any required data at startup
130
140
  this.hydrate();
131
141
  }
@@ -159,6 +169,10 @@ export default class BaseAnnotator extends EventEmitter {
159
169
  this.removeListener(Event.BOUNDING_BOX_HIGHLIGHT_NAVIGATE, this.handleNavigateBoundingBoxHighlight);
160
170
  this.removeListener(Event.BOUNDING_BOX_HIGHLIGHT_SELECT, this.handleSelectBoundingBoxHighlight);
161
171
  this.removeListener(Event.VIEW_MODE_SET, this.handleSetViewMode);
172
+ this.removeListener(SidebarEvent.SIDEBAR_ANNOTATION_UPDATE, this.handleSidebarAnnotationUpdate);
173
+ this.removeListener(SidebarEvent.SIDEBAR_REPLY_CREATE, this.handleSidebarReplyCreate);
174
+ this.removeListener(SidebarEvent.SIDEBAR_REPLY_UPDATE, this.handleSidebarReplyUpdate);
175
+ this.removeListener(SidebarEvent.SIDEBAR_REPLY_DELETE, this.handleSidebarReplyDelete);
162
176
  }
163
177
 
164
178
  public init(scale = 1, rotation = 0): void {
@@ -352,6 +366,22 @@ export default class BaseAnnotator extends EventEmitter {
352
366
  this.setViewMode(viewMode);
353
367
  };
354
368
 
369
+ protected handleSidebarAnnotationUpdate = (annotation: store.SidebarAnnotationUpdatePayload): void => {
370
+ this.store.dispatch(store.applySidebarAnnotationUpdateAction(annotation));
371
+ };
372
+
373
+ protected handleSidebarReplyCreate = (payload: store.SidebarReplyMutationPayload): void => {
374
+ this.store.dispatch(store.applySidebarReplyCreateAction(payload));
375
+ };
376
+
377
+ protected handleSidebarReplyUpdate = (payload: store.SidebarReplyMutationPayload): void => {
378
+ this.store.dispatch(store.applySidebarReplyUpdateAction(payload));
379
+ };
380
+
381
+ protected handleSidebarReplyDelete = ({ annotationId, id }: { annotationId: string; id: string }): void => {
382
+ this.store.dispatch(store.applySidebarReplyDeleteAction({ annotationId, replyId: id }));
383
+ };
384
+
355
385
  protected hydrate(): void {
356
386
  // Redux dispatch method signature doesn't seem to like async actions
357
387
  this.store.dispatch<any>(store.fetchAnnotationsAction()); // eslint-disable-line @typescript-eslint/no-explicit-any
@@ -1,6 +1,7 @@
1
1
  import * as ReactDOM from 'react-dom/client';
2
2
  import { IntlShape } from 'react-intl';
3
3
  import { Store } from 'redux';
4
+ import { AnnotationCallbacks } from './AnnotationCallbacksContext';
4
5
  import { applyResinTags } from '../utils/resin';
5
6
  import { TARGET_TYPE } from '../constants';
6
7
 
@@ -14,6 +15,7 @@ export type Options = {
14
15
  };
15
16
 
16
17
  export type Props = {
18
+ callbacks?: AnnotationCallbacks;
17
19
  intl: IntlShape;
18
20
  store: Store;
19
21
  };
@@ -8,7 +8,7 @@ export default function DeselectListener(): null {
8
8
  React.useEffect(() => {
9
9
  const handleMouseDown = (event: MouseEvent): void => {
10
10
  // Popup is portaled outside .ba-Layer; native mousedown still bubbles here.
11
- if ((event.target as Element | null)?.closest?.('.ba-PopupV2')) return;
11
+ if ((event.target as Element | null)?.closest?.('.ba-PopupAnnotation, .ba-Popup')) return;
12
12
  dispatch(setActiveAnnotationIdAction(null));
13
13
  };
14
14
 
@@ -2,8 +2,10 @@ import * as React from 'react';
2
2
  import { IntlShape, RawIntlProvider } from 'react-intl';
3
3
  import { Provider as StoreProvider } from 'react-redux';
4
4
  import { Store } from 'redux';
5
+ import AnnotationCallbacksContext, { AnnotationCallbacks } from './AnnotationCallbacksContext';
5
6
 
6
7
  type WrapperProps = {
8
+ callbacks?: AnnotationCallbacks;
7
9
  intl: IntlShape;
8
10
  store: Store;
9
11
  };
@@ -11,11 +13,13 @@ type WrapperProps = {
11
13
  type WrapperReturn<P> = React.FC<P & WrapperProps>;
12
14
 
13
15
  export default function withProviders<P extends object>(WrappedComponent: React.ComponentType<P>): WrapperReturn<P> {
14
- return function RootProvider({ intl, store, ...rest }: P & WrapperProps): JSX.Element {
16
+ return function RootProvider({ callbacks, intl, store, ...rest }: P & WrapperProps): JSX.Element {
15
17
  return (
16
18
  <RawIntlProvider value={intl}>
17
19
  <StoreProvider store={store}>
18
- <WrappedComponent {...(rest as P)} />
20
+ <AnnotationCallbacksContext.Provider value={callbacks ?? {}}>
21
+ <WrappedComponent {...(rest as P)} />
22
+ </AnnotationCallbacksContext.Provider>
19
23
  </StoreProvider>
20
24
  </RawIntlProvider>
21
25
  );
@@ -1,5 +1,5 @@
1
1
  $ba-BoundingBoxHighlightNav-bg: #fff;
2
- $ba-BoundingBoxHighlightNav-shadow: 0 6px 20px rgba(0, 0, 0, .1);
2
+ $ba-BoundingBoxHighlightNav-shadow: 0 6px 20px rgb(0 0 0 / 10%);
3
3
  $ba-BoundingBoxHighlightNav-arrow: #909090;
4
4
  $ba-BoundingBoxHighlightNav-border: #e8e8e8;
5
5
  $ba-BoundingBoxHighlightNav-counter: #222;
@@ -45,11 +45,11 @@ $ba-BoundingBoxHighlightNav-counter: #222;
45
45
  }
46
46
 
47
47
  &:hover:not(:disabled) {
48
- background: rgba(0, 0, 0, .06);
48
+ background: rgb(0 0 0 / 6%);
49
49
  }
50
50
 
51
51
  &:active:not(:disabled) {
52
- background: rgba(0, 0, 0, .12);
52
+ background: rgb(0 0 0 / 12%);
53
53
  }
54
54
 
55
55
  &:disabled {
@@ -1,22 +1,27 @@
1
1
  $ba-BoundingBoxHighlight-color: #0061d5;
2
- $ba-BoundingBoxHighlight-bgColor--default: rgba($ba-BoundingBoxHighlight-color, .05);
3
- $ba-BoundingBoxHighlight-bgColor--hover: rgba($ba-BoundingBoxHighlight-color, .16);
4
- $ba-BoundingBoxHighlight-bgColor--selected: rgba($ba-BoundingBoxHighlight-color, .1);
2
+ $ba-BoundingBoxHighlight-bgColor--default: rgba($ba-BoundingBoxHighlight-color, 0.05);
3
+ $ba-BoundingBoxHighlight-bgColor--hover: rgba($ba-BoundingBoxHighlight-color, 0.16);
4
+ $ba-BoundingBoxHighlight-bgColor--selected: rgba($ba-BoundingBoxHighlight-color, 0.1);
5
5
 
6
6
  .ba-BoundingBoxHighlightRect {
7
7
  position: absolute;
8
8
  box-sizing: border-box;
9
9
  background-color: $ba-BoundingBoxHighlight-bgColor--default;
10
- border: 2px solid rgba($ba-BoundingBoxHighlight-color, .2);
10
+ border: 2px solid rgba($ba-BoundingBoxHighlight-color, 0.2);
11
11
  border-radius: 8px;
12
12
  outline: none;
13
13
  cursor: pointer;
14
- transition: background-color 200ms ease, border-color 200ms ease, box-shadow 200ms ease;
14
+ transition:
15
+ background-color 200ms ease,
16
+ border-color 200ms ease,
17
+ box-shadow 200ms ease;
15
18
  pointer-events: auto;
16
19
 
17
20
  &.is-selected {
18
21
  background-color: $ba-BoundingBoxHighlight-bgColor--selected;
19
22
  border-color: $ba-BoundingBoxHighlight-color;
20
- box-shadow: 0 0 0 2px rgba($ba-BoundingBoxHighlight-color, .3), 0 4px 12px rgba(0, 0, 0, .15);
23
+ box-shadow:
24
+ 0 0 0 2px rgba($ba-BoundingBoxHighlight-color, 0.3),
25
+ 0 4px 12px rgb(0 0 0 / 15%);
21
26
  }
22
27
  }
@@ -25,7 +25,7 @@
25
25
  }
26
26
 
27
27
  .ba-ReplyForm {
28
- opacity: .99; // Creates a new stacking context so that the collaborators list shows on top of the ba-Popup-footer
28
+ opacity: 0.99; // Creates a new stacking context so that the collaborators list shows on top of the ba-Popup-footer
29
29
  }
30
30
  }
31
31
 
@@ -34,7 +34,7 @@
34
34
  background-color: $popup-content-bg;
35
35
  border: 1px solid $popup-border-color;
36
36
  border-radius: 6px;
37
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .15);
37
+ box-shadow: 0 2px 12px 0 rgb(0 0 0 / 15%);
38
38
  }
39
39
 
40
40
  .ba-Popup-footer {
@@ -13,7 +13,7 @@
13
13
  border-radius: $bdl-border-radius-size;
14
14
  outline: none;
15
15
  cursor: pointer;
16
- opacity: .7;
16
+ opacity: 0.7;
17
17
  transition: opacity 200ms ease;
18
18
 
19
19
  &:focus,
@@ -23,7 +23,7 @@
23
23
 
24
24
  &[disabled] {
25
25
  cursor: default;
26
- opacity: .2;
26
+ opacity: 0.2;
27
27
  }
28
28
  }
29
29
 
@@ -53,7 +53,7 @@
53
53
  .ba-Popup-content {
54
54
  gap: 4px;
55
55
  padding: 8px;
56
- background-color: rgba(0, 0, 0, .8);
56
+ background-color: rgb(0 0 0 / 80%);
57
57
  border-radius: 46px;
58
58
  }
59
59
  }
@@ -75,7 +75,7 @@
75
75
 
76
76
  // Modernized border-left for adjacent groups
77
77
  .ba-PopupDrawingToolbar--modernized .ba-PopupDrawingToolbar-group + .ba-PopupDrawingToolbar-group {
78
- border-left: 1px solid rgb(255, 255, 255, 8%);
78
+ border-left: 1px solid rgb(255 255 255 / 8%);
79
79
  }
80
80
 
81
81
  .ba-PopupDrawingToolbar-delete,
@@ -33,12 +33,6 @@ export type Props = {
33
33
 
34
34
  const options: Partial<Options> = {
35
35
  modifiers: [
36
- {
37
- name: 'eventListeners',
38
- options: {
39
- scroll: false,
40
- },
41
- },
42
36
  {
43
37
  name: 'offset',
44
38
  options: {
@@ -48,7 +42,6 @@ const options: Partial<Options> = {
48
42
  {
49
43
  name: 'preventOverflow',
50
44
  options: {
51
- altAxis: true,
52
45
  padding: 50,
53
46
  },
54
47
  },
@@ -8,7 +8,7 @@
8
8
  .ba-Popup-content {
9
9
  border: solid 1px $bdl-gray-30;
10
10
  border-radius: $bdl-border-radius-size;
11
- box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .05);
11
+ box-shadow: 0 1px 2px 0 rgb(0 0 0 / 5%);
12
12
  }
13
13
 
14
14
  .ba-PopupList-prompt {
@@ -1,4 +1,4 @@
1
- .ba-PopupV2 {
1
+ .ba-PopupAnnotation {
2
2
  position: absolute;
3
3
  top: 0;
4
4
  left: 0;
@@ -8,7 +8,7 @@
8
8
 
9
9
  // Specificity must beat .ba selectors from box-ui-elements globals
10
10
  // (forms, buttons, links) that cascade into threaded-annotations components.
11
- .ba .ba-PopupV2 {
11
+ .ba .ba-PopupAnnotation {
12
12
  div[contenteditable='true'],
13
13
  div[contenteditable='true']:hover,
14
14
  div[contenteditable='true']:focus {