@nebula.js/stardust 5.3.0 → 5.4.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 v5.3.0
2
+ * @nebula.js/stardust v5.4.0
3
3
  * Copyright (c) 2024 QlikTech International AB
4
4
  * Released under the MIT license.
5
5
  */
@@ -7349,7 +7349,7 @@
7349
7349
  }
7350
7350
 
7351
7351
  /**
7352
- * @mui/styled-engine v5.16.4
7352
+ * @mui/styled-engine v5.16.6
7353
7353
  *
7354
7354
  * @license MIT
7355
7355
  * This source code is licensed under the MIT license found in the
@@ -13544,7 +13544,7 @@
13544
13544
  return cache[key];
13545
13545
  }
13546
13546
 
13547
- const NEBULA_VERSION_HASH = "b434";
13547
+ const NEBULA_VERSION_HASH = "4310";
13548
13548
  ClassNameGenerator.configure(componentName => {
13549
13549
  return "njs-".concat(NEBULA_VERSION_HASH, "-").concat(componentName.replace('Mui', ''));
13550
13550
  });
@@ -13776,7 +13776,7 @@
13776
13776
  const appRef = React$1.createRef();
13777
13777
  const element = document.createElement('div');
13778
13778
  element.style.display = 'none';
13779
- element.setAttribute('data-nebulajs-version', "5.3.0");
13779
+ element.setAttribute('data-nebulajs-version', "5.4.0");
13780
13780
  element.setAttribute('data-app-id', app.id);
13781
13781
  document.body.appendChild(element);
13782
13782
  if (context) {
@@ -19082,6 +19082,8 @@
19082
19082
  whiteSpace: 'nowrap',
19083
19083
  textAlign: 'center',
19084
19084
  border: 0,
19085
+ borderTopStyle: 'solid',
19086
+ borderLeftStyle: 'solid',
19085
19087
  '&::before, &::after': {
19086
19088
  content: '""',
19087
19089
  alignSelf: 'center'
@@ -19092,7 +19094,8 @@
19092
19094
  }) => _extends$6({}, ownerState.children && ownerState.orientation !== 'vertical' && {
19093
19095
  '&::before, &::after': {
19094
19096
  width: '100%',
19095
- borderTop: `thin solid ${(theme.vars || theme).palette.divider}`
19097
+ borderTop: `thin solid ${(theme.vars || theme).palette.divider}`,
19098
+ borderTopStyle: 'inherit'
19096
19099
  }
19097
19100
  }), ({
19098
19101
  theme,
@@ -19101,7 +19104,8 @@
19101
19104
  flexDirection: 'column',
19102
19105
  '&::before, &::after': {
19103
19106
  height: '100%',
19104
- borderLeft: `thin solid ${(theme.vars || theme).palette.divider}`
19107
+ borderLeft: `thin solid ${(theme.vars || theme).palette.divider}`,
19108
+ borderLeftStyle: 'inherit'
19105
19109
  }
19106
19110
  }), ({
19107
19111
  ownerState
@@ -27999,9 +28003,6 @@
27999
28003
  ref: ref,
28000
28004
  open: show,
28001
28005
  anchorEl: alignTo.current,
28002
- getContentAnchorEl: null,
28003
- container: alignTo.current,
28004
- disablePortal: true,
28005
28006
  hideBackdrop: true,
28006
28007
  transitionDuration: 0,
28007
28008
  slotProps: {
@@ -28421,7 +28422,7 @@
28421
28422
  boxShadow: 'inset 0 0 0 2px rgb(2, 117, 217)'
28422
28423
  }
28423
28424
  }));
28424
- function ListBoxSearch(_ref2) {
28425
+ function ListBoxSearch(_ref2, ref) {
28425
28426
  let {
28426
28427
  popoverOpen,
28427
28428
  selections,
@@ -28583,7 +28584,7 @@
28583
28584
  abortSearch();
28584
28585
  focusOnInput();
28585
28586
  };
28586
- const onKeyDownClearSearch = async e => {
28587
+ const onKeyDownClearSearch = e => {
28587
28588
  const container = e.currentTarget.closest('.listbox-container');
28588
28589
  switch (e.key) {
28589
28590
  case 'Enter':
@@ -28606,6 +28607,11 @@
28606
28607
  e.stopPropagation();
28607
28608
  return undefined;
28608
28609
  };
28610
+ reactExports.useImperativeHandle(ref, () => ({
28611
+ focus() {
28612
+ focusOnInput();
28613
+ }
28614
+ }));
28609
28615
  if (!visible || searchEnabled === false) {
28610
28616
  return null;
28611
28617
  }
@@ -28653,6 +28659,7 @@
28653
28659
  }
28654
28660
  });
28655
28661
  }
28662
+ var ListBoxSearch$1 = reactExports.forwardRef(ListBoxSearch);
28656
28663
 
28657
28664
  /* eslint no-underscore-dangle: 0 */
