@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.
package/core/esm/dev.js CHANGED
@@ -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
  */
@@ -5251,7 +5251,7 @@ function GlobalStyles(props) {
5251
5251
  }
5252
5252
 
5253
5253
  /**
5254
- * @mui/styled-engine v5.16.4
5254
+ * @mui/styled-engine v5.16.6
5255
5255
  *
5256
5256
  * @license MIT
5257
5257
  * This source code is licensed under the MIT license found in the
@@ -9081,7 +9081,7 @@ function create$3(definition) {
9081
9081
  return cache[key];
9082
9082
  }
9083
9083
 
9084
- const NEBULA_VERSION_HASH = "b434";
9084
+ const NEBULA_VERSION_HASH = "4310";
9085
9085
  ClassNameGenerator.configure(componentName => {
9086
9086
  return "njs-".concat(NEBULA_VERSION_HASH, "-").concat(componentName.replace('Mui', ''));
9087
9087
  });
@@ -9313,7 +9313,7 @@ function boot(_ref2) {
9313
9313
  const appRef = React__default.createRef();
9314
9314
  const element = document.createElement('div');
9315
9315
  element.style.display = 'none';
9316
- element.setAttribute('data-nebulajs-version', "5.3.0");
9316
+ element.setAttribute('data-nebulajs-version', "5.4.0");
9317
9317
  element.setAttribute('data-app-id', app.id);
9318
9318
  document.body.appendChild(element);
9319
9319
  if (context) {
@@ -15247,9 +15247,6 @@ const More$1 = React__default.forwardRef((_ref3, ref) => {
15247
15247
  ref: ref,
15248
15248
  open: show,
15249
15249
  anchorEl: alignTo.current,
15250
- getContentAnchorEl: null,
15251
- container: alignTo.current,
15252
- disablePortal: true,
15253
15250
  hideBackdrop: true,
15254
15251
  transitionDuration: 0,
15255
15252
  slotProps: {
@@ -15669,7 +15666,7 @@ const StyledIconButton = styled(IconButton)(() => ({
15669
15666
  boxShadow: 'inset 0 0 0 2px rgb(2, 117, 217)'
15670
15667
  }
15671
15668
  }));
15672
- function ListBoxSearch(_ref2) {
15669
+ function ListBoxSearch(_ref2, ref) {
15673
15670
  let {
15674
15671
  popoverOpen,
15675
15672
  selections,
@@ -15831,7 +15828,7 @@ function ListBoxSearch(_ref2) {
15831
15828
  abortSearch();
15832
15829
  focusOnInput();
15833
15830
  };
15834
- const onKeyDownClearSearch = async e => {
15831
+ const onKeyDownClearSearch = e => {
15835
15832
  const container = e.currentTarget.closest('.listbox-container');
15836
15833
  switch (e.key) {
15837
15834
  case 'Enter':
@@ -15854,6 +15851,11 @@ function ListBoxSearch(_ref2) {
15854
15851
  e.stopPropagation();
15855
15852
  return undefined;
15856
15853
  };
15854
+ useImperativeHandle$1(ref, () => ({
15855
+ focus() {
15856
+ focusOnInput();
15857
+ }
15858
+ }));
15857
15859
  if (!visible || searchEnabled === false) {
15858
15860
  return null;
15859
15861
  }
@@ -15901,6 +15903,7 @@ function ListBoxSearch(_ref2) {
15901
15903
  }
15902
15904
  });
15903
15905
  }
15906
+ var ListBoxSearch$1 = forwardRef(ListBoxSearch);
15904
15907
 
15905
15908
  /* eslint no-underscore-dangle: 0 */
