@atlaskit/link-picker 1.8.2 → 1.8.5

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 (91) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/cjs/analytics.codegen.js +1 -1
  3. package/dist/cjs/{ui/link-picker → common/utils}/url.js +0 -0
  4. package/dist/cjs/controllers/use-fix-height/index.js +27 -0
  5. package/dist/cjs/services/use-plugins/index.js +48 -90
  6. package/dist/cjs/services/use-plugins/reducer.js +64 -0
  7. package/dist/cjs/services/use-plugins/utils.js +134 -0
  8. package/dist/cjs/services/use-search-query/index.js +1 -1
  9. package/dist/cjs/services/with-link-picker-analytics/index.js +33 -0
  10. package/dist/cjs/ui/link-picker/form-footer/index.js +76 -0
  11. package/dist/cjs/ui/link-picker/form-footer/styled.js +17 -0
  12. package/dist/cjs/ui/link-picker/index.js +33 -75
  13. package/dist/cjs/ui/link-picker/link-search-error/index.js +47 -6
  14. package/dist/cjs/ui/link-picker/link-search-list/index.js +89 -20
  15. package/dist/cjs/ui/link-picker/link-search-list/link-search-no-results/index.js +54 -0
  16. package/dist/cjs/ui/link-picker/{link-search-no-results → link-search-list/link-search-no-results}/no-results-svg/index.js +0 -0
  17. package/dist/cjs/ui/link-picker/{link-search-no-results → link-search-list/link-search-no-results}/no-results-svg/styled.js +0 -0
  18. package/dist/cjs/ui/link-picker/link-search-list/link-search-no-results/styled.js +17 -0
  19. package/dist/cjs/ui/link-picker/link-search-list/styled.js +13 -6
  20. package/dist/cjs/ui/link-picker/messages.js +0 -50
  21. package/dist/cjs/ui/link-picker/styled.js +16 -11
  22. package/dist/cjs/ui/link-picker/text-input/styled.js +1 -1
  23. package/dist/cjs/version.json +1 -1
  24. package/dist/es2019/analytics.codegen.js +1 -1
  25. package/dist/es2019/{ui/link-picker → common/utils}/url.js +0 -0
  26. package/dist/es2019/controllers/use-fix-height/index.js +19 -0
  27. package/dist/es2019/services/use-plugins/index.js +35 -57
  28. package/dist/es2019/services/use-plugins/reducer.js +37 -0
  29. package/dist/es2019/services/use-plugins/utils.js +59 -0
  30. package/dist/es2019/services/use-search-query/index.js +1 -1
  31. package/dist/es2019/services/with-link-picker-analytics/index.js +15 -0
  32. package/dist/es2019/ui/link-picker/form-footer/index.js +51 -0
  33. package/dist/es2019/ui/link-picker/form-footer/styled.js +5 -0
  34. package/dist/es2019/ui/link-picker/index.js +28 -69
  35. package/dist/es2019/ui/link-picker/link-search-error/index.js +40 -4
  36. package/dist/es2019/ui/link-picker/link-search-list/index.js +60 -14
  37. package/dist/es2019/ui/link-picker/link-search-list/link-search-no-results/index.js +35 -0
  38. package/dist/es2019/ui/link-picker/{link-search-no-results → link-search-list/link-search-no-results}/no-results-svg/index.js +0 -0
  39. package/dist/es2019/ui/link-picker/{link-search-no-results → link-search-list/link-search-no-results}/no-results-svg/styled.js +0 -0
  40. package/dist/es2019/ui/link-picker/link-search-list/link-search-no-results/styled.js +6 -0
  41. package/dist/es2019/ui/link-picker/link-search-list/styled.js +23 -2
  42. package/dist/es2019/ui/link-picker/messages.js +0 -50
  43. package/dist/es2019/ui/link-picker/styled.js +20 -15
  44. package/dist/es2019/ui/link-picker/text-input/styled.js +3 -1
  45. package/dist/es2019/version.json +1 -1
  46. package/dist/esm/analytics.codegen.js +1 -1
  47. package/dist/esm/{ui/link-picker → common/utils}/url.js +0 -0
  48. package/dist/esm/controllers/use-fix-height/index.js +19 -0
  49. package/dist/esm/services/use-plugins/index.js +49 -94
  50. package/dist/esm/services/use-plugins/reducer.js +43 -0
  51. package/dist/esm/services/use-plugins/utils.js +111 -0
  52. package/dist/esm/services/use-search-query/index.js +1 -1
  53. package/dist/esm/services/with-link-picker-analytics/index.js +17 -0
  54. package/dist/esm/ui/link-picker/form-footer/index.js +53 -0
  55. package/dist/esm/ui/link-picker/form-footer/styled.js +6 -0
  56. package/dist/esm/ui/link-picker/index.js +29 -74
  57. package/dist/esm/ui/link-picker/link-search-error/index.js +41 -5
  58. package/dist/esm/ui/link-picker/link-search-list/index.js +67 -13
  59. package/dist/esm/ui/link-picker/link-search-list/link-search-no-results/index.js +37 -0
  60. package/dist/esm/ui/link-picker/{link-search-no-results → link-search-list/link-search-no-results}/no-results-svg/index.js +0 -0
  61. package/dist/esm/ui/link-picker/{link-search-no-results → link-search-list/link-search-no-results}/no-results-svg/styled.js +0 -0
  62. package/dist/esm/ui/link-picker/link-search-list/link-search-no-results/styled.js +6 -0
  63. package/dist/esm/ui/link-picker/link-search-list/styled.js +11 -5
  64. package/dist/esm/ui/link-picker/messages.js +0 -50
  65. package/dist/esm/ui/link-picker/styled.js +14 -11
  66. package/dist/esm/ui/link-picker/text-input/styled.js +1 -1
  67. package/dist/esm/version.json +1 -1
  68. package/dist/types/analytics.codegen.d.ts +7 -4
  69. package/dist/types/{ui/link-picker → common/utils}/url.d.ts +0 -0
  70. package/dist/types/controllers/use-fix-height/index.d.ts +8 -0
  71. package/dist/types/services/use-plugins/reducer.d.ts +30 -0
  72. package/dist/types/services/use-plugins/utils.d.ts +18 -0
  73. package/dist/types/services/with-link-picker-analytics/index.d.ts +4 -0
  74. package/dist/types/ui/link-picker/form-footer/index.d.ts +13 -0
  75. package/dist/types/ui/link-picker/form-footer/styled.d.ts +1 -0
  76. package/dist/types/ui/link-picker/index.d.ts +19 -19
  77. package/dist/types/ui/link-picker/link-search-error/index.d.ts +19 -3
  78. package/dist/types/ui/link-picker/link-search-list/index.d.ts +30 -5
  79. package/dist/types/ui/link-picker/link-search-list/link-search-no-results/index.d.ts +19 -0
  80. package/dist/types/ui/link-picker/{link-search-no-results → link-search-list/link-search-no-results}/no-results-svg/index.d.ts +0 -0
  81. package/dist/types/ui/link-picker/{link-search-no-results → link-search-list/link-search-no-results}/no-results-svg/styled.d.ts +0 -0
  82. package/dist/types/ui/link-picker/link-search-list/link-search-no-results/styled.d.ts +1 -0
  83. package/dist/types/ui/link-picker/link-search-list/styled.d.ts +1 -0
  84. package/dist/types/ui/link-picker/messages.d.ts +0 -50
  85. package/dist/types/ui/link-picker/styled.d.ts +5 -1
  86. package/package.json +12 -12
  87. package/report.api.md +2 -0
  88. package/dist/cjs/ui/link-picker/link-search-no-results/index.js +0 -27
  89. package/dist/es2019/ui/link-picker/link-search-no-results/index.js +0 -10
  90. package/dist/esm/ui/link-picker/link-search-no-results/index.js +0 -14
  91. package/dist/types/ui/link-picker/link-search-no-results/index.d.ts +0 -4
