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

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.8
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 = "757e" ;
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.8" );
15632
15632
  element.setAttribute('data-app-id', app.id);
15633
15633
  document.body.appendChild(element);
15634
15634
  const root = client.createRoot(element);
@@ -21702,21 +21702,70 @@
21702
21702
  return elemNumbersOrdered.slice(min, max + 1);
21703
21703
  }
21704
21704
 
21705
+ const PREFIX$c = 'RowColumn';
21706
+ const rowColClasses = {
21707
+ row: "".concat(PREFIX$c, "-row"),
21708
+ rowBorderBottom: "".concat(PREFIX$c, "-rowBorderBottom"),
21709
+ column: "".concat(PREFIX$c, "-column"),
21710
+ fieldRoot: "".concat(PREFIX$c, "-fieldRoot"),
21711
+ cell: "".concat(PREFIX$c, "-cell"),
21712
+ labelText: "".concat(PREFIX$c, "-labelText"),
21713
+ labelDense: "".concat(PREFIX$c, "-labelDense"),
21714
+ highlighted: "".concat(PREFIX$c, "-highlighted"),
21715
+ checkboxLabel: "".concat(PREFIX$c, "-checkboxLabel"),
21716
+ icon: "".concat(PREFIX$c, "-icon"),
21717
+ S: "".concat(PREFIX$c, "-S"),
21718
+ XS: "".concat(PREFIX$c, "-XS"),
21719
+ A: "".concat(PREFIX$c, "-A"),
21720
+ X: "".concat(PREFIX$c, "-X"),
21721
+ frequencyCount: "".concat(PREFIX$c, "-frequencyCount"),
21722
+ barContainer: "".concat(PREFIX$c, "-barContainer"),
21723
+ bar: "".concat(PREFIX$c, "-bar"),
21724
+ barSelected: "".concat(PREFIX$c, "-barSelected"),
21725
+ barWithCheckbox: "".concat(PREFIX$c, "-barWithCheckbox"),
21726
+ barSelectedWithCheckbox: "".concat(PREFIX$c, "-barSelectedWithCheckbox"),
21727
+ excludedTextWithCheckbox: "".concat(PREFIX$c, "-excludedTextWithCheckbox")
21728
+ };
21729
+
21730
+ /* eslint-disable no-underscore-dangle */
21731
+ const dataItemSelector = ".".concat(rowColClasses.fieldRoot);
21705
21732
  const getKeyAsToggleSelected = event => !(event !== null && event !== void 0 && event.metaKey || event !== null && event !== void 0 && event.ctrlKey);
21706
21733
  function useSelectionsInteractions(_ref) {
21734
+ var _loaderRef$current2, _loaderRef$current2$_;
21707
21735
  let {
21708
21736
  selectionState,
21709
21737
  selections,
21710
21738
  checkboxes = false,
21711
- doc = document
21739
+ doc = document,
21740
+ loaderRef
21712
21741
  } = _ref;
21713
21742
  const currentSelect = reactExports.useRef({
21714
21743
  startElemNumber: undefined,
21715
21744
  elemNumbers: [],
21716
21745
  isRange: false,
21717
21746
  toggle: false,
21718
- active: false
21747
+ active: false,
21748
+ touchElemNumbers: [],
21749
+ touchRangeSmall: false
21719
21750
  });
21751
+ reactExports.useEffect(() => {
21752
+ var _loaderRef$current, _loaderRef$current$_l;
21753
+ if (!((_loaderRef$current = loaderRef.current) !== null && _loaderRef$current !== void 0 && (_loaderRef$current$_l = _loaderRef$current._listRef) !== null && _loaderRef$current$_l !== void 0 && _loaderRef$current$_l._outerRef)) {
21754
+ return undefined;
21755
+ }
21756
+ const preventGestureStart = e => e.preventDefault();
21757
+ const preventGestureChange = e => e.preventDefault();
21758
+ const preventGestureEnd = e => e.preventDefault();
21759
+ const listRef = loaderRef.current._listRef._outerRef;
21760
+ listRef.addEventListener('gesturestart', preventGestureStart);
21761
+ listRef.addEventListener('gesturechange', preventGestureChange);
21762
+ listRef.addEventListener('gestureend', preventGestureEnd);
21763
+ return () => {
21764
+ listRef.removeEventListener('gesturestart', preventGestureStart);
21765
+ listRef.removeEventListener('gesturechange', preventGestureChange);
21766
+ listRef.removeEventListener('gestureend', preventGestureEnd);
21767
+ };
21768
+ }, [(_loaderRef$current2 = loaderRef.current) === null || _loaderRef$current2 === void 0 ? void 0 : (_loaderRef$current2$_ = _loaderRef$current2._listRef) === null || _loaderRef$current2$_ === void 0 ? void 0 : _loaderRef$current2$_._outerRef]);
21720
21769
 
21721
21770
  // eslint-disable-next-line arrow-body-style
21722
21771
  const doSelect = () => {
@@ -21728,6 +21777,10 @@
21728
21777
  toggle: currentSelect.current.toggle
21729
21778
  });
21730
21779
  };
21780
+ const getRange = (start, end) => {
21781
+ const elemNumbersOrdered = getElemNumbersFromPages(selectionState.enginePages);
21782
+ return fillRange([start, end], elemNumbersOrdered);
21783
+ };
21731
21784
  const addToRange = elemNumber => {
21732
21785
  const {
21733
21786
  startElemNumber
@@ -21735,9 +21788,7 @@
21735
21788
  if (startElemNumber === elemNumber) {
21736
21789
  return;
21737
21790
  }
21738
- const rangeEnds = [currentSelect.current.startElemNumber, elemNumber];
21739
- const elemNumbersOrdered = getElemNumbersFromPages(selectionState.enginePages);
21740
- const toMaybeAdd = fillRange(rangeEnds, elemNumbersOrdered);
21791
+ const toMaybeAdd = getRange(currentSelect.current.startElemNumber, elemNumber);
21741
21792
  selectionState.updateItems(toMaybeAdd, true, currentSelect.current.elemNumbers);
21742
21793
  };
21743
21794
  const selectManually = function () {
@@ -21833,6 +21884,48 @@
21833
21884
  const elemNumber = +event.currentTarget.getAttribute('data-n');
21834
21885
  addToRange(elemNumber);
21835
21886
  }, []);