28658
28665
  function createAppSelections(_ref) {
@@ -31185,13 +31192,19 @@
31185
31192
  components,
31186
31193
  checkboxes: checkboxesOption,
31187
31194
  selectDisabled = () => false,
31188
- flags
31195
+ flags,
31196
+ sortCriteria = [{
31197
+ qSortByState: 1,
31198
+ qSortByAscii: 1,
31199
+ qSortByNumeric: 1,
31200
+ qSortByLoadOrder: 1
31201
+ }]
31189
31202
  } = _ref;
31190
31203
  const isMasterDim = Boolean(fieldName === null || fieldName === void 0 ? void 0 : fieldName.qLibraryId);
31191
31204
  const open = show && Boolean(alignTo.current);
31192
31205
  const [listCount, setListCount] = reactExports.useState(0);
31193
31206
  const theme = useTheme$2();
31194
- const searchContainerRef = reactExports.useRef();
31207
+ const searchInputRef = reactExports.useRef();
31195
31208
  const [model] = useSessionModel({
31196
31209
  qInfo: {
31197
31210
  qType: 'njsListbox'
@@ -31206,12 +31219,7 @@
31206
31219
  qHeight: 0
31207
31220
  }],
31208
31221
  qDef: {
31209
- qSortCriterias: [{
31210
- qSortByState: 1,
31211
- qSortByAscii: 1,
31212
- qSortByNumeric: 1,
31213
- qSortByLoadOrder: 1
31214
- }],
31222
+ qSortCriterias: sortCriteria,
31215
31223
  qFieldDefs: isMasterDim ? undefined : [fieldName]
31216
31224
  },
31217
31225
  qLibraryId: isMasterDim ? fieldName.qLibraryId : undefined
@@ -31274,8 +31282,7 @@
31274
31282
  selections
31275
31283
  });
31276
31284
  const onCtrlF = () => {
31277
- const input = searchContainerRef.current.querySelector('input');
31278
- input === null || input === void 0 || input.focus();
31285
+ searchInputRef.current.focus();
31279
31286
  };
31280
31287
  const hasSelections$1 = hasSelections(layout);
31281
31288
  return /*#__PURE__*/React$1.createElement(Popover, {
@@ -31349,9 +31356,9 @@
31349
31356
  }, /*#__PURE__*/React$1.createElement("div", {
31350
31357
  ref: moreAlignTo
31351
31358
  }), /*#__PURE__*/React$1.createElement(Grid, {
31352
- item: true,
31353
- ref: searchContainerRef
31354
- }, /*#__PURE__*/React$1.createElement(ListBoxSearch, {
31359
+ item: true
31360
+ }, /*#__PURE__*/React$1.createElement(ListBoxSearch$1, {
31361
+ ref: searchInputRef,
31355
31362
  popoverOpen: open,
31356
31363
  styles: styles,
31357
31364
  visible: true,
@@ -33308,18 +33315,6 @@
33308
33315
  selectDisabled = () => false,
33309
33316
  flags
33310
33317
  } = options;
33311
-
33312
- // Hook that will trigger update when used in useEffects.
33313
- // Modified from: https://medium.com/@teh_builder/ref-objects-inside-useeffect-hooks-eb7c15198780
33314
- const useRefWithCallback = () => {
33315
- const [ref, setInternalRef] = reactExports.useState({});
33316
- const setRef = reactExports.useCallback(node => {
33317
- setInternalRef({
33318
- current: node
33319
- });
33320
- }, [setInternalRef]);
33321
- return [ref, setRef];
33322
- };
33323
33318
  const theme = useTheme$2();
33324
33319
  const {
33325
33320
  translator,
@@ -33343,8 +33338,8 @@
33343
33338
  appLayout: app === null || app === void 0 ? void 0 : app.layout
33344
33339
  });
33345
33340
  const containerRef = reactExports.useRef();
33341
+ const searchInputRef = reactExports.useRef();
33346
33342
  const [containerRectRef, containerRect] = useRect$1();
33347
- const [searchContainer, searchContainerRef] = useRefWithCallback();
33348
33343
  const [showToolbar, setShowToolbar] = reactExports.useState(false);
33349
33344
  const [showSearch, setShowSearch] = reactExports.useState(false);
33350
33345
  const hovering = reactExports.useRef(false);
@@ -33430,16 +33425,6 @@
33430
33425
  }
33431
33426
  };
33432
33427
  }, [toolbar, selections, isPopover]);
