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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /*
2
- * @nebula.js/stardust v4.0.0-alpha.5
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
  */
@@ -1563,7 +1563,7 @@
1563
1563
  var SelectionToolbar_ClickToUnlock = {
1564
1564
  id: "SelectionToolbar.ClickToUnlock",
1565
1565
  locale: {
1566
- "de-DE": "Klicken zum Freigeben",
1566
+ "de-DE": "Zum Entsperren klicken",
1567
1567
  "en-US": "Click to unlock",
1568
1568
  "es-ES": "Haga clic para desbloquearla",
1569
1569
  "fr-FR": "Cliquez pour déverrouiller",
@@ -15420,7 +15420,7 @@
15420
15420
  return cache[key];
15421
15421
  }
15422
15422
 
15423
- const NEBULA_VERSION_HASH = "6643" ;
15423
+ const NEBULA_VERSION_HASH = "a704" ;
15424
15424
  ClassNameGenerator$1.configure(componentName => {
15425
15425
  return "njs-".concat(NEBULA_VERSION_HASH, "-").concat(componentName.replace('Mui', ''));
15426
15426
  });
@@ -15628,7 +15628,7 @@
15628
15628
  const appRef = React.createRef();
15629
15629
  const element = document.createElement('div');
15630
15630
  element.style.display = 'none';
15631
- element.setAttribute('data-nebulajs-version', "4.0.0-alpha.5" );
15631
+ element.setAttribute('data-nebulajs-version', "4.0.0-alpha.7" );
15632
15632
  element.setAttribute('data-app-id', app.id);
15633
15633
  document.body.appendChild(element);
15634
15634
  const root = client.createRoot(element);
@@ -21702,7 +21702,7 @@
21702
21702
  return elemNumbersOrdered.slice(min, max + 1);
21703
21703
  }
21704
21704
 
21705
- const getKeyAsToggleSelected = event => !(event.metaKey || event.ctrlKey);
21705
+ const getKeyAsToggleSelected = event => !(event !== null && event !== void 0 && event.metaKey || event !== null && event !== void 0 && event.ctrlKey);
21706
21706
  function useSelectionsInteractions(_ref) {
21707
21707
  let {
21708
21708
  selectionState,
@@ -21743,6 +21743,11 @@
21743
21743
  const selectManually = function () {
21744
21744
  let elementIds = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
21745
21745
  let additive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
21746
+ let event = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
21747
+ const toggle = !selectionState.isSingleSelect && getKeyAsToggleSelected(event === null || event === void 0 ? void 0 : event.nativeEvent);
21748
+ if (!toggle) {
21749
+ selectionState.clearItemStates(true);
21750
+ }
21746
21751
  const elemNumbers = [];
21747
21752
  selectionState.updateItems(elementIds, additive, elemNumbers);
21748
21753
  selectionState.setSelectableValuesUpdating();
@@ -21750,7 +21755,7 @@
21750
21755
  selections,
21751
21756
  elemNumbers: additive ? elemNumbers : elementIds,
21752
21757
  isSingleSelect: selectionState.isSingleSelect,
21753
- toggle: !selectionState.isSingleSelect
21758
+ toggle
21754
21759
  });
21755
21760
  };
21756
21761
  const handleSingleSelectKey = (event, target) => {
@@ -21974,6 +21979,84 @@
21974
21979
  isArrow: key => key === KEYS.ARROW_UP || key === KEYS.ARROW_DOWN || key === KEYS.ARROW_LEFT || key === KEYS.ARROW_RIGHT
21975
21980
  });
21976
21981
 