21887
+ const onTouchStart = reactExports.useCallback(event => {
21888
+ var _event$touches$0$targ, _event$touches$0$targ2, _event$touches$1$targ, _event$touches$1$targ2;
21889
+ // Handle range selection with two finger touch
21890
+ if (currentSelect.current.active || currentSelect.current.isRange || selectionState.isSingleSelect || event.touches.length <= 1) {
21891
+ return;
21892
+ }
21893
+ if (event.touches.length > 2) {
21894
+ doSelect();
21895
+ return;
21896
+ }
21897
+ const startTouchElemNumber = Number((_event$touches$0$targ = event.touches[0].target) === null || _event$touches$0$targ === void 0 ? void 0 : (_event$touches$0$targ2 = _event$touches$0$targ.closest(dataItemSelector)) === null || _event$touches$0$targ2 === void 0 ? void 0 : _event$touches$0$targ2.getAttribute('data-n'));
21898
+ const endTouchElemNumber = Number((_event$touches$1$targ = event.touches[1].target) === null || _event$touches$1$targ === void 0 ? void 0 : (_event$touches$1$targ2 = _event$touches$1$targ.closest(dataItemSelector)) === null || _event$touches$1$targ2 === void 0 ? void 0 : _event$touches$1$targ2.getAttribute('data-n'));
21899
+ if (Number.isNaN(startTouchElemNumber) || Number.isNaN(startTouchElemNumber)) {
21900
+ doSelect();
21901
+ return;
21902
+ }
21903
+ currentSelect.current.active = true;
21904
+ const range = getRange(startTouchElemNumber, endTouchElemNumber);
21905
+ if (range.length < 7) {
21906
+ currentSelect.current.touchRangeSmall = true;
21907
+ }
21908
+ currentSelect.current.elemNumbers = [];
21909
+ currentSelect.current.touchElemNumbers = [startTouchElemNumber, endTouchElemNumber];
21910
+ }, []);
21911
+ const onTouchEnd = reactExports.useCallback(() => {
21912
+ if (currentSelect.current.touchElemNumbers.length !== 2) {
21913
+ return;
21914
+ }
21915
+ if (currentSelect.current.touchRangeSmall) {
21916
+ currentSelect.current.touchRangeSmall = false;
21917
+ currentSelect.current.touchElemNumbers = [];
21918
+ currentSelect.current.active = false;
21919
+ return;
21920
+ }
21921
+ const [startTouchElemNumber, endTouchElemNumber] = currentSelect.current.touchElemNumbers;
21922
+ currentSelect.current.startElemNumber = startTouchElemNumber;
21923
+ addToRange(endTouchElemNumber);
21924
+ currentSelect.current.touchElemNumbers = [];
21925
+ currentSelect.current.active = false;
21926
+ currentSelect.current.toggle = true;
21927
+ doSelect();
21928
+ }, []);
21836
21929
  reactExports.useEffect(() => {
21837
21930
  doc.addEventListener('mouseup', onMouseUpDoc);
21838
21931
  return () => {
@@ -21865,7 +21958,9 @@
21865
21958
  Object.assign(interactionEvents, {
21866
21959
  onMouseUp,
21867
21960
  onMouseDown,
21868
- onMouseEnter
21961
+ onMouseEnter,
21962
+ onTouchStart,
21963
+ onTouchEnd
21869
21964
  });
21870
21965
  }
21871
21966
  return {
@@ -21979,6 +22074,84 @@
21979
22074
  isArrow: key => key === KEYS.ARROW_UP || key === KEYS.ARROW_DOWN || key === KEYS.ARROW_LEFT || key === KEYS.ARROW_RIGHT
21980
22075
  });
21981
22076
 
22077
+ function removeInnnerTabStops(container) {
22078
+ container === null || container === void 0 ? void 0 : container.querySelectorAll('[tabIndex="0"]').forEach(elm => {
22079
+ elm.setAttribute('tabIndex', -1);
22080
+ });
22081
+ }
22082
+ function removeLastFocused(container) {
22083
+ container === null || container === void 0 ? void 0 : container.querySelectorAll('.last-focused').forEach(elm => {
22084
+ elm.classList.remove('last-focused');
22085
+ });
22086
+ }
22087
+ function getVizCell(container) {
22088
+ return (container === null || container === void 0 ? void 0 : container.closest('.njs-cell')) || (container === null || container === void 0 ? void 0 : container.closest('.qv-gridcell'));
22089
+ }
22090
+
22091
+ // Emulate the keyboard hook, until we support it in the Listbox.
22092
+ function useTempKeyboard(_ref) {
22093
+ let {
22094
+ containerRef,
22095
+ enabled
22096
+ } = _ref;
22097
+ const [keyboardActive, setKeyboardActive] = reactExports.useState(false);
22098
+ const keyboard = {
22099
+ enabled,
22100
+ active: keyboardActive,
22101
+ // innerTabStops: whether keyboard permits inner tab stops
22102
+ // (inner = everything inside .listbox-container)
22103
+
22104
+ innerTabStops: !enabled || keyboardActive,
22105
+ blur(resetFocus) {
22106
+ var _containerRef$current;
22107
+ if (!enabled) {
22108
+ return;
22109
+ }
22110
+ setKeyboardActive(false);
22111
+ const vizCell = getVizCell(containerRef.current) || ((_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.parentElement);
22112
+ removeInnnerTabStops(containerRef.current);
22113
+ removeLastFocused(containerRef.current);
22114
+ if (resetFocus && vizCell) {
22115
+ // Move focus to the viz's cell.
22116
+ vizCell.setAttribute('tabIndex', 0);
22117
+ vizCell.focus();
22118
+ }
22119
+ },
22120
+ focus() {
22121
+ if (!enabled) {
22122
+ return;
22123
+ }
22124
+ setKeyboardActive(true);
22125
+ const c = containerRef.current;
22126
+ const searchField = c === null || c === void 0 ? void 0 : c.querySelector('.search input');
22127
+ const lastSelectedRow = c === null || c === void 0 ? void 0 : c.querySelector('.value.last-focused');
22128
+ const fieldElement = c === null || c === void 0 ? void 0 : c.querySelector('.value.selector, .value, .ActionsToolbar-item button');
22129
+ const elementToFocus = searchField || lastSelectedRow || fieldElement;
22130
+ elementToFocus === null || elementToFocus === void 0 ? void 0 : elementToFocus.setAttribute('tabIndex', 0);
22131
+ elementToFocus === null || elementToFocus === void 0 ? void 0 : elementToFocus.focus();
22132
+ },
22133
+ focusSelection() {
22134
+ const confirmButton = document.querySelector('.actions-toolbar-default-actions .actions-toolbar-confirm');
22135
+ confirmButton === null || confirmButton === void 0 ? void 0 : confirmButton.setAttribute('tabIndex', 0);
22136
+ confirmButton === null || confirmButton === void 0 ? void 0 : confirmButton.focus();
22137
+ }
22138
+ };
22139
+ return keyboard;
22140
+ }
22141
+
22142
+ /* eslint-disable no-param-reassign */
22143
+ const getElementIndex = currentTarget => +currentTarget.getAttribute('data-n');
22144
+ const focusSearch = container => {
22145
+ const searchField = container === null || container === void 0 ? void 0 : container.querySelector('.search input');
22146
+ searchField === null || searchField === void 0 ? void 0 : searchField.focus();
22147
+ return searchField;
22148
+ };
22149
+ const focusRow = container => {
22150
+ const row = container === null || container === void 0 ? void 0 : container.querySelector('.value.last-focused, .value.selector, .value');
22151
+ row === null || row === void 0 ? void 0 : row.setAttribute('tabIndex', 0);
22152
+ row === null || row === void 0 ? void 0 : row.focus();
22153
+ return row;
22154
+ };
21982
22155
  function getFieldKeyboardNavigation(_ref) {
21983
22156
  let {
21984
22157
  select,
@@ -21987,7 +22160,9 @@
21987
22160
  confirm,
21988
22161
  cancel,
21989
22162
  setScrollPosition,
21990
- focusListItems
22163
+ focusListItems,
22164
+ keyboard,
22165
+ isModal
21991
22166
  } = _ref;
21992
22167
  const getElement = function (elm) {
21993
22168
  let next = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
@@ -22000,49 +22175,86 @@
22000
22175
  };
22001
22176
  const handleKeyDown = event => {
22002
22177
  let elementToFocus;
22178
+ const {
22179
+ currentTarget,
22180
+ nativeEvent
22181
+ } = event;
22003
22182
  const {
22004
22183
  keyCode,
22005
22184
  shiftKey = false,
22006
22185
  ctrlKey = false,
22007
22186
  metaKey = false
22008
- } = event.nativeEvent;
22187
+ } = nativeEvent;
22009
22188
  switch (keyCode) {
22189
+ case KEYS.TAB:
22190
+ {
22191
+ // Try to focus search field, otherwise confirm button.
22192
+ const container = currentTarget.closest('.listbox-container');
22193
+ const inSelection = isModal();
22194
+
22195
+ // TODO: use a store to keep track of this row.
22196
+ currentTarget.classList.add('last-focused'); // so that we can go back here when we tab back
22197
+
22198
+ if (shiftKey) {
22199
+ if (!focusSearch(container)) {
22200
+ if (inSelection) {
22201
+ keyboard.focusSelection();
22202
+ } else {
22203
+ keyboard.blur(true);
22204
+ }
22205
+ }
22206
+ break;
22207
+ }
22208
+
22209
+ // Without shift key
22210
+ if (inSelection) {
22211
+ keyboard.focusSelection();
22212
+ } else {
22213
+ currentTarget.blur();
22214
+ keyboard.blur();
22215
+ }
22216
+ break;
22217
+ }
22010
22218
  case KEYS.SHIFT:
22011
22219
  // This is to ensure we include the first value when starting a range selection.
22012
22220
  setStartedRange(true);
22013
22221
  break;
22014
22222
  case KEYS.SPACE:
22015
- select([+event.currentTarget.getAttribute('data-n')], false, event);
22223
+ select([getElementIndex(currentTarget)], false, event);
22016
22224
  break;
22017
22225
  case KEYS.ARROW_DOWN:
22018
22226
  case KEYS.ARROW_RIGHT:
22019
- elementToFocus = getElement(event.currentTarget, true);
22227
+ elementToFocus = getElement(currentTarget, true);
22020
22228
  if (shiftKey && elementToFocus) {
22021
22229
  if (startedRange) {
22022
- select([+event.currentTarget.getAttribute('data-n')], true);
22230
+ select([getElementIndex(currentTarget)], true);
22023
22231
  setStartedRange(false);
22024
22232
  }
22025
- select([+elementToFocus.getAttribute('data-n')], true);
22233
+ select([getElementIndex(elementToFocus)], true);
22026
22234
  }
22027
22235
  break;
22028
22236
  case KEYS.ARROW_UP:
22029
22237
  case KEYS.ARROW_LEFT:
22030
- elementToFocus = getElement(event.currentTarget, false);
22238
+ elementToFocus = getElement(currentTarget, false);
22031
22239
  if (shiftKey && elementToFocus) {
22032
22240
  if (startedRange) {
22033
- select([+event.currentTarget.getAttribute('data-n')], true);
22241
+ select([getElementIndex(currentTarget)], true);
22034
22242
  setStartedRange(false);
22035
22243
  }
22036
- select([+elementToFocus.getAttribute('data-n')], true);
22244
+ select([getElementIndex(elementToFocus)], true);
22037
22245
  }
22038
22246
  break;
22039
22247
  case KEYS.ENTER:
22040
22248
  confirm();
22041
22249
  break;
22042
22250
  case KEYS.ESCAPE:
22043
- cancel();
22044
- return;
22045
- // let it propagate to top-level
22251
+ if (isModal()) {
22252
+ cancel();
22253
+ } else {
22254
+ return; // propagate to other Esc handler
22255
+ }
22256
+
22257
+ break;
22046
22258
  case KEYS.HOME:
22047
22259
  focusListItems.setFirst(true);
22048
22260
  if (ctrlKey) {
@@ -22086,159 +22298,154 @@
22086
22298
  }
22087
22299
  function getListboxInlineKeyboardNavigation(_ref2) {
22088
22300
  let {
22089
- setKeyboardActive,
22301
+ keyboard,
22090
22302
  hovering,
22091
- setHovering,
22092
22303
  updateKeyScroll,
22093
22304
  containerRef,
22094
22305
  currentScrollIndex,
22095
- app,
22096
- appSelections,
22306
+ isModal,
22097
22307
  constraints
22098
22308
  } = _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);
22309
+ const blur = event => {
22310
+ const {
22311
+ currentTarget,
22312
+ target
22313
+ } = event;
22314
+ const isFocusedOnListbox = target.classList.contains('listbox-container');
22315
+ const container = currentTarget.closest('.listbox-container');
22316
+ const vizCell = getVizCell(container);
22317
+ const isSingleListbox = (vizCell === null || vizCell === void 0 ? void 0 : vizCell.querySelectorAll('.listbox-container').length) === 1;
22318
+ if (isFocusedOnListbox || isSingleListbox) {
22319
+ // Move the focus from listbox container to the viz container.
22320
+ keyboard.blur(true);
22112
22321
  } 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();
22122
- }
22123
- };
22124
- const updateKeyScrollOnHover = newState => {
22125
- if (hovering) {
22126
- updateKeyScroll(newState);
22322
+ // More than one listbox: Move focus from row to listbox container.
22323
+
22324
+ // 1. Remove last-focused class from row siblings.
22325
+ removeLastFocused(containerRef.current);
22326
+
22327
+ // 2. Add last-focused class so we can re-focus it later.
22328
+ currentTarget.classList.add('last-focused');
22329
+
22330
+ // 3. Blur row and focus the listbox container.
22331
+ keyboard.blur();
22332
+ const c = currentTarget.closest('.listbox-container');
22333
+ c.setAttribute('tabIndex', 0);
22334
+ c === null || c === void 0 ? void 0 : c.focus();
22127
22335
  }
22128
22336
  };
22129
22337
  const handleKeyDown = event => {
22130
22338
  const {
22131
22339
  keyCode,
22132
- ctrlKey = false,
22133
22340
  shiftKey = false
22134
22341
  } = event.nativeEvent;
22342
+ const prevent = () => {
22343
+ event.stopPropagation();
22344
+ event.preventDefault();
22345
+ };
22346
+ if (!keyboard.enabled) {
22347
+ // Other keys should not be handled unless keyboard is enabled.
22348
+ return;
22349
+ }
22350
+ const container = event.currentTarget.closest('.listbox-container');
22351
+ const inSelection = isModal();
22135
22352
  switch (keyCode) {
22136
- // case KEYS.TAB: TODO: Focus confirm button using keyboard.focusSelection when we can access the useKeyboard hook.
22353
+ case KEYS.TAB:
22354
+ if (inSelection) {
22355
+ if (shiftKey) {
22356
+ focusRow(container) || focusSearch(container);
22357
+ } else {
22358
+ focusSearch(container) || focusRow(container);
22359
+ }
22360
+ } else if (shiftKey) {
22361
+ keyboard.blur(true);
22362
+ } else {
22363
+ break;
22364
+ }
22365
+ prevent();
22366
+ break;
22137
22367
  case KEYS.ENTER:
22138
22368
  case KEYS.SPACE:
22139
22369
  if (!event.target.classList.contains('listbox-container')) {
22140
- return; // don't mess with keydown handlers within the listbox
22370
+ break; // don't mess with keydown handlers within the listbox (e.g. row seletion)
22141
22371
  }
22142
22372
 
22143
- focusInsideListbox(event.currentTarget);
22373
+ keyboard.focus();
22374
+ prevent();
22144
22375
  break;
22145
22376
  case KEYS.ESCAPE:
22146
- changeFocus(event);
22377
+ blur(event);
22147
22378
  break;
22379
+ }
22380
+ };
22381
+ const globalKeyDown = event => {
22382
+ if (!hovering.current) {
22383
+ return;
22384
+ }
22385
+ const {
22386
+ keyCode,
22387
+ ctrlKey = false,
22388
+ shiftKey = false
22389
+ } = event;
22390
+ switch (keyCode) {
22148
22391
  case KEYS.ARROW_UP:
22149
- updateKeyScrollOnHover({
22392
+ updateKeyScroll({
22150
22393
  up: 1
22151
22394
  });
22152
22395
  break;
22153
22396
  case KEYS.ARROW_DOWN:
22154
- updateKeyScrollOnHover({
22397
+ updateKeyScroll({
22155
22398
  down: 1
22156
22399
  });
22157
22400
  break;
22158
- case KEYS.ARROW_LEFT:
22159
- case KEYS.ARROW_RIGHT:
22160
- return;
22161
- // let it propagate to top-level
22162
22401
  case KEYS.PAGE_UP:
22163
- updateKeyScrollOnHover({
22402
+ updateKeyScroll({
22164
22403
  up: currentScrollIndex.stop - currentScrollIndex.start
22165
22404
  });
22166
22405
  break;
22167
22406
  case KEYS.PAGE_DOWN:
22168
- updateKeyScrollOnHover({
22407
+ updateKeyScroll({
22169
22408
  down: currentScrollIndex.stop - currentScrollIndex.start
22170
22409
  });
22171
22410
  break;
22172
22411
  case KEYS.HOME:
22173
- updateKeyScrollOnHover({
22412
+ updateKeyScroll({
22174
22413
  scrollPosition: ctrlKey && shiftKey ? 'overflowStart' : 'start'
22175
22414
  });
22176
22415
  break;
22177
22416
  case KEYS.END:
22178
- updateKeyScrollOnHover({
22417
+ updateKeyScroll({
22179
22418
  scrollPosition: ctrlKey && shiftKey ? 'overflowEnd' : 'end'
22180
22419
  });
22181
22420
  break;
22182
22421
  default:
22183
22422
  return;
22184
22423
  }
22185
-
22186
- // Note: We should not stop propagation here as it will block the containing app
22187
- // from handling keydown events.
22188
22424
  event.preventDefault();
22189
22425
  };
22190
22426
  const focusOnHoverDisabled = () => {
22191
- var _app$isInModalSelecti, _app$isInModalSelecti2;
22192
22427
  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();
22428
+ const appInModal = isModal();
22194
22429
  return selectNotAllowed || appInModal;
22195
22430
  };
22196
22431
  const handleOnMouseEnter = () => {
22197
22432
  if (!focusOnHoverDisabled()) {
22198
- var _containerRef$current, _containerRef$current2;
22199
- setHovering(true);
22200
- containerRef === null || containerRef === void 0 ? void 0 : (_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : (_containerRef$current2 = _containerRef$current.focus) === null || _containerRef$current2 === void 0 ? void 0 : _containerRef$current2.call(_containerRef$current);
22433
+ hovering.current = true;
22201
22434
  }
22202
22435
  };
22203
22436
  const handleOnMouseLeave = () => {
22204
- if (hovering) {
22205
- var _containerRef$current3, _containerRef$current4;
22206
- setHovering(false);
22207
- containerRef === null || containerRef === void 0 ? void 0 : (_containerRef$current3 = containerRef.current) === null || _containerRef$current3 === void 0 ? void 0 : (_containerRef$current4 = _containerRef$current3.blur) === null || _containerRef$current4 === void 0 ? void 0 : _containerRef$current4.call(_containerRef$current3);
22437
+ if (hovering.current) {
22438
+ hovering.current = false;
22208
22439
  }
22209
22440
  };
22210
22441
  return {
22211
22442
  handleKeyDown,
22212
22443
  handleOnMouseEnter,
22213
- handleOnMouseLeave
22444
+ handleOnMouseLeave,
22445
+ globalKeyDown
22214
22446
  };
22215
22447
  }
22216
22448
 
22217
- const PREFIX$c = 'RowColumn';
22218
- const rowColClasses = {
22219
- row: "".concat(PREFIX$c, "-row"),
22220
- rowBorderBottom: "".concat(PREFIX$c, "-rowBorderBottom"),
22221
- column: "".concat(PREFIX$c, "-column"),
22222
- fieldRoot: "".concat(PREFIX$c, "-fieldRoot"),
22223
- cell: "".concat(PREFIX$c, "-cell"),
22224
- labelText: "".concat(PREFIX$c, "-labelText"),
22225
- labelDense: "".concat(PREFIX$c, "-labelDense"),
22226
- highlighted: "".concat(PREFIX$c, "-highlighted"),
22227
- checkboxLabel: "".concat(PREFIX$c, "-checkboxLabel"),
22228
- icon: "".concat(PREFIX$c, "-icon"),
22229
- S: "".concat(PREFIX$c, "-S"),
22230
- XS: "".concat(PREFIX$c, "-XS"),
22231
- A: "".concat(PREFIX$c, "-A"),
22232
- X: "".concat(PREFIX$c, "-X"),
22233
- frequencyCount: "".concat(PREFIX$c, "-frequencyCount"),
22234
- barContainer: "".concat(PREFIX$c, "-barContainer"),
22235
- bar: "".concat(PREFIX$c, "-bar"),
22236
- barSelected: "".concat(PREFIX$c, "-barSelected"),
22237
- barWithCheckbox: "".concat(PREFIX$c, "-barWithCheckbox"),
22238
- barSelectedWithCheckbox: "".concat(PREFIX$c, "-barSelectedWithCheckbox"),
22239
- excludedTextWithCheckbox: "".concat(PREFIX$c, "-excludedTextWithCheckbox")
22240
- };
22241
-
22242
22449
  const isExcluded = c => c ? c.qState === 'X' || c.qState === 'XS' || c.qState === 'XL' : null;
22243
22450
  const isAlternative = c => c ? c.qState === 'A' : null;
22244
22451
  const excludedOrAlternative = _ref => {
@@ -22878,13 +23085,15 @@
22878
23085
  dense,
22879
23086
  showGray
22880
23087
  } = _ref;
23088
+ const frequencyText = getFrequencyText(cell === null || cell === void 0 ? void 0 : cell.qFrequency);
22881
23089
  return /*#__PURE__*/React.createElement(Grid$1, {
22882
23090
  item: true,
22883
23091
  style: {
22884
23092
  display: 'flex',
22885
23093
  alignItems: 'center'
22886
23094
  },
22887
- className: rowColClasses.frequencyCount
23095
+ className: rowColClasses.frequencyCount,
23096
+ "aria-label": frequencyText
22888
23097
  }, /*#__PURE__*/React.createElement(Typography$1, {
22889
23098
  noWrap: true,
22890
23099
  color: "inherit",
@@ -22893,7 +23102,7 @@
22893
23102
  cell,
22894
23103
  checkboxes
22895
23104
  }) && rowColClasses.excludedTextWithCheckbox])
22896
- }, getFrequencyText(cell === null || cell === void 0 ? void 0 : cell.qFrequency)));
23105
+ }, frequencyText));
22897
23106
  }
22898
23107
 
22899
23108
  function getGridItemSizes(_ref) {
@@ -22930,7 +23139,7 @@
22930
23139
  }
22931
23140
 
22932
23141
  const ItemGrid = styled$1(Grid$1, {
22933
- shouldForwardProp: prop => !['dataLayout', 'layoutOrder', 'itemPadding', 'checkboxes'].includes(prop)
23142
+ shouldForwardProp: prop => !['dataLayout', 'layoutOrder', 'itemPadding', 'cellPaddingRight'].includes(prop)
22934
23143
  })(_ref => {
22935
23144
  let {
22936
23145
  dataLayout,
@@ -22965,6 +23174,79 @@
22965
23174
  return c;
22966
23175
  }
22967
23176
 
23177
+ /* eslint-disable import/prefer-default-export */
23178
+ const LOC_STATES = {
23179
+ S: 'Object.Listbox.Selected',
23180
+ A: 'Object.Listbox.Alternative',
23181
+ O: 'Object.Listbox.Optional',
23182
+ XS: 'Object.Listbox.SelectedExcluded',
23183
+ L: 'Object.Listbox.Locked',
23184
+ X: 'Object.Listbox.Excluded',
23185
+ XL: 'Object.Listbox.ExcludedLock'
23186
+ };
23187
+ function getValueLabel(_ref) {
23188
+ let {
23189
+ translator,
23190
+ label,
23191
+ qState,
23192
+ isSelected,
23193
+ currentIndex,
23194
+ maxIndex,
23195
+ showSearch
23196
+ } = _ref;
23197
+ const stateTranslation = LOC_STATES[qState];
23198
+ const state = translator.get(stateTranslation);
23199
+ const srStringArr = [];
23200
+ if (isSelected) {
23201
+ const navTranslation = showSearch ? 'Listbox.ScreenReader.SearchThenSelectionsMenu.WithAccSelMenu' : 'Listbox.ScreenReader.SelectionMenu.WithAccSelMenu';
23202
+ const nav = translator.get(navTranslation);
23203
+ srStringArr.push(nav);
23204
+ }
23205
+ const valueString = "".concat(label, " ").concat(state);
23206
+ const indexString = translator.get('CurrentSelections.Of', [currentIndex + 1, maxIndex + 1]); // E.g. 3 of 20
23207
+ srStringArr.unshift(valueString, indexString);
23208
+ const srString = srStringArr.join('. ').trim();
23209
+ return srString;
23210
+ }
23211
+
23212
+ /**
23213
+ * Announces the selection state.
23214
+ *
23215
+ * @ignore
23216
+ * @param {Layout} object
23217
+ * @returns {Element} An (invisible) component.
23218
+ */
23219
+ function ScreenReaderForSelections(_ref2) {
23220
+ var _layout$qListObject;
23221
+ let {
23222
+ layout
23223
+ } = _ref2;
23224
+ const {
23225
+ translator
23226
+ } = reactExports.useContext(InstanceContext);
23227
+ const {
23228
+ qStateCounts: s = {}
23229
+ } = (layout === null || layout === void 0 ? void 0 : (_layout$qListObject = layout.qListObject) === null || _layout$qListObject === void 0 ? void 0 : _layout$qListObject.qDimensionInfo) || {};
23230
+ const count = s.qSelected + s.qSelectedExcluded + s.qLocked + s.qLockedExcluded;
23231
+ let t;
23232
+ switch (count) {
23233
+ case 0:
23234
+ t = 'ScreenReader.ZeroSelected';
23235
+ break;
23236
+ case 1:
23237
+ t = 'ScreenReader.OneSelected';
23238
+ break;
23239
+ default:
23240
+ t = 'ScreenReader.ManySelected';
23241
+ break;
23242
+ }
23243
+ const text = translator.get(t, [count]);
23244
+ return /*#__PURE__*/React.createElement("div", {
23245
+ className: "screenReaderOnly",
23246
+ "aria-live": "assertive"
23247
+ }, text);
23248
+ }
23249
+
22968
23250
  function RowColumn(_ref) {
22969
23251
  var _cell$qText, _cell$qHighlightRange, _cell$qHighlightRange2;
22970
23252
  let {
@@ -22980,6 +23262,8 @@
22980
23262
  onMouseDown,
22981
23263
  onMouseUp,
22982
23264
  onMouseEnter,
23265
+ onTouchStart,
23266
+ onTouchEnd,
22983
23267
  pages,
22984
23268
  isLocked,
22985
23269
  column = false,
@@ -23001,7 +23285,10 @@
23001
23285
  focusListItems,
23002
23286
  listCount,
23003
23287
  itemPadding,
23004
- frequencyWidth
23288
+ frequencyWidth,
23289
+ translator,
23290
+ showSearch,
23291
+ isModal
23005
23292
  } = data;
23006
23293
  const {
23007
23294
  dense = false,
@@ -23051,8 +23338,10 @@
23051
23338
  }
23052
23339
  }, [rowRef.current]);
23053
23340
  const handleKeyDownCallback = reactExports.useCallback(getFieldKeyboardNavigation(_objectSpread2(_objectSpread2({}, actions), {}, {
23054
- focusListItems
23055
- })), [actions]);
23341
+ focusListItems,
23342
+ keyboard,
23343
+ isModal
23344
+ })), [actions, keyboard === null || keyboard === void 0 ? void 0 : keyboard.innerTabStops]);
23056
23345
  const cell = reactExports.useMemo(() => getCellFromPages({
23057
23346
  pages,
23058
23347
  cellIndex
@@ -23117,6 +23406,14 @@
23117
23406
  const showTick = !checkboxes && isSelected && !isLocked;
23118
23407
  const showIcon = !checkboxes && sizePermitsTickOrLock;
23119
23408
  const cellPaddingRight = checkboxes || !sizePermitsTickOrLock;
23409
+ const ariaLabel = getValueLabel({
23410
+ translator,
23411
+ label,
23412
+ qState: cell.qState,
23413
+ currentIndex: count.currentIndex,
23414
+ maxIndex: count.max,
23415
+ showSearch
23416
+ });
23120
23417
  return /*#__PURE__*/React.createElement(RowColRoot$1, {
23121
23418
  className: rowColClasses.barContainer,
23122
23419
  flexBasisProp: flexBasisVal,
@@ -23127,6 +23424,11 @@
23127
23424
  frequencyWidth: frequencyWidth,
23128
23425
  "data-testid": "listbox.item"
23129
23426
  }, /*#__PURE__*/React.createElement(ItemGrid, {
23427
+ role: "row",
23428
+ "aria-label": ariaLabel,
23429
+ "aria-selected": isSelected,
23430
+ "aria-setsize": count.max,
23431
+ "aria-rowindex": count.currentIndex,
23130
23432
  ref: rowRef,
23131
23433
  container: true,
23132
23434
  dataLayout: dataLayout,
@@ -23143,9 +23445,10 @@
23143
23445
  onMouseUp: onMouseUp,
23144
23446
  onMouseEnter: onMouseEnter,
23145
23447
  onKeyDown: handleKeyDownCallback,
23448
+ onTouchStart: onTouchStart,
23449
+ onTouchEnd: onTouchEnd,
23146
23450
  onContextMenu: preventContextMenu,
23147
- role: column ? 'column' : 'row',
23148
- tabIndex: isFirstElement && (!keyboard.enabled || keyboard.active) ? 0 : -1,
23451
+ tabIndex: isFirstElement && keyboard.innerTabStops ? 0 : -1,
23149
23452
  "data-n": cell === null || cell === void 0 ? void 0 : cell.qElemNumber
23150
23453
  }, (cell === null || cell === void 0 ? void 0 : cell.qFrequency) && /*#__PURE__*/React.createElement(Histogram, {
23151
23454
  qFrequency: cell === null || cell === void 0 ? void 0 : cell.qFrequency,
@@ -24761,7 +25064,10 @@
24761
25064
  setCurrentScrollIndex,
24762
25065
  constraints,
24763
25066
  frequencyMax,
24764
- freqIsAllowed
25067
+ freqIsAllowed,
25068
+ translator,
25069
+ showSearch,
25070
+ isModal
24765
25071
  } = _ref;
24766
25072
  const {
24767
25073
  layoutOptions = {}
@@ -24815,7 +25121,10 @@
24815
25121
  showTick,
24816
25122
  dataOffset: local.current.dataOffset,
24817
25123
  focusListItems,
24818
- direction
25124
+ direction,
25125
+ translator,
25126
+ showSearch,
25127
+ isModal
24819
25128
  });
24820
25129
  const List = _ref2 => {
24821
25130
  let {
@@ -25257,17 +25566,14 @@
25257
25566
  };
25258
25567
  }
25259
25568
 
25260
- function ListBoxDisclaimer(_ref) {
25569
+ const StyledText = styled$1(Typography$1, {
25570
+ shouldForwardProp: p => !['width', 'dense'].includes(p)
25571
+ })(_ref => {
25261
25572
  let {
25262
25573
  width,
25263
- text,
25264
- dense,
25265
- tooltip
25574
+ dense
25266
25575
  } = _ref;
25267
- const {
25268
- translator
25269
- } = reactExports.useContext(InstanceContext);
25270
- const StyledText = styled$1(Typography$1)(() => _objectSpread2({
25576
+ return _objectSpread2({
25271
25577
  minWidth: "".concat(width, "px"),
25272
25578
  textAlign: 'center',
25273
25579
  fontSize: "".concat(dense ? '12px' : '14px')
@@ -25276,10 +25582,23 @@
25276
25582
  overflow: 'hidden',
25277
25583
  whiteSpace: 'nowrap',
25278
25584
  width
25279
- }));
25585
+ });
25586
+ });
25587
+ function ListBoxDisclaimer(_ref2) {
25588
+ let {
25589
+ width,
25590
+ text,
25591
+ dense,
25592
+ tooltip
25593
+ } = _ref2;
25594
+ const {
25595
+ translator
25596
+ } = reactExports.useContext(InstanceContext);
25280
25597
  return /*#__PURE__*/React.createElement(Tooltip$1, {
25281
25598
  title: tooltip ? translator.get(text) : ''
25282
25599
  }, /*#__PURE__*/React.createElement(StyledText, {
25600
+ width: width,
25601
+ dense: dense,
25283
25602
  component: "div",
25284
25603
  variant: "body1",
25285
25604
  py: "12px"
@@ -25501,6 +25820,14 @@
25501
25820
 
25502
25821
  const _excluded$4 = ["isLoadingData"];
25503
25822
  const DEFAULT_MIN_BATCH_SIZE = 100;
25823
+ const StyledWrapper = styled$1('div')(() => ({
25824
+ ["& .screenReaderOnly"]: {
25825
+ position: 'absolute',
25826
+ height: 0,
25827
+ width: 0,
25828
+ overflow: 'hidden'
25829
+ }
25830
+ }));
25504
25831
  function ListBox(_ref) {
25505
25832
  var _layout$qListObject$q, _loaderRef$current, _loaderRef$current$_l, _loaderRef$current$_l2;
25506
25833
  let {
@@ -25531,8 +25858,13 @@
25531
25858
  set: () => {}
25532
25859
  },
25533
25860
  renderedCallback,
25534
- onCtrlF
25861
+ onCtrlF,
25862
+ showSearch,
25863
+ isModal
25535
25864
  } = _ref;
25865
+ const {
25866
+ translator
25867
+ } = reactExports.useContext(InstanceContext);
25536
25868
  const [initScrollPosIsSet, setInitScrollPosIsSet] = reactExports.useState(false);
25537
25869
  const isSingleSelect = !!(layout && layout.qListObject.qDimensionInfo.qIsOneAndOnlyOne);
25538
25870
  const {
@@ -25606,7 +25938,8 @@
25606
25938
  selectionState,
25607
25939
  selections,
25608
25940
  checkboxes,
25609
- doc: document
25941
+ doc: document,
25942
+ loaderRef
25610
25943
  });
25611
25944
  const {
25612
25945
  layoutOptions = {}
@@ -25787,7 +26120,10 @@
25787
26120
  setCurrentScrollIndex: currentScrollIndex.set,
25788
26121
  constraints,
25789
26122
  frequencyMax,
25790
- freqIsAllowed
26123
+ freqIsAllowed,
26124
+ translator,
26125
+ showSearch,
26126
+ isModal
25791
26127
  });
25792
26128
  const {
25793
26129
  columnWidth,
@@ -25802,7 +26138,10 @@
25802
26138
  itemHeight
25803
26139
  });
25804
26140
  }
25805
- return /*#__PURE__*/React.createElement(React.Fragment, null, !listCount && /*#__PURE__*/React.createElement(ListBoxDisclaimer, {
26141
+ return /*#__PURE__*/React.createElement(StyledWrapper, null, /*#__PURE__*/React.createElement(ScreenReaderForSelections, {
26142
+ className: "screenReaderOnly",
26143
+ layout: layout
26144
+ }), !listCount && /*#__PURE__*/React.createElement(ListBoxDisclaimer, {
25806
26145
  width: width,
25807
26146
  text: "Listbox.NoMatchesForYourTerms"
25808
26147
  }), /*#__PURE__*/React.createElement(InfiniteLoader, {
@@ -25814,7 +26153,8 @@
25814
26153
  }),
25815
26154
  threshold: 0,
25816
26155
  minimumBatchSize: minimumBatchSize,
25817
- ref: loaderRef
26156
+ ref: loaderRef,
26157
+ role: "grid"
25818
26158
  }, isVertical ? List : Grid), overflowDisclaimer.show && !overflowDisclaimer.dismissed && /*#__PURE__*/React.createElement(ListBoxFooter, {
25819
26159
  text: "Listbox.ItemsOverflow",
25820
26160
  dismiss: () => setOverflowDisclaimer(state => _objectSpread2(_objectSpread2({}, state), {}, {
@@ -25966,6 +26306,7 @@
25966
26306
  if (hidden) return null;
25967
26307
  const spacing = Number.parseInt(theme.spacing(0.5), 10);
25968
26308
  const handleKeyDown = item.keyboardAction ? e => ['Enter', ' ', 'Spacebar'].includes(e.key) && item.keyboardAction() : null;
26309
+ const btnId = "actions-toolbar-".concat(item.key);
25969
26310
  return /*#__PURE__*/React.createElement(IconButton$1, {
25970
26311
  ref: !addAnchor ? ref : null,
25971
26312
  title: item.label,
@@ -25973,12 +26314,12 @@
25973
26314
  onKeyDown: handleKeyDown,
25974
26315
  disabled: disabled,
25975
26316
  style: style,
25976
- className: ActionElement.className,
26317
+ className: [ActionElement.className, btnId].join(' '),
25977
26318
  size: "large",
25978
26319
  disableRipple: true,
25979
26320
  "aria-expanded": ariaExpanded,
25980
26321
  "aria-controls": "moreMenuList",
25981
- "data-testid": "actions-toolbar-".concat(item.key)
26322
+ "data-testid": btnId
25982
26323
  }, hasSvgIconShape && SvgIcon(item.getSvgIconShape()), addAnchor && /*#__PURE__*/React.createElement("div", {
25983
26324
  ref: ref,
25984
26325
  style: {
@@ -26157,6 +26498,70 @@
26157
26498
  }))));
26158
26499
  });
26159
26500
 
26501
+ const getActionButtonIndex = btn => {
26502
+ const toolbar = btn.closest('#actions-toolbar');
26503
+ const nodeList = toolbar === null || toolbar === void 0 ? void 0 : toolbar.querySelectorAll('.njs-cell-action');
26504
+ return Array.from(nodeList).indexOf(btn);
26505
+ };
26506
+ const focusButton = index => {
26507
+ const toolbar = document.querySelector('#actions-toolbar');
26508
+ const nodeList = toolbar === null || toolbar === void 0 ? void 0 : toolbar.querySelectorAll('.njs-cell-action');
26509
+ if (!nodeList.length) {
26510
+ return;
26511
+ }
26512
+ const ix = Math.min(Math.max(0, index), nodeList.length - 1);
26513
+ const btn = nodeList[ix];
26514
+ btn.focus();
26515
+ };
26516
+ function getActionsKeyDownHandler(_ref) {
26517
+ let {
26518
+ keyboardNavigation,
26519
+ focusHandler,
26520
+ getEnabledButton
26521
+ } = _ref;
26522
+ const handleActionsKeyDown = evt => {
26523
+ const {
26524
+ target,
26525
+ nativeEvent
26526
+ } = evt;
26527
+ const {
26528
+ keyCode
26529
+ } = nativeEvent;
26530
+ switch (keyCode) {
26531
+ case KEYS.ARROW_LEFT:
26532
+ case KEYS.ARROW_DOWN:
26533
+ case KEYS.ARROW_RIGHT:
26534
+ case KEYS.ARROW_UP:
26535
+ {
26536
+ const isActionButton = target.classList.contains('njs-cell-action');
26537
+ if (isActionButton) {
26538
+ const index = getActionButtonIndex(target);
26539
+ const pressedLeft = [KEYS.ARROW_LEFT, KEYS.ARROW_DOWN].includes(keyCode);
26540
+ focusButton(pressedLeft ? index - 1 : index + 1);
26541
+ }
26542
+ evt.stopPropagation();
26543
+ evt.preventDefault();
26544
+ break;
26545
+ }
26546
+ case KEYS.SPACE:
26547
+ evt.preventDefault(); // prevent scrolling in listbox
26548
+ break;
26549
+ case KEYS.TAB:
26550
+ if (keyboardNavigation && focusHandler !== null && focusHandler !== void 0 && focusHandler.refocusContent) {
26551
+ const isTabbingOut = evt.shiftKey && getEnabledButton(false) === evt.target || !evt.shiftKey && getEnabledButton(true) === evt.target;
26552
+ if (isTabbingOut) {
26553
+ evt.preventDefault();
26554
+ evt.stopPropagation();
26555
+ // if keyboardNavigation is true, create a callback to handle tabbing from the first/last button in the toolbar that resets focus on the content
26556
+ focusHandler.refocusContent();
26557
+ }
26558
+ }
26559
+ break;
26560
+ }
26561
+ };
26562
+ return handleActionsKeyDown;
26563
+ }
26564
+
26160
26565
  const PREFIX$7 = 'ActionsToolbar';
26161
26566
  const classes$7 = {
26162
26567
  item: "".concat(PREFIX$7, "-item"),
@@ -26192,6 +26597,7 @@
26192
26597
  };
26193
26598
  const ActionsGroup = React.forwardRef((_ref2, ref) => {
26194
26599
  let {
26600
+ className,
26195
26601
  ariaExpanded = false,
26196
26602
  actions = [],
26197
26603
  first = false,
@@ -26204,7 +26610,8 @@
26204
26610
  container: true,
26205
26611
  gap: 0,
26206
26612
  flexDirection: isRtl ? 'row-reverse' : 'row',
26207
- wrap: "nowrap"
26613
+ wrap: "nowrap",
26614
+ className: className
26208
26615
  }, actions.map((e, ix) => {
26209
26616
  let cls = [];
26210
26617
  const isFirstItem = first && ix === 0;
@@ -26272,22 +26679,27 @@
26272
26679
  keyboardNavigation
26273
26680
  } = reactExports.useContext(InstanceContext);
26274
26681
  const [showMoreItems, setShowMoreItems] = reactExports.useState(false);
26275
- const moreRef = reactExports.useRef();
26682
+ const popoverAnchorOrigin = {
26683
+ vertical: 7,
26684
+ 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
26685
+ };
26276
26686
  const actionsRef = reactExports.useRef();
26687
+ const moreRef = reactExports.useRef();
26277
26688
  const theme = useTheme$1();
26278
26689
  const dividerStyle = reactExports.useMemo(() => ({
26279
26690
  margin: theme.spacing(0.5, 0)
26280
26691
  }));
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
26692
  const getEnabledButton = last => {
26286
26693
  const actionsElement = actionsRef.current || actionsRefMock;
26287
26694
  if (!actionsElement) return null;
26288
26695
  const buttons = actionsElement.querySelectorAll('button:not(.Mui-disabled)');
26289
26696
  return buttons[last ? buttons.length - 1 : 0];
26290
26697
  };
26698
+ const handleActionsKeyDown = reactExports.useMemo(() => getActionsKeyDownHandler({
26699
+ keyboardNavigation,
26700
+ focusHandler,
26701
+ getEnabledButton
26702
+ }), [keyboardNavigation, focusHandler, getEnabledButton]);
26291
26703
  reactExports.useEffect(() => () => {
26292
26704
  setShowMoreItems(false);
26293
26705
  }, [popover.show, show, selections.show]);
@@ -26327,27 +26739,18 @@
26327
26739
  enabled: () => moreEnabled,
26328
26740
  action: () => setShowMoreItems(!showMoreItems)
26329
26741
  };
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
26742
  const showActions = newActions.length > 0;
26342
26743
  const showMore = moreActions.length > 0;
26343
26744
  const showDivider = showActions && selections.show || showMore && selections.show;
26344
26745
  const isRtl = direction === 'rtl';
26345
26746
  const Actions = /*#__PURE__*/React.createElement(Grid$1, {
26346
26747
  ref: actionsRef,
26347
- onKeyDown: tabCallback,
26748
+ onKeyDown: handleActionsKeyDown,
26348
26749
  container: true,
26349
26750
  gap: 0,
26350
26751
  wrap: "nowrap",
26752
+ id: "actions-toolbar",
26753
+ "data-testid": "actions-toolbar",
26351
26754
  sx: {
26352
26755
  flexDirection: isRtl ? 'row-reverse' : 'row'
26353
26756
  }
@@ -26356,6 +26759,8 @@
26356
26759
  first: true,
26357
26760
  last: !showMore && !selections.show
26358
26761
  }), showMore && /*#__PURE__*/React.createElement(ActionsGroup, {
26762
+ id: "actions-toolbar-show-more",
26763
+ "data-testid": "actions-toolbar-show-more",
26359
26764
  ref: moreRef,
26360
26765
  ariaExpanded: showMoreItems,
26361
26766
  actions: [moreItem],
@@ -26369,6 +26774,7 @@
26369
26774
  }, /*#__PURE__*/React.createElement(Divider$1, {
26370
26775
  orientation: "vertical"
26371
26776
  })), selections.show && /*#__PURE__*/React.createElement(ActionsGroup, {
26777
+ className: "actions-toolbar-default-actions",
26372
26778
  actions: defaultSelectionActions,
26373
26779
  first: !showActions && !showMore,
26374
26780
  last: true,
@@ -26392,6 +26798,8 @@
26392
26798
  hideBackdrop: true,
26393
26799
  style: popoverStyle,
26394
26800
  PaperProps: {
26801
+ id: 'njs-action-toolbar-popover',
26802
+ 'data-testid': 'njs-action-toolbar-popover',
26395
26803
  className: ActionToolbarElement.className,
26396
26804
  style: {
26397
26805
  pointerEvents: 'auto',
@@ -26519,29 +26927,57 @@
26519
26927
  }
26520
26928
  return response;
26521
26929
  };
26930
+ function focusRow(container) {
26931
+ 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'));
26932
+ row.setAttribute('tabIndex', 0);
26933
+ row === null || row === void 0 ? void 0 : row.focus();
26934
+ }
26522
26935
  const onKeyDown = async e => {
26523
- let response;
26936
+ const {
26937
+ currentTarget
26938
+ } = e;
26939
+ const container = currentTarget.closest('.listbox-container');
26524
26940
  switch (e.key) {
26525
26941
  case 'Enter':
26526
- response = await performSearch();
26942
+ performSearch();
26527
26943
  break;
26528
26944
  case 'Escape':
26529
- response = cancel();
26530
- e.preventDefault();
26531
- e.stopPropagation();
26532
- break;
26945
+ {
26946
+ focusRow(container);
26947
+ cancel();
26948
+ break;
26949
+ }
26950
+ case 'Tab':
26951
+ {
26952
+ if (e.shiftKey) {
26953
+ keyboard.focusSelection();
26954
+ } else {
26955
+ // Focus the row we last visited or the first one.
26956
+ focusRow(container);
26957
+
26958
+ // Clean up.
26959
+ container === null || container === void 0 ? void 0 : container.querySelectorAll('.last-focused').forEach(elm => {
26960
+ elm.classList.remove('last-focused');
26961
+ });
26962
+ }
26963
+ break;
26964
+ }
26533
26965
  case 'f':
26534
26966
  case 'F':
26535
26967
  if (e.ctrlKey || e.metaKey) {
26536
26968
  if (hide) {
26537
26969
  hide();
26538
26970
  }
26539
- e.preventDefault();
26540
- e.stopPropagation();
26971
+ } else {
26972
+ return undefined;
26541
26973
  }
26542
26974
  break;
26975
+ default:
26976
+ return undefined;
26543
26977
  }
26544
- return response;
26978
+ e.preventDefault();
26979
+ e.stopPropagation();
26980
+ return undefined;
26545
26981
  };
26546
26982
  if (!visible || searchEnabled === false) {
26547
26983
  return null;
@@ -26587,10 +27023,11 @@
26587
27023
  onKeyDown: onKeyDown,
26588
27024
  autoFocus: autoFocus,
26589
27025
  inputProps: {
26590
- tabIndex: keyboard && (!keyboard.enabled || keyboard.active) ? 0 : -1,
27026
+ tabIndex: keyboard.innerTabStops ? 0 : -1,
26591
27027
  style: {
26592
27028
  textAlign: "".concat(inpuTextAlign)
26593
- }
27029
+ },
27030
+ 'data-testid': 'search-input-field'
26594
27031
  }
26595
27032
  });
26596
27033
  }
@@ -26834,6 +27271,12 @@
26834
27271
  objectSelections.addListener('activated', activateClickOut);
26835
27272
  objectSelections.addListener('deactivated', deactivateClickOut);
26836
27273
  return () => {
27274
+ // confirm selection before removing event handler
27275
+ // to end the selection when the object is removed
27276
+ // and remove the (ClickOut) mousedown handler from the document
27277
+ if (objectSelections.isActive()) {
27278
+ objectSelections.confirm();
27279
+ }
26837
27280
  objectSelections.removeListener('activated', activateClickOut);
26838
27281
  objectSelections.removeListener('deactivated', deactivateClickOut);
26839
27282
  };
@@ -28438,6 +28881,7 @@
28438
28881
  };
28439
28882
  };
28440
28883
 
28884
+ /* eslint-disable no-nested-ternary */
28441
28885
  function showToolbarDetached(_ref) {
28442
28886
  var _containerRef$current, _containerRef$current2, _titleRef$current$cli, _titleRef$current, _titleRef$current2, _titleRef$current3;
28443
28887
  let {
@@ -28451,12 +28895,17 @@
28451
28895
  const actionToolbarWidth = 128;
28452
28896
  const notSufficientSpace = containerWidth < contentWidth + actionToolbarWidth;
28453
28897
  const isTruncated = (titleRef === null || titleRef === void 0 ? void 0 : (_titleRef$current2 = titleRef.current) === null || _titleRef$current2 === void 0 ? void 0 : _titleRef$current2.scrollWidth) > (titleRef === null || titleRef === void 0 ? void 0 : (_titleRef$current3 = titleRef.current) === null || _titleRef$current3 === void 0 ? void 0 : _titleRef$current3.offsetWidth);
28454
- return !!(notSufficientSpace | isTruncated);
28898
+ const isDetached = !!(notSufficientSpace | isTruncated);
28899
+ const reasonDetached = isDetached ? notSufficientSpace ? 'noSpace' : 'truncated' : '';
28900
+ return {
28901
+ isDetached,
28902
+ reasonDetached
28903
+ };
28455
28904
  }
28456
28905
 
28457
28906
  function getListboxActionProps(_ref) {
28458
28907
  let {
28459
- isPopover,
28908
+ isDetached,
28460
28909
  showToolbar,
28461
28910
  containerRef,
28462
28911
  isLocked,
@@ -28464,9 +28913,9 @@
28464
28913
  selections
28465
28914
  } = _ref;
28466
28915
  return {
28467
- show: showToolbar && !isPopover,
28916
+ show: showToolbar && !isDetached,
28468
28917
  popover: {
28469
- show: showToolbar && isPopover,
28918
+ show: showToolbar && isDetached,
28470
28919
  anchorEl: containerRef.current
28471
28920
  },
28472
28921
  more: {
@@ -28489,6 +28938,13 @@
28489
28938
  };
28490
28939
  }
28491
28940
 
28941
+ const StyledDiv = styled$1('div')(() => ({
28942
+ display: 'flex',
28943
+ width: '100%',
28944
+ height: '100%',
28945
+ alignItems: 'center',
28946
+ justifyContent: 'center'
28947
+ }));
28492
28948
  function ListBoxError(_ref) {
28493
28949
  let {
28494
28950
  text
@@ -28496,13 +28952,6 @@
28496
28952
  const {
28497
28953
  translator
28498
28954
  } = 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
28955
  return /*#__PURE__*/React.createElement(StyledDiv, null, translator.get(text));
28507
28956
  }
28508
28957
 
@@ -28537,7 +28986,7 @@
28537
28986
  ["& .".concat(classes$4.listboxWrapper)]: {
28538
28987
  padding: containerPadding
28539
28988
  },
28540
- '&:focus:not(:hover)': {
28989
+ '&:focus': {
28541
28990
  boxShadow: "inset 0 0 0 2px ".concat(theme.palette.custom.focusBorder, " !important")
28542
28991
  },
28543
28992
  '&:focus-visible': {
@@ -28557,12 +29006,20 @@
28557
29006
  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
29007
  };
28559
29008
  });
28560
- function ListBoxInline(_ref3) {
29009
+ const isModal = _ref3 => {
29010
+ var _app$isInModalSelecti, _app$isInModalSelecti2;
29011
+ let {
29012
+ app,
29013
+ appSelections
29014
+ } = _ref3;
29015
+ 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();
29016
+ };
29017
+ function ListBoxInline(_ref4) {
28561
29018
  var _layoutOptions$dense;
28562
29019
  let {
28563
29020
  options,
28564
29021
  layout
28565
- } = _ref3;
29022
+ } = _ref4;
28566
29023
  const {
28567
29024
  app,
28568
29025
  direction,
@@ -28581,7 +29038,8 @@
28581
29038
  showGray = true,
28582
29039
  scrollState = undefined,
28583
29040
  renderedCallback,
28584
- toolbar = true
29041
+ toolbar = true,
29042
+ isPopover = false
28585
29043
  } = options;
28586
29044
 
28587
29045
  // Hook that will trigger update when used in useEffects.
@@ -28610,8 +29068,7 @@
28610
29068
  const [searchContainer, searchContainerRef] = useRefWithCallback();
28611
29069
  const [showToolbar, setShowToolbar] = reactExports.useState(false);
28612
29070
  const [showSearch, setShowSearch] = reactExports.useState(false);
28613
- const [keyboardActive, setKeyboardActive] = reactExports.useState(false);
28614
- const [hovering, setHovering] = reactExports.useState(false);
29071
+ const hovering = reactExports.useRef(false);
28615
29072
  const [keyScroll, setKeyScroll] = reactExports.useState({
28616
29073
  down: 0,
28617
29074
  up: 0,
@@ -28625,32 +29082,40 @@
28625
29082
  const [appSelections] = useAppSelections(app);
28626
29083
  const titleRef = reactExports.useRef(null);
28627
29084
  const [selectionState$1] = reactExports.useState(() => selectionState());
29085
+ const keyboard = useTempKeyboard({
29086
+ containerRef,
29087
+ enabled: keyboardNavigation
29088
+ });
29089
+ const isModalMode = reactExports.useCallback(() => isModal({
29090
+ app,
29091
+ appSelections
29092
+ }), [app, appSelections]);
28628
29093
  const isInvalid = layout === null || layout === void 0 ? void 0 : layout.qListObject.qDimensionInfo.qError;
28629
29094
  const errorText = isInvalid && constraints.active ? 'Visualization.Invalid.Dimension' : 'Visualization.Incomplete';
28630
29095
  const {
28631
29096
  handleKeyDown,
28632
29097
  handleOnMouseEnter,
28633
- handleOnMouseLeave
28634
- } = getListboxInlineKeyboardNavigation({
28635
- setKeyboardActive,
29098
+ handleOnMouseLeave,
29099
+ globalKeyDown
29100
+ } = reactExports.useMemo(() => getListboxInlineKeyboardNavigation({
29101
+ keyboard,
28636
29102
  hovering,
28637
- setHovering,
28638
29103
  updateKeyScroll,
28639
29104
  containerRef,
28640
29105
  currentScrollIndex,
28641
29106
  app,
28642
29107
  appSelections,
28643
- constraints
28644
- });
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
- const showDetachedToolbarOnly = toolbar && ((layout === null || layout === void 0 ? void 0 : layout.title) === '' || (layout === null || layout === void 0 ? void 0 : layout.showTitle) === false);
28653
- const showToolbarWithTitle = toolbar && (layout === null || layout === void 0 ? void 0 : layout.title) !== '' && (layout === null || layout === void 0 ? void 0 : layout.showTitle) !== false;
29108
+ constraints,
29109
+ isModal: isModalMode
29110
+ }), [keyboard, hovering, updateKeyScroll, containerRef, currentScrollIndex, app, appSelections, constraints, isModalMode]);
29111
+ const showDetachedToolbarOnly = toolbar && ((layout === null || layout === void 0 ? void 0 : layout.title) === '' || (layout === null || layout === void 0 ? void 0 : layout.showTitle) === false) && !isPopover;
29112
+ const showToolbarWithTitle = toolbar && (layout === null || layout === void 0 ? void 0 : layout.title) !== '' && (layout === null || layout === void 0 ? void 0 : layout.showTitle) !== false || isPopover;
29113
+ reactExports.useEffect(() => {
29114
+ document.addEventListener('keydown', globalKeyDown);
29115
+ return () => {
29116
+ document.removeEventListener('keydown', globalKeyDown);
29117
+ };
29118
+ }, [globalKeyDown]);
28654
29119
  reactExports.useEffect(() => {
28655
29120
  const show = () => {
28656
29121
  setShowToolbar(true);
@@ -28661,6 +29126,14 @@
28661
29126
  setShowSearch(false);
28662
29127
  }
28663
29128
  };
29129
+ if (isPopover) {
29130
+ if (!selections.isActive()) {
29131
+ selections.begin('/qListObjectDef');
29132
+ selections.on('activated', show);
29133
+ selections.on('deactivated', hide);
29134
+ }
29135
+ setShowToolbar(isPopover);
29136
+ }
28664
29137
  if (selections) {
28665
29138
  if (!selections.isModal()) {
28666
29139
  selections.on('activated', show);
@@ -28674,7 +29147,7 @@
28674
29147
  selections.removeListener('deactivated', hide);
28675
29148
  }
28676
29149
  };
28677
- }, [selections]);
29150
+ }, [selections, isPopover]);
28678
29151
  reactExports.useEffect(() => {
28679
29152
  if (!searchContainer || !searchContainer.current) {
28680
29153
  return;
@@ -28722,8 +29195,8 @@
28722
29195
  input === null || input === void 0 ? void 0 : input.focus();
28723
29196
  }
28724
29197
  };
28725
- const getActionToolbarProps = isPopover => getListboxActionProps({
28726
- isPopover,
29198
+ const getActionToolbarProps = isDetached => getListboxActionProps({
29199
+ isDetached: isPopover ? false : isDetached,
28727
29200
  showToolbar,
28728
29201
  containerRef,
28729
29202
  isLocked,
@@ -28737,6 +29210,14 @@
28737
29210
  const iconsWidth = (showSearchOrLockIcon ? BUTTON_ICON_WIDTH : 0) + (isDrillDown ? ICON_WIDTH + ICON_PADDING : 0); // Drill-down icon needs padding right so there is space between the icon and the title
28738
29211
  const headerPaddingLeft = CELL_PADDING_LEFT - (showSearchOrLockIcon ? ICON_PADDING : 0);
28739
29212
  const headerPaddingRight = isRtl ? CELL_PADDING_LEFT - (showIcons ? ICON_PADDING : 0) : 0;
29213
+ const {
29214
+ isDetached,
29215
+ reasonDetached
29216
+ } = showToolbarDetached({
29217
+ containerRef,
29218
+ titleRef,
29219
+ iconsWidth
29220
+ });
28740
29221
 
28741
29222
  // Add a container padding for grid mode to harmonize with the grid item margins (should sum to 8px).
28742
29223
  const isGridMode = (layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.dataLayout) === 'grid';
@@ -28785,7 +29266,7 @@
28785
29266
  }, getActionToolbarProps(true))), /*#__PURE__*/React.createElement(StyledGrid$3, {
28786
29267
  className: "listbox-container",
28787
29268
  container: true,
28788
- tabIndex: keyboard.enabled && !keyboard.active ? 0 : -1,
29269
+ tabIndex: keyboard.enabled ? -1 : undefined,
28789
29270
  direction: "column",
28790
29271
  gap: 0,
28791
29272
  containerPadding: containerPadding,
@@ -28841,6 +29322,9 @@
28841
29322
  className: classes$4.listBoxHeader
28842
29323
  }, /*#__PURE__*/React.createElement(Title, {
28843
29324
  variant: "h6",
29325
+ sx: {
29326
+ width: isPopover && reasonDetached === 'noSpace' ? '60px' : undefined
29327
+ },
28844
29328
  noWrap: true,
28845
29329
  ref: titleRef,
28846
29330
  title: layout.title
@@ -28851,11 +29335,7 @@
28851
29335
  item: true
28852
29336
  }, /*#__PURE__*/React.createElement(ActionsToolbar, _extends$8({
28853
29337
  direction: direction
28854
- }, getActionToolbarProps(showToolbarDetached({
28855
- containerRef,
28856
- titleRef,
28857
- iconsWidth
28858
- })))))), /*#__PURE__*/React.createElement(Grid$1, {
29338
+ }, getActionToolbarProps(isDetached))))), /*#__PURE__*/React.createElement(Grid$1, {
28859
29339
  item: true,
28860
29340
  container: true,
28861
29341
  direction: "column",
@@ -28891,11 +29371,11 @@
28891
29371
  className: classes$4.screenReaderOnly
28892
29372
  }, translator.get('Listbox.ScreenReaderInstructions')), isInvalid ? /*#__PURE__*/React.createElement(ListBoxError, {
28893
29373
  text: errorText
28894
- }) : /*#__PURE__*/React.createElement(AutoSizer, null, _ref4 => {
29374
+ }) : /*#__PURE__*/React.createElement(AutoSizer, null, _ref5 => {
28895
29375
  let {
28896
29376
  height,
28897
29377
  width
28898
- } = _ref4;
29378
+ } = _ref5;
28899
29379
  return /*#__PURE__*/React.createElement(ListBox, {
28900
29380
  model: model,
28901
29381
  app: app,
@@ -28930,15 +29410,16 @@
28930
29410
  set: setCurrentScrollIndex
28931
29411
  },
28932
29412
  renderedCallback: renderedCallback,
28933
- onCtrlF: onCtrlF
29413
+ onCtrlF: onCtrlF,
29414
+ isModal: isModalMode
28934
29415
  });
28935
29416
  })))));
28936
29417
  }
28937
29418
  const ListBoxInlineMemoed = React.memo(ListBoxInline);
28938
- function IsolateUseLayoutWrapper(_ref5) {
29419
+ function IsolateUseLayoutWrapper(_ref6) {
28939
29420
  let {
28940
29421
  options = {}
28941
- } = _ref5;
29422
+ } = _ref6;
28942
29423
  const {
28943
29424
  model
28944
29425
  } = options;
@@ -34035,7 +34516,7 @@
34035
34516
  * Gets an event emitter instance for the visualization.
34036
34517
  * @entry
34037
34518
  * @experimental
34038
- * @returns {Emitter} The emitter instance.
34519
+ * @returns {Emitter} The emitter instance. Implements https://nodejs.org/api/events.html#class-eventemitter.
34039
34520
  * @example
34040
34521
  * // In a Nebula visualization
34041
34522
  * import { useEmitter } from '@nebula.js/stardust';