33433
- reactExports.useEffect(() => {
33434
- if (!searchContainer || !searchContainer.current) {
33435
- return;
33436
- }
33437
- // Focus search field on toggle-show or when focusSearch is true.
33438
- if (search && focusSearch || search === 'toggle' && showSearch) {
33439
- const input = searchContainer.current.querySelector('input');
33440
- input && input.focus();
33441
- }
33442
- }, [searchContainer && searchContainer.current, showSearch, search, focusSearch]);
33443
33428
  const {
33444
33429
  wildCardSearch,
33445
33430
  searchEnabled,
@@ -33466,11 +33451,10 @@
33466
33451
  if (search === 'toggle') {
33467
33452
  handleShowSearch();
33468
33453
  } else {
33469
- const input = searchContainer.current.querySelector('input');
33470
- input === null || input === void 0 || input.focus();
33454
+ searchInputRef.current.focus();
33471
33455
  }
33472
33456
  };
33473
- const shouldAutoFocus = searchVisible && search === 'toggle';
33457
+ const shouldAutoFocus = searchVisible && (search === 'toggle' || focusSearch);
33474
33458
 
33475
33459
  // Add a container padding for grid mode to harmonize with the grid item margins (should sum to 8px).
33476
33460
  const isGridMode = (layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.dataLayout) === 'grid';
@@ -33537,9 +33521,9 @@
33537
33521
  role: "region",
33538
33522
  "aria-label": translator.get('Listbox.ResultFilterLabel')
33539
33523
  }, /*#__PURE__*/React$1.createElement(Grid, {
33540
- item: true,
33541
- ref: searchContainerRef
33542
- }, /*#__PURE__*/React$1.createElement(ListBoxSearch, {
33524
+ item: true
33525
+ }, /*#__PURE__*/React$1.createElement(ListBoxSearch$1, {
33526
+ ref: searchInputRef,
33543
33527
  selections: selections,
33544
33528
  selectionState: selectionState$1,
33545
33529
  model: model,
@@ -34165,7 +34149,8 @@
34165
34149
  stateName: stateName,
34166
34150
  autoFocus: options.autoFocus,
34167
34151
  components: options.components,
34168
- flags: flags
34152
+ flags: flags,
34153
+ sortCriteria: options.sortCriteria
34169
34154
  });
34170
34155
  }
34171
34156
 
@@ -36299,7 +36284,8 @@
36299
36284
  nebbie,
36300
36285
  focusHandler,
36301
36286
  emitter,
36302
- onMount
36287
+ onMount,
36288
+ navigation
36303
36289
  } = _ref5;
