@nebula.js/stardust 1.7.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /*
2
- * @nebula.js/stardust v1.7.0
2
+ * @nebula.js/stardust v2.2.0
3
3
  * Copyright (c) 2021 QlikTech International AB
4
4
  * Released under the MIT license.
5
5
  */
@@ -8,7 +8,7 @@
8
8
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
9
9
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
10
10
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.stardust = {}));
11
- }(this, (function (exports) { 'use strict';
11
+ })(this, (function (exports) { 'use strict';
12
12
 
13
13
  function ownKeys(object, enumerableOnly) {
14
14
  var keys = Object.keys(object);
@@ -11479,7 +11479,7 @@
11479
11479
  return [appSelections, navState];
11480
11480
  }
11481
11481
 
11482
- var NEBULA_VERSION_HASH = "6a15" ;
11482
+ var NEBULA_VERSION_HASH = "34e9" ;
11483
11483
  var counter = 0;
11484
11484
  var NebulaApp = react.exports.forwardRef(function (_ref, ref) {
11485
11485
  var initialContext = _ref.initialContext,
@@ -11555,7 +11555,7 @@
11555
11555
  var appRef = React.createRef();
11556
11556
  var element = document.createElement('div');
11557
11557
  element.style.display = 'none';
11558
- element.setAttribute('data-nebulajs-version', "1.7.0" );
11558
+ element.setAttribute('data-nebulajs-version', "2.2.0" );
11559
11559
  element.setAttribute('data-app-id', app.id);
11560
11560
  document.body.appendChild(element);
11561
11561
  ReactDOM.render( /*#__PURE__*/React.createElement(NebulaApp, {
@@ -11563,7 +11563,17 @@
11563
11563
  app: app,
11564
11564
  initialContext: context
11565
11565
  }), element, resolveRender);
11566
+ var cells = {};
11566
11567
  return [{
11568
+ toggleFocusOfCells: function toggleFocusOfCells(cellIdToFocus) {
11569
+ Object.keys(cells).forEach(function (i) {
11570
+ cells[i].current.toggleFocus(i === cellIdToFocus);
11571
+ });
11572
+ },
11573
+ cells: cells,
11574
+ addCell: function addCell(id, cell) {
11575
+ cells[id] = cell;
11576
+ },
11567
11577
  add: function add(component) {
11568
11578
  _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
11569
11579
  return regeneratorRuntime.wrap(function _callee$(_context) {
@@ -19499,6 +19509,16 @@
19499
19509
  };
19500
19510
  }
19501
19511
 
19512
+ /**
19513
+ * @interface
19514
+ * @extends HTMLElement
19515
+ * @since 2.0.0
19516
+ */
19517
+
19518
+ var ActionElement = {
19519
+ /** @type {'njs-cell-action'} */
19520
+ className: 'njs-cell-action'
19521
+ };
19502
19522
  var Item = React.forwardRef(function (_ref, ref) {
19503
19523
  var item = _ref.item,
19504
19524
  _ref$addAnchor = _ref.addAnchor,
@@ -19516,8 +19536,12 @@
19516
19536
  ref: !addAnchor ? ref : null,
19517
19537
  title: item.label,
19518
19538
  onClick: item.action,
19539
+ onKeyDown: function onKeyDown(e) {
19540
+ return ['Enter', ' ', 'Spacebar'].includes(e.key) && item.keyboardAction();
19541
+ },
19519
19542
  disabled: disabled,
19520
- style: style
19543
+ style: style,
19544
+ className: ActionElement.className
19521
19545
  }, hasSvgIconShape && SvgIcon(item.getSvgIconShape()), addAnchor && /*#__PURE__*/React.createElement("div", {
19522
19546
  ref: ref,
19523
19547
  style: {
@@ -19561,7 +19585,9 @@
19561
19585
  _ref$onConfirm = _ref.onConfirm,
19562
19586
  onConfirm = _ref$onConfirm === void 0 ? function () {} : _ref$onConfirm,
19563
19587
  _ref$onCancel = _ref.onCancel,
19564
- onCancel = _ref$onCancel === void 0 ? function () {} : _ref$onCancel;
19588
+ onCancel = _ref$onCancel === void 0 ? function () {} : _ref$onCancel,
19589
+ _ref$onKeyDeactivate = _ref.onKeyDeactivate,
19590
+ onKeyDeactivate = _ref$onKeyDeactivate === void 0 ? function () {} : _ref$onKeyDeactivate;
19565
19591
 
19566
19592
  var _useContext = react.exports.useContext(InstanceContext),
19567
19593
  translator = _useContext.translator;
@@ -19585,8 +19611,13 @@
19585
19611
  return api.canCancel();
19586
19612
  },
19587
19613
  action: function action() {
19614
+ onCancel();
19588
19615
  api.cancel();
19616
+ },
19617
+ keyboardAction: function keyboardAction(e) {
19618
+ onKeyDeactivate(e);
19589
19619
  onCancel();
19620
+ api.cancel();
19590
19621
  },
19591
19622
  getSvgIconShape: close
19592
19623
  }, {
@@ -19597,8 +19628,13 @@
19597
19628
  return api.canConfirm();
19598
19629
  },
19599
19630
  action: function action() {
19631
+ onConfirm();
19600
19632
  api.confirm();
19633
+ },
19634
+ keyboardAction: function keyboardAction(e) {
19635
+ onKeyDeactivate(e);
19601
19636
  onConfirm();
19637
+ api.confirm();
19602
19638
  },
19603
19639
  getSvgIconShape: tick
19604
19640
  }];
@@ -19695,6 +19731,16 @@
19695
19731
  })));
19696
19732
  });
19697
19733
 
19734
+ /**
19735
+ * @interface
19736
+ * @extends HTMLElement
19737
+ * @since 2.1.0
19738
+ */
19739
+
19740
+ var ActionToolbarElement = {
19741
+ /** @type {'njs-action-toolbar-popover'} */
19742
+ className: 'njs-action-toolbar-popover'
19743
+ };
19698
19744
  var useStyles$8 = makeStyles(function (theme) {
19699
19745
  return {
19700
19746
  itemSpacing: {
@@ -19795,14 +19841,19 @@
19795
19841
  popover = _ref2$popover === void 0 ? {
19796
19842
  show: false,
19797
19843
  anchorEl: null
19798
- } : _ref2$popover;
19844
+ } : _ref2$popover,
19845
+ _ref2$focusHandler = _ref2.focusHandler,
19846
+ focusHandler = _ref2$focusHandler === void 0 ? null : _ref2$focusHandler,
19847
+ _ref2$actionsRefMock = _ref2.actionsRefMock,
19848
+ actionsRefMock = _ref2$actionsRefMock === void 0 ? null : _ref2$actionsRefMock;
19799
19849
  var defaultSelectionActions = useDefaultSelectionActions(selections);
19800
19850
 
19801
19851
  var _useStyles2 = useStyles$8(),
19802
19852
  itemSpacing = _useStyles2.itemSpacing;
19803
19853
 
19804
19854
  var _useContext = react.exports.useContext(InstanceContext),
19805
- translator = _useContext.translator;
19855
+ translator = _useContext.translator,
19856
+ keyboardNavigation = _useContext.keyboardNavigation;
19806
19857
 
19807
19858
  var _useState = react.exports.useState(false),
19808
19859
  _useState2 = _slicedToArray$2(_useState, 2),
@@ -19825,12 +19876,21 @@
19825
19876
  setMoreAlignTo = _useState8[1];
19826
19877
 
19827
19878
  var moreRef = react.exports.useRef();
19879
+ var actionsRef = react.exports.useRef();
19828
19880
  var theme = useTheme$2();
19829
19881
  var dividerStyle = react.exports.useMemo(function () {
19830
19882
  return {
19831
19883
  margin: theme.spacing(0.5, 0)
19832
19884
  };
19833
19885
  });
19886
+
19887
+ var getEnabledButton = function getEnabledButton(last) {
19888
+ var actionsElement = actionsRef.current || actionsRefMock;
19889
+ if (!actionsElement) return null;
19890
+ var buttons = actionsElement.querySelectorAll('button:not(.Mui-disabled)');
19891
+ return buttons[last ? buttons.length - 1 : 0];
19892
+ };
19893
+
19834
19894
  react.exports.useEffect(function () {
19835
19895
  return function () {
19836
19896
  return setShowMoreItems(false);
@@ -19839,6 +19899,22 @@
19839
19899
  react.exports.useEffect(function () {
19840
19900
  setMoreEnabled(more$1.enabled);
19841
19901
  }, [more$1.enabled]);
19902
+ react.exports.useEffect(function () {
19903
+ if (!focusHandler) return;
19904
+
19905
+ var focusFirst = function focusFirst() {
19906
+ var enabledButton = getEnabledButton(false);
19907
+ enabledButton && enabledButton.focus();
19908
+ };
19909
+
19910
+ var focusLast = function focusLast() {
19911
+ var enabledButton = getEnabledButton(true);
19912
+ enabledButton && enabledButton.focus();
19913
+ };
19914
+
19915
+ focusHandler.on('focus_toolbar_first', focusFirst);
19916
+ focusHandler.on('focus_toolbar_last', focusLast);
19917
+ }, []);
19842
19918
  var newActions = react.exports.useMemo(function () {
19843
19919
  return actions.filter(function (a) {
19844
19920
  return !a.hidden;
@@ -19871,10 +19947,23 @@
19871
19947
  setMoreAlignTo(moreRef);
19872
19948
  }
19873
19949
 
19950
+ var tabCallback = // if keyboardNavigation is true, create a callback to handle tabbing from the first/last button in the toolbar that resets focus on the content
19951
+ keyboardNavigation && focusHandler && focusHandler.refocusContent ? function (evt) {
19952
+ if (evt.key !== 'Tab') return;
19953
+ var isTabbingOut = evt.shiftKey && getEnabledButton(false) === evt.target || !evt.shiftKey && getEnabledButton(true) === evt.target;
19954
+
19955
+ if (isTabbingOut) {
19956
+ evt.preventDefault();
19957
+ evt.stopPropagation();
19958
+ focusHandler.refocusContent();
19959
+ }
19960
+ } : null;
19874
19961
  var showActions = newActions.length > 0;
19875
19962
  var showMore = moreActions.length > 0;
19876
19963
  var showDivider = showActions && selections.show || showMore && selections.show;
19877
19964
  var Actions = /*#__PURE__*/React.createElement(Grid$1, {
19965
+ ref: actionsRef,
19966
+ onKeyDown: tabCallback,
19878
19967
  container: true,
19879
19968
  spacing: 0,
19880
19969
  wrap: "nowrap"
@@ -19917,6 +20006,7 @@
19917
20006
  hideBackdrop: true,
19918
20007
  style: popoverStyle,
19919
20008
  PaperProps: {
20009
+ className: ActionToolbarElement.className,
19920
20010
  style: {
19921
20011
  pointerEvents: 'auto',
19922
20012
  padding: theme.spacing(1, 1)
@@ -19952,7 +20042,9 @@
19952
20042
  });
19953
20043
  var TREE_PATH = '/qListObjectDef';
19954
20044
  function ListBoxSearch(_ref) {
19955
- var model = _ref.model;
20045
+ var model = _ref.model,
20046
+ _ref$autoFocus = _ref.autoFocus,
20047
+ autoFocus = _ref$autoFocus === void 0 ? true : _ref$autoFocus;
19956
20048
 
19957
20049
  var _useContext = react.exports.useContext(InstanceContext),
19958
20050
  translator = _useContext.translator;
@@ -19986,7 +20078,7 @@
19986
20078
  position: "start"
19987
20079
  }, /*#__PURE__*/React.createElement(Search, null)),
19988
20080
  className: [classes.root].join(' '),
19989
- autoFocus: true,
20081
+ autoFocus: autoFocus,
19990
20082
  margin: "dense",
19991
20083
  fullWidth: true,
19992
20084
  placeholder: translator.get('Listbox.Search'),
@@ -21246,6 +21338,106 @@
21246
21338
  }), element);
21247
21339
  }
21248
21340
 
21341
+ var classCallCheck = function (instance, Constructor) {
21342
+ if (!(instance instanceof Constructor)) {
21343
+ throw new TypeError("Cannot call a class as a function");
21344
+ }
21345
+ };
21346
+
21347
+ var createClass = function () {
21348
+ function defineProperties(target, props) {
21349
+ for (var i = 0; i < props.length; i++) {
21350
+ var descriptor = props[i];
21351
+ descriptor.enumerable = descriptor.enumerable || false;
21352
+ descriptor.configurable = true;
21353
+ if ("value" in descriptor) descriptor.writable = true;
21354
+ Object.defineProperty(target, descriptor.key, descriptor);
21355
+ }
21356
+ }
21357
+
21358
+ return function (Constructor, protoProps, staticProps) {
21359
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
21360
+ if (staticProps) defineProperties(Constructor, staticProps);
21361
+ return Constructor;
21362
+ };
21363
+ }();
21364
+
21365
+ var _extends = Object.assign || function (target) {
21366
+ for (var i = 1; i < arguments.length; i++) {
21367
+ var source = arguments[i];
21368
+
21369
+ for (var key in source) {
21370
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
21371
+ target[key] = source[key];
21372
+ }
21373
+ }
21374
+ }
21375
+
21376
+ return target;
21377
+ };
21378
+
21379
+ var inherits = function (subClass, superClass) {
21380
+ if (typeof superClass !== "function" && superClass !== null) {
21381
+ throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
21382
+ }
21383
+
21384
+ subClass.prototype = Object.create(superClass && superClass.prototype, {
21385
+ constructor: {
21386
+ value: subClass,
21387
+ enumerable: false,
21388
+ writable: true,
21389
+ configurable: true
21390
+ }
21391
+ });
21392
+ if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
21393
+ };
21394
+
21395
+ var possibleConstructorReturn = function (self, call) {
21396
+ if (!self) {
21397
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
21398
+ }
21399
+
21400
+ return call && (typeof call === "object" || typeof call === "function") ? call : self;
21401
+ };
21402
+
21403
+ var slicedToArray = function () {
21404
+ function sliceIterator(arr, i) {
21405
+ var _arr = [];
21406
+ var _n = true;
21407
+ var _d = false;
21408
+ var _e = undefined;
21409
+
21410
+ try {
21411
+ for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
21412
+ _arr.push(_s.value);
21413
+
21414
+ if (i && _arr.length === i) break;
21415
+ }
21416
+ } catch (err) {
21417
+ _d = true;
21418
+ _e = err;
21419
+ } finally {
21420
+ try {
21421
+ if (!_n && _i["return"]) _i["return"]();
21422
+ } finally {
21423
+ if (_d) throw _e;
21424
+ }
21425
+ }
21426
+
21427
+ return _arr;
21428
+ }
21429
+
21430
+ return function (arr, i) {
21431
+ if (Array.isArray(arr)) {
21432
+ return arr;
21433
+ } else if (Symbol.iterator in Object(arr)) {
21434
+ return sliceIterator(arr, i);
21435
+ } else {
21436
+ throw new TypeError("Invalid attempt to destructure non-iterable instance");
21437
+ }
21438
+ };
21439
+ }();
21440
+
21249
21441
  /**
21250
21442
  * Detect Element Resize.
21251
21443
  * https://github.com/sdecima/javascript-detect-element-resize
@@ -21258,37 +21450,77 @@
21258
21450
  * 4) Add nonce for style element.
21259
21451
  **/
21260
21452
 
21261
- function createDetectElementResize(nonce) {
21262
- // Check `document` and `window` in case of server-side rendering
21263
- var _window;
21264
- if (typeof window !== 'undefined') {
21265
- _window = window;
21266
- } else if (typeof self !== 'undefined') {
21267
- _window = self;
21268
- } else {
21269
- _window = global;
21270
- }
21453
+ // Check `document` and `window` in case of server-side rendering
21454
+ var windowObject = void 0;
21455
+ if (typeof window !== 'undefined') {
21456
+ windowObject = window;
21271
21457
 
21272
- var attachEvent = typeof document !== 'undefined' && document.attachEvent;
21458
+ // eslint-disable-next-line no-restricted-globals
21459
+ } else if (typeof self !== 'undefined') {
21460
+ // eslint-disable-next-line no-restricted-globals
21461
+ windowObject = self;
21462
+ } else {
21463
+ windowObject = global;
21464
+ }
21273
21465
 
21274
- if (!attachEvent) {
21275
- var requestFrame = function () {
21276
- var raf = _window.requestAnimationFrame || _window.mozRequestAnimationFrame || _window.webkitRequestAnimationFrame || function (fn) {
21277
- return _window.setTimeout(fn, 20);
21278
- };
21279
- return function (fn) {
21280
- return raf(fn);
21281
- };
21282
- }();
21466
+ var cancelFrame = null;
21467
+ var requestFrame = null;
21283
21468
 
21284
- var cancelFrame = function () {
21285
- var cancel = _window.cancelAnimationFrame || _window.mozCancelAnimationFrame || _window.webkitCancelAnimationFrame || _window.clearTimeout;
21286
- return function (id) {
21287
- return cancel(id);
21288
- };
21289
- }();
21469
+ var TIMEOUT_DURATION = 20;
21470
+
21471
+ var clearTimeoutFn = windowObject.clearTimeout;
21472
+ var setTimeoutFn = windowObject.setTimeout;
21473
+
21474
+ var cancelAnimationFrameFn = windowObject.cancelAnimationFrame || windowObject.mozCancelAnimationFrame || windowObject.webkitCancelAnimationFrame;
21475
+
21476
+ var requestAnimationFrameFn = windowObject.requestAnimationFrame || windowObject.mozRequestAnimationFrame || windowObject.webkitRequestAnimationFrame;
21477
+
21478
+ if (cancelAnimationFrameFn == null || requestAnimationFrameFn == null) {
21479
+ // For environments that don't support animation frame,
21480
+ // fallback to a setTimeout based approach.
21481
+ cancelFrame = clearTimeoutFn;
21482
+ requestFrame = function requestAnimationFrameViaSetTimeout(callback) {
21483
+ return setTimeoutFn(callback, TIMEOUT_DURATION);
21484
+ };
21485
+ } else {
21486
+ // Counter intuitively, environments that support animation frames can be trickier.
21487
+ // Chrome's "Throttle non-visible cross-origin iframes" flag can prevent rAFs from being called.
21488
+ // In this case, we should fallback to a setTimeout() implementation.
21489
+ cancelFrame = function cancelFrame(_ref) {
21490
+ var _ref2 = slicedToArray(_ref, 2),
21491
+ animationFrameID = _ref2[0],
21492
+ timeoutID = _ref2[1];
21493
+
21494
+ cancelAnimationFrameFn(animationFrameID);
21495
+ clearTimeoutFn(timeoutID);
21496
+ };
21497
+ requestFrame = function requestAnimationFrameWithSetTimeoutFallback(callback) {
21498
+ var animationFrameID = requestAnimationFrameFn(function animationFrameCallback() {
21499
+ clearTimeoutFn(timeoutID);
21500
+ callback();
21501
+ });
21502
+
21503
+ var timeoutID = setTimeoutFn(function timeoutCallback() {
21504
+ cancelAnimationFrameFn(animationFrameID);
21505
+ callback();
21506
+ }, TIMEOUT_DURATION);
21290
21507
 
21291
- var resetTriggers = function resetTriggers(element) {
21508
+ return [animationFrameID, timeoutID];
21509
+ };
21510
+ }
21511
+
21512
+ function createDetectElementResize(nonce) {
21513
+ var animationKeyframes = void 0;
21514
+ var animationName = void 0;
21515
+ var animationStartEvent = void 0;
21516
+ var animationStyle = void 0;
21517
+ var checkTriggers = void 0;
21518
+ var resetTriggers = void 0;
21519
+ var scrollListener = void 0;
21520
+
21521
+ var attachEvent = typeof document !== 'undefined' && document.attachEvent;
21522
+ if (!attachEvent) {
21523
+ resetTriggers = function resetTriggers(element) {
21292
21524
  var triggers = element.__resizeTriggers__,
21293
21525
  expand = triggers.firstElementChild,
21294
21526
  contract = triggers.lastElementChild,
@@ -21301,11 +21533,11 @@
21301
21533
  expand.scrollTop = expand.scrollHeight;
21302
21534
  };
21303
21535
 
21304
- var checkTriggers = function checkTriggers(element) {
21305
- return element.offsetWidth != element.__resizeLast__.width || element.offsetHeight != element.__resizeLast__.height;
21536
+ checkTriggers = function checkTriggers(element) {
21537
+ return element.offsetWidth !== element.__resizeLast__.width || element.offsetHeight !== element.__resizeLast__.height;
21306
21538
  };
21307
21539
 
21308
- var scrollListener = function scrollListener(e) {
21540
+ scrollListener = function scrollListener(e) {
21309
21541
  // Don't measure (which forces) reflow for scrolls that happen inside of children!
21310
21542
  if (e.target.className && typeof e.target.className.indexOf === 'function' && e.target.className.indexOf('contract-trigger') < 0 && e.target.className.indexOf('expand-trigger') < 0) {
21311
21543
  return;
@@ -21316,11 +21548,11 @@
21316
21548
  if (this.__resizeRAF__) {
21317
21549
  cancelFrame(this.__resizeRAF__);
21318
21550
  }
21319
- this.__resizeRAF__ = requestFrame(function () {
21551
+ this.__resizeRAF__ = requestFrame(function animationFrame() {
21320
21552
  if (checkTriggers(element)) {
21321
21553
  element.__resizeLast__.width = element.offsetWidth;
21322
21554
  element.__resizeLast__.height = element.offsetHeight;
21323
- element.__resizeListeners__.forEach(function (fn) {
21555
+ element.__resizeListeners__.forEach(function forEachResizeListener(fn) {
21324
21556
  fn.call(element, e);
21325
21557
  });
21326
21558
  }
@@ -21328,12 +21560,12 @@
21328
21560
  };
21329
21561
 
21330
21562
  /* Detect CSS Animations support to detect element display/re-attach */
21331
- var animation = false,
21332
- keyframeprefix = '',
21333
- animationstartevent = 'animationstart',
21334
- domPrefixes = 'Webkit Moz O ms'.split(' '),
21335
- startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '),
21336
- pfx = '';
21563
+ var animation = false;
21564
+ var keyframeprefix = '';
21565
+ animationStartEvent = 'animationstart';
21566
+ var domPrefixes = 'Webkit Moz O ms'.split(' ');
21567
+ var startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' ');
21568
+ var pfx = '';
21337
21569
  {
21338
21570
  var elm = document.createElement('fakeelement');
21339
21571
  if (elm.style.animationName !== undefined) {
@@ -21345,7 +21577,7 @@
21345
21577
  if (elm.style[domPrefixes[i] + 'AnimationName'] !== undefined) {
21346
21578
  pfx = domPrefixes[i];
21347
21579
  keyframeprefix = '-' + pfx.toLowerCase() + '-';
21348
- animationstartevent = startEvents[i];
21580
+ animationStartEvent = startEvents[i];
21349
21581
  animation = true;
21350
21582
  break;
21351
21583
  }
@@ -21353,9 +21585,9 @@
21353
21585
  }
21354
21586
  }
21355
21587
 
21356
- var animationName = 'resizeanim';
21357
- var animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } ';
21358
- var animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; ';
21588
+ animationName = 'resizeanim';
21589
+ animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } ';
21590
+ animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; ';
21359
21591
  }
21360
21592
 
21361
21593
  var createStyles = function createStyles(doc) {
@@ -21388,8 +21620,8 @@
21388
21620
  } else {
21389
21621
  if (!element.__resizeTriggers__) {
21390
21622
  var doc = element.ownerDocument;
21391
- var elementStyle = _window.getComputedStyle(element);
21392
- if (elementStyle && elementStyle.position == 'static') {
21623
+ var elementStyle = windowObject.getComputedStyle(element);
21624
+ if (elementStyle && elementStyle.position === 'static') {
21393
21625
  element.style.position = 'relative';
21394
21626
  }
21395
21627
  createStyles(doc);
@@ -21408,13 +21640,13 @@
21408
21640
  element.addEventListener('scroll', scrollListener, true);
21409
21641
 
21410
21642
  /* Listen for a css animation to detect element display/re-attach */
21411
- if (animationstartevent) {
21643
+ if (animationStartEvent) {
21412
21644
  element.__resizeTriggers__.__animationListener__ = function animationListener(e) {
21413
- if (e.animationName == animationName) {
21645
+ if (e.animationName === animationName) {
21414
21646
  resetTriggers(element);
21415
21647
  }
21416
21648
  };
21417
- element.__resizeTriggers__.addEventListener(animationstartevent, element.__resizeTriggers__.__animationListener__);
21649
+ element.__resizeTriggers__.addEventListener(animationStartEvent, element.__resizeTriggers__.__animationListener__);
21418
21650
  }
21419
21651
  }
21420
21652
  element.__resizeListeners__.push(fn);
@@ -21429,7 +21661,7 @@
21429
21661
  if (!element.__resizeListeners__.length) {
21430
21662
  element.removeEventListener('scroll', scrollListener, true);
21431
21663
  if (element.__resizeTriggers__.__animationListener__) {
21432
- element.__resizeTriggers__.removeEventListener(animationstartevent, element.__resizeTriggers__.__animationListener__);
21664
+ element.__resizeTriggers__.removeEventListener(animationStartEvent, element.__resizeTriggers__.__animationListener__);
21433
21665
  element.__resizeTriggers__.__animationListener__ = null;
21434
21666
  }
21435
21667
  try {
@@ -21447,68 +21679,6 @@
21447
21679
  };
21448
21680
  }
21449
21681
 
21450
- var classCallCheck = function (instance, Constructor) {
21451
- if (!(instance instanceof Constructor)) {
21452
- throw new TypeError("Cannot call a class as a function");
21453
- }
21454
- };
21455
-
21456
- var createClass = function () {
21457
- function defineProperties(target, props) {
21458
- for (var i = 0; i < props.length; i++) {
21459
- var descriptor = props[i];
21460
- descriptor.enumerable = descriptor.enumerable || false;
21461
- descriptor.configurable = true;
21462
- if ("value" in descriptor) descriptor.writable = true;
21463
- Object.defineProperty(target, descriptor.key, descriptor);
21464
- }
21465
- }
21466
-
21467
- return function (Constructor, protoProps, staticProps) {
21468
- if (protoProps) defineProperties(Constructor.prototype, protoProps);
21469
- if (staticProps) defineProperties(Constructor, staticProps);
21470
- return Constructor;
21471
- };
21472
- }();
21473
-
21474
- var _extends = Object.assign || function (target) {
21475
- for (var i = 1; i < arguments.length; i++) {
21476
- var source = arguments[i];
21477
-
21478
- for (var key in source) {
21479
- if (Object.prototype.hasOwnProperty.call(source, key)) {
21480
- target[key] = source[key];
21481
- }
21482
- }
21483
- }
21484
-
21485
- return target;
21486
- };
21487
-
21488
- var inherits = function (subClass, superClass) {
21489
- if (typeof superClass !== "function" && superClass !== null) {
21490
- throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
21491
- }
21492
-
21493
- subClass.prototype = Object.create(superClass && superClass.prototype, {
21494
- constructor: {
21495
- value: subClass,
21496
- enumerable: false,
21497
- writable: true,
21498
- configurable: true
21499
- }
21500
- });
21501
- if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
21502
- };
21503
-
21504
- var possibleConstructorReturn = function (self, call) {
21505
- if (!self) {
21506
- throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
21507
- }
21508
-
21509
- return call && (typeof call === "object" || typeof call === "function") ? call : self;
21510
- };
21511
-
21512
21682
  var AutoSizer = function (_React$PureComponent) {
21513
21683
  inherits(AutoSizer, _React$PureComponent);
21514
21684
 
@@ -21635,7 +21805,8 @@
21635
21805
  {
21636
21806
  className: className,
21637
21807
  ref: this._setRef,
21638
- style: _extends({}, outerStyle, style) },
21808
+ style: _extends({}, outerStyle, style)
21809
+ },
21639
21810
  !bailoutOnChildren && children(childParams)
21640
21811
  );
21641
21812
  }
@@ -21830,7 +22001,8 @@
21830
22001
  }))), search ? /*#__PURE__*/React.createElement(Grid$1, {
21831
22002
  item: true
21832
22003
  }, /*#__PURE__*/React.createElement(ListBoxSearch, {
21833
- model: model
22004
+ model: model,
22005
+ autoFocus: false
21834
22006
  })) : '', /*#__PURE__*/React.createElement(Grid$1, {
21835
22007
  item: true,
21836
22008
  xs: true
@@ -22010,7 +22182,9 @@
22010
22182
 
22011
22183
  function fieldType(f) {
22012
22184
  if ( // a string starting with '=' is just a convention we use
22013
- typeof f === 'string' && f[0] === '=' || _typeof$3(f) === 'object' && f.qDef && f.qDef.qDef || _typeof$3(f) === 'object' && f.qLibraryId && f.type === 'measure') {
22185
+ typeof f === 'string' && f[0] === '=' || // based on NxMeasure and NxInlineMeasureDef
22186
+ _typeof$3(f) === 'object' && f.qDef && f.qDef.qDef || // use 'type' instead of 'qType' since this is not a real property
22187
+ _typeof$3(f) === 'object' && f.qLibraryId && f.type === 'measure') {
22014
22188
  return 'measure';
22015
22189
  }
22016
22190
 
@@ -22067,14 +22241,12 @@
22067
22241
  * An object that imports from this structure is responsible for putting the existing properties where they should be
22068
22242
  * in the new model.
22069
22243
  * @interface ExportFormat
22070
- * @experimental
22071
22244
  * @since 1.1.0
22072
22245
  * @property {(ExportDataDef[])=} data
22073
22246
  * @property {object=} properties
22074
22247
  */
22075
22248
 
22076
22249
  /**
22077
- * @experimental
22078
22250
  * @since 1.1.0
22079
22251
  * @interface ExportDataDef
22080
22252
  * @property {qae.NxDimension[]} dimensions
@@ -22085,7 +22257,6 @@
22085
22257
  */
22086
22258
 
22087
22259
  /**
22088
- * @experimental
22089
22260
  * @since 1.1.0
22090
22261
  * @ignore
22091
22262
  * @param {number} nDataGroups
@@ -22859,7 +23030,6 @@
22859
23030
 
22860
23031
  /**
22861
23032
  * @interface hyperCubeConversion
22862
- * @experimental
22863
23033
  * @since 1.1.0
22864
23034
  * @implements {ConversionType}
22865
23035
  */
@@ -23006,7 +23176,6 @@
23006
23176
  }();
23007
23177
  /**
23008
23178
  * @interface ConversionType
23009
- * @experimental
23010
23179
  * @since 1.1.0
23011
23180
  * @property {importProperties} importProperties
23012
23181
  * @property {exportProperties} exportProperties
@@ -23015,7 +23184,6 @@
23015
23184
  /**
23016
23185
  * @interface
23017
23186
  * @alias Conversion
23018
- * @experimental
23019
23187
  * @since 1.1.0
23020
23188
  * @description Provides conversion functionality to extensions.
23021
23189
  * @example
@@ -23037,7 +23205,6 @@
23037
23205
  var conversion = {
23038
23206
  /**
23039
23207
  * @type {hyperCubeConversion}
23040
- * @experimental
23041
23208
  * @since 1.1.0
23042
23209
  * @description Provides conversion functionality to extensions with hyperCubes.
23043
23210
  */
@@ -23371,6 +23538,26 @@
23371
23538
  var DIVIDER = 1;
23372
23539
  var NUMBER_OF_ITEMS = 6;
23373
23540
  var MIN_WIDTH = (ITEM_WIDTH + ITEM_SPACING) * NUMBER_OF_ITEMS + DIVIDER + ITEM_SPACING;
23541
+ /**
23542
+ * @interface
23543
+ * @extends HTMLElement
23544
+ * @since 2.0.0
23545
+ */
23546
+
23547
+ var CellTitle = {
23548
+ /** @type {'njs-cell-title'} */
23549
+ className: 'njs-cell-title'
23550
+ };
23551
+ /**
23552
+ * @interface
23553
+ * @extends HTMLElement
23554
+ * @since 2.0.0
23555
+ */
23556
+
23557
+ var CellSubTitle = {
23558
+ /** @type {'njs-cell-sub-title'} */
23559
+ className: 'njs-cell-sub-title'
23560
+ };
23374
23561
  var useStyles$1 = makeStyles(function (theme) {
23375
23562
  return {
23376
23563
  containerStyle: {
@@ -23386,7 +23573,8 @@
23386
23573
  var layout = _ref.layout,
23387
23574
  sn = _ref.sn,
23388
23575
  anchorEl = _ref.anchorEl,
23389
- hovering = _ref.hovering;
23576
+ hovering = _ref.hovering,
23577
+ focusHandler = _ref.focusHandler;
23390
23578
  var showTitle = layout.showTitles && !!layout.title;
23391
23579
  var showSubtitle = layout.showTitles && !!layout.subtitle;
23392
23580
  var showInSelectionActions = layout.qSelectionInfo && layout.qSelectionInfo.qInSelections;
@@ -23432,13 +23620,15 @@
23432
23620
  show: showToolbar,
23433
23621
  selections: {
23434
23622
  show: showInSelectionActions,
23435
- api: sn.component.selections
23623
+ api: sn.component.selections,
23624
+ onKeyDeactivate: focusHandler.refocusContent
23436
23625
  },
23437
23626
  actions: actions,
23438
23627
  popover: {
23439
23628
  show: showPopoverToolbar,
23440
23629
  anchorEl: anchorEl
23441
- }
23630
+ },
23631
+ focusHandler: focusHandler
23442
23632
  });
23443
23633
  return /*#__PURE__*/React.createElement(Grid$1, {
23444
23634
  ref: containerRef,
@@ -23456,15 +23646,27 @@
23456
23646
  direction: "column"
23457
23647
  }, showTitle && /*#__PURE__*/React.createElement(Typography$1, {
23458
23648
  variant: "h6",
23459
- noWrap: true
23649
+ noWrap: true,
23650
+ className: CellTitle.className
23460
23651
  }, layout.title), showSubtitle && /*#__PURE__*/React.createElement(Typography$1, {
23461
23652
  variant: "body2",
23462
- noWrap: true
23653
+ noWrap: true,
23654
+ className: CellSubTitle.className
23463
23655
  }, layout.subtitle))), /*#__PURE__*/React.createElement(Grid$1, {
23464
23656
  item: true
23465
23657
  }, Toolbar));
23466
23658
  };
23467
23659
 
23660
+ /**
23661
+ * @interface
23662
+ * @extends HTMLElement
23663
+ * @since 2.0.0
23664
+ */
23665
+
23666
+ var CellFooter = {
23667
+ /** @type {'njs-cell-footer'} */
23668
+ className: 'njs-cell-footer'
23669
+ };
23468
23670
  var useStyles = makeStyles(function (theme) {
23469
23671
  return {
23470
23672
  itemStyle: {
@@ -23487,10 +23689,103 @@
23487
23689
  className: itemStyle
23488
23690
  }, /*#__PURE__*/React.createElement(Typography$1, {
23489
23691
  noWrap: true,
23490
- variant: "body2"
23692
+ variant: "body2",
23693
+ className: CellFooter.className
23491
23694
  }, layout.footnote))) : null;
23492
23695
  };
23493
23696
 
23697
+ var RenderDebouncer = /*#__PURE__*/function () {
23698
+ function RenderDebouncer() {
23699
+ _classCallCheck$1(this, RenderDebouncer);
23700
+
23701
+ this.timer = null;
23702
+ this.next = null;
23703
+ this.running = false;
23704
+ }
23705
+
23706
+ _createClass$2(RenderDebouncer, [{
23707
+ key: "start",
23708
+ value: function start() {
23709
+ if (this.running) {
23710
+ return;
23711
+ }
23712
+
23713
+ this.running = true;
23714
+ this.scheduleNext();
23715
+ }
23716
+ }, {
23717
+ key: "scheduleNext",
23718
+ value: function scheduleNext() {
23719
+ var _this = this;
23720
+
23721
+ this.timer = setTimeout(function () {
23722
+ _this.doNext();
23723
+ }, 10);
23724
+ }
23725
+ }, {
23726
+ key: "doNext",
23727
+ value: function () {
23728
+ var _doNext = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
23729
+ var fn;
23730
+ return regeneratorRuntime.wrap(function _callee$(_context) {
23731
+ while (1) {
23732
+ switch (_context.prev = _context.next) {
23733
+ case 0:
23734
+ fn = this.next;
23735
+ this.next = null;
23736
+
23737
+ if (!fn) {
23738
+ _context.next = 8;
23739
+ break;
23740
+ }
23741
+
23742
+ _context.next = 5;
23743
+ return fn();
23744
+
23745
+ case 5:
23746
+ this.scheduleNext();
23747
+ _context.next = 9;
23748
+ break;
23749
+
23750
+ case 8:
23751
+ this.stop();
23752
+
23753
+ case 9:
23754
+ case "end":
23755
+ return _context.stop();
23756
+ }
23757
+ }
23758
+ }, _callee, this);
23759
+ }));
23760
+
23761
+ function doNext() {
23762
+ return _doNext.apply(this, arguments);
23763
+ }
23764
+
23765
+ return doNext;
23766
+ }()
23767
+ }, {
23768
+ key: "schedule",
23769
+ value: function schedule(fn) {
23770
+ this.next = fn;
23771
+ this.start();
23772
+ }
23773
+ }, {
23774
+ key: "stop",
23775
+ value: function stop() {
23776
+ if (!this.running) {
23777
+ return;
23778
+ }
23779
+
23780
+ clearTimeout(this.timer);
23781
+ this.timer = null;
23782
+ this.running = false;
23783
+ }
23784
+ }]);
23785
+
23786
+ return RenderDebouncer;
23787
+ }();
23788
+
23494
23789
  /**
23495
23790
  * @interface
23496
23791
  * @extends HTMLElement
@@ -23514,19 +23809,24 @@
23514
23809
  var _useContext = react.exports.useContext(InstanceContext),
23515
23810
  themeName = _useContext.theme,
23516
23811
  language = _useContext.language,
23517
- constraints = _useContext.constraints;
23518
-
23519
- var renderDebouncer = react.exports.useRef(null);
23812
+ constraints = _useContext.constraints,
23813
+ keyboardNavigation = _useContext.keyboardNavigation;
23520
23814
 
23521
- var _useState = react.exports.useState(false),
23522
- _useState2 = _slicedToArray$2(_useState, 2),
23523
- isMounted = _useState2[0],
23524
- setIsMounted = _useState2[1];
23815
+ var _useState = react.exports.useState(function () {
23816
+ return new RenderDebouncer();
23817
+ }),
23818
+ _useState2 = _slicedToArray$2(_useState, 1),
23819
+ renderDebouncer = _useState2[0];
23525
23820
 
23526
- var _useState3 = react.exports.useState(0),
23821
+ var _useState3 = react.exports.useState(false),
23527
23822
  _useState4 = _slicedToArray$2(_useState3, 2),
23528
- renderCnt = _useState4[0],
23529
- setRenderCnt = _useState4[1];
23823
+ isMounted = _useState4[0],
23824
+ setIsMounted = _useState4[1];
23825
+
23826
+ var _useState5 = react.exports.useState(0),
23827
+ _useState6 = _slicedToArray$2(_useState5, 2),
23828
+ renderCnt = _useState6[0],
23829
+ setRenderCnt = _useState6[1];
23530
23830
 
23531
23831
  var _useRect = useRect$1(),
23532
23832
  _useRect2 = _slicedToArray$2(_useRect, 3),
@@ -23534,10 +23834,10 @@
23534
23834
  containerRect = _useRect2[1],
23535
23835
  containerNode = _useRect2[2];
23536
23836
 
23537
- var _useState5 = react.exports.useState(null),
23538
- _useState6 = _slicedToArray$2(_useState5, 2),
23539
- snNode = _useState6[0],
23540
- setSnNode = _useState6[1];
23837
+ var _useState7 = react.exports.useState(null),
23838
+ _useState8 = _slicedToArray$2(_useState7, 2),
23839
+ snNode = _useState8[0],
23840
+ setSnNode = _useState8[1];
23541
23841
 
23542
23842
  var snRef = react.exports.useCallback(function (ref) {
23543
23843
  if (!ref) {
@@ -23555,8 +23855,7 @@
23555
23855
  component.mounted(snNode);
23556
23856
  setIsMounted(true);
23557
23857
  return function () {
23558
- clearTimeout(renderDebouncer.current);
23559
- renderDebouncer.current = null;
23858
+ renderDebouncer.stop();
23560
23859
  component.willUnmount();
23561
23860
  };
23562
23861
  }, [snNode, component]); // Render
@@ -23571,13 +23870,7 @@
23571
23870
  return;
23572
23871
  }
23573
23872
 
23574
- if (renderDebouncer.current) {
23575
- // rendering already scheduled
23576
- return;
23577
- }
23578
-
23579
- renderDebouncer.current = setTimeout(function () {
23580
- // temporarily map constraints to permissions
23873
+ renderDebouncer.schedule(function () {
23581
23874
  var permissions = [];
23582
23875
 
23583
23876
  if (!constraints.passive) {
@@ -23596,7 +23889,7 @@
23596
23889
  permissions.push('fetch');
23597
23890
  }
23598
23891
 
23599
- Promise.resolve(component.render({
23892
+ return Promise.resolve(component.render({
23600
23893
  layout: layout,
23601
23894
  options: options,
23602
23895
  plugins: plugins,
@@ -23605,7 +23898,8 @@
23605
23898
  constraints: constraints,
23606
23899
  // halo.public.theme is a singleton so themeName is used as dep to make sure this effect is triggered
23607
23900
  theme: halo.public.theme,
23608
- appLayout: appLayout
23901
+ appLayout: appLayout,
23902
+ keyboardNavigation: keyboardNavigation
23609
23903
  }, component.isHooked ? {} : {
23610
23904
  logicalSize: sn.logicalSize({
23611
23905
  layout: layout
@@ -23613,8 +23907,10 @@
23613
23907
  localeInfo: (appLayout || {}).qLocaleInfo,
23614
23908
  permissions: permissions
23615
23909
  })
23616
- })).then(function () {
23617
- renderDebouncer.current = null;
23910
+ })).then(function (done) {
23911
+ if (done === false) {
23912
+ return;
23913
+ }
23618
23914
 
23619
23915
  if (renderCnt === 0 && typeof options.onInitialRender === 'function') {
23620
23916
  options.onInitialRender.call(null);
@@ -23622,8 +23918,8 @@
23622
23918
 
23623
23919
  setRenderCnt(renderCnt + 1);
23624
23920
  });
23625
- }, 10);
23626
- }, [containerRect, options, plugins, snNode, containerNode, layout, appLayout, themeName, language, constraints, isMounted]);
23921
+ });
23922
+ }, [containerRect, options, plugins, snNode, containerNode, layout, appLayout, themeName, language, constraints, isMounted, keyboardNavigation]);
23627
23923
  return /*#__PURE__*/React.createElement("div", {
23628
23924
  ref: containerRef,
23629
23925
  "data-render-count": renderCnt,
@@ -23737,7 +24033,7 @@
23737
24033
  return clearTimeout(handle);
23738
24034
  };
23739
24035
  }, []);
23740
- return showLoading && /*#__PURE__*/React.createElement(Loading, null);
24036
+ return showLoading ? /*#__PURE__*/React.createElement(Loading, null) : null;
23741
24037
  };
23742
24038
 
23743
24039
  var handleModal = function handleModal(_ref2) {
@@ -23978,12 +24274,12 @@
23978
24274
 
23979
24275
  var loadType = /*#__PURE__*/function () {
23980
24276
  var _ref8 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(_ref7) {
23981
- var dispatch, types, visualization, version, model, app, selections, nebbie, snType, sn;
24277
+ var dispatch, types, visualization, version, model, app, selections, nebbie, focusHandler, snType, sn;
23982
24278
  return regeneratorRuntime.wrap(function _callee3$(_context3) {
23983
24279
  while (1) {
23984
24280
  switch (_context3.prev = _context3.next) {
23985
24281
  case 0:
23986
- dispatch = _ref7.dispatch, types = _ref7.types, visualization = _ref7.visualization, version = _ref7.version, model = _ref7.model, app = _ref7.app, selections = _ref7.selections, nebbie = _ref7.nebbie;
24282
+ dispatch = _ref7.dispatch, types = _ref7.types, visualization = _ref7.visualization, version = _ref7.version, model = _ref7.model, app = _ref7.app, selections = _ref7.selections, nebbie = _ref7.nebbie, focusHandler = _ref7.focusHandler;
23987
24283
  _context3.prev = 1;
23988
24284
  _context3.next = 4;
23989
24285
  return getType({
@@ -23998,7 +24294,8 @@
23998
24294
  model: model,
23999
24295
  app: app,
24000
24296
  selections: selections,
24001
- nebbie: nebbie
24297
+ nebbie: nebbie,
24298
+ focusHandler: focusHandler
24002
24299
  });
24003
24300
  return _context3.abrupt("return", sn);
24004
24301
 
@@ -24034,14 +24331,16 @@
24034
24331
  initialSnOptions = _ref9.initialSnOptions,
24035
24332
  initialSnPlugins = _ref9.initialSnPlugins,
24036
24333
  initialError = _ref9.initialError,
24037
- onMount = _ref9.onMount;
24334
+ onMount = _ref9.onMount,
24335
+ currentId = _ref9.currentId;
24038
24336
  var app = halo.app,
24039
24337
  types = halo.types;
24040
24338
  var nebbie = halo.public.nebbie;
24041
24339
 
24042
24340
  var _useContext = react.exports.useContext(InstanceContext),
24043
24341
  translator = _useContext.translator,
24044
- language = _useContext.language;
24342
+ language = _useContext.language,
24343
+ keyboardNavigation = _useContext.keyboardNavigation;
24045
24344
 
24046
24345
  var theme = useTheme$2();
24047
24346
 
@@ -24070,9 +24369,10 @@
24070
24369
  appLayout = _useAppLayout2[0];
24071
24370
 
24072
24371
  var _useRect3 = useRect$1(),
24073
- _useRect4 = _slicedToArray$2(_useRect3, 2),
24372
+ _useRect4 = _slicedToArray$2(_useRect3, 3),
24074
24373
  contentRef = _useRect4[0],
24075
- contentRect = _useRect4[1];
24374
+ contentRect = _useRect4[1],
24375
+ contentNode = _useRect4[2];
24076
24376
 
24077
24377
  var _useState3 = react.exports.useState(initialSnOptions),
24078
24378
  _useState4 = _slicedToArray$2(_useState3, 2),
@@ -24097,6 +24397,27 @@
24097
24397
  enter: null,
24098
24398
  leave: null
24099
24399
  });
24400
+ var focusHandler = react.exports.useRef({
24401
+ focusToolbarButton: function focusToolbarButton(last) {
24402
+ // eslint-disable-next-line react/no-this-in-sfc
24403
+ this.emit(last ? 'focus_toolbar_last' : 'focus_toolbar_first');
24404
+ }
24405
+ });
24406
+ react.exports.useEffect(function () {
24407
+ eventmixin(focusHandler.current);
24408
+ }, []);
24409
+
24410
+ focusHandler.current.blurCallback = function (resetFocus) {
24411
+ halo.root.toggleFocusOfCells();
24412
+
24413
+ if (resetFocus && contentNode) {
24414
+ contentNode.focus();
24415
+ }
24416
+ };
24417
+
24418
+ focusHandler.current.refocusContent = function () {
24419
+ state.sn.component && typeof state.sn.component.focus === 'function' && state.sn.component.focus();
24420
+ };
24100
24421
 
24101
24422
  var handleOnMouseEnter = function handleOnMouseEnter() {
24102
24423
  if (hoveringDebouncer.current.leave) {
@@ -24122,6 +24443,13 @@
24122
24443
  }, 750);
24123
24444
  };
24124
24445
 
24446
+ var handleKeyDown = function handleKeyDown(e) {
24447
+ // Enter or space
24448
+ if (['Enter', ' ', 'Spacebar'].includes(e.key)) {
24449
+ halo.root.toggleFocusOfCells(currentId);
24450
+ }
24451
+ };
24452
+
24125
24453
  react.exports.useEffect(function () {
24126
24454
  if (initialError || !appLayout || !layout) {
24127
24455
  return undefined;
@@ -24193,7 +24521,8 @@
24193
24521
  model: model,
24194
24522
  app: app,
24195
24523
  selections: selections,
24196
- nebbie: nebbie
24524
+ nebbie: nebbie,
24525
+ focusHandler: focusHandler.current
24197
24526
  });
24198
24527
 
24199
24528
  case 3:
@@ -24266,6 +24595,15 @@
24266
24595
  getQae: function getQae() {
24267
24596
  return state.sn.generator.qae;
24268
24597
  },
24598
+ toggleFocus: function toggleFocus(active) {
24599
+ if (typeof state.sn.component.focus === 'function') {
24600
+ if (active) {
24601
+ state.sn.component.focus();
24602
+ } else {
24603
+ state.sn.component.blur();
24604
+ }
24605
+ }
24606
+ },
24269
24607
  setSnOptions: setSnOptions,
24270
24608
  setSnPlugins: setSnPlugins,
24271
24609
  takeSnapshot: function takeSnapshot() {
@@ -24407,8 +24745,11 @@
24407
24745
  layout: layout,
24408
24746
  sn: state.sn,
24409
24747
  anchorEl: cellNode,
24410
- hovering: hovering
24748
+ hovering: hovering,
24749
+ focusHandler: focusHandler.current
24411
24750
  }, "\xA0"), /*#__PURE__*/React.createElement(Grid$1, {
24751
+ tabIndex: keyboardNavigation ? 0 : -1,
24752
+ onKeyDown: keyboardNavigation ? handleKeyDown : null,
24412
24753
  item: true,
24413
24754
  xs: true,
24414
24755
  style: {
@@ -24434,10 +24775,12 @@
24434
24775
  initialError = _ref.initialError;
24435
24776
  var root = halo.root;
24436
24777
  var cellRef = React.createRef();
24778
+ var currentId = uid();
24437
24779
  var portal = ReactDOM.createPortal( /*#__PURE__*/React.createElement(Cell, {
24438
24780
  ref: cellRef,
24439
24781
  halo: halo,
24440
24782
  model: model,
24783
+ currentId: currentId,
24441
24784
  initialSnOptions: initialSnOptions,
24442
24785
  initialSnPlugins: initialSnPlugins,
24443
24786
  initialError: initialError,
@@ -24450,7 +24793,9 @@
24450
24793
  };
24451
24794
 
24452
24795
  model.on('closed', unmount);
24453
- root.add(portal);
24796
+ root.add(portal); // Cannot use model.id as it is not unique in a given mashup
24797
+
24798
+ root.addCell(currentId, cellRef);
24454
24799
  return [unmount, cellRef];
24455
24800
  }
24456
24801
 
@@ -24702,7 +25047,6 @@
24702
25047
 
24703
25048
  /**
24704
25049
  * Converts the visualization to a different registered type
24705
- * @experimental
24706
25050
  * @since 1.1.0
24707
25051
  * @param {string} newType - Which registered type to convert to.
24708
25052
  * @param {boolean=} forceUpdate - Whether to run setProperties or not, defaults to true.
@@ -25612,6 +25956,7 @@
25612
25956
  component.__hooks = {
25613
25957
  obsolete: false,
25614
25958
  error: false,
25959
+ waitForData: false,
25615
25960
  chain: {
25616
25961
  promise: null,
25617
25962
  resolve: function resolve() {}
@@ -25627,6 +25972,9 @@
25627
25972
  resizer: {
25628
25973
  setters: [],
25629
25974
  explicitResize: explicitResize
25975
+ },
25976
+ accessibility: {
25977
+ setter: null
25630
25978
  }
25631
25979
  };
25632
25980
  }
@@ -25639,6 +25987,7 @@
25639
25987
  component.__hooks.actions = null;
25640
25988
  component.__hooks.imperativeHandle = null;
25641
25989
  component.__hooks.resizer = null;
25990
+ component.__hooks.accessibility = null;
25642
25991
  component.__actionsDispatch = null;
25643
25992
  clearTimeout(component.__hooks.micro);
25644
25993
  cancelAnimationFrame(component.__hooks.macro);
@@ -25742,7 +26091,7 @@
25742
26091
  }
25743
26092
 
25744
26093
  hooks.chain.promise = null;
25745
- hooks.chain.resolve();
26094
+ hooks.chain.resolve(!hooks.waitForData);
25746
26095
  }
25747
26096
 
25748
26097
  function runSnaps(component, layout) {
@@ -25834,6 +26183,8 @@
25834
26183
  run: run,
25835
26184
  teardown: teardown,
25836
26185
  runSnaps: runSnaps,
26186
+ focus: focus,
26187
+ blur: blur,
25837
26188
  observeActions: observeActions,
25838
26189
  getImperativeHandle: getImperativeHandle,
25839
26190
  updateRectOnNextRun: updateRectOnNextRun
@@ -26348,6 +26699,7 @@
26348
26699
  * Gets the embed instance used.
26349
26700
  * @entry
26350
26701
  * @experimental
26702
+ * @since 1.7.0
26351
26703
  * @returns {Embed} The embed instance used.
26352
26704
  * @example
26353
26705
  * import { useEmbed } from '@nebula.js/stardust';
@@ -26480,9 +26832,9 @@
26480
26832
  }
26481
26833
  /**
26482
26834
  * @interface Constraints
26483
- * @property {boolean=} passive
26484
- * @property {boolean=} active
26485
- * @property {boolean=} select
26835
+ * @property {boolean=} passive Whether or not passive constraints are on. Should block any passive interaction by users, ie: tooltips
26836
+ * @property {boolean=} active Whether or not active constraints are on. Should block any active interaction by users, ie: scroll, click
26837
+ * @property {boolean=} select Whether or not active select are on. Should block any selection action. Implied when active is true.
26486
26838
  */
26487
26839
 
26488
26840
  /**
@@ -26641,6 +26993,183 @@
26641
26993
 
26642
26994
  h.fn = cb;
26643
26995
  }
26996
+ /**
26997
+ * Gets render state instance.
26998
+ *
26999
+ * Used to update properties and get a new layout without triggering onInitialRender.
27000
+ * @entry
27001
+ * @experimental
27002
+ * @returns {{ pending, restore }} The render state.
27003
+ * @example
27004
+ * import { useRenderState } from '@nebula.js/stardust';
27005
+ *
27006
+ * const renderState = useRenderState();
27007
+ * useState(() => {
27008
+ * if(needProperteisUpdate(...)) {
27009
+ * useRenderState.pending();
27010
+ * updateProperties(...);
27011
+ * } else {
27012
+ * useRenderState.restore();
27013
+ * ...
27014
+ * }
27015
+ * }, [...]);
27016
+ */
27017
+
27018
+ function useRenderState() {
27019
+ getHook(++currentIndex);
27020
+ var hooks = currentComponent.__hooks;
27021
+ return {
27022
+ pending: function pending() {
27023
+ hooks.waitForData = true;
27024
+ },
27025
+ restore: function restore() {
27026
+ hooks.waitForData = false;
27027
+ }
27028
+ };
27029
+ }
27030
+ /**
27031
+ * @experimental
27032
+ * @interface Keyboard
27033
+ * @property {boolean} enabled Whether or not Nebula handles keyboard navigation or not.
27034
+ * @property {boolean} active Set to true when the chart is activated, ie a user tabs to the chart and presses Enter or Space.
27035
+ * @property {function=} blur Function used by the visualization to tell Nebula to it wants to relinquish focus
27036
+ * @property {function=} focus Function used by the visualization to tell Nebula to it wants focus
27037
+ * @property {function=} focusSelection Function used by the visualization to tell Nebula to focus the selection toolbar
27038
+ */
27039
+
27040
+ /**
27041
+ * Gets the desired keyboard settings and status to applied when rendering the visualization.
27042
+ * A visualization should in general only have tab stops if either `keyboard.enabled` is false or if active is true.
27043
+ * This means that either Nebula isn't configured to handle keyboard input or the chart is currently focused.
27044
+ * Enabling or disabling keyboardNavigation are set on the embed configuration and
27045
+ * should be respected by the visualization.
27046
+ * @entry
27047
+ * @returns {Keyboard}
27048
+ * @example
27049
+ * // configure nebula to enable navigation between charts
27050
+ * embed(app, {
27051
+ * context: {
27052
+ * keyboardNavigation: true, // tell Nebula to handle navigation
27053
+ * }
27054
+ * }).render({ element, id: 'sdfsdf' });
27055
+ *
27056
+ * @example
27057
+ * import { useKeyboard } from '@nebula.js/stardust';
27058
+ * // ...
27059
+ * const keyboard = useKeyboard();
27060
+ * useEffect(() => {
27061
+ * // Set a tab stop on our button if in focus or if Nebulas navigation is disabled
27062
+ * button.setAttribute('tabIndex', keyboard.active || !keyboard.enabled ? 0 : -1);
27063
+ * // If navigation is enabled and focus has shifted, lets focus the button
27064
+ * keyboard.enabled && keyboard.active && button.focus();
27065
+ * }, [keyboard])
27066
+ *
27067
+ */
27068
+
27069
+ function useKeyboard() {
27070
+ var keyboardNavigation = useInternalContext('keyboardNavigation');
27071
+ var focusHandler = useInternalContext('focusHandler');
27072
+
27073
+ if (!currentComponent.__hooks.accessibility.exitFunction) {
27074
+ var exitFunction = function (resetFocus) {
27075
+ var acc = this.__hooks.accessibility;
27076
+
27077
+ if (acc.enabled && acc.active) {
27078
+ blur(this);
27079
+ focusHandler && focusHandler.blurCallback && focusHandler.blurCallback(resetFocus);
27080
+ }
27081
+ }.bind(currentComponent);
27082
+
27083
+ currentComponent.__hooks.accessibility.exitFunction = exitFunction;
27084
+
27085
+ var focusFunction = function () {
27086
+ var acc = this.__hooks.accessibility;
27087
+
27088
+ if (acc.enabled && !acc.active) {
27089
+ focusHandler && focusHandler.blurCallback && focusHandler.blurCallback(false);
27090
+ focus(this);
27091
+ }
27092
+ }.bind(currentComponent);
27093
+
27094
+ currentComponent.__hooks.accessibility.focusFunction = focusFunction;
27095
+
27096
+ var focusSelectionFunction = function (focusLast) {
27097
+ var acc = this.__hooks.accessibility;
27098
+
27099
+ if (acc.enabled) {
27100
+ focusHandler && focusHandler.focusToolbarButton && focusHandler.focusToolbarButton(focusLast);
27101
+ }
27102
+ }.bind(currentComponent);
27103
+
27104
+ currentComponent.__hooks.accessibility.focusSelectionFunction = focusSelectionFunction;
27105
+ }
27106
+
27107
+ var focusFunc = currentComponent.__hooks.accessibility.focusFunction;
27108
+ var exitFunc = currentComponent.__hooks.accessibility.exitFunction;
27109
+ var focusSelectionFunc = currentComponent.__hooks.accessibility.focusSelectionFunction;
27110
+
27111
+ var _useState9 = useState({
27112
+ active: false,
27113
+ enabled: keyboardNavigation,
27114
+ blur: exitFunc,
27115
+ focus: focusFunc,
27116
+ focusSelection: focusSelectionFunc
27117
+ }),
27118
+ _useState10 = _slicedToArray$2(_useState9, 2),
27119
+ acc = _useState10[0],
27120
+ setAcc = _useState10[1];
27121
+
27122
+ currentComponent.__hooks.accessibility.setter = setAcc;
27123
+ currentComponent.__hooks.accessibility.enabled = keyboardNavigation;
27124
+ useEffect(function () {
27125
+ return setAcc({
27126
+ active: false,
27127
+ enabled: keyboardNavigation,
27128
+ blur: exitFunc,
27129
+ focus: focusFunc,
27130
+ focusSelection: focusSelectionFunc
27131
+ });
27132
+ }, [keyboardNavigation]);
27133
+ return acc;
27134
+ }
27135
+ function focus(component) {
27136
+ var acc = component.__hooks.accessibility;
27137
+
27138
+ if (acc.active) {
27139
+ return;
27140
+ }
27141
+
27142
+ acc.active = true;
27143
+
27144
+ if (acc && acc.setter) {
27145
+ acc.setter({
27146
+ active: true,
27147
+ enabled: acc.enabled,
27148
+ blur: acc.exitFunction,
27149
+ focus: acc.focusFunction,
27150
+ focusSelection: acc.focusSelectionFunction
27151
+ });
27152
+ }
27153
+ }
27154
+ function blur(component) {
27155
+ var acc = component.__hooks.accessibility; // Incomplete/Invalid/Legacy viz hasn't been initialized with hooks
27156
+
27157
+ if (!acc || !acc.active) {
27158
+ return;
27159
+ }
27160
+
27161
+ acc.active = false;
27162
+
27163
+ if (acc && acc.setter) {
27164
+ acc.setter({
27165
+ active: false,
27166
+ enabled: acc.enabled,
27167
+ blur: acc.exitFunction,
27168
+ focus: acc.focusFunction,
27169
+ focusSelection: acc.focusSelectionFunction
27170
+ });
27171
+ }
27172
+ }
26644
27173
 
26645
27174
  var defaultComponent = {
26646
27175
  app: null,
@@ -26712,6 +27241,8 @@
26712
27241
  // --- dynamic values ---
26713
27242
  layout: {},
26714
27243
  appLayout: {},
27244
+ keyboardNavigation: opts.keyboardNavigation,
27245
+ focusHandler: opts.focusHandler,
26715
27246
  constraints: forcedConstraints,
26716
27247
  options: {},
26717
27248
  plugins: []
@@ -26738,6 +27269,17 @@
26738
27269
  if (r.context && r.context.theme) {
26739
27270
  // changed is set further down only if the name is different
26740
27271
  this.context.theme = r.context.theme;
27272
+ } // false equals undefined, so we to cast to bool here
27273
+
27274
+
27275
+ if (r.context && !!r.context.keyboardNavigation !== !!this.context.keyboardNavigation) {
27276
+ this.context.keyboardNavigation = !!r.context.keyboardNavigation;
27277
+ changed = true;
27278
+ }
27279
+
27280
+ if (r.context && r.context.focusHandler) {
27281
+ // Needs to be added here due to how the client renders
27282
+ this.context.focusHandler = r.context.focusHandler;
26741
27283
  }
26742
27284
 
26743
27285
  if (r.options) {
@@ -26837,6 +27379,12 @@
26837
27379
  setSnapshotData: function setSnapshotData(layout) {
26838
27380
  return generator.component.runSnaps(this, layout);
26839
27381
  },
27382
+ focus: function focus() {
27383
+ generator.component.focus(this);
27384
+ },
27385
+ blur: function blur() {
27386
+ generator.component.blur(this);
27387
+ },
26840
27388
  getImperativeHandle: function getImperativeHandle() {
26841
27389
  return generator.component.getImperativeHandle(this);
26842
27390
  },
@@ -27000,7 +27548,6 @@
27000
27548
  /**
27001
27549
  * @function importProperties
27002
27550
  * @description Imports properties for a chart with a hypercube.
27003
- * @experimental
27004
27551
  * @since 1.1.0
27005
27552
  * @param {Object} args
27006
27553
  * @param {ExportFormat} args.exportFormat The export object which is the output of exportProperties.
@@ -27014,7 +27561,6 @@
27014
27561
  /**
27015
27562
  * @function exportProperties
27016
27563
  * @description Exports properties for a chart with a hypercube.
27017
- * @experimental
27018
27564
  * @since 1.1.0
27019
27565
  * @param {Object} args
27020
27566
  * @param {Object} args.propertyTree
@@ -29036,6 +29582,7 @@
29036
29582
 
29037
29583
  /**
29038
29584
  * @interface Context
29585
+ * @property {boolean=} keyboardNavigation
29039
29586
  * @property {object=} constraints
29040
29587
  * @property {boolean=} constraints.active
29041
29588
  * @property {boolean=} constraints.passive
@@ -29053,7 +29600,8 @@
29053
29600
 
29054
29601
  /** @type {string=} */
29055
29602
  deviceType: 'auto',
29056
- constraints: {}
29603
+ constraints: {},
29604
+ keyboardNavigation: false
29057
29605
  };
29058
29606
  /**
29059
29607
  * @interface SnapshotConfiguration
@@ -29344,8 +29892,8 @@
29344
29892
  switch (_context4.prev = _context4.next) {
29345
29893
  case 0:
29346
29894
  // filter valid values to avoid triggering unnecessary rerender
29347
- ['theme', 'language', 'constraints'].forEach(function (key) {
29348
- if (ctx[key] && ctx[key] !== currentContext[key]) {
29895
+ ['theme', 'language', 'constraints', 'keyboardNavigation'].forEach(function (key) {
29896
+ if (Object.prototype.hasOwnProperty.call(ctx, key) && ctx[key] !== currentContext[key]) {
29349
29897
  if (!changes) {
29350
29898
  changes = {};
29351
29899
  }
@@ -29473,7 +30021,6 @@
29473
30021
  * Gets the listbox instance of the specified field
29474
30022
  * @param {string|LibraryField} fieldIdentifier Fieldname as a string or a Library dimension
29475
30023
  * @returns {Promise<FieldInstance>}
29476
- * @experimental
29477
30024
  * @since 1.1.0
29478
30025
  * @example
29479
30026
  * const fieldInstance = await n.field("MyField");
@@ -29499,7 +30046,6 @@
29499
30046
  /**
29500
30047
  * @class
29501
30048
  * @alias FieldInstance
29502
- * @experimental
29503
30049
  * @since 1.1.0
29504
30050
  */
29505
30051
  fieldSels = {
@@ -29515,7 +30061,6 @@
29515
30061
  * @param {boolean=} [options.search=true] To show the search bar
29516
30062
  * @param {boolean=} [options.stateName="$"] Sets the state to make selections in
29517
30063
  * @param {object=} [options.properties={}] Properties object to extend default properties with
29518
- * @experimental
29519
30064
  * @since 1.1.0
29520
30065
  * @example
29521
30066
  * fieldInstance.mount(element);
@@ -29543,7 +30088,6 @@
29543
30088
 
29544
30089
  /**
29545
30090
  * Unmounts the field listbox from the DOM.
29546
- * @experimental
29547
30091
  * @since 1.1.0
29548
30092
  * @example
29549
30093
  * listbox.unmount();
@@ -29664,6 +30208,7 @@
29664
30208
  exports.useEmbed = useEmbed;
29665
30209
  exports.useGlobal = useGlobal;
29666
30210
  exports.useImperativeHandle = useImperativeHandle;
30211
+ exports.useKeyboard = useKeyboard;
29667
30212
  exports.useLayout = useLayout;
29668
30213
  exports.useMemo = useMemo;
29669
30214
  exports.useModel = useModel;
@@ -29671,6 +30216,7 @@
29671
30216
  exports.usePlugins = usePlugins;
29672
30217
  exports.usePromise = usePromise;
29673
30218
  exports.useRect = useRect;
30219
+ exports.useRenderState = useRenderState;
29674
30220
  exports.useSelections = useSelections;
29675
30221
  exports.useStaleLayout = useStaleLayout;
29676
30222
  exports.useState = useState;
@@ -29679,5 +30225,5 @@
29679
30225
 
29680
30226
  Object.defineProperty(exports, '__esModule', { value: true });
29681
30227
 
29682
- })));
30228
+ }));
29683
30229
  //# sourceMappingURL=stardust.dev.js.map