@atlaskit/reactions 31.3.1 → 31.5.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 (28) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/cjs/analytics/index.js +1 -1
  3. package/dist/cjs/components/ReactionPicker.js +4 -0
  4. package/dist/cjs/components/ReactionSummaryView.js +83 -26
  5. package/dist/cjs/components/ReactionSummaryViewEmojiPicker.js +8 -6
  6. package/dist/cjs/hooks/useDelayedState.js +37 -0
  7. package/dist/cjs/shared/i18n.js +5 -0
  8. package/dist/es2019/analytics/index.js +1 -1
  9. package/dist/es2019/components/ReactionPicker.js +6 -1
  10. package/dist/es2019/components/ReactionSummaryView.js +73 -19
  11. package/dist/es2019/components/ReactionSummaryViewEmojiPicker.js +8 -4
  12. package/dist/es2019/hooks/useDelayedState.js +25 -0
  13. package/dist/es2019/shared/i18n.js +5 -0
  14. package/dist/esm/analytics/index.js +1 -1
  15. package/dist/esm/components/ReactionPicker.js +5 -1
  16. package/dist/esm/components/ReactionSummaryView.js +83 -26
  17. package/dist/esm/components/ReactionSummaryViewEmojiPicker.js +8 -6
  18. package/dist/esm/hooks/useDelayedState.js +30 -0
  19. package/dist/esm/shared/i18n.js +5 -0
  20. package/dist/types/components/ReactionSummaryView.d.ts +5 -1
  21. package/dist/types/components/ReactionSummaryViewEmojiPicker.d.ts +2 -1
  22. package/dist/types/hooks/useDelayedState.d.ts +3 -0
  23. package/dist/types/shared/i18n.d.ts +5 -0
  24. package/dist/types-ts4.5/components/ReactionSummaryView.d.ts +5 -1
  25. package/dist/types-ts4.5/components/ReactionSummaryViewEmojiPicker.d.ts +2 -1
  26. package/dist/types-ts4.5/hooks/useDelayedState.d.ts +6 -0
  27. package/dist/types-ts4.5/shared/i18n.d.ts +5 -0
  28. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @atlaskit/reactions
2
2
 
3
+ ## 31.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#145160](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/145160)
8
+ [`cab4c531afd63`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/cab4c531afd63) -
9
+ [ux] Modifies the clicking behavior for the hoverable summary view feature
10
+
11
+ ## 31.4.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [#144510](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/144510)
16
+ [`9d23464afe923`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/9d23464afe923) -
17
+ [ux] adding delay to opening/closing the summary view tray when hovering is enabled via the
18
+ hoverableSummaryView prop
19
+
20
+ ### Patch Changes
21
+
22
+ - Updated dependencies
23
+
3
24
  ## 31.3.1
4
25
 
5
26
  ### Patch Changes
@@ -11,7 +11,7 @@ var _analyticsGasTypes = require("@atlaskit/analytics-gas-types");
11
11
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
12
12
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
13
13
  var packageName = "@atlaskit/reactions";
14
- var packageVersion = "31.3.1";
14
+ var packageVersion = "31.5.0";
15
15
  /**
16
16
  * TODO: move to utility package?
17
17
  * A random sampling function
@@ -277,6 +277,8 @@ var PopperWrapper = exports.PopperWrapper = function PopperWrapper(props) {
277
277
  _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
278
278
  popupRef = _useState6[0],
279
279
  setPopupRef = _useState6[1];
280
+ var _useIntl = (0, _reactIntlNext.useIntl)(),
281
+ formatMessage = _useIntl.formatMessage;
280
282
  /**
281
283
  * add focus lock to popup
282
284
  */