36304
36290
  try {
36305
36291
  const snType = await getType({
@@ -36313,7 +36299,8 @@
36313
36299
  selections,
36314
36300
  nebbie,
36315
36301
  focusHandler,
36316
- emitter
36302
+ emitter,
36303
+ navigation
36317
36304
  });
36318
36305
  if (sn) {
36319
36306
  dispatch({
@@ -36351,7 +36338,8 @@
36351
36338
  initialError,
36352
36339
  onMount,
36353
36340
  currentId,
36354
- emitter
36341
+ emitter,
36342
+ navigation
36355
36343
  } = _ref6;
36356
36344
  const {
36357
36345
  app,
@@ -36481,7 +36469,8 @@
36481
36469
  nebbie,
36482
36470
  focusHandler: focusHandler.current,
36483
36471
  emitter,
36484
- onMount
36472
+ onMount,
36473
+ navigation
36485
36474
  });
36486
36475
  };
36487
36476
 
@@ -36656,7 +36645,8 @@
36656
36645
  initialSnPlugins,
36657
36646
  onMount,
36658
36647
  emitter,
36659
- initialError
36648
+ initialError,
36649
+ navigation
36660
36650
  } = _ref;
36661
36651
  const {
36662
36652
  root
@@ -36672,7 +36662,8 @@
36672
36662
  initialSnPlugins: initialSnPlugins,
36673
36663
  initialError: initialError,
36674
36664
  onMount: onMount,
36675
- emitter: emitter
36665
+ emitter: emitter,
36666
+ navigation: navigation
36676
36667
  }), element, currentId);
36677
36668
  const unmount = () => {
36678
36669
  root.remove(portal);
@@ -37888,7 +37879,6 @@
37888
37879
  /**
37889
37880
  * Gets the embed instance used.
37890
37881
  * @entry
37891
- * @experimental
37892
37882
  * @since 1.7.0
37893
37883
  * @returns {Embed} The embed instance used.
37894
37884
  * @example
@@ -37929,6 +37919,22 @@
37929
37919
  return useInternalContext('deviceType');
37930
37920
  }
37931
37921
 
37922
+ /**
37923
+ * Gets the navigation api to control sheet navigation. When useNavigation is used in Sense, it returns Sense.navigation.
37924
+ * @entry
37925
+ * @experimental
37926
+ * @since 5.4.0
37927
+ * @returns {Navigation} navigation api.
37928
+ * @example
37929
+ * import { useNavigation } from "@nebula.js/stardust";
37930
+ * // ...
37931
+ * const navigation = useNavigation();
37932
+ * const [activeSheetId, setActiveSheetId] = useState(navigation?.getCurrentSheetId() || "");
37933
+ */
37934
+ function useNavigation() {
37935
+ return useInternalContext('navigation');
37936
+ }
37937
+
37932
37938
  /**
37933
37939
  * Gets the array of plugins provided when rendering the visualization.
37934
37940
  * @entry
@@ -38254,7 +38260,6 @@
38254
38260
  *
38255
38261
  * Used to update properties and get a new layout without triggering onInitialRender.
38256
38262
  * @entry
38257
- * @experimental
38258
38263
  * @returns {RenderState} The render state.
38259
38264
  * @example
38260
38265
  * import { useRenderState } from '@nebula.js/stardust';
@@ -38291,7 +38296,6 @@
38291
38296
  /**
38292
38297
  * Gets an event emitter instance for the visualization.
38293
38298
  * @entry
38294
- * @experimental
38295
38299
  * @returns {Emitter}
38296
38300
  * @example
38297
38301
  * // In a Nebula visualization
@@ -38315,7 +38319,6 @@
38315
38319
  }
38316
38320
 
38317
38321
  /**
38318
- * @experimental
38319
38322
  * @interface Keyboard
38320
38323
  * @property {boolean} enabled Whether or not Nebula handles keyboard navigation or not.
38321
38324
  * @property {boolean} active Set to true when the chart is activated, ie a user tabs to the chart and presses Enter or Space.
@@ -38506,6 +38509,7 @@
38506
38509
  deviceType: galaxy.deviceType,
38507
38510
  theme: undefined,
38508
38511
  translator: galaxy.translator,
38512
+ navigation: opts.navigation,
38509
38513
  // --- dynamic values ---
38510
38514
  layout: {},
38511
38515
  appLayout: {},
@@ -39036,6 +39040,7 @@
39036
39040
  let {
39037
39041
  model,
39038
39042
  halo,
39043
+ navigation,
39039
39044
  initialError,
39040
39045
  onDestroy = async () => {}
39041
39046
  } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
@@ -39277,7 +39282,8 @@
39277
39282
  initialSnPlugins,
39278
39283
  initialError,
39279
39284
  onMount,
39280
- emitter
39285
+ emitter,
39286
+ navigation
39281
39287
  });
39282
39288
  return mounted;
39283
39289
  },
@@ -39372,11 +39378,12 @@
39372
39378
  }
39373
39379
 
39374
39380
  /* eslint no-underscore-dangle:0 */
39375
- async function init(model, optional, halo, initialError) {
39376
- let onDestroy = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : async () => {};
39381
+ async function init(model, optional, halo, navigation, initialError) {
39382
+ let onDestroy = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : async () => {};
39377
39383
  const api = viz({
39378
39384
  model,
39379
39385
  halo,
39386
+ navigation,
39380
39387
  initialError,
39381
39388
  onDestroy
39382
39389
  });
@@ -39438,7 +39445,8 @@
39438
39445
  options,
39439
39446
  plugins,
39440
39447
  element,
39441
- extendProperties
39448
+ extendProperties,
39449
+ navigation
39442
39450
  } = _ref;
39443
39451
  let mergedProps = {};
39444
39452
  const children = [];
@@ -39494,7 +39502,7 @@
39494
39502
  options,
39495
39503
  plugins,
39496
39504
  element
39497
- }, halo, error, onDestroy);
39505
+ }, halo, navigation, error, onDestroy);
39498
39506
  }