@@ -0,0 +1,111 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
+ import _createClass from "@babel/runtime/helpers/createClass";
3
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
4
+ import _inherits from "@babel/runtime/helpers/inherits";
5
+ import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
6
+ import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
7
+ import _wrapNativeSuper from "@babel/runtime/helpers/wrapNativeSuper";
8
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
9
+
10
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
11
+
12
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
13
+
14
+ export var CancellationError = /*#__PURE__*/function (_Error) {
15
+ _inherits(CancellationError, _Error);
16
+
17
+ var _super = _createSuper(CancellationError);
18
+
19
+ function CancellationError() {
20
+ _classCallCheck(this, CancellationError);
21
+
22
+ return _super.apply(this, arguments);
23
+ }
24
+
25
+ return _createClass(CancellationError);
26
+ }( /*#__PURE__*/_wrapNativeSuper(Error));
27
+ export var cancellable = function cancellable(promise) {
28
+ var reject;
29
+ return {
30
+ promise: new Promise(function (resolve, _reject) {
31
+ reject = _reject;
32
+ promise.then(resolve, reject);
33
+ }),
34
+ cancel: function cancel() {
35
+ reject(new CancellationError('Promise cancelled'));
36
+ }
37
+ };
38
+ };
39
+ /**
40
+ * Wraps the resolve with a cancellation wrapper and makes promise + generator plugin resolves more compatible
41
+ * Calling cancel for generator plugin prevents it from yielding any further updates
42
+ */
43
+
44
+ export var resolvePluginUpdates = function resolvePluginUpdates(plugin, state) {
45
+ var updates = plugin.resolve(state); // Promise plugin
46
+
47
+ if (updates instanceof Promise) {
48
+ var _cancellable = cancellable(updates),
49
+ promise = _cancellable.promise,
50
+ cancel = _cancellable.cancel;
51
+
52
+ return {
53
+ cancel: cancel,
54
+ next: function () {
55
+ var _next = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
56
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
57
+ while (1) {
58
+ switch (_context.prev = _context.next) {
59
+ case 0:
60
+ _context.next = 2;
61
+ return promise;
62
+
63
+ case 2:
64
+ _context.t0 = _context.sent;
65
+ return _context.abrupt("return", {
66
+ value: _context.t0,
67
+ done: true
68
+ });
69
+
70
+ case 4:
71
+ case "end":
72
+ return _context.stop();
73
+ }
74
+ }
75
+ }, _callee);
76
+ }));
77
+
78
+ function next() {
79
+ return _next.apply(this, arguments);
80
+ }
81
+
82
+ return next;
83
+ }()
84
+ };
85
+ } // Generator plugin
86
+
87
+
88
+ var cancellationCallbacks = [];
89
+ var cancelled = false;
90
+ return {
91
+ cancel: function cancel() {
92
+ cancelled = true;
93
+ cancellationCallbacks.forEach(function (cb) {
94
+ return cb();
95
+ });
96
+ },
97
+ next: function next() {
98
+ var _cancellable2 = cancellable(updates.next()),
99
+ promise = _cancellable2.promise,
100
+ cancel = _cancellable2.cancel;
101
+
102
+ if (cancelled) {
103
+ cancel();
104
+ } else {
105
+ cancellationCallbacks.push(cancel);
106
+ }
107
+
108
+ return promise;
109
+ }
110
+ };
111
+ };
@@ -1,5 +1,5 @@
1
1
  import { useRef } from 'react';
