@atlaskit/smart-user-picker 8.6.0 → 8.8.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,29 @@
1
1
  # @atlassian/smart-user-picker
2
2
 
3
+ ## 8.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`386987f274ff5`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/386987f274ff5) -
8
+ Add support for `restrictTo` prop to filter recommendations by user IDs and group IDs. This allows
9
+ filtering down results based on specific groups or users in a site.
10
+
11
+ **New prop:** `restrictTo?: { userIds?: string[], groupIds?: string[] }`
12
+
13
+ This prop is passed directly to the URS recommendations endpoint's `searchQuery.restrictTo` field,
14
+ enabling you to constrain recommendations to a specific set of users and/or groups.
15
+
16
+ **Feature gate:** `smart-user-picker-restrict-to-gate` - The prop is only forwarded to the backend
17
+ when this feature gate is enabled.
18
+
19
+ ## 8.7.0
20
+
21
+ ### Minor Changes
22
+
23
+ - [`ae3f597598ae8`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/ae3f597598ae8) -
24
+ Added prop to toggle the ability to return only verified teams. Only applies when includeTeams is
25
+ true.
26
+
3
27
  ## 8.6.0
4
28
 
5
29
  ### Minor Changes
@@ -32,13 +32,13 @@ var _MessagesIntlProvider = _interopRequireDefault(require("./MessagesIntlProvid
32
32
  var _types = require("../types");
33
33
  var _service = require("../service");
34
34
  var _ufoExperiences = require("../ufoExperiences");
35
- var _excluded = ["allowEmail", "enableEmailSearch", "allowEmailSelectionWhenEmailMatched", "fetchOptions"];
35
+ var _excluded = ["allowEmail", "enableEmailSearch", "allowEmailSelectionWhenEmailMatched"];
36
36
  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); }
37
- 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; }
38
- 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; }
39
37
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
40
38
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
41
39
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
40
+ 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; }
41
+ 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; }
42
42
  function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); }
43
43
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
44
44
  var DEFAULT_DEBOUNCE_TIME_MS = 150;
@@ -118,16 +118,16 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
118
118
  });
119
119
  (0, _defineProperty2.default)(_this, "memoizedFilterOptions", (0, _memoizeOne.default)(_this.filterOptions));