39499
39507
 
39500
39508
  /**
@@ -39608,7 +39616,7 @@
39608
39616
  /** @type {'njs-sheet'} */
39609
39617
  className: 'njs-sheet'
39610
39618
  };
39611
- function getCellRenderer(cell, halo, initialSnOptions, initialSnPlugins, initialError, onMount) {
39619
+ function getCellRenderer(cell, halo, initialSnOptions, initialSnPlugins, initialError, onMount, navigation) {
39612
39620
  const {
39613
39621
  x,
39614
39622
  y,
@@ -39622,7 +39630,8 @@
39622
39630
  width: "".concat(width, "%"),
39623
39631
  height: "".concat(height, "%"),
39624
39632
  position: 'absolute'
39625
- }
39633
+ },
39634
+ key: cell.model.id
39626
39635
  }, /*#__PURE__*/React$1.createElement(Cell, {
39627
39636
  ref: cell.cellRef,
39628
39637
  halo: halo,
@@ -39631,7 +39640,8 @@
39631
39640
  initialSnOptions: initialSnOptions,
39632
39641
  initialSnPlugins: initialSnPlugins,
39633
39642
  initialError: initialError,
39634
- onMount: onMount
39643
+ onMount: onMount,
39644
+ navigation: navigation
39635
39645
  }));
39636
39646
  }
39637
39647
  function getBounds(pos, columns, rows) {
@@ -39645,18 +39655,22 @@
39645
39655
  height: pos.rowspan / rows * 100
39646
39656
  };
39647
39657
  }
