@atlaskit/link-picker 1.1.0 → 1.1.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 (73) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +4 -1
  3. package/dist/cjs/browser.js +0 -39
  4. package/dist/cjs/index.js +0 -13
  5. package/dist/cjs/messages.js +0 -112
  6. package/dist/cjs/transformTimeStamp.js +0 -55
  7. package/dist/cjs/types.js +0 -5
  8. package/dist/cjs/ui/announcer.js +0 -64
  9. package/dist/cjs/ui/link-picker.js +0 -611
  10. package/dist/cjs/ui/link-search-list/index.js +0 -102
  11. package/dist/cjs/ui/link-search-list/styled.js +0 -21
  12. package/dist/cjs/ui/link-search-no-results/index.js +0 -27
  13. package/dist/cjs/ui/list-item/index.js +0 -103
  14. package/dist/cjs/ui/list-item/styled.js +0 -59
  15. package/dist/cjs/ui/styled.js +0 -32
  16. package/dist/cjs/ui/text-input/index.js +0 -116
  17. package/dist/cjs/ui/text-input/styled.js +0 -25
  18. package/dist/cjs/url.js +0 -104
  19. package/dist/cjs/utils.js +0 -27
  20. package/dist/cjs/version.json +0 -5
  21. package/dist/es2019/browser.js +0 -34
  22. package/dist/es2019/index.js +0 -1
  23. package/dist/es2019/messages.js +0 -103
  24. package/dist/es2019/transformTimeStamp.js +0 -41
  25. package/dist/es2019/types.js +0 -1
  26. package/dist/es2019/ui/announcer.js +0 -38
  27. package/dist/es2019/ui/link-picker.js +0 -499
  28. package/dist/es2019/ui/link-search-list/index.js +0 -60
  29. package/dist/es2019/ui/link-search-list/styled.js +0 -13
  30. package/dist/es2019/ui/link-search-no-results/index.js +0 -12
  31. package/dist/es2019/ui/list-item/index.js +0 -88
  32. package/dist/es2019/ui/list-item/styled.js +0 -65
  33. package/dist/es2019/ui/styled.js +0 -28
  34. package/dist/es2019/ui/text-input/index.js +0 -99
  35. package/dist/es2019/ui/text-input/styled.js +0 -15
  36. package/dist/es2019/url.js +0 -88
  37. package/dist/es2019/utils.js +0 -13
  38. package/dist/es2019/version.json +0 -5
  39. package/dist/esm/browser.js +0 -34
  40. package/dist/esm/index.js +0 -1
  41. package/dist/esm/messages.js +0 -103
  42. package/dist/esm/transformTimeStamp.js +0 -41
  43. package/dist/esm/types.js +0 -1
  44. package/dist/esm/ui/announcer.js +0 -51
  45. package/dist/esm/ui/link-picker.js +0 -589
  46. package/dist/esm/ui/link-search-list/index.js +0 -88
  47. package/dist/esm/ui/link-search-list/styled.js +0 -8
  48. package/dist/esm/ui/link-search-no-results/index.js +0 -14
  49. package/dist/esm/ui/list-item/index.js +0 -90
  50. package/dist/esm/ui/list-item/styled.js +0 -37
  51. package/dist/esm/ui/styled.js +0 -16
  52. package/dist/esm/ui/text-input/index.js +0 -99
  53. package/dist/esm/ui/text-input/styled.js +0 -10
  54. package/dist/esm/url.js +0 -90
  55. package/dist/esm/utils.js +0 -13
  56. package/dist/esm/version.json +0 -5
  57. package/dist/types/browser.d.ts +0 -15
  58. package/dist/types/index.d.ts +0 -3
  59. package/dist/types/messages.d.ts +0 -102
  60. package/dist/types/transformTimeStamp.d.ts +0 -3
  61. package/dist/types/types.d.ts +0 -40
  62. package/dist/types/ui/announcer.d.ts +0 -22
  63. package/dist/types/ui/link-picker.d.ts +0 -51
  64. package/dist/types/ui/link-search-list/index.d.ts +0 -20
  65. package/dist/types/ui/link-search-list/styled.d.ts +0 -3
  66. package/dist/types/ui/link-search-no-results/index.d.ts +0 -4
  67. package/dist/types/ui/list-item/index.d.ts +0 -17
  68. package/dist/types/ui/list-item/styled.d.ts +0 -7
  69. package/dist/types/ui/styled.d.ts +0 -4
  70. package/dist/types/ui/text-input/index.d.ts +0 -17
  71. package/dist/types/ui/text-input/styled.d.ts +0 -2
  72. package/dist/types/url.d.ts +0 -5
  73. package/dist/types/utils.d.ts +0 -3