21982
+ function removeInnnerTabStops(container) {
21983
+ container === null || container === void 0 ? void 0 : container.querySelectorAll('[tabIndex="0"]').forEach(elm => {
21984
+ elm.setAttribute('tabIndex', -1);
21985
+ });
21986
+ }
21987
+ function removeLastFocused(container) {
21988
+ container === null || container === void 0 ? void 0 : container.querySelectorAll('.last-focused').forEach(elm => {
21989
+ elm.classList.remove('last-focused');
21990
+ });
21991
+ }
21992
+ function getVizCell(container) {
21993
+ return (container === null || container === void 0 ? void 0 : container.closest('.njs-cell')) || (container === null || container === void 0 ? void 0 : container.closest('.qv-gridcell'));
21994
+ }
21995
+
21996
+ // Emulate the keyboard hook, until we support it in the Listbox.
21997
+ function useTempKeyboard(_ref) {
21998
+ let {
21999
+ containerRef,
22000
+ enabled
22001
+ } = _ref;
22002
+ const [keyboardActive, setKeyboardActive] = reactExports.useState(false);
22003
+ const innerTabStops = !enabled || keyboardActive;
22004
+ const keyboard = {
22005
+ enabled,
22006
+ active: keyboardActive,
22007
+ innerTabStops,
22008
+ // does keyboard permit inner tab stops
22009
+ outerTabStops: !innerTabStops,
22010
+ // does keyboard permit outer tab stops
22011
+ blur: resetFocus => {
22012
+ var _containerRef$current;
22013
+ if (!enabled) {
22014
+ return;
22015
+ }
22016
+ setKeyboardActive(false);
22017
+ const vizCell = getVizCell(containerRef.current) || ((_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.parentElement);
22018
+ removeInnnerTabStops(containerRef.current);
22019
+ removeLastFocused(containerRef.current);
22020
+ if (resetFocus && vizCell) {
22021
+ // Move focus to the viz's cell.
22022
+ vizCell.setAttribute('tabIndex', 0);
22023
+ vizCell.focus();
22024
+ }
22025
+ },
22026
+ focus: () => {
22027
+ if (!enabled) {
22028
+ return;
22029
+ }
22030
+ setKeyboardActive(true);
22031
+ const c = containerRef.current;
22032
+ const searchField = c === null || c === void 0 ? void 0 : c.querySelector('.search input');
22033
+ const lastSelectedRow = c === null || c === void 0 ? void 0 : c.querySelector('.value.last-focused');
22034
+ const fieldElement = c === null || c === void 0 ? void 0 : c.querySelector('.value.selector, .value, .ActionsToolbar-item button');
22035
+ const elementToFocus = searchField || lastSelectedRow || fieldElement;
22036
+ elementToFocus === null || elementToFocus === void 0 ? void 0 : elementToFocus.setAttribute('tabIndex', 0);
22037
+ elementToFocus === null || elementToFocus === void 0 ? void 0 : elementToFocus.focus();
22038
+ },
22039
+ focusSelection: () => {
22040
+ const confirmButton = document.querySelector('.actions-toolbar-default-actions .actions-toolbar-confirm');
22041
+ confirmButton === null || confirmButton === void 0 ? void 0 : confirmButton.setAttribute('tabIndex', 0);
22042
+ confirmButton === null || confirmButton === void 0 ? void 0 : confirmButton.focus();
22043
+ }
22044
+ };
22045
+ return keyboard;
22046
+ }
22047
+
22048
+ const getElementIndex = currentTarget => +currentTarget.getAttribute('data-n');
22049
+ const focusSearch = container => {
22050
+ const searchField = container === null || container === void 0 ? void 0 : container.querySelector('.search input');
22051
+ searchField === null || searchField === void 0 ? void 0 : searchField.focus();
22052
+ return searchField;
22053
+ };
22054
+ const focusRow = container => {
22055
+ const row = container === null || container === void 0 ? void 0 : container.querySelector('.value.last-focused, .value.selector, .value');
22056
+ row === null || row === void 0 ? void 0 : row.setAttribute('tabIndex', 0);
22057
+ row === null || row === void 0 ? void 0 : row.focus();
22058
+ return row;
22059
+ };
21977
22060
  function getFieldKeyboardNavigation(_ref) {
21978
22061
  let {
21979
22062
  select,
@@ -21982,7 +22065,9 @@
21982
22065
  confirm,
21983
22066
  cancel,
21984
22067
  setScrollPosition,
21985
- focusListItems
22068
+ focusListItems,
22069
+ keyboard,
22070
+ isModal
21986
22071
  } = _ref;
21987
22072
  const getElement = function (elm) {
21988
22073
  let next = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
@@ -21995,49 +22080,86 @@
21995
22080
  };
21996
22081
  const handleKeyDown = event => {
21997
22082
  let elementToFocus;
22083
+ const {
22084
+ currentTarget,
22085
+ nativeEvent
22086
+ } = event;
21998
22087
  const {
21999
22088
  keyCode,
22000
22089
  shiftKey = false,
22001
22090
  ctrlKey = false,
22002
22091
  metaKey = false
22003
- } = event.nativeEvent;
22092
+ } = nativeEvent;
22004
22093
  switch (keyCode) {
22094
+ case KEYS.TAB:
22095
+ {
22096
+ // Try to focus search field, otherwise confirm button.
22097
+ const container = currentTarget.closest('.listbox-container');
22098
+ const inSelection = isModal();
22099
+
22100
+ // TODO: use a store to keep track of this row.
22101
+ currentTarget.classList.add('last-focused'); // so that we can go back here when we tab back
22102
+
22103
+ if (shiftKey) {
22104
+ if (!focusSearch(container)) {
22105
+ if (inSelection) {
22106
+ keyboard.focusSelection();
22107
+ } else {
22108
+ keyboard.blur(true);
22109
+ }
22110
+ }
22111
+ break;
22112
+ }
22113
+
22114
+ // Without shift key
22115
+ if (inSelection) {
22116
+ keyboard.focusSelection();
22117
+ } else {
22118
+ currentTarget.blur();
22119
+ keyboard.blur();
22120
+ }
22121
+ break;
22122
+ }
22005
22123
  case KEYS.SHIFT:
22006
22124
  // This is to ensure we include the first value when starting a range selection.
22007
22125
  setStartedRange(true);
22008
22126
  break;
22009
22127
  case KEYS.SPACE:
22010
- select([+event.currentTarget.getAttribute('data-n')]);
22128
+ select([getElementIndex(currentTarget)], false, event);
22011
22129
  break;
22012
22130
  case KEYS.ARROW_DOWN:
22013
22131
  case KEYS.ARROW_RIGHT:
22014
- elementToFocus = getElement(event.currentTarget, true);
22132
+ elementToFocus = getElement(currentTarget, true);
22015
22133
  if (shiftKey && elementToFocus) {
22016
22134
  if (startedRange) {
22017
- select([+event.currentTarget.getAttribute('data-n')], true);
22135
+ select([getElementIndex(currentTarget)], true);
22018
22136
  setStartedRange(false);
22019
22137
  }
22020
- select([+elementToFocus.getAttribute('data-n')], true);
22138
+ select([getElementIndex(elementToFocus)], true);
22021
22139
  }
22022
22140
  break;
22023
22141
  case KEYS.ARROW_UP:
22024
22142
  case KEYS.ARROW_LEFT:
22025
- elementToFocus = getElement(event.currentTarget, false);
22143
+ elementToFocus = getElement(currentTarget, false);
22026
22144
  if (shiftKey && elementToFocus) {
22027
22145
  if (startedRange) {
22028
- select([+event.currentTarget.getAttribute('data-n')], true);
22146
+ select([getElementIndex(currentTarget)], true);
22029
22147
  setStartedRange(false);
22030
22148
  }
22031
- select([+elementToFocus.getAttribute('data-n')], true);
22149
+ select([getElementIndex(elementToFocus)], true);
22032
22150
  }
22033
22151
  break;
22034
22152
  case KEYS.ENTER:
22035
22153
  confirm();
22036
22154
  break;
22037
22155
  case KEYS.ESCAPE:
22038
- cancel();
22039
- return;
22040
- // let it propagate to top-level
22156
+ if (isModal()) {
22157
+ cancel();
22158
+ } else {
22159
+ return; // propagate to other Esc handler
22160
+ }
22161
+
22162
+ break;
22041
22163
  case KEYS.HOME:
22042
22164
  focusListItems.setFirst(true);
22043
22165
  if (ctrlKey) {
@@ -22081,39 +22203,41 @@
22081
22203
  }
22082
22204
  function getListboxInlineKeyboardNavigation(_ref2) {
22083
22205
  let {
22084
- setKeyboardActive,
22206
+ keyboard,
22085
22207
  hovering,
22086
22208
  setHovering,
22087
22209
  updateKeyScroll,
22088
22210
  containerRef,
22089
22211
  currentScrollIndex,
22090
- app,
22091
- appSelections,
22212
+ isModal,
22092
22213
  constraints
22093
22214
  } = _ref2;
22094
- const focusInsideListbox = element => {
22095
- const fieldElement = element.querySelector('.search input, .value.selector, .value, .ActionsToolbar-item button');
22096
- setKeyboardActive(true);
22097
- if (fieldElement) {
22098
- fieldElement.focus();
22099
- }
22100
- };
22101
- const changeFocus = event => {
22102
- var _event$target;
22103
- if ((_event$target = event.target) !== null && _event$target !== void 0 && _event$target.classList.contains('listbox-container')) {
22104
- // Focus currently on a listbox
22105
- // Esc on a list box should move the focus to its parent, i.e. a filter pane if any
22106
- setKeyboardActive(false);
22215
+ const blur = event => {
22216
+ const {
22217
+ currentTarget,
22218
+ target
22219
+ } = event;
22220
+ const isFocusedOnListbox = target.classList.contains('listbox-container');
22221
+ const container = currentTarget.closest('.listbox-container');
22222
+ const vizCell = getVizCell(container);
22223
+ const isSingleListbox = (vizCell === null || vizCell === void 0 ? void 0 : vizCell.querySelectorAll('.listbox-container').length) === 1;
22224
+ if (isFocusedOnListbox || isSingleListbox) {
22225
+ // Move the focus from listbox container to the viz container.
22226
+ keyboard.blur(true);
22107
22227
  } else {
22108
- var _event$target2, _event$target3, _event$currentTarget, _event$currentTarget2;
22109
- // Focus currently on a row
22110
- // Esc on a row should move the focus to its parent, i.e. a listbox
22111
- // First unfocus the row
22112
- (_event$target2 = event.target) === null || _event$target2 === void 0 ? void 0 : _event$target2.setAttribute('tabIndex', '-1');
22113
- (_event$target3 = event.target) === null || _event$target3 === void 0 ? void 0 : _event$target3.blur();
22114
- // Then focus the listbox
22115
- (_event$currentTarget = event.currentTarget) === null || _event$currentTarget === void 0 ? void 0 : _event$currentTarget.setAttribute('tabIndex', '0');
22116
- (_event$currentTarget2 = event.currentTarget) === null || _event$currentTarget2 === void 0 ? void 0 : _event$currentTarget2.focus();
22228
+ // More than one listbox: Move focus from row to listbox container.
22229
+
22230
+ // 1. Remove last-focused class from row siblings.
22231
+ removeLastFocused(containerRef.current);
22232
+
22233
+ // 2. Add last-focused class so we can re-focus it later.
22234
+ currentTarget.classList.add('last-focused');
22235
+
22236
+ // 3. Blur row and focus the listbox container.
22237
+ keyboard.blur();
22238
+ const c = currentTarget.closest('.listbox-container');
22239
+ c.setAttribute('tabIndex', 0);
22240
+ c === null || c === void 0 ? void 0 : c.focus();
22117
22241
  }
22118
22242
  };
22119
22243
  const updateKeyScrollOnHover = newState => {
@@ -22127,65 +22251,84 @@
22127
22251
  ctrlKey = false,
22128
22252
  shiftKey = false
22129
22253
  } = event.nativeEvent;
22254
+ const prevent = () => {
22255
+ event.stopPropagation();
22256
+ event.preventDefault();
22257
+ };
22130
22258
  switch (keyCode) {
22131
- // case KEYS.TAB: TODO: Focus confirm button using keyboard.focusSelection when we can access the useKeyboard hook.
22132
- case KEYS.ENTER:
22133
- case KEYS.SPACE:
22134
- if (!event.target.classList.contains('listbox-container')) {
22135
- return; // don't mess with keydown handlers within the listbox
22136
- }
22137
-
22138
- focusInsideListbox(event.currentTarget);
22139
- break;
22140
- case KEYS.ESCAPE:
22141
- changeFocus(event);
22142
- break;
22143
- case KEYS.ARROW_UP:
22144
- updateKeyScrollOnHover({
22145
- up: 1
22146
- });
22147
- break;
22148
- case KEYS.ARROW_DOWN:
22149
- updateKeyScrollOnHover({
22150
- down: 1
22151
- });
22152
- break;
22153
- case KEYS.ARROW_LEFT:
22154
- case KEYS.ARROW_RIGHT:
22155
- return;
22156
- // let it propagate to top-level
22157
22259
  case KEYS.PAGE_UP:
22158
22260
  updateKeyScrollOnHover({
22159
22261
  up: currentScrollIndex.stop - currentScrollIndex.start
22160
22262
  });
22263
+ prevent();
22161
22264
  break;
22162
22265
  case KEYS.PAGE_DOWN:
22163
22266
  updateKeyScrollOnHover({
22164
22267
  down: currentScrollIndex.stop - currentScrollIndex.start
22165
22268
  });
22269
+ prevent();
22166
22270
  break;
22167
22271
  case KEYS.HOME:
22168
22272
  updateKeyScrollOnHover({
22169
22273
  scrollPosition: ctrlKey && shiftKey ? 'overflowStart' : 'start'
22170
22274
  });
22275
+ prevent();
22171
22276
  break;
22172
22277
  case KEYS.END:
22173
22278
  updateKeyScrollOnHover({
22174
22279
  scrollPosition: ctrlKey && shiftKey ? 'overflowEnd' : 'end'
22175
22280
  });
22281
+ prevent();
22282
+ break;
22283
+ case KEYS.ARROW_UP:
22284
+ updateKeyScrollOnHover({
22285
+ up: 1
22286
+ });
22287
+ prevent();
22288
+ break;
22289
+ case KEYS.ARROW_DOWN:
22290
+ updateKeyScrollOnHover({
22291
+ down: 1
22292
+ });
22293
+ prevent();
22176
22294
  break;
22177
- default:
22178
- return;
22179
22295
  }
22296
+ if (!keyboard.enabled) {
22297
+ // Other keys should not be handled unless keyboard is enabled.
22298
+ return undefined;
22299
+ }
22300
+ const container = event.currentTarget.closest('.listbox-container');
22301
+ switch (keyCode) {
22302
+ case KEYS.TAB:
22303
+ if (shiftKey) {
22304
+ focusRow(container) || focusSearch(container);
22305
+ } else {
22306
+ focusSearch(container) || focusRow(container);
22307
+ }
22308
+ prevent();
22309
+ break;
22310
+ case KEYS.ENTER:
22311
+ case KEYS.SPACE:
22312
+ if (!event.target.classList.contains('listbox-container')) {
22313
+ return undefined; // don't mess with keydown handlers within the listbox (e.g. row seletion)
22314
+ }
22180
22315
 
22181
- // Note: We should not stop propagation here as it will block the containing app
22182
- // from handling keydown events.
22183
- event.preventDefault();
22316
+ keyboard.focus();
22317
+ prevent();
22318
+ break;
22319
+ case KEYS.ESCAPE:
22320
+ blur(event);
22321
+ prevent();
22322
+ break;
22323
+ case KEYS.ARROW_LEFT:
22324
+ case KEYS.ARROW_RIGHT:
22325
+ return undefined;
22326
+ }
22327
+ return undefined;
22184
22328
  };
22185
22329
  const focusOnHoverDisabled = () => {
22186
- var _app$isInModalSelecti, _app$isInModalSelecti2;
22187
22330
  const selectNotAllowed = (constraints === null || constraints === void 0 ? void 0 : constraints.select) || (constraints === null || constraints === void 0 ? void 0 : constraints.active);
22188
- const appInModal = (_app$isInModalSelecti = (_app$isInModalSelecti2 = app.isInModalSelection) === null || _app$isInModalSelecti2 === void 0 ? void 0 : _app$isInModalSelecti2.call(app)) !== null && _app$isInModalSelecti !== void 0 ? _app$isInModalSelecti : appSelections.isInModal();
22331
+ const appInModal = isModal();
22189
22332
  return selectNotAllowed || appInModal;
22190
22333
  };
22191
22334
  const handleOnMouseEnter = () => {
@@ -22390,15 +22533,10 @@
22390
22533
  ["& .".concat(rowColClasses.labelDense)]: {
22391
22534
  fontSize: 12
22392
22535
  },
22393
- // Highlight is added to labelText spans, which are created as siblings to original labelText,
22536
+ // Highlight is added to labelText spans, which are created as children to original labelText,
22394
22537
  // when a search string is matched.
22395
22538
  ["& .".concat(rowColClasses.highlighted)]: {
22396
- overflow: 'visible',
22397
- width: '100%',
22398
- '& > span': {
22399
- width: '100%',
22400
- backgroundColor: '#FFC72A'
22401
- }
22539
+ backgroundColor: '#FFC72A'
22402
22540
  },
22403
22541
  // Checkbox and label container.
22404
22542
  ["& .".concat(rowColClasses.checkboxLabel)]: {
@@ -22418,12 +22556,6 @@
22418
22556
  paddingRight: '2px'
22419
22557
  })
22420
22558
  },
22421
- ["& .".concat(rowColClasses.checkboxLabel, " .").concat(rowColClasses.labelText)]: {
22422
- width: 'auto'
22423
- },
22424
- ["& .".concat(rowColClasses.checkboxLabel, " .").concat(rowColClasses.labelText, ".").concat(rowColClasses.highlighted)]: {
22425
- width: 'auto'
22426
- },
22427
22559
  // The icons container holding tick and lock, shown inside fields.
22428
22560
  ["& .".concat(rowColClasses.icon)]: {
22429
22561
  display: 'flex',
@@ -22658,7 +22790,6 @@
22658
22790
  let {
22659
22791
  label,
22660
22792
  color,
22661
- highlighted = false,
22662
22793
  dense,
22663
22794
  showGray = true,
22664
22795
  checkboxes,
@@ -22668,14 +22799,14 @@
22668
22799
  return /*#__PURE__*/React.createElement(Typography$1, {
22669
22800
  component: "span",
22670
22801
  variant: "body2",
22671
- className: joinClassNames([rowColClasses.labelText, highlighted && rowColClasses.highlighted, dense && rowColClasses.labelDense, showGray && excludedOrAlternative({
22802
+ className: joinClassNames([rowColClasses.labelText, dense && rowColClasses.labelDense, showGray && excludedOrAlternative({
22672
22803
  cell,
22673
22804
  checkboxes
22674
22805
  }) && rowColClasses.excludedTextWithCheckbox]),
22675
22806
  color: color,
22676
- align: valueTextAlign
22807
+ align: valueTextAlign,
22808
+ dir: "auto"
22677
22809
  }, /*#__PURE__*/React.createElement("span", {
22678
- dir: "auto",
22679
22810
  style: {
22680
22811
  whiteSpace: 'pre'
22681
22812
  }
@@ -22686,7 +22817,6 @@
22686
22817
  let {
22687
22818
  label,
22688
22819
  color,
22689
- highlighted,
22690
22820
  dense,
22691
22821
  showGray,
22692
22822
  checkboxes,
@@ -22697,7 +22827,6 @@
22697
22827
  return /*#__PURE__*/React.createElement(ValueField, {
22698
22828
  label: label,
22699
22829
  color: color,
22700
- highlighted: highlighted,
22701
22830
  dense: dense,
22702
22831
  showGray: showGray,
22703
22832
  checkboxes: checkboxes,
@@ -22720,7 +22849,6 @@
22720
22849
  isGridCol,
22721
22850
  showGray,
22722
22851
  isSingleSelect,
22723
- highlighted,
22724
22852
  checkboxes,
22725
22853
  valueTextAlign
22726
22854
  } = _ref;
@@ -22748,7 +22876,6 @@
22748
22876
  label: /*#__PURE__*/React.createElement(LabelTag, {
22749
22877
  label: label,
22750
22878
  color: color,
22751
- highlighted: highlighted,
22752
22879
  dense: dense,
22753
22880
  showGray: showGray,
22754
22881
  checkboxes: checkboxes,
@@ -22764,23 +22891,21 @@
22764
22891
  labels,
22765
22892
  dense,
22766
22893
  showGray,
22767
- checkboxes,
22768
- textDirection
22894
+ checkboxes
22769
22895
  } = _ref;
22770
- return /*#__PURE__*/React.createElement("div", {
22771
- dir: textDirection
22772
- }, labels.map((_ref2, index) => {
22896
+ const text = labels.map((_ref2, index) => {
22773
22897
  let [label, highlighted] = _ref2;
22774
- const key = "".concat(index);
22775
- return /*#__PURE__*/React.createElement(ValueField, {
22776
- label: label,
22777
- key: key,
22778
- highlighted: highlighted,
22779
- dense: dense,
22780
- showGray: showGray,
22781
- checkboxes: checkboxes
22782
- });
22783
- }));
22898
+ return /*#__PURE__*/React.createElement("span", {
22899
+ id: index,
22900
+ className: highlighted ? rowColClasses.highlighted : ''
22901
+ }, label);
22902
+ });
22903
+ return /*#__PURE__*/React.createElement(ValueField, {
22904
+ label: text,
22905
+ dense: dense,
22906
+ showGray: showGray,
22907
+ checkboxes: checkboxes
22908
+ });
22784
22909
  }
22785
22910
  function FieldWithRanges(_ref3) {
22786
22911
  let {
@@ -22795,15 +22920,13 @@
22795
22920
  cell,
22796
22921
  isGridCol,
22797
22922
  isSingleSelect,
22798
- valueTextAlign,
22799
- textDirection
22923
+ valueTextAlign
22800
22924
  } = _ref3;
22801
22925
  const LWR = /*#__PURE__*/React.createElement(LabelsWithRanges, {
22802
22926
  labels: labels,
22803
22927
  dense: dense,
22804
22928
  showGray: showGray,
22805
- checkboxes: checkboxes,
22806
- textDirection: textDirection
22929
+ checkboxes: checkboxes
22807
22930
  });
22808
22931
  return checkboxes ? /*#__PURE__*/React.createElement(CheckboxField, {
22809
22932
  onChange: onChange,
@@ -22833,7 +22956,6 @@
22833
22956
  isGridCol,
22834
22957
  showGray,
22835
22958
  isSingleSelect,
22836
- highlighted,
22837
22959
  checkboxes,
22838
22960
  valueTextAlign
22839
22961
  } = _ref;
@@ -22848,13 +22970,11 @@
22848
22970
  isGridCol: isGridCol,
22849
22971
  showGray: showGray,
22850
22972
  isSingleSelect: isSingleSelect,
22851
- highlighted: highlighted,
22852
22973
  checkboxes: checkboxes,
22853
22974
  valueTextAlign: valueTextAlign
22854
22975
  }) : /*#__PURE__*/React.createElement(ValueField, {
22855
22976
  label: label,
22856
22977
  color: color,
22857
- highlighted: false,
22858
22978
  dense: dense,
22859
22979
  showGray: true,
22860
22980
  checkboxes: checkboxes,
@@ -22896,13 +23016,15 @@
22896
23016
  dense,
22897
23017
  showGray
22898
23018
  } = _ref;
23019
+ const frequencyText = getFrequencyText(cell === null || cell === void 0 ? void 0 : cell.qFrequency);
22899
23020
  return /*#__PURE__*/React.createElement(Grid$1, {
22900
23021
  item: true,
22901
23022
  style: {
22902
23023
  display: 'flex',
22903
23024
  alignItems: 'center'
22904
23025
  },
22905
- className: rowColClasses.frequencyCount
23026
+ className: rowColClasses.frequencyCount,
23027
+ "aria-label": frequencyText
22906
23028
  }, /*#__PURE__*/React.createElement(Typography$1, {
22907
23029
  noWrap: true,
22908
23030
  color: "inherit",
@@ -22911,7 +23033,7 @@
22911
23033
  cell,
22912
23034
  checkboxes
22913
23035
  }) && rowColClasses.excludedTextWithCheckbox])
22914
- }, getFrequencyText(cell === null || cell === void 0 ? void 0 : cell.qFrequency)));
23036
+ }, frequencyText));
22915
23037
  }
22916
23038
 
22917
23039
  function getGridItemSizes(_ref) {
@@ -22948,7 +23070,7 @@
22948
23070
  }
22949
23071
 
22950
23072
  const ItemGrid = styled$1(Grid$1, {
22951
- shouldForwardProp: prop => !['dataLayout', 'layoutOrder', 'itemPadding', 'checkboxes'].includes(prop)
23073
+ shouldForwardProp: prop => !['dataLayout', 'layoutOrder', 'itemPadding', 'cellPaddingRight'].includes(prop)
22952
23074
  })(_ref => {
22953
23075
  let {
22954
23076
  dataLayout,
@@ -22983,54 +23105,78 @@
22983
23105
  return c;
22984
23106
  }
22985
23107
 
22986
- // Source: https://en.wikipedia.org/wiki/Bi-directional_text and http://www.unicode.org/Public/6.0.0/ucd/UnicodeData.txt
22987
- // 3 types of strong direction characters: L (strong left-to-right), R(strong right-to-left, Hebrew) and AL(strong right-to-left, Arabic language)
22988
- const rangesOfLChars = '[\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u02BB-\u02C1\u02D0-\u02D1\u02E0-\u02E4\u02EE\u0370-\u0373\u0376-\u037D\u0386\u0388-\u03F5\u03F7-\u0482\u048A-\u0589\u0903-\u0939\u093B\u093D-\u0940\u0949-\u094C\u094E-\u0950\u0958-\u0961\u0964-\u097F\u0982-\u09B9\u09BD-\u09C0\u09C7-\u09CC\u09CE-\u09E1\u09E6-\u09F1\u09F4-\u09FA\u0A03-\u0A39\u0A3E-\u0A40\u0A59-\u0A6F\u0A72-\u0A74\u0A83-\u0AB9\u0ABD-\u0AC0\u0AC9-\u0ACC\u0AD0-\u0AE1\u0AE6-\u0AEF\u0B02-\u0B39\u0B3D-\u0B3E\u0B40\u0B47-\u0B4C\u0B57-\u0B61\u0B66-\u0B77\u0B83-\u0BBF\u0BC1-\u0BCC\u0BD0-\u0BF2\u0C01-\u0C3D\u0C41-\u0C44\u0C58-\u0C61\u0C66-\u0C6F\u0C7F-\u0CB9\u0CBD-\u0CCB\u0CD5-\u0CE1\u0CE6-\u0D40\u0D46-\u0D4C\u0D4E-\u0D61\u0D66-\u0DC6\u0DCF-\u0DD1\u0DD8-\u0E30\u0E32-\u0E33\u0E40-\u0E46\u0E4F-\u0EB0\u0EB2-\u0EB3\u0EBD-\u0EC6\u0ED0-\u0F17\u0F1A-\u0F34\u0F36\u0F38\u0F3E-\u0F6C\u0F7F\u0F85\u0F88-\u0F8C\u0FBE-\u0FC5\u0FC7-\u102C\u1031\u1038\u103B-\u103C\u103F-\u1057\u105A-\u105D\u1061-\u1070\u1075-\u1081\u1083-\u1084\u1087-\u108C\u108E-\u109C\u109E-\u135A\u1360-\u138F\u13A0-\u13F4\u1401-\u167F\u1681-\u169A\u16A0-\u1711\u1720-\u1731\u1735-\u1751\u1760-\u1770\u1780-\u17B6\u17BE-\u17C5\u17C7-\u17C8\u17D4-\u17DA\u17DC\u17E0-\u17E9\u1810-\u18A8\u18AA-\u191C\u1923-\u1926\u1929-\u1931\u1933-\u1938\u1946-\u19DA\u1A00-\u1A16\u1A19-\u1A55\u1A57\u1A61\u1A63-\u1A64\u1A6D-\u1A72\u1A80-\u1AAD\u1B04-\u1B33\u1B35\u1B3B\u1B3D-\u1B41\u1B43-\u1B6A\u1B74-\u1B7C\u1B82-\u1BA1\u1BA6-\u1BA7\u1BAA-\u1BE5\u1BE7\u1BEA-\u1BEC\u1BEE\u1BF2-\u1C2B\u1C34-\u1C35\u1C3B-\u1C7F\u1CD3\u1CE1\u1CE9-\u1CEC\u1CEE-\u1DBF\u1E00-\u1FBC\u1FBE\u1FC2-\u1FCC\u1FD0-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FFC\u200E\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E-\u214F\u2160-\u2188\u2336-\u237A\u2395\u249C-\u24E9\u26AC\u2800-\u28FF\u2C00-\u2CE4\u2CEB-\u2CEE\u2D00-\u2D70\u2D80-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u31BA\u31F0-\u321C\u3220-\u324F\u3260-\u327B\u327F-\u32B0\u32C0-\u32CB\u32D0-\u3376\u337B-\u33DD\u33E0-\u33FE\u3400-\u4DB5\u4E00-\uA48C\uA4D0-\uA60C\uA610-\uA66E\uA680-\uA6EF\uA6F2-\uA6F7\uA722-\uA787\uA789-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA824\uA827\uA830-\uA837\uA840-\uA873\uA880-\uA8C3\uA8CE-\uA8D9\uA8F2-\uA925\uA92E-\uA946\uA952-\uA97C\uA983-\uA9B2\uA9B4-\uA9B5\uA9BA-\uA9BB\uA9BD-\uAA28\uAA2F-\uAA30\uAA33-\uAA34\uAA40-\uAA42\uAA44-\uAA4B\uAA4D-\uAAAF\uAAB1\uAAB5-\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2-\uABE4\uABE6-\uABE7\uABE9-\uABEC\uABF0-\uFB17\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]';
22989
- const rangesOfRChars = '[\u05BE\u05C0\u05C3\u05C6\u05D0-\u05F4\u07C0-\u07EA\u07F4-\u07F5\u07FA-\u0815\u081A\u0824\u0828\u0830-\u0858\u085E\u200F\uFB1D\uFB1F-\uFB28\uFB2A-\uFB4F]';
22990
- const rangesOfALChars = '[\u0608\u060B\u060D\u061B-\u064A\u066D-\u066F\u0671-\u06D5\u06E5-\u06E6\u06EE-\u06EF\u06FA-\u070D\u0710\u0712-\u072F\u074D-\u07A5\u07B1\uFB50-\uFD3D\uFD50-\uFDFC\uFE70-\uFEFC]';
22991
- const rangesOfNChars = '[\u0009-\u000D\u001C-\u0022\u0026-\u002A\u003B-\u0040\u005B-\u0060\u007B-\u007E\u0085\u00A1\u00A6-\u00A9\u00AB-\u00AC\u00AE-\u00AF\u00B4\u00B6-\u00B8\u00BB-\u00BF\u00D7\u00F7\u02B9-\u02BA\u02C2-\u02CF\u02D2-\u02DF\u02E5-\u02ED\u02EF-\u02FF\u0374-\u0375\u037E-\u0385\u0387\u03F6\u058A\u0606-\u0607\u060E-\u060F\u06DE\u06E9\u07F6-\u07F9\u0BF3-\u0BF8\u0BFA\u0C78-\u0C7E\u0F3A-\u0F3D\u1390-\u1399\u1400\u1680\u169B-\u169C\u17F0-\u180A\u180E\u1940-\u1945\u19DE-\u19FF\u1FBD\u1FBF-\u1FC1\u1FCD-\u1FCF\u1FDD-\u1FDF\u1FED-\u1FEF\u1FFD-\u200A\u2010-\u2029\u2035-\u2043\u2045-\u205F\u207C-\u207E\u208C-\u208E\u2100-\u2101\u2103-\u2106\u2108-\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u213A-\u213B\u2140-\u2144\u214A-\u214D\u2150-\u215F\u2189-\u2211\u2214-\u2335\u237B-\u2394\u2396-\u2487\u24EA-\u26AB\u26AD-\u27FF\u2900-\u2B59\u2CE5-\u2CEA\u2CF9-\u2CFF\u2E00-\u3004\u3008-\u3020\u3030\u3036-\u3037\u303D-\u303F\u309B-\u309C\u30A0\u30FB\u31C0-\u31E3\u321D-\u321E\u3250-\u325F\u327C-\u327E\u32B1-\u32BF\u32CC-\u32CF\u3377-\u337A\u33DE-\u33DF\u33FF\u4DC0-\u4DFF\uA490-\uA4C6\uA60D-\uA60F\uA673\uA67E-\uA67F\uA700-\uA721\uA788\uA828-\uA82B\uA874-\uA877\uFD3E-\uFD3F\uFDFD\uFE10-\uFE19\uFE30-\uFE4F\uFE51\uFE54\uFE56-\uFE5E\uFE60-\uFE61\uFE64-\uFE68\uFE6B\uFF01-\uFF02\uFF06-\uFF0A\uFF1B-\uFF20\uFF3B-\uFF40\uFF5B-\uFF65\uFFE2-\uFFE4\uFFE8-\uFFFD]';
22992
- // eslint-disable-next-line no-misleading-character-class
22993
- const rangesOfLRgExp = new RegExp(rangesOfLChars);
22994
- const rangesOfRRgExp = new RegExp(rangesOfRChars);
22995
- const rangesOfALRgExp = new RegExp(rangesOfALChars);
22996
- const rangesOfNRgExp = new RegExp(rangesOfNChars);
22997
- const
22998
- // left-to-right marker
22999
- lrm = String.fromCharCode(8206); // right-to-left marker
23000
-
23001
- const rlm = String.fromCharCode(8207);
23002
- function isLtrChar(c) {
23003
- return rangesOfLRgExp.test(c);
23004
- }
23005
- function isRtlChar(c) {
23006
- return rangesOfRRgExp.test(c) || rangesOfALRgExp.test(c);
23007
- }
23008
- function isNeutralChar(c) {
23009
- return rangesOfNRgExp.test(c);
23010
- }
23011
- function detectTextDirection(s) {
23012
- const n = s ? s.length : 0;
23013
- let i;
23014
- let c;
23015
- for (i = 0; i < n; i++) {
23016
- c = s[i];
23017
- if (isLtrChar(c)) {
23018
- return 'ltr';
23019
- }
23020
- if (isRtlChar(c)) {
23021
- return 'rtl';
23022
- }
23108
+ /* eslint-disable import/prefer-default-export */
23109
+ const LOC_STATES = {
23110
+ S: 'Object.Listbox.Selected',
23111
+ A: 'Object.Listbox.Alternative',
23112
+ O: 'Object.Listbox.Optional',
23113
+ XS: 'Object.Listbox.SelectedExcluded',
23114
+ L: 'Object.Listbox.Locked',
23115
+ X: 'Object.Listbox.Excluded',
23116
+ XL: 'Object.Listbox.ExcludedLock'
23117
+ };
23118
+ function getValueLabel(_ref) {
23119
+ let {
23120
+ translator,
23121
+ label,
23122
+ qState,
23123
+ isSelected,
23124
+ currentIndex,
23125
+ maxIndex,
23126
+ showSearch
23127
+ } = _ref;
23128
+ const stateTranslation = LOC_STATES[qState];
23129
+ const state = translator.get(stateTranslation);
23130
+ const srStringArr = [];
23131
+ if (isSelected) {
23132
+ const navTranslation = showSearch ? 'Listbox.ScreenReader.SearchThenSelectionsMenu.WithAccSelMenu' : 'Listbox.ScreenReader.SelectionMenu.WithAccSelMenu';
23133
+ const nav = translator.get(navTranslation);
23134
+ srStringArr.push(nav);
23023
23135
  }
23024
- return 'ltr';
23136
+ const valueString = "".concat(label, " ").concat(state);
23137
+ const indexString = translator.get('CurrentSelections.Of', [currentIndex + 1, maxIndex + 1]); // E.g. 3 of 20
23138
+ srStringArr.unshift(valueString, indexString);
23139
+ const srString = srStringArr.join('. ').trim();
23140
+ return srString;
23141
+ }
23142
+
23143
+ /**
23144
+ * Announces the selection state.
23145
+ *
23146
+ * @ignore
23147
+ * @param {Layout} object
23148
+ * @returns {Element} An (invisible) component.
23149
+ */
23150
+ function ScreenReaderForSelections(_ref2) {
23151
+ var _layout$qListObject;
23152
+ let {
23153
+ layout
23154
+ } = _ref2;
23155
+ const {
23156
+ translator
23157
+ } = reactExports.useContext(InstanceContext);
23158
+ const {
23159
+ qStateCounts: s = {}
23160
+ } = (layout === null || layout === void 0 ? void 0 : (_layout$qListObject = layout.qListObject) === null || _layout$qListObject === void 0 ? void 0 : _layout$qListObject.qDimensionInfo) || {};
23161
+ const count = s.qSelected + s.qSelectedExcluded + s.qLocked + s.qLockedExcluded;
23162
+ let t;
23163
+ switch (count) {
23164
+ case 0:
23165
+ t = 'ScreenReader.ZeroSelected';
23166
+ break;
23167
+ case 1:
23168
+ t = 'ScreenReader.OneSelected';
23169
+ break;
23170
+ default:
23171
+ t = 'ScreenReader.ManySelected';
23172
+ break;
23173
+ }
23174
+ const text = translator.get(t, [count]);
23175
+ return /*#__PURE__*/React.createElement("div", {
23176
+ className: "screenReaderOnly",
23177
+ "aria-live": "assertive"
23178
+ }, text);
23025
23179
  }
23026
- var rtlUtil = {
23027
- detectTextDirection,
23028
- isLtrChar,
23029
- isRtlChar,
23030
- isNeutralChar,
23031
- lrm,
23032
- rlm
23033
- };
23034
23180
 
23035
23181
  function RowColumn(_ref) {
23036
23182
  var _cell$qText, _cell$qHighlightRange, _cell$qHighlightRange2;
@@ -23068,7 +23214,10 @@
23068
23214
  focusListItems,
23069
23215
  listCount,
23070
23216
  itemPadding,
23071
- frequencyWidth
23217
+ frequencyWidth,
23218
+ translator,
23219
+ showSearch,
23220
+ isModal
23072
23221
  } = data;
23073
23222
  const {
23074
23223
  dense = false,
@@ -23118,8 +23267,10 @@
23118
23267
  }
23119
23268
  }, [rowRef.current]);
23120
23269
  const handleKeyDownCallback = reactExports.useCallback(getFieldKeyboardNavigation(_objectSpread2(_objectSpread2({}, actions), {}, {
23121
- focusListItems
23122
- })), [actions]);
23270
+ focusListItems,
23271
+ keyboard,
23272
+ isModal
23273
+ })), [actions, keyboard === null || keyboard === void 0 ? void 0 : keyboard.innerTabStops]);
23123
23274
  const cell = reactExports.useMemo(() => getCellFromPages({
23124
23275
  pages,
23125
23276
  cellIndex
@@ -23157,7 +23308,6 @@
23157
23308
  }
23158
23309
  const isGridCol = dataLayout === 'grid' && layoutOrder === 'column';
23159
23310
  const label = (_cell$qText = cell === null || cell === void 0 ? void 0 : cell.qText) !== null && _cell$qText !== void 0 ? _cell$qText : '';
23160
- const textDirection = rtlUtil.detectTextDirection(label);
23161
23311
  // Search highlights. Split up labelText span into several and add the highlighted class to matching sub-strings.
23162
23312
 
23163
23313
  let labels;
@@ -23185,6 +23335,14 @@
23185
23335
  const showTick = !checkboxes && isSelected && !isLocked;
23186
23336
  const showIcon = !checkboxes && sizePermitsTickOrLock;
23187
23337
  const cellPaddingRight = checkboxes || !sizePermitsTickOrLock;
23338
+ const ariaLabel = getValueLabel({
23339
+ translator,
23340
+ label,
23341
+ qState: cell.qState,
23342
+ currentIndex: count.currentIndex,
23343
+ maxIndex: count.max,
23344
+ showSearch
23345
+ });
23188
23346
  return /*#__PURE__*/React.createElement(RowColRoot$1, {
23189
23347
  className: rowColClasses.barContainer,
23190
23348
  flexBasisProp: flexBasisVal,
@@ -23195,6 +23353,11 @@
23195
23353
  frequencyWidth: frequencyWidth,
23196
23354
  "data-testid": "listbox.item"
23197
23355
  }, /*#__PURE__*/React.createElement(ItemGrid, {
23356
+ role: "row",
23357
+ "aria-label": ariaLabel,
23358
+ "aria-selected": isSelected,
23359
+ "aria-setsize": count.max,
23360
+ "aria-rowindex": count.currentIndex,
23198
23361
  ref: rowRef,
23199
23362
  container: true,
23200
23363
  dataLayout: dataLayout,
@@ -23212,8 +23375,7 @@
23212
23375
  onMouseEnter: onMouseEnter,
23213
23376
  onKeyDown: handleKeyDownCallback,
23214
23377
  onContextMenu: preventContextMenu,
23215
- role: column ? 'column' : 'row',
23216
- tabIndex: isFirstElement && (!keyboard.enabled || keyboard.active) ? 0 : -1,
23378
+ tabIndex: isFirstElement && keyboard.innerTabStops ? 0 : -1,
23217
23379
  "data-n": cell === null || cell === void 0 ? void 0 : cell.qElemNumber
23218
23380
  }, (cell === null || cell === void 0 ? void 0 : cell.qFrequency) && /*#__PURE__*/React.createElement(Histogram, {
23219
23381
  qFrequency: cell === null || cell === void 0 ? void 0 : cell.qFrequency,
@@ -23239,8 +23401,7 @@
23239
23401
  cell: cell,
23240
23402
  isGridCol: isGridCol,
23241
23403
  isSingleSelect: isSingleSelect,
23242
- valueTextAlign: valueTextAlign,
23243
- textDirection: textDirection
23404
+ valueTextAlign: valueTextAlign
23244
23405
  }) : /*#__PURE__*/React.createElement(Field$1, {
23245
23406
  onChange: onChange,
23246
23407
  label: label,
@@ -24830,7 +24991,10 @@
24830
24991
  setCurrentScrollIndex,
24831
24992
  constraints,
24832
24993
  frequencyMax,
24833
- freqIsAllowed
24994
+ freqIsAllowed,
24995
+ translator,
24996
+ showSearch,
24997
+ isModal
24834
24998
  } = _ref;
24835
24999
  const {
24836
25000
  layoutOptions = {}
@@ -24884,7 +25048,10 @@
24884
25048
  showTick,
24885
25049
  dataOffset: local.current.dataOffset,
24886
25050
  focusListItems,
24887
- direction
25051
+ direction,
25052
+ translator,
25053
+ showSearch,
25054
+ isModal
24888
25055
  });
24889
25056
  const List = _ref2 => {
24890
25057
  let {
@@ -25326,17 +25493,14 @@
25326
25493
  };
25327
25494
  }
25328
25495
 
25329
- function ListBoxDisclaimer(_ref) {
25496
+ const StyledText = styled$1(Typography$1, {
25497
+ shouldForwardProp: p => !['width', 'dense'].includes(p)
25498
+ })(_ref => {
25330
25499
  let {
25331
25500
  width,
25332
- text,
25333
- dense,
25334
- tooltip
25501
+ dense
25335
25502
  } = _ref;
25336
- const {
25337
- translator
25338
- } = reactExports.useContext(InstanceContext);
25339
- const StyledText = styled$1(Typography$1)(() => _objectSpread2({
25503
+ return _objectSpread2({
25340
25504
  minWidth: "".concat(width, "px"),
25341
25505
  textAlign: 'center',
25342
25506
  fontSize: "".concat(dense ? '12px' : '14px')
@@ -25345,10 +25509,23 @@
25345
25509
  overflow: 'hidden',
25346
25510
  whiteSpace: 'nowrap',
25347
25511
  width
25348
- }));
25512
+ });
25513
+ });
25514
+ function ListBoxDisclaimer(_ref2) {
25515
+ let {
25516
+ width,
25517
+ text,
25518
+ dense,
25519
+ tooltip
25520
+ } = _ref2;
25521
+ const {
25522
+ translator
25523
+ } = reactExports.useContext(InstanceContext);
25349
25524
  return /*#__PURE__*/React.createElement(Tooltip$1, {
25350
25525
  title: tooltip ? translator.get(text) : ''
25351
25526
  }, /*#__PURE__*/React.createElement(StyledText, {
25527
+ width: width,
25528
+ dense: dense,
25352
25529
  component: "div",
25353
25530
  variant: "body1",
25354
25531
  py: "12px"
@@ -25570,6 +25747,14 @@
25570
25747
 
25571
25748
  const _excluded$4 = ["isLoadingData"];
25572
25749
  const DEFAULT_MIN_BATCH_SIZE = 100;
25750
+ const StyledWrapper = styled$1('div')(() => ({
25751
+ ["& .screenReaderOnly"]: {
25752
+ position: 'absolute',
25753
+ height: 0,
25754
+ width: 0,
25755
+ overflow: 'hidden'
25756
+ }
25757
+ }));
25573
25758
  function ListBox(_ref) {
25574
25759
  var _layout$qListObject$q, _loaderRef$current, _loaderRef$current$_l, _loaderRef$current$_l2;
25575
25760
  let {
@@ -25600,8 +25785,13 @@
25600
25785
  set: () => {}
25601
25786
  },
25602
25787
  renderedCallback,
25603
- onCtrlF
25788
+ onCtrlF,
25789
+ showSearch,
25790
+ isModal
25604
25791
  } = _ref;
25792
+ const {
25793
+ translator
25794
+ } = reactExports.useContext(InstanceContext);
25605
25795
  const [initScrollPosIsSet, setInitScrollPosIsSet] = reactExports.useState(false);
25606
25796
  const isSingleSelect = !!(layout && layout.qListObject.qDimensionInfo.qIsOneAndOnlyOne);
25607
25797
  const {
@@ -25856,7 +26046,10 @@
25856
26046
  setCurrentScrollIndex: currentScrollIndex.set,
25857
26047
  constraints,
25858
26048
  frequencyMax,
25859
- freqIsAllowed
26049
+ freqIsAllowed,
26050
+ translator,
26051
+ showSearch,
26052
+ isModal
25860
26053
  });
25861
26054
  const {
25862
26055
  columnWidth,
@@ -25871,7 +26064,10 @@
25871
26064
  itemHeight
25872
26065
  });
25873
26066
  }
25874
- return /*#__PURE__*/React.createElement(React.Fragment, null, !listCount && /*#__PURE__*/React.createElement(ListBoxDisclaimer, {
26067
+ return /*#__PURE__*/React.createElement(StyledWrapper, null, /*#__PURE__*/React.createElement(ScreenReaderForSelections, {
26068
+ className: "screenReaderOnly",
26069
+ layout: layout
26070
+ }), !listCount && /*#__PURE__*/React.createElement(ListBoxDisclaimer, {
25875
26071
  width: width,
25876
26072
  text: "Listbox.NoMatchesForYourTerms"
25877
26073
  }), /*#__PURE__*/React.createElement(InfiniteLoader, {
@@ -25883,7 +26079,8 @@
25883
26079
  }),
25884
26080
  threshold: 0,
25885
26081
  minimumBatchSize: minimumBatchSize,
25886
- ref: loaderRef
26082
+ ref: loaderRef,
26083
+ role: "grid"
25887
26084
  }, isVertical ? List : Grid), overflowDisclaimer.show && !overflowDisclaimer.dismissed && /*#__PURE__*/React.createElement(ListBoxFooter, {
25888
26085
  text: "Listbox.ItemsOverflow",
25889
26086
  dismiss: () => setOverflowDisclaimer(state => _objectSpread2(_objectSpread2({}, state), {}, {
@@ -26035,6 +26232,7 @@
26035
26232
  if (hidden) return null;
26036
26233
  const spacing = Number.parseInt(theme.spacing(0.5), 10);
26037
26234
  const handleKeyDown = item.keyboardAction ? e => ['Enter', ' ', 'Spacebar'].includes(e.key) && item.keyboardAction() : null;
26235
+ const btnId = "actions-toolbar-".concat(item.key);
26038
26236
  return /*#__PURE__*/React.createElement(IconButton$1, {
26039
26237
  ref: !addAnchor ? ref : null,
26040
26238
  title: item.label,
@@ -26042,12 +26240,12 @@
26042
26240
  onKeyDown: handleKeyDown,
26043
26241
  disabled: disabled,
26044
26242
  style: style,
26045
- className: ActionElement.className,
26243
+ className: [ActionElement.className, btnId].join(' '),
26046
26244
  size: "large",
26047
26245
  disableRipple: true,
26048
26246
  "aria-expanded": ariaExpanded,
26049
26247
  "aria-controls": "moreMenuList",
26050
- "data-testid": "actions-toolbar-".concat(item.key)
26248
+ "data-testid": btnId
26051
26249
  }, hasSvgIconShape && SvgIcon(item.getSvgIconShape()), addAnchor && /*#__PURE__*/React.createElement("div", {
26052
26250
  ref: ref,
26053
26251
  style: {
@@ -26226,6 +26424,70 @@
26226
26424
  }))));
26227
26425
  });
26228
26426
 
26427
+ const getActionButtonIndex = btn => {
26428
+ const toolbar = btn.closest('#actions-toolbar');
26429
+ const nodeList = toolbar === null || toolbar === void 0 ? void 0 : toolbar.querySelectorAll('.njs-cell-action');
26430
+ return Array.from(nodeList).indexOf(btn);
26431
+ };
26432
+ const focusButton = index => {
26433
+ const toolbar = document.querySelector('#actions-toolbar');
26434
+ const nodeList = toolbar === null || toolbar === void 0 ? void 0 : toolbar.querySelectorAll('.njs-cell-action');
26435
+ if (!nodeList.length) {
26436
+ return;
26437
+ }
26438
+ const ix = Math.min(Math.max(0, index), nodeList.length - 1);
26439
+ const btn = nodeList[ix];
26440
+ btn.focus();
26441
+ };
26442
+ function getActionsKeyDownHandler(_ref) {
26443
+ let {
26444
+ keyboardNavigation,
26445
+ focusHandler,
26446
+ getEnabledButton
26447
+ } = _ref;
26448
+ const handleActionsKeyDown = evt => {
26449
+ const {
26450
+ target,
26451
+ nativeEvent
26452
+ } = evt;
26453
+ const {
26454
+ keyCode
26455
+ } = nativeEvent;
26456
+ switch (keyCode) {
26457
+ case KEYS.ARROW_LEFT:
26458
+ case KEYS.ARROW_DOWN:
26459
+ case KEYS.ARROW_RIGHT:
26460
+ case KEYS.ARROW_UP:
26461
+ {
26462
+ const isActionButton = target.classList.contains('njs-cell-action');
26463
+ if (isActionButton) {
26464
+ const index = getActionButtonIndex(target);
26465
+ const pressedLeft = [KEYS.ARROW_LEFT, KEYS.ARROW_DOWN].includes(keyCode);
26466
+ focusButton(pressedLeft ? index - 1 : index + 1);
26467
+ }
26468
+ evt.stopPropagation();
26469
+ evt.preventDefault();
26470
+ break;
26471
+ }
26472
+ case KEYS.SPACE:
26473
+ evt.preventDefault(); // prevent scrolling in listbox
26474
+ break;
26475
+ case KEYS.TAB:
26476
+ if (keyboardNavigation && focusHandler !== null && focusHandler !== void 0 && focusHandler.refocusContent) {
26477
+ const isTabbingOut = evt.shiftKey && getEnabledButton(false) === evt.target || !evt.shiftKey && getEnabledButton(true) === evt.target;
26478
+ if (isTabbingOut) {
26479
+ evt.preventDefault();
26480
+ evt.stopPropagation();
26481
+ // if keyboardNavigation is true, create a callback to handle tabbing from the first/last button in the toolbar that resets focus on the content
26482
+ focusHandler.refocusContent();
26483
+ }
26484
+ }
26485
+ break;
26486
+ }
26487
+ };
26488
+ return handleActionsKeyDown;
26489
+ }
26490
+
26229
26491
  const PREFIX$7 = 'ActionsToolbar';
26230
26492
  const classes$7 = {
26231
26493
  item: "".concat(PREFIX$7, "-item"),
@@ -26261,6 +26523,7 @@
26261
26523
  };
26262
26524
  const ActionsGroup = React.forwardRef((_ref2, ref) => {
26263
26525
  let {
26526
+ className,
26264
26527
  ariaExpanded = false,
26265
26528
  actions = [],
26266
26529
  first = false,
@@ -26273,7 +26536,8 @@
26273
26536
  container: true,
26274
26537
  gap: 0,
26275
26538
  flexDirection: isRtl ? 'row-reverse' : 'row',
26276
- wrap: "nowrap"
26539
+ wrap: "nowrap",
26540
+ className: className
26277
26541
  }, actions.map((e, ix) => {
26278
26542
  let cls = [];
26279
26543
  const isFirstItem = first && ix === 0;
@@ -26341,22 +26605,27 @@
26341
26605
  keyboardNavigation
26342
26606
  } = reactExports.useContext(InstanceContext);
26343
26607
  const [showMoreItems, setShowMoreItems] = reactExports.useState(false);
26344
- const moreRef = reactExports.useRef();
26608
+ const popoverAnchorOrigin = {
26609
+ vertical: 7,
26610
+ horizontal: ((_popover$anchorEl$cli = (_popover$anchorEl = popover.anchorEl) === null || _popover$anchorEl === void 0 ? void 0 : _popover$anchorEl.clientWidth) !== null && _popover$anchorEl$cli !== void 0 ? _popover$anchorEl$cli : 0) - 7
26611
+ };
26345
26612
  const actionsRef = reactExports.useRef();
26613
+ const moreRef = reactExports.useRef();
26346
26614
  const theme = useTheme$1();
26347
26615
  const dividerStyle = reactExports.useMemo(() => ({
26348
26616
  margin: theme.spacing(0.5, 0)
26349
26617
  }));
26350
- const popoverAnchorOrigin = {
26351
- vertical: 15,
26352
- 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
26353
- };
26354
26618
  const getEnabledButton = last => {
26355
26619
  const actionsElement = actionsRef.current || actionsRefMock;
26356
26620
  if (!actionsElement) return null;
26357
26621
  const buttons = actionsElement.querySelectorAll('button:not(.Mui-disabled)');
26358
26622
  return buttons[last ? buttons.length - 1 : 0];
26359
26623
  };
26624
+ const handleActionsKeyDown = reactExports.useMemo(() => getActionsKeyDownHandler({
26625
+ keyboardNavigation,
26626
+ focusHandler,
26627
+ getEnabledButton
26628
+ }), [keyboardNavigation, focusHandler, getEnabledButton]);
26360
26629
  reactExports.useEffect(() => () => {
26361
26630
  setShowMoreItems(false);
26362
26631
  }, [popover.show, show, selections.show]);
@@ -26396,27 +26665,18 @@
26396
26665
  enabled: () => moreEnabled,
26397
26666
  action: () => setShowMoreItems(!showMoreItems)
26398
26667
  };
26399
- const tabCallback =
26400
- // if keyboardNavigation is true, create a callback to handle tabbing from the first/last button in the toolbar that resets focus on the content
26401
- keyboardNavigation && focusHandler && focusHandler.refocusContent ? evt => {
26402
- if (evt.key !== 'Tab') return;
26403
- const isTabbingOut = evt.shiftKey && getEnabledButton(false) === evt.target || !evt.shiftKey && getEnabledButton(true) === evt.target;
26404
- if (isTabbingOut) {
26405
- evt.preventDefault();
26406
- evt.stopPropagation();
26407
- focusHandler.refocusContent();
26408
- }
26409
- } : null;
26410
26668
  const showActions = newActions.length > 0;
26411
26669
  const showMore = moreActions.length > 0;
26412
26670
  const showDivider = showActions && selections.show || showMore && selections.show;
26413
26671
  const isRtl = direction === 'rtl';
26414
26672
  const Actions = /*#__PURE__*/React.createElement(Grid$1, {
26415
26673
  ref: actionsRef,
26416
- onKeyDown: tabCallback,
26674
+ onKeyDown: handleActionsKeyDown,
26417
26675
  container: true,
26418
26676
  gap: 0,
26419
26677
  wrap: "nowrap",
26678
+ id: "actions-toolbar",
26679
+ "data-testid": "actions-toolbar",
26420
26680
  sx: {
26421
26681
  flexDirection: isRtl ? 'row-reverse' : 'row'
26422
26682
  }
@@ -26425,6 +26685,8 @@
26425
26685
  first: true,
26426
26686
  last: !showMore && !selections.show
26427
26687
  }), showMore && /*#__PURE__*/React.createElement(ActionsGroup, {
26688
+ id: "actions-toolbar-show-more",
26689
+ "data-testid": "actions-toolbar-show-more",
26428
26690
  ref: moreRef,
26429
26691
  ariaExpanded: showMoreItems,
26430
26692
  actions: [moreItem],
@@ -26438,6 +26700,7 @@
26438
26700
  }, /*#__PURE__*/React.createElement(Divider$1, {
26439
26701
  orientation: "vertical"
26440
26702
  })), selections.show && /*#__PURE__*/React.createElement(ActionsGroup, {
26703
+ className: "actions-toolbar-default-actions",
26441
26704
  actions: defaultSelectionActions,
26442
26705
  first: !showActions && !showMore,
26443
26706
  last: true,
@@ -26461,6 +26724,8 @@
26461
26724
  hideBackdrop: true,
26462
26725
  style: popoverStyle,
26463
26726
  PaperProps: {
26727
+ id: 'njs-action-toolbar-popover',
26728
+ 'data-testid': 'njs-action-toolbar-popover',
26464
26729
  className: ActionToolbarElement.className,
26465
26730
  style: {
26466
26731
  pointerEvents: 'auto',
@@ -26588,29 +26853,57 @@
26588
26853
  }
26589
26854
  return response;
26590
26855
  };
26856
+ function focusRow(container) {
26857
+ const row = (container === null || container === void 0 ? void 0 : container.querySelector('.last-focused')) || (container === null || container === void 0 ? void 0 : container.querySelector('[role="row"]:first-child'));
26858
+ row.setAttribute('tabIndex', 0);
26859
+ row === null || row === void 0 ? void 0 : row.focus();
26860
+ }
26591
26861
  const onKeyDown = async e => {
26592
- let response;
26862
+ const {
26863
+ currentTarget
26864
+ } = e;
26865
+ const container = currentTarget.closest('.listbox-container');
26593
26866
  switch (e.key) {
26594
26867
  case 'Enter':
26595
- response = await performSearch();
26868
+ performSearch();
26596
26869
  break;
26597
26870
  case 'Escape':
26598
- response = cancel();
26599
- e.preventDefault();
26600
- e.stopPropagation();
26601
- break;
26871
+ {
26872
+ focusRow(container);
26873
+ cancel();
26874
+ break;
26875
+ }
26876
+ case 'Tab':
26877
+ {
26878
+ if (e.shiftKey) {
26879
+ keyboard.focusSelection();
26880
+ } else {
26881
+ // Focus the row we last visited or the first one.
26882
+ focusRow(container);
26883
+
26884
+ // Clean up.
26885
+ container === null || container === void 0 ? void 0 : container.querySelectorAll('.last-focused').forEach(elm => {
26886
+ elm.classList.remove('last-focused');
26887
+ });
26888
+ }
26889
+ break;
26890
+ }
26602
26891
  case 'f':
26603
26892
  case 'F':
26604
26893
  if (e.ctrlKey || e.metaKey) {
26605
26894
  if (hide) {
26606
26895
  hide();
26607
26896
  }
26608
- e.preventDefault();
26609
- e.stopPropagation();
26897
+ } else {
26898
+ return undefined;
26610
26899
  }
26611
26900
  break;
26901
+ default:
26902
+ return undefined;
26612
26903
  }
26613
- return response;
26904
+ e.preventDefault();
26905
+ e.stopPropagation();
26906
+ return undefined;
26614
26907
  };
26615
26908
  if (!visible || searchEnabled === false) {
26616
26909
  return null;
@@ -26656,10 +26949,11 @@
26656
26949
  onKeyDown: onKeyDown,
26657
26950
  autoFocus: autoFocus,
26658
26951
  inputProps: {
26659
- tabIndex: keyboard && (!keyboard.enabled || keyboard.active) ? 0 : -1,
26952
+ tabIndex: keyboard.innerTabStops ? 0 : -1,
26660
26953
  style: {
26661
26954
  textAlign: "".concat(inpuTextAlign)
26662
- }
26955
+ },
26956
+ 'data-testid': 'search-input-field'
26663
26957
  }
26664
26958
  });
26665
26959
  }
@@ -26903,6 +27197,12 @@
26903
27197
  objectSelections.addListener('activated', activateClickOut);
26904
27198
  objectSelections.addListener('deactivated', deactivateClickOut);
26905
27199
  return () => {
27200
+ // confirm selection before removing event handler
27201
+ // to end the selection when the object is removed
27202
+ // and remove the (ClickOut) mousedown handler from the document
27203
+ if (objectSelections.isActive()) {
27204
+ objectSelections.confirm();
27205
+ }
26906
27206
  objectSelections.removeListener('activated', activateClickOut);
26907
27207
  objectSelections.removeListener('deactivated', deactivateClickOut);
26908
27208
  };
@@ -28558,6 +28858,23 @@
28558
28858
  };
28559
28859
  }
28560
28860
 
28861
+ const StyledDiv = styled$1('div')(() => ({
28862
+ display: 'flex',
28863
+ width: '100%',
28864
+ height: '100%',
28865
+ alignItems: 'center',
28866
+ justifyContent: 'center'
28867
+ }));
28868
+ function ListBoxError(_ref) {
28869
+ let {
28870
+ text
28871
+ } = _ref;
28872
+ const {
28873
+ translator
28874
+ } = reactExports.useContext(InstanceContext);
28875
+ return /*#__PURE__*/React.createElement(StyledDiv, null, translator.get(text));
28876
+ }
28877
+
28561
28878
  const PREFIX$4 = 'ListBoxInline';
28562
28879
  const classes$4 = {
28563
28880
  listBoxHeader: "".concat(PREFIX$4, "-listBoxHeader"),
@@ -28609,12 +28926,20 @@
28609
28926
  fontWeight: ((_theme$listBox5 = theme.listBox) === null || _theme$listBox5 === void 0 ? void 0 : (_theme$listBox5$title = _theme$listBox5.title) === null || _theme$listBox5$title === void 0 ? void 0 : (_theme$listBox5$title2 = _theme$listBox5$title.main) === null || _theme$listBox5$title2 === void 0 ? void 0 : _theme$listBox5$title2.fontWeight) || 'bold'
28610
28927
  };
28611
28928
  });
28612
- function ListBoxInline(_ref3) {
28929
+ const isModal = _ref3 => {
28930
+ var _app$isInModalSelecti, _app$isInModalSelecti2;
28931
+ let {
28932
+ app,
28933
+ appSelections
28934
+ } = _ref3;
28935
+ return (_app$isInModalSelecti = (_app$isInModalSelecti2 = app.isInModalSelection) === null || _app$isInModalSelecti2 === void 0 ? void 0 : _app$isInModalSelecti2.call(app)) !== null && _app$isInModalSelecti !== void 0 ? _app$isInModalSelecti : appSelections.isInModal();
28936
+ };
28937
+ function ListBoxInline(_ref4) {
28613
28938
  var _layoutOptions$dense;
28614
28939
  let {
28615
28940
  options,
28616
28941
  layout
28617
- } = _ref3;
28942
+ } = _ref4;
28618
28943
  const {
28619
28944
  app,
28620
28945
  direction,
@@ -28632,9 +28957,7 @@
28632
28957
  calculatePagesHeight,
28633
28958
  showGray = true,
28634
28959
  scrollState = undefined,
28635
- renderedCallback
28636
- } = options;
28637
- let {
28960
+ renderedCallback,
28638
28961
  toolbar = true
28639
28962
  } = options;
28640
28963
 
@@ -28664,7 +28987,6 @@
28664
28987
  const [searchContainer, searchContainerRef] = useRefWithCallback();
28665
28988
  const [showToolbar, setShowToolbar] = reactExports.useState(false);
28666
28989
  const [showSearch, setShowSearch] = reactExports.useState(false);
28667
- const [keyboardActive, setKeyboardActive] = reactExports.useState(false);
28668
28990
  const [hovering, setHovering] = reactExports.useState(false);
28669
28991
  const [keyScroll, setKeyScroll] = reactExports.useState({
28670
28992
  down: 0,
@@ -28679,12 +29001,22 @@
28679
29001
  const [appSelections] = useAppSelections(app);
28680
29002
  const titleRef = reactExports.useRef(null);
28681
29003
  const [selectionState$1] = reactExports.useState(() => selectionState());
29004
+ const keyboard = useTempKeyboard({
29005
+ containerRef,
29006
+ enabled: keyboardNavigation
29007
+ });
29008
+ const isModalMode = reactExports.useCallback(() => isModal({
29009
+ app,
29010
+ appSelections
29011
+ }), [app, appSelections]);
29012
+ const isInvalid = layout === null || layout === void 0 ? void 0 : layout.qListObject.qDimensionInfo.qError;
29013
+ const errorText = isInvalid && constraints.active ? 'Visualization.Invalid.Dimension' : 'Visualization.Incomplete';
28682
29014
  const {
28683
29015
  handleKeyDown,
28684
29016
  handleOnMouseEnter,
28685
29017
  handleOnMouseLeave
28686
29018
  } = getListboxInlineKeyboardNavigation({
28687
- setKeyboardActive,
29019
+ keyboard,
28688
29020
  hovering,
28689
29021
  setHovering,
28690
29022
  updateKeyScroll,
@@ -28692,20 +29024,11 @@
28692
29024
  currentScrollIndex,
28693
29025
  app,
28694
29026
  appSelections,
28695
- constraints
29027
+ constraints,
29028
+ isModal: isModalMode
28696
29029
  });
28697
-
28698
- // Expose the keyboard flags in the same way as the keyboard hook does.
28699
- const keyboard = {
28700
- enabled: keyboardNavigation,
28701
- // this will be static until we can access the useKeyboard hook
28702
- active: keyboardActive
28703
- };
28704
- if ((layout === null || layout === void 0 ? void 0 : layout.toolbar) !== undefined) {
28705
- toolbar = layout.toolbar;
28706
- }
28707
- const toolbarDetachedOnly = toolbar && (layout === null || layout === void 0 ? void 0 : layout.title) === '';
28708
- toolbar = toolbar && (layout === null || layout === void 0 ? void 0 : layout.title) !== '';
29030
+ const showDetachedToolbarOnly = toolbar && ((layout === null || layout === void 0 ? void 0 : layout.title) === '' || (layout === null || layout === void 0 ? void 0 : layout.showTitle) === false);
29031
+ const showToolbarWithTitle = toolbar && (layout === null || layout === void 0 ? void 0 : layout.title) !== '' && (layout === null || layout === void 0 ? void 0 : layout.showTitle) !== false;
28709
29032
  reactExports.useEffect(() => {
28710
29033
  const show = () => {
28711
29034
  setShowToolbar(true);
@@ -28729,7 +29052,7 @@
28729
29052
  selections.removeListener('deactivated', hide);
28730
29053
  }
28731
29054
  };
28732
- }, [selections, toolbar]);
29055
+ }, [selections]);
28733
29056
  reactExports.useEffect(() => {
28734
29057
  if (!searchContainer || !searchContainer.current) {
28735
29058
  return;
@@ -28763,7 +29086,7 @@
28763
29086
  const searchHeight = dense ? 27 : 40;
28764
29087
  const extraheight = dense ? 39 : 49;
28765
29088
  const searchAddHeight = searchVisible ? searchHeight : 0;
28766
- const minHeight = toolbar ? 49 + searchAddHeight + extraheight : 0;
29089
+ const minHeight = showToolbarWithTitle ? 49 + searchAddHeight + extraheight : 0;
28767
29090
  const headerHeight = 32;
28768
29091
  const onShowSearch = () => {
28769
29092
  const newValue = !showSearch;
@@ -28835,12 +29158,12 @@
28835
29158
  fontSize: '12px'
28836
29159
  }
28837
29160
  }));
28838
- return /*#__PURE__*/React.createElement(React.Fragment, null, toolbarDetachedOnly && /*#__PURE__*/React.createElement(ActionsToolbar, _extends$8({
29161
+ return /*#__PURE__*/React.createElement(React.Fragment, null, showDetachedToolbarOnly && /*#__PURE__*/React.createElement(ActionsToolbar, _extends$8({
28839
29162
  direction: direction
28840
29163
  }, getActionToolbarProps(true))), /*#__PURE__*/React.createElement(StyledGrid$3, {
28841
29164
  className: "listbox-container",
28842
29165
  container: true,
28843
- tabIndex: keyboard.enabled && !keyboard.active ? 0 : -1,
29166
+ tabIndex: keyboard.outerTabStops ? 0 : -1,
28844
29167
  direction: "column",
28845
29168
  gap: 0,
28846
29169
  containerPadding: containerPadding,
@@ -28854,7 +29177,7 @@
28854
29177
  onMouseLeave: handleOnMouseLeave,
28855
29178
  ref: containerRef,
28856
29179
  hasIcon: showIcons
28857
- }, toolbar && /*#__PURE__*/React.createElement(Grid$1, {
29180
+ }, showToolbarWithTitle && /*#__PURE__*/React.createElement(Grid$1, {
28858
29181
  item: true,
28859
29182
  container: true,
28860
29183
  style: {
@@ -28944,11 +29267,13 @@
28944
29267
  className: classes$4.listboxWrapper
28945
29268
  }, /*#__PURE__*/React.createElement("div", {
28946
29269
  className: classes$4.screenReaderOnly
28947
- }, translator.get('Listbox.ScreenReaderInstructions')), /*#__PURE__*/React.createElement(AutoSizer, null, _ref4 => {
29270
+ }, translator.get('Listbox.ScreenReaderInstructions')), isInvalid ? /*#__PURE__*/React.createElement(ListBoxError, {
29271
+ text: errorText
29272
+ }) : /*#__PURE__*/React.createElement(AutoSizer, null, _ref5 => {
28948
29273
  let {
28949
29274
  height,
28950
29275
  width
28951
- } = _ref4;
29276
+ } = _ref5;
28952
29277
  return /*#__PURE__*/React.createElement(ListBox, {
28953
29278
  model: model,
28954
29279
  app: app,
@@ -28983,15 +29308,16 @@
28983
29308
  set: setCurrentScrollIndex
28984
29309
  },
28985
29310
  renderedCallback: renderedCallback,
28986
- onCtrlF: onCtrlF
29311
+ onCtrlF: onCtrlF,
29312
+ isModal: isModalMode
28987
29313
  });
28988
29314
  })))));
28989
29315
  }
28990
29316
  const ListBoxInlineMemoed = React.memo(ListBoxInline);
28991
- function IsolateUseLayoutWrapper(_ref5) {
29317
+ function IsolateUseLayoutWrapper(_ref6) {
28992
29318
  let {
28993
29319
  options = {}
28994
- } = _ref5;
29320
+ } = _ref6;
28995
29321
  const {
28996
29322
  model
28997
29323
  } = options;
@@ -29393,7 +29719,7 @@
29393
29719
  array.splice(removeIdx, 1);
29394
29720
  return removeIdx;
29395
29721
  }
29396
- const nxDimension = f => ({
29722
+ const nxDimension$1 = f => ({
29397
29723
  qDef: {
29398
29724
  qFieldDefs: [f]
29399
29725
  }
@@ -29424,7 +29750,7 @@
29424
29750
  return hc.qMeasures;
29425
29751
  },
29426
29752
  addDimension(d) {
29427
- const dimension = typeof d === 'string' ? nxDimension(d) : _objectSpread2(_objectSpread2({}, d), {}, {
29753
+ const dimension = typeof d === 'string' ? nxDimension$1(d) : _objectSpread2(_objectSpread2({}, d), {}, {
29428
29754
  qDef: d.qDef || {}
29429
29755
  });
29430
29756
  dimension.qDef.cId = dimension.qDef.cId || uid();
@@ -29507,6 +29833,69 @@
29507
29833
  return handler;
29508
29834
  }
29509
29835
 
29836
+ const nxDimension = f => ({
29837
+ qDef: {
29838
+ qFieldDefs: [f]
29839
+ }
29840
+ });
29841
+ function loHandler(_ref) {
29842
+ let {
29843
+ dc: lo,
29844
+ def,
29845
+ properties
29846
+ } = _ref;
29847
+ lo.qInitialDataFetch = lo.qInitialDataFetch || [];
29848
+ const objectProperties = properties;
29849
+ const handler = {
29850
+ dimensions() {
29851
+ if (!lo.qLibraryId && (!lo.qDef || !lo.qDef.qFieldDefs || lo.qDef.qFieldDefs.length === 0)) return [];
29852
+ return [lo];
29853
+ },
29854
+ measures() {
29855
+ return [];
29856
+ },
29857
+ addDimension(d) {
29858
+ const dimension = typeof d === 'string' ? nxDimension(d) : _objectSpread2(_objectSpread2({}, d), {}, {
29859
+ qDef: d.qDef || {}
29860
+ });
29861
+ dimension.qDef.cId = dimension.qDef.cId || uid();
29862
+ dimension.qDef.qSortCriterias = lo.qDef.qSortCriterias || [{
29863
+ qSortByState: 1,
29864
+ qSortByLoadOrder: 1,
29865
+ qSortByNumeric: 1,
29866
+ qSortByAscii: 1
29867
+ }];
29868
+ Object.keys(dimension).forEach(k => {
29869
+ lo[k] = dimension[k];
29870
+ });
29871
+ def.dimensions.added(dimension, objectProperties);
29872
+ return dimension;
29873
+ },
29874
+ removeDimension(idx) {
29875
+ const dimension = lo;
29876
+ delete lo.qDef;
29877
+ delete lo.qLibraryId;
29878
+ def.dimensions.removed(dimension, objectProperties, idx);
29879
+ return dimension;
29880
+ },
29881
+ addMeasure() {},
29882
+ removeMeasure() {},
29883
+ maxDimensions() {
29884
+ return 1;
29885
+ },
29886
+ maxMeasures() {
29887
+ return 0;
29888
+ },
29889
+ canAddDimension() {
29890
+ return handler.dimensions().length === 0;
29891
+ },
29892
+ canAddMeasure() {
29893
+ return false;
29894
+ }
29895
+ };
29896
+ return handler;
29897
+ }
29898
+
29510
29899
  /**
29511
29900
  * @interface LibraryField
29512
29901
  * @property {string} qLibraryId
@@ -29551,7 +29940,8 @@
29551
29940
  const s = parts[i];
29552
29941
  p = s ? p[s] : p;
29553
29942
  }
29554
- const hc = hcHandler({
29943
+ const createHandler = propertyPath.match('/qListObjectDef') ? loHandler : hcHandler;
29944
+ const handler = createHandler({
29555
29945
  dc: p,
29556
29946
  def: target,
29557
29947
  properties
@@ -29559,9 +29949,9 @@
29559
29949
  fields.forEach(f => {
29560
29950
  const type = fieldType(f);
29561
29951
  if (type === 'measure') {
29562
- hc.addMeasure(f);
29952
+ handler.addMeasure(f);
29563
29953
  } else {
29564
- hc.addDimension(f);
29954
+ handler.addDimension(f);
29565
29955
  }
29566
29956
  });
29567
29957
  }
@@ -30792,7 +31182,8 @@
30792
31182
  sn,
30793
31183
  anchorEl,
30794
31184
  hovering,
30795
- focusHandler
31185
+ focusHandler,
31186
+ titleStyles = {}
30796
31187
  } = _ref2;
30797
31188
  const showTitle = layout.showTitles && !!layout.title;
30798
31189
  const showSubtitle = layout.showTitles && !!layout.subtitle;
@@ -30850,11 +31241,13 @@
30850
31241
  }, showTitle && /*#__PURE__*/React.createElement(Typography$1, {
30851
31242
  variant: "h6",
30852
31243
  noWrap: true,
30853
- className: CellTitle.className
31244
+ className: CellTitle.className,
31245
+ style: titleStyles.main
30854
31246
  }, layout.title), showSubtitle && /*#__PURE__*/React.createElement(Typography$1, {
30855
31247
  variant: "body2",
30856
31248
  noWrap: true,
30857
- className: CellSubTitle.className
31249
+ className: CellSubTitle.className,
31250
+ style: titleStyles.subTitle
30858
31251
  }, layout.subtitle))), /*#__PURE__*/React.createElement(Grid$1, {
30859
31252
  item: true
30860
31253
  }, Toolbar));
@@ -30887,7 +31280,8 @@
30887
31280
  };
30888
31281
  function Footer(_ref2) {
30889
31282
  let {
30890
- layout
31283
+ layout,
31284
+ titleStyles = {}
30891
31285
  } = _ref2;
30892
31286
  return layout && layout.showTitles && layout.footnote ? /*#__PURE__*/React.createElement(StyledGrid, {
30893
31287
  container: true
@@ -30897,7 +31291,8 @@
30897
31291
  }, /*#__PURE__*/React.createElement(Typography$1, {
30898
31292
  noWrap: true,
30899
31293
  variant: "body2",
30900
- className: CellFooter.className
31294
+ className: CellFooter.className,
31295
+ style: titleStyles.footer
30901
31296
  }, layout.footnote))) : null;
30902
31297
  }
30903
31298
 
@@ -31127,7 +31522,7 @@
31127
31522
  function resolveImageUrl(app, relativeUrl) {
31128
31523
  return relativeUrl ? getSenseServerUrl(app) + relativeUrl : undefined;
31129
31524
  }
31130
- const resolveBgImage = (bgComp, app) => {
31525
+ function resolveBgImage(bgComp, app) {
31131
31526
  const bgImageDef = bgComp === null || bgComp === void 0 ? void 0 : bgComp.bgImage;
31132
31527
  if (bgImageDef) {
31133
31528
  let url = '';
@@ -31148,8 +31543,8 @@
31148
31543
  } : undefined;
31149
31544
  }
31150
31545
  return undefined;
31151
- };
31152
- const resolveBgColor = (bgComp, theme) => {
31546
+ }
31547
+ function resolveBgColor(bgComp, theme, objectType) {
31153
31548
  const bgColor = bgComp === null || bgComp === void 0 ? void 0 : bgComp.bgColor;
31154
31549
  if (bgColor && theme) {
31155
31550
  if (bgColor.useExpression) {
@@ -31157,8 +31552,32 @@
31157
31552
  }
31158
31553
  return bgColor.color && bgColor.color.color !== 'none' ? theme.getColorPickerColor(bgColor.color, true) : undefined;
31159
31554
  }
31555
+ if (theme && objectType) {
31556
+ return theme.getStyle("object.".concat(objectType), '', 'backgroundColor');
31557
+ }
31558
+ if (theme) {
31559
+ return theme.getStyle('', '', 'backgroundColor');
31560
+ }
31160
31561
  return undefined;
31161
- };
31562
+ }
31563
+ function unfurlFontStyle(fontStyle, target) {
31564
+ if (fontStyle && Array.isArray(fontStyle)) {
31565
+ return fontStyle;
31566
+ }
31567
+ return target === 'main' ? ['bold'] : [];
31568
+ }
31569
+ function resolveTextStyle(textComp, target, theme, objectType) {
31570
+ var _textComp$title;
31571
+ const textProps = (textComp === null || textComp === void 0 ? void 0 : (_textComp$title = textComp.title) === null || _textComp$title === void 0 ? void 0 : _textComp$title[target]) || {};
31572
+ const fontStyle = unfurlFontStyle(textProps.fontStyle, target);
31573
+ return {
31574
+ fontFamily: textProps.fontFamily || theme.getStyle("object.".concat(objectType), "title.".concat(target), 'fontFamily'),
31575
+ color: textProps.color && textProps.color.color !== 'none' ? theme.getColorPickerColor(textProps.color, true) : theme.getStyle("object.".concat(objectType), target, 'color'),
31576
+ fontWeight: fontStyle.includes('bold') ? 'bold' : 'normal',
31577
+ fontStyle: fontStyle.includes('italic') ? 'italic' : 'normal',
31578
+ textDecoration: fontStyle.includes('underline') ? 'underline' : 'initial'
31579
+ };
31580
+ }
31162
31581
 
31163
31582
  /**
31164
31583
  * @interface
@@ -31400,7 +31819,8 @@
31400
31819
  app,
31401
31820
  selections,
31402
31821
  nebbie,
31403
- focusHandler
31822
+ focusHandler,
31823
+ emitter
31404
31824
  } = _ref5;
31405
31825
  try {
31406
31826
  const snType = await getType({
@@ -31413,7 +31833,8 @@
31413
31833
  app,
31414
31834
  selections,
31415
31835
  nebbie,
31416
- focusHandler
31836
+ focusHandler,
31837
+ emitter
31417
31838
  });
31418
31839
  return sn;
31419
31840
  } catch (err) {
@@ -31443,7 +31864,8 @@
31443
31864
  initialSnPlugins,
31444
31865
  initialError,
31445
31866
  onMount,
31446
- currentId
31867
+ currentId,
31868
+ emitter
31447
31869
  } = _ref6;
31448
31870
  const {
31449
31871
  app,
@@ -31482,7 +31904,7 @@
31482
31904
  });
31483
31905
  const [bgColor, setBgColor] = reactExports.useState(undefined);
31484
31906
  const [bgImage, setBgImage] = reactExports.useState(undefined); // {url: "", size: "", pos: ""}
31485
-
31907
+ const [titleStyles, setTitleStyles] = reactExports.useState(undefined);
31486
31908
  const focusHandler = reactExports.useRef({
31487
31909
  focusToolbarButton(last) {
31488
31910
  // eslint-disable-next-line react/no-this-in-sfc
@@ -31493,9 +31915,16 @@
31493
31915
  eventmixin(focusHandler.current);
31494
31916
  }, []);
31495
31917
  reactExports.useEffect(() => {
31496
- const bgComp = layout !== null && layout !== void 0 && layout.components ? layout.components.find(comp => comp.key === 'general') : null;
31497
- setBgColor(resolveBgColor(bgComp, halo.public.theme));
31498
- setBgImage(resolveBgImage(bgComp, halo.app));
31918
+ if (layout && halo.public.theme) {
31919
+ const bgComp = layout.components ? layout.components.find(comp => comp.key === 'general') : null;
31920
+ setTitleStyles({
31921
+ main: resolveTextStyle(bgComp, 'main', halo.public.theme, layout.visualization),
31922
+ footer: resolveTextStyle(bgComp, 'footer', halo.public.theme, layout.visualization),
31923
+ subTitle: resolveTextStyle(bgComp, 'subTitle', halo.public.theme, layout.visualization)
31924
+ });
31925
+ setBgColor(resolveBgColor(bgComp, halo.public.theme, layout.visualization));
31926
+ setBgImage(resolveBgImage(bgComp, halo.app));
31927
+ }
31499
31928
  }, [layout, halo.public.theme, halo.app, themeName]);
31500
31929
  focusHandler.current.blurCallback = resetFocus => {
31501
31930
  halo.root.toggleFocusOfCells();
@@ -31567,7 +31996,8 @@
31567
31996
  app,
31568
31997
  selections,
31569
31998
  nebbie,
31570
- focusHandler: focusHandler.current
31999
+ focusHandler: focusHandler.current,
32000
+ emitter
31571
32001
  });
31572
32002
  if (sn) {
31573
32003
  dispatch({
@@ -31709,7 +32139,8 @@
31709
32139
  sn: state.sn,
31710
32140
  anchorEl: cellNode,
31711
32141
  hovering: hovering,
31712
- focusHandler: focusHandler.current
32142
+ focusHandler: focusHandler.current,
32143
+ titleStyles: titleStyles
31713
32144
  }, "\xA0"), /*#__PURE__*/React.createElement(Grid$1, {
31714
32145
  tabIndex: keyboardNavigation ? 0 : -1,
31715
32146
  onKeyDown: keyboardNavigation ? handleKeyDown : null,
@@ -31720,7 +32151,8 @@
31720
32151
  },
31721
32152
  ref: contentRef
31722
32153
  }, Content), /*#__PURE__*/React.createElement(Footer, {
31723
- layout: layout
32154
+ layout: layout,
32155
+ titleStyles: titleStyles
31724
32156
  })), state.longRunningQuery && /*#__PURE__*/React.createElement(LongRunningQuery, {
31725
32157
  canCancel: canCancel,
31726
32158
  canRetry: canRetry,
@@ -31736,6 +32168,7 @@
31736
32168
  initialSnOptions,
31737
32169
  initialSnPlugins,
31738
32170
  onMount,
32171
+ emitter,
31739
32172
  initialError
31740
32173
  } = _ref;
31741
32174
  const {
@@ -31751,7 +32184,8 @@
31751
32184
  initialSnOptions: initialSnOptions,
31752
32185
  initialSnPlugins: initialSnPlugins,
31753
32186
  initialError: initialError,
31754
- onMount: onMount
32187
+ onMount: onMount,
32188
+ emitter: emitter
31755
32189
  }), element, currentId);
31756
32190
  const unmount = () => {
31757
32191
  root.remove(portal);
@@ -31851,6 +32285,7 @@
31851
32285
  });
31852
32286
  let initialSnOptions = {};
31853
32287
  let initialSnPlugins = [];
32288
+ const emitter = new nodeEventEmitter();
31854
32289
  const setSnOptions = async opts => {
31855
32290
  if (mountedReference) {
31856
32291
  (async () => {
@@ -31941,6 +32376,24 @@
31941
32376
  }
31942
32377
  return propertyTree;
31943
32378
  },
32379
+ /**
32380
+ * Listens to custom events from inside the visualization. See useEmitter
32381
+ * @experimental
32382
+ * @param {string} eventName Event name to listen to
32383
+ * @param {Function} listener Callback function to invoke
32384
+ */
32385
+ on(eventName, listener) {
32386
+ emitter.on(eventName, listener);
32387
+ },
32388
+ /**
32389
+ * Removes a listener
32390
+ * @experimental
32391
+ * @param {string} eventName Event name to remove from
32392
+ * @param {Function} listener Callback function to remove
32393
+ */
32394
+ off(eventName, listener) {
32395
+ emitter.off(eventName, listener);
32396
+ },
31944
32397
  // ===== unexposed experimental API - use at own risk ======
31945
32398
  __DO_NOT_USE__: {
31946
32399
  mount(element) {
@@ -31955,7 +32408,8 @@
31955
32408
  initialSnOptions,
31956
32409
  initialSnPlugins,
31957
32410
  initialError,
31958
- onMount
32411
+ onMount,
32412
+ emitter
31959
32413
  });
31960
32414
  return mounted;
31961
32415
  },
@@ -33902,7 +34356,7 @@
33902
34356
  * @ignore
33903
34357
  * @example
33904
34358
  * import { onContextMenu } from '@nebula.js/stardust';
33905
-
34359
+
33906
34360
  * onContextMenu((menu, event) => {
33907
34361
  * menu.addItem(item, index);
33908
34362
  * });
@@ -33956,6 +34410,32 @@
33956
34410
  };
33957
34411
  }
33958
34412
 
34413
+ /**
34414
+ * Gets an event emitter instance for the visualization.
34415
+ * @entry
34416
+ * @experimental
34417
+ * @returns {Emitter} The emitter instance. Implements https://nodejs.org/api/events.html#class-eventemitter.
34418
+ * @example
34419
+ * // In a Nebula visualization
34420
+ * import { useEmitter } from '@nebula.js/stardust';
34421
+ * useEffect(()=> {
34422
+ * // on some trigger
34423
+ * emitter.emit("trigger", params)
34424
+ * }, [...])
34425
+ *
34426
+ * // In a mashup
34427
+ * const viz = await n.render({
34428
+ * element: el,
34429
+ * id: 'abcdef'
34430
+ * });
34431
+ * viz.on("trigger", ()=> {
34432
+ * // do something
34433
+ * })
34434
+ */
34435
+ function useEmitter() {
34436
+ return useInternalContext('emitter');
34437
+ }
34438
+
33959
34439
  /**
33960
34440
  * @experimental
33961
34441
  * @interface Keyboard
@@ -34137,6 +34617,7 @@
34137
34617
  nebbie: opts.nebbie,
34138
34618
  element: undefined,
34139
34619
  // set on mount
34620
+ emitter: opts.emitter,
34140
34621
  // ---- singletons ----
34141
34622
  deviceType: galaxy.deviceType,
34142
34623
  theme: undefined,
@@ -37340,6 +37821,7 @@
37340
37821
  exports.useEffect = useEffect;
37341
37822
  exports.useElement = useElement;
37342
37823
  exports.useEmbed = useEmbed;
37824
+ exports.useEmitter = useEmitter;
37343
37825
  exports.useGlobal = useGlobal;
37344
37826
  exports.useImperativeHandle = useImperativeHandle;
37345
37827
  exports.useKeyboard = useKeyboard;