@atlaskit/link-picker 1.16.9 → 1.16.10

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 (153) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/cjs/analytics.codegen.js +1 -2
  3. package/dist/cjs/common/analytics/context.js +11 -36
  4. package/dist/cjs/common/analytics/experiences.js +0 -13
  5. package/dist/cjs/common/analytics/index.js +0 -2
  6. package/dist/cjs/common/analytics/input-field-tracking.js +16 -35
  7. package/dist/cjs/common/generic-error-svg/index.js +1 -7
  8. package/dist/cjs/common/generic-error-svg/styled.js +0 -6
  9. package/dist/cjs/common/utils/errors.js +0 -15
  10. package/dist/cjs/controllers/session-provider/index.js +1 -17
  11. package/dist/cjs/controllers/use-fix-height/index.js +0 -3
  12. package/dist/cjs/i18n/cs.js +0 -1
  13. package/dist/cjs/i18n/da.js +0 -1
  14. package/dist/cjs/i18n/de.js +0 -1
  15. package/dist/cjs/i18n/en.js +0 -1
  16. package/dist/cjs/i18n/en_GB.js +0 -1
  17. package/dist/cjs/i18n/es.js +0 -1
  18. package/dist/cjs/i18n/fi.js +0 -1
  19. package/dist/cjs/i18n/fr.js +0 -1
  20. package/dist/cjs/i18n/hu.js +0 -1
  21. package/dist/cjs/i18n/it.js +0 -1
  22. package/dist/cjs/i18n/ja.js +0 -1
  23. package/dist/cjs/i18n/ko.js +0 -1
  24. package/dist/cjs/i18n/nb.js +0 -1
  25. package/dist/cjs/i18n/nl.js +0 -1
  26. package/dist/cjs/i18n/pl.js +0 -1
  27. package/dist/cjs/i18n/pt_BR.js +0 -1
  28. package/dist/cjs/i18n/ru.js +0 -1
  29. package/dist/cjs/i18n/sv.js +0 -1
  30. package/dist/cjs/i18n/th.js +0 -1
  31. package/dist/cjs/i18n/tr.js +0 -1
  32. package/dist/cjs/i18n/uk.js +0 -1
  33. package/dist/cjs/i18n/vi.js +0 -1
  34. package/dist/cjs/i18n/zh.js +0 -1
  35. package/dist/cjs/i18n/zh_TW.js +0 -1
  36. package/dist/cjs/index.js +0 -2
  37. package/dist/cjs/services/use-plugins/index.js +13 -44
  38. package/dist/cjs/services/use-plugins/reducer.js +0 -13
  39. package/dist/cjs/services/use-plugins/utils.js +9 -35
  40. package/dist/cjs/services/use-search-query/index.js +3 -9
  41. package/dist/cjs/ui/error-boundary/error-boundary-base/index.js +2 -22
  42. package/dist/cjs/ui/error-boundary/error-boundary-fallback/index.js +1 -9
  43. package/dist/cjs/ui/error-boundary/index.js +3 -18
  44. package/dist/cjs/ui/index.js +0 -13
  45. package/dist/cjs/ui/link-picker/announcer.js +15 -25
  46. package/dist/cjs/ui/link-picker/browser.js +0 -1
  47. package/dist/cjs/ui/link-picker/form-footer/index.js +6 -26
  48. package/dist/cjs/ui/link-picker/form-footer/styled.js +0 -5
  49. package/dist/cjs/ui/link-picker/form-footer/utils.js +2 -8
  50. package/dist/cjs/ui/link-picker/index.js +44 -111
  51. package/dist/cjs/ui/link-picker/link-search-error/index.js +1 -10
  52. package/dist/cjs/ui/link-picker/link-search-list/index.js +12 -38
  53. package/dist/cjs/ui/link-picker/link-search-list/link-search-no-results/index.js +1 -9
  54. package/dist/cjs/ui/link-picker/link-search-list/link-search-no-results/no-results-svg/index.js +1 -5
  55. package/dist/cjs/ui/link-picker/link-search-list/link-search-no-results/no-results-svg/styled.js +0 -6
  56. package/dist/cjs/ui/link-picker/link-search-list/link-search-no-results/styled.js +0 -5
  57. package/dist/cjs/ui/link-picker/link-search-list/styled.js +0 -7
  58. package/dist/cjs/ui/link-picker/link-search-list/use-track-results-shown/index.js +11 -21
  59. package/dist/cjs/ui/link-picker/list-item/index.js +11 -32
  60. package/dist/cjs/ui/link-picker/list-item/styled.js +0 -13
  61. package/dist/cjs/ui/link-picker/messages.js +0 -2
  62. package/dist/cjs/ui/link-picker/styled.js +1 -8
  63. package/dist/cjs/ui/link-picker/text-input/index.js +9 -26
  64. package/dist/cjs/ui/link-picker/text-input/styled.js +0 -7
  65. package/dist/cjs/ui/link-picker/track-mount/index.js +1 -11
  66. package/dist/cjs/ui/link-picker/track-tab-viewed/index.js +2 -10
  67. package/dist/cjs/ui/link-picker/transformTimeStamp.js +0 -13
  68. package/dist/cjs/ui/link-picker/utils.js +11 -19
  69. package/dist/cjs/ui/loader-fallback/index.js +1 -5
  70. package/dist/cjs/ui/scrolling-tabs/index.js +6 -44
  71. package/dist/cjs/ui/scrolling-tabs/scrolling-tabs.js +4 -33
  72. package/dist/cjs/ui/scrolling-tabs/styles.js +0 -3
  73. package/dist/cjs/version.json +1 -1
  74. package/dist/es2019/analytics.codegen.js +1 -1
  75. package/dist/es2019/common/analytics/context.js +11 -13
  76. package/dist/es2019/common/analytics/experiences.js +0 -1
  77. package/dist/es2019/common/analytics/input-field-tracking.js +13 -12
  78. package/dist/es2019/common/generic-error-svg/index.js +0 -4
  79. package/dist/es2019/common/utils/errors.js +0 -1
  80. package/dist/es2019/controllers/session-provider/index.js +0 -4
  81. package/dist/es2019/controllers/use-fix-height/index.js +0 -2
  82. package/dist/es2019/services/use-plugins/index.js +2 -8
  83. package/dist/es2019/services/use-plugins/reducer.js +8 -8
  84. package/dist/es2019/services/use-plugins/utils.js +5 -6
  85. package/dist/es2019/services/use-search-query/index.js +3 -6
  86. package/dist/es2019/ui/error-boundary/error-boundary-base/index.js +0 -5
  87. package/dist/es2019/ui/error-boundary/index.js +2 -4
  88. package/dist/es2019/ui/index.js +1 -2
  89. package/dist/es2019/ui/link-picker/announcer.js +6 -1
  90. package/dist/es2019/ui/link-picker/browser.js +0 -2
  91. package/dist/es2019/ui/link-picker/form-footer/index.js +0 -5
  92. package/dist/es2019/ui/link-picker/form-footer/utils.js +2 -5
  93. package/dist/es2019/ui/link-picker/index.js +21 -37
  94. package/dist/es2019/ui/link-picker/link-search-error/index.js +0 -3
  95. package/dist/es2019/ui/link-picker/link-search-list/index.js +2 -6
  96. package/dist/es2019/ui/link-picker/link-search-list/link-search-no-results/index.js +0 -2
  97. package/dist/es2019/ui/link-picker/link-search-list/link-search-no-results/no-results-svg/index.js +0 -3
  98. package/dist/es2019/ui/link-picker/link-search-list/styled.js +2 -2
  99. package/dist/es2019/ui/link-picker/link-search-list/use-track-results-shown/index.js +7 -5
  100. package/dist/es2019/ui/link-picker/list-item/index.js +0 -14
  101. package/dist/es2019/ui/link-picker/list-item/styled.js +2 -4
  102. package/dist/es2019/ui/link-picker/styled.js +1 -1
  103. package/dist/es2019/ui/link-picker/text-input/index.js +0 -6
  104. package/dist/es2019/ui/link-picker/track-mount/index.js +1 -2
  105. package/dist/es2019/ui/link-picker/track-tab-viewed/index.js +0 -2
  106. package/dist/es2019/ui/link-picker/transformTimeStamp.js +0 -7
  107. package/dist/es2019/ui/link-picker/utils.js +7 -5
  108. package/dist/es2019/ui/scrolling-tabs/index.js +2 -14
  109. package/dist/es2019/ui/scrolling-tabs/scrolling-tabs.js +0 -14
  110. package/dist/es2019/version.json +1 -1
  111. package/dist/esm/analytics.codegen.js +1 -1
  112. package/dist/esm/common/analytics/context.js +11 -21
  113. package/dist/esm/common/analytics/experiences.js +0 -3
  114. package/dist/esm/common/analytics/input-field-tracking.js +16 -22
  115. package/dist/esm/common/generic-error-svg/index.js +0 -4
  116. package/dist/esm/common/generic-error-svg/styled.js +0 -2
  117. package/dist/esm/common/utils/errors.js +0 -8
  118. package/dist/esm/controllers/session-provider/index.js +1 -7
  119. package/dist/esm/controllers/use-fix-height/index.js +0 -2
  120. package/dist/esm/services/use-plugins/index.js +13 -31
  121. package/dist/esm/services/use-plugins/reducer.js +0 -7
  122. package/dist/esm/services/use-plugins/utils.js +9 -22
  123. package/dist/esm/services/use-search-query/index.js +3 -6
  124. package/dist/esm/ui/error-boundary/error-boundary-base/index.js +2 -13
  125. package/dist/esm/ui/error-boundary/index.js +3 -5
  126. package/dist/esm/ui/index.js +1 -2
  127. package/dist/esm/ui/link-picker/announcer.js +20 -17
  128. package/dist/esm/ui/link-picker/browser.js +0 -2
  129. package/dist/esm/ui/link-picker/form-footer/index.js +6 -12
  130. package/dist/esm/ui/link-picker/form-footer/styled.js +0 -2
  131. package/dist/esm/ui/link-picker/form-footer/utils.js +2 -5
  132. package/dist/esm/ui/link-picker/index.js +44 -74
  133. package/dist/esm/ui/link-picker/link-search-error/index.js +0 -3
  134. package/dist/esm/ui/link-picker/link-search-list/index.js +12 -20
  135. package/dist/esm/ui/link-picker/link-search-list/link-search-no-results/index.js +0 -2
  136. package/dist/esm/ui/link-picker/link-search-list/link-search-no-results/no-results-svg/index.js +0 -3
  137. package/dist/esm/ui/link-picker/link-search-list/link-search-no-results/no-results-svg/styled.js +0 -2
  138. package/dist/esm/ui/link-picker/link-search-list/link-search-no-results/styled.js +0 -2
  139. package/dist/esm/ui/link-picker/link-search-list/styled.js +2 -4
  140. package/dist/esm/ui/link-picker/link-search-list/use-track-results-shown/index.js +11 -11
  141. package/dist/esm/ui/link-picker/list-item/index.js +10 -25
  142. package/dist/esm/ui/link-picker/list-item/styled.js +2 -6
  143. package/dist/esm/ui/link-picker/styled.js +1 -3
  144. package/dist/esm/ui/link-picker/text-input/index.js +9 -16
  145. package/dist/esm/ui/link-picker/text-input/styled.js +0 -2
  146. package/dist/esm/ui/link-picker/track-mount/index.js +2 -4
  147. package/dist/esm/ui/link-picker/track-tab-viewed/index.js +1 -5
  148. package/dist/esm/ui/link-picker/transformTimeStamp.js +0 -7
  149. package/dist/esm/ui/link-picker/utils.js +11 -9
  150. package/dist/esm/ui/scrolling-tabs/index.js +6 -28
  151. package/dist/esm/ui/scrolling-tabs/scrolling-tabs.js +4 -19
  152. package/dist/esm/version.json +1 -1
  153. package/package.json +2 -2