2
- import { isSafeUrl } from '../../ui/link-picker/url';
2
+ import { isSafeUrl } from '../../common/utils/url';
3
3
  export function useSearchQuery(state) {
4
4
  var _queryState$current;
5
5
 
@@ -0,0 +1,17 @@
1
+ import React, { useMemo } from 'react';
2
+ import { AnalyticsContext } from '@atlaskit/analytics-next';
3
+ import { normalizeUrl } from '../../common/utils/url';
4
+ export function withLinkPickerAnalyticsContext(WrappedComponent) {
5
+ return function (props) {
6
+ var data = useMemo(function () {
7
+ return {
8
+ attributes: {
9
+ linkState: normalizeUrl(props.url) ? 'editLink' : 'newLink'
10
+ }
11
+ };
12
+ }, [props.url]);
13
+ return /*#__PURE__*/React.createElement(AnalyticsContext, {
14
+ data: data
15
+ }, /*#__PURE__*/React.createElement(WrappedComponent, props));
16
+ };
17
+ }
@@ -0,0 +1,53 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
+ var _excluded = ["isEditing", "onCancel"];
4
+
5
+ /** @jsx jsx */
6
+ import { jsx } from '@emotion/react';
7
+ import { useIntl, defineMessages } from 'react-intl-next';
8
+ import Button, { ButtonGroup } from '@atlaskit/button';
9
+ import { formFooterStyles } from './styled';
10
+ import { memo } from 'react';
11
+ var messages = defineMessages({
12
+ cancelButton: {
13
+ id: 'fabric.linkPicker.button.cancel',
14
+ defaultMessage: 'Cancel',
15
+ description: 'Button to cancel and dismiss the link picker'
16
+ },
17
+ saveButton: {
18
+ id: 'fabric.linkPicker.button.save',
19
+ defaultMessage: 'Save',
20
+ description: 'Button to save edited link'
21
+ },
22
+ insertButton: {
23
+ id: 'fabric.linkPicker.button.insert',
24
+ defaultMessage: 'Insert',
25
+ description: 'Button to insert searched or selected link'
26
+ }
27
+ });
28
+ export var testIds = {
29
+ insertButton: 'link-picker-insert-button',
30
+ cancelButton: 'link-picker-cancel-button'
31
+ };
32
+
33
+ var FormFooter = function FormFooter(_ref) {
34
+ var isEditing = _ref.isEditing,
35
+ onCancel = _ref.onCancel,
36
+ restProps = _objectWithoutProperties(_ref, _excluded);
37
+
38
+ var intl = useIntl();
39
+ var insertButtonMsg = isEditing ? messages.saveButton : messages.insertButton;
40
+ return jsx("footer", _extends({
41
+ css: formFooterStyles
42
+ }, restProps), jsx(ButtonGroup, null, jsx(Button, {
43
+ appearance: "default",
44
+ onClick: onCancel,
45
+ testId: testIds.cancelButton
46
+ }, intl.formatMessage(messages.cancelButton)), jsx(Button, {
47
+ type: "submit",
48
+ appearance: "primary",
49
+ testId: testIds.insertButton
50
+ }, intl.formatMessage(insertButtonMsg))));
51
+ };
52
+
53
+ export default /*#__PURE__*/memo(FormFooter);
@@ -0,0 +1,6 @@
1
+ import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
2
+
3
+ var _templateObject;
4
+
5
+ import { css } from '@emotion/react';
6
+ export var formFooterStyles = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n display: flex;\n justify-content: flex-end;\n"])));
@@ -7,12 +7,10 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
7
7
  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; }