120
120
  (0, _defineProperty2.default)(_this, "getUsers", (0, _debounce.default)( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
121
- var _this$state, query, sessionId, closed, _this$props, baseUrl, childObjectId, containerId, fieldId, includeGroups, includeTeams, includeTeamsUpdates, includeUsers, includeNonLicensedUsers, intl, fetchOptions, maxOptions, objectId, onEmpty, onError, overrideByline, displayEmailInByline, orgId, principalId, productAttributes, productKey, searchQueryFilter, siteId, transformOptions, userResolvers, enableEmailSearch, maxNumberOfResults, startTime, isEmail, recommendationsRequest, _yield$onEmpty, _query, recommendedUsers, userRecommendationsPromise, userResolversPromises, _yield$Promise$all, _yield$Promise$all2, mainRecommendations, userResolverResults, _iterator, _step, option, _iterator2, _step2, _option, _iterator3, _step3, _option2, elapsedTimeMilli, transformedOptions, displayedUsers, is5xxEvent, onErrorProducedError, defaultUsers, _elapsedTimeMilli;
121
+ var _this$state, query, sessionId, closed, _this$props, baseUrl, childObjectId, containerId, fieldId, includeGroups, includeTeams, includeTeamsUpdates, includeUsers, includeNonLicensedUsers, intl, fetchOptions, maxOptions, objectId, onEmpty, onError, overrideByline, displayEmailInByline, verifiedTeams, orgId, principalId, productAttributes, productKey, restrictTo, searchQueryFilter, siteId, transformOptions, userResolvers, enableEmailSearch, maxNumberOfResults, startTime, isEmail, recommendationsRequest, _yield$onEmpty, _query, recommendedUsers, userRecommendationsPromise, userResolversPromises, _yield$Promise$all, _yield$Promise$all2, mainRecommendations, userResolverResults, _iterator, _step, option, _iterator2, _step2, _option, _iterator3, _step3, _option2, elapsedTimeMilli, transformedOptions, displayedUsers, is5xxEvent, onErrorProducedError, defaultUsers, _elapsedTimeMilli;
122
122
  return _regenerator.default.wrap(function _callee$(_context) {
123
123
  while (1) switch (_context.prev = _context.next) {
124
124
  case 0:
125
125
  _this$state = _this.state, query = _this$state.query, sessionId = _this$state.sessionId, closed = _this$state.closed;
126
- _this$props = _this.props, baseUrl = _this$props.baseUrl, childObjectId = _this$props.childObjectId, containerId = _this$props.containerId, fieldId = _this$props.fieldId, includeGroups = _this$props.includeGroups, includeTeams = _this$props.includeTeams, includeTeamsUpdates = _this$props.includeTeamsUpdates, includeUsers = _this$props.includeUsers, includeNonLicensedUsers = _this$props.includeNonLicensedUsers, intl = _this$props.intl, fetchOptions = _this$props.fetchOptions, maxOptions = _this$props.maxOptions, objectId = _this$props.objectId, onEmpty = _this$props.onEmpty, onError = _this$props.onError, overrideByline = _this$props.overrideByline, displayEmailInByline = _this$props.displayEmailInByline, orgId = _this$props.orgId, principalId = _this$props.principalId, productAttributes = _this$props.productAttributes, productKey = _this$props.productKey, searchQueryFilter = _this$props.searchQueryFilter, siteId = _this$props.siteId, transformOptions = _this$props.transformOptions, userResolvers = _this$props.userResolvers, enableEmailSearch = _this$props.enableEmailSearch;
126
+ _this$props = _this.props, baseUrl = _this$props.baseUrl, childObjectId = _this$props.childObjectId, containerId = _this$props.containerId, fieldId = _this$props.fieldId, includeGroups = _this$props.includeGroups, includeTeams = _this$props.includeTeams, includeTeamsUpdates = _this$props.includeTeamsUpdates, includeUsers = _this$props.includeUsers, includeNonLicensedUsers = _this$props.includeNonLicensedUsers, intl = _this$props.intl, fetchOptions = _this$props.fetchOptions, maxOptions = _this$props.maxOptions, objectId = _this$props.objectId, onEmpty = _this$props.onEmpty, onError = _this$props.onError, overrideByline = _this$props.overrideByline, displayEmailInByline = _this$props.displayEmailInByline, verifiedTeams = _this$props.verifiedTeams, orgId = _this$props.orgId, principalId = _this$props.principalId, productAttributes = _this$props.productAttributes, productKey = _this$props.productKey, restrictTo = _this$props.restrictTo, searchQueryFilter = _this$props.searchQueryFilter, siteId = _this$props.siteId, transformOptions = _this$props.transformOptions, userResolvers = _this$props.userResolvers, enableEmailSearch = _this$props.enableEmailSearch;
127
127
  maxNumberOfResults = maxOptions || 100;
128
128
  startTime = window.performance.now(); // Check if this is an email search
129
129
  isEmail = enableEmailSearch && isEmailQuery(query);
130
- recommendationsRequest = {
130
+ recommendationsRequest = _objectSpread({
131
131
  baseUrl: baseUrl,
132
132
  context: {
133
133
  containerId: containerId,
@@ -149,6 +149,7 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
149
149
  maxNumberOfResults: maxNumberOfResults,
150
150
  query: query,
151
151
  searchEmail: isEmail,
152
+ verifiedTeams: verifiedTeams,
152
153
  /*
153
154
  For email-based searches, we have decided to filter out apps.
154
155
  Also - because the other 2 filters ((NOT not_mentionable:true) AND (account_status:active)) are included
@@ -156,7 +157,9 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
156
157
  Further ref: https://developer.atlassian.com/platform/user-recommendations/guides/frequently-asked-questions/#filter-behavior
157
158
  */
158
159
  searchQueryFilter: isEmail && !searchQueryFilter ? '(NOT not_mentionable:true) AND (account_status:active) AND (NOT account_type:app)' : searchQueryFilter
159
- };
160
+ }, restrictTo && (0, _platformFeatureFlags.fg)('smart-user-picker-restrict-to-gate') && {
161
+ restrictTo: restrictTo
162
+ });
160
163
  _context.prev = 6;
161
164
  _query = _this.state.query;
162
165
  _this.fireEvent(_analytics.requestUsersEvent);
@@ -252,6 +255,19 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
252
255
  }
253
256
  }
254
257
 
258
+ // Filter to only verified teams when verifiedTeams is true and feature flag is enabled
259
+ if (verifiedTeams && includeTeams && (0, _platformFeatureFlags.fg)('smart-user-picker-managed-teams-gate')) {
260
+ recommendedUsers = recommendedUsers.filter(function (option) {
261
+ if ((0, _userPicker.isTeam)(option)) {
262
+ // Only include teams that are verified
263
+ // The verified property is set by the transformer from the server response
264
+ var team = option;
265
+ return team.verified === true;
266
+ }
267
+ return true; // Keep non-team options
268
+ });
269
+ }
270
+
255
271
  // Track if email search found matches for conditional allowEmail logic
256
272
  if (isEmail) {
257
273
  _this.lastEmailSearchFoundMatches = recommendedUsers.length > 0;
@@ -260,50 +276,50 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
260
276
  }
261
277
  elapsedTimeMilli = window.performance.now() - startTime;
262
278
  if (!transformOptions) {
263
- _context.next = 41;
279
+ _context.next = 42;
264
280
  break;
265
281
  }
266
- _context.next = 38;
282
+ _context.next = 39;
267
283
  return transformOptions(recommendedUsers, _query);
268
- case 38:
284
+ case 39:
269
285
  _context.t0 = _context.sent;
270
- _context.next = 42;
286
+ _context.next = 43;
271
287
  break;
272
- case 41:
273
- _context.t0 = recommendedUsers;
274
288
  case 42:
289
+ _context.t0 = recommendedUsers;
290
+ case 43:
275
291
  transformedOptions = _context.t0;
276
292
  if (!(transformedOptions.length === 0 && onEmpty)) {
277
- _context.next = 58;
293
+ _context.next = 59;
278
294
  break;
279
295
  }
280
- _context.next = 46;
296
+ _context.next = 47;
281
297
  return onEmpty(_query);
282
- case 46:
298
+ case 47:
283
299
  _context.t3 = _yield$onEmpty = _context.sent;
284
300
  _context.t2 = _context.t3 !== null;
285
301
  if (!_context.t2) {
286
- _context.next = 50;
302
+ _context.next = 51;
287
303
  break;
288
304
  }
289
305
  _context.t2 = _yield$onEmpty !== void 0;
290
- case 50:
306
+ case 51:
291
307
  if (!_context.t2) {
292
- _context.next = 54;
308
+ _context.next = 55;
293
309
  break;
294
310
  }
295
311
  _context.t4 = _yield$onEmpty;
296
- _context.next = 55;
312
+ _context.next = 56;
297
313
  break;
298
- case 54:
299
- _context.t4 = [];
300
314
  case 55:
315
+ _context.t4 = [];
316
+ case 56:
301
317
  _context.t1 = _context.t4;
302
- _context.next = 59;
318
+ _context.next = 60;
303
319
  break;
304
- case 58:
305
- _context.t1 = transformedOptions;
306
320
  case 59:
321
+ _context.t1 = transformedOptions;
322
+ case 60:
307
323
  displayedUsers = _context.t1;
308
324
  _this.setState(function (state) {
309
325
  var applicable = state.query === _query;
@@ -325,10 +341,10 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
325
341
  loading: loading
326
342
  };
327
343
  });
328
- _context.next = 92;
344
+ _context.next = 93;
329
345
  break;
330
- case 63:
331
- _context.prev = 63;
346
+ case 64:
347
+ _context.prev = 64;
332
348
  _context.t5 = _context["catch"](6);
333
349
  is5xxEvent = checkIf500Event(_context.t5.statusCode);
334
350
  if (!closed && !onError && is5xxEvent) {
@@ -341,35 +357,35 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
341
357
  });
342
358
  onErrorProducedError = false;
343
359
  defaultUsers = [];
344
- _context.prev = 70;
360
+ _context.prev = 71;
345
361
  if (!onError) {
346
- _context.next = 80;
362
+ _context.next = 81;
347
363
  break;
348
364
  }
349
- _context.next = 74;
365
+ _context.next = 75;
350
366
  return onError(_context.t5, recommendationsRequest);
351
- case 74:
367
+ case 75:
352
368
  _context.t7 = _context.sent;
353
369
  if (_context.t7) {
354
- _context.next = 77;
370
+ _context.next = 78;
355
371
  break;
356
372
  }
357
373
  _context.t7 = [];
358
- case 77:
374
+ case 78:
359
375
  _context.t6 = _context.t7;
360
- _context.next = 81;
376
+ _context.next = 82;
361
377
  break;
362
- case 80:
363
- _context.t6 = [];
364
378
  case 81:
379
+ _context.t6 = [];
380
+ case 82:
365
381
  defaultUsers = _context.t6;
366
- _context.next = 87;
382
+ _context.next = 88;
367
383
  break;
368
- case 84:
369
- _context.prev = 84;
370
- _context.t8 = _context["catch"](70);
384
+ case 85:
385
+ _context.prev = 85;
386
+ _context.t8 = _context["catch"](71);
371
387
  onErrorProducedError = true;
372
- case 87:
388
+ case 88:
373
389
  if (onErrorProducedError && is5xxEvent) {
374
390
  // Log error from fallback data source `onError` to UFO
375
391
  _this.optionsShownUfoExperienceInstance.failure(ufoEndStateConfig(_this.props.fieldId));
@@ -386,11 +402,11 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
386
402
  elapsedTimeMilli: _elapsedTimeMilli,
387
403
  productAttributes: productAttributes
388
404
  });
389
- case 92:
405
+ case 93:
390
406
  case "end":
391
407
  return _context.stop();
392
408
  }
