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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.7
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 = "a704" ;
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.7" );
8276
8276
  element.setAttribute('data-app-id', app.id);
8277
8277
  document.body.appendChild(element);
8278
8278
  const root = client.createRoot(element);
@@ -9348,6 +9348,84 @@ const KEYS = Object.freeze({
9348
9348
  isArrow: key => key === KEYS.ARROW_UP || key === KEYS.ARROW_DOWN || key === KEYS.ARROW_LEFT || key === KEYS.ARROW_RIGHT
9349
9349
  });
9350
9350
 
9351
+ function removeInnnerTabStops(container) {
9352
+ container === null || container === void 0 ? void 0 : container.querySelectorAll('[tabIndex="0"]').forEach(elm => {
9353
+ elm.setAttribute('tabIndex', -1);
9354
+ });
9355
+ }
9356
+ function removeLastFocused(container) {
9357
+ container === null || container === void 0 ? void 0 : container.querySelectorAll('.last-focused').forEach(elm => {
9358
+ elm.classList.remove('last-focused');
9359
+ });
9360
+ }
9361
+ function getVizCell(container) {
9362
+ return (container === null || container === void 0 ? void 0 : container.closest('.njs-cell')) || (container === null || container === void 0 ? void 0 : container.closest('.qv-gridcell'));
9363
+ }
9364
+
9365
+ // Emulate the keyboard hook, until we support it in the Listbox.
9366
+ function useTempKeyboard(_ref) {
9367
+ let {
9368
+ containerRef,
9369
+ enabled
9370
+ } = _ref;
9371
+ const [keyboardActive, setKeyboardActive] = useState$1(false);
9372
+ const innerTabStops = !enabled || keyboardActive;
9373
+ const keyboard = {
9374
+ enabled,
9375
+ active: keyboardActive,
9376
+ innerTabStops,
9377
+ // does keyboard permit inner tab stops
9378
+ outerTabStops: !innerTabStops,
9379
+ // does keyboard permit outer tab stops
9380
+ blur: resetFocus => {
9381
+ var _containerRef$current;
9382
+ if (!enabled) {
9383
+ return;
9384
+ }
9385
+ setKeyboardActive(false);
9386
+ const vizCell = getVizCell(containerRef.current) || ((_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.parentElement);
9387
+ removeInnnerTabStops(containerRef.current);
9388
+ removeLastFocused(containerRef.current);
9389
+ if (resetFocus && vizCell) {
9390
+ // Move focus to the viz's cell.
9391
+ vizCell.setAttribute('tabIndex', 0);
9392
+ vizCell.focus();
9393
+ }
9394
+ },
9395
+ focus: () => {
9396
+ if (!enabled) {
9397
+ return;
9398
+ }
9399
+ setKeyboardActive(true);
9400
+ const c = containerRef.current;
9401
+ const searchField = c === null || c === void 0 ? void 0 : c.querySelector('.search input');
9402
+ const lastSelectedRow = c === null || c === void 0 ? void 0 : c.querySelector('.value.last-focused');
9403
+ const fieldElement = c === null || c === void 0 ? void 0 : c.querySelector('.value.selector, .value, .ActionsToolbar-item button');
9404
+ const elementToFocus = searchField || lastSelectedRow || fieldElement;
9405
+ elementToFocus === null || elementToFocus === void 0 ? void 0 : elementToFocus.setAttribute('tabIndex', 0);
9406
+ elementToFocus === null || elementToFocus === void 0 ? void 0 : elementToFocus.focus();
9407
+ },
9408
+ focusSelection: () => {
9409
+ const confirmButton = document.querySelector('.actions-toolbar-default-actions .actions-toolbar-confirm');
9410
+ confirmButton === null || confirmButton === void 0 ? void 0 : confirmButton.setAttribute('tabIndex', 0);
9411
+ confirmButton === null || confirmButton === void 0 ? void 0 : confirmButton.focus();
9412
+ }
9413
+ };
9414
+ return keyboard;
9415
+ }
9416
+
9417
+ const getElementIndex = currentTarget => +currentTarget.getAttribute('data-n');
9418
+ const focusSearch = container => {
9419
+ const searchField = container === null || container === void 0 ? void 0 : container.querySelector('.search input');
9420
+ searchField === null || searchField === void 0 ? void 0 : searchField.focus();
9421
+ return searchField;
9422
+ };
9423
+ const focusRow = container => {
9424
+ const row = container === null || container === void 0 ? void 0 : container.querySelector('.value.last-focused, .value.selector, .value');
9425
+ row === null || row === void 0 ? void 0 : row.setAttribute('tabIndex', 0);
9426
+ row === null || row === void 0 ? void 0 : row.focus();
9427
+ return row;
9428
+ };
9351
9429
  function getFieldKeyboardNavigation(_ref) {
9352
9430
  let {
9353
9431
  select,
@@ -9356,7 +9434,9 @@ function getFieldKeyboardNavigation(_ref) {
9356
9434
  confirm,
9357
9435
  cancel,
9358
9436
  setScrollPosition,
9359
- focusListItems
9437
+ focusListItems,
9438
+ keyboard,
9439
+ isModal
9360
9440
  } = _ref;
9361
9441
  const getElement = function (elm) {
9362
9442
  let next = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
@@ -9369,49 +9449,86 @@ function getFieldKeyboardNavigation(_ref) {
9369
9449
  };
9370
9450
  const handleKeyDown = event => {
9371
9451
  let elementToFocus;
9452
+ const {
9453
+ currentTarget,
9454
+ nativeEvent
9455
+ } = event;
9372
9456
  const {
9373
9457
  keyCode,
9374
9458
  shiftKey = false,
9375
9459
  ctrlKey = false,
9376
9460
  metaKey = false
9377
- } = event.nativeEvent;
9461
+ } = nativeEvent;
9378
9462
  switch (keyCode) {
9463
+ case KEYS.TAB:
9464
+ {
9465
+ // Try to focus search field, otherwise confirm button.
9466
+ const container = currentTarget.closest('.listbox-container');
9467
+ const inSelection = isModal();
9468
+
9469
+ // TODO: use a store to keep track of this row.
9470
+ currentTarget.classList.add('last-focused'); // so that we can go back here when we tab back
9471
+
9472
+ if (shiftKey) {
9473
+ if (!focusSearch(container)) {
9474
+ if (inSelection) {
9475
+ keyboard.focusSelection();
9476
+ } else {
9477
+ keyboard.blur(true);
9478
+ }
9479
+ }
9480
+ break;
9481
+ }
9482
+
9483
+ // Without shift key
9484
+ if (inSelection) {
9485
+ keyboard.focusSelection();
9486
+ } else {
9487
+ currentTarget.blur();
9488
+ keyboard.blur();
9489
+ }
9490
+ break;
9491
+ }
9379
9492
  case KEYS.SHIFT:
9380
9493
  // This is to ensure we include the first value when starting a range selection.
9381
9494
  setStartedRange(true);
9382
9495
  break;
9383
9496
  case KEYS.SPACE:
9384
- select([+event.currentTarget.getAttribute('data-n')], false, event);
9497
+ select([getElementIndex(currentTarget)], false, event);
9385
9498
  break;
9386
9499
  case KEYS.ARROW_DOWN:
9387
9500
  case KEYS.ARROW_RIGHT:
9388
- elementToFocus = getElement(event.currentTarget, true);
9501
+ elementToFocus = getElement(currentTarget, true);
9389
9502
  if (shiftKey && elementToFocus) {
9390
9503
  if (startedRange) {
9391
- select([+event.currentTarget.getAttribute('data-n')], true);
9504
+ select([getElementIndex(currentTarget)], true);
9392
9505
  setStartedRange(false);
9393
9506
  }
9394
- select([+elementToFocus.getAttribute('data-n')], true);
9507
+ select([getElementIndex(elementToFocus)], true);
9395
9508
  }
9396
9509
  break;
9397
9510
  case KEYS.ARROW_UP:
9398
9511
  case KEYS.ARROW_LEFT:
9399
- elementToFocus = getElement(event.currentTarget, false);
9512
+ elementToFocus = getElement(currentTarget, false);
9400
9513
  if (shiftKey && elementToFocus) {
9401
9514
  if (startedRange) {
9402
- select([+event.currentTarget.getAttribute('data-n')], true);
9515
+ select([getElementIndex(currentTarget)], true);
9403
9516
  setStartedRange(false);
9404
9517
  }
9405
- select([+elementToFocus.getAttribute('data-n')], true);
9518
+ select([getElementIndex(elementToFocus)], true);
9406
9519
  }
9407
9520
  break;
9408
9521
  case KEYS.ENTER:
9409
9522
  confirm();
9410
9523
  break;
9411
9524
  case KEYS.ESCAPE:
9412
- cancel();
9413
- return;
9414
- // let it propagate to top-level
9525
+ if (isModal()) {
9526
+ cancel();
9527
+ } else {
9528
+ return; // propagate to other Esc handler
9529
+ }
9530
+
9531
+ break;
9415
9532
  case KEYS.HOME:
9416
9533
  focusListItems.setFirst(true);
9417
9534
  if (ctrlKey) {
@@ -9455,39 +9572,41 @@ function getFieldKeyboardNavigation(_ref) {
9455
9572
  }
9456
9573
  function getListboxInlineKeyboardNavigation(_ref2) {
9457
9574
  let {
9458
- setKeyboardActive,
9575
+ keyboard,
9459
9576
  hovering,
9460
9577
  setHovering,
9461
9578
  updateKeyScroll,
9462
9579
  containerRef,
9463
9580
  currentScrollIndex,
9464
- app,
9465
- appSelections,
9581
+ isModal,
9466
9582
  constraints
9467
9583
  } = _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);
9584
+ const blur = event => {
9585
+ const {
9586
+ currentTarget,
9587
+ target
9588
+ } = event;
9589
+ const isFocusedOnListbox = target.classList.contains('listbox-container');
9590
+ const container = currentTarget.closest('.listbox-container');
9591
+ const vizCell = getVizCell(container);
9592
+ const isSingleListbox = (vizCell === null || vizCell === void 0 ? void 0 : vizCell.querySelectorAll('.listbox-container').length) === 1;
9593
+ if (isFocusedOnListbox || isSingleListbox) {
9594
+ // Move the focus from listbox container to the viz container.
9595
+ keyboard.blur(true);
9481
9596
  } 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();
9597
+ // More than one listbox: Move focus from row to listbox container.
9598
+
9599
+ // 1. Remove last-focused class from row siblings.
9600
+ removeLastFocused(containerRef.current);
9601
+
9602
+ // 2. Add last-focused class so we can re-focus it later.
9603
+ currentTarget.classList.add('last-focused');
9604
+
9605
+ // 3. Blur row and focus the listbox container.
9606
+ keyboard.blur();
9607
+ const c = currentTarget.closest('.listbox-container');
9608
+ c.setAttribute('tabIndex', 0);
9609
+ c === null || c === void 0 ? void 0 : c.focus();
9491
9610
  }
9492
9611
  };
9493
9612
  const updateKeyScrollOnHover = newState => {
@@ -9501,65 +9620,84 @@ function getListboxInlineKeyboardNavigation(_ref2) {
9501
9620
  ctrlKey = false,
9502
9621
  shiftKey = false
9503
9622
  } = event.nativeEvent;
9623
+ const prevent = () => {
9624
+ event.stopPropagation();
9625
+ event.preventDefault();
9626
+ };
9504
9627
  switch (keyCode) {
9505
- // case KEYS.TAB: TODO: Focus confirm button using keyboard.focusSelection when we can access the useKeyboard hook.
9506
- case KEYS.ENTER:
9507
- case KEYS.SPACE:
9508
- if (!event.target.classList.contains('listbox-container')) {
9509
- return; // don't mess with keydown handlers within the listbox
9510
- }
9511
-
9512
- focusInsideListbox(event.currentTarget);
9513
- break;
9514
- case KEYS.ESCAPE:
9515
- changeFocus(event);
9516
- break;
9517
- case KEYS.ARROW_UP:
9518
- updateKeyScrollOnHover({
9519
- up: 1
9520
- });
9521
- break;
9522
- case KEYS.ARROW_DOWN:
9523
- updateKeyScrollOnHover({
9524
- down: 1
9525
- });
9526
- break;
9527
- case KEYS.ARROW_LEFT:
9528
- case KEYS.ARROW_RIGHT:
9529
- return;
9530
- // let it propagate to top-level
9531
9628
  case KEYS.PAGE_UP:
9532
9629
  updateKeyScrollOnHover({
9533
9630
  up: currentScrollIndex.stop - currentScrollIndex.start
9534
9631
  });
9632
+ prevent();
9535
9633
  break;
9536
9634
  case KEYS.PAGE_DOWN:
9537
9635
  updateKeyScrollOnHover({
9538
9636
  down: currentScrollIndex.stop - currentScrollIndex.start
9539
9637
  });
9638
+ prevent();
9540
9639
  break;
9541
9640
  case KEYS.HOME:
9542
9641
  updateKeyScrollOnHover({
9543
9642
  scrollPosition: ctrlKey && shiftKey ? 'overflowStart' : 'start'
9544
9643
  });
9644
+ prevent();
9545
9645
  break;
9546
9646
  case KEYS.END:
9547
9647
  updateKeyScrollOnHover({
9548
9648
  scrollPosition: ctrlKey && shiftKey ? 'overflowEnd' : 'end'
9549
9649
  });
9650
+ prevent();
9550
9651
  break;
9551
- default:
9552
- return;
9652
+ case KEYS.ARROW_UP:
9653
+ updateKeyScrollOnHover({
9654
+ up: 1
9655
+ });
9656
+ prevent();
9657
+ break;
9658
+ case KEYS.ARROW_DOWN:
9659
+ updateKeyScrollOnHover({
9660
+ down: 1
9661
+ });
9662
+ prevent();
9663
+ break;
9664
+ }
9665
+ if (!keyboard.enabled) {
9666
+ // Other keys should not be handled unless keyboard is enabled.
9667
+ return undefined;
9553
9668
  }
9669
+ const container = event.currentTarget.closest('.listbox-container');
9670
+ switch (keyCode) {
9671
+ case KEYS.TAB:
9672
+ if (shiftKey) {
9673
+ focusRow(container) || focusSearch(container);
9674
+ } else {
9675
+ focusSearch(container) || focusRow(container);
9676
+ }
9677
+ prevent();
9678
+ break;
9679
+ case KEYS.ENTER:
9680
+ case KEYS.SPACE:
9681
+ if (!event.target.classList.contains('listbox-container')) {
9682
+ return undefined; // don't mess with keydown handlers within the listbox (e.g. row seletion)
9683
+ }
9554
9684
 
9555
- // Note: We should not stop propagation here as it will block the containing app
9556
- // from handling keydown events.
9557
- event.preventDefault();
9685
+ keyboard.focus();
9686
+ prevent();
9687
+ break;
9688
+ case KEYS.ESCAPE:
9689
+ blur(event);
9690
+ prevent();
9691
+ break;
9692
+ case KEYS.ARROW_LEFT:
9693
+ case KEYS.ARROW_RIGHT:
9694
+ return undefined;
9695
+ }
9696
+ return undefined;
9558
9697
  };
9559
9698
  const focusOnHoverDisabled = () => {
9560
- var _app$isInModalSelecti, _app$isInModalSelecti2;
9561
9699
  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();
9700
+ const appInModal = isModal();
9563
9701
  return selectNotAllowed || appInModal;
9564
9702
  };
9565
9703
  const handleOnMouseEnter = () => {
@@ -10247,13 +10385,15 @@ function Frequency(_ref) {
10247
10385
  dense,
10248
10386
  showGray
10249
10387
  } = _ref;
10388
+ const frequencyText = getFrequencyText(cell === null || cell === void 0 ? void 0 : cell.qFrequency);
10250
10389
  return /*#__PURE__*/React__default.createElement(Grid, {
10251
10390
  item: true,
10252
10391
  style: {
10253
10392
  display: 'flex',
10254
10393
  alignItems: 'center'
10255
10394
  },
10256
- className: rowColClasses.frequencyCount
10395
+ className: rowColClasses.frequencyCount,
10396
+ "aria-label": frequencyText
10257
10397
  }, /*#__PURE__*/React__default.createElement(Typography, {
10258
10398
  noWrap: true,
10259
10399
  color: "inherit",
@@ -10262,7 +10402,7 @@ function Frequency(_ref) {
10262
10402
  cell,
10263
10403
  checkboxes
10264
10404
  }) && rowColClasses.excludedTextWithCheckbox])
10265
- }, getFrequencyText(cell === null || cell === void 0 ? void 0 : cell.qFrequency)));
10405
+ }, frequencyText));
10266
10406
  }
