@atlaskit/link-picker 1.6.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/cjs/analytics.codegen.js +28 -0
  3. package/dist/cjs/common/constants.js +10 -0
  4. package/dist/cjs/{ui/error-boundary-fallback → common}/generic-error-svg/index.js +0 -0
  5. package/dist/cjs/{ui/error-boundary-fallback → common}/generic-error-svg/styled.js +0 -0
  6. package/dist/cjs/services/use-plugins/index.js +32 -35
  7. package/dist/cjs/services/use-search-query/index.js +41 -0
  8. package/dist/cjs/ui/error-boundary-fallback/index.js +1 -1
  9. package/dist/cjs/ui/index.js +4 -4
  10. package/dist/cjs/ui/link-picker/index.js +68 -41
  11. package/dist/cjs/ui/link-picker/link-search-error/index.js +27 -0
  12. package/dist/cjs/ui/link-picker/messages.js +10 -0
  13. package/dist/cjs/ui/link-picker/url.js +0 -5
  14. package/dist/cjs/version.json +1 -1
  15. package/dist/es2019/analytics.codegen.js +20 -0
  16. package/dist/es2019/common/constants.js +2 -0
  17. package/dist/es2019/{ui/error-boundary-fallback → common}/generic-error-svg/index.js +0 -0
  18. package/dist/es2019/{ui/error-boundary-fallback → common}/generic-error-svg/styled.js +0 -0
  19. package/dist/es2019/services/use-plugins/index.js +28 -38
  20. package/dist/es2019/services/use-search-query/index.js +32 -0
  21. package/dist/es2019/ui/error-boundary-fallback/index.js +1 -1
  22. package/dist/es2019/ui/index.js +1 -2
  23. package/dist/es2019/ui/link-picker/index.js +59 -40
  24. package/dist/es2019/ui/link-picker/link-search-error/index.js +10 -0
  25. package/dist/es2019/ui/link-picker/messages.js +10 -0
  26. package/dist/es2019/ui/link-picker/url.js +0 -5
  27. package/dist/es2019/version.json +1 -1
  28. package/dist/esm/analytics.codegen.js +20 -0
  29. package/dist/esm/common/constants.js +2 -0
  30. package/dist/esm/{ui/error-boundary-fallback → common}/generic-error-svg/index.js +0 -0
  31. package/dist/esm/{ui/error-boundary-fallback → common}/generic-error-svg/styled.js +0 -0
  32. package/dist/esm/services/use-plugins/index.js +33 -35
  33. package/dist/esm/services/use-search-query/index.js +32 -0
  34. package/dist/esm/ui/error-boundary-fallback/index.js +1 -1
  35. package/dist/esm/ui/index.js +1 -2
  36. package/dist/esm/ui/link-picker/index.js +61 -40
  37. package/dist/esm/ui/link-picker/link-search-error/index.js +14 -0
  38. package/dist/esm/ui/link-picker/messages.js +10 -0
  39. package/dist/esm/ui/link-picker/url.js +0 -5
  40. package/dist/esm/version.json +1 -1
  41. package/dist/types/analytics.codegen.d.ts +20 -0
  42. package/dist/types/common/constants.d.ts +2 -0
  43. package/dist/types/{ui/error-boundary-fallback → common}/generic-error-svg/index.d.ts +0 -0
  44. package/dist/types/{ui/error-boundary-fallback → common}/generic-error-svg/styled.d.ts +0 -0
  45. package/dist/types/index.d.ts +1 -1
  46. package/dist/types/services/use-plugins/index.d.ts +6 -5
  47. package/dist/types/services/use-search-query/index.d.ts +3 -0
  48. package/dist/types/ui/link-picker/index.d.ts +2 -0
  49. package/dist/types/ui/link-picker/link-search-error/index.d.ts +4 -0
  50. package/dist/types/ui/link-picker/messages.d.ts +10 -0
  51. package/dist/types/ui/types.d.ts +5 -2
  52. package/package.json +12 -6
  53. package/report.api.md +21 -13
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @atlaskit/link-picker
2
2
 
