@atlaskit/link-picker 1.31.0 → 1.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/cjs/ui/index.js +1 -1
  3. package/dist/cjs/ui/link-picker/form-footer/index.js +33 -9
  4. package/dist/cjs/ui/link-picker/form-footer/utils.js +4 -1
  5. package/dist/cjs/ui/link-picker/index.js +32 -5
  6. package/dist/cjs/ui/link-picker/search-results/index.js +2 -0
  7. package/dist/cjs/ui/link-picker/search-results/link-search-list/index.js +3 -1
  8. package/dist/cjs/ui/messages-provider/lazy-messages-provider/utils/fetch-messages-for-locale.js +5 -15
  9. package/dist/es2019/ui/index.js +1 -1
  10. package/dist/es2019/ui/link-picker/form-footer/index.js +29 -8
  11. package/dist/es2019/ui/link-picker/form-footer/utils.js +4 -1
  12. package/dist/es2019/ui/link-picker/index.js +31 -5
  13. package/dist/es2019/ui/link-picker/search-results/index.js +2 -0
  14. package/dist/es2019/ui/link-picker/search-results/link-search-list/index.js +2 -0
  15. package/dist/es2019/ui/messages-provider/lazy-messages-provider/utils/fetch-messages-for-locale.js +0 -10
  16. package/dist/esm/ui/index.js +1 -1
  17. package/dist/esm/ui/link-picker/form-footer/index.js +33 -9
  18. package/dist/esm/ui/link-picker/form-footer/utils.js +4 -1
  19. package/dist/esm/ui/link-picker/index.js +32 -5
  20. package/dist/esm/ui/link-picker/search-results/index.js +2 -0
  21. package/dist/esm/ui/link-picker/search-results/link-search-list/index.js +3 -1
  22. package/dist/esm/ui/messages-provider/lazy-messages-provider/utils/fetch-messages-for-locale.js +5 -15
  23. package/dist/types/ui/link-picker/form-footer/index.d.ts +26 -1
  24. package/dist/types/ui/link-picker/form-footer/utils.d.ts +1 -1
  25. package/dist/types/ui/link-picker/index.d.ts +3 -0
  26. package/dist/types/ui/link-picker/search-results/index.d.ts +2 -1
  27. package/dist/types/ui/link-picker/search-results/link-search-list/index.d.ts +1 -0
  28. package/dist/types-ts4.5/ui/link-picker/form-footer/index.d.ts +26 -1
  29. package/dist/types-ts4.5/ui/link-picker/form-footer/utils.d.ts +1 -1
  30. package/dist/types-ts4.5/ui/link-picker/index.d.ts +3 -0
  31. package/dist/types-ts4.5/ui/link-picker/search-results/index.d.ts +2 -1
  32. package/dist/types-ts4.5/ui/link-picker/search-results/link-search-list/index.d.ts +1 -0
  33. package/package.json +1 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @atlaskit/link-picker
2
2
 