10267
10407
 
10268
10408
  function getGridItemSizes(_ref) {
@@ -10299,7 +10439,7 @@ function getGridItemSizes(_ref) {
10299
10439
  }
10300
10440
 
10301
10441
  const ItemGrid = styled$1(Grid, {
10302
- shouldForwardProp: prop => !['dataLayout', 'layoutOrder', 'itemPadding', 'checkboxes'].includes(prop)
10442
+ shouldForwardProp: prop => !['dataLayout', 'layoutOrder', 'itemPadding', 'cellPaddingRight'].includes(prop)
10303
10443
  })(_ref => {
10304
10444
  let {
10305
10445
  dataLayout,
@@ -10334,6 +10474,79 @@ function getCellFromPages(_ref) {
10334
10474
  return c;
10335
10475
  }
10336
10476
 
10477
+ /* eslint-disable import/prefer-default-export */
10478
+ const LOC_STATES = {
10479
+ S: 'Object.Listbox.Selected',
10480
+ A: 'Object.Listbox.Alternative',
10481
+ O: 'Object.Listbox.Optional',
10482
+ XS: 'Object.Listbox.SelectedExcluded',
10483
+ L: 'Object.Listbox.Locked',
10484
+ X: 'Object.Listbox.Excluded',
10485
+ XL: 'Object.Listbox.ExcludedLock'
10486
+ };
10487
+ function getValueLabel(_ref) {
10488
+ let {
10489
+ translator,
10490
+ label,
10491
+ qState,
10492
+ isSelected,
10493
+ currentIndex,
10494
+ maxIndex,
10495
+ showSearch
10496
+ } = _ref;
10497
+ const stateTranslation = LOC_STATES[qState];
10498
+ const state = translator.get(stateTranslation);
10499
+ const srStringArr = [];
10500
+ if (isSelected) {
10501
+ const navTranslation = showSearch ? 'Listbox.ScreenReader.SearchThenSelectionsMenu.WithAccSelMenu' : 'Listbox.ScreenReader.SelectionMenu.WithAccSelMenu';
10502
+ const nav = translator.get(navTranslation);
10503
+ srStringArr.push(nav);
10504
+ }
10505
+ const valueString = "".concat(label, " ").concat(state);
10506
+ const indexString = translator.get('CurrentSelections.Of', [currentIndex + 1, maxIndex + 1]); // E.g. 3 of 20
10507
+ srStringArr.unshift(valueString, indexString);
10508
+ const srString = srStringArr.join('. ').trim();
10509
+ return srString;
10510
+ }
10511
+
10512
+ /**
10513
+ * Announces the selection state.
10514
+ *
10515
+ * @ignore
10516
+ * @param {Layout} object
10517
+ * @returns {Element} An (invisible) component.
10518
+ */
10519
+ function ScreenReaderForSelections(_ref2) {
10520
+ var _layout$qListObject;
10521
+ let {
10522
+ layout
10523
+ } = _ref2;
10524
+ const {
10525
+ translator
10526
+ } = useContext(InstanceContext);
10527
+ const {
10528
+ qStateCounts: s = {}
10529
+ } = (layout === null || layout === void 0 ? void 0 : (_layout$qListObject = layout.qListObject) === null || _layout$qListObject === void 0 ? void 0 : _layout$qListObject.qDimensionInfo) || {};
10530
+ const count = s.qSelected + s.qSelectedExcluded + s.qLocked + s.qLockedExcluded;
10531
+ let t;
10532
+ switch (count) {
10533
+ case 0:
10534
+ t = 'ScreenReader.ZeroSelected';
10535
+ break;
10536
+ case 1:
10537
+ t = 'ScreenReader.OneSelected';
10538
+ break;
10539
+ default:
10540
+ t = 'ScreenReader.ManySelected';
10541
+ break;
10542
+ }
10543
+ const text = translator.get(t, [count]);
10544
+ return /*#__PURE__*/React__default.createElement("div", {
10545
+ className: "screenReaderOnly",
10546
+ "aria-live": "assertive"
10547
+ }, text);
10548
+ }
10549
+
10337
10550
  function RowColumn(_ref) {
10338
10551
  var _cell$qText, _cell$qHighlightRange, _cell$qHighlightRange2;
10339
10552
  let {
@@ -10370,7 +10583,10 @@ function RowColumn(_ref) {
10370
10583
  focusListItems,
10371
10584
  listCount,
10372
10585
  itemPadding,
10373
- frequencyWidth
10586
+ frequencyWidth,
10587
+ translator,
10588
+ showSearch,
10589
+ isModal
10374
10590
  } = data;
10375
10591
  const {
10376
10592
  dense = false,
@@ -10420,8 +10636,10 @@ function RowColumn(_ref) {
10420
10636
  }
10421
10637
  }, [rowRef.current]);
10422
10638
  const handleKeyDownCallback = useCallback(getFieldKeyboardNavigation(_objectSpread2(_objectSpread2({}, actions), {}, {
10423
- focusListItems
10424
- })), [actions]);
10639
+ focusListItems,
10640
+ keyboard,
10641
+ isModal
10642
+ })), [actions, keyboard === null || keyboard === void 0 ? void 0 : keyboard.innerTabStops]);
10425
10643
  const cell = useMemo$1(() => getCellFromPages({
10426
10644
  pages,
10427
10645
  cellIndex
@@ -10486,6 +10704,14 @@ function RowColumn(_ref) {
10486
10704
  const showTick = !checkboxes && isSelected && !isLocked;
10487
10705
  const showIcon = !checkboxes && sizePermitsTickOrLock;
10488
10706
  const cellPaddingRight = checkboxes || !sizePermitsTickOrLock;
10707
+ const ariaLabel = getValueLabel({
10708
+ translator,
10709
+ label,
10710
+ qState: cell.qState,
10711
+ currentIndex: count.currentIndex,
10712
+ maxIndex: count.max,
10713
+ showSearch
10714
+ });
10489
10715
  return /*#__PURE__*/React__default.createElement(RowColRoot$1, {
10490
10716
  className: rowColClasses.barContainer,
10491
10717
  flexBasisProp: flexBasisVal,
@@ -10496,6 +10722,11 @@ function RowColumn(_ref) {
10496
10722
  frequencyWidth: frequencyWidth,
10497
10723
  "data-testid": "listbox.item"
10498
10724
  }, /*#__PURE__*/React__default.createElement(ItemGrid, {
10725
+ role: "row",
10726
+ "aria-label": ariaLabel,
10727
+ "aria-selected": isSelected,
10728
+ "aria-setsize": count.max,
10729
+ "aria-rowindex": count.currentIndex,
10499
10730
  ref: rowRef,
10500
10731
  container: true,
10501
10732
  dataLayout: dataLayout,
@@ -10513,8 +10744,7 @@ function RowColumn(_ref) {
10513
10744
  onMouseEnter: onMouseEnter,
10514
10745
  onKeyDown: handleKeyDownCallback,
10515
10746
  onContextMenu: preventContextMenu,
10516
- role: column ? 'column' : 'row',
10517
- tabIndex: isFirstElement && (!keyboard.enabled || keyboard.active) ? 0 : -1,
10747
+ tabIndex: isFirstElement && keyboard.innerTabStops ? 0 : -1,
10518
10748
  "data-n": cell === null || cell === void 0 ? void 0 : cell.qElemNumber
10519
10749
  }, (cell === null || cell === void 0 ? void 0 : cell.qFrequency) && /*#__PURE__*/React__default.createElement(Histogram, {
10520
10750
  qFrequency: cell === null || cell === void 0 ? void 0 : cell.qFrequency,
@@ -12130,7 +12360,10 @@ function getListBoxComponents(_ref) {
12130
12360
  setCurrentScrollIndex,
12131
12361
  constraints,
12132
12362
  frequencyMax,
12133
- freqIsAllowed
12363
+ freqIsAllowed,
12364
+ translator,
12365
+ showSearch,
12366
+ isModal
12134
12367
  } = _ref;
12135
12368
  const {
12136
12369
  layoutOptions = {}
@@ -12184,7 +12417,10 @@ function getListBoxComponents(_ref) {
12184
12417
  showTick,
12185
12418
  dataOffset: local.current.dataOffset,
12186
12419
  focusListItems,
12187
- direction
12420
+ direction,
12421
+ translator,
12422
+ showSearch,
12423
+ isModal
12188
12424
  });
12189
12425
  const List = _ref2 => {
12190
12426
  let {
@@ -12626,17 +12862,14 @@ function useDataStore(model) {
12626
12862
  };
12627
12863
  }
12628
12864
 
12629
- function ListBoxDisclaimer(_ref) {
12865
+ const StyledText = styled$1(Typography, {
12866
+ shouldForwardProp: p => !['width', 'dense'].includes(p)
12867
+ })(_ref => {
12630
12868
  let {
12631
12869
  width,
12632
- text,
12633
- dense,
12634
- tooltip
12870
+ dense
12635
12871
  } = _ref;
12636
- const {
12637
- translator
12638
- } = useContext(InstanceContext);
12639
- const StyledText = styled$1(Typography)(() => _objectSpread2({
12872
+ return _objectSpread2({
12640
12873
  minWidth: "".concat(width, "px"),
12641
12874
  textAlign: 'center',
12642
12875
  fontSize: "".concat(dense ? '12px' : '14px')
@@ -12645,10 +12878,23 @@ function ListBoxDisclaimer(_ref) {
12645
12878
  overflow: 'hidden',
12646
12879
  whiteSpace: 'nowrap',
12647
12880
  width
12648
- }));
12881
+ });
12882
+ });
12883
+ function ListBoxDisclaimer(_ref2) {
12884
+ let {
12885
+ width,
12886
+ text,
12887
+ dense,
12888
+ tooltip
12889
+ } = _ref2;
12890
+ const {
12891
+ translator
12892
+ } = useContext(InstanceContext);
12649
12893
  return /*#__PURE__*/React__default.createElement(Tooltip, {
12650
12894
  title: tooltip ? translator.get(text) : ''
12651
12895
  }, /*#__PURE__*/React__default.createElement(StyledText, {
12896
+ width: width,
12897
+ dense: dense,
12652
12898
  component: "div",
12653
12899
  variant: "body1",
12654
12900
  py: "12px"
@@ -13016,6 +13262,14 @@ const useFrequencyMax = (app, layout) => {
13016
13262
 
13017
13263
  const _excluded$4 = ["isLoadingData"];
13018
13264
  const DEFAULT_MIN_BATCH_SIZE = 100;
13265
+ const StyledWrapper = styled$4('div')(() => ({
13266
+ ["& .screenReaderOnly"]: {
13267
+ position: 'absolute',
13268
+ height: 0,
13269
+ width: 0,
13270
+ overflow: 'hidden'
13271
+ }
13272
+ }));
13019
13273
  function ListBox(_ref) {
13020
13274
  var _layout$qListObject$q, _loaderRef$current, _loaderRef$current$_l, _loaderRef$current$_l2;
13021
13275
  let {
@@ -13046,8 +13300,13 @@ function ListBox(_ref) {
13046
13300
  set: () => {}
13047
13301
  },
13048
13302
  renderedCallback,
13049
- onCtrlF
13303
+ onCtrlF,
13304
+ showSearch,
13305
+ isModal
13050
13306
  } = _ref;
13307
+ const {
13308
+ translator
13309
+ } = useContext(InstanceContext);
13051
13310
  const [initScrollPosIsSet, setInitScrollPosIsSet] = useState$1(false);
13052
13311
  const isSingleSelect = !!(layout && layout.qListObject.qDimensionInfo.qIsOneAndOnlyOne);
13053
13312
  const {
@@ -13302,7 +13561,10 @@ function ListBox(_ref) {
13302
13561
  setCurrentScrollIndex: currentScrollIndex.set,
13303
13562
  constraints,
13304
13563
  frequencyMax,
13305
- freqIsAllowed
13564
+ freqIsAllowed,
13565
+ translator,
13566
+ showSearch,
13567
+ isModal
13306
13568
  });
13307
13569
  const {
13308
13570
  columnWidth,
@@ -13317,7 +13579,10 @@ function ListBox(_ref) {
13317
13579
  itemHeight
13318
13580
  });
13319
13581
  }
13320
- return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, !listCount && /*#__PURE__*/React__default.createElement(ListBoxDisclaimer, {
13582
+ return /*#__PURE__*/React__default.createElement(StyledWrapper, null, /*#__PURE__*/React__default.createElement(ScreenReaderForSelections, {
13583
+ className: "screenReaderOnly",
13584
+ layout: layout
13585
+ }), !listCount && /*#__PURE__*/React__default.createElement(ListBoxDisclaimer, {
13321
13586
  width: width,
13322
13587
  text: "Listbox.NoMatchesForYourTerms"
13323
13588
  }), /*#__PURE__*/React__default.createElement(InfiniteLoader, {
@@ -13329,7 +13594,8 @@ function ListBox(_ref) {
13329
13594
  }),
13330
13595
  threshold: 0,
13331
13596
  minimumBatchSize: minimumBatchSize,
13332
- ref: loaderRef
13597
+ ref: loaderRef,
13598
+ role: "grid"
13333
13599
  }, isVertical ? List : Grid), overflowDisclaimer.show && !overflowDisclaimer.dismissed && /*#__PURE__*/React__default.createElement(ListBoxFooter, {
13334
13600
  text: "Listbox.ItemsOverflow",
13335
13601
  dismiss: () => setOverflowDisclaimer(state => _objectSpread2(_objectSpread2({}, state), {}, {
@@ -13481,6 +13747,7 @@ const Item = React__default.forwardRef((_ref, ref) => {
13481
13747
  if (hidden) return null;
13482
13748
  const spacing = Number.parseInt(theme.spacing(0.5), 10);
13483
13749
  const handleKeyDown = item.keyboardAction ? e => ['Enter', ' ', 'Spacebar'].includes(e.key) && item.keyboardAction() : null;
13750
+ const btnId = "actions-toolbar-".concat(item.key);
13484
13751
  return /*#__PURE__*/React__default.createElement(IconButton, {
13485
13752
  ref: !addAnchor ? ref : null,
13486
13753
  title: item.label,
@@ -13488,12 +13755,12 @@ const Item = React__default.forwardRef((_ref, ref) => {
13488
13755
  onKeyDown: handleKeyDown,
13489
13756
  disabled: disabled,
13490
13757
  style: style,
13491
- className: ActionElement.className,
13758
+ className: [ActionElement.className, btnId].join(' '),
13492
13759
  size: "large",
13493
13760
  disableRipple: true,
13494
13761
  "aria-expanded": ariaExpanded,
13495
13762
  "aria-controls": "moreMenuList",
13496
- "data-testid": "actions-toolbar-".concat(item.key)
13763
+ "data-testid": btnId
13497
13764
  }, hasSvgIconShape && SvgIcon$2(item.getSvgIconShape()), addAnchor && /*#__PURE__*/React__default.createElement("div", {
13498
13765
  ref: ref,
13499
13766
  style: {
@@ -13672,6 +13939,70 @@ const More$1 = React__default.forwardRef((_ref3, ref) => {
13672
13939
  }))));
13673
13940
  });
13674
13941
 
13942
+ const getActionButtonIndex = btn => {
13943
+ const toolbar = btn.closest('#actions-toolbar');
13944
+ const nodeList = toolbar === null || toolbar === void 0 ? void 0 : toolbar.querySelectorAll('.njs-cell-action');
13945
+ return Array.from(nodeList).indexOf(btn);
13946
+ };
13947
+ const focusButton = index => {
13948
+ const toolbar = document.querySelector('#actions-toolbar');
13949
+ const nodeList = toolbar === null || toolbar === void 0 ? void 0 : toolbar.querySelectorAll('.njs-cell-action');
13950
+ if (!nodeList.length) {
13951
+ return;
13952
+ }
13953
+ const ix = Math.min(Math.max(0, index), nodeList.length - 1);
13954
+ const btn = nodeList[ix];
13955
+ btn.focus();
13956
+ };
13957
+ function getActionsKeyDownHandler(_ref) {
13958
+ let {
13959
+ keyboardNavigation,
13960
+ focusHandler,
13961
+ getEnabledButton
13962
+ } = _ref;
13963
+ const handleActionsKeyDown = evt => {
13964
+ const {
13965
+ target,
13966
+ nativeEvent
13967
+ } = evt;
13968
+ const {
13969
+ keyCode
13970
+ } = nativeEvent;
13971
+ switch (keyCode) {
13972
+ case KEYS.ARROW_LEFT:
13973
+ case KEYS.ARROW_DOWN:
13974
+ case KEYS.ARROW_RIGHT:
13975
+ case KEYS.ARROW_UP:
13976
+ {
13977
+ const isActionButton = target.classList.contains('njs-cell-action');
13978
+ if (isActionButton) {
13979
+ const index = getActionButtonIndex(target);
13980
+ const pressedLeft = [KEYS.ARROW_LEFT, KEYS.ARROW_DOWN].includes(keyCode);
13981
+ focusButton(pressedLeft ? index - 1 : index + 1);
13982
+ }
13983
+ evt.stopPropagation();
13984
+ evt.preventDefault();
13985
+ break;
13986
+ }
13987
+ case KEYS.SPACE:
13988
+ evt.preventDefault(); // prevent scrolling in listbox
13989
+ break;
13990
+ case KEYS.TAB:
13991
+ if (keyboardNavigation && focusHandler !== null && focusHandler !== void 0 && focusHandler.refocusContent) {
13992
+ const isTabbingOut = evt.shiftKey && getEnabledButton(false) === evt.target || !evt.shiftKey && getEnabledButton(true) === evt.target;
13993
+ if (isTabbingOut) {
13994
+ evt.preventDefault();
13995
+ evt.stopPropagation();
13996
+ // if keyboardNavigation is true, create a callback to handle tabbing from the first/last button in the toolbar that resets focus on the content
13997
+ focusHandler.refocusContent();
13998
+ }
13999
+ }
14000
+ break;
14001
+ }
14002
+ };
14003
+ return handleActionsKeyDown;
14004
+ }
14005
+
13675
14006
  const PREFIX$7 = 'ActionsToolbar';
13676
14007
  const classes$7 = {
13677
14008
  item: "".concat(PREFIX$7, "-item"),
@@ -13707,6 +14038,7 @@ const ActionToolbarElement = {
13707
14038
  };
13708
14039
  const ActionsGroup = React__default.forwardRef((_ref2, ref) => {
13709
14040
  let {
14041
+ className,
13710
14042
  ariaExpanded = false,
13711
14043
  actions = [],
13712
14044
  first = false,
@@ -13719,7 +14051,8 @@ const ActionsGroup = React__default.forwardRef((_ref2, ref) => {
13719
14051
  container: true,
13720
14052
  gap: 0,
13721
14053
  flexDirection: isRtl ? 'row-reverse' : 'row',
13722
- wrap: "nowrap"
14054
+ wrap: "nowrap",
14055
+ className: className
13723
14056
  }, actions.map((e, ix) => {
13724
14057
  let cls = [];
13725
14058
  const isFirstItem = first && ix === 0;
@@ -13787,22 +14120,27 @@ function ActionsToolbar(_ref3) {
13787
14120
  keyboardNavigation
13788
14121
  } = useContext(InstanceContext);
13789
14122
  const [showMoreItems, setShowMoreItems] = useState$1(false);
13790
- const moreRef = useRef();
14123
+ const popoverAnchorOrigin = {
14124
+ vertical: 7,
14125
+ 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
14126
+ };
13791
14127
  const actionsRef = useRef();
14128
+ const moreRef = useRef();
13792
14129
  const theme = useTheme$1();
13793
14130
  const dividerStyle = useMemo$1(() => ({
13794
14131
  margin: theme.spacing(0.5, 0)
13795
14132
  }));
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
14133
  const getEnabledButton = last => {
13801
14134
  const actionsElement = actionsRef.current || actionsRefMock;
13802
14135
  if (!actionsElement) return null;
13803
14136
  const buttons = actionsElement.querySelectorAll('button:not(.Mui-disabled)');
13804
14137
  return buttons[last ? buttons.length - 1 : 0];
13805
14138
  };
14139
+ const handleActionsKeyDown = useMemo$1(() => getActionsKeyDownHandler({
14140
+ keyboardNavigation,
14141
+ focusHandler,
14142
+ getEnabledButton
14143
+ }), [keyboardNavigation, focusHandler, getEnabledButton]);
13806
14144
  useEffect$1(() => () => {
13807
14145
  setShowMoreItems(false);
13808
14146
  }, [popover.show, show, selections.show]);
@@ -13842,27 +14180,18 @@ function ActionsToolbar(_ref3) {
13842
14180
  enabled: () => moreEnabled,
13843
14181
  action: () => setShowMoreItems(!showMoreItems)
13844
14182
  };
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
14183
  const showActions = newActions.length > 0;
13857
14184
  const showMore = moreActions.length > 0;
13858
14185
  const showDivider = showActions && selections.show || showMore && selections.show;
13859
14186
  const isRtl = direction === 'rtl';
13860
14187
  const Actions = /*#__PURE__*/React__default.createElement(Grid, {
13861
14188
  ref: actionsRef,
13862
- onKeyDown: tabCallback,
14189
+ onKeyDown: handleActionsKeyDown,
13863
14190
  container: true,
13864
14191
  gap: 0,
13865
14192
  wrap: "nowrap",
14193
+ id: "actions-toolbar",
14194
+ "data-testid": "actions-toolbar",
13866
14195
  sx: {
13867
14196
  flexDirection: isRtl ? 'row-reverse' : 'row'
13868
14197
  }
@@ -13871,6 +14200,8 @@ function ActionsToolbar(_ref3) {
13871
14200
  first: true,
13872
14201
  last: !showMore && !selections.show
13873
14202
  }), showMore && /*#__PURE__*/React__default.createElement(ActionsGroup, {
14203
+ id: "actions-toolbar-show-more",
14204
+ "data-testid": "actions-toolbar-show-more",
13874
14205
  ref: moreRef,
13875
14206
  ariaExpanded: showMoreItems,
13876
14207
  actions: [moreItem],
@@ -13884,6 +14215,7 @@ function ActionsToolbar(_ref3) {
13884
14215
  }, /*#__PURE__*/React__default.createElement(Divider, {
13885
14216
  orientation: "vertical"
13886
14217
  })), selections.show && /*#__PURE__*/React__default.createElement(ActionsGroup, {
14218
+ className: "actions-toolbar-default-actions",
13887
14219
  actions: defaultSelectionActions,
13888
14220
  first: !showActions && !showMore,
13889
14221
  last: true,
@@ -13907,6 +14239,8 @@ function ActionsToolbar(_ref3) {
13907
14239
  hideBackdrop: true,
13908
14240
  style: popoverStyle,
13909
14241
  PaperProps: {
14242
+ id: 'njs-action-toolbar-popover',
14243
+ 'data-testid': 'njs-action-toolbar-popover',
13910
14244
  className: ActionToolbarElement.className,
13911
14245
  style: {
13912
14246
  pointerEvents: 'auto',
@@ -14034,29 +14368,57 @@ function ListBoxSearch(_ref3) {
14034
14368
  }
14035
14369
  return response;
14036
14370
  };
14371
+ function focusRow(container) {
14372
+ 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'));
14373
+ row.setAttribute('tabIndex', 0);
14374
+ row === null || row === void 0 ? void 0 : row.focus();
14375
+ }
14037
14376
  const onKeyDown = async e => {
14038
- let response;
14377
+ const {
14378
+ currentTarget
14379
+ } = e;
14380
+ const container = currentTarget.closest('.listbox-container');
14039
14381
  switch (e.key) {
14040
14382
  case 'Enter':
14041
- response = await performSearch();
14383
+ performSearch();
14042
14384
  break;
14043
14385
  case 'Escape':
14044
- response = cancel();
14045
- e.preventDefault();
14046
- e.stopPropagation();
14047
- break;
14386
+ {
14387
+ focusRow(container);
14388
+ cancel();
14389
+ break;
14390
+ }
14391
+ case 'Tab':
14392
+ {
14393
+ if (e.shiftKey) {
14394
+ keyboard.focusSelection();
14395
+ } else {
14396
+ // Focus the row we last visited or the first one.
14397
+ focusRow(container);
14398
+
14399
+ // Clean up.
14400
+ container === null || container === void 0 ? void 0 : container.querySelectorAll('.last-focused').forEach(elm => {
14401
+ elm.classList.remove('last-focused');
14402
+ });
14403
+ }
14404
+ break;
14405
+ }
14048
14406
  case 'f':
14049
14407
  case 'F':
14050
14408
  if (e.ctrlKey || e.metaKey) {
14051
14409
  if (hide) {
14052
14410
  hide();
14053
14411
  }
14054
- e.preventDefault();
14055
- e.stopPropagation();
14412
+ } else {
14413
+ return undefined;
14056
14414
  }
14057
14415
  break;
14416
+ default:
14417
+ return undefined;
14058
14418
  }
14059
- return response;
14419
+ e.preventDefault();
14420
+ e.stopPropagation();
14421
+ return undefined;
14060
14422
  };
14061
14423
  if (!visible || searchEnabled === false) {
14062
14424
  return null;
@@ -14102,10 +14464,11 @@ function ListBoxSearch(_ref3) {
14102
14464
  onKeyDown: onKeyDown,
14103
14465
  autoFocus: autoFocus,
14104
14466
  inputProps: {
14105
- tabIndex: keyboard && (!keyboard.enabled || keyboard.active) ? 0 : -1,
14467
+ tabIndex: keyboard.innerTabStops ? 0 : -1,
14106
14468
  style: {
14107
14469
  textAlign: "".concat(inpuTextAlign)
14108
- }
14470
+ },
14471
+ 'data-testid': 'search-input-field'
14109
14472
  }
14110
14473
  });
14111
14474
  }
@@ -14349,6 +14712,12 @@ function useObjectSelections(app, model, elements, options) {
14349
14712
  objectSelections.addListener('activated', activateClickOut);
14350
14713
  objectSelections.addListener('deactivated', deactivateClickOut);
14351
14714
  return () => {
14715
+ // confirm selection before removing event handler
14716
+ // to end the selection when the object is removed
14717
+ // and remove the (ClickOut) mousedown handler from the document
14718
+ if (objectSelections.isActive()) {
14719
+ objectSelections.confirm();
14720
+ }
14352
14721
  objectSelections.removeListener('activated', activateClickOut);
14353
14722
  objectSelections.removeListener('deactivated', deactivateClickOut);
14354
14723
  };
@@ -16004,6 +16373,13 @@ function getListboxActionProps(_ref) {
16004
16373
  };
16005
16374
  }
16006
16375
 
16376
+ const StyledDiv = styled$1('div')(() => ({
16377
+ display: 'flex',
16378
+ width: '100%',
16379
+ height: '100%',
16380
+ alignItems: 'center',
16381
+ justifyContent: 'center'
16382
+ }));
16007
16383
  function ListBoxError(_ref) {
16008
16384
  let {
16009
16385
  text
@@ -16011,13 +16387,6 @@ function ListBoxError(_ref) {
16011
16387
  const {
16012
16388
  translator
16013
16389
  } = 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
16390
  return /*#__PURE__*/React__default.createElement(StyledDiv, null, translator.get(text));
16022
16391
  }
16023
16392
 
@@ -16072,12 +16441,20 @@ const Title = styled$1(Typography)(_ref2 => {
16072
16441
  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
16442
  };
16074
16443
  });
16075
- function ListBoxInline(_ref3) {
16444
+ const isModal = _ref3 => {
16445
+ var _app$isInModalSelecti, _app$isInModalSelecti2;
16446
+ let {
16447
+ app,
16448
+ appSelections
16449
+ } = _ref3;
16450
+ 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();
16451
+ };
16452
+ function ListBoxInline(_ref4) {
16076
16453
  var _layoutOptions$dense;
16077
16454
  let {
16078
16455
  options,
16079
16456
  layout
16080
- } = _ref3;
16457
+ } = _ref4;
16081
16458
  const {
16082
16459
  app,
16083
16460
  direction,
@@ -16125,7 +16502,6 @@ function ListBoxInline(_ref3) {
16125
16502
  const [searchContainer, searchContainerRef] = useRefWithCallback();
16126
16503
  const [showToolbar, setShowToolbar] = useState$1(false);
16127
16504
  const [showSearch, setShowSearch] = useState$1(false);
16128
- const [keyboardActive, setKeyboardActive] = useState$1(false);
16129
16505
  const [hovering, setHovering] = useState$1(false);
16130
16506
  const [keyScroll, setKeyScroll] = useState$1({
16131
16507
  down: 0,
@@ -16140,6 +16516,14 @@ function ListBoxInline(_ref3) {
16140
16516
  const [appSelections] = useAppSelections(app);
16141
16517
  const titleRef = useRef(null);
16142
16518
  const [selectionState$1] = useState$1(() => selectionState());
16519
+ const keyboard = useTempKeyboard({
16520
+ containerRef,
16521
+ enabled: keyboardNavigation
16522
+ });
16523
+ const isModalMode = useCallback(() => isModal({
16524
+ app,
16525
+ appSelections
16526
+ }), [app, appSelections]);
16143
16527
  const isInvalid = layout === null || layout === void 0 ? void 0 : layout.qListObject.qDimensionInfo.qError;
16144
16528
  const errorText = isInvalid && constraints.active ? 'Visualization.Invalid.Dimension' : 'Visualization.Incomplete';
16145
16529
  const {
@@ -16147,7 +16531,7 @@ function ListBoxInline(_ref3) {
16147
16531
  handleOnMouseEnter,
16148
16532
  handleOnMouseLeave
16149
16533
  } = getListboxInlineKeyboardNavigation({
16150
- setKeyboardActive,
16534
+ keyboard,
16151
16535
  hovering,
16152
16536
  setHovering,
16153
16537
  updateKeyScroll,
@@ -16155,15 +16539,9 @@ function ListBoxInline(_ref3) {
16155
16539
  currentScrollIndex,
16156
16540
  app,
16157
16541
  appSelections,
16158
- constraints
16542
+ constraints,
16543
+ isModal: isModalMode
16159
16544
  });
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
16545
  const showDetachedToolbarOnly = toolbar && ((layout === null || layout === void 0 ? void 0 : layout.title) === '' || (layout === null || layout === void 0 ? void 0 : layout.showTitle) === false);
16168
16546
  const showToolbarWithTitle = toolbar && (layout === null || layout === void 0 ? void 0 : layout.title) !== '' && (layout === null || layout === void 0 ? void 0 : layout.showTitle) !== false;
16169
16547
  useEffect$1(() => {
@@ -16300,7 +16678,7 @@ function ListBoxInline(_ref3) {
16300
16678
  }, getActionToolbarProps(true))), /*#__PURE__*/React__default.createElement(StyledGrid$3, {
16301
16679
  className: "listbox-container",
16302
16680
  container: true,
16303
- tabIndex: keyboard.enabled && !keyboard.active ? 0 : -1,
16681
+ tabIndex: keyboard.outerTabStops ? 0 : -1,
16304
16682
  direction: "column",
16305
16683
  gap: 0,
16306
16684
  containerPadding: containerPadding,
@@ -16406,11 +16784,11 @@ function ListBoxInline(_ref3) {
16406
16784
  className: classes$4.screenReaderOnly
16407
16785
  }, translator.get('Listbox.ScreenReaderInstructions')), isInvalid ? /*#__PURE__*/React__default.createElement(ListBoxError, {
16408
16786
  text: errorText
16409
- }) : /*#__PURE__*/React__default.createElement(AutoSizer, null, _ref4 => {
16787
+ }) : /*#__PURE__*/React__default.createElement(AutoSizer, null, _ref5 => {
16410
16788
  let {
16411
16789
  height,
16412
16790
  width
16413
- } = _ref4;
16791
+ } = _ref5;
16414
16792
  return /*#__PURE__*/React__default.createElement(ListBox, {
16415
16793
  model: model,
16416
16794
  app: app,
@@ -16445,15 +16823,16 @@ function ListBoxInline(_ref3) {
16445
16823
  set: setCurrentScrollIndex
16446
16824
  },
16447
16825
  renderedCallback: renderedCallback,
16448
- onCtrlF: onCtrlF
16826
+ onCtrlF: onCtrlF,
16827
+ isModal: isModalMode
16449
16828
  });
16450
16829
  })))));
16451
16830
  }
16452
16831
  const ListBoxInlineMemoed = React__default.memo(ListBoxInline);
16453
- function IsolateUseLayoutWrapper(_ref5) {
16832
+ function IsolateUseLayoutWrapper(_ref6) {
16454
16833
  let {
16455
16834
  options = {}
16456
- } = _ref5;
16835
+ } = _ref6;
16457
16836
  const {
16458
16837
  model
16459
16838
  } = options;
@@ -21550,7 +21929,7 @@ function useRenderState() {
21550
21929
  * Gets an event emitter instance for the visualization.
21551
21930
  * @entry
21552
21931
  * @experimental
21553
- * @returns {Emitter} The emitter instance.
21932
+ * @returns {Emitter} The emitter instance. Implements https://nodejs.org/api/events.html#class-eventemitter.
21554
21933
  * @example
21555
21934
  * // In a Nebula visualization
21556
21935
  * import { useEmitter } from '@nebula.js/stardust';