@@ -293,6 +295,8 @@ var PopperWrapper = exports.PopperWrapper = function PopperWrapper(props) {
293
295
  style = _ref3.style,
294
296
  update = _ref3.update;
295
297
  return /*#__PURE__*/_react.default.createElement("div", {
298
+ role: "group",
299
+ "aria-label": formatMessage(_i18n.messages.popperWrapperLabel),
296
300
  id: PICKER_CONTROL_ID,
297
301
  "data-testid": RENDER_REACTIONPICKERPANEL_TESTID
298
302
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
@@ -14,9 +14,12 @@ var _runtime = require("@compiled/react/runtime");
14
14
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
15
15
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
16
16
  var _popup = _interopRequireDefault(require("@atlaskit/popup"));
17
+ var _picker = require("@atlaskit/emoji/picker");
18
+ var _useDelayedState3 = require("../hooks/useDelayedState");
17
19
  var _Reaction = require("./Reaction");
18
20
  var _ReactionSummaryViewEmojiPicker = require("./ReactionSummaryViewEmojiPicker");
19
21
  var _ReactionSummaryButton = require("./ReactionSummaryButton");
22
+ var _ufo = require("../ufo");
20
23
  var _compiled = require("@atlaskit/primitives/compiled");
21
24
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
22
25
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
@@ -59,65 +62,118 @@ var ReactionSummaryView = exports.ReactionSummaryView = function ReactionSummary
59
62
  useButtonAlignmentStyling = _ref.useButtonAlignmentStyling,
60
63
  reactionPickerTriggerText = _ref.reactionPickerTriggerText,
61
64
  _ref$hoverableSummary = _ref.hoverableSummaryView,
62
- hoverableSummaryView = _ref$hoverableSummary === void 0 ? false : _ref$hoverableSummary;
65
+ hoverableSummaryView = _ref$hoverableSummary === void 0 ? false : _ref$hoverableSummary,
66
+ _ref$hoverableSummary2 = _ref.hoverableSummaryViewDelay,
67
+ hoverableSummaryViewDelay = _ref$hoverableSummary2 === void 0 ? 300 : _ref$hoverableSummary2;
68
+ var _useDelayedState = (0, _useDelayedState3.useDelayedState)(false, hoverableSummaryViewDelay),
69
+ _useDelayedState2 = (0, _slicedToArray2.default)(_useDelayedState, 2),
70
+ isSummaryPopupOpen = _useDelayedState2[0],
71
+ setSummaryPopupOpen = _useDelayedState2[1];
63
72
  var _useState = (0, _react.useState)(false),
64
73
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
65
- isSummaryPopupOpen = _useState2[0],
66
- setSummaryPopupOpen = _useState2[1];
74
+ isHoveringSummaryView = _useState2[0],
75
+ setIsHoveringSummaryView = _useState2[1];
67
76
  var _useState3 = (0, _react.useState)(false),
68
77
  _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
69
- isHoveringSummaryView = _useState4[0],
70
- setIsHoveringSummaryView = _useState4[1];
78
+ isSummaryViewButtonHovered = _useState4[0],
79
+ setIsSummaryViewButtonHovered = _useState4[1];
71
80
  var _useState5 = (0, _react.useState)(false),
72
81
  _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
73
- isSummaryViewButtonHovered = _useState6[0],
74
- setIsSummaryViewButtonHovered = _useState6[1];
82
+ isSummaryButtonEmojiPickerOpen = _useState6[0],
83
+ setIsSummaryButtonEmojiPickerOpen = _useState6[1];
84
+ var _useState7 = (0, _react.useState)(false),
85
+ _useState8 = (0, _slicedToArray2.default)(_useState7, 2),
86
+ isSummaryViewTrayEmojiPickerOpen = _useState8[0],
87
+ setIsSummaryViewTrayEmojiPickerOpen = _useState8[1];
88
+
89
+ /**
90
+ * Event callback when the picker is closed
91
+ * @param _id Optional id if an emoji button was selected or undefined if was clicked outside the picker
92
+ */
93
+ var close = (0, _react.useCallback)(function (_id) {
94
+ setIsSummaryButtonEmojiPickerOpen(false);
95
+ // ufo abort reaction experience
96
+ _ufo.PickerRender.abort({
97
+ metadata: {
98
+ emojiId: _id,
99
+ source: 'ReactionPicker',
100
+ reason: 'close dialog'
101
+ }
102
+ });
103
+ }, [setIsSummaryButtonEmojiPickerOpen]);
104
+ /**
105
+ * Event callback when an emoji icon is selected
106
+ * @param item selected item
107
+ */
108
+ var onEmojiSelected = (0, _react.useCallback)(function (item) {
109
+ // no emoji was selected
110
+ if (!item.id) {
111
+ return;
112
+ }
113
+ onSelection(item.id, 'emojiPicker');
114
+ close(item.id);
115
+ }, [onSelection, close]);
75
116
  var handlePopupClose = (0, _react.useCallback)(function () {
76
- return setSummaryPopupOpen(false);
77
- }, []);
117
+ setSummaryPopupOpen(false);
118
+ setIsSummaryButtonEmojiPickerOpen(false);
119
+ }, [setSummaryPopupOpen, setIsSummaryButtonEmojiPickerOpen]);
78
120
  var handleSummaryClick = (0, _react.useCallback)(function () {
79
- return setSummaryPopupOpen(!isSummaryPopupOpen);
80
- }, [isSummaryPopupOpen]);
121
+ if (hoverableSummaryView) {
122
+ // ufo start reactions picker open experience
123
+ _ufo.PickerRender.start();
124
+ onOpen && onOpen();
125
+ setSummaryPopupOpen(false);
126
+ // ufo reactions picker opened success
127
+ _ufo.PickerRender.success();
128
+ } else {
129
+ setSummaryPopupOpen(!isSummaryPopupOpen);
130
+ }
131
+ setIsSummaryButtonEmojiPickerOpen(!isSummaryButtonEmojiPickerOpen);
132
+ }, [isSummaryPopupOpen, onOpen, isSummaryButtonEmojiPickerOpen, hoverableSummaryView, setSummaryPopupOpen, setIsSummaryButtonEmojiPickerOpen]);
81
133
  var handleButtonMouseEnter = (0, _react.useCallback)(function () {
82
134
  setIsSummaryViewButtonHovered(true);
83
- if (hoverableSummaryView) {
135
+ if (hoverableSummaryView && !isSummaryButtonEmojiPickerOpen) {
84
136
  setSummaryPopupOpen(true);
85
137
  }
86
- }, [hoverableSummaryView]);
138
+ }, [hoverableSummaryView, setSummaryPopupOpen, setIsSummaryViewButtonHovered, isSummaryButtonEmojiPickerOpen]);
87
139
  var handleButtonMouseLeave = (0, _react.useCallback)(function () {
88
140
  setIsSummaryViewButtonHovered(false);
89
- if (hoverableSummaryView && !isHoveringSummaryView) {
141
+ if (hoverableSummaryView && !isHoveringSummaryView && !isSummaryViewTrayEmojiPickerOpen) {
90
142
  setSummaryPopupOpen(false);
91
143
  }
92
- }, [hoverableSummaryView, isHoveringSummaryView]);
144
+ }, [hoverableSummaryView, isHoveringSummaryView, setSummaryPopupOpen, setIsSummaryViewButtonHovered, isSummaryViewTrayEmojiPickerOpen]);
93
145
  var handleSummaryViewTrayMouseEnter = (0, _react.useCallback)(function () {
94
146
  setIsHoveringSummaryView(true);
95
- if (hoverableSummaryView) {
147
+ if (hoverableSummaryView && !isSummaryButtonEmojiPickerOpen) {
96
148
  setSummaryPopupOpen(true);
97
149
  }
98
- }, [hoverableSummaryView]);
150
+ }, [hoverableSummaryView, setSummaryPopupOpen, setIsHoveringSummaryView, isSummaryButtonEmojiPickerOpen]);
99
151
  var handleSummaryViewTrayMouseLeave = (0, _react.useCallback)(function () {
100
152
  setIsHoveringSummaryView(false);
101
- if (hoverableSummaryView && !isSummaryViewButtonHovered) {
153
+ if (hoverableSummaryView && !isSummaryViewButtonHovered && !isSummaryViewTrayEmojiPickerOpen) {
102
154
  setSummaryPopupOpen(false);
103
155
  }
104
- }, [hoverableSummaryView, isSummaryViewButtonHovered]);
156
+ }, [hoverableSummaryView, isSummaryViewButtonHovered, setIsHoveringSummaryView, setSummaryPopupOpen, isSummaryViewTrayEmojiPickerOpen]);
105
157
  var handleEmojiSelection = (0, _react.useCallback)(function (emojiId, source) {
106
158
  onSelection(emojiId, source);
107
159
  if (hoverableSummaryView) {
108
- setSummaryPopupOpen(false);
160
+ setSummaryPopupOpen(false, true);
109
161
  }
110
- }, [onSelection, hoverableSummaryView]);
162
+ }, [onSelection, hoverableSummaryView, setSummaryPopupOpen]);
111
163
  return /*#__PURE__*/React.createElement(_popup.default, {
112
164
  placement: placement,
113
- offset: hoverableSummaryView ? [0, 0] : undefined,
114
165
  content: function content() {
115
- return /*#__PURE__*/React.createElement(_compiled.Box, {
166
+ return isSummaryButtonEmojiPickerOpen && hoverableSummaryView ? /*#__PURE__*/React.createElement(_picker.EmojiPicker, {
167
+ emojiProvider: emojiProvider,
168
+ onSelection: onEmojiSelected,
169
+ size: emojiPickerSize
170
+ }) : /*#__PURE__*/React.createElement(_compiled.Box, {
116
171
  testId: RENDER_SUMMARY_VIEW_POPUP_TESTID,
117
172
  onMouseEnter: handleSummaryViewTrayMouseEnter,
118
173
  onMouseLeave: handleSummaryViewTrayMouseLeave
119
174
  }, allowSelectFromSummaryView && /*#__PURE__*/React.createElement(_compiled.Flex, {
120
- justifyContent: "center"
175
+ justifyContent: "center",
176
+ testId: "reaction-summary-view-emoji-picker-container"
121
177
  }, /*#__PURE__*/React.createElement(_ReactionSummaryViewEmojiPicker.ReactionSummaryViewEmojiPicker, {
122
178
  emojiProvider: emojiProvider,
123
179
  disabled: disabled,
@@ -126,7 +182,8 @@ var ReactionSummaryView = exports.ReactionSummaryView = function ReactionSummary
126
182
  tooltipContent: tooltipContent,
127
183
  reactionPickerTriggerIcon: reactionPickerTriggerIcon,
128
184
  reactionPickerTriggerText: reactionPickerTriggerText,
129
- onOpen: onOpen
185
+ onOpen: onOpen,
186
+ setIsSummaryViewTrayEmojiPickerOpen: setIsSummaryViewTrayEmojiPickerOpen
130
187
  })), /*#__PURE__*/React.createElement(_compiled.Inline, {
131
188
  xcss: styles.summaryPopup,
132
189
  space: "space.025",
@@ -148,7 +205,7 @@ var ReactionSummaryView = exports.ReactionSummaryView = function ReactionSummary
148
205
  });
149
206
  })));
150
207
  },
151
- isOpen: isSummaryPopupOpen,
208
+ isOpen: isSummaryPopupOpen || isSummaryButtonEmojiPickerOpen,
152
209
  onClose: handlePopupClose,
153
210
  trigger: function trigger(triggerProps) {
154
211
  return /*#__PURE__*/React.createElement(_ReactionSummaryButton.ReactionSummaryButton, (0, _extends2.default)({}, triggerProps, {
@@ -23,7 +23,8 @@ var ReactionSummaryViewEmojiPicker = exports.ReactionSummaryViewEmojiPicker = fu
23
23
  reactionPickerTriggerIcon = _ref.reactionPickerTriggerIcon,
24
24
  tooltipContent = _ref.tooltipContent,
25
25
  onOpen = _ref.onOpen,
26
- reactionPickerTriggerText = _ref.reactionPickerTriggerText;
26
+ reactionPickerTriggerText = _ref.reactionPickerTriggerText,
27
+ setIsSummaryViewTrayEmojiPickerOpen = _ref.setIsSummaryViewTrayEmojiPickerOpen;
27
28
  var _useState = (0, _react.useState)(false),
28
29
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
29
30
  isOpen = _useState2[0],
@@ -31,9 +32,9 @@ var ReactionSummaryViewEmojiPicker = exports.ReactionSummaryViewEmojiPicker = fu
31
32
  var handleClick = function handleClick() {
32
33
  // ufo start reactions picker open experience
33
34
  _ufo.PickerRender.start();
34
- setIsOpen(function (prevIsOpen) {
35
- return !prevIsOpen;
36
- });
35
+ var newIsOpen = !isOpen;
36
+ setIsOpen(newIsOpen);
37
+ setIsSummaryViewTrayEmojiPickerOpen && setIsSummaryViewTrayEmojiPickerOpen(newIsOpen);
37
38
  onOpen && onOpen();
38
39
 
39
40
  // ufo reactions picker opened success
@@ -46,6 +47,7 @@ var ReactionSummaryViewEmojiPicker = exports.ReactionSummaryViewEmojiPicker = fu
46
47
  */
47
48
  var close = (0, _react.useCallback)(function (_id) {
48
49
  setIsOpen(false);
50
+ setIsSummaryViewTrayEmojiPickerOpen && setIsSummaryViewTrayEmojiPickerOpen(false);
49
51
  // ufo abort reaction experience
50
52
  _ufo.PickerRender.abort({
51
53
  metadata: {
@@ -54,7 +56,7 @@ var ReactionSummaryViewEmojiPicker = exports.ReactionSummaryViewEmojiPicker = fu
54
56
  reason: 'close dialog'
55
57
  }
56
58
  });
57
- }, [setIsOpen]);
59
+ }, [setIsOpen, setIsSummaryViewTrayEmojiPickerOpen]);
58
60
 
59
61
  /**
60
62
  * Event callback when an emoji icon is selected
@@ -72,7 +74,7 @@ var ReactionSummaryViewEmojiPicker = exports.ReactionSummaryViewEmojiPicker = fu
72
74
  testId: "reaction-summary-view-emoji-picker",
73
75
  isOpen: isOpen,
74
76
  placement: "bottom-start",
75
- offset: [-10, -66],
77
+ offset: [-10, -34],
76
78
  onClose: function onClose() {
77
79
  return close();
78
80
  },
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useDelayedState = void 0;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _react = require("react");
10
+ var useDelayedState = exports.useDelayedState = function useDelayedState(initialState, delay) {
11
+ var _useState = (0, _react.useState)(initialState),
12
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
13
+ state = _useState2[0],
14
+ setState = _useState2[1];
15
+ var timeoutRef = (0, _react.useRef)(null);
16
+ (0, _react.useEffect)(function () {
17
+ return function () {
18
+ if (timeoutRef.current) {
19
+ clearTimeout(timeoutRef.current);
20
+ }
21
+ };
22
+ }, []);
23
+ var handleDelayedStateChange = (0, _react.useCallback)(function (newState) {
24
+ var immediate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
25
+ if (timeoutRef.current) {
26
+ clearTimeout(timeoutRef.current);
27
+ }
28
+ if (immediate) {
29
+ setState(newState);
30
+ } else {
31
+ timeoutRef.current = setTimeout(function () {
32
+ setState(newState);
33
+ }, delay);
34
+ }
35
+ }, [delay]);
36
+ return [state, handleDelayedStateChange];
37
+ };
@@ -75,5 +75,10 @@ var messages = exports.messages = (0, _reactIntlNext.defineMessages)({
75
75
  id: 'reactions.dialog.viewall.tooltip',
76
76
  defaultMessage: 'View all user reactions',
77
77
  description: 'Tooltip content of see who reacted link'
78
+ },
79
+ popperWrapperLabel: {
80
+ id: 'reactions-reaction.picker-label',
81
+ defaultMessage: 'Add reactions',
82
+ description: 'A label to the reaction picker group'
78
83
  }
79
84
  });
@@ -1,7 +1,7 @@
1
1
  import { createAndFireEvent } from '@atlaskit/analytics-next';
2
2
  import { UI_EVENT_TYPE, OPERATIONAL_EVENT_TYPE } from '@atlaskit/analytics-gas-types';
3
3
  const packageName = "@atlaskit/reactions";
4
- const packageVersion = "31.3.1";
4
+ const packageVersion = "31.5.0";
5
5
  /**
6
6
  * TODO: move to utility package?
7
7
  * A random sampling function
@@ -2,7 +2,7 @@
2
2
  import "./ReactionPicker.compiled.css";
3
3
  import { ax, ix } from "@compiled/react/runtime";
4
4
  import React, { useCallback, useLayoutEffect, useRef, useState } from 'react';
5
- import { FormattedMessage } from 'react-intl-next';
5
+ import { FormattedMessage, useIntl } from 'react-intl-next';
6
6
  import { EmojiPicker } from '@atlaskit/emoji/picker';
7
7
  import { Manager, Popper, Reference } from '@atlaskit/popper';
8
8
  import { layers } from '@atlaskit/theme/constants';
@@ -249,6 +249,9 @@ export const PopperWrapper = props => {
249
249
  popperModifiers
250
250
  } = props;
251
251
  const [popupRef, setPopupRef] = useState(null);
252
+ const {
253
+ formatMessage
254
+ } = useIntl();
252
255
  /**
253
256
  * add focus lock to popup
254
257
  */
@@ -266,6 +269,8 @@ export const PopperWrapper = props => {
266
269
  update
267
270
  }) => {
268
271
  return /*#__PURE__*/React.createElement("div", {
272
+ role: "group",
273
+ "aria-label": formatMessage(messages.popperWrapperLabel),
269
274
  id: PICKER_CONTROL_ID,
270
275
  "data-testid": RENDER_REACTIONPICKERPANEL_TESTID
271
276
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
@@ -5,9 +5,12 @@ import * as React from 'react';
5
5
  import { ax, ix } from "@compiled/react/runtime";
6
6
  import { useCallback, useState } from 'react';
7
7
  import Popup from '@atlaskit/popup';
8
+ import { EmojiPicker } from '@atlaskit/emoji/picker';
9
+ import { useDelayedState } from '../hooks/useDelayedState';
8
10
  import { Reaction } from './Reaction';
9
11
  import { ReactionSummaryViewEmojiPicker } from './ReactionSummaryViewEmojiPicker';
10
12
  import { ReactionSummaryButton } from './ReactionSummaryButton';
13
+ import { PickerRender } from '../ufo';
11
14
  import { Box, Flex, Inline } from '@atlaskit/primitives/compiled';
12
15
  const styles = {
13
16
  summaryPopup: "_ca0q1b66 _u5f3u2gc _n3tdu2gc _19bvu2gc _p12foiq5"
@@ -40,52 +43,102 @@ export const ReactionSummaryView = ({
40
43
  onOpen,
41
44
  useButtonAlignmentStyling,
42
45
  reactionPickerTriggerText,
43
- hoverableSummaryView = false
46
+ hoverableSummaryView = false,
47
+ hoverableSummaryViewDelay = 300
44
48
  }) => {
45
- const [isSummaryPopupOpen, setSummaryPopupOpen] = useState(false);
49
+ const [isSummaryPopupOpen, setSummaryPopupOpen] = useDelayedState(false, hoverableSummaryViewDelay);
46
50
  const [isHoveringSummaryView, setIsHoveringSummaryView] = useState(false);
47
51
  const [isSummaryViewButtonHovered, setIsSummaryViewButtonHovered] = useState(false);
48
- const handlePopupClose = useCallback(() => setSummaryPopupOpen(false), []);
49
- const handleSummaryClick = useCallback(() => setSummaryPopupOpen(!isSummaryPopupOpen), [isSummaryPopupOpen]);
52
+ const [isSummaryButtonEmojiPickerOpen, setIsSummaryButtonEmojiPickerOpen] = useState(false);
53
+ const [isSummaryViewTrayEmojiPickerOpen, setIsSummaryViewTrayEmojiPickerOpen] = useState(false);
54
+
55
+ /**
56
+ * Event callback when the picker is closed
57
+ * @param _id Optional id if an emoji button was selected or undefined if was clicked outside the picker
58
+ */
59
+ const close = useCallback(_id => {
60
+ setIsSummaryButtonEmojiPickerOpen(false);
61
+ // ufo abort reaction experience
62
+ PickerRender.abort({
63
+ metadata: {
64
+ emojiId: _id,
65
+ source: 'ReactionPicker',
66
+ reason: 'close dialog'
67
+ }
68
+ });
69
+ }, [setIsSummaryButtonEmojiPickerOpen]);
70
+ /**
71
+ * Event callback when an emoji icon is selected
72
+ * @param item selected item
73
+ */
74
+ const onEmojiSelected = useCallback(item => {
75
+ // no emoji was selected
76
+ if (!item.id) {
77
+ return;
78
+ }
79
+ onSelection(item.id, 'emojiPicker');
80
+ close(item.id);
81
+ }, [onSelection, close]);
82
+ const handlePopupClose = useCallback(() => {
83
+ setSummaryPopupOpen(false);
84
+ setIsSummaryButtonEmojiPickerOpen(false);
85
+ }, [setSummaryPopupOpen, setIsSummaryButtonEmojiPickerOpen]);
86
+ const handleSummaryClick = useCallback(() => {
87
+ if (hoverableSummaryView) {
88
+ // ufo start reactions picker open experience
89
+ PickerRender.start();
90
+ onOpen && onOpen();
91
+ setSummaryPopupOpen(false);
92
+ // ufo reactions picker opened success
93
+ PickerRender.success();
94
+ } else {
95
+ setSummaryPopupOpen(!isSummaryPopupOpen);
96
+ }
97
+ setIsSummaryButtonEmojiPickerOpen(!isSummaryButtonEmojiPickerOpen);
98
+ }, [isSummaryPopupOpen, onOpen, isSummaryButtonEmojiPickerOpen, hoverableSummaryView, setSummaryPopupOpen, setIsSummaryButtonEmojiPickerOpen]);
50
99
  const handleButtonMouseEnter = useCallback(() => {
51
100
  setIsSummaryViewButtonHovered(true);
52
- if (hoverableSummaryView) {
101
+ if (hoverableSummaryView && !isSummaryButtonEmojiPickerOpen) {
53
102
  setSummaryPopupOpen(true);
54
103
  }
55
- }, [hoverableSummaryView]);
104
+ }, [hoverableSummaryView, setSummaryPopupOpen, setIsSummaryViewButtonHovered, isSummaryButtonEmojiPickerOpen]);
56
105
  const handleButtonMouseLeave = useCallback(() => {
57
106
  setIsSummaryViewButtonHovered(false);
58
- if (hoverableSummaryView && !isHoveringSummaryView) {
107
+ if (hoverableSummaryView && !isHoveringSummaryView && !isSummaryViewTrayEmojiPickerOpen) {
59
108
  setSummaryPopupOpen(false);
60
109
  }
61
- }, [hoverableSummaryView, isHoveringSummaryView]);
110
+ }, [hoverableSummaryView, isHoveringSummaryView, setSummaryPopupOpen, setIsSummaryViewButtonHovered, isSummaryViewTrayEmojiPickerOpen]);
62
111
  const handleSummaryViewTrayMouseEnter = useCallback(() => {
63
112
  setIsHoveringSummaryView(true);
64
- if (hoverableSummaryView) {
113
+ if (hoverableSummaryView && !isSummaryButtonEmojiPickerOpen) {
65
114
  setSummaryPopupOpen(true);
66
115
  }
67
- }, [hoverableSummaryView]);
116
+ }, [hoverableSummaryView, setSummaryPopupOpen, setIsHoveringSummaryView, isSummaryButtonEmojiPickerOpen]);
68
117
  const handleSummaryViewTrayMouseLeave = useCallback(() => {
69
118
  setIsHoveringSummaryView(false);
70
- if (hoverableSummaryView && !isSummaryViewButtonHovered) {
119
+ if (hoverableSummaryView && !isSummaryViewButtonHovered && !isSummaryViewTrayEmojiPickerOpen) {
71
120
  setSummaryPopupOpen(false);
72
121
  }
73
- }, [hoverableSummaryView, isSummaryViewButtonHovered]);
122
+ }, [hoverableSummaryView, isSummaryViewButtonHovered, setIsHoveringSummaryView, setSummaryPopupOpen, isSummaryViewTrayEmojiPickerOpen]);
74
123
  const handleEmojiSelection = useCallback((emojiId, source) => {
75
124
  onSelection(emojiId, source);
76
125
  if (hoverableSummaryView) {
77
- setSummaryPopupOpen(false);
126
+ setSummaryPopupOpen(false, true);
78
127
  }
79
- }, [onSelection, hoverableSummaryView]);
128
+ }, [onSelection, hoverableSummaryView, setSummaryPopupOpen]);
80
129
  return /*#__PURE__*/React.createElement(Popup, {
81
130
  placement: placement,
82
- offset: hoverableSummaryView ? [0, 0] : undefined,
83
- content: () => /*#__PURE__*/React.createElement(Box, {
131
+ content: () => isSummaryButtonEmojiPickerOpen && hoverableSummaryView ? /*#__PURE__*/React.createElement(EmojiPicker, {
132
+ emojiProvider: emojiProvider,
133
+ onSelection: onEmojiSelected,
134
+ size: emojiPickerSize
135
+ }) : /*#__PURE__*/React.createElement(Box, {
84
136
  testId: RENDER_SUMMARY_VIEW_POPUP_TESTID,
85
137
  onMouseEnter: handleSummaryViewTrayMouseEnter,
86
138
  onMouseLeave: handleSummaryViewTrayMouseLeave
87
139
  }, allowSelectFromSummaryView && /*#__PURE__*/React.createElement(Flex, {
88
- justifyContent: "center"
140
+ justifyContent: "center",
141
+ testId: "reaction-summary-view-emoji-picker-container"
89
142
  }, /*#__PURE__*/React.createElement(ReactionSummaryViewEmojiPicker, {
90
143
  emojiProvider: emojiProvider,
91
144
  disabled: disabled,
@@ -94,7 +147,8 @@ export const ReactionSummaryView = ({
94
147
  tooltipContent: tooltipContent,
95
148
  reactionPickerTriggerIcon: reactionPickerTriggerIcon,
96
149
  reactionPickerTriggerText: reactionPickerTriggerText,
97
- onOpen: onOpen
150
+ onOpen: onOpen,
151
+ setIsSummaryViewTrayEmojiPickerOpen: setIsSummaryViewTrayEmojiPickerOpen
98
152
  })), /*#__PURE__*/React.createElement(Inline, {
99
153
  xcss: styles.summaryPopup,
100
154
  space: "space.025",
@@ -113,7 +167,7 @@ export const ReactionSummaryView = ({
113
167
  handleOpenReactionsDialog: handleOpenReactionsDialog,
114
168
  isViewOnly: isViewOnly
115
169
  })))),
116
- isOpen: isSummaryPopupOpen,
170
+ isOpen: isSummaryPopupOpen || isSummaryButtonEmojiPickerOpen,
117
171
  onClose: handlePopupClose,
118
172
  trigger: triggerProps => /*#__PURE__*/React.createElement(ReactionSummaryButton, _extends({}, triggerProps, {
119
173
  emojiProvider: emojiProvider,
@@ -12,13 +12,16 @@ export const ReactionSummaryViewEmojiPicker = ({
12
12
  reactionPickerTriggerIcon,
13
13
  tooltipContent,
14
14
  onOpen,
15
- reactionPickerTriggerText
15
+ reactionPickerTriggerText,
16
+ setIsSummaryViewTrayEmojiPickerOpen
16
17
  }) => {
17
18
  const [isOpen, setIsOpen] = useState(false);
18
19
  const handleClick = () => {
19
20
  // ufo start reactions picker open experience
20
21
  PickerRender.start();
21
- setIsOpen(prevIsOpen => !prevIsOpen);
22
+ const newIsOpen = !isOpen;
23
+ setIsOpen(newIsOpen);
24
+ setIsSummaryViewTrayEmojiPickerOpen && setIsSummaryViewTrayEmojiPickerOpen(newIsOpen);
22
25
  onOpen && onOpen();
23
26
 
24
27
  // ufo reactions picker opened success
@@ -31,6 +34,7 @@ export const ReactionSummaryViewEmojiPicker = ({
31
34
  */
32
35
  const close = useCallback(_id => {
33
36
  setIsOpen(false);
37
+ setIsSummaryViewTrayEmojiPickerOpen && setIsSummaryViewTrayEmojiPickerOpen(false);
34
38
  // ufo abort reaction experience
35
39
  PickerRender.abort({
36
40
  metadata: {
@@ -39,7 +43,7 @@ export const ReactionSummaryViewEmojiPicker = ({
39
43
  reason: 'close dialog'
40
44
  }
41
45
  });
42
- }, [setIsOpen]);
46
+ }, [setIsOpen, setIsSummaryViewTrayEmojiPickerOpen]);
43
47
 
44
48
  /**
45
49
  * Event callback when an emoji icon is selected
@@ -57,7 +61,7 @@ export const ReactionSummaryViewEmojiPicker = ({
57
61
  testId: "reaction-summary-view-emoji-picker",
58
62
  isOpen: isOpen,
59
63
  placement: "bottom-start",
60
- offset: [-10, -66],
64
+ offset: [-10, -34],
61
65
  onClose: () => close(),
62
66
  content: () => /*#__PURE__*/React.createElement(EmojiPicker, {
63
67
  emojiProvider: emojiProvider,
@@ -0,0 +1,25 @@
1
+ import { useCallback, useRef, useEffect, useState } from 'react';
2
+ export const useDelayedState = (initialState, delay) => {
3
+ const [state, setState] = useState(initialState);
4
+ const timeoutRef = useRef(null);
5
+ useEffect(() => {
6
+ return () => {
7
+ if (timeoutRef.current) {
8
+ clearTimeout(timeoutRef.current);
9
+ }
10
+ };
11
+ }, []);
12
+ const handleDelayedStateChange = useCallback((newState, immediate = false) => {
13
+ if (timeoutRef.current) {
14
+ clearTimeout(timeoutRef.current);
15
+ }
16
+ if (immediate) {
17
+ setState(newState);
18
+ } else {
19
+ timeoutRef.current = setTimeout(() => {
20
+ setState(newState);
21
+ }, delay);
22
+ }
23
+ }, [delay]);
24
+ return [state, handleDelayedStateChange];
25
+ };
@@ -72,5 +72,10 @@ export const messages = defineMessages({
72
72
  id: 'reactions.dialog.viewall.tooltip',
73
73
  defaultMessage: 'View all user reactions',
74
74
  description: 'Tooltip content of see who reacted link'
75
+ },
76
+ popperWrapperLabel: {
77
+ id: 'reactions-reaction.picker-label',
78
+ defaultMessage: 'Add reactions',
79
+ description: 'A label to the reaction picker group'
75
80
  }
76
81
  });
@@ -4,7 +4,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
4
4
  import { createAndFireEvent } from '@atlaskit/analytics-next';
5
5
  import { UI_EVENT_TYPE, OPERATIONAL_EVENT_TYPE } from '@atlaskit/analytics-gas-types';
6
6
  var packageName = "@atlaskit/reactions";
7
- var packageVersion = "31.3.1";
7
+ var packageVersion = "31.5.0";
8
8
  /**
9
9
  * TODO: move to utility package?
10
10
  * A random sampling function
@@ -6,7 +6,7 @@ import { ax, ix } from "@compiled/react/runtime";
6
6
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
7
7
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
8
8
  import React, { useCallback, useLayoutEffect, useRef, useState } from 'react';
9
- import { FormattedMessage } from 'react-intl-next';
9
+ import { FormattedMessage, useIntl } from 'react-intl-next';
10
10
  import { EmojiPicker } from '@atlaskit/emoji/picker';
11
11
  import { Manager, Popper, Reference } from '@atlaskit/popper';
12
12
  import { layers } from '@atlaskit/theme/constants';
@@ -268,6 +268,8 @@ export var PopperWrapper = function PopperWrapper(props) {
268
268
  _useState6 = _slicedToArray(_useState5, 2),
269
269
  popupRef = _useState6[0],
270
270
  setPopupRef = _useState6[1];
271
+ var _useIntl = useIntl(),
272
+ formatMessage = _useIntl.formatMessage;
271
273
  /**
272
274
  * add focus lock to popup
273
275
  */
@@ -284,6 +286,8 @@ export var PopperWrapper = function PopperWrapper(props) {
284
286
  style = _ref3.style,
285
287
  update = _ref3.update;
286
288
  return /*#__PURE__*/React.createElement("div", {
289
+ role: "group",
290
+ "aria-label": formatMessage(messages.popperWrapperLabel),
287
291
  id: PICKER_CONTROL_ID,
288
292
  "data-testid": RENDER_REACTIONPICKERPANEL_TESTID
289
293
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
@@ -6,9 +6,12 @@ import * as React from 'react';
6
6
  import { ax, ix } from "@compiled/react/runtime";
7
7
  import { useCallback, useState } from 'react';
8
8
  import Popup from '@atlaskit/popup';
9
+ import { EmojiPicker } from '@atlaskit/emoji/picker';
10
+ import { useDelayedState } from '../hooks/useDelayedState';
9
11
  import { Reaction } from './Reaction';
10
12
  import { ReactionSummaryViewEmojiPicker } from './ReactionSummaryViewEmojiPicker';
11
13
  import { ReactionSummaryButton } from './ReactionSummaryButton';
14
+ import { PickerRender } from '../ufo';
12
15
  import { Box, Flex, Inline } from '@atlaskit/primitives/compiled';
13
16
  var styles = {
14
17
  summaryPopup: "_ca0q1b66 _u5f3u2gc _n3tdu2gc _19bvu2gc _p12foiq5"
@@ -49,65 +52,118 @@ export var ReactionSummaryView = function ReactionSummaryView(_ref) {
49
52
  useButtonAlignmentStyling = _ref.useButtonAlignmentStyling,
50
53
  reactionPickerTriggerText = _ref.reactionPickerTriggerText,
51
54
  _ref$hoverableSummary = _ref.hoverableSummaryView,
52
- hoverableSummaryView = _ref$hoverableSummary === void 0 ? false : _ref$hoverableSummary;
55
+ hoverableSummaryView = _ref$hoverableSummary === void 0 ? false : _ref$hoverableSummary,
56
+ _ref$hoverableSummary2 = _ref.hoverableSummaryViewDelay,
57
+ hoverableSummaryViewDelay = _ref$hoverableSummary2 === void 0 ? 300 : _ref$hoverableSummary2;
58
+ var _useDelayedState = useDelayedState(false, hoverableSummaryViewDelay),
59
+ _useDelayedState2 = _slicedToArray(_useDelayedState, 2),
60
+ isSummaryPopupOpen = _useDelayedState2[0],
61
+ setSummaryPopupOpen = _useDelayedState2[1];
53
62
  var _useState = useState(false),
54
63
  _useState2 = _slicedToArray(_useState, 2),
55
- isSummaryPopupOpen = _useState2[0],
56
- setSummaryPopupOpen = _useState2[1];
64
+ isHoveringSummaryView = _useState2[0],
65
+ setIsHoveringSummaryView = _useState2[1];
57
66
  var _useState3 = useState(false),
58
67
  _useState4 = _slicedToArray(_useState3, 2),
59
- isHoveringSummaryView = _useState4[0],
60
- setIsHoveringSummaryView = _useState4[1];
68
+ isSummaryViewButtonHovered = _useState4[0],
69
+ setIsSummaryViewButtonHovered = _useState4[1];
61
70
  var _useState5 = useState(false),
62
71
  _useState6 = _slicedToArray(_useState5, 2),
63
- isSummaryViewButtonHovered = _useState6[0],
64
- setIsSummaryViewButtonHovered = _useState6[1];
72
+ isSummaryButtonEmojiPickerOpen = _useState6[0],
73
+ setIsSummaryButtonEmojiPickerOpen = _useState6[1];
74
+ var _useState7 = useState(false),
75
+ _useState8 = _slicedToArray(_useState7, 2),
76
+ isSummaryViewTrayEmojiPickerOpen = _useState8[0],
77
+ setIsSummaryViewTrayEmojiPickerOpen = _useState8[1];
78
+
79
+ /**
80
+ * Event callback when the picker is closed
81
+ * @param _id Optional id if an emoji button was selected or undefined if was clicked outside the picker
82
+ */
83
+ var close = useCallback(function (_id) {
84
+ setIsSummaryButtonEmojiPickerOpen(false);
85
+ // ufo abort reaction experience
86
+ PickerRender.abort({
87
+ metadata: {
88
+ emojiId: _id,
89
+ source: 'ReactionPicker',
90
+ reason: 'close dialog'
91
+ }
92
+ });
93
+ }, [setIsSummaryButtonEmojiPickerOpen]);
94
+ /**
95
+ * Event callback when an emoji icon is selected
96
+ * @param item selected item
97
+ */
98
+ var onEmojiSelected = useCallback(function (item) {
99
+ // no emoji was selected
100
+ if (!item.id) {
101
+ return;
102
+ }
103
+ onSelection(item.id, 'emojiPicker');
104
+ close(item.id);
105
+ }, [onSelection, close]);
65
106
  var handlePopupClose = useCallback(function () {
66
- return setSummaryPopupOpen(false);
67
- }, []);
107
+ setSummaryPopupOpen(false);
108
+ setIsSummaryButtonEmojiPickerOpen(false);
109
+ }, [setSummaryPopupOpen, setIsSummaryButtonEmojiPickerOpen]);
68
110
  var handleSummaryClick = useCallback(function () {
69
- return setSummaryPopupOpen(!isSummaryPopupOpen);
70
- }, [isSummaryPopupOpen]);
111
+ if (hoverableSummaryView) {
112
+ // ufo start reactions picker open experience
113
+ PickerRender.start();
114
+ onOpen && onOpen();
115
+ setSummaryPopupOpen(false);
116
+ // ufo reactions picker opened success
117
+ PickerRender.success();
118
+ } else {
119
+ setSummaryPopupOpen(!isSummaryPopupOpen);
120
+ }
121
+ setIsSummaryButtonEmojiPickerOpen(!isSummaryButtonEmojiPickerOpen);
122
+ }, [isSummaryPopupOpen, onOpen, isSummaryButtonEmojiPickerOpen, hoverableSummaryView, setSummaryPopupOpen, setIsSummaryButtonEmojiPickerOpen]);
71
123
  var handleButtonMouseEnter = useCallback(function () {
72
124
  setIsSummaryViewButtonHovered(true);
73
- if (hoverableSummaryView) {
125
+ if (hoverableSummaryView && !isSummaryButtonEmojiPickerOpen) {
74
126
  setSummaryPopupOpen(true);
75
127
  }
76
- }, [hoverableSummaryView]);
128
+ }, [hoverableSummaryView, setSummaryPopupOpen, setIsSummaryViewButtonHovered, isSummaryButtonEmojiPickerOpen]);
77
129
  var handleButtonMouseLeave = useCallback(function () {
78
130
  setIsSummaryViewButtonHovered(false);
79
- if (hoverableSummaryView && !isHoveringSummaryView) {
131
+ if (hoverableSummaryView && !isHoveringSummaryView && !isSummaryViewTrayEmojiPickerOpen) {
80
132
  setSummaryPopupOpen(false);
81
133
  }
82
- }, [hoverableSummaryView, isHoveringSummaryView]);
134
+ }, [hoverableSummaryView, isHoveringSummaryView, setSummaryPopupOpen, setIsSummaryViewButtonHovered, isSummaryViewTrayEmojiPickerOpen]);
83
135
  var handleSummaryViewTrayMouseEnter = useCallback(function () {
84
136
  setIsHoveringSummaryView(true);
85
- if (hoverableSummaryView) {
137
+ if (hoverableSummaryView && !isSummaryButtonEmojiPickerOpen) {
86
138
  setSummaryPopupOpen(true);
87
139
  }
88
- }, [hoverableSummaryView]);
140
+ }, [hoverableSummaryView, setSummaryPopupOpen, setIsHoveringSummaryView, isSummaryButtonEmojiPickerOpen]);
89
141
  var handleSummaryViewTrayMouseLeave = useCallback(function () {
90
142
  setIsHoveringSummaryView(false);
91
- if (hoverableSummaryView && !isSummaryViewButtonHovered) {
143
+ if (hoverableSummaryView && !isSummaryViewButtonHovered && !isSummaryViewTrayEmojiPickerOpen) {
92
144
  setSummaryPopupOpen(false);
93
145
  }
94
- }, [hoverableSummaryView, isSummaryViewButtonHovered]);
146
+ }, [hoverableSummaryView, isSummaryViewButtonHovered, setIsHoveringSummaryView, setSummaryPopupOpen, isSummaryViewTrayEmojiPickerOpen]);
95
147
  var handleEmojiSelection = useCallback(function (emojiId, source) {
96
148
  onSelection(emojiId, source);
97
149
  if (hoverableSummaryView) {
98
- setSummaryPopupOpen(false);
150
+ setSummaryPopupOpen(false, true);
99
151
  }
100
- }, [onSelection, hoverableSummaryView]);
152
+ }, [onSelection, hoverableSummaryView, setSummaryPopupOpen]);
101
153
  return /*#__PURE__*/React.createElement(Popup, {
102
154
  placement: placement,
103
- offset: hoverableSummaryView ? [0, 0] : undefined,
104
155
  content: function content() {
105
- return /*#__PURE__*/React.createElement(Box, {
156
+ return isSummaryButtonEmojiPickerOpen && hoverableSummaryView ? /*#__PURE__*/React.createElement(EmojiPicker, {
157
+ emojiProvider: emojiProvider,
158
+ onSelection: onEmojiSelected,
159
+ size: emojiPickerSize
160
+ }) : /*#__PURE__*/React.createElement(Box, {
106
161
  testId: RENDER_SUMMARY_VIEW_POPUP_TESTID,
107
162
  onMouseEnter: handleSummaryViewTrayMouseEnter,
108
163
  onMouseLeave: handleSummaryViewTrayMouseLeave
109
164
  }, allowSelectFromSummaryView && /*#__PURE__*/React.createElement(Flex, {
110
- justifyContent: "center"
165
+ justifyContent: "center",
166
+ testId: "reaction-summary-view-emoji-picker-container"
111
167
  }, /*#__PURE__*/React.createElement(ReactionSummaryViewEmojiPicker, {
112
168
  emojiProvider: emojiProvider,
113
169
  disabled: disabled,
@@ -116,7 +172,8 @@ export var ReactionSummaryView = function ReactionSummaryView(_ref) {
116
172
  tooltipContent: tooltipContent,
117
173
  reactionPickerTriggerIcon: reactionPickerTriggerIcon,
118
174
  reactionPickerTriggerText: reactionPickerTriggerText,
119
- onOpen: onOpen
175
+ onOpen: onOpen,
176
+ setIsSummaryViewTrayEmojiPickerOpen: setIsSummaryViewTrayEmojiPickerOpen
120
177
  })), /*#__PURE__*/React.createElement(Inline, {
121
178
  xcss: styles.summaryPopup,
122
179
  space: "space.025",
@@ -138,7 +195,7 @@ export var ReactionSummaryView = function ReactionSummaryView(_ref) {
138
195
  });
139
196
  })));
140
197
  },
141
- isOpen: isSummaryPopupOpen,
198
+ isOpen: isSummaryPopupOpen || isSummaryButtonEmojiPickerOpen,
142
199
  onClose: handlePopupClose,
143
200
  trigger: function trigger(triggerProps) {
144
201
  return /*#__PURE__*/React.createElement(ReactionSummaryButton, _extends({}, triggerProps, {
@@ -13,7 +13,8 @@ export var ReactionSummaryViewEmojiPicker = function ReactionSummaryViewEmojiPic
13
13
  reactionPickerTriggerIcon = _ref.reactionPickerTriggerIcon,
14
14
  tooltipContent = _ref.tooltipContent,
15
15
  onOpen = _ref.onOpen,
16
- reactionPickerTriggerText = _ref.reactionPickerTriggerText;
16
+ reactionPickerTriggerText = _ref.reactionPickerTriggerText,
17
+ setIsSummaryViewTrayEmojiPickerOpen = _ref.setIsSummaryViewTrayEmojiPickerOpen;
17
18
  var _useState = useState(false),
18
19
  _useState2 = _slicedToArray(_useState, 2),
19
20
  isOpen = _useState2[0],
@@ -21,9 +22,9 @@ export var ReactionSummaryViewEmojiPicker = function ReactionSummaryViewEmojiPic
21
22
  var handleClick = function handleClick() {
22
23
  // ufo start reactions picker open experience
23
24
  PickerRender.start();
24
- setIsOpen(function (prevIsOpen) {
25
- return !prevIsOpen;
26
- });
25
+ var newIsOpen = !isOpen;
26
+ setIsOpen(newIsOpen);
27
+ setIsSummaryViewTrayEmojiPickerOpen && setIsSummaryViewTrayEmojiPickerOpen(newIsOpen);
27
28
  onOpen && onOpen();
28
29
 
29
30
  // ufo reactions picker opened success
@@ -36,6 +37,7 @@ export var ReactionSummaryViewEmojiPicker = function ReactionSummaryViewEmojiPic
36
37
  */
37
38
  var close = useCallback(function (_id) {
38
39
  setIsOpen(false);
40
+ setIsSummaryViewTrayEmojiPickerOpen && setIsSummaryViewTrayEmojiPickerOpen(false);
39
41
  // ufo abort reaction experience
40
42
  PickerRender.abort({
41
43
  metadata: {
@@ -44,7 +46,7 @@ export var ReactionSummaryViewEmojiPicker = function ReactionSummaryViewEmojiPic
44
46
  reason: 'close dialog'
45
47
  }
46
48
  });
47
- }, [setIsOpen]);
49
+ }, [setIsOpen, setIsSummaryViewTrayEmojiPickerOpen]);
48
50
 
49
51
  /**
50
52
  * Event callback when an emoji icon is selected
@@ -62,7 +64,7 @@ export var ReactionSummaryViewEmojiPicker = function ReactionSummaryViewEmojiPic
62
64
  testId: "reaction-summary-view-emoji-picker",
63
65
  isOpen: isOpen,
64
66
  placement: "bottom-start",
65
- offset: [-10, -66],
67
+ offset: [-10, -34],
66
68
  onClose: function onClose() {
67
69
  return close();
68
70
  },
@@ -0,0 +1,30 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import { useCallback, useRef, useEffect, useState } from 'react';
3
+ export var useDelayedState = function useDelayedState(initialState, delay) {
4
+ var _useState = useState(initialState),
5
+ _useState2 = _slicedToArray(_useState, 2),
6
+ state = _useState2[0],
7
+ setState = _useState2[1];
8
+ var timeoutRef = useRef(null);
9
+ useEffect(function () {
10
+ return function () {
11
+ if (timeoutRef.current) {
12
+ clearTimeout(timeoutRef.current);
13
+ }
14
+ };
15
+ }, []);
16
+ var handleDelayedStateChange = useCallback(function (newState) {
17
+ var immediate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
18
+ if (timeoutRef.current) {
19
+ clearTimeout(timeoutRef.current);
20
+ }
21
+ if (immediate) {
22
+ setState(newState);
23
+ } else {
24
+ timeoutRef.current = setTimeout(function () {
25
+ setState(newState);
26
+ }, delay);
27
+ }
28
+ }, [delay]);
29
+ return [state, handleDelayedStateChange];
30
+ };
@@ -69,5 +69,10 @@ export var messages = defineMessages({
69
69
  id: 'reactions.dialog.viewall.tooltip',
70
70
  defaultMessage: 'View all user reactions',
71
71
  description: 'Tooltip content of see who reacted link'
72
+ },
73
+ popperWrapperLabel: {
74
+ id: 'reactions-reaction.picker-label',
75
+ defaultMessage: 'Add reactions',
76
+ description: 'A label to the reaction picker group'
72
77
  }
73
78
  });
@@ -57,6 +57,10 @@ interface ReactionSummaryViewProps extends Pick<ReactionsProps, 'emojiProvider'
57
57
  * Optional prop to make the summary view open on hover
58
58
  */
59
59
  hoverableSummaryView?: boolean;
60
+ /**
61
+ * Optional prop to set a delay for the summary view when it opens/closes on hover
62
+ */
63
+ hoverableSummaryViewDelay?: number;
60
64
  }
61
- export declare const ReactionSummaryView: ({ emojiProvider, reactions, flash, particleEffectByEmoji, placement, onReactionClick, onReactionFocused, onReactionMouseEnter, showOpaqueBackground, subtleReactionsSummaryAndPicker, allowUserDialog, handleOpenReactionsDialog, isViewOnly, allowSelectFromSummaryView, disabled, emojiPickerSize, onSelection, tooltipContent, reactionPickerTriggerIcon, onOpen, useButtonAlignmentStyling, reactionPickerTriggerText, hoverableSummaryView, }: ReactionSummaryViewProps) => JSX.Element;
65
+ export declare const ReactionSummaryView: ({ emojiProvider, reactions, flash, particleEffectByEmoji, placement, onReactionClick, onReactionFocused, onReactionMouseEnter, showOpaqueBackground, subtleReactionsSummaryAndPicker, allowUserDialog, handleOpenReactionsDialog, isViewOnly, allowSelectFromSummaryView, disabled, emojiPickerSize, onSelection, tooltipContent, reactionPickerTriggerIcon, onOpen, useButtonAlignmentStyling, reactionPickerTriggerText, hoverableSummaryView, hoverableSummaryViewDelay, }: ReactionSummaryViewProps) => JSX.Element;
62
66
  export {};
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { type ReactionPickerProps } from './ReactionPicker';
3
3
  interface ReactionSummaryViewEmojiPickerProps extends ReactionPickerProps {
4
+ setIsSummaryViewTrayEmojiPickerOpen?: (isOpen: boolean) => void;
4
5
  }
5
- export declare const ReactionSummaryViewEmojiPicker: ({ emojiProvider, onSelection, emojiPickerSize, disabled, reactionPickerTriggerIcon, tooltipContent, onOpen, reactionPickerTriggerText, }: ReactionSummaryViewEmojiPickerProps) => React.JSX.Element;
6
+ export declare const ReactionSummaryViewEmojiPicker: ({ emojiProvider, onSelection, emojiPickerSize, disabled, reactionPickerTriggerIcon, tooltipContent, onOpen, reactionPickerTriggerText, setIsSummaryViewTrayEmojiPickerOpen, }: ReactionSummaryViewEmojiPickerProps) => React.JSX.Element;
6
7
  export {};
@@ -0,0 +1,3 @@
1
+ type useDelayedStateResponse<T> = [T, (value: T, immediate?: boolean) => void];
2
+ export declare const useDelayedState: <T>(initialState: T, delay: number) => useDelayedStateResponse<T>;
3
+ export {};
@@ -69,4 +69,9 @@ export declare const messages: {
69
69
  defaultMessage: string;
70
70
  description: string;
71
71
  };
72
+ popperWrapperLabel: {
73
+ id: string;
74
+ defaultMessage: string;
75
+ description: string;
76
+ };
72
77
  };
@@ -57,6 +57,10 @@ interface ReactionSummaryViewProps extends Pick<ReactionsProps, 'emojiProvider'
57
57
  * Optional prop to make the summary view open on hover
58
58
  */
59
59
  hoverableSummaryView?: boolean;
60
+ /**
61
+ * Optional prop to set a delay for the summary view when it opens/closes on hover
62
+ */
63
+ hoverableSummaryViewDelay?: number;
60
64
  }
61
- export declare const ReactionSummaryView: ({ emojiProvider, reactions, flash, particleEffectByEmoji, placement, onReactionClick, onReactionFocused, onReactionMouseEnter, showOpaqueBackground, subtleReactionsSummaryAndPicker, allowUserDialog, handleOpenReactionsDialog, isViewOnly, allowSelectFromSummaryView, disabled, emojiPickerSize, onSelection, tooltipContent, reactionPickerTriggerIcon, onOpen, useButtonAlignmentStyling, reactionPickerTriggerText, hoverableSummaryView, }: ReactionSummaryViewProps) => JSX.Element;
65
+ export declare const ReactionSummaryView: ({ emojiProvider, reactions, flash, particleEffectByEmoji, placement, onReactionClick, onReactionFocused, onReactionMouseEnter, showOpaqueBackground, subtleReactionsSummaryAndPicker, allowUserDialog, handleOpenReactionsDialog, isViewOnly, allowSelectFromSummaryView, disabled, emojiPickerSize, onSelection, tooltipContent, reactionPickerTriggerIcon, onOpen, useButtonAlignmentStyling, reactionPickerTriggerText, hoverableSummaryView, hoverableSummaryViewDelay, }: ReactionSummaryViewProps) => JSX.Element;
62
66
  export {};
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { type ReactionPickerProps } from './ReactionPicker';
3
3
  interface ReactionSummaryViewEmojiPickerProps extends ReactionPickerProps {
4
+ setIsSummaryViewTrayEmojiPickerOpen?: (isOpen: boolean) => void;
4
5
  }
5
- export declare const ReactionSummaryViewEmojiPicker: ({ emojiProvider, onSelection, emojiPickerSize, disabled, reactionPickerTriggerIcon, tooltipContent, onOpen, reactionPickerTriggerText, }: ReactionSummaryViewEmojiPickerProps) => React.JSX.Element;
6
+ export declare const ReactionSummaryViewEmojiPicker: ({ emojiProvider, onSelection, emojiPickerSize, disabled, reactionPickerTriggerIcon, tooltipContent, onOpen, reactionPickerTriggerText, setIsSummaryViewTrayEmojiPickerOpen, }: ReactionSummaryViewEmojiPickerProps) => React.JSX.Element;
6
7
  export {};
@@ -0,0 +1,6 @@
1
+ type useDelayedStateResponse<T> = [
2
+ T,
3
+ (value: T, immediate?: boolean) => void
4
+ ];
5
+ export declare const useDelayedState: <T>(initialState: T, delay: number) => useDelayedStateResponse<T>;
6
+ export {};
@@ -69,4 +69,9 @@ export declare const messages: {
69
69
  defaultMessage: string;
70
70
  description: string;
71
71
  };
72
+ popperWrapperLabel: {
73
+ id: string;
74
+ defaultMessage: string;
75
+ description: string;
76
+ };
72
77
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/reactions",
3
- "version": "31.3.1",
3
+ "version": "31.5.0",
4
4
  "description": "Reactions component",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -38,7 +38,7 @@
38
38
  "@atlaskit/avatar": "^25.0.0",
39
39
  "@atlaskit/button": "^23.0.0",
40
40
  "@atlaskit/css": "^0.10.0",
41
- "@atlaskit/emoji": "^69.0.0",
41
+ "@atlaskit/emoji": "^69.1.0",
42
42
  "@atlaskit/heading": "^5.2.0",
43
43
  "@atlaskit/icon": "^25.6.0",
44
44
  "@atlaskit/modal-dialog": "^14.1.0",