@nebula.js/stardust 2.3.1 → 2.6.1

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,13 +1,13 @@
1
1
  /*
2
- * @nebula.js/stardust v2.3.1
3
- * Copyright (c) 2021 QlikTech International AB
2
+ * @nebula.js/stardust v2.6.1
3
+ * Copyright (c) 2022 QlikTech International AB
4
4
  * Released under the MIT license.
5
5
  */
6
6
 
7
7
  import React, { 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';
8
8
  import ReactDOM from 'react-dom';
9
9
  import { createGenerateClassName, StylesProvider, ThemeProvider, makeStyles, useTheme as useTheme$1 } from '@material-ui/styles';
10
- import { Grid, Typography, IconButton, makeStyles as makeStyles$1, Popover, MenuList, MenuItem, ListItemIcon, Divider, OutlinedInput, InputAdornment, Badge, List, ListItem, Button, Box, Icon, CircularProgress, Paper } from '@material-ui/core';
10
+ import { Checkbox, Grid, FormControlLabel, Typography, IconButton, makeStyles as makeStyles$1, Popover, MenuList, MenuItem, ListItemIcon, Divider, OutlinedInput, InputAdornment, Badge, List, ListItem, Button, Box, Icon, CircularProgress, Paper } from '@material-ui/core';
11
11
 
12
12
  var runtime = {exports: {}};
13
13
 
@@ -3209,8 +3209,8 @@ function theme() {
3209
3209
  * @returns {string} The style value
3210
3210
  *
3211
3211
  * @example
3212
- * theme.getStyle('object', 'title.main', 'fontSize'));
3213
- * theme.getStyle('', '', 'fontSize'));
3212
+ * theme.getStyle('object', 'title.main', 'fontSize');
3213
+ * theme.getStyle('', '', 'fontSize');
3214
3214
  */
