@atlaskit/link-datasource 7.12.3 → 7.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/dist/cjs/ui/common/modal/basic-search-input/index.js +8 -3
  3. package/dist/cjs/ui/common/modal/mode-switcher/ModeSwitcher.compiled.css +1 -0
  4. package/dist/cjs/ui/common/modal/mode-switcher/ModeSwitcher.js +3 -1
  5. package/dist/cjs/ui/common/modal/popup-select/index.js +34 -5
  6. package/dist/cjs/ui/common/modal/popup-select/useInlinePopupLayout.js +123 -0
  7. package/dist/cjs/ui/datasource-table-view/datasourceTableView.js +9 -3
  8. package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +4 -1
  9. package/dist/cjs/ui/jira-issues-modal/basic-filters/ui/index.js +5 -1
  10. package/dist/cjs/ui/jira-issues-modal/jira-search-container/JiraSearchContainerWithWrappers.js +19 -0
  11. package/dist/cjs/ui/jira-issues-modal/jira-search-container/buildJQL.js +12 -2
  12. package/dist/cjs/ui/jira-issues-modal/jira-search-container/embedded.compiled.css +11 -0
  13. package/dist/cjs/ui/jira-issues-modal/jira-search-container/embedded.js +321 -0
  14. package/dist/cjs/ui/jira-issues-modal/jira-search-container/index.js +12 -0
  15. package/dist/cjs/ui/jira-issues-modal/jql-editor/index.js +9 -1
  16. package/dist/cjs/ui/jira-search-state/index.compiled.css +12 -0
  17. package/dist/cjs/ui/jira-search-state/index.js +90 -0
  18. package/dist/es2019/ui/common/modal/basic-search-input/index.js +5 -2
  19. package/dist/es2019/ui/common/modal/mode-switcher/ModeSwitcher.compiled.css +1 -0
  20. package/dist/es2019/ui/common/modal/mode-switcher/ModeSwitcher.js +3 -1
  21. package/dist/es2019/ui/common/modal/popup-select/index.js +34 -4
  22. package/dist/es2019/ui/common/modal/popup-select/useInlinePopupLayout.js +103 -0
  23. package/dist/es2019/ui/datasource-table-view/datasourceTableView.js +8 -3
  24. package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +3 -1
  25. package/dist/es2019/ui/jira-issues-modal/basic-filters/ui/index.js +4 -1
  26. package/dist/es2019/ui/jira-issues-modal/jira-search-container/JiraSearchContainerWithWrappers.js +11 -0
  27. package/dist/es2019/ui/jira-issues-modal/jira-search-container/buildJQL.js +10 -2
  28. package/dist/es2019/ui/jira-issues-modal/jira-search-container/embedded.compiled.css +11 -0
  29. package/dist/es2019/ui/jira-issues-modal/jira-search-container/embedded.js +283 -0
  30. package/dist/es2019/ui/jira-issues-modal/jira-search-container/index.js +12 -0
  31. package/dist/es2019/ui/jira-issues-modal/jql-editor/index.js +7 -1
  32. package/dist/es2019/ui/jira-search-state/index.compiled.css +12 -0
  33. package/dist/es2019/ui/jira-search-state/index.js +82 -0
  34. package/dist/esm/ui/common/modal/basic-search-input/index.js +8 -3
  35. package/dist/esm/ui/common/modal/mode-switcher/ModeSwitcher.compiled.css +1 -0
  36. package/dist/esm/ui/common/modal/mode-switcher/ModeSwitcher.js +3 -1
  37. package/dist/esm/ui/common/modal/popup-select/index.js +35 -5
  38. package/dist/esm/ui/common/modal/popup-select/useInlinePopupLayout.js +116 -0
  39. package/dist/esm/ui/datasource-table-view/datasourceTableView.js +9 -3
  40. package/dist/esm/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.js +4 -1
  41. package/dist/esm/ui/jira-issues-modal/basic-filters/ui/index.js +5 -1
  42. package/dist/esm/ui/jira-issues-modal/jira-search-container/JiraSearchContainerWithWrappers.js +13 -0
  43. package/dist/esm/ui/jira-issues-modal/jira-search-container/buildJQL.js +12 -2
  44. package/dist/esm/ui/jira-issues-modal/jira-search-container/embedded.compiled.css +11 -0
  45. package/dist/esm/ui/jira-issues-modal/jira-search-container/embedded.js +312 -0
  46. package/dist/esm/ui/jira-issues-modal/jira-search-container/index.js +12 -0
  47. package/dist/esm/ui/jira-issues-modal/jql-editor/index.js +9 -1
  48. package/dist/esm/ui/jira-search-state/index.compiled.css +12 -0
  49. package/dist/esm/ui/jira-search-state/index.js +83 -0
  50. package/dist/types/ui/common/modal/basic-search-input/index.d.ts +5 -1
  51. package/dist/types/ui/common/modal/mode-switcher/ModeSwitcher.d.ts +1 -0
  52. package/dist/types/ui/common/modal/popup-select/index.d.ts +2 -1
  53. package/dist/types/ui/common/modal/popup-select/useInlinePopupLayout.d.ts +9 -0
  54. package/dist/types/ui/datasource-table-view/datasourceTableView.d.ts +5 -1
  55. package/dist/types/ui/datasource-table-view/types.d.ts +5 -0
  56. package/dist/types/ui/jira-issues-modal/basic-filters/ui/async-popup-select/index.d.ts +2 -1
  57. package/dist/types/ui/jira-issues-modal/basic-filters/ui/index.d.ts +2 -1
  58. package/dist/types/ui/jira-issues-modal/jira-search-container/JiraSearchContainerWithWrappers.d.ts +4 -0
  59. package/dist/types/ui/jira-issues-modal/jira-search-container/buildJQL.d.ts +1 -0
  60. package/dist/types/ui/jira-issues-modal/jira-search-container/embedded.d.ts +9 -0
  61. package/dist/types/ui/jira-issues-modal/jira-search-container/index.d.ts +11 -0
  62. package/dist/types/ui/jira-issues-modal/jql-editor/index.d.ts +4 -1
  63. package/dist/types/ui/jira-search-state/index.d.ts +9 -0
  64. package/jira-search-container/package.json +10 -0
  65. package/jira-search-state/package.json +10 -0
  66. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,64 @@