3
+ ## 1.7.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`e900714203d`](https://bitbucket.org/atlassian/atlassian-frontend/commits/e900714203d) - Add "form submitted" analytics event.
8
+
9
+ ## 1.7.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [`d0feee9b4ad`](https://bitbucket.org/atlassian/atlassian-frontend/commits/d0feee9b4ad) - [ux] Add a UI error message to display when the link picker plugin resolve throws an error
14
+
15
+ ## 1.6.1
16
+
17
+ ### Patch Changes
18
+
19
+ - [`e3f36b94557`](https://bitbucket.org/atlassian/atlassian-frontend/commits/e3f36b94557) - Inlines svg assets directly into the UI
20
+
3
21
  ## 1.6.0
4
22
 
5
23
  ### Minor Changes
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ /**
9
+ * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
10
+ *
11
+ * Generates analytics utilities from the package analytics spec yaml
12
+ *
13
+ * @codegen <<SignedSource::0cc1b4d9c22b31491ded3e581114ab2c>>
14
+ * @codegenCommand yarn workspace @atlaskit/link-picker run codegen-analytics
15
+ */
16
+ function createEventPayload(eventKey, attributes) {
17
+ var event = eventKey.split('.');
18
+ return {
19
+ eventType: 'ui',
20
+ actionSubject: event[0],
21
+ action: event[1],
22
+ actionSubjectId: event[2],
23
+ attributes: attributes
24
+ };
25
+ }
26
+
27
+ var _default = createEventPayload;
28
+ exports.default = _default;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.COMPONENT_NAME = exports.ANALYTICS_CHANNEL = void 0;
7
+ var ANALYTICS_CHANNEL = 'media';
8
+ exports.ANALYTICS_CHANNEL = ANALYTICS_CHANNEL;
9
+ var COMPONENT_NAME = 'LinkPicker';
10
+ exports.COMPONENT_NAME = COMPONENT_NAME;
@@ -19,8 +19,6 @@ var _react = require("react");
19
19
 
20
20
  var _linkPicker = require("../../ui/link-picker");
21
21
 
22
- var _url = require("../../ui/link-picker/url");
23
-
24
22
  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; }
25
23
 