3215
3215
  getStyle(basePath, path, attribute) {
3216
3216
  if (!styleResolverInstanceCache[basePath]) {
@@ -5234,7 +5234,7 @@ function useAppSelections(app) {
5234
5234
  return [appSelections, navState];
5235
5235
  }
5236
5236
 
5237
- const NEBULA_VERSION_HASH = "03e4" ;
5237
+ const NEBULA_VERSION_HASH = "375a" ;
5238
5238
  let counter = 0;
5239
5239
  const NebulaApp = forwardRef((_ref, ref) => {
5240
5240
  let {
@@ -5294,7 +5294,7 @@ function boot(_ref2) {
5294
5294
  const appRef = React.createRef();
5295
5295
  const element = document.createElement('div');
5296
5296
  element.style.display = 'none';
5297
- element.setAttribute('data-nebulajs-version', "2.3.1" );
5297
+ element.setAttribute('data-nebulajs-version', "2.6.1" );
5298
5298
  element.setAttribute('data-app-id', app.id);
5299
5299
  document.body.appendChild(element);
5300
5300
  ReactDOM.render( /*#__PURE__*/React.createElement(NebulaApp, {
@@ -6435,6 +6435,278 @@ var InfiniteLoader = function (_PureComponent) {
6435
6435
  return InfiniteLoader;
6436
6436
  }(PureComponent);
6437
6437
 
6438
+ const SELECTED_STATES = ['S', 'XS'];
6439
+
6440
+ const flatten = arr => arr.reduce((prev, cur) => prev.concat(cur));
6441
+
6442
+ function isStateSelected(qState) {
6443
+ return SELECTED_STATES.includes(qState);
6444
+ }
6445
+
6446
+ function getUniques(arr) {
6447
+ return Array.isArray(arr) ? Array.from(new Set(arr)) : undefined;
6448
+ }
6449
+ function getSelectedValues(pages) {
6450
+ if (!pages || !pages.length) {
6451
+ return [];
6452
+ }
6453
+
6454
+ const elementNbrs = pages.map(page => {
6455
+ const elementNumbers = page.qMatrix.map(p => {
6456
+ const [p0] = p;
6457
+ return isStateSelected(p0.qState) ? p0.qElemNumber : false;
6458
+ });
6459
+ return elementNumbers.filter(n => n !== false);
6460
+ });
6461
+ return flatten(elementNbrs);
6462
+ }
6463
+ function applySelectionsOnPages(pages, elmNumbers) {
6464
+ const getNewSelectionState = qState => elmNumbers.length <= 1 && isStateSelected(qState) ? 'A' : 'S';
6465
+
6466
+ const matrices = pages.map(page => {
6467
+ const qMatrix = page.qMatrix.map(p => {
6468
+ const [p0] = p;
6469
+ const selectionMatchesElement = elmNumbers.includes(p0.qElemNumber);
6470
+ const qState = selectionMatchesElement ? getNewSelectionState(p0.qState) : p0.qState;
6471
+ return [_objectSpread2(_objectSpread2({}, p0), {}, {
6472
+ qState
6473
+ }), p.slice(1)];
6474
+ });
6475
+ return _objectSpread2(_objectSpread2({}, page), {}, {
6476
+ qMatrix
6477
+ });
6478
+ });
6479
+ return matrices;
6480
+ }
6481
+ async function selectValues(_ref) {
6482
+ let {
6483
+ selections,
6484
+ elemNumbers,
6485
+ isSingleSelect = false
6486
+ } = _ref;
6487
+ let resolved = Promise.resolve(false);
6488
+ const hasNanValues = elemNumbers.some(elemNumber => Number.isNaN(elemNumber));
6489
+
6490
+ if (!hasNanValues) {
6491
+ const elemNumbersToSelect = elemNumbers;
6492
+ resolved = selections.select({
6493
+ method: 'selectListObjectValues',
6494
+ params: ['/qListObjectDef', elemNumbersToSelect, !isSingleSelect]
6495
+ }).then(success => success !== false).catch(() => false);
6496
+ }
6497
+
6498
+ return resolved;
6499
+ }
6500
+ function getElemNumbersFromPages(pages) {
6501
+ if (!pages || !pages.length) {
6502
+ return [];
6503
+ }
6504
+
6505
+ const elemNumbersArr = pages.map(page => {
6506
+ const qElemNumbers = page.qMatrix.map(p => {
6507
+ const [{
6508
+ qElemNumber
6509
+ }] = p;
6510
+ return qElemNumber;
6511
+ });
6512
+ return qElemNumbers;
6513
+ });
6514
+ const elemNumbers = flatten(elemNumbersArr);
6515
+ return elemNumbers;
6516
+ }
6517
+ /**
6518
+ * @typedef {object} MinMaxResult
6519
+ * @property {number} min
6520
+ * @property {number} max
6521
+ */
6522
+
6523
+ /**
6524
+ * Returns the min and max indices of elemNumbersOrdered which contains
6525
+ * all numbers in elementNbrs.
6526
+ *
6527
+ * @param {number[]} elementNbrs
6528
+ * @param {number[]} elemNumbersOrdered
6529
+ * @returns {MinMaxResult}
6530
+ */
6531
+
6532
+ function getMinMax(elementNbrs, elemNumbersOrdered) {
6533
+ let min = Infinity;
6534
+ let max = -Infinity;
6535
+ elementNbrs.forEach(nbr => {
6536
+ const index = elemNumbersOrdered.indexOf(nbr);
6537
+ min = index < min ? index : min;
6538
+ max = index > max ? index : max;
6539
+ });
6540
+ return {
6541
+ min,
6542
+ max
6543
+ };
6544
+ }
6545
+
6546
+ function fillRange(elementNbrs, elemNumbersOrdered) {
6547
+ if (!elementNbrs) {
6548
+ return [];
6549
+ }
6550
+
6551
+ if (elementNbrs.length <= 1) {
6552
+ return elementNbrs;
6553
+ } // Interpolate values algorithm
6554
+
6555
+
6556
+ const {
6557
+ min,
6558
+ max
6559
+ } = getMinMax(elementNbrs, elemNumbersOrdered);
6560
+ return elemNumbersOrdered.slice(min, max + 1);
6561
+ }
6562
+
6563
+ function useSelectionsInteractions(_ref) {
6564
+ let {
6565
+ layout,
6566
+ selections,
6567
+ pages = [],
6568
+ rangeSelect = true,
6569
+ checkboxes = false,
6570
+ doc = document
6571
+ } = _ref;
6572
+ const [instantPages, setInstantPages] = useState$1(pages);
6573
+ const [mouseDown, setMouseDown] = useState$1(false);
6574
+ const [selectingValues, setSelectingValues] = useState$1(false);
6575
+ const [selected, setSelected] = useState$1([]);
6576
+ const [isRangeSelection, setIsRangeSelection] = useState$1(false);
6577
+ const [preSelected, setPreSelected] = useState$1([]);
6578
+ const elemNumbersOrdered = getElemNumbersFromPages(pages);
6579
+
6580
+ const getIsSingleSelect = () => !!(layout && layout.qListObject.qDimensionInfo.qIsOneAndOnlyOne); // Select values for real, by calling the backend.
6581
+
6582
+
6583
+ const select = async function () {
6584
+ let elemNumbers = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
6585
+ let additive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
6586
+ setSelectingValues(true);
6587
+ const isSingleSelect = getIsSingleSelect();
6588
+ const filtered = additive ? elemNumbers.filter(n => !selected.includes(n)) : elemNumbers;
6589
+ await selectValues({
6590
+ selections,
6591
+ elemNumbers: filtered,
6592
+ isSingleSelect
6593
+ });
6594
+ setSelectingValues(false);
6595
+ }; // Show estimated selection states instantly before applying the selections for real.
6596
+
6597
+
6598
+ const preSelect = function (elemNumbers) {
6599
+ let additive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
6600
+ setPreSelected(existing => {
6601
+ const uniques = getUniques([...existing, ...elemNumbers]);
6602
+ const filtered = additive ? uniques.filter(n => !selected.includes(n)) : uniques;
6603
+ const filled = additive ? fillRange(uniques, elemNumbersOrdered) : filtered;
6604
+ return filled;
6605
+ });
6606
+ };
6607
+
6608
+ const onClick = useCallback(event => {
6609
+ if (selectingValues) {
6610
+ return;
6611
+ }
6612
+
6613
+ const elemNumber = +event.currentTarget.getAttribute('data-n');
6614
+ setPreSelected([elemNumber]);
6615
+ }, [selectingValues]);
6616
+ const onMouseDown = useCallback(event => {
6617
+ if (selectingValues) {
6618
+ return;
6619
+ }
6620
+
6621
+ setIsRangeSelection(false);
6622
+ setMouseDown(true);
6623
+ const elemNumber = +event.currentTarget.getAttribute('data-n');
6624
+ setPreSelected([elemNumber]);
6625
+ }, [selectingValues]);
6626
+ const onMouseUp = useCallback(event => {
6627
+ const elemNumber = +event.currentTarget.getAttribute('data-n');
6628
+
6629
+ if (getIsSingleSelect() || !rangeSelect || !mouseDown || selectingValues || preSelected.length === 1 && preSelected[0] === elemNumber // prevent toggling again on mouseup
6630
+ ) {
6631
+ return;
6632
+ }
6633
+
6634
+ preSelect([elemNumber]);
6635
+ }, [mouseDown, selectingValues, preSelected, selected, isRangeSelection]);
6636
+ const onMouseUpDoc = useCallback(() => {
6637
+ // Ensure we end interactions when mouseup happens outside the Listbox.
6638
+ setMouseDown(false);
6639
+ setSelectingValues(false);
6640
+ }, []);
6641
+ const onMouseEnter = useCallback(event => {
6642
+ if (getIsSingleSelect() || !mouseDown || selectingValues) {
6643
+ return;
6644
+ }
6645
+
6646
+ setIsRangeSelection(true);
6647
+ const elemNumber = +event.currentTarget.getAttribute('data-n');
6648
+ preSelect([elemNumber], true);
6649
+ }, [mouseDown, selectingValues, isRangeSelection, preSelected, selected, layout && layout.qListObject.qDimensionInfo.qIsOneAndOnlyOne]);
6650
+ useEffect$1(() => {
6651
+ // Perform selections of pre-selected values. This can
6652
+ // happen only when interactions have finished (mouseup).
6653
+ const interactionIsFinished = !mouseDown;
6654
+
6655
+ if (!preSelected || !preSelected.length || selectingValues || !interactionIsFinished || !layout) {
6656
+ return;
6657
+ }
6658
+
6659
+ select(preSelected, isRangeSelection);
6660
+ }, [preSelected, mouseDown]);
6661
+ useEffect$1(() => {
6662
+ doc.addEventListener('mouseup', onMouseUpDoc);
6663
+ return () => {
6664
+ doc.removeEventListener('mouseup', onMouseUpDoc);
6665
+ };
6666
+ }, []);
6667
+ useEffect$1(() => {
6668
+ if (selectingValues || mouseDown) {
6669
+ return;
6670
+ } // Keep track of (truely) selected fields so we can prevent toggling them on range select.
6671
+
6672
+
6673
+ const alreadySelected = getSelectedValues(pages);
6674
+ setSelected(alreadySelected);
6675
+ }, [pages]);
6676
+ useEffect$1(() => {
6677
+ if (selectingValues || !pages || !checkboxes && !mouseDown) {
6678
+ return;
6679
+ } // Render pre-selections before they have been selected in Engine.
6680
+
6681
+
6682
+ const newPages = applySelectionsOnPages(pages, preSelected);
6683
+ setInstantPages(newPages);
6684
+ }, [preSelected]);
6685
+ const interactionEvents = {};
6686
+
6687
+ if (checkboxes) {
6688
+ Object.assign(interactionEvents, {
6689
+ onClick
6690
+ });
6691
+ } else if (rangeSelect) {
6692
+ Object.assign(interactionEvents, {
6693
+ onMouseUp,
6694
+ onMouseDown,
6695
+ onMouseEnter
6696
+ });
6697
+ } else {
6698
+ Object.assign(interactionEvents, {
6699
+ onMouseUp,
6700
+ onMouseDown
6701
+ });
6702
+ }
6703
+
6704
+ return {
6705
+ instantPages,
6706
+ interactionEvents
6707
+ };
6708
+ }
6709
+
6438
6710
  const tick = props => _objectSpread2(_objectSpread2({}, props), {}, {
6439
6711
  shapes: [{
6440
6712
  type: 'path',
@@ -6446,181 +6718,196 @@ const tick = props => _objectSpread2(_objectSpread2({}, props), {}, {
6446
6718
 
6447
6719
  var Tick = (props => SvgIcon(tick(props)));
6448
6720
 
6721
+ const CheckboxChecked = "url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath" + " fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 " + "1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='%23fff'/%3E%3C/svg%3E\")";
6722
+
6449
6723
  const useStyles$b = makeStyles(theme => ({
6450
- row: {
6451
- flexWrap: 'nowrap',
6452
- borderBottom: "1px solid ".concat(theme.palette.divider),
6453
- '&:focus': {
6454
- boxShadow: "inset 0 0 0 2px ".concat(theme.palette.custom.focusOutline),
6455
- outline: 'none'
6456
- }
6724
+ cbIcon: {
6725
+ borderRadius: 3,
6726
+ width: 16,
6727
+ height: 16,
6728
+ boxShadow: 'inset 0 0 0 1px rgba(16,22,26,.2), inset 0 -1px 0 rgba(16,22,26,.1)',
6729
+ backgroundColor: '#f5f8fa',
6730
+ backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.8),hsla(0,0%,100%,0))'
6457
6731
  },
6458
- cell: {
6459
- padding: '8px',
6460
- '& span': {
6461
- whiteSpace: 'nowrap',
6462
- fontSize: '12px',
6463
- lineHeight: '16px'
6464
- },
6465
- overflow: 'hidden',
6466
- textOverflow: 'ellipsis'
6467
- },
6468
- icon: {
6469
- padding: theme.spacing(1)
6470
- },
6471
- S: {
6472
- background: theme.palette.selected.main,
6473
- color: theme.palette.selected.mainContrastText,
6474
- '&:focus': {
6475
- boxShadow: "inset 0 0 0 2px rgba(0, 0, 0, 0.3)",
6476
- outline: 'none'
6732
+ cbIconChecked: {
6733
+ borderRadius: 3,
6734
+ backgroundColor: theme.palette.selected.main,
6735
+ backgroundImage: 'linear-gradient(180deg,hsla(0,0%,100%,.1),hsla(0,0%,100%,0))',
6736
+ '&:before': {
6737
+ display: 'block',
6738
+ width: 16,
6739
+ height: 16,
6740
+ backgroundImage: CheckboxChecked,
6741
+ content: '""'
6477
6742
  }
6478
6743
  },
6479
- A: {
6480
- background: theme.palette.selected.alternative,
6481
- color: theme.palette.selected.alternativeContrastText
6482
- },
6483
- X: {
6484
- background: theme.palette.selected.excluded,
6485
- color: theme.palette.selected.excludedContrastText
6744
+ checkbox: {
6745
+ margin: 0,
6746
+ '&:hover': {
6747
+ backgroundColor: 'inherit !important'
6748
+ }
6486
6749
  },
6487
- highlighted: {
6488
- backgroundColor: '#FFC72A'
6750
+ dense: {
6751
+ padding: '4px 8px'
6489
6752
  }
6490
6753
  }));
6491
- function Row(_ref) {
6754
+ function ListboxCheckbox(_ref) {
6492
6755
  let {
6493
- index,
6494
- style,
6495
- data
6756
+ checked,
6757
+ label,
6758
+ dense
6496
6759
  } = _ref;
6497
- const classes = useStyles$b();
6498
- const classArr = [classes.row];
6499
- let label = '';
6500
- const {
6501
- onClick,
6502
- pages
6503
- } = data;
6504
- let cell;
6505
-
6506
- if (pages) {
6507
- const page = pages.filter(p => p.qArea.qTop <= index && index < p.qArea.qTop + p.qArea.qHeight)[0];
6508
-
6509
- if (page) {
6510
- const area = page.qArea;
6511
-
6512
- if (index >= area.qTop && index < area.qTop + area.qHeight) {
6513
- [cell] = page.qMatrix[index - area.qTop];
6514
- }
6515
- }
6516
- }
6760
+ const styles = useStyles$b();
6761
+ return /*#__PURE__*/React.createElement(Checkbox, {
6762
+ edge: "start",
6763
+ checked: checked,
6764
+ tabIndex: -1,
6765
+ disableRipple: true,
6766
+ className: [styles.checkbox, dense && styles.dense].filter(Boolean).join(' '),
6767
+ inputProps: {
6768
+ 'aria-labelledby': label
6769
+ },
6770
+ name: label,
6771
+ icon: /*#__PURE__*/React.createElement("span", {
6772
+ className: styles.cbIcon
6773
+ }),
6774
+ checkedIcon: /*#__PURE__*/React.createElement("span", {
6775
+ className: styles.cbIconChecked
6776
+ })
6777
+ });
6778
+ }
6517
6779
 
6518
- let locked = false;
6519
- let selected = false;
6780
+ /**
6781
+ * @typedef {object} Range
6782
+ * @property {number} qCharPos The (absolute) index where the highlighted range starts.
6783
+ * @property {number} qCharCount The length of the sub-string (starting from qChartPos) that should be highlighted.
6784
+ */
6520
6785
 
6521
- if (cell) {
6522
- label = cell.qText;
6523
- locked = cell.qState === 'L' || cell.qState === 'XL';
6524
- selected = cell.qState === 'S' || cell.qState === 'XS';
6786
+ /**
6787
+ * @typedef {object} Segment
6788
+ * @property {string} segment The sub-string/segment cut out from the original label.
6789
+ * @property {boolean} highlighted A flag which tells whether the segment should be highlighted or not.
6790
+ */
6525
6791
 
6526
- if (cell.qState === 'S' || cell.qState === 'L') {
6527
- classArr.push(classes.S);
6528
- } else if (cell.qState === 'A') {
6529
- classArr.push(classes.A);
6530
- } else if (cell.qState === 'X' || cell.qState === 'XS' || cell.qState === 'XL') {
6531
- classArr.push(classes.X);
6532
- }
6533
- } // Handle search highlights
6792
+ /**
6793
+ * @param {string} label The label we want to create segments out of.
6794
+ * @param {Range} range The indexes which define how to create the segments.
6795
+ * @param {number=} [startIndex] An optional index which tells where we want to start the first segment from
6796
+ * (only relevant for creating the first unhighlighted segment of a string/sub-string).
6797
+ * @returns {Segment[]} An array of segments.
6798
+ */
6799
+ function getSegmentsFromRange(label, range) {
6800
+ let startIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
6801
+ const {
6802
+ qCharPos,
6803
+ qCharCount
6804
+ } = range;
6805
+ const segments = [];
6534
6806
 
6807
+ if (qCharPos > startIndex) {
6808
+ // Create a non-highlighted section before the highighted section.
6809
+ segments.push([label.slice(startIndex, qCharPos), false]);
6810
+ } // Highlighted segment.
6535
6811
 
6536
- const ranges = cell && cell.qHighlightRanges && cell.qHighlightRanges.qRanges.sort((a, b) => a.qCharPos - b.qCharPos) || [];
6537
- const labels = ranges.reduce((acc, curr, ix) => {
6538
- // First non highlighted segment
6539
- if (curr.qCharPos > 0 && ix === 0) {
6540
- acc.push([label.slice(0, curr.qCharPos)]);
6541
- } // Previous non highlighted segment
6542
6812
 
6813
+ segments.push([label.slice(qCharPos, qCharPos + qCharCount), true]);
6814
+ return segments;
6815
+ }
6816
+ /**
6817
+ * @param {string} label The label we want to create segments out of.
6818
+ * @param {Range[]} ranges The ranges defining indices for cutting the string into segments.
6819
+ * @returns {Segment[]} An array of segments, covering the entire string label.
6820
+ */
6543
6821
 
6544
- const prev = ranges[ix - 1];
6545
6822
 
6546
- if (prev) {
6547
- acc.push([label.slice(prev.qCharPos + prev.qCharPos + 1, curr.qCharPos)]);
6548
- } // Highlighted segment
6823
+ function getSegmentsFromRanges(label, ranges) {
6824
+ if (!ranges.length) {
6825
+ return [];
6826
+ }
6549
6827
 
6828
+ const labels = ranges.reduce((acc, curr, ix) => {
6829
+ const startIndex = ix === 0 ? 0 : ranges[ix - 1].qCharPos + ranges[ix - 1].qCharCount;
6830
+ acc.push(...getSegmentsFromRange(label, curr, startIndex)); // Last non highlighted segment
6550
6831
 
6551
- acc.push([label.slice(curr.qCharPos, curr.qCharPos + curr.qCharCount), classes.highlighted]); // Last non highlighted segment
6832
+ const isLastRange = ix === ranges.length - 1;
6833
+ const endIndex = ranges[ix].qCharPos + ranges[ix].qCharCount;
6552
6834
 
6553
- if (ix === ranges.length - 1 && curr.qCharPos + curr.qCharCount < label.length) {
6554
- acc.push([label.slice(curr.qCharPos + curr.qCharCount)]);
6835
+ if (isLastRange && endIndex < label.length) {
6836
+ acc.push([label.slice(endIndex), false]);
6555
6837
  }
6556
6838
 
6557
6839
  return acc;
6558
6840
  }, []);
6559
- return /*#__PURE__*/React.createElement(Grid, {
6560
- container: true,
6561
- spacing: 0,
6562
- className: classArr.join(' ').trim(),
6563
- style: style,
6564
- onClick: onClick,
6565
- role: "row",
6566
- tabIndex: 0,
6567
- "data-n": cell && cell.qElemNumber
6568
- }, /*#__PURE__*/React.createElement(Grid, {
6569
- item: true,
6570
- style: {
6571
- minWidth: 0,
6572
- flexGrow: 1
6573
- },
6574
- className: classes.cell,
6575
- title: "".concat(label)
6576
- }, ranges.length === 0 ? /*#__PURE__*/React.createElement(Typography, {
6577
- component: "span",
6578
- noWrap: true,
6579
- color: "inherit"
6580
- }, "".concat(label)) : labels.map((_ref2, ix) => {
6581
- let [l, highlighted] = _ref2;
6582
- return (
6583
- /*#__PURE__*/
6584
- // eslint-disable-next-line react/no-array-index-key
6585
- React.createElement(Typography, {
6586
- component: "span",
6587
- key: ix,
6588
- className: highlighted,
6589
- noWrap: true
6590
- }, l)
6591
- );
6592
- })), /*#__PURE__*/React.createElement(Grid, {
6593
- item: true,
6594
- className: classes.icon
6595
- }, locked && /*#__PURE__*/React.createElement(Lock, {
6596
- size: "small"
6597
- }), selected && /*#__PURE__*/React.createElement(Tick, {
6598
- size: "small"
6599
- })));
6841
+ return labels;
6600
6842
  }
6601
6843
 
6844
+ const ellipsis = {
6845
+ width: '100%',
6846
+ overflow: 'hidden',
6847
+ textOverflow: 'ellipsis'
6848
+ };
6602
6849
  const useStyles$a = makeStyles(theme => ({
6850
+ row: {
6851
+ flexWrap: 'nowrap',
6852
+ borderBottom: "1px solid ".concat(theme.palette.divider),
6853
+ color: theme.palette.text.primary,
6854
+ '&:focus': {
6855
+ boxShadow: "inset 0 0 0 2px ".concat(theme.palette.custom.focusOutline),
6856
+ outline: 'none'
6857
+ }
6858
+ },
6603
6859
  column: {
6604
6860
  flexWrap: 'nowrap',
6605
6861
  borderRight: "1px solid ".concat(theme.palette.divider),
6862
+ color: theme.palette.text.primary,
6606
6863
  '&:focus': {
6607
6864
  boxShadow: "inset 0 0 0 2px ".concat(theme.palette.custom.focusOutline),
6608
6865
  outline: 'none'
6609
6866
  }
6610
6867
  },
6868
+ // The interior wrapper for all field content.
6611
6869
  cell: {
6612
- padding: '8px',
6613
- '& span': {
6614
- whiteSpace: 'nowrap',
6615
- fontSize: '12px',
6616
- lineHeight: '16px'
6617
- },
6618
- overflow: 'hidden',
6619
- textOverflow: 'ellipsis'
6870
+ display: 'flex',
6871
+ alignItems: 'center',
6872
+ minWidth: 0,
6873
+ flexGrow: 1,
6874
+ // Note that this padding is overridden when using checkboxes.
6875
+ paddingLeft: '12px',
6876
+ paddingRight: '12px'
6877
+ },
6878
+ // The leaf node, containing the label text.
6879
+ labelText: _objectSpread2({
6880
+ flexBasis: 'max-content',
6881
+ lineHeight: '16px',
6882
+ userSelect: 'none',
6883
+ whiteSpace: 'pre'
6884
+ }, ellipsis),
6885
+ labelDense: {
6886
+ fontSize: 12
6620
6887
  },
6888
+ // Highlight is added to labelText spans, which are created as siblings to original labelText,
6889
+ // when a search string is matched.
6890
+ highlighted: {
6891
+ overflow: 'visible',
6892
+ width: '100%',
6893
+ '& > span': {
6894
+ width: '100%',
6895
+ backgroundColor: '#FFC72A'
6896
+ }
6897
+ },
6898
+ // Checkbox and label container.
6899
+ checkboxLabel: {
6900
+ margin: 0,
6901
+ width: '100%',
6902
+ // For checkboxes the first child is the checkbox container, second is the label container.
6903
+ '& > span:nth-child(2)': _objectSpread2({}, ellipsis)
6904
+ },
6905
+ // The icons container holding tick and lock, shown inside fields.
6621
6906
  icon: {
6907
+ display: 'flex',
6622
6908
  padding: theme.spacing(1)
6623
6909
  },
6910
+ // Selection styles (S=Selected, A=Available, X=Excluded).
6624
6911
  S: {
6625
6912
  background: theme.palette.selected.main,
6626
6913
  color: theme.palette.selected.mainContrastText,
@@ -6636,135 +6923,232 @@ const useStyles$a = makeStyles(theme => ({
6636
6923
  X: {
6637
6924
  background: theme.palette.selected.excluded,
6638
6925
  color: theme.palette.selected.excludedContrastText
6639
- },
6640
- highlighted: {
6641
- backgroundColor: '#FFC72A'
6642
6926
  }
6643
6927
  }));
6644
- function Column(_ref) {
6928
+ function RowColumn(_ref) {
6645
6929
  let {
6646
6930
  index,
6647
6931
  style,
6648
- data
6932
+ data,
6933
+ column = false
6649
6934
  } = _ref;
6650
- const classes = useStyles$a();
6651
- const classArr = [classes.column];
6652
- let label = '';
6653
6935
  const {
6654
6936
  onClick,
6655
- pages
6937
+ onMouseDown,
6938
+ onMouseUp,
6939
+ onMouseEnter,
6940
+ pages,
6941
+ isLocked,
6942
+ checkboxes = false,
6943
+ dense = false
6656
6944
  } = data;
6657
- let cell;
6945
+ const [isSelected, setSelected] = useState$1(false);
6946
+ const [cell, setCell] = useState$1();
6947
+ const classes = useStyles$a();
6948
+ const [classArr, setClassArr] = useState$1([]);
6949
+ useEffect$1(() => {
6950
+ if (!pages) {
6951
+ return;
6952
+ }
6658
6953
 
6659
- if (pages) {
6954
+ let c;
6660
6955
  const page = pages.filter(p => p.qArea.qTop <= index && index < p.qArea.qTop + p.qArea.qHeight)[0];
6661
6956
 
6662
6957
  if (page) {
6663
6958
  const area = page.qArea;
6664
6959
 
6665
6960
  if (index >= area.qTop && index < area.qTop + area.qHeight) {
6666
- [cell] = page.qMatrix[index - area.qTop];
6961
+ [c] = page.qMatrix[index - area.qTop];
6667
6962
  }
6668
6963
  }
6669
- }
6670
-
6671
- let locked = false;
6672
- let selected = false;
6673
6964
 
6674
- if (cell) {
6675
- label = cell.qText;
6676
- locked = cell.qState === 'L' || cell.qState === 'XL';
6677
- selected = cell.qState === 'S' || cell.qState === 'XS';
6678
-
6679
- if (cell.qState === 'S' || cell.qState === 'L') {
6680
- classArr.push(classes.S);
6681
- } else if (cell.qState === 'A') {
6682
- classArr.push(classes.A);
6683
- } else if (cell.qState === 'X' || cell.qState === 'XS' || cell.qState === 'XL') {
6684
- classArr.push(classes.X);
6965
+ setCell(c);
6966
+ }, [pages]);
6967
+ useEffect$1(() => {
6968
+ if (!cell) {
6969
+ return;
6685
6970
  }
6686
- } // Handle search highlights
6687
6971
 
6972
+ const selected = cell.qState === 'S' || cell.qState === 'XS' || cell.qState === 'L';
6973
+ setSelected(selected);
6974
+ const clazzArr = [column ? classes.column : classes.row];
6688
6975
 
6689
- const ranges = cell && cell.qHighlightRanges && cell.qHighlightRanges.qRanges.sort((a, b) => a.qCharPos - b.qCharPos) || [];
6690
- const labels = ranges.reduce((acc, curr, ix) => {
6691
- // First non highlighted segment
6692
- if (curr.qCharPos > 0 && ix === 0) {
6693
- acc.push([label.slice(0, curr.qCharPos)]);
6694
- } // Previous non highlighted segment
6976
+ if (!checkboxes) {
6977
+ if (cell.qState === 'S' || cell.qState === 'L') {
6978
+ clazzArr.push(classes.S);
6979
+ } else if (cell.qState === 'A') {
6980
+ clazzArr.push(classes.A);
6981
+ } else if (cell.qState === 'X' || cell.qState === 'XS' || cell.qState === 'XL') {
6982
+ clazzArr.push(classes.X);
6983
+ }
6984
+ }
6695
6985
 
6986
+ setClassArr(clazzArr);
6987
+ }, [cell && cell.qState]);
6696
6988
 
6697
- const prev = ranges[ix - 1];
6989
+ const getValueField = _ref2 => {
6990
+ let {
6991
+ lbl,
6992
+ ix,
6993
+ color,
6994
+ highlighted = false
6995
+ } = _ref2;
6996
+ return /*#__PURE__*/React.createElement(Typography, {
6997
+ component: "span",
6998
+ variant: "body2",
6999
+ key: ix,
7000
+ className: [classes.labelText, highlighted && classes.highlighted, dense && classes.labelDense].filter(c => !!c).join(' ').trim(),
7001
+ color: color
7002
+ }, /*#__PURE__*/React.createElement("span", {
7003
+ style: {
7004
+ whiteSpace: 'pre'
7005
+ }
7006
+ }, lbl));
7007
+ };
6698
7008
 
6699
- if (prev) {
6700
- acc.push([label.slice(prev.qCharPos + prev.qCharPos + 1, curr.qCharPos)]);
6701
- } // Highlighted segment
7009
+ const getCheckboxField = _ref3 => {
7010
+ let {
7011
+ lbl,
7012
+ color,
7013
+ qElemNumber
7014
+ } = _ref3;
7015
+ const cb = /*#__PURE__*/React.createElement(ListboxCheckbox, {
7016
+ label: lbl,
7017
+ checked: isSelected,
7018
+ dense: dense
7019
+ });
7020
+ const labelTag = typeof lbl === 'string' ? getValueField({
7021
+ lbl,
7022
+ color,
7023
+ highlighted: false
7024
+ }) : lbl;
7025
+ return /*#__PURE__*/React.createElement(FormControlLabel, {
7026
+ color: color,
7027
+ control: cb,
7028
+ className: classes.checkboxLabel,
7029
+ label: labelTag,
7030
+ key: qElemNumber
7031
+ });
7032
+ };
6702
7033
 
7034
+ const label = cell ? cell.qText : ''; // Search highlights. Split up labelText span into several and add the highlighted class to matching sub-strings.
6703
7035
 
6704
- acc.push([label.slice(curr.qCharPos, curr.qCharPos + curr.qCharCount), classes.highlighted]); // Last non highlighted segment
7036
+ const ranges = cell && cell.qHighlightRanges && cell.qHighlightRanges.qRanges.sort((a, b) => a.qCharPos - b.qCharPos) || [];
7037
+ const labels = getSegmentsFromRanges(label, ranges);
7038
+ const getField = checkboxes ? getCheckboxField : getValueField;
6705
7039
 
6706
- if (ix === ranges.length - 1 && curr.qCharPos + curr.qCharCount < label.length) {
6707
- acc.push([label.slice(curr.qCharPos + curr.qCharCount)]);
6708
- }
7040
+ const getFieldWithRanges = _ref4 => {
7041
+ let {
7042
+ lbls
7043
+ } = _ref4;
7044
+ const labelsWithRanges = lbls.map((_ref5, ix) => {
7045
+ let [lbl, highlighted] = _ref5;
7046
+ return getValueField({
7047
+ ix,
7048
+ highlighted,
7049
+ lbl
7050
+ });
7051
+ });
7052
+ return checkboxes ? getCheckboxField({
7053
+ lbl: labelsWithRanges
7054
+ }) : labelsWithRanges;
7055
+ };
6709
7056
 
6710
- return acc;
6711
- }, []);
7057
+ const iconStyles = {
7058
+ alignItems: 'center',
7059
+ display: 'flex'
7060
+ };
7061
+ const showLock = isSelected && isLocked;
7062
+ const showTick = !checkboxes && isSelected && !isLocked;
7063
+ const cellStyle = {
7064
+ display: 'flex',
7065
+ alignItems: 'center',
7066
+ minWidth: 0,
7067
+ flexGrow: 1,
7068
+ padding: checkboxes ? 0 : undefined
7069
+ };
6712
7070
  return /*#__PURE__*/React.createElement(Grid, {
6713
7071
  container: true,
6714
7072
  spacing: 0,
6715
- className: classArr.join(' ').trim(),
7073
+ className: ['value', ...classArr].join(' ').trim(),
6716
7074
  style: style,
6717
7075
  onClick: onClick,
6718
- alignItems: "center",
6719
- role: "row",
7076
+ onMouseDown: onMouseDown,
7077
+ onMouseUp: onMouseUp,
7078
+ onMouseEnter: onMouseEnter,
7079
+ role: column ? 'column' : 'row',
6720
7080
  tabIndex: 0,
6721
7081
  "data-n": cell && cell.qElemNumber
6722
7082
  }, /*#__PURE__*/React.createElement(Grid, {
6723
7083
  item: true,
6724
- style: {
6725
- minWidth: 0,
6726
- flexGrow: 1
6727
- },
7084
+ style: cellStyle,
6728
7085
  className: classes.cell,
6729
7086
  title: "".concat(label)
6730
- }, ranges.length === 0 ? /*#__PURE__*/React.createElement(Typography, {
6731
- component: "span",
6732
- noWrap: true,
6733
- color: "inherit"
6734
- }, "".concat(label)) : labels.map((_ref2, ix) => {
6735
- let [l, highlighted] = _ref2;
6736
- return (
6737
- /*#__PURE__*/
6738
- // eslint-disable-next-line react/no-array-index-key
6739
- React.createElement(Typography, {
6740
- component: "span",
6741
- key: ix,
6742
- className: highlighted,
6743
- noWrap: true
6744
- }, l)
6745
- );
6746
- })), /*#__PURE__*/React.createElement(Grid, {
7087
+ }, ranges.length === 0 ? getField({
7088
+ lbl: label,
7089
+ color: 'inherit'
7090
+ }) : getFieldWithRanges({
7091
+ lbls: labels
7092
+ })), (showLock || showTick) && /*#__PURE__*/React.createElement(Grid, {
6747
7093
  item: true,
6748
7094
  className: classes.icon
6749
- }, locked && /*#__PURE__*/React.createElement(Lock, {
7095
+ }, showLock && /*#__PURE__*/React.createElement(Lock, {
7096
+ style: iconStyles,
6750
7097
  size: "small"
6751
- }), selected && /*#__PURE__*/React.createElement(Tick, {
7098
+ }), showTick && /*#__PURE__*/React.createElement(Tick, {
7099
+ style: iconStyles,
6752
7100
  size: "small"
6753
7101
  })));
6754
7102
  }
6755
7103
 
6756
- /* eslint no-underscore-dangle:0 */
6757
- function ListBox(_ref) {
7104
+ function getSizeInfo(_ref) {
7105
+ let {
7106
+ isVertical,
7107
+ checkboxes,
7108
+ dense,
7109
+ height
7110
+ } = _ref;
7111
+ let sizeVertical = checkboxes ? 40 : 33;
7112
+
7113
+ if (dense) {
7114
+ sizeVertical = 24;
7115
+ }
7116
+
7117
+ const itemSize = isVertical ? sizeVertical : 200;
7118
+ const listHeight = height || 8 * itemSize;
7119
+ return {
7120
+ itemSize,
7121
+ listHeight
7122
+ };
7123
+ }
7124
+
7125
+ function ListBox(_ref2) {
6758
7126
  let {
6759
7127
  model,
6760
7128
  selections,
6761
7129
  direction,
6762
7130
  height,
6763
7131
  width,
6764
- listLayout = 'vertical'
6765
- } = _ref;
7132
+ listLayout = 'vertical',
7133
+ rangeSelect = true,
7134
+ checkboxes = false,
7135
+ update = undefined,
7136
+ dense = false
7137
+ } = _ref2;
6766
7138
  const [layout] = useLayout$1(model);
6767
7139
  const [pages, setPages] = useState$1(null);
7140
+ const [isLoadingData, setIsLoadingData] = useState$1(false);
7141
+ const {
7142
+ instantPages = [],
7143
+ interactionEvents
7144
+ } = useSelectionsInteractions({
7145
+ layout,
7146
+ selections,
7147
+ pages,
7148
+ rangeSelect,
7149
+ checkboxes,
7150
+ doc: document
7151
+ });
6768
7152
  const loaderRef = useRef(null);
6769
7153
  const local = useRef({
6770
7154
  queue: [],
@@ -6773,28 +7157,17 @@ function ListBox(_ref) {
6773
7157
  const listData = useRef({
6774
7158
  pages: []
6775
7159
  });
6776
- const onClick = useCallback(e => {
6777
- if (layout && layout.qListObject.qDimensionInfo.qLocked) {
6778
- return;
6779
- }
6780
-
6781
- const elemNumber = +e.currentTarget.getAttribute('data-n');
6782
-
6783
- if (!Number.isNaN(elemNumber)) {
6784
- selections.select({
6785
- method: 'selectListObjectValues',
6786
- params: ['/qListObjectDef', [elemNumber], !layout.qListObject.qDimensionInfo.qIsOneAndOnlyOne]
6787
- });
6788
- }
6789
- }, [model, layout && !!layout.qListObject.qDimensionInfo.qLocked, layout && !!layout.qListObject.qDimensionInfo.qIsOneAndOnlyOne]);
6790
7160
  const isItemLoaded = useCallback(index => {
6791
7161
  if (!pages || !local.current.validPages) {
6792
7162
  return false;
6793
7163
  }
6794
7164
 
6795
7165
  local.current.checkIdx = index;
6796
- const page = pages.filter(p => p.qArea.qTop <= index && index < p.qArea.qTop + p.qArea.qHeight)[0];
6797
- return page && page.qArea.qTop <= index && index < page.qArea.qTop + page.qArea.qHeight;
7166
+
7167
+ const isLoaded = p => p.qArea.qTop <= index && index < p.qArea.qTop + p.qArea.qHeight;
7168
+
7169
+ const page = pages.filter(p => isLoaded(p))[0];
7170
+ return page && isLoaded(page);
6798
7171
  }, [layout, pages]);
6799
7172
  const loadMoreItems = useCallback((startIndex, stopIndex) => {
6800
7173
  local.current.queue.push({
@@ -6808,6 +7181,7 @@ function ListBox(_ref) {
6808
7181
  }
6809
7182
 
6810
7183
  clearTimeout(local.current.timeout);
7184
+ setIsLoadingData(true);
6811
7185
  return new Promise(resolve => {
6812
7186
  local.current.timeout = setTimeout(() => {
6813
7187
  const sorted = local.current.queue.slice(-2).sort((a, b) => a.start - b.start);
@@ -6820,12 +7194,14 @@ function ListBox(_ref) {
6820
7194
  local.current.validPages = true;
6821
7195
  listData.current.pages = p;
6822
7196
  setPages(p);
7197
+ setIsLoadingData(false);
6823
7198
  resolve();
6824
7199
  });
6825
7200
  }, isScrolling ? 500 : 0);
6826
7201
  });
6827
7202
  }, [layout]);
6828
- useEffect$1(() => {
7203
+
7204
+ const fetchData = () => {
6829
7205
  local.current.queue = [];
6830
7206
  local.current.validPages = false;
6831
7207
 
@@ -6838,7 +7214,23 @@ function ListBox(_ref) {
6838
7214
 
6839
7215
  loaderRef.current._listRef.scrollToItem(0);
6840
7216
  }
7217
+ };
7218
+
7219
+ if (update) {
7220
+ // Hand over the update function for manual refresh from hosting application.
7221
+ update.call(null, fetchData);
7222
+ }
7223
+
7224
+ useEffect$1(() => {
7225
+ fetchData();
6841
7226
  }, [layout]);
7227
+ useEffect$1(() => {
7228
+ if (!instantPages || isLoadingData) {
7229
+ return;
7230
+ }
7231
+
7232
+ setPages(instantPages);
7233
+ }, [instantPages]);
6842
7234
 
6843
7235
  if (!layout) {
6844
7236
  return null;
@@ -6846,8 +7238,16 @@ function ListBox(_ref) {
6846
7238
 
6847
7239
  const isVertical = listLayout !== 'horizontal';
6848
7240
  const count = layout.qListObject.qSize.qcy;
6849
- const ITEM_SIZE = isVertical ? 33 : 200;
6850
- const listHeight = height || 8 * ITEM_SIZE;
7241
+ const {
7242
+ itemSize,
7243
+ listHeight
7244
+ } = getSizeInfo({
7245
+ isVertical,
7246
+ checkboxes,
7247
+ dense,
7248
+ height
7249
+ });
7250
+ const isLocked = layout && layout.qListObject.qDimensionInfo.qLocked;
6851
7251
  return /*#__PURE__*/React.createElement(InfiniteLoader, {
6852
7252
  isItemLoaded: isItemLoaded,
6853
7253
  itemCount: count,
@@ -6855,28 +7255,33 @@ function ListBox(_ref) {
6855
7255
  threshold: 0,
6856
7256
  minimumBatchSize: 100,
6857
7257
  ref: loaderRef
6858
- }, _ref2 => {
7258
+ }, _ref3 => {
6859
7259
  let {
6860
7260
  onItemsRendered,
6861
7261
  ref
6862
- } = _ref2;
7262
+ } = _ref3;
6863
7263
  local.current.listRef = ref;
6864
7264
  return /*#__PURE__*/React.createElement(FixedSizeList, {
6865
7265
  direction: direction,
7266
+ "data-testid": "fixed-size-list",
6866
7267
  useIsScrolling: true,
6867
7268
  style: {},
6868
7269
  height: listHeight,
6869
7270
  width: width,
6870
7271
  itemCount: count,
6871
7272
  layout: listLayout,
6872
- itemData: {
6873
- onClick,
7273
+ itemData: _objectSpread2(_objectSpread2({
7274
+ isLocked,
7275
+ column: !isVertical,
6874
7276
  pages
6875
- },
6876
- itemSize: ITEM_SIZE,
7277
+ }, isLocked ? {} : interactionEvents), {}, {
7278
+ checkboxes,
7279
+ dense
7280
+ }),
7281
+ itemSize: itemSize,
6877
7282
  onItemsRendered: onItemsRendered,
6878
7283
  ref: ref
6879
- }, isVertical ? Row : Column);
7284
+ }, RowColumn);
6880
7285
  });
6881
7286
  }
6882
7287
 
@@ -7451,13 +7856,22 @@ const useStyles$7 = makeStyles(theme => ({
7451
7856
  borderRadius: 0,
7452
7857
  borderColor: "".concat(theme.palette.divider, " transparent")
7453
7858
  }
7859
+ },
7860
+ dense: {
7861
+ fontSize: 12,
7862
+ paddingLeft: theme.spacing(1),
7863
+ '& input': {
7864
+ paddingTop: '5px',
7865
+ paddingBottom: '5px'
7866
+ }
7454
7867
  }
7455
7868
  }));
7456
7869
  const TREE_PATH = '/qListObjectDef';
7457
7870
  function ListBoxSearch(_ref) {
7458
7871
  let {
7459
7872
  model,
7460
- autoFocus = true
7873
+ autoFocus = true,
7874
+ dense = false
7461
7875
  } = _ref;
7462
7876
  const {
7463
7877
  translator
@@ -7486,8 +7900,10 @@ function ListBoxSearch(_ref) {
7486
7900
  return /*#__PURE__*/React.createElement(OutlinedInput, {
7487
7901
  startAdornment: /*#__PURE__*/React.createElement(InputAdornment, {
7488
7902
  position: "start"
7489
- }, /*#__PURE__*/React.createElement(Search, null)),
7490
- className: [classes.root].join(' '),
7903
+ }, /*#__PURE__*/React.createElement(Search, {
7904
+ size: dense ? 'small' : 'normal'
7905
+ })),
7906
+ className: ['search', classes.root, dense && classes.dense].filter(Boolean).join(' '),
7491
7907
  autoFocus: autoFocus,
7492
7908
  margin: "dense",
7493
7909
  fullWidth: true,
@@ -9098,7 +9514,14 @@ function ListBoxInline(_ref2) {
9098
9514
  direction,
9099
9515
  listLayout,
9100
9516
  search = true,
9101
- properties = {}
9517
+ toolbar = true,
9518
+ rangeSelect = true,
9519
+ checkboxes = false,
9520
+ properties = {},
9521
+ sessionModel = undefined,
9522
+ selectionsApi = undefined,
9523
+ update = undefined,
9524
+ dense = false
9102
9525
  } = options;
9103
9526
 
9104
9527
  const listdef = _objectSpread2({
@@ -9124,9 +9547,10 @@ function ListBoxInline(_ref2) {
9124
9547
  }
9125
9548
  },
9126
9549
  title
9127
- }, properties);
9550
+ }, properties); // Something something lib dimension
9551
+
9128
9552
 
9129
- let fieldName; // Something something lib dimension
9553
+ let fieldName;
9130
9554
 
9131
9555
  if (fieldIdentifier.qLibraryId) {
9132
9556
  listdef.qListObjectDef.qLibraryId = fieldIdentifier.qLibraryId;
@@ -9136,8 +9560,19 @@ function ListBoxInline(_ref2) {
9136
9560
  fieldName = fieldIdentifier;
9137
9561
  }
9138
9562
 
9563
+ let [model] = useSessionModel(listdef, sessionModel ? null : app, fieldName, stateName);
9564
+
9565
+ if (sessionModel) {
9566
+ model = sessionModel;
9567
+ }
9568
+
9569
+ let selections = useObjectSelections(selectionsApi ? {} : app, model)[0];
9570
+
9571
+ if (selectionsApi) {
9572
+ selections = selectionsApi;
9573
+ }
9574
+
9139
9575
  const theme = useTheme$1();
9140
- const [model] = useSessionModel(listdef, app, fieldName, stateName);
9141
9576
  const lock = useCallback(() => {
9142
9577
  model.lock('/qListObjectDef');
9143
9578
  }, [model]);
@@ -9148,7 +9583,6 @@ function ListBoxInline(_ref2) {
9148
9583
  translator
9149
9584
  } = useContext(InstanceContext);
9150
9585
  const moreAlignTo = useRef();
9151
- const [selections] = useObjectSelections(app, model);
9152
9586
  const [layout] = useLayout$1(model);
9153
9587
  const [showToolbar, setShowToolbar] = useState$1(false);
9154
9588
  useEffect$1(() => {
@@ -9174,11 +9608,11 @@ function ListBoxInline(_ref2) {
9174
9608
  }
9175
9609
 
9176
9610
  const isLocked = layout.qListObject.qDimensionInfo.qLocked === true;
9177
- const listboxSelectionToolbarItems = createListboxSelectionToolbar({
9611
+ const listboxSelectionToolbarItems = toolbar ? createListboxSelectionToolbar({
9178
9612
  layout,
9179
9613
  model,
9180
9614
  translator
9181
- });
9615
+ }) : [];
9182
9616
  const counts = layout.qListObject.qDimensionInfo.qStateCounts;
9183
9617
  const hasSelections = counts.qSelected + counts.qSelectedExcluded + counts.qLocked + counts.qLockedExcluded > 0;
9184
9618
  const minHeight = 49 + (search ? 40 : 0) + 49;
@@ -9190,7 +9624,7 @@ function ListBoxInline(_ref2) {
9190
9624
  height: '100%',
9191
9625
  minHeight: "".concat(minHeight, "px")
9192
9626
  }
9193
- }, /*#__PURE__*/React.createElement(Grid, {
9627
+ }, toolbar && /*#__PURE__*/React.createElement(Grid, {
9194
9628
  item: true,
9195
9629
  container: true,
9196
9630
  style: {
@@ -9238,7 +9672,8 @@ function ListBoxInline(_ref2) {
9238
9672
  item: true
9239
9673
  }, /*#__PURE__*/React.createElement(ListBoxSearch, {
9240
9674
  model: model,
9241
- autoFocus: false
9675
+ autoFocus: false,
9676
+ dense: dense
9242
9677
  })) : '', /*#__PURE__*/React.createElement(Grid, {
9243
9678
  item: true,
9244
9679
  xs: true
@@ -9254,8 +9689,12 @@ function ListBoxInline(_ref2) {
9254
9689
  selections: selections,
9255
9690
  direction: direction,
9256
9691
  listLayout: listLayout,
9692
+ rangeSelect: rangeSelect,
9693
+ checkboxes: checkboxes,
9257
9694
  height: height,
9258
- width: width
9695
+ width: width,
9696
+ update: update,
9697
+ dense: dense
9259
9698
  });
9260
9699
  })));
9261
9700
  }
@@ -9496,10 +9935,10 @@ function populateData(_ref) {
9496
9935
  /**
9497
9936
  * @since 1.1.0
9498
9937
  * @interface ExportDataDef
9499
- * @property {qae.NxDimension[]} dimensions
9500
- * @property {qae.NxMeasure[]} measures
9501
- * @property {qae.NxDimension[]} excludedDimensions
9502
- * @property {qae.NxMeasure[]} excludedMeasures
9938
+ * @property {EngineAPI.INxDimension[]} dimensions
9939
+ * @property {EngineAPI.INxMeasure[]} measures
9940
+ * @property {EngineAPI.INxDimension[]} excludedDimensions
9941
+ * @property {EngineAPI.INxMeasure[]} excludedMeasures
9503
9942
  * @property {number[]} interColumnSortOrder
9504
9943
  */
9505
9944
 
@@ -10943,10 +11382,16 @@ class RenderDebouncer {
10943
11382
 
10944
11383
  }
10945
11384
 
11385
+ /**
11386
+ * @interface VizElementAttributes
11387
+ * @extends NamedNodeMap
11388
+ * @property {string} data-render-count
11389
+ */
11390
+
10946
11391
  /**
10947
11392
  * @interface
10948
11393
  * @extends HTMLElement
10949
- * @property {string} attributes.data-render-count
11394
+ * @property {VizElementAttributes} attributes
10950
11395
  */
10951
11396
 
10952
11397
  const VizElement = {
@@ -11390,6 +11835,9 @@ const Cell = forwardRef((_ref6, ref) => {
11390
11835
  const {
11391
11836
  nebbie
11392
11837
  } = halo.public;
11838
+ const {
11839
+ disableCellPadding = false
11840
+ } = halo.context || {};
11393
11841
  const {
11394
11842
  translator,
11395
11843
  language,
@@ -11649,12 +12097,13 @@ const Cell = forwardRef((_ref6, ref) => {
11649
12097
  container: true,
11650
12098
  direction: "column",
11651
12099
  spacing: 0,
11652
- style: _objectSpread2({
12100
+ style: _objectSpread2(_objectSpread2({
11653
12101
  position: 'relative',
11654
12102
  width: '100%',
11655
- height: '100%',
12103
+ height: '100%'
12104
+ }, !disableCellPadding ? {
11656
12105
  padding: theme.spacing(1)
11657
- }, state.longRunningQuery ? {
12106
+ } : {}), state.longRunningQuery ? {
11658
12107
  opacity: '0.3'
11659
12108
  } : {})
11660
12109
  }, cellNode && layout && state.sn && /*#__PURE__*/React.createElement(Header, {
@@ -11996,7 +12445,7 @@ async function init(model, optional, halo, initialError) {
11996
12445
  }
11997
12446
 
11998
12447
  /**
11999
- * @typedef {string | qae.NxDimension | qae.NxMeasure | LibraryField} Field
12448
+ * @typedef {string | EngineAPI.INxDimension | EngineAPI.INxMeasure | LibraryField} Field
12000
12449
  */
12001
12450
 
12002
12451
  /**
@@ -12004,9 +12453,9 @@ async function init(model, optional, halo, initialError) {
12004
12453
  * @description Rendering configuration for creating and rendering a new object
12005
12454
  * @extends BaseConfig
12006
12455
  * @property {string} type
12007
- * @property {string} version
12456
+ * @property {string=} version
12008
12457
  * @property {(Field[])=} fields
12009
- * @property {qae.GenericObjectProperties=} properties
12458
+ * @property {EngineAPI.IGenericObjectProperties=} properties
12010
12459
  */
12011
12460
 
12012
12461
  async function createSessionObject(_ref, halo) {
@@ -13179,7 +13628,7 @@ function useRect() {
13179
13628
  /**
13180
13629
  * Gets the layout of the generic object associated with this visualization.
13181
13630
  * @entry
13182
- * @returns {qae.GenericObjectLayout}
13631
+ * @returns {EngineAPI.IGenericObjectLayout}
13183
13632
  * @example
13184
13633
  * import { useLayout } from '@nebula.js/stardust';
13185
13634
  * // ...
@@ -13199,7 +13648,7 @@ function useLayout() {
13199
13648
  * The returned value from `useStaleLayout()` and `useLayout()` are identical when the object
13200
13649
  * is not in a modal state.
13201
13650
  * @entry
13202
- * @returns {qae.GenericObjectLayout}
13651
+ * @returns {EngineAPI.IGenericObjectLayout}
13203
13652
  * @example
13204
13653
  * import { useStaleLayout } from '@nebula.js/stardust';
13205
13654
  * // ...
@@ -13222,7 +13671,7 @@ function useStaleLayout() {
13222
13671
  /**
13223
13672
  * Gets the layout of the app associated with this visualization.
13224
13673
  * @entry
13225
- * @returns {qae.NxAppLayout} The app layout
13674
+ * @returns {EngineAPI.INxAppLayout} The app layout
13226
13675
  * @example
13227
13676
  * import { useAppLayout } from '@nebula.js/stardust';
13228
13677
  * // ...
@@ -13236,7 +13685,7 @@ function useAppLayout() {
13236
13685
  /**
13237
13686
  * Gets the generic object API of the generic object connected to this visualization.
13238
13687
  * @entry
13239
- * @returns {enigma.GenericObject|undefined}
13688
+ * @returns {EngineAPI.IGenericObject|undefined}
13240
13689
  * @example
13241
13690
  * import { useModel } from '@nebula.js/stardust';
13242
13691
  * // ...
@@ -13255,7 +13704,7 @@ function useModel() {
13255
13704
  /**
13256
13705
  * Gets the doc API.
13257
13706
  * @entry
13258
- * @returns {enigma.Doc|undefined} The doc API.
13707
+ * @returns {EngineAPI.IApp|undefined} The doc API.
13259
13708
  * @example
13260
13709
  * import { useApp } from '@nebula.js/stardust';
13261
13710
  * // ...
@@ -13274,7 +13723,7 @@ function useApp() {
13274
13723
  /**
13275
13724
  * Gets the global API.
13276
13725
  * @entry
13277
- * @returns {enigma.Global|undefined} The global API.
13726
+ * @returns {EngineAPI.IGlobal|undefined} The global API.
13278
13727
  * @example
13279
13728
  * import { useGlobal } from '@nebula.js/stardust';
13280
13729
  *
@@ -13479,9 +13928,11 @@ function useAction(fn, deps) {
13479
13928
  * @example
13480
13929
  * // configure embed to disallow active interactions when rendering
13481
13930
  * embed(app, {
13482
- * constraints: {
13483
- * active: true, // do not allow interactions
13484
- * }
13931
+ * context: {
13932
+ * constraints: {
13933
+ * active: true, // do not allow interactions
13934
+ * }
13935
+ * }
13485
13936
  * }).render({ element, id: 'sdfsdf' });
13486
13937
  *
13487
13938
  * @example
@@ -13599,7 +14050,7 @@ function useImperativeHandle(fn, deps) {
13599
14050
  /**
13600
14051
  * Registers a callback that is called when a snapshot is taken.
13601
14052
  * @entry
13602
- * @param {function(qae.GenericObjectLayout): Promise<qae.GenericObjectLayout>} snapshotCallback
14053
+ * @param {function(EngineAPI.IGenericObjectLayout): Promise<EngineAPI.IGenericObjectLayout>} snapshotCallback
13603
14054
  * @example
13604
14055
  * import { onTakeSnapshot } from '@nebula.js/stardust';
13605
14056
  * import { useState } from '@nebula.js/stardust';
@@ -13625,13 +14076,19 @@ function onTakeSnapshot(cb) {
13625
14076
 
13626
14077
  h.fn = cb;
13627
14078
  }
14079
+ /**
14080
+ * @interface RenderState
14081
+ * @property {any} pending
14082
+ * @property {any} restore
14083
+ */
14084
+
13628
14085
  /**
13629
14086
  * Gets render state instance.
13630
14087
  *
13631
14088
  * Used to update properties and get a new layout without triggering onInitialRender.
13632
14089
  * @entry
13633
14090
  * @experimental
13634
- * @returns {{ pending, restore }} The render state.
14091
+ * @returns {RenderState} The render state.
13635
14092
  * @example
13636
14093
  * import { useRenderState } from '@nebula.js/stardust';
13637
14094
  *
@@ -14191,7 +14648,7 @@ const noop = () => {};
14191
14648
 
14192
14649
  /**
14193
14650
  * @interface QAEDefinition
14194
- * @property {qae.GenericObjectProperties=} properties
14651
+ * @property {EngineAPI.IGenericObjectProperties=} properties
14195
14652
  * @property {object=} data
14196
14653
  * @property {DataTarget[]} data.targets
14197
14654
  * @property {importProperties=} importProperties
@@ -14201,8 +14658,23 @@ const noop = () => {};
14201
14658
  /**
14202
14659
  * @interface DataTarget
14203
14660
  * @property {string} path
14204
- * @property {FieldTarget<qae.NxDimension>=} dimensions
14205
- * @property {FieldTarget<qae.NxMeasure>=} measures
14661
+ * @property {FieldTarget<EngineAPI.INxDimension>=} dimensions
14662
+ * @property {FieldTarget<EngineAPI.INxMeasure>=} measures
14663
+ */
14664
+
14665
+ /**
14666
+ * @callback fieldTargetAddedCallback
14667
+ * @template T
14668
+ * @param {T} field
14669
+ * @param {EngineAPI.IGenericObjectProperties} properties
14670
+ */
14671
+
14672
+ /**
14673
+ * @callback fieldTargetRemovedCallback
14674
+ * @template T
14675
+ * @param {T} field
14676
+ * @param {EngineAPI.IGenericObjectProperties} properties
14677
+ * @param {number} index
14206
14678
  */
14207
14679
 
14208
14680
  /**
@@ -14210,8 +14682,8 @@ const noop = () => {};
14210
14682
  * @template T
14211
14683
  * @property {function():number} [min]
14212
14684
  * @property {function():number} [max]
14213
- * @property {function(T, qae.GenericObjectProperties)} [added]
14214
- * @property {function(T, qae.GenericObjectProperties, number)} [removed]
14685
+ * @property {fieldTargetAddedCallback<T>} [added]
14686
+ * @property {fieldTargetRemovedCallback<T>} [removed]
14215
14687
  */
14216
14688
 
14217
14689
 
@@ -15999,7 +16471,7 @@ function clearFromCache(name) {
15999
16471
  /**
16000
16472
  * @interface TypeInfo
16001
16473
  * @property {string} name
16002
- * @property {string} version
16474
+ * @property {string=} version
16003
16475
  * @property {LoadType} load
16004
16476
  * @property {object=} meta
16005
16477
  */
@@ -16159,6 +16631,7 @@ function create(_ref) {
16159
16631
 
16160
16632
  /**
16161
16633
  * @interface Context
16634
+ * @property {boolean=} disableCellPadding
16162
16635
  * @property {boolean=} keyboardNavigation
16163
16636
  * @property {object=} constraints
16164
16637
  * @property {boolean=} constraints.active
@@ -16178,7 +16651,8 @@ const DEFAULT_CONTEXT =
16178
16651
  /** @type {string=} */
16179
16652
  deviceType: 'auto',
16180
16653
  constraints: {},
16181
- keyboardNavigation: false
16654
+ keyboardNavigation: false,
16655
+ disableCellPadding: false
16182
16656
  };
16183
16657
  /**
16184
16658
  * @interface SnapshotConfiguration
@@ -16280,7 +16754,7 @@ function nuked() {
16280
16754
  * Initiates a new `Embed` instance using the specified enigma `app`.
16281
16755
  * @entry
16282
16756
  * @function embed
16283
- * @param {enigma.Doc} app
16757
+ * @param {EngineAPI.IApp} app
16284
16758
  * @param {Configuration=} instanceConfig
16285
16759
  * @returns {Embed}
16286
16760
  * @example
@@ -16499,6 +16973,10 @@ function nuked() {
16499
16973
  if (!fieldName) {
16500
16974
  throw new Error("Field identifier must be provided");
16501
16975
  }
16976
+ /**
16977
+ * @typedef {function(function)} ReceiverFunction A callback function which receives another function as input.
16978
+ */
16979
+
16502
16980
  /**
16503
16981
  * @class
16504
16982
  * @alias FieldInstance
@@ -16516,10 +16994,18 @@ function nuked() {
16516
16994
  * @param {string=} options.title Custom title, defaults to fieldname
16517
16995
  * @param {string=} [options.direction=ltr] Direction setting ltr|rtl.
16518
16996
  * @param {string=} [options.listLayout=vertical] Layout direction vertical|horizontal
16519
- * @param {boolean=} [options.search=true] To show the search bar
16997
+ * @param {boolean=} [options.search=true] Show the search bar
16998
+ * @param {boolean=} [options.toolbar=true] Show the toolbar
16999
+ * @param {boolean=} [options.checkboxes=false] Show values as checkboxes instead of as fields
17000
+ * @param {boolean=} [options.rangeSelect=true] Enable range selection
17001
+ * @param {boolean=} [options.dense=false] Reduces padding and text size
16520
17002
  * @param {boolean=} [options.stateName="$"] Sets the state to make selections in
16521
17003
  * @param {object=} [options.properties={}] Properties object to extend default properties with
17004
+ * @param {object} [options.sessionModel] Use a custom sessionModel.
17005
+ * @param {object} [options.selectionsApi] Use a custom selectionsApi to customize how values are selected.
17006
+ * @param {ReceiverFunction} [options.update] A function which receives an update function which upon call will trigger a data fetch.
16522
17007
  * @since 1.1.0
17008
+ * @instance
16523
17009
  * @example
16524
17010
  * fieldInstance.mount(element);
16525
17011
  */
@@ -16547,6 +17033,7 @@ function nuked() {
16547
17033
  /**
16548
17034
  * Unmounts the field listbox from the DOM.
16549
17035
  * @since 1.1.0
17036
+ * @instance
16550
17037
  * @example
16551
17038
  * listbox.unmount();
16552
17039
  */
@@ -16605,7 +17092,9 @@ function nuked() {
16605
17092
  * // create an alternate config with dark theme
16606
17093
  * // and inherit the config from the previous
16607
17094
  * const d = m.createConfiguration({
16608
- * theme: 'dark'
17095
+ * context: {
17096
+ * theme: 'dark'
17097
+ * }
16609
17098
  * });
16610
17099
  *
16611
17100
  * m(app).render({ type: 'mekko' }); // will render the object with default theme
@@ -16619,6 +17108,10 @@ function nuked() {
16619
17108
  embed.config = configuration;
16620
17109
  return embed;
16621
17110
  }
17111
+ /**
17112
+ * @typedef {any} ThemeJSON
17113
+ */
17114
+
16622
17115
  /**
16623
17116
  * @interface ThemeInfo
16624
17117
  * @property {string} id Theme identifier