1
1
  # @atlaskit/link-datasource
2
2
 
3
+ ## 7.13.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`d72c778a8a606`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/d72c778a8a606) -
8
+ Keep inline Basic filter dropdowns within the visible viewport, including the search control and
9
+ pagination footer, and resize their scrollable option lists on window or viewport changes.
10
+
11
+ Reuse the work-item picker's search and no-results illustrations in a stable in-card search area.
12
+ Use its native table skeleton for every retry, hold the measured card height and keep loading
13
+ perceptible for fast unchanged-query requests, preserve the existing result table, and remove the
14
+ explanatory Basic/JQL helper copy.
15
+
16
+ Ease the loading-to-no-results content change with a short opacity entrance using ADS motion
17
+ tokens, disabled when reduced motion is requested.
18
+
19
+ Use a smaller illustrated area for the recovery card, remove the duplicate visible no-results
20
+ message above the toolbar while retaining accessible status announcements, and preserve the
21
+ measured area during retries. The compact illustrated layout is optional and leaves the shared
22
+ default intact.
23
+
24
+ Expose the existing Jira Basic/JQL search controls through a supported, localized subpath with an
25
+ optional inline layout, keyword prefill, and preserved drafts when complex JQL needs a separate
26
+ Basic search. Add an optional full empty-table renderer that keeps datasource requests active.
27
+
28
+ Implement in-card Jira no-result recovery for `JiraCardNoResultsVariant: jql-search` in the
29
+ existing SAIN UX Hello/customer layers. Reuse `kd_sain_jira_card_no_results_rollout` and preserve
30
+ its collapse override. Keyword intent starts in Basic; natural-language intent starts with the
31
+ generated JQL. Keep the card frame, feedback, hide/reveal, and result expansion, and attribute
32
+ retries and a deduplicated recovery interaction to the original FPS search.
33
+
34
+ Keep existing modal search behavior on its original component path. Mount draft preservation and
35
+ viewport-aware popup hooks only for explicitly opted-in embedded consumers, preserve the default
36
+ JQL focus lifecycle, and separate optional completion reporting from empty-state rendering through
37
+ `enableRequestSettled`. Match the configured Arm 2 experiment value, `jql-search`.
38
+
39
+ Preserve the original gate-controlled Jira result interaction reporting after recovery. Keep
40
+ Basic/JQL toolbar clicks and retries separate from the existing answer-click and SAIN usage
41
+ signals, and include the retry attempt in submission activity events. Experiment metric
42
+ definitions remain downstream.
43
+
44
+ Share the existing Jira search default query and allowed sort keys between modal and embedded
45
+ controls without changing their values or the existing exported entry points.
46
+
47
+ Add optional `noResultsVariant: jql-search` metadata to the existing Search AI work-item click and
48
+ edit-start events after a recovery retry returns results. Preserve normal result payloads, event
49
+ names/counts and existing usage gates; toolbar, retry and table-refresh activity are not tagged as
50
+ recovered work-item interactions.
51
+
52
+ Keep embedded debounced Basic filter search metadata aligned with the submitted JQL by using the
53
+ scheduled filter selection snapshot, even when pending hydration updates the displayed selections.
54
+
55
+ Use compact Basic/JQL inputs in the opt-in inline recovery toolbar to align with the mode toggle
56
+ and filter buttons, and omit the keyword helper line in this layout. Keep the standard input size
57
+ and helper text for existing modal consumers.
58
+
59
+ Add an optional Basic submit-button visibility setting. Search AI recovery opts out of the button
60
+ and retains Enter-to-search; other consumers keep the existing button and submission behavior.
61
+
3
62
  ## 7.12.3
