@nebula.js/stardust 4.0.0-alpha.6 → 4.0.0-alpha.7

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.
@@ -1,5 +1,5 @@
1
1
  /*
2
- * @nebula.js/stardust v4.0.0-alpha.6
2
+ * @nebula.js/stardust v4.0.0-alpha.7
3
3
  * Copyright (c) 2023 QlikTech International AB
4
4
  * Released under the MIT license.
5
5
  */
@@ -15420,7 +15420,7 @@
15420
15420
  return cache[key];
15421
15421
  }
15422
15422
 
15423
- const NEBULA_VERSION_HASH = "9917" ;
15423
+ const NEBULA_VERSION_HASH = "a704" ;
15424
15424
  ClassNameGenerator$1.configure(componentName => {
15425
15425
  return "njs-".concat(NEBULA_VERSION_HASH, "-").concat(componentName.replace('Mui', ''));
15426
15426
  });
@@ -15628,7 +15628,7 @@
15628
15628
  const appRef = React.createRef();
15629
15629
  const element = document.createElement('div');
15630
15630
  element.style.display = 'none';
15631
- element.setAttribute('data-nebulajs-version', "4.0.0-alpha.6" );
15631
+ element.setAttribute('data-nebulajs-version', "4.0.0-alpha.7" );
15632
15632
  element.setAttribute('data-app-id', app.id);
15633
15633
  document.body.appendChild(element);
15634
15634
  const root = client.createRoot(element);
@@ -21979,6 +21979,84 @@
21979
21979
  isArrow: key => key === KEYS.ARROW_UP || key === KEYS.ARROW_DOWN || key === KEYS.ARROW_LEFT || key === KEYS.ARROW_RIGHT
21980
21980
  });
21981
21981
 
