@atlaskit/feedback-collector 15.4.0 → 15.6.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @atlaskit/feedback-collector
2
2
 
3
+ ## 15.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`fcbbf3c80f95a`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/fcbbf3c80f95a) -
8
+ [ux] AX-2068 — Announce feedback collector validation errors to screen readers and move focus to
9
+ the first invalid field on failed submit by delegating validation to @atlaskit/form's built-in
10
+ Field validate API.
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies
15
+
16
+ ## 15.5.0
17
+
18
+ ### Minor Changes
19
+
20
+ - [`7bbde375a3b30`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/7bbde375a3b30) -
21
+ Add onCancel callback to FeedbackCollector and FeedbackForm
22
+
3
23
  ## 15.4.0
4
24
 
5
25
  ### Minor Changes
@@ -164,7 +164,7 @@ var FeedbackCollector = exports.default = /*#__PURE__*/function (_Component) {
164
164
  }, {
165
165
  key: "getPackageVersion",
166
166
  value: function getPackageVersion() {
167
- return "15.3.0" || 'Unknown, at least 11.0.0';
167
+ return "15.5.0" || 'Unknown, at least 11.0.0';
168
168
  }
169
169
  }, {
170
170
  key: "getEntitlementInformation",
@@ -7,7 +7,6 @@ Object.defineProperty(exports, "__esModule", {
7
7
  });
8
8
  exports.default = void 0;
9
9
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
10
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
10
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
12
11
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
13
12
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
@@ -29,8 +28,6 @@ var _excluded = ["id"],
29
28
  _excluded2 = ["id"],
30
29
  _excluded3 = ["locale"];
31
30
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
32
- 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; }
33
- 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; }
34
31
  var LinkWrapper = function LinkWrapper(_ref) {
35
32
  var children = _ref.children;
36
33
  return /*#__PURE__*/_react.default.createElement("span", {
@@ -91,36 +88,33 @@ var FeedbackForm = function FeedbackForm(_ref2) {
91
88
  _useState0 = (0, _slicedToArray2.default)(_useState9, 2),
92
89
  isSubmitting = _useState0[0],
93
90
  setIsSubmitting = _useState0[1];
94
- var _useState1 = (0, _react.useState)({}),
95
- _useState10 = (0, _slicedToArray2.default)(_useState1, 2),
96
- validationErrors = _useState10[0],
97
- setValidationErrors = _useState10[1];
98
91
  var _useIntl = (0, _reactIntl.useIntl)(),
99
92
  formatMessage = _useIntl.formatMessage;
100
93
  var isTypeSelected = function isTypeSelected() {
101
94
  return type !== 'empty';
102
95
  };
103
- var handleCancel = function handleCancel() {
104
- onCancel === null || onCancel === void 0 || onCancel();
105
- onClose();
96
+ var validateType = function validateType(value) {
97
+ return showTypeField && (!value || value === 'empty') ? formatMessage(_messages.messages.validationErrorTypeRequired) : undefined;
106
98
  };
107
- var canShowTextField = isTypeSelected() || !showTypeField;
108
- var hasDescription = description || hasDescriptionDefaultValue;
109
- var isDisabled = isSubmitting || disableSubmitButton;
110
- var getValidationErrors = function getValidationErrors() {
111
- var errors = {};
112
-
113
- // Validate type selection if showTypeField is true
114
- if (showTypeField && !isTypeSelected()) {
115
- errors.type = formatMessage(_messages.messages.validationErrorTypeRequired);
99
+ var validateDescription = function validateDescription(value) {
100
+ if (!showDefaultTextFields || hasDescriptionDefaultValue) {
101
+ return undefined;
116
102
  }
103
+ return !value || !value.trim() ? formatMessage(_messages.messages.validationErrorDescriptionRequired) : undefined;
104
+ };
117
105
 
118
- // Validate description if showDefaultTextFields is true
119
- if (showDefaultTextFields && !hasDescription) {
120
- errors.description = formatMessage(_messages.messages.validationErrorDescriptionRequired);
106
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
107
+ var handleCancel = function handleCancel() {
108
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
109
+ args[_key] = arguments[_key];
121
110
  }
122
- return errors;
111
+ onCancel === null || onCancel === void 0 || onCancel.apply(void 0, args);
112
+ // Forward every arg the click handler received so consumers retain the full
113
+ // pre-change runtime contract (originating event + Atlaskit UI analytics event).
114
+ onClose.apply(void 0, args);
123
115
  };
116
+ var canShowTextField = isTypeSelected() || !showTypeField;
117
+ var isDisabled = isSubmitting || disableSubmitButton;
124
118
  var getFieldLabels = function getFieldLabels(record) {
125
119
  var _record$bug, _record$comment, _record$suggestion, _record$question, _record$empty, _record$not_relevant, _record$not_accurate, _record$too_slow, _record$unhelpful_lin, _record$other;
126
120
  return {
@@ -193,60 +187,53 @@ var FeedbackForm = function FeedbackForm(_ref2) {
193
187
  shouldScrollInViewport: true
194
188
  }, (0, _platformFeatureFlags.fg)('platform-design_system_team-form_conversion') ? /*#__PURE__*/_react.default.createElement(_form.default, {
195
189
  onSubmit: /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
196
- var errors;
197
190
  return _regenerator.default.wrap(function (_context) {
198
191
  while (1) switch (_context.prev = _context.next) {
199
192
  case 0:
200
- errors = getValidationErrors();
201
- if (!(Object.keys(errors).length > 0)) {
202
- _context.next = 1;
203
- break;
204
- }
205
- setValidationErrors(errors);
206
- return _context.abrupt("return");
207
- case 1:
208
193
  setIsSubmitting(true);
209
- _context.prev = 2;
210
- _context.next = 3;
194
+ _context.prev = 1;
195
+ _context.next = 2;
211
196
  return onSubmit({
212
197
  canBeContacted: canBeContacted,
213
198
  description: description,
214
199
  enrollInResearchGroup: enrollInResearchGroup,
215
200
  type: type
216
201
  });
217
- case 3:
218
- _context.prev = 3;
202
+ case 2:
203
+ _context.prev = 2;
219
204
  setIsSubmitting(false);
220
- return _context.finish(3);
221
- case 4:
205
+ return _context.finish(2);
206
+ case 3:
222
207
  case "end":
223
208
  return _context.stop();
224
209
  }
225
- }, _callee, null, [[2,, 3, 4]]);
210
+ }, _callee, null, [[1,, 2, 3]]);
226
211
  }))
227
212
  }, /*#__PURE__*/_react.default.createElement(_modalDialog.ModalHeader, {
228
213
  hasCloseButton: true
229
214
  }, /*#__PURE__*/_react.default.createElement(_modalDialog.ModalTitle, null, feedbackTitle || /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, _messages.messages.feedbackTitle))), /*#__PURE__*/_react.default.createElement(_modalDialog.ModalBody, null, (0, _platformFeatureFlags.fg)('ak_feedback_collector_hide_required_summary') ? showRequiredFieldsSummary && requiredFieldsSummary : requiredFieldsSummary, feedbackTitleDetails, customContent, showTypeField ? /*#__PURE__*/_react.default.createElement(_form.Field, {
230
215
  name: "topic",
216
+ id: "topic",
231
217
  label: selectLabel || formatMessage(_messages.messages.selectionOptionDefaultLabel),
232
- isRequired: true
218
+ isRequired: true,
219
+ validate: validateType
233
220
  }, function (_ref4) {
221
+ var _selectOptions$find;
234
222
  var _ref4$fieldProps = _ref4.fieldProps,
235
223
  id = _ref4$fieldProps.id,
236
- restProps = (0, _objectWithoutProperties2.default)(_ref4$fieldProps, _excluded);
224
+ restProps = (0, _objectWithoutProperties2.default)(_ref4$fieldProps, _excluded),
225
+ error = _ref4.error;
237
226
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_select.default, (0, _extends2.default)({}, restProps, {
227
+ value: (_selectOptions$find = selectOptions.find(function (opt) {
228
+ return opt.value === type;
229
+ })) !== null && _selectOptions$find !== void 0 ? _selectOptions$find : null,
238
230
  onChange: function onChange(option) {
231
+ var _restProps$onChange;
239
232
  if (!option || option instanceof Array) {
240
233
  return;
241
234
  }
242
235
  setType(option.value);
243
- if (validationErrors.type) {
244
- setValidationErrors(function (prev) {
245
- return _objectSpread(_objectSpread({}, prev), {}, {
246
- type: undefined
247
- });
248
- });
249
- }
236
+ (_restProps$onChange = restProps.onChange) === null || _restProps$onChange === void 0 || _restProps$onChange.call(restProps, option.value);
250
237
  },
251
238
  menuPosition: "fixed",
252
239
  options: selectOptions
@@ -254,30 +241,28 @@ var FeedbackForm = function FeedbackForm(_ref2) {
254
241
  ,
255
242
  ref: focusRef,
256
243
  placeholder: getDefaultPlaceholder(feedbackGroupLabels),
257
- inputId: id
258
- })), validationErrors.type && /*#__PURE__*/_react.default.createElement(_form.ErrorMessage, null, validationErrors.type));
244
+ inputId: id,
245
+ isInvalid: !!error
246
+ })), error && /*#__PURE__*/_react.default.createElement(_form.ErrorMessage, null, error));
259
247
  }) : null, showDefaultTextFields && canShowTextField && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_form.Field, {
260
248
  label: showTypeField ? getFieldLabels(feedbackGroupLabels)[type] : customTextAreaLabel || formatMessage(_messages.messages.defaultCustomTextAreaLabel),
261
249
  isRequired: true,
262
- name: "description"
250
+ name: "description",
251
+ id: "description",
252
+ validate: validateDescription
263
253
  }, function (_ref5) {
264
- var fieldProps = _ref5.fieldProps;
254
+ var fieldProps = _ref5.fieldProps,
255
+ error = _ref5.error;
265
256
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_textarea.default, (0, _extends2.default)({}, fieldProps, {
266
257
  name: "foo",
267
258
  minimumRows: 6,
268
259
  placeholder: summaryPlaceholder || undefined,
269
260
  onChange: function onChange(e) {
270
261
  setDescription(e.target.value);
271
- if (validationErrors.description) {
272
- setValidationErrors(function (prev) {
273
- return _objectSpread(_objectSpread({}, prev), {}, {
274
- description: undefined
275
- });
276
- });
277
- }
262
+ fieldProps.onChange(e.target.value);
278
263
  },
279
264
  value: description
280
- })), validationErrors.description && /*#__PURE__*/_react.default.createElement(_form.ErrorMessage, null, validationErrors.description));
265
+ })), error && /*#__PURE__*/_react.default.createElement(_form.ErrorMessage, null, error));
281
266
  }), !anonymousFeedback && /*#__PURE__*/_react.default.createElement(_form.Fieldset, null, /*#__PURE__*/_react.default.createElement("legend", null, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, _messages.messages.optInOptionsLegend)), /*#__PURE__*/_react.default.createElement(_form.Field, {
282
267
  name: "can-be-contacted"
283
268
  }, function (_ref6) {
@@ -331,36 +316,27 @@ var FeedbackForm = function FeedbackForm(_ref2) {
331
316
  testId: "feedbackCollectorSubmitBtn"
332
317
  }, submitButtonLabel || /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, _messages.messages.submitButtonLabel)))) : /*#__PURE__*/_react.default.createElement(_form.default, {
333
318
  onSubmit: /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
334
- var errors;
335
319
  return _regenerator.default.wrap(function (_context2) {
336
320
  while (1) switch (_context2.prev = _context2.next) {
337
321
  case 0:
338
- errors = getValidationErrors();
339
- if (!(Object.keys(errors).length > 0)) {
340
- _context2.next = 1;
341
- break;
342
- }
343
- setValidationErrors(errors);
344
- return _context2.abrupt("return");
345
- case 1:
346
322
  setIsSubmitting(true);
347
- _context2.prev = 2;
348
- _context2.next = 3;
323
+ _context2.prev = 1;
324
+ _context2.next = 2;
349
325
  return onSubmit({
350
326
  canBeContacted: canBeContacted,
351
327
  description: description,
352
328
  enrollInResearchGroup: enrollInResearchGroup,
353
329
  type: type
354
330
  });
355
- case 3:
356
- _context2.prev = 3;
331
+ case 2:
332
+ _context2.prev = 2;
357
333
  setIsSubmitting(false);
358
- return _context2.finish(3);
359
- case 4:
334
+ return _context2.finish(2);
335
+ case 3:
360
336
  case "end":
361
337
  return _context2.stop();
362
338
  }
363
- }, _callee2, null, [[2,, 3, 4]]);
339
+ }, _callee2, null, [[1,, 2, 3]]);
364
340
  }))