26
24
  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) { (0, _defineProperty2.default)(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; }
@@ -29,56 +27,46 @@ function reducer(state, payload) {
29
27
  return _objectSpread(_objectSpread({}, state), payload);
30
28
  }
31
29
 
32
- function usePlugins(state, plugins) {
30
+ function usePlugins(state, activeTab, plugins) {
31
+ var _useState = (0, _react.useState)(0),
32
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
33
+ retries = _useState2[0],
34
+ setRetries = _useState2[1];
35
+
33
36
  var _useReducer = (0, _react.useReducer)(reducer, {
34
- items: [],
37
+ items: null,
38
+ error: null,
35
39
  isLoading: false
36
40
  }),
37
41
  _useReducer2 = (0, _slicedToArray2.default)(_useReducer, 2),
38
42
  pluginState = _useReducer2[0],
39
43
  dispatch = _useReducer2[1];
40
44
 
41
- var url = state.url,
42
- selectedIndex = state.selectedIndex;
43
45
  var items = pluginState.items,
44
- isLoading = pluginState.isLoading;
45
- var activePlugin = !plugins || plugins.length === 0 ? null : plugins[state.activeTab];
46
+ isLoading = pluginState.isLoading,
47
+ error = pluginState.error;
46
48
  var queryVersion = (0, _react.useRef)(0);
47
- var pluginRef = (0, _react.useRef)(activePlugin);
48
- var selectedItem = items[selectedIndex];
49
- var isSelectedItem = (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.url) === url;
49
+ var activePlugin = plugins === null || plugins === void 0 ? void 0 : plugins[activeTab];
50
50
  (0, _react.useEffect)(function () {
51
51
  if (!activePlugin) {
52
52
  return;
53
53
  }
54
54
 
55
- if (isSelectedItem) {
56
- return;
57
- }
58
-
59
- if ((0, _url.isSafeUrl)(url) && url.length) {
55
+ if (!state) {
60
56
  dispatch({
61
- items: [],
62
- isLoading: false
57
+ items: null,
58
+ isLoading: false,
59
+ error: null
63
60
  });
64
61
  return;
65
62
  }
66
63
 
67
- var updates = activePlugin.resolve({
68
- query: url
64
+ var updates = activePlugin.resolve(state);
65
+ dispatch({
66
+ items: null,
67
+ isLoading: true,
68
+ error: null
69
69
  });
70
-
71
- if (pluginRef.current !== activePlugin) {
72
- dispatch({
73
- items: [],
74
- isLoading: true
75
- });
76
- } else {
77
- dispatch({
78
- isLoading: true
79
- });
80
- }
81
-
82
70
  var newQuery = ++queryVersion.current;
83
71
 
84
72
  var updateResults = /*#__PURE__*/function () {
@@ -156,6 +144,8 @@ function usePlugins(state, plugins) {
156
144
  _context.prev = 25;
157
145
  _context.t0 = _context["catch"](0);
158
146
  dispatch({
147
+ error: _context.t0,
148
+ items: null,
159
149
  isLoading: false
160
150
  });
161
151
 
@@ -173,7 +163,7 @@ function usePlugins(state, plugins) {
173
163
  }();
174
164
 
175
165
  updateResults();
176
- }, [activePlugin, queryVersion, url, isSelectedItem]);
166
+ }, [activePlugin, queryVersion, state, retries]);
177
167
  var tabs = (0, _react.useMemo)(function () {
178
168
  if (!plugins || plugins.length <= 1) {
179
169
  return [];
@@ -187,12 +177,19 @@ function usePlugins(state, plugins) {
187
177
  };
188
178
  });
189
179
  }, [plugins]);
180
+ var handleRetry = (0, _react.useCallback)(function () {
181
+ setRetries(function (prev) {
182
+ return ++prev;
183
+ });
184
+ }, []);
190
185
  return {
191
186
  tabs: tabs,
192
187
  items: items,
193
188
  isLoading: isLoading,
194
- isSelectedItem: isSelectedItem,
195
- isActivePlugin: !!activePlugin
189
+ isActivePlugin: !!activePlugin,
190
+ error: error,
191
+ retry: handleRetry,
192
+ errorFallback: activePlugin === null || activePlugin === void 0 ? void 0 : activePlugin.errorFallback
196
193
  };
197
194
  }
198
195
 
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useSearchQuery = useSearchQuery;
7
+
8
+ var _react = require("react");
9
+
10
+ var _url = require("../../ui/link-picker/url");
11
+
12
+ function useSearchQuery(state) {
13
+ var _queryState$current;
14
+
15
+ var queryState = (0, _react.useRef)(null);
16
+ /*
17
+ * When state contains a valid url AND is NOT selected from results
18
+ * queryState should be null to clear the items in plugin state
19
+ */
20
+
21
+ if ((0, _url.isSafeUrl)(state.url) && state.selectedIndex === -1) {
22
+ queryState.current = null;
23
+ }
24
+ /*
25
+ * When state contains a search term e.g. Not a valid url return a query
26
+ */
27
+
28
+
29
+ if (((_queryState$current = queryState.current) === null || _queryState$current === void 0 ? void 0 : _queryState$current.query) !== state.url && !(0, _url.isSafeUrl)(state.url)) {
30
+ queryState.current = {
31
+ query: state.url
32
+ };
33
+ }
34
+ /*
35
+ * When state contains a valid url and is selected from the list
36
+ * return current state to prevent triger a new plugin search
37
+ */
38
+
39
+
40
+ return queryState.current;
41
+ }
@@ -13,7 +13,7 @@ var _emptyState = _interopRequireDefault(require("@atlaskit/empty-state"));
13
13
 
14
14
  var _reactIntlNext = require("react-intl-next");
15
15
 
16
- var _genericErrorSvg = _interopRequireDefault(require("./generic-error-svg"));
16
+ var _genericErrorSvg = _interopRequireDefault(require("../../common/generic-error-svg"));
17
17
 
18
18
  var _styled = require("../link-picker/styled");
19
19
 
@@ -15,6 +15,8 @@ var _analyticsNext = require("@atlaskit/analytics-next");
15
15
 
16
16
  var _reactLooselyLazy = require("react-loosely-lazy");
17
17
 
18
+ var _constants = require("../common/constants");
19
+
18
20
  var _version = require("../version.json");
19
21
 
20
22
  var _errorBoundaryFallback = require("./error-boundary-fallback");
@@ -25,12 +27,10 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
25
27
 
26
28
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || (0, _typeof2.default)(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
27
29
 
28
- var COMPONENT_NAME = 'LinkPicker';
29
- var ANALYTICS_CHANNEL = 'media';
30
30
  var PACKAGE_DATA = {
31
31
  packageName: _version.name,
32
32
  packageVersion: _version.version,
33
- componentName: COMPONENT_NAME
33
+ componentName: _constants.COMPONENT_NAME
34
34
  };
35
35
  var LazyLinkPicker = (0, _reactLooselyLazy.lazyForPaint)(function () {
36
36
  return Promise.resolve().then(function () {
@@ -39,7 +39,7 @@ var LazyLinkPicker = (0, _reactLooselyLazy.lazyForPaint)(function () {
39
39
  });
40
40
  var ComposedLinkPicker = /*#__PURE__*/(0, _react.memo)(function (props) {
41
41
  return /*#__PURE__*/_react.default.createElement(_analyticsNext.AnalyticsErrorBoundary, {
42
- channel: ANALYTICS_CHANNEL,
42
+ channel: _constants.ANALYTICS_CHANNEL,
43
43
  data: PACKAGE_DATA,
44
44
  ErrorComponent: _errorBoundaryFallback.ErrorBoundaryFallback
45
45
  }, /*#__PURE__*/_react.default.createElement(_reactLooselyLazy.LazySuspense, {
@@ -7,7 +7,7 @@ var _typeof = require("@babel/runtime/helpers/typeof");
7
7
  Object.defineProperty(exports, "__esModule", {
8
8
  value: true
9
9
  });
10
- exports.testIds = exports.default = exports.RECENT_SEARCH_LIST_SIZE = void 0;
10
+ exports.testIds = exports.default = exports.RECENT_SEARCH_LIST_SIZE = exports.CONTACT_SUPPORT_LINK = void 0;
11
11
 
12
12
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
13
13
 
@@ -21,6 +21,8 @@ var _react2 = require("@emotion/react");
21
21
 
22
22
  var _reactIntlNext = require("react-intl-next");
23
23
 
24
+ var _analyticsNext = require("@atlaskit/analytics-next");
25
+
24
26
  var _button = _interopRequireWildcard(require("@atlaskit/button"));
25
27
 
26
28
  var _form = require("@atlaskit/form");
@@ -31,6 +33,14 @@ var _tabs = _interopRequireWildcard(require("@atlaskit/tabs"));
31
33
 
32
34
  var _visuallyHidden = _interopRequireDefault(require("@atlaskit/visually-hidden"));
33
35
 
36
+ var _analytics = _interopRequireDefault(require("../../analytics.codegen"));
37
+
38
+ var _constants = require("../../common/constants");
39
+
40
+ var _usePlugins2 = require("../../services/use-plugins");
41
+
42
+ var _useSearchQuery = require("../../services/use-search-query");
43
+
34
44
  var _messages = require("./messages");
35
45
 
36
46
  var _textInput = _interopRequireDefault(require("./text-input"));
@@ -43,13 +53,13 @@ var _styled = require("./styled");
43
53
 
44
54
  var _browser = require("./browser");
45
55
 
46
- var _transformTimeStamp = require("./transformTimeStamp");
47
-
48
56
  var _announcer = _interopRequireDefault(require("./announcer"));
49
57
 
50
58
  var _linkSearchNoResults = _interopRequireDefault(require("./link-search-no-results"));
51
59
 
52
- var _usePlugins2 = require("../../services/use-plugins");
60
+ var _transformTimeStamp = require("./transformTimeStamp");
61
+
62
+ var _linkSearchError = _interopRequireDefault(require("./link-search-error"));
53
63
 
54
64
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
55
65
 
@@ -61,6 +71,8 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
61
71
 
62
72
  var RECENT_SEARCH_LIST_SIZE = 5;
63
73
  exports.RECENT_SEARCH_LIST_SIZE = RECENT_SEARCH_LIST_SIZE;
74
+ var CONTACT_SUPPORT_LINK = 'https://support.atlassian.com/contact/';
75
+ exports.CONTACT_SUPPORT_LINK = CONTACT_SUPPORT_LINK;
64
76
  var testIds = {
65
77
  linkPicker: 'link-picker',
66
78
  urlInputField: 'link-url',
@@ -76,7 +88,8 @@ var testIds = {
76
88
  searchResultLoadingIndicator: 'link-picker.results-loading-indicator',
77
89
  urlError: 'link-error',
78
90
  tabList: 'link-picker-tabs',
79
- tabItem: 'link-picker-tab'
91
+ tabItem: 'link-picker-tab',
92
+ searchError: 'link-search-error'
80
93
  };
81
94
  exports.testIds = testIds;
82
95
  var initState = {
@@ -100,6 +113,8 @@ function reducer(state, payload) {
100
113
  }
101
114
 
102
115
  function LinkPicker(_ref) {
116
+ var _queryState$query, _items$length, _errorFallback;
117
+
103
118
  var onSubmit = _ref.onSubmit,
104
119
  onCancel = _ref.onCancel,
105
120
  onContentResize = _ref.onContentResize,
@@ -107,6 +122,9 @@ function LinkPicker(_ref) {
107
122
  initUrl = _ref.url,
108
123
  initDisplayText = _ref.displayText;
109
124
 
125
+ var _useAnalyticsEvents = (0, _analyticsNext.useAnalyticsEvents)(),
126
+ createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
127
+
110
128
  var _useReducer = (0, _react.useReducer)(reducer, _objectSpread(_objectSpread({}, initState), {}, {
111
129
  url: (0, _url2.normalizeUrl)(initUrl) || '',
112
130
  displayText: initDisplayText || ''
@@ -119,17 +137,23 @@ function LinkPicker(_ref) {
119
137
  selectedIndex = state.selectedIndex,
120
138
  url = state.url,
121
139
  displayText = state.displayText,
122
- invalidUrl = state.invalidUrl;
123
- var isEditing = !!initUrl;
140
+ invalidUrl = state.invalidUrl,
141
+ activeTab = state.activeTab;
124
142
  var intl = (0, _reactIntlNext.useIntl)();
143
+ var queryState = (0, _useSearchQuery.useSearchQuery)(state);
125
144
 
126
- var _usePlugins = (0, _usePlugins2.usePlugins)(state, plugins),
145
+ var _usePlugins = (0, _usePlugins2.usePlugins)(queryState, activeTab, plugins),
127
146
  items = _usePlugins.items,
128
147
  isLoading = _usePlugins.isLoading,
129
- isSelectedItem = _usePlugins.isSelectedItem,
130
148
  isActivePlugin = _usePlugins.isActivePlugin,
131
- tabs = _usePlugins.tabs;
149
+ tabs = _usePlugins.tabs,
150
+ error = _usePlugins.error,
151
+ retry = _usePlugins.retry,
152
+ errorFallback = _usePlugins.errorFallback;
132
153
 
154
+ var isEditing = !!initUrl;
155
+ var selectedItem = items === null || items === void 0 ? void 0 : items[selectedIndex];
156
+ var isSelectedItem = (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.url) === url;
133
157
  (0, _react.useLayoutEffect)(function () {
134
158
  if (onContentResize) {
135
159
  onContentResize();
@@ -183,15 +207,15 @@ function LinkPicker(_ref) {
183
207
  dispatch((0, _defineProperty2.default)({}, field, ''));
184
208
  }, []);
185
209
  var handleMouseEnterResultItem = (0, _react.useCallback)(function (objectId) {
186
- var index = findIndex(items, function (item) {
210
+ var index = items === null || items === void 0 ? void 0 : items.findIndex(function (item) {
187
211
  return item.objectId === objectId;
188
212
  });
189
213
  dispatch({
190
- activeIndex: index
214
+ activeIndex: index !== null && index !== void 0 ? index : -1
191
215
  });
192
216
  }, [items]);
193
217
  var handleMouseLeaveResultItem = (0, _react.useCallback)(function (objectId) {
194
- var index = findIndex(items, function (item) {
218
+ var index = items === null || items === void 0 ? void 0 : items.findIndex(function (item) {
195
219
  return item.objectId === objectId;
196
220
  }); // This is to avoid updating index that was set by other mouseenter event
197
221
 
@@ -202,6 +226,8 @@ function LinkPicker(_ref) {
202
226
  }
203
227
  }, [activeIndex, items]);
204
228
  var handleInsert = (0, _react.useCallback)(function (url, title, inputType) {
229
+ var event = createAnalyticsEvent((0, _analytics.default)('form.submitted.linkPicker', {}));
230
+ event.fire(_constants.ANALYTICS_CHANNEL);
205
231
  onSubmit(_objectSpread({
206
232
  url: url,
207
233
  displayText: displayText || null,
@@ -212,9 +238,9 @@ function LinkPicker(_ref) {
212
238
  }, inputType === 'manual' ? {
213
239
  rawUrl: state.url
214
240
  } : {}));
215
- }, [displayText, onSubmit, state.url]);
241
+ }, [displayText, onSubmit, state.url, createAnalyticsEvent]);
216
242
  var handleSelected = (0, _react.useCallback)(function (objectId) {
217
- var selectedItem = items.find(function (item) {
243
+ var selectedItem = items === null || items === void 0 ? void 0 : items.find(function (item) {
218
244
  return item.objectId === objectId;
219
245
  });
220
246
 
@@ -225,9 +251,7 @@ function LinkPicker(_ref) {
225
251
  }
226
252
  }, [handleInsert, items]);
227
253
  var handleSubmit = (0, _react.useCallback)(function () {
228
- var selectedItem = items[selectedIndex];
229
-
230
- if (isSelectedItem) {
254
+ if (isSelectedItem && selectedItem) {
231
255
  return handleInsert(selectedItem.url, selectedItem.name, 'typeAhead');
232
256
  }
233
257
 
@@ -240,18 +264,18 @@ function LinkPicker(_ref) {
240
264
  return dispatch({
241
265
  invalidUrl: true
242
266
  });
243
- }, [handleInsert, isSelectedItem, items, selectedIndex, url]);
267
+ }, [handleInsert, isSelectedItem, selectedItem, url]);
244
268
  var linkPlaceHolder = isActivePlugin ? _messages.messages.placeholder : _messages.messages.linkPlaceholder;
245
- var linkListTitle = url ? _messages.messages.titleResults : _messages.messages.titleRecentlyViewed;
269
+ 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.messages.titleResults : _messages.messages.titleRecentlyViewed;
246
270
  var insertButtonMsg = isEditing ? _messages.messages.saveButton : _messages.messages.insertButton;
247
- var noResults = isActivePlugin && !isLoading && !items.length && !(0, _url2.isSafeUrl)(url);
271
+ var noResults = (items === null || items === void 0 ? void 0 : items.length) === 0 && !error;
248
272
  var screenReaderDescriptionId = 'search-recent-links-field-description';
249
273
  var linkSearchListId = 'link-picker-search-list';
250
274
  var ariaActiveDescendant = selectedIndex > -1 ? "link-search-list-item-".concat(selectedIndex) : ''; // Added workaround with a screen reader Announcer specifically for VoiceOver + Safari
251
275
  // as the Aria design pattern for combobox does not work in this case
252
276
  // for details: https://a11y-internal.atlassian.net/browse/AK-740
253
277
 
254
- var screenReaderText = _browser.browser.safari && getScreenReaderText(items, selectedIndex, intl);
278
+ var screenReaderText = _browser.browser.safari && getScreenReaderText(items !== null && items !== void 0 ? items : [], selectedIndex, intl);
255
279
  var searchIcon = isActivePlugin && (0, _react2.jsx)("span", {
256
280
  css: _styled.searchIconStyles,
257
281
  "data-testid": testIds.searchIcon
@@ -303,7 +327,7 @@ function LinkPicker(_ref) {
303
327
  onSubmit: handleSubmit,
304
328
  onKeyDown: handleKeyDown,
305
329
  onChange: handleChangeText
306
- }), tabs.length > 0 && (0, _react2.jsx)("div", {
330
+ }), queryState && (0, _react2.jsx)(_react.Fragment, null, tabs.length > 0 && (0, _react2.jsx)("div", {
307
331
  css: _styled.tabsWrapperStyles
308
332
  }, (0, _react2.jsx)(_tabs.default, {
309
333
  id: testIds.tabList,
@@ -321,7 +345,7 @@ function LinkPicker(_ref) {
321
345
  key: tab.tabTitle,
322
346
  testId: testIds.tabItem
323
347
  }, tab.tabTitle);
324
- })))), !!items.length && (0, _react2.jsx)("div", {
348
+ })))), !!(items !== null && items !== void 0 && items.length) && (0, _react2.jsx)("div", {
325
349
  css: _styled.listTitleStyles,
326
350
  id: testIds.resultListTitle,
327
351
  "data-testid": testIds.resultListTitle
@@ -329,7 +353,7 @@ function LinkPicker(_ref) {
329
353
  id: "fabric.smartcard.linkpicker.suggested.results"
330
354
  }, url && (0, _react2.jsx)(_reactIntlNext.FormattedMessage, (0, _extends2.default)({}, _messages.messages.searchLinkResults, {
331
355
  values: {
332
- count: items.length
356
+ count: (_items$length = items === null || items === void 0 ? void 0 : items.length) !== null && _items$length !== void 0 ? _items$length : 0
333
357
  },
334
358
  "aria-live": "polite",
335
359
  "aria-atomic": "true"
@@ -338,18 +362,34 @@ function LinkPicker(_ref) {
338
362
  ariaControls: "fabric.smartcard.linkpicker.suggested.results",
339
363
  id: linkSearchListId,
340
364
  role: "listbox",
341
- items: items,
365
+ items: items !== null && items !== void 0 ? items : [],
342
366
  isLoading: isLoading,
343
367
  selectedIndex: selectedIndex,
344
368
  activeIndex: activeIndex,
345
369
  onSelect: handleSelected,
346
370
  onMouseEnter: handleMouseEnterResultItem,
347
371
  onMouseLeave: handleMouseLeaveResultItem
348
- }), noResults && (0, _react2.jsx)(_linkSearchNoResults.default, {
372
+ }), error && ((_errorFallback = errorFallback === null || errorFallback === void 0 ? void 0 : errorFallback(error, retry)) !== null && _errorFallback !== void 0 ? _errorFallback : (0, _react2.jsx)(_linkSearchError.default, {
373
+ testId: testIds.searchError,
374
+ header: intl.formatMessage(_messages.messages.searchErrorHeader),
375
+ description: (0, _react2.jsx)(_reactIntlNext.FormattedMessage, (0, _extends2.default)({}, _messages.messages.searchErrorDescription, {
376
+ values: {
377
+ a: function a(label) {
378
+ return (0, _react2.jsx)(_button.default, {
379
+ appearance: "link",
380
+ spacing: "none",
381
+ href: CONTACT_SUPPORT_LINK,
382
+ target: "_blank",
383
+ rel: "noopener noreferrer"
384
+ }, label);
385
+ }
386
+ }
387
+ }))
388
+ })), noResults && (0, _react2.jsx)(_linkSearchNoResults.default, {
349
389
  testId: testIds.emptyResultPage,
350
390
  header: intl.formatMessage(_messages.messages.noResults),
351
391
  description: intl.formatMessage(_messages.messages.noResultsDescription)
352
- }), (0, _react2.jsx)(_form.FormFooter, {
392
+ })), (0, _react2.jsx)(_form.FormFooter, {
353
393
  align: "end"
354
394
  }, (0, _react2.jsx)(_button.ButtonGroup, null, (0, _react2.jsx)(_button.default, {
355
395
  appearance: "default",
@@ -377,17 +417,4 @@ function getScreenReaderText(items, selectedIndex, intl) {
377
417
  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(' ');
378
418
  return [name, container, formattedDate].filter(Boolean).join(', ');
379
419
  }
380
- }
381
-
382
- function findIndex(array, predicate) {
383
- var index = -1;
384
- array.some(function (item, i) {
385
- if (predicate(item)) {
386
- index = i;
387
- return true;
388
- }
389
-
390
- return false;
391
- });
392
- return index;
393
420
  }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+
10
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
11
+
12
+ var _react = _interopRequireDefault(require("react"));
13
+
14
+ var _emptyState = _interopRequireDefault(require("@atlaskit/empty-state"));
15
+
16
+ var _genericErrorSvg = _interopRequireDefault(require("../../../common/generic-error-svg"));
17
+
18
+ var LinkSearchError = function LinkSearchError(props) {
19
+ return /*#__PURE__*/_react.default.createElement(_emptyState.default, (0, _extends2.default)({}, props, {
20
+ renderImage: function renderImage() {
21
+ return /*#__PURE__*/_react.default.createElement(_genericErrorSvg.default, null);
22
+ }
23
+ }));
24
+ };
25
+
26
+ var _default = LinkSearchError;
27
+ exports.default = _default;
@@ -112,6 +112,16 @@ var messages = (0, _reactIntlNext.defineMessages)({
112
112
  id: 'fabric.linkPicker.button.save',
113
113
  defaultMessage: 'Save',
114
114
  description: 'Button to save edited link'
115
+ },
116
+ searchErrorHeader: {
117
+ id: 'fabric.linkPicker.search.error.heading',
118
+ defaultMessage: 'We’re having trouble loading data.',
119
+ description: 'Heading message shown when a search throws an error'
120
+ },
121
+ searchErrorDescription: {
122
+ id: 'fabric.linkPicker.search.error.description',
123
+ defaultMessage: 'Refresh the page, or contact <a>Atlassian Support</a> if this keeps happening.',
124
+ description: 'Describes possible actions when search throws an error'
115
125
  }
116
126
  });
117
127
  exports.messages = messages;
@@ -75,11 +75,6 @@ var linkifyMatch = function linkifyMatch(text) {
75
75
 
76
76
  var isSafeUrl = function isSafeUrl(url) {
77
77
  var urlTrimmed = url.trim();
78
-
79
- if (urlTrimmed.length === 0) {
80
- return true;
81
- }
82
-
83
78
  return whitelistedURLPatterns.some(function (p) {
84
79
  return p.test(urlTrimmed);
85
80
  });
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/link-picker",
3
- "version": "1.6.0",
3
+ "version": "1.7.1",
4
4
  "sideEffects": false
5
5
  }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
+ *
4
+ * Generates analytics utilities from the package analytics spec yaml
5
+ *
6
+ * @codegen <<SignedSource::0cc1b4d9c22b31491ded3e581114ab2c>>
7
+ * @codegenCommand yarn workspace @atlaskit/link-picker run codegen-analytics
8
+ */
9
+ function createEventPayload(eventKey, attributes) {
10
+ const event = eventKey.split('.');
11
+ return {
12
+ eventType: 'ui',
13
+ actionSubject: event[0],
14
+ action: event[1],
15
+ actionSubjectId: event[2],
16
+ attributes: attributes
17
+ };
18
+ }
19
+
20
+ export default createEventPayload;
@@ -0,0 +1,2 @@
1
+ export const ANALYTICS_CHANNEL = 'media';
2
+ export const COMPONENT_NAME = 'LinkPicker';