39648
- function Sheet(_ref) {
39658
+ const Sheet = reactExports.forwardRef((_ref, ref) => {
39659
+ var _navigation$setCurren;
39649
39660
  let {
39650
- model,
39661
+ model: inputModel,
39651
39662
  halo,
39652
39663
  initialSnOptions,
39653
39664
  initialSnPlugins,
39654
39665
  initialError,
39655
- onMount
39666
+ onMount,
39667
+ unmount,
39668
+ navigation
39656
39669
  } = _ref;
39657
39670
  const {
39658
39671
  root
39659
39672
  } = halo;
39673
+ const [model, setModel] = reactExports.useState(inputModel);
39660
39674
  const [layout] = useLayout$1(model);
39661
39675
  const {
39662
39676
  theme: themeName,
@@ -39666,7 +39680,7 @@
39666
39680
  const [bgColor, setBgColor] = reactExports.useState(undefined);
39667
39681
  const [bgImage, setBgImage] = reactExports.useState(undefined);
39668
39682
  const [deepHash, setDeepHash] = reactExports.useState('');
39669
-
39683
+ navigation === null || navigation === void 0 || (_navigation$setCurren = navigation.setCurrentSheetId) === null || _navigation$setCurren === void 0 || _navigation$setCurren.call(navigation, model.id);
39670
39684
  /// For each object
39671
39685
  reactExports.useEffect(() => {
39672
39686
  if (layout) {
@@ -39677,8 +39691,8 @@
39677
39691
  setDeepHash(hash);
39678
39692
  const fetchObjects = async () => {
39679
39693
  /*
39680
- Need to always fetch and evaluate everything as the sheet need to support multiple instances of the same object?
39681
- No, there is no way to add the same chart twice, so the optimization should be worth it.
39694
+ Need to always fetch and evaluate everything as the sheet need to support multiple instances of the same object?
39695
+ No, there is no way to add the same chart twice, so the optimization should be worth it.
39682
39696
  */
39683
39697
 
39684
39698
  // Clear the cell list
@@ -39722,16 +39736,29 @@
39722
39736
  fetchObjects();
39723
39737
  }
39724
39738
  }, [layout]);
39725
- const cellRenderers = reactExports.useMemo(() => cells ? cells.map(c => getCellRenderer(c, halo, initialSnOptions, initialSnPlugins, initialError, c.mounted)) : [], [cells]);
39739
+ reactExports.useEffect(() => {
39740
+ const onModelClose = () => {
39741
+ model.removeListener('closed', onModelClose);
39742
+ unmount();
39743
+ };
39744
+ model.on('closed', onModelClose);
39745
+ return () => model.removeListener('closed', onModelClose);
39746
+ }, [model]);
39747
+ const cellRenderers = reactExports.useMemo(() => cells ? cells.map(c => getCellRenderer(c, halo, initialSnOptions, initialSnPlugins, initialError, c.mounted, navigation)) : [], [cells]);
39726
39748
  reactExports.useEffect(() => {
39727
39749
  const bgComp = layout !== null && layout !== void 0 && layout.components ? layout.components.find(comp => comp.key === 'general') : null;
39728
39750
  setBgColor(resolveBgColor(bgComp, halo.public.theme));
39729
39751
  setBgImage(resolveBgImage(bgComp, halo.app));
39730
39752
  }, [layout, halo.public.theme, halo.app, themeName]);
39731
39753
 
39754
+ // Expose sheet ref api
39755
+ reactExports.useImperativeHandle(ref, () => ({
39756
+ setModel
39757
+ }), []);
39758
+
39732
39759
  /* TODO
39733
- - sheet title + bg + logo etc + as option
39734
- - sheet exposed classnames for theming
39760
+ - sheet title + bg + logo etc + as option
39761
+ - sheet exposed classnames for theming
39735
39762
  */
39736
39763
 
39737
39764
  const height = !layout || Number.isNaN(layout.height) ? '100%' : "".concat(Number(layout.height), "%");
@@ -39756,7 +39783,7 @@
39756
39783
  backgroundPosition: bgImage && bgImage.pos
39757
39784
  }
39758
39785
  }, cellRenderers);
39759
- }
39786
+ });
39760
39787
 