393
- }, _callee, null, [[6, 63], [70, 84]]);
409
+ }, _callee, null, [[6, 64], [71, 85]]);
394
410
  })), (_this$props$debounceT = _this.props.debounceTime) !== null && _this$props$debounceT !== void 0 ? _this$props$debounceT : 0));
395
411
  (0, _defineProperty2.default)(_this, "onInputChange", function (newQuery, sessionId) {
396
412
  var query = newQuery || '';
@@ -562,7 +578,6 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
562
578
  allowEmail = _this$props2.allowEmail,
563
579
  enableEmailSearch = _this$props2.enableEmailSearch,
564
580
  allowEmailSelectionWhenEmailMatched = _this$props2.allowEmailSelectionWhenEmailMatched,
565
- fetchOptions = _this$props2.fetchOptions,
566
581
  restProps = (0, _objectWithoutProperties2.default)(_this$props2, _excluded);
567
582
 
568
583
  // Determine whether to allow email selection based on allowEmailSelectionWhenEmailMatched, if needed
@@ -598,6 +613,7 @@ var SmartUserPickerWithoutAnalytics = exports.SmartUserPickerWithoutAnalytics =
598
613
  debounceTime: DEFAULT_DEBOUNCE_TIME_MS,
599
614
  userResolvers: [],
600
615
  enableEmailSearch: false,
601
- allowEmailSelectionWhenEmailMatched: true
616
+ allowEmailSelectionWhenEmailMatched: true,
617
+ verifiedTeams: false
602
618
  });
