box-annotations 5.2.1-beta.0 → 5.2.1-beta.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "box-annotations",
3
- "version": "5.2.1-beta.0",
3
+ "version": "5.2.1-beta.1",
4
4
  "description": "Box Annotations",
5
5
  "author": "Box (https://www.box.com/)",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -36,6 +36,9 @@
36
36
  "@formatjs/intl-relativetimeformat": "^4.5.12",
37
37
  "@popperjs/core": "^2.4.0",
38
38
  "@reduxjs/toolkit": "^1.3.5",
39
+ "@testing-library/dom": "^10.4.1",
40
+ "@testing-library/jest-dom": "^6.9.1",
41
+ "@testing-library/react": "^16.3.2",
39
42
  "@types/classnames": "^2.2.10",
40
43
  "@types/draft-js": "^0.10.40",
41
44
  "@types/enzyme": "^3.10.5",
@@ -19,7 +19,8 @@ type AnnotationsOptions = {
19
19
  };
20
20
 
21
21
  export type Features = {
22
- [key: string]: boolean;
22
+ isThreadedAnnotation?: boolean;
23
+ [key: string]: boolean | undefined;
23
24
  };
24
25
 
25
26
  type PreviewOptions = {
@@ -5,14 +5,19 @@ import { useIntl } from 'react-intl';
5
5
  import FocusTrap from 'box-ui-elements/es/components/focus-trap/FocusTrap';
6
6
  import messages from './messages';
7
7
  import PopupBase from './PopupBase';
8
+ import PopupReplyV2 from './PopupReplyV2';
8
9
  import ReplyForm from '../ReplyForm';
9
10
  import { getScale, getRotation } from '../../store/options';
10
11
  import { PopupReference } from './Popper';
11
12
  import './PopupReply.scss';
12
13
 
13
- export type Props = {
14
+ type BaseProps = {
14
15
  className?: string;
16
+ };
17
+
18
+ type LegacyProps = BaseProps & {
15
19
  isPending: boolean;
20
+ isThreadedAnnotation?: false;
16
21
  onCancel: (text?: string) => void;
17
22
  onChange: (text?: string) => void;
18
23
  onSubmit: (text: string) => void;
@@ -20,6 +25,18 @@ export type Props = {
20
25
  value?: string;
21
26
  };
22
27
 
28
+ type ThreadedProps = BaseProps & {
29
+ isThreadedAnnotation: true;
30
+ isPending?: boolean;
31
+ onCancel?: (text?: string) => void;
32
+ onChange?: (text?: string) => void;
33
+ onSubmit?: (text: string) => void;
34
+ reference?: PopupReference;
35
+ value?: string;
36
+ };
37
+
38
+ export type Props = LegacyProps | ThreadedProps;
39
+
23
40
  const isIE = (): boolean => {
24
41
  const { userAgent } = navigator;
25
42
  return userAgent.indexOf('Trident/') > 0;
@@ -77,14 +94,7 @@ const getOptions = (): Partial<Popper.Options> => {
77
94
  };
78
95
  };
79
96
 
80
- export default function PopupReply({
81
- isPending,
82
- onCancel,
83
- onChange,
84
- onSubmit,
85
- value = '',
86
- ...rest
87
- }: Props): JSX.Element {
97
+ export default function PopupReply(props: Props): JSX.Element {
88
98
  const intl = useIntl();
89
99
  const popupRef = React.useRef<PopupBase>(null);
90
100
  const popupOptions = React.useRef<Partial<Popper.Options>>(getOptions()); // Keep the options reference the same between renders
@@ -99,6 +109,14 @@ export default function PopupReply({
99
109
  }
100
110
  }, [popupRef, rotation, scale]);
101
111
 
112
+ // TODO: PopupReplyV2 is a placeholder stub. Props (isPending, onCancel, etc.)
113
+ // are not yet forwarded and will need to be wired up when V2 is implemented.
114
+ if (props.isThreadedAnnotation) {
115
+ return <PopupReplyV2 />;
116
+ }
117
+
118
+ const { isPending, onCancel, onChange, onSubmit, value = '', isThreadedAnnotation: _, ...rest } = props as LegacyProps;
119
+
102
120
  return (
103
121
  <FocusTrap>
104
122
  <PopupBase
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+
3
+ /**
4
+ * Placeholder for the threaded annotation reply popup (V2).
5
+ * Replaces PopupReply when the isThreadedAnnotation feature flag is enabled.
6
+ * Currently renders an empty container — props will be wired up when V2 is implemented.
7
+ */
8
+ export default function PopupReplyV2(): JSX.Element {
9
+ return <div data-testid="popup-reply-v2" />;
10
+ }
@@ -15,12 +15,14 @@ import {
15
15
  setMessageAction,
16
16
  getCreatorReferenceId,
17
17
  } from '../store';
18
+ import { isFeatureEnabled } from '../store/options';
18
19
  import { createDrawingAction } from '../drawing/actions';
19
20
  import { createHighlightAction } from '../highlight/actions';
20
21
  import { createRegionAction } from '../region';
21
22
 
22
23
  export type Props = {
23
24
  isPromoting: boolean;
25
+ isThreadedAnnotation?: boolean;
24
26
  message: string;
25
27
  mode: Mode;
26
28
  referenceId: string | null;
@@ -31,6 +33,7 @@ export type Props = {
31
33
  export const mapStateToProps = (state: AppState, { location }: { location: number }): Props => {
32
34
  return {
33
35
  isPromoting: getIsPromoting(state),
36
+ isThreadedAnnotation: isFeatureEnabled(state, 'isThreadedAnnotation'),
34
37
  message: getCreatorMessage(state),
35
38
  mode: getAnnotationMode(state),
36
39
  referenceId: getCreatorReferenceId(state),
@@ -21,6 +21,7 @@ export type Props = {
21
21
  createHighlight?: (arg: HighlightCreateArg) => void;
22
22
  createRegion?: (arg: RegionCreateArg) => void;
23
23
  isPromoting: boolean;
24
+ isThreadedAnnotation?: boolean;
24
25
  location: number;
25
26
  message: string;
26
27
  mode: Mode;
@@ -44,6 +45,7 @@ const PopupLayer = (props: Props): JSX.Element | null => {
44
45
  createHighlight = noop,
45
46
  createRegion = noop,
46
47
  isPromoting = false,
48
+ isThreadedAnnotation = false,
47
49
  message,
48
50
  mode,
49
51
  referenceId,
@@ -92,6 +94,7 @@ const PopupLayer = (props: Props): JSX.Element | null => {
92
94
  <div className="ba-PopupLayer-popup">
93
95
  <PopupReply
94
96
  isPending={isPending}
97
+ isThreadedAnnotation={isThreadedAnnotation}
95
98
  onCancel={handleCancel}
96
99
  onChange={handleChange}
97
100
  onSubmit={handleSubmit}