39761
39788
  function glue(_ref) {
39762
39789
  let {
@@ -39766,26 +39793,29 @@
39766
39793
  initialSnOptions,
39767
39794
  initialSnPlugins,
39768
39795
  onMount,
39769
- initialError
39796
+ initialError,
39797
+ navigation
39770
39798
  } = _ref;
39771
39799
  const {
39772
39800
  root
39773
39801
  } = halo;
39774
39802
  const sheetRef = React$1.createRef();
39775
- const portal = ReactDOM.createPortal( /*#__PURE__*/React$1.createElement(Sheet, {
39803
+ let portal;
39804
+ const unmount = () => {
39805
+ root.remove(portal);
39806
+ };
39807
+ portal = ReactDOM.createPortal( /*#__PURE__*/React$1.createElement(Sheet, {
39776
39808
  ref: sheetRef,
39777
39809
  halo: halo,
39778
39810
  model: model,
39779
39811
  initialSnOptions: initialSnOptions,
39780
39812
  initialSnPlugins: initialSnPlugins,
39781
39813
  initialError: initialError,
39782
- onMount: onMount
39814
+ onMount: onMount,
39815
+ unmount: unmount,
39816
+ navigation: navigation
39783
39817
  }), element, model.id);
39784
- const unmount = () => {
39785
- root.remove(portal);
39786
- model.removeListener('closed', unmount);
39787
- };
39788
- model.on('closed', unmount);
39818
+ navigation.setSheetRef(sheetRef);
39789
39819
  root.add(portal);
39790
39820
  return [unmount, sheetRef];
39791
39821
  }
@@ -39795,6 +39825,7 @@
39795
39825
  let {
39796
39826
  model,
39797
39827
  halo,
39828
+ navigation,
39798
39829
  initialError,
39799
39830
  onDestroy = async () => {}
39800
39831
  } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
@@ -39855,6 +39886,13 @@
39855
39886
  * @type {string}
39856
39887
  */
39857
39888
  model,
39889
+ /**
39890
+ * The navigation api to control sheet navigation.
39891
+ * @experimental
39892
+ * @since 5.4.0
39893
+ * @type {Navigation}
39894
+ */
39895
+ navigation,
39858
39896
  /**
39859
39897
  * Destroys the sheet and removes it from the the DOM.
39860
39898
  * @example
@@ -39886,7 +39924,8 @@
39886
39924
  initialSnOptions,
39887
39925
  initialSnPlugins,
39888
39926
  initialError,
39889
- onMount
39927
+ onMount,
39928
+ navigation
39890
39929
  });
39891
39930
  return mounted;
39892
39931
  },
@@ -39919,11 +39958,12 @@
39919
39958
  }
39920
39959
 
39921
39960
  /* eslint no-underscore-dangle:0 */
39922
- async function initSheet(model, optional, halo, initialError) {
39923
- let onDestroy = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : async () => {};
39961
+ async function initSheet(model, optional, halo, navigation, initialError) {
39962
+ let onDestroy = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : async () => {};
39924
39963
  const api = sheet({
39925
39964
  model,
39926
39965
  halo,
39966
+ navigation,
39927
39967
  initialError,
39928
39968
  onDestroy
39929
39969
  });
@@ -39939,12 +39979,115 @@
39939
39979
  return api;
39940
39980
  }
39941
39981
 
39982
+ function createNavigationApi(halo, store, model) {
39983
+ var _galaxy$anything;
39984
+ const {
39985
+ galaxy
39986
+ } = halo.public;
39987
+ if ((_galaxy$anything = galaxy.anything) !== null && _galaxy$anything !== void 0 && (_galaxy$anything = _galaxy$anything.sense) !== null && _galaxy$anything !== void 0 && _galaxy$anything.navigation) {
39988
+ var _galaxy$anything2;
39989
+ return (_galaxy$anything2 = galaxy.anything) === null || _galaxy$anything2 === void 0 || (_galaxy$anything2 = _galaxy$anything2.sense) === null || _galaxy$anything2 === void 0 ? void 0 : _galaxy$anything2.navigation;
39990
+ }
39991
+ const State = {
39992
+ model
39993
+ };
39994
+
39995
+ /**
39996
+ * @class Navigation
39997
+ * @description The navigation api instance.
39998
+ * @implements Emitter
39999
+ * @experimental
40000
+ * @since 5.4.0
40001
+ * @example
40002
+ * const navigation = useNavigation();
40003
+ * //...
40004
+ * useEffect(() => {
40005
+ * const onSheetChanged = () => {
40006
+ * // do something
40007
+ * };
40008
+ * if (navigation?.addListener) {
40009
+ * navigation.addListener("sheetChanged", onSheetChanged);
40010
+ * }
40011
+ * return () => {
40012
+ * if (navigation?.removeListener) {
40013
+ * navigation.removeListener("sheetChanged", onSheetChanged);
40014
+ * }
40015
+ * };
40016
+ * }, [navigation]);
40017
+ *
40018
+ * const onSheetClick = (sheetId: string) => {
40019
+ * navigation?.goToSheet(sheetId);
40020
+ * };
40021
+ */
40022
+ const navigationAPI = /** @lends Navigation# */{
40023
+ /**
40024
+ * Navigate to the supplied sheet and emit 'sheetChanged' event if the target sheet Id is valid.
40025
+ * This allows a navigation object to synchronize its current sheet item with the active sheet.
40026
+ * @experimental
40027
+ * @since 5.4.0
40028
+ * @param {string} sheetId Id of the sheet to navigate to
40029
+ */
40030
+ goToSheet: async sheetId => {
40031
+ var _State$sheetRef, _State$sheetRef$setMo;
40032
+ if (!State.sheetRef) {
40033
+ return;
40034
+ }
40035
+ const {
40036
+ modelStore,
40037
+ rpcRequestModelStore
40038
+ } = store;
40039
+ const key = "".concat(sheetId);
40040
+ let rpc = rpcRequestModelStore.get(key);
40041
+ if (!rpc) {
40042
+ rpc = halo.app.getObject(sheetId);
40043
+ rpcRequestModelStore.set(key, rpc);
40044
+ }
40045
+ let newModel;
40046
+ try {
40047
+ newModel = await rpc;
40048
+ if (newModel.genericType !== 'sheet') {
40049
+ return;
40050
+ }
40051
+ } catch (e) {
40052
+ return;
40053
+ }
40054
+ modelStore.set(key, newModel);
40055
+ (_State$sheetRef = State.sheetRef) === null || _State$sheetRef === void 0 || (_State$sheetRef = _State$sheetRef.current) === null || _State$sheetRef === void 0 || (_State$sheetRef$setMo = _State$sheetRef.setModel) === null || _State$sheetRef$setMo === void 0 || _State$sheetRef$setMo.call(_State$sheetRef, newModel);
40056
+ State.model = newModel;
40057
+ navigationAPI.emit('sheetChanged');
40058
+ },
40059
+ /**
40060
+ * @private
40061
+ * Set the sheet ref
40062
+ * @param {object} sheetRef sheet ref object
40063
+ */
40064
+ setSheetRef: sheetRef => {
40065
+ State.sheetRef = sheetRef;
40066
+ },
40067
+ /**
40068
+ * Return the current sheet id
40069
+ * @experimental
40070
+ * @since 5.4.0
40071
+ * @returns {string|false} The current sheet Id. false means there is no current sheet.
40072
+ */
40073
+ getCurrentSheetId: () => {
40074
+ if (State.model) {
40075
+ return State.model.id;
40076
+ }
40077
+ return false;
40078
+ }
40079
+ };
40080
+ eventmixin(navigationAPI);
40081
+ return navigationAPI;
40082
+ }
40083
+
39942
40084
  async function getObject(_ref, halo, store) {
39943
40085
  let {
39944
40086
  id,
39945
40087
  options,
39946
40088
  plugins,
39947
- element
40089
+ element,
40090
+ navigation: inputNavigation
39948
40091
  } = _ref;
39949
40092
  const {
39950
40093
  modelStore,
@@ -39958,18 +40101,19 @@
39958
40101
  }
39959
40102
  const model = await rpc;
39960
40103
  modelStore.set(key, model);
40104
+ const navigation = inputNavigation || (model.genericType === 'sheet' ? createNavigationApi(halo, store, model) : undefined);
39961
40105
  if (model.genericType === 'sheet') {
39962
40106
  return initSheet(model, {
39963
40107
  options,
39964
40108
  plugins,
39965
40109
  element
39966
- }, halo);
40110
+ }, halo, navigation);
39967
40111
  }
39968
40112
  return init(model, {
39969
40113
  options,
39970
40114
  plugins,
39971
40115
  element
39972
- }, halo);
40116
+ }, halo, navigation);
39973
40117
  }
39974
40118
 
39975
40119
  function flagsFn () {
@@ -42405,6 +42549,7 @@
42405
42549
  exports.useLayout = useLayout;
42406
42550
  exports.useMemo = useMemo;
42407
42551
  exports.useModel = useModel;
42552
+ exports.useNavigation = useNavigation;
42408
42553
  exports.useOptions = useOptions;
42409
42554
  exports.usePlugins = usePlugins;
42410
42555
  exports.usePromise = usePromise;