8
8
 
9
9
  /** @jsx jsx */
10
- import { Fragment, useCallback, useEffect, useLayoutEffect, useReducer } from 'react';
10
+ import { Fragment, useCallback, useEffect, useLayoutEffect, useReducer, memo } from 'react';
11
11
  import { jsx } from '@emotion/react';
12
12
  import { useIntl, FormattedMessage } from 'react-intl-next';
13
13
  import { useAnalyticsEvents } from '@atlaskit/analytics-next';
14
- import Button, { ButtonGroup } from '@atlaskit/button';
15
- import { FormFooter } from '@atlaskit/form';
16
14
  import EditorSearchIcon from '@atlaskit/icon/glyph/editor/search';
17
15
  import Tabs, { Tab, TabList } from '@atlaskit/tabs';
18
16
  import VisuallyHidden from '@atlaskit/visually-hidden';
@@ -20,36 +18,31 @@ import createEventPayload from '../../analytics.codegen';
20
18
  import { ANALYTICS_CHANNEL } from '../../common/constants';
21
19
  import { usePlugins } from '../../services/use-plugins';
22
20
  import { useSearchQuery } from '../../services/use-search-query';
21
+ import { withLinkPickerAnalyticsContext } from '../../services/with-link-picker-analytics';
23
22
  import { messages } from './messages';
24
23
  import PanelTextInput from './text-input';
25
- import LinkSearchList from './link-search-list';
26
- import { normalizeUrl, isSafeUrl } from './url';
27
- import { rootContainerStyles, searchIconStyles, listTitleStyles, tabsWrapperStyles } from './styled';
24
+ import { normalizeUrl, isSafeUrl } from '../../common/utils/url';
25
+ import useFixHeight from '../../controllers/use-fix-height';
26
+ import { rootContainerStyles, searchIconStyles, tabsWrapperStyles, flexColumnStyles, formFooterMargin } from './styled';
28
27
  import { browser } from './browser';
29
28
  import Announcer from './announcer';
30
- import LinkSearchNoResults from './link-search-no-results';
31
29
  import { transformTimeStamp } from './transformTimeStamp';
32
- import LinkSearchError from './link-search-error';
30
+ import LinkSearchList, { testIds as listTestIds } from './link-search-list';
31
+ import LinkSearchError, { testIds as searchErrorTestIds } from './link-search-error';
32
+ import FormFooter, { testIds as formFooterTestIds } from './form-footer';
33
33
  export var RECENT_SEARCH_LIST_SIZE = 5;
34
34
  export var CONTACT_SUPPORT_LINK = 'https://support.atlassian.com/contact/';