@@ -4,18 +4,16 @@ import { useAnalyticsEvents } from '@atlaskit/analytics-next';
4
4
  import { ANALYTICS_CHANNEL } from '../constants';
5
5
  import createEventPayload from '../../analytics.codegen';
6
6
  import { useLinkPickerAnalytics } from '.';
7
-
8
7
  const isEventWithInputType = e => {
9
8
  return typeof e === 'object' && e !== null && 'inputType' in e;
10
9
  };
11
-
12
10
  const getChangeEventInputMethodType = event => {
13
11
  if (isEventWithInputType(event.nativeEvent) && typeof event.nativeEvent.inputType === 'string' && event.nativeEvent.inputType.includes('insertFromPaste')) {
14
12
  return 'paste';
15
13
  }
16
-
17
14
  return 'manual';
18
15
  };
16
+
19
17
  /**
20
18
  * Wraps an input field and connects it to the link picker analytics context to provide a baseline of analytics tracking
21
19
  * @param WrappedComponent The input field to be tracked
@@ -23,9 +21,8 @@ const getChangeEventInputMethodType = event => {
23
21
  * @param filterOnChangeEventAttrs Function to hook into and filter/customise the default attribute tracking logic
24
22
  * @returns HOC Input field with tracking
25
23
  */
26
-
27
-
28
- export const withInputFieldTracking = (WrappedComponent, field, filterOnChangeEventAttrs = (_, attributes) => attributes // TODO: Consider refactor to use template literal type if it makes these more usable / safe / dev friendly
24
+ export const withInputFieldTracking = (WrappedComponent, field, filterOnChangeEventAttrs = (_, attributes) => attributes
25
+ // TODO: Consider refactor to use template literal type if it makes these more usable / safe / dev friendly
29
26
  // contentTypeFn: (value: string) => LinkPickerAnalyticsContextType[`${Field}FieldContent`],
30
27
  ) => {
31
28
  return props => {
@@ -41,10 +38,12 @@ export const withInputFieldTracking = (WrappedComponent, field, filterOnChangeEv
41
38
  } = useLinkPickerAnalytics();
42
39
  const {
43
40
  createAnalyticsEvent
44
- } = useAnalyticsEvents(); // Ref to track if the value of the field has changed between focus and blur
41
+ } = useAnalyticsEvents();
45
42
 
46
- const valueOnFocus = useRef(null); // Track the content and input method on every direct change to the input
43
+ // Ref to track if the value of the field has changed between focus and blur
44
+ const valueOnFocus = useRef(null);
47
45
 
46
+ // Track the content and input method on every direct change to the input
48
47
  const handleOnChange = useCallback(event => {
49
48
  // TODO: See above re template literal, improve typesafety here
50
49
  // trackAttribute(`${field}FieldContent`, contentTypeFn(event.currentTarget.value));
@@ -54,22 +53,24 @@ export const withInputFieldTracking = (WrappedComponent, field, filterOnChangeEv
54
53
  [`${field}FieldContentInputMethod`]: getChangeEventInputMethodType(event)
55
54
  }));
56
55
  onChange === null || onChange === void 0 ? void 0 : onChange(event);
57
- }, [onChange, trackAttributes]); // Store the value of the field at the time the field is focused so we can know if it changes when the user's focus leaves
56
+ }, [onChange, trackAttributes]);
58
57
 
