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

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,5 +1,5 @@
1
1
  /*
2
- * @nebula.js/stardust v4.0.0-alpha.4
2
+ * @nebula.js/stardust v4.0.0-alpha.6
3
3
  * Copyright (c) 2023 QlikTech International AB
4
4
  * Released under the MIT license.
5
5
  */
@@ -1496,7 +1496,7 @@ var Selection_SelectPossible = {
1496
1496
  var SelectionToolbar_ClickToUnlock = {
1497
1497
  id: "SelectionToolbar.ClickToUnlock",
1498
1498
  locale: {
1499
- "de-DE": "Klicken zum Freigeben",
1499
+ "de-DE": "Zum Entsperren klicken",
1500
1500
  "en-US": "Click to unlock",
1501
1501
  "es-ES": "Haga clic para desbloquearla",
1502
1502
  "fr-FR": "Cliquez pour déverrouiller",
@@ -8064,7 +8064,7 @@ function create$3(definition) {
8064
8064
  return cache[key];
8065
8065
  }
8066
8066
 
8067
- const NEBULA_VERSION_HASH = "0bc0" ;
8067
+ const NEBULA_VERSION_HASH = "9917" ;
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.4" );
8275
+ element.setAttribute('data-nebulajs-version', "4.0.0-alpha.6" );
8276
8276
  element.setAttribute('data-app-id', app.id);
8277
8277
  document.body.appendChild(element);
8278
8278
  const root = client.createRoot(element);
@@ -9071,7 +9071,7 @@ function fillRange(elementNbrs, elemNumbersOrdered) {
9071
9071
  return elemNumbersOrdered.slice(min, max + 1);
9072
9072
  }
9073
9073
 
9074
- const getKeyAsToggleSelected = event => !(event.metaKey || event.ctrlKey);
9074
+ const getKeyAsToggleSelected = event => !(event !== null && event !== void 0 && event.metaKey || event !== null && event !== void 0 && event.ctrlKey);
9075
9075
  function useSelectionsInteractions(_ref) {
9076
9076
  let {
9077
9077
  selectionState,
@@ -9112,6 +9112,11 @@ function useSelectionsInteractions(_ref) {
9112
9112
  const selectManually = function () {
9113
9113
  let elementIds = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
9114
9114
  let additive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
9115
+ let event = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
9116
+ const toggle = !selectionState.isSingleSelect && getKeyAsToggleSelected(event === null || event === void 0 ? void 0 : event.nativeEvent);
9117
+ if (!toggle) {
9118
+ selectionState.clearItemStates(true);
9119
+ }
9115
9120
  const elemNumbers = [];
9116
9121
  selectionState.updateItems(elementIds, additive, elemNumbers);
9117
9122
  selectionState.setSelectableValuesUpdating();
@@ -9119,7 +9124,7 @@ function useSelectionsInteractions(_ref) {
9119
9124
  selections,
9120
9125
  elemNumbers: additive ? elemNumbers : elementIds,
9121
9126
  isSingleSelect: selectionState.isSingleSelect,
9122
- toggle: !selectionState.isSingleSelect
9127
+ toggle
9123
9128
  });
9124
9129
  };
9125
9130
  const handleSingleSelectKey = (event, target) => {
@@ -9376,7 +9381,7 @@ function getFieldKeyboardNavigation(_ref) {
9376
9381
  setStartedRange(true);
9377
9382
  break;
9378
9383
  case KEYS.SPACE:
9379
- select([+event.currentTarget.getAttribute('data-n')]);
9384
+ select([+event.currentTarget.getAttribute('data-n')], false, event);
9380
9385
  break;
9381
9386
  case KEYS.ARROW_DOWN:
9382
9387
  case KEYS.ARROW_RIGHT:
@@ -9641,6 +9646,16 @@ const getValueStateClasses = _ref2 => {
9641
9646
  return clazzArr;
9642
9647
  };
9643
9648
 
9649
+ const CELL_PADDING_LEFT = 9;
9650
+ const ICON_WIDTH = 12;
9651
+ const ICON_PADDING = 7;
9652
+ const BUTTON_ICON_WIDTH = ICON_WIDTH + (ICON_PADDING + 1) * 2; // 1 is border width
9653
+ const REMOVE_TICK_LIMIT = 80; // an item width equal to or less than this, will hide the select tick
9654
+ const SCROLL_BAR_WIDTH = 10; // TODO: ignore this - instead set the styling only show on hover...
9655
+ const ITEM_MAX_WIDTH = 150;
9656
+ const FREQUENCY_WIDTH = 40;
9657
+ const ITEM_MIN_WIDTH = 56;
9658
+ const CHECKBOX_WIDTH = 20;
9644
9659
  const frequencyTextNone = '-';
9645
9660
  const barPadPx = 4;
9646
9661
  const barBorderWidthPx = 1;
@@ -9660,11 +9675,6 @@ const getBarWidth = _ref => {
9660
9675
  };
9661
9676
  const getFrequencyText = qFrequency => qFrequency || frequencyTextNone;
9662
9677
 
9663
- const CELL_PADDING_LEFT = 9;
9664
- const ICON_WIDTH = 12;
9665
- const ICON_PADDING = 7;
9666
- const BUTTON_ICON_WIDTH = ICON_WIDTH + (ICON_PADDING + 1) * 2; // 1 is border width
9667
-
9668
9678
  const getSelectedStyle = _ref => {
9669
9679
  let {
9670
9680
  theme
@@ -9690,7 +9700,7 @@ const ellipsis = {
9690
9700
  const iconWidth = 24; // tick and lock icon width in px
9691
9701
 
9692
9702
  const RowColRoot = styled$1('div', {
9693
- shouldForwardProp: prop => !['flexBasisProp', 'isGridMode', 'isGridCol', 'dense', 'frequencyWidth', 'showIcon', 'checkboxes'].includes(prop)
9703
+ shouldForwardProp: prop => !['flexBasisProp', 'isGridMode', 'isGridCol', 'dense', 'frequencyWidth'].includes(prop)
9694
9704
  })(_ref2 => {
9695
9705
  var _theme$listBox$conten, _theme$listBox, _theme$listBox$conten2, _theme$listBox$conten3, _theme$listBox2, _theme$listBox2$conte, _theme$listBox3, _theme$listBox3$conte, _theme$listBox4, _theme$listBox4$conte;
9696
9706
  let {
@@ -9699,9 +9709,7 @@ const RowColRoot = styled$1('div', {
9699
9709
  isGridMode,
9700
9710
  isGridCol,
9701
9711
  dense,
9702
- frequencyWidth,
9703
- showIcon,
9704
- checkboxes
9712
+ frequencyWidth
9705
9713
  } = _ref2;
9706
9714
  return {
9707
9715
  '&:focus': {
@@ -9746,7 +9754,7 @@ const RowColRoot = styled$1('div', {
9746
9754
  flexBasis: flexBasisProp,
9747
9755
  lineHeight: '16px',
9748
9756
  userSelect: 'none',
9749
- paddingRight: showIcon || checkboxes ? '1px' : "".concat(iconWidth, "px")
9757
+ paddingRight: '1px'
9750
9758
  }, ellipsis), {}, {
9751
9759
  whiteSpace: 'pre',
9752
9760
  // to keep white-space on highlight
@@ -9756,15 +9764,10 @@ const RowColRoot = styled$1('div', {
9756
9764
  ["& .".concat(rowColClasses.labelDense)]: {
9757
9765
  fontSize: 12
9758
9766
  },
9759
- // Highlight is added to labelText spans, which are created as siblings to original labelText,
9767
+ // Highlight is added to labelText spans, which are created as children to original labelText,
9760
9768
  // when a search string is matched.
9761
9769
  ["& .".concat(rowColClasses.highlighted)]: {
9762
- overflow: 'visible',
9763
- width: '100%',
9764
- '& > span': {
9765
- width: '100%',
9766
- backgroundColor: '#FFC72A'
9767
- }
9770
+ backgroundColor: '#FFC72A'
9768
9771
  },
9769
9772
  // Checkbox and label container.
9770
9773
  ["& .".concat(rowColClasses.checkboxLabel)]: {
@@ -9818,7 +9821,7 @@ const RowColRoot = styled$1('div', {
9818
9821
  ["& .".concat(rowColClasses.frequencyCount)]: _objectSpread2(_objectSpread2({
9819
9822
  justifyContent: 'flex-end'
9820
9823
  }, ellipsis), {}, {
9821
- flex: "0 1 ".concat(frequencyWidth + (showIcon || checkboxes ? 0 : iconWidth), "px"),
9824
+ flex: "0 1 ".concat(frequencyWidth, "px"),
9822
9825
  textAlign: 'right',
9823
9826
  paddingLeft: '2px'
9824
9827
  }),
@@ -10018,7 +10021,6 @@ function ValueField(_ref) {
10018
10021
  let {
10019
10022
  label,
10020
10023
  color,
10021
- highlighted = false,
10022
10024
  dense,
10023
10025
  showGray = true,
10024
10026
  checkboxes,
@@ -10028,14 +10030,14 @@ function ValueField(_ref) {
10028
10030
  return /*#__PURE__*/React__default.createElement(Typography, {
10029
10031
  component: "span",
10030
10032
  variant: "body2",
10031
- className: joinClassNames([rowColClasses.labelText, highlighted && rowColClasses.highlighted, dense && rowColClasses.labelDense, showGray && excludedOrAlternative({
10033
+ className: joinClassNames([rowColClasses.labelText, dense && rowColClasses.labelDense, showGray && excludedOrAlternative({
10032
10034
  cell,
10033
10035
  checkboxes
10034
10036
  }) && rowColClasses.excludedTextWithCheckbox]),
10035
10037
  color: color,
10036
- align: valueTextAlign
10038
+ align: valueTextAlign,
10039
+ dir: "auto"
10037
10040
  }, /*#__PURE__*/React__default.createElement("span", {
10038
- dir: "auto",
10039
10041
  style: {
10040
10042
  whiteSpace: 'pre'
10041
10043
  }
@@ -10046,7 +10048,6 @@ function LabelTag(_ref) {
10046
10048
  let {
10047
10049
  label,
10048
10050
  color,
10049
- highlighted,
10050
10051
  dense,
10051
10052
  showGray,
10052
10053
  checkboxes,
@@ -10057,7 +10058,6 @@ function LabelTag(_ref) {
10057
10058
  return /*#__PURE__*/React__default.createElement(ValueField, {
10058
10059
  label: label,
10059
10060
  color: color,
10060
- highlighted: highlighted,
10061
10061
  dense: dense,
10062
10062
  showGray: showGray,
10063
10063
  checkboxes: checkboxes,
@@ -10080,7 +10080,6 @@ function CheckboxField(_ref) {
10080
10080
  isGridCol,
10081
10081
  showGray,
10082
10082
  isSingleSelect,
10083
- highlighted,
10084
10083
  checkboxes,
10085
10084
  valueTextAlign
10086
10085
  } = _ref;
@@ -10108,7 +10107,6 @@ function CheckboxField(_ref) {
10108
10107
  label: /*#__PURE__*/React__default.createElement(LabelTag, {
10109
10108
  label: label,
10110
10109
  color: color,
10111
- highlighted: highlighted,
10112
10110
  dense: dense,
10113
10111
  showGray: showGray,
10114
10112
  checkboxes: checkboxes,
@@ -10126,18 +10124,19 @@ function LabelsWithRanges(_ref) {
10126
10124
  showGray,
10127
10125
  checkboxes
10128
10126
  } = _ref;
10129
- return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, labels.map((_ref2, index) => {
10127
+ const text = labels.map((_ref2, index) => {
10130
10128
  let [label, highlighted] = _ref2;
10131
- const key = "".concat(index);
10132
- return /*#__PURE__*/React__default.createElement(ValueField, {
10133
- label: label,
10134
- key: key,
10135
- highlighted: highlighted,
10136
- dense: dense,
10137
- showGray: showGray,
10138
- checkboxes: checkboxes
10139
- });
10140
- }));
10129
+ return /*#__PURE__*/React__default.createElement("span", {
10130
+ id: index,
10131
+ className: highlighted ? rowColClasses.highlighted : ''
10132
+ }, label);
10133
+ });
10134
+ return /*#__PURE__*/React__default.createElement(ValueField, {
10135
+ label: text,
10136
+ dense: dense,
10137
+ showGray: showGray,
10138
+ checkboxes: checkboxes
10139
+ });
10141
10140
  }
10142
10141
  function FieldWithRanges(_ref3) {
10143
10142
  let {
@@ -10188,7 +10187,6 @@ function Field(_ref) {
10188
10187
  isGridCol,
10189
10188
  showGray,
10190
10189
  isSingleSelect,
10191
- highlighted,
10192
10190
  checkboxes,
10193
10191
  valueTextAlign
10194
10192
  } = _ref;
@@ -10203,13 +10201,11 @@ function Field(_ref) {
10203
10201
  isGridCol: isGridCol,
10204
10202
  showGray: showGray,
10205
10203
  isSingleSelect: isSingleSelect,
10206
- highlighted: highlighted,
10207
10204
  checkboxes: checkboxes,
10208
10205
  valueTextAlign: valueTextAlign
10209
10206
  }) : /*#__PURE__*/React__default.createElement(ValueField, {
10210
10207
  label: label,
10211
10208
  color: color,
10212
- highlighted: false,
10213
10209
  dense: dense,
10214
10210
  showGray: true,
10215
10211
  checkboxes: checkboxes,
@@ -10309,7 +10305,7 @@ const ItemGrid = styled$1(Grid, {
10309
10305
  dataLayout,
10310
10306
  layoutOrder,
10311
10307
  itemPadding,
10312
- checkboxes
10308
+ cellPaddingRight
10313
10309
  } = _ref;
10314
10310
  return {
10315
10311
  ["&.".concat(rowColClasses.fieldRoot)]: _objectSpread2(_objectSpread2({}, getGridItemSizes({
@@ -10317,7 +10313,7 @@ const ItemGrid = styled$1(Grid, {
10317
10313
  layoutOrder,
10318
10314
  itemPadding
10319
10315
  })), {}, {
10320
- paddingRight: checkboxes ? '8px' : undefined
10316
+ paddingRight: cellPaddingRight ? '8px' : undefined
10321
10317
  })
10322
10318
  };
10323
10319
  });
@@ -10367,7 +10363,7 @@ function RowColumn(_ref) {
10367
10363
  histogram = false,
10368
10364
  keyboard,
10369
10365
  showGray = true,
10370
- showTick: sizePermitsTick = true,
10366
+ showTick: sizePermitsTickOrLock = true,
10371
10367
  columnCount = 1,
10372
10368
  rowCount = 1,
10373
10369
  dataOffset,
@@ -10463,7 +10459,6 @@ function RowColumn(_ref) {
10463
10459
  }
10464
10460
  const isGridCol = dataLayout === 'grid' && layoutOrder === 'column';
10465
10461
  const label = (_cell$qText = cell === null || cell === void 0 ? void 0 : cell.qText) !== null && _cell$qText !== void 0 ? _cell$qText : '';
10466
-
10467
10462
  // Search highlights. Split up labelText span into several and add the highlighted class to matching sub-strings.
10468
10463
 
10469
10464
  let labels;
@@ -10488,23 +10483,23 @@ function RowColumn(_ref) {
10488
10483
  const isFirstElement = index === 0;
10489
10484
  const flexBasisVal = checkboxes ? 'auto' : 'max-content';
10490
10485
  const showLock = isSelected && isLocked;
10491
- const showTick = !checkboxes && isSelected && !isLocked && sizePermitsTick;
10492
- const showIcon = !checkboxes && (showTick || showLock);
10486
+ const showTick = !checkboxes && isSelected && !isLocked;
10487
+ const showIcon = !checkboxes && sizePermitsTickOrLock;
10488
+ const cellPaddingRight = checkboxes || !sizePermitsTickOrLock;
10493
10489
  return /*#__PURE__*/React__default.createElement(RowColRoot$1, {
10494
10490
  className: rowColClasses.barContainer,
10495
10491
  flexBasisProp: flexBasisVal,
10496
10492
  style: styles,
10497
- showIcon: showIcon,
10498
- checkboxes: checkboxes,
10499
10493
  isGridCol: isGridCol,
10500
10494
  isGridMode: dataLayout === 'grid',
10501
10495
  dense: dense,
10502
- frequencyWidth: frequencyWidth
10496
+ frequencyWidth: frequencyWidth,
10497
+ "data-testid": "listbox.item"
10503
10498
  }, /*#__PURE__*/React__default.createElement(ItemGrid, {
10504
10499
  ref: rowRef,
10505
10500
  container: true,
10506
10501
  dataLayout: dataLayout,
10507
- checkboxes: checkboxes,
10502
+ cellPaddingRight: cellPaddingRight,
10508
10503
  layoutOrder: layoutOrder,
10509
10504
  itemPadding: itemPadding,
10510
10505
  gap: 0,
@@ -12101,8 +12096,6 @@ function handleSetOverflowDisclaimer(_ref) {
12101
12096
  overflowDisclaimer.set(show);
12102
12097
  }
12103
12098
 
12104
- const REMOVE_TICK_LIMIT = 80; // an item width equal to or less than this, will hide the select tick
12105
-
12106
12099
  const {
12107
12100
  StyledFixedSizeList,
12108
12101
  StyledFixedSizeGrid
@@ -12331,12 +12324,6 @@ function calculateColumnMode(_ref) {
12331
12324
  };
12332
12325
  }
12333
12326
 
12334
- const SCROLL_BAR_WIDTH = 10; // TODO: ignore this - instead set the styling only show on hover...
12335
- const ITEM_MAX_WIDTH = 150;
12336
- const FREQUENCY_WIDTH = 40;
12337
- const ITEM_MIN_WIDTH = 56;
12338
- const CHECKBOX_WIDTH = 20;
12339
-
12340
12327
  function calculateRowMode(_ref) {
12341
12328
  let {
12342
12329
  maxVisibleColumns,
@@ -12348,7 +12335,7 @@ function calculateRowMode(_ref) {
12348
12335
  const maxColumns = (maxVisibleColumns === null || maxVisibleColumns === void 0 ? void 0 : maxVisibleColumns.maxColumns) || 3;
12349
12336
  const innerWidth = containerWidth - SCROLL_BAR_WIDTH;
12350
12337
  let columnCount;
12351
- const autoColumnCount = Math.min(listCount, Math.ceil(innerWidth / Math.max(itemMinWidth, columnAutoWidth))); // TODO: smarter sizing... based on glyph count + font size etc...??
12338
+ const autoColumnCount = Math.min(listCount, Math.max(1, Math.round(innerWidth / Math.max(itemMinWidth, columnAutoWidth)))); // TODO: smarter sizing... based on glyph count + font size etc...??
12352
12339
  if ((maxVisibleColumns === null || maxVisibleColumns === void 0 ? void 0 : maxVisibleColumns.auto) !== false) {
12353
12340
  columnCount = autoColumnCount;
12354
12341
  } else {
@@ -12386,8 +12373,16 @@ function getListSizes(_ref) {
12386
12373
  } = layoutOptions;
12387
12374
  const frequencyAddWidth = freqIsAllowed ? FREQUENCY_WIDTH : 0;
12388
12375
  const checkboxAddWidth = checkboxes ? CHECKBOX_WIDTH : 0;
12389
- const dynamicItemMinWidth = ITEM_MIN_WIDTH + frequencyAddWidth + checkboxAddWidth;
12390
- const columnAutoWidth = Math.max(Math.min(ITEM_MAX_WIDTH, textWidth + 18 + frequencyAddWidth + checkboxAddWidth), dynamicItemMinWidth);
12376
+ const tickIconWidth = CHECKBOX_WIDTH;
12377
+ let dynamicItemMinWidth = ITEM_MIN_WIDTH + frequencyAddWidth + checkboxAddWidth;
12378
+ if (!checkboxes && dynamicItemMinWidth >= REMOVE_TICK_LIMIT) {
12379
+ dynamicItemMinWidth += tickIconWidth;
12380
+ }
12381
+ let columnAutoWidth = textWidth + 18 + frequencyAddWidth + checkboxAddWidth;
12382
+ if (!checkboxes && columnAutoWidth >= REMOVE_TICK_LIMIT) {
12383
+ columnAutoWidth += tickIconWidth;
12384
+ }
12385
+ columnAutoWidth = Math.min(ITEM_MAX_WIDTH, Math.max(columnAutoWidth, dynamicItemMinWidth));
12391
12386
  let overflowStyling;
12392
12387
  let columnCount;
12393
12388
  let columnWidth;
@@ -13107,7 +13102,7 @@ function ListBox(_ref) {
13107
13102
  });
13108
13103
  if (itemsLoader.pages.length && !awaitingFrequencyMax) {
13109
13104
  // All necessary data fetching done - signal rendering done!
13110
- renderedCallback();
13105
+ renderedCallback === null || renderedCallback === void 0 ? void 0 : renderedCallback();
13111
13106
  }
13112
13107
  }
13113
13108
  const isItemLoaded = useCallback(index => {
@@ -13497,7 +13492,8 @@ const Item = React__default.forwardRef((_ref, ref) => {
13497
13492
  size: "large",
13498
13493
  disableRipple: true,
13499
13494
  "aria-expanded": ariaExpanded,
13500
- "aria-controls": "moreMenuList"
13495
+ "aria-controls": "moreMenuList",
13496
+ "data-testid": "actions-toolbar-".concat(item.key)
13501
13497
  }, hasSvgIconShape && SvgIcon$2(item.getSvgIconShape()), addAnchor && /*#__PURE__*/React__default.createElement("div", {
13502
13498
  ref: ref,
13503
13499
  style: {
@@ -16008,6 +16004,23 @@ function getListboxActionProps(_ref) {
16008
16004
  };
16009
16005
  }
16010
16006
 
16007
+ function ListBoxError(_ref) {
16008
+ let {
16009
+ text
16010
+ } = _ref;
16011
+ const {
16012
+ translator
16013
+ } = 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
+ return /*#__PURE__*/React__default.createElement(StyledDiv, null, translator.get(text));
16022
+ }
16023
+
16011
16024
  const PREFIX$4 = 'ListBoxInline';
16012
16025
  const classes$4 = {
16013
16026
  listBoxHeader: "".concat(PREFIX$4, "-listBoxHeader"),
@@ -16082,9 +16095,7 @@ function ListBoxInline(_ref3) {
16082
16095
  calculatePagesHeight,
16083
16096
  showGray = true,
16084
16097
  scrollState = undefined,
16085
- renderedCallback
16086
- } = options;
16087
- let {
16098
+ renderedCallback,
16088
16099
  toolbar = true
16089
16100
  } = options;
16090
16101
 
@@ -16129,6 +16140,8 @@ function ListBoxInline(_ref3) {
16129
16140
  const [appSelections] = useAppSelections(app);
16130
16141
  const titleRef = useRef(null);
16131
16142
  const [selectionState$1] = useState$1(() => selectionState());
16143
+ const isInvalid = layout === null || layout === void 0 ? void 0 : layout.qListObject.qDimensionInfo.qError;
16144
+ const errorText = isInvalid && constraints.active ? 'Visualization.Invalid.Dimension' : 'Visualization.Incomplete';
16132
16145
  const {
16133
16146
  handleKeyDown,
16134
16147
  handleOnMouseEnter,
@@ -16151,11 +16164,8 @@ function ListBoxInline(_ref3) {
16151
16164
  // this will be static until we can access the useKeyboard hook
16152
16165
  active: keyboardActive
16153
16166
  };
16154
- if ((layout === null || layout === void 0 ? void 0 : layout.toolbar) !== undefined) {
16155
- toolbar = layout.toolbar;
16156
- }
16157
- const toolbarDetachedOnly = toolbar && (layout === null || layout === void 0 ? void 0 : layout.title) === '';
16158
- toolbar = toolbar && (layout === null || layout === void 0 ? void 0 : layout.title) !== '';
16167
+ const showDetachedToolbarOnly = toolbar && ((layout === null || layout === void 0 ? void 0 : layout.title) === '' || (layout === null || layout === void 0 ? void 0 : layout.showTitle) === false);
16168
+ const showToolbarWithTitle = toolbar && (layout === null || layout === void 0 ? void 0 : layout.title) !== '' && (layout === null || layout === void 0 ? void 0 : layout.showTitle) !== false;
16159
16169
  useEffect$1(() => {
16160
16170
  const show = () => {
16161
16171
  setShowToolbar(true);
@@ -16179,7 +16189,7 @@ function ListBoxInline(_ref3) {
16179
16189
  selections.removeListener('deactivated', hide);
16180
16190
  }
16181
16191
  };
16182
- }, [selections, toolbar]);
16192
+ }, [selections]);
16183
16193
  useEffect$1(() => {
16184
16194
  if (!searchContainer || !searchContainer.current) {
16185
16195
  return;
@@ -16213,7 +16223,7 @@ function ListBoxInline(_ref3) {
16213
16223
  const searchHeight = dense ? 27 : 40;
16214
16224
  const extraheight = dense ? 39 : 49;
16215
16225
  const searchAddHeight = searchVisible ? searchHeight : 0;
16216
- const minHeight = toolbar ? 49 + searchAddHeight + extraheight : 0;
16226
+ const minHeight = showToolbarWithTitle ? 49 + searchAddHeight + extraheight : 0;
16217
16227
  const headerHeight = 32;
16218
16228
  const onShowSearch = () => {
16219
16229
  const newValue = !showSearch;
@@ -16236,7 +16246,7 @@ function ListBoxInline(_ref3) {
16236
16246
  selections
16237
16247
  });
16238
16248
  const shouldAutoFocus = searchVisible && search === 'toggle';
16239
- const showSearchIcon = searchEnabled !== false && search === 'toggle' && !(constraints !== null && constraints !== void 0 && constraints.active);
16249
+ const showSearchIcon = searchEnabled !== false && search === 'toggle';
16240
16250
  const showSearchOrLockIcon = isLocked || showSearchIcon;
16241
16251
  const showIcons = showSearchOrLockIcon || isDrillDown;
16242
16252
  const iconsWidth = (showSearchOrLockIcon ? BUTTON_ICON_WIDTH : 0) + (isDrillDown ? ICON_WIDTH + ICON_PADDING : 0); // Drill-down icon needs padding right so there is space between the icon and the title
@@ -16249,7 +16259,43 @@ function ListBoxInline(_ref3) {
16249
16259
  if (isGridMode) {
16250
16260
  containerPadding = layoutOptions.layoutOrder === 'row' ? '2px 4px' : '2px 6px 2px 4px';
16251
16261
  }
16252
- return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, toolbarDetachedOnly && /*#__PURE__*/React__default.createElement(ActionsToolbar, _extends$6({
16262
+ const searchIconComp = constraints !== null && constraints !== void 0 && constraints.active ? /*#__PURE__*/React__default.createElement(SearchIcon, {
16263
+ title: translator.get('Listbox.Search'),
16264
+ size: "large",
16265
+ style: {
16266
+ fontSize: '12px',
16267
+ padding: '7px'
16268
+ }
16269
+ }) : /*#__PURE__*/React__default.createElement(IconButton, {
16270
+ onClick: onShowSearch,
16271
+ tabIndex: -1,
16272
+ title: translator.get('Listbox.Search'),
16273
+ size: "large",
16274
+ disableRipple: true,
16275
+ "data-testid": "search-toggle-btn"
16276
+ }, /*#__PURE__*/React__default.createElement(SearchIcon, {
16277
+ style: {
16278
+ fontSize: '12px'
16279
+ }
16280
+ }));
16281
+ const lockIconComp = selectDisabled() ? /*#__PURE__*/React__default.createElement(Lock, {
16282
+ size: "large",
16283
+ style: {
16284
+ fontSize: '12px',
16285
+ padding: '7px'
16286
+ }
16287
+ }) : /*#__PURE__*/React__default.createElement(IconButton, {
16288
+ title: translator.get('SelectionToolbar.ClickToUnlock'),
16289
+ tabIndex: -1,
16290
+ onClick: unlock,
16291
+ size: "large"
16292
+ }, /*#__PURE__*/React__default.createElement(Lock, {
16293
+ disableRipple: true,
16294
+ style: {
16295
+ fontSize: '12px'
16296
+ }
16297
+ }));
16298
+ return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, showDetachedToolbarOnly && /*#__PURE__*/React__default.createElement(ActionsToolbar, _extends$6({
16253
16299
  direction: direction
16254
16300
  }, getActionToolbarProps(true))), /*#__PURE__*/React__default.createElement(StyledGrid$3, {
16255
16301
  className: "listbox-container",
@@ -16268,7 +16314,7 @@ function ListBoxInline(_ref3) {
16268
16314
  onMouseLeave: handleOnMouseLeave,
16269
16315
  ref: containerRef,
16270
16316
  hasIcon: showIcons
16271
- }, toolbar && /*#__PURE__*/React__default.createElement(Grid, {
16317
+ }, showToolbarWithTitle && /*#__PURE__*/React__default.createElement(Grid, {
16272
16318
  item: true,
16273
16319
  container: true,
16274
16320
  style: {
@@ -16295,29 +16341,7 @@ function ListBoxInline(_ref3) {
16295
16341
  alignItems: 'center',
16296
16342
  width: iconsWidth
16297
16343
  }
16298
- }, isLocked ? /*#__PURE__*/React__default.createElement(IconButton, {
16299
- title: translator.get('SelectionToolbar.ClickToUnlock'),
16300
- tabIndex: -1,
16301
- onClick: unlock,
16302
- disabled: selectDisabled(),
16303
- size: "large"
16304
- }, /*#__PURE__*/React__default.createElement(Lock, {
16305
- disableRipple: true,
16306
- style: {
16307
- fontSize: '12px'
16308
- }
16309
- })) : showSearchIcon && /*#__PURE__*/React__default.createElement(IconButton, {
16310
- onClick: onShowSearch,
16311
- tabIndex: -1,
16312
- title: translator.get('Listbox.Search'),
16313
- size: "large",
16314
- disableRipple: true,
16315
- "data-testid": "search-toggle-btn"
16316
- }, /*#__PURE__*/React__default.createElement(SearchIcon, {
16317
- style: {
16318
- fontSize: '12px'
16319
- }
16320
- })), isDrillDown && /*#__PURE__*/React__default.createElement(DrillDownIcon, {
16344
+ }, isLocked ? lockIconComp : showSearchIcon && searchIconComp, isDrillDown && /*#__PURE__*/React__default.createElement(DrillDownIcon, {
16321
16345
  tabIndex: -1,
16322
16346
  title: translator.get('Listbox.DrillDown'),
16323
16347
  size: "large",
@@ -16380,7 +16404,9 @@ function ListBoxInline(_ref3) {
16380
16404
  className: classes$4.listboxWrapper
16381
16405
  }, /*#__PURE__*/React__default.createElement("div", {
16382
16406
  className: classes$4.screenReaderOnly
16383
- }, translator.get('Listbox.ScreenReaderInstructions')), /*#__PURE__*/React__default.createElement(AutoSizer, null, _ref4 => {
16407
+ }, translator.get('Listbox.ScreenReaderInstructions')), isInvalid ? /*#__PURE__*/React__default.createElement(ListBoxError, {
16408
+ text: errorText
16409
+ }) : /*#__PURE__*/React__default.createElement(AutoSizer, null, _ref4 => {
16384
16410
  let {
16385
16411
  height,
16386
16412
  width
@@ -16829,7 +16855,7 @@ function removeIndex(array, index) {
16829
16855
  array.splice(removeIdx, 1);
16830
16856
  return removeIdx;
16831
16857
  }
16832
- const nxDimension = f => ({
16858
+ const nxDimension$1 = f => ({
16833
16859
  qDef: {
16834
16860
  qFieldDefs: [f]
16835
16861
  }
@@ -16860,7 +16886,7 @@ function hcHandler(_ref) {
16860
16886
  return hc.qMeasures;
16861
16887
  },
16862
16888
  addDimension(d) {
16863
- const dimension = typeof d === 'string' ? nxDimension(d) : _objectSpread2(_objectSpread2({}, d), {}, {
16889
+ const dimension = typeof d === 'string' ? nxDimension$1(d) : _objectSpread2(_objectSpread2({}, d), {}, {
16864
16890
  qDef: d.qDef || {}
16865
16891
  });
16866
16892
  dimension.qDef.cId = dimension.qDef.cId || uid();
@@ -16943,6 +16969,69 @@ function hcHandler(_ref) {
16943
16969
  return handler;
16944
16970
  }
16945
16971
 
16972
+ const nxDimension = f => ({
16973
+ qDef: {
16974
+ qFieldDefs: [f]
16975
+ }
16976
+ });
16977
+ function loHandler(_ref) {
16978
+ let {
16979
+ dc: lo,
16980
+ def,
16981
+ properties
16982
+ } = _ref;
16983
+ lo.qInitialDataFetch = lo.qInitialDataFetch || [];
16984
+ const objectProperties = properties;
16985
+ const handler = {
16986
+ dimensions() {
16987
+ if (!lo.qLibraryId && (!lo.qDef || !lo.qDef.qFieldDefs || lo.qDef.qFieldDefs.length === 0)) return [];
16988
+ return [lo];
16989
+ },
16990
+ measures() {
16991
+ return [];
16992
+ },
16993
+ addDimension(d) {
16994
+ const dimension = typeof d === 'string' ? nxDimension(d) : _objectSpread2(_objectSpread2({}, d), {}, {
16995
+ qDef: d.qDef || {}
16996
+ });
16997
+ dimension.qDef.cId = dimension.qDef.cId || uid();
16998
+ dimension.qDef.qSortCriterias = lo.qDef.qSortCriterias || [{
16999
+ qSortByState: 1,
17000
+ qSortByLoadOrder: 1,
17001
+ qSortByNumeric: 1,
17002
+ qSortByAscii: 1
17003
+ }];
17004
+ Object.keys(dimension).forEach(k => {
17005
+ lo[k] = dimension[k];
17006
+ });
17007
+ def.dimensions.added(dimension, objectProperties);
17008
+ return dimension;
17009
+ },
17010
+ removeDimension(idx) {
17011
+ const dimension = lo;
17012
+ delete lo.qDef;
17013
+ delete lo.qLibraryId;
17014
+ def.dimensions.removed(dimension, objectProperties, idx);
17015
+ return dimension;
17016
+ },
17017
+ addMeasure() {},
17018
+ removeMeasure() {},
17019
+ maxDimensions() {
17020
+ return 1;
17021
+ },
17022
+ maxMeasures() {
17023
+ return 0;
17024
+ },
17025
+ canAddDimension() {
17026
+ return handler.dimensions().length === 0;
17027
+ },
17028
+ canAddMeasure() {
17029
+ return false;
17030
+ }
17031
+ };
17032
+ return handler;
17033
+ }
17034
+
16946
17035
  /**
16947
17036
  * @interface LibraryField
16948
17037
  * @property {string} qLibraryId
@@ -16987,7 +17076,8 @@ function populateData(_ref) {
16987
17076
  const s = parts[i];
16988
17077
  p = s ? p[s] : p;
16989
17078
  }
16990
- const hc = hcHandler({
17079
+ const createHandler = propertyPath.match('/qListObjectDef') ? loHandler : hcHandler;
17080
+ const handler = createHandler({
16991
17081
  dc: p,
16992
17082
  def: target,
16993
17083
  properties
@@ -16995,9 +17085,9 @@ function populateData(_ref) {
16995
17085
  fields.forEach(f => {
16996
17086
  const type = fieldType(f);
16997
17087
  if (type === 'measure') {
16998
- hc.addMeasure(f);
17088
+ handler.addMeasure(f);
16999
17089
  } else {
17000
- hc.addDimension(f);
17090
+ handler.addDimension(f);
17001
17091
  }
17002
17092
  });
17003
17093
  }
@@ -18228,7 +18318,8 @@ function Header(_ref2) {
18228
18318
  sn,
18229
18319
  anchorEl,
18230
18320
  hovering,
18231
- focusHandler
18321
+ focusHandler,
18322
+ titleStyles = {}
18232
18323
  } = _ref2;
18233
18324
  const showTitle = layout.showTitles && !!layout.title;
18234
18325
  const showSubtitle = layout.showTitles && !!layout.subtitle;
@@ -18286,11 +18377,13 @@ function Header(_ref2) {
18286
18377
  }, showTitle && /*#__PURE__*/React__default.createElement(Typography, {
18287
18378
  variant: "h6",
18288
18379
  noWrap: true,
18289
- className: CellTitle.className
18380
+ className: CellTitle.className,
18381
+ style: titleStyles.main
18290
18382
  }, layout.title), showSubtitle && /*#__PURE__*/React__default.createElement(Typography, {
18291
18383
  variant: "body2",
18292
18384
  noWrap: true,
18293
- className: CellSubTitle.className
18385
+ className: CellSubTitle.className,
18386
+ style: titleStyles.subTitle
18294
18387
  }, layout.subtitle))), /*#__PURE__*/React__default.createElement(Grid, {
18295
18388
  item: true
18296
18389
  }, Toolbar));
@@ -18323,7 +18416,8 @@ const CellFooter = {
18323
18416
  };
18324
18417
  function Footer(_ref2) {
18325
18418
  let {
18326
- layout
18419
+ layout,
18420
+ titleStyles = {}
18327
18421
  } = _ref2;
18328
18422
  return layout && layout.showTitles && layout.footnote ? /*#__PURE__*/React__default.createElement(StyledGrid, {
18329
18423
  container: true
@@ -18333,7 +18427,8 @@ function Footer(_ref2) {
18333
18427
  }, /*#__PURE__*/React__default.createElement(Typography, {
18334
18428
  noWrap: true,
18335
18429
  variant: "body2",
18336
- className: CellFooter.className
18430
+ className: CellFooter.className,
18431
+ style: titleStyles.footer
18337
18432
  }, layout.footnote))) : null;
18338
18433
  }
18339
18434
 
@@ -18563,7 +18658,7 @@ function getBackgroundSize(bgComp) {
18563
18658
  function resolveImageUrl(app, relativeUrl) {
18564
18659
  return relativeUrl ? getSenseServerUrl(app) + relativeUrl : undefined;
18565
18660
  }
18566
- const resolveBgImage = (bgComp, app) => {
18661
+ function resolveBgImage(bgComp, app) {
18567
18662
  const bgImageDef = bgComp === null || bgComp === void 0 ? void 0 : bgComp.bgImage;
18568
18663
  if (bgImageDef) {
18569
18664
  let url = '';
@@ -18584,8 +18679,8 @@ const resolveBgImage = (bgComp, app) => {
18584
18679
  } : undefined;
18585
18680
  }
18586
18681
  return undefined;
18587
- };
18588
- const resolveBgColor = (bgComp, theme) => {
18682
+ }
18683
+ function resolveBgColor(bgComp, theme, objectType) {
18589
18684
  const bgColor = bgComp === null || bgComp === void 0 ? void 0 : bgComp.bgColor;
18590
18685
  if (bgColor && theme) {
18591
18686
  if (bgColor.useExpression) {
@@ -18593,8 +18688,32 @@ const resolveBgColor = (bgComp, theme) => {
18593
18688
  }
18594
18689
  return bgColor.color && bgColor.color.color !== 'none' ? theme.getColorPickerColor(bgColor.color, true) : undefined;
18595
18690
  }
18691
+ if (theme && objectType) {
18692
+ return theme.getStyle("object.".concat(objectType), '', 'backgroundColor');
18693
+ }
18694
+ if (theme) {
18695
+ return theme.getStyle('', '', 'backgroundColor');
18696
+ }
18596
18697
  return undefined;
18597
- };
18698
+ }
18699
+ function unfurlFontStyle(fontStyle, target) {
18700
+ if (fontStyle && Array.isArray(fontStyle)) {
18701
+ return fontStyle;
18702
+ }
18703
+ return target === 'main' ? ['bold'] : [];
18704
+ }
18705
+ function resolveTextStyle(textComp, target, theme, objectType) {
18706
+ var _textComp$title;
18707
+ const textProps = (textComp === null || textComp === void 0 ? void 0 : (_textComp$title = textComp.title) === null || _textComp$title === void 0 ? void 0 : _textComp$title[target]) || {};
18708
+ const fontStyle = unfurlFontStyle(textProps.fontStyle, target);
18709
+ return {
18710
+ fontFamily: textProps.fontFamily || theme.getStyle("object.".concat(objectType), "title.".concat(target), 'fontFamily'),
18711
+ color: textProps.color && textProps.color.color !== 'none' ? theme.getColorPickerColor(textProps.color, true) : theme.getStyle("object.".concat(objectType), target, 'color'),
18712
+ fontWeight: fontStyle.includes('bold') ? 'bold' : 'normal',
18713
+ fontStyle: fontStyle.includes('italic') ? 'italic' : 'normal',
18714
+ textDecoration: fontStyle.includes('underline') ? 'underline' : 'initial'
18715
+ };
18716
+ }
18598
18717
 
18599
18718
  /**
18600
18719
  * @interface
@@ -18836,7 +18955,8 @@ const loadType = async _ref5 => {
18836
18955
  app,
18837
18956
  selections,
18838
18957
  nebbie,
18839
- focusHandler
18958
+ focusHandler,
18959
+ emitter
18840
18960
  } = _ref5;
18841
18961
  try {
18842
18962
  const snType = await getType({
@@ -18849,16 +18969,26 @@ const loadType = async _ref5 => {
18849
18969
  app,
18850
18970
  selections,
18851
18971
  nebbie,
18852
- focusHandler
18972
+ focusHandler,
18973
+ emitter
18853
18974
  });
18854
18975
  return sn;
18855
18976
  } catch (err) {
18856
- dispatch({
18857
- type: 'ERROR',
18858
- error: {
18859
- title: err.message
18860
- }
18861
- });
18977
+ if (!version) {
18978
+ dispatch({
18979
+ type: 'ERROR',
18980
+ error: {
18981
+ title: "Could not find a version of '".concat(visualization, "' that supports current object version. Did you forget to register ").concat(visualization, "?")
18982
+ }
18983
+ });
18984
+ } else {
18985
+ dispatch({
18986
+ type: 'ERROR',
18987
+ error: {
18988
+ title: err.message
18989
+ }
18990
+ });
18991
+ }
18862
18992
  }
18863
18993
  return undefined;
18864
18994
  };
@@ -18870,7 +19000,8 @@ const Cell = forwardRef((_ref6, ref) => {
18870
19000
  initialSnPlugins,
18871
19001
  initialError,
18872
19002
  onMount,
18873
- currentId
19003
+ currentId,
19004
+ emitter
18874
19005
  } = _ref6;
18875
19006
  const {
18876
19007
  app,
@@ -18909,7 +19040,7 @@ const Cell = forwardRef((_ref6, ref) => {
18909
19040
  });
18910
19041
  const [bgColor, setBgColor] = useState$1(undefined);
18911
19042
  const [bgImage, setBgImage] = useState$1(undefined); // {url: "", size: "", pos: ""}
18912
-
19043
+ const [titleStyles, setTitleStyles] = useState$1(undefined);
18913
19044
  const focusHandler = useRef({
18914
19045
  focusToolbarButton(last) {
18915
19046
  // eslint-disable-next-line react/no-this-in-sfc
@@ -18920,9 +19051,16 @@ const Cell = forwardRef((_ref6, ref) => {
18920
19051
  eventmixin(focusHandler.current);
18921
19052
  }, []);
18922
19053
  useEffect$1(() => {
18923
- const bgComp = layout !== null && layout !== void 0 && layout.components ? layout.components.find(comp => comp.key === 'general') : null;
18924
- setBgColor(resolveBgColor(bgComp, halo.public.theme));
18925
- setBgImage(resolveBgImage(bgComp, halo.app));
19054
+ if (layout && halo.public.theme) {
19055
+ const bgComp = layout.components ? layout.components.find(comp => comp.key === 'general') : null;
19056
+ setTitleStyles({
19057
+ main: resolveTextStyle(bgComp, 'main', halo.public.theme, layout.visualization),
19058
+ footer: resolveTextStyle(bgComp, 'footer', halo.public.theme, layout.visualization),
19059
+ subTitle: resolveTextStyle(bgComp, 'subTitle', halo.public.theme, layout.visualization)
19060
+ });
19061
+ setBgColor(resolveBgColor(bgComp, halo.public.theme, layout.visualization));
19062
+ setBgImage(resolveBgImage(bgComp, halo.app));
19063
+ }
18926
19064
  }, [layout, halo.public.theme, halo.app, themeName]);
18927
19065
  focusHandler.current.blurCallback = resetFocus => {
18928
19066
  halo.root.toggleFocusOfCells();
@@ -18994,7 +19132,8 @@ const Cell = forwardRef((_ref6, ref) => {
18994
19132
  app,
18995
19133
  selections,
18996
19134
  nebbie,
18997
- focusHandler: focusHandler.current
19135
+ focusHandler: focusHandler.current,
19136
+ emitter
18998
19137
  });
18999
19138
  if (sn) {
19000
19139
  dispatch({
@@ -19015,15 +19154,6 @@ const Cell = forwardRef((_ref6, ref) => {
19015
19154
 
19016
19155
  // Load supernova
19017
19156
  const withVersion = types.getSupportedVersion(layout.visualization, layout.version);
19018
- if (!withVersion) {
19019
- dispatch({
19020
- type: 'ERROR',
19021
- error: {
19022
- title: "Could not find a version of '".concat(layout.visualization, "' that supports current object version. Did you forget to register ").concat(layout.visualization, "?")
19023
- }
19024
- });
19025
- return undefined;
19026
- }
19027
19157
  load(layout.visualization, withVersion);
19028
19158
  return () => {};
19029
19159
  }, [types, state.sn, model, selections, layout, appLayout, language]);
@@ -19145,7 +19275,8 @@ const Cell = forwardRef((_ref6, ref) => {
19145
19275
  sn: state.sn,
19146
19276
  anchorEl: cellNode,
19147
19277
  hovering: hovering,
19148
- focusHandler: focusHandler.current
19278
+ focusHandler: focusHandler.current,
19279
+ titleStyles: titleStyles
19149
19280
  }, "\xA0"), /*#__PURE__*/React__default.createElement(Grid, {
19150
19281
  tabIndex: keyboardNavigation ? 0 : -1,
19151
19282
  onKeyDown: keyboardNavigation ? handleKeyDown : null,
@@ -19156,7 +19287,8 @@ const Cell = forwardRef((_ref6, ref) => {
19156
19287
  },
19157
19288
  ref: contentRef
19158
19289
  }, Content), /*#__PURE__*/React__default.createElement(Footer, {
19159
- layout: layout
19290
+ layout: layout,
19291
+ titleStyles: titleStyles
19160
19292
  })), state.longRunningQuery && /*#__PURE__*/React__default.createElement(LongRunningQuery, {
19161
19293
  canCancel: canCancel,
19162
19294
  canRetry: canRetry,
@@ -19172,6 +19304,7 @@ function glue$1(_ref) {
19172
19304
  initialSnOptions,
19173
19305
  initialSnPlugins,
19174
19306
  onMount,
19307
+ emitter,
19175
19308
  initialError
19176
19309
  } = _ref;
19177
19310
  const {
@@ -19187,7 +19320,8 @@ function glue$1(_ref) {
19187
19320
  initialSnOptions: initialSnOptions,
19188
19321
  initialSnPlugins: initialSnPlugins,
19189
19322
  initialError: initialError,
19190
- onMount: onMount
19323
+ onMount: onMount,
19324
+ emitter: emitter
19191
19325
  }), element, currentId);
19192
19326
  const unmount = () => {
19193
19327
  root.remove(portal);
@@ -19287,6 +19421,7 @@ function viz() {
19287
19421
  });
19288
19422
  let initialSnOptions = {};
19289
19423
  let initialSnPlugins = [];
19424
+ const emitter = new nodeEventEmitter();
19290
19425
  const setSnOptions = async opts => {
19291
19426
  if (mountedReference) {
19292
19427
  (async () => {
@@ -19377,6 +19512,24 @@ function viz() {
19377
19512
  }
19378
19513
  return propertyTree;
19379
19514
  },
19515
+ /**
19516
+ * Listens to custom events from inside the visualization. See useEmitter
19517
+ * @experimental
19518
+ * @param {string} eventName Event name to listen to
19519
+ * @param {Function} listener Callback function to invoke
19520
+ */
19521
+ on(eventName, listener) {
19522
+ emitter.on(eventName, listener);
19523
+ },
19524
+ /**
19525
+ * Removes a listener
19526
+ * @experimental
19527
+ * @param {string} eventName Event name to remove from
19528
+ * @param {Function} listener Callback function to remove
19529
+ */
19530
+ off(eventName, listener) {
19531
+ emitter.off(eventName, listener);
19532
+ },
19380
19533
  // ===== unexposed experimental API - use at own risk ======
19381
19534
  __DO_NOT_USE__: {
19382
19535
  mount(element) {
@@ -19391,7 +19544,8 @@ function viz() {
19391
19544
  initialSnOptions,
19392
19545
  initialSnPlugins,
19393
19546
  initialError,
19394
- onMount
19547
+ onMount,
19548
+ emitter
19395
19549
  });
19396
19550
  return mounted;
19397
19551
  },
@@ -21338,7 +21492,7 @@ function onTakeSnapshot(cb) {
21338
21492
  * @ignore
21339
21493
  * @example
21340
21494
  * import { onContextMenu } from '@nebula.js/stardust';
21341
-
21495
+
21342
21496
  * onContextMenu((menu, event) => {
21343
21497
  * menu.addItem(item, index);
21344
21498
  * });
@@ -21392,6 +21546,32 @@ function useRenderState() {
21392
21546
  };
21393
21547
  }
21394
21548
 
21549
+ /**
21550
+ * Gets an event emitter instance for the visualization.
21551
+ * @entry
21552
+ * @experimental
21553
+ * @returns {Emitter} The emitter instance.
21554
+ * @example
21555
+ * // In a Nebula visualization
21556
+ * import { useEmitter } from '@nebula.js/stardust';
21557
+ * useEffect(()=> {
21558
+ * // on some trigger
21559
+ * emitter.emit("trigger", params)
21560
+ * }, [...])
21561
+ *
21562
+ * // In a mashup
21563
+ * const viz = await n.render({
21564
+ * element: el,
21565
+ * id: 'abcdef'
21566
+ * });
21567
+ * viz.on("trigger", ()=> {
21568
+ * // do something
21569
+ * })
21570
+ */
21571
+ function useEmitter() {
21572
+ return useInternalContext('emitter');
21573
+ }
21574
+
21395
21575
  /**
21396
21576
  * @experimental
21397
21577
  * @interface Keyboard
@@ -21573,6 +21753,7 @@ function createWithHooks(generator, opts, galaxy) {
21573
21753
  nebbie: opts.nebbie,
21574
21754
  element: undefined,
21575
21755
  // set on mount
21756
+ emitter: opts.emitter,
21576
21757
  // ---- singletons ----
21577
21758
  deviceType: galaxy.deviceType,
21578
21759
  theme: undefined,
@@ -24762,5 +24943,5 @@ const __DO_NOT_USE__ = {
24762
24943
  locale
24763
24944
  };
24764
24945
 
24765
- export { mocker as EnigmaMocker, __DO_NOT_USE__, conversion, index as embed, onContextMenu, onTakeSnapshot, useAction, useApp, useAppLayout, useConstraints, useDeviceType, useEffect, useElement, useEmbed, useGlobal, useImperativeHandle, useKeyboard, useLayout, useMemo, useModel, useOptions, usePlugins, usePromise, useRect, useRenderState, useSelections, useStaleLayout, useState, useTheme, useTranslator };
24946
+ export { mocker as EnigmaMocker, __DO_NOT_USE__, conversion, index as embed, onContextMenu, onTakeSnapshot, useAction, useApp, useAppLayout, useConstraints, useDeviceType, useEffect, useElement, useEmbed, useEmitter, useGlobal, useImperativeHandle, useKeyboard, useLayout, useMemo, useModel, useOptions, usePlugins, usePromise, useRect, useRenderState, useSelections, useStaleLayout, useState, useTheme, useTranslator };
24766
24947
  //# sourceMappingURL=dev.js.map