35
- export var testIds = {
35
+ export var testIds = _objectSpread(_objectSpread(_objectSpread(_objectSpread({
36
36
  linkPicker: 'link-picker',
37
37
  urlInputField: 'link-url',
38
38
  textInputField: 'link-text',
39
- searchIcon: 'link-picker-search-icon',
40
- insertButton: 'link-picker-insert-button',
41
- cancelButton: 'link-picker-cancel-button',
39
+ searchIcon: 'link-picker-search-icon'
40
+ }, formFooterTestIds), searchErrorTestIds), listTestIds), {}, {
42
41
  clearUrlButton: 'clear-text',
43
- resultListTitle: 'link-picker-list-title',
44
- emptyResultPage: 'link-search-no-results',
45
- searchResultList: 'link-search-list',
46
- searchResultItem: 'link-search-list-item',
47
- searchResultLoadingIndicator: 'link-picker.results-loading-indicator',
48
42
  urlError: 'link-error',
49
43
  tabList: 'link-picker-tabs',
50
- tabItem: 'link-picker-tab',
51
- searchError: 'link-search-error'
52
- };
44
+ tabItem: 'link-picker-tab'
45
+ });
53
46
  var initState = {
54
47
  url: '',
55
48
  displayText: '',
@@ -71,7 +64,7 @@ function reducer(state, payload) {
71
64
  }
72
65
 
73
66
  function LinkPicker(_ref) {
74
- var _queryState$query, _items$length, _errorFallback;
67
+ var _errorFallback;
75
68
 
76
69
  var onSubmit = _ref.onSubmit,
77
70
  onCancel = _ref.onCancel,
@@ -109,6 +102,7 @@ function LinkPicker(_ref) {
109
102
  retry = _usePlugins.retry,
110
103
  errorFallback = _usePlugins.errorFallback;
111
104
 
105
+ var fixListHeightProps = useFixHeight(isLoading);
112
106
  var isEditing = !!initUrl;
113
107
  var selectedItem = items === null || items === void 0 ? void 0 : items[selectedIndex];
114
108
  var isSelectedItem = (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.url) === url;
@@ -237,9 +231,6 @@ function LinkPicker(_ref) {
237
231
  });
238
232
  }, [handleInsert, isSelectedItem, selectedItem, url]);
239
233
  var linkPlaceHolder = isActivePlugin ? messages.placeholder : messages.linkPlaceholder;
240
- var linkListTitle = (queryState === null || queryState === void 0 ? void 0 : (_queryState$query = queryState.query) === null || _queryState$query === void 0 ? void 0 : _queryState$query.length) !== 0 ? messages.titleResults : messages.titleRecentlyViewed;
241
- var insertButtonMsg = isEditing ? messages.saveButton : messages.insertButton;
242
- var noResults = (items === null || items === void 0 ? void 0 : items.length) === 0 && !error;
243
234
  var screenReaderDescriptionId = 'search-recent-links-field-description';
244
235
  var linkSearchListId = 'link-picker-search-list';
245
236
  var ariaActiveDescendant = selectedIndex > -1 ? "link-search-list-item-".concat(selectedIndex) : ''; // Added workaround with a screen reader Announcer specifically for VoiceOver + Safari
@@ -297,7 +288,7 @@ function LinkPicker(_ref) {
297
288
  onClear: handleClear,
298
289
  onKeyDown: handleKeyDown,
299
290
  onChange: handleChangeText
300
- }), queryState && jsx(Fragment, null, tabs.length > 0 && jsx("div", {
291
+ }), isActivePlugin && !!queryState && jsx(Fragment, null, tabs.length > 0 && jsx("div", {
301
292
  css: tabsWrapperStyles
302
293
  }, jsx(Tabs, {
303
294
  id: testIds.tabList,
@@ -315,64 +306,28 @@ function LinkPicker(_ref) {
315
306
  key: tab.tabTitle,
316
307
  testId: testIds.tabItem
317
308
  }, tab.tabTitle);
318
- })))), !!(items !== null && items !== void 0 && items.length) && jsx("div", {
319
- css: listTitleStyles,
320
- id: testIds.resultListTitle,
321
- "data-testid": testIds.resultListTitle
322
- }, jsx(FormattedMessage, linkListTitle)), jsx(VisuallyHidden, {
323
- id: "fabric.smartcard.linkpicker.suggested.results"
324
- }, url && jsx(FormattedMessage, _extends({}, messages.searchLinkResults, {
325
- values: {
326
- count: (_items$length = items === null || items === void 0 ? void 0 : items.length) !== null && _items$length !== void 0 ? _items$length : 0
327
- },
328
- "aria-live": "polite",
329
- "aria-atomic": "true"
330
- }))), jsx(LinkSearchList, {
331
- ariaLabelledBy: testIds.resultListTitle,
332
- ariaControls: "fabric.smartcard.linkpicker.suggested.results",
309
+ })))), jsx("div", _extends({
310
+ css: flexColumnStyles
311
+ }, fixListHeightProps), !error && jsx(LinkSearchList, {
333
312
  id: linkSearchListId,
334
313
  role: "listbox",
335
- items: items !== null && items !== void 0 ? items : [],
314
+ items: items,
336
315
  isLoading: isLoading,
337
316
  selectedIndex: selectedIndex,
338
317
  activeIndex: activeIndex,
339
318
  onSelect: handleSelected,
340
319
  onMouseEnter: handleMouseEnterResultItem,
341
- onMouseLeave: handleMouseLeaveResultItem
342
- }), error && ((_errorFallback = errorFallback === null || errorFallback === void 0 ? void 0 : errorFallback(error, retry)) !== null && _errorFallback !== void 0 ? _errorFallback : jsx(LinkSearchError, {
343
- testId: testIds.searchError,
344
- header: intl.formatMessage(messages.searchErrorHeader),
345
- description: jsx(FormattedMessage, _extends({}, messages.searchErrorDescription, {
346
- values: {
347
- a: function a(label) {
348
- return jsx(Button, {
349
- appearance: "link",
350
- spacing: "none",
351
- href: CONTACT_SUPPORT_LINK,
352
- target: "_blank",
353
- rel: "noopener noreferrer"
354
- }, label);
355
- }
356
- }
357
- }))
358
- })), noResults && jsx(LinkSearchNoResults, {
359
- testId: testIds.emptyResultPage,
360
- header: intl.formatMessage(messages.noResults),
361
- description: intl.formatMessage(messages.noResultsDescription)
362
- })), jsx(FormFooter, {
363
- align: "end"
364
- }, jsx(ButtonGroup, null, jsx(Button, {
365
- appearance: "default",
366
- onClick: onCancel,
367
- testId: testIds.cancelButton
368
- }, intl.formatMessage(messages.cancelButton)), jsx(Button, {
369
- type: "submit",
370
- appearance: "primary",
371
- testId: testIds.insertButton
372
- }, intl.formatMessage(insertButtonMsg)))));
320
+ onMouseLeave: handleMouseLeaveResultItem,
321
+ error: error,
322
+ hasSearchTerm: !!(queryState !== null && queryState !== void 0 && queryState.query.length)
323
+ }), error && ((_errorFallback = errorFallback === null || errorFallback === void 0 ? void 0 : errorFallback(error, retry)) !== null && _errorFallback !== void 0 ? _errorFallback : jsx(LinkSearchError, null)))), jsx(FormFooter, {
324
+ css: !queryState || !(plugins !== null && plugins !== void 0 && plugins.length) ? formFooterMargin : undefined,
325
+ isEditing: isEditing,
326
+ onCancel: onCancel
327
+ }));
373
328
  }