58
+ // Store the value of the field at the time the field is focused so we can know if it changes when the user's focus leaves
59
59
  const handleOnFocus = useCallback(event => {
60
60
  valueOnFocus.current = event.currentTarget.value;
61
61
  onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
62
- }, [onFocus]); // Fire updated events only when the user's focus leaves the field
62
+ }, [onFocus]);
63
63
 
64
+ // Fire updated events only when the user's focus leaves the field
64
65
  const handleOnBlur = useCallback(event => {
65
66
  // Only fire if the value has changed since the field was focused (we are only concerned with the net change to the field)
66
67
  if (event.currentTarget.value !== valueOnFocus.current) {
67
68
  createAnalyticsEvent(createEventPayload(`ui.textField.updated.${field}Field`, {})).fire(ANALYTICS_CHANNEL);
68
69
  }
69
-
70
70
  onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
71
- }, [onBlur, createAnalyticsEvent]); // Track the values as null when the text field is cleared
71
+ }, [onBlur, createAnalyticsEvent]);
72
72
 
73
+ // Track the values as null when the text field is cleared
73
74
  const handleOnClear = useCallback((...args) => {
74
75
  trackAttribute(`${field}FieldContent`, null);
75
76
  trackAttribute(`${field}FieldContentInputMethod`, null);
@@ -1,11 +1,8 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
-
3
2
  /* eslint-disable @atlaskit/design-system/ensure-design-token-usage */
4
-
5
3
  /** @jsx jsx */
6
4
  import { jsx } from '@emotion/react';
7
5
  import { genericErrorStyles } from './styled';
8
-
9
6
  const GenericErrorSVG = props => {
10
7
  const id = 'link-picker-ui-generic-error-svg';
11
8
  return jsx("svg", _extends({
@@ -52,5 +49,4 @@ const GenericErrorSVG = props => {
52
49
  stopOpacity: ".6"
53
50
  }))));
54
51
  };
55
-
56
52
  export default GenericErrorSVG;
@@ -5,5 +5,4 @@ export class UnauthenticatedError extends Error {
5
5
  this.authUrl = authUrl;
6
6
  this.description = description;
7
7
  }
8
-
9
8
  }