21982
+ function removeInnnerTabStops(container) {
21983
+ container === null || container === void 0 ? void 0 : container.querySelectorAll('[tabIndex="0"]').forEach(elm => {
21984
+ elm.setAttribute('tabIndex', -1);
21985
+ });
21986
+ }
21987
+ function removeLastFocused(container) {
21988
+ container === null || container === void 0 ? void 0 : container.querySelectorAll('.last-focused').forEach(elm => {
21989
+ elm.classList.remove('last-focused');
21990
+ });
21991
+ }
21992
+ function getVizCell(container) {
21993
+ return (container === null || container === void 0 ? void 0 : container.closest('.njs-cell')) || (container === null || container === void 0 ? void 0 : container.closest('.qv-gridcell'));
21994
+ }
21995
+
21996
+ // Emulate the keyboard hook, until we support it in the Listbox.
21997
+ function useTempKeyboard(_ref) {
21998
+ let {
21999
+ containerRef,
22000
+ enabled
22001
+ } = _ref;
22002
+ const [keyboardActive, setKeyboardActive] = reactExports.useState(false);
22003
+ const innerTabStops = !enabled || keyboardActive;
22004
+ const keyboard = {
22005
+ enabled,
22006
+ active: keyboardActive,
22007
+ innerTabStops,
22008
+ // does keyboard permit inner tab stops
22009
+ outerTabStops: !innerTabStops,
22010
+ // does keyboard permit outer tab stops
22011
+ blur: resetFocus => {
22012
+ var _containerRef$current;
22013
+ if (!enabled) {
22014
+ return;
22015
+ }
22016
+ setKeyboardActive(false);
22017
+ const vizCell = getVizCell(containerRef.current) || ((_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.parentElement);
22018
+ removeInnnerTabStops(containerRef.current);
22019
+ removeLastFocused(containerRef.current);
22020
+ if (resetFocus && vizCell) {
22021
+ // Move focus to the viz's cell.
22022
+ vizCell.setAttribute('tabIndex', 0);
22023
+ vizCell.focus();
22024
+ }
22025
+ },
22026
+ focus: () => {
22027
+ if (!enabled) {
22028
+ return;
22029
+ }
22030
+ setKeyboardActive(true);
22031
+ const c = containerRef.current;
22032
+ const searchField = c === null || c === void 0 ? void 0 : c.querySelector('.search input');
22033
+ const lastSelectedRow = c === null || c === void 0 ? void 0 : c.querySelector('.value.last-focused');
22034
+ const fieldElement = c === null || c === void 0 ? void 0 : c.querySelector('.value.selector, .value, .ActionsToolbar-item button');
22035
+ const elementToFocus = searchField || lastSelectedRow || fieldElement;
22036
+ elementToFocus === null || elementToFocus === void 0 ? void 0 : elementToFocus.setAttribute('tabIndex', 0);
22037
+ elementToFocus === null || elementToFocus === void 0 ? void 0 : elementToFocus.focus();
22038
+ },
22039
+ focusSelection: () => {
22040
+ const confirmButton = document.querySelector('.actions-toolbar-default-actions .actions-toolbar-confirm');
22041
+ confirmButton === null || confirmButton === void 0 ? void 0 : confirmButton.setAttribute('tabIndex', 0);
22042
+ confirmButton === null || confirmButton === void 0 ? void 0 : confirmButton.focus();
22043
+ }
22044
+ };
22045
+ return keyboard;
22046
+ }
22047
+
22048
+ const getElementIndex = currentTarget => +currentTarget.getAttribute('data-n');
22049
+ const focusSearch = container => {
22050
+ const searchField = container === null || container === void 0 ? void 0 : container.querySelector('.search input');
22051
+ searchField === null || searchField === void 0 ? void 0 : searchField.focus();
22052
+ return searchField;
22053
+ };
22054
+ const focusRow = container => {
22055
+ const row = container === null || container === void 0 ? void 0 : container.querySelector('.value.last-focused, .value.selector, .value');
22056
+ row === null || row === void 0 ? void 0 : row.setAttribute('tabIndex', 0);
22057
+ row === null || row === void 0 ? void 0 : row.focus();
22058
+ return row;
22059
+ };
21982
22060
  function getFieldKeyboardNavigation(_ref) {
21983
22061
  let {
21984
22062
  select,
@@ -21987,7 +22065,9 @@
21987
22065
  confirm,
21988
22066
  cancel,
21989
22067
  setScrollPosition,
21990
- focusListItems
22068
+ focusListItems,
22069
+ keyboard,
22070
+ isModal
21991
22071
  } = _ref;
21992
22072
  const getElement = function (elm) {
21993
22073
  let next = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
@@ -22000,49 +22080,86 @@
22000
22080
  };
22001
22081
  const handleKeyDown = event => {
22002
22082
  let elementToFocus;
22083
+ const {
22084
+ currentTarget,
22085
+ nativeEvent
22086
+ } = event;
22003
22087
  const {
22004
22088
  keyCode,
22005
22089
  shiftKey = false,
22006
22090
  ctrlKey = false,
22007
22091
  metaKey = false
22008
- } = event.nativeEvent;
22092
+ } = nativeEvent;
22009
22093
  switch (keyCode) {
22094
+ case KEYS.TAB:
22095
+ {
22096
+ // Try to focus search field, otherwise confirm button.
22097
+ const container = currentTarget.closest('.listbox-container');
22098
+ const inSelection = isModal();
22099
+
22100
+ // TODO: use a store to keep track of this row.
22101
+ currentTarget.classList.add('last-focused'); // so that we can go back here when we tab back
22102
+
22103
+ if (shiftKey) {
22104
+ if (!focusSearch(container)) {
22105
+ if (inSelection) {
22106
+ keyboard.focusSelection();
22107
+ } else {
22108
+ keyboard.blur(true);
22109
+ }
22110
+ }
22111
+ break;
22112
+ }
22113
+
22114
+ // Without shift key
22115
+ if (inSelection) {
22116
+ keyboard.focusSelection();
22117
+ } else {
22118
+ currentTarget.blur();
22119
+ keyboard.blur();
22120
+ }
22121
+ break;
22122
+ }
22010
22123
  case KEYS.SHIFT:
22011
22124
  // This is to ensure we include the first value when starting a range selection.
22012
22125
  setStartedRange(true);
22013
22126
  break;
22014
22127
  case KEYS.SPACE:
22015
- select([+event.currentTarget.getAttribute('data-n')], false, event);
22128
+ select([getElementIndex(currentTarget)], false, event);
22016
22129
  break;
22017
22130
  case KEYS.ARROW_DOWN:
22018
22131
  case KEYS.ARROW_RIGHT:
22019
- elementToFocus = getElement(event.currentTarget, true);
22132
+ elementToFocus = getElement(currentTarget, true);
22020
22133
  if (shiftKey && elementToFocus) {
22021
22134
  if (startedRange) {
22022
- select([+event.currentTarget.getAttribute('data-n')], true);
22135
+ select([getElementIndex(currentTarget)], true);
22023
22136
  setStartedRange(false);
22024
22137
  }
22025
- select([+elementToFocus.getAttribute('data-n')], true);
22138
+ select([getElementIndex(elementToFocus)], true);
22026
22139
  }
22027
22140
  break;
22028
22141
  case KEYS.ARROW_UP:
22029
22142
  case KEYS.ARROW_LEFT:
22030
- elementToFocus = getElement(event.currentTarget, false);
22143
+ elementToFocus = getElement(currentTarget, false);
22031
22144
  if (shiftKey && elementToFocus) {
22032
22145
  if (startedRange) {
22033
- select([+event.currentTarget.getAttribute('data-n')], true);
22146
+ select([getElementIndex(currentTarget)], true);
22034
22147
  setStartedRange(false);
22035
22148
  }
22036
- select([+elementToFocus.getAttribute('data-n')], true);
22149
+ select([getElementIndex(elementToFocus)], true);
22037
22150
  }
22038
22151
  break;
22039
22152
  case KEYS.ENTER:
22040
22153
  confirm();
22041
22154
  break;
22042
22155
  case KEYS.ESCAPE:
22043
- cancel();
22044
- return;
22045
- // let it propagate to top-level
22156
+ if (isModal()) {
22157
+ cancel();
22158
+ } else {
22159
+ return; // propagate to other Esc handler
22160
+ }
22161
+
22162
+ break;
22046
22163
  case KEYS.HOME:
22047
22164
  focusListItems.setFirst(true);
22048
22165
  if (ctrlKey) {
@@ -22086,39 +22203,41 @@
22086
22203
  }
22087
22204
  function getListboxInlineKeyboardNavigation(_ref2) {
22088
22205
  let {
22089
- setKeyboardActive,
22206
+ keyboard,
22090
22207
  hovering,
22091
22208
  setHovering,
22092
22209
  updateKeyScroll,
22093
22210
  containerRef,
22094
22211
  currentScrollIndex,
22095
- app,
22096
- appSelections,
22212
+ isModal,
22097
22213
  constraints
22098
22214
  } = _ref2;
22099
- const focusInsideListbox = element => {
22100
- const fieldElement = element.querySelector('.search input, .value.selector, .value, .ActionsToolbar-item button');
22101
- setKeyboardActive(true);
22102
- if (fieldElement) {
22103
- fieldElement.focus();
22104
- }
22105
- };
22106
- const changeFocus = event => {
22107
- var _event$target;
22108
- if ((_event$target = event.target) !== null && _event$target !== void 0 && _event$target.classList.contains('listbox-container')) {
22109
- // Focus currently on a listbox
22110
- // Esc on a list box should move the focus to its parent, i.e. a filter pane if any
22111
- setKeyboardActive(false);
22215
+ const blur = event => {
22216
+ const {
22217
+ currentTarget,
22218
+ target
22219
+ } = event;
22220
+ const isFocusedOnListbox = target.classList.contains('listbox-container');
22221
+ const container = currentTarget.closest('.listbox-container');
22222
+ const vizCell = getVizCell(container);
22223
+ const isSingleListbox = (vizCell === null || vizCell === void 0 ? void 0 : vizCell.querySelectorAll('.listbox-container').length) === 1;
22224
+ if (isFocusedOnListbox || isSingleListbox) {
22225
+ // Move the focus from listbox container to the viz container.
22226
+ keyboard.blur(true);
22112
22227
  } else {
22113
- var _event$target2, _event$target3, _event$currentTarget, _event$currentTarget2;
22114
- // Focus currently on a row
22115
- // Esc on a row should move the focus to its parent, i.e. a listbox
22116
- // First unfocus the row
22117
- (_event$target2 = event.target) === null || _event$target2 === void 0 ? void 0 : _event$target2.setAttribute('tabIndex', '-1');
22118
- (_event$target3 = event.target) === null || _event$target3 === void 0 ? void 0 : _event$target3.blur();
22119
- // Then focus the listbox
22120
- (_event$currentTarget = event.currentTarget) === null || _event$currentTarget === void 0 ? void 0 : _event$currentTarget.setAttribute('tabIndex', '0');
22121
- (_event$currentTarget2 = event.currentTarget) === null || _event$currentTarget2 === void 0 ? void 0 : _event$currentTarget2.focus();
22228
+ // More than one listbox: Move focus from row to listbox container.
22229
+
22230
+ // 1. Remove last-focused class from row siblings.
22231
+ removeLastFocused(containerRef.current);
22232
+
22233
+ // 2. Add last-focused class so we can re-focus it later.
22234
+ currentTarget.classList.add('last-focused');
22235
+
22236
+ // 3. Blur row and focus the listbox container.
22237
+ keyboard.blur();
22238
+ const c = currentTarget.closest('.listbox-container');
22239
+ c.setAttribute('tabIndex', 0);
22240
+ c === null || c === void 0 ? void 0 : c.focus();
22122
22241
  }
22123
22242
  };
22124
22243
  const updateKeyScrollOnHover = newState => {
@@ -22132,65 +22251,84 @@
22132
22251
  ctrlKey = false,
22133
22252
  shiftKey = false
22134
22253
  } = event.nativeEvent;
22254
+ const prevent = () => {
22255
+ event.stopPropagation();
22256
+ event.preventDefault();
22257
+ };
22135
22258
  switch (keyCode) {
22136
- // case KEYS.TAB: TODO: Focus confirm button using keyboard.focusSelection when we can access the useKeyboard hook.
22137
- case KEYS.ENTER:
22138
- case KEYS.SPACE:
22139
- if (!event.target.classList.contains('listbox-container')) {
22140
- return; // don't mess with keydown handlers within the listbox
22141
- }
22142
-
22143
- focusInsideListbox(event.currentTarget);
22144
- break;
22145
- case KEYS.ESCAPE:
22146
- changeFocus(event);
22147
- break;
22148
- case KEYS.ARROW_UP:
22149
- updateKeyScrollOnHover({
22150
- up: 1
22151
- });
22152
- break;
22153
- case KEYS.ARROW_DOWN:
22154
- updateKeyScrollOnHover({
22155
- down: 1
22156
- });
22157
- break;
22158
- case KEYS.ARROW_LEFT:
22159
- case KEYS.ARROW_RIGHT:
22160
- return;
22161
- // let it propagate to top-level
22162
22259
  case KEYS.PAGE_UP:
22163
22260
  updateKeyScrollOnHover({
22164
22261
  up: currentScrollIndex.stop - currentScrollIndex.start
22165
22262
  });
22263
+ prevent();
22166
22264
  break;
22167
22265
  case KEYS.PAGE_DOWN:
22168
22266
  updateKeyScrollOnHover({
22169
22267
  down: currentScrollIndex.stop - currentScrollIndex.start
22170
22268
  });
22269
+ prevent();
22171
22270
  break;
22172
22271
  case KEYS.HOME:
22173
22272
  updateKeyScrollOnHover({
22174
22273
  scrollPosition: ctrlKey && shiftKey ? 'overflowStart' : 'start'
22175
22274
  });
22275
+ prevent();
22176
22276
  break;
22177
22277
  case KEYS.END:
22178
22278
  updateKeyScrollOnHover({
22179
22279
  scrollPosition: ctrlKey && shiftKey ? 'overflowEnd' : 'end'
22180
22280
  });
22281
+ prevent();
22181
22282
  break;
22182
- default:
22183
- return;
22283
+ case KEYS.ARROW_UP:
22284
+ updateKeyScrollOnHover({
22285
+ up: 1
22286
+ });
22287
+ prevent();
22288
+ break;
22289
+ case KEYS.ARROW_DOWN:
22290
+ updateKeyScrollOnHover({
22291
+ down: 1
22292
+ });
22293
+ prevent();
22294
+ break;
22295
+ }
22296
+ if (!keyboard.enabled) {
22297
+ // Other keys should not be handled unless keyboard is enabled.
22298
+ return undefined;
22184
22299
  }
22300
+ const container = event.currentTarget.closest('.listbox-container');
22301
+ switch (keyCode) {
22302
+ case KEYS.TAB:
22303
+ if (shiftKey) {
22304
+ focusRow(container) || focusSearch(container);
22305
+ } else {
22306
+ focusSearch(container) || focusRow(container);
22307
+ }
22308
+ prevent();
22309
+ break;
22310
+ case KEYS.ENTER:
22311
+ case KEYS.SPACE:
22312
+ if (!event.target.classList.contains('listbox-container')) {
22313
+ return undefined; // don't mess with keydown handlers within the listbox (e.g. row seletion)
22314
+ }
22185
22315
 
22186
- // Note: We should not stop propagation here as it will block the containing app
22187
- // from handling keydown events.
22188
- event.preventDefault();
22316
+ keyboard.focus();
22317
+ prevent();
22318
+ break;
22319
+ case KEYS.ESCAPE:
22320
+ blur(event);
22321
+ prevent();
22322
+ break;
22323
+ case KEYS.ARROW_LEFT:
22324
+ case KEYS.ARROW_RIGHT:
22325
+ return undefined;
22326
+ }
22327
+ return undefined;
22189
22328
  };
22190
22329
  const focusOnHoverDisabled = () => {
22191
- var _app$isInModalSelecti, _app$isInModalSelecti2;
22192
22330
  const selectNotAllowed = (constraints === null || constraints === void 0 ? void 0 : constraints.select) || (constraints === null || constraints === void 0 ? void 0 : constraints.active);
22193
- const appInModal = (_app$isInModalSelecti = (_app$isInModalSelecti2 = app.isInModalSelection) === null || _app$isInModalSelecti2 === void 0 ? void 0 : _app$isInModalSelecti2.call(app)) !== null && _app$isInModalSelecti !== void 0 ? _app$isInModalSelecti : appSelections.isInModal();
22331
+ const appInModal = isModal();
22194
22332
  return selectNotAllowed || appInModal;
22195
22333
  };
22196
22334
  const handleOnMouseEnter = () => {
@@ -22878,13 +23016,15 @@
22878
23016
  dense,
22879
23017
  showGray
22880
23018
  } = _ref;
23019
+ const frequencyText = getFrequencyText(cell === null || cell === void 0 ? void 0 : cell.qFrequency);
22881
23020
  return /*#__PURE__*/React.createElement(Grid$1, {
22882
23021
  item: true,
22883
23022
  style: {
22884
23023
  display: 'flex',
22885
23024
  alignItems: 'center'
22886
23025
  },
22887
- className: rowColClasses.frequencyCount
23026
+ className: rowColClasses.frequencyCount,
23027
+ "aria-label": frequencyText
22888
23028
  }, /*#__PURE__*/React.createElement(Typography$1, {
22889
23029
  noWrap: true,
22890
23030
  color: "inherit",
@@ -22893,7 +23033,7 @@
22893
23033
  cell,
22894
23034
  checkboxes
22895
23035
  }) && rowColClasses.excludedTextWithCheckbox])
22896
- }, getFrequencyText(cell === null || cell === void 0 ? void 0 : cell.qFrequency)));
23036
+ }, frequencyText));
22897
23037
  }
