@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.
package/core/esm/dev.js CHANGED
@@ -1,14 +1,14 @@
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
  */
6
6
 
7
7
  import * as React from 'react';
8
- import React__default, { useState as useState$1, useEffect as useEffect$1, forwardRef, useMemo as useMemo$1, useImperativeHandle as useImperativeHandle$1, useReducer, useCallback, useLayoutEffect as useLayoutEffect$1, PureComponent, useRef, createElement, useContext } from 'react';
8
+ import React__default, { useState as useState$1, useEffect as useEffect$1, forwardRef, useMemo as useMemo$1, useImperativeHandle as useImperativeHandle$1, useReducer, useCallback, useLayoutEffect as useLayoutEffect$1, PureComponent, useRef, useContext, createElement } from 'react';
9
9
  import ReactDOM from 'react-dom';
10
10
  import { CacheProvider, ThemeContext as ThemeContext$2 } from '@emotion/react';
11
- import { Checkbox, Radio, Typography, FormControlLabel, Box, Grid, Tooltip, Paper, IconButton, Popover, MenuList, MenuItem, ListItemIcon, Divider, InputAdornment, OutlinedInput, Badge, List, ListItem, Button, Icon, CircularProgress } from '@mui/material';
11
+ import { Checkbox, Radio, Typography, FormControlLabel, Box, Grid, Tooltip, Paper, IconButton, styled as styled$4, Popover, MenuList, MenuItem, ListItemIcon, Divider, InputAdornment, OutlinedInput, Badge, List, ListItem, Button, Icon, CircularProgress } from '@mui/material';
12
12
  import styled$3 from '@emotion/styled';
13
13
 