365
341
  }, function (_ref9) {
366
342
  var formProps = _ref9.formProps;
@@ -368,25 +344,27 @@ var FeedbackForm = function FeedbackForm(_ref2) {
368
344
  hasCloseButton: true
369
345
  }, /*#__PURE__*/_react.default.createElement(_modalDialog.ModalTitle, null, feedbackTitle || /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, _messages.messages.feedbackTitle))), /*#__PURE__*/_react.default.createElement(_modalDialog.ModalBody, null, (0, _platformFeatureFlags.fg)('ak_feedback_collector_hide_required_summary') ? showRequiredFieldsSummary && requiredFieldsSummary : requiredFieldsSummary, feedbackTitleDetails, customContent, showTypeField ? /*#__PURE__*/_react.default.createElement(_form.Field, {
370
346
  name: "topic",
347
+ id: "topic",
371
348
  label: selectLabel || formatMessage(_messages.messages.selectionOptionDefaultLabel),
372
- isRequired: true
349
+ isRequired: true,
350
+ validate: validateType
373
351
  }, function (_ref0) {
352
+ var _selectOptions$find2;
374
353
  var _ref0$fieldProps = _ref0.fieldProps,
375
354
  id = _ref0$fieldProps.id,
376
- restProps = (0, _objectWithoutProperties2.default)(_ref0$fieldProps, _excluded2);
355
+ restProps = (0, _objectWithoutProperties2.default)(_ref0$fieldProps, _excluded2),
356
+ error = _ref0.error;
377
357
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_select.default, (0, _extends2.default)({}, restProps, {
358
+ value: (_selectOptions$find2 = selectOptions.find(function (opt) {
359
+ return opt.value === type;
360
+ })) !== null && _selectOptions$find2 !== void 0 ? _selectOptions$find2 : null,
378
361
  onChange: function onChange(option) {
362
+ var _restProps$onChange2;
379
363
  if (!option || option instanceof Array) {
380
364
  return;
381
365
  }
382
366
  setType(option.value);
383
- if (validationErrors.type) {
384
- setValidationErrors(function (prev) {
385
- return _objectSpread(_objectSpread({}, prev), {}, {
386
- type: undefined
387
- });
388
- });
389
- }
367
+ (_restProps$onChange2 = restProps.onChange) === null || _restProps$onChange2 === void 0 || _restProps$onChange2.call(restProps, option.value);
390
368
  },
391
369
  menuPosition: "fixed",
392
370
  options: selectOptions
@@ -394,30 +372,28 @@ var FeedbackForm = function FeedbackForm(_ref2) {
394
372
  ,
395
373
  ref: focusRef,
396
374
  placeholder: getDefaultPlaceholder(feedbackGroupLabels),
397
- inputId: id
398
- })), validationErrors.type && /*#__PURE__*/_react.default.createElement(_form.ErrorMessage, null, validationErrors.type));
375
+ inputId: id,
376
+ isInvalid: !!error
377
+ })), error && /*#__PURE__*/_react.default.createElement(_form.ErrorMessage, null, error));
399
378
  }) : null, showDefaultTextFields && canShowTextField && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_form.Field, {
400
379
  label: showTypeField ? getFieldLabels(feedbackGroupLabels)[type] : customTextAreaLabel || formatMessage(_messages.messages.defaultCustomTextAreaLabel),
401
380
  isRequired: true,
402
- name: "description"
381
+ name: "description",
382
+ id: "description",
383
+ validate: validateDescription
403
384
  }, function (_ref1) {
404
- var fieldProps = _ref1.fieldProps;
385
+ var fieldProps = _ref1.fieldProps,
386
+ error = _ref1.error;
405
387
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_textarea.default, (0, _extends2.default)({}, fieldProps, {
406
388
  name: "foo",
407
389
  minimumRows: 6,
408
390
  placeholder: summaryPlaceholder || undefined,
409
391
  onChange: function onChange(e) {
410
392
  setDescription(e.target.value);
411
- if (validationErrors.description) {
412
- setValidationErrors(function (prev) {
413
- return _objectSpread(_objectSpread({}, prev), {}, {
414
- description: undefined
415
- });
416
- });
417
- }
393
+ fieldProps.onChange(e.target.value);
418
394
  },
419
395
  value: description
420
- })), validationErrors.description && /*#__PURE__*/_react.default.createElement(_form.ErrorMessage, null, validationErrors.description));
396
+ })), error && /*#__PURE__*/_react.default.createElement(_form.ErrorMessage, null, error));
421
397
  }), !anonymousFeedback && /*#__PURE__*/_react.default.createElement(_form.Fieldset, null, /*#__PURE__*/_react.default.createElement("legend", null, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, _messages.messages.optInOptionsLegend)), /*#__PURE__*/_react.default.createElement(_form.Field, {
422
398
  name: "can-be-contacted"
423
399
  }, function (_ref10) {
@@ -92,7 +92,7 @@ export default class FeedbackCollector extends Component {
92
92
  return FeedbackCollector.defaultProps.url;
93
93
  }
94
94
  getPackageVersion() {
95
- return "15.3.0" || 'Unknown, at least 11.0.0';
95
+ return "15.5.0" || 'Unknown, at least 11.0.0';
96
96
  }
97
97
  async getEntitlementInformation() {
98
98
  var _entitlementDetails, _entitlementDetails2, _productName, _entitlement, _productEntitlement;
@@ -55,32 +55,27 @@ const FeedbackForm = ({
55
55
  const [enrollInResearchGroup, setEnrollInResearchGroup] = useState(false);
56
56
  const [type, setType] = useState('empty');
57
57
  const [isSubmitting, setIsSubmitting] = useState(false);
58
- const [validationErrors, setValidationErrors] = useState({});
59
58
  const {
60
59
  formatMessage
61
60
  } = useIntl();
62
61
  const isTypeSelected = () => type !== 'empty';
63
- const handleCancel = () => {
64
- onCancel === null || onCancel === void 0 ? void 0 : onCancel();
65
- onClose();
66
- };
67
- const canShowTextField = isTypeSelected() || !showTypeField;
68
- const hasDescription = description || hasDescriptionDefaultValue;
69
- const isDisabled = isSubmitting || disableSubmitButton;
70
- const getValidationErrors = () => {
71
- const errors = {};
72
-
73
- // Validate type selection if showTypeField is true
74
- if (showTypeField && !isTypeSelected()) {
75
- errors.type = formatMessage(messages.validationErrorTypeRequired);
62
+ const validateType = value => showTypeField && (!value || value === 'empty') ? formatMessage(messages.validationErrorTypeRequired) : undefined;
63
+ const validateDescription = value => {
64
+ if (!showDefaultTextFields || hasDescriptionDefaultValue) {
65
+ return undefined;
76
66
  }
67
+ return !value || !value.trim() ? formatMessage(messages.validationErrorDescriptionRequired) : undefined;
68
+ };
77
69
 
78
- // Validate description if showDefaultTextFields is true
79
- if (showDefaultTextFields && !hasDescription) {
80
- errors.description = formatMessage(messages.validationErrorDescriptionRequired);
81
- }
82
- return errors;
70
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
71
+ const handleCancel = (...args) => {
72
+ onCancel === null || onCancel === void 0 ? void 0 : onCancel(...args);
73
+ // Forward every arg the click handler received so consumers retain the full
74
+ // pre-change runtime contract (originating event + Atlaskit UI analytics event).
75
+ onClose(...args);
83
76
  };
77
+ const canShowTextField = isTypeSelected() || !showTypeField;
78
+ const isDisabled = isSubmitting || disableSubmitButton;
84
79
  const getFieldLabels = record => {
85
80
  var _record$bug, _record$comment, _record$suggestion, _record$question, _record$empty, _record$not_relevant, _record$not_accurate, _record$too_slow, _record$unhelpful_lin, _record$other;
86
81
  return {
@@ -153,11 +148,6 @@ const FeedbackForm = ({
153
148
  shouldScrollInViewport: true
154
149
  }, fg('platform-design_system_team-form_conversion') ? /*#__PURE__*/React.createElement(Form, {
155
150
  onSubmit: async () => {
156
- const errors = getValidationErrors();
157
- if (Object.keys(errors).length > 0) {
158
- setValidationErrors(errors);
159
- return;
160
- }
161
151
  setIsSubmitting(true);
162
152
  try {
163
153
  await onSubmit({
@@ -174,54 +164,56 @@ const FeedbackForm = ({
174
164
  hasCloseButton: true
175
165
  }, /*#__PURE__*/React.createElement(ModalTitle, null, feedbackTitle || /*#__PURE__*/React.createElement(FormattedMessage, messages.feedbackTitle))), /*#__PURE__*/React.createElement(ModalBody, null, fg('ak_feedback_collector_hide_required_summary') ? showRequiredFieldsSummary && requiredFieldsSummary : requiredFieldsSummary, feedbackTitleDetails, customContent, showTypeField ? /*#__PURE__*/React.createElement(Field, {
176
166
  name: "topic",
167
+ id: "topic",
177
168
  label: selectLabel || formatMessage(messages.selectionOptionDefaultLabel),
178
- isRequired: true
169
+ isRequired: true,
170
+ validate: validateType
179
171
  }, ({
180
172
  fieldProps: {
181
173
  id,
182
174
  ...restProps
183
- }
184
- }) => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Select, _extends({}, restProps, {
185
- onChange: option => {
186
- if (!option || option instanceof Array) {
187
- return;
188
- }
189
- setType(option.value);
190
- if (validationErrors.type) {
191
- setValidationErrors(prev => ({
192
- ...prev,
193
- type: undefined
194
- }));
195
- }
196
175
  },
197
- menuPosition: "fixed",
198
- options: selectOptions
199
- // @ts-ignore
200
- ,
201
- ref: focusRef,
202
- placeholder: getDefaultPlaceholder(feedbackGroupLabels),
203
- inputId: id
204
- })), validationErrors.type && /*#__PURE__*/React.createElement(ErrorMessage, null, validationErrors.type))) : null, showDefaultTextFields && canShowTextField && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Field, {
176
+ error
177
+ }) => {
178
+ var _selectOptions$find;
179
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Select, _extends({}, restProps, {
180
+ value: (_selectOptions$find = selectOptions.find(opt => opt.value === type)) !== null && _selectOptions$find !== void 0 ? _selectOptions$find : null,
181
+ onChange: option => {
182
+ var _restProps$onChange;
183
+ if (!option || option instanceof Array) {
184
+ return;
185
+ }
186
+ setType(option.value);
187
+ (_restProps$onChange = restProps.onChange) === null || _restProps$onChange === void 0 ? void 0 : _restProps$onChange.call(restProps, option.value);
188
+ },
189
+ menuPosition: "fixed",
190
+ options: selectOptions
191
+ // @ts-ignore
192
+ ,
193
+ ref: focusRef,
194
+ placeholder: getDefaultPlaceholder(feedbackGroupLabels),
195
+ inputId: id,
196
+ isInvalid: !!error
197
+ })), error && /*#__PURE__*/React.createElement(ErrorMessage, null, error));
198
+ }) : null, showDefaultTextFields && canShowTextField && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Field, {
205
199
  label: showTypeField ? getFieldLabels(feedbackGroupLabels)[type] : customTextAreaLabel || formatMessage(messages.defaultCustomTextAreaLabel),
206
200
  isRequired: true,
207
- name: "description"
201
+ name: "description",
202
+ id: "description",
203
+ validate: validateDescription
208
204
  }, ({
209
- fieldProps
205
+ fieldProps,
206
+ error
210
207
  }) => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TextArea, _extends({}, fieldProps, {
211
208
  name: "foo",
212
209
  minimumRows: 6,
213
210
  placeholder: summaryPlaceholder || undefined,
214
211
  onChange: e => {
215
212
  setDescription(e.target.value);
216
- if (validationErrors.description) {
217
- setValidationErrors(prev => ({
218
- ...prev,
219
- description: undefined
220
- }));
221
- }
213
+ fieldProps.onChange(e.target.value);
222
214
  },
223
215
  value: description
224
- })), validationErrors.description && /*#__PURE__*/React.createElement(ErrorMessage, null, validationErrors.description))), !anonymousFeedback && /*#__PURE__*/React.createElement(Fieldset, null, /*#__PURE__*/React.createElement("legend", null, /*#__PURE__*/React.createElement(FormattedMessage, messages.optInOptionsLegend)), /*#__PURE__*/React.createElement(Field, {
216
+ })), error && /*#__PURE__*/React.createElement(ErrorMessage, null, error))), !anonymousFeedback && /*#__PURE__*/React.createElement(Fieldset, null, /*#__PURE__*/React.createElement("legend", null, /*#__PURE__*/React.createElement(FormattedMessage, messages.optInOptionsLegend)), /*#__PURE__*/React.createElement(Field, {
225
217
  name: "can-be-contacted"
226
218
  }, ({
227
219
  fieldProps
@@ -264,11 +256,6 @@ const FeedbackForm = ({
264
256
  testId: "feedbackCollectorSubmitBtn"
265
257
  }, submitButtonLabel || /*#__PURE__*/React.createElement(FormattedMessage, messages.submitButtonLabel)))) : /*#__PURE__*/React.createElement(Form, {
266
258
  onSubmit: async () => {
267
- const errors = getValidationErrors();
268
- if (Object.keys(errors).length > 0) {
269
- setValidationErrors(errors);
270
- return;
271
- }
272
259
  setIsSubmitting(true);
273
260
  try {
274
261
  await onSubmit({
@@ -287,54 +274,56 @@ const FeedbackForm = ({
287
274
  hasCloseButton: true
288
275
  }, /*#__PURE__*/React.createElement(ModalTitle, null, feedbackTitle || /*#__PURE__*/React.createElement(FormattedMessage, messages.feedbackTitle))), /*#__PURE__*/React.createElement(ModalBody, null, fg('ak_feedback_collector_hide_required_summary') ? showRequiredFieldsSummary && requiredFieldsSummary : requiredFieldsSummary, feedbackTitleDetails, customContent, showTypeField ? /*#__PURE__*/React.createElement(Field, {
289
276
  name: "topic",
277
+ id: "topic",
290
278
  label: selectLabel || formatMessage(messages.selectionOptionDefaultLabel),
291
- isRequired: true
279
+ isRequired: true,
280
+ validate: validateType
292
281
  }, ({
293
282
  fieldProps: {
294
283
  id,
295
284
  ...restProps
296
- }
297
- }) => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Select, _extends({}, restProps, {
298
- onChange: option => {
299
- if (!option || option instanceof Array) {
300
- return;
301
- }
302
- setType(option.value);
303
- if (validationErrors.type) {
304
- setValidationErrors(prev => ({
305
- ...prev,
306
- type: undefined
307
- }));
308
- }
309
285
  },
310
- menuPosition: "fixed",
311
- options: selectOptions
312
- // @ts-ignore
313
- ,
314
- ref: focusRef,
315
- placeholder: getDefaultPlaceholder(feedbackGroupLabels),
316
- inputId: id
317
- })), validationErrors.type && /*#__PURE__*/React.createElement(ErrorMessage, null, validationErrors.type))) : null, showDefaultTextFields && canShowTextField && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Field, {
286
+ error
287
+ }) => {
288
+ var _selectOptions$find2;
289
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Select, _extends({}, restProps, {
290
+ value: (_selectOptions$find2 = selectOptions.find(opt => opt.value === type)) !== null && _selectOptions$find2 !== void 0 ? _selectOptions$find2 : null,
291
+ onChange: option => {
292
+ var _restProps$onChange2;
293
+ if (!option || option instanceof Array) {
294
+ return;
295
+ }
296
+ setType(option.value);
297
+ (_restProps$onChange2 = restProps.onChange) === null || _restProps$onChange2 === void 0 ? void 0 : _restProps$onChange2.call(restProps, option.value);
298
+ },
299
+ menuPosition: "fixed",
300
+ options: selectOptions
301
+ // @ts-ignore
302
+ ,
303
+ ref: focusRef,
304
+ placeholder: getDefaultPlaceholder(feedbackGroupLabels),
305
+ inputId: id,
306
+ isInvalid: !!error
307
+ })), error && /*#__PURE__*/React.createElement(ErrorMessage, null, error));
308
+ }) : null, showDefaultTextFields && canShowTextField && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Field, {
318
309
  label: showTypeField ? getFieldLabels(feedbackGroupLabels)[type] : customTextAreaLabel || formatMessage(messages.defaultCustomTextAreaLabel),
319
310
  isRequired: true,
320
- name: "description"
311
+ name: "description",
312
+ id: "description",
313
+ validate: validateDescription
321
314
  }, ({
322
- fieldProps
315
+ fieldProps,
316
+ error
323
317
  }) => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TextArea, _extends({}, fieldProps, {
324
318
  name: "foo",
325
319
  minimumRows: 6,
326
320
  placeholder: summaryPlaceholder || undefined,
327
321
  onChange: e => {
328
322
  setDescription(e.target.value);
329
- if (validationErrors.description) {
330
- setValidationErrors(prev => ({
331
- ...prev,
332
- description: undefined
333
- }));
334
- }
323
+ fieldProps.onChange(e.target.value);
335
324
  },
336
325
  value: description
337
- })), validationErrors.description && /*#__PURE__*/React.createElement(ErrorMessage, null, validationErrors.description))), !anonymousFeedback && /*#__PURE__*/React.createElement(Fieldset, null, /*#__PURE__*/React.createElement("legend", null, /*#__PURE__*/React.createElement(FormattedMessage, messages.optInOptionsLegend)), /*#__PURE__*/React.createElement(Field, {
326
+ })), error && /*#__PURE__*/React.createElement(ErrorMessage, null, error))), !anonymousFeedback && /*#__PURE__*/React.createElement(Fieldset, null, /*#__PURE__*/React.createElement("legend", null, /*#__PURE__*/React.createElement(FormattedMessage, messages.optInOptionsLegend)), /*#__PURE__*/React.createElement(Field, {
338
327
  name: "can-be-contacted"
339
328
  }, ({
340
329
  fieldProps
@@ -155,7 +155,7 @@ var FeedbackCollector = /*#__PURE__*/function (_Component) {
155
155
  }, {
156
156
  key: "getPackageVersion",
157
157
  value: function getPackageVersion() {
158
- return "15.3.0" || 'Unknown, at least 11.0.0';
158
+ return "15.5.0" || 'Unknown, at least 11.0.0';
159
159
  }
160
160
  }, {
161
161
  key: "getEntitlementInformation",
@@ -1,13 +1,10 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
- import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
2
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
4
3
  import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
5
4
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
6
5
  var _excluded = ["id"],
7
6
  _excluded2 = ["id"],
8
7
  _excluded3 = ["locale"];
9
- 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; }
10
- 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; }
11
8
  import _regeneratorRuntime from "@babel/runtime/regenerator";
12
9
  import React, { useRef, useState } from 'react';
13
10
  import { FormattedMessage, useIntl } from 'react-intl';
@@ -82,36 +79,33 @@ var FeedbackForm = function FeedbackForm(_ref2) {
82
79
  _useState0 = _slicedToArray(_useState9, 2),
83
80
  isSubmitting = _useState0[0],
84
81
  setIsSubmitting = _useState0[1];
85
- var _useState1 = useState({}),
86
- _useState10 = _slicedToArray(_useState1, 2),
87
- validationErrors = _useState10[0],
88
- setValidationErrors = _useState10[1];
89
82
  var _useIntl = useIntl(),
90
83
  formatMessage = _useIntl.formatMessage;
91
84
  var isTypeSelected = function isTypeSelected() {
92
85
  return type !== 'empty';
93
86
  };
94
- var handleCancel = function handleCancel() {
95
- onCancel === null || onCancel === void 0 || onCancel();
96
- onClose();
87
+ var validateType = function validateType(value) {
88
+ return showTypeField && (!value || value === 'empty') ? formatMessage(messages.validationErrorTypeRequired) : undefined;
97
89
  };
98
- var canShowTextField = isTypeSelected() || !showTypeField;
99
- var hasDescription = description || hasDescriptionDefaultValue;
100
- var isDisabled = isSubmitting || disableSubmitButton;
101
- var getValidationErrors = function getValidationErrors() {
102
- var errors = {};
103
-
104
- // Validate type selection if showTypeField is true
105
- if (showTypeField && !isTypeSelected()) {
106
- errors.type = formatMessage(messages.validationErrorTypeRequired);
90
+ var validateDescription = function validateDescription(value) {
91
+ if (!showDefaultTextFields || hasDescriptionDefaultValue) {
92
+ return undefined;
107
93
  }
94
+ return !value || !value.trim() ? formatMessage(messages.validationErrorDescriptionRequired) : undefined;
95
+ };
108
96
 
109
- // Validate description if showDefaultTextFields is true
110
- if (showDefaultTextFields && !hasDescription) {
111
- errors.description = formatMessage(messages.validationErrorDescriptionRequired);
97
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
98
+ var handleCancel = function handleCancel() {
99
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
100
+ args[_key] = arguments[_key];
112
101
  }
113
- return errors;
102
+ onCancel === null || onCancel === void 0 || onCancel.apply(void 0, args);
103
+ // Forward every arg the click handler received so consumers retain the full
104
+ // pre-change runtime contract (originating event + Atlaskit UI analytics event).
105
+ onClose.apply(void 0, args);
114
106
  };
107
+ var canShowTextField = isTypeSelected() || !showTypeField;
108
+ var isDisabled = isSubmitting || disableSubmitButton;
115
109
  var getFieldLabels = function getFieldLabels(record) {
116
110
  var _record$bug, _record$comment, _record$suggestion, _record$question, _record$empty, _record$not_relevant, _record$not_accurate, _record$too_slow, _record$unhelpful_lin, _record$other;
117
111
  return {
@@ -184,60 +178,53 @@ var FeedbackForm = function FeedbackForm(_ref2) {
184
178
  shouldScrollInViewport: true
185
179
  }, fg('platform-design_system_team-form_conversion') ? /*#__PURE__*/React.createElement(Form, {
186
180
  onSubmit: /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
187
- var errors;
188
181
  return _regeneratorRuntime.wrap(function (_context) {
189
182
  while (1) switch (_context.prev = _context.next) {
190
183
  case 0:
191
- errors = getValidationErrors();
192
- if (!(Object.keys(errors).length > 0)) {
193
- _context.next = 1;
194
- break;
195
- }
196
- setValidationErrors(errors);
197
- return _context.abrupt("return");
198
- case 1:
199
184
  setIsSubmitting(true);
200
- _context.prev = 2;
201
- _context.next = 3;
185
+ _context.prev = 1;
186
+ _context.next = 2;
202
187
  return onSubmit({
203
188
  canBeContacted: canBeContacted,
204
189
  description: description,
205
190
  enrollInResearchGroup: enrollInResearchGroup,
206
191
  type: type
207
192
  });
208
- case 3:
209
- _context.prev = 3;
193
+ case 2:
194
+ _context.prev = 2;
210
195
  setIsSubmitting(false);
211
- return _context.finish(3);
212
- case 4:
196
+ return _context.finish(2);
197
+ case 3:
213
198
  case "end":
214
199
  return _context.stop();
215
200
  }
216
- }, _callee, null, [[2,, 3, 4]]);
201
+ }, _callee, null, [[1,, 2, 3]]);
217
202
  }))
218
203
  }, /*#__PURE__*/React.createElement(ModalHeader, {
219
204
  hasCloseButton: true
220
205
  }, /*#__PURE__*/React.createElement(ModalTitle, null, feedbackTitle || /*#__PURE__*/React.createElement(FormattedMessage, messages.feedbackTitle))), /*#__PURE__*/React.createElement(ModalBody, null, fg('ak_feedback_collector_hide_required_summary') ? showRequiredFieldsSummary && requiredFieldsSummary : requiredFieldsSummary, feedbackTitleDetails, customContent, showTypeField ? /*#__PURE__*/React.createElement(Field, {
221
206
  name: "topic",
207
+ id: "topic",
222
208
  label: selectLabel || formatMessage(messages.selectionOptionDefaultLabel),
223
- isRequired: true
209
+ isRequired: true,
210
+ validate: validateType
224
211
  }, function (_ref4) {
212
+ var _selectOptions$find;
225
213
  var _ref4$fieldProps = _ref4.fieldProps,
226
214
  id = _ref4$fieldProps.id,
227
- restProps = _objectWithoutProperties(_ref4$fieldProps, _excluded);
215
+ restProps = _objectWithoutProperties(_ref4$fieldProps, _excluded),
216
+ error = _ref4.error;
228
217
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Select, _extends({}, restProps, {
218
+ value: (_selectOptions$find = selectOptions.find(function (opt) {
219
+ return opt.value === type;
220
+ })) !== null && _selectOptions$find !== void 0 ? _selectOptions$find : null,
229
221
  onChange: function onChange(option) {
222
+ var _restProps$onChange;
230
223
  if (!option || option instanceof Array) {
231
224
  return;
232
225
  }
233
226
  setType(option.value);
234
- if (validationErrors.type) {
235
- setValidationErrors(function (prev) {
236
- return _objectSpread(_objectSpread({}, prev), {}, {
237
- type: undefined
238
- });
239
- });
240
- }
227
+ (_restProps$onChange = restProps.onChange) === null || _restProps$onChange === void 0 || _restProps$onChange.call(restProps, option.value);
241
228
  },
242
229
  menuPosition: "fixed",
243
230
  options: selectOptions
@@ -245,30 +232,28 @@ var FeedbackForm = function FeedbackForm(_ref2) {
245
232
  ,
246
233
  ref: focusRef,
247
234
  placeholder: getDefaultPlaceholder(feedbackGroupLabels),
248
- inputId: id
249
- })), validationErrors.type && /*#__PURE__*/React.createElement(ErrorMessage, null, validationErrors.type));
235
+ inputId: id,
236
+ isInvalid: !!error
237
+ })), error && /*#__PURE__*/React.createElement(ErrorMessage, null, error));
250
238
  }) : null, showDefaultTextFields && canShowTextField && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Field, {
251
239
  label: showTypeField ? getFieldLabels(feedbackGroupLabels)[type] : customTextAreaLabel || formatMessage(messages.defaultCustomTextAreaLabel),
252
240
  isRequired: true,
253
- name: "description"
241
+ name: "description",
242
+ id: "description",
243
+ validate: validateDescription
254
244
  }, function (_ref5) {
255
- var fieldProps = _ref5.fieldProps;
245
+ var fieldProps = _ref5.fieldProps,
246
+ error = _ref5.error;
256
247
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TextArea, _extends({}, fieldProps, {
257
248
  name: "foo",
258
249
  minimumRows: 6,
259
250
  placeholder: summaryPlaceholder || undefined,
260
251
  onChange: function onChange(e) {
261
252
  setDescription(e.target.value);
262
- if (validationErrors.description) {
263
- setValidationErrors(function (prev) {
264
- return _objectSpread(_objectSpread({}, prev), {}, {
265
- description: undefined
266
- });
267
- });
268
- }
253
+ fieldProps.onChange(e.target.value);
269
254
  },
270
255
  value: description
271
- })), validationErrors.description && /*#__PURE__*/React.createElement(ErrorMessage, null, validationErrors.description));
256
+ })), error && /*#__PURE__*/React.createElement(ErrorMessage, null, error));
272
257
  }), !anonymousFeedback && /*#__PURE__*/React.createElement(Fieldset, null, /*#__PURE__*/React.createElement("legend", null, /*#__PURE__*/React.createElement(FormattedMessage, messages.optInOptionsLegend)), /*#__PURE__*/React.createElement(Field, {
273
258
  name: "can-be-contacted"
274
259
  }, function (_ref6) {
@@ -322,36 +307,27 @@ var FeedbackForm = function FeedbackForm(_ref2) {
322
307
  testId: "feedbackCollectorSubmitBtn"
323
308
  }, submitButtonLabel || /*#__PURE__*/React.createElement(FormattedMessage, messages.submitButtonLabel)))) : /*#__PURE__*/React.createElement(Form, {
324
309
  onSubmit: /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
325
- var errors;
326
310
  return _regeneratorRuntime.wrap(function (_context2) {
327
311
  while (1) switch (_context2.prev = _context2.next) {
328
312
  case 0:
329
- errors = getValidationErrors();
330
- if (!(Object.keys(errors).length > 0)) {
331
- _context2.next = 1;
332
- break;
333
- }
334
- setValidationErrors(errors);
335
- return _context2.abrupt("return");
336
- case 1:
337
313
  setIsSubmitting(true);
338
- _context2.prev = 2;
339
- _context2.next = 3;
314
+ _context2.prev = 1;
315
+ _context2.next = 2;
340
316
  return onSubmit({
341
317
  canBeContacted: canBeContacted,
342
318
  description: description,
343
319
  enrollInResearchGroup: enrollInResearchGroup,
344
320
  type: type
345
321
  });
346
- case 3:
347
- _context2.prev = 3;
322
+ case 2:
323
+ _context2.prev = 2;
348
324
  setIsSubmitting(false);
349
- return _context2.finish(3);
350
- case 4:
325
+ return _context2.finish(2);
326
+ case 3:
351
327
  case "end":
352
328
  return _context2.stop();
353
329
  }
354
- }, _callee2, null, [[2,, 3, 4]]);
330
+ }, _callee2, null, [[1,, 2, 3]]);
355
331
  }))