@@ -3,18 +3,14 @@ import { v4 as uuidv4 } from 'uuid';
3
3
  import { abortUfoExperience, startUfoExperience, ufoExperience } from '../../common/analytics/experiences';
4
4
  export const INIT_CONTEXT = 'SESSION_UNINITIALIZED';
5
5
  export const SessionContext = /*#__PURE__*/createContext(INIT_CONTEXT);
6
-
7
6
  const useConstructor = callback => {
8
7
  const hasBeenFired = useRef(false);
9
-
10
8
  if (!hasBeenFired.current) {
11
9
  callback();
12
10
  hasBeenFired.current = true;
13
11
  }
14
-
15
12
  return null;
16
13
  };
17
-
18
14
  export const LinkPickerSessionProvider = ({
19
15
  children
20
16
  }) => {
@@ -1,5 +1,4 @@
1
1
  import { useLayoutEffect, useRef } from 'react';
2
-
3
2
  const useFixHeight = shouldFixHeight => {
4
3
  const ref = useRef(null);
5
4
  const currentHeight = useRef(null);
@@ -15,5 +14,4 @@ const useFixHeight = shouldFixHeight => {
15
14
  } : undefined
16
15
  };
17
16
  };
18
-
19
17
  export default useFixHeight;
@@ -12,8 +12,9 @@ export function usePlugins(state, activeTab, plugins) {
12
12
  } = useAnalyticsEvents();
13
13
  const [retries, setRetries] = useState(0);
14
14
  const [pluginState, dispatch] = usePluginReducer();
15
- const activePlugin = plugins === null || plugins === void 0 ? void 0 : plugins[activeTab]; // This useEffect block must be called before any other to ensure onActivation is fired at before resolve
15
+ const activePlugin = plugins === null || plugins === void 0 ? void 0 : plugins[activeTab];
16
16
 