14
14
  function getAugmentedNamespace(n) {
@@ -8064,7 +8064,7 @@ function create$3(definition) {
8064
8064
  return cache[key];
8065
8065
  }
8066
8066
 
8067
- const NEBULA_VERSION_HASH = "9917" ;
8067
+ const NEBULA_VERSION_HASH = "757e" ;
8068
8068
  ClassNameGenerator$1.configure(componentName => {
8069
8069
  return "njs-".concat(NEBULA_VERSION_HASH, "-").concat(componentName.replace('Mui', ''));
8070
8070
  });
@@ -8272,7 +8272,7 @@ function boot(_ref2) {
8272
8272
  const appRef = React__default.createRef();
8273
8273
  const element = document.createElement('div');
8274
8274
  element.style.display = 'none';
8275
- element.setAttribute('data-nebulajs-version', "4.0.0-alpha.6" );
8275
+ element.setAttribute('data-nebulajs-version', "4.0.0-alpha.8" );
8276
8276
  element.setAttribute('data-app-id', app.id);
8277
8277
  document.body.appendChild(element);
8278
8278
  const root = client.createRoot(element);
@@ -9071,21 +9071,70 @@ function fillRange(elementNbrs, elemNumbersOrdered) {
9071
9071
  return elemNumbersOrdered.slice(min, max + 1);
9072
9072
  }
9073
9073
 
9074
+ const PREFIX$c = 'RowColumn';
9075
+ const rowColClasses = {
9076
+ row: "".concat(PREFIX$c, "-row"),
9077
+ rowBorderBottom: "".concat(PREFIX$c, "-rowBorderBottom"),
9078
+ column: "".concat(PREFIX$c, "-column"),
9079
+ fieldRoot: "".concat(PREFIX$c, "-fieldRoot"),
9080
+ cell: "".concat(PREFIX$c, "-cell"),
9081
+ labelText: "".concat(PREFIX$c, "-labelText"),
9082
+ labelDense: "".concat(PREFIX$c, "-labelDense"),
9083
+ highlighted: "".concat(PREFIX$c, "-highlighted"),
9084
+ checkboxLabel: "".concat(PREFIX$c, "-checkboxLabel"),
9085
+ icon: "".concat(PREFIX$c, "-icon"),
9086
+ S: "".concat(PREFIX$c, "-S"),
9087
+ XS: "".concat(PREFIX$c, "-XS"),
9088
+ A: "".concat(PREFIX$c, "-A"),
9089
+ X: "".concat(PREFIX$c, "-X"),
9090
+ frequencyCount: "".concat(PREFIX$c, "-frequencyCount"),
9091
+ barContainer: "".concat(PREFIX$c, "-barContainer"),
9092
+ bar: "".concat(PREFIX$c, "-bar"),
9093
+ barSelected: "".concat(PREFIX$c, "-barSelected"),
9094
+ barWithCheckbox: "".concat(PREFIX$c, "-barWithCheckbox"),
9095
+ barSelectedWithCheckbox: "".concat(PREFIX$c, "-barSelectedWithCheckbox"),
9096
+ excludedTextWithCheckbox: "".concat(PREFIX$c, "-excludedTextWithCheckbox")
9097
+ };
9098
+
9099
+ /* eslint-disable no-underscore-dangle */
9100
+ const dataItemSelector = ".".concat(rowColClasses.fieldRoot);
9074
9101
  const getKeyAsToggleSelected = event => !(event !== null && event !== void 0 && event.metaKey || event !== null && event !== void 0 && event.ctrlKey);
9075
9102
  function useSelectionsInteractions(_ref) {
9103
+ var _loaderRef$current2, _loaderRef$current2$_;
9076
9104
  let {
9077
9105
  selectionState,
9078
9106
  selections,
9079
9107
  checkboxes = false,
9080
- doc = document
9108
+ doc = document,
9109
+ loaderRef
9081
9110
  } = _ref;
9082
9111
  const currentSelect = useRef({
9083
9112
  startElemNumber: undefined,
9084
9113
  elemNumbers: [],
9085
9114
  isRange: false,
9086
9115
  toggle: false,
9087
- active: false
9116
+ active: false,
9117
+ touchElemNumbers: [],
9118
+ touchRangeSmall: false
9088
9119
  });
9120
+ useEffect$1(() => {
9121
+ var _loaderRef$current, _loaderRef$current$_l;
9122
+ 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)) {
9123
+ return undefined;
9124
+ }
9125
+ const preventGestureStart = e => e.preventDefault();
9126
+ const preventGestureChange = e => e.preventDefault();
9127
+ const preventGestureEnd = e => e.preventDefault();
9128
+ const listRef = loaderRef.current._listRef._outerRef;
9129
+ listRef.addEventListener('gesturestart', preventGestureStart);
9130
+ listRef.addEventListener('gesturechange', preventGestureChange);
9131
+ listRef.addEventListener('gestureend', preventGestureEnd);
9132
+ return () => {
9133
+ listRef.removeEventListener('gesturestart', preventGestureStart);
9134
+ listRef.removeEventListener('gesturechange', preventGestureChange);
9135
+ listRef.removeEventListener('gestureend', preventGestureEnd);
9136
+ };
9137
+ }, [(_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]);
9089
9138
 
9090
9139
  // eslint-disable-next-line arrow-body-style
9091
9140
  const doSelect = () => {
@@ -9097,6 +9146,10 @@ function useSelectionsInteractions(_ref) {
9097
9146
  toggle: currentSelect.current.toggle
9098
9147
  });
9099
9148
  };
9149
+ const getRange = (start, end) => {
9150
+ const elemNumbersOrdered = getElemNumbersFromPages(selectionState.enginePages);
9151
+ return fillRange([start, end], elemNumbersOrdered);
9152
+ };
9100
9153
  const addToRange = elemNumber => {
9101
9154
  const {
9102
9155
  startElemNumber
@@ -9104,9 +9157,7 @@ function useSelectionsInteractions(_ref) {
9104
9157
  if (startElemNumber === elemNumber) {
9105
9158
  return;
9106
9159
  }
9107
- const rangeEnds = [currentSelect.current.startElemNumber, elemNumber];
9108
- const elemNumbersOrdered = getElemNumbersFromPages(selectionState.enginePages);
9109
- const toMaybeAdd = fillRange(rangeEnds, elemNumbersOrdered);
9160
+ const toMaybeAdd = getRange(currentSelect.current.startElemNumber, elemNumber);
9110
9161
  selectionState.updateItems(toMaybeAdd, true, currentSelect.current.elemNumbers);
9111
9162
  };
9112
9163
  const selectManually = function () {
@@ -9202,6 +9253,48 @@ function useSelectionsInteractions(_ref) {
9202
9253
  const elemNumber = +event.currentTarget.getAttribute('data-n');
9203
9254
  addToRange(elemNumber);
9204
9255
  }, []);
9256
+ const onTouchStart = useCallback(event => {
9257
+ var _event$touches$0$targ, _event$touches$0$targ2, _event$touches$1$targ, _event$touches$1$targ2;
9258
+ // Handle range selection with two finger touch
9259
+ if (currentSelect.current.active || currentSelect.current.isRange || selectionState.isSingleSelect || event.touches.length <= 1) {
9260
+ return;
9261
+ }
9262
+ if (event.touches.length > 2) {
9263
+ doSelect();
9264
+ return;
9265
+ }
9266
+ 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'));
9267
+ 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'));
9268
+ if (Number.isNaN(startTouchElemNumber) || Number.isNaN(startTouchElemNumber)) {
9269
+ doSelect();
9270
+ return;
9271
+ }
9272
+ currentSelect.current.active = true;
9273
+ const range = getRange(startTouchElemNumber, endTouchElemNumber);
9274
+ if (range.length < 7) {
9275
+ currentSelect.current.touchRangeSmall = true;
9276
+ }
9277
+ currentSelect.current.elemNumbers = [];
9278
+ currentSelect.current.touchElemNumbers = [startTouchElemNumber, endTouchElemNumber];
9279
+ }, []);
9280
+ const onTouchEnd = useCallback(() => {
9281
+ if (currentSelect.current.touchElemNumbers.length !== 2) {
9282
+ return;
9283
+ }
9284
+ if (currentSelect.current.touchRangeSmall) {
9285
+ currentSelect.current.touchRangeSmall = false;
9286
+ currentSelect.current.touchElemNumbers = [];
9287
+ currentSelect.current.active = false;
9288
+ return;
9289
+ }
9290
+ const [startTouchElemNumber, endTouchElemNumber] = currentSelect.current.touchElemNumbers;
9291
+ currentSelect.current.startElemNumber = startTouchElemNumber;
9292
+ addToRange(endTouchElemNumber);
9293
+ currentSelect.current.touchElemNumbers = [];
9294
+ currentSelect.current.active = false;
9295
+ currentSelect.current.toggle = true;
9296
+ doSelect();
9297
+ }, []);
9205
9298
  useEffect$1(() => {
9206
9299
  doc.addEventListener('mouseup', onMouseUpDoc);
9207
9300
  return () => {
@@ -9234,7 +9327,9 @@ function useSelectionsInteractions(_ref) {
9234
9327
  Object.assign(interactionEvents, {
9235
9328
  onMouseUp,
9236
9329
  onMouseDown,
9237
- onMouseEnter
9330
+ onMouseEnter,
9331
+ onTouchStart,
9332
+ onTouchEnd
9238
9333
  });
9239
9334
  }
9240
9335
  return {
@@ -9348,6 +9443,84 @@ const KEYS = Object.freeze({
9348
9443
  isArrow: key => key === KEYS.ARROW_UP || key === KEYS.ARROW_DOWN || key === KEYS.ARROW_LEFT || key === KEYS.ARROW_RIGHT
9349
9444
  });
9350
9445
 
9446
+ function removeInnnerTabStops(container) {
9447
+ container === null || container === void 0 ? void 0 : container.querySelectorAll('[tabIndex="0"]').forEach(elm => {
9448
+ elm.setAttribute('tabIndex', -1);
9449
+ });
9450
+ }
9451
+ function removeLastFocused(container) {
9452
+ container === null || container === void 0 ? void 0 : container.querySelectorAll('.last-focused').forEach(elm => {
9453
+ elm.classList.remove('last-focused');
9454
+ });
9455
+ }
9456
+ function getVizCell(container) {
9457
+ return (container === null || container === void 0 ? void 0 : container.closest('.njs-cell')) || (container === null || container === void 0 ? void 0 : container.closest('.qv-gridcell'));
9458
+ }
9459
+
9460
+ // Emulate the keyboard hook, until we support it in the Listbox.
9461
+ function useTempKeyboard(_ref) {
9462
+ let {
9463
+ containerRef,
9464
+ enabled
9465
+ } = _ref;
9466
+ const [keyboardActive, setKeyboardActive] = useState$1(false);
9467
+ const keyboard = {
9468
+ enabled,
9469
+ active: keyboardActive,
9470
+ // innerTabStops: whether keyboard permits inner tab stops
9471
+ // (inner = everything inside .listbox-container)
9472
+
9473
+ innerTabStops: !enabled || keyboardActive,
9474
+ blur(resetFocus) {
9475
+ var _containerRef$current;
9476
+ if (!enabled) {
9477
+ return;
9478
+ }
9479
+ setKeyboardActive(false);
9480
+ const vizCell = getVizCell(containerRef.current) || ((_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.parentElement);
9481
+ removeInnnerTabStops(containerRef.current);
9482
+ removeLastFocused(containerRef.current);
9483
+ if (resetFocus && vizCell) {
9484
+ // Move focus to the viz's cell.
9485
+ vizCell.setAttribute('tabIndex', 0);
9486
+ vizCell.focus();
9487
+ }
9488
+ },
9489
+ focus() {
9490
+ if (!enabled) {
9491
+ return;
9492
+ }
9493
+ setKeyboardActive(true);
9494
+ const c = containerRef.current;
9495
+ const searchField = c === null || c === void 0 ? void 0 : c.querySelector('.search input');
9496
+ const lastSelectedRow = c === null || c === void 0 ? void 0 : c.querySelector('.value.last-focused');
9497
+ const fieldElement = c === null || c === void 0 ? void 0 : c.querySelector('.value.selector, .value, .ActionsToolbar-item button');
9498
+ const elementToFocus = searchField || lastSelectedRow || fieldElement;
9499
+ elementToFocus === null || elementToFocus === void 0 ? void 0 : elementToFocus.setAttribute('tabIndex', 0);
9500
+ elementToFocus === null || elementToFocus === void 0 ? void 0 : elementToFocus.focus();
9501
+ },
9502
+ focusSelection() {
9503
+ const confirmButton = document.querySelector('.actions-toolbar-default-actions .actions-toolbar-confirm');
9504
+ confirmButton === null || confirmButton === void 0 ? void 0 : confirmButton.setAttribute('tabIndex', 0);
9505
+ confirmButton === null || confirmButton === void 0 ? void 0 : confirmButton.focus();
9506
+ }
9507
+ };
9508
+ return keyboard;
9509
+ }
9510
+
9511
+ /* eslint-disable no-param-reassign */
9512
+ const getElementIndex = currentTarget => +currentTarget.getAttribute('data-n');
9513
+ const focusSearch = container => {
9514
+ const searchField = container === null || container === void 0 ? void 0 : container.querySelector('.search input');
9515
+ searchField === null || searchField === void 0 ? void 0 : searchField.focus();
9516
+ return searchField;
9517
+ };
9518
+ const focusRow = container => {
9519
+ const row = container === null || container === void 0 ? void 0 : container.querySelector('.value.last-focused, .value.selector, .value');
9520
+ row === null || row === void 0 ? void 0 : row.setAttribute('tabIndex', 0);
9521
+ row === null || row === void 0 ? void 0 : row.focus();
9522
+ return row;
9523
+ };
9351
9524
  function getFieldKeyboardNavigation(_ref) {
9352
9525
  let {
9353
9526
  select,
@@ -9356,7 +9529,9 @@ function getFieldKeyboardNavigation(_ref) {
9356
9529
  confirm,
9357
9530
  cancel,
9358
9531
  setScrollPosition,
9359
- focusListItems
9532
+ focusListItems,
9533
+ keyboard,
9534
+ isModal
9360
9535
  } = _ref;
9361
9536
  const getElement = function (elm) {
9362
9537
  let next = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
@@ -9369,49 +9544,86 @@ function getFieldKeyboardNavigation(_ref) {
9369
9544
  };
9370
9545
  const handleKeyDown = event => {
9371
9546
  let elementToFocus;
9547
+ const {
9548
+ currentTarget,
9549
+ nativeEvent
9550
+ } = event;
9372
9551
  const {
9373
9552
  keyCode,
9374
9553
  shiftKey = false,
9375
9554
  ctrlKey = false,
9376
9555
  metaKey = false
9377
- } = event.nativeEvent;
9556
+ } = nativeEvent;
9378
9557
  switch (keyCode) {
9558
+ case KEYS.TAB:
9559
+ {
9560
+ // Try to focus search field, otherwise confirm button.
9561
+ const container = currentTarget.closest('.listbox-container');
9562
+ const inSelection = isModal();
9563
+
9564
+ // TODO: use a store to keep track of this row.
9565
+ currentTarget.classList.add('last-focused'); // so that we can go back here when we tab back
9566
+
9567
+ if (shiftKey) {
9568
+ if (!focusSearch(container)) {
9569
+ if (inSelection) {
9570
+ keyboard.focusSelection();
9571
+ } else {
9572
+ keyboard.blur(true);
9573
+ }
9574
+ }
9575
+ break;
9576
+ }
9577
+
9578
+ // Without shift key
9579
+ if (inSelection) {
9580
+ keyboard.focusSelection();
9581
+ } else {
9582
+ currentTarget.blur();
9583
+ keyboard.blur();
9584
+ }
9585
+ break;
9586
+ }
9379
9587
  case KEYS.SHIFT:
9380
9588
  // This is to ensure we include the first value when starting a range selection.
9381
9589
  setStartedRange(true);
9382
9590
  break;
9383
9591
  case KEYS.SPACE:
9384
- select([+event.currentTarget.getAttribute('data-n')], false, event);
9592
+ select([getElementIndex(currentTarget)], false, event);
9385
9593
  break;
9386
9594
  case KEYS.ARROW_DOWN:
9387
9595
  case KEYS.ARROW_RIGHT:
9388
- elementToFocus = getElement(event.currentTarget, true);
9596
+ elementToFocus = getElement(currentTarget, true);
9389
9597
  if (shiftKey && elementToFocus) {
9390
9598
  if (startedRange) {
9391
- select([+event.currentTarget.getAttribute('data-n')], true);
9599
+ select([getElementIndex(currentTarget)], true);
9392
9600
  setStartedRange(false);
9393
9601
  }
9394
- select([+elementToFocus.getAttribute('data-n')], true);
9602
+ select([getElementIndex(elementToFocus)], true);
9395
9603
  }
9396
9604
  break;
9397
9605
  case KEYS.ARROW_UP:
9398
9606
  case KEYS.ARROW_LEFT:
9399
- elementToFocus = getElement(event.currentTarget, false);
9607
+ elementToFocus = getElement(currentTarget, false);
9400
9608
  if (shiftKey && elementToFocus) {
9401
9609
  if (startedRange) {
9402
- select([+event.currentTarget.getAttribute('data-n')], true);
9610
+ select([getElementIndex(currentTarget)], true);
9403
9611
  setStartedRange(false);
9404
9612
  }
9405
- select([+elementToFocus.getAttribute('data-n')], true);
9613
+ select([getElementIndex(elementToFocus)], true);
9406
9614
  }
9407
9615
  break;
9408
9616
  case KEYS.ENTER:
9409
9617
  confirm();
9410
9618
  break;
9411
9619
  case KEYS.ESCAPE:
9412
- cancel();
9413
- return;
9414
- // let it propagate to top-level
9620
+ if (isModal()) {
9621
+ cancel();
9622
+ } else {
9623
+ return; // propagate to other Esc handler
9624
+ }
9625
+
9626
+ break;
9415
9627
  case KEYS.HOME:
9416
9628
  focusListItems.setFirst(true);
9417
9629
  if (ctrlKey) {
@@ -9455,159 +9667,154 @@ function getFieldKeyboardNavigation(_ref) {
9455
9667
  }
9456
9668
  function getListboxInlineKeyboardNavigation(_ref2) {
9457
9669
  let {
9458
- setKeyboardActive,
9670
+ keyboard,
9459
9671
  hovering,
9460
- setHovering,
9461
9672
  updateKeyScroll,
9462
9673
  containerRef,
9463
9674
  currentScrollIndex,
9464
- app,
9465
- appSelections,
9675
+ isModal,
9466
9676
  constraints
9467
9677
  } = _ref2;
9468
- const focusInsideListbox = element => {
9469
- const fieldElement = element.querySelector('.search input, .value.selector, .value, .ActionsToolbar-item button');
9470
- setKeyboardActive(true);
9471
- if (fieldElement) {
9472
- fieldElement.focus();
9473
- }
9474
- };
9475
- const changeFocus = event => {
9476
- var _event$target;
9477
- if ((_event$target = event.target) !== null && _event$target !== void 0 && _event$target.classList.contains('listbox-container')) {
9478
- // Focus currently on a listbox
9479
- // Esc on a list box should move the focus to its parent, i.e. a filter pane if any
9480
- setKeyboardActive(false);
9678
+ const blur = event => {
9679
+ const {
9680
+ currentTarget,
9681
+ target
9682
+ } = event;
9683
+ const isFocusedOnListbox = target.classList.contains('listbox-container');
9684
+ const container = currentTarget.closest('.listbox-container');
9685
+ const vizCell = getVizCell(container);
9686
+ const isSingleListbox = (vizCell === null || vizCell === void 0 ? void 0 : vizCell.querySelectorAll('.listbox-container').length) === 1;
9687
+ if (isFocusedOnListbox || isSingleListbox) {
9688
+ // Move the focus from listbox container to the viz container.
9689
+ keyboard.blur(true);
9481
9690
  } else {
9482
- var _event$target2, _event$target3, _event$currentTarget, _event$currentTarget2;
9483
- // Focus currently on a row
9484
- // Esc on a row should move the focus to its parent, i.e. a listbox
9485
- // First unfocus the row
9486
- (_event$target2 = event.target) === null || _event$target2 === void 0 ? void 0 : _event$target2.setAttribute('tabIndex', '-1');
9487
- (_event$target3 = event.target) === null || _event$target3 === void 0 ? void 0 : _event$target3.blur();
9488
- // Then focus the listbox
9489
- (_event$currentTarget = event.currentTarget) === null || _event$currentTarget === void 0 ? void 0 : _event$currentTarget.setAttribute('tabIndex', '0');
9490
- (_event$currentTarget2 = event.currentTarget) === null || _event$currentTarget2 === void 0 ? void 0 : _event$currentTarget2.focus();
9491
- }
9492
- };
9493
- const updateKeyScrollOnHover = newState => {
9494
- if (hovering) {
9495
- updateKeyScroll(newState);
9691
+ // More than one listbox: Move focus from row to listbox container.
9692
+
9693
+ // 1. Remove last-focused class from row siblings.
9694
+ removeLastFocused(containerRef.current);
9695
+
9696
+ // 2. Add last-focused class so we can re-focus it later.
9697
+ currentTarget.classList.add('last-focused');
9698
+
9699
+ // 3. Blur row and focus the listbox container.
9700
+ keyboard.blur();
9701
+ const c = currentTarget.closest('.listbox-container');
9702
+ c.setAttribute('tabIndex', 0);
9703
+ c === null || c === void 0 ? void 0 : c.focus();
9496
9704
  }
9497
9705
  };
9498
9706
  const handleKeyDown = event => {
9499
9707
  const {
9500
9708
  keyCode,
9501
- ctrlKey = false,
9502
9709
  shiftKey = false
9503
9710
  } = event.nativeEvent;
9711
+ const prevent = () => {
9712
+ event.stopPropagation();
9713
+ event.preventDefault();
9714
+ };
9715
+ if (!keyboard.enabled) {
9716
+ // Other keys should not be handled unless keyboard is enabled.
9717
+ return;
9718
+ }
9719
+ const container = event.currentTarget.closest('.listbox-container');
9720
+ const inSelection = isModal();
9504
9721
  switch (keyCode) {
9505
- // case KEYS.TAB: TODO: Focus confirm button using keyboard.focusSelection when we can access the useKeyboard hook.
9722
+ case KEYS.TAB:
9723
+ if (inSelection) {
9724
+ if (shiftKey) {
9725
+ focusRow(container) || focusSearch(container);
9726
+ } else {
9727
+ focusSearch(container) || focusRow(container);
9728
+ }
9729
+ } else if (shiftKey) {
9730
+ keyboard.blur(true);
9731
+ } else {
9732
+ break;
9733
+ }
9734
+ prevent();
9735
+ break;
9506
9736
  case KEYS.ENTER:
9507
9737
  case KEYS.SPACE:
9508
9738
  if (!event.target.classList.contains('listbox-container')) {
9509
- return; // don't mess with keydown handlers within the listbox
9739
+ break; // don't mess with keydown handlers within the listbox (e.g. row seletion)
9510
9740
  }
9511
9741
 
9512
- focusInsideListbox(event.currentTarget);
9742
+ keyboard.focus();
9743
+ prevent();
9513
9744
  break;
9514
9745
  case KEYS.ESCAPE:
9515
- changeFocus(event);
9746
+ blur(event);
9516
9747
  break;
9748
+ }
9749
+ };
9750
+ const globalKeyDown = event => {
9751
+ if (!hovering.current) {
9752
+ return;
9753
+ }
9754
+ const {
9755
+ keyCode,
9756
+ ctrlKey = false,
9757
+ shiftKey = false
9758
+ } = event;
9759
+ switch (keyCode) {
9517
9760
  case KEYS.ARROW_UP:
9518
- updateKeyScrollOnHover({
9761
+ updateKeyScroll({
9519
9762
  up: 1
9520
9763
  });
9521
9764
  break;
9522
9765
  case KEYS.ARROW_DOWN:
9523
- updateKeyScrollOnHover({
9766
+ updateKeyScroll({
9524
9767
  down: 1
9525
9768
  });
9526
9769
  break;
9527
- case KEYS.ARROW_LEFT:
9528
- case KEYS.ARROW_RIGHT:
9529
- return;
9530
- // let it propagate to top-level
9531
9770
  case KEYS.PAGE_UP:
9532
- updateKeyScrollOnHover({
9771
+ updateKeyScroll({
9533
9772
  up: currentScrollIndex.stop - currentScrollIndex.start
9534
9773
  });
9535
9774
  break;
9536
9775
  case KEYS.PAGE_DOWN:
9537
- updateKeyScrollOnHover({
9776
+ updateKeyScroll({
9538
9777
  down: currentScrollIndex.stop - currentScrollIndex.start
9539
9778
  });
9540
9779
  break;
9541
9780
  case KEYS.HOME:
9542
- updateKeyScrollOnHover({
9781
+ updateKeyScroll({
9543
9782
  scrollPosition: ctrlKey && shiftKey ? 'overflowStart' : 'start'
9544
9783
  });
9545
9784
  break;
9546
9785
  case KEYS.END:
9547
- updateKeyScrollOnHover({
9786
+ updateKeyScroll({
9548
9787
  scrollPosition: ctrlKey && shiftKey ? 'overflowEnd' : 'end'
9549
9788
  });
9550
9789
  break;
9551
9790
  default:
9552
9791
  return;
9553
9792
  }
9554
-
9555
- // Note: We should not stop propagation here as it will block the containing app
9556
- // from handling keydown events.
9557
9793
  event.preventDefault();
9558
9794
  };
9559
9795
  const focusOnHoverDisabled = () => {
9560
- var _app$isInModalSelecti, _app$isInModalSelecti2;
9561
9796
  const selectNotAllowed = (constraints === null || constraints === void 0 ? void 0 : constraints.select) || (constraints === null || constraints === void 0 ? void 0 : constraints.active);
9562
- 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();
9797
+ const appInModal = isModal();
9563
9798
  return selectNotAllowed || appInModal;
9564
9799
  };
9565
9800
  const handleOnMouseEnter = () => {
9566
9801
  if (!focusOnHoverDisabled()) {
9567
- var _containerRef$current, _containerRef$current2;
9568
- setHovering(true);
9569
- 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);
9802
+ hovering.current = true;
9570
9803
  }
9571
9804
  };
9572
9805
  const handleOnMouseLeave = () => {
9573
- if (hovering) {
9574
- var _containerRef$current3, _containerRef$current4;
9575
- setHovering(false);
9576
- 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);
9806
+ if (hovering.current) {
9807
+ hovering.current = false;
9577
9808
  }
9578
9809
  };
9579
9810
  return {
9580
9811
  handleKeyDown,
9581
9812
  handleOnMouseEnter,
9582
- handleOnMouseLeave
9813
+ handleOnMouseLeave,
9814
+ globalKeyDown
9583
9815
  };
9584
9816
  }
9585
9817
 
9586
- const PREFIX$c = 'RowColumn';
9587
- const rowColClasses = {
9588
- row: "".concat(PREFIX$c, "-row"),
9589
- rowBorderBottom: "".concat(PREFIX$c, "-rowBorderBottom"),
9590
- column: "".concat(PREFIX$c, "-column"),
9591
- fieldRoot: "".concat(PREFIX$c, "-fieldRoot"),
9592
- cell: "".concat(PREFIX$c, "-cell"),
9593
- labelText: "".concat(PREFIX$c, "-labelText"),
9594
- labelDense: "".concat(PREFIX$c, "-labelDense"),
9595
- highlighted: "".concat(PREFIX$c, "-highlighted"),
9596
- checkboxLabel: "".concat(PREFIX$c, "-checkboxLabel"),
9597
- icon: "".concat(PREFIX$c, "-icon"),
9598
- S: "".concat(PREFIX$c, "-S"),
9599
- XS: "".concat(PREFIX$c, "-XS"),
9600
- A: "".concat(PREFIX$c, "-A"),
9601
- X: "".concat(PREFIX$c, "-X"),
9602
- frequencyCount: "".concat(PREFIX$c, "-frequencyCount"),
9603
- barContainer: "".concat(PREFIX$c, "-barContainer"),
9604
- bar: "".concat(PREFIX$c, "-bar"),
9605
- barSelected: "".concat(PREFIX$c, "-barSelected"),
9606
- barWithCheckbox: "".concat(PREFIX$c, "-barWithCheckbox"),
9607
- barSelectedWithCheckbox: "".concat(PREFIX$c, "-barSelectedWithCheckbox"),
9608
- excludedTextWithCheckbox: "".concat(PREFIX$c, "-excludedTextWithCheckbox")
9609
- };
9610
-
9611
9818
  const isExcluded = c => c ? c.qState === 'X' || c.qState === 'XS' || c.qState === 'XL' : null;
9612
9819
  const isAlternative = c => c ? c.qState === 'A' : null;
9613
9820
  const excludedOrAlternative = _ref => {
@@ -10247,13 +10454,15 @@ function Frequency(_ref) {
10247
10454
  dense,
10248
10455
  showGray
10249
10456
  } = _ref;
10457
+ const frequencyText = getFrequencyText(cell === null || cell === void 0 ? void 0 : cell.qFrequency);
10250
10458
  return /*#__PURE__*/React__default.createElement(Grid, {
10251
10459
  item: true,
10252
10460
  style: {
10253
10461
  display: 'flex',
10254
10462
  alignItems: 'center'
10255
10463
  },
10256
- className: rowColClasses.frequencyCount
10464
+ className: rowColClasses.frequencyCount,
10465
+ "aria-label": frequencyText
10257
10466
  }, /*#__PURE__*/React__default.createElement(Typography, {
10258
10467
  noWrap: true,
10259
10468
  color: "inherit",
@@ -10262,7 +10471,7 @@ function Frequency(_ref) {
10262
10471
  cell,
10263
10472
  checkboxes
10264
10473
  }) && rowColClasses.excludedTextWithCheckbox])
10265
- }, getFrequencyText(cell === null || cell === void 0 ? void 0 : cell.qFrequency)));
10474
+ }, frequencyText));
10266
10475
  }
10267
10476
 
10268
10477
  function getGridItemSizes(_ref) {
@@ -10299,7 +10508,7 @@ function getGridItemSizes(_ref) {
10299
10508
  }
10300
10509
 
10301
10510
  const ItemGrid = styled$1(Grid, {
10302
- shouldForwardProp: prop => !['dataLayout', 'layoutOrder', 'itemPadding', 'checkboxes'].includes(prop)
10511
+ shouldForwardProp: prop => !['dataLayout', 'layoutOrder', 'itemPadding', 'cellPaddingRight'].includes(prop)
10303
10512
  })(_ref => {
10304
10513
  let {
10305
10514
  dataLayout,
@@ -10334,6 +10543,79 @@ function getCellFromPages(_ref) {
10334
10543
  return c;
10335
10544
  }
10336
10545
 
10546
+ /* eslint-disable import/prefer-default-export */
10547
+ const LOC_STATES = {
10548
+ S: 'Object.Listbox.Selected',
10549
+ A: 'Object.Listbox.Alternative',
10550
+ O: 'Object.Listbox.Optional',
10551
+ XS: 'Object.Listbox.SelectedExcluded',
10552
+ L: 'Object.Listbox.Locked',
10553
+ X: 'Object.Listbox.Excluded',
10554
+ XL: 'Object.Listbox.ExcludedLock'
10555
+ };
10556
+ function getValueLabel(_ref) {
10557
+ let {
10558
+ translator,
10559
+ label,
10560
+ qState,
10561
+ isSelected,
10562
+ currentIndex,
10563
+ maxIndex,
10564
+ showSearch
10565
+ } = _ref;
10566
+ const stateTranslation = LOC_STATES[qState];
10567
+ const state = translator.get(stateTranslation);
10568
+ const srStringArr = [];
10569
+ if (isSelected) {
10570
+ const navTranslation = showSearch ? 'Listbox.ScreenReader.SearchThenSelectionsMenu.WithAccSelMenu' : 'Listbox.ScreenReader.SelectionMenu.WithAccSelMenu';
10571
+ const nav = translator.get(navTranslation);
10572
+ srStringArr.push(nav);
10573
+ }
10574
+ const valueString = "".concat(label, " ").concat(state);
10575
+ const indexString = translator.get('CurrentSelections.Of', [currentIndex + 1, maxIndex + 1]); // E.g. 3 of 20
10576
+ srStringArr.unshift(valueString, indexString);
10577
+ const srString = srStringArr.join('. ').trim();
10578
+ return srString;
10579
+ }
10580
+
10581
+ /**
10582
+ * Announces the selection state.
10583
+ *
10584
+ * @ignore
10585
+ * @param {Layout} object
10586
+ * @returns {Element} An (invisible) component.
10587
+ */
10588
+ function ScreenReaderForSelections(_ref2) {
10589
+ var _layout$qListObject;
10590
+ let {
10591
+ layout
10592
+ } = _ref2;
10593
+ const {
10594
+ translator
10595
+ } = useContext(InstanceContext);
10596
+ const {
10597
+ qStateCounts: s = {}
10598
+ } = (layout === null || layout === void 0 ? void 0 : (_layout$qListObject = layout.qListObject) === null || _layout$qListObject === void 0 ? void 0 : _layout$qListObject.qDimensionInfo) || {};
10599
+ const count = s.qSelected + s.qSelectedExcluded + s.qLocked + s.qLockedExcluded;
10600
+ let t;
10601
+ switch (count) {
10602
+ case 0:
10603
+ t = 'ScreenReader.ZeroSelected';
10604
+ break;
10605
+ case 1:
10606
+ t = 'ScreenReader.OneSelected';
10607
+ break;
10608
+ default:
10609
+ t = 'ScreenReader.ManySelected';
10610
+ break;
10611
+ }
10612
+ const text = translator.get(t, [count]);
10613
+ return /*#__PURE__*/React__default.createElement("div", {
10614
+ className: "screenReaderOnly",
10615
+ "aria-live": "assertive"
10616
+ }, text);
10617
+ }
10618
+
10337
10619
  function RowColumn(_ref) {
10338
10620
  var _cell$qText, _cell$qHighlightRange, _cell$qHighlightRange2;
10339
10621
  let {
@@ -10349,6 +10631,8 @@ function RowColumn(_ref) {
10349
10631
  onMouseDown,
10350
10632
  onMouseUp,
10351
10633
  onMouseEnter,
10634
+ onTouchStart,
10635
+ onTouchEnd,
10352
10636
  pages,
10353
10637
  isLocked,
10354
10638
  column = false,
@@ -10370,7 +10654,10 @@ function RowColumn(_ref) {
10370
10654
  focusListItems,
10371
10655
  listCount,
10372
10656
  itemPadding,
10373
- frequencyWidth
10657
+ frequencyWidth,
10658
+ translator,
10659
+ showSearch,
10660
+ isModal
10374
10661
  } = data;
10375
10662
  const {
10376
10663
  dense = false,
@@ -10420,8 +10707,10 @@ function RowColumn(_ref) {
10420
10707
  }
10421
10708
  }, [rowRef.current]);
10422
10709
  const handleKeyDownCallback = useCallback(getFieldKeyboardNavigation(_objectSpread2(_objectSpread2({}, actions), {}, {
10423
- focusListItems
10424
- })), [actions]);
10710
+ focusListItems,
10711
+ keyboard,
10712
+ isModal
10713
+ })), [actions, keyboard === null || keyboard === void 0 ? void 0 : keyboard.innerTabStops]);
10425
10714
  const cell = useMemo$1(() => getCellFromPages({
10426
10715
  pages,
10427
10716
  cellIndex
@@ -10486,6 +10775,14 @@ function RowColumn(_ref) {
10486
10775
  const showTick = !checkboxes && isSelected && !isLocked;
10487
10776
  const showIcon = !checkboxes && sizePermitsTickOrLock;
10488
10777
  const cellPaddingRight = checkboxes || !sizePermitsTickOrLock;
10778
+ const ariaLabel = getValueLabel({
10779
+ translator,
10780
+ label,
10781
+ qState: cell.qState,
10782
+ currentIndex: count.currentIndex,
10783
+ maxIndex: count.max,
10784
+ showSearch
10785
+ });
10489
10786
  return /*#__PURE__*/React__default.createElement(RowColRoot$1, {
10490
10787
  className: rowColClasses.barContainer,
10491
10788
  flexBasisProp: flexBasisVal,
@@ -10496,6 +10793,11 @@ function RowColumn(_ref) {
10496
10793
  frequencyWidth: frequencyWidth,
10497
10794
  "data-testid": "listbox.item"
10498
10795
  }, /*#__PURE__*/React__default.createElement(ItemGrid, {
10796
+ role: "row",
10797
+ "aria-label": ariaLabel,
10798
+ "aria-selected": isSelected,
10799
+ "aria-setsize": count.max,
10800
+ "aria-rowindex": count.currentIndex,
10499
10801
  ref: rowRef,
10500
10802
  container: true,
10501
10803
  dataLayout: dataLayout,
@@ -10512,9 +10814,10 @@ function RowColumn(_ref) {
10512
10814
  onMouseUp: onMouseUp,
10513
10815
  onMouseEnter: onMouseEnter,
10514
10816
  onKeyDown: handleKeyDownCallback,
10817
+ onTouchStart: onTouchStart,
10818
+ onTouchEnd: onTouchEnd,
10515
10819
  onContextMenu: preventContextMenu,
10516
- role: column ? 'column' : 'row',
10517
- tabIndex: isFirstElement && (!keyboard.enabled || keyboard.active) ? 0 : -1,
10820
+ tabIndex: isFirstElement && keyboard.innerTabStops ? 0 : -1,
10518
10821
  "data-n": cell === null || cell === void 0 ? void 0 : cell.qElemNumber
10519
10822
  }, (cell === null || cell === void 0 ? void 0 : cell.qFrequency) && /*#__PURE__*/React__default.createElement(Histogram, {
10520
10823
  qFrequency: cell === null || cell === void 0 ? void 0 : cell.qFrequency,
@@ -12130,7 +12433,10 @@ function getListBoxComponents(_ref) {
12130
12433
  setCurrentScrollIndex,
12131
12434
  constraints,
12132
12435
  frequencyMax,
12133
- freqIsAllowed
12436
+ freqIsAllowed,
12437
+ translator,
12438
+ showSearch,
12439
+ isModal
12134
12440
  } = _ref;
12135
12441
  const {
12136
12442
  layoutOptions = {}
@@ -12184,7 +12490,10 @@ function getListBoxComponents(_ref) {
12184
12490
  showTick,
12185
12491
  dataOffset: local.current.dataOffset,
12186
12492
  focusListItems,
12187
- direction
12493
+ direction,
12494
+ translator,
12495
+ showSearch,
12496
+ isModal
12188
12497
  });
12189
12498
  const List = _ref2 => {
12190
12499
  let {
@@ -12626,17 +12935,14 @@ function useDataStore(model) {
12626
12935
  };
12627
12936
  }
12628
12937
 
12629
- function ListBoxDisclaimer(_ref) {
12938
+ const StyledText = styled$1(Typography, {
12939
+ shouldForwardProp: p => !['width', 'dense'].includes(p)
12940
+ })(_ref => {
12630
12941
  let {
12631
12942
  width,
12632
- text,
12633
- dense,
12634
- tooltip
12943
+ dense
12635
12944
  } = _ref;
12636
- const {
12637
- translator
12638
- } = useContext(InstanceContext);
12639
- const StyledText = styled$1(Typography)(() => _objectSpread2({
12945
+ return _objectSpread2({
12640
12946
  minWidth: "".concat(width, "px"),
12641
12947
  textAlign: 'center',
12642
12948
  fontSize: "".concat(dense ? '12px' : '14px')
@@ -12645,10 +12951,23 @@ function ListBoxDisclaimer(_ref) {
12645
12951
  overflow: 'hidden',
12646
12952
  whiteSpace: 'nowrap',
12647
12953
  width
12648
- }));
12954
+ });
12955
+ });
12956
+ function ListBoxDisclaimer(_ref2) {
12957
+ let {
12958
+ width,
12959
+ text,
12960
+ dense,
12961
+ tooltip
12962
+ } = _ref2;
12963
+ const {
12964
+ translator
12965
+ } = useContext(InstanceContext);
12649
12966
  return /*#__PURE__*/React__default.createElement(Tooltip, {
12650
12967
  title: tooltip ? translator.get(text) : ''
12651
12968
  }, /*#__PURE__*/React__default.createElement(StyledText, {
12969
+ width: width,
12970
+ dense: dense,
12652
12971
  component: "div",
12653
12972
  variant: "body1",
12654
12973
  py: "12px"
@@ -13016,6 +13335,14 @@ const useFrequencyMax = (app, layout) => {
13016
13335
 
13017
13336
  const _excluded$4 = ["isLoadingData"];
13018
13337
  const DEFAULT_MIN_BATCH_SIZE = 100;
13338
+ const StyledWrapper = styled$4('div')(() => ({
13339
+ ["& .screenReaderOnly"]: {
13340
+ position: 'absolute',
13341
+ height: 0,
13342
+ width: 0,
13343
+ overflow: 'hidden'
13344
+ }
13345
+ }));
13019
13346
  function ListBox(_ref) {
13020
13347
  var _layout$qListObject$q, _loaderRef$current, _loaderRef$current$_l, _loaderRef$current$_l2;
13021
13348
  let {
@@ -13046,8 +13373,13 @@ function ListBox(_ref) {
13046
13373
  set: () => {}
13047
13374
  },
13048
13375
  renderedCallback,
13049
- onCtrlF
13376
+ onCtrlF,
13377
+ showSearch,
13378
+ isModal
13050
13379
  } = _ref;
13380
+ const {
13381
+ translator
13382
+ } = useContext(InstanceContext);
13051
13383
  const [initScrollPosIsSet, setInitScrollPosIsSet] = useState$1(false);
13052
13384
  const isSingleSelect = !!(layout && layout.qListObject.qDimensionInfo.qIsOneAndOnlyOne);
13053
13385
  const {
@@ -13121,7 +13453,8 @@ function ListBox(_ref) {
13121
13453
  selectionState,
13122
13454
  selections,
13123
13455
  checkboxes,
13124
- doc: document
13456
+ doc: document,
13457
+ loaderRef
13125
13458
  });
13126
13459
  const {
13127
13460
  layoutOptions = {}
@@ -13302,7 +13635,10 @@ function ListBox(_ref) {
13302
13635
  setCurrentScrollIndex: currentScrollIndex.set,
13303
13636
  constraints,
13304
13637
  frequencyMax,
13305
- freqIsAllowed
13638
+ freqIsAllowed,
13639
+ translator,
13640
+ showSearch,
13641
+ isModal
13306
13642
  });
13307
13643
  const {
13308
13644
  columnWidth,
@@ -13317,7 +13653,10 @@ function ListBox(_ref) {
13317
13653
  itemHeight
13318
13654
  });
13319
13655
  }
13320
- return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, !listCount && /*#__PURE__*/React__default.createElement(ListBoxDisclaimer, {
13656
+ return /*#__PURE__*/React__default.createElement(StyledWrapper, null, /*#__PURE__*/React__default.createElement(ScreenReaderForSelections, {
13657
+ className: "screenReaderOnly",
13658
+ layout: layout
13659
+ }), !listCount && /*#__PURE__*/React__default.createElement(ListBoxDisclaimer, {
13321
13660
  width: width,
13322
13661
  text: "Listbox.NoMatchesForYourTerms"
13323
13662
  }), /*#__PURE__*/React__default.createElement(InfiniteLoader, {
@@ -13329,7 +13668,8 @@ function ListBox(_ref) {
13329
13668
  }),
13330
13669
  threshold: 0,
13331
13670
  minimumBatchSize: minimumBatchSize,
13332
- ref: loaderRef
13671
+ ref: loaderRef,
13672
+ role: "grid"
13333
13673
  }, isVertical ? List : Grid), overflowDisclaimer.show && !overflowDisclaimer.dismissed && /*#__PURE__*/React__default.createElement(ListBoxFooter, {
13334
13674
  text: "Listbox.ItemsOverflow",
13335
13675
  dismiss: () => setOverflowDisclaimer(state => _objectSpread2(_objectSpread2({}, state), {}, {
@@ -13481,6 +13821,7 @@ const Item = React__default.forwardRef((_ref, ref) => {
13481
13821
  if (hidden) return null;
13482
13822
  const spacing = Number.parseInt(theme.spacing(0.5), 10);
13483
13823
  const handleKeyDown = item.keyboardAction ? e => ['Enter', ' ', 'Spacebar'].includes(e.key) && item.keyboardAction() : null;
13824
+ const btnId = "actions-toolbar-".concat(item.key);
13484
13825
  return /*#__PURE__*/React__default.createElement(IconButton, {
13485
13826
  ref: !addAnchor ? ref : null,
13486
13827
  title: item.label,
@@ -13488,12 +13829,12 @@ const Item = React__default.forwardRef((_ref, ref) => {
13488
13829
  onKeyDown: handleKeyDown,
13489
13830
  disabled: disabled,
13490
13831
  style: style,
13491
- className: ActionElement.className,
13832
+ className: [ActionElement.className, btnId].join(' '),
13492
13833
  size: "large",
13493
13834
  disableRipple: true,
13494
13835
  "aria-expanded": ariaExpanded,
13495
13836
  "aria-controls": "moreMenuList",
13496
- "data-testid": "actions-toolbar-".concat(item.key)
13837
+ "data-testid": btnId
13497
13838
  }, hasSvgIconShape && SvgIcon$2(item.getSvgIconShape()), addAnchor && /*#__PURE__*/React__default.createElement("div", {
13498
13839
  ref: ref,
13499
13840
  style: {
@@ -13672,6 +14013,70 @@ const More$1 = React__default.forwardRef((_ref3, ref) => {
13672
14013
  }))));
13673
14014
  });
13674
14015
 
14016
+ const getActionButtonIndex = btn => {
14017
+ const toolbar = btn.closest('#actions-toolbar');
14018
+ const nodeList = toolbar === null || toolbar === void 0 ? void 0 : toolbar.querySelectorAll('.njs-cell-action');
14019
+ return Array.from(nodeList).indexOf(btn);
14020
+ };
14021
+ const focusButton = index => {
14022
+ const toolbar = document.querySelector('#actions-toolbar');
14023
+ const nodeList = toolbar === null || toolbar === void 0 ? void 0 : toolbar.querySelectorAll('.njs-cell-action');
14024
+ if (!nodeList.length) {
14025
+ return;
14026
+ }
14027
+ const ix = Math.min(Math.max(0, index), nodeList.length - 1);
14028
+ const btn = nodeList[ix];
14029
+ btn.focus();
14030
+ };
14031
+ function getActionsKeyDownHandler(_ref) {
14032
+ let {
14033
+ keyboardNavigation,
14034
+ focusHandler,
14035
+ getEnabledButton
14036
+ } = _ref;
14037
+ const handleActionsKeyDown = evt => {
14038
+ const {
14039
+ target,
14040
+ nativeEvent
14041
+ } = evt;
14042
+ const {
14043
+ keyCode
14044
+ } = nativeEvent;
14045
+ switch (keyCode) {
14046
+ case KEYS.ARROW_LEFT:
14047
+ case KEYS.ARROW_DOWN:
14048
+ case KEYS.ARROW_RIGHT:
14049
+ case KEYS.ARROW_UP:
14050
+ {
14051
+ const isActionButton = target.classList.contains('njs-cell-action');
14052
+ if (isActionButton) {
14053
+ const index = getActionButtonIndex(target);
14054
+ const pressedLeft = [KEYS.ARROW_LEFT, KEYS.ARROW_DOWN].includes(keyCode);
14055
+ focusButton(pressedLeft ? index - 1 : index + 1);
14056
+ }
14057
+ evt.stopPropagation();
14058
+ evt.preventDefault();
14059
+ break;
14060
+ }
14061
+ case KEYS.SPACE:
14062
+ evt.preventDefault(); // prevent scrolling in listbox
14063
+ break;
14064
+ case KEYS.TAB:
14065
+ if (keyboardNavigation && focusHandler !== null && focusHandler !== void 0 && focusHandler.refocusContent) {
14066
+ const isTabbingOut = evt.shiftKey && getEnabledButton(false) === evt.target || !evt.shiftKey && getEnabledButton(true) === evt.target;
14067
+ if (isTabbingOut) {
14068
+ evt.preventDefault();
14069
+ evt.stopPropagation();
14070
+ // if keyboardNavigation is true, create a callback to handle tabbing from the first/last button in the toolbar that resets focus on the content
14071
+ focusHandler.refocusContent();
14072
+ }
14073
+ }
14074
+ break;
14075
+ }
14076
+ };
14077
+ return handleActionsKeyDown;
14078
+ }
14079
+
13675
14080
  const PREFIX$7 = 'ActionsToolbar';
13676
14081
  const classes$7 = {
13677
14082
  item: "".concat(PREFIX$7, "-item"),
@@ -13707,6 +14112,7 @@ const ActionToolbarElement = {
13707
14112
  };
13708
14113
  const ActionsGroup = React__default.forwardRef((_ref2, ref) => {
13709
14114
  let {
14115
+ className,
13710
14116
  ariaExpanded = false,
13711
14117
  actions = [],
13712
14118
  first = false,
@@ -13719,7 +14125,8 @@ const ActionsGroup = React__default.forwardRef((_ref2, ref) => {
13719
14125
  container: true,
13720
14126
  gap: 0,
13721
14127
  flexDirection: isRtl ? 'row-reverse' : 'row',
13722
- wrap: "nowrap"
14128
+ wrap: "nowrap",
14129
+ className: className
13723
14130
  }, actions.map((e, ix) => {
13724
14131
  let cls = [];
13725
14132
  const isFirstItem = first && ix === 0;
@@ -13787,22 +14194,27 @@ function ActionsToolbar(_ref3) {
13787
14194
  keyboardNavigation
13788
14195
  } = useContext(InstanceContext);
13789
14196
  const [showMoreItems, setShowMoreItems] = useState$1(false);
13790
- const moreRef = useRef();
14197
+ const popoverAnchorOrigin = {
14198
+ vertical: 7,
14199
+ 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
14200
+ };
13791
14201
  const actionsRef = useRef();
14202
+ const moreRef = useRef();
13792
14203
  const theme = useTheme$1();
13793
14204
  const dividerStyle = useMemo$1(() => ({
13794
14205
  margin: theme.spacing(0.5, 0)
13795
14206
  }));
13796
- const popoverAnchorOrigin = {
13797
- vertical: 15,
13798
- 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
13799
- };
13800
14207
  const getEnabledButton = last => {
13801
14208
  const actionsElement = actionsRef.current || actionsRefMock;
13802
14209
  if (!actionsElement) return null;
13803
14210
  const buttons = actionsElement.querySelectorAll('button:not(.Mui-disabled)');
13804
14211
  return buttons[last ? buttons.length - 1 : 0];
13805
14212
  };
14213
+ const handleActionsKeyDown = useMemo$1(() => getActionsKeyDownHandler({
14214
+ keyboardNavigation,
14215
+ focusHandler,
14216
+ getEnabledButton
14217
+ }), [keyboardNavigation, focusHandler, getEnabledButton]);
13806
14218
  useEffect$1(() => () => {
13807
14219
  setShowMoreItems(false);
13808
14220
  }, [popover.show, show, selections.show]);
@@ -13842,27 +14254,18 @@ function ActionsToolbar(_ref3) {
13842
14254
  enabled: () => moreEnabled,
13843
14255
  action: () => setShowMoreItems(!showMoreItems)
13844
14256
  };
13845
- const tabCallback =
13846
- // if keyboardNavigation is true, create a callback to handle tabbing from the first/last button in the toolbar that resets focus on the content
13847
- keyboardNavigation && focusHandler && focusHandler.refocusContent ? evt => {
13848
- if (evt.key !== 'Tab') return;
13849
- const isTabbingOut = evt.shiftKey && getEnabledButton(false) === evt.target || !evt.shiftKey && getEnabledButton(true) === evt.target;
13850
- if (isTabbingOut) {
13851
- evt.preventDefault();
13852
- evt.stopPropagation();
13853
- focusHandler.refocusContent();
13854
- }
13855
- } : null;
13856
14257
  const showActions = newActions.length > 0;
13857
14258
  const showMore = moreActions.length > 0;
13858
14259
  const showDivider = showActions && selections.show || showMore && selections.show;
13859
14260
  const isRtl = direction === 'rtl';
13860
14261
  const Actions = /*#__PURE__*/React__default.createElement(Grid, {
13861
14262
  ref: actionsRef,
13862
- onKeyDown: tabCallback,
14263
+ onKeyDown: handleActionsKeyDown,
13863
14264
  container: true,
13864
14265
  gap: 0,
13865
14266
  wrap: "nowrap",
14267
+ id: "actions-toolbar",
14268
+ "data-testid": "actions-toolbar",
13866
14269
  sx: {
13867
14270
  flexDirection: isRtl ? 'row-reverse' : 'row'
13868
14271
  }
@@ -13871,6 +14274,8 @@ function ActionsToolbar(_ref3) {
13871
14274
  first: true,
13872
14275
  last: !showMore && !selections.show
13873
14276
  }), showMore && /*#__PURE__*/React__default.createElement(ActionsGroup, {
14277
+ id: "actions-toolbar-show-more",
14278
+ "data-testid": "actions-toolbar-show-more",
13874
14279
  ref: moreRef,
13875
14280
  ariaExpanded: showMoreItems,
13876
14281
  actions: [moreItem],
@@ -13884,6 +14289,7 @@ function ActionsToolbar(_ref3) {
13884
14289
  }, /*#__PURE__*/React__default.createElement(Divider, {
13885
14290
  orientation: "vertical"
13886
14291
  })), selections.show && /*#__PURE__*/React__default.createElement(ActionsGroup, {
14292
+ className: "actions-toolbar-default-actions",
13887
14293
  actions: defaultSelectionActions,
13888
14294
  first: !showActions && !showMore,
13889
14295
  last: true,
@@ -13907,6 +14313,8 @@ function ActionsToolbar(_ref3) {
13907
14313
  hideBackdrop: true,
13908
14314
  style: popoverStyle,
13909
14315
  PaperProps: {
14316
+ id: 'njs-action-toolbar-popover',
14317
+ 'data-testid': 'njs-action-toolbar-popover',
13910
14318
  className: ActionToolbarElement.className,
13911
14319
  style: {
13912
14320
  pointerEvents: 'auto',
@@ -14034,29 +14442,57 @@ function ListBoxSearch(_ref3) {
14034
14442
  }
14035
14443
  return response;
14036
14444
  };
14445
+ function focusRow(container) {
14446
+ 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'));
14447
+ row.setAttribute('tabIndex', 0);
14448
+ row === null || row === void 0 ? void 0 : row.focus();
14449
+ }
14037
14450
  const onKeyDown = async e => {
14038
- let response;
14451
+ const {
14452
+ currentTarget
14453
+ } = e;
14454
+ const container = currentTarget.closest('.listbox-container');
14039
14455
  switch (e.key) {
14040
14456
  case 'Enter':
14041
- response = await performSearch();
14457
+ performSearch();
14042
14458
  break;
14043
14459
  case 'Escape':
14044
- response = cancel();
14045
- e.preventDefault();
14046
- e.stopPropagation();
14047
- break;
14460
+ {
14461
+ focusRow(container);
14462
+ cancel();
14463
+ break;
14464
+ }
14465
+ case 'Tab':
14466
+ {
14467
+ if (e.shiftKey) {
14468
+ keyboard.focusSelection();
14469
+ } else {
14470
+ // Focus the row we last visited or the first one.
14471
+ focusRow(container);
14472
+
14473
+ // Clean up.
14474
+ container === null || container === void 0 ? void 0 : container.querySelectorAll('.last-focused').forEach(elm => {
14475
+ elm.classList.remove('last-focused');
14476
+ });
14477
+ }
14478
+ break;
14479
+ }
14048
14480
  case 'f':
14049
14481
  case 'F':
14050
14482
  if (e.ctrlKey || e.metaKey) {
14051
14483
  if (hide) {
14052
14484
  hide();
14053
14485
  }
14054
- e.preventDefault();
14055
- e.stopPropagation();
14486
+ } else {
14487
+ return undefined;
14056
14488
  }
14057
14489
  break;
14490
+ default:
14491
+ return undefined;
14058
14492
  }
14059
- return response;
14493
+ e.preventDefault();
14494
+ e.stopPropagation();
14495
+ return undefined;
14060
14496
  };
14061
14497
  if (!visible || searchEnabled === false) {
14062
14498
  return null;
@@ -14102,10 +14538,11 @@ function ListBoxSearch(_ref3) {
14102
14538
  onKeyDown: onKeyDown,
14103
14539
  autoFocus: autoFocus,
14104
14540
  inputProps: {
14105
- tabIndex: keyboard && (!keyboard.enabled || keyboard.active) ? 0 : -1,
14541
+ tabIndex: keyboard.innerTabStops ? 0 : -1,
14106
14542
  style: {
14107
14543
  textAlign: "".concat(inpuTextAlign)
14108
- }
14544
+ },
14545
+ 'data-testid': 'search-input-field'
14109
14546
  }
14110
14547
  });
14111
14548
  }
@@ -14349,6 +14786,12 @@ function useObjectSelections(app, model, elements, options) {
14349
14786
  objectSelections.addListener('activated', activateClickOut);
14350
14787
  objectSelections.addListener('deactivated', deactivateClickOut);
14351
14788
  return () => {
14789
+ // confirm selection before removing event handler
14790
+ // to end the selection when the object is removed
14791
+ // and remove the (ClickOut) mousedown handler from the document
14792
+ if (objectSelections.isActive()) {
14793
+ objectSelections.confirm();
14794
+ }
14352
14795
  objectSelections.removeListener('activated', activateClickOut);
14353
14796
  objectSelections.removeListener('deactivated', deactivateClickOut);
14354
14797
  };
@@ -15953,6 +16396,7 @@ const addListboxTheme = themeApi => {
15953
16396
  };
15954
16397
  };
15955
16398
 
16399
+ /* eslint-disable no-nested-ternary */
15956
16400
  function showToolbarDetached(_ref) {
15957
16401
  var _containerRef$current, _containerRef$current2, _titleRef$current$cli, _titleRef$current, _titleRef$current2, _titleRef$current3;
15958
16402
  let {
@@ -15966,12 +16410,17 @@ function showToolbarDetached(_ref) {
15966
16410
  const actionToolbarWidth = 128;
15967
16411
  const notSufficientSpace = containerWidth < contentWidth + actionToolbarWidth;
15968
16412
  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);
15969
- return !!(notSufficientSpace | isTruncated);
16413
+ const isDetached = !!(notSufficientSpace | isTruncated);
16414
+ const reasonDetached = isDetached ? notSufficientSpace ? 'noSpace' : 'truncated' : '';
16415
+ return {
16416
+ isDetached,
16417
+ reasonDetached
16418
+ };
15970
16419
  }
15971
16420
 
15972
16421
  function getListboxActionProps(_ref) {
15973
16422
  let {
15974
- isPopover,
16423
+ isDetached,
15975
16424
  showToolbar,
15976
16425
  containerRef,
15977
16426
  isLocked,
@@ -15979,9 +16428,9 @@ function getListboxActionProps(_ref) {
15979
16428
  selections
15980
16429
  } = _ref;
15981
16430
  return {
15982
- show: showToolbar && !isPopover,
16431
+ show: showToolbar && !isDetached,
15983
16432
  popover: {
15984
- show: showToolbar && isPopover,
16433
+ show: showToolbar && isDetached,
15985
16434
  anchorEl: containerRef.current
15986
16435
  },
15987
16436
  more: {
@@ -16004,6 +16453,13 @@ function getListboxActionProps(_ref) {
16004
16453
  };
16005
16454
  }
16006
16455
 
16456
+ const StyledDiv = styled$1('div')(() => ({
16457
+ display: 'flex',
16458
+ width: '100%',
16459
+ height: '100%',
16460
+ alignItems: 'center',
16461
+ justifyContent: 'center'
16462
+ }));
16007
16463
  function ListBoxError(_ref) {
16008
16464
  let {
16009
16465
  text
@@ -16011,13 +16467,6 @@ function ListBoxError(_ref) {
16011
16467
  const {
16012
16468
  translator
16013
16469
  } = useContext(InstanceContext);
16014
- const StyledDiv = styled$1('div')(() => ({
16015
- display: 'flex',
16016
- width: '100%',
16017
- height: '100%',
16018
- alignItems: 'center',
16019
- justifyContent: 'center'
16020
- }));
16021
16470
  return /*#__PURE__*/React__default.createElement(StyledDiv, null, translator.get(text));
16022
16471
  }
16023
16472
 
@@ -16052,7 +16501,7 @@ const StyledGrid$3 = styled$1(Grid, {
16052
16501
  ["& .".concat(classes$4.listboxWrapper)]: {
16053
16502
  padding: containerPadding
16054
16503
  },
16055
- '&:focus:not(:hover)': {
16504
+ '&:focus': {
16056
16505
  boxShadow: "inset 0 0 0 2px ".concat(theme.palette.custom.focusBorder, " !important")
16057
16506
  },
16058
16507
  '&:focus-visible': {
@@ -16072,12 +16521,20 @@ const Title = styled$1(Typography)(_ref2 => {
16072
16521
  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'
16073
16522
  };
16074
16523
  });
16075
- function ListBoxInline(_ref3) {
16524
+ const isModal = _ref3 => {
16525
+ var _app$isInModalSelecti, _app$isInModalSelecti2;
16526
+ let {
16527
+ app,
16528
+ appSelections
16529
+ } = _ref3;
16530
+ 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();
16531
+ };
16532
+ function ListBoxInline(_ref4) {
16076
16533
  var _layoutOptions$dense;
16077
16534
  let {
16078
16535
  options,
16079
16536
  layout
16080
- } = _ref3;
16537
+ } = _ref4;
16081
16538
  const {
16082
16539
  app,
16083
16540
  direction,
@@ -16096,7 +16553,8 @@ function ListBoxInline(_ref3) {
16096
16553
  showGray = true,
16097
16554
  scrollState = undefined,
16098
16555
  renderedCallback,
16099
- toolbar = true
16556
+ toolbar = true,
16557
+ isPopover = false
16100
16558
  } = options;
16101
16559
 
16102
16560
  // Hook that will trigger update when used in useEffects.
@@ -16125,8 +16583,7 @@ function ListBoxInline(_ref3) {
16125
16583
  const [searchContainer, searchContainerRef] = useRefWithCallback();
16126
16584
  const [showToolbar, setShowToolbar] = useState$1(false);
16127
16585
  const [showSearch, setShowSearch] = useState$1(false);
16128
- const [keyboardActive, setKeyboardActive] = useState$1(false);
16129
- const [hovering, setHovering] = useState$1(false);
16586
+ const hovering = useRef(false);
16130
16587
  const [keyScroll, setKeyScroll] = useState$1({
16131
16588
  down: 0,
16132
16589
  up: 0,
@@ -16140,32 +16597,40 @@ function ListBoxInline(_ref3) {
16140
16597
  const [appSelections] = useAppSelections(app);
16141
16598
  const titleRef = useRef(null);
16142
16599
  const [selectionState$1] = useState$1(() => selectionState());
16600
+ const keyboard = useTempKeyboard({
16601
+ containerRef,
16602
+ enabled: keyboardNavigation
16603
+ });
16604
+ const isModalMode = useCallback(() => isModal({
16605
+ app,
16606
+ appSelections
16607
+ }), [app, appSelections]);
16143
16608
  const isInvalid = layout === null || layout === void 0 ? void 0 : layout.qListObject.qDimensionInfo.qError;
16144
16609
  const errorText = isInvalid && constraints.active ? 'Visualization.Invalid.Dimension' : 'Visualization.Incomplete';
16145
16610
  const {
16146
16611
  handleKeyDown,
16147
16612
  handleOnMouseEnter,
16148
- handleOnMouseLeave
16149
- } = getListboxInlineKeyboardNavigation({
16150
- setKeyboardActive,
16613
+ handleOnMouseLeave,
16614
+ globalKeyDown
16615
+ } = useMemo$1(() => getListboxInlineKeyboardNavigation({
16616
+ keyboard,
16151
16617
  hovering,
16152
- setHovering,
16153
16618
  updateKeyScroll,
16154
16619
  containerRef,
16155
16620
  currentScrollIndex,
16156
16621
  app,
16157
16622
  appSelections,
16158
- constraints
16159
- });
16160
-
16161
- // Expose the keyboard flags in the same way as the keyboard hook does.
16162
- const keyboard = {
16163
- enabled: keyboardNavigation,
16164
- // this will be static until we can access the useKeyboard hook
16165
- active: keyboardActive
16166
- };
16167
- const showDetachedToolbarOnly = toolbar && ((layout === null || layout === void 0 ? void 0 : layout.title) === '' || (layout === null || layout === void 0 ? void 0 : layout.showTitle) === false);
16168
- const showToolbarWithTitle = toolbar && (layout === null || layout === void 0 ? void 0 : layout.title) !== '' && (layout === null || layout === void 0 ? void 0 : layout.showTitle) !== false;
16623
+ constraints,
16624
+ isModal: isModalMode
16625
+ }), [keyboard, hovering, updateKeyScroll, containerRef, currentScrollIndex, app, appSelections, constraints, isModalMode]);
16626
+ const showDetachedToolbarOnly = toolbar && ((layout === null || layout === void 0 ? void 0 : layout.title) === '' || (layout === null || layout === void 0 ? void 0 : layout.showTitle) === false) && !isPopover;
16627
+ const showToolbarWithTitle = toolbar && (layout === null || layout === void 0 ? void 0 : layout.title) !== '' && (layout === null || layout === void 0 ? void 0 : layout.showTitle) !== false || isPopover;
16628
+ useEffect$1(() => {
16629
+ document.addEventListener('keydown', globalKeyDown);
16630
+ return () => {
16631
+ document.removeEventListener('keydown', globalKeyDown);
16632
+ };
16633
+ }, [globalKeyDown]);
16169
16634
  useEffect$1(() => {
16170
16635
  const show = () => {
16171
16636
  setShowToolbar(true);
@@ -16176,6 +16641,14 @@ function ListBoxInline(_ref3) {
16176
16641
  setShowSearch(false);
16177
16642
  }
16178
16643
  };
16644
+ if (isPopover) {
16645
+ if (!selections.isActive()) {
16646
+ selections.begin('/qListObjectDef');
16647
+ selections.on('activated', show);
16648
+ selections.on('deactivated', hide);
16649
+ }
16650
+ setShowToolbar(isPopover);
16651
+ }
16179
16652
  if (selections) {
16180
16653
  if (!selections.isModal()) {
16181
16654
  selections.on('activated', show);
@@ -16189,7 +16662,7 @@ function ListBoxInline(_ref3) {
16189
16662
  selections.removeListener('deactivated', hide);
16190
16663
  }
16191
16664
  };
16192
- }, [selections]);
16665
+ }, [selections, isPopover]);
16193
16666
  useEffect$1(() => {
16194
16667
  if (!searchContainer || !searchContainer.current) {
16195
16668
  return;
@@ -16237,8 +16710,8 @@ function ListBoxInline(_ref3) {
16237
16710
  input === null || input === void 0 ? void 0 : input.focus();
16238
16711
  }
16239
16712
  };
16240
- const getActionToolbarProps = isPopover => getListboxActionProps({
16241
- isPopover,
16713
+ const getActionToolbarProps = isDetached => getListboxActionProps({
16714
+ isDetached: isPopover ? false : isDetached,
16242
16715
  showToolbar,
16243
16716
  containerRef,
16244
16717
  isLocked,
@@ -16252,6 +16725,14 @@ function ListBoxInline(_ref3) {
16252
16725
  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
16253
16726
  const headerPaddingLeft = CELL_PADDING_LEFT - (showSearchOrLockIcon ? ICON_PADDING : 0);
16254
16727
  const headerPaddingRight = isRtl ? CELL_PADDING_LEFT - (showIcons ? ICON_PADDING : 0) : 0;
16728
+ const {
16729
+ isDetached,
16730
+ reasonDetached
16731
+ } = showToolbarDetached({
16732
+ containerRef,
16733
+ titleRef,
16734
+ iconsWidth
16735
+ });
16255
16736
 
16256
16737
  // Add a container padding for grid mode to harmonize with the grid item margins (should sum to 8px).
16257
16738
  const isGridMode = (layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.dataLayout) === 'grid';
@@ -16300,7 +16781,7 @@ function ListBoxInline(_ref3) {
16300
16781
  }, getActionToolbarProps(true))), /*#__PURE__*/React__default.createElement(StyledGrid$3, {
16301
16782
  className: "listbox-container",
16302
16783
  container: true,
16303
- tabIndex: keyboard.enabled && !keyboard.active ? 0 : -1,
16784
+ tabIndex: keyboard.enabled ? -1 : undefined,
16304
16785
  direction: "column",
16305
16786
  gap: 0,
16306
16787
  containerPadding: containerPadding,
@@ -16356,6 +16837,9 @@ function ListBoxInline(_ref3) {
16356
16837
  className: classes$4.listBoxHeader
16357
16838
  }, /*#__PURE__*/React__default.createElement(Title, {
16358
16839
  variant: "h6",
16840
+ sx: {
16841
+ width: isPopover && reasonDetached === 'noSpace' ? '60px' : undefined
16842
+ },
16359
16843
  noWrap: true,
16360
16844
  ref: titleRef,
16361
16845
  title: layout.title
@@ -16366,11 +16850,7 @@ function ListBoxInline(_ref3) {
16366
16850
  item: true
16367
16851
  }, /*#__PURE__*/React__default.createElement(ActionsToolbar, _extends$6({
16368
16852
  direction: direction
16369
- }, getActionToolbarProps(showToolbarDetached({
16370
- containerRef,
16371
- titleRef,
16372
- iconsWidth
16373
- })))))), /*#__PURE__*/React__default.createElement(Grid, {
16853
+ }, getActionToolbarProps(isDetached))))), /*#__PURE__*/React__default.createElement(Grid, {
16374
16854
  item: true,
16375
16855
  container: true,
16376
16856
  direction: "column",
@@ -16406,11 +16886,11 @@ function ListBoxInline(_ref3) {
16406
16886
  className: classes$4.screenReaderOnly
16407
16887
  }, translator.get('Listbox.ScreenReaderInstructions')), isInvalid ? /*#__PURE__*/React__default.createElement(ListBoxError, {
16408
16888
  text: errorText
16409
- }) : /*#__PURE__*/React__default.createElement(AutoSizer, null, _ref4 => {
16889
+ }) : /*#__PURE__*/React__default.createElement(AutoSizer, null, _ref5 => {
16410
16890
  let {
16411
16891
  height,
16412
16892
  width
16413
- } = _ref4;
16893
+ } = _ref5;
16414
16894
  return /*#__PURE__*/React__default.createElement(ListBox, {
16415
16895
  model: model,
16416
16896
  app: app,
@@ -16445,15 +16925,16 @@ function ListBoxInline(_ref3) {
16445
16925
  set: setCurrentScrollIndex
16446
16926
  },
16447
16927
  renderedCallback: renderedCallback,
16448
- onCtrlF: onCtrlF
16928
+ onCtrlF: onCtrlF,
16929
+ isModal: isModalMode
16449
16930
  });
16450
16931
  })))));
16451
16932
  }
16452
16933
  const ListBoxInlineMemoed = React__default.memo(ListBoxInline);
16453
- function IsolateUseLayoutWrapper(_ref5) {
16934
+ function IsolateUseLayoutWrapper(_ref6) {
16454
16935
  let {
16455
16936
  options = {}
16456
- } = _ref5;
16937
+ } = _ref6;
16457
16938
  const {
16458
16939
  model
16459
16940
  } = options;
@@ -21550,7 +22031,7 @@ function useRenderState() {
21550
22031
  * Gets an event emitter instance for the visualization.
21551
22032
  * @entry
21552
22033
  * @experimental
21553
- * @returns {Emitter} The emitter instance.
22034
+ * @returns {Emitter} The emitter instance. Implements https://nodejs.org/api/events.html#class-eventemitter.
21554
22035
  * @example
21555
22036
  * // In a Nebula visualization
21556
22037
  * import { useEmitter } from '@nebula.js/stardust';