@@ -1,103 +0,0 @@
1
- import { defineMessages } from 'react-intl-next';
2
- export const messages = defineMessages({
3
- placeholder: {
4
- id: 'fabric.linkPicker.hyperlinkToolbarPlaceholder',
5
- defaultMessage: 'Search or paste a link',
6
- description: 'Search or paste a link'
7
- },
8
- linkPlaceholder: {
9
- id: 'fabric.linkPicker.linkPlaceholder',
10
- defaultMessage: 'Paste link',
11
- description: 'Create a new link by pasting a URL.'
12
- },
13
- linkTextPlaceholder: {
14
- id: 'fabric.linkPicker.linkTextPlaceholder',
15
- defaultMessage: 'Add a description',
16
- description: 'Text to display'
17
- },
18
- linkLabel: {
19
- id: 'fabric.linkPicker.linkAddress',
20
- defaultMessage: 'Link',
21
- description: 'Link Label'
22
- },
23
- linkInvalid: {
24
- id: 'fabric.linkPicker.linkInvalid',
25
- defaultMessage: 'Enter a valid URL.',
26
- description: 'Input Error the URL is invalid'
27
- },
28
- linkTextLabel: {
29
- id: 'fabric.linkPicker.displayText',
30
- defaultMessage: 'Link text',
31
- description: 'Link text label'
32
- },
33
- clearText: {
34
- id: 'fabric.linkPicker.clearLinkText',
35
- defaultMessage: 'Clear text',
36
- description: 'Clears text on the link toolbar'
37
- },
38
- clearLink: {
39
- id: 'fabric.linkPicker.clearLink',
40
- defaultMessage: 'Clear link',
41
- description: 'Clears link in the link toolbar'
42
- },
43
- searchLinkAriaDescription: {
44
- id: 'fabric.linkPicker.hyperlink.searchLinkAriaDescription',
45
- defaultMessage: 'Suggestions will appear below as you type into the field',
46
- description: 'Describes what the search field does for screen reader users.'
47
- },
48
- searchLinkResults: {
49
- id: 'fabric.linkPicker.hyperlink.searchLinkResults',
50
- defaultMessage: '{count, plural, =0 {no results} one {# result} other {# results}} found',
51
- description: 'Announce search results for screen-reader users.'
52
- },
53
- linkAriaLabel: {
54
- id: 'fabric.linkPicker.hyperlink.linkAriaLabel',
55
- defaultMessage: 'Link label',
56
- description: 'aria label for a link'
57
- },
58
- timeUpdated: {
59
- id: 'fabric.linkPicker.time.updated',
60
- defaultMessage: 'Updated',
61
- description: 'Time last updated'
62
- },
63
- timeViewed: {
64
- id: 'fabric.linkPicker.time.viewed',
65
- defaultMessage: 'Viewed',
66
- description: 'Time last viewed'
67
- },
68
- timeAgo: {
69
- id: 'fabric.linkPicker.time.ago',
70
- defaultMessage: 'ago',
71
- description: 'Some time ago'
72
- },
73
- titleRecentlyViewed: {
74
- id: 'fabric.linkPicker.listTitle.recentlyViewed',
75
- defaultMessage: 'Recently Viewed',
76
- description: 'Describes type of items shown in the list for screen-reader users'
77
- },
78
- titleResults: {
79
- id: 'fabric.linkPicker.listTitle.results',
80
- defaultMessage: 'Results',
81
- description: 'Describes type of items shown in the list for screen-reader users'
82
- },
83
- cancelButton: {
84
- id: 'fabric.linkPicker.button.cancel',
85
- defaultMessage: 'Cancel',
86
- description: 'Button to cancel and dismiss the link picker'
87
- },
88
- insertButton: {
89
- id: 'fabric.linkPicker.button.insert',
90
- defaultMessage: 'Insert',
91
- description: 'Button to insert searched or selected link'
92
- },
93
- noResults: {
94
- id: 'fabric.linkPicker.search.noResults.heading',
95
- defaultMessage: 'We couldn’t find anything matching your search.',
96
- description: 'Heading message shown when a search has no results'
97
- },
98
- noResultsDescription: {
99
- id: 'fabric.linkPicker.search.noResults.description',
100
- defaultMessage: 'Try again with a different term.',
101
- description: 'Describes possible action when a search returns no results'
102
- }
103
- });
@@ -1,41 +0,0 @@
1
- import formatDistance from 'date-fns/formatDistance';
2
- import differenceInCalendarDays from 'date-fns/differenceInCalendarDays';
3
- import format from 'date-fns/format';
4
- import { messages } from './messages';
5
-
6
- const renderAbsoluteOrRelativeDate = (timeStamp, pageAction, intl) => {
7
- let pageActionText = '';
8
-
9
- switch (pageAction) {
10
- case 'updated':
11
- pageActionText = intl.formatMessage(messages.timeUpdated);
12
- break;
13
-
14
- case 'viewed':
15
- pageActionText = intl.formatMessage(messages.timeViewed);
16
- break;
17
- }
18
-
19
- if (differenceInCalendarDays(timeStamp, Date.now()) < -7) {
20
- return {
21
- pageAction: pageActionText,
22
- dateString: format(timeStamp, 'MMMM dd, yyyy')
23
- };
24
- }
25
-
26
- return {
27
- pageAction: pageActionText,
28
- dateString: formatDistance(timeStamp, Date.now()),
29
- timeSince: intl.formatMessage(messages.timeAgo)
30
- };
31
- };
32
-
33
- export const transformTimeStamp = (intl, lastViewedDate, lastUpdatedDate) => {
34
- if (lastViewedDate) {
35
- return renderAbsoluteOrRelativeDate(lastViewedDate, 'viewed', intl);
36
- }
37
-
38
- if (lastUpdatedDate) {
39
- return renderAbsoluteOrRelativeDate(lastUpdatedDate, 'updated', intl);
40
- }
41
- };
@@ -1 +0,0 @@
1
- export {};
@@ -1,38 +0,0 @@
1
- import React, { forwardRef, memo, useState, useEffect } from 'react'; // How to use:
2
- // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions#Preferring_specialized_live_region_roles
3
- // Demo: https://dequeuniversity.com/library/aria/liveregion-playground
4
- // Important: Strongly recommend test your solution in all supported screen readers
5
- // if you use non default value of properties: ariaAtomic, ariaLive, ariaRelevant, role
6
- // Note: Text won't be announced if the text message doesn't change after the render.
7
- // For using a forced announcement in this case, set the 'key' attribute - key={Date.now()}
8
-
9
- // Note: Flag 'contentRendered' resolves bug with duplicates messages (NVDA + Firefox)
10
- // https://github.com/nvaccess/nvda/labels/bug%2Fdouble-speaking
11
- let timer;
12
- const Announcer = /*#__PURE__*/forwardRef(({
13
- ariaAtomic = 'true',
14
- ariaLive = 'polite',
15
- ariaRelevant = 'all',
16
- role = 'status',
17
- text = '',
18
- delay = 0
19
- }, ref) => {
20
- const [contentRendered, setContentRendered] = useState(false);
21
- useEffect(() => {
22
- clearTimeout(timer);
23
- setContentRendered(false);
24
- timer = setTimeout(() => {
25
- setContentRendered(true);
26
- }, delay);
27
- return () => clearTimeout(timer);
28
- }, [text, delay]);
29
- return /*#__PURE__*/React.createElement("div", {
30
- className: "assistive",
31
- ref: ref,
32
- role: role,
33
- "aria-atomic": ariaAtomic,
34
- "aria-relevant": ariaRelevant,
35
- "aria-live": ariaLive
36
- }, contentRendered && /*#__PURE__*/React.createElement("span", null, text));
37
- });
38
- export default /*#__PURE__*/memo(Announcer);
@@ -1,499 +0,0 @@
1
- import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
-
3
- /** @jsx jsx */
4
- import React, { PureComponent } from 'react';
5
- import { jsx } from '@emotion/react';
6
- import { injectIntl } from 'react-intl-next';
7
- import { messages } from '../messages';
8
- import PanelTextInput from './text-input';
9
- import LinkSearchList from './link-search-list';
10
- import { normalizeUrl, isSafeUrl } from '../url';
11
- import { recentListStyles, containerStyles, searchIconStyles, listTitleStyles } from './styled';
12
- import { browser } from '../browser';
13
- import { transformTimeStamp } from '../transformTimeStamp';
14
- import Announcer from './announcer';
15
- import Button, { ButtonGroup } from '@atlaskit/button';
16
- import { FormFooter } from '@atlaskit/form';
17
- import EditorSearchIcon from '@atlaskit/icon/glyph/editor/search';
18
- import VisuallyHidden from '@atlaskit/visually-hidden';
19
- import LinkSearchNoResults from './link-search-no-results';
20
- export const RECENT_SEARCH_LIST_SIZE = 5;
21
-
22
- class LinkPicker extends PureComponent {
23
- constructor(props) {
24
- super(props);
25
-
26
- _defineProperty(this, "wrapperRef", /*#__PURE__*/React.createRef());
27
-
28
- _defineProperty(this, "queryVersion", 0);
29
-
30
- _defineProperty(this, "updateInput", async input => {
31
- // If input is a valid URL, do not search or display link suggestions
32
- if (input.length && isSafeUrl(input)) {
33
- return this.setState({
34
- url: input,
35
- selectedIndex: -1,
36
- items: [],
37
- isLoading: false,
38
- invalidUrl: null
39
- });
40
- }
41
-
42
- return this.setState({
43
- url: input,
44
- // Unset selection on any input change
45
- selectedIndex: -1,
46
- invalidUrl: null
47
- }, () => {
48
- this.updateResults();
49
- });
50
- });
51
-
52
- _defineProperty(this, "createClearHandler", field => {
53
- return () => {
54
- switch (field) {
55
- case 'url':
56
- {
57
- this.updateInput('');
58
- break;
59
- }
60
-
61
- case 'displayText':
62
- {
63
- this.setState({
64
- [field]: ''
65
- });
66
- }
67
- }
68
- };
69
- });
70
-
71
- _defineProperty(this, "getScreenReaderText", () => {
72
- const {
73
- intl
74
- } = this.props;
75
- const {
76
- items,
77
- selectedIndex
78
- } = this.state;
79
-
80
- if (items.length && selectedIndex > -1) {
81
- const {
82
- name,
83
- container,
84
- lastUpdatedDate,
85
- lastViewedDate
86
- } = items[selectedIndex];
87
- const date = transformTimeStamp(intl, lastViewedDate, lastUpdatedDate);
88
- const formattedDate = [date === null || date === void 0 ? void 0 : date.pageAction, date === null || date === void 0 ? void 0 : date.dateString, date === null || date === void 0 ? void 0 : date.timeSince].filter(Boolean).join(' ');
89
- return [name, container, formattedDate].filter(Boolean).join(', ');
90
- }
91
- });
92
-
93
- _defineProperty(this, "isUrlPopulatedWithSelectedItem", () => {
94
- /**
95
- * When we use ArrowKey to navigate through result items,
96
- * the URL field will be populated with the content of
97
- * selected item.
98
- * This function will check if the URL field is populated
99
- * with selected item.
100
- * It can be useful to detect whether we want to insert a
101
- * smartlink or a hyperlink with customized title
102
- */
103
- const {
104
- items,
105
- selectedIndex,
106
- url
107
- } = this.state;
108
- const selectedItem = items[selectedIndex];
109
-
110
- if (selectedItem && selectedItem.url === url) {
111
- return true;
112
- }
113
-
114
- return false;
115
- });
116
-
117
- _defineProperty(this, "handleSelected", objectId => {
118
- const {
119
- items
120
- } = this.state;
121
- const selectedItem = items.find(item => item.objectId === objectId);
122
-
123
- if (selectedItem) {
124
- const {
125
- url,
126
- name
127
- } = selectedItem;
128
- this.handleInsert(url, name, 'typeAhead');
129
- }
130
- });
131
-
132
- _defineProperty(this, "handleInsert", (url, title, inputType) => {
133
- const {
134
- onSubmit
135
- } = this.props;
136
- const {
137
- url: rawUrl,
138
- displayText
139
- } = this.state;
140
-
141
- if (onSubmit) {
142
- onSubmit({
143
- url,
144
- displayText: displayText || null,
145
- title: title || null,
146
- meta: {
147
- inputMethod: inputType
148
- },
149
- ...(inputType === 'manual' ? {
150
- rawUrl
151
- } : {})
152
- });
153
- }
154
- });
155
-
156
- _defineProperty(this, "handleMouseEnterResultItem", objectId => {
157
- const {
158
- items
159
- } = this.state;
160
- const index = findIndex(items, item => item.objectId === objectId);
161
- this.setState({
162
- activeIndex: index
163
- });
164
- });
165
-
166
- _defineProperty(this, "handleMouseLeaveResultItem", objectId => {
167
- const {
168
- items,
169
- activeIndex
170
- } = this.state;
171
- const index = findIndex(items, item => item.objectId === objectId); // This is to avoid updating index that was set by other mouseenter event
172
-
173
- if (activeIndex === index) {
174
- this.setState({
175
- activeIndex: -1
176
- });
177
- }
178
- });
179
-
180
- _defineProperty(this, "handleSubmit", () => {
181
- const {
182
- url,
183
- selectedIndex,
184
- items
185
- } = this.state;
186
- const selectedItem = items[selectedIndex];
187
-
188
- if (this.isUrlPopulatedWithSelectedItem()) {
189
- this.handleInsert(selectedItem.url, selectedItem.name, 'typeAhead');
190
- } else if (url.length > 0) {
191
- const normalized = normalizeUrl(url);
192
-
193
- if (normalized) {
194
- this.handleInsert(normalized, null, 'manual');
195
- } else {
196
- const {
197
- intl
198
- } = this.props;
199
- const linkInvalid = intl.formatMessage(messages.linkInvalid);
200
- this.setState({
201
- invalidUrl: linkInvalid
202
- });
203
- }
204
- }
205
- });
206
-
207
- _defineProperty(this, "handleKeyDown", event => {
208
- const {
209
- items,
210
- activeIndex
211
- } = this.state;
212
- const {
213
- keyCode
214
- } = event;
215
- const KEY_CODE_ARROW_DOWN = 40;
216
- const KEY_CODE_ARROW_UP = 38;
217
-
218
- if (!items || !items.length) {
219
- return;
220
- }
221
-
222
- let updatedIndex = activeIndex;
223
-
224
- switch (keyCode) {
225
- case KEY_CODE_ARROW_DOWN:
226
- // down
227
- event.preventDefault();
228
- updatedIndex = (activeIndex + 1) % items.length;
229
- break;
230
-
231
- case KEY_CODE_ARROW_UP:
232
- // up
233
- event.preventDefault();
234
- updatedIndex = activeIndex > 0 ? activeIndex - 1 : items.length - 1;
235
- break;
236
- }
237
-
238
- if ([KEY_CODE_ARROW_DOWN, KEY_CODE_ARROW_UP].includes(keyCode) && items[updatedIndex]) {
239
- this.setState({
240
- activeIndex: updatedIndex,
241
- selectedIndex: updatedIndex,
242
- url: items[updatedIndex].url,
243
- invalidUrl: null
244
- });
245
- }
246
- });
247
-
248
- _defineProperty(this, "handleCancel", () => {
249
- const {
250
- onCancel
251
- } = this.props;
252
-
253
- if (onCancel) {
254
- onCancel();
255
- }
256
- });
257
-
258
- _defineProperty(this, "updateTextInput", displayText => {
259
- this.setState({
260
- displayText: displayText
261
- });
262
- });
263
-
264
- this.state = {
265
- selectedIndex: -1,
266
- activeIndex: -1,
267
- isLoading: false,
268
- url: normalizeUrl(props.url) || '',
269
- displayText: props.displayText || '',
270
- items: [],
271
- invalidUrl: null
272
- };
273
- /* Cache functions */
274
-
275
- this.handleClearUrl = this.createClearHandler('url');
276
- this.handleClearDisplayText = this.createClearHandler('displayText');
277
- }
278
-
279
- componentDidMount() {
280
- this.loadInitialLinkSearchResult();
281
- }
282
-
283
- loadInitialLinkSearchResult() {
284
- const {
285
- url
286
- } = this.state;
287
-
288
- if (!url) {
289
- this.updateResults();
290
- }
291
- }
292
-
293
- getActivePlugin() {
294
- if (!this.props.plugins || this.props.plugins.length === 0) {
295
- return null;
296
- }
297
-
298
- return this.props.plugins[0];
299
- }
300
- /**
301
- * Interface between link picker and plugins to update results
302
- */
303
-
304
-
305
- async updateResults() {
306
- const queryVersion = ++this.queryVersion;
307
- const activePlugin = this.getActivePlugin();
308
-
309
- if (!activePlugin) {
310
- return;
311
- }
312
-
313
- const updates = activePlugin.resolve({
314
- query: this.state.url
315
- });
316
- this.setState({
317
- isLoading: true,
318
- items: []
319
- });
320
-
321
- try {
322
- while (queryVersion === this.queryVersion) {
323
- let done = false;
324
- let value;
325
-
326
- if (updates instanceof Promise) {
327
- done = true;
328
- value = await updates;
329
- } else {
330
- var _result$done;
331
-
332
- const result = await updates.next();
333
- done = (_result$done = result.done) !== null && _result$done !== void 0 ? _result$done : false;
334
- value = result.value;
335
- }
336
-
337
- if (queryVersion !== this.queryVersion) {
338
- return;
339
- }
340
-
341
- this.setState({
342
- items: limit(value.data),
343
- isLoading: !done
344
- });
345
-
346
- if (done) {
347
- return;
348
- }
349
- }
350
- } catch {
351
- this.setState({
352
- isLoading: false
353
- });
354
- }
355
- }
356
-
357
- render() {
358
- const {
359
- items,
360
- isLoading,
361
- activeIndex,
362
- selectedIndex,
363
- url,
364
- displayText
365
- } = this.state;
366
- const {
367
- intl: {
368
- formatMessage
369
- }
370
- } = this.props;
371
- const activePlugin = this.getActivePlugin();
372
- const linkPlaceHolder = formatMessage(activePlugin ? messages.placeholder : messages.linkPlaceholder);
373
- const linkLabel = formatMessage(messages.linkLabel);
374
- const linkTextLabel = formatMessage(messages.linkTextLabel);
375
- const linkTextPlaceHolder = formatMessage(messages.linkTextPlaceholder);
376
- const screenReaderDescriptionId = 'search-recent-links-field-description';
377
- const linkSearchListId = 'link-picker-search-list';
378
- const ariaActiveDescendant = selectedIndex > -1 ? `link-search-list-item-${selectedIndex}` : ''; // Added workaround with a screen reader Announcer specifically for VoiceOver + Safari
379
- // as the Aria design pattern for combobox does not work in this case
380
- // for details: https://a11y-internal.atlassian.net/browse/AK-740
381
-
382
- const screenReaderText = browser.safari && this.getScreenReaderText();
383
- const searchIcon = activePlugin && jsx("span", {
384
- css: searchIconStyles,
385
- "data-testid": "link-picker-search-icon"
386
- }, jsx(EditorSearchIcon, {
387
- size: "medium",
388
- label: ''
389
- }));
390
- const noResults = activePlugin && !isLoading && !items.length && !isSafeUrl(url);
391
- return jsx("div", {
392
- "data-testid": "link-picker",
393
- className: "recent-list",
394
- css: recentListStyles
395
- }, jsx("div", {
396
- css: containerStyles,
397
- ref: this.wrapperRef
398
- }, screenReaderText && jsx(Announcer, {
399
- ariaLive: "assertive",
400
- text: screenReaderText,
401
- ariaRelevant: "additions",
402
- delay: 250
403
- }), jsx(VisuallyHidden, null, jsx("span", {
404
- "aria-hidden": "true",
405
- id: screenReaderDescriptionId
406
- }, formatMessage(messages.searchLinkAriaDescription))), jsx(PanelTextInput, {
407
- name: "link",
408
- testId: "link-url",
409
- role: "combobox",
410
- label: linkLabel,
411
- placeholder: linkPlaceHolder,
412
- value: url,
413
- autoFocus: true,
414
- autoComplete: "off",
415
- elemBeforeInput: searchIcon,
416
- onSubmit: this.handleSubmit,
417
- onChange: this.updateInput,
418
- onKeyDown: this.handleKeyDown,
419
- onClear: this.handleClearUrl,
420
- error: this.state.invalidUrl,
421
- clearLabel: formatMessage(messages.clearLink),
422
- "aria-controls": linkSearchListId,
423
- "aria-autocomplete": "list",
424
- "aria-activedescendant": ariaActiveDescendant,
425
- "aria-describedby": screenReaderDescriptionId,
426
- "aria-expanded": true
427
- }), jsx(PanelTextInput, {
428
- name: "link-text",
429
- testId: "link-text",
430
- autoComplete: "off",
431
- label: linkTextLabel,
432
- placeholder: linkTextPlaceHolder,
433
- "aria-label": formatMessage(messages.linkAriaLabel),
434
- value: displayText,
435
- onSubmit: this.handleSubmit,
436
- onKeyDown: this.handleKeyDown,
437
- onChange: this.updateTextInput,
438
- onClear: this.handleClearDisplayText,
439
- clearLabel: formatMessage(messages.clearText)
440
- }), !!items.length && jsx("div", {
441
- css: listTitleStyles,
442
- id: "link-picker-list-title",
443
- "data-testid": "link-picker-list-title"
444
- }, formatMessage(this.state.url ? messages.titleResults : messages.titleRecentlyViewed)), jsx(VisuallyHidden, null, jsx("span", {
445
- "aria-live": "polite",
446
- "aria-atomic": "true",
447
- id: "fabric.smartcard.linkpicker.suggested.results"
448
- }, url && formatMessage(messages.searchLinkResults, {
449
- count: items.length
450
- }))), jsx(LinkSearchList, {
451
- ariaLabelledBy: "link-picker-list-title",
452
- ariaControls: "fabric.smartcard.linkpicker.suggested.results",
453
- id: linkSearchListId,
454
- role: "listbox",
455
- items: items,
456
- isLoading: isLoading,
457
- selectedIndex: selectedIndex,
458
- activeIndex: activeIndex,
459
- onSelect: this.handleSelected,
460
- onMouseEnter: this.handleMouseEnterResultItem,
461
- onMouseLeave: this.handleMouseLeaveResultItem
462
- }), noResults && jsx(LinkSearchNoResults, {
463
- testId: "link-search-no-results",
464
- header: formatMessage(messages.noResults),
465
- description: formatMessage(messages.noResultsDescription)
466
- }), jsx(FormFooter, {
467
- align: "end"
468
- }, jsx(ButtonGroup, null, jsx(Button, {
469
- appearance: "default",
470
- onClick: this.handleCancel,
471
- testId: "link-picker-cancel-button"
472
- }, formatMessage(messages.cancelButton)), jsx(Button, {
473
- type: "submit",
474
- appearance: "primary",
475
- onClick: this.handleSubmit,
476
- testId: "link-picker-insert-button"
477
- }, formatMessage(messages.insertButton))))));
478
- }
479
-
480
- }
481
-
482
- function findIndex(array, predicate) {
483
- let index = -1;
484
- array.some((item, i) => {
485
- if (predicate(item)) {
486
- index = i;
487
- return true;
488
- }
489
-
490
- return false;
491
- });
492
- return index;
493
- }
494
-
495
- function limit(items) {
496
- return items.slice(0, RECENT_SEARCH_LIST_SIZE);
497
- }
498
-
499
- export const LinkPickerWithIntl = injectIntl(LinkPicker);