374
329
 
375
- export default LinkPicker;
330
+ export default withLinkPickerAnalyticsContext( /*#__PURE__*/memo(LinkPicker));
376
331
 
377
332
  function getScreenReaderText(items, selectedIndex, intl) {
378
333
  if (items.length && selectedIndex > -1) {
@@ -1,14 +1,50 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
- import React from 'react';
2
+
3
+ /** @jsx jsx */
4
+ import { jsx } from '@emotion/react';
5
+ import { useIntl, FormattedMessage, defineMessages } from 'react-intl-next';
6
+ import Button from '@atlaskit/button';
7
+ export var CONTACT_SUPPORT_LINK = 'https://support.atlassian.com/contact/';
8
+ export var messages = defineMessages({
9
+ searchErrorHeader: {
10
+ id: 'fabric.linkPicker.search.error.heading',
11
+ defaultMessage: 'We’re having trouble loading data.',
12
+ description: 'Heading message shown when a search throws an error'
13
+ },
14
+ searchErrorDescription: {
15
+ id: 'fabric.linkPicker.search.error.description',
16
+ defaultMessage: 'Refresh the page, or contact <a>Atlassian Support</a> if this keeps happening.',
17
+ description: 'Describes possible actions when search throws an error'
18
+ }
19
+ });
3
20
  import EmptyState from '@atlaskit/empty-state';
4
21
  import GenericErrorSVG from '../../../common/generic-error-svg';
22
+ export var testIds = {
23
+ searchError: 'link-search-error'
24
+ };
5
25
 
6
- var LinkSearchError = function LinkSearchError(props) {
7
- return /*#__PURE__*/React.createElement(EmptyState, _extends({}, props, {
26
+ var LinkSearchError = function LinkSearchError() {
27
+ var intl = useIntl();
28
+ return jsx(EmptyState, {
29
+ testId: testIds.searchError,
30
+ header: intl.formatMessage(messages.searchErrorHeader),
31
+ description: jsx(FormattedMessage, _extends({}, messages.searchErrorDescription, {
32
+ values: {
33
+ a: function a(label) {
34
+ return jsx(Button, {
35
+ appearance: "link",
36
+ spacing: "none",
37
+ href: CONTACT_SUPPORT_LINK,
38
+ target: "_blank",
39
+ rel: "noopener noreferrer"
40
+ }, label);
41
+ }
42
+ }
43
+ })),
8
44
  renderImage: function renderImage() {
9
- return /*#__PURE__*/React.createElement(GenericErrorSVG, null);
45
+ return jsx(GenericErrorSVG, null);
10
46
  }
11
- }));
47
+ });
12
48
  };
13
49
 
14
50
  export default LinkSearchError;
@@ -1,11 +1,45 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
+ var _excluded = ["onSelect", "onMouseEnter", "onMouseLeave", "items", "activeIndex", "selectedIndex", "isLoading", "ariaControls", "ariaLabelledBy", "role", "id", "hasSearchTerm"];
5
+
6
+ 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; }
7
+
8
+ 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; }
9
+
1
10
  /** @jsx jsx */
11
+ import { forwardRef, Fragment } from 'react';
2
12
  import { jsx } from '@emotion/react';
13
+ import { defineMessages, FormattedMessage } from 'react-intl-next';
3
14
  import Spinner from '@atlaskit/spinner';
15
+ import VisuallyHidden from '@atlaskit/visually-hidden';
4
16
  import LinkSearchListItem from '../list-item';
5
- import { listContainerStyles, spinnerContainerStyles, listStyles } from './styled';
6
- import { testIds } from '../';
7
-
8
- var LinkSearchList = function LinkSearchList(_ref) {
17
+ import { listContainerStyles, spinnerContainerStyles, listStyles, listTitleStyles } from './styled';
18
+ import LinkSearchNoResults, { testIds as noResultsTestIds } from './link-search-no-results';
19
+ export var messages = defineMessages({
20
+ titleRecentlyViewed: {
21
+ id: 'fabric.linkPicker.listTitle.recentlyViewed',
22
+ defaultMessage: 'Recently Viewed',
23
+ description: 'Describes type of items shown in the list for screen-reader users'
24
+ },
25
+ titleResults: {
26
+ id: 'fabric.linkPicker.listTitle.results',
27
+ defaultMessage: 'Results',
28
+ description: 'Describes type of items shown in the list for screen-reader users'
29
+ },
30
+ searchLinkResults: {
31
+ id: 'fabric.linkPicker.hyperlink.searchLinkResults',
32
+ defaultMessage: '{count, plural, =0 {no results} one {# result} other {# results}} found',
33
+ description: 'Announce search results for screen-reader users.'
34
+ }
35
+ });
36
+ export var testIds = _objectSpread(_objectSpread({}, noResultsTestIds), {}, {
37
+ resultListTitle: 'link-picker-list-title',
38
+ searchResultItem: 'link-search-list-item',
39
+ searchResultList: 'link-search-list',
40
+ searchResultLoadingIndicator: 'link-picker.results-loading-indicator'
41
+ });
42
+ var LinkSearchList = /*#__PURE__*/forwardRef(function (_ref, ref) {
9
43
  var onSelect = _ref.onSelect,
10
44
  onMouseEnter = _ref.onMouseEnter,
11
45
  onMouseLeave = _ref.onMouseLeave,
@@ -16,17 +50,37 @@ var LinkSearchList = function LinkSearchList(_ref) {
16
50
  ariaControls = _ref.ariaControls,
17
51
  ariaLabelledBy = _ref.ariaLabelledBy,
18
52
  role = _ref.role,
19
- id = _ref.id;
53
+ id = _ref.id,
54
+ hasSearchTerm = _ref.hasSearchTerm,
55
+ restProps = _objectWithoutProperties(_ref, _excluded);
56
+
20
57
  var itemsContent;
21
58
  var loadingContent;
59
+ var linkListTitle = hasSearchTerm ? messages.titleResults : messages.titleRecentlyViewed;
60
+
61
+ if ((items === null || items === void 0 ? void 0 : items.length) === 0) {
62
+ return jsx(LinkSearchNoResults, null);
63
+ }
22
64
 
23
65
  if (items && items.length > 0) {
24
- itemsContent = jsx("ul", {
66
+ itemsContent = jsx(Fragment, null, jsx("div", {
67
+ css: listTitleStyles,
68
+ id: testIds.resultListTitle,
69
+ "data-testid": testIds.resultListTitle
70
+ }, jsx(FormattedMessage, linkListTitle)), jsx(VisuallyHidden, {
71
+ id: "fabric.smartcard.linkpicker.suggested.results"
72
+ }, hasSearchTerm && jsx(FormattedMessage, _extends({}, messages.searchLinkResults, {
73
+ values: {
74
+ count: items.length
75
+ },
76
+ "aria-live": "polite",
77
+ "aria-atomic": "true"
78
+ }))), jsx("ul", {
25
79
  id: id,
26
80
  role: role,
27
81
  css: listStyles,
28
- "aria-controls": ariaControls,
29
- "aria-labelledby": ariaLabelledBy,
82
+ "aria-controls": "fabric.smartcard.linkpicker.suggested.results",
83
+ "aria-labelledby": testIds.resultListTitle,
30
84
  "data-testid": testIds.searchResultList
31
85
  }, items.map(function (item, index) {
32
86
  return jsx(LinkSearchListItem, {
@@ -40,7 +94,7 @@ var LinkSearchList = function LinkSearchList(_ref) {
40
94
  onSelect: onSelect,
41
95
  key: item.objectId
42
96
  });
43
- }));
97
+ })));
44
98
  }
45
99
 
46
100
  if (isLoading) {
@@ -52,9 +106,9 @@ var LinkSearchList = function LinkSearchList(_ref) {
52
106
  }));
53
107
  }
54
108
 
55
- return jsx("div", {
109
+ return jsx("div", _extends({
110
+ ref: ref,
56
111
  css: listContainerStyles
57
- }, itemsContent, loadingContent);
58
- };
59
-
112
+ }, restProps), itemsContent, loadingContent);
113
+ });
60
114
  export default LinkSearchList;
