@atlaskit/link-picker 1.4.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cjs/services/use-plugins/index.js +201 -0
  3. package/dist/cjs/ui/link-picker/index.js +314 -599
  4. package/dist/cjs/ui/link-picker/link-search-list/index.js +54 -82
  5. package/dist/cjs/ui/link-picker/list-item/index.js +5 -3
  6. package/dist/cjs/ui/link-picker/styled.js +5 -3
  7. package/dist/cjs/ui/link-picker/text-input/index.js +6 -4
  8. package/dist/cjs/version.json +1 -1
  9. package/dist/es2019/services/use-plugins/index.js +122 -0
  10. package/dist/es2019/ui/link-picker/index.js +294 -467
  11. package/dist/es2019/ui/link-picker/link-search-list/index.js +49 -50
  12. package/dist/es2019/ui/link-picker/list-item/index.js +4 -3
  13. package/dist/es2019/ui/link-picker/styled.js +4 -0
  14. package/dist/es2019/ui/link-picker/text-input/index.js +5 -4
  15. package/dist/es2019/version.json +1 -1
  16. package/dist/esm/services/use-plugins/index.js +187 -0
  17. package/dist/esm/ui/link-picker/index.js +304 -601
  18. package/dist/esm/ui/link-picker/link-search-list/index.js +51 -79
  19. package/dist/esm/ui/link-picker/list-item/index.js +4 -3
  20. package/dist/esm/ui/link-picker/styled.js +3 -2
  21. package/dist/esm/ui/link-picker/text-input/index.js +5 -4
  22. package/dist/esm/version.json +1 -1
  23. package/dist/types/services/use-plugins/index.d.ts +12 -0
  24. package/dist/types/ui/link-picker/index.d.ts +26 -13
  25. package/dist/types/ui/link-picker/link-search-list/index.d.ts +3 -5
  26. package/dist/types/ui/link-picker/styled.d.ts +1 -0
  27. package/dist/types/ui/link-picker/text-input/index.d.ts +1 -1
  28. package/package.json +5 -3
@@ -1,637 +1,346 @@
1
- import _typeof from "@babel/runtime/helpers/typeof";
2
- import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
3
- import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
4
- import _createClass from "@babel/runtime/helpers/createClass";
5
- import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
6
- import _inherits from "@babel/runtime/helpers/inherits";
7
- import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
8
- import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
9
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
10
4
 
11
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; }
12
6
 
13
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; }
14
8
 
15
- import _regeneratorRuntime from "@babel/runtime/regenerator";
16
-
17
- 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); }; }
18
-
19
- 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; } }
20
-
21
9
  /** @jsx jsx */
22
- import { PureComponent } from 'react';
10
+ import { useCallback, useLayoutEffect, useReducer } from 'react';
23
11
  import { jsx } from '@emotion/react';
24
- import { injectIntl } from 'react-intl-next';
12
+ import { useIntl, FormattedMessage } from 'react-intl-next';
13
+ import Button, { ButtonGroup } from '@atlaskit/button';
14
+ import { FormFooter } from '@atlaskit/form';
15
+ import EditorSearchIcon from '@atlaskit/icon/glyph/editor/search';
25
16
  import Tabs, { Tab, TabList } from '@atlaskit/tabs';
17
+ import VisuallyHidden from '@atlaskit/visually-hidden';
26
18
  import { messages } from './messages';
27
19
  import PanelTextInput from './text-input';
28
20
  import LinkSearchList from './link-search-list';
29
21
  import { normalizeUrl, isSafeUrl } from './url';
30
- import { rootContainerStyles, searchIconStyles, listTitleStyles } from './styled';
22
+ import { rootContainerStyles, searchIconStyles, listTitleStyles, tabsWrapperStyles } from './styled';
31
23
  import { browser } from './browser';
32
24
  import { transformTimeStamp } from './transformTimeStamp';
33
- import Announcer from './/announcer';
34
- import Button, { ButtonGroup } from '@atlaskit/button';
35
- import { FormFooter } from '@atlaskit/form';
36
- import EditorSearchIcon from '@atlaskit/icon/glyph/editor/search';
37
- import VisuallyHidden from '@atlaskit/visually-hidden';
25
+ import Announcer from './announcer';
38
26
  import LinkSearchNoResults from './link-search-no-results';
27
+ import { usePlugins } from '../../services/use-plugins';
39
28
  export var RECENT_SEARCH_LIST_SIZE = 5;