603
619
  var SmartUserPicker = exports.SmartUserPicker = (0, _analyticsNext.withAnalyticsEvents)()((0, _reactIntlNext.injectIntl)(SmartUserPickerWithoutAnalytics));
@@ -40,7 +40,7 @@ var getUserRecommendations = function getUserRecommendations(request, intl) {
40
40
  filter: request.searchQueryFilter || '',
41
41
  minimumAccessLevel: 'APPLICATION',
42
42
  queryString: request.query,
43
- restrictTo: {
43
+ restrictTo: request.restrictTo || {
44
44
  userIds: [],
45
45
  groupIds: []
46
46
  },
@@ -103,10 +103,12 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
103
103
  onError,
104
104
  overrideByline,
105
105
  displayEmailInByline,
106
+ verifiedTeams,
106
107
  orgId,
107
108
  principalId,
108
109
  productAttributes,
109
110
  productKey,
111
+ restrictTo,
110
112
  searchQueryFilter,
111
113
  siteId,
112
114
  transformOptions,
@@ -140,13 +142,17 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
140
142
  maxNumberOfResults,
141
143
  query,
142
144
  searchEmail: isEmail,
145
+ verifiedTeams,
143
146
  /*
144
147
  For email-based searches, we have decided to filter out apps.
145
148
  Also - because the other 2 filters ((NOT not_mentionable:true) AND (account_status:active)) are included
146
149
  when filter is empty, they have been added here to maintain consistency.
147
150
  Further ref: https://developer.atlassian.com/platform/user-recommendations/guides/frequently-asked-questions/#filter-behavior
148
151
  */
149
- searchQueryFilter: isEmail && !searchQueryFilter ? '(NOT not_mentionable:true) AND (account_status:active) AND (NOT account_type:app)' : searchQueryFilter
152
+ searchQueryFilter: isEmail && !searchQueryFilter ? '(NOT not_mentionable:true) AND (account_status:active) AND (NOT account_type:app)' : searchQueryFilter,
153
+ ...(restrictTo && fg('smart-user-picker-restrict-to-gate') && {
154
+ restrictTo
155
+ })
150
156
  };
151
157
  try {
152
158
  var _await$onEmpty;
@@ -198,6 +204,19 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
198
204
  }
199
205
  }
200
206
 
207
+ // Filter to only verified teams when verifiedTeams is true and feature flag is enabled
208
+ if (verifiedTeams && includeTeams && fg('smart-user-picker-managed-teams-gate')) {
209
+ recommendedUsers = recommendedUsers.filter(option => {
210
+ if (isTeam(option)) {
211
+ // Only include teams that are verified
212
+ // The verified property is set by the transformer from the server response
213
+ const team = option;
214
+ return team.verified === true;
215
+ }
216
+ return true; // Keep non-team options
217
+ });
218
+ }
219
+
201
220
  // Track if email search found matches for conditional allowEmail logic
202
221
  if (isEmail) {
203
222
  this.lastEmailSearchFoundMatches = recommendedUsers.length > 0;
@@ -240,7 +259,7 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
240
259
  let defaultUsers = [];
241
260
  try {
242
261
  defaultUsers = onError ? (await onError(e, recommendationsRequest)) || [] : [];
243
- } catch (error) {
262
+ } catch {
244
263
  onErrorProducedError = true;
245
264
  }
246
265
  if (onErrorProducedError && is5xxEvent) {
@@ -402,7 +421,6 @@ export class SmartUserPickerWithoutAnalytics extends React.Component {
402
421
  allowEmail,
403
422
  enableEmailSearch,
404
423
  allowEmailSelectionWhenEmailMatched,
405
- fetchOptions,
406
424
  ...restProps
407
425
  } = this.props;
408
426
 
@@ -440,6 +458,7 @@ _defineProperty(SmartUserPickerWithoutAnalytics, "defaultProps", {
440
458
  debounceTime: DEFAULT_DEBOUNCE_TIME_MS,
441
459
  userResolvers: [],
442
460
  enableEmailSearch: false,
443
- allowEmailSelectionWhenEmailMatched: true
461
+ allowEmailSelectionWhenEmailMatched: true,
462
+ verifiedTeams: false
444
463
  });
445
464
  export const SmartUserPicker = withAnalyticsEvents()(injectIntl(SmartUserPickerWithoutAnalytics));
@@ -30,7 +30,7 @@ const getUserRecommendations = (request, intl) => {
30
30
  filter: request.searchQueryFilter || '',
31
31
  minimumAccessLevel: 'APPLICATION',
32
32
  queryString: request.query,
33
- restrictTo: {
33
+ restrictTo: request.restrictTo || {
34
34
  userIds: [],
35
35
  groupIds: []
36
36
  },
@@ -9,13 +9,13 @@ import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstruct
9
9
  import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
10
10
  import _inherits from "@babel/runtime/helpers/inherits";
11
11
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
12
- var _excluded = ["allowEmail", "enableEmailSearch", "allowEmailSelectionWhenEmailMatched", "fetchOptions"];
12
+ var _excluded = ["allowEmail", "enableEmailSearch", "allowEmailSelectionWhenEmailMatched"];
13
13
  import _regeneratorRuntime from "@babel/runtime/regenerator";
14
- 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; }
15
- 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; }
16
14
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
17
15
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
18
16
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
17
+ 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; }
18
+ 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; }
19
19
  function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