@@ -0,0 +1,37 @@
1
+ /** @jsx jsx */
2
+ import { jsx } from '@emotion/react';
3
+ import EmptyState from '@atlaskit/empty-state';
4
+ import { useIntl, defineMessages } from 'react-intl-next';
5
+ import NoResultsSVG from './no-results-svg';
6
+ import { emptyStateWrapperStyles } from './styled';
7
+ export var messages = defineMessages({
8
+ noResults: {
9
+ id: 'fabric.linkPicker.search.noResults.heading',
10
+ defaultMessage: 'We couldn’t find anything matching your search.',
11
+ description: 'Heading message shown when a search has no results'
12
+ },
13
+ noResultsDescription: {
14
+ id: 'fabric.linkPicker.search.noResults.description',
15
+ defaultMessage: 'Try again with a different term.',
16
+ description: 'Describes possible action when a search returns no results'
17
+ }
18
+ });
19
+ export var testIds = {
20
+ emptyResultPage: 'link-search-no-results'
21
+ };
22
+
23
+ var NoResults = function NoResults() {
24
+ var intl = useIntl();
25
+ return jsx("div", {
26
+ css: emptyStateWrapperStyles
27
+ }, jsx(EmptyState, {
28
+ testId: testIds.emptyResultPage,
29
+ header: intl.formatMessage(messages.noResults),
30
+ description: intl.formatMessage(messages.noResultsDescription),
31
+ renderImage: function renderImage() {
32
+ return jsx(NoResultsSVG, null);
33
+ }
34
+ }));
35
+ };
36
+
37
+ export default NoResults;
@@ -0,0 +1,6 @@
1
+ import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
2
+
3
+ var _templateObject;
4
+
5
+ import { css } from '@emotion/react';
6
+ export var emptyStateWrapperStyles = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n & p {\n margin: 0;\n }\n"])));
@@ -1,8 +1,14 @@
1
1
  import _taggedTemplateLiteral from "@babel/runtime/helpers/taggedTemplateLiteral";