15906
15909
  function createAppSelections(_ref) {
@@ -18433,13 +18436,19 @@ function ListBoxPopover(_ref) {
18433
18436
  components,
18434
18437
  checkboxes: checkboxesOption,
18435
18438
  selectDisabled = () => false,
18436
- flags
18439
+ flags,
18440
+ sortCriteria = [{
18441
+ qSortByState: 1,
18442
+ qSortByAscii: 1,
18443
+ qSortByNumeric: 1,
18444
+ qSortByLoadOrder: 1
18445
+ }]
18437
18446
  } = _ref;
18438
18447
  const isMasterDim = Boolean(fieldName === null || fieldName === void 0 ? void 0 : fieldName.qLibraryId);
18439
18448
  const open = show && Boolean(alignTo.current);
18440
18449
  const [listCount, setListCount] = useState$1(0);
18441
18450
  const theme = useTheme$1();
18442
- const searchContainerRef = useRef();
18451
+ const searchInputRef = useRef();
18443
18452
  const [model] = useSessionModel({
18444
18453
  qInfo: {
18445
18454
  qType: 'njsListbox'
@@ -18454,12 +18463,7 @@ function ListBoxPopover(_ref) {
18454
18463
  qHeight: 0
18455
18464
  }],
18456
18465
  qDef: {
18457
- qSortCriterias: [{
18458
- qSortByState: 1,
18459
- qSortByAscii: 1,
18460
- qSortByNumeric: 1,
18461
- qSortByLoadOrder: 1
18462
- }],
18466
+ qSortCriterias: sortCriteria,
18463
18467
  qFieldDefs: isMasterDim ? undefined : [fieldName]
18464
18468
  },
18465
18469
  qLibraryId: isMasterDim ? fieldName.qLibraryId : undefined
@@ -18522,8 +18526,7 @@ function ListBoxPopover(_ref) {
18522
18526
  selections
18523
18527
  });
18524
18528
  const onCtrlF = () => {
18525
- const input = searchContainerRef.current.querySelector('input');
18526
- input === null || input === void 0 || input.focus();
18529
+ searchInputRef.current.focus();
18527
18530
  };
18528
18531
  const hasSelections$1 = hasSelections(layout);
18529
18532
  return /*#__PURE__*/React__default.createElement(Popover, {
@@ -18597,9 +18600,9 @@ function ListBoxPopover(_ref) {
18597
18600
  }, /*#__PURE__*/React__default.createElement("div", {
18598
18601
  ref: moreAlignTo
18599
18602
  }), /*#__PURE__*/React__default.createElement(Grid, {
18600
- item: true,
18601
- ref: searchContainerRef
18602
- }, /*#__PURE__*/React__default.createElement(ListBoxSearch, {
18603
+ item: true
18604
+ }, /*#__PURE__*/React__default.createElement(ListBoxSearch$1, {
18605
+ ref: searchInputRef,
18603
18606
  popoverOpen: open,
18604
18607
  styles: styles,
18605
18608
  visible: true,
@@ -20556,18 +20559,6 @@ function ListBoxInline(_ref3) {
20556
20559
  selectDisabled = () => false,
20557
20560
  flags
20558
20561
  } = options;
20559
-
20560
- // Hook that will trigger update when used in useEffects.
20561
- // Modified from: https://medium.com/@teh_builder/ref-objects-inside-useeffect-hooks-eb7c15198780
20562
- const useRefWithCallback = () => {
20563
- const [ref, setInternalRef] = useState$1({});
20564
- const setRef = useCallback(node => {
20565
- setInternalRef({
20566
- current: node
20567
- });
20568
- }, [setInternalRef]);
20569
- return [ref, setRef];
20570
- };
20571
20562
  const theme = useTheme$1();
20572
20563
  const {
20573
20564
  translator,
@@ -20591,8 +20582,8 @@ function ListBoxInline(_ref3) {
20591
20582
  appLayout: app === null || app === void 0 ? void 0 : app.layout
20592
20583
  });
20593
20584
  const containerRef = useRef();
20585
+ const searchInputRef = useRef();
20594
20586
  const [containerRectRef, containerRect] = useRect$1();
20595
- const [searchContainer, searchContainerRef] = useRefWithCallback();
20596
20587
  const [showToolbar, setShowToolbar] = useState$1(false);
20597
20588
  const [showSearch, setShowSearch] = useState$1(false);
20598
20589
  const hovering = useRef(false);
@@ -20678,16 +20669,6 @@ function ListBoxInline(_ref3) {
20678
20669
  }
20679
20670
  };
20680
20671
  }, [toolbar, selections, isPopover]);
20681
- useEffect$1(() => {
20682
- if (!searchContainer || !searchContainer.current) {
20683
- return;
20684
- }
20685
- // Focus search field on toggle-show or when focusSearch is true.
20686
- if (search && focusSearch || search === 'toggle' && showSearch) {
20687
- const input = searchContainer.current.querySelector('input');
20688
- input && input.focus();
20689
- }
20690
- }, [searchContainer && searchContainer.current, showSearch, search, focusSearch]);
20691
20672
  const {
20692
20673
  wildCardSearch,
20693
20674
  searchEnabled,
@@ -20714,11 +20695,10 @@ function ListBoxInline(_ref3) {
20714
20695
  if (search === 'toggle') {
20715
20696
  handleShowSearch();
20716
20697
  } else {
20717
- const input = searchContainer.current.querySelector('input');
20718
- input === null || input === void 0 || input.focus();
20698
+ searchInputRef.current.focus();
20719
20699
  }
20720
20700
  };
20721
- const shouldAutoFocus = searchVisible && search === 'toggle';
20701
+ const shouldAutoFocus = searchVisible && (search === 'toggle' || focusSearch);
20722
20702
 
20723
20703
  // Add a container padding for grid mode to harmonize with the grid item margins (should sum to 8px).
20724
20704
  const isGridMode = (layoutOptions === null || layoutOptions === void 0 ? void 0 : layoutOptions.dataLayout) === 'grid';
@@ -20785,9 +20765,9 @@ function ListBoxInline(_ref3) {
20785
20765
  role: "region",
20786
20766
  "aria-label": translator.get('Listbox.ResultFilterLabel')
20787
20767
  }, /*#__PURE__*/React__default.createElement(Grid, {
20788
- item: true,
20789
- ref: searchContainerRef
20790
- }, /*#__PURE__*/React__default.createElement(ListBoxSearch, {
20768
+ item: true
20769
+ }, /*#__PURE__*/React__default.createElement(ListBoxSearch$1, {
20770
+ ref: searchInputRef,
20791
20771
  selections: selections,
20792
20772
  selectionState: selectionState$1,
20793
20773
  model: model,
@@ -21413,7 +21393,8 @@ function ListBoxPopoverWrapper(_ref) {
21413
21393
  stateName: stateName,
21414
21394
  autoFocus: options.autoFocus,
21415
21395
  components: options.components,
21416
- flags: flags
21396
+ flags: flags,
21397
+ sortCriteria: options.sortCriteria
21417
21398
  });
21418
21399
  }
21419
21400
 
@@ -23547,7 +23528,8 @@ const loadType = async _ref5 => {
23547
23528
  nebbie,
23548
23529
  focusHandler,
23549
23530
  emitter,
23550
- onMount
23531
+ onMount,
23532
+ navigation
23551
23533
  } = _ref5;
23552
23534
  try {
23553
23535
  const snType = await getType({
@@ -23561,7 +23543,8 @@ const loadType = async _ref5 => {
23561
23543
  selections,
23562
23544
  nebbie,
23563
23545
  focusHandler,
23564
- emitter
23546
+ emitter,
23547
+ navigation
23565
23548
  });
23566
23549
  if (sn) {
23567
23550
  dispatch({
@@ -23599,7 +23582,8 @@ const Cell = forwardRef((_ref6, ref) => {
23599
23582
  initialError,
23600
23583
  onMount,
23601
23584
  currentId,
23602
- emitter
23585
+ emitter,
23586
+ navigation
23603
23587
  } = _ref6;
23604
23588
  const {
23605
23589
  app,
@@ -23729,7 +23713,8 @@ const Cell = forwardRef((_ref6, ref) => {
23729
23713
  nebbie,
23730
23714
  focusHandler: focusHandler.current,
23731
23715
  emitter,
23732
- onMount
23716
+ onMount,
23717
+ navigation
23733
23718
  });
23734
23719
  };
23735
23720
 
@@ -23904,7 +23889,8 @@ function glue$1(_ref) {
23904
23889
  initialSnPlugins,
23905
23890
  onMount,
23906
23891
  emitter,
23907
- initialError
23892
+ initialError,
23893
+ navigation
23908
23894
  } = _ref;
23909
23895
  const {
23910
23896
  root
@@ -23920,7 +23906,8 @@ function glue$1(_ref) {
23920
23906
  initialSnPlugins: initialSnPlugins,
23921
23907
  initialError: initialError,
23922
23908
  onMount: onMount,
23923
- emitter: emitter
23909
+ emitter: emitter,
23910
+ navigation: navigation
23924
23911
  }), element, currentId);
23925
23912
  const unmount = () => {
23926
23913
  root.remove(portal);
@@ -25136,7 +25123,6 @@ function useTheme() {
25136
25123
  /**
25137
25124
  * Gets the embed instance used.
25138
25125
  * @entry
25139
- * @experimental
25140
25126
  * @since 1.7.0
25141
25127
  * @returns {Embed} The embed instance used.
25142
25128
  * @example
@@ -25177,6 +25163,22 @@ function useDeviceType() {
25177
25163
  return useInternalContext('deviceType');
25178
25164
  }
25179
25165
 
25166
+ /**
25167
+ * Gets the navigation api to control sheet navigation. When useNavigation is used in Sense, it returns Sense.navigation.
25168
+ * @entry
25169
+ * @experimental
25170
+ * @since 5.4.0
25171
+ * @returns {Navigation} navigation api.
25172
+ * @example
25173
+ * import { useNavigation } from "@nebula.js/stardust";
25174
+ * // ...
25175
+ * const navigation = useNavigation();
25176
+ * const [activeSheetId, setActiveSheetId] = useState(navigation?.getCurrentSheetId() || "");
25177
+ */
25178
+ function useNavigation() {
25179
+ return useInternalContext('navigation');
25180
+ }
25181
+
25180
25182
  /**
25181
25183
  * Gets the array of plugins provided when rendering the visualization.
25182
25184
  * @entry
@@ -25502,7 +25504,6 @@ function onContextMenu(cb) {
25502
25504
  *
25503
25505
  * Used to update properties and get a new layout without triggering onInitialRender.
25504
25506
  * @entry
25505
- * @experimental
25506
25507
  * @returns {RenderState} The render state.
25507
25508
  * @example
25508
25509
  * import { useRenderState } from '@nebula.js/stardust';
@@ -25539,7 +25540,6 @@ function useRenderState() {
25539
25540
  /**
25540
25541
  * Gets an event emitter instance for the visualization.
25541
25542
  * @entry
25542
- * @experimental
25543
25543
  * @returns {Emitter}
25544
25544
  * @example
25545
25545
  * // In a Nebula visualization
@@ -25563,7 +25563,6 @@ function useEmitter() {
25563
25563
  }
25564
25564
 
25565
25565
  /**
25566
- * @experimental
25567
25566
  * @interface Keyboard
25568
25567
  * @property {boolean} enabled Whether or not Nebula handles keyboard navigation or not.
25569
25568
  * @property {boolean} active Set to true when the chart is activated, ie a user tabs to the chart and presses Enter or Space.
@@ -25754,6 +25753,7 @@ function createWithHooks(generator, opts, galaxy) {
25754
25753
  deviceType: galaxy.deviceType,
25755
25754
  theme: undefined,
25756
25755
  translator: galaxy.translator,
25756
+ navigation: opts.navigation,
25757
25757
  // --- dynamic values ---
25758
25758
  layout: {},
25759
25759
  appLayout: {},
@@ -26284,6 +26284,7 @@ function viz() {
26284
26284
  let {
26285
26285
  model,
26286
26286
  halo,
26287
+ navigation,
26287
26288
  initialError,
26288
26289
  onDestroy = async () => {}
26289
26290
  } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
@@ -26525,7 +26526,8 @@ function viz() {
26525
26526
  initialSnPlugins,
26526
26527
  initialError,
26527
26528
  onMount,
26528
- emitter
26529
+ emitter,
26530
+ navigation
26529
26531
  });
26530
26532
  return mounted;
26531
26533
  },
@@ -26620,11 +26622,12 @@ function viz() {
26620
26622
  }
26621
26623
 
26622
26624
  /* eslint no-underscore-dangle:0 */
26623
- async function init(model, optional, halo, initialError) {
26624
- let onDestroy = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : async () => {};
26625
+ async function init(model, optional, halo, navigation, initialError) {
26626
+ let onDestroy = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : async () => {};
26625
26627
  const api = viz({
26626
26628
  model,
26627
26629
  halo,
26630
+ navigation,
26628
26631
  initialError,
26629
26632
  onDestroy
26630
26633
  });
@@ -26686,7 +26689,8 @@ async function createSessionObject(_ref, halo, store) {
26686
26689
  options,
26687
26690
  plugins,
26688
26691
  element,
26689
- extendProperties
26692
+ extendProperties,
26693
+ navigation
26690
26694
  } = _ref;
26691
26695
  let mergedProps = {};
26692
26696
  const children = [];
@@ -26742,7 +26746,7 @@ async function createSessionObject(_ref, halo, store) {
26742
26746
  options,
26743
26747
  plugins,
26744
26748
  element
26745
- }, halo, error, onDestroy);
26749
+ }, halo, navigation, error, onDestroy);
26746
26750
  }
26747
26751
 
26748
26752
  /**
@@ -26856,7 +26860,7 @@ const SheetElement = {
26856
26860
  /** @type {'njs-sheet'} */
26857
26861
  className: 'njs-sheet'
26858
26862
  };
26859
- function getCellRenderer(cell, halo, initialSnOptions, initialSnPlugins, initialError, onMount) {
26863
+ function getCellRenderer(cell, halo, initialSnOptions, initialSnPlugins, initialError, onMount, navigation) {
26860
26864
  const {
26861
26865
  x,
26862
26866
  y,
@@ -26870,7 +26874,8 @@ function getCellRenderer(cell, halo, initialSnOptions, initialSnPlugins, initial
26870
26874
  width: "".concat(width, "%"),
26871
26875
  height: "".concat(height, "%"),
26872
26876
  position: 'absolute'
26873
- }
26877
+ },
26878
+ key: cell.model.id
26874
26879
  }, /*#__PURE__*/React__default.createElement(Cell, {
26875
26880
  ref: cell.cellRef,
26876
26881
  halo: halo,
@@ -26879,7 +26884,8 @@ function getCellRenderer(cell, halo, initialSnOptions, initialSnPlugins, initial
26879
26884
  initialSnOptions: initialSnOptions,
26880
26885
  initialSnPlugins: initialSnPlugins,
26881
26886
  initialError: initialError,
26882
- onMount: onMount
26887
+ onMount: onMount,
26888
+ navigation: navigation
26883
26889
  }));
26884
26890
  }
26885
26891
  function getBounds(pos, columns, rows) {
@@ -26893,18 +26899,22 @@ function getBounds(pos, columns, rows) {
26893
26899
  height: pos.rowspan / rows * 100
26894
26900
  };
26895
26901
  }
26896
- function Sheet(_ref) {
26902
+ const Sheet = forwardRef((_ref, ref) => {
26903
+ var _navigation$setCurren;
26897
26904
  let {
26898
- model,
26905
+ model: inputModel,
26899
26906
  halo,
26900
26907
  initialSnOptions,
26901
26908
  initialSnPlugins,
26902
26909
  initialError,
26903
- onMount
26910
+ onMount,
26911
+ unmount,
26912
+ navigation
26904
26913
  } = _ref;
26905
26914
  const {
26906
26915
  root
26907
26916
  } = halo;
26917
+ const [model, setModel] = useState$1(inputModel);
26908
26918
  const [layout] = useLayout$1(model);
26909
26919
  const {
26910
26920
  theme: themeName,
@@ -26914,7 +26924,7 @@ function Sheet(_ref) {
26914
26924
  const [bgColor, setBgColor] = useState$1(undefined);
26915
26925
  const [bgImage, setBgImage] = useState$1(undefined);
26916
26926
  const [deepHash, setDeepHash] = useState$1('');
26917
-
26927
+ navigation === null || navigation === void 0 || (_navigation$setCurren = navigation.setCurrentSheetId) === null || _navigation$setCurren === void 0 || _navigation$setCurren.call(navigation, model.id);
26918
26928
  /// For each object
26919
26929
  useEffect$1(() => {
26920
26930
  if (layout) {
@@ -26925,8 +26935,8 @@ function Sheet(_ref) {
26925
26935
  setDeepHash(hash);
26926
26936
  const fetchObjects = async () => {
26927
26937
  /*
26928
- Need to always fetch and evaluate everything as the sheet need to support multiple instances of the same object?
26929
- No, there is no way to add the same chart twice, so the optimization should be worth it.
26938
+ Need to always fetch and evaluate everything as the sheet need to support multiple instances of the same object?
26939
+ No, there is no way to add the same chart twice, so the optimization should be worth it.
26930
26940
  */
26931
26941
 
26932
26942
  // Clear the cell list
@@ -26970,16 +26980,29 @@ function Sheet(_ref) {
26970
26980
  fetchObjects();
26971
26981
  }
26972
26982
  }, [layout]);
26973
- const cellRenderers = useMemo$1(() => cells ? cells.map(c => getCellRenderer(c, halo, initialSnOptions, initialSnPlugins, initialError, c.mounted)) : [], [cells]);
26983
+ useEffect$1(() => {
26984
+ const onModelClose = () => {
26985
+ model.removeListener('closed', onModelClose);
26986
+ unmount();
26987
+ };
26988
+ model.on('closed', onModelClose);
26989
+ return () => model.removeListener('closed', onModelClose);
26990
+ }, [model]);
26991
+ const cellRenderers = useMemo$1(() => cells ? cells.map(c => getCellRenderer(c, halo, initialSnOptions, initialSnPlugins, initialError, c.mounted, navigation)) : [], [cells]);
26974
26992
  useEffect$1(() => {
26975
26993
  const bgComp = layout !== null && layout !== void 0 && layout.components ? layout.components.find(comp => comp.key === 'general') : null;
26976
26994
  setBgColor(resolveBgColor(bgComp, halo.public.theme));
26977
26995
  setBgImage(resolveBgImage(bgComp, halo.app));
26978
26996
  }, [layout, halo.public.theme, halo.app, themeName]);
26979
26997
 
26998
+ // Expose sheet ref api
26999
+ useImperativeHandle$1(ref, () => ({
27000
+ setModel
27001
+ }), []);
27002
+
26980
27003
  /* TODO
26981
- - sheet title + bg + logo etc + as option
26982
- - sheet exposed classnames for theming
27004
+ - sheet title + bg + logo etc + as option
27005
+ - sheet exposed classnames for theming
26983
27006
  */
26984
27007
 
26985
27008
  const height = !layout || Number.isNaN(layout.height) ? '100%' : "".concat(Number(layout.height), "%");
@@ -27004,7 +27027,7 @@ function Sheet(_ref) {
27004
27027
  backgroundPosition: bgImage && bgImage.pos
27005
27028
  }
27006
27029
  }, cellRenderers);
27007
- }
27030
+ });
27008
27031
 
27009
27032
  function glue(_ref) {
27010
27033
  let {
@@ -27014,26 +27037,29 @@ function glue(_ref) {
27014
27037
  initialSnOptions,
27015
27038
  initialSnPlugins,
27016
27039
  onMount,
27017
- initialError
27040
+ initialError,
27041
+ navigation
27018
27042
  } = _ref;
27019
27043
  const {
27020
27044
  root
27021
27045
  } = halo;
27022
27046
  const sheetRef = React__default.createRef();
27023
- const portal = ReactDOM.createPortal( /*#__PURE__*/React__default.createElement(Sheet, {
27047
+ let portal;
27048
+ const unmount = () => {
27049
+ root.remove(portal);
27050
+ };
27051
+ portal = ReactDOM.createPortal( /*#__PURE__*/React__default.createElement(Sheet, {
27024
27052
  ref: sheetRef,
27025
27053
  halo: halo,
27026
27054
  model: model,
27027
27055
  initialSnOptions: initialSnOptions,
27028
27056
  initialSnPlugins: initialSnPlugins,
27029
27057
  initialError: initialError,
27030
- onMount: onMount
27058
+ onMount: onMount,
27059
+ unmount: unmount,
27060
+ navigation: navigation
27031
27061
  }), element, model.id);
27032
- const unmount = () => {
27033
- root.remove(portal);
27034
- model.removeListener('closed', unmount);
27035
- };
27036
- model.on('closed', unmount);
27062
+ navigation.setSheetRef(sheetRef);
27037
27063
  root.add(portal);
27038
27064
  return [unmount, sheetRef];
27039
27065
  }
@@ -27043,6 +27069,7 @@ function sheet() {
27043
27069
  let {
27044
27070
  model,
27045
27071
  halo,
27072
+ navigation,
27046
27073
  initialError,
27047
27074
  onDestroy = async () => {}
27048
27075
  } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
@@ -27103,6 +27130,13 @@ function sheet() {
27103
27130
  * @type {string}
27104
27131
  */
27105
27132
  model,
27133
+ /**
27134
+ * The navigation api to control sheet navigation.
27135
+ * @experimental
27136
+ * @since 5.4.0
27137
+ * @type {Navigation}
27138
+ */
27139
+ navigation,
27106
27140
  /**
27107
27141
  * Destroys the sheet and removes it from the the DOM.
27108
27142
  * @example
@@ -27134,7 +27168,8 @@ function sheet() {
27134
27168
  initialSnOptions,
27135
27169
  initialSnPlugins,
27136
27170
  initialError,
27137
- onMount
27171
+ onMount,
27172
+ navigation
27138
27173
  });
27139
27174
  return mounted;
27140
27175
  },
@@ -27167,11 +27202,12 @@ function sheet() {
27167
27202
  }
27168
27203
 
27169
27204
  /* eslint no-underscore-dangle:0 */
27170
- async function initSheet(model, optional, halo, initialError) {
27171
- let onDestroy = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : async () => {};
27205
+ async function initSheet(model, optional, halo, navigation, initialError) {
27206
+ let onDestroy = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : async () => {};
27172
27207
  const api = sheet({
27173
27208
  model,
27174
27209
  halo,
27210
+ navigation,
27175
27211
  initialError,
27176
27212
  onDestroy
27177
27213
  });
@@ -27187,12 +27223,115 @@ async function initSheet(model, optional, halo, initialError) {
27187
27223
  return api;
27188
27224
  }
27189
27225
 
27226
+ function createNavigationApi(halo, store, model) {
27227
+ var _galaxy$anything;
27228
+ const {
27229
+ galaxy
27230
+ } = halo.public;
27231
+ if ((_galaxy$anything = galaxy.anything) !== null && _galaxy$anything !== void 0 && (_galaxy$anything = _galaxy$anything.sense) !== null && _galaxy$anything !== void 0 && _galaxy$anything.navigation) {
27232
+ var _galaxy$anything2;
27233
+ 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;
27234
+ }
27235
+ const State = {
27236
+ model
27237
+ };
27238
+
27239
+ /**
27240
+ * @class Navigation
27241
+ * @description The navigation api instance.
27242
+ * @implements Emitter
27243
+ * @experimental
27244
+ * @since 5.4.0
27245
+ * @example
27246
+ * const navigation = useNavigation();
27247
+ * //...
27248
+ * useEffect(() => {
27249
+ * const onSheetChanged = () => {
27250
+ * // do something
27251
+ * };
27252
+ * if (navigation?.addListener) {
27253
+ * navigation.addListener("sheetChanged", onSheetChanged);
27254
+ * }
27255
+ * return () => {
27256
+ * if (navigation?.removeListener) {
27257
+ * navigation.removeListener("sheetChanged", onSheetChanged);
27258
+ * }
27259
+ * };
27260
+ * }, [navigation]);
27261
+ *
27262
+ * const onSheetClick = (sheetId: string) => {
27263
+ * navigation?.goToSheet(sheetId);
27264
+ * };
27265
+ */
27266
+ const navigationAPI = /** @lends Navigation# */{
27267
+ /**
27268
+ * Navigate to the supplied sheet and emit 'sheetChanged' event if the target sheet Id is valid.
27269
+ * This allows a navigation object to synchronize its current sheet item with the active sheet.
27270
+ * @experimental
27271
+ * @since 5.4.0
27272
+ * @param {string} sheetId Id of the sheet to navigate to
27273
+ */
27274
+ goToSheet: async sheetId => {
27275
+ var _State$sheetRef, _State$sheetRef$setMo;
27276
+ if (!State.sheetRef) {
27277
+ return;
27278
+ }
27279
+ const {
27280
+ modelStore,
27281
+ rpcRequestModelStore
27282
+ } = store;
27283
+ const key = "".concat(sheetId);
27284
+ let rpc = rpcRequestModelStore.get(key);
27285
+ if (!rpc) {
27286
+ rpc = halo.app.getObject(sheetId);
27287
+ rpcRequestModelStore.set(key, rpc);
27288
+ }
27289
+ let newModel;
27290
+ try {
27291
+ newModel = await rpc;
27292
+ if (newModel.genericType !== 'sheet') {
27293
+ return;
27294
+ }
27295
+ } catch (e) {
27296
+ return;
27297
+ }
27298
+ modelStore.set(key, newModel);
27299
+ (_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);
27300
+ State.model = newModel;
27301
+ navigationAPI.emit('sheetChanged');
27302
+ },
27303
+ /**
27304
+ * @private
27305
+ * Set the sheet ref
27306
+ * @param {object} sheetRef sheet ref object
27307
+ */
27308
+ setSheetRef: sheetRef => {
27309
+ State.sheetRef = sheetRef;
27310
+ },
27311
+ /**
27312
+ * Return the current sheet id
27313
+ * @experimental
27314
+ * @since 5.4.0
27315
+ * @returns {string|false} The current sheet Id. false means there is no current sheet.
27316
+ */
27317
+ getCurrentSheetId: () => {
27318
+ if (State.model) {
27319
+ return State.model.id;
27320
+ }
27321
+ return false;
27322
+ }
27323
+ };
27324
+ eventmixin(navigationAPI);
27325
+ return navigationAPI;
27326
+ }
27327
+
27190
27328
  async function getObject(_ref, halo, store) {
27191
27329
  let {
27192
27330
  id,
27193
27331
  options,
27194
27332
  plugins,
27195
- element
27333
+ element,
27334
+ navigation: inputNavigation
27196
27335
  } = _ref;
27197
27336
  const {
27198
27337
  modelStore,
@@ -27206,18 +27345,19 @@ async function getObject(_ref, halo, store) {
27206
27345
  }
27207
27346
  const model = await rpc;
27208
27347
  modelStore.set(key, model);
27348
+ const navigation = inputNavigation || (model.genericType === 'sheet' ? createNavigationApi(halo, store, model) : undefined);
27209
27349
  if (model.genericType === 'sheet') {
27210
27350
  return initSheet(model, {
27211
27351
  options,
27212
27352
  plugins,
27213
27353
  element
27214
- }, halo);
27354
+ }, halo, navigation);
27215
27355
  }
27216
27356
  return init(model, {
27217
27357
  options,
27218
27358
  plugins,
27219
27359
  element
27220
- }, halo);
27360
+ }, halo, navigation);
27221
27361
  }
27222
27362
 
27223
27363
  function flagsFn () {
@@ -29631,5 +29771,5 @@ const __DO_NOT_USE__ = {
29631
29771
  locale
29632
29772
  };
29633
29773
 
29634
- export { mocker as EnigmaMocker, __DO_NOT_USE__, conversion, index as embed, onContextMenu, onTakeSnapshot, useAction, useApp, useAppLayout, useConstraints, useDeviceType, useEffect, useElement, useEmbed, useEmitter, useGlobal, useImperativeHandle, useInteractionState, useKeyboard, useLayout, useMemo, useModel, useOptions, usePlugins, usePromise, useRect, useRenderState, useSelections, useStaleLayout, useState, useTheme, useTranslator };
29774
+ export { mocker as EnigmaMocker, __DO_NOT_USE__, conversion, index as embed, onContextMenu, onTakeSnapshot, useAction, useApp, useAppLayout, useConstraints, useDeviceType, useEffect, useElement, useEmbed, useEmitter, useGlobal, useImperativeHandle, useInteractionState, useKeyboard, useLayout, useMemo, useModel, useNavigation, useOptions, usePlugins, usePromise, useRect, useRenderState, useSelections, useStaleLayout, useState, useTheme, useTranslator };
29635
29775
  //# sourceMappingURL=dev.js.map