@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.
- package/CHANGELOG.md +18 -0
- package/dist/cjs/analytics.codegen.js +28 -0
- package/dist/cjs/common/constants.js +10 -0
- package/dist/cjs/{ui/error-boundary-fallback → common}/generic-error-svg/index.js +0 -0
- package/dist/cjs/{ui/error-boundary-fallback → common}/generic-error-svg/styled.js +0 -0
- package/dist/cjs/services/use-plugins/index.js +32 -35
- package/dist/cjs/services/use-search-query/index.js +41 -0
- package/dist/cjs/ui/error-boundary-fallback/index.js +1 -1
- package/dist/cjs/ui/index.js +4 -4
- package/dist/cjs/ui/link-picker/index.js +68 -41
- package/dist/cjs/ui/link-picker/link-search-error/index.js +27 -0
- package/dist/cjs/ui/link-picker/messages.js +10 -0
- package/dist/cjs/ui/link-picker/url.js +0 -5
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/analytics.codegen.js +20 -0
- package/dist/es2019/common/constants.js +2 -0
- package/dist/es2019/{ui/error-boundary-fallback → common}/generic-error-svg/index.js +0 -0
- package/dist/es2019/{ui/error-boundary-fallback → common}/generic-error-svg/styled.js +0 -0
- package/dist/es2019/services/use-plugins/index.js +28 -38
- package/dist/es2019/services/use-search-query/index.js +32 -0
- package/dist/es2019/ui/error-boundary-fallback/index.js +1 -1
- package/dist/es2019/ui/index.js +1 -2
- package/dist/es2019/ui/link-picker/index.js +59 -40
- package/dist/es2019/ui/link-picker/link-search-error/index.js +10 -0
- package/dist/es2019/ui/link-picker/messages.js +10 -0
- package/dist/es2019/ui/link-picker/url.js +0 -5
- package/dist/es2019/version.json +1 -1
- package/dist/esm/analytics.codegen.js +20 -0
- package/dist/esm/common/constants.js +2 -0
- package/dist/esm/{ui/error-boundary-fallback → common}/generic-error-svg/index.js +0 -0
- package/dist/esm/{ui/error-boundary-fallback → common}/generic-error-svg/styled.js +0 -0
- package/dist/esm/services/use-plugins/index.js +33 -35
- package/dist/esm/services/use-search-query/index.js +32 -0
- package/dist/esm/ui/error-boundary-fallback/index.js +1 -1
- package/dist/esm/ui/index.js +1 -2
- package/dist/esm/ui/link-picker/index.js +61 -40
- package/dist/esm/ui/link-picker/link-search-error/index.js +14 -0
- package/dist/esm/ui/link-picker/messages.js +10 -0
- package/dist/esm/ui/link-picker/url.js +0 -5
- package/dist/esm/version.json +1 -1
- package/dist/types/analytics.codegen.d.ts +20 -0
- package/dist/types/common/constants.d.ts +2 -0
- package/dist/types/{ui/error-boundary-fallback → common}/generic-error-svg/index.d.ts +0 -0
- package/dist/types/{ui/error-boundary-fallback → common}/generic-error-svg/styled.d.ts +0 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/services/use-plugins/index.d.ts +6 -5
- package/dist/types/services/use-search-query/index.d.ts +3 -0
- package/dist/types/ui/link-picker/index.d.ts +2 -0
- package/dist/types/ui/link-picker/link-search-error/index.d.ts +4 -0
- package/dist/types/ui/link-picker/messages.d.ts +10 -0
- package/dist/types/ui/types.d.ts +5 -2
- package/package.json +12 -6
- package/report.api.md +21 -13
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { useEffect, useRef,
|
|
1
|
+
import { useEffect, useReducer, useMemo, useRef, useState, useCallback } from 'react';
|
|
2
2
|
import { RECENT_SEARCH_LIST_SIZE } from '../../ui/link-picker';
|
|
3
|
-
import { isSafeUrl } from '../../ui/link-picker/url';
|
|
4
3
|
|
|
5
4
|
function reducer(state, payload) {
|
|
6
5
|
return { ...state,
|
|
@@ -8,56 +7,40 @@ function reducer(state, payload) {
|
|
|
8
7
|
};
|
|
9
8
|
}
|
|
10
9
|
|
|
11
|
-
export function usePlugins(state, plugins) {
|
|
10
|
+
export function usePlugins(state, activeTab, plugins) {
|
|
11
|
+
const [retries, setRetries] = useState(0);
|
|
12
12
|
const [pluginState, dispatch] = useReducer(reducer, {
|
|
13
|
-
items:
|
|
13
|
+
items: null,
|
|
14
|
+
error: null,
|
|
14
15
|
isLoading: false
|
|
15
16
|
});
|
|
16
|
-
const {
|
|
17
|
-
url,
|
|
18
|
-
selectedIndex
|
|
19
|
-
} = state;
|
|
20
17
|
const {
|
|
21
18
|
items,
|
|
22
|
-
isLoading
|
|
19
|
+
isLoading,
|
|
20
|
+
error
|
|
23
21
|
} = pluginState;
|
|
24
|
-
const activePlugin = !plugins || plugins.length === 0 ? null : plugins[state.activeTab];
|
|
25
22
|
const queryVersion = useRef(0);
|
|
26
|
-
const
|
|
27
|
-
const selectedItem = items[selectedIndex];
|
|
28
|
-
const isSelectedItem = (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.url) === url;
|
|
23
|
+
const activePlugin = plugins === null || plugins === void 0 ? void 0 : plugins[activeTab];
|
|
29
24
|
useEffect(() => {
|
|
30
25
|
if (!activePlugin) {
|
|
31
26
|
return;
|
|
32
27
|
}
|
|
33
28
|
|
|
34
|
-
if (
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (isSafeUrl(url) && url.length) {
|
|
29
|
+
if (!state) {
|
|
39
30
|
dispatch({
|
|
40
|
-
items:
|
|
41
|
-
isLoading: false
|
|
31
|
+
items: null,
|
|
32
|
+
isLoading: false,
|
|
33
|
+
error: null
|
|
42
34
|
});
|
|
43
35
|
return;
|
|
44
36
|
}
|
|
45
37
|
|
|
46
|
-
const updates = activePlugin.resolve(
|
|
47
|
-
|
|
38
|
+
const updates = activePlugin.resolve(state);
|
|
39
|
+
dispatch({
|
|
40
|
+
items: null,
|
|
41
|
+
isLoading: true,
|
|
42
|
+
error: null
|
|
48
43
|
});
|
|
49
|
-
|
|
50
|
-
if (pluginRef.current !== activePlugin) {
|
|
51
|
-
dispatch({
|
|
52
|
-
items: [],
|
|
53
|
-
isLoading: true
|
|
54
|
-
});
|
|
55
|
-
} else {
|
|
56
|
-
dispatch({
|
|
57
|
-
isLoading: true
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
44
|
const newQuery = ++queryVersion.current;
|
|
62
45
|
|
|
63
46
|
const updateResults = async () => {
|
|
@@ -90,15 +73,17 @@ export function usePlugins(state, plugins) {
|
|
|
90
73
|
return;
|
|
91
74
|
}
|
|
92
75
|
}
|
|
93
|
-
} catch {
|
|
76
|
+
} catch (error) {
|
|
94
77
|
dispatch({
|
|
78
|
+
error,
|
|
79
|
+
items: null,
|
|
95
80
|
isLoading: false
|
|
96
81
|
});
|
|
97
82
|
}
|
|
98
83
|
};
|
|
99
84
|
|
|
100
85
|
updateResults();
|
|
101
|
-
}, [activePlugin, queryVersion,
|
|
86
|
+
}, [activePlugin, queryVersion, state, retries]);
|
|
102
87
|
const tabs = useMemo(() => {
|
|
103
88
|
if (!plugins || plugins.length <= 1) {
|
|
104
89
|
return [];
|
|
@@ -108,12 +93,17 @@ export function usePlugins(state, plugins) {
|
|
|
108
93
|
tabTitle: plugin.tabTitle
|
|
109
94
|
}));
|
|
110
95
|
}, [plugins]);
|
|
96
|
+
const handleRetry = useCallback(() => {
|
|
97
|
+
setRetries(prev => ++prev);
|
|
98
|
+
}, []);
|
|
111
99
|
return {
|
|
112
100
|
tabs,
|
|
113
101
|
items,
|
|
114
102
|
isLoading,
|
|
115
|
-
|
|
116
|
-
|
|
103
|
+
isActivePlugin: !!activePlugin,
|
|
104
|
+
error,
|
|
105
|
+
retry: handleRetry,
|
|
106
|
+
errorFallback: activePlugin === null || activePlugin === void 0 ? void 0 : activePlugin.errorFallback
|
|
117
107
|
};
|
|
118
108
|
}
|
|
119
109
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
import { isSafeUrl } from '../../ui/link-picker/url';
|
|
3
|
+
export function useSearchQuery(state) {
|
|
4
|
+
var _queryState$current;
|
|
5
|
+
|
|
6
|
+
const queryState = useRef(null);
|
|
7
|
+
/*
|
|
8
|
+
* When state contains a valid url AND is NOT selected from results
|
|
9
|
+
* queryState should be null to clear the items in plugin state
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
if (isSafeUrl(state.url) && state.selectedIndex === -1) {
|
|
13
|
+
queryState.current = null;
|
|
14
|
+
}
|
|
15
|
+
/*
|
|
16
|
+
* When state contains a search term e.g. Not a valid url return a query
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if (((_queryState$current = queryState.current) === null || _queryState$current === void 0 ? void 0 : _queryState$current.query) !== state.url && !isSafeUrl(state.url)) {
|
|
21
|
+
queryState.current = {
|
|
22
|
+
query: state.url
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/*
|
|
26
|
+
* When state contains a valid url and is selected from the list
|
|
27
|
+
* return current state to prevent triger a new plugin search
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
return queryState.current;
|
|
32
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx } from '@emotion/react';
|
|
3
3
|
import EmptyState from '@atlaskit/empty-state';
|
|
4
4
|
import { defineMessages, useIntl } from 'react-intl-next';
|
|
5
|
-
import GenericErrorSVG from '
|
|
5
|
+
import GenericErrorSVG from '../../common/generic-error-svg';
|
|
6
6
|
import { rootContainerStyles } from '../link-picker/styled';
|
|
7
7
|
const messages = defineMessages({
|
|
8
8
|
heading: {
|
package/dist/es2019/ui/index.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import React, { memo } from 'react';
|
|
2
2
|
import { AnalyticsErrorBoundary } from '@atlaskit/analytics-next';
|
|
3
3
|
import { LazySuspense, lazyForPaint } from 'react-loosely-lazy';
|
|
4
|
+
import { COMPONENT_NAME, ANALYTICS_CHANNEL } from '../common/constants';
|
|
4
5
|
import { name as packageName, version as packageVersion } from '../version.json';
|
|
5
6
|
import { ErrorBoundaryFallback } from './error-boundary-fallback';
|
|
6
7
|
import { LoaderFallback } from './loader-fallback';
|
|
7
|
-
const COMPONENT_NAME = 'LinkPicker';
|
|
8
|
-
const ANALYTICS_CHANNEL = 'media';
|
|
9
8
|
const PACKAGE_DATA = {
|
|
10
9
|
packageName,
|
|
11
10
|
packageVersion,
|
|
@@ -1,25 +1,31 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
2
|
|
|
3
3
|
/** @jsx jsx */
|
|
4
|
-
import { useCallback, useLayoutEffect, useReducer } from 'react';
|
|
4
|
+
import { Fragment, useCallback, useLayoutEffect, useReducer } from 'react';
|
|
5
5
|
import { jsx } from '@emotion/react';
|
|
6
6
|
import { useIntl, FormattedMessage } from 'react-intl-next';
|
|
7
|
+
import { useAnalyticsEvents } from '@atlaskit/analytics-next';
|
|
7
8
|
import Button, { ButtonGroup } from '@atlaskit/button';
|
|
8
9
|
import { FormFooter } from '@atlaskit/form';
|
|
9
10
|
import EditorSearchIcon from '@atlaskit/icon/glyph/editor/search';
|
|
10
11
|
import Tabs, { Tab, TabList } from '@atlaskit/tabs';
|
|
11
12
|
import VisuallyHidden from '@atlaskit/visually-hidden';
|
|
13
|
+
import createEventPayload from '../../analytics.codegen';
|
|
14
|
+
import { ANALYTICS_CHANNEL } from '../../common/constants';
|
|
15
|
+
import { usePlugins } from '../../services/use-plugins';
|
|
16
|
+
import { useSearchQuery } from '../../services/use-search-query';
|
|
12
17
|
import { messages } from './messages';
|
|
13
18
|
import PanelTextInput from './text-input';
|
|
14
19
|
import LinkSearchList from './link-search-list';
|
|
15
20
|
import { normalizeUrl, isSafeUrl } from './url';
|
|
16
21
|
import { rootContainerStyles, searchIconStyles, listTitleStyles, tabsWrapperStyles } from './styled';
|
|
17
22
|
import { browser } from './browser';
|
|
18
|
-
import { transformTimeStamp } from './transformTimeStamp';
|
|
19
23
|
import Announcer from './announcer';
|
|
20
24
|
import LinkSearchNoResults from './link-search-no-results';
|
|
21
|
-
import {
|
|
25
|
+
import { transformTimeStamp } from './transformTimeStamp';
|
|
26
|
+
import LinkSearchError from './link-search-error';
|
|
22
27
|
export const RECENT_SEARCH_LIST_SIZE = 5;
|
|
28
|
+
export const CONTACT_SUPPORT_LINK = 'https://support.atlassian.com/contact/';
|
|
23
29
|
export const testIds = {
|
|
24
30
|
linkPicker: 'link-picker',
|
|
25
31
|
urlInputField: 'link-url',
|
|
@@ -35,7 +41,8 @@ export const testIds = {
|
|
|
35
41
|
searchResultLoadingIndicator: 'link-picker.results-loading-indicator',
|
|
36
42
|
urlError: 'link-error',
|
|
37
43
|
tabList: 'link-picker-tabs',
|
|
38
|
-
tabItem: 'link-picker-tab'
|
|
44
|
+
tabItem: 'link-picker-tab',
|
|
45
|
+
searchError: 'link-search-error'
|
|
39
46
|
};
|
|
40
47
|
const initState = {
|
|
41
48
|
url: '',
|
|
@@ -68,6 +75,11 @@ function LinkPicker({
|
|
|
68
75
|
url: initUrl,
|
|
69
76
|
displayText: initDisplayText
|
|
70
77
|
}) {
|
|
78
|
+
var _queryState$query, _items$length, _errorFallback;
|
|
79
|
+
|
|
80
|
+
const {
|
|
81
|
+
createAnalyticsEvent
|
|
82
|
+
} = useAnalyticsEvents();
|
|
71
83
|
const [state, dispatch] = useReducer(reducer, { ...initState,
|
|
72
84
|
url: normalizeUrl(initUrl) || '',
|
|
73
85
|
displayText: initDisplayText || ''
|
|
@@ -77,17 +89,23 @@ function LinkPicker({
|
|
|
77
89
|
selectedIndex,
|
|
78
90
|
url,
|
|
79
91
|
displayText,
|
|
80
|
-
invalidUrl
|
|
92
|
+
invalidUrl,
|
|
93
|
+
activeTab
|
|
81
94
|
} = state;
|
|
82
|
-
const isEditing = !!initUrl;
|
|
83
95
|
const intl = useIntl();
|
|
96
|
+
const queryState = useSearchQuery(state);
|
|
84
97
|
const {
|
|
85
98
|
items,
|
|
86
99
|
isLoading,
|
|
87
|
-
isSelectedItem,
|
|
88
100
|
isActivePlugin,
|
|
89
|
-
tabs
|
|
90
|
-
|
|
101
|
+
tabs,
|
|
102
|
+
error,
|
|
103
|
+
retry,
|
|
104
|
+
errorFallback
|
|
105
|
+
} = usePlugins(queryState, activeTab, plugins);
|
|
106
|
+
const isEditing = !!initUrl;
|
|
107
|
+
const selectedItem = items === null || items === void 0 ? void 0 : items[selectedIndex];
|
|
108
|
+
const isSelectedItem = (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.url) === url;
|
|
91
109
|
useLayoutEffect(() => {
|
|
92
110
|
if (onContentResize) {
|
|
93
111
|
onContentResize();
|
|
@@ -145,13 +163,13 @@ function LinkPicker({
|
|
|
145
163
|
});
|
|
146
164
|
}, []);
|
|
147
165
|
const handleMouseEnterResultItem = useCallback(objectId => {
|
|
148
|
-
const index = findIndex(
|
|
166
|
+
const index = items === null || items === void 0 ? void 0 : items.findIndex(item => item.objectId === objectId);
|
|
149
167
|
dispatch({
|
|
150
|
-
activeIndex: index
|
|
168
|
+
activeIndex: index !== null && index !== void 0 ? index : -1
|
|
151
169
|
});
|
|
152
170
|
}, [items]);
|
|
153
171
|
const handleMouseLeaveResultItem = useCallback(objectId => {
|
|
154
|
-
const index = findIndex(
|
|
172
|
+
const index = items === null || items === void 0 ? void 0 : items.findIndex(item => item.objectId === objectId); // This is to avoid updating index that was set by other mouseenter event
|
|
155
173
|
|
|
156
174
|
if (activeIndex === index) {
|
|
157
175
|
dispatch({
|
|
@@ -160,6 +178,8 @@ function LinkPicker({
|
|
|
160
178
|
}
|
|
161
179
|
}, [activeIndex, items]);
|
|
162
180
|
const handleInsert = useCallback((url, title, inputType) => {
|
|
181
|
+
const event = createAnalyticsEvent(createEventPayload('form.submitted.linkPicker', {}));
|
|
182
|
+
event.fire(ANALYTICS_CHANNEL);
|
|
163
183
|
onSubmit({
|
|
164
184
|
url,
|
|
165
185
|
displayText: displayText || null,
|
|
@@ -171,9 +191,9 @@ function LinkPicker({
|
|
|
171
191
|
rawUrl: state.url
|
|
172
192
|
} : {})
|
|
173
193
|
});
|
|
174
|
-
}, [displayText, onSubmit, state.url]);
|
|
194
|
+
}, [displayText, onSubmit, state.url, createAnalyticsEvent]);
|
|
175
195
|
const handleSelected = useCallback(objectId => {
|
|
176
|
-
const selectedItem = items.find(item => item.objectId === objectId);
|
|
196
|
+
const selectedItem = items === null || items === void 0 ? void 0 : items.find(item => item.objectId === objectId);
|
|
177
197
|
|
|
178
198
|
if (selectedItem) {
|
|
179
199
|
const {
|
|
@@ -184,9 +204,7 @@ function LinkPicker({
|
|
|
184
204
|
}
|
|
185
205
|
}, [handleInsert, items]);
|
|
186
206
|
const handleSubmit = useCallback(() => {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (isSelectedItem) {
|
|
207
|
+
if (isSelectedItem && selectedItem) {
|
|
190
208
|
return handleInsert(selectedItem.url, selectedItem.name, 'typeAhead');
|
|
191
209
|
}
|
|
192
210
|
|
|
@@ -199,18 +217,18 @@ function LinkPicker({
|
|
|
199
217
|
return dispatch({
|
|
200
218
|
invalidUrl: true
|
|
201
219
|
});
|
|
202
|
-
}, [handleInsert, isSelectedItem,
|
|
220
|
+
}, [handleInsert, isSelectedItem, selectedItem, url]);
|
|
203
221
|
const linkPlaceHolder = isActivePlugin ? messages.placeholder : messages.linkPlaceholder;
|
|
204
|
-
const linkListTitle =
|
|
222
|
+
const 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;
|
|
205
223
|
const insertButtonMsg = isEditing ? messages.saveButton : messages.insertButton;
|
|
206
|
-
const noResults =
|
|
224
|
+
const noResults = (items === null || items === void 0 ? void 0 : items.length) === 0 && !error;
|
|
207
225
|
const screenReaderDescriptionId = 'search-recent-links-field-description';
|
|
208
226
|
const linkSearchListId = 'link-picker-search-list';
|
|
209
227
|
const ariaActiveDescendant = selectedIndex > -1 ? `link-search-list-item-${selectedIndex}` : ''; // Added workaround with a screen reader Announcer specifically for VoiceOver + Safari
|
|
210
228
|
// as the Aria design pattern for combobox does not work in this case
|
|
211
229
|
// for details: https://a11y-internal.atlassian.net/browse/AK-740
|
|
212
230
|
|
|
213
|
-
const screenReaderText = browser.safari && getScreenReaderText(items, selectedIndex, intl);
|
|
231
|
+
const screenReaderText = browser.safari && getScreenReaderText(items !== null && items !== void 0 ? items : [], selectedIndex, intl);
|
|
214
232
|
const searchIcon = isActivePlugin && jsx("span", {
|
|
215
233
|
css: searchIconStyles,
|
|
216
234
|
"data-testid": testIds.searchIcon
|
|
@@ -262,7 +280,7 @@ function LinkPicker({
|
|
|
262
280
|
onSubmit: handleSubmit,
|
|
263
281
|
onKeyDown: handleKeyDown,
|
|
264
282
|
onChange: handleChangeText
|
|
265
|
-
}), tabs.length > 0 && jsx("div", {
|
|
283
|
+
}), queryState && jsx(Fragment, null, tabs.length > 0 && jsx("div", {
|
|
266
284
|
css: tabsWrapperStyles
|
|
267
285
|
}, jsx(Tabs, {
|
|
268
286
|
id: testIds.tabList,
|
|
@@ -276,7 +294,7 @@ function LinkPicker({
|
|
|
276
294
|
}, jsx(TabList, null, tabs.map(tab => jsx(Tab, {
|
|
277
295
|
key: tab.tabTitle,
|
|
278
296
|
testId: testIds.tabItem
|
|
279
|
-
}, tab.tabTitle))))), !!items.length && jsx("div", {
|
|
297
|
+
}, tab.tabTitle))))), !!(items !== null && items !== void 0 && items.length) && jsx("div", {
|
|
280
298
|
css: listTitleStyles,
|
|
281
299
|
id: testIds.resultListTitle,
|
|
282
300
|
"data-testid": testIds.resultListTitle
|
|
@@ -284,7 +302,7 @@ function LinkPicker({
|
|
|
284
302
|
id: "fabric.smartcard.linkpicker.suggested.results"
|
|
285
303
|
}, url && jsx(FormattedMessage, _extends({}, messages.searchLinkResults, {
|
|
286
304
|
values: {
|
|
287
|
-
count: items.length
|
|
305
|
+
count: (_items$length = items === null || items === void 0 ? void 0 : items.length) !== null && _items$length !== void 0 ? _items$length : 0
|
|
288
306
|
},
|
|
289
307
|
"aria-live": "polite",
|
|
290
308
|
"aria-atomic": "true"
|
|
@@ -293,18 +311,32 @@ function LinkPicker({
|
|
|
293
311
|
ariaControls: "fabric.smartcard.linkpicker.suggested.results",
|
|
294
312
|
id: linkSearchListId,
|
|
295
313
|
role: "listbox",
|
|
296
|
-
items: items,
|
|
314
|
+
items: items !== null && items !== void 0 ? items : [],
|
|
297
315
|
isLoading: isLoading,
|
|
298
316
|
selectedIndex: selectedIndex,
|
|
299
317
|
activeIndex: activeIndex,
|
|
300
318
|
onSelect: handleSelected,
|
|
301
319
|
onMouseEnter: handleMouseEnterResultItem,
|
|
302
320
|
onMouseLeave: handleMouseLeaveResultItem
|
|
303
|
-
}),
|
|
321
|
+
}), error && ((_errorFallback = errorFallback === null || errorFallback === void 0 ? void 0 : errorFallback(error, retry)) !== null && _errorFallback !== void 0 ? _errorFallback : jsx(LinkSearchError, {
|
|
322
|
+
testId: testIds.searchError,
|
|
323
|
+
header: intl.formatMessage(messages.searchErrorHeader),
|
|
324
|
+
description: jsx(FormattedMessage, _extends({}, messages.searchErrorDescription, {
|
|
325
|
+
values: {
|
|
326
|
+
a: label => jsx(Button, {
|
|
327
|
+
appearance: "link",
|
|
328
|
+
spacing: "none",
|
|
329
|
+
href: CONTACT_SUPPORT_LINK,
|
|
330
|
+
target: "_blank",
|
|
331
|
+
rel: "noopener noreferrer"
|
|
332
|
+
}, label)
|
|
333
|
+
}
|
|
334
|
+
}))
|
|
335
|
+
})), noResults && jsx(LinkSearchNoResults, {
|
|
304
336
|
testId: testIds.emptyResultPage,
|
|
305
337
|
header: intl.formatMessage(messages.noResults),
|
|
306
338
|
description: intl.formatMessage(messages.noResultsDescription)
|
|
307
|
-
}), jsx(FormFooter, {
|
|
339
|
+
})), jsx(FormFooter, {
|
|
308
340
|
align: "end"
|
|
309
341
|
}, jsx(ButtonGroup, null, jsx(Button, {
|
|
310
342
|
appearance: "default",
|
|
@@ -332,17 +364,4 @@ function getScreenReaderText(items, selectedIndex, intl) {
|
|
|
332
364
|
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(' ');
|
|
333
365
|
return [name, container, formattedDate].filter(Boolean).join(', ');
|
|
334
366
|
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
function findIndex(array, predicate) {
|
|
338
|
-
let index = -1;
|
|
339
|
-
array.some((item, i) => {
|
|
340
|
-
if (predicate(item)) {
|
|
341
|
-
index = i;
|
|
342
|
-
return true;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
return false;
|
|
346
|
-
});
|
|
347
|
-
return index;
|
|
348
367
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import EmptyState from '@atlaskit/empty-state';
|
|
4
|
+
import GenericErrorSVG from '../../../common/generic-error-svg';
|
|
5
|
+
|
|
6
|
+
const LinkSearchError = props => /*#__PURE__*/React.createElement(EmptyState, _extends({}, props, {
|
|
7
|
+
renderImage: () => /*#__PURE__*/React.createElement(GenericErrorSVG, null)
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
export default LinkSearchError;
|
|
@@ -104,5 +104,15 @@ export const messages = defineMessages({
|
|
|
104
104
|
id: 'fabric.linkPicker.button.save',
|
|
105
105
|
defaultMessage: 'Save',
|
|
106
106
|
description: 'Button to save edited link'
|
|
107
|
+
},
|
|
108
|
+
searchErrorHeader: {
|
|
109
|
+
id: 'fabric.linkPicker.search.error.heading',
|
|
110
|
+
defaultMessage: 'We’re having trouble loading data.',
|
|
111
|
+
description: 'Heading message shown when a search throws an error'
|
|
112
|
+
},
|
|
113
|
+
searchErrorDescription: {
|
|
114
|
+
id: 'fabric.linkPicker.search.error.description',
|
|
115
|
+
defaultMessage: 'Refresh the page, or contact <a>Atlassian Support</a> if this keeps happening.',
|
|
116
|
+
description: 'Describes possible actions when search throws an error'
|
|
107
117
|
}
|
|
108
118
|
});
|
package/dist/es2019/version.json
CHANGED
|
@@ -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
|
+
var 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;
|
|
File without changes
|
|
File without changes
|
|
@@ -7,64 +7,53 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
7
7
|
|
|
8
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
9
|
|
|
10
|
-
import { useEffect, useRef,
|
|
10
|
+
import { useEffect, useReducer, useMemo, useRef, useState, useCallback } from 'react';
|
|
11
11
|
import { RECENT_SEARCH_LIST_SIZE } from '../../ui/link-picker';
|
|
12
|
-
import { isSafeUrl } from '../../ui/link-picker/url';
|
|
13
12
|
|
|
14
13
|
function reducer(state, payload) {
|
|
15
14
|
return _objectSpread(_objectSpread({}, state), payload);
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
export function usePlugins(state, plugins) {
|
|
17
|
+
export function usePlugins(state, activeTab, plugins) {
|
|
18
|
+
var _useState = useState(0),
|
|
19
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
20
|
+
retries = _useState2[0],
|
|
21
|
+
setRetries = _useState2[1];
|
|
22
|
+
|
|
19
23
|
var _useReducer = useReducer(reducer, {
|
|
20
|
-
items:
|
|
24
|
+
items: null,
|
|
25
|
+
error: null,
|
|
21
26
|
isLoading: false
|
|
22
27
|
}),
|
|
23
28
|
_useReducer2 = _slicedToArray(_useReducer, 2),
|
|
24
29
|
pluginState = _useReducer2[0],
|
|
25
30
|
dispatch = _useReducer2[1];
|
|
26
31
|
|
|
27
|
-
var url = state.url,
|
|
28
|
-
selectedIndex = state.selectedIndex;
|
|
29
32
|
var items = pluginState.items,
|
|
30
|
-
isLoading = pluginState.isLoading
|
|
31
|
-
|
|
33
|
+
isLoading = pluginState.isLoading,
|
|
34
|
+
error = pluginState.error;
|
|
32
35
|
var queryVersion = useRef(0);
|
|
33
|
-
var
|
|
34
|
-
var selectedItem = items[selectedIndex];
|
|
35
|
-
var isSelectedItem = (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.url) === url;
|
|
36
|
+
var activePlugin = plugins === null || plugins === void 0 ? void 0 : plugins[activeTab];
|
|
36
37
|
useEffect(function () {
|
|
37
38
|
if (!activePlugin) {
|
|
38
39
|
return;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
if (
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (isSafeUrl(url) && url.length) {
|
|
42
|
+
if (!state) {
|
|
46
43
|
dispatch({
|
|
47
|
-
items:
|
|
48
|
-
isLoading: false
|
|
44
|
+
items: null,
|
|
45
|
+
isLoading: false,
|
|
46
|
+
error: null
|
|
49
47
|
});
|
|
50
48
|
return;
|
|
51
49
|
}
|
|
52
50
|
|
|
53
|
-
var updates = activePlugin.resolve(
|
|
54
|
-
|
|
51
|
+
var updates = activePlugin.resolve(state);
|
|
52
|
+
dispatch({
|
|
53
|
+
items: null,
|
|
54
|
+
isLoading: true,
|
|
55
|
+
error: null
|
|
55
56
|
});
|
|
56
|
-
|
|
57
|
-
if (pluginRef.current !== activePlugin) {
|
|
58
|
-
dispatch({
|
|
59
|
-
items: [],
|
|
60
|
-
isLoading: true
|
|
61
|
-
});
|
|
62
|
-
} else {
|
|
63
|
-
dispatch({
|
|
64
|
-
isLoading: true
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
57
|
var newQuery = ++queryVersion.current;
|
|
69
58
|
|
|
70
59
|
var updateResults = /*#__PURE__*/function () {
|
|
@@ -142,6 +131,8 @@ export function usePlugins(state, plugins) {
|
|
|
142
131
|
_context.prev = 25;
|
|
143
132
|
_context.t0 = _context["catch"](0);
|
|
144
133
|
dispatch({
|
|
134
|
+
error: _context.t0,
|
|
135
|
+
items: null,
|
|
145
136
|
isLoading: false
|
|
146
137
|
});
|
|
147
138
|
|
|
@@ -159,7 +150,7 @@ export function usePlugins(state, plugins) {
|
|
|
159
150
|
}();
|
|
160
151
|
|
|
161
152
|
updateResults();
|
|
162
|
-
}, [activePlugin, queryVersion,
|
|
153
|
+
}, [activePlugin, queryVersion, state, retries]);
|
|
163
154
|
var tabs = useMemo(function () {
|
|
164
155
|
if (!plugins || plugins.length <= 1) {
|
|
165
156
|
return [];
|
|
@@ -173,12 +164,19 @@ export function usePlugins(state, plugins) {
|
|
|
173
164
|
};
|
|
174
165
|
});
|
|
175
166
|
}, [plugins]);
|
|
167
|
+
var handleRetry = useCallback(function () {
|
|
168
|
+
setRetries(function (prev) {
|
|
169
|
+
return ++prev;
|
|
170
|
+
});
|
|
171
|
+
}, []);
|
|
176
172
|
return {
|
|
177
173
|
tabs: tabs,
|
|
178
174
|
items: items,
|
|
179
175
|
isLoading: isLoading,
|
|
180
|
-
|
|
181
|
-
|
|
176
|
+
isActivePlugin: !!activePlugin,
|
|
177
|
+
error: error,
|
|
178
|
+
retry: handleRetry,
|
|
179
|
+
errorFallback: activePlugin === null || activePlugin === void 0 ? void 0 : activePlugin.errorFallback
|
|
182
180
|
};
|
|
183
181
|
}
|
|
184
182
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
import { isSafeUrl } from '../../ui/link-picker/url';
|
|
3
|
+
export function useSearchQuery(state) {
|
|
4
|
+
var _queryState$current;
|
|
5
|
+
|
|
6
|
+
var queryState = useRef(null);
|
|
7
|
+
/*
|
|
8
|
+
* When state contains a valid url AND is NOT selected from results
|
|
9
|
+
* queryState should be null to clear the items in plugin state
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
if (isSafeUrl(state.url) && state.selectedIndex === -1) {
|
|
13
|
+
queryState.current = null;
|
|
14
|
+
}
|
|
15
|
+
/*
|
|
16
|
+
* When state contains a search term e.g. Not a valid url return a query
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if (((_queryState$current = queryState.current) === null || _queryState$current === void 0 ? void 0 : _queryState$current.query) !== state.url && !isSafeUrl(state.url)) {
|
|
21
|
+
queryState.current = {
|
|
22
|
+
query: state.url
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/*
|
|
26
|
+
* When state contains a valid url and is selected from the list
|
|
27
|
+
* return current state to prevent triger a new plugin search
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
return queryState.current;
|
|
32
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx } from '@emotion/react';
|
|
3
3
|
import EmptyState from '@atlaskit/empty-state';
|
|
4
4
|
import { defineMessages, useIntl } from 'react-intl-next';
|
|
5
|
-
import GenericErrorSVG from '
|
|
5
|
+
import GenericErrorSVG from '../../common/generic-error-svg';
|
|
6
6
|
import { rootContainerStyles } from '../link-picker/styled';
|
|
7
7
|
var messages = defineMessages({
|
|
8
8
|
heading: {
|
package/dist/esm/ui/index.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import React, { memo } from 'react';
|
|
2
2
|
import { AnalyticsErrorBoundary } from '@atlaskit/analytics-next';
|
|
3
3
|
import { LazySuspense, lazyForPaint } from 'react-loosely-lazy';
|
|
4
|
+
import { COMPONENT_NAME, ANALYTICS_CHANNEL } from '../common/constants';
|
|
4
5
|
import { name as packageName, version as packageVersion } from '../version.json';
|
|
5
6
|
import { ErrorBoundaryFallback } from './error-boundary-fallback';
|
|
6
7
|
import { LoaderFallback } from './loader-fallback';
|
|
7
|
-
var COMPONENT_NAME = 'LinkPicker';
|
|
8
|
-
var ANALYTICS_CHANNEL = 'media';
|
|
9
8
|
var PACKAGE_DATA = {
|
|
10
9
|
packageName: packageName,
|
|
11
10
|
packageVersion: packageVersion,
|