2
2
 
3
- var _templateObject, _templateObject2, _templateObject3;
3
+ var _templateObject, _templateObject2, _templateObject3, _templateObject4;
4
4
 
5
- import { css } from '@emotion/react';
6
- export var listContainerStyles = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n padding-top: 0;\n"])));
7
- export var spinnerContainerStyles = css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n text-align: center;\n min-height: 80px;\n margin-top: 30px;\n"])));
8
- export var listStyles = css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n padding: 0;\n list-style: none;\n"])));
5
+ import { css } from '@emotion/react'; // AFP-2532 TODO: Fix automatic suppressions below
6
+ // eslint-disable-next-line @atlassian/tangerine/import/entry-points
7
+
8
+ import { typography } from '@atlaskit/theme';
9
+ import { gridSize as getGridSize } from '@atlaskit/theme/constants';
10
+ var gridSize = getGridSize();
11
+ export var listContainerStyles = css(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n padding-top: 0;\n min-height: 80px;\n margin-top: ", "px;\n margin-bottom: ", "px;\n flex-grow: 1;\n display: flex;\n flex-direction: column;\n"])), gridSize * 2, gridSize * 2);
12
+ export var spinnerContainerStyles = css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n text-align: center;\n min-height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-grow: 1;\n"])));
13
+ export var listStyles = css(_templateObject3 || (_templateObject3 = _taggedTemplateLiteral(["\n padding: 0;\n margin: 0;\n list-style: none;\n"])));
14
+ export var listTitleStyles = css(_templateObject4 || (_templateObject4 = _taggedTemplateLiteral(["\n ", "\n text-transform: uppercase;\n margin-top: 0;\n margin-bottom: ", "px;\n"])), typography.h100(), gridSize / 2);