3
+ ## 1.32.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#61981](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/61981) [`0d7a20c43478`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/0d7a20c43478) - [ux] Added a UI experience for when a submission is in progress
8
+
9
+ ### Patch Changes
10
+
11
+ - [#64291](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/64291) [`c44535acbea9`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/c44535acbea9) - remove platform.linking-platform.link-create.tmp-fix-translations to permanently return undefined in the loaderFn when dynamic import of locale messages fail.
12
+
3
13
  ## 1.31.0
4
14
 
5
15
  ### Minor Changes
@@ -26,7 +26,7 @@ var testIds = exports.testIds = {
26
26
  };
27
27
  var PACKAGE_DATA = exports.PACKAGE_DATA = {
28
28
  packageName: "@atlaskit/link-picker" || '',
29
- packageVersion: "1.31.0" || '',
29
+ packageVersion: "1.32.0" || '',
30
30
  componentName: _constants.COMPONENT_NAME,
31
31
  source: _constants.COMPONENT_NAME
32
32
  };
@@ -5,23 +5,26 @@ var _typeof = require("@babel/runtime/helpers/typeof");
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports.testIds = exports.FormFooter = void 0;
8
+ exports.testIds = exports.messages = exports.FormFooter = void 0;
9
9
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
10
10
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
11
11
  var _react = require("react");
12
12
  var _react2 = require("@emotion/react");
13
13
  var _reactIntlNext = require("react-intl-next");
14
+ var _uuid = _interopRequireDefault(require("uuid"));
14
15
  var _button = _interopRequireWildcard(require("@atlaskit/button"));
16
+ var _loadingButton = _interopRequireDefault(require("@atlaskit/button/loading-button"));
15
17
  var _add = _interopRequireDefault(require("@atlaskit/icon/glyph/editor/add"));
18
+ var _visuallyHidden = _interopRequireDefault(require("@atlaskit/visually-hidden"));
16
19
  var _errors = require("../../../common/utils/errors");
17
20
  var _featureDiscovery = _interopRequireDefault(require("./feature-discovery"));
18
21
  var _styled = require("./styled");
19
22
  var _utils = require("./utils");
20
- var _excluded = ["isLoading", "error", "url", "queryState", "items", "isEditing", "onCancel", "action", "createFeatureDiscovery", "customSubmitButtonLabel"];
23
+ var _excluded = ["isLoading", "isSubmitting", "error", "url", "queryState", "items", "isEditing", "onCancel", "action", "createFeatureDiscovery", "customSubmitButtonLabel"];
21
24
  /** @jsx jsx */
22
25
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
23
26
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
24
- var messages = (0, _reactIntlNext.defineMessages)({
27
+ var messages = exports.messages = (0, _reactIntlNext.defineMessages)({
25
28
  cancelButton: {
26
29
  id: 'fabric.linkPicker.button.cancel',
27
30
  defaultMessage: 'Cancel',
@@ -36,17 +39,25 @@ var messages = (0, _reactIntlNext.defineMessages)({
36
39
  id: 'fabric.linkPicker.button.insert',
37
40
  defaultMessage: 'Insert',
38
41
  description: 'Button to insert searched or selected link'
42
+ },
43
+ submittingStatusMessage: {
44
+ id: 'fabric.linkPicker.status.submitting',
45
+ defaultMessage: 'Submitting',
46
+ description: 'Accessibility text to indicate the form has been submitted, and submission is in-progress'
39
47
  }
40
48
  });
41
49
  var testIds = exports.testIds = {
42
50
  insertButton: 'link-picker-insert-button',
43
51
  cancelButton: 'link-picker-cancel-button',
44
52
  actionButton: 'link-picker-action-button',
53
+ submitStatusA11yIndicator: 'link-picker-submit-status-a11y-indicator',
45
54
  /** Feature discovery for action button (css pulse) */
46
55
  actionButtonDiscovery: 'link-picker-action-button-discovery'
47
56
  };
48
57
  var FormFooter = exports.FormFooter = /*#__PURE__*/(0, _react.memo)(function (_ref) {
49
58
  var isLoading = _ref.isLoading,
59
+ _ref$isSubmitting = _ref.isSubmitting,
60
+ isSubmitting = _ref$isSubmitting === void 0 ? false : _ref$isSubmitting,
50
61
  error = _ref.error,
51
62
  url = _ref.url,
52
63
  queryState = _ref.queryState,
@@ -59,10 +70,13 @@ var FormFooter = exports.FormFooter = /*#__PURE__*/(0, _react.memo)(function (_r
59
70
  customSubmitButtonLabel = _ref.customSubmitButtonLabel,
60
71
  restProps = (0, _objectWithoutProperties2.default)(_ref, _excluded);
61
72
  var intl = (0, _reactIntlNext.useIntl)();
73
+ var submitMessageId = (0, _react.useMemo)(function () {
74
+ return (0, _uuid.default)();
75
+ }, []);
62
76
  if (error && error instanceof _errors.UnauthenticatedError) {
63
77
  return null;
64
78
  }
65
- var isSubmitDisabled = (0, _utils.checkSubmitDisabled)(isLoading, error, url, queryState, items);
79
+ var isSubmitDisabled = (0, _utils.checkSubmitDisabled)(isLoading, isSubmitting, error, url, queryState, items);
66
80
  var insertButtonMsg = isEditing ? messages.saveButton : messages.insertButton;
67
81
  var createButton = function createButton(pluginAction) {
68
82
  return (0, _react2.jsx)(_button.default, {
@@ -72,23 +86,33 @@ var FormFooter = exports.FormFooter = /*#__PURE__*/(0, _react.memo)(function (_r
72
86
  iconBefore: (0, _react2.jsx)(_add.default, {
73
87
  label: "",
74
88
  size: "medium"
75
- })
89
+ }),
90
+ isDisabled: isSubmitting,
91
+ "aria-labelledby": isSubmitting ? submitMessageId : undefined
76
92
  }, typeof pluginAction.label === 'string' ? pluginAction.label : intl.formatMessage(pluginAction.label));
77
93
  };
78
94
  return (0, _react2.jsx)("footer", (0, _extends2.default)({
79
95
  css: _styled.formFooterStyles
80
- }, restProps), action && (0, _react2.jsx)("div", {
96
+ }, restProps), isSubmitting && (0, _react2.jsx)(_visuallyHidden.default, {
97
+ role: "status",
98
+ id: submitMessageId,
99
+ testId: testIds.submitStatusA11yIndicator
100
+ }, intl.formatMessage(messages.submittingStatusMessage)), action && (0, _react2.jsx)("div", {
81
101
  css: _styled.formFooterActionStyles
82
102
  }, createFeatureDiscovery ? (0, _react2.jsx)(_featureDiscovery.default, {
83
103
  testId: testIds.actionButtonDiscovery
84
104
  }, createButton(action)) : createButton(action)), (0, _react2.jsx)(_button.ButtonGroup, null, (0, _react2.jsx)(_button.default, {
85
105
  appearance: "subtle",
86
106
  onClick: onCancel,
87
- testId: testIds.cancelButton
88
- }, intl.formatMessage(messages.cancelButton)), (0, _react2.jsx)(_button.default, {
107
+ testId: testIds.cancelButton,
108
+ isDisabled: isSubmitting,
109
+ "aria-labelledby": isSubmitting ? submitMessageId : undefined
110
+ }, intl.formatMessage(messages.cancelButton)), (0, _react2.jsx)(_loadingButton.default, {
89
111
  type: "submit",
90
112
  appearance: "primary",
91
113
  testId: testIds.insertButton,
92
- isDisabled: isSubmitDisabled
114
+ isDisabled: isSubmitDisabled,
115
+ "aria-labelledby": isSubmitting ? submitMessageId : undefined,
116
+ isLoading: isSubmitting
93
117
  }, customSubmitButtonLabel ? intl.formatMessage(customSubmitButtonLabel) : intl.formatMessage(insertButtonMsg))));
94
118
  });
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.checkSubmitDisabled = void 0;
7
7
  var _url = require("@atlaskit/linking-common/url");
8
- var checkSubmitDisabled = exports.checkSubmitDisabled = function checkSubmitDisabled(isLoading, error, url, queryState, items) {
8
+ var checkSubmitDisabled = exports.checkSubmitDisabled = function checkSubmitDisabled(isLoading, isSubmitting, error, url, queryState, items) {
9
9
  /*
10
10
  * Enable insert when search term is a valid url and it can be normalized
11
11
  * Need to explicitly enable it here otherwise next condition could meet
@@ -13,6 +13,9 @@ var checkSubmitDisabled = exports.checkSubmitDisabled = function checkSubmitDisa
13
13
  * This should effectively be the validation function for the form, ie if the form
14
14
  * could be submitted, then it should not be disabled
15
15
  */
16
+ if (isSubmitting) {
17
+ return true;
18
+ }
16
19
  if (url && (0, _url.normalizeUrl)(url)) {
17
20
  return false;
18
21
  }
@@ -86,7 +86,9 @@ var LinkPicker = exports.LinkPicker = (0, _analytics.withLinkPickerAnalyticsCont
86
86
  initDisplayText = _ref.displayText,
87
87
  hideDisplayText = _ref.hideDisplayText,
88
88
  featureFlags = _ref.featureFlags,
89
- customMessages = _ref.customMessages;
89
+ customMessages = _ref.customMessages,
90
+ _ref$isSubmitting = _ref.isSubmitting,
91
+ isSubmitting = _ref$isSubmitting === void 0 ? false : _ref$isSubmitting;
90
92
  var _useAnalyticsEvents = (0, _analyticsNext.useAnalyticsEvents)(),
91
93
  createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
92
94
  var _useReducer = (0, _react.useReducer)(reducer, _objectSpread(_objectSpread({}, initState), {}, {
@@ -126,6 +128,11 @@ var LinkPicker = exports.LinkPicker = (0, _analytics.withLinkPickerAnalyticsCont
126
128
  }
127
129
  }, [onContentResize, items, isLoadingResults, isActivePlugin, tabs]);
128
130
  var handleChangeUrl = (0, _react.useCallback)(function (e) {
131
+ if (isSubmitting) {
132
+ // Prevent changing url while submitting
133
+ return;
134
+ }
135
+
129
136
  /** Any on change event is triggered by manual input or paste, so source is null */
130
137
  trackAttribute('linkFieldContentInputSource', null);
131
138
  dispatch({
@@ -133,7 +140,7 @@ var LinkPicker = exports.LinkPicker = (0, _analytics.withLinkPickerAnalyticsCont
133
140
  // If the last action was changing tabs, make sure we're now allowing recents to be hidden
134
141
  preventHidingRecents: false
135
142
  });
136
- }, [dispatch, trackAttribute]);
143
+ }, [dispatch, trackAttribute, isSubmitting]);
137
144
  var handleChangeText = (0, _react.useCallback)(function (e) {
138
145
  dispatch({
139
146
  displayText: e.currentTarget.value
@@ -146,9 +153,13 @@ var LinkPicker = exports.LinkPicker = (0, _analytics.withLinkPickerAnalyticsCont
146
153
  }, field, ''));
147
154
  }, [dispatch]);
148
155
  var handleUrlClear = (0, _react.useCallback)(function () {
156
+ if (isSubmitting) {
157
+ // Prevent clearing url while submitting
158
+ return;
159
+ }
149
160
  trackAttribute('linkFieldContentInputSource', null);
150
161
  handleClear('url');
151
- }, [trackAttribute, handleClear]);
162
+ }, [trackAttribute, handleClear, isSubmitting]);
152
163
  var handleInsert = (0, _react.useCallback)(function (url, title, inputType) {
153
164
  var event = createAnalyticsEvent((0, _analytics2.default)('ui.form.submitted.linkPicker', {}));
154
165
 
@@ -174,6 +185,10 @@ var LinkPicker = exports.LinkPicker = (0, _analytics.withLinkPickerAnalyticsCont
174
185
  } : {}), consumerEvent);
175
186
  }, [displayText, onSubmit, state.url, createAnalyticsEvent, getAttributes]);
176
187
  var handleSelected = (0, _react.useCallback)(function (objectId) {
188
+ if (isSubmitting) {
189
+ // Prevent changing selection while submitting
190
+ return;
191
+ }
177
192
  var selectedItem = items === null || items === void 0 ? void 0 : items.find(function (item) {
178
193
  return item.objectId === objectId;
179
194
  });
@@ -189,9 +204,13 @@ var LinkPicker = exports.LinkPicker = (0, _analytics.withLinkPickerAnalyticsCont
189
204
  trackAttribute('linkFieldContentInputSource', (0, _utils.getDataSource)(selectedItem, activePlugin));
190
205
  handleInsert(_url, name, 'typeAhead');
191
206
  }
192
- }, [handleInsert, trackAttribute, items, activePlugin]);
207
+ }, [handleInsert, trackAttribute, items, activePlugin, isSubmitting]);
193
208
  var handleSubmit = (0, _react.useCallback)(function (event) {
194
209
  event === null || event === void 0 || event.preventDefault();
210
+ if (isSubmitting) {
211
+ // Prevent submit while submitting
212
+ return;
213
+ }
195
214
  if (isSelectedItem && selectedItem) {
196
215
  return handleInsert(selectedItem.url, selectedItem.name, 'typeAhead');
197
216
  }
@@ -202,7 +221,7 @@ var LinkPicker = exports.LinkPicker = (0, _analytics.withLinkPickerAnalyticsCont
202
221
  return dispatch({
203
222
  invalidUrl: true
204
223
  });
205
- }, [dispatch, handleInsert, isSelectedItem, selectedItem, url]);
224
+ }, [dispatch, handleInsert, isSelectedItem, selectedItem, url, isSubmitting]);
206
225
  var handleTabChange = (0, _react.useCallback)(function (activeTab) {
207
226
  var _plugins$activeTab$ta, _plugins$activeTab;
208
227
  dispatch({
@@ -218,6 +237,10 @@ var LinkPicker = exports.LinkPicker = (0, _analytics.withLinkPickerAnalyticsCont
218
237
  trackAttribute('tab', (_plugins$activeTab$ta = plugins === null || plugins === void 0 || (_plugins$activeTab = plugins[activeTab]) === null || _plugins$activeTab === void 0 ? void 0 : _plugins$activeTab.tabKey) !== null && _plugins$activeTab$ta !== void 0 ? _plugins$activeTab$ta : null);
219
238
  }, [dispatch, plugins, trackAttribute]);
220
239
  var handleSearchListOnChange = function handleSearchListOnChange(id) {
240
+ if (isSubmitting) {
241
+ // Prevent changing item while submitting
242
+ return;
243
+ }
221
244
  var index = items === null || items === void 0 ? void 0 : items.findIndex(function (item) {
222
245
  return item.objectId === id;
223
246
  });
@@ -306,6 +329,7 @@ var LinkPicker = exports.LinkPicker = (0, _analytics.withLinkPickerAnalyticsCont
306
329
  "aria-controls": linkSearchListId,
307
330
  "aria-activedescendant": ariaActiveDescendant,
308
331
  "aria-describedby": screenReaderDescriptionId,
332
+ "aria-readonly": isSubmitting,
309
333
  error: invalidUrl ? intl.formatMessage(_messages.formMessages.linkInvalid) : null,
310
334
  spotlightTargetName: "link-picker-search-field-spotlight-target",
311
335
  onClear: handleUrlClear,
@@ -319,6 +343,7 @@ var LinkPicker = exports.LinkPicker = (0, _analytics.withLinkPickerAnalyticsCont
319
343
  label: customMessages !== null && customMessages !== void 0 && customMessages.linkTextLabel ? intl.formatMessage(customMessages.linkTextLabel) : intl.formatMessage(_messages.linkTextMessages.linkTextLabel),
320
344
  placeholder: customMessages !== null && customMessages !== void 0 && customMessages.linkTextPlaceholder ? intl.formatMessage(customMessages === null || customMessages === void 0 ? void 0 : customMessages.linkTextPlaceholder) : intl.formatMessage(_messages.linkTextMessages.linkTextPlaceholder),
321
345
  clearLabel: intl.formatMessage(_messages.linkTextMessages.clearLinkText),
346
+ readOnly: isSubmitting,
322
347
  onClear: handleClear,
323
348
  onChange: handleChangeText
324
349
  }), !!queryState && (isLoadingPlugins || isActivePlugin) && (0, _react2.jsx)(_searchResults.SearchResults, {
@@ -327,6 +352,7 @@ var LinkPicker = exports.LinkPicker = (0, _analytics.withLinkPickerAnalyticsCont
327
352
  activePlugin: activePlugin,
328
353
  isLoadingResults: isLoadingResults,
329
354
  isLoadingPlugins: isLoadingPlugins,
355
+ isSubmitting: isSubmitting,
330
356
  linkSearchListId: linkSearchListId,
331
357
  error: error,
332
358
  featureFlags: featureFlags,
@@ -344,6 +370,7 @@ var LinkPicker = exports.LinkPicker = (0, _analytics.withLinkPickerAnalyticsCont
344
370
  items: items
345
371
  /** If the results section appears to be loading, impact whether the submit button is disabled */,
346
372
  isLoading: isLoadingResults || !!isLoadingPlugins,
373
+ isSubmitting: isSubmitting,
347
374
  queryState: queryState,
348
375
  url: url,
349
376
  isEditing: isEditing,
@@ -35,6 +35,7 @@ var SearchResults = exports.SearchResults = function SearchResults(_ref) {
35
35
  activePlugin = _ref.activePlugin,
36
36
  isLoadingPlugins = _ref.isLoadingPlugins,
37
37
  isLoadingResults = _ref.isLoadingResults,
38
+ isSubmitting = _ref.isSubmitting,
38
39
  handleTabChange = _ref.handleTabChange,
39
40
  handleSearchListOnChange = _ref.handleSearchListOnChange,
40
41
  featureFlags = _ref.featureFlags,
@@ -76,6 +77,7 @@ var SearchResults = exports.SearchResults = function SearchResults(_ref) {
76
77
  })), !error && (0, _react2.jsx)(_linkSearchList.LinkSearchList, {
77
78
  id: linkSearchListId,
78
79
  role: "listbox",
80
+ ariaReadOnly: isSubmitting,
79
81
  items: items,
80
82
  isLoading: isLoadingResults,
81
83
  selectedIndex: selectedIndex,
@@ -21,7 +21,7 @@ var _styled = require("./link-search-no-results/styled");
21
21
  var _listItem = require("./list-item");
22
22
  var _styled2 = require("./styled");
23
23
  var _useTrackResultsShown = require("./use-track-results-shown");
24
- var _excluded = ["onChange", "onSelect", "onKeyDown", "items", "activeIndex", "selectedIndex", "isLoading", "ariaControls", "ariaLabelledBy", "role", "id", "hasSearchTerm", "activePlugin"];
24
+ var _excluded = ["onChange", "onSelect", "onKeyDown", "items", "activeIndex", "selectedIndex", "isLoading", "ariaControls", "ariaLabelledBy", "ariaReadOnly", "role", "id", "hasSearchTerm", "activePlugin"];
25
25
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
26
26
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /** @jsx jsx */
27
27
  var messages = exports.messages = (0, _reactIntlNext.defineMessages)({
@@ -57,6 +57,7 @@ var LinkSearchList = exports.LinkSearchList = /*#__PURE__*/(0, _react.forwardRef
57
57
  isLoading = _ref.isLoading,
58
58
  ariaControls = _ref.ariaControls,
59
59
  ariaLabelledBy = _ref.ariaLabelledBy,
60
+ ariaReadOnly = _ref.ariaReadOnly,
60
61
  role = _ref.role,
61
62
  id = _ref.id,
62
63
  hasSearchTerm = _ref.hasSearchTerm,
@@ -132,6 +133,7 @@ var LinkSearchList = exports.LinkSearchList = /*#__PURE__*/(0, _react.forwardRef
132
133
  css: _styled2.listStyles,
133
134
  "aria-controls": "fabric.smartcard.linkpicker.suggested.results",
134
135
  "aria-labelledby": testIds.resultListTitle,
136
+ "aria-readonly": ariaReadOnly,
135
137
  "data-testid": testIds.searchResultList
136
138
  }, items.map(function (item, index) {
137
139
  return (0, _react2.jsx)(_listItem.LinkSearchListItem, {
@@ -8,13 +8,11 @@ Object.defineProperty(exports, "__esModule", {
8
8
  exports.fetchMessagesForLocale = void 0;
9
9
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
10
10
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
11
- var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
12
- var _en = _interopRequireDefault(require("../../../../i18n/en"));
13
11
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
14
12
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
15
13
  var fetchMessagesForLocale = exports.fetchMessagesForLocale = /*#__PURE__*/function () {
16
14
  var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(locale) {
17
- var _messages, parentLocale, _messages2;
15
+ var messages, parentLocale, _messages;
18
16
  return _regenerator.default.wrap(function _callee$(_context) {
19
17
  while (1) switch (_context.prev = _context.next) {
20
18
  case 0:
@@ -28,8 +26,8 @@ var fetchMessagesForLocale = exports.fetchMessagesForLocale = /*#__PURE__*/funct
28
26
  });
29
27
  }( /* webpackChunkName: "@atlaskit-internal_link-picker-i18n-[request]" */"../../../../i18n/".concat(locale.replace('-', '_')));
30
28
  case 3:
31
- _messages = _context.sent;
32
- return _context.abrupt("return", _messages.default);
29
+ messages = _context.sent;
30
+ return _context.abrupt("return", messages.default);
33
31
  case 7:
34
32
  _context.prev = 7;
35
33
  _context.t0 = _context["catch"](0);
@@ -45,20 +43,12 @@ var fetchMessagesForLocale = exports.fetchMessagesForLocale = /*#__PURE__*/funct
45
43
  });
46
44
  }( /* webpackChunkName: "@atlaskit-internal_link-picker-i18n-[request]" */"../../../../i18n/".concat(parentLocale));
47
45
  case 13:
48
- _messages2 = _context.sent;
49
- return _context.abrupt("return", _messages2.default);
46
+ _messages = _context.sent;
47
+ return _context.abrupt("return", _messages.default);
50
48
  case 17:
51
49
  _context.prev = 17;
52
50
  _context.t1 = _context["catch"](9);
53
51
  case 19:
54
- if (!(0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.link-create.tmp-fix-translations')) {
55
- _context.next = 21;
56
- break;
57
- }
58
- return _context.abrupt("return");
59
- case 21:
60
- return _context.abrupt("return", _en.default);
61
- case 22:
62
52
  case "end":
63
53
  return _context.stop();
64
54
  }
@@ -16,7 +16,7 @@ export const testIds = {
16
16
  };
17
17
  export const PACKAGE_DATA = {
18
18
  packageName: "@atlaskit/link-picker" || '',
19
- packageVersion: "1.31.0" || '',
19
+ packageVersion: "1.32.0" || '',
20
20
  componentName: COMPONENT_NAME,
21
21
  source: COMPONENT_NAME
22
22
  };
@@ -1,15 +1,18 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  /** @jsx jsx */
3
- import { memo } from 'react';
3
+ import { memo, useMemo } from 'react';
4
4
  import { jsx } from '@emotion/react';
5
5
  import { defineMessages, useIntl } from 'react-intl-next';
6
+ import uuid from 'uuid';
6
7
  import Button, { ButtonGroup } from '@atlaskit/button';
8
+ import LoadingButton from '@atlaskit/button/loading-button';
7
9
  import EditorAddIcon from '@atlaskit/icon/glyph/editor/add';
10
+ import VisuallyHidden from '@atlaskit/visually-hidden';
8
11
  import { UnauthenticatedError } from '../../../common/utils/errors';
9
12
  import FeatureDiscovery from './feature-discovery';
10
13
  import { formFooterActionStyles, formFooterStyles } from './styled';
11
14
  import { checkSubmitDisabled } from './utils';
12
- const messages = defineMessages({
15
+ export const messages = defineMessages({
13
16
  cancelButton: {
14
17
  id: 'fabric.linkPicker.button.cancel',
15
18
  defaultMessage: 'Cancel',
@@ -24,17 +27,24 @@ const messages = defineMessages({
24
27
  id: 'fabric.linkPicker.button.insert',
25
28
  defaultMessage: 'Insert',
26
29
  description: 'Button to insert searched or selected link'
30
+ },
31
+ submittingStatusMessage: {
32
+ id: 'fabric.linkPicker.status.submitting',
33
+ defaultMessage: 'Submitting',
34
+ description: 'Accessibility text to indicate the form has been submitted, and submission is in-progress'
27
35
  }
28
36
  });
29
37
  export const testIds = {
30
38
  insertButton: 'link-picker-insert-button',
31
39
  cancelButton: 'link-picker-cancel-button',
32
40
  actionButton: 'link-picker-action-button',
41
+ submitStatusA11yIndicator: 'link-picker-submit-status-a11y-indicator',
33
42
  /** Feature discovery for action button (css pulse) */
34
43
  actionButtonDiscovery: 'link-picker-action-button-discovery'
35
44
  };
36
45
  export const FormFooter = /*#__PURE__*/memo(({
37
46
  isLoading,
47
+ isSubmitting = false,
38
48
  error,
39
49
  url,
40
50
  queryState,
@@ -47,10 +57,11 @@ export const FormFooter = /*#__PURE__*/memo(({
47
57
  ...restProps
48
58
  }) => {
49
59
  const intl = useIntl();
60
+ const submitMessageId = useMemo(() => uuid(), []);
50
61
  if (error && error instanceof UnauthenticatedError) {
51
62
  return null;
52
63
  }
53
- const isSubmitDisabled = checkSubmitDisabled(isLoading, error, url, queryState, items);
64
+ const isSubmitDisabled = checkSubmitDisabled(isLoading, isSubmitting, error, url, queryState, items);
54
65
  const insertButtonMsg = isEditing ? messages.saveButton : messages.insertButton;
55
66
  const createButton = pluginAction => jsx(Button, {
56
67
  testId: testIds.actionButton,
@@ -59,22 +70,32 @@ export const FormFooter = /*#__PURE__*/memo(({
59
70
  iconBefore: jsx(EditorAddIcon, {
60
71
  label: "",
61
72
  size: "medium"
62
- })
73
+ }),
74
+ isDisabled: isSubmitting,
75
+ "aria-labelledby": isSubmitting ? submitMessageId : undefined
63
76
  }, typeof pluginAction.label === 'string' ? pluginAction.label : intl.formatMessage(pluginAction.label));
64
77
  return jsx("footer", _extends({
65
78
  css: formFooterStyles
66
- }, restProps), action && jsx("div", {
79
+ }, restProps), isSubmitting && jsx(VisuallyHidden, {
80
+ role: "status",
81
+ id: submitMessageId,
82
+ testId: testIds.submitStatusA11yIndicator
83
+ }, intl.formatMessage(messages.submittingStatusMessage)), action && jsx("div", {
67
84
  css: formFooterActionStyles
68
85
  }, createFeatureDiscovery ? jsx(FeatureDiscovery, {
69
86
  testId: testIds.actionButtonDiscovery
70
87
  }, createButton(action)) : createButton(action)), jsx(ButtonGroup, null, jsx(Button, {
71
88
  appearance: "subtle",
72
89
  onClick: onCancel,
73
- testId: testIds.cancelButton
74
- }, intl.formatMessage(messages.cancelButton)), jsx(Button, {
90
+ testId: testIds.cancelButton,
91
+ isDisabled: isSubmitting,
92
+ "aria-labelledby": isSubmitting ? submitMessageId : undefined
93
+ }, intl.formatMessage(messages.cancelButton)), jsx(LoadingButton, {
75
94
  type: "submit",
76
95
  appearance: "primary",
77
96
  testId: testIds.insertButton,
78
- isDisabled: isSubmitDisabled
97
+ isDisabled: isSubmitDisabled,
98
+ "aria-labelledby": isSubmitting ? submitMessageId : undefined,
99
+ isLoading: isSubmitting
79
100
  }, customSubmitButtonLabel ? intl.formatMessage(customSubmitButtonLabel) : intl.formatMessage(insertButtonMsg))));
80
101
  });
@@ -1,5 +1,5 @@
1
1
  import { normalizeUrl } from '@atlaskit/linking-common/url';
2
- export const checkSubmitDisabled = (isLoading, error, url, queryState, items) => {
2
+ export const checkSubmitDisabled = (isLoading, isSubmitting, error, url, queryState, items) => {
3
3
  /*
4
4
  * Enable insert when search term is a valid url and it can be normalized
5
5
  * Need to explicitly enable it here otherwise next condition could meet
@@ -7,6 +7,9 @@ export const checkSubmitDisabled = (isLoading, error, url, queryState, items) =>
7
7
  * This should effectively be the validation function for the form, ie if the form
8
8
  * could be submitted, then it should not be disabled
9
9
  */
10
+ if (isSubmitting) {
11
+ return true;
12
+ }
10
13
  if (url && normalizeUrl(url)) {
11
14
  return false;
12
15
  }
@@ -83,7 +83,8 @@ export const LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(({
83
83
  displayText: initDisplayText,
84
84
  hideDisplayText,
85
85
  featureFlags,
86
- customMessages
86
+ customMessages,
87
+ isSubmitting = false
87
88
  }) => {
88
89
  const {
89
90
  createAnalyticsEvent
@@ -127,6 +128,11 @@ export const LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(({
127
128
  }
128
129
  }, [onContentResize, items, isLoadingResults, isActivePlugin, tabs]);
129
130
  const handleChangeUrl = useCallback(e => {
131
+ if (isSubmitting) {
132
+ // Prevent changing url while submitting
133
+ return;
134
+ }
135
+
130
136
  /** Any on change event is triggered by manual input or paste, so source is null */
131
137
  trackAttribute('linkFieldContentInputSource', null);
132
138
  dispatch({
@@ -134,7 +140,7 @@ export const LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(({
134
140
  // If the last action was changing tabs, make sure we're now allowing recents to be hidden
135
141
  preventHidingRecents: false
136
142
  });
137
- }, [dispatch, trackAttribute]);
143
+ }, [dispatch, trackAttribute, isSubmitting]);
138
144
  const handleChangeText = useCallback(e => {
139
145
  dispatch({
140
146
  displayText: e.currentTarget.value
@@ -148,9 +154,13 @@ export const LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(({
148
154
  });
149
155
  }, [dispatch]);
150
156
  const handleUrlClear = useCallback(() => {
157
+ if (isSubmitting) {
158
+ // Prevent clearing url while submitting
159
+ return;
160
+ }
151
161
  trackAttribute('linkFieldContentInputSource', null);
152
162
  handleClear('url');
153
- }, [trackAttribute, handleClear]);
163
+ }, [trackAttribute, handleClear, isSubmitting]);
154
164
  const handleInsert = useCallback((url, title, inputType) => {
155
165
  const event = createAnalyticsEvent(createEventPayload('ui.form.submitted.linkPicker', {}));
156
166
 
@@ -177,6 +187,10 @@ export const LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(({
177
187
  }, consumerEvent);
178
188
  }, [displayText, onSubmit, state.url, createAnalyticsEvent, getAttributes]);
179
189
  const handleSelected = useCallback(objectId => {
190
+ if (isSubmitting) {
191
+ // Prevent changing selection while submitting
192
+ return;
193
+ }
180
194
  const selectedItem = items === null || items === void 0 ? void 0 : items.find(item => item.objectId === objectId);
181
195
  if (selectedItem) {
182
196
  const {
@@ -192,9 +206,13 @@ export const LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(({
192
206
  trackAttribute('linkFieldContentInputSource', getDataSource(selectedItem, activePlugin));
193
207
  handleInsert(url, name, 'typeAhead');
194
208
  }
195
- }, [handleInsert, trackAttribute, items, activePlugin]);
209
+ }, [handleInsert, trackAttribute, items, activePlugin, isSubmitting]);
196
210
  const handleSubmit = useCallback(event => {
197
211
  event === null || event === void 0 ? void 0 : event.preventDefault();
212
+ if (isSubmitting) {
213
+ // Prevent submit while submitting
214
+ return;
215
+ }
198
216
  if (isSelectedItem && selectedItem) {
199
217
  return handleInsert(selectedItem.url, selectedItem.name, 'typeAhead');
200
218
  }
@@ -205,7 +223,7 @@ export const LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(({
205
223
  return dispatch({
206
224
  invalidUrl: true
207
225
  });
208
- }, [dispatch, handleInsert, isSelectedItem, selectedItem, url]);
226
+ }, [dispatch, handleInsert, isSelectedItem, selectedItem, url, isSubmitting]);
209
227
  const handleTabChange = useCallback(activeTab => {
210
228
  var _plugins$activeTab$ta, _plugins$activeTab;
211
229
  dispatch({
@@ -221,6 +239,10 @@ export const LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(({
221
239
  trackAttribute('tab', (_plugins$activeTab$ta = plugins === null || plugins === void 0 ? void 0 : (_plugins$activeTab = plugins[activeTab]) === null || _plugins$activeTab === void 0 ? void 0 : _plugins$activeTab.tabKey) !== null && _plugins$activeTab$ta !== void 0 ? _plugins$activeTab$ta : null);
222
240
  }, [dispatch, plugins, trackAttribute]);
223
241
  const handleSearchListOnChange = id => {
242
+ if (isSubmitting) {
243
+ // Prevent changing item while submitting
244
+ return;
245
+ }
224
246
  const index = items === null || items === void 0 ? void 0 : items.findIndex(item => item.objectId === id);
225
247
  if (typeof index === 'number') {
226
248
  const item = items === null || items === void 0 ? void 0 : items[index];
@@ -307,6 +329,7 @@ export const LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(({
307
329
  "aria-controls": linkSearchListId,
308
330
  "aria-activedescendant": ariaActiveDescendant,
309
331
  "aria-describedby": screenReaderDescriptionId,
332
+ "aria-readonly": isSubmitting,
310
333
  error: invalidUrl ? intl.formatMessage(formMessages.linkInvalid) : null,
311
334
  spotlightTargetName: "link-picker-search-field-spotlight-target",
312
335
  onClear: handleUrlClear,
@@ -320,6 +343,7 @@ export const LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(({
320
343
  label: customMessages !== null && customMessages !== void 0 && customMessages.linkTextLabel ? intl.formatMessage(customMessages.linkTextLabel) : intl.formatMessage(linkTextMessages.linkTextLabel),
321
344
  placeholder: customMessages !== null && customMessages !== void 0 && customMessages.linkTextPlaceholder ? intl.formatMessage(customMessages === null || customMessages === void 0 ? void 0 : customMessages.linkTextPlaceholder) : intl.formatMessage(linkTextMessages.linkTextPlaceholder),
322
345
  clearLabel: intl.formatMessage(linkTextMessages.clearLinkText),
346
+ readOnly: isSubmitting,
323
347
  onClear: handleClear,
324
348
  onChange: handleChangeText
325
349
  }), !!queryState && (isLoadingPlugins || isActivePlugin) && jsx(SearchResults, {
@@ -328,6 +352,7 @@ export const LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(({
328
352
  activePlugin: activePlugin,
329
353
  isLoadingResults: isLoadingResults,
330
354
  isLoadingPlugins: isLoadingPlugins,
355
+ isSubmitting: isSubmitting,
331
356
  linkSearchListId: linkSearchListId,
332
357
  error: error,
333
358
  featureFlags: featureFlags,
@@ -345,6 +370,7 @@ export const LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(({
345
370
  items: items
346
371
  /** If the results section appears to be loading, impact whether the submit button is disabled */,
347
372
  isLoading: isLoadingResults || !!isLoadingPlugins,
373
+ isSubmitting: isSubmitting,
348
374
  queryState: queryState,
349
375
  url: url,
350
376
  isEditing: isEditing,
@@ -24,6 +24,7 @@ export const SearchResults = ({
24
24
  activePlugin,
25
25
  isLoadingPlugins,
26
26
  isLoadingResults,
27
+ isSubmitting,
27
28
  handleTabChange,
28
29
  handleSearchListOnChange,
29
30
  featureFlags,
@@ -65,6 +66,7 @@ export const SearchResults = ({
65
66
  })), !error && jsx(LinkSearchList, {
66
67
  id: linkSearchListId,
67
68
  role: "listbox",
69
+ ariaReadOnly: isSubmitting,
68
70
  items: items,
69
71
  isLoading: isLoadingResults,
70
72
  selectedIndex: selectedIndex,
@@ -48,6 +48,7 @@ export const LinkSearchList = /*#__PURE__*/forwardRef(({
48
48
  isLoading,
49
49
  ariaControls,
50
50
  ariaLabelledBy,
51
+ ariaReadOnly,
51
52
  role,
52
53
  id,
53
54
  hasSearchTerm,
@@ -124,6 +125,7 @@ export const LinkSearchList = /*#__PURE__*/forwardRef(({
124
125
  css: listStyles,
125
126
  "aria-controls": "fabric.smartcard.linkpicker.suggested.results",
126
127
  "aria-labelledby": testIds.resultListTitle,
128
+ "aria-readonly": ariaReadOnly,
127
129
  "data-testid": testIds.searchResultList
128
130
  }, items.map((item, index) => jsx(LinkSearchListItem, {
129
131
  id: `${testIds.searchResultItem}-${index}`,
@@ -1,5 +1,3 @@
1
- import { getBooleanFF } from '@atlaskit/platform-feature-flags';
2
- import messages from '../../../../i18n/en';
3
1
  export const fetchMessagesForLocale = async locale => {
4
2
  try {
5
3
  const messages = await import( /* webpackChunkName: "@atlaskit-internal_link-picker-i18n-[request]" */`../../../../i18n/${locale.replace('-', '_')}`);
@@ -14,12 +12,4 @@ export const fetchMessagesForLocale = async locale => {
14
12
  } catch (e) {
15
13
  // ignore
16
14
  }
17
- if (getBooleanFF('platform.linking-platform.link-create.tmp-fix-translations')) {
18
- return;
19
- }
20
-
21
- /**
22
- * English bundled by default as this is the majority of users
23
- */
24
- return messages;
25
15
  };
@@ -17,7 +17,7 @@ export var testIds = {
17
17
  };
18
18
  export var PACKAGE_DATA = {
19
19
  packageName: "@atlaskit/link-picker" || '',
20
- packageVersion: "1.31.0" || '',
20
+ packageVersion: "1.32.0" || '',
21
21
  componentName: COMPONENT_NAME,
22
22
  source: COMPONENT_NAME
23
23
  };
@@ -1,17 +1,20 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
- var _excluded = ["isLoading", "error", "url", "queryState", "items", "isEditing", "onCancel", "action", "createFeatureDiscovery", "customSubmitButtonLabel"];
3
+ var _excluded = ["isLoading", "isSubmitting", "error", "url", "queryState", "items", "isEditing", "onCancel", "action", "createFeatureDiscovery", "customSubmitButtonLabel"];
4
4
  /** @jsx jsx */
5
- import { memo } from 'react';
5
+ import { memo, useMemo } from 'react';
6
6
  import { jsx } from '@emotion/react';
7
7
  import { defineMessages, useIntl } from 'react-intl-next';
8
+ import uuid from 'uuid';
8
9
  import Button, { ButtonGroup } from '@atlaskit/button';
10
+ import LoadingButton from '@atlaskit/button/loading-button';
9
11
  import EditorAddIcon from '@atlaskit/icon/glyph/editor/add';
12
+ import VisuallyHidden from '@atlaskit/visually-hidden';
10
13
  import { UnauthenticatedError } from '../../../common/utils/errors';
11
14
  import FeatureDiscovery from './feature-discovery';
12
15
  import { formFooterActionStyles, formFooterStyles } from './styled';
13
16
  import { checkSubmitDisabled } from './utils';
14
- var messages = defineMessages({
17
+ export var messages = defineMessages({
15
18
  cancelButton: {
16
19
  id: 'fabric.linkPicker.button.cancel',
17
20
  defaultMessage: 'Cancel',
@@ -26,17 +29,25 @@ var messages = defineMessages({
26
29
  id: 'fabric.linkPicker.button.insert',
27
30
  defaultMessage: 'Insert',
28
31
  description: 'Button to insert searched or selected link'
32
+ },
33
+ submittingStatusMessage: {
34
+ id: 'fabric.linkPicker.status.submitting',
35
+ defaultMessage: 'Submitting',
36
+ description: 'Accessibility text to indicate the form has been submitted, and submission is in-progress'
29
37
  }
30
38
  });
31
39
  export var testIds = {
32
40
  insertButton: 'link-picker-insert-button',
33
41
  cancelButton: 'link-picker-cancel-button',
34
42
  actionButton: 'link-picker-action-button',
43
+ submitStatusA11yIndicator: 'link-picker-submit-status-a11y-indicator',
35
44
  /** Feature discovery for action button (css pulse) */
36
45
  actionButtonDiscovery: 'link-picker-action-button-discovery'
37
46
  };
38
47
  export var FormFooter = /*#__PURE__*/memo(function (_ref) {
39
48
  var isLoading = _ref.isLoading,
49
+ _ref$isSubmitting = _ref.isSubmitting,
50
+ isSubmitting = _ref$isSubmitting === void 0 ? false : _ref$isSubmitting,
40
51
  error = _ref.error,
41
52
  url = _ref.url,
42
53
  queryState = _ref.queryState,
@@ -49,10 +60,13 @@ export var FormFooter = /*#__PURE__*/memo(function (_ref) {
49
60
  customSubmitButtonLabel = _ref.customSubmitButtonLabel,
50
61
  restProps = _objectWithoutProperties(_ref, _excluded);
51
62
  var intl = useIntl();
63
+ var submitMessageId = useMemo(function () {
64
+ return uuid();
65
+ }, []);
52
66
  if (error && error instanceof UnauthenticatedError) {
53
67
  return null;
54
68
  }
55
- var isSubmitDisabled = checkSubmitDisabled(isLoading, error, url, queryState, items);
69
+ var isSubmitDisabled = checkSubmitDisabled(isLoading, isSubmitting, error, url, queryState, items);
56
70
  var insertButtonMsg = isEditing ? messages.saveButton : messages.insertButton;
57
71
  var createButton = function createButton(pluginAction) {
58
72
  return jsx(Button, {
@@ -62,23 +76,33 @@ export var FormFooter = /*#__PURE__*/memo(function (_ref) {
62
76
  iconBefore: jsx(EditorAddIcon, {
63
77
  label: "",
64
78
  size: "medium"
65
- })
79
+ }),
80
+ isDisabled: isSubmitting,
81
+ "aria-labelledby": isSubmitting ? submitMessageId : undefined
66
82
  }, typeof pluginAction.label === 'string' ? pluginAction.label : intl.formatMessage(pluginAction.label));
67
83
  };
68
84
  return jsx("footer", _extends({
69
85
  css: formFooterStyles
70
- }, restProps), action && jsx("div", {
86
+ }, restProps), isSubmitting && jsx(VisuallyHidden, {
87
+ role: "status",
88
+ id: submitMessageId,
89
+ testId: testIds.submitStatusA11yIndicator
90
+ }, intl.formatMessage(messages.submittingStatusMessage)), action && jsx("div", {
71
91
  css: formFooterActionStyles
72
92
  }, createFeatureDiscovery ? jsx(FeatureDiscovery, {
73
93
  testId: testIds.actionButtonDiscovery
74
94
  }, createButton(action)) : createButton(action)), jsx(ButtonGroup, null, jsx(Button, {
75
95
  appearance: "subtle",
76
96
  onClick: onCancel,
77
- testId: testIds.cancelButton
78
- }, intl.formatMessage(messages.cancelButton)), jsx(Button, {
97
+ testId: testIds.cancelButton,
98
+ isDisabled: isSubmitting,
99
+ "aria-labelledby": isSubmitting ? submitMessageId : undefined
100
+ }, intl.formatMessage(messages.cancelButton)), jsx(LoadingButton, {
79
101
  type: "submit",
80
102
  appearance: "primary",
81
103
  testId: testIds.insertButton,
82
- isDisabled: isSubmitDisabled
104
+ isDisabled: isSubmitDisabled,
105
+ "aria-labelledby": isSubmitting ? submitMessageId : undefined,
106
+ isLoading: isSubmitting
83
107
  }, customSubmitButtonLabel ? intl.formatMessage(customSubmitButtonLabel) : intl.formatMessage(insertButtonMsg))));
84
108
  });
@@ -1,5 +1,5 @@
1
1
  import { normalizeUrl } from '@atlaskit/linking-common/url';
2
- export var checkSubmitDisabled = function checkSubmitDisabled(isLoading, error, url, queryState, items) {
2
+ export var checkSubmitDisabled = function checkSubmitDisabled(isLoading, isSubmitting, error, url, queryState, items) {
3
3
  /*
4
4
  * Enable insert when search term is a valid url and it can be normalized
5
5
  * Need to explicitly enable it here otherwise next condition could meet
@@ -7,6 +7,9 @@ export var checkSubmitDisabled = function checkSubmitDisabled(isLoading, error,
7
7
  * This should effectively be the validation function for the form, ie if the form
8
8
  * could be submitted, then it should not be disabled
9
9
  */
10
+ if (isSubmitting) {
11
+ return true;
12
+ }
10
13
  if (url && normalizeUrl(url)) {
11
14
  return false;
12
15
  }
@@ -80,7 +80,9 @@ export var LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(functi
80
80
  initDisplayText = _ref.displayText,
81
81
  hideDisplayText = _ref.hideDisplayText,
82
82
  featureFlags = _ref.featureFlags,
83
- customMessages = _ref.customMessages;
83
+ customMessages = _ref.customMessages,
84
+ _ref$isSubmitting = _ref.isSubmitting,
85
+ isSubmitting = _ref$isSubmitting === void 0 ? false : _ref$isSubmitting;
84
86
  var _useAnalyticsEvents = useAnalyticsEvents(),
85
87
  createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;
86
88
  var _useReducer = useReducer(reducer, _objectSpread(_objectSpread({}, initState), {}, {
@@ -120,6 +122,11 @@ export var LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(functi
120
122
  }
121
123
  }, [onContentResize, items, isLoadingResults, isActivePlugin, tabs]);
122
124
  var handleChangeUrl = useCallback(function (e) {
125
+ if (isSubmitting) {
126
+ // Prevent changing url while submitting
127
+ return;
128
+ }
129
+
123
130
  /** Any on change event is triggered by manual input or paste, so source is null */
124
131
  trackAttribute('linkFieldContentInputSource', null);
125
132
  dispatch({
@@ -127,7 +134,7 @@ export var LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(functi
127
134
  // If the last action was changing tabs, make sure we're now allowing recents to be hidden
128
135
  preventHidingRecents: false
129
136
  });
130
- }, [dispatch, trackAttribute]);
137
+ }, [dispatch, trackAttribute, isSubmitting]);
131
138
  var handleChangeText = useCallback(function (e) {
132
139
  dispatch({
133
140
  displayText: e.currentTarget.value
@@ -140,9 +147,13 @@ export var LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(functi
140
147
  }, field, ''));
141
148
  }, [dispatch]);
142
149
  var handleUrlClear = useCallback(function () {
150
+ if (isSubmitting) {
151
+ // Prevent clearing url while submitting
152
+ return;
153
+ }
143
154
  trackAttribute('linkFieldContentInputSource', null);
144
155
  handleClear('url');
145
- }, [trackAttribute, handleClear]);
156
+ }, [trackAttribute, handleClear, isSubmitting]);
146
157
  var handleInsert = useCallback(function (url, title, inputType) {
147
158
  var event = createAnalyticsEvent(createEventPayload('ui.form.submitted.linkPicker', {}));
148
159
 
@@ -168,6 +179,10 @@ export var LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(functi
168
179
  } : {}), consumerEvent);
169
180
  }, [displayText, onSubmit, state.url, createAnalyticsEvent, getAttributes]);
170
181
  var handleSelected = useCallback(function (objectId) {
182
+ if (isSubmitting) {
183
+ // Prevent changing selection while submitting
184
+ return;
185
+ }
171
186
  var selectedItem = items === null || items === void 0 ? void 0 : items.find(function (item) {
172
187
  return item.objectId === objectId;
173
188
  });
@@ -183,9 +198,13 @@ export var LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(functi
183
198
  trackAttribute('linkFieldContentInputSource', getDataSource(selectedItem, activePlugin));
184
199
  handleInsert(_url, name, 'typeAhead');
185
200
  }
186
- }, [handleInsert, trackAttribute, items, activePlugin]);
201
+ }, [handleInsert, trackAttribute, items, activePlugin, isSubmitting]);
187
202
  var handleSubmit = useCallback(function (event) {
188
203
  event === null || event === void 0 || event.preventDefault();
204
+ if (isSubmitting) {
205
+ // Prevent submit while submitting
206
+ return;
207
+ }
189
208
  if (isSelectedItem && selectedItem) {
190
209
  return handleInsert(selectedItem.url, selectedItem.name, 'typeAhead');
191
210
  }
@@ -196,7 +215,7 @@ export var LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(functi
196
215
  return dispatch({
197
216
  invalidUrl: true
198
217
  });
199
- }, [dispatch, handleInsert, isSelectedItem, selectedItem, url]);
218
+ }, [dispatch, handleInsert, isSelectedItem, selectedItem, url, isSubmitting]);
200
219
  var handleTabChange = useCallback(function (activeTab) {
201
220
  var _plugins$activeTab$ta, _plugins$activeTab;
202
221
  dispatch({
@@ -212,6 +231,10 @@ export var LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(functi
212
231
  trackAttribute('tab', (_plugins$activeTab$ta = plugins === null || plugins === void 0 || (_plugins$activeTab = plugins[activeTab]) === null || _plugins$activeTab === void 0 ? void 0 : _plugins$activeTab.tabKey) !== null && _plugins$activeTab$ta !== void 0 ? _plugins$activeTab$ta : null);
213
232
  }, [dispatch, plugins, trackAttribute]);
214
233
  var handleSearchListOnChange = function handleSearchListOnChange(id) {
234
+ if (isSubmitting) {
235
+ // Prevent changing item while submitting
236
+ return;
237
+ }
215
238
  var index = items === null || items === void 0 ? void 0 : items.findIndex(function (item) {
216
239
  return item.objectId === id;
217
240
  });
@@ -300,6 +323,7 @@ export var LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(functi
300
323
  "aria-controls": linkSearchListId,
301
324
  "aria-activedescendant": ariaActiveDescendant,
302
325
  "aria-describedby": screenReaderDescriptionId,
326
+ "aria-readonly": isSubmitting,
303
327
  error: invalidUrl ? intl.formatMessage(formMessages.linkInvalid) : null,
304
328
  spotlightTargetName: "link-picker-search-field-spotlight-target",
305
329
  onClear: handleUrlClear,
@@ -313,6 +337,7 @@ export var LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(functi
313
337
  label: customMessages !== null && customMessages !== void 0 && customMessages.linkTextLabel ? intl.formatMessage(customMessages.linkTextLabel) : intl.formatMessage(linkTextMessages.linkTextLabel),
314
338
  placeholder: customMessages !== null && customMessages !== void 0 && customMessages.linkTextPlaceholder ? intl.formatMessage(customMessages === null || customMessages === void 0 ? void 0 : customMessages.linkTextPlaceholder) : intl.formatMessage(linkTextMessages.linkTextPlaceholder),
315
339
  clearLabel: intl.formatMessage(linkTextMessages.clearLinkText),
340
+ readOnly: isSubmitting,
316
341
  onClear: handleClear,
317
342
  onChange: handleChangeText
318
343
  }), !!queryState && (isLoadingPlugins || isActivePlugin) && jsx(SearchResults, {
@@ -321,6 +346,7 @@ export var LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(functi
321
346
  activePlugin: activePlugin,
322
347
  isLoadingResults: isLoadingResults,
323
348
  isLoadingPlugins: isLoadingPlugins,
349
+ isSubmitting: isSubmitting,
324
350
  linkSearchListId: linkSearchListId,
325
351
  error: error,
326
352
  featureFlags: featureFlags,
@@ -338,6 +364,7 @@ export var LinkPicker = withLinkPickerAnalyticsContext( /*#__PURE__*/memo(functi
338
364
  items: items
339
365
  /** If the results section appears to be loading, impact whether the submit button is disabled */,
340
366
  isLoading: isLoadingResults || !!isLoadingPlugins,
367
+ isSubmitting: isSubmitting,
341
368
  queryState: queryState,
342
369
  url: url,
343
370
  isEditing: isEditing,
@@ -26,6 +26,7 @@ export var SearchResults = function SearchResults(_ref) {
26
26
  activePlugin = _ref.activePlugin,
27
27
  isLoadingPlugins = _ref.isLoadingPlugins,
28
28
  isLoadingResults = _ref.isLoadingResults,
29
+ isSubmitting = _ref.isSubmitting,
29
30
  handleTabChange = _ref.handleTabChange,
30
31
  handleSearchListOnChange = _ref.handleSearchListOnChange,
31
32
  featureFlags = _ref.featureFlags,
@@ -67,6 +68,7 @@ export var SearchResults = function SearchResults(_ref) {
67
68
  })), !error && jsx(LinkSearchList, {
68
69
  id: linkSearchListId,
69
70
  role: "listbox",
71
+ ariaReadOnly: isSubmitting,
70
72
  items: items,
71
73
  isLoading: isLoadingResults,
72
74
  selectedIndex: selectedIndex,
@@ -1,7 +1,7 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
- var _excluded = ["onChange", "onSelect", "onKeyDown", "items", "activeIndex", "selectedIndex", "isLoading", "ariaControls", "ariaLabelledBy", "role", "id", "hasSearchTerm", "activePlugin"];
4
+ var _excluded = ["onChange", "onSelect", "onKeyDown", "items", "activeIndex", "selectedIndex", "isLoading", "ariaControls", "ariaLabelledBy", "ariaReadOnly", "role", "id", "hasSearchTerm", "activePlugin"];
5
5
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
6
6
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
7
7
  /** @jsx jsx */
@@ -51,6 +51,7 @@ export var LinkSearchList = /*#__PURE__*/forwardRef(function (_ref, ref) {
51
51
  isLoading = _ref.isLoading,
52
52
  ariaControls = _ref.ariaControls,
53
53
  ariaLabelledBy = _ref.ariaLabelledBy,
54
+ ariaReadOnly = _ref.ariaReadOnly,
54
55
  role = _ref.role,
55
56
  id = _ref.id,
56
57
  hasSearchTerm = _ref.hasSearchTerm,
@@ -126,6 +127,7 @@ export var LinkSearchList = /*#__PURE__*/forwardRef(function (_ref, ref) {
126
127
  css: listStyles,
127
128
  "aria-controls": "fabric.smartcard.linkpicker.suggested.results",
128
129
  "aria-labelledby": testIds.resultListTitle,
130
+ "aria-readonly": ariaReadOnly,
129
131
  "data-testid": testIds.searchResultList
130
132
  }, items.map(function (item, index) {
131
133
  return jsx(LinkSearchListItem, {
@@ -1,10 +1,8 @@
1
1
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
2
  import _regeneratorRuntime from "@babel/runtime/regenerator";
3
- import { getBooleanFF } from '@atlaskit/platform-feature-flags';
4
- import messages from '../../../../i18n/en';
5
3
  export var fetchMessagesForLocale = /*#__PURE__*/function () {
6
4
  var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(locale) {
7
- var _messages, parentLocale, _messages2;
5
+ var messages, parentLocale, _messages;
8
6
  return _regeneratorRuntime.wrap(function _callee$(_context) {
9
7
  while (1) switch (_context.prev = _context.next) {
10
8
  case 0:
@@ -12,8 +10,8 @@ export var fetchMessagesForLocale = /*#__PURE__*/function () {
12
10
  _context.next = 3;
13
11
  return import( /* webpackChunkName: "@atlaskit-internal_link-picker-i18n-[request]" */"../../../../i18n/".concat(locale.replace('-', '_')));
14
12
  case 3:
15
- _messages = _context.sent;
16
- return _context.abrupt("return", _messages.default);
13
+ messages = _context.sent;
14
+ return _context.abrupt("return", messages.default);
17
15
  case 7:
18
16
  _context.prev = 7;
19
17
  _context.t0 = _context["catch"](0);
@@ -23,20 +21,12 @@ export var fetchMessagesForLocale = /*#__PURE__*/function () {
23
21
  _context.next = 13;
24
22
  return import( /* webpackChunkName: "@atlaskit-internal_link-picker-i18n-[request]" */"../../../../i18n/".concat(parentLocale));
25
23
  case 13:
26
- _messages2 = _context.sent;
27
- return _context.abrupt("return", _messages2.default);
24
+ _messages = _context.sent;
25
+ return _context.abrupt("return", _messages.default);
28
26
  case 17:
29
27
  _context.prev = 17;
30
28
  _context.t1 = _context["catch"](9);
31
29
  case 19:
32
- if (!getBooleanFF('platform.linking-platform.link-create.tmp-fix-translations')) {
33
- _context.next = 21;
34
- break;
35
- }
36
- return _context.abrupt("return");
37
- case 21:
38
- return _context.abrupt("return", messages);
39
- case 22:
40
30
  case "end":
41
31
  return _context.stop();
42
32
  }
@@ -2,16 +2,41 @@
2
2
  import { jsx } from '@emotion/react';
3
3
  import { MessageDescriptor } from 'react-intl-next';
4
4
  import { LinkPickerPluginAction, LinkPickerState, LinkSearchListItemData } from '../../../common/types';
5
+ export declare const messages: {
6
+ cancelButton: {
7
+ id: string;
8
+ defaultMessage: string;
9
+ description: string;
10
+ };
11
+ saveButton: {
12
+ id: string;
13
+ defaultMessage: string;
14
+ description: string;
15
+ };
16
+ insertButton: {
17
+ id: string;
18
+ defaultMessage: string;
19
+ description: string;
20
+ };
21
+ submittingStatusMessage: {
22
+ id: string;
23
+ defaultMessage: string;
24
+ description: string;
25
+ };
26
+ };
5
27
  export declare const testIds: {
6
28
  readonly insertButton: "link-picker-insert-button";
7
29
  readonly cancelButton: "link-picker-cancel-button";
8
30
  readonly actionButton: "link-picker-action-button";
31
+ readonly submitStatusA11yIndicator: "link-picker-submit-status-a11y-indicator";
9
32
  /** Feature discovery for action button (css pulse) */
10
33
  readonly actionButtonDiscovery: "link-picker-action-button-discovery";
11
34
  };
12
35
  interface FormFooterProps extends React.HTMLAttributes<HTMLElement> {
13
36
  /** If the results section appears to be loading, impact whether the submit button is disabled */
14
37
  isLoading: boolean;
38
+ /** Controls showing a "submission in-progres" UX */
39
+ isSubmitting?: boolean;
15
40
  error: unknown | null;
16
41
  url: string;
17
42
  queryState: LinkPickerState | null;
@@ -22,5 +47,5 @@ interface FormFooterProps extends React.HTMLAttributes<HTMLElement> {
22
47
  createFeatureDiscovery?: boolean;
23
48
  customSubmitButtonLabel?: MessageDescriptor;
24
49
  }
25
- export declare const FormFooter: import("react").MemoExoticComponent<({ isLoading, error, url, queryState, items, isEditing, onCancel, action, createFeatureDiscovery, customSubmitButtonLabel, ...restProps }: FormFooterProps) => jsx.JSX.Element | null>;
50
+ export declare const FormFooter: import("react").MemoExoticComponent<({ isLoading, isSubmitting, error, url, queryState, items, isEditing, onCancel, action, createFeatureDiscovery, customSubmitButtonLabel, ...restProps }: FormFooterProps) => jsx.JSX.Element | null>;
26
51
  export {};
@@ -1,2 +1,2 @@
1
1
  import { LinkPickerState, LinkSearchListItemData } from '../../../common/types';
2
- export declare const checkSubmitDisabled: (isLoading: boolean, error: unknown | null, url: string, queryState: LinkPickerState | null, items: LinkSearchListItemData[] | null) => boolean;
2
+ export declare const checkSubmitDisabled: (isLoading: boolean, isSubmitting: boolean, error: unknown | null, url: string, queryState: LinkPickerState | null, items: LinkSearchListItemData[] | null) => boolean;
@@ -8,6 +8,7 @@ export declare const testIds: {
8
8
  readonly insertButton: "link-picker-insert-button";
9
9
  readonly cancelButton: "link-picker-cancel-button";
10
10
  readonly actionButton: "link-picker-action-button";
11
+ readonly submitStatusA11yIndicator: "link-picker-submit-status-a11y-indicator";
11
12
  readonly actionButtonDiscovery: "link-picker-action-button-discovery";
12
13
  readonly tabsLoadingIndicator: string;
13
14
  readonly tabList: string;
@@ -81,6 +82,8 @@ export interface LinkPickerProps {
81
82
  /** Allows for customisation of text in the link picker. */
82
83
  customMessages?: CustomLinkPickerMessages;
83
84
  featureFlags?: Record<string, unknown>;
85
+ /** Controls showing a "submission in-progres" UX */
86
+ isSubmitting?: boolean;
84
87
  }
85
88
  type CustomLinkPickerMessages = {
86
89
  /** Label for the link input field */
@@ -21,6 +21,7 @@ export type SearchResultsProps = {
21
21
  }[];
22
22
  isLoadingPlugins?: boolean;
23
23
  isLoadingResults: boolean;
24
+ isSubmitting?: boolean;
24
25
  activeTab: number;
25
26
  handleTabChange: (activeTab: number) => void;
26
27
  handleSearchListOnChange: (id: string) => void;
@@ -37,4 +38,4 @@ export type SearchResultsProps = {
37
38
  error?: unknown;
38
39
  retry: () => void;
39
40
  };
40
- export declare const SearchResults: ({ tabs, activeTab, activePlugin, isLoadingPlugins, isLoadingResults, handleTabChange, handleSearchListOnChange, featureFlags, linkSearchListId, error, queryState, items, activeIndex, selectedIndex, handleSelected, handleKeyDown, retry, }: SearchResultsProps) => jsx.JSX.Element;
41
+ export declare const SearchResults: ({ tabs, activeTab, activePlugin, isLoadingPlugins, isLoadingResults, isSubmitting, handleTabChange, handleSearchListOnChange, featureFlags, linkSearchListId, error, queryState, items, activeIndex, selectedIndex, handleSelected, handleKeyDown, retry, }: SearchResultsProps) => jsx.JSX.Element;
@@ -38,6 +38,7 @@ export interface LinkSearchListProps extends Omit<React.HTMLAttributes<LinkSearc
38
38
  onKeyDown?: (e: KeyboardEvent<LinkSearchListElement>) => void;
39
39
  ariaControls?: string;
40
40
  ariaLabelledBy?: string;
41
+ ariaReadOnly?: boolean;
41
42
  role?: string;
42
43
  id?: string;
43
44
  hasSearchTerm?: boolean;
@@ -2,16 +2,41 @@
2
2
  import { jsx } from '@emotion/react';
3
3
  import { MessageDescriptor } from 'react-intl-next';
4
4
  import { LinkPickerPluginAction, LinkPickerState, LinkSearchListItemData } from '../../../common/types';
5
+ export declare const messages: {
6
+ cancelButton: {
7
+ id: string;
8
+ defaultMessage: string;
9
+ description: string;
10
+ };
11
+ saveButton: {
12
+ id: string;
13
+ defaultMessage: string;
14
+ description: string;
15
+ };
16
+ insertButton: {
17
+ id: string;
18
+ defaultMessage: string;
19
+ description: string;
20
+ };
21
+ submittingStatusMessage: {
22
+ id: string;
23
+ defaultMessage: string;
24
+ description: string;
25
+ };
26
+ };
5
27
  export declare const testIds: {
6
28
  readonly insertButton: "link-picker-insert-button";
7
29
  readonly cancelButton: "link-picker-cancel-button";
8
30
  readonly actionButton: "link-picker-action-button";
31
+ readonly submitStatusA11yIndicator: "link-picker-submit-status-a11y-indicator";
9
32
  /** Feature discovery for action button (css pulse) */
10
33
  readonly actionButtonDiscovery: "link-picker-action-button-discovery";
11
34
  };
12
35
  interface FormFooterProps extends React.HTMLAttributes<HTMLElement> {
13
36
  /** If the results section appears to be loading, impact whether the submit button is disabled */
14
37
  isLoading: boolean;
38
+ /** Controls showing a "submission in-progres" UX */
39
+ isSubmitting?: boolean;
15
40
  error: unknown | null;
16
41
  url: string;
17
42
  queryState: LinkPickerState | null;
@@ -22,5 +47,5 @@ interface FormFooterProps extends React.HTMLAttributes<HTMLElement> {
22
47
  createFeatureDiscovery?: boolean;
23
48
  customSubmitButtonLabel?: MessageDescriptor;
24
49
  }
25
- export declare const FormFooter: import("react").MemoExoticComponent<({ isLoading, error, url, queryState, items, isEditing, onCancel, action, createFeatureDiscovery, customSubmitButtonLabel, ...restProps }: FormFooterProps) => jsx.JSX.Element | null>;
50
+ export declare const FormFooter: import("react").MemoExoticComponent<({ isLoading, isSubmitting, error, url, queryState, items, isEditing, onCancel, action, createFeatureDiscovery, customSubmitButtonLabel, ...restProps }: FormFooterProps) => jsx.JSX.Element | null>;
26
51
  export {};
@@ -1,2 +1,2 @@
1
1
  import { LinkPickerState, LinkSearchListItemData } from '../../../common/types';
2
- export declare const checkSubmitDisabled: (isLoading: boolean, error: unknown | null, url: string, queryState: LinkPickerState | null, items: LinkSearchListItemData[] | null) => boolean;
2
+ export declare const checkSubmitDisabled: (isLoading: boolean, isSubmitting: boolean, error: unknown | null, url: string, queryState: LinkPickerState | null, items: LinkSearchListItemData[] | null) => boolean;
@@ -8,6 +8,7 @@ export declare const testIds: {
8
8
  readonly insertButton: "link-picker-insert-button";
9
9
  readonly cancelButton: "link-picker-cancel-button";
10
10
  readonly actionButton: "link-picker-action-button";
11
+ readonly submitStatusA11yIndicator: "link-picker-submit-status-a11y-indicator";
11
12
  readonly actionButtonDiscovery: "link-picker-action-button-discovery";
12
13
  readonly tabsLoadingIndicator: string;
13
14
  readonly tabList: string;
@@ -81,6 +82,8 @@ export interface LinkPickerProps {
81
82
  /** Allows for customisation of text in the link picker. */
82
83
  customMessages?: CustomLinkPickerMessages;
83
84
  featureFlags?: Record<string, unknown>;
85
+ /** Controls showing a "submission in-progres" UX */
86
+ isSubmitting?: boolean;
84
87
  }
85
88
  type CustomLinkPickerMessages = {
86
89
  /** Label for the link input field */
@@ -21,6 +21,7 @@ export type SearchResultsProps = {
21
21
  }[];
22
22
  isLoadingPlugins?: boolean;
23
23
  isLoadingResults: boolean;
24
+ isSubmitting?: boolean;
24
25
  activeTab: number;
25
26
  handleTabChange: (activeTab: number) => void;
26
27
  handleSearchListOnChange: (id: string) => void;
@@ -37,4 +38,4 @@ export type SearchResultsProps = {
37
38
  error?: unknown;
38
39
  retry: () => void;
39
40
  };
40
- export declare const SearchResults: ({ tabs, activeTab, activePlugin, isLoadingPlugins, isLoadingResults, handleTabChange, handleSearchListOnChange, featureFlags, linkSearchListId, error, queryState, items, activeIndex, selectedIndex, handleSelected, handleKeyDown, retry, }: SearchResultsProps) => jsx.JSX.Element;
41
+ export declare const SearchResults: ({ tabs, activeTab, activePlugin, isLoadingPlugins, isLoadingResults, isSubmitting, handleTabChange, handleSearchListOnChange, featureFlags, linkSearchListId, error, queryState, items, activeIndex, selectedIndex, handleSelected, handleKeyDown, retry, }: SearchResultsProps) => jsx.JSX.Element;
@@ -38,6 +38,7 @@ export interface LinkSearchListProps extends Omit<React.HTMLAttributes<LinkSearc
38
38
  onKeyDown?: (e: KeyboardEvent<LinkSearchListElement>) => void;
39
39
  ariaControls?: string;
40
40
  ariaLabelledBy?: string;
41
+ ariaReadOnly?: boolean;
41
42
  role?: string;
42
43
  id?: string;
43
44
  hasSearchTerm?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/link-picker",
3
- "version": "1.31.0",
3
+ "version": "1.32.0",
4
4
  "description": "Standalone link picker",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "publishConfig": {
@@ -49,9 +49,6 @@
49
49
  },
50
50
  "platform.linking-platform.link-picker.enable-jira-create": {
51
51
  "type": "boolean"
52
- },
53
- "platform.linking-platform.link-create.tmp-fix-translations": {
54
- "type": "boolean"
55
52
  }
56
53
  },
57
54
  "scripts": {