22898
23038
 
22899
23039
  function getGridItemSizes(_ref) {
@@ -22930,7 +23070,7 @@
22930
23070
  }
22931
23071
 
22932
23072
  const ItemGrid = styled$1(Grid$1, {
22933
- shouldForwardProp: prop => !['dataLayout', 'layoutOrder', 'itemPadding', 'checkboxes'].includes(prop)
23073
+ shouldForwardProp: prop => !['dataLayout', 'layoutOrder', 'itemPadding', 'cellPaddingRight'].includes(prop)
22934
23074
  })(_ref => {
22935
23075
  let {
22936
23076
  dataLayout,
@@ -22965,6 +23105,79 @@
22965
23105
  return c;
22966
23106
  }
22967
23107
 
23108
+ /* eslint-disable import/prefer-default-export */
23109
+ const LOC_STATES = {
23110
+ S: 'Object.Listbox.Selected',
23111
+ A: 'Object.Listbox.Alternative',
23112
+ O: 'Object.Listbox.Optional',
23113
+ XS: 'Object.Listbox.SelectedExcluded',
23114
+ L: 'Object.Listbox.Locked',
23115
+ X: 'Object.Listbox.Excluded',
23116
+ XL: 'Object.Listbox.ExcludedLock'
23117
+ };
23118
+ function getValueLabel(_ref) {
23119
+ let {
23120
+ translator,
23121
+ label,
23122
+ qState,
23123
+ isSelected,
23124
+ currentIndex,
23125
+ maxIndex,
23126
+ showSearch
23127
+ } = _ref;
23128
+ const stateTranslation = LOC_STATES[qState];
23129
+ const state = translator.get(stateTranslation);
23130
+ const srStringArr = [];
23131
+ if (isSelected) {
23132
+ const navTranslation = showSearch ? 'Listbox.ScreenReader.SearchThenSelectionsMenu.WithAccSelMenu' : 'Listbox.ScreenReader.SelectionMenu.WithAccSelMenu';
23133
+ const nav = translator.get(navTranslation);
23134
+ srStringArr.push(nav);
23135
+ }
23136
+ const valueString = "".concat(label, " ").concat(state);
23137
+ const indexString = translator.get('CurrentSelections.Of', [currentIndex + 1, maxIndex + 1]); // E.g. 3 of 20
23138
+ srStringArr.unshift(valueString, indexString);
23139
+ const srString = srStringArr.join('. ').trim();
23140
+ return srString;
23141
+ }
23142
+
23143
+ /**
23144
+ * Announces the selection state.
23145
+ *
23146
+ * @ignore
23147
+ * @param {Layout} object
23148
+ * @returns {Element} An (invisible) component.
23149
+ */
23150
+ function ScreenReaderForSelections(_ref2) {
23151
+ var _layout$qListObject;
23152
+ let {
23153
+ layout
23154
+ } = _ref2;
23155
+ const {
23156
+ translator
23157
+ } = reactExports.useContext(InstanceContext);
23158
+ const {
23159
+ qStateCounts: s = {}
23160
+ } = (layout === null || layout === void 0 ? void 0 : (_layout$qListObject = layout.qListObject) === null || _layout$qListObject === void 0 ? void 0 : _layout$qListObject.qDimensionInfo) || {};
23161
+ const count = s.qSelected + s.qSelectedExcluded + s.qLocked + s.qLockedExcluded;
23162
+ let t;
23163
+ switch (count) {
23164
+ case 0:
23165
+ t = 'ScreenReader.ZeroSelected';
23166
+ break;
23167
+ case 1:
23168
+ t = 'ScreenReader.OneSelected';
23169
+ break;
23170
+ default:
23171
+ t = 'ScreenReader.ManySelected';
23172
+ break;
23173
+ }
23174
+ const text = translator.get(t, [count]);
23175
+ return /*#__PURE__*/React.createElement("div", {
23176
+ className: "screenReaderOnly",
23177
+ "aria-live": "assertive"
23178
+ }, text);
23179
+ }
23180
+
22968
23181
  function RowColumn(_ref) {
22969
23182
  var _cell$qText, _cell$qHighlightRange, _cell$qHighlightRange2;
22970
23183
  let {
@@ -23001,7 +23214,10 @@
23001
23214
  focusListItems,
23002
23215
  listCount,
23003
23216
  itemPadding,
23004
- frequencyWidth
23217
+ frequencyWidth,
23218
+ translator,
23219
+ showSearch,
23220
+ isModal
23005
23221
  } = data;
23006
23222
  const {
23007
23223
  dense = false,
@@ -23051,8 +23267,10 @@
23051
23267
  }
23052
23268
  }, [rowRef.current]);
23053
23269
  const handleKeyDownCallback = reactExports.useCallback(getFieldKeyboardNavigation(_objectSpread2(_objectSpread2({}, actions), {}, {
23054
- focusListItems
23055
- })), [actions]);
23270
+ focusListItems,
23271
+ keyboard,
23272
+ isModal
23273
+ })), [actions, keyboard === null || keyboard === void 0 ? void 0 : keyboard.innerTabStops]);
23056
23274
  const cell = reactExports.useMemo(() => getCellFromPages({
23057
23275
  pages,
23058
23276
  cellIndex
@@ -23117,6 +23335,14 @@
23117
23335
  const showTick = !checkboxes && isSelected && !isLocked;
23118
23336
  const showIcon = !checkboxes && sizePermitsTickOrLock;
23119
23337
  const cellPaddingRight = checkboxes || !sizePermitsTickOrLock;
23338
+ const ariaLabel = getValueLabel({
23339
+ translator,
23340
+ label,
23341
+ qState: cell.qState,
23342
+ currentIndex: count.currentIndex,
23343
+ maxIndex: count.max,
23344
+ showSearch
23345
+ });
23120
23346
  return /*#__PURE__*/React.createElement(RowColRoot$1, {
23121
23347
  className: rowColClasses.barContainer,
23122
23348
  flexBasisProp: flexBasisVal,
@@ -23127,6 +23353,11 @@
23127
23353
  frequencyWidth: frequencyWidth,
23128
23354
  "data-testid": "listbox.item"
23129
23355
  }, /*#__PURE__*/React.createElement(ItemGrid, {
23356
+ role: "row",
23357
+ "aria-label": ariaLabel,
23358
+ "aria-selected": isSelected,
23359
+ "aria-setsize": count.max,
23360
+ "aria-rowindex": count.currentIndex,
23130
23361
  ref: rowRef,
23131
23362
  container: true,
23132
23363
  dataLayout: dataLayout,
@@ -23144,8 +23375,7 @@
23144
23375
  onMouseEnter: onMouseEnter,
23145
23376
  onKeyDown: handleKeyDownCallback,
23146
23377
  onContextMenu: preventContextMenu,
23147
- role: column ? 'column' : 'row',
23148
- tabIndex: isFirstElement && (!keyboard.enabled || keyboard.active) ? 0 : -1,
23378
+ tabIndex: isFirstElement && keyboard.innerTabStops ? 0 : -1,
23149
23379
  "data-n": cell === null || cell === void 0 ? void 0 : cell.qElemNumber
23150
23380
  }, (cell === null || cell === void 0 ? void 0 : cell.qFrequency) && /*#__PURE__*/React.createElement(Histogram, {
23151
23381
  qFrequency: cell === null || cell === void 0 ? void 0 : cell.qFrequency,
@@ -24761,7 +24991,10 @@
24761
24991
  setCurrentScrollIndex,
24762
24992
  constraints,
24763
24993
  frequencyMax,
24764
- freqIsAllowed
24994
+ freqIsAllowed,
24995
+ translator,
24996
+ showSearch,
24997
+ isModal
24765
24998
  } = _ref;
24766
24999
  const {
24767
25000
  layoutOptions = {}
@@ -24815,7 +25048,10 @@
24815
25048
  showTick,
24816
25049
  dataOffset: local.current.dataOffset,
24817
25050
  focusListItems,
24818
- direction
25051
+ direction,
25052
+ translator,
25053
+ showSearch,
25054
+ isModal
24819
25055
  });
24820
25056
  const List = _ref2 => {
24821
25057
  let {
@@ -25257,17 +25493,14 @@
25257
25493
  };
25258
25494
  }
25259
25495
 
25260
- function ListBoxDisclaimer(_ref) {
25496
+ const StyledText = styled$1(Typography$1, {
25497
+ shouldForwardProp: p => !['width', 'dense'].includes(p)
25498
+ })(_ref => {
25261
25499
  let {
25262
25500
  width,
25263
- text,
25264
- dense,
25265
- tooltip
25501
+ dense
25266
25502
  } = _ref;
25267
- const {
25268
- translator
25269
- } = reactExports.useContext(InstanceContext);
25270
- const StyledText = styled$1(Typography$1)(() => _objectSpread2({
25503
+ return _objectSpread2({
25271
25504
  minWidth: "".concat(width, "px"),
25272
25505
  textAlign: 'center',
25273
25506
  fontSize: "".concat(dense ? '12px' : '14px')
@@ -25276,10 +25509,23 @@
25276
25509
  overflow: 'hidden',
25277
25510
  whiteSpace: 'nowrap',
25278
25511
  width
25279
- }));
25512
+ });
25513
+ });
25514
+ function ListBoxDisclaimer(_ref2) {
25515
+ let {
25516
+ width,
25517
+ text,
25518
+ dense,
25519
+ tooltip
25520
+ } = _ref2;
25521
+ const {
25522
+ translator
25523
+ } = reactExports.useContext(InstanceContext);
25280
25524
  return /*#__PURE__*/React.createElement(Tooltip$1, {
25281
25525
  title: tooltip ? translator.get(text) : ''
25282
25526
  }, /*#__PURE__*/React.createElement(StyledText, {
25527
+ width: width,
25528
+ dense: dense,
25283
25529
  component: "div",
25284
25530
  variant: "body1",
25285
25531
  py: "12px"
@@ -25501,6 +25747,14 @@
25501
25747
 
25502
25748
  const _excluded$4 = ["isLoadingData"];
25503
25749
  const DEFAULT_MIN_BATCH_SIZE = 100;
25750
+ const StyledWrapper = styled$1('div')(() => ({
25751
+ ["& .screenReaderOnly"]: {
25752
+ position: 'absolute',
25753
+ height: 0,
25754
+ width: 0,
25755
+ overflow: 'hidden'
25756
+ }
25757
+ }));
25504
25758
  function ListBox(_ref) {
25505
25759
  var _layout$qListObject$q, _loaderRef$current, _loaderRef$current$_l, _loaderRef$current$_l2;
25506
25760
  let {
@@ -25531,8 +25785,13 @@
25531
25785
  set: () => {}
25532
25786
  },
25533
25787
  renderedCallback,
25534
- onCtrlF
25788
+ onCtrlF,
25789
+ showSearch,
25790
+ isModal
25535
25791
  } = _ref;
25792
+ const {
25793
+ translator
25794
+ } = reactExports.useContext(InstanceContext);
25536
25795
  const [initScrollPosIsSet, setInitScrollPosIsSet] = reactExports.useState(false);
25537
25796
  const isSingleSelect = !!(layout && layout.qListObject.qDimensionInfo.qIsOneAndOnlyOne);
25538
25797
  const {
@@ -25787,7 +26046,10 @@
25787
26046
  setCurrentScrollIndex: currentScrollIndex.set,
25788
26047
  constraints,
25789
26048
  frequencyMax,
25790
- freqIsAllowed
26049
+ freqIsAllowed,
26050
+ translator,
26051
+ showSearch,
26052
+ isModal
25791
26053
  });
25792
26054
  const {
25793
26055
  columnWidth,
@@ -25802,7 +26064,10 @@
25802
26064
  itemHeight
25803
26065
  });
25804
26066
  }
25805
- return /*#__PURE__*/React.createElement(React.Fragment, null, !listCount && /*#__PURE__*/React.createElement(ListBoxDisclaimer, {
26067
+ return /*#__PURE__*/React.createElement(StyledWrapper, null, /*#__PURE__*/React.createElement(ScreenReaderForSelections, {
26068
+ className: "screenReaderOnly",
26069
+ layout: layout
26070
+ }), !listCount && /*#__PURE__*/React.createElement(ListBoxDisclaimer, {
25806
26071
  width: width,
25807
26072
  text: "Listbox.NoMatchesForYourTerms"
25808
26073
  }), /*#__PURE__*/React.createElement(InfiniteLoader, {
@@ -25814,7 +26079,8 @@
25814
26079
  }),
25815
26080
  threshold: 0,
25816
26081
  minimumBatchSize: minimumBatchSize,
25817
- ref: loaderRef
26082
+ ref: loaderRef,
26083
+ role: "grid"
25818
26084
  }, isVertical ? List : Grid), overflowDisclaimer.show && !overflowDisclaimer.dismissed && /*#__PURE__*/React.createElement(ListBoxFooter, {
25819
26085
  text: "Listbox.ItemsOverflow",
25820
26086
  dismiss: () => setOverflowDisclaimer(state => _objectSpread2(_objectSpread2({}, state), {}, {
@@ -25966,6 +26232,7 @@
25966
26232
  if (hidden) return null;
25967
26233
  const spacing = Number.parseInt(theme.spacing(0.5), 10);
25968
26234
  const handleKeyDown = item.keyboardAction ? e => ['Enter', ' ', 'Spacebar'].includes(e.key) && item.keyboardAction() : null;
26235
+ const btnId = "actions-toolbar-".concat(item.key);
25969
26236
  return /*#__PURE__*/React.createElement(IconButton$1, {
25970
26237
  ref: !addAnchor ? ref : null,
25971
26238
  title: item.label,
@@ -25973,12 +26240,12 @@
25973
26240
  onKeyDown: handleKeyDown,
25974
26241
  disabled: disabled,
25975
26242
  style: style,
25976
- className: ActionElement.className,
26243
+ className: [ActionElement.className, btnId].join(' '),
25977
26244
  size: "large",
25978
26245
  disableRipple: true,
25979
26246
  "aria-expanded": ariaExpanded,
25980
26247
  "aria-controls": "moreMenuList",
25981
- "data-testid": "actions-toolbar-".concat(item.key)
26248
+ "data-testid": btnId
25982
26249
  }, hasSvgIconShape && SvgIcon(item.getSvgIconShape()), addAnchor && /*#__PURE__*/React.createElement("div", {
25983
26250
  ref: ref,
25984
26251
  style: {
@@ -26157,6 +26424,70 @@
26157
26424
  }))));
26158
26425
  });
26159
26426
 
26427
+ const getActionButtonIndex = btn => {
26428
+ const toolbar = btn.closest('#actions-toolbar');
26429
+ const nodeList = toolbar === null || toolbar === void 0 ? void 0 : toolbar.querySelectorAll('.njs-cell-action');
26430
+ return Array.from(nodeList).indexOf(btn);
26431
+ };
26432
+ const focusButton = index => {
26433
+ const toolbar = document.querySelector('#actions-toolbar');
26434
+ const nodeList = toolbar === null || toolbar === void 0 ? void 0 : toolbar.querySelectorAll('.njs-cell-action');
26435
+ if (!nodeList.length) {
26436
+ return;
26437
+ }
26438
+ const ix = Math.min(Math.max(0, index), nodeList.length - 1);
26439
+ const btn = nodeList[ix];
26440
+ btn.focus();
26441
+ };
26442
+ function getActionsKeyDownHandler(_ref) {
26443
+ let {
26444
+ keyboardNavigation,
26445
+ focusHandler,
26446
+ getEnabledButton
26447
+ } = _ref;
26448
+ const handleActionsKeyDown = evt => {
26449
+ const {
26450
+ target,
26451
+ nativeEvent
26452
+ } = evt;
26453
+ const {
26454
+ keyCode
26455
+ } = nativeEvent;
26456
+ switch (keyCode) {
26457
+ case KEYS.ARROW_LEFT:
26458
+ case KEYS.ARROW_DOWN:
26459
+ case KEYS.ARROW_RIGHT:
26460
+ case KEYS.ARROW_UP:
26461
+ {
26462
+ const isActionButton = target.classList.contains('njs-cell-action');
26463
+ if (isActionButton) {
26464
+ const index = getActionButtonIndex(target);
26465
+ const pressedLeft = [KEYS.ARROW_LEFT, KEYS.ARROW_DOWN].includes(keyCode);
26466
+ focusButton(pressedLeft ? index - 1 : index + 1);
26467
+ }
26468
+ evt.stopPropagation();
26469
+ evt.preventDefault();
26470
+ break;
26471
+ }
26472
+ case KEYS.SPACE:
26473
+ evt.preventDefault(); // prevent scrolling in listbox
26474
+ break;
26475
+ case KEYS.TAB:
26476
+ if (keyboardNavigation && focusHandler !== null && focusHandler !== void 0 && focusHandler.refocusContent) {
26477
+ const isTabbingOut = evt.shiftKey && getEnabledButton(false) === evt.target || !evt.shiftKey && getEnabledButton(true) === evt.target;
26478
+ if (isTabbingOut) {
26479
+ evt.preventDefault();
26480
+ evt.stopPropagation();
26481
+ // if keyboardNavigation is true, create a callback to handle tabbing from the first/last button in the toolbar that resets focus on the content
26482
+ focusHandler.refocusContent();
26483
+ }
26484
+ }
26485
+ break;
26486
+ }
26487
+ };
26488
+ return handleActionsKeyDown;
26489
+ }
26490
+
26160
26491
  const PREFIX$7 = 'ActionsToolbar';
26161
26492
  const classes$7 = {
26162
26493
  item: "".concat(PREFIX$7, "-item"),
@@ -26192,6 +26523,7 @@
26192
26523
  };
26193
26524
  const ActionsGroup = React.forwardRef((_ref2, ref) => {
26194
26525
  let {
26526
+ className,
26195
26527
  ariaExpanded = false,
26196
26528
  actions = [],
26197
26529
  first = false,
@@ -26204,7 +26536,8 @@
26204
26536
  container: true,
26205
26537
  gap: 0,
26206
26538
  flexDirection: isRtl ? 'row-reverse' : 'row',
26207
- wrap: "nowrap"
26539
+ wrap: "nowrap",
26540
+ className: className
26208
26541
  }, actions.map((e, ix) => {
26209
26542
  let cls = [];
26210
26543
  const isFirstItem = first && ix === 0;
@@ -26272,22 +26605,27 @@
26272
26605
  keyboardNavigation
26273
26606
  } = reactExports.useContext(InstanceContext);
26274
26607
  const [showMoreItems, setShowMoreItems] = reactExports.useState(false);
26275
- const moreRef = reactExports.useRef();
26608
+ const popoverAnchorOrigin = {
26609
+ vertical: 7,
26610
+ horizontal: ((_popover$anchorEl$cli = (_popover$anchorEl = popover.anchorEl) === null || _popover$anchorEl === void 0 ? void 0 : _popover$anchorEl.clientWidth) !== null && _popover$anchorEl$cli !== void 0 ? _popover$anchorEl$cli : 0) - 7
26611
+ };
26276
26612
  const actionsRef = reactExports.useRef();
26613
+ const moreRef = reactExports.useRef();
26277
26614
  const theme = useTheme$1();
26278
26615
  const dividerStyle = reactExports.useMemo(() => ({
26279
26616
  margin: theme.spacing(0.5, 0)
26280
26617
  }));
26281
- const popoverAnchorOrigin = {
26282
- vertical: 15,
26283
- horizontal: ((_popover$anchorEl$cli = (_popover$anchorEl = popover.anchorEl) === null || _popover$anchorEl === void 0 ? void 0 : _popover$anchorEl.clientWidth) !== null && _popover$anchorEl$cli !== void 0 ? _popover$anchorEl$cli : 0) - 7
26284
- };
26285
26618
  const getEnabledButton = last => {
26286
26619
  const actionsElement = actionsRef.current || actionsRefMock;
26287
26620
  if (!actionsElement) return null;
26288
26621
  const buttons = actionsElement.querySelectorAll('button:not(.Mui-disabled)');
26289
26622
  return buttons[last ? buttons.length - 1 : 0];
26290
26623
  };
26624
+ const handleActionsKeyDown = reactExports.useMemo(() => getActionsKeyDownHandler({
26625
+ keyboardNavigation,
26626
+ focusHandler,
26627
+ getEnabledButton
26628
+ }), [keyboardNavigation, focusHandler, getEnabledButton]);
26291
26629
  reactExports.useEffect(() => () => {
26292
26630
  setShowMoreItems(false);
26293
26631
  }, [popover.show, show, selections.show]);
@@ -26327,27 +26665,18 @@
26327
26665
  enabled: () => moreEnabled,
26328
26666
  action: () => setShowMoreItems(!showMoreItems)
26329
26667
  };
26330
- const tabCallback =
26331
- // if keyboardNavigation is true, create a callback to handle tabbing from the first/last button in the toolbar that resets focus on the content
26332
- keyboardNavigation && focusHandler && focusHandler.refocusContent ? evt => {
26333
- if (evt.key !== 'Tab') return;
26334
- const isTabbingOut = evt.shiftKey && getEnabledButton(false) === evt.target || !evt.shiftKey && getEnabledButton(true) === evt.target;
26335
- if (isTabbingOut) {
26336
- evt.preventDefault();
26337
- evt.stopPropagation();
26338
- focusHandler.refocusContent();
26339
- }
26340
- } : null;
26341
26668
  const showActions = newActions.length > 0;
26342
26669
  const showMore = moreActions.length > 0;
26343
26670
  const showDivider = showActions && selections.show || showMore && selections.show;
26344
26671
  const isRtl = direction === 'rtl';
26345
26672
  const Actions = /*#__PURE__*/React.createElement(Grid$1, {
26346
26673
  ref: actionsRef,
26347
- onKeyDown: tabCallback,
26674
+ onKeyDown: handleActionsKeyDown,
26348
26675
  container: true,
26349
26676
  gap: 0,
26350
26677
  wrap: "nowrap",
26678
+ id: "actions-toolbar",
26679
+ "data-testid": "actions-toolbar",
26351
26680
  sx: {
26352
26681
  flexDirection: isRtl ? 'row-reverse' : 'row'
26353
26682
  }
@@ -26356,6 +26685,8 @@
26356
26685
  first: true,
26357
26686
  last: !showMore && !selections.show
26358
26687
  }), showMore && /*#__PURE__*/React.createElement(ActionsGroup, {
26688
+ id: "actions-toolbar-show-more",
26689
+ "data-testid": "actions-toolbar-show-more",
26359
26690
  ref: moreRef,
26360
26691
  ariaExpanded: showMoreItems,
26361
26692
  actions: [moreItem],
@@ -26369,6 +26700,7 @@
26369
26700
  }, /*#__PURE__*/React.createElement(Divider$1, {
26370
26701
  orientation: "vertical"
26371
26702
  })), selections.show && /*#__PURE__*/React.createElement(ActionsGroup, {
26703
+ className: "actions-toolbar-default-actions",
26372
26704
  actions: defaultSelectionActions,
26373
26705
  first: !showActions && !showMore,
26374
26706
  last: true,
@@ -26392,6 +26724,8 @@
26392
26724
  hideBackdrop: true,
26393
26725
  style: popoverStyle,
26394
26726
  PaperProps: {
26727
+ id: 'njs-action-toolbar-popover',
26728
+ 'data-testid': 'njs-action-toolbar-popover',
26395
26729
  className: ActionToolbarElement.className,
26396
26730
  style: {
26397
26731
  pointerEvents: 'auto',
@@ -26519,29 +26853,57 @@
26519
26853
  }
26520
26854
  return response;
26521
26855
  };
26856
+ function focusRow(container) {
26857
+ const row = (container === null || container === void 0 ? void 0 : container.querySelector('.last-focused')) || (container === null || container === void 0 ? void 0 : container.querySelector('[role="row"]:first-child'));
26858
+ row.setAttribute('tabIndex', 0);
26859
+ row === null || row === void 0 ? void 0 : row.focus();
26860
+ }
26522
26861
  const onKeyDown = async e => {
26523
- let response;
26862
+ const {
26863
+ currentTarget
26864
+ } = e;
26865
+ const container = currentTarget.closest('.listbox-container');
26524
26866
  switch (e.key) {
26525
26867
  case 'Enter':
26526
- response = await performSearch();
26868
+ performSearch();
26527
26869
  break;
26528
26870
  case 'Escape':
26529
- response = cancel();
26530
- e.preventDefault();
26531
- e.stopPropagation();
26532
- break;
26871
+ {
26872
+ focusRow(container);
26873
+ cancel();
26874
+ break;
26875
+ }
26876
+ case 'Tab':
26877
+ {
26878
+ if (e.shiftKey) {
26879
+ keyboard.focusSelection();
26880
+ } else {
26881
+ // Focus the row we last visited or the first one.
26882
+ focusRow(container);
26883
+
26884
+ // Clean up.
26885
+ container === null || container === void 0 ? void 0 : container.querySelectorAll('.last-focused').forEach(elm => {
26886
+ elm.classList.remove('last-focused');
26887
+ });
26888
+ }
26889
+ break;
26890
+ }
26533
26891
  case 'f':
26534
26892
  case 'F':
26535
26893
  if (e.ctrlKey || e.metaKey) {
26536
26894
  if (hide) {
26537
26895
  hide();
26538
26896
  }
26539
- e.preventDefault();
26540
- e.stopPropagation();
26897
+ } else {
26898
+ return undefined;
26541
26899
  }
26542
26900
  break;
26901
+ default:
26902
+ return undefined;
26543
26903
  }
26544
- return response;
26904
+ e.preventDefault();
26905
+ e.stopPropagation();
26906
+ return undefined;
26545
26907
  };
26546
26908
  if (!visible || searchEnabled === false) {
26547
26909
  return null;
@@ -26587,10 +26949,11 @@
26587
26949
  onKeyDown: onKeyDown,
26588
26950
  autoFocus: autoFocus,
26589
26951
  inputProps: {
26590
- tabIndex: keyboard && (!keyboard.enabled || keyboard.active) ? 0 : -1,
26952
+ tabIndex: keyboard.innerTabStops ? 0 : -1,
26591
26953
  style: {
26592
26954
  textAlign: "".concat(inpuTextAlign)
26593
- }
26955
+ },
26956
+ 'data-testid': 'search-input-field'
26594
26957
  }
26595
26958
  });
26596
26959
  }
@@ -26834,6 +27197,12 @@
26834
27197
  objectSelections.addListener('activated', activateClickOut);
26835
27198
  objectSelections.addListener('deactivated', deactivateClickOut);
26836
27199
  return () => {
27200
+ // confirm selection before removing event handler
27201
+ // to end the selection when the object is removed
27202
+ // and remove the (ClickOut) mousedown handler from the document
27203
+ if (objectSelections.isActive()) {
27204
+ objectSelections.confirm();
27205
+ }
26837
27206
  objectSelections.removeListener('activated', activateClickOut);
26838
27207
  objectSelections.removeListener('deactivated', deactivateClickOut);
26839
27208
  };
@@ -28489,6 +28858,13 @@
28489
28858
  };
28490
28859
  }
28491
28860
 
28861
+ const StyledDiv = styled$1('div')(() => ({
28862
+ display: 'flex',
28863
+ width: '100%',
28864
+ height: '100%',
28865
+ alignItems: 'center',
28866
+ justifyContent: 'center'
28867
+ }));
28492
28868
  function ListBoxError(_ref) {
28493
28869
  let {
28494
28870
  text
@@ -28496,13 +28872,6 @@
28496
28872
  const {
28497
28873
  translator
28498
28874
  } = reactExports.useContext(InstanceContext);
28499
- const StyledDiv = styled$1('div')(() => ({
28500
- display: 'flex',
28501
- width: '100%',
28502
- height: '100%',
28503
- alignItems: 'center',
28504
- justifyContent: 'center'
28505
- }));
28506
28875
  return /*#__PURE__*/React.createElement(StyledDiv, null, translator.get(text));
28507
28876
  }
28508
28877
 
@@ -28557,12 +28926,20 @@
28557
28926
  fontWeight: ((_theme$listBox5 = theme.listBox) === null || _theme$listBox5 === void 0 ? void 0 : (_theme$listBox5$title = _theme$listBox5.title) === null || _theme$listBox5$title === void 0 ? void 0 : (_theme$listBox5$title2 = _theme$listBox5$title.main) === null || _theme$listBox5$title2 === void 0 ? void 0 : _theme$listBox5$title2.fontWeight) || 'bold'
28558
28927
  };
28559
28928
  });
28560
- function ListBoxInline(_ref3) {
28929
+ const isModal = _ref3 => {
28930
+ var _app$isInModalSelecti, _app$isInModalSelecti2;
28931
+ let {
28932
+ app,
28933
+ appSelections
28934
+ } = _ref3;
28935
+ return (_app$isInModalSelecti = (_app$isInModalSelecti2 = app.isInModalSelection) === null || _app$isInModalSelecti2 === void 0 ? void 0 : _app$isInModalSelecti2.call(app)) !== null && _app$isInModalSelecti !== void 0 ? _app$isInModalSelecti : appSelections.isInModal();
28936
+ };
28937
+ function ListBoxInline(_ref4) {
28561
28938
  var _layoutOptions$dense;
28562
28939
  let {
28563
28940
  options,
28564
28941
  layout
28565
- } = _ref3;
28942
+ } = _ref4;
28566
28943
  const {
28567
28944
  app,
28568
28945
  direction,
@@ -28610,7 +28987,6 @@
28610
28987
  const [searchContainer, searchContainerRef] = useRefWithCallback();
28611
28988
  const [showToolbar, setShowToolbar] = reactExports.useState(false);
28612
28989
  const [showSearch, setShowSearch] = reactExports.useState(false);
28613
- const [keyboardActive, setKeyboardActive] = reactExports.useState(false);
28614
28990
  const [hovering, setHovering] = reactExports.useState(false);
28615
28991
  const [keyScroll, setKeyScroll] = reactExports.useState({
28616
28992
  down: 0,
@@ -28625,6 +29001,14 @@
28625
29001
  const [appSelections] = useAppSelections(app);
28626
29002
  const titleRef = reactExports.useRef(null);
28627
29003
  const [selectionState$1] = reactExports.useState(() => selectionState());
29004
+ const keyboard = useTempKeyboard({
29005
+ containerRef,
29006
+ enabled: keyboardNavigation
29007
+ });
29008
+ const isModalMode = reactExports.useCallback(() => isModal({
29009
+ app,
29010
+ appSelections
29011
+ }), [app, appSelections]);
28628
29012
  const isInvalid = layout === null || layout === void 0 ? void 0 : layout.qListObject.qDimensionInfo.qError;
28629
29013
  const errorText = isInvalid && constraints.active ? 'Visualization.Invalid.Dimension' : 'Visualization.Incomplete';
28630
29014
  const {
@@ -28632,7 +29016,7 @@
28632
29016
  handleOnMouseEnter,
28633
29017
  handleOnMouseLeave
28634
29018
  } = getListboxInlineKeyboardNavigation({
28635
- setKeyboardActive,
29019
+ keyboard,
28636
29020
  hovering,
28637
29021
  setHovering,
28638
29022
  updateKeyScroll,
@@ -28640,15 +29024,9 @@
28640
29024
  currentScrollIndex,
28641
29025
  app,
28642
29026
  appSelections,
28643
- constraints
29027
+ constraints,
29028
+ isModal: isModalMode
28644
29029
  });
28645
-
28646
- // Expose the keyboard flags in the same way as the keyboard hook does.
28647
- const keyboard = {
28648
- enabled: keyboardNavigation,
28649
- // this will be static until we can access the useKeyboard hook
28650
- active: keyboardActive
28651
- };
28652
29030
  const showDetachedToolbarOnly = toolbar && ((layout === null || layout === void 0 ? void 0 : layout.title) === '' || (layout === null || layout === void 0 ? void 0 : layout.showTitle) === false);
28653
29031
  const showToolbarWithTitle = toolbar && (layout === null || layout === void 0 ? void 0 : layout.title) !== '' && (layout === null || layout === void 0 ? void 0 : layout.showTitle) !== false;
28654
29032
  reactExports.useEffect(() => {
@@ -28785,7 +29163,7 @@
28785
29163
  }, getActionToolbarProps(true))), /*#__PURE__*/React.createElement(StyledGrid$3, {
28786
29164
  className: "listbox-container",
28787
29165
  container: true,
28788
- tabIndex: keyboard.enabled && !keyboard.active ? 0 : -1,
29166
+ tabIndex: keyboard.outerTabStops ? 0 : -1,
28789
29167
  direction: "column",
28790
29168
  gap: 0,
28791
29169
  containerPadding: containerPadding,
@@ -28891,11 +29269,11 @@
28891
29269
  className: classes$4.screenReaderOnly
28892
29270
  }, translator.get('Listbox.ScreenReaderInstructions')), isInvalid ? /*#__PURE__*/React.createElement(ListBoxError, {
28893
29271
  text: errorText
28894
- }) : /*#__PURE__*/React.createElement(AutoSizer, null, _ref4 => {
29272
+ }) : /*#__PURE__*/React.createElement(AutoSizer, null, _ref5 => {
28895
29273
  let {
28896
29274
  height,
28897
29275
  width
28898
- } = _ref4;
29276
+ } = _ref5;
28899
29277
  return /*#__PURE__*/React.createElement(ListBox, {
28900
29278
  model: model,
28901
29279
  app: app,
@@ -28930,15 +29308,16 @@
28930
29308
  set: setCurrentScrollIndex
28931
29309
  },
28932
29310
  renderedCallback: renderedCallback,
28933
- onCtrlF: onCtrlF
29311
+ onCtrlF: onCtrlF,
29312
+ isModal: isModalMode
28934
29313
  });
28935
29314
  })))));
28936
29315
  }
28937
29316
  const ListBoxInlineMemoed = React.memo(ListBoxInline);
28938
- function IsolateUseLayoutWrapper(_ref5) {
29317
+ function IsolateUseLayoutWrapper(_ref6) {
28939
29318
  let {
28940
29319
  options = {}
28941
- } = _ref5;
29320
+ } = _ref6;
28942
29321
  const {
28943
29322
  model
28944
29323
  } = options;
@@ -34035,7 +34414,7 @@
34035
34414
  * Gets an event emitter instance for the visualization.
34036
34415
  * @entry
34037
34416
  * @experimental
34038
- * @returns {Emitter} The emitter instance.
34417
+ * @returns {Emitter} The emitter instance. Implements https://nodejs.org/api/events.html#class-eventemitter.
34039
34418
  * @example
34040
34419
  * // In a Nebula visualization
34041
34420
  * import { useEmitter } from '@nebula.js/stardust';