@atlaskit/link-picker 1.9.2 → 1.9.4

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 (46) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/analytics.codegen.js +1 -1
  3. package/dist/cjs/common/analytics/context.js +137 -0
  4. package/dist/cjs/common/analytics/index.js +27 -0
  5. package/dist/cjs/common/analytics/input-field-tracking.js +115 -0
  6. package/dist/cjs/common/constants.js +1 -1
  7. package/dist/cjs/ui/error-boundary/index.js +104 -0
  8. package/dist/cjs/ui/index.js +10 -6
  9. package/dist/cjs/ui/link-picker/index.js +56 -16
  10. package/dist/cjs/ui/link-picker/text-input/index.js +18 -23
  11. package/dist/cjs/version.json +1 -1
  12. package/dist/es2019/analytics.codegen.js +1 -1
  13. package/dist/es2019/common/analytics/context.js +95 -0
  14. package/dist/es2019/common/analytics/index.js +2 -0
  15. package/dist/es2019/common/analytics/input-field-tracking.js +85 -0
  16. package/dist/es2019/common/constants.js +1 -1
  17. package/dist/es2019/ui/error-boundary/index.js +62 -0
  18. package/dist/es2019/ui/index.js +8 -5
  19. package/dist/es2019/ui/link-picker/index.js +51 -14
  20. package/dist/es2019/ui/link-picker/link-search-error/index.js +2 -2
  21. package/dist/es2019/ui/link-picker/text-input/index.js +14 -20
  22. package/dist/es2019/version.json +1 -1
  23. package/dist/esm/analytics.codegen.js +1 -1
  24. package/dist/esm/common/analytics/context.js +110 -0
  25. package/dist/esm/common/analytics/index.js +2 -0
  26. package/dist/esm/common/analytics/input-field-tracking.js +91 -0
  27. package/dist/esm/common/constants.js +1 -1
  28. package/dist/esm/ui/error-boundary/index.js +81 -0
  29. package/dist/esm/ui/index.js +8 -5
  30. package/dist/esm/ui/link-picker/index.js +54 -14
  31. package/dist/esm/ui/link-picker/link-search-error/index.js +2 -2
  32. package/dist/esm/ui/link-picker/text-input/index.js +16 -21
  33. package/dist/esm/version.json +1 -1
  34. package/dist/types/analytics.codegen.d.ts +21 -1
  35. package/dist/types/common/analytics/context.d.ts +28 -0
  36. package/dist/types/common/analytics/index.d.ts +2 -0
  37. package/dist/types/common/analytics/input-field-tracking.d.ts +17 -0
  38. package/dist/types/common/constants.d.ts +1 -1
  39. package/dist/types/ui/error-boundary/index.d.ts +27 -0
  40. package/dist/types/ui/index.d.ts +2 -5
  41. package/dist/types/ui/link-picker/text-input/index.d.ts +6 -8
  42. package/package.json +1 -1
  43. package/dist/cjs/services/with-link-picker-analytics/index.js +0 -33
  44. package/dist/es2019/services/with-link-picker-analytics/index.js +0 -15
  45. package/dist/esm/services/with-link-picker-analytics/index.js +0 -17
  46. package/dist/types/services/with-link-picker-analytics/index.d.ts +0 -4