29
+ export var testIds = {
30
+ linkPicker: 'link-picker',
31
+ urlInputField: 'link-url',
32
+ textInputField: 'link-text',
33
+ searchIcon: 'link-picker-search-icon',
34
+ insertButton: 'link-picker-insert-button',
35
+ cancelButton: 'link-picker-cancel-button',
36
+ clearUrlButton: 'clear-text',
37
+ resultListTitle: 'link-picker-list-title',
38
+ emptyResultPage: 'link-search-no-results',
39
+ searchResultList: 'link-search-list',
40
+ searchResultItem: 'link-search-list-item',
41
+ searchResultLoadingIndicator: 'link-picker.results-loading-indicator',
42
+ urlError: 'link-error',
43
+ tabList: 'link-picker-tabs',
44
+ tabItem: 'link-picker-tab'
45
+ };
46
+ var initState = {
47
+ url: '',
48
+ displayText: '',
49
+ activeIndex: -1,
50
+ selectedIndex: -1,
51
+ invalidUrl: false,
52
+ activeTab: 0
53
+ };
54
+
55
+ function reducer(state, payload) {
56
+ if (payload.url && state.url !== payload.url) {
57
+ return _objectSpread(_objectSpread({}, state), {}, {
58
+ invalidUrl: false,
59
+ selectedIndex: isSafeUrl(payload.url) && payload.url.length ? -1 : state.selectedIndex
60
+ }, payload);
61
+ }
40
62
 
41
- var LinkPicker = /*#__PURE__*/function (_PureComponent) {
42
- _inherits(LinkPicker, _PureComponent);
43
-
44
- var _super = _createSuper(LinkPicker);
45
-
46
- function LinkPicker(props) {
47
- var _this;
48
-
49
- _classCallCheck(this, LinkPicker);
50
-
51
- _this = _super.call(this, props);
52
-
53
- _defineProperty(_assertThisInitialized(_this), "queryVersion", 0);
54
-
55
- _defineProperty(_assertThisInitialized(_this), "updateInput", /*#__PURE__*/function () {
56
- var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(input) {
57
- return _regeneratorRuntime.wrap(function _callee$(_context) {
58
- while (1) {
59
- switch (_context.prev = _context.next) {
60
- case 0:
61
- if (!(input.length && isSafeUrl(input))) {
62
- _context.next = 2;
63
- break;
64
- }
65
-
66
- return _context.abrupt("return", _this.setState({
67
- url: input,
68
- selectedIndex: -1,
69
- items: [],
70
- isLoading: false,
71
- invalidUrl: null
72
- }));
73
-
74
- case 2:
75
- return _context.abrupt("return", _this.setState({
76
- url: input,
77
- // Unset selection on any input change
78
- selectedIndex: -1,
79
- invalidUrl: null
80
- }, function () {
81
- _this.updateResults();
82
- }));
83
-
84
- case 3:
85
- case "end":
86
- return _context.stop();
87
- }
88
- }
89
- }, _callee);
90
- }));
91
-
92
- return function (_x) {
93
- return _ref.apply(this, arguments);
94
- };
95
- }());
96
-
97
- _defineProperty(_assertThisInitialized(_this), "createClearHandler", function (field) {
98
- return function () {
99
- switch (field) {
100
- case 'url':
101
- {
102
- _this.updateInput('');
103
-
104
- break;
105
- }
106
-
107
- case 'displayText':
108
- {
109
- _this.setState(_defineProperty({}, field, ''));
110
- }
111
- }
112
- };
113
- });
114
-
115
- _defineProperty(_assertThisInitialized(_this), "getScreenReaderText", function () {
116
- var intl = _this.props.intl;
117
- var _this$state = _this.state,
118
- items = _this$state.items,
119
- selectedIndex = _this$state.selectedIndex;
120
-
121
- if (items.length && selectedIndex > -1) {
122
- var _items$selectedIndex = items[selectedIndex],
123
- name = _items$selectedIndex.name,
124
- container = _items$selectedIndex.container,
125
- lastUpdatedDate = _items$selectedIndex.lastUpdatedDate,
126
- lastViewedDate = _items$selectedIndex.lastViewedDate;
127
- var date = transformTimeStamp(intl, lastViewedDate, lastUpdatedDate);
128
- 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(' ');
129
- return [name, container, formattedDate].filter(Boolean).join(', ');
130
- }
131
- });
132
-
133
- _defineProperty(_assertThisInitialized(_this), "getTabs", function () {
134
- if (_this.props.plugins && _this.props.plugins.length > 1) {
135
- return _this.props.plugins.filter(function (plugin) {
136
- return !!plugin.tabTitle;
137
- }).map(function (plugin) {
138
- return {
139
- tabTitle: plugin.tabTitle
140
- };
141
- });
142
- }
143
-
144
- return [];
145
- });
146
-
147
- _defineProperty(_assertThisInitialized(_this), "isUrlPopulatedWithSelectedItem", function () {
148
- /**
149
- * When we use ArrowKey to navigate through result items,
150
- * the URL field will be populated with the content of
151
- * selected item.
152
- * This function will check if the URL field is populated
153
- * with selected item.
154
- * It can be useful to detect whether we want to insert a
155
- * smartlink or a hyperlink with customized title
156
- */
157
- var _this$state2 = _this.state,
158
- items = _this$state2.items,
159
- selectedIndex = _this$state2.selectedIndex,
160
- url = _this$state2.url;
161
- var selectedItem = items[selectedIndex];
162
-
163
- if (selectedItem && selectedItem.url === url) {
164
- return true;
165
- }
63
+ return _objectSpread(_objectSpread({}, state), payload);
64
+ }
166
65
 
167
- return false;
66
+ function LinkPicker(_ref) {
67
+ var onSubmit = _ref.onSubmit,
68
+ onCancel = _ref.onCancel,
69
+ onContentResize = _ref.onContentResize,
70
+ plugins = _ref.plugins,
71
+ initUrl = _ref.url,
72
+ initDisplayText = _ref.displayText;
73
+
74
+ var _useReducer = useReducer(reducer, _objectSpread(_objectSpread({}, initState), {}, {
75
+ url: normalizeUrl(initUrl) || '',
76
+ displayText: initDisplayText || ''
77
+ })),
78
+ _useReducer2 = _slicedToArray(_useReducer, 2),
79
+ state = _useReducer2[0],
80
+ dispatch = _useReducer2[1];
81
+
82
+ var activeIndex = state.activeIndex,
83
+ selectedIndex = state.selectedIndex,
84
+ url = state.url,
85
+ displayText = state.displayText,
86
+ invalidUrl = state.invalidUrl;
87
+ var isEditing = !!initUrl;
88
+ var intl = useIntl();
89
+
90
+ var _usePlugins = usePlugins(state, plugins),
91
+ items = _usePlugins.items,
92
+ isLoading = _usePlugins.isLoading,
93
+ isSelectedItem = _usePlugins.isSelectedItem,
94
+ isActivePlugin = _usePlugins.isActivePlugin,
95
+ tabs = _usePlugins.tabs;
96
+
97
+ useLayoutEffect(function () {
98
+ if (onContentResize) {
99
+ onContentResize();
100
+ }
101
+ }, [onContentResize, items, isLoading, isActivePlugin, tabs]);
102
+ var handleChangeUrl = useCallback(function (url) {
103
+ dispatch({
104
+ url: url
168
105
  });
169
-
170
- _defineProperty(_assertThisInitialized(_this), "handleSelected", function (objectId) {
171
- var items = _this.state.items;
172
- var selectedItem = items.find(function (item) {
173
- return item.objectId === objectId;
174
- });
175
-
176
- if (selectedItem) {
177
- var url = selectedItem.url,
178
- name = selectedItem.name;
179
-
180
- _this.handleInsert(url, name, 'typeAhead');
181
- }
106
+ }, []);
107
+ var handleChangeText = useCallback(function (displayText) {
108
+ dispatch({
109
+ displayText: displayText
182
110
  });
111
+ }, []);
112
+ var handleKeyDown = useCallback(function (event) {
113
+ var keyCode = event.keyCode;
114
+ var KEY_CODE_ARROW_DOWN = 40;
115
+ var KEY_CODE_ARROW_UP = 38;
116
+
117
+ if (!items || !items.length) {
118
+ return;
119
+ }
183
120
 
184
- _defineProperty(_assertThisInitialized(_this), "handleInsert", function (url, title, inputType) {
185
- var onSubmit = _this.props.onSubmit;
186
- var _this$state3 = _this.state,
187
- rawUrl = _this$state3.url,
188
- displayText = _this$state3.displayText;
121
+ var updatedIndex = activeIndex;
189
122
 
190
- if (onSubmit) {
191
- onSubmit(_objectSpread({
192
- url: url,
193
- displayText: displayText || null,
194
- title: title || null,
195
- meta: {
196
- inputMethod: inputType
197
- }
198
- }, inputType === 'manual' ? {
199
- rawUrl: rawUrl
200
- } : {}));
201
- }
202
- });
123
+ switch (keyCode) {
124
+ case KEY_CODE_ARROW_DOWN:
125
+ // down
126
+ event.preventDefault();
127
+ updatedIndex = (activeIndex + 1) % items.length;
128
+ break;
203
129
 
204
- _defineProperty(_assertThisInitialized(_this), "handleMouseEnterResultItem", function (objectId) {
205
- var items = _this.state.items;
206
- var index = findIndex(items, function (item) {
207
- return item.objectId === objectId;
208
- });
130
+ case KEY_CODE_ARROW_UP:
131
+ // up
132
+ event.preventDefault();
133
+ updatedIndex = activeIndex > 0 ? activeIndex - 1 : items.length - 1;
134
+ break;
135
+ }
209
136
 
210
- _this.setState({
211
- activeIndex: index
137
+ if ([KEY_CODE_ARROW_DOWN, KEY_CODE_ARROW_UP].includes(keyCode) && items[updatedIndex]) {
138
+ dispatch({
139
+ activeIndex: updatedIndex,
140
+ selectedIndex: updatedIndex,
141
+ url: items[updatedIndex].url,
142
+ invalidUrl: false
212
143
  });
144
+ }
145
+ }, [activeIndex, items]);
146
+ var handleClear = useCallback(function (field) {
147
+ dispatch(_defineProperty({}, field, ''));
148
+ }, []);
149
+ var handleMouseEnterResultItem = useCallback(function (objectId) {
150
+ var index = findIndex(items, function (item) {
151
+ return item.objectId === objectId;
213
152
  });
214
-
215
- _defineProperty(_assertThisInitialized(_this), "handleMouseLeaveResultItem", function (objectId) {
216
- var _this$state4 = _this.state,
217
- items = _this$state4.items,
218
- activeIndex = _this$state4.activeIndex;
219
- var index = findIndex(items, function (item) {
220
- return item.objectId === objectId;
221
- }); // This is to avoid updating index that was set by other mouseenter event
222
-
223
- if (activeIndex === index) {
224
- _this.setState({
225
- activeIndex: -1
226
- });
227
- }
153
+ dispatch({
154
+ activeIndex: index
228
155
  });
229
-
230
- _defineProperty(_assertThisInitialized(_this), "handleSubmit", function () {
231
- var _this$state5 = _this.state,
232
- url = _this$state5.url,
233
- selectedIndex = _this$state5.selectedIndex,
234
- items = _this$state5.items;
235
- var intl = _this.props.intl;
236
- var selectedItem = items[selectedIndex];
237
-
238
- if (_this.isUrlPopulatedWithSelectedItem()) {
239
- return _this.handleInsert(selectedItem.url, selectedItem.name, 'typeAhead');
240
- }
241
-
242
- var normalized = normalizeUrl(url);
243
-
244
- if (normalized) {
245
- return _this.handleInsert(normalized, null, 'manual');
246
- }
247
-
248
- return _this.setState({
249
- invalidUrl: intl.formatMessage(messages.linkInvalid)
156
+ }, [items]);
157
+ var handleMouseLeaveResultItem = useCallback(function (objectId) {
158
+ var index = findIndex(items, function (item) {
159
+ return item.objectId === objectId;
160
+ }); // This is to avoid updating index that was set by other mouseenter event
161
+
162
+ if (activeIndex === index) {
163
+ dispatch({
164
+ activeIndex: -1
250
165
  });
251
- });
252
-
253
- _defineProperty(_assertThisInitialized(_this), "handleKeyDown", function (event) {
254
- var _this$state6 = _this.state,
255
- items = _this$state6.items,
256
- activeIndex = _this$state6.activeIndex;
257
- var keyCode = event.keyCode;
258
- var KEY_CODE_ARROW_DOWN = 40;
259
- var KEY_CODE_ARROW_UP = 38;
260
-
261
- if (!items || !items.length) {
262
- return;
263
- }
264
-
265
- var updatedIndex = activeIndex;
266
-
267
- switch (keyCode) {
268
- case KEY_CODE_ARROW_DOWN:
269
- // down
270
- event.preventDefault();
271
- updatedIndex = (activeIndex + 1) % items.length;
272
- break;
273
-
274
- case KEY_CODE_ARROW_UP:
275
- // up
276
- event.preventDefault();
277
- updatedIndex = activeIndex > 0 ? activeIndex - 1 : items.length - 1;
278
- break;
279
- }
280
-
281
- if ([KEY_CODE_ARROW_DOWN, KEY_CODE_ARROW_UP].includes(keyCode) && items[updatedIndex]) {
282
- _this.setState({
283
- activeIndex: updatedIndex,
284
- selectedIndex: updatedIndex,
285
- url: items[updatedIndex].url,
286
- invalidUrl: null
287
- });
288
- }
289
- });
290
-
291
- _defineProperty(_assertThisInitialized(_this), "handleCancel", function () {
292
- var onCancel = _this.props.onCancel;
293
-
294
- if (onCancel) {
295
- onCancel();
166
+ }
167
+ }, [activeIndex, items]);
168
+ var handleInsert = useCallback(function (url, title, inputType) {
169
+ onSubmit(_objectSpread({
170
+ url: url,
171
+ displayText: displayText || null,
172
+ title: title || null,
173
+ meta: {
174
+ inputMethod: inputType
296
175
  }
176
+ }, inputType === 'manual' ? {
177
+ rawUrl: state.url
178
+ } : {}));
179
+ }, [displayText, onSubmit, state.url]);
180
+ var handleSelected = useCallback(function (objectId) {
181
+ var selectedItem = items.find(function (item) {
182
+ return item.objectId === objectId;
297
183
  });
298
184
 
299
- _defineProperty(_assertThisInitialized(_this), "updateTextInput", function (displayText) {
300
- _this.setState({
301
- displayText: displayText
302
- });
303
- });
304
-
305
- _this.state = {
306
- selectedIndex: -1,
307
- activeIndex: -1,
308
- isLoading: false,
309
- isEditing: !!props.url,
310
- url: normalizeUrl(props.url) || '',
311
- displayText: props.displayText || '',
312
- items: [],
313
- invalidUrl: null,
314
- activePlugin: 0
315
- };
316
- /* Cache functions */
317
-
318
- _this.handleClearUrl = _this.createClearHandler('url');
319
- _this.handleClearDisplayText = _this.createClearHandler('displayText');
320
- return _this;
321
- }
322
-
323
- _createClass(LinkPicker, [{
324
- key: "componentDidMount",
325
- value: function componentDidMount() {
326
- this.loadInitialLinkSearchResult();
327
- }
328
- }, {
329
- key: "loadInitialLinkSearchResult",
330
- value: function loadInitialLinkSearchResult() {
331
- var url = this.state.url;
332
-
333
- if (!url) {
334
- this.updateResults();
335
- }
185
+ if (selectedItem) {
186
+ var _url = selectedItem.url,
187
+ name = selectedItem.name;
188
+ handleInsert(_url, name, 'typeAhead');
336
189
  }
337
- }, {
338
- key: "getActivePlugin",
339
- value: function getActivePlugin() {
340
- if (!this.props.plugins || this.props.plugins.length === 0) {
341
- return null;
342
- }
190
+ }, [handleInsert, items]);
191
+ var handleSubmit = useCallback(function () {
192
+ var selectedItem = items[selectedIndex];
343
193
 
344
- return this.props.plugins[this.state.activePlugin];
194
+ if (isSelectedItem) {
195
+ return handleInsert(selectedItem.url, selectedItem.name, 'typeAhead');
345
196
  }
346
- /**
347
- * Interface between link picker and plugins to update results
348
- */
349
-
350
- }, {
351
- key: "updateResults",
352
- value: function () {
353
- var _updateResults = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
354
- var _this2 = this;
355
-
356
- var queryVersion, activePlugin, updates, _loop, _ret;
357
-
358
- return _regeneratorRuntime.wrap(function _callee2$(_context3) {
359
- while (1) {
360
- switch (_context3.prev = _context3.next) {
361
- case 0:
362
- queryVersion = ++this.queryVersion;
363
- activePlugin = this.getActivePlugin();
364
-
365
- if (activePlugin) {
366
- _context3.next = 4;
367
- break;
368
- }
369
-
370
- return _context3.abrupt("return");
371
-
372
- case 4:
373
- updates = activePlugin.resolve({
374
- query: this.state.url
375
- });
376
- this.setState({
377
- isLoading: true,
378
- items: []
379
- });
380
- _context3.prev = 6;
381
- _loop = /*#__PURE__*/_regeneratorRuntime.mark(function _loop() {
382
- var done, value, _result$done, result;
383
-
384
- return _regeneratorRuntime.wrap(function _loop$(_context2) {
385
- while (1) {
386
- switch (_context2.prev = _context2.next) {
387
- case 0:
388
- done = false;
389
- value = void 0;
390
-
391
- if (!(updates instanceof Promise)) {
392
- _context2.next = 9;
393
- break;
394
- }
395
-
396
- done = true;
397
- _context2.next = 6;
398
- return updates;
399
197
 
400
- case 6:
401
- value = _context2.sent;
402
- _context2.next = 14;
403
- break;
198
+ var normalized = normalizeUrl(url);
404
199
 
405
- case 9:
406
- _context2.next = 11;
407
- return updates.next();
408
-
409
- case 11:
410
- result = _context2.sent;
411
- done = (_result$done = result.done) !== null && _result$done !== void 0 ? _result$done : false;
412
- value = result.value;
413
-
414
- case 14:
415
- if (!(queryVersion !== _this2.queryVersion)) {
416
- _context2.next = 16;
417
- break;
418
- }
419
-
420
- return _context2.abrupt("return", {
421
- v: void 0
422
- });
423
-
424
- case 16:
425
- _this2.setState(function (prev) {
426
- return {
427
- items: limit(value.data),
428
- isLoading: !done
429
- };
430
- });
431
-
432
- if (!done) {
433
- _context2.next = 19;
434
- break;
435
- }
436
-
437
- return _context2.abrupt("return", {
438
- v: void 0
439
- });
440
-
441
- case 19:
442
- case "end":
443
- return _context2.stop();
444
- }
445
- }
446
- }, _loop);
447
- });
448
-
449
- case 8:
450
- if (!(queryVersion === this.queryVersion)) {
451
- _context3.next = 15;
452
- break;
453
- }
454
-
455
- return _context3.delegateYield(_loop(), "t0", 10);
456
-
457
- case 10:
458
- _ret = _context3.t0;
459
-
460
- if (!(_typeof(_ret) === "object")) {
461
- _context3.next = 13;
462
- break;
463
- }
464
-
465
- return _context3.abrupt("return", _ret.v);
466
-
467
- case 13:
468
- _context3.next = 8;
469
- break;
470
-
471
- case 15:
472
- _context3.next = 20;
473
- break;
474
-
475
- case 17:
476
- _context3.prev = 17;
477
- _context3.t1 = _context3["catch"](6);
478
- this.setState({
479
- isLoading: false
480
- });
481
-
482
- case 20:
483
- case "end":
484
- return _context3.stop();
485
- }
486
- }
487
- }, _callee2, this, [[6, 17]]);
488
- }));
489
-
490
- function updateResults() {
491
- return _updateResults.apply(this, arguments);
492
- }
493
-
494
- return updateResults;
495
- }()
496
- }, {
497
- key: "render",
498
- value: function render() {
499
- var _this3 = this;
500
-
501
- var _this$state7 = this.state,
502
- items = _this$state7.items,
503
- isLoading = _this$state7.isLoading,
504
- isEditing = _this$state7.isEditing,
505
- activeIndex = _this$state7.activeIndex,
506
- selectedIndex = _this$state7.selectedIndex,
507
- url = _this$state7.url,
508
- displayText = _this$state7.displayText;
509
- var formatMessage = this.props.intl.formatMessage;
510
- var activePlugin = this.getActivePlugin();
511
- var tabs = this.getTabs();
512
- var linkPlaceHolder = formatMessage(activePlugin ? messages.placeholder : messages.linkPlaceholder);
513
- var linkLabel = formatMessage(messages.linkLabel);
514
- var linkTextLabel = formatMessage(messages.linkTextLabel);
515
- var linkTextPlaceHolder = formatMessage(messages.linkTextPlaceholder);
516
- var screenReaderDescriptionId = 'search-recent-links-field-description';
517
- var linkSearchListId = 'link-picker-search-list';
518
- var ariaActiveDescendant = selectedIndex > -1 ? "link-search-list-item-".concat(selectedIndex) : ''; // Added workaround with a screen reader Announcer specifically for VoiceOver + Safari
519
- // as the Aria design pattern for combobox does not work in this case
520
- // for details: https://a11y-internal.atlassian.net/browse/AK-740
200
+ if (normalized) {
201
+ return handleInsert(normalized, null, 'manual');
202
+ }
521
203
 
522
- var screenReaderText = browser.safari && this.getScreenReaderText();
523
- var searchIcon = activePlugin && jsx("span", {
524
- css: searchIconStyles,
525
- "data-testid": "link-picker-search-icon"
526
- }, jsx(EditorSearchIcon, {
527
- size: "medium",
528
- label: ''
529
- }));
530
- var noResults = activePlugin && !isLoading && !items.length && !isSafeUrl(url);
531
- return jsx("div", {
532
- "data-testid": "link-picker",
533
- css: rootContainerStyles
534
- }, screenReaderText && jsx(Announcer, {
535
- ariaLive: "assertive",
536
- text: screenReaderText,
537
- ariaRelevant: "additions",
538
- delay: 250
539
- }), jsx(VisuallyHidden, null, jsx("span", {
540
- "aria-hidden": "true",
541
- id: screenReaderDescriptionId
542
- }, formatMessage(messages.searchLinkAriaDescription))), jsx(PanelTextInput, {
543
- name: "link",
544
- testId: "link-url",
545
- role: "combobox",
546
- label: linkLabel,
547
- placeholder: linkPlaceHolder,
548
- value: url,
549
- autoFocus: true,
550
- autoComplete: "off",
551
- elemBeforeInput: searchIcon,
552
- onSubmit: this.handleSubmit,
553
- onChange: this.updateInput,
554
- onKeyDown: this.handleKeyDown,
555
- onClear: this.handleClearUrl,
556
- error: this.state.invalidUrl,
557
- clearLabel: formatMessage(messages.clearLink),
558
- "aria-controls": linkSearchListId,
559
- "aria-autocomplete": "list",
560
- "aria-activedescendant": ariaActiveDescendant,
561
- "aria-describedby": screenReaderDescriptionId,
562
- "aria-expanded": true
563
- }), jsx(PanelTextInput, {
564
- name: "link-text",
565
- testId: "link-text",
566
- autoComplete: "off",
567
- label: linkTextLabel,
568
- placeholder: linkTextPlaceHolder,
569
- "aria-label": formatMessage(messages.linkAriaLabel),
570
- value: displayText,
571
- onSubmit: this.handleSubmit,
572
- onKeyDown: this.handleKeyDown,
573
- onChange: this.updateTextInput,
574
- onClear: this.handleClearDisplayText,
575
- clearLabel: formatMessage(messages.clearText)
576
- }), tabs.length > 0 && jsx(Tabs, {
577
- id: "link-picker-tabs",
578
- testId: "link-picker-tabs",
579
- onChange: function onChange(activePlugin) {
580
- return _this3.setState({
581
- activePlugin: activePlugin
582
- }, function () {
583
- _this3.updateResults();
584
- });
585
- }
586
- }, jsx(TabList, null, tabs.map(function (tab) {
587
- var label = tab.tabTitle;
588
- return jsx(Tab, {
589
- key: label,
590
- testId: "link-picker-tab"
591
- }, label);
592
- }))), !!items.length && jsx("div", {
593
- css: listTitleStyles,
594
- id: "link-picker-list-title",
595
- "data-testid": "link-picker-list-title"
596
- }, formatMessage(this.state.url ? messages.titleResults : messages.titleRecentlyViewed)), jsx(VisuallyHidden, null, jsx("span", {
597
- "aria-live": "polite",
598
- "aria-atomic": "true",
599
- id: "fabric.smartcard.linkpicker.suggested.results"
600
- }, url && formatMessage(messages.searchLinkResults, {
601
- count: items.length
602
- }))), jsx(LinkSearchList, {
603
- ariaLabelledBy: "link-picker-list-title",
604
- ariaControls: "fabric.smartcard.linkpicker.suggested.results",
605
- id: linkSearchListId,
606
- role: "listbox",
607
- items: items,
608
- isLoading: isLoading,
609
- selectedIndex: selectedIndex,
610
- activeIndex: activeIndex,
611
- onSelect: this.handleSelected,
612
- onMouseEnter: this.handleMouseEnterResultItem,
613
- onMouseLeave: this.handleMouseLeaveResultItem
614
- }), noResults && jsx(LinkSearchNoResults, {
615
- testId: "link-search-no-results",
616
- header: formatMessage(messages.noResults),
617
- description: formatMessage(messages.noResultsDescription)
618
- }), jsx(FormFooter, {
619
- align: "end"
620
- }, jsx(ButtonGroup, null, jsx(Button, {
621
- appearance: "default",
622
- onClick: this.handleCancel,
623
- testId: "link-picker-cancel-button"
624
- }, formatMessage(messages.cancelButton)), jsx(Button, {
625
- type: "submit",
626
- appearance: "primary",
627
- onClick: this.handleSubmit,
628
- testId: "link-picker-insert-button"
629
- }, formatMessage(isEditing ? messages.saveButton : messages.insertButton)))));
204
+ return dispatch({
205
+ invalidUrl: true
206
+ });
207
+ }, [handleInsert, isSelectedItem, items, selectedIndex, url]);
208
+ var linkPlaceHolder = isActivePlugin ? messages.placeholder : messages.linkPlaceholder;
209
+ var linkListTitle = url ? messages.titleResults : messages.titleRecentlyViewed;
210
+ var insertButtonMsg = isEditing ? messages.saveButton : messages.insertButton;
211
+ var noResults = isActivePlugin && !isLoading && !items.length && !isSafeUrl(url);
212
+ var screenReaderDescriptionId = 'search-recent-links-field-description';
213
+ var linkSearchListId = 'link-picker-search-list';
214
+ var ariaActiveDescendant = selectedIndex > -1 ? "link-search-list-item-".concat(selectedIndex) : ''; // Added workaround with a screen reader Announcer specifically for VoiceOver + Safari
215
+ // as the Aria design pattern for combobox does not work in this case
216
+ // for details: https://a11y-internal.atlassian.net/browse/AK-740
217
+
218
+ var screenReaderText = browser.safari && getScreenReaderText(items, selectedIndex, intl);
219
+ var searchIcon = isActivePlugin && jsx("span", {
220
+ css: searchIconStyles,
221
+ "data-testid": testIds.searchIcon
222
+ }, jsx(EditorSearchIcon, {
223
+ size: "medium",
224
+ label: ''
225
+ }));
226
+ return jsx("div", {
227
+ "data-testid": testIds.linkPicker,
228
+ css: rootContainerStyles
229
+ }, screenReaderText && jsx(Announcer, {
230
+ ariaLive: "assertive",
231
+ text: screenReaderText,
232
+ ariaRelevant: "additions",
233
+ delay: 250
234
+ }), jsx(VisuallyHidden, {
235
+ id: screenReaderDescriptionId
236
+ }, jsx(FormattedMessage, messages.searchLinkAriaDescription)), jsx(PanelTextInput, {
237
+ role: "combobox",
238
+ autoComplete: "off",
239
+ name: "url",
240
+ testId: testIds.urlInputField,
241
+ label: intl.formatMessage(messages.linkLabel),
242
+ placeholder: intl.formatMessage(linkPlaceHolder),
243
+ value: url,
244
+ autoFocus: true,
245
+ elemBeforeInput: searchIcon,
246
+ clearLabel: intl.formatMessage(messages.clearLink),
247
+ "aria-expanded": true,
248
+ "aria-autocomplete": "list",
249
+ "aria-controls": linkSearchListId,
250
+ "aria-activedescendant": ariaActiveDescendant,
251
+ "aria-describedby": screenReaderDescriptionId,
252
+ error: invalidUrl ? intl.formatMessage(messages.linkInvalid) : null,
253
+ onClear: handleClear,
254
+ onSubmit: handleSubmit,
255
+ onKeyDown: handleKeyDown,
256
+ onChange: handleChangeUrl
257
+ }), jsx(PanelTextInput, {
258
+ autoComplete: "off",
259
+ name: "displayText",
260
+ testId: testIds.textInputField,
261
+ value: displayText,
262
+ label: intl.formatMessage(messages.linkTextLabel),
263
+ placeholder: intl.formatMessage(messages.linkTextPlaceholder),
264
+ clearLabel: intl.formatMessage(messages.clearText),
265
+ "aria-label": intl.formatMessage(messages.linkAriaLabel),
266
+ onClear: handleClear,
267
+ onSubmit: handleSubmit,
268
+ onKeyDown: handleKeyDown,
269
+ onChange: handleChangeText
270
+ }), tabs.length > 0 && jsx("div", {
271
+ css: tabsWrapperStyles
272
+ }, jsx(Tabs, {
273
+ id: testIds.tabList,
274
+ testId: testIds.tabList,
275
+ onChange: function onChange(activeTab) {
276
+ return dispatch({
277
+ selectedIndex: -1,
278
+ activeIndex: -1,
279
+ invalidUrl: false,
280
+ activeTab: activeTab
281
+ });
630
282
  }
631
- }]);
283
+ }, jsx(TabList, null, tabs.map(function (tab) {
284
+ return jsx(Tab, {
285
+ key: tab.tabTitle,
286
+ testId: testIds.tabItem
287
+ }, tab.tabTitle);
288
+ })))), !!items.length && jsx("div", {
289
+ css: listTitleStyles,
290
+ id: testIds.resultListTitle,
291
+ "data-testid": testIds.resultListTitle
292
+ }, jsx(FormattedMessage, linkListTitle)), jsx(VisuallyHidden, {
293
+ id: "fabric.smartcard.linkpicker.suggested.results"
294
+ }, url && jsx(FormattedMessage, _extends({}, messages.searchLinkResults, {
295
+ values: {
296
+ count: items.length
297
+ },
298
+ "aria-live": "polite",
299
+ "aria-atomic": "true"
300
+ }))), jsx(LinkSearchList, {
301
+ ariaLabelledBy: testIds.resultListTitle,
302
+ ariaControls: "fabric.smartcard.linkpicker.suggested.results",
303
+ id: linkSearchListId,
304
+ role: "listbox",
305
+ items: items,
306
+ isLoading: isLoading,
307
+ selectedIndex: selectedIndex,
308
+ activeIndex: activeIndex,
309
+ onSelect: handleSelected,
310
+ onMouseEnter: handleMouseEnterResultItem,
311
+ onMouseLeave: handleMouseLeaveResultItem
312
+ }), noResults && jsx(LinkSearchNoResults, {
313
+ testId: testIds.emptyResultPage,
314
+ header: intl.formatMessage(messages.noResults),
315
+ description: intl.formatMessage(messages.noResultsDescription)
316
+ }), jsx(FormFooter, {
317
+ align: "end"
318
+ }, jsx(ButtonGroup, null, jsx(Button, {
319
+ appearance: "default",
320
+ onClick: onCancel,
321
+ testId: testIds.cancelButton
322
+ }, intl.formatMessage(messages.cancelButton)), jsx(Button, {
323
+ type: "submit",
324
+ appearance: "primary",
325
+ onClick: handleSubmit,
326
+ testId: testIds.insertButton
327
+ }, intl.formatMessage(insertButtonMsg)))));
328
+ }
632
329
 
633
- return LinkPicker;
634
- }(PureComponent);
330
+ export default LinkPicker;
331
+
332
+ function getScreenReaderText(items, selectedIndex, intl) {
333
+ if (items.length && selectedIndex > -1) {
334
+ var _items$selectedIndex = items[selectedIndex],
335
+ name = _items$selectedIndex.name,
336
+ container = _items$selectedIndex.container,
337
+ lastUpdatedDate = _items$selectedIndex.lastUpdatedDate,
338
+ lastViewedDate = _items$selectedIndex.lastViewedDate;
339
+ var date = transformTimeStamp(intl, lastViewedDate, lastUpdatedDate);
340
+ 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(' ');
341
+ return [name, container, formattedDate].filter(Boolean).join(', ');
342
+ }
343
+ }
635
344
 
636
345
  function findIndex(array, predicate) {
637
346
  var index = -1;
@@ -644,10 +353,4 @@ function findIndex(array, predicate) {
644
353
  return false;
645
354
  });
646
355
  return index;
647
- }
648
-
649
- function limit(items) {
650
- return items.slice(0, RECENT_SEARCH_LIST_SIZE);
651
- }
652
-
653
- export default injectIntl(LinkPicker);
356
+ }