356
332
  }, function (_ref9) {
357
333
  var formProps = _ref9.formProps;
@@ -359,25 +335,27 @@ var FeedbackForm = function FeedbackForm(_ref2) {
359
335
  hasCloseButton: true
360
336
  }, /*#__PURE__*/React.createElement(ModalTitle, null, feedbackTitle || /*#__PURE__*/React.createElement(FormattedMessage, messages.feedbackTitle))), /*#__PURE__*/React.createElement(ModalBody, null, fg('ak_feedback_collector_hide_required_summary') ? showRequiredFieldsSummary && requiredFieldsSummary : requiredFieldsSummary, feedbackTitleDetails, customContent, showTypeField ? /*#__PURE__*/React.createElement(Field, {
361
337
  name: "topic",
338
+ id: "topic",
362
339
  label: selectLabel || formatMessage(messages.selectionOptionDefaultLabel),
363
- isRequired: true
340
+ isRequired: true,
341
+ validate: validateType
364
342
  }, function (_ref0) {
343
+ var _selectOptions$find2;
365
344
  var _ref0$fieldProps = _ref0.fieldProps,
366
345
  id = _ref0$fieldProps.id,
367
- restProps = _objectWithoutProperties(_ref0$fieldProps, _excluded2);
346
+ restProps = _objectWithoutProperties(_ref0$fieldProps, _excluded2),
347
+ error = _ref0.error;
368
348
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Select, _extends({}, restProps, {
349
+ value: (_selectOptions$find2 = selectOptions.find(function (opt) {
350
+ return opt.value === type;
351
+ })) !== null && _selectOptions$find2 !== void 0 ? _selectOptions$find2 : null,
369
352
  onChange: function onChange(option) {
353
+ var _restProps$onChange2;
370
354
  if (!option || option instanceof Array) {
371
355
  return;
372
356
  }
373
357
  setType(option.value);
374
- if (validationErrors.type) {
375
- setValidationErrors(function (prev) {
376
- return _objectSpread(_objectSpread({}, prev), {}, {
377
- type: undefined
378
- });
379
- });
380
- }
358
+ (_restProps$onChange2 = restProps.onChange) === null || _restProps$onChange2 === void 0 || _restProps$onChange2.call(restProps, option.value);
381
359
  },
382
360
  menuPosition: "fixed",
383
361
  options: selectOptions
@@ -385,30 +363,28 @@ var FeedbackForm = function FeedbackForm(_ref2) {
385
363
  ,
386
364
  ref: focusRef,
387
365
  placeholder: getDefaultPlaceholder(feedbackGroupLabels),
388
- inputId: id
389
- })), validationErrors.type && /*#__PURE__*/React.createElement(ErrorMessage, null, validationErrors.type));
366
+ inputId: id,
367
+ isInvalid: !!error
368
+ })), error && /*#__PURE__*/React.createElement(ErrorMessage, null, error));
390
369
  }) : null, showDefaultTextFields && canShowTextField && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Field, {
391
370
  label: showTypeField ? getFieldLabels(feedbackGroupLabels)[type] : customTextAreaLabel || formatMessage(messages.defaultCustomTextAreaLabel),
392
371
  isRequired: true,
393
- name: "description"
372
+ name: "description",
373
+ id: "description",
374
+ validate: validateDescription
394
375
  }, function (_ref1) {
395
- var fieldProps = _ref1.fieldProps;
376
+ var fieldProps = _ref1.fieldProps,
377
+ error = _ref1.error;
396
378
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TextArea, _extends({}, fieldProps, {
397
379
  name: "foo",
398
380
  minimumRows: 6,
399
381
  placeholder: summaryPlaceholder || undefined,
400
382
  onChange: function onChange(e) {
401
383
  setDescription(e.target.value);
402
- if (validationErrors.description) {
403
- setValidationErrors(function (prev) {
404
- return _objectSpread(_objectSpread({}, prev), {}, {
405
- description: undefined
406
- });
407
- });
408
- }
384
+ fieldProps.onChange(e.target.value);
409
385
  },
410
386
  value: description
411
- })), validationErrors.description && /*#__PURE__*/React.createElement(ErrorMessage, null, validationErrors.description));
387
+ })), error && /*#__PURE__*/React.createElement(ErrorMessage, null, error));
412
388
  }), !anonymousFeedback && /*#__PURE__*/React.createElement(Fieldset, null, /*#__PURE__*/React.createElement("legend", null, /*#__PURE__*/React.createElement(FormattedMessage, messages.optInOptionsLegend)), /*#__PURE__*/React.createElement(Field, {
413
389
  name: "can-be-contacted"
414
390
  }, function (_ref10) {
@@ -86,10 +86,16 @@ export interface Props {
86
86
  cancelButtonLabel?: string;
87
87
  /** Message for select option labels and field labels */
88
88
  feedbackGroupLabels?: Partial<Record<SelectValue, SelectOptionDetails>>;
89
- /** Function that will be called to initiate the exit transition. */
90
- onClose: () => void;
89
+ /**
90
+ * Function that will be called to initiate the exit transition.
91
+ * When triggered by the cancel button the originating event and Atlaskit UI analytics
92
+ * event are forwarded; programmatic close paths (e.g. after submit) invoke it with no
93
+ * arguments. Typed as a variadic `any[]` to maximise backward compatibility with
94
+ * consumers that declared any conceivable signature for this callback.
95
+ */
96
+ onClose: (...args: any[]) => void;
91
97
  /** Optional function that will be called when the cancel button is clicked, in addition to onClose. */
92
- onCancel?: () => void;
98
+ onCancel?: (...args: any[]) => void;
93
99
  /** Function that will be called optimistically after a delay when the feedback is submitted. */
94
100
  onSubmit: (formFields: FormFields) => void;
95
101
  /** Locale for i18n */
@@ -168,7 +174,7 @@ export default class FeedbackCollector extends Component<Props> {
168
174
  showTypeField: boolean;
169
175
  showDefaultTextFields: boolean;
170
176
  anonymousFeedback: boolean;
171
- onClose: () => void;
177
+ onClose: (...args: any[]) => void;
172
178
  onSubmit: () => void;
173
179
  };
174
180
  getGatewayUrl(): string;
@@ -27,10 +27,16 @@ interface Props {
27
27
  cancelButtonLabel?: string;
28
28
  /** Message for select option labels and field labels **/
29
29
  feedbackGroupLabels?: Partial<Record<SelectValue, SelectOptionDetails>>;
30
- /** Function that will be called to initiate the exit transition. */
31
- onClose: () => void;
30
+ /**
31
+ * Function that will be called to initiate the exit transition.
32
+ * When triggered by the cancel button the originating event and Atlaskit UI analytics
33
+ * event are forwarded; programmatic close paths (e.g. after submit) invoke it with no
34
+ * arguments. Typed as a variadic `any[]` to maximise backward compatibility with
35
+ * consumers that declared any conceivable signature for this callback.
36
+ */
37
+ onClose: (...args: any[]) => void;
32
38
  /** Optional function that will be called when the cancel button is clicked, in addition to onClose. */
33
- onCancel?: () => void;
39
+ onCancel?: (...args: any[]) => void;
34
40
  /** Function that will be called immediately after the submit action */
35
41
  onSubmit: (formValues: FormFields) => Promise<void>;
36
42
  /** Optional locale for i18n **/
@@ -86,10 +86,16 @@ export interface Props {
86
86
  cancelButtonLabel?: string;
87
87
  /** Message for select option labels and field labels */
88
88
  feedbackGroupLabels?: Partial<Record<SelectValue, SelectOptionDetails>>;
89
- /** Function that will be called to initiate the exit transition. */
90
- onClose: () => void;
89
+ /**
90
+ * Function that will be called to initiate the exit transition.
91
+ * When triggered by the cancel button the originating event and Atlaskit UI analytics
92
+ * event are forwarded; programmatic close paths (e.g. after submit) invoke it with no
93
+ * arguments. Typed as a variadic `any[]` to maximise backward compatibility with
94
+ * consumers that declared any conceivable signature for this callback.
95
+ */
96
+ onClose: (...args: any[]) => void;
91
97
  /** Optional function that will be called when the cancel button is clicked, in addition to onClose. */
92
- onCancel?: () => void;
98
+ onCancel?: (...args: any[]) => void;
93
99
  /** Function that will be called optimistically after a delay when the feedback is submitted. */
94
100
  onSubmit: (formFields: FormFields) => void;
95
101
  /** Locale for i18n */
@@ -168,7 +174,7 @@ export default class FeedbackCollector extends Component<Props> {
168
174
  showTypeField: boolean;
169
175
  showDefaultTextFields: boolean;
170
176
  anonymousFeedback: boolean;
171
- onClose: () => void;
177
+ onClose: (...args: any[]) => void;
172
178
  onSubmit: () => void;
173
179
  };
174
180
  getGatewayUrl(): string;
@@ -27,10 +27,16 @@ interface Props {
27
27
  cancelButtonLabel?: string;
28
28
  /** Message for select option labels and field labels **/
29
29
  feedbackGroupLabels?: Partial<Record<SelectValue, SelectOptionDetails>>;
30
- /** Function that will be called to initiate the exit transition. */
31
- onClose: () => void;
30
+ /**
31
+ * Function that will be called to initiate the exit transition.
32
+ * When triggered by the cancel button the originating event and Atlaskit UI analytics
33
+ * event are forwarded; programmatic close paths (e.g. after submit) invoke it with no
34
+ * arguments. Typed as a variadic `any[]` to maximise backward compatibility with
35
+ * consumers that declared any conceivable signature for this callback.
36
+ */
37
+ onClose: (...args: any[]) => void;
32
38
  /** Optional function that will be called when the cancel button is clicked, in addition to onClose. */
33
- onCancel?: () => void;
39
+ onCancel?: (...args: any[]) => void;
34
40
  /** Function that will be called immediately after the submit action */
35
41
  onSubmit: (formValues: FormFields) => Promise<void>;
36
42
  /** Optional locale for i18n **/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/feedback-collector",
3
- "version": "15.4.0",
3
+ "version": "15.6.0",
4
4
  "description": "A component that collects feedback across Atlassian products.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -23,7 +23,7 @@
23
23
  "sideEffects": false,
24
24
  "atlaskit:src": "src/index.ts",
25
25
  "atlassian": {
26
- "team": "Belugas: Feedback Collector",
26
+ "team": "Cloud Readiness: Otter",
27
27
  "website": {
28
28
  "name": "Feedback Collector"
29
29
  }
@@ -35,7 +35,7 @@
35
35
  "@atlaskit/afm-i18n-platform-web-platform-feedback-collector": "2.96.0",
36
36
  "@atlaskit/button": "^23.11.0",
37
37
  "@atlaskit/checkbox": "^17.3.0",
38
- "@atlaskit/flag": "^17.12.0",
38
+ "@atlaskit/flag": "^17.13.0",
39
39
  "@atlaskit/form": "^15.5.0",
40
40
  "@atlaskit/icon": "^35.4.0",
41
41
  "@atlaskit/link": "^3.4.0",
@@ -44,7 +44,8 @@
44
44
  "@atlaskit/section-message": "^8.13.0",
45
45
  "@atlaskit/select": "^21.12.0",
46
46
  "@atlaskit/textarea": "^8.3.0",
47
- "@atlaskit/tokens": "^13.2.0",
47
+ "@atlaskit/tokens": "^13.3.0",
48
+ "@atlaskit/visually-hidden": "^3.1.0",
48
49
  "@babel/runtime": "^7.0.0"
49
50
  },
50
51
  "peerDependencies": {