@@ -25,24 +25,23 @@ var _selectClear = _interopRequireDefault(require("@atlaskit/icon/glyph/select-c
25
25
 
26
26
  var _utils = require("../utils");
27
27
 
28
- var _styled = require("./styled");
29
-
30
28
  var _ = require("../");
31
29
 
32
- var _excluded = ["name", "label", "autoFocus", "onRedo", "onUndo", "onChange", "onKeyDown", "onClear", "clearLabel", "error"];
33
-
34
- var PanelTextInput = function PanelTextInput(props) {
35
- var name = props.name,
36
- label = props.label,
37
- autoFocus = props.autoFocus,
38
- onRedo = props.onRedo,
39
- onUndo = props.onUndo,
40
- onChange = props.onChange,
41
- onKeyDown = props.onKeyDown,
42
- onClear = props.onClear,
43
- clearLabel = props.clearLabel,
44
- error = props.error,
45
- restProps = (0, _objectWithoutProperties2.default)(props, _excluded);
30
+ var _styled = require("./styled");
31
+
32
+ var _excluded = ["name", "label", "autoFocus", "onRedo", "onUndo", "onKeyDown", "onClear", "clearLabel", "error"];
33
+
34
+ var TextInput = function TextInput(_ref) {
35
+ var name = _ref.name,
36
+ label = _ref.label,
37
+ autoFocus = _ref.autoFocus,
38
+ onRedo = _ref.onRedo,
39
+ onUndo = _ref.onUndo,
40
+ onKeyDown = _ref.onKeyDown,
41
+ onClear = _ref.onClear,
42
+ clearLabel = _ref.clearLabel,
43
+ error = _ref.error,
44
+ restProps = (0, _objectWithoutProperties2.default)(_ref, _excluded);
46
45
  var inputRef = (0, _react.useRef)(null);
47
46
  var handleRef = (0, _react.useCallback)(function (input) {
48
47
  if (input) {
@@ -56,9 +55,6 @@ var PanelTextInput = function PanelTextInput(props) {
56
55
  }
57
56
  }
58
57
  }, [autoFocus]);
59
- var handleChange = (0, _react.useCallback)(function (e) {
60
- onChange(e.currentTarget.value);
61
- }, [onChange]);
62
58
  var handleKeydown = (0, _react.useCallback)(function (e) {
63
59
  if (typeof onUndo === 'function' && (0, _utils.isUndoEvent)(e)) {
64
60
  e.preventDefault();
@@ -96,11 +92,10 @@ var PanelTextInput = function PanelTextInput(props) {
96
92
  }, (0, _react2.jsx)(_form.Field, {
97
93
  label: label,
98
94
  name: name
99
- }, function (_ref) {
100
- var fieldProps = _ref.fieldProps;
95
+ }, function (_ref2) {
96
+ var fieldProps = _ref2.fieldProps;
101
97
  return (0, _react2.jsx)(_react.Fragment, null, (0, _react2.jsx)(_textfield.default, (0, _extends2.default)({}, fieldProps, restProps, {
102
98
  onKeyDown: handleKeydown,
103
- onChange: handleChange,
104
99
  ref: handleRef,
105
100
  elemAfterInput: clearText,
106
101
  isInvalid: !!error
@@ -110,5 +105,5 @@ var PanelTextInput = function PanelTextInput(props) {
110
105
  }));
111
106
  };
112
107
 
113
- var _default = PanelTextInput;
108
+ var _default = TextInput;
114
109
  exports.default = _default;
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/link-picker",
3
- "version": "1.9.2",
3
+ "version": "1.9.4",
4
4
  "sideEffects": false
5
5
  }
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Generates analytics utilities from the package analytics spec yaml
5
5
  *
6
- * @codegen <<SignedSource::115bafba068f36f76da67200ee2d08c4>>
6
+ * @codegen <<SignedSource::3c46f1d8f463b6898a7a0e1e1f4676b4>>
7
7
  * @codegenCommand yarn workspace @atlaskit/link-picker run codegen-analytics
8
8
  */
9
9
  function createEventPayload(eventKey, attributes) {
@@ -0,0 +1,95 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import React, { useCallback, useContext, useMemo, useRef, useState } from 'react';
3
+ import { AnalyticsListener } from '@atlaskit/analytics-next';
4
+ import { ANALYTICS_CHANNEL } from '../constants';
5
+ import { normalizeUrl } from '../utils/url';
6
+ const DEFAULT_CONTEXT_ATTRIBUTES = {
7
+ linkState: 'newLink',
8
+ linkFieldContent: null,
9
+ linkFieldContentInputMethod: null,
10
+ displayTextFieldContent: null,
11
+ displayTextFieldContentInputMethod: null
12
+ };
13
+ const LinkPickerAnalyticsContext = /*#__PURE__*/React.createContext({
14
+ trackAttribute: () => {},
15
+ trackAttributes: () => {},
16
+ getAttributes: () => DEFAULT_CONTEXT_ATTRIBUTES
17
+ });
18
+ /**
19
+ * TODO: Should we hook this into the form state/reducer?
20
+ */
21
+
22
+ const contextAttributesFromIntialProps = props => {
23
+ return {
24
+ linkState: normalizeUrl(props.url) ? 'editLink' : 'newLink',
25
+ linkFieldContent: normalizeUrl(props.url) ? 'url' : null,
26
+ displayTextFieldContent: Boolean(props.displayText) ? 'text_string' : null
27
+ };
28
+ };
29
+ /**
30
+ * Context for tracking attributes to deliver at a context-level
31
+ */
32
+
33
+
34
+ const LinkPickerAnalytics = ({
35
+ initialContext,
36
+ children
37
+ }) => {
38
+ const dataRef = useRef({ ...DEFAULT_CONTEXT_ATTRIBUTES,
39
+ ...initialContext
40
+ });
41
+ const methods = useMemo(() => ({
42
+ trackAttribute: (key, value) => {
43
+ dataRef.current[key] = value;
44
+ },
45
+ trackAttributes: attributes => {
46
+ dataRef.current = { ...dataRef.current,
47
+ ...attributes
48
+ };
49
+ },
50
+ getAttributes: () => dataRef.current
51
+ }), []);
52
+ return /*#__PURE__*/React.createElement(LinkPickerAnalyticsContext.Provider, {
53
+ value: methods
54
+ }, children);
55
+ };
56
+ /**
57
+ * Hook that exposes the context-level attribute getters and setters.
58
+ */
59
+
60
+
61
+ export const useLinkPickerAnalytics = () => useContext(LinkPickerAnalyticsContext);
62
+ /**
63
+ * Wrap component in "attributes" context store and initialise the initial context attributes from props.
64
+ */
65
+
66
+ function withLinkPickerAnalytics(WrappedComponent) {
67
+ return props => {
68
+ const [initialContext] = useState(() => contextAttributesFromIntialProps(props));
69
+ return /*#__PURE__*/React.createElement(LinkPickerAnalytics, _extends({
70
+ initialContext: initialContext
71
+ }, props), /*#__PURE__*/React.createElement(WrappedComponent, props));
72
+ };
73
+ }
74
+ /**
75
+ * Wraps a component with the analytics context + listener to update events with contextual-level attributes.
76
+ * Should be implemented once at the root of the link picker.
77
+ */
78
+
79
+
80
+ export function withLinkPickerAnalyticsContext(WrappedComponent) {
81
+ return withLinkPickerAnalytics(props => {
82
+ const {
83
+ getAttributes
84
+ } = useLinkPickerAnalytics();
85
+ const onEvent = useCallback(event => {
86
+ event.update({
87
+ attributes: getAttributes()
88
+ });
89
+ }, [getAttributes]);
90
+ return /*#__PURE__*/React.createElement(AnalyticsListener, {
91
+ channel: ANALYTICS_CHANNEL,
92
+ onEvent: onEvent
93
+ }, /*#__PURE__*/React.createElement(WrappedComponent, props));
94
+ });
95
+ }
@@ -0,0 +1,2 @@
1
+ export { useLinkPickerAnalytics, withLinkPickerAnalyticsContext } from './context';
2
+ export { withInputFieldTracking } from './input-field-tracking';
@@ -0,0 +1,85 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import React, { useCallback, useRef } from 'react';
3
+ import { useAnalyticsEvents } from '@atlaskit/analytics-next';
4
+ import { ANALYTICS_CHANNEL } from '../constants';
5
+ import createEventPayload from '../../analytics.codegen';
6
+ import { useLinkPickerAnalytics } from '.';
7
+
8
+ const isEventWithInputType = e => {
9
+ return typeof e === 'object' && e !== null && 'inputType' in e;
10
+ };
11
+
12
+ const getChangeEventInputMethodType = event => {
13
+ if (isEventWithInputType(event.nativeEvent) && typeof event.nativeEvent.inputType === 'string' && event.nativeEvent.inputType.includes('insertFromPaste')) {
14
+ return 'paste';
15
+ }
16
+
17
+ return 'manual';
18
+ };
19
+ /**
20
+ * Wraps an input field and connects it to the link picker analytics context to provide a baseline of analytics tracking
21
+ * @param WrappedComponent The input field to be tracked
22
+ * @param field The name of the field (ie matching actionSubjectId)
23
+ * @param filterOnChangeEventAttrs Function to hook into and filter/customise the default attribute tracking logic
24
+ * @returns HOC Input field with tracking
25
+ */
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
29
+ // contentTypeFn: (value: string) => LinkPickerAnalyticsContextType[`${Field}FieldContent`],
30
+ ) => {
31
+ return props => {
32
+ const {
33
+ onBlur,
34
+ onChange,
35
+ onClear,
36
+ onFocus
37
+ } = props;
38
+ const {
39
+ trackAttribute,
40
+ trackAttributes
41
+ } = useLinkPickerAnalytics();
42
+ const {
43
+ createAnalyticsEvent
44
+ } = useAnalyticsEvents(); // Ref to track if the value of the field has changed between focus and blur
45
+
46
+ const valueOnFocus = useRef(null); // Track the content and input method on every direct change to the input
47
+
48
+ const handleOnChange = useCallback(event => {
49
+ // TODO: See above re template literal, improve typesafety here
50
+ // trackAttribute(`${field}FieldContent`, contentTypeFn(event.currentTarget.value));
51
+ // trackAttribute(`${field}FieldContentInputMethod`, methodTypeFn(event));
52
+ trackAttributes(filterOnChangeEventAttrs(event, {
53
+ [`${field}FieldContent`]: Boolean(event.currentTarget.value) ? 'text_string' : null,
54
+ [`${field}FieldContentInputMethod`]: getChangeEventInputMethodType(event)
55
+ }));
56
+ 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
58
+
59
+ const handleOnFocus = useCallback(event => {
60
+ valueOnFocus.current = event.currentTarget.value;
61
+ onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
62
+ }, [onFocus]); // Fire updated events only when the user's focus leaves the field
63
+
64
+ const handleOnBlur = useCallback(event => {
65
+ // Only fire if the value has changed since the field was focused (we are only concerned with the net change to the field)
66
+ if (event.currentTarget.value !== valueOnFocus.current) {
67
+ createAnalyticsEvent(createEventPayload(`ui.textField.updated.${field}Field`, {})).fire(ANALYTICS_CHANNEL);
68
+ }
69
+
70
+ onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
71
+ }, [onBlur, createAnalyticsEvent]); // Track the values as null when the text field is cleared
72
+
73
+ const handleOnClear = useCallback((...args) => {
74
+ trackAttribute(`${field}FieldContent`, null);
75
+ trackAttribute(`${field}FieldContentInputMethod`, null);
76
+ onClear === null || onClear === void 0 ? void 0 : onClear(...args);
77
+ }, [onClear, trackAttribute]);
78
+ return /*#__PURE__*/React.createElement(WrappedComponent, _extends({}, props, {
79
+ onBlur: handleOnBlur,
80
+ onChange: handleOnChange,
81
+ onClear: handleOnClear,
82
+ onFocus: handleOnFocus
83
+ }));
84
+ };
85
+ };
@@ -1,2 +1,2 @@
1
1
  export const ANALYTICS_CHANNEL = 'media';
2
- export const COMPONENT_NAME = 'LinkPicker';
2
+ export const COMPONENT_NAME = 'linkPicker';
@@ -0,0 +1,62 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import React, { Component } from 'react';
3
+ import { withAnalyticsEvents } from '@atlaskit/analytics-next';
4
+ import createEventPayload from '../../analytics.codegen';
5
+ // eslint-disable-next-line @repo/internal/react/no-class-components
6
+ export class BaseErrorBoundary extends Component {
7
+ constructor(props) {
8
+ super(props);
9
+
10
+ _defineProperty(this, "fireAnalytics", analyticsErrorPayload => {
11
+ var _window, _window$navigator, _analyticsErrorPayloa, _analyticsErrorPayloa2;
12
+
13
+ const {
14
+ createAnalyticsEvent,
15
+ channel
16
+ } = this.props;
17
+ createAnalyticsEvent(createEventPayload('ui.linkPicker.unhandledErrorCaught', {
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',
19
+ error: analyticsErrorPayload.error.toString(),
20
+ componentStack: (_analyticsErrorPayloa = (_analyticsErrorPayloa2 = analyticsErrorPayload.info) === null || _analyticsErrorPayloa2 === void 0 ? void 0 : _analyticsErrorPayloa2.componentStack) !== null && _analyticsErrorPayloa !== void 0 ? _analyticsErrorPayloa : ''
21
+ })).fire(channel);
22
+ });
23
+
24
+ this.state = {
25
+ hasError: false
26
+ };
27
+ }
28
+
29
+ componentDidCatch(error, info) {
30
+ const {
31
+ onError
32
+ } = this.props;
33
+ const payload = {
34
+ error,
35
+ info
36
+ };
37
+ this.fireAnalytics(payload);
38
+ onError && onError(error, info);
39
+ this.setState({
40
+ hasError: true
41
+ });
42
+ }
43
+
44
+ render() {
45
+ const {
46
+ children,
47
+ ErrorComponent
48
+ } = this.props;
49
+ const {
50
+ hasError
51
+ } = this.state;
52
+
53
+ if (hasError && ErrorComponent) {
54
+ return /*#__PURE__*/React.createElement(ErrorComponent, null);
55
+ }
56
+
57
+ return children;
58
+ }
59
+
60
+ }
61
+ const ErrorBoundary = withAnalyticsEvents()(BaseErrorBoundary);
62
+ export default ErrorBoundary;
@@ -1,22 +1,25 @@
1
1
  import React, { memo } from 'react';
2
- import { AnalyticsErrorBoundary } from '@atlaskit/analytics-next';
3
2
  import { LazySuspense, lazyForPaint } from 'react-loosely-lazy';
3
+ import { AnalyticsContext } from '@atlaskit/analytics-next';
4
4
  import { COMPONENT_NAME, ANALYTICS_CHANNEL } from '../common/constants';
5
5
  import { name as packageName, version as packageVersion } from '../version.json';
6
+ import ErrorBoundary from './error-boundary';
6
7
  import { ErrorBoundaryFallback } from './error-boundary-fallback';
7
8
  import { LoaderFallback } from './loader-fallback';
8
9
  export const PACKAGE_DATA = {
9
10
  packageName,
10
11
  packageVersion,
11
- componentName: COMPONENT_NAME
12
+ componentName: COMPONENT_NAME,
13
+ source: COMPONENT_NAME
12
14
  };
13
15
  const LazyLinkPicker = lazyForPaint(() => import(
14
16
  /* webpackChunkName: "@atlaskit-internal_link-picker" */
15
17
  './link-picker'));
16
- export const ComposedLinkPicker = /*#__PURE__*/memo(props => /*#__PURE__*/React.createElement(AnalyticsErrorBoundary, {
18
+ export const ComposedLinkPicker = /*#__PURE__*/memo(props => /*#__PURE__*/React.createElement(AnalyticsContext, {
19
+ data: PACKAGE_DATA
20
+ }, /*#__PURE__*/React.createElement(ErrorBoundary, {
17
21
  channel: ANALYTICS_CHANNEL,
18
- data: PACKAGE_DATA,
19
22
  ErrorComponent: ErrorBoundaryFallback
20
23
  }, /*#__PURE__*/React.createElement(LazySuspense, {
21
24
  fallback: LoaderFallback
22
- }, /*#__PURE__*/React.createElement(LazyLinkPicker, props))));
25
+ }, /*#__PURE__*/React.createElement(LazyLinkPicker, props)))));
@@ -10,13 +10,13 @@ import Tabs, { Tab, TabList } from '@atlaskit/tabs';
10
10
  import VisuallyHidden from '@atlaskit/visually-hidden';
11
11
  import createEventPayload from '../../analytics.codegen';
12
12
  import { ANALYTICS_CHANNEL } from '../../common/constants';
13
+ import { useLinkPickerAnalytics, withInputFieldTracking, withLinkPickerAnalyticsContext } from '../../common/analytics';
14
+ import { normalizeUrl, isSafeUrl } from '../../common/utils/url';
13
15
  import { usePlugins } from '../../services/use-plugins';
14
16
  import { useSearchQuery } from '../../services/use-search-query';
15
- import { withLinkPickerAnalyticsContext } from '../../services/with-link-picker-analytics';
16
- import { messages } from './messages';
17
- import PanelTextInput from './text-input';
18
- import { normalizeUrl, isSafeUrl } from '../../common/utils/url';
19
17
  import useFixHeight from '../../controllers/use-fix-height';
18
+ import { messages } from './messages';
19
+ import TextInput from './text-input';
20
20
  import { rootContainerStyles, searchIconStyles, tabsWrapperStyles, flexColumnStyles, formFooterMargin } from './styled';
21
21
  import { browser } from './browser';
22
22
  import Announcer from './announcer';
@@ -61,6 +61,23 @@ function reducer(state, payload) {
61
61
  ...payload
62
62
  };
63
63
  }
64
+ /**
65
+ * Bind input fields to analytics tracking
66
+ */
67
+
68
+
69
+ const getLinkFieldContent = value => {
70
+ if (!Boolean(value)) {
71
+ return null;
72
+ }
73
+
74
+ return isSafeUrl(value) ? 'url' : 'text_string';
75
+ };
76
+
77
+ const LinkInputField = withInputFieldTracking(TextInput, 'link', (event, attributes) => ({ ...attributes,
78
+ linkFieldContent: getLinkFieldContent(event.currentTarget.value)
79
+ }));
80
+ const DisplayTextInputField = withInputFieldTracking(TextInput, 'displayText');
64
81
 
65
82
  function LinkPicker({
66
83
  onSubmit,
@@ -102,6 +119,10 @@ function LinkPicker({
102
119
  const isEditing = !!initUrl;
103
120
  const selectedItem = items === null || items === void 0 ? void 0 : items[selectedIndex];
104
121
  const isSelectedItem = (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.url) === url;
122
+ const {
123
+ trackAttribute,
124
+ getAttributes
125
+ } = useLinkPickerAnalytics();
105
126
  useEffect(() => {
106
127
  // Anything in here is fired on component mount.
107
128
  const event = createAnalyticsEvent(createEventPayload('ui.inlineDialog.viewed.linkPicker', {}));
@@ -117,14 +138,14 @@ function LinkPicker({
117
138
  onContentResize();
118
139
  }
119
140
  }, [onContentResize, items, isLoading, isActivePlugin, tabs]);
120
- const handleChangeUrl = useCallback(url => {
141
+ const handleChangeUrl = useCallback(e => {
121
142
  dispatch({
122
- url
143
+ url: e.currentTarget.value
123
144
  });
124
145
  }, []);
125
- const handleChangeText = useCallback(displayText => {
146
+ const handleChangeText = useCallback(e => {
126
147
  dispatch({
127
- displayText
148
+ displayText: e.currentTarget.value
128
149
  });
129
150
  }, []);
130
151
  const handleKeyDown = useCallback(event => {
@@ -155,6 +176,11 @@ function LinkPicker({
155
176
  }
156
177
 
157
178
  if ([KEY_CODE_ARROW_DOWN, KEY_CODE_ARROW_UP].includes(keyCode) && items[updatedIndex]) {
179
+ /**
180
+ * Manually track that the url has been updated using searchResult method
181
+ */
182
+ trackAttribute('linkFieldContent', getLinkFieldContent(items[updatedIndex].url));
183
+ trackAttribute('linkFieldContentInputMethod', 'searchResult');
158
184
  dispatch({
159
185
  activeIndex: updatedIndex,
160
186
  selectedIndex: updatedIndex,
@@ -162,7 +188,7 @@ function LinkPicker({
162
188
  invalidUrl: false
163
189
  });
164
190
  }
165
- }, [activeIndex, items]);
191
+ }, [activeIndex, items, trackAttribute]);
166
192
  const handleClear = useCallback(field => {
167
193
  dispatch({
168
194
  [field]: ''
@@ -187,7 +213,12 @@ function LinkPicker({
187
213
  const event = createAnalyticsEvent(createEventPayload('ui.form.submitted.linkPicker', {})); // Clone the event so that it can be emitted for consumer usage
188
214
  // This must happen BEFORE the original event is fired!
189
215
 
190
- const consumerEvent = event.clone(); // Dispatch the original event to our channel
216
+ const consumerEvent = event.clone(); // Cloned event doesnt have the attributes that are added by
217
+ // the analytics listener in the LinkPickerAnalyticsContext, add them here
218
+
219
+ consumerEvent === null || consumerEvent === void 0 ? void 0 : consumerEvent.update({
220
+ attributes: getAttributes()
221
+ }); // Dispatch the original event to our channel
191
222
 
192
223
  event.fire(ANALYTICS_CHANNEL);
193
224
  onSubmit({
@@ -201,7 +232,7 @@ function LinkPicker({
201
232
  rawUrl: state.url
202
233
  } : {})
203
234
  }, consumerEvent);
204
- }, [displayText, onSubmit, state.url, createAnalyticsEvent]);
235
+ }, [displayText, onSubmit, state.url, createAnalyticsEvent, getAttributes]);
205
236
  const handleSelected = useCallback(objectId => {
206
237
  const selectedItem = items === null || items === void 0 ? void 0 : items.find(item => item.objectId === objectId);
207
238
 
@@ -211,9 +242,15 @@ function LinkPicker({
211
242
  name
212
243
  } = selectedItem;
213
244
  dispatchEvent(new Event('submit'));
245
+ /**
246
+ * Manually track that the url has been updated using searchResult method
247
+ */
248
+
249
+ trackAttribute('linkFieldContent', getLinkFieldContent(url));
250
+ trackAttribute('linkFieldContentInputMethod', 'searchResult');
214
251
  handleInsert(url, name, 'typeAhead');
215
252
  }
216
- }, [handleInsert, items]);
253
+ }, [handleInsert, trackAttribute, items]);
217
254
  const handleSubmit = useCallback(event => {
218
255
  event.preventDefault();
219
256
 
@@ -257,7 +294,7 @@ function LinkPicker({
257
294
  delay: 250
258
295
  }), jsx(VisuallyHidden, {
259
296
  id: screenReaderDescriptionId
260
- }, jsx(FormattedMessage, messages.searchLinkAriaDescription)), jsx(PanelTextInput, {
297
+ }, jsx(FormattedMessage, messages.searchLinkAriaDescription)), jsx(LinkInputField, {
261
298
  role: "combobox",
262
299
  autoComplete: "off",
263
300
  name: "url",
@@ -277,7 +314,7 @@ function LinkPicker({
277
314
  onClear: handleClear,
278
315
  onKeyDown: handleKeyDown,
279
316
  onChange: handleChangeUrl
280
- }), jsx(PanelTextInput, {
317
+ }), jsx(DisplayTextInputField, {
281
318
  autoComplete: "off",
282
319
  name: "displayText",
283
320
  testId: testIds.textInputField,
@@ -4,6 +4,8 @@ import _extends from "@babel/runtime/helpers/extends";
4
4
  import { jsx } from '@emotion/react';
5
5
  import { useIntl, FormattedMessage, defineMessages } from 'react-intl-next';
6
6
  import Button from '@atlaskit/button';
7
+ import EmptyState from '@atlaskit/empty-state';
8
+ import GenericErrorSVG from '../../../common/generic-error-svg';
7
9
  export const CONTACT_SUPPORT_LINK = 'https://support.atlassian.com/contact/';
8
10
  export const messages = defineMessages({
9
11
  searchErrorHeader: {
@@ -17,8 +19,6 @@ export const messages = defineMessages({
17
19
  description: 'Describes possible actions when search throws an error'
18
20
  }
19
21
  });
20
- import EmptyState from '@atlaskit/empty-state';
21
- import GenericErrorSVG from '../../../common/generic-error-svg';
22
22
  export const testIds = {
23
23
  searchError: 'link-search-error'
24
24
  };
@@ -8,23 +8,21 @@ import Tooltip from '@atlaskit/tooltip';
8
8
  import Textfield from '@atlaskit/textfield';
9
9
  import Selectclear from '@atlaskit/icon/glyph/select-clear';
10
10
  import { isRedoEvent, isUndoEvent } from '../utils';
11
- import { clearTextButtonStyles, fieldStyles } from './styled';
12
11
  import { testIds } from '../';
12
+ import { clearTextButtonStyles, fieldStyles } from './styled';
13
13
 
14
- const PanelTextInput = props => {
15
- const {
16
- name,
17
- label,
18
- autoFocus,
19
- onRedo,
20
- onUndo,
21
- onChange,
22
- onKeyDown,
23
- onClear,
24
- clearLabel,
25
- error,
26
- ...restProps
27
- } = props;
14
+ const TextInput = ({
15
+ name,
16
+ label,
17
+ autoFocus,
18
+ onRedo,
19
+ onUndo,
20
+ onKeyDown,
21
+ onClear,
22
+ clearLabel,
23
+ error,
24
+ ...restProps
25
+ }) => {
28
26
  const inputRef = useRef(null);
29
27
  const handleRef = useCallback(input => {
30
28
  if (input) {
@@ -38,9 +36,6 @@ const PanelTextInput = props => {
38
36
  }
39
37
  }
40
38
  }, [autoFocus]);
41
- const handleChange = useCallback(e => {
42
- onChange(e.currentTarget.value);
43
- }, [onChange]);
44
39
  const handleKeydown = useCallback(e => {
45
40
  if (typeof onUndo === 'function' && isUndoEvent(e)) {
46
41
  e.preventDefault();
@@ -83,7 +78,6 @@ const PanelTextInput = props => {
83
78
  }) => {
84
79
  return jsx(Fragment, null, jsx(Textfield, _extends({}, fieldProps, restProps, {
85
80
  onKeyDown: handleKeydown,
86
- onChange: handleChange,
87
81
  ref: handleRef,
88
82
  elemAfterInput: clearText,
89
83
  isInvalid: !!error
@@ -93,4 +87,4 @@ const PanelTextInput = props => {
93
87
  }));
94
88
  };
95
89
 
96
- export default PanelTextInput;
90
+ export default TextInput;
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/link-picker",
3
- "version": "1.9.2",
3
+ "version": "1.9.4",
4
4
  "sideEffects": false
5
5
  }
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Generates analytics utilities from the package analytics spec yaml
5
5
  *
6
- * @codegen <<SignedSource::115bafba068f36f76da67200ee2d08c4>>
6
+ * @codegen <<SignedSource::3c46f1d8f463b6898a7a0e1e1f4676b4>>
7
7
  * @codegenCommand yarn workspace @atlaskit/link-picker run codegen-analytics
8
8
  */
9
9
  function createEventPayload(eventKey, attributes) {