@qualtrics/plugin-ui-react 1.3.0-alpha.0 → 1.3.3

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
@@ -13,7 +13,11 @@
13
13
  * ~~Allow for field-row dropdowns to accept 'searchable' prop allowing for the dropdown to be input searched.~~
14
14
  * Fixed Chinese language codes to work with the latest version of `@qualtrics/ui-i18n`.
15
15
 
16
+ ## 1.3.2
17
+ * Added capability for the TaskFields/FieldRow component to handle submenus in the fields.
18
+ * Added capability to disable the popover functionality of the `Add a field` button, replaced the popover functionality with functionality to automatically add a field from the list of available fields.
16
19
  ## 1.3.0
20
+ * fix traditional and simplified chinese codes to work with the latest version of ui-i18n
17
21
  * Typescript@4.x
18
22
  * [8f3c89c8](https://gitlab-app.eng.qops.net/integrations/qualtrics-plugin-ui-react/-/commit/8f3c89c8) fix issue where lodash hits maximum callstack and throws a cross-origin error sometimes
19
23
  * [ee1cc9f6](https://gitlab-app.eng.qops.net/integrations/qualtrics-plugin-ui-react/-/commit/ee1cc9f6) Merge branch 'bump-1.2.4' into 'master'
@@ -1 +1 @@
1
- export function Popover(props: any, ref: any): JSX.Element;
1
+ export function Popover(props: any): JSX.Element;
package/dist/main.es.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! @license @qualtrics/plugin-ui-react 1.3.0-alpha.0
1
+ /*! @license @qualtrics/plugin-ui-react 1.3.3
2
2
  Qualtrics Software License Agreement
3
3
 
4
4
  1. General.
@@ -55,17 +55,17 @@ import 'core-js/modules/es.array.find-index.js';
55
55
  import 'core-js/modules/es.array.splice.js';
56
56
  import 'core-js/modules/es.array.for-each.js';
57
57
  import 'core-js/modules/web.dom-collections.for-each.js';
58
- import React, { Component, useState, useEffect, useRef } from 'react';
58
+ import React, { Component, useState, useEffect, useRef, useCallback } from 'react';
59
59
  import _get from 'lodash.get';
60
60
  import { Button, InputGroup, Input, Icon, IconTypes, LoadingSpinner, IconButton, Tooltip, SelectMenu, MenuItem, Label } from '@qualtrics/ui-react';
61
61
  import { ErrorIcon, PipedTextIcon, RemoveItemIcon } from '@qualtrics/ui-react/icons';
62
62
  import 'core-js/modules/es.string.anchor.js';
63
- import _cloneDeep from 'lodash.clonedeep';
64
63
  import 'core-js/modules/es.string.trim.js';
65
64
  import 'core-js/modules/es.array.map.js';
66
65
  import 'core-js/modules/es.array.concat.js';
67
66
  import 'core-js/modules/es.array.filter.js';
68
67
  import 'regenerator-runtime/runtime.js';
68
+ import _cloneDeep from 'lodash.clonedeep';
69
69
  import 'core-js/modules/es.array.is-array.js';
70
70
  import { Manager, Reference, Popper } from 'react-popper';
71
71
  import ReactDOM from 'react-dom';
@@ -116,14 +116,9 @@ function ownKeys(object, enumerableOnly) {
116
116
 
117
117
  if (Object.getOwnPropertySymbols) {
118
118
  var symbols = Object.getOwnPropertySymbols(object);
119
-
120
- if (enumerableOnly) {
121
- symbols = symbols.filter(function (sym) {
122
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
123
- });
124
- }
125
-
126
- keys.push.apply(keys, symbols);
119
+ enumerableOnly && (symbols = symbols.filter(function (sym) {
120
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
121
+ })), keys.push.apply(keys, symbols);
127
122
  }
128
123
 
129
124
  return keys;
@@ -131,19 +126,12 @@ function ownKeys(object, enumerableOnly) {
131
126
 
132
127
  function _objectSpread2(target) {
133
128
  for (var i = 1; i < arguments.length; i++) {
134
- var source = arguments[i] != null ? arguments[i] : {};
135
-
136
- if (i % 2) {
137
- ownKeys(Object(source), true).forEach(function (key) {
138
- _defineProperty(target, key, source[key]);
139
- });
140
- } else if (Object.getOwnPropertyDescriptors) {
141
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
142
- } else {
143
- ownKeys(Object(source)).forEach(function (key) {
144
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
145
- });
146
- }
129
+ var source = null != arguments[i] ? arguments[i] : {};
130
+ i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
131
+ _defineProperty(target, key, source[key]);
132
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
133
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
134
+ });
147
135
  }
148
136
 
149
137
  return target;
@@ -152,17 +140,11 @@ function _objectSpread2(target) {
152
140
  function _typeof(obj) {
153
141
  "@babel/helpers - typeof";
154
142
 
155
- if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
156
- _typeof = function (obj) {
157
- return typeof obj;
158
- };
159
- } else {
160
- _typeof = function (obj) {
161
- return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
162
- };
163
- }
164
-
165
- return _typeof(obj);
143
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
144
+ return typeof obj;
145
+ } : function (obj) {
146
+ return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
147
+ }, _typeof(obj);
166
148
  }
167
149
 
168
150
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
@@ -220,6 +202,9 @@ function _defineProperties(target, props) {
220
202
  function _createClass(Constructor, protoProps, staticProps) {
221
203
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
222
204
  if (staticProps) _defineProperties(Constructor, staticProps);
205
+ Object.defineProperty(Constructor, "prototype", {
206
+ writable: false
207
+ });
223
208
  return Constructor;
224
209
  }
225
210
 
@@ -250,6 +235,9 @@ function _inherits(subClass, superClass) {
250
235
  configurable: true
251
236
  }
252
237
  });
238
+ Object.defineProperty(subClass, "prototype", {
239
+ writable: false
240
+ });
253
241
  if (superClass) _setPrototypeOf(subClass, superClass);
254
242
  }
255
243
 
@@ -681,7 +669,7 @@ var DEFAULT_PLACEMENT = 'bottom-start';
681
669
  var DEFAULT_ANCHOR = React.createElement(Button, null, " anchor ");
682
670
  var defaultModifiers = [];
683
671
  initGlobalListener();
684
- function Popover(props, ref) {
672
+ function Popover(props) {
685
673
  var _useState = useState(false),
686
674
  _useState2 = _slicedToArray(_useState, 2),
687
675
  isOpen = _useState2[0],
@@ -878,7 +866,7 @@ var css_248z$8 = "div[role=\"menu\"] .piped-text-search-input-container {\n pad
878
866
  styleInject(css_248z$8);
879
867
 
880
868
  var EMBEDDED_DATA_LOCATOR = 'embeddedData';
881
- var PipedTextMenu = React.forwardRef(function (props, ref) {
869
+ var PipedTextMenu = React.forwardRef(function PipedTextMenu(props, ref) {
882
870
  var defaultMenuItems = undefined;
883
871
 
884
872
  if (typeof props.items !== 'function') {
@@ -907,8 +895,47 @@ var PipedTextMenu = React.forwardRef(function (props, ref) {
907
895
  searchValue = _useState8[0],
908
896
  setSearchValue = _useState8[1];
909
897
 
910
- var onClose = props.onClose || function () {};
898
+ var _useState9 = useState(undefined),
899
+ _useState10 = _slicedToArray(_useState9, 2),
900
+ isSubmenu = _useState10[0],
901
+ setIsSubmenu = _useState10[1];
902
+
903
+ var onClose = props.onClose || function () {
904
+ return undefined;
905
+ };
906
+
907
+ var _useState11 = useState(null),
908
+ _useState12 = _slicedToArray(_useState11, 2),
909
+ popoverEl = _useState12[0],
910
+ setPopoverEl = _useState12[1];
911
+
912
+ var popoverRefCb = useCallback(function (el) {
913
+ setPopoverEl(el);
914
+ }, []);
915
+
916
+ var _useState13 = useState(null),
917
+ _useState14 = _slicedToArray(_useState13, 2),
918
+ searchBoxEl = _useState14[0],
919
+ setSearchBoxEl = _useState14[1];
911
920
 
921
+ var searchBoxRefCb = useCallback(function (el) {
922
+ setSearchBoxEl(el);
923
+ }, []);
924
+ useEffect(function () {
925
+ var anchorRefEl = _get(props, 'anchorRef.current');
926
+
927
+ if (anchorRefEl) {
928
+ var anchorRefElRole = anchorRefEl.getAttribute('role');
929
+ var nextIsSubmenu = anchorRefElRole === 'menuitem';
930
+ setIsSubmenu(nextIsSubmenu);
931
+ }
932
+
933
+ if (isSubmenu === true) ; else if (isSubmenu === false) {
934
+ if (popoverEl !== null) {
935
+ popoverEl.focus();
936
+ }
937
+ }
938
+ }, [popoverEl, searchBoxEl, props.anchorRef, isSubmenu]);
912
939
  useEffect(function () {
913
940
  _asyncToGenerator(regeneratorRuntime.mark(function _callee() {
914
941
  var newMenuItems;
@@ -1003,6 +1030,10 @@ var PipedTextMenu = React.forwardRef(function (props, ref) {
1003
1030
  setSearchValue(searchVal);
1004
1031
  };
1005
1032
 
1033
+ var handleSearchInputClick = function handleSearchInputClick(evt) {
1034
+ evt.stopPropagation();
1035
+ };
1036
+
1006
1037
  var matchesSearch = function matchesSearch(item) {
1007
1038
  var searchVal = searchValue || '';
1008
1039
  searchVal = searchVal.trim().toLowerCase();
@@ -1032,11 +1063,12 @@ var PipedTextMenu = React.forwardRef(function (props, ref) {
1032
1063
  props.onSelected(edMenuItem);
1033
1064
  };
1034
1065
 
1035
- var getSubmenuItem = function getSubmenuItem(menuItem) {
1066
+ var SubmenuItem = function SubmenuItem(props) {
1067
+ var submenuAnchorRef = useRef(null);
1068
+ var menuItem = props.menuItem;
1036
1069
  return React.createElement("div", {
1037
1070
  "data-testid": "piped-text-submenu",
1038
- className: "piped-text-submenu-item-container",
1039
- key: menuItem.key
1071
+ className: "piped-text-submenu-item-container"
1040
1072
  }, menuItem.show && React.createElement(PipedTextMenu, {
1041
1073
  items: menuItem.submenu.items,
1042
1074
  show: menuItem.show,
@@ -1055,12 +1087,16 @@ var PipedTextMenu = React.forwardRef(function (props, ref) {
1055
1087
  ref: ref,
1056
1088
  className: "piped-text-submenu-anchor"
1057
1089
  });
1058
- }
1090
+ },
1091
+ anchorRef: submenuAnchorRef
1059
1092
  }), React.createElement("div", {
1060
1093
  className: "piped-text-submenu-item",
1094
+ "aria-haspopup": "menu",
1095
+ role: "menuitem",
1061
1096
  onMouseEnter: function onMouseEnter($e) {
1062
1097
  return submenuHovered(menuItem);
1063
- }
1098
+ },
1099
+ ref: submenuAnchorRef
1064
1100
  }, React.createElement("div", {
1065
1101
  className: "label-text"
1066
1102
  }, menuItem.label), React.createElement("div", {
@@ -1082,7 +1118,10 @@ var PipedTextMenu = React.forwardRef(function (props, ref) {
1082
1118
  var menuItemHeaderClass, menuItemDisabledClass, menuItemClassName;
1083
1119
 
1084
1120
  if (menuItem.hasSubmenu) {
1085
- return getSubmenuItem(menuItem);
1121
+ return React.createElement(SubmenuItem, {
1122
+ key: menuItem.key,
1123
+ menuItem: menuItem
1124
+ });
1086
1125
  } else if (menuItem.header === true || menuItem.disabled === true) {
1087
1126
  menuItemHeaderClass = menuItem.header === true ? 'piped-text-header' : '';
1088
1127
  menuItemDisabledClass = menuItem.disabled === true ? 'piped-text-disabled' : '';
@@ -1180,7 +1219,7 @@ var PipedTextMenu = React.forwardRef(function (props, ref) {
1180
1219
  } else {
1181
1220
  var itemsToRender = (menuItems || []).filter(matchesSearch);
1182
1221
  return React.createElement("div", {
1183
- className: "piped-text-popover-container"
1222
+ className: "piped-text-popover-menu"
1184
1223
  }, React.createElement("div", {
1185
1224
  className: "piped-text-search-input"
1186
1225
  }, React.createElement("form", {
@@ -1193,7 +1232,11 @@ var PipedTextMenu = React.forwardRef(function (props, ref) {
1193
1232
  value: searchValue,
1194
1233
  onChange: function onChange($e) {
1195
1234
  return onSearchInputChange($e);
1196
- }
1235
+ },
1236
+ onClick: function onClick($e) {
1237
+ return handleSearchInputClick($e);
1238
+ },
1239
+ ref: searchBoxRefCb
1197
1240
  }))), menuItems === undefined ? getLoadingSpinner() : getPipedTextMenuItems(itemsToRender));
1198
1241
  }
1199
1242
  };
@@ -1207,10 +1250,23 @@ var PipedTextMenu = React.forwardRef(function (props, ref) {
1207
1250
  anchor: props.anchor,
1208
1251
  ignoreClickSelector: props.ignoreClickSelector
1209
1252
  }, React.createElement("div", {
1210
- className: "piped-text-popover-container"
1253
+ className: "piped-text-popover-container",
1254
+ ref: popoverRefCb,
1255
+ onFocus: function onFocus($e) {
1256
+ return handleFocus($e);
1257
+ },
1258
+ tabIndex: props.tabIndex !== undefined ? props.tabIndex : -1
1211
1259
  }, getMenuContent()), React.createElement(OptionsPlaceholder, {
1212
1260
  optionsRef: optionsRef
1213
1261
  })));
1262
+
1263
+ function handleFocus(evt) {
1264
+ if (!isSubmenu && searchBoxEl !== null) {
1265
+ searchBoxEl.focus();
1266
+ }
1267
+
1268
+ evt.stopPropagation();
1269
+ }
1214
1270
  });
1215
1271
 
1216
1272
  function OptionsPlaceholder() {
@@ -1271,23 +1327,8 @@ function PipedTextSelect(props) {
1271
1327
  pipedTextItems = _useState4[0],
1272
1328
  setPipedTextItems = _useState4[1];
1273
1329
 
1274
- function initializePipedText() {
1275
- if (props.items) {
1276
- return pipedTextDataAdapter(props.items);
1277
- }
1278
- }
1279
-
1280
- var onClose = function onClose() {
1281
- if (props.onClose) {
1282
- props.onClose();
1283
- }
1284
- };
1285
-
1286
- var onSelect = function onSelect(selected) {
1287
- props.onSelect(selected);
1288
- onClose();
1289
- };
1290
-
1330
+ var defaultAnchorRef = useRef(null);
1331
+ var externalAnchor = props.anchor;
1291
1332
  useEffect(function () {
1292
1333
  return function () {
1293
1334
  return onClose();
@@ -1302,6 +1343,22 @@ function PipedTextSelect(props) {
1302
1343
  var formattedPipedText = initializePipedText();
1303
1344
  setPipedTextItems(formattedPipedText);
1304
1345
  }, [props.items]);
1346
+
1347
+ var onClose = function onClose() {
1348
+ if (props.onClose) {
1349
+ props.onClose();
1350
+ }
1351
+ };
1352
+
1353
+ var onSelect = function onSelect(selected) {
1354
+ props.onSelect(selected);
1355
+ onClose();
1356
+ };
1357
+
1358
+ var actualAnchor = externalAnchor !== undefined ? React.cloneElement(externalAnchor, {
1359
+ ref: externalAnchor.ref
1360
+ }) : defaultAnchor(defaultAnchorRef);
1361
+ var anchorRef = props.anchorRef || actualAnchor.ref;
1305
1362
  return React.createElement("div", {
1306
1363
  className: "piped-text-dropdown"
1307
1364
  }, isMenuOpen && React.createElement(PipedTextMenu, {
@@ -1309,9 +1366,16 @@ function PipedTextSelect(props) {
1309
1366
  show: isMenuOpen,
1310
1367
  onSelected: onSelect,
1311
1368
  items: pipedTextItems,
1312
- anchor: props.anchor || defaultAnchor,
1369
+ anchor: actualAnchor,
1370
+ anchorRef: anchorRef,
1313
1371
  ignoreClickSelector: props.ignoreClickSelector
1314
1372
  }));
1373
+
1374
+ function initializePipedText() {
1375
+ if (props.items) {
1376
+ return pipedTextDataAdapter(props.items);
1377
+ }
1378
+ }
1315
1379
  }
1316
1380
 
1317
1381
  var css_248z$6 = ".piped-text-input .piped-text-input-toggle, .piped-text-input .piped-text-select-container {\n display: inline-block; }\n\n.piped-text-input .piped-text-input-toggle {\n display: flex; }\n .piped-text-input .piped-text-input-toggle input {\n flex: 1 1;\n box-sizing: border-box; }\n .piped-text-input .piped-text-input-toggle input:first-child {\n border-right: 0;\n border-top-right-radius: 0;\n border-bottom-right-radius: 0; }\n .piped-text-input .piped-text-input-toggle.multiline-input textarea {\n flex: 1 1;\n box-sizing: border-box; }\n .piped-text-input .piped-text-input-toggle input + button, .piped-text-input .piped-text-input-toggle textarea + button {\n margin-left: 4px; }\n\n.piped-text-input .addon-text-container {\n /*\n These styles are intended to match CFE QDS components,\n notably FormField and InputField.\n See: https://gitlab-app.eng.qops.net/cfe/ui/-/blob/master/packages/ui-react/src/FormField/Caption.less\n */\n margin-top: 6px; }\n .piped-text-input .addon-text-container .helper-text, .piped-text-input .addon-text-container .error-text {\n font-size: 12px; }\n .piped-text-input .addon-text-container .helper-text {\n color: #74777a;\n fill: #74777a; }\n .piped-text-input .addon-text-container .helper-text + .error-text {\n margin-top: 4px; }\n .piped-text-input .addon-text-container .error-text {\n display: flex;\n align-items: center;\n color: #b00;\n fill: #b00; }\n .piped-text-input .addon-text-container .error-text .error-text-icon svg {\n margin-left: -2px;\n margin-right: 3px;\n width: 16px;\n height: 16px; }\n";
@@ -1320,6 +1384,7 @@ styleInject(css_248z$6);
1320
1384
  function PipedTextInput(props) {
1321
1385
  var _a = useState(false), showMenu = _a[0], setShowMenu = _a[1];
1322
1386
  var _b = useState(), cursorPosition = _b[0], setCursorPosition = _b[1];
1387
+ var pipedTextButtonRef = useRef(null);
1323
1388
  /*
1324
1389
  This has to be an Object type ref instead of 'string' or React will lose
1325
1390
  track of state, and the supplied props input value will become stale
@@ -1354,10 +1419,10 @@ function PipedTextInput(props) {
1354
1419
  React.createElement(Input, __assign({ value: inputRefValue.value, onChange: function (evt) {
1355
1420
  onInputChange(evt);
1356
1421
  }, onBlur: onInputBlur, placeholder: placeholder, multiline: multiline }, restProps)),
1357
- React.createElement(IconButton, { "aria-label": "PipedText", size: "medium", onClick: toggleMenu },
1422
+ React.createElement(IconButton, { "aria-label": "PipedText", "aria-haspopup": "menu", "aria-expanded": showMenu ? true : undefined, role: "button", onClick: toggleMenu, ref: pipedTextButtonRef },
1358
1423
  React.createElement(PipedTextIcon, null)),
1359
1424
  React.createElement("div", { className: "piped-text-select-container" },
1360
- React.createElement(PipedTextSelect, { items: items, onSelect: pipedTextSelected, show: showMenu, onClose: handleClose, ignoreClickSelector: "piped-text-input-toggle" }))),
1425
+ React.createElement(PipedTextSelect, { items: items, onSelect: pipedTextSelected, show: showMenu, onClose: handleClose, ignoreClickSelector: "piped-text-input-toggle", anchorRef: pipedTextButtonRef }))),
1361
1426
  showAddonText() && (React.createElement("div", { className: "addon-text-container" },
1362
1427
  helperText && (React.createElement("div", { className: "helper-text" }, helperText)),
1363
1428
  errorText && (React.createElement("div", { className: "error-text" },
@@ -1389,7 +1454,7 @@ function PipedTextInput(props) {
1389
1454
  if (_get(selected, 'value.locator')) {
1390
1455
  prependString = inputRefValue.value.substring(0, cursorPosition);
1391
1456
  appendString = inputRefValue.value.substring(cursorPosition);
1392
- nextInputValue = "" + prependString + selected.value.locator + appendString;
1457
+ nextInputValue = "".concat(prependString).concat(selected.value.locator).concat(appendString);
1393
1458
  setInputRefValue({
1394
1459
  value: nextInputValue,
1395
1460
  });
@@ -1512,13 +1577,28 @@ function FieldRow(props) {
1512
1577
  }
1513
1578
 
1514
1579
  if (props.required || !props.children || Array.isArray(children) && children.length === 0) {
1515
- return React.createElement("div", {
1516
- className: "required-indicator-container"
1517
- }, React.createElement("div", {
1518
- className: "required-indicator-text"
1519
- }, props.fieldName), props.required && React.createElement("div", {
1520
- className: "required-indicator-symbol"
1521
- }, "*"));
1580
+ if (props.subMenu) {
1581
+ return React.createElement(SelectMenu, {
1582
+ searchable: props.searchable !== undefined && props.searchable !== false,
1583
+ defaultLabel: props.fieldName || '',
1584
+ label: props.fieldName,
1585
+ className: "full-width left-align",
1586
+ onChange: handleFieldSwitch
1587
+ }, createMenuItems([{
1588
+ id: props.id,
1589
+ name: props.fieldName,
1590
+ subMenu: props.subMenu,
1591
+ subMenuLabel: props.subMenuLabel
1592
+ }]));
1593
+ } else {
1594
+ return React.createElement("div", {
1595
+ className: "required-indicator-container"
1596
+ }, React.createElement("div", {
1597
+ className: "required-indicator-text"
1598
+ }, props.fieldName), props.required && React.createElement("div", {
1599
+ className: "required-indicator-symbol"
1600
+ }, "*"));
1601
+ }
1522
1602
  }
1523
1603
 
1524
1604
  return React.createElement(SelectMenu, {
@@ -1527,12 +1607,7 @@ function FieldRow(props) {
1527
1607
  label: props.fieldName,
1528
1608
  className: "full-width left-align",
1529
1609
  onChange: handleFieldSwitch
1530
- }, children.map(function (field) {
1531
- return React.createElement(MenuItem, {
1532
- value: field.id,
1533
- key: field.id
1534
- }, field.name);
1535
- }));
1610
+ }, createMenuItems(children));
1536
1611
  };
1537
1612
 
1538
1613
  var tooltipContent = React.createElement("div", null, props.nameTooltip);
@@ -1543,6 +1618,22 @@ function FieldRow(props) {
1543
1618
  }, React.createElement("div", null, getInternalContent()));
1544
1619
  };
1545
1620
 
1621
+ var createMenuItems = function createMenuItems(items) {
1622
+ return items.map(function (_ref) {
1623
+ var id = _ref.id,
1624
+ name = _ref.name,
1625
+ subMenu = _ref.subMenu,
1626
+ subMenuLabel = _ref.subMenuLabel;
1627
+ return subMenu !== undefined ? React.createElement(SelectMenu, {
1628
+ label: subMenuLabel ? subMenuLabel : name,
1629
+ key: id
1630
+ }, createMenuItems(subMenu)) : React.createElement(MenuItem, {
1631
+ key: id,
1632
+ value: id
1633
+ }, name);
1634
+ });
1635
+ };
1636
+
1546
1637
  var getFieldInput = function getFieldInput() {
1547
1638
  var getInternalContent = function getInternalContent() {
1548
1639
  if (props.customInput) {
@@ -1568,7 +1659,7 @@ function FieldRow(props) {
1568
1659
  return React.createElement("div", {
1569
1660
  className: "field-row"
1570
1661
  }, React.createElement("div", {
1571
- className: "field-selector ".concat(props.required ? 'required-field' : '')
1662
+ className: "field-selector ".concat(props.required && !props.subMenu ? 'required-field' : '')
1572
1663
  }, getFieldSelector()), React.createElement("div", {
1573
1664
  className: "field-input-container"
1574
1665
  }, React.createElement("div", {
@@ -1644,6 +1735,8 @@ function TaskFields(props) {
1644
1735
  required: field.required,
1645
1736
  fieldName: field.name,
1646
1737
  id: field.id,
1738
+ subMenu: field.subMenu,
1739
+ subMenuLabel: field.subMenuLabel,
1647
1740
  nameTooltip: field.type === CUSTOM_TYPE ? _get(props, 'customFieldOptions.nameTooltip', '') : field.nameTooltip,
1648
1741
  valueTooltip: field.type === CUSTOM_TYPE ? _get(props, 'customFieldOptions.valueTooltip', '') : field.valueTooltip,
1649
1742
  onFieldNameChange: onFieldNameChange,
@@ -1657,8 +1750,24 @@ function TaskFields(props) {
1657
1750
  customNamePlaceholder: _get(props, 'customFieldOptions.namePlaceholder', ''),
1658
1751
  pipedTextItems: props.pipedTextItems,
1659
1752
  searchable: props.searchable
1660
- }, allFieldOptions && availableFields);
1753
+ }, allFieldOptions && getFieldsForFieldRow(availableFields, allFieldOptions, field.id));
1754
+ });
1755
+ };
1756
+
1757
+ var getFieldsForFieldRow = function getFieldsForFieldRow(allAvailableFields, allFields, fieldId) {
1758
+ var fieldsToAdd = allAvailableFields.slice();
1759
+ allFields.forEach(function (field) {
1760
+ if (field.subMenu !== undefined && fieldId === field.id) {
1761
+ var foundIndex = fieldsToAdd.findIndex(function (fieldToAdd) {
1762
+ return fieldToAdd.id === field.id;
1763
+ });
1764
+
1765
+ if (foundIndex === -1) {
1766
+ fieldsToAdd.push(field);
1767
+ }
1768
+ }
1661
1769
  });
1770
+ return fieldsToAdd;
1662
1771
  };
1663
1772
 
1664
1773
  var onFieldAdd = function onFieldAdd(fieldId) {
@@ -1680,7 +1789,9 @@ function TaskFields(props) {
1680
1789
  type: field.type,
1681
1790
  required: field.required,
1682
1791
  key: field.id,
1683
- id: field.id
1792
+ id: field.id,
1793
+ subMenu: field.subMenu,
1794
+ subMenuLabel: field.subMenuLabel
1684
1795
  });
1685
1796
  });
1686
1797
  };
@@ -1733,7 +1844,9 @@ function TaskFields(props) {
1733
1844
  children: foundNextChild.props.children,
1734
1845
  nameTooltip: foundNextChild.props.nameTooltip,
1735
1846
  valueTooltip: foundNextChild.props.valueTooltip,
1736
- valuePlaceholder: foundNextChild.props.valuePlaceholder
1847
+ valuePlaceholder: foundNextChild.props.valuePlaceholder,
1848
+ subMenu: foundNextChild.props.subMenu,
1849
+ subMenuLabel: foundNextChild.props.subMenuLabel
1737
1850
  });
1738
1851
  }
1739
1852
 
@@ -1754,7 +1867,9 @@ function TaskFields(props) {
1754
1867
  nameTooltip: field.props.nameTooltip,
1755
1868
  valueTooltip: field.props.valueTooltip,
1756
1869
  value: field.props.value || undefined,
1757
- valuePlaceholder: field.props.valuePlaceholder
1870
+ valuePlaceholder: field.props.valuePlaceholder,
1871
+ subMenu: field.props.subMenu,
1872
+ subMenuLabel: field.props.subMenuLabel
1758
1873
  });
1759
1874
  }
1760
1875
  });
@@ -1780,7 +1895,9 @@ function TaskFields(props) {
1780
1895
  nameTooltip: _get(props, 'customFieldOptions.nameTooltip', ''),
1781
1896
  valueTooltip: _get(props, 'customFieldOptions.valueTooltip', ''),
1782
1897
  namePlaceholder: _get(props, 'customFieldOptions.namePlaceholder', ''),
1783
- type: CUSTOM_TYPE
1898
+ type: CUSTOM_TYPE,
1899
+ subMenu: currentField.subMenu,
1900
+ subMenuLabel: currentField.subMenuLabel
1784
1901
  };
1785
1902
  nextFieldsInUse.push(customFieldValue);
1786
1903
  }
@@ -1818,7 +1935,9 @@ function TaskFields(props) {
1818
1935
  children: childProps.children,
1819
1936
  nameTooltip: childProps.nameTooltip,
1820
1937
  valueTooltip: childProps.valueTooltip,
1821
- valuePlaceholder: childProps.valuePlaceholder
1938
+ valuePlaceholder: childProps.valuePlaceholder,
1939
+ subMenu: childProps.subMenu,
1940
+ subMenuLabel: childProps.subMenuLabel
1822
1941
  };
1823
1942
  });
1824
1943
  var nextFieldsInUse = getFieldsInUse(nextAllFieldOptions);
@@ -1853,6 +1972,7 @@ function TaskFields(props) {
1853
1972
  }, React.createElement(AddFieldButton, {
1854
1973
  label: props.addFieldLabel,
1855
1974
  onFieldAdded: onFieldAdd,
1975
+ disableAddFieldPopover: props.disableAddFieldPopover,
1856
1976
  allowCustom: props.customFieldOptions,
1857
1977
  customLabel: _get(props, 'customFieldOptions.label', ''),
1858
1978
  onCustomFieldAdded: props.customFieldOptions ? onCustomFieldAdd : function () {}
@@ -1862,6 +1982,7 @@ function TaskFields(props) {
1862
1982
  function AddFieldButton(props) {
1863
1983
  var label = props.label || '';
1864
1984
  var customLabel = props.customLabel || '';
1985
+ var disableAddFieldPopover = props.disableAddFieldPopover;
1865
1986
 
1866
1987
  var _useState7 = useState(false),
1867
1988
  _useState8 = _slicedToArray(_useState7, 2),
@@ -1883,15 +2004,30 @@ function AddFieldButton(props) {
1883
2004
  setPopoverShow(false);
1884
2005
  };
1885
2006
 
2007
+ var children = [];
2008
+
1886
2009
  var onPopoverAnchorClick = function onPopoverAnchorClick() {
1887
- setPopoverShow(!popoverShow);
2010
+ if (!disableAddFieldPopover) {
2011
+ setPopoverShow(!popoverShow);
2012
+ } else {
2013
+ props.onFieldAdded(props.children !== 0 ? getFieldIdWhenPopoverIsClicked(props.children[0].props) : '');
2014
+ }
2015
+ };
2016
+
2017
+ var getFieldIdWhenPopoverIsClicked = function getFieldIdWhenPopoverIsClicked(field) {
2018
+ if (field.subMenu) {
2019
+ return getFieldIdWhenPopoverIsClicked(field.subMenu[0]);
2020
+ } else {
2021
+ return field.id;
2022
+ }
1888
2023
  };
1889
2024
 
1890
- var children = props.children.map(function (child) {
2025
+ children = props.children.map(function (child) {
1891
2026
  return React.createElement(FieldItem, {
1892
2027
  name: child.props.name,
1893
2028
  key: child.props.id,
1894
2029
  id: child.props.id,
2030
+ subMenu: child.props.subMenu,
1895
2031
  onClick: function onClick(fieldId) {
1896
2032
  setPopoverShow(false);
1897
2033
  props.onFieldAdded(fieldId);
package/dist/main.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! @license @qualtrics/plugin-ui-react 1.3.0-alpha.0
1
+ /*! @license @qualtrics/plugin-ui-react 1.3.3
2
2
  Qualtrics Software License Agreement
3
3
 
4
4
  1. General.
@@ -64,12 +64,12 @@ var _get = require('lodash.get');
64
64
  var uiReact = require('@qualtrics/ui-react');
65
65
  var icons = require('@qualtrics/ui-react/icons');
66
66
  require('core-js/modules/es.string.anchor.js');
67
- var _cloneDeep = require('lodash.clonedeep');
68
67
  require('core-js/modules/es.string.trim.js');
69
68
  require('core-js/modules/es.array.map.js');
70
69
  require('core-js/modules/es.array.concat.js');
71
70
  require('core-js/modules/es.array.filter.js');
72
71
  require('regenerator-runtime/runtime.js');
72
+ var _cloneDeep = require('lodash.clonedeep');
73
73
  require('core-js/modules/es.array.is-array.js');
74
74
  var reactPopper = require('react-popper');
75
75
  var ReactDOM = require('react-dom');
@@ -129,14 +129,9 @@ function ownKeys(object, enumerableOnly) {
129
129
 
130
130
  if (Object.getOwnPropertySymbols) {
131
131
  var symbols = Object.getOwnPropertySymbols(object);
132
-
133
- if (enumerableOnly) {
134
- symbols = symbols.filter(function (sym) {
135
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
136
- });
137
- }
138
-
139
- keys.push.apply(keys, symbols);
132
+ enumerableOnly && (symbols = symbols.filter(function (sym) {
133
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
134
+ })), keys.push.apply(keys, symbols);
140
135
  }
141
136
 
142
137
  return keys;
@@ -144,19 +139,12 @@ function ownKeys(object, enumerableOnly) {
144
139
 
145
140
  function _objectSpread2(target) {
146
141
  for (var i = 1; i < arguments.length; i++) {
147
- var source = arguments[i] != null ? arguments[i] : {};
148
-
149
- if (i % 2) {
150
- ownKeys(Object(source), true).forEach(function (key) {
151
- _defineProperty(target, key, source[key]);
152
- });
153
- } else if (Object.getOwnPropertyDescriptors) {
154
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
155
- } else {
156
- ownKeys(Object(source)).forEach(function (key) {
157
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
158
- });
159
- }
142
+ var source = null != arguments[i] ? arguments[i] : {};
143
+ i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
144
+ _defineProperty(target, key, source[key]);
145
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
146
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
147
+ });
160
148
  }
161
149
 
162
150
  return target;
@@ -165,17 +153,11 @@ function _objectSpread2(target) {
165
153
  function _typeof(obj) {
166
154
  "@babel/helpers - typeof";
167
155
 
168
- if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
169
- _typeof = function (obj) {
170
- return typeof obj;
171
- };
172
- } else {
173
- _typeof = function (obj) {
174
- return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
175
- };
176
- }
177
-
178
- return _typeof(obj);
156
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
157
+ return typeof obj;
158
+ } : function (obj) {
159
+ return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
160
+ }, _typeof(obj);
179
161
  }
180
162
 
181
163
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
@@ -233,6 +215,9 @@ function _defineProperties(target, props) {
233
215
  function _createClass(Constructor, protoProps, staticProps) {
234
216
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
235
217
  if (staticProps) _defineProperties(Constructor, staticProps);
218
+ Object.defineProperty(Constructor, "prototype", {
219
+ writable: false
220
+ });
236
221
  return Constructor;
237
222
  }
238
223
 
@@ -263,6 +248,9 @@ function _inherits(subClass, superClass) {
263
248
  configurable: true
264
249
  }
265
250
  });
251
+ Object.defineProperty(subClass, "prototype", {
252
+ writable: false
253
+ });
266
254
  if (superClass) _setPrototypeOf(subClass, superClass);
267
255
  }
268
256
 
@@ -694,7 +682,7 @@ var DEFAULT_PLACEMENT = 'bottom-start';
694
682
  var DEFAULT_ANCHOR = React__default["default"].createElement(uiReact.Button, null, " anchor ");
695
683
  var defaultModifiers = [];
696
684
  initGlobalListener();
697
- function Popover(props, ref) {
685
+ function Popover(props) {
698
686
  var _useState = React.useState(false),
699
687
  _useState2 = _slicedToArray(_useState, 2),
700
688
  isOpen = _useState2[0],
@@ -891,7 +879,7 @@ var css_248z$8 = "div[role=\"menu\"] .piped-text-search-input-container {\n pad
891
879
  styleInject(css_248z$8);
892
880
 
893
881
  var EMBEDDED_DATA_LOCATOR = 'embeddedData';
894
- var PipedTextMenu = React__default["default"].forwardRef(function (props, ref) {
882
+ var PipedTextMenu = React__default["default"].forwardRef(function PipedTextMenu(props, ref) {
895
883
  var defaultMenuItems = undefined;
896
884
 
897
885
  if (typeof props.items !== 'function') {
@@ -920,8 +908,47 @@ var PipedTextMenu = React__default["default"].forwardRef(function (props, ref) {
920
908
  searchValue = _useState8[0],
921
909
  setSearchValue = _useState8[1];
922
910
 
923
- var onClose = props.onClose || function () {};
911
+ var _useState9 = React.useState(undefined),
912
+ _useState10 = _slicedToArray(_useState9, 2),
913
+ isSubmenu = _useState10[0],
914
+ setIsSubmenu = _useState10[1];
915
+
916
+ var onClose = props.onClose || function () {
917
+ return undefined;
918
+ };
919
+
920
+ var _useState11 = React.useState(null),
921
+ _useState12 = _slicedToArray(_useState11, 2),
922
+ popoverEl = _useState12[0],
923
+ setPopoverEl = _useState12[1];
924
+
925
+ var popoverRefCb = React.useCallback(function (el) {
926
+ setPopoverEl(el);
927
+ }, []);
928
+
929
+ var _useState13 = React.useState(null),
930
+ _useState14 = _slicedToArray(_useState13, 2),
931
+ searchBoxEl = _useState14[0],
932
+ setSearchBoxEl = _useState14[1];
924
933
 
934
+ var searchBoxRefCb = React.useCallback(function (el) {
935
+ setSearchBoxEl(el);
936
+ }, []);
937
+ React.useEffect(function () {
938
+ var anchorRefEl = _get__default["default"](props, 'anchorRef.current');
939
+
940
+ if (anchorRefEl) {
941
+ var anchorRefElRole = anchorRefEl.getAttribute('role');
942
+ var nextIsSubmenu = anchorRefElRole === 'menuitem';
943
+ setIsSubmenu(nextIsSubmenu);
944
+ }
945
+
946
+ if (isSubmenu === true) ; else if (isSubmenu === false) {
947
+ if (popoverEl !== null) {
948
+ popoverEl.focus();
949
+ }
950
+ }
951
+ }, [popoverEl, searchBoxEl, props.anchorRef, isSubmenu]);
925
952
  React.useEffect(function () {
926
953
  _asyncToGenerator(regeneratorRuntime.mark(function _callee() {
927
954
  var newMenuItems;
@@ -1016,6 +1043,10 @@ var PipedTextMenu = React__default["default"].forwardRef(function (props, ref) {
1016
1043
  setSearchValue(searchVal);
1017
1044
  };
1018
1045
 
1046
+ var handleSearchInputClick = function handleSearchInputClick(evt) {
1047
+ evt.stopPropagation();
1048
+ };
1049
+
1019
1050
  var matchesSearch = function matchesSearch(item) {
1020
1051
  var searchVal = searchValue || '';
1021
1052
  searchVal = searchVal.trim().toLowerCase();
@@ -1045,11 +1076,12 @@ var PipedTextMenu = React__default["default"].forwardRef(function (props, ref) {
1045
1076
  props.onSelected(edMenuItem);
1046
1077
  };
1047
1078
 
1048
- var getSubmenuItem = function getSubmenuItem(menuItem) {
1079
+ var SubmenuItem = function SubmenuItem(props) {
1080
+ var submenuAnchorRef = React.useRef(null);
1081
+ var menuItem = props.menuItem;
1049
1082
  return React__default["default"].createElement("div", {
1050
1083
  "data-testid": "piped-text-submenu",
1051
- className: "piped-text-submenu-item-container",
1052
- key: menuItem.key
1084
+ className: "piped-text-submenu-item-container"
1053
1085
  }, menuItem.show && React__default["default"].createElement(PipedTextMenu, {
1054
1086
  items: menuItem.submenu.items,
1055
1087
  show: menuItem.show,
@@ -1068,12 +1100,16 @@ var PipedTextMenu = React__default["default"].forwardRef(function (props, ref) {
1068
1100
  ref: ref,
1069
1101
  className: "piped-text-submenu-anchor"
1070
1102
  });
1071
- }
1103
+ },
1104
+ anchorRef: submenuAnchorRef
1072
1105
  }), React__default["default"].createElement("div", {
1073
1106
  className: "piped-text-submenu-item",
1107
+ "aria-haspopup": "menu",
1108
+ role: "menuitem",
1074
1109
  onMouseEnter: function onMouseEnter($e) {
1075
1110
  return submenuHovered(menuItem);
1076
- }
1111
+ },
1112
+ ref: submenuAnchorRef
1077
1113
  }, React__default["default"].createElement("div", {
1078
1114
  className: "label-text"
1079
1115
  }, menuItem.label), React__default["default"].createElement("div", {
@@ -1095,7 +1131,10 @@ var PipedTextMenu = React__default["default"].forwardRef(function (props, ref) {
1095
1131
  var menuItemHeaderClass, menuItemDisabledClass, menuItemClassName;
1096
1132
 
1097
1133
  if (menuItem.hasSubmenu) {
1098
- return getSubmenuItem(menuItem);
1134
+ return React__default["default"].createElement(SubmenuItem, {
1135
+ key: menuItem.key,
1136
+ menuItem: menuItem
1137
+ });
1099
1138
  } else if (menuItem.header === true || menuItem.disabled === true) {
1100
1139
  menuItemHeaderClass = menuItem.header === true ? 'piped-text-header' : '';
1101
1140
  menuItemDisabledClass = menuItem.disabled === true ? 'piped-text-disabled' : '';
@@ -1193,7 +1232,7 @@ var PipedTextMenu = React__default["default"].forwardRef(function (props, ref) {
1193
1232
  } else {
1194
1233
  var itemsToRender = (menuItems || []).filter(matchesSearch);
1195
1234
  return React__default["default"].createElement("div", {
1196
- className: "piped-text-popover-container"
1235
+ className: "piped-text-popover-menu"
1197
1236
  }, React__default["default"].createElement("div", {
1198
1237
  className: "piped-text-search-input"
1199
1238
  }, React__default["default"].createElement("form", {
@@ -1206,7 +1245,11 @@ var PipedTextMenu = React__default["default"].forwardRef(function (props, ref) {
1206
1245
  value: searchValue,
1207
1246
  onChange: function onChange($e) {
1208
1247
  return onSearchInputChange($e);
1209
- }
1248
+ },
1249
+ onClick: function onClick($e) {
1250
+ return handleSearchInputClick($e);
1251
+ },
1252
+ ref: searchBoxRefCb
1210
1253
  }))), menuItems === undefined ? getLoadingSpinner() : getPipedTextMenuItems(itemsToRender));
1211
1254
  }
1212
1255
  };
@@ -1220,10 +1263,23 @@ var PipedTextMenu = React__default["default"].forwardRef(function (props, ref) {
1220
1263
  anchor: props.anchor,
1221
1264
  ignoreClickSelector: props.ignoreClickSelector
1222
1265
  }, React__default["default"].createElement("div", {
1223
- className: "piped-text-popover-container"
1266
+ className: "piped-text-popover-container",
1267
+ ref: popoverRefCb,
1268
+ onFocus: function onFocus($e) {
1269
+ return handleFocus($e);
1270
+ },
1271
+ tabIndex: props.tabIndex !== undefined ? props.tabIndex : -1
1224
1272
  }, getMenuContent()), React__default["default"].createElement(OptionsPlaceholder, {
1225
1273
  optionsRef: optionsRef
1226
1274
  })));
1275
+
1276
+ function handleFocus(evt) {
1277
+ if (!isSubmenu && searchBoxEl !== null) {
1278
+ searchBoxEl.focus();
1279
+ }
1280
+
1281
+ evt.stopPropagation();
1282
+ }
1227
1283
  });
1228
1284
 
1229
1285
  function OptionsPlaceholder() {
@@ -1284,23 +1340,8 @@ function PipedTextSelect(props) {
1284
1340
  pipedTextItems = _useState4[0],
1285
1341
  setPipedTextItems = _useState4[1];
1286
1342
 
1287
- function initializePipedText() {
1288
- if (props.items) {
1289
- return pipedTextDataAdapter(props.items);
1290
- }
1291
- }
1292
-
1293
- var onClose = function onClose() {
1294
- if (props.onClose) {
1295
- props.onClose();
1296
- }
1297
- };
1298
-
1299
- var onSelect = function onSelect(selected) {
1300
- props.onSelect(selected);
1301
- onClose();
1302
- };
1303
-
1343
+ var defaultAnchorRef = React.useRef(null);
1344
+ var externalAnchor = props.anchor;
1304
1345
  React.useEffect(function () {
1305
1346
  return function () {
1306
1347
  return onClose();
@@ -1315,6 +1356,22 @@ function PipedTextSelect(props) {
1315
1356
  var formattedPipedText = initializePipedText();
1316
1357
  setPipedTextItems(formattedPipedText);
1317
1358
  }, [props.items]);
1359
+
1360
+ var onClose = function onClose() {
1361
+ if (props.onClose) {
1362
+ props.onClose();
1363
+ }
1364
+ };
1365
+
1366
+ var onSelect = function onSelect(selected) {
1367
+ props.onSelect(selected);
1368
+ onClose();
1369
+ };
1370
+
1371
+ var actualAnchor = externalAnchor !== undefined ? React__default["default"].cloneElement(externalAnchor, {
1372
+ ref: externalAnchor.ref
1373
+ }) : defaultAnchor(defaultAnchorRef);
1374
+ var anchorRef = props.anchorRef || actualAnchor.ref;
1318
1375
  return React__default["default"].createElement("div", {
1319
1376
  className: "piped-text-dropdown"
1320
1377
  }, isMenuOpen && React__default["default"].createElement(PipedTextMenu, {
@@ -1322,9 +1379,16 @@ function PipedTextSelect(props) {
1322
1379
  show: isMenuOpen,
1323
1380
  onSelected: onSelect,
1324
1381
  items: pipedTextItems,
1325
- anchor: props.anchor || defaultAnchor,
1382
+ anchor: actualAnchor,
1383
+ anchorRef: anchorRef,
1326
1384
  ignoreClickSelector: props.ignoreClickSelector
1327
1385
  }));
1386
+
1387
+ function initializePipedText() {
1388
+ if (props.items) {
1389
+ return pipedTextDataAdapter(props.items);
1390
+ }
1391
+ }
1328
1392
  }
1329
1393
 
1330
1394
  var css_248z$6 = ".piped-text-input .piped-text-input-toggle, .piped-text-input .piped-text-select-container {\n display: inline-block; }\n\n.piped-text-input .piped-text-input-toggle {\n display: flex; }\n .piped-text-input .piped-text-input-toggle input {\n flex: 1 1;\n box-sizing: border-box; }\n .piped-text-input .piped-text-input-toggle input:first-child {\n border-right: 0;\n border-top-right-radius: 0;\n border-bottom-right-radius: 0; }\n .piped-text-input .piped-text-input-toggle.multiline-input textarea {\n flex: 1 1;\n box-sizing: border-box; }\n .piped-text-input .piped-text-input-toggle input + button, .piped-text-input .piped-text-input-toggle textarea + button {\n margin-left: 4px; }\n\n.piped-text-input .addon-text-container {\n /*\n These styles are intended to match CFE QDS components,\n notably FormField and InputField.\n See: https://gitlab-app.eng.qops.net/cfe/ui/-/blob/master/packages/ui-react/src/FormField/Caption.less\n */\n margin-top: 6px; }\n .piped-text-input .addon-text-container .helper-text, .piped-text-input .addon-text-container .error-text {\n font-size: 12px; }\n .piped-text-input .addon-text-container .helper-text {\n color: #74777a;\n fill: #74777a; }\n .piped-text-input .addon-text-container .helper-text + .error-text {\n margin-top: 4px; }\n .piped-text-input .addon-text-container .error-text {\n display: flex;\n align-items: center;\n color: #b00;\n fill: #b00; }\n .piped-text-input .addon-text-container .error-text .error-text-icon svg {\n margin-left: -2px;\n margin-right: 3px;\n width: 16px;\n height: 16px; }\n";
@@ -1333,6 +1397,7 @@ styleInject(css_248z$6);
1333
1397
  function PipedTextInput(props) {
1334
1398
  var _a = React.useState(false), showMenu = _a[0], setShowMenu = _a[1];
1335
1399
  var _b = React.useState(), cursorPosition = _b[0], setCursorPosition = _b[1];
1400
+ var pipedTextButtonRef = React.useRef(null);
1336
1401
  /*
1337
1402
  This has to be an Object type ref instead of 'string' or React will lose
1338
1403
  track of state, and the supplied props input value will become stale
@@ -1367,10 +1432,10 @@ function PipedTextInput(props) {
1367
1432
  React__default["default"].createElement(uiReact.Input, __assign({ value: inputRefValue.value, onChange: function (evt) {
1368
1433
  onInputChange(evt);
1369
1434
  }, onBlur: onInputBlur, placeholder: placeholder, multiline: multiline }, restProps)),
1370
- React__default["default"].createElement(uiReact.IconButton, { "aria-label": "PipedText", size: "medium", onClick: toggleMenu },
1435
+ React__default["default"].createElement(uiReact.IconButton, { "aria-label": "PipedText", "aria-haspopup": "menu", "aria-expanded": showMenu ? true : undefined, role: "button", onClick: toggleMenu, ref: pipedTextButtonRef },
1371
1436
  React__default["default"].createElement(icons.PipedTextIcon, null)),
1372
1437
  React__default["default"].createElement("div", { className: "piped-text-select-container" },
1373
- React__default["default"].createElement(PipedTextSelect, { items: items, onSelect: pipedTextSelected, show: showMenu, onClose: handleClose, ignoreClickSelector: "piped-text-input-toggle" }))),
1438
+ React__default["default"].createElement(PipedTextSelect, { items: items, onSelect: pipedTextSelected, show: showMenu, onClose: handleClose, ignoreClickSelector: "piped-text-input-toggle", anchorRef: pipedTextButtonRef }))),
1374
1439
  showAddonText() && (React__default["default"].createElement("div", { className: "addon-text-container" },
1375
1440
  helperText && (React__default["default"].createElement("div", { className: "helper-text" }, helperText)),
1376
1441
  errorText && (React__default["default"].createElement("div", { className: "error-text" },
@@ -1402,7 +1467,7 @@ function PipedTextInput(props) {
1402
1467
  if (_get__default["default"](selected, 'value.locator')) {
1403
1468
  prependString = inputRefValue.value.substring(0, cursorPosition);
1404
1469
  appendString = inputRefValue.value.substring(cursorPosition);
1405
- nextInputValue = "" + prependString + selected.value.locator + appendString;
1470
+ nextInputValue = "".concat(prependString).concat(selected.value.locator).concat(appendString);
1406
1471
  setInputRefValue({
1407
1472
  value: nextInputValue,
1408
1473
  });
@@ -1525,13 +1590,28 @@ function FieldRow(props) {
1525
1590
  }
1526
1591
 
1527
1592
  if (props.required || !props.children || Array.isArray(children) && children.length === 0) {
1528
- return React__default["default"].createElement("div", {
1529
- className: "required-indicator-container"
1530
- }, React__default["default"].createElement("div", {
1531
- className: "required-indicator-text"
1532
- }, props.fieldName), props.required && React__default["default"].createElement("div", {
1533
- className: "required-indicator-symbol"
1534
- }, "*"));
1593
+ if (props.subMenu) {
1594
+ return React__default["default"].createElement(uiReact.SelectMenu, {
1595
+ searchable: props.searchable !== undefined && props.searchable !== false,
1596
+ defaultLabel: props.fieldName || '',
1597
+ label: props.fieldName,
1598
+ className: "full-width left-align",
1599
+ onChange: handleFieldSwitch
1600
+ }, createMenuItems([{
1601
+ id: props.id,
1602
+ name: props.fieldName,
1603
+ subMenu: props.subMenu,
1604
+ subMenuLabel: props.subMenuLabel
1605
+ }]));
1606
+ } else {
1607
+ return React__default["default"].createElement("div", {
1608
+ className: "required-indicator-container"
1609
+ }, React__default["default"].createElement("div", {
1610
+ className: "required-indicator-text"
1611
+ }, props.fieldName), props.required && React__default["default"].createElement("div", {
1612
+ className: "required-indicator-symbol"
1613
+ }, "*"));
1614
+ }
1535
1615
  }
1536
1616
 
1537
1617
  return React__default["default"].createElement(uiReact.SelectMenu, {
@@ -1540,12 +1620,7 @@ function FieldRow(props) {
1540
1620
  label: props.fieldName,
1541
1621
  className: "full-width left-align",
1542
1622
  onChange: handleFieldSwitch
1543
- }, children.map(function (field) {
1544
- return React__default["default"].createElement(uiReact.MenuItem, {
1545
- value: field.id,
1546
- key: field.id
1547
- }, field.name);
1548
- }));
1623
+ }, createMenuItems(children));
1549
1624
  };
1550
1625
 
1551
1626
  var tooltipContent = React__default["default"].createElement("div", null, props.nameTooltip);
@@ -1556,6 +1631,22 @@ function FieldRow(props) {
1556
1631
  }, React__default["default"].createElement("div", null, getInternalContent()));
1557
1632
  };
1558
1633
 
1634
+ var createMenuItems = function createMenuItems(items) {
1635
+ return items.map(function (_ref) {
1636
+ var id = _ref.id,
1637
+ name = _ref.name,
1638
+ subMenu = _ref.subMenu,
1639
+ subMenuLabel = _ref.subMenuLabel;
1640
+ return subMenu !== undefined ? React__default["default"].createElement(uiReact.SelectMenu, {
1641
+ label: subMenuLabel ? subMenuLabel : name,
1642
+ key: id
1643
+ }, createMenuItems(subMenu)) : React__default["default"].createElement(uiReact.MenuItem, {
1644
+ key: id,
1645
+ value: id
1646
+ }, name);
1647
+ });
1648
+ };
1649
+
1559
1650
  var getFieldInput = function getFieldInput() {
1560
1651
  var getInternalContent = function getInternalContent() {
1561
1652
  if (props.customInput) {
@@ -1581,7 +1672,7 @@ function FieldRow(props) {
1581
1672
  return React__default["default"].createElement("div", {
1582
1673
  className: "field-row"
1583
1674
  }, React__default["default"].createElement("div", {
1584
- className: "field-selector ".concat(props.required ? 'required-field' : '')
1675
+ className: "field-selector ".concat(props.required && !props.subMenu ? 'required-field' : '')
1585
1676
  }, getFieldSelector()), React__default["default"].createElement("div", {
1586
1677
  className: "field-input-container"
1587
1678
  }, React__default["default"].createElement("div", {
@@ -1657,6 +1748,8 @@ function TaskFields(props) {
1657
1748
  required: field.required,
1658
1749
  fieldName: field.name,
1659
1750
  id: field.id,
1751
+ subMenu: field.subMenu,
1752
+ subMenuLabel: field.subMenuLabel,
1660
1753
  nameTooltip: field.type === CUSTOM_TYPE ? _get__default["default"](props, 'customFieldOptions.nameTooltip', '') : field.nameTooltip,
1661
1754
  valueTooltip: field.type === CUSTOM_TYPE ? _get__default["default"](props, 'customFieldOptions.valueTooltip', '') : field.valueTooltip,
1662
1755
  onFieldNameChange: onFieldNameChange,
@@ -1670,8 +1763,24 @@ function TaskFields(props) {
1670
1763
  customNamePlaceholder: _get__default["default"](props, 'customFieldOptions.namePlaceholder', ''),
1671
1764
  pipedTextItems: props.pipedTextItems,
1672
1765
  searchable: props.searchable
1673
- }, allFieldOptions && availableFields);
1766
+ }, allFieldOptions && getFieldsForFieldRow(availableFields, allFieldOptions, field.id));
1767
+ });
1768
+ };
1769
+
1770
+ var getFieldsForFieldRow = function getFieldsForFieldRow(allAvailableFields, allFields, fieldId) {
1771
+ var fieldsToAdd = allAvailableFields.slice();
1772
+ allFields.forEach(function (field) {
1773
+ if (field.subMenu !== undefined && fieldId === field.id) {
1774
+ var foundIndex = fieldsToAdd.findIndex(function (fieldToAdd) {
1775
+ return fieldToAdd.id === field.id;
1776
+ });
1777
+
1778
+ if (foundIndex === -1) {
1779
+ fieldsToAdd.push(field);
1780
+ }
1781
+ }
1674
1782
  });
1783
+ return fieldsToAdd;
1675
1784
  };
1676
1785
 
1677
1786
  var onFieldAdd = function onFieldAdd(fieldId) {
@@ -1693,7 +1802,9 @@ function TaskFields(props) {
1693
1802
  type: field.type,
1694
1803
  required: field.required,
1695
1804
  key: field.id,
1696
- id: field.id
1805
+ id: field.id,
1806
+ subMenu: field.subMenu,
1807
+ subMenuLabel: field.subMenuLabel
1697
1808
  });
1698
1809
  });
1699
1810
  };
@@ -1746,7 +1857,9 @@ function TaskFields(props) {
1746
1857
  children: foundNextChild.props.children,
1747
1858
  nameTooltip: foundNextChild.props.nameTooltip,
1748
1859
  valueTooltip: foundNextChild.props.valueTooltip,
1749
- valuePlaceholder: foundNextChild.props.valuePlaceholder
1860
+ valuePlaceholder: foundNextChild.props.valuePlaceholder,
1861
+ subMenu: foundNextChild.props.subMenu,
1862
+ subMenuLabel: foundNextChild.props.subMenuLabel
1750
1863
  });
1751
1864
  }
1752
1865
 
@@ -1767,7 +1880,9 @@ function TaskFields(props) {
1767
1880
  nameTooltip: field.props.nameTooltip,
1768
1881
  valueTooltip: field.props.valueTooltip,
1769
1882
  value: field.props.value || undefined,
1770
- valuePlaceholder: field.props.valuePlaceholder
1883
+ valuePlaceholder: field.props.valuePlaceholder,
1884
+ subMenu: field.props.subMenu,
1885
+ subMenuLabel: field.props.subMenuLabel
1771
1886
  });
1772
1887
  }
1773
1888
  });
@@ -1793,7 +1908,9 @@ function TaskFields(props) {
1793
1908
  nameTooltip: _get__default["default"](props, 'customFieldOptions.nameTooltip', ''),
1794
1909
  valueTooltip: _get__default["default"](props, 'customFieldOptions.valueTooltip', ''),
1795
1910
  namePlaceholder: _get__default["default"](props, 'customFieldOptions.namePlaceholder', ''),
1796
- type: CUSTOM_TYPE
1911
+ type: CUSTOM_TYPE,
1912
+ subMenu: currentField.subMenu,
1913
+ subMenuLabel: currentField.subMenuLabel
1797
1914
  };
1798
1915
  nextFieldsInUse.push(customFieldValue);
1799
1916
  }
@@ -1831,7 +1948,9 @@ function TaskFields(props) {
1831
1948
  children: childProps.children,
1832
1949
  nameTooltip: childProps.nameTooltip,
1833
1950
  valueTooltip: childProps.valueTooltip,
1834
- valuePlaceholder: childProps.valuePlaceholder
1951
+ valuePlaceholder: childProps.valuePlaceholder,
1952
+ subMenu: childProps.subMenu,
1953
+ subMenuLabel: childProps.subMenuLabel
1835
1954
  };
1836
1955
  });
1837
1956
  var nextFieldsInUse = getFieldsInUse(nextAllFieldOptions);
@@ -1866,6 +1985,7 @@ function TaskFields(props) {
1866
1985
  }, React__default["default"].createElement(AddFieldButton, {
1867
1986
  label: props.addFieldLabel,
1868
1987
  onFieldAdded: onFieldAdd,
1988
+ disableAddFieldPopover: props.disableAddFieldPopover,
1869
1989
  allowCustom: props.customFieldOptions,
1870
1990
  customLabel: _get__default["default"](props, 'customFieldOptions.label', ''),
1871
1991
  onCustomFieldAdded: props.customFieldOptions ? onCustomFieldAdd : function () {}
@@ -1875,6 +1995,7 @@ function TaskFields(props) {
1875
1995
  function AddFieldButton(props) {
1876
1996
  var label = props.label || '';
1877
1997
  var customLabel = props.customLabel || '';
1998
+ var disableAddFieldPopover = props.disableAddFieldPopover;
1878
1999
 
1879
2000
  var _useState7 = React.useState(false),
1880
2001
  _useState8 = _slicedToArray(_useState7, 2),
@@ -1896,15 +2017,30 @@ function AddFieldButton(props) {
1896
2017
  setPopoverShow(false);
1897
2018
  };
1898
2019
 
2020
+ var children = [];
2021
+
1899
2022
  var onPopoverAnchorClick = function onPopoverAnchorClick() {
1900
- setPopoverShow(!popoverShow);
2023
+ if (!disableAddFieldPopover) {
2024
+ setPopoverShow(!popoverShow);
2025
+ } else {
2026
+ props.onFieldAdded(props.children !== 0 ? getFieldIdWhenPopoverIsClicked(props.children[0].props) : '');
2027
+ }
2028
+ };
2029
+
2030
+ var getFieldIdWhenPopoverIsClicked = function getFieldIdWhenPopoverIsClicked(field) {
2031
+ if (field.subMenu) {
2032
+ return getFieldIdWhenPopoverIsClicked(field.subMenu[0]);
2033
+ } else {
2034
+ return field.id;
2035
+ }
1901
2036
  };
1902
2037
 
1903
- var children = props.children.map(function (child) {
2038
+ children = props.children.map(function (child) {
1904
2039
  return React__default["default"].createElement(FieldItem, {
1905
2040
  name: child.props.name,
1906
2041
  key: child.props.id,
1907
2042
  id: child.props.id,
2043
+ subMenu: child.props.subMenu,
1908
2044
  onClick: function onClick(fieldId) {
1909
2045
  setPopoverShow(false);
1910
2046
  props.onFieldAdded(fieldId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qualtrics/plugin-ui-react",
3
- "version": "1.3.0-alpha.0",
3
+ "version": "1.3.3",
4
4
  "description": "",
5
5
  "main": "dist/main.js",
6
6
  "module": "dist/main.es.js",
@@ -52,12 +52,12 @@
52
52
  "jest": "^26.6.3",
53
53
  "jest-css-modules": "^2.1.0",
54
54
  "jest-junit": "^12.0.0",
55
- "node-sass": "^5.0.0",
55
+ "node-sass": "^6.0.1",
56
56
  "postcss-preset-env": "^6.7.0",
57
57
  "postcss-reporter": "^7.0.1",
58
58
  "react": "^16.8.0",
59
59
  "react-dom": "^16.8.0",
60
- "react-test-renderer": "^17.0.1",
60
+ "react-test-renderer": "^16.14.0",
61
61
  "rimraf": "^3.0.2",
62
62
  "rollup": "^2.52.2",
63
63
  "rollup-plugin-babel": "^4.3.3",
@@ -75,10 +75,10 @@
75
75
  "typescript": "^4.3.4"
76
76
  },
77
77
  "peerDependencies": {
78
- "react": "^16.8.0",
79
- "react-dom": "^16.8.0",
80
78
  "@qualtrics/base-styles": "^0.2.1",
81
- "@qualtrics/ui-react": "^1.60.0"
79
+ "@qualtrics/ui-react": "^1.60.0",
80
+ "react": "^16.8.0",
81
+ "react-dom": "^16.8.0"
82
82
  },
83
83
  "dependencies": {
84
84
  "@popperjs/core": "^2.5.4",
@@ -1,91 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <testsuites name="jest tests" tests="36" failures="0" errors="0" time="36.055">
3
- <testsuite name="FieldItem" errors="0" failures="0" skipped="0" timestamp="2021-06-29T23:21:26" time="10.95" tests="2">
4
- <testcase classname="FieldItem renders properly" name="FieldItem renders properly" time="0.019">
5
- </testcase>
6
- <testcase classname="FieldItem invokes onClick handler with expected arguments when clicked" name="FieldItem invokes onClick handler with expected arguments when clicked" time="0.046">
7
- </testcase>
8
- </testsuite>
9
- <testsuite name="SelectItem" errors="0" failures="0" skipped="0" timestamp="2021-06-29T23:21:26" time="13.889" tests="1">
10
- <testcase classname="SelectItem fires the onChange handler with expected args" name="SelectItem fires the onChange handler with expected args" time="0.048">
11
- </testcase>
12
- </testsuite>
13
- <testsuite name="DynamicSearchInput" errors="0" failures="0" skipped="0" timestamp="2021-06-29T23:21:26" time="15.874" tests="1">
14
- <testcase classname="DynamicSearchInput renders correctly" name="DynamicSearchInput renders correctly" time="0.002">
15
- </testcase>
16
- </testsuite>
17
- <testsuite name="FieldRow" errors="0" failures="0" skipped="0" timestamp="2021-06-29T23:21:26" time="16.197" tests="1">
18
- <testcase classname="FieldRow fires the onFieldNameChange handler when field name is changed" name="FieldRow fires the onFieldNameChange handler when field name is changed" time="0.063">
19
- </testcase>
20
- </testsuite>
21
- <testsuite name="MultiselectDropdown" errors="0" failures="0" skipped="0" timestamp="2021-06-29T23:21:26" time="17.095" tests="3">
22
- <testcase classname="MultiselectDropdown toggles dropdown when button is clicked" name="MultiselectDropdown toggles dropdown when button is clicked" time="0.276">
23
- </testcase>
24
- <testcase classname="MultiselectDropdown calls onChange handler when item is clicked" name="MultiselectDropdown calls onChange handler when item is clicked" time="0.705">
25
- </testcase>
26
- <testcase classname="MultiselectDropdown closes menu on click away" name="MultiselectDropdown closes menu on click away" time="0.109">
27
- </testcase>
28
- </testsuite>
29
- <testsuite name="PipedTextInput" errors="0" failures="0" skipped="0" timestamp="2021-06-29T23:21:26" time="17.619" tests="6">
30
- <testcase classname="PipedTextInput toggles menu open/closed on click" name="PipedTextInput toggles menu open/closed on click" time="0.372">
31
- </testcase>
32
- <testcase classname="PipedTextInput fires onChange handler when input value changes from selecting piped text" name="PipedTextInput fires onChange handler when input value changes from selecting piped text" time="0.09">
33
- </testcase>
34
- <testcase classname="PipedTextInput fires onChange handler when input value changes from user typing in input box" name="PipedTextInput fires onChange handler when input value changes from user typing in input box" time="0.008">
35
- </testcase>
36
- <testcase classname="PipedTextInput fires onSelect handler when piped text is selected" name="PipedTextInput fires onSelect handler when piped text is selected" time="0.077">
37
- </testcase>
38
- <testcase classname="PipedTextInput fires onClose handler when menu is closed" name="PipedTextInput fires onClose handler when menu is closed" time="0.074">
39
- </testcase>
40
- <testcase classname="PipedTextInput inserts piped text at the position of the cursor in the input box when piped text is selected" name="PipedTextInput inserts piped text at the position of the cursor in the input box when piped text is selected" time="0.111">
41
- </testcase>
42
- </testsuite>
43
- <testsuite name="TaskFields" errors="0" failures="0" skipped="0" timestamp="2021-06-29T23:21:26" time="18.071" tests="4">
44
- <testcase classname="TaskFields only renders custom fields if custom field configuration options provided" name="TaskFields only renders custom fields if custom field configuration options provided" time="1.013">
45
- </testcase>
46
- <testcase classname="TaskFields fires onFieldNameChange handler when a custom field&apos;s name is changed" name="TaskFields fires onFieldNameChange handler when a custom field&apos;s name is changed" time="0.033">
47
- </testcase>
48
- <testcase classname="TaskFields fires onFieldAdd handler when a field is added" name="TaskFields fires onFieldAdd handler when a field is added" time="0.053">
49
- </testcase>
50
- <testcase classname="TaskFields fires onCustomFieldAdd handler when a custom field is added" name="TaskFields fires onCustomFieldAdd handler when a custom field is added" time="0.058">
51
- </testcase>
52
- </testsuite>
53
- <testsuite name="PipedTextSelect" errors="0" failures="0" skipped="0" timestamp="2021-06-29T23:21:26" time="26.879" tests="18">
54
- <testcase classname="PipedTextSelect filters menu items to items containing the search value as text" name="PipedTextSelect filters menu items to items containing the search value as text" time="1.028">
55
- </testcase>
56
- <testcase classname="PipedTextSelect filters menu items to items containing the search value as a substring" name="PipedTextSelect filters menu items to items containing the search value as a substring" time="0.174">
57
- </testcase>
58
- <testcase classname="PipedTextSelect filters menu items with special characters to items containing the search value" name="PipedTextSelect filters menu items with special characters to items containing the search value" time="0.152">
59
- </testcase>
60
- <testcase classname="PipedTextSelect renders submenu correctly when hovering over a submenu item" name="PipedTextSelect renders submenu correctly when hovering over a submenu item" time="0.554">
61
- </testcase>
62
- <testcase classname="PipedTextSelect hides other submenus when hovering over another submenu" name="PipedTextSelect hides other submenus when hovering over another submenu" time="0.618">
63
- </testcase>
64
- <testcase classname="PipedTextSelect hides other submenus when hovering over another item" name="PipedTextSelect hides other submenus when hovering over another item" time="0.387">
65
- </testcase>
66
- <testcase classname="PipedTextSelect fires onSelect handler when a menu item is selected" name="PipedTextSelect fires onSelect handler when a menu item is selected" time="0.148">
67
- </testcase>
68
- <testcase classname="PipedTextSelect doesn&apos;t fire onSelect handler when a disabled menu item is selected" name="PipedTextSelect doesn&apos;t fire onSelect handler when a disabled menu item is selected" time="0.146">
69
- </testcase>
70
- <testcase classname="PipedTextSelect fires onClose handler when menu item selected" name="PipedTextSelect fires onClose handler when menu item selected" time="0.148">
71
- </testcase>
72
- <testcase classname="PipedTextSelect fires onClose handler when nested item selected" name="PipedTextSelect fires onClose handler when nested item selected" time="1.37">
73
- </testcase>
74
- <testcase classname="PipedTextSelect fires onClose handler when clicking outside of the menu" name="PipedTextSelect fires onClose handler when clicking outside of the menu" time="0.207">
75
- </testcase>
76
- <testcase classname="PipedTextSelect displays the custom input message if none of the menu items match the search query and custom input is enabled" name="PipedTextSelect displays the custom input message if none of the menu items match the search query and custom input is enabled" time="0.626">
77
- </testcase>
78
- <testcase classname="PipedTextSelect correctly creates a custom locator based on the provided scheme when the user hits the &quot;enter&quot; in the search query" name="PipedTextSelect correctly creates a custom locator based on the provided scheme when the user hits the &quot;enter&quot; in the search query" time="0.541">
79
- </testcase>
80
- <testcase classname="PipedTextSelect calls the onClose handler when custom input is enabled and the user hits &quot;enter&quot; in the search query" name="PipedTextSelect calls the onClose handler when custom input is enabled and the user hits &quot;enter&quot; in the search query" time="0.565">
81
- </testcase>
82
- <testcase classname="PipedTextSelect does not call the onClose handler when custom input is disabled and the user hits &quot;enter&quot; in the search query" name="PipedTextSelect does not call the onClose handler when custom input is disabled and the user hits &quot;enter&quot; in the search query" time="0.651">
83
- </testcase>
84
- <testcase classname="PipedTextSelect displays piped text items provided by an async &quot;items&quot; function" name="PipedTextSelect displays piped text items provided by an async &quot;items&quot; function" time="0.555">
85
- </testcase>
86
- <testcase classname="PipedTextSelect displays piped text items provided by a non-async &quot;items&quot; function" name="PipedTextSelect displays piped text items provided by a non-async &quot;items&quot; function" time="0.547">
87
- </testcase>
88
- <testcase classname="PipedTextSelect displays loading error message if async piped text items function fails to resolve" name="PipedTextSelect displays loading error message if async piped text items function fails to resolve" time="0.557">
89
- </testcase>
90
- </testsuite>
91
- </testsuites>