20
20
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
21
21
  import React from 'react';
@@ -110,16 +110,16 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
110
110
  });
111
111
  _defineProperty(_this, "memoizedFilterOptions", memoizeOne(_this.filterOptions));
112
112
  _defineProperty(_this, "getUsers", debounce( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
113
- var _this$state, query, sessionId, closed, _this$props, baseUrl, childObjectId, containerId, fieldId, includeGroups, includeTeams, includeTeamsUpdates, includeUsers, includeNonLicensedUsers, intl, fetchOptions, maxOptions, objectId, onEmpty, onError, overrideByline, displayEmailInByline, orgId, principalId, productAttributes, productKey, searchQueryFilter, siteId, transformOptions, userResolvers, enableEmailSearch, maxNumberOfResults, startTime, isEmail, recommendationsRequest, _yield$onEmpty, _query, recommendedUsers, userRecommendationsPromise, userResolversPromises, _yield$Promise$all, _yield$Promise$all2, mainRecommendations, userResolverResults, _iterator, _step, option, _iterator2, _step2, _option, _iterator3, _step3, _option2, elapsedTimeMilli, transformedOptions, displayedUsers, is5xxEvent, onErrorProducedError, defaultUsers, _elapsedTimeMilli;
113
+ var _this$state, query, sessionId, closed, _this$props, baseUrl, childObjectId, containerId, fieldId, includeGroups, includeTeams, includeTeamsUpdates, includeUsers, includeNonLicensedUsers, intl, fetchOptions, maxOptions, objectId, onEmpty, onError, overrideByline, displayEmailInByline, verifiedTeams, orgId, principalId, productAttributes, productKey, restrictTo, searchQueryFilter, siteId, transformOptions, userResolvers, enableEmailSearch, maxNumberOfResults, startTime, isEmail, recommendationsRequest, _yield$onEmpty, _query, recommendedUsers, userRecommendationsPromise, userResolversPromises, _yield$Promise$all, _yield$Promise$all2, mainRecommendations, userResolverResults, _iterator, _step, option, _iterator2, _step2, _option, _iterator3, _step3, _option2, elapsedTimeMilli, transformedOptions, displayedUsers, is5xxEvent, onErrorProducedError, defaultUsers, _elapsedTimeMilli;
114
114
  return _regeneratorRuntime.wrap(function _callee$(_context) {
115
115
  while (1) switch (_context.prev = _context.next) {
116
116
  case 0:
117
117
  _this$state = _this.state, query = _this$state.query, sessionId = _this$state.sessionId, closed = _this$state.closed;
118
- _this$props = _this.props, baseUrl = _this$props.baseUrl, childObjectId = _this$props.childObjectId, containerId = _this$props.containerId, fieldId = _this$props.fieldId, includeGroups = _this$props.includeGroups, includeTeams = _this$props.includeTeams, includeTeamsUpdates = _this$props.includeTeamsUpdates, includeUsers = _this$props.includeUsers, includeNonLicensedUsers = _this$props.includeNonLicensedUsers, intl = _this$props.intl, fetchOptions = _this$props.fetchOptions, maxOptions = _this$props.maxOptions, objectId = _this$props.objectId, onEmpty = _this$props.onEmpty, onError = _this$props.onError, overrideByline = _this$props.overrideByline, displayEmailInByline = _this$props.displayEmailInByline, orgId = _this$props.orgId, principalId = _this$props.principalId, productAttributes = _this$props.productAttributes, productKey = _this$props.productKey, searchQueryFilter = _this$props.searchQueryFilter, siteId = _this$props.siteId, transformOptions = _this$props.transformOptions, userResolvers = _this$props.userResolvers, enableEmailSearch = _this$props.enableEmailSearch;
118
+ _this$props = _this.props, baseUrl = _this$props.baseUrl, childObjectId = _this$props.childObjectId, containerId = _this$props.containerId, fieldId = _this$props.fieldId, includeGroups = _this$props.includeGroups, includeTeams = _this$props.includeTeams, includeTeamsUpdates = _this$props.includeTeamsUpdates, includeUsers = _this$props.includeUsers, includeNonLicensedUsers = _this$props.includeNonLicensedUsers, intl = _this$props.intl, fetchOptions = _this$props.fetchOptions, maxOptions = _this$props.maxOptions, objectId = _this$props.objectId, onEmpty = _this$props.onEmpty, onError = _this$props.onError, overrideByline = _this$props.overrideByline, displayEmailInByline = _this$props.displayEmailInByline, verifiedTeams = _this$props.verifiedTeams, orgId = _this$props.orgId, principalId = _this$props.principalId, productAttributes = _this$props.productAttributes, productKey = _this$props.productKey, restrictTo = _this$props.restrictTo, searchQueryFilter = _this$props.searchQueryFilter, siteId = _this$props.siteId, transformOptions = _this$props.transformOptions, userResolvers = _this$props.userResolvers, enableEmailSearch = _this$props.enableEmailSearch;
119
119
  maxNumberOfResults = maxOptions || 100;
120
120
  startTime = window.performance.now(); // Check if this is an email search
121
121
  isEmail = enableEmailSearch && isEmailQuery(query);
122
- recommendationsRequest = {
122
+ recommendationsRequest = _objectSpread({
123
123
  baseUrl: baseUrl,
124
124
  context: {
125
125
  containerId: containerId,
@@ -141,6 +141,7 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
141
141
  maxNumberOfResults: maxNumberOfResults,
142
142
  query: query,
143
143
  searchEmail: isEmail,
144
+ verifiedTeams: verifiedTeams,
144
145
  /*
145
146
  For email-based searches, we have decided to filter out apps.
146
147
  Also - because the other 2 filters ((NOT not_mentionable:true) AND (account_status:active)) are included
@@ -148,7 +149,9 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
148
149
  Further ref: https://developer.atlassian.com/platform/user-recommendations/guides/frequently-asked-questions/#filter-behavior
149
150
  */
150
151
  searchQueryFilter: isEmail && !searchQueryFilter ? '(NOT not_mentionable:true) AND (account_status:active) AND (NOT account_type:app)' : searchQueryFilter
151
- };
152
+ }, restrictTo && fg('smart-user-picker-restrict-to-gate') && {
153
+ restrictTo: restrictTo
154
+ });
152
155
  _context.prev = 6;
153
156
  _query = _this.state.query;
154
157
  _this.fireEvent(requestUsersEvent);
@@ -244,6 +247,19 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
244
247
  }
245
248
  }
246
249
 
250
+ // Filter to only verified teams when verifiedTeams is true and feature flag is enabled
251
+ if (verifiedTeams && includeTeams && fg('smart-user-picker-managed-teams-gate')) {
252
+ recommendedUsers = recommendedUsers.filter(function (option) {
253
+ if (isTeam(option)) {
254
+ // Only include teams that are verified
255
+ // The verified property is set by the transformer from the server response
256
+ var team = option;
257
+ return team.verified === true;
258
+ }
259
+ return true; // Keep non-team options
260
+ });
261
+ }
262
+
247
263
  // Track if email search found matches for conditional allowEmail logic
248
264
  if (isEmail) {
249
265
  _this.lastEmailSearchFoundMatches = recommendedUsers.length > 0;
@@ -252,50 +268,50 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
252
268
  }
253
269
  elapsedTimeMilli = window.performance.now() - startTime;
254
270
  if (!transformOptions) {
255
- _context.next = 41;
271
+ _context.next = 42;
256
272
  break;
257
273
  }
258
- _context.next = 38;
274
+ _context.next = 39;
259
275
  return transformOptions(recommendedUsers, _query);
260
- case 38:
276
+ case 39:
261
277
  _context.t0 = _context.sent;
262
- _context.next = 42;
278
+ _context.next = 43;
263
279
  break;
264
- case 41:
265
- _context.t0 = recommendedUsers;
266
280
  case 42:
281
+ _context.t0 = recommendedUsers;
282
+ case 43:
267
283
  transformedOptions = _context.t0;
268
284
  if (!(transformedOptions.length === 0 && onEmpty)) {
269
- _context.next = 58;
285
+ _context.next = 59;
270
286
  break;
271
287
  }
272
- _context.next = 46;
288
+ _context.next = 47;
273
289
  return onEmpty(_query);
274
- case 46:
290
+ case 47:
275
291
  _context.t3 = _yield$onEmpty = _context.sent;
276
292
  _context.t2 = _context.t3 !== null;
277
293
  if (!_context.t2) {
278
- _context.next = 50;
294
+ _context.next = 51;
279
295
  break;
280
296
  }
281
297
  _context.t2 = _yield$onEmpty !== void 0;
282
- case 50:
298
+ case 51:
283
299
  if (!_context.t2) {
284
- _context.next = 54;
300
+ _context.next = 55;
285
301
  break;
286
302
  }
287
303
  _context.t4 = _yield$onEmpty;
288
- _context.next = 55;
304
+ _context.next = 56;
289
305
  break;
290
- case 54:
291
- _context.t4 = [];
292
306
  case 55:
307
+ _context.t4 = [];
308
+ case 56:
293
309
  _context.t1 = _context.t4;
294
- _context.next = 59;
310
+ _context.next = 60;
295
311
  break;
296
- case 58:
297
- _context.t1 = transformedOptions;
298
312
  case 59:
313
+ _context.t1 = transformedOptions;
314
+ case 60:
299
315
  displayedUsers = _context.t1;
300
316
  _this.setState(function (state) {
301
317
  var applicable = state.query === _query;
@@ -317,10 +333,10 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
317
333
  loading: loading
318
334
  };
319
335
  });
320
- _context.next = 92;
336
+ _context.next = 93;
321
337
  break;
322
- case 63:
323
- _context.prev = 63;
338
+ case 64:
339
+ _context.prev = 64;
324
340
  _context.t5 = _context["catch"](6);
325
341
  is5xxEvent = checkIf500Event(_context.t5.statusCode);
326
342
  if (!closed && !onError && is5xxEvent) {
@@ -333,35 +349,35 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
333
349
  });
334
350
  onErrorProducedError = false;
335
351
  defaultUsers = [];
336
- _context.prev = 70;
352
+ _context.prev = 71;
337
353
  if (!onError) {
338
- _context.next = 80;
354
+ _context.next = 81;
339
355
  break;
340
356
  }
341
- _context.next = 74;
357
+ _context.next = 75;
342
358
  return onError(_context.t5, recommendationsRequest);
343
- case 74:
359
+ case 75:
344
360
  _context.t7 = _context.sent;
345
361
  if (_context.t7) {
346
- _context.next = 77;
362
+ _context.next = 78;
347
363
  break;
348
364
  }
349
365
  _context.t7 = [];
350
- case 77:
366
+ case 78:
351
367
  _context.t6 = _context.t7;
352
- _context.next = 81;
368
+ _context.next = 82;
353
369
  break;
354
- case 80:
355
- _context.t6 = [];
356
370
  case 81:
371
+ _context.t6 = [];
372
+ case 82:
357
373
  defaultUsers = _context.t6;
358
- _context.next = 87;
374
+ _context.next = 88;
359
375
  break;
360
- case 84:
361
- _context.prev = 84;
362
- _context.t8 = _context["catch"](70);
376
+ case 85:
377
+ _context.prev = 85;
378
+ _context.t8 = _context["catch"](71);
363
379
  onErrorProducedError = true;
364
- case 87:
380
+ case 88:
365
381
  if (onErrorProducedError && is5xxEvent) {
366
382
  // Log error from fallback data source `onError` to UFO
367
383
  _this.optionsShownUfoExperienceInstance.failure(ufoEndStateConfig(_this.props.fieldId));
@@ -378,11 +394,11 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
378
394
  elapsedTimeMilli: _elapsedTimeMilli,
379
395
  productAttributes: productAttributes
380
396
  });
381
- case 92:
397
+ case 93:
382
398
  case "end":
383
399
  return _context.stop();
384
400
  }