17
+ // This useEffect block must be called before any other to ensure onActivation is fired at before resolve
17
18
  useEffect(() => {
18
19
  if (activePlugin && activePlugin.UNSAFE_onActivation) {
19
20
  activePlugin.UNSAFE_onActivation();
@@ -23,14 +24,12 @@ export function usePlugins(state, activeTab, plugins) {
23
24
  if (!activePlugin) {
24
25
  return;
25
26
  }
26
-
27
27
  if (!state) {
28
28
  dispatch({
29
29
  type: 'CLEAR'
30
30
  });
31
31
  return;
32
32
  }
33
-
34
33
  dispatch({
35
34
  type: 'LOADING'
36
35
  });
@@ -38,11 +37,9 @@ export function usePlugins(state, activeTab, plugins) {
38
37
  next,
39
38
  cancel
40
39
  } = resolvePluginUpdates(activePlugin, state);
41
-
42
40
  const updateResults = async () => {
43
41
  try {
44
42
  let isLoading = true;
45
-
46
43
  while (isLoading) {
47
44
  const {
48
45
  value,
@@ -69,7 +66,6 @@ export function usePlugins(state, activeTab, plugins) {
69
66
  }
70
67
  }
71
68
  };
72
-
73
69
  updateResults();
74
70
  return cancel;
75
71
  }, [activePlugin, state, retries, createAnalyticsEvent, dispatch]);
@@ -77,7 +73,6 @@ export function usePlugins(state, activeTab, plugins) {
77
73
  if (!plugins || plugins.length <= 1) {
78
74
  return [];
79
75
  }
80
-
81
76
  return plugins.filter(plugin => !!plugin.tabTitle).map(plugin => ({
82
77
  tabTitle: plugin.tabTitle
83
78
  }));
@@ -101,7 +96,6 @@ export function usePlugins(state, activeTab, plugins) {
101
96
  errorFallback: activePlugin === null || activePlugin === void 0 ? void 0 : activePlugin.errorFallback
102
97
  };
103
98
  }
104
-
105
99
  function limit(items) {
106
100
  return items.slice(0, RECENT_SEARCH_LIST_SIZE);
107
101
  }
@@ -11,25 +11,25 @@ export const INITIAL_STATE = {
11
11
  export function reducer(state, action) {
12
12
  switch (action.type) {
13
13
  case ACTION_CLEAR:
14
- return { ...INITIAL_STATE
14
+ return {
15
+ ...INITIAL_STATE
15
16
  };
16
-
17
17
  case ACTION_LOADING:
18
- return { ...INITIAL_STATE,
18
+ return {
19
+ ...INITIAL_STATE,
19
20
  isLoading: true
20
21
  };
21
-
22
22
  case ACTION_SUCCESS:
23
- return { ...state,
23
+ return {
24
+ ...state,
24
25
  ...action.payload,
25
26
  error: null
26
27
  };
27
-
28
28
  case ACTION_ERRORED:
29
- return { ...INITIAL_STATE,
29
+ return {
30
+ ...INITIAL_STATE,
30
31
  error: action.payload
31
32
  };
32
-
33
33
  default:
34
34
  return state;
35
35
  }
@@ -11,14 +11,15 @@ export const cancellable = promise => {
11
11
  }
12
12
  };
13
13
  };
14
+
14
15
  /**
15
16
  * Wraps the resolve with a cancellation wrapper and makes promise + generator plugin resolves more compatible
16
17
  * Calling cancel for generator plugin prevents it from yielding any further updates
17
18
  */
18
-
19
19
  export const resolvePluginUpdates = (plugin, state) => {
20
- const updates = plugin.resolve(state); // Promise plugin
20
+ const updates = plugin.resolve(state);
21
21
 
22
+ // Promise plugin
22
23
  if (updates instanceof Promise) {
23
24
  const {
24
25
  promise,
@@ -31,9 +32,9 @@ export const resolvePluginUpdates = (plugin, state) => {
31
32
  done: true
32
33
  })
33
34
  };
34
- } // Generator plugin
35
-
35
+ }
36
36
 
37
+ // Generator plugin
37
38
  const cancellationCallbacks = [];
38
39
  let cancelled = false;
39
40
  return {
@@ -46,13 +47,11 @@ export const resolvePluginUpdates = (plugin, state) => {
46
47
  promise,
47
48
  cancel
48
49
  } = cancellable(updates.next());
49
-
50
50
  if (cancelled) {
51
51
  cancel();
52
52
  } else {
53
53
  cancellationCallbacks.push(cancel);
54
54
  }
55
-
56
55
  return promise;
57
56
  }
58
57
  };
@@ -2,33 +2,30 @@ import { useRef } from 'react';
2
2
  import { isSafeUrl } from '@atlaskit/linking-common/url';
3
3
  export function useSearchQuery(state) {
4
4
  var _queryState$current;
5
-
6
5
  const queryState = useRef(null);
6
+
7
7
  /*
8
8
  * When state contains a valid url AND is NOT selected from results, and the url was updated
9
9
  * from the textbox, queryState should be null to clear the items in plugin state.
10
10
  *
11
11
  * Checking `lastEditedBy` prevents the items being cleared when the tab is changed.
12
12
  */
13
-
14
13
  if (isSafeUrl(state.url) && state.selectedIndex === -1 && !state.preventHidingRecents) {
15
14
  queryState.current = null;
16
15
  }
16
+
17
17
  /*
18
18
  * When state contains a search term e.g. Not a valid url return a query
19
19
  */
20
-
21
-
22
20
  if (((_queryState$current = queryState.current) === null || _queryState$current === void 0 ? void 0 : _queryState$current.query) !== state.url && !isSafeUrl(state.url)) {
23
21
  queryState.current = {
24
22
  query: state.url
25
23
  };
26
24
  }
25
+
27
26
  /*
28
27
  * When state contains a valid url and is selected from the list
29
28
  * return current state to prevent triger a new plugin search
30
29
  */
31
-
32
-
33
30
  return queryState.current;
34
31
  }
@@ -7,7 +7,6 @@ export class BaseErrorBoundary extends Component {
7
7
  hasError: false
8
8
  };
9
9
  }
10
-
11
10
  componentDidCatch(error, info) {
12
11
  const {
13
12
  onError
@@ -17,7 +16,6 @@ export class BaseErrorBoundary extends Component {
17
16
  hasError: true
18
17
  });
19
18
  }
20
-
21
19
  render() {
22
20
  const {
23
21
  children,
@@ -26,12 +24,9 @@ export class BaseErrorBoundary extends Component {
26
24
  const {
27
25
  hasError
28
26
  } = this.state;
29
-
30
27
  if (hasError && ErrorComponent) {
31
28
  return /*#__PURE__*/React.createElement(ErrorComponent, null);
32
29
  }
33
-
34
30
  return children;
35
31
  }
36
-
37
32
  }
@@ -6,7 +6,6 @@ import { failUfoExperience, ufoExperience } from '../../common/analytics/experie
6
6
  import { useLinkPickerSessionId } from '../../controllers/session-provider';
7
7
  import { ErrorBoundaryFallback } from './error-boundary-fallback';
8
8
  import { BaseErrorBoundary } from './error-boundary-base';
9
-
10
9
  function ErrorBoundary({
11
10
  children,
12
11
  createAnalyticsEvent
@@ -14,14 +13,14 @@ function ErrorBoundary({
14
13
  const linkPickerSessionId = useLinkPickerSessionId();
15
14
  const handleError = useCallback((error, info) => {
16
15
  var _window, _window$navigator, _info$componentStack;
17
-
18
16
  // Fire Analytics event
19
17
  createAnalyticsEvent(createEventPayload('ui.linkPicker.unhandledErrorCaught', {
20
18
  browserInfo: ((_window = window) === null || _window === void 0 ? void 0 : (_window$navigator = _window.navigator) === null || _window$navigator === void 0 ? void 0 : _window$navigator.userAgent) || 'unknown',
21
19
  error: error.toString(),
22
20
  componentStack: (_info$componentStack = info === null || info === void 0 ? void 0 : info.componentStack) !== null && _info$componentStack !== void 0 ? _info$componentStack : ''
23
- })).fire(ANALYTICS_CHANNEL); // Fire UFO failed experience
21
+ })).fire(ANALYTICS_CHANNEL);
24
22
 
23
+ // Fire UFO failed experience
25
24
  failUfoExperience(ufoExperience.mounted, linkPickerSessionId);
26
25
  }, [createAnalyticsEvent, linkPickerSessionId]);
27
26
  return /*#__PURE__*/React.createElement(BaseErrorBoundary, {
@@ -29,5 +28,4 @@ function ErrorBoundary({
29
28
  ErrorComponent: ErrorBoundaryFallback
30
29
  }, children);
31
30
  }
32
-
33
31
  export default withAnalyticsEvents()(ErrorBoundary);
@@ -12,8 +12,7 @@ export const PACKAGE_DATA = {
12
12
  componentName: COMPONENT_NAME,
13
13
  source: COMPONENT_NAME
14
14
  };
15
- const LazyLinkPicker = lazyForPaint(() => import(
16
- /* webpackChunkName: "@atlaskit-internal_link-picker" */
15
+ const LazyLinkPicker = lazyForPaint(() => import( /* webpackChunkName: "@atlaskit-internal_link-picker" */
17
16
  './link-picker'));
18
17
  export const ComposedLinkPicker = /*#__PURE__*/memo(props => /*#__PURE__*/React.createElement(AnalyticsContext, {
19
18
  data: PACKAGE_DATA
@@ -1,13 +1,18 @@
1
- import React, { forwardRef, memo, useState, useEffect } from 'react'; // How to use:
1
+ import React, { forwardRef, memo, useState, useEffect } from 'react';
2
+
3
+ // How to use:
2
4
  // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions#Preferring_specialized_live_region_roles
3
5
  // Demo: https://dequeuniversity.com/library/aria/liveregion-playground
6
+
4
7
  // Important: Strongly recommend test your solution in all supported screen readers
5
8
  // if you use non default value of properties: ariaAtomic, ariaLive, ariaRelevant, role
9
+
6
10
  // Note: Text won't be announced if the text message doesn't change after the render.
7
11
  // For using a forced announcement in this case, set the 'key' attribute - key={Date.now()}
8
12
 
9
13
  // Note: Flag 'contentRendered' resolves bug with duplicates messages (NVDA + Firefox)
10
14
  // https://github.com/nvaccess/nvda/labels/bug%2Fdouble-speaking
15
+
11
16
  let timer;
12
17
  const Announcer = /*#__PURE__*/forwardRef(({
13
18
  ariaAtomic = 'true',
@@ -12,7 +12,6 @@ const result = {
12
12
  supportsIntersectionObserver: false,
13
13
  supportsResizeObserver: false
14
14
  };
15
-
16
15
  if (typeof navigator !== 'undefined') {
17
16
  const ieEdge = /Edge\/(\d+)/.exec(navigator.userAgent);
18
17
  const ieUpTo10 = /MSIE \d/.test(navigator.userAgent);
@@ -30,5 +29,4 @@ if (typeof navigator !== 'undefined') {
30
29
  result.supportsIntersectionObserver = typeof window !== 'undefined' && 'IntersectionObserver' in window && 'IntersectionObserverEntry' in window && 'intersectionRatio' in window.IntersectionObserverEntry.prototype;
31
30
  result.supportsResizeObserver = typeof window !== 'undefined' && 'ResizeObserver' in window && 'ResizeObserverEntry' in window;
32
31
  }
33
-
34
32
  export { result as browser };
@@ -1,5 +1,4 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
-
3
2
  /** @jsx jsx */
4
3
  import { jsx } from '@emotion/react';
5
4
  import { memo } from 'react';
@@ -29,7 +28,6 @@ export const testIds = {
29
28
  insertButton: 'link-picker-insert-button',
30
29
  cancelButton: 'link-picker-cancel-button'
31
30
  };
32
-
33
31
  const FormFooter = ({
34
32
  isLoading,
35
33
  error,
@@ -40,11 +38,9 @@ const FormFooter = ({
40
38
  ...restProps
41
39
  }) => {
42
40
  const intl = useIntl();
43
-
44
41
  if (error && error instanceof UnauthenticatedError) {
45
42
  return null;
46
43
  }
47
-
48
44
  const isSubmitDisabled = checkSubmitDisabled(isLoading, error, state, items);
49
45
  const insertButtonMsg = isEditing ? messages.saveButton : messages.insertButton;
50
46
  return jsx("footer", _extends({
@@ -60,5 +56,4 @@ const FormFooter = ({
60
56
  isDisabled: isSubmitDisabled
61
57
  }, intl.formatMessage(insertButtonMsg))));
62
58
  };
63
-
64
59
  export default /*#__PURE__*/memo(FormFooter);
@@ -7,24 +7,21 @@ export const checkSubmitDisabled = (isLoading, error, state, items) => {
7
7
  if (state && normalizeUrl(state.query)) {
8
8
  return false;
9
9
  }
10
+
10
11
  /*
11
12
  * Disable insert button when plugin returns no results,
12
13
  * but not if it is a valid url
13
14
  */
14
-
15
-
16
15
  if (state && (items === null || items === void 0 ? void 0 : items.length) === 0) {
17
16
  return true;
18
17
  }
18
+
19
19
  /*
20
20
  * Disable insert button when is plugin is loading or
21
21
  * for any search error
22
22
  */
23
-
24
-
25
23
  if (isLoading || error) {
26
24
  return true;
27
25
  }
28
-
29
26
  return false;
30
27
  };
@@ -1,5 +1,4 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
-
3
2
  /** @jsx jsx */
4
3
  import { Fragment, useCallback, useLayoutEffect, useReducer, memo } from 'react';
5
4
  import { jsx } from '@emotion/react';
@@ -50,38 +49,36 @@ const initState = {
50
49
  activeTab: 0,
51
50
  preventHidingRecents: false
52
51
  };
53
-
54
52
  function reducer(state, payload) {
55
53
  if (payload.url && state.url !== payload.url) {
56
- return { ...state,
54
+ return {
55
+ ...state,
57
56
  invalidUrl: false,
58
57
  selectedIndex: isSafeUrl(payload.url) && payload.url.length ? -1 : state.selectedIndex,
59
58
  ...payload
60
59
  };
61
60
  }
62
-
63
- return { ...state,
61
+ return {
62
+ ...state,
64
63
  ...payload
65
64
  };
66
65
  }
66
+
67
67
  /**
68
68
  * Bind input fields to analytics tracking
69
69
  */
70
70
 
71
-
72
71
  const getLinkFieldContent = value => {
73
72
  if (!Boolean(value)) {
74
73
  return null;
75
74
  }
76
-
77
75
  return isSafeUrl(value) ? 'url' : 'text_string';
78
76
  };
79
-
80
- const LinkInputField = withInputFieldTracking(TextInput, 'link', (event, attributes) => ({ ...attributes,
77
+ const LinkInputField = withInputFieldTracking(TextInput, 'link', (event, attributes) => ({
78
+ ...attributes,
81
79
  linkFieldContent: getLinkFieldContent(event.currentTarget.value)
82
80
  }));
83
81
  const DisplayTextInputField = withInputFieldTracking(TextInput, 'displayText');
84
-
85
82
  function LinkPicker({
86
83
  onSubmit,
87
84
  onCancel,
@@ -93,11 +90,11 @@ function LinkPicker({
93
90
  featureFlags
94
91
  }) {
95
92
  var _errorFallback;
96
-
97
93
  const {
98
94
  createAnalyticsEvent
99
95
  } = useAnalyticsEvents();
100
- const [state, dispatch] = useReducer(reducer, { ...initState,
96
+ const [state, dispatch] = useReducer(reducer, {
97
+ ...initState,
101
98
  url: normalizeUrl(initUrl) || '',
102
99
  displayText: initDisplayText || ''
103
100
  });
@@ -154,29 +151,23 @@ function LinkPicker({
154
151
  } = event;
155
152
  const KEY_ARROW_DOWN = 'ArrowDown';
156
153
  const KEY_ARROW_UP = 'ArrowUp';
157
-
158
154
  if (!items || !items.length) {
159
155
  return;
160
156
  }
161
-
162
157
  let updatedIndex = activeIndex;
163
-
164
158
  switch (key) {
165
159
  case KEY_ARROW_DOWN:
166
160
  // down
167
161
  event.preventDefault();
168
162
  updatedIndex = (activeIndex + 1) % items.length;
169
163
  break;
170
-
171
164
  case KEY_ARROW_UP:
172
165
  // up
173
166
  event.preventDefault();
174
167
  updatedIndex = activeIndex > 0 ? activeIndex - 1 : items.length - 1;
175
168
  break;
176
169
  }
177
-
178
170
  const item = items[updatedIndex];
179
-
180
171
  if ([KEY_ARROW_DOWN, KEY_ARROW_UP].includes(key) && item) {
181
172
  /**
182
173
  * Manually track that the url has been updated using searchResult method
@@ -208,8 +199,8 @@ function LinkPicker({
208
199
  });
209
200
  }, [dispatch, items]);
210
201
  const handleMouseLeaveResultItem = useCallback(objectId => {
211
- 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
212
-
202
+ const index = items === null || items === void 0 ? void 0 : items.findIndex(item => item.objectId === objectId);
203
+ // This is to avoid updating index that was set by other mouseenter event
213
204
  if (activeIndex === index) {
214
205
  dispatch({
215
206
  activeIndex: -1
@@ -217,16 +208,17 @@ function LinkPicker({
217
208
  }
218
209
  }, [dispatch, activeIndex, items]);
219
210
  const handleInsert = useCallback((url, title, inputType) => {
220
- const event = createAnalyticsEvent(createEventPayload('ui.form.submitted.linkPicker', {})); // Clone the event so that it can be emitted for consumer usage
221
- // This must happen BEFORE the original event is fired!
211
+ const event = createAnalyticsEvent(createEventPayload('ui.form.submitted.linkPicker', {}));
222
212
 
223
- const consumerEvent = event.clone(); // Cloned event doesnt have the attributes that are added by
213
+ // Clone the event so that it can be emitted for consumer usage
214
+ // This must happen BEFORE the original event is fired!
215
+ const consumerEvent = event.clone();
216
+ // Cloned event doesnt have the attributes that are added by
224
217
  // the analytics listener in the LinkPickerAnalyticsContext, add them here
225
-
226
218
  consumerEvent === null || consumerEvent === void 0 ? void 0 : consumerEvent.update({
227
219
  attributes: getAttributes()
228
- }); // Dispatch the original event to our channel
229
-
220
+ });
221
+ // Dispatch the original event to our channel
230
222
  event.fire(ANALYTICS_CHANNEL);
231
223
  onSubmit({
232
224
  url,
@@ -242,7 +234,6 @@ function LinkPicker({
242
234
  }, [displayText, onSubmit, state.url, createAnalyticsEvent, getAttributes]);
243
235
  const handleSelected = useCallback(objectId => {
244
236
  const selectedItem = items === null || items === void 0 ? void 0 : items.find(item => item.objectId === objectId);
245
-
246
237
  if (selectedItem) {
247
238
  const {
248
239
  url,
@@ -251,7 +242,6 @@ function LinkPicker({
251
242
  /**
252
243
  * Manually track that the url has been updated using searchResult method
253
244
  */
254
-
255
245
  dispatchEvent(new Event('submit'));
256
246
  trackAttribute('linkFieldContent', getLinkFieldContent(url));
257
247
  trackAttribute('linkFieldContentInputMethod', 'searchResult');
@@ -261,24 +251,19 @@ function LinkPicker({
261
251
  }, [handleInsert, trackAttribute, items, activePlugin]);
262
252
  const handleSubmit = useCallback(event => {
263
253
  event.preventDefault();
264
-
265
254
  if (isSelectedItem && selectedItem) {
266
255
  return handleInsert(selectedItem.url, selectedItem.name, 'typeAhead');
267
256
  }
268
-
269
257
  const normalized = normalizeUrl(url);
270
-
271
258
  if (normalized) {
272
259
  return handleInsert(normalized, null, 'manual');
273
260
  }
274
-
275
261
  return dispatch({
276
262
  invalidUrl: true
277
263
  });
278
264
  }, [dispatch, handleInsert, isSelectedItem, selectedItem, url]);
279
265
  const handleTabChange = useCallback(activeTab => {
280
266
  var _plugins$activeTab$ta, _plugins$activeTab;
281
-
282
267
  dispatch({
283
268
  // We don't want any selection to exist after changing tab, as the selection
284
269
  // wouldn't mean anything.
@@ -294,10 +279,11 @@ function LinkPicker({
294
279
  const messages = isActivePlugin ? searchMessages : linkMessages;
295
280
  const screenReaderDescriptionId = 'search-recent-links-field-description';
296
281
  const linkSearchListId = 'link-picker-search-list';
297
- const ariaActiveDescendant = selectedIndex > -1 ? `link-search-list-item-${selectedIndex}` : ''; // Added workaround with a screen reader Announcer specifically for VoiceOver + Safari
282
+ const ariaActiveDescendant = selectedIndex > -1 ? `link-search-list-item-${selectedIndex}` : '';
283
+
284
+ // Added workaround with a screen reader Announcer specifically for VoiceOver + Safari
298
285
  // as the Aria design pattern for combobox does not work in this case
299
286
  // for details: https://a11y-internal.atlassian.net/browse/AK-740
300
-
301
287
  const screenReaderText = browser.safari && getScreenReaderText(items !== null && items !== void 0 ? items : [], selectedIndex, intl);
302
288
  const searchIcon = isActivePlugin && jsx("span", {
303
289
  css: searchIconStyles,
@@ -385,7 +371,6 @@ function LinkPicker({
385
371
  css: !queryState || !(plugins !== null && plugins !== void 0 && plugins.length) ? formFooterMargin : undefined
386
372
  }));
387
373
  }
388
-
389
374
  const DefaultRootComponent = ({
390
375
  children
391
376
  }) => {
@@ -393,7 +378,6 @@ const DefaultRootComponent = ({
393
378
  "data-testid": testIds.linkPickerRoot
394
379
  }, children);
395
380
  };
396
-
397
381
  export default withLinkPickerAnalyticsContext( /*#__PURE__*/memo(({
398
382
  component,
399
383
  ...props