@atlaskit/link-picker 1.18.2 → 1.18.4

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.
@@ -1,6 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  /** @jsx jsx */
3
- import { forwardRef, Fragment } from 'react';
3
+ import { forwardRef, Fragment, useCallback, useRef } from 'react';
4
4
  import { jsx } from '@emotion/react';
5
5
  import { defineMessages, FormattedMessage } from 'react-intl-next';
6
6
  import Spinner from '@atlaskit/spinner';
@@ -9,6 +9,7 @@ import LinkSearchListItem from '../list-item';
9
9
  import { listContainerStyles, spinnerContainerStyles, listStyles, listTitleStyles } from './styled';
10
10
  import LinkSearchNoResults, { testIds as noResultsTestIds } from './link-search-no-results';
11
11
  import { useTrackResultsShown } from './use-track-results-shown';
12
+ import { handleNavKeyDown } from '../utils';
12
13
  export const messages = defineMessages({
13
14
  titleRecentlyViewed: {
14
15
  id: 'fabric.linkPicker.listTitle.recentlyViewed',
@@ -34,9 +35,9 @@ export const testIds = {
34
35
  searchResultLoadingIndicator: 'link-picker.results-loading-indicator'
35
36
  };
36
37
  const LinkSearchList = /*#__PURE__*/forwardRef(({
38
+ onChange,
37
39
  onSelect,
38
- onMouseEnter,
39
- onMouseLeave,
40
+ onKeyDown,
40
41
  items,
41
42
  activeIndex,
42
43
  selectedIndex,
@@ -52,6 +53,47 @@ const LinkSearchList = /*#__PURE__*/forwardRef(({
52
53
  let loadingContent;
53
54
  const linkListTitle = hasSearchTerm ? messages.titleResults : messages.titleRecentlyViewed;
54
55
  useTrackResultsShown(isLoading, items, hasSearchTerm);
56
+ const itemRefs = useRef({});
57
+ const itemRefCallback = useCallback((el, id) => {
58
+ if (el === null) {
59
+ delete itemRefs.current[id];
60
+ } else {
61
+ itemRefs.current[id] = el;
62
+ }
63
+ }, []);
64
+ const getTabIndex = useCallback(index => {
65
+ if (selectedIndex > -1) {
66
+ return selectedIndex === index ? 0 : -1;
67
+ }
68
+ if (index === 0) {
69
+ return 0;
70
+ }
71
+ return -1;
72
+ }, [selectedIndex]);
73
+ const handleOnFocus = () => {
74
+ if (items && items.length > 0 && selectedIndex === -1) {
75
+ const item = items[0];
76
+ onChange(item.objectId);
77
+ }
78
+ };
79
+ const handleKeyDown = useCallback(event => {
80
+ let updatedIndex = activeIndex;
81
+ if (onKeyDown) {
82
+ onKeyDown(event);
83
+ }
84
+ if (!(items !== null && items !== void 0 && items.length)) {
85
+ return;
86
+ }
87
+ updatedIndex = handleNavKeyDown(event, items.length, activeIndex);
88
+ const item = items === null || items === void 0 ? void 0 : items[updatedIndex];
89
+ if (['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key) && item) {
90
+ onChange(item.objectId);
91
+ if (itemRefs.current) {
92
+ var _itemRefs$current$ite;
93
+ (_itemRefs$current$ite = itemRefs.current[item.objectId]) === null || _itemRefs$current$ite === void 0 ? void 0 : _itemRefs$current$ite.focus();
94
+ }
95
+ }
96
+ }, [activeIndex, items, onChange, onKeyDown]);
55
97
  if ((items === null || items === void 0 ? void 0 : items.length) === 0) {
56
98
  return jsx(LinkSearchNoResults, null);
57
99
  }
@@ -81,10 +123,12 @@ const LinkSearchList = /*#__PURE__*/forwardRef(({
81
123
  item: item,
82
124
  selected: selectedIndex === index,
83
125
  active: activeIndex === index,
84
- onMouseEnter: onMouseEnter,
85
- onMouseLeave: onMouseLeave,
126
+ onFocus: handleOnFocus,
127
+ onKeyDown: handleKeyDown,
86
128
  onSelect: onSelect,
87
- key: item.objectId
129
+ key: item.objectId,
130
+ tabIndex: getTabIndex(index),
131
+ ref: el => itemRefCallback(el, item.objectId)
88
132
  }))));
89
133
  }
90
134
  if (isLoading) {
@@ -1,35 +1,36 @@
1
1
  /** @jsx jsx */
2
- import { Fragment } from 'react';
2
+ import { forwardRef, Fragment } from 'react';
3
3
  import { jsx } from '@emotion/react';
4
- import { injectIntl } from 'react-intl-next';
5
4
  import { transformTimeStamp } from '../transformTimeStamp';
6
5
  import { itemNameStyles, itemIconStyles, listItemContextStyles, listItemNameStyles, composeListItemStyles, imgStyles, listItemContainerStyles, listItemContainerInnerStyles } from './styled';
7
6
  import { testIds } from '..';
8
- const LinkSearchListItem = ({
7
+ import { useIntl } from 'react-intl-next';
8
+ const LinkSearchListItem = /*#__PURE__*/forwardRef(({
9
9
  item,
10
10
  selected,
11
11
  active,
12
12
  id,
13
13
  role,
14
- intl,
15
14
  onSelect,
16
- onMouseEnter,
17
- onMouseLeave
18
- }) => {
15
+ tabIndex,
16
+ onKeyDown,
17
+ onFocus
18
+ }, ref) => {
19
+ const intl = useIntl();
19
20
  const handleSelect = () => onSelect(item.objectId);
20
- const handleMouseEnter = () => onMouseEnter(item.objectId);
21
- const handleMouseLeave = () => onMouseLeave(item.objectId);
22
21
  const container = item.container || null;
23
22
  const date = transformTimeStamp(intl, item.lastViewedDate, item.lastUpdatedDate);
24
23
  return jsx("div", {
25
- css: composeListItemStyles(active, selected),
24
+ css: composeListItemStyles(selected),
26
25
  role: role,
27
26
  id: id,
28
27
  "aria-selected": selected,
29
28
  "data-testid": testIds.searchResultItem,
30
- onMouseEnter: handleMouseEnter,
31
- onMouseLeave: handleMouseLeave,
32
- onClick: handleSelect
29
+ onKeyDown: onKeyDown,
30
+ onClick: handleSelect,
31
+ onFocus: onFocus,
32
+ tabIndex: tabIndex,
33
+ ref: ref
33
34
  }, jsx(ListItemIcon, {
34
35
  item: item,
35
36
  intl: intl
@@ -48,8 +49,8 @@ const LinkSearchListItem = ({
48
49
  }, container)), date && jsx("div", {
49
50
  css: listItemContainerInnerStyles
50
51
  }, container && jsx(Fragment, null, "\xA0 \u2022\xA0 "), jsx(Fragment, null, formatDate(date))))));
51
- };
52
- export default injectIntl(LinkSearchListItem);
52
+ });
53
+ export default LinkSearchListItem;
53
54
  const formatDate = date => {
54
55
  return [date.pageAction, date.dateString, date.timeSince].filter(Boolean).join(' ');
55
56
  };
@@ -1,5 +1,5 @@
1
1
  import { css } from '@emotion/react';
2
- import { B50, N300, N800, N20, B400 } from '@atlaskit/theme/colors';
2
+ import { B50, N300, N800, N20, B400, B100 } from '@atlaskit/theme/colors';
3
3
  // AFP-2532 TODO: Fix automatic suppressions below
4
4
  // eslint-disable-next-line @atlassian/tangerine/import/entry-points
5
5
  import { fontSizeSmall, fontSize } from '@atlaskit/theme';
@@ -18,22 +18,32 @@ const listItemBaseStyles = css`
18
18
  margin: 0 calc(-1 * ${"var(--ds-space-200, 16px)"});
19
19
  cursor: pointer;
20
20
  `;
21
+ const listItemFocusStyles = css`
22
+ &:focus {
23
+ outline: none;
24
+ box-shadow: 0 0 0 2px ${`var(--ds-border-focused, ${B100})`} inset;
25
+ text-decoration: none;
26
+ }
27
+ `;
21
28
  const listItemBoxShadow = css`
22
29
  box-shadow: inset 2px 0px 0px ${`var(--ds-border-selected, ${B400})`};
23
30
  `;
24
31
  const listItemActive = css`
25
- background-color: ${`var(--ds-background-neutral-subtle-hovered, ${N20})`};
32
+ &:hover {
33
+ background-color: ${`var(--ds-background-neutral-subtle-hovered, ${N20})`};
34
+ ${listItemBoxShadow};
35
+ }
26
36
  `;
27
37
  const listItemSelected = css`
28
38
  background-color: ${`var(--ds-background-selected, ${B50})`};
39
+ ${listItemBoxShadow};
29
40
  `;
30
- export const composeListItemStyles = (active = false, selected = false) => {
31
- const hasShadow = active || selected;
41
+ export const composeListItemStyles = (selected = false) => {
32
42
  return css`
33
43
  ${listItemBaseStyles};
34
- ${active && listItemActive};
44
+ ${!selected && listItemActive};
35
45
  ${selected && listItemSelected};
36
- ${hasShadow && listItemBoxShadow};
46
+ ${listItemFocusStyles};
37
47
  `;
38
48
  };
39
49
  export const itemNameStyles = css`
@@ -41,4 +41,26 @@ export function getScreenReaderText(items, selectedIndex, intl) {
41
41
  const formattedDate = [date === null || date === void 0 ? void 0 : date.pageAction, date === null || date === void 0 ? void 0 : date.dateString, date === null || date === void 0 ? void 0 : date.timeSince].filter(Boolean).join(' ');
42
42
  return [name, container, formattedDate].filter(Boolean).join(', ');
43
43
  }
44
- }
44
+ }
45
+ export const handleNavKeyDown = (event, itemsLength, activeIndex) => {
46
+ let updatedIndex = activeIndex;
47
+ switch (event.key) {
48
+ case 'ArrowDown':
49
+ event.preventDefault();
50
+ updatedIndex = (activeIndex + 1) % itemsLength;
51
+ break;
52
+ case 'ArrowUp':
53
+ event.preventDefault();
54
+ updatedIndex = activeIndex > 0 ? activeIndex - 1 : itemsLength - 1;
55
+ break;
56
+ case 'Home':
57
+ event.preventDefault();
58
+ updatedIndex = 0;
59
+ break;
60
+ case 'End':
61
+ event.preventDefault();
62
+ updatedIndex = itemsLength - 1;
63
+ break;
64
+ }
65
+ return updatedIndex;
66
+ };
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/link-picker",
3
- "version": "1.18.2",
3
+ "version": "1.18.4",
4
4
  "sideEffects": false
5
5
  }
@@ -29,7 +29,7 @@ import ScrollingTabList from '../scrolling-tabs';
29
29
  import LinkSearchList, { testIds as listTestIds } from './link-search-list';
30
30
  import LinkSearchError, { testIds as searchErrorTestIds } from './link-search-error';
31
31
  import FormFooter, { testIds as formFooterTestIds } from './form-footer';
32
- import { getDataSource, getScreenReaderText } from './utils';
32
+ import { getDataSource, getScreenReaderText, handleNavKeyDown } from './utils';
33
33
  import TrackTabViewed from './track-tab-viewed';
34
34
  import TrackMount from './track-mount';
35
35
  export var RECENT_SEARCH_LIST_SIZE = 5;
@@ -141,68 +141,16 @@ function LinkPicker(_ref) {
141
141
  displayText: e.currentTarget.value
142
142
  });
143
143
  }, [dispatch]);
144
- var handleKeyDown = useCallback(function (event) {
145
- var key = event.key;
146
- var KEY_ARROW_DOWN = 'ArrowDown';
147
- var KEY_ARROW_UP = 'ArrowUp';
148
- if (!items || !items.length) {
149
- return;
150
- }
151
- var updatedIndex = activeIndex;
152
- switch (key) {
153
- case KEY_ARROW_DOWN:
154
- // down
155
- event.preventDefault();
156
- updatedIndex = (activeIndex + 1) % items.length;
157
- break;
158
- case KEY_ARROW_UP:
159
- // up
160
- event.preventDefault();
161
- updatedIndex = activeIndex > 0 ? activeIndex - 1 : items.length - 1;
162
- break;
163
- }
164
- var item = items[updatedIndex];
165
- if ([KEY_ARROW_DOWN, KEY_ARROW_UP].includes(key) && item) {
166
- /**
167
- * Manually track that the url has been updated using searchResult method
168
- */
169
- trackAttribute('linkFieldContent', getLinkFieldContent(item.url));
170
- trackAttribute('linkFieldContentInputMethod', 'searchResult');
171
- trackAttribute('linkFieldContentInputSource', getDataSource(item, activePlugin));
172
- dispatch({
173
- activeIndex: updatedIndex,
174
- selectedIndex: updatedIndex,
175
- url: item.url,
176
- invalidUrl: false
177
- });
178
- }
179
- }, [dispatch, activeIndex, items, trackAttribute, activePlugin]);
180
144
  var handleClear = useCallback(function (field) {
181
- dispatch(_defineProperty({}, field, ''));
145
+ dispatch(_defineProperty({
146
+ activeIndex: -1,
147
+ selectedIndex: -1
148
+ }, field, ''));
182
149
  }, [dispatch]);
183
150
  var handleUrlClear = useCallback(function () {
184
151
  trackAttribute('linkFieldContentInputSource', null);
185
152
  handleClear('url');
186
153
  }, [trackAttribute, handleClear]);
187
- var handleMouseEnterResultItem = useCallback(function (objectId) {
188
- var index = items === null || items === void 0 ? void 0 : items.findIndex(function (item) {
189
- return item.objectId === objectId;
190
- });
191
- dispatch({
192
- activeIndex: index !== null && index !== void 0 ? index : -1
193
- });
194
- }, [dispatch, items]);
195
- var handleMouseLeaveResultItem = useCallback(function (objectId) {
196
- var index = items === null || items === void 0 ? void 0 : items.findIndex(function (item) {
197
- return item.objectId === objectId;
198
- });
199
- // This is to avoid updating index that was set by other mouseenter event
200
- if (activeIndex === index) {
201
- dispatch({
202
- activeIndex: -1
203
- });
204
- }
205
- }, [dispatch, activeIndex, items]);
206
154
  var handleInsert = useCallback(function (url, title, inputType) {
207
155
  var event = createAnalyticsEvent(createEventPayload('ui.form.submitted.linkPicker', {}));
208
156
 
@@ -245,7 +193,7 @@ function LinkPicker(_ref) {
245
193
  }
246
194
  }, [handleInsert, trackAttribute, items, activePlugin]);
247
195
  var handleSubmit = useCallback(function (event) {
248
- event.preventDefault();
196
+ event === null || event === void 0 ? void 0 : event.preventDefault();
249
197
  if (isSelectedItem && selectedItem) {
250
198
  return handleInsert(selectedItem.url, selectedItem.name, 'typeAhead');
251
199
  }
@@ -271,6 +219,60 @@ function LinkPicker(_ref) {
271
219
  });
272
220
  trackAttribute('tab', (_plugins$activeTab$ta = plugins === null || plugins === void 0 ? void 0 : (_plugins$activeTab = plugins[activeTab]) === null || _plugins$activeTab === void 0 ? void 0 : _plugins$activeTab.tabKey) !== null && _plugins$activeTab$ta !== void 0 ? _plugins$activeTab$ta : null);
273
221
  }, [dispatch, plugins, trackAttribute]);
222
+ var handleSearchListOnChange = function handleSearchListOnChange(id) {
223
+ var index = items === null || items === void 0 ? void 0 : items.findIndex(function (item) {
224
+ return item.objectId === id;
225
+ });
226
+ if (typeof index === 'number') {
227
+ var item = items === null || items === void 0 ? void 0 : items[index];
228
+ if (item) {
229
+ /**
230
+ * Manually track that the url has been updated using searchResult method
231
+ */
232
+ trackAttribute('linkFieldContent', getLinkFieldContent(item.url));
233
+ trackAttribute('linkFieldContentInputMethod', 'searchResult');
234
+ trackAttribute('linkFieldContentInputSource', getDataSource(item, activePlugin));
235
+ dispatch({
236
+ activeIndex: index,
237
+ selectedIndex: index,
238
+ url: item.url,
239
+ invalidUrl: false
240
+ });
241
+ }
242
+ }
243
+ };
244
+ var handleKeyDown = useCallback(function (event) {
245
+ if (!(items !== null && items !== void 0 && items.length)) {
246
+ return;
247
+ }
248
+ var updatedIndex = activeIndex;
249
+ if (event.key === 'Enter') {
250
+ event.preventDefault();
251
+ if (selectedItem) {
252
+ handleSelected(selectedItem.objectId);
253
+ } else {
254
+ // triggers validation error message
255
+ handleSubmit();
256
+ }
257
+ } else {
258
+ updatedIndex = handleNavKeyDown(event, items.length, activeIndex);
259
+ }
260
+ var item = items[updatedIndex];
261
+ if (['Enter', 'ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key) && item) {
262
+ /**
263
+ * Manually track that the url has been updated using searchResult method
264
+ */
265
+ trackAttribute('linkFieldContent', getLinkFieldContent(item.url));
266
+ trackAttribute('linkFieldContentInputMethod', 'searchResult');
267
+ trackAttribute('linkFieldContentInputSource', getDataSource(item, activePlugin));
268
+ dispatch({
269
+ activeIndex: updatedIndex,
270
+ selectedIndex: updatedIndex,
271
+ url: item.url,
272
+ invalidUrl: false
273
+ });
274
+ }
275
+ }, [items, activeIndex, selectedItem, handleSelected, handleSubmit, trackAttribute, activePlugin]);
274
276
  var messages = isActivePlugin ? searchMessages : linkMessages;
275
277
  var screenReaderDescriptionId = 'search-recent-links-field-description';
276
278
  var linkSearchListId = 'link-picker-search-list';
@@ -334,7 +336,6 @@ function LinkPicker(_ref) {
334
336
  clearLabel: intl.formatMessage(linkTextMessages.clearLinkText),
335
337
  "aria-label": intl.formatMessage(linkTextMessages.linkTextAriaLabel),
336
338
  onClear: handleClear,
337
- onKeyDown: handleKeyDown,
338
339
  onChange: handleChangeText
339
340
  }), isActivePlugin && !!queryState && jsx(Fragment, null, tabs.length > 0 && jsx("div", {
340
341
  css: tabsWrapperStyles
@@ -355,8 +356,8 @@ function LinkPicker(_ref) {
355
356
  selectedIndex: selectedIndex,
356
357
  activeIndex: activeIndex,
357
358
  onSelect: handleSelected,
358
- onMouseEnter: handleMouseEnterResultItem,
359
- onMouseLeave: handleMouseLeaveResultItem,
359
+ onChange: handleSearchListOnChange,
360
+ onKeyDown: handleKeyDown,
360
361
  hasSearchTerm: !!(queryState !== null && queryState !== void 0 && queryState.query.length)
361
362
  }), error && ((_errorFallback = errorFallback === null || errorFallback === void 0 ? void 0 : errorFallback(error, retry)) !== null && _errorFallback !== void 0 ? _errorFallback : jsx(LinkSearchError, null)))), jsx(FormFooter, {
362
363
  error: error,
@@ -1,11 +1,11 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
- var _excluded = ["onSelect", "onMouseEnter", "onMouseLeave", "items", "activeIndex", "selectedIndex", "isLoading", "ariaControls", "ariaLabelledBy", "role", "id", "hasSearchTerm"];
4
+ var _excluded = ["onChange", "onSelect", "onKeyDown", "items", "activeIndex", "selectedIndex", "isLoading", "ariaControls", "ariaLabelledBy", "role", "id", "hasSearchTerm"];
5
5
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
6
6
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
7
7
  /** @jsx jsx */
8
- import { forwardRef, Fragment } from 'react';
8
+ import { forwardRef, Fragment, useCallback, useRef } from 'react';
9
9
  import { jsx } from '@emotion/react';
10
10
  import { defineMessages, FormattedMessage } from 'react-intl-next';
11
11
  import Spinner from '@atlaskit/spinner';
@@ -14,6 +14,7 @@ import LinkSearchListItem from '../list-item';
14
14
  import { listContainerStyles, spinnerContainerStyles, listStyles, listTitleStyles } from './styled';
15
15
  import LinkSearchNoResults, { testIds as noResultsTestIds } from './link-search-no-results';
16
16
  import { useTrackResultsShown } from './use-track-results-shown';
17
+ import { handleNavKeyDown } from '../utils';
17
18
  export var messages = defineMessages({
18
19
  titleRecentlyViewed: {
19
20
  id: 'fabric.linkPicker.listTitle.recentlyViewed',
@@ -38,9 +39,9 @@ export var testIds = _objectSpread(_objectSpread({}, noResultsTestIds), {}, {
38
39
  searchResultLoadingIndicator: 'link-picker.results-loading-indicator'
39
40
  });
40
41
  var LinkSearchList = /*#__PURE__*/forwardRef(function (_ref, ref) {
41
- var onSelect = _ref.onSelect,
42
- onMouseEnter = _ref.onMouseEnter,
43
- onMouseLeave = _ref.onMouseLeave,
42
+ var onChange = _ref.onChange,
43
+ onSelect = _ref.onSelect,
44
+ onKeyDown = _ref.onKeyDown,
44
45
  items = _ref.items,
45
46
  activeIndex = _ref.activeIndex,
46
47
  selectedIndex = _ref.selectedIndex,
@@ -55,6 +56,47 @@ var LinkSearchList = /*#__PURE__*/forwardRef(function (_ref, ref) {
55
56
  var loadingContent;
56
57
  var linkListTitle = hasSearchTerm ? messages.titleResults : messages.titleRecentlyViewed;
57
58
  useTrackResultsShown(isLoading, items, hasSearchTerm);
59
+ var itemRefs = useRef({});
60
+ var itemRefCallback = useCallback(function (el, id) {
61
+ if (el === null) {
62
+ delete itemRefs.current[id];
63
+ } else {
64
+ itemRefs.current[id] = el;
65
+ }
66
+ }, []);
67
+ var getTabIndex = useCallback(function (index) {
68
+ if (selectedIndex > -1) {
69
+ return selectedIndex === index ? 0 : -1;
70
+ }
71
+ if (index === 0) {
72
+ return 0;
73
+ }
74
+ return -1;
75
+ }, [selectedIndex]);
76
+ var handleOnFocus = function handleOnFocus() {
77
+ if (items && items.length > 0 && selectedIndex === -1) {
78
+ var item = items[0];
79
+ onChange(item.objectId);
80
+ }
81
+ };
82
+ var handleKeyDown = useCallback(function (event) {
83
+ var updatedIndex = activeIndex;
84
+ if (onKeyDown) {
85
+ onKeyDown(event);
86
+ }
87
+ if (!(items !== null && items !== void 0 && items.length)) {
88
+ return;
89
+ }
90
+ updatedIndex = handleNavKeyDown(event, items.length, activeIndex);
91
+ var item = items === null || items === void 0 ? void 0 : items[updatedIndex];
92
+ if (['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key) && item) {
93
+ onChange(item.objectId);
94
+ if (itemRefs.current) {
95
+ var _itemRefs$current$ite;
96
+ (_itemRefs$current$ite = itemRefs.current[item.objectId]) === null || _itemRefs$current$ite === void 0 ? void 0 : _itemRefs$current$ite.focus();
97
+ }
98
+ }
99
+ }, [activeIndex, items, onChange, onKeyDown]);
58
100
  if ((items === null || items === void 0 ? void 0 : items.length) === 0) {
59
101
  return jsx(LinkSearchNoResults, null);
60
102
  }
@@ -85,10 +127,14 @@ var LinkSearchList = /*#__PURE__*/forwardRef(function (_ref, ref) {
85
127
  item: item,
86
128
  selected: selectedIndex === index,
87
129
  active: activeIndex === index,
88
- onMouseEnter: onMouseEnter,
89
- onMouseLeave: onMouseLeave,
130
+ onFocus: handleOnFocus,
131
+ onKeyDown: handleKeyDown,
90
132
  onSelect: onSelect,
91
- key: item.objectId
133
+ key: item.objectId,
134
+ tabIndex: getTabIndex(index),
135
+ ref: function ref(el) {
136
+ return itemRefCallback(el, item.objectId);
137
+ }
92
138
  });
93
139
  })));
94
140
  }
@@ -1,40 +1,37 @@
1
1
  /** @jsx jsx */
2
- import { Fragment } from 'react';
2
+ import { forwardRef, Fragment } from 'react';
3
3
  import { jsx } from '@emotion/react';
4
- import { injectIntl } from 'react-intl-next';
5
4
  import { transformTimeStamp } from '../transformTimeStamp';
6
5
  import { itemNameStyles, itemIconStyles, listItemContextStyles, listItemNameStyles, composeListItemStyles, imgStyles, listItemContainerStyles, listItemContainerInnerStyles } from './styled';
7
6
  import { testIds } from '..';
8
- var LinkSearchListItem = function LinkSearchListItem(_ref) {
7
+ import { useIntl } from 'react-intl-next';
8
+ var LinkSearchListItem = /*#__PURE__*/forwardRef(function (_ref, ref) {
9
9
  var item = _ref.item,
10
10
  selected = _ref.selected,
11
11
  active = _ref.active,
12
12
  id = _ref.id,
13
13
  role = _ref.role,
14
- intl = _ref.intl,
15
14
  onSelect = _ref.onSelect,
16
- onMouseEnter = _ref.onMouseEnter,
17
- onMouseLeave = _ref.onMouseLeave;
15
+ tabIndex = _ref.tabIndex,
16
+ onKeyDown = _ref.onKeyDown,
17
+ onFocus = _ref.onFocus;
18
+ var intl = useIntl();
18
19
  var handleSelect = function handleSelect() {
19
20
  return onSelect(item.objectId);
20
21
  };
21
- var handleMouseEnter = function handleMouseEnter() {
22
- return onMouseEnter(item.objectId);
23
- };
24
- var handleMouseLeave = function handleMouseLeave() {
25
- return onMouseLeave(item.objectId);
26
- };
27
22
  var container = item.container || null;
28
23
  var date = transformTimeStamp(intl, item.lastViewedDate, item.lastUpdatedDate);
29
24
  return jsx("div", {
30
- css: composeListItemStyles(active, selected),
25
+ css: composeListItemStyles(selected),
31
26
  role: role,
32
27
  id: id,
33
28
  "aria-selected": selected,
34
29
  "data-testid": testIds.searchResultItem,
35
- onMouseEnter: handleMouseEnter,
36
- onMouseLeave: handleMouseLeave,
37
- onClick: handleSelect
30
+ onKeyDown: onKeyDown,
31
+ onClick: handleSelect,
32
+ onFocus: onFocus,
33
+ tabIndex: tabIndex,
34
+ ref: ref
38
35
  }, jsx(ListItemIcon, {
39
36
  item: item,
40
37
  intl: intl
@@ -53,8 +50,8 @@ var LinkSearchListItem = function LinkSearchListItem(_ref) {
53
50
  }, container)), date && jsx("div", {
54
51
  css: listItemContainerInnerStyles
55
52
  }, container && jsx(Fragment, null, "\xA0 \u2022\xA0 "), jsx(Fragment, null, formatDate(date))))));
56
- };
57
- export default injectIntl(LinkSearchListItem);
53
+ });
54
+ export default LinkSearchListItem;
58
55
  var formatDate = function formatDate(date) {
59
56
  return [date.pageAction, date.dateString, date.timeSince].filter(Boolean).join(' ');
60
57
  };
@@ -1,7 +1,7 @@
1
1
  import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
2
- var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5, _templateObject6, _templateObject7, _templateObject8, _templateObject9, _templateObject10, _templateObject11, _templateObject12;
2
+ var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5, _templateObject6, _templateObject7, _templateObject8, _templateObject9, _templateObject10, _templateObject11, _templateObject12, _templateObject13;
3
3
  import { css } from '@emotion/react';
4
- import { B50, N300, N800, N20, B400 } from '@atlaskit/theme/colors';
4
+ import { B50, N300, N800, N20, B400, B100 } from '@atlaskit/theme/colors';
5
5
  // AFP-2532 TODO: Fix automatic suppressions below
6
6
  // eslint-disable-next-line @atlassian/tangerine/import/entry-points
7
7
  import { fontSizeSmall, fontSize } from '@atlaskit/theme';
@@ -15,19 +15,18 @@ export var relativeFontSizeToBase16 = function relativeFontSizeToBase16(px) {
15
15
  return "".concat(px / 16, "rem");
16
16
  };
17
17
  var listItemBaseStyles = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n display: flex;\n padding: ", " ", ";\n margin: 0 calc(-1 * ", ");\n cursor: pointer;\n"])), "var(--ds-space-100, 8px)", "var(--ds-space-200, 16px)", "var(--ds-space-200, 16px)");
18
- var listItemBoxShadow = css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n box-shadow: inset 2px 0px 0px ", ";\n"])), "var(--ds-border-selected, ".concat(B400, ")"));
19
- var listItemActive = css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n background-color: ", ";\n"])), "var(--ds-background-neutral-subtle-hovered, ".concat(N20, ")"));
20
- var listItemSelected = css(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["\n background-color: ", ";\n"])), "var(--ds-background-selected, ".concat(B50, ")"));
18
+ var listItemFocusStyles = css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n &:focus {\n outline: none;\n box-shadow: 0 0 0 2px ", " inset;\n text-decoration: none;\n }\n"])), "var(--ds-border-focused, ".concat(B100, ")"));
19
+ var listItemBoxShadow = css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n box-shadow: inset 2px 0px 0px ", ";\n"])), "var(--ds-border-selected, ".concat(B400, ")"));
20
+ var listItemActive = css(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["\n &:hover {\n background-color: ", ";\n ", ";\n }\n"])), "var(--ds-background-neutral-subtle-hovered, ".concat(N20, ")"), listItemBoxShadow);
21
+ var listItemSelected = css(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["\n background-color: ", ";\n ", ";\n"])), "var(--ds-background-selected, ".concat(B50, ")"), listItemBoxShadow);
21
22
  export var composeListItemStyles = function composeListItemStyles() {
22
- var active = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
23
- var selected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
24
- var hasShadow = active || selected;
25
- return css(_templateObject5 || (_templateObject5 = _taggedTemplateLiteral(["\n ", ";\n ", ";\n ", ";\n ", ";\n "])), listItemBaseStyles, active && listItemActive, selected && listItemSelected, hasShadow && listItemBoxShadow);
23
+ var selected = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
24
+ return css(_templateObject6 || (_templateObject6 = _taggedTemplateLiteral(["\n ", ";\n ", ";\n ", ";\n ", ";\n "])), listItemBaseStyles, !selected && listItemActive, selected && listItemSelected, listItemFocusStyles);
26
25
  };
27
- export var itemNameStyles = css(_templateObject6 || (_templateObject6 = _taggedTemplateLiteral(["\n overflow: hidden;\n"])));
28
- export var listItemNameStyles = css(_templateObject7 || (_templateObject7 = _taggedTemplateLiteral(["\n color: ", ";\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n line-height: 20px;\n"])), "var(--ds-text, ".concat(N800, ")"));
29
- export var listItemContextStyles = css(_templateObject8 || (_templateObject8 = _taggedTemplateLiteral(["\n color: ", ";\n font-size: ", ";\n line-height: ", "px;\n display: flex;\n"])), "var(--ds-text, ".concat(N300, ")"), relativeFontSizeToBase16(fontSizeSmall()), fontSize());
30
- export var listItemContainerStyles = css(_templateObject9 || (_templateObject9 = _taggedTemplateLiteral(["\n overflow: hidden;\n text-overflow: ellipsis;\n"])));
31
- export var listItemContainerInnerStyles = css(_templateObject10 || (_templateObject10 = _taggedTemplateLiteral(["\n white-space: nowrap;\n"])));
32
- export var itemIconStyles = css(_templateObject11 || (_templateObject11 = _taggedTemplateLiteral(["\n min-width: ", ";\n margin-top: 3px;\n margin-right: ", ";\n"])), "var(--ds-space-200, 16px)", "var(--ds-space-150, 12px)");
33
- export var imgStyles = css(_templateObject12 || (_templateObject12 = _taggedTemplateLiteral(["\n max-width: ", ";\n"])), "var(--ds-space-200, 16px)");
26
+ export var itemNameStyles = css(_templateObject7 || (_templateObject7 = _taggedTemplateLiteral(["\n overflow: hidden;\n"])));
27
+ export var listItemNameStyles = css(_templateObject8 || (_templateObject8 = _taggedTemplateLiteral(["\n color: ", ";\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n line-height: 20px;\n"])), "var(--ds-text, ".concat(N800, ")"));
28
+ export var listItemContextStyles = css(_templateObject9 || (_templateObject9 = _taggedTemplateLiteral(["\n color: ", ";\n font-size: ", ";\n line-height: ", "px;\n display: flex;\n"])), "var(--ds-text, ".concat(N300, ")"), relativeFontSizeToBase16(fontSizeSmall()), fontSize());
29
+ export var listItemContainerStyles = css(_templateObject10 || (_templateObject10 = _taggedTemplateLiteral(["\n overflow: hidden;\n text-overflow: ellipsis;\n"])));
30
+ export var listItemContainerInnerStyles = css(_templateObject11 || (_templateObject11 = _taggedTemplateLiteral(["\n white-space: nowrap;\n"])));
31
+ export var itemIconStyles = css(_templateObject12 || (_templateObject12 = _taggedTemplateLiteral(["\n min-width: ", ";\n margin-top: 3px;\n margin-right: ", ";\n"])), "var(--ds-space-200, 16px)", "var(--ds-space-150, 12px)");
32
+ export var imgStyles = css(_templateObject13 || (_templateObject13 = _taggedTemplateLiteral(["\n max-width: ", ";\n"])), "var(--ds-space-200, 16px)");
@@ -38,4 +38,26 @@ export function getScreenReaderText(items, selectedIndex, intl) {
38
38
  var formattedDate = [date === null || date === void 0 ? void 0 : date.pageAction, date === null || date === void 0 ? void 0 : date.dateString, date === null || date === void 0 ? void 0 : date.timeSince].filter(Boolean).join(' ');
39
39
  return [name, container, formattedDate].filter(Boolean).join(', ');
40
40
  }
41
- }
41
+ }
42
+ export var handleNavKeyDown = function handleNavKeyDown(event, itemsLength, activeIndex) {
43
+ var updatedIndex = activeIndex;
44
+ switch (event.key) {
45
+ case 'ArrowDown':
46
+ event.preventDefault();
47
+ updatedIndex = (activeIndex + 1) % itemsLength;
48
+ break;
49
+ case 'ArrowUp':
50
+ event.preventDefault();
51
+ updatedIndex = activeIndex > 0 ? activeIndex - 1 : itemsLength - 1;
52
+ break;
53
+ case 'Home':
54
+ event.preventDefault();
55
+ updatedIndex = 0;
56
+ break;
57
+ case 'End':
58
+ event.preventDefault();
59
+ updatedIndex = itemsLength - 1;
60
+ break;
61
+ }
62
+ return updatedIndex;
63
+ };
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/link-picker",
3
- "version": "1.18.2",
3
+ "version": "1.18.4",
4
4
  "sideEffects": false
5
5
  }