385
- }, _callee, null, [[6, 63], [70, 84]]);
401
+ }, _callee, null, [[6, 64], [71, 85]]);
386
402
  })), (_this$props$debounceT = _this.props.debounceTime) !== null && _this$props$debounceT !== void 0 ? _this$props$debounceT : 0));
387
403
  _defineProperty(_this, "onInputChange", function (newQuery, sessionId) {
388
404
  var query = newQuery || '';
@@ -554,7 +570,6 @@ export var SmartUserPickerWithoutAnalytics = /*#__PURE__*/function (_React$Compo
554
570
  allowEmail = _this$props2.allowEmail,
555
571
  enableEmailSearch = _this$props2.enableEmailSearch,
556
572
  allowEmailSelectionWhenEmailMatched = _this$props2.allowEmailSelectionWhenEmailMatched,
557
- fetchOptions = _this$props2.fetchOptions,
558
573
  restProps = _objectWithoutProperties(_this$props2, _excluded);
559
574
 
560
575
  // Determine whether to allow email selection based on allowEmailSelectionWhenEmailMatched, if needed
@@ -592,6 +607,7 @@ _defineProperty(SmartUserPickerWithoutAnalytics, "defaultProps", {
592
607
  debounceTime: DEFAULT_DEBOUNCE_TIME_MS,
593
608
  userResolvers: [],
594
609
  enableEmailSearch: false,
595
- allowEmailSelectionWhenEmailMatched: true
610
+ allowEmailSelectionWhenEmailMatched: true,
611
+ verifiedTeams: false
596
612
  });
597
613
  export var SmartUserPicker = withAnalyticsEvents()(injectIntl(SmartUserPickerWithoutAnalytics));
@@ -33,7 +33,7 @@ var getUserRecommendations = function getUserRecommendations(request, intl) {
33
33
  filter: request.searchQueryFilter || '',
34
34
  minimumAccessLevel: 'APPLICATION',
35
35
  queryString: request.query,
36
- restrictTo: {
36
+ restrictTo: request.restrictTo || {
37
37
  userIds: [],
38
38
  groupIds: []
39
39
  },
@@ -21,6 +21,7 @@ export declare class SmartUserPickerWithoutAnalytics extends React.Component<Pro
21
21
  userResolvers: never[];
22
22
  enableEmailSearch: boolean;
23
23
  allowEmailSelectionWhenEmailMatched: boolean;
24
+ verifiedTeams: boolean;
24
25
  };
25
26
  constructor(props: Props & WrappedComponentProps);
26
27
  componentDidMount(): Promise<void>;
@@ -12,6 +12,10 @@ export interface Context {
12
12
  organizationId?: string;
13
13
  productAttributes?: ProductAttributes;
14
14
  }
15
+ export interface RestrictionFilter {
16
+ userIds?: string[];
17
+ groupIds?: string[];
18
+ }
15
19
  export interface RecommendationRequest {
16
20
  baseUrl?: string;
17
21
  context: Context;
@@ -23,6 +27,8 @@ export interface RecommendationRequest {
23
27
  includeTeams?: boolean;
24
28
  includeNonLicensedUsers?: boolean;
25
29
  searchEmail?: boolean;
30
+ verifiedTeams?: boolean;
31
+ restrictTo?: RestrictionFilter;
26
32
  }
27
33
  type OnError = (error: any, request: RecommendationRequest) => Promise<OptionData[]> | void;
28
34
  type OnValueError = (error: any, defaultValue: DefaultValue) => Promise<OptionData[]> | void;
@@ -126,6 +132,10 @@ export interface SmartProps {
126
132
  * Whether to include teams in the resultset. @default false
127
133
  */
128
134
  includeTeams?: boolean;
135
+ /**
136
+ * When set to true, only returns verified teams. Only applies when includeTeams is true. @default false
137
+ */
138
+ verifiedTeams?: boolean;
129
139
  /**
130
140
  * Whether to include users in the resultset. @default true
131
141
  */
@@ -242,6 +252,12 @@ export interface SmartProps {
242
252
  isFooterFocused?: boolean;
243
253
  /** Sets if the footer is focused or not. This is needed to keep the menu open when the footer is focused */
244
254
  setIsFooterFocused?: React.Dispatch<React.SetStateAction<boolean>>;
255
+ /**
256
+ * Restricts the recommendations to specific users and/or groups.
257
+ * If provided, only users matching the provided user IDs and/or groups matching the provided group IDs will be included in the results.
258
+ * @example { userIds: ["123", "456"], groupIds: ["789"] }
259
+ */
260
+ restrictTo?: RestrictionFilter;
245
261
  }
246
262
  export interface Props extends SmartProps, UserPickerProps, WithAnalyticsEventsProps {
247
263
  /**
@@ -21,6 +21,7 @@ export declare class SmartUserPickerWithoutAnalytics extends React.Component<Pro
21
21
  userResolvers: never[];
22
22
  enableEmailSearch: boolean;
23
23
  allowEmailSelectionWhenEmailMatched: boolean;
24
+ verifiedTeams: boolean;
24
25
  };
25
26
  constructor(props: Props & WrappedComponentProps);
26
27
  componentDidMount(): Promise<void>;
@@ -12,6 +12,10 @@ export interface Context {
12
12
  organizationId?: string;
13
13
  productAttributes?: ProductAttributes;
14
14
  }
15
+ export interface RestrictionFilter {
16
+ userIds?: string[];
17
+ groupIds?: string[];
18
+ }
15
19
  export interface RecommendationRequest {
16
20
  baseUrl?: string;
17
21
  context: Context;
@@ -23,6 +27,8 @@ export interface RecommendationRequest {
23
27
  includeTeams?: boolean;
24
28
  includeNonLicensedUsers?: boolean;
25
29
  searchEmail?: boolean;
30
+ verifiedTeams?: boolean;
31
+ restrictTo?: RestrictionFilter;
26
32
  }
27
33
  type OnError = (error: any, request: RecommendationRequest) => Promise<OptionData[]> | void;
28
34
  type OnValueError = (error: any, defaultValue: DefaultValue) => Promise<OptionData[]> | void;
@@ -126,6 +132,10 @@ export interface SmartProps {
126
132
  * Whether to include teams in the resultset. @default false
127
133
  */
128
134
  includeTeams?: boolean;
135
+ /**
136
+ * When set to true, only returns verified teams. Only applies when includeTeams is true. @default false
137
+ */
138
+ verifiedTeams?: boolean;
129
139
  /**
130
140
  * Whether to include users in the resultset. @default true
131
141
  */
@@ -242,6 +252,12 @@ export interface SmartProps {
242
252
  isFooterFocused?: boolean;
243
253
  /** Sets if the footer is focused or not. This is needed to keep the menu open when the footer is focused */
244
254
  setIsFooterFocused?: React.Dispatch<React.SetStateAction<boolean>>;
255
+ /**
256
+ * Restricts the recommendations to specific users and/or groups.
257
+ * If provided, only users matching the provided user IDs and/or groups matching the provided group IDs will be included in the results.
258
+ * @example { userIds: ["123", "456"], groupIds: ["789"] }
259
+ */
260
+ restrictTo?: RestrictionFilter;
245
261
  }
246
262
  export interface Props extends SmartProps, UserPickerProps, WithAnalyticsEventsProps {
247
263
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/smart-user-picker",
3
- "version": "8.6.0",
3
+ "version": "8.8.0",
4
4
  "license": "Apache-2.0",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -66,6 +66,12 @@
66
66
  },
67
67
  "smart-user-picker-load-options-gate": {
68
68
  "type": "boolean"
69
+ },
70
+ "smart-user-picker-managed-teams-gate": {
71
+ "type": "boolean"
72
+ },
73
+ "smart-user-picker-restrict-to-gate": {
74
+ "type": "boolean"
69
75
  }
70
76
  }
71
77
  }