4
63
 
5
64
  ### Patch Changes
@@ -26,11 +26,15 @@ var styles = {
26
26
  var formStyles = null;
27
27
  var formWithMaxWidthStyles = null;
28
28
  var BasicSearchInput = exports.BasicSearchInput = function BasicSearchInput(_ref) {
29
- var isDisabled = _ref.isDisabled,
29
+ var _ref$isCompact = _ref.isCompact,
30
+ isCompact = _ref$isCompact === void 0 ? false : _ref$isCompact,
31
+ isDisabled = _ref.isDisabled,
30
32
  isSearching = _ref.isSearching,
31
33
  onChange = _ref.onChange,
32
34
  onSearch = _ref.onSearch,
33
35
  searchTerm = _ref.searchTerm,
36
+ _ref$showSearchButton = _ref.showSearchButton,
37
+ showSearchButton = _ref$showSearchButton === void 0 ? true : _ref$showSearchButton,
34
38
  fullWidth = _ref.fullWidth,
35
39
  testId = _ref.testId,
36
40
  ariaLabel = _ref.ariaLabel;
@@ -50,7 +54,8 @@ var BasicSearchInput = exports.BasicSearchInput = function BasicSearchInput(_ref
50
54
  onSubmit: handleFormSubmit,
51
55
  className: (0, _runtime.ax)([fullWidth ? "_16jlkb7n _1o9zkb7n _i0dlf1ug" : "_16jlkb7n _1o9zkb7n _i0dlf1ug _p12f1mjv"])
52
56
  }, /*#__PURE__*/React.createElement(_textField.default, {
53
- elemAfterInput: /*#__PURE__*/React.createElement(_box.Box, {
57
+ isCompact: isCompact,
58
+ elemAfterInput: showSearchButton ? /*#__PURE__*/React.createElement(_box.Box, {
54
59
  xcss: styles.searchButtonContainer
55
60
  }, /*#__PURE__*/React.createElement(_button.default, {
56
61
  appearance: "primary",
@@ -67,7 +72,7 @@ var BasicSearchInput = exports.BasicSearchInput = function BasicSearchInput(_ref
67
72
  isDisabled: isDisabled,
68
73
  testId: "".concat(testId, "--basic-search-button"),
69
74
  onClick: handleSearchWithAnalytics
70
- })),
75
+ })) : undefined,
71
76
  autoFocus: true,
72
77
  onChange: onChange,
73
78
  testId: "".concat(testId, "--basic-search-input"),
@@ -7,6 +7,7 @@
7
7
  ._1h6d1l7x{border-color:var(--ds-border,#0b120e24)}
8
8
  ._1h6dq98m{border-color:var(--ds-border-selected,#1868db)}
9
9
  ._18u0v47k{margin-left:var(--ds-space-250,20px)}
10
+ ._18u0ze3t{margin-left:var(--ds-space-0,0)}
10
11
  ._19bv1b66{padding-left:var(--ds-space-050,4px)}
11
12
  ._19bvutpp{padding-left:var(--ds-space-150,9pt)}
12
13
  ._1bah1h6o{justify-content:center}
@@ -13,6 +13,7 @@ var _react = _interopRequireDefault(require("react"));
13
13
  var _Tooltip = _interopRequireDefault(require("@atlaskit/tooltip/Tooltip"));
14
14
  var _visuallyHidden = _interopRequireDefault(require("@atlaskit/visually-hidden/visually-hidden"));
15
15
  var modeSwitcherStyles = null;
16
+ var inlineModeSwitcherStyles = null;
16
17
  var compactModeSwitcherStyles = null;
17
18
  var modeFocusStyles = null;
18
19
  var modeSwitcherLabelStyles = null;
@@ -23,6 +24,7 @@ var compactModeSwitcherLabelStyles = null;
23
24
  var ModeSwitcher = exports.ModeSwitcher = function ModeSwitcher(props) {
24
25
  var _options$;
25
26
  var isCompact = props.isCompact,
27
+ isInline = props.isInline,
26
28
  isDisabled = props.isDisabled,
27
29
  onOptionValueChange = props.onOptionValueChange,
28
30
  options = props.options,
@@ -34,7 +36,7 @@ var ModeSwitcher = exports.ModeSwitcher = function ModeSwitcher(props) {
34
36
  return options.length > 0 ? /*#__PURE__*/_react.default.createElement("fieldset", {
35
37
  "data-testid": "mode-toggle-container",
36
38
  disabled: isDisabled,
37
- className: (0, _runtime.ax)(["_2rko1b66 _1h6d1l7x _189ee4h9 _1dqonqa1 _4cvr1h6o _vchhusvi _1e0c116y _u5f31b66 _19bv1b66 _18u0v47k _4t3izwfg _1j55105o", isCompact && "_zulpv77o _ca0q1b66 _u5f31b66 _n3td1b66 _19bv1b66"])
39
+ className: (0, _runtime.ax)(["_2rko1b66 _1h6d1l7x _189ee4h9 _1dqonqa1 _4cvr1h6o _vchhusvi _1e0c116y _u5f31b66 _19bv1b66 _18u0v47k _4t3izwfg _1j55105o", isCompact && "_zulpv77o _ca0q1b66 _u5f31b66 _n3td1b66 _19bv1b66", isInline && "_18u0ze3t"])
38
40
  }, options.map(function (_ref) {
39
41
  var value = _ref.value,
40
42
  label = _ref.label,
@@ -6,13 +6,13 @@ Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
8
  exports.FilterPopupSelect = void 0;
9
- var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
10
9
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
11
10
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
12
11
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
13
12
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
14
13
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
15
14
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
15
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
16
16
  var _react = _interopRequireWildcard(require("react"));
17
17
  var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
18
18
  var _reactIntl = require("react-intl");
@@ -26,6 +26,7 @@ var _formatOptionLabel = _interopRequireDefault(require("./formatOptionLabel"));
26
26
  var _menuList = _interopRequireDefault(require("./menu-list"));
27
27
  var _messages = require("./messages");
28
28
  var _trigger = _interopRequireDefault(require("./trigger"));
29
+ var _useInlinePopupLayout = require("./useInlinePopupLayout");
29
30
  var _excluded = ["isOpen"];
30
31
  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); }
31
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; }
@@ -34,7 +35,34 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
34
35
  var noFilterOptions = function noFilterOptions() {
35
36
  return true;
36
37
  };
37
- var FilterPopupSelect = exports.FilterPopupSelect = function FilterPopupSelect(_ref) {
38
+ var FilterPopupSelect = exports.FilterPopupSelect = function FilterPopupSelect(props) {
39
+ return props.isInline ? /*#__PURE__*/_react.default.createElement(InlineFilterPopupSelect, props) : /*#__PURE__*/_react.default.createElement(FilterPopupSelectBase, props);
40
+ };
41
+ var InlineFilterPopupSelect = function InlineFilterPopupSelect(props) {
42
+ var popupRef = (0, _react.useRef)(null);
43
+ var layout = (0, _useInlinePopupLayout.useInlinePopupLayout)(true, popupRef);
44
+ var onMenuOpen = props.onMenuOpen,
45
+ onMenuClose = props.onMenuClose;
46
+ var handleOpen = (0, _react.useCallback)(function () {
47
+ layout.onOpen();
48
+ onMenuOpen === null || onMenuOpen === void 0 || onMenuOpen();
49
+ }, [layout.onOpen, onMenuOpen]);
50
+ var handleClose = (0, _react.useCallback)(function () {
51
+ layout.onClose();
52
+ onMenuClose === null || onMenuClose === void 0 || onMenuClose();
53
+ }, [layout.onClose, onMenuClose]);
54
+ return /*#__PURE__*/_react.default.createElement(FilterPopupSelectBase, (0, _extends2.default)({}, props, {
55
+ onMenuOpen: handleOpen,
56
+ onMenuClose: handleClose,
57
+ inlinePopupProps: {
58
+ ref: popupRef,
59
+ maxMenuHeight: layout.maxMenuHeight,
60
+ minMenuHeight: 0,
61
+ popperProps: layout.popperProps
62
+ }
63
+ }));
64
+ };
65
+ var FilterPopupSelectBase = function FilterPopupSelectBase(_ref) {
38
66
  var filterName = _ref.filterName,
39
67
  _ref$totalCount = _ref.totalCount,
40
68
  totalCount = _ref$totalCount === void 0 ? 0 : _ref$totalCount,
@@ -55,7 +83,8 @@ var FilterPopupSelect = exports.FilterPopupSelect = function FilterPopupSelect(_
55
83
  onSelectionChange = _ref.onSelectionChange,
56
84
  onInputChange = _ref.onInputChange,
57
85
  onMenuClose = _ref.onMenuClose,
58
- onMenuOpen = _ref.onMenuOpen;
86
+ onMenuOpen = _ref.onMenuOpen,
87
+ inlinePopupProps = _ref.inlinePopupProps;
59
88
  var _useIntl = (0, _reactIntl.useIntl)(),
60
89
  formatMessage = _useIntl.formatMessage;
61
90
  var _useDatasourceAnalyti = (0, _analytics.useDatasourceAnalyticsEvents)(),
@@ -171,7 +200,7 @@ var FilterPopupSelect = exports.FilterPopupSelect = function FilterPopupSelect(_
171
200
  sortPaginatedResults.current = true;
172
201
  }
173
202
  }, [status]);
174
- return /*#__PURE__*/_react.default.createElement(_popupSelect.PopupSelect, {
203
+ return /*#__PURE__*/_react.default.createElement(_popupSelect.PopupSelect, (0, _extends2.default)({}, inlinePopupProps, {
175
204
  isMulti: true,
176
205
  maxMenuWidth: 300,
177
206
  minMenuWidth: 300,
@@ -239,5 +268,5 @@ var FilterPopupSelect = exports.FilterPopupSelect = function FilterPopupSelect(_
239
268
  totalCount: totalCount,
240
269
  filterName: filterName
241
270
  })
242
- });
271
+ }));
243
272
  };
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useInlinePopupLayout = useInlinePopupLayout;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _react = require("react");
10
+ var VIEWPORT_PADDING = 8;
11
+ var TRIGGER_GAP = 8;
12
+ var MAX_MENU_HEIGHT = 300;
13
+ var MIN_PREFERRED_SPACE = 180;
14
+ // Reserve the footer and container padding until the open popup can be measured.
15
+ var INITIAL_EXTRA_HEIGHT = 72;
16
+ var INITIAL_CONTROL_HEIGHT = 48;
17
+ var viewportModifiers = [{
18
+ name: 'offset',
19
+ options: {
20
+ offset: [0, TRIGGER_GAP]
21
+ }
22
+ },
23
+ // Placement and height are calculated together; flipping independently can clip the search box.
24
+ {
25
+ name: 'flip',
26
+ enabled: false
27
+ }, {
28
+ name: 'preventOverflow',
29
+ enabled: true,
30
+ options: {
31
+ rootBoundary: 'viewport',
32
+ padding: VIEWPORT_PADDING,
33
+ altAxis: true,
34
+ tether: false
35
+ }
36
+ }];
37
+ function useInlinePopupLayout(isInline, popupRef) {
38
+ var _useState = (0, _react.useState)(false),
39
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
40
+ isOpen = _useState2[0],
41
+ setIsOpen = _useState2[1];
42
+ var _useState3 = (0, _react.useState)({
43
+ maxMenuHeight: MAX_MENU_HEIGHT,
44
+ placement: 'bottom-start'
45
+ }),
46
+ _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
47
+ layout = _useState4[0],
48
+ setLayout = _useState4[1];
49
+ var updateLayout = (0, _react.useCallback)(function () {
50
+ var _viewport$offsetTop, _viewport$height, _popup$selectRef$sele, _popup$selectRef;
51
+ var popup = popupRef.current;
52
+ var trigger = popup === null || popup === void 0 ? void 0 : popup.targetRef;
53
+ if (!isInline || !trigger) {
54
+ return;
55
+ }
56
+ var viewport = window.visualViewport;
57
+ var viewportTop = (_viewport$offsetTop = viewport === null || viewport === void 0 ? void 0 : viewport.offsetTop) !== null && _viewport$offsetTop !== void 0 ? _viewport$offsetTop : 0;
58
+ var viewportBottom = viewportTop + ((_viewport$height = viewport === null || viewport === void 0 ? void 0 : viewport.height) !== null && _viewport$height !== void 0 ? _viewport$height : window.innerHeight);
59
+ var rect = trigger.getBoundingClientRect();
60
+ var below = Math.max(0, viewportBottom - rect.bottom - TRIGGER_GAP - VIEWPORT_PADDING);
61
+ var above = Math.max(0, rect.top - viewportTop - TRIGGER_GAP - VIEWPORT_PADDING);
62
+ var placement = below >= MIN_PREFERRED_SPACE || below >= above ? 'bottom-start' : 'top-start';
63
+ var available = placement === 'bottom-start' ? below : above;
64
+ var menu = popup.menuRef;
65
+ var list = menu === null || menu === void 0 ? void 0 : menu.querySelector('[role="listbox"]');
66
+ var controlHeight = (_popup$selectRef$sele = (_popup$selectRef = popup.selectRef) === null || _popup$selectRef === void 0 || (_popup$selectRef = _popup$selectRef.select) === null || _popup$selectRef === void 0 || (_popup$selectRef = _popup$selectRef.controlRef) === null || _popup$selectRef === void 0 ? void 0 : _popup$selectRef.offsetHeight) !== null && _popup$selectRef$sele !== void 0 ? _popup$selectRef$sele : INITIAL_CONTROL_HEIGHT;
67
+ // PopupSelect already subtracts the search control from maxMenuHeight. Reserve the
68
+ // remaining chrome separately, including the pagination footer outside its scroll area.
69
+ var extraHeight = menu && list ? Math.max(0, menu.offsetHeight - list.offsetHeight - controlHeight) : INITIAL_EXTRA_HEIGHT;
70
+ var maxMenuHeight = Math.max(controlHeight, Math.min(MAX_MENU_HEIGHT, available - extraHeight));
71
+ setLayout(function (previous) {
72
+ return previous.placement === placement && previous.maxMenuHeight === maxMenuHeight ? previous : {
73
+ placement: placement,
74
+ maxMenuHeight: maxMenuHeight
75
+ };
76
+ });
77
+ }, [isInline, popupRef]);
78
+ (0, _react.useEffect)(function () {
79
+ var _popupRef$current;
80
+ if (!isInline || !isOpen) {
81
+ return;
82
+ }
83
+ updateLayout();
84
+ var viewport = window.visualViewport;
85
+ var observer = typeof ResizeObserver === 'undefined' ? undefined : new ResizeObserver(updateLayout);
86
+ var menu = (_popupRef$current = popupRef.current) === null || _popupRef$current === void 0 ? void 0 : _popupRef$current.menuRef;
87
+ if (menu) {
88
+ observer === null || observer === void 0 || observer.observe(menu);
89
+ }
90
+ window.addEventListener('resize', updateLayout);
91
+ window.addEventListener('scroll', updateLayout, true);
92
+ viewport === null || viewport === void 0 || viewport.addEventListener('resize', updateLayout);
93
+ viewport === null || viewport === void 0 || viewport.addEventListener('scroll', updateLayout);
94
+ return function () {
95
+ observer === null || observer === void 0 || observer.disconnect();
96
+ window.removeEventListener('resize', updateLayout);
97
+ window.removeEventListener('scroll', updateLayout, true);
98
+ viewport === null || viewport === void 0 || viewport.removeEventListener('resize', updateLayout);
99
+ viewport === null || viewport === void 0 || viewport.removeEventListener('scroll', updateLayout);
100
+ };
101
+ }, [isInline, isOpen, popupRef, updateLayout]);
102
+ var onOpen = (0, _react.useCallback)(function () {
103
+ if (isInline) {
104
+ updateLayout();
105
+ setIsOpen(true);
106
+ }
107
+ }, [isInline, updateLayout]);
108
+ var onClose = (0, _react.useCallback)(function () {
109
+ return setIsOpen(false);
110
+ }, []);
111
+ var popperProps = (0, _react.useMemo)(function () {
112
+ return {
113
+ placement: layout.placement,
114
+ modifiers: viewportModifiers
115
+ };
116
+ }, [layout.placement]);
117
+ return {
118
+ onOpen: onOpen,
119
+ onClose: onClose,
120
+ maxMenuHeight: isInline ? layout.maxMenuHeight : undefined,
121
+ popperProps: isInline ? popperProps : undefined
122
+ };
123
+ }
@@ -55,7 +55,10 @@ var DatasourceTableViewWithoutAnalytics = function DatasourceTableViewWithoutAna
55
55
  onWrappedColumnsChange = _ref.onWrappedColumnsChange,
56
56
  _ref$scrollableContai = _ref.scrollableContainerHeight,
57
57
  scrollableContainerHeight = _ref$scrollableContai === void 0 ? DefaultScrollableContainerHeight : _ref$scrollableContai,
58
- onRequestSettled = _ref.onRequestSettled;
58
+ onRequestSettled = _ref.onRequestSettled,
59
+ _ref$enableRequestSet = _ref.enableRequestSettled,
60
+ enableRequestSettled = _ref$enableRequestSet === void 0 ? false : _ref$enableRequestSet,
61
+ renderEmptyState = _ref.renderEmptyState;
59
62
  // Local copy lets us apply in-session sort mutations without mutating external parameters.
60
63
  var _useState = (0, _react.useState)(parameters),
61
64
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
@@ -150,7 +153,7 @@ var DatasourceTableViewWithoutAnalytics = function DatasourceTableViewWithoutAna
150
153
  // settled request is reported exactly once.
151
154
  var lastSettledResultRef = (0, _react.useRef)(null);
152
155
  (0, _react.useEffect)(function () {
153
- if (!(0, _fg.fg)('platform_lp_sllv_on_request_settled')) {
156
+ if (!(0, _fg.fg)('platform_lp_sllv_on_request_settled') && !enableRequestSettled) {
154
157
  return;
155
158
  }
156
159
  if (status !== 'resolved' && status !== 'rejected' && status !== 'unauthorized' && status !== 'forbidden') {
@@ -167,7 +170,7 @@ var DatasourceTableViewWithoutAnalytics = function DatasourceTableViewWithoutAna
167
170
  }
168
171
  lastSettledResultRef.current = result;
169
172
  onRequestSettled === null || onRequestSettled === void 0 || onRequestSettled(result);
170
- }, [status, responseItems.length, totalCount, onRequestSettled]);
173
+ }, [status, responseItems.length, totalCount, onRequestSettled, enableRequestSettled]);
171
174
  (0, _react.useEffect)(function () {
172
175
  var shouldStartUfoExperience = datasourceId && parameters && visibleColumnKeys && status === 'loading';
173
176
  if (shouldStartUfoExperience) {
@@ -215,6 +218,9 @@ var DatasourceTableViewWithoutAnalytics = function DatasourceTableViewWithoutAna
215
218
  });
216
219
  }, [reset]);
217
220
  var isResolvedWithNoResults = status === 'resolved' && !responseItems.length;
221
+ if (isResolvedWithNoResults && renderEmptyState) {
222
+ return renderEmptyState();
223
+ }
218
224
  // With columns available the table can keep its headers and footer and show the empty state
219
225
  // in place of the rows, instead of replacing the whole view with it.
220
226
  var shouldRenderTableWithNoResults = isResolvedWithNoResults && hasColumns;
@@ -26,7 +26,9 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
26
26
  _ref$onSelectionChang = _ref.onSelectionChange,
27
27
  onSelectionChange = _ref$onSelectionChang === void 0 ? function () {} : _ref$onSelectionChang,
28
28
  _ref$isDisabled = _ref.isDisabled,
29
- isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled;
29
+ isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled,
30
+ _ref$isInline = _ref.isInline,
31
+ isInline = _ref$isInline === void 0 ? false : _ref$isInline;
30
32
  var _useIntl = (0, _reactIntl.useIntl)(),
31
33
  formatMessage = _useIntl.formatMessage;
32
34
  var _useState = (0, _react.useState)(''),
@@ -118,6 +120,7 @@ var AsyncPopupSelect = function AsyncPopupSelect(_ref) {
118
120
  var shouldDisplayShowMoreButton = status === 'resolved' && !!pageCursor && !areAllResultsLoaded;
119
121
  var triggerButtonLabel = formatMessage(_messages.asyncPopupSelectMessages["".concat(filterType, "Label")]);
120
122
  return /*#__PURE__*/_react.default.createElement(_popupSelect.FilterPopupSelect, {
123
+ isInline: isInline,
121
124
  filterName: filterName,
122
125
  status: status,
123
126
  showLoading: isLoading,
@@ -23,7 +23,9 @@ var BasicFilterContainer = function BasicFilterContainer(_ref) {
23
23
  site = _ref.site,
24
24
  onChange = _ref.onChange,
25
25
  selections = _ref.selections,
26
- isJQLHydrating = _ref.isJQLHydrating;
26
+ isJQLHydrating = _ref.isJQLHydrating,
27
+ _ref$isInline = _ref.isInline,
28
+ isInline = _ref$isInline === void 0 ? false : _ref$isInline;
27
29
  var extractedFilterValues = (0, _react.useMemo)(function () {
28
30
  return isJQLHydrating ? (0, _extractValuesFromNonComplexJQL.extractValuesFromNonComplexJQL)(jql) : {};
29
31
  }, [isJQLHydrating, jql]);
@@ -32,11 +34,13 @@ var BasicFilterContainer = function BasicFilterContainer(_ref) {
32
34
  return /*#__PURE__*/_react.default.createElement(_flex.Flex, {
33
35
  xcss: styles.basicFilterContainerStyles,
34
36
  gap: "space.100",
37
+ wrap: isInline ? 'wrap' : 'nowrap',
35
38
  testId: "jlol-basic-filter-container"
36
39
  }, availableBasicFilterTypes.map(function (filter) {
37
40
  var _extractedFilterValue;
38
41
  var shouldShowHydrationLoader = isJQLHydrating && ((_extractedFilterValue = extractedFilterValues[filter]) === null || _extractedFilterValue === void 0 ? void 0 : _extractedFilterValue.length) > 0;
39
42
  return /*#__PURE__*/_react.default.createElement(_asyncPopupSelect.default, {
43
+ isInline: isInline,
40
44
  site: site,
41
45
  filterType: filter,
42
46
  key: filter,
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.JiraSearchContainer = void 0;
8
+ var _react = _interopRequireDefault(require("react"));
9
+ var _main = _interopRequireDefault(require("@atlaskit/intl-messages-provider/main"));
10
+ var _fetchMessagesForLocale = require("../../../common/utils/locale/fetch-messages-for-locale");
11
+ var _en = _interopRequireDefault(require("../../../i18n/en"));
12
+ var _index = require("./index");
13
+ /** Embedded consumers need the same translated search controls as the configuration modal. */
14
+ var JiraSearchContainer = exports.JiraSearchContainer = function JiraSearchContainer(props) {
15
+ return /*#__PURE__*/_react.default.createElement(_main.default, {
16
+ defaultMessages: _en.default,
17
+ loaderFn: _fetchMessagesForLocale.fetchMessagesForLocale
18
+ }, /*#__PURE__*/_react.default.createElement(_index.JiraSearchContainer, props));
19
+ };
@@ -19,6 +19,12 @@ var fuzzyCharacter = exports.fuzzyCharacter = '*';
19
19
  var constructTerminalClause = function constructTerminalClause(field, operator, value) {
20
20
  return _creators.default.terminalClause(_creators.default.field(field), _creators.default.operator(operator), _creators.default.valueOperand(value));
21
21
  };
22
+
23
+ // The generic AST string sanitizer quotes values but does not escape backslashes.
24
+ // Embedded keyword search accepts literal user text, so quote both delimiters explicitly.
25
+ var escapedValueOperand = function escapedValueOperand(value) {
26
+ return _creators.default.byText.valueOperand("\"".concat(value.replace(/\\/g, '\\\\').replace(/"/g, '\\"'), "\""));
27
+ };
22
28
  var buildJQL = exports.buildJQL = function buildJQL(input) {
23
29
  /**
24
30
  * Jql ast - Transforming the ast
@@ -27,6 +33,7 @@ var buildJQL = exports.buildJQL = function buildJQL(input) {
27
33
  var jast = new _jastBuilder.JastBuilder().build('');
28
34
  var query = jast.query;
29
35
  var rawSearch = input.rawSearch,
36
+ textSearchField = input.textSearchField,
30
37
  _input$orderDirection = input.orderDirection,
31
38
  orderDirection = _input$orderDirection === void 0 ? _orderBy.ORDER_BY_DIRECTION_DESC : _input$orderDirection,
32
39
  _input$orderKey = input.orderKey,
@@ -47,7 +54,10 @@ var buildJQL = exports.buildJQL = function buildJQL(input) {
47
54
  if (!query) {
48
55
  return '';
49
56
  }
50
- if (trimmedRawSearch) {
57
+ if (trimmedRawSearch && textSearchField === 'textfields') {
58
+ var suffix = /["*?]$/.test(trimmedRawSearch) ? '' : fuzzyCharacter;
59
+ query.appendClause(_creators.default.terminalClause(_creators.default.field('textfields'), _creators.default.operator(_operator.OPERATOR_LIKE), escapedValueOperand("".concat(trimmedRawSearch).concat(suffix))), _compound.COMPOUND_OPERATOR_AND);
60
+ } else if (trimmedRawSearch) {
51
61
  var fuzzy = !trimmedRawSearch.match(fuzzySearchRegExp) ? fuzzyCharacter : '';
52
62
  var basicSearch = trimmedRawSearch.replace(/['"?*]+/g, '');
53
63
  var text = constructTerminalClause('text', _operator.OPERATOR_LIKE, "".concat(basicSearch).concat(fuzzy));
@@ -69,7 +79,7 @@ var buildJQL = exports.buildJQL = function buildJQL(input) {
69
79
  return;
70
80
  }
71
81
  var filterInClause = _creators.default.terminalClause(_creators.default.field(key), _creators.default.operator(_operator.OPERATOR_IN), _creators.default.listOperand(filterFieldValues.map(function (filterFieldValue) {
72
- return _creators.default.valueOperand(filterFieldValue.value);
82
+ return textSearchField ? escapedValueOperand(filterFieldValue.value) : _creators.default.valueOperand(filterFieldValue.value);
73
83
  })));
74
84
  query.appendClause(filterInClause, _compound.COMPOUND_OPERATOR_AND);
75
85
  });
@@ -0,0 +1,11 @@
1
+ ._16jlkb7n{flex-grow:1}
2
+ ._19pk1b66{margin-top:var(--ds-space-050,4px)}
3
+ ._1bsb1osq{width:100%}
4
+ ._1e0c1txw{display:flex}
5
+ ._1n261g80{flex-wrap:wrap}
6
+ ._1o9zidpf{flex-shrink:0}
7
+ ._1p57u2gc{row-gap:var(--ds-space-100,8px)}
8
+ ._1tket9kd{min-height:72px}
9
+ ._1ul9idpf{min-width:0}
10
+ ._4cvr1y6m{align-items:flex-start}
11
+ ._i0dlghg7{flex-basis:240px}