@nebula.js/stardust 3.1.0-alpha.2 → 3.1.0-alpha.3

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 v3.1.0-alpha.2
2
+ * @nebula.js/stardust v3.1.0-alpha.3
3
3
  * Copyright (c) 2022 QlikTech International AB
4
4
  * Released under the MIT license.
5
5
  */
@@ -8,7 +8,7 @@ import * as React from 'react';
8
8
  import React__default, { useState as useState$1, useEffect as useEffect$1, useReducer, forwardRef, useMemo as useMemo$1, useImperativeHandle as useImperativeHandle$1, useCallback, useLayoutEffect as useLayoutEffect$1, createElement, PureComponent, useRef, useContext } from 'react';
9
9
  import ReactDOM from 'react-dom';
10
10
  import { CacheProvider, ThemeContext as ThemeContext$2 } from '@emotion/react';
11
- import { Checkbox, Radio, Grid, Typography, FormControlLabel, IconButton, Popover, MenuList, MenuItem, ListItemIcon, Divider, OutlinedInput, InputAdornment, Badge, List, ListItem, Button, Box, Icon, CircularProgress, Paper } from '@mui/material';
11
+ import { Checkbox, Radio, Grid, Typography, FormControlLabel, IconButton, Popover, MenuList, MenuItem, ListItemIcon, Divider, InputAdornment, OutlinedInput, Badge, List, ListItem, Button, Box, Icon, CircularProgress, Paper } from '@mui/material';
12
12
  import emStyled from '@emotion/styled';
13
13
 
14
14
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -2742,7 +2742,9 @@ function theme$1(resolvedTheme) {
2742
2742
  }
2743
2743
  );
2744
2744
  },
2745
- uiColor(c) {
2745
+ uiColor(c, shift) {
2746
+ // eslint-disable-next-line no-param-reassign
2747
+ shift = !!shift;
2746
2748
  if (c.index < 0 || typeof c.index === 'undefined') {
2747
2749
  return c.color;
2748
2750
  }
@@ -2752,10 +2754,10 @@ function theme$1(resolvedTheme) {
2752
2754
  if (!uiPalette) {
2753
2755
  return c.color;
2754
2756
  }
2755
- if (typeof uiPalette.colors[c.index] === 'undefined') {
2757
+ if (typeof uiPalette.colors[c.index - shift] === 'undefined') {
2756
2758
  return c.color;
2757
2759
  }
2758
- return uiPalette.colors[c.index];
2760
+ return uiPalette.colors[c.index - shift];
2759
2761
  }
2760
2762
  };
2761
2763
  }
@@ -2978,7 +2980,7 @@ function constructPaths(pathSteps, baseSteps) {
2978
2980
  }
2979
2981
  return ret;
2980
2982
  }
2981
- function getObject$1(root, steps) {
2983
+ function getObject$2(root, steps) {
2982
2984
  let obj = root;
2983
2985
  for (let i = 0; i < steps.length; i++) {
2984
2986
  if (obj[steps[i]]) {
@@ -2992,7 +2994,7 @@ function getObject$1(root, steps) {
2992
2994
  function searchPathArray(pathArray, attribute, theme) {
2993
2995
  const attributeArray = attribute.split('.');
2994
2996
  for (let i = 0; i < pathArray.length; i++) {
2995
- const restult = getObject$1(theme, [...pathArray[i], ...attributeArray]);
2997
+ const restult = getObject$2(theme, [...pathArray[i], ...attributeArray]);
2996
2998
  if (restult !== undefined) return restult;
2997
2999
  }
2998
3000
  return undefined;
@@ -3161,10 +3163,12 @@ function theme() {
3161
3163
  * @param {object} c
3162
3164
  * @param {number=} c.index
3163
3165
  * @param {string=} c.color
3166
+ * @param {boolean=} supportNone Shifts the palette index by one to account for the "none" color
3164
3167
  * @returns {string} The resolved color.
3165
3168
  *
3166
3169
  * @example
3167
3170
  * theme.getColorPickerColor({ index: 1 });
3171
+ * theme.getColorPickerColor({ index: 1 }, true);
3168
3172
  * theme.getColorPickerColor({ color: 'red' });
3169
3173
  */
3170
3174
  getColorPickerColor() {
@@ -7226,7 +7230,7 @@ function create$3(definition) {
7226
7230
  return cache[key];
7227
7231
  }
7228
7232
 
7229
- const NEBULA_VERSION_HASH = "de86" ;
7233
+ const NEBULA_VERSION_HASH = "d1ab" ;
7230
7234
  ClassNameGenerator$1.configure(componentName => {
7231
7235
  return "njs-".concat(NEBULA_VERSION_HASH, "-").concat(componentName.replace('Mui', ''));
7232
7236
  });
@@ -7235,7 +7239,8 @@ var InstanceContext = React__default.createContext({
7235
7239
  language: null,
7236
7240
  theme: null,
7237
7241
  translator: null,
7238
- constraints: {}
7242
+ constraints: {},
7243
+ themeApi: null
7239
7244
  });
7240
7245
 
7241
7246
  var createKeyStore = (function () {
@@ -7744,7 +7749,7 @@ function boot(_ref2) {
7744
7749
  const appRef = React__default.createRef();
7745
7750
  const element = document.createElement('div');
7746
7751
  element.style.display = 'none';
7747
- element.setAttribute('data-nebulajs-version', "3.1.0-alpha.2" );
7752
+ element.setAttribute('data-nebulajs-version', "3.1.0-alpha.3" );
7748
7753
  element.setAttribute('data-app-id', app.id);
7749
7754
  document.body.appendChild(element);
7750
7755
  ReactDOM.render( /*#__PURE__*/React__default.createElement(NebulaApp, {
@@ -7763,6 +7768,9 @@ function boot(_ref2) {
7763
7768
  addCell(id, cell) {
7764
7769
  cells[id] = cell;
7765
7770
  },
7771
+ removeCell(id) {
7772
+ delete cells[id];
7773
+ },
7766
7774
  add(component) {
7767
7775
  (async () => {
7768
7776
  await rendered;
@@ -9534,7 +9542,7 @@ const ellipsis = {
9534
9542
  const barPadPx = 4;
9535
9543
  const barBorderWidthPx = 1;
9536
9544
  const barWithCheckboxLeftPadPx = 29;
9537
- const frequencyTextNone = '0';
9545
+ const frequencyTextNone = '-';
9538
9546
  const getSelectedStyle = _ref => {
9539
9547
  let {
9540
9548
  theme
@@ -9552,13 +9560,14 @@ const getSelectedStyle = _ref => {
9552
9560
  };
9553
9561
  };
9554
9562
  const Root$1 = styled$1('div')(_ref2 => {
9563
+ 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;
9555
9564
  let {
9556
9565
  theme
9557
9566
  } = _ref2;
9558
9567
  return {
9559
9568
  ["& .".concat(classes$a.row)]: {
9560
9569
  flexWrap: 'nowrap',
9561
- color: theme.palette.text.primary
9570
+ color: (_theme$listBox$conten = (_theme$listBox = theme.listBox) === null || _theme$listBox === void 0 ? void 0 : (_theme$listBox$conten2 = _theme$listBox.content) === null || _theme$listBox$conten2 === void 0 ? void 0 : _theme$listBox$conten2.color) !== null && _theme$listBox$conten !== void 0 ? _theme$listBox$conten : theme.palette.text.primary
9562
9571
  },
9563
9572
  ["& .".concat(classes$a.rowBorderBottom)]: {
9564
9573
  borderBottom: "1px solid ".concat(theme.palette.divider)
@@ -9566,7 +9575,7 @@ const Root$1 = styled$1('div')(_ref2 => {
9566
9575
  ["& .".concat(classes$a.column)]: {
9567
9576
  flexWrap: 'nowrap',
9568
9577
  borderRight: "1px solid ".concat(theme.palette.divider),
9569
- color: theme.palette.text.primary
9578
+ color: (_theme$listBox$conten3 = (_theme$listBox2 = theme.listBox) === null || _theme$listBox2 === void 0 ? void 0 : (_theme$listBox2$conte = _theme$listBox2.content) === null || _theme$listBox2$conte === void 0 ? void 0 : _theme$listBox2$conte.color) !== null && _theme$listBox$conten3 !== void 0 ? _theme$listBox$conten3 : theme.palette.text.primary
9570
9579
  },
9571
9580
  ["& .".concat(classes$a.fieldRoot)]: {
9572
9581
  '&:focus': {
@@ -9587,12 +9596,15 @@ const Root$1 = styled$1('div')(_ref2 => {
9587
9596
  paddingRight: '9px'
9588
9597
  },
9589
9598
  // The leaf node, containing the label text.
9590
- ["& .".concat(classes$a.labelText)]: _objectSpread2({
9599
+ ["& .".concat(classes$a.labelText)]: _objectSpread2(_objectSpread2({
9591
9600
  flexBasis: 'max-content',
9592
9601
  lineHeight: '16px',
9593
9602
  userSelect: 'none',
9594
9603
  whiteSpace: 'pre'
9595
- }, ellipsis),
9604
+ }, ellipsis), {}, {
9605
+ fontSize: (_theme$listBox3 = theme.listBox) === null || _theme$listBox3 === void 0 ? void 0 : (_theme$listBox3$conte = _theme$listBox3.content) === null || _theme$listBox3$conte === void 0 ? void 0 : _theme$listBox3$conte.fontSize,
9606
+ fontFamily: (_theme$listBox4 = theme.listBox) === null || _theme$listBox4 === void 0 ? void 0 : (_theme$listBox4$conte = _theme$listBox4.content) === null || _theme$listBox4$conte === void 0 ? void 0 : _theme$listBox4$conte.fontFamily
9607
+ }),
9596
9608
  ["& .".concat(classes$a.labelDense)]: {
9597
9609
  fontSize: 12
9598
9610
  },
@@ -9698,7 +9710,7 @@ function RowColumn(_ref3) {
9698
9710
  column = false,
9699
9711
  checkboxes = false,
9700
9712
  dense = false,
9701
- frequencyMode = 'N',
9713
+ freqIsAllowed,
9702
9714
  isSingleSelect,
9703
9715
  actions,
9704
9716
  frequencyMax = '',
@@ -9891,7 +9903,7 @@ function RowColumn(_ref3) {
9891
9903
  color: 'inherit'
9892
9904
  }) : getFieldWithRanges({
9893
9905
  lbls: labels
9894
- })), frequencyMode !== 'N' && /*#__PURE__*/React__default.createElement(Grid, {
9906
+ })), freqIsAllowed && /*#__PURE__*/React__default.createElement(Grid, {
9895
9907
  item: true,
9896
9908
  style: {
9897
9909
  display: 'flex',
@@ -9920,6 +9932,7 @@ const scrollBarThumb = '#BBB';
9920
9932
  const scrollBarThumbHover = '#555';
9921
9933
  const scrollBarBackground = '#f1f1f1';
9922
9934
  const MINIMUM_BATCH_SIZE = 100;
9935
+ const FREQUENCY_MIN_SHOW_WIDTH = 80;
9923
9936
  const classes$9 = {
9924
9937
  styledScrollbars: "".concat(PREFIX$9, "-styledScrollbars")
9925
9938
  };
@@ -9970,7 +9983,7 @@ function ListBox(_ref2) {
9970
9983
  height,
9971
9984
  width,
9972
9985
  listLayout = 'vertical',
9973
- frequencyMode = 'N',
9986
+ frequencyMode,
9974
9987
  histogram = false,
9975
9988
  checkboxes = false,
9976
9989
  update = undefined,
@@ -10110,6 +10123,14 @@ function ListBox(_ref2) {
10110
10123
  const h = Math.max(...ps.map(page => page.qArea.qTop + page.qArea.qHeight));
10111
10124
  return hasFilteredValues ? h : count;
10112
10125
  };
10126
+ const getFrequencyAllowed = () => {
10127
+ const widthPermitsFreq = width > FREQUENCY_MIN_SHOW_WIDTH;
10128
+ const {
10129
+ frequencyEnabled = false
10130
+ } = layout.qListObject;
10131
+ const hasValidFreqOption = !['none', undefined].includes(frequencyMode);
10132
+ return widthPermitsFreq && (hasValidFreqOption || frequencyEnabled);
10133
+ };
10113
10134
  const listCount = pages && pages.length && calculatePagesHeight ? getCalculatedHeight(pages) : count;
10114
10135
  onSetListCount === null || onSetListCount === void 0 ? void 0 : onSetListCount(listCount);
10115
10136
  const dense = (_layout$layoutOptions = (_layout$layoutOptions2 = layout.layoutOptions) === null || _layout$layoutOptions2 === void 0 ? void 0 : _layout$layoutOptions2.dense) !== null && _layout$layoutOptions !== void 0 ? _layout$layoutOptions : false;
@@ -10126,6 +10147,7 @@ function ListBox(_ref2) {
10126
10147
  const {
10127
10148
  frequencyMax
10128
10149
  } = layout;
10150
+ const freqIsAllowed = getFrequencyAllowed();
10129
10151
  return /*#__PURE__*/React__default.createElement(InfiniteLoader, {
10130
10152
  isItemLoaded: isItemLoaded,
10131
10153
  itemCount: listCount || 1 // must be more than 0 or loadMoreItems will never be called again
@@ -10159,6 +10181,7 @@ function ListBox(_ref2) {
10159
10181
  checkboxes,
10160
10182
  dense,
10161
10183
  frequencyMode,
10184
+ freqIsAllowed,
10162
10185
  isSingleSelect,
10163
10186
  actions: {
10164
10187
  select,
@@ -10745,7 +10768,25 @@ const search = props => _objectSpread2(_objectSpread2({}, props), {}, {
10745
10768
  var SearchIcon = (props => SvgIcon(search(props)));
10746
10769
 
10747
10770
  const TREE_PATH = '/qListObjectDef';
10748
- function ListBoxSearch(_ref) {
10771
+ const StyledInputAdornment = styled$1(InputAdornment)(_ref => {
10772
+ var _theme$listBox, _theme$listBox$conten;
10773
+ let {
10774
+ theme
10775
+ } = _ref;
10776
+ return {
10777
+ color: (_theme$listBox = theme.listBox) === null || _theme$listBox === void 0 ? void 0 : (_theme$listBox$conten = _theme$listBox.content) === null || _theme$listBox$conten === void 0 ? void 0 : _theme$listBox$conten.color
10778
+ };
10779
+ });
10780
+ const StyledOutlinedInput = styled$1(OutlinedInput)(_ref2 => {
10781
+ var _theme$listBox2, _theme$listBox2$conte;
10782
+ let {
10783
+ theme
10784
+ } = _ref2;
10785
+ return {
10786
+ color: (_theme$listBox2 = theme.listBox) === null || _theme$listBox2 === void 0 ? void 0 : (_theme$listBox2$conte = _theme$listBox2.content) === null || _theme$listBox2$conte === void 0 ? void 0 : _theme$listBox2$conte.color
10787
+ };
10788
+ });
10789
+ function ListBoxSearch(_ref3) {
10749
10790
  let {
10750
10791
  selections,
10751
10792
  model,
@@ -10753,7 +10794,7 @@ function ListBoxSearch(_ref) {
10753
10794
  listCount,
10754
10795
  dense = false,
10755
10796
  visible = true
10756
- } = _ref;
10797
+ } = _ref3;
10757
10798
  const {
10758
10799
  translator
10759
10800
  } = useContext(InstanceContext);
@@ -10822,8 +10863,8 @@ function ListBoxSearch(_ref) {
10822
10863
  if (!visible) {
10823
10864
  return null;
10824
10865
  }
10825
- return /*#__PURE__*/React__default.createElement(OutlinedInput, {
10826
- startAdornment: /*#__PURE__*/React__default.createElement(InputAdornment, {
10866
+ return /*#__PURE__*/React__default.createElement(StyledOutlinedInput, {
10867
+ startAdornment: /*#__PURE__*/React__default.createElement(StyledInputAdornment, {
10827
10868
  position: "start"
10828
10869
  }, /*#__PURE__*/React__default.createElement(SearchIcon, {
10829
10870
  size: dense ? 'small' : 'normal'
@@ -10832,6 +10873,7 @@ function ListBoxSearch(_ref) {
10832
10873
  sx: [{
10833
10874
  border: 'none',
10834
10875
  borderRadius: 0,
10876
+ backgroundColor: 'transparent',
10835
10877
  '& fieldset': {
10836
10878
  border: "1px solid ".concat(theme.palette.divider),
10837
10879
  borderWidth: '1px 0 1px 0',
@@ -12470,28 +12512,65 @@ AutoSizer.defaultProps = {
12470
12512
  style: {}
12471
12513
  };
12472
12514
 
12515
+ const addListboxTheme = themeApi => {
12516
+ const getListboxStyle = prop => themeApi.getStyle('object', '', "listBox.".concat(prop));
12517
+ return {
12518
+ backgroundColor: getListboxStyle('backgroundColor'),
12519
+ title: {
12520
+ main: {
12521
+ color: getListboxStyle('title.main.color'),
12522
+ fontSize: getListboxStyle('title.main.fontSize'),
12523
+ fontFamily: getListboxStyle('title.main.fontFamily')
12524
+ }
12525
+ },
12526
+ content: {
12527
+ color: getListboxStyle('content.color'),
12528
+ fontSize: getListboxStyle('content.fontSize'),
12529
+ fontFamily: getListboxStyle('content.fontFamily')
12530
+ }
12531
+ };
12532
+ };
12533
+
12473
12534
  const PREFIX$4 = 'ListBoxInline';
12474
12535
  const classes$4 = {
12475
12536
  listBoxHeader: "".concat(PREFIX$4, "-listBoxHeader"),
12476
12537
  screenReaderOnly: "".concat(PREFIX$4, "-screenReaderOnly")
12477
12538
  };
12478
- const StyledGrid$3 = styled$1(Grid)(() => ({
12479
- ["& .".concat(classes$4.listBoxHeader)]: {
12480
- alignSelf: 'center',
12481
- display: 'inline-flex'
12482
- },
12483
- ["& .".concat(classes$4.screenReaderOnly)]: {
12484
- position: 'absolute',
12485
- height: 0,
12486
- width: 0,
12487
- overflow: 'hidden'
12488
- }
12489
- }));
12490
- function ListBoxInline(_ref) {
12539
+ const StyledGrid$3 = styled$1(Grid)(_ref => {
12540
+ var _theme$listBox$backgr, _theme$listBox;
12541
+ let {
12542
+ theme
12543
+ } = _ref;
12544
+ return {
12545
+ backgroundColor: (_theme$listBox$backgr = (_theme$listBox = theme.listBox) === null || _theme$listBox === void 0 ? void 0 : _theme$listBox.backgroundColor) !== null && _theme$listBox$backgr !== void 0 ? _theme$listBox$backgr : theme.palette.background.default,
12546
+ ["& .".concat(classes$4.listBoxHeader)]: {
12547
+ alignSelf: 'center',
12548
+ display: 'inline-flex'
12549
+ },
12550
+ ["& .".concat(classes$4.screenReaderOnly)]: {
12551
+ position: 'absolute',
12552
+ height: 0,
12553
+ width: 0,
12554
+ overflow: 'hidden'
12555
+ }
12556
+ };
12557
+ });
12558
+ const Title = styled$1(Typography)(_ref2 => {
12559
+ var _theme$listBox2, _theme$listBox2$title, _theme$listBox2$title2, _theme$listBox3, _theme$listBox3$title, _theme$listBox3$title2, _theme$listBox4, _theme$listBox4$title, _theme$listBox4$title2;
12560
+ let {
12561
+ theme
12562
+ } = _ref2;
12563
+ return {
12564
+ color: (_theme$listBox2 = theme.listBox) === null || _theme$listBox2 === void 0 ? void 0 : (_theme$listBox2$title = _theme$listBox2.title) === null || _theme$listBox2$title === void 0 ? void 0 : (_theme$listBox2$title2 = _theme$listBox2$title.main) === null || _theme$listBox2$title2 === void 0 ? void 0 : _theme$listBox2$title2.color,
12565
+ fontSize: (_theme$listBox3 = theme.listBox) === null || _theme$listBox3 === void 0 ? void 0 : (_theme$listBox3$title = _theme$listBox3.title) === null || _theme$listBox3$title === void 0 ? void 0 : (_theme$listBox3$title2 = _theme$listBox3$title.main) === null || _theme$listBox3$title2 === void 0 ? void 0 : _theme$listBox3$title2.fontSize,
12566
+ fontFamily: (_theme$listBox4 = theme.listBox) === null || _theme$listBox4 === void 0 ? void 0 : (_theme$listBox4$title = _theme$listBox4.title) === null || _theme$listBox4$title === void 0 ? void 0 : (_theme$listBox4$title2 = _theme$listBox4$title.main) === null || _theme$listBox4$title2 === void 0 ? void 0 : _theme$listBox4$title2.fontFamily
12567
+ };
12568
+ });
12569
+ function ListBoxInline(_ref3) {
12491
12570
  var _layout$layoutOptions, _layout$layoutOptions2;
12492
12571
  let {
12493
12572
  options = {}
12494
- } = _ref;
12573
+ } = _ref3;
12495
12574
  const {
12496
12575
  direction,
12497
12576
  frequencyMode,
@@ -12534,8 +12613,10 @@ function ListBoxInline(_ref) {
12534
12613
  }, [model]);
12535
12614
  const {
12536
12615
  translator,
12537
- keyboardNavigation
12616
+ keyboardNavigation,
12617
+ themeApi
12538
12618
  } = useContext(InstanceContext);
12619
+ theme.listBox = addListboxTheme(themeApi);
12539
12620
  const moreAlignTo = useRef();
12540
12621
  const [searchContainer, searchContainerRef] = useRefWithCallback();
12541
12622
  const [layout] = useLayout$1(model);
@@ -12650,7 +12731,7 @@ function ListBoxInline(_ref) {
12650
12731
  })) : getSearchOrUnlock()), /*#__PURE__*/React__default.createElement(Grid, {
12651
12732
  item: true,
12652
12733
  className: classes$4.listBoxHeader
12653
- }, /*#__PURE__*/React__default.createElement(Typography, {
12734
+ }, /*#__PURE__*/React__default.createElement(Title, {
12654
12735
  variant: "h6",
12655
12736
  noWrap: true
12656
12737
  }, layout.title || layout.qListObject.qDimensionInfo.qFallbackTitle)), /*#__PURE__*/React__default.createElement(Grid, {
@@ -12707,11 +12788,11 @@ function ListBoxInline(_ref) {
12707
12788
  ref: moreAlignTo
12708
12789
  }), /*#__PURE__*/React__default.createElement("div", {
12709
12790
  className: classes$4.screenReaderOnly
12710
- }, translator.get('Listbox.ScreenReaderInstructions')), /*#__PURE__*/React__default.createElement(AutoSizer, null, _ref2 => {
12791
+ }, translator.get('Listbox.ScreenReaderInstructions')), /*#__PURE__*/React__default.createElement(AutoSizer, null, _ref4 => {
12711
12792
  let {
12712
12793
  height,
12713
12794
  width
12714
- } = _ref2;
12795
+ } = _ref4;
12715
12796
  return /*#__PURE__*/React__default.createElement(ListBox, {
12716
12797
  model: model,
12717
12798
  selections: selections,
@@ -12751,6 +12832,9 @@ function useExistingModel(_ref) {
12751
12832
  if (options.dense) {
12752
12833
  throw new Error('Option "dense" is not applicable for existing objects.');
12753
12834
  }
12835
+ if (options.frequencyMode) {
12836
+ throw new Error('Option "frequencyMode" is not applicable for existing objects.');
12837
+ }
12754
12838
  useEffect$1(() => {
12755
12839
  async function fetchObject() {
12756
12840
  const modelFromStore = modelStore.get(qId);
@@ -14734,7 +14818,7 @@ const resolveBgImage = (bgComp, app) => {
14734
14818
  const bgImageDef = bgComp === null || bgComp === void 0 ? void 0 : bgComp.bgImage;
14735
14819
  if (bgImageDef) {
14736
14820
  let url = '';
14737
- if (bgImageDef.mode === 'media') {
14821
+ if (bgImageDef.mode === 'media' || bgComp.useImage === 'media') {
14738
14822
  var _bgImageDef$mediaUrl, _bgImageDef$mediaUrl$;
14739
14823
  url = bgImageDef !== null && bgImageDef !== void 0 && (_bgImageDef$mediaUrl = bgImageDef.mediaUrl) !== null && _bgImageDef$mediaUrl !== void 0 && (_bgImageDef$mediaUrl$ = _bgImageDef$mediaUrl.qStaticContentUrl) !== null && _bgImageDef$mediaUrl$ !== void 0 && _bgImageDef$mediaUrl$.qUrl ? decodeURIComponent(bgImageDef.mediaUrl.qStaticContentUrl.qUrl) : undefined;
14740
14824
  url = resolveImageUrl(app, url);
@@ -14758,7 +14842,7 @@ const resolveBgColor = (bgComp, theme) => {
14758
14842
  if (bgColor.useColorExpression) {
14759
14843
  return theme.validateColor(bgColor.colorExpression);
14760
14844
  }
14761
- return bgColor.color && bgColor.color.color !== 'none' ? theme.getColorPickerColor(bgColor.color) : undefined;
14845
+ return bgColor.color && bgColor.color.color !== 'none' ? theme.getColorPickerColor(bgColor.color, true) : undefined;
14762
14846
  }
14763
14847
  return undefined;
14764
14848
  };
@@ -15050,6 +15134,7 @@ const Cell = forwardRef((_ref6, ref) => {
15050
15134
  disableCellPadding = false
15051
15135
  } = halo.context || {};
15052
15136
  const {
15137
+ theme: themeName,
15053
15138
  translator,
15054
15139
  language,
15055
15140
  keyboardNavigation
@@ -15066,11 +15151,8 @@ const Cell = forwardRef((_ref6, ref) => {
15066
15151
  const [contentRef, contentRect, contentNode] = useRect$1();
15067
15152
  const [snOptions, setSnOptions] = useState$1(initialSnOptions);
15068
15153
  const [snPlugins, setSnPlugins] = useState$1(initialSnPlugins);
15069
- const [clickOutElement, setClickOutElement] = useState$1();
15070
- const clickOutElements = [{
15071
- current: clickOutElement
15072
- }, '.njs-action-toolbar-popover']; // elements which will not trigger the click out listener
15073
- const [selections] = useObjectSelections(app, model, clickOutElements);
15154
+ const cellElementId = "njs-cell-".concat(currentId);
15155
+ const [selections] = useObjectSelections(app, model, ["#".concat(cellElementId), '.njs-action-toolbar-popover']); // elements which will not trigger the click out listener
15074
15156
  const [hovering, setHover] = useState$1(false);
15075
15157
  const hoveringDebouncer = useRef({
15076
15158
  enter: null,
@@ -15088,17 +15170,11 @@ const Cell = forwardRef((_ref6, ref) => {
15088
15170
  useEffect$1(() => {
15089
15171
  eventmixin(focusHandler.current);
15090
15172
  }, []);
15091
- useEffect$1(() => {
15092
- if (!contentNode) {
15093
- return;
15094
- }
15095
- setClickOutElement(cellNode);
15096
- }, [cellRect]);
15097
15173
  useEffect$1(() => {
15098
15174
  const bgComp = layout !== null && layout !== void 0 && layout.components ? layout.components.find(comp => comp.key === 'general') : null;
15099
15175
  setBgColor(resolveBgColor(bgComp, halo.public.theme));
15100
15176
  setBgImage(resolveBgImage(bgComp, halo.app));
15101
- }, [layout, halo.public.theme, halo.app]);
15177
+ }, [layout, halo.public.theme, halo.app, themeName]);
15102
15178
  focusHandler.current.blurCallback = resetFocus => {
15103
15179
  halo.root.toggleFocusOfCells();
15104
15180
  if (resetFocus && contentNode) {
@@ -15289,7 +15365,7 @@ const Cell = forwardRef((_ref6, ref) => {
15289
15365
  width: '100%',
15290
15366
  height: '100%',
15291
15367
  overflow: 'hidden',
15292
- backgroundColor: bgColor,
15368
+ backgroundColor: bgColor || 'unset',
15293
15369
  backgroundImage: bgImage && bgImage.url ? "url(".concat(bgImage.url, ")") : undefined,
15294
15370
  backgroundRepeat: 'no-repeat',
15295
15371
  backgroundSize: bgImage && bgImage.size,
@@ -15299,6 +15375,7 @@ const Cell = forwardRef((_ref6, ref) => {
15299
15375
  square: true,
15300
15376
  className: CellElement.className,
15301
15377
  ref: cellRef,
15378
+ id: cellElementId,
15302
15379
  onMouseEnter: handleOnMouseEnter,
15303
15380
  onMouseLeave: handleOnMouseLeave
15304
15381
  }, /*#__PURE__*/React__default.createElement(Grid, {
@@ -15338,7 +15415,7 @@ const Cell = forwardRef((_ref6, ref) => {
15338
15415
  }));
15339
15416
  });
15340
15417
 
15341
- function glue(_ref) {
15418
+ function glue$1(_ref) {
15342
15419
  let {
15343
15420
  halo,
15344
15421
  element,
@@ -15444,7 +15521,7 @@ function validatePlugins(plugins) {
15444
15521
  });
15445
15522
  }
15446
15523
 
15447
- const noopi = () => {};
15524
+ const noopi$1 = () => {};
15448
15525
  function viz() {
15449
15526
  let {
15450
15527
  model,
@@ -15452,7 +15529,7 @@ function viz() {
15452
15529
  initialError,
15453
15530
  onDestroy = async () => {}
15454
15531
  } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
15455
- let unmountCell = noopi;
15532
+ let unmountCell = noopi$1;
15456
15533
  let cellRef = null;
15457
15534
  let mountedReference = null;
15458
15535
  let onMount = null;
@@ -15502,6 +15579,11 @@ function viz() {
15502
15579
  * @type {string}
15503
15580
  */
15504
15581
  id: model.id,
15582
+ /**
15583
+ * This visualizations Enigma model, a representation of the generic object.
15584
+ * @type {string}
15585
+ */
15586
+ model,
15505
15587
  /**
15506
15588
  * Destroys the visualization and removes it from the the DOM.
15507
15589
  * @example
@@ -15514,7 +15596,7 @@ function viz() {
15514
15596
  async destroy() {
15515
15597
  await onDestroy();
15516
15598
  unmountCell();
15517
- unmountCell = noopi;
15599
+ unmountCell = noopi$1;
15518
15600
  },
15519
15601
  /**
15520
15602
  * Converts the visualization to a different registered type
@@ -15553,7 +15635,7 @@ function viz() {
15553
15635
  throw new Error('Already mounted');
15554
15636
  }
15555
15637
  mountedReference = element;
15556
- [unmountCell, cellRef] = glue({
15638
+ [unmountCell, cellRef] = glue$1({
15557
15639
  halo,
15558
15640
  element,
15559
15641
  model,
@@ -15693,6 +15775,350 @@ async function createSessionObject(_ref, halo) {
15693
15775
  }, halo, error, onDestroy);
15694
15776
  }
15695
15777
 
15778
+ async function getObject$1(_ref, halo) {
15779
+ let {
15780
+ id,
15781
+ options,
15782
+ plugins,
15783
+ element
15784
+ } = _ref;
15785
+ const key = "".concat(id);
15786
+ let rpc = rpcRequestModelStore.get(key);
15787
+ if (!rpc) {
15788
+ rpc = halo.app.getObject(id);
15789
+ rpcRequestModelStore.set(key, rpc);
15790
+ }
15791
+ const model = await rpc;
15792
+ modelStore.set(key, model);
15793
+ return init(model, {
15794
+ options,
15795
+ plugins,
15796
+ element
15797
+ }, halo);
15798
+ }
15799
+
15800
+ /**
15801
+ * @interface
15802
+ * @extends HTMLElement
15803
+ * @experimental
15804
+ * @since 3.1.0
15805
+ */
15806
+ const SheetElement = {
15807
+ /** @type {'njs-sheet'} */
15808
+ className: 'njs-sheet'
15809
+ };
15810
+ function getCellRenderer(cell, halo, initialSnOptions, initialSnPlugins, initialError, onMount) {
15811
+ const {
15812
+ x,
15813
+ y,
15814
+ width,
15815
+ height
15816
+ } = cell.bounds;
15817
+ return /*#__PURE__*/React__default.createElement("div", {
15818
+ style: {
15819
+ left: "".concat(x, "%"),
15820
+ top: "".concat(y, "%"),
15821
+ width: "".concat(width, "%"),
15822
+ height: "".concat(height, "%"),
15823
+ position: 'absolute'
15824
+ }
15825
+ }, /*#__PURE__*/React__default.createElement(Cell, {
15826
+ ref: cell.cellRef,
15827
+ halo: halo,
15828
+ model: cell.model,
15829
+ currentId: cell.currentId,
15830
+ initialSnOptions: initialSnOptions,
15831
+ initialSnPlugins: initialSnPlugins,
15832
+ initialError: initialError,
15833
+ onMount: onMount
15834
+ }));
15835
+ }
15836
+ function Sheet(_ref) {
15837
+ let {
15838
+ model,
15839
+ halo,
15840
+ initialSnOptions,
15841
+ initialSnPlugins,
15842
+ initialError,
15843
+ onMount
15844
+ } = _ref;
15845
+ const {
15846
+ root
15847
+ } = halo;
15848
+ const [layout] = useLayout$1(model);
15849
+ const {
15850
+ theme: themeName
15851
+ } = useContext(InstanceContext);
15852
+ const [cells, setCells] = useState$1([]);
15853
+ const [bgColor, setBgColor] = useState$1(undefined);
15854
+ const [bgImage, setBgImage] = useState$1(undefined);
15855
+ const [deepHash, setDeepHash] = useState$1('');
15856
+
15857
+ /// For each object
15858
+ useEffect$1(() => {
15859
+ if (layout) {
15860
+ const hash = JSON.stringify(layout.cells);
15861
+ if (hash === deepHash) {
15862
+ return;
15863
+ }
15864
+ setDeepHash(hash);
15865
+ const fetchObjects = async () => {
15866
+ /*
15867
+ Need to always fetch and evaluate everything as the sheet need to support multiple instances of the same object?
15868
+ No, there is no way to add the same chart twice, so the optimization should be worth it.
15869
+ */
15870
+
15871
+ // Clear the cell list
15872
+ cells.forEach(c => {
15873
+ root.removeCell(c.currentId);
15874
+ });
15875
+ const lCells = layout.cells;
15876
+ // TODO - should try reuse existing objects on subsequent renders
15877
+ // Non-id updates should only change the "css"
15878
+ const cs = await Promise.all(lCells.map(async c => {
15879
+ let mounted;
15880
+ const mountedPromise = new Promise(resolve => {
15881
+ mounted = resolve;
15882
+ });
15883
+ const cell = cells.find(ce => ce.id === c.name);
15884
+ if (cell) {
15885
+ cell.bounds = c.bounds;
15886
+ delete cell.mountedPromise;
15887
+ return cell;
15888
+ }
15889
+ const vs = await getObject$1({
15890
+ id: c.name
15891
+ }, halo);
15892
+ return {
15893
+ model: vs.model,
15894
+ id: c.name,
15895
+ bounds: c.bounds,
15896
+ cellRef: React__default.createRef(),
15897
+ currentId: uid(),
15898
+ mounted,
15899
+ mountedPromise
15900
+ };
15901
+ }));
15902
+ cs.forEach(c => root.addCell(c.currentId, c.cellRef));
15903
+ setCells(cs);
15904
+ };
15905
+ fetchObjects();
15906
+ }
15907
+ }, [layout]);
15908
+ const cellRenderers = useMemo$1(() => cells ? cells.map(c => getCellRenderer(c, halo, initialSnOptions, initialSnPlugins, initialError, c.mounted)) : [], [cells]);
15909
+ useEffect$1(() => {
15910
+ const bgComp = layout !== null && layout !== void 0 && layout.components ? layout.components.find(comp => comp.key === 'general') : null;
15911
+ setBgColor(resolveBgColor(bgComp, halo.public.theme));
15912
+ setBgImage(resolveBgImage(bgComp, halo.app));
15913
+ }, [layout, halo.public.theme, halo.app, themeName]);
15914
+
15915
+ /* TODO
15916
+ - sheet title + bg + logo etc + as option
15917
+ - sheet exposed classnames for theming
15918
+ */
15919
+
15920
+ const height = !layout || Number.isNaN(layout.height) ? '100%' : "".concat(Number(layout.height), "%");
15921
+ const promises = cells.map(c => c.mountedPromise);
15922
+ const ps = promises.filter(p => !!p);
15923
+ if (ps.length) {
15924
+ Promise.all(promises).then(() => {
15925
+ // TODO - correct? Currently called each time a new cell is mounted?
15926
+ onMount();
15927
+ });
15928
+ }
15929
+ return /*#__PURE__*/React__default.createElement("div", {
15930
+ className: SheetElement.className,
15931
+ style: {
15932
+ width: "100%",
15933
+ height,
15934
+ position: 'relative',
15935
+ backgroundColor: bgColor,
15936
+ backgroundImage: bgImage && bgImage.url ? "url(".concat(bgImage.url, ")") : undefined,
15937
+ backgroundRepeat: 'no-repeat',
15938
+ backgroundSize: bgImage && bgImage.size,
15939
+ backgroundPosition: bgImage && bgImage.pos
15940
+ }
15941
+ }, cellRenderers);
15942
+ }
15943
+
15944
+ function glue(_ref) {
15945
+ let {
15946
+ halo,
15947
+ element,
15948
+ model,
15949
+ initialSnOptions,
15950
+ initialSnPlugins,
15951
+ onMount,
15952
+ initialError
15953
+ } = _ref;
15954
+ const {
15955
+ root
15956
+ } = halo;
15957
+ const sheetRef = React__default.createRef();
15958
+ const portal = ReactDOM.createPortal( /*#__PURE__*/React__default.createElement(Sheet, {
15959
+ ref: sheetRef,
15960
+ halo: halo,
15961
+ model: model,
15962
+ initialSnOptions: initialSnOptions,
15963
+ initialSnPlugins: initialSnPlugins,
15964
+ initialError: initialError,
15965
+ onMount: onMount
15966
+ }), element, model.id);
15967
+ const unmount = () => {
15968
+ root.remove(portal);
15969
+ model.removeListener('closed', unmount);
15970
+ };
15971
+ model.on('closed', unmount);
15972
+ root.add(portal);
15973
+ return [unmount, sheetRef];
15974
+ }
15975
+
15976
+ const noopi = () => {};
15977
+ function sheet() {
15978
+ let {
15979
+ model,
15980
+ halo,
15981
+ initialError,
15982
+ onDestroy = async () => {}
15983
+ } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
15984
+ let unmountSheet = noopi;
15985
+ let sheetRef = null;
15986
+ let mountedReference = null;
15987
+ let onMount = null;
15988
+ const mounted = new Promise(resolve => {
15989
+ onMount = resolve;
15990
+ });
15991
+ let initialSnOptions = {};
15992
+ let initialSnPlugins = [];
15993
+ const setSnOptions = async opts => {
15994
+ if (mountedReference) {
15995
+ (async () => {
15996
+ await mounted;
15997
+ sheetRef.current.setSnOptions(_objectSpread2(_objectSpread2({}, initialSnOptions), opts));
15998
+ })();
15999
+ } else {
16000
+ // Handle setting options before mount
16001
+ initialSnOptions = _objectSpread2(_objectSpread2({}, initialSnOptions), opts);
16002
+ }
16003
+ };
16004
+ const setSnPlugins = async plugins => {
16005
+ validatePlugins(plugins);
16006
+ if (mountedReference) {
16007
+ (async () => {
16008
+ await mounted;
16009
+ sheetRef.current.setSnPlugins(plugins);
16010
+ })();
16011
+ } else {
16012
+ // Handle setting plugins before mount
16013
+ initialSnPlugins = plugins;
16014
+ }
16015
+ };
16016
+
16017
+ /**
16018
+ * @class
16019
+ * @alias Sheet
16020
+ * @classdesc A controller to further modify a visualization after it has been rendered.
16021
+ * @experimental
16022
+ * @since 3.1.0
16023
+ * @example
16024
+ * const sheet = await embed(app).render({
16025
+ * element,
16026
+ * id: "jD5Gd"
16027
+ * });
16028
+ * sheet.destroy();
16029
+ */
16030
+ const api = /** @lends Sheet# */{
16031
+ /**
16032
+ * The id of this sheets's generic object.
16033
+ * @type {string}
16034
+ */
16035
+ id: model.id,
16036
+ /**
16037
+ * This sheets Enigma model, a representation of the generic object.
16038
+ * @type {string}
16039
+ */
16040
+ model,
16041
+ /**
16042
+ * Destroys the sheet and removes it from the the DOM.
16043
+ * @example
16044
+ * const sheet = await embed(app).render({
16045
+ * element,
16046
+ * id: "jD5Gd"
16047
+ * });
16048
+ * sheet.destroy();
16049
+ */
16050
+ async destroy() {
16051
+ await onDestroy();
16052
+ unmountSheet();
16053
+ unmountSheet = noopi;
16054
+ },
16055
+ // ===== unexposed experimental API - use at own risk ======
16056
+ __DO_NOT_USE__: {
16057
+ mount(element) {
16058
+ if (mountedReference) {
16059
+ throw new Error('Already mounted');
16060
+ }
16061
+ mountedReference = element;
16062
+ [unmountSheet, sheetRef] = glue({
16063
+ halo,
16064
+ element,
16065
+ model,
16066
+ initialSnOptions,
16067
+ initialSnPlugins,
16068
+ initialError,
16069
+ onMount
16070
+ });
16071
+ return mounted;
16072
+ },
16073
+ async applyProperties(props) {
16074
+ const current = await model.getEffectiveProperties();
16075
+ const patches = getPatches('/', props, current);
16076
+ if (patches.length) {
16077
+ return model.applyPatches(patches, true);
16078
+ }
16079
+ return undefined;
16080
+ },
16081
+ options(opts) {
16082
+ setSnOptions(opts);
16083
+ },
16084
+ plugins(plugins) {
16085
+ setSnPlugins(plugins);
16086
+ },
16087
+ exportImage() {
16088
+ throw new Error('Not implemented');
16089
+ },
16090
+ takeSnapshot() {
16091
+ throw new Error('Not implemented');
16092
+ },
16093
+ getModel() {
16094
+ return model;
16095
+ }
16096
+ }
16097
+ };
16098
+ return api;
16099
+ }
16100
+
16101
+ /* eslint no-underscore-dangle:0 */
16102
+ async function initSheet(model, optional, halo, initialError) {
16103
+ let onDestroy = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : async () => {};
16104
+ const api = sheet({
16105
+ model,
16106
+ halo,
16107
+ initialError,
16108
+ onDestroy
16109
+ });
16110
+ if (optional.options) {
16111
+ api.__DO_NOT_USE__.options(optional.options);
16112
+ }
16113
+ if (optional.plugins) {
16114
+ api.__DO_NOT_USE__.plugins(optional.plugins);
16115
+ }
16116
+ if (optional.element) {
16117
+ await api.__DO_NOT_USE__.mount(optional.element);
16118
+ }
16119
+ return api;
16120
+ }
16121
+
15696
16122
  /**
15697
16123
  * @interface BaseConfig
15698
16124
  * @description Basic rendering configuration for rendering an object
@@ -15723,6 +16149,13 @@ async function getObject(_ref, halo) {
15723
16149
  }
15724
16150
  const model = await rpc;
15725
16151
  modelStore.set(key, model);
16152
+ if (model.genericType === 'sheet') {
16153
+ return initSheet(model, {
16154
+ options,
16155
+ plugins,
16156
+ element
16157
+ }, halo);
16158
+ }
15726
16159
  return init(model, {
15727
16160
  options,
15728
16161
  plugins,
@@ -19592,6 +20025,7 @@ function nuked() {
19592
20025
  themes: configuration.themes,
19593
20026
  root
19594
20027
  });
20028
+ currentContext.themeApi = appTheme$1.externalAPI;
19595
20029
  const publicAPIs = {
19596
20030
  galaxy: /** @lends Galaxy */{
19597
20031
  /** @type {Translator} */
@@ -19637,9 +20071,10 @@ function nuked() {
19637
20071
  */
19638
20072
  const api = /** @lends Embed# */{
19639
20073
  /**
19640
- * Renders a visualization into an HTMLElement.
20074
+ * Renders a visualization or sheet into an HTMLElement.
20075
+ * Support for sense sheets is experimental.
19641
20076
  * @param {CreateConfig | GetConfig} cfg - The render configuration.
19642
- * @returns {Promise<Viz>} A controller to the rendered visualization.
20077
+ * @returns {Promise<Viz|Sheet>} A controller to the rendered visualization or sheet.
19643
20078
  * @example
19644
20079
  * // render from existing object
19645
20080
  * n.render({
@@ -19923,7 +20358,7 @@ var enigmaMocker = {exports: {}};
19923
20358
  var enigmaMocker_dev = {exports: {}};
19924
20359
 
19925
20360
  /*
19926
- * @nebula.js/enigma-mocker v3.1.0-alpha.1
20361
+ * @nebula.js/enigma-mocker v3.1.0-alpha.2
19927
20362
  * Copyright (c) 2022 QlikTech International AB
19928
20363
  * Released under the MIT license.
19929
20364
  */
@@ -20297,7 +20732,7 @@ var enigmaMocker_dev = {exports: {}};
20297
20732
  throw new Error("Generic object has multiple IDs, qInfo.qId: ".concat(qId, ", id: ").concat(id));
20298
20733
  }
20299
20734
  qId = qId || id || "object - ".concat(+Date.now());
20300
- const mock = _objectSpread2({
20735
+ const mock = _objectSpread2(_objectSpread2({
20301
20736
  id: qId,
20302
20737
  session: getPropValue(session, {
20303
20738
  defaultValue: true
@@ -20312,7 +20747,9 @@ var enigmaMocker_dev = {exports: {}};
20312
20747
  delay
20313
20748
  })
20314
20749
  });
20315
- }, {}));
20750
+ }, {})), {}, {
20751
+ genericType: genericObject.type
20752
+ });
20316
20753
  return {
20317
20754
  [qId]: mock
20318
20755
  };