@apia/dashboard-controller 3.0.8 → 3.0.10

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/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { ApiaApi, makeApiaUrl } from '@apia/api';
2
- import { EventEmitter, useMount, useImperativeComponentEvents, getLabel, makeImperativeComponent, parseXmlAsync, toBoolean, isChild, getSpecificParent, ucfirst, useLatest } from '@apia/util';
2
+ import { EventEmitter, useMount, useImperativeComponentEvents, getLabel, makeImperativeComponent, parseXmlAsync, toBoolean, isChild, getSpecificParent, ucfirst, downloadUrl, useLatest } from '@apia/util';
3
3
  import { createContext, useMemo, useContext, useState, useEffect, useCallback, useRef, useDeferredValue, Suspense, lazy, Component, startTransition } from 'react';
4
4
  import { jsx, jsxs, Fragment } from '@apia/theme/jsx-runtime';
5
5
  import { Icon } from '@apia/icons';
6
- import { spacing, responsive, getSpacingLayouts, spacingLayouts, Box, makeStyledComponent, Heading, Paragraph } from '@apia/theme';
6
+ import { spacingLayouts, Box, getVariant, Heading, makeStyledComponent, Paragraph } from '@apia/theme';
7
7
  import { shallowEqual } from 'react-redux';
8
8
  import { createSlice, injectReducers, shallowEqual as shallowEqual$1 } from '@apia/store';
9
9
  import { IconButton, AutoEllipsis, SimpleButton } from '@apia/components';
@@ -214,18 +214,14 @@ function usePanelOnEvent(distinction, callback) {
214
214
  });
215
215
  }
216
216
 
217
- function changePanelTitle(panelId, newTitle) {
218
- eventsController.fireEvent(
219
- { panelId },
220
- "changeTitle",
221
- newTitle
222
- );
217
+ function changePanelTitle(identifier, newTitle) {
218
+ eventsController.fireEvent(identifier, "__changePanelTitle__", newTitle);
223
219
  }
224
220
  function usePanelChangeTitle() {
225
221
  const fireEvent = usePanelFireEvent();
226
222
  return useCallback(
227
223
  (newTitle) => {
228
- fireEvent("changeTitle", newTitle);
224
+ fireEvent("__changePanelTitle__", newTitle);
229
225
  },
230
226
  [fireEvent]
231
227
  );
@@ -238,20 +234,22 @@ function changePanelFooter(panelId, footer) {
238
234
  footer
239
235
  );
240
236
  }
241
- function usePanelFooter(panelId, { initialData }) {
237
+ function usePanelFooter({
238
+ initialData
239
+ }) {
240
+ const identifier = usePanelIdentity();
242
241
  const [footer, setFooter] = useState(
243
242
  initialData?.footer?.footer?.text ? initialData?.footer?.footer : null
244
243
  );
245
244
  const handleFooterClick = useCallback(
246
245
  (ev) => {
247
- console.log(ev.type);
248
246
  if (footer)
249
- handleAction(panelId, ev, footer);
247
+ handleAction(identifier, ev, footer);
250
248
  },
251
- [footer, panelId]
249
+ [footer, identifier]
252
250
  );
253
251
  usePanelOnEvent(
254
- { eventType: "changeFooter", panelId },
252
+ { eventType: "changeFooter", panelId: identifier.panelId },
255
253
  (ev) => {
256
254
  if (!ev.payload.text)
257
255
  setFooter(null);
@@ -301,113 +299,6 @@ function useDashboardContext() {
301
299
  return context;
302
300
  }
303
301
 
304
- const defaultPanelWrapperStyles = {
305
- pb: spacing(6),
306
- "&:last-child": {
307
- pb: 0
308
- },
309
- ".panel__container": {
310
- background: "palette.background.paper",
311
- border: "1px solid",
312
- borderColor: "palette.gray.800",
313
- display: "flex",
314
- flexDirection: "column",
315
- borderRadius: "panel",
316
- boxShadow: "panel"
317
- },
318
- ".panel__icon": {
319
- height: "24px",
320
- width: "24px",
321
- borderRadius: "100%",
322
- transform: "scale(1.25)",
323
- marginRight: "6px"
324
- },
325
- ".panel__header": {
326
- alignItems: "center",
327
- cursor: "grab",
328
- display: "flex",
329
- flexWrap: "nowrap",
330
- fontWeight: "bold",
331
- justifyContent: "space-between",
332
- maxWidth: "100%",
333
- overflow: "visible",
334
- backgroundColor: "palette.secondary.light",
335
- borderBottomRightRadius: "0px !important",
336
- borderBottomLeftRadius: "0px !important",
337
- pl: 4,
338
- py: 4,
339
- borderRadius: "panel",
340
- ".panel__header__left": {
341
- alignItems: "center",
342
- display: "flex",
343
- gap: 2,
344
- overflow: "visible",
345
- svg: {
346
- color: "palette.error.dark"
347
- }
348
- },
349
- "& > *": {
350
- flexShrink: 0
351
- },
352
- ".panel__header__buttons": {
353
- alignSelf: "end",
354
- display: "flex",
355
- flexGrow: 1,
356
- fontWeight: "normal",
357
- gap: 2,
358
- justifyContent: "end",
359
- right: 0,
360
- background: "transparent",
361
- pr: 3,
362
- opacity: responsive({ 0: 1, 3: 0 }),
363
- alignItems: "center",
364
- pl: 3,
365
- height: "24px",
366
- button: {
367
- width: "30px",
368
- height: "30px"
369
- }
370
- }
371
- },
372
- ".panel__content": {
373
- ...getSpacingLayouts()
374
- },
375
- ".panel__container:hover, .panel__container:focus, .panel__container:focus-within, .panel__container.isLoading": {
376
- ".panel__header__buttons, .lastUpdate__wrapper": {
377
- opacity: responsive({ 0: 1 })
378
- }
379
- },
380
- ".panel__footer": {
381
- display: "flex",
382
- justifyContent: "space-between",
383
- gap: spacing(3),
384
- background: "palette.secondary.light",
385
- px: 4,
386
- py: 3,
387
- color: "palette.text.primary",
388
- borderRadius: "panel",
389
- borderTopRightRadius: "0px",
390
- borderTopLeftRadius: "0px",
391
- overflow: "hidden",
392
- alignItems: "center"
393
- },
394
- ".panel__iconButton, .lastUpdate__wrapper": {
395
- transition: "opacity 300ms"
396
- },
397
- ".lastUpdate__wrapper": {
398
- fontSize: 14,
399
- opacity: 0,
400
- flexShrink: 0
401
- },
402
- ".panel__footer__text": {
403
- overflow: "hidden",
404
- flexShrink: 1
405
- },
406
- "span.panel__title": {
407
- flexShrink: "1 !important"
408
- }
409
- };
410
-
411
302
  const RefreshButton = (props) => {
412
303
  const [isDisabled, setIsDisabled] = useState(false);
413
304
  const isLoading = usePanelIsLoading();
@@ -546,25 +437,23 @@ const PanelContextProvider = ({
546
437
  }) => {
547
438
  return /* @__PURE__ */ jsx(PanelContext.Provider, { value, children });
548
439
  };
549
- function useMakePanelContext(panelId, panelProps) {
440
+ function useMakePanelContext(panelProps) {
441
+ const identifier = usePanelIdentity();
550
442
  const setTitle = useCallback(
551
443
  (newTitle) => {
552
- changePanelTitle(panelId, newTitle);
444
+ changePanelTitle(identifier, newTitle);
553
445
  },
554
- [panelId]
446
+ [identifier]
555
447
  );
556
448
  const { ref, setLayout } = usePanelContextLayout();
557
449
  const [title, setTitleState] = useState(panelProps.title);
558
450
  usePanelOnEvent(
559
- { eventType: "changeTitle", panelId },
451
+ { eventType: "changeTitle", panelId: identifier.panelId },
560
452
  (ev) => {
561
453
  setTitleState(ev.payload);
562
454
  }
563
455
  );
564
- const { footer, handleFooterClick } = usePanelFooter(
565
- panelId,
566
- panelProps.initialData
567
- );
456
+ const { footer, handleFooterClick } = usePanelFooter(panelProps.initialData);
568
457
  const [footerContent, setFooterContent] = useState(null);
569
458
  const dispatch = usePanelActions();
570
459
  const hasRefreshedOnStartup = useRef(false);
@@ -575,14 +464,19 @@ function useMakePanelContext(panelId, panelProps) {
575
464
  hasRefreshedOnStartup.current = true;
576
465
  if (panelProps.refreshOnStart) {
577
466
  void dispatch({ action: "refresh" }).then(() => {
578
- dashboard.bootstrapper.setPanelHasLoaded(panelId);
467
+ dashboard.bootstrapper.setPanelHasLoaded(identifier.panelId);
579
468
  });
580
469
  } else {
581
- dashboard.bootstrapper.setPanelHasLoaded(panelId);
470
+ dashboard.bootstrapper.setPanelHasLoaded(identifier.panelId);
582
471
  }
583
472
  }
584
473
  },
585
- [dashboard.bootstrapper, dispatch, panelId, panelProps.refreshOnStart]
474
+ [
475
+ dashboard.bootstrapper,
476
+ dispatch,
477
+ identifier.panelId,
478
+ panelProps.refreshOnStart
479
+ ]
586
480
  );
587
481
  const contextValue = useMemo(
588
482
  () => ({ setFooterContent, setTitle, setLayout, panelProps, setRef }),
@@ -654,64 +548,56 @@ const PanelFooter = ({
654
548
  ] }) });
655
549
  };
656
550
 
657
- const DefaultPanelWrapper = makeStyledComponent(
658
- "DefaultPanelWrapper",
659
- "layout.common.dashboards.panel",
660
- defaultPanelWrapperStyles,
661
- ({ children, ...props }) => {
662
- const { panelId, panelName, panelType } = usePanelIdentity();
663
- const { contextValue, title, ref, ...footerProps } = useMakePanelContext(
664
- panelId,
665
- props
666
- );
667
- const panelTitleDescription = usePanelTitleDescription();
668
- const panelImage = usePanelImage() ?? props.image;
669
- const showHeader = props.showTitle || props.isConfigurable || props.isRefreshable || panelImage;
670
- const isLoading = usePanelIsLoading();
671
- return /* @__PURE__ */ jsx(PanelContextProvider, { value: contextValue, children: /* @__PURE__ */ jsxs(
672
- "div",
673
- {
674
- ref,
675
- className: `panel__container ${isLoading ? "isLoading" : ""}`,
676
- "data-panelname": panelName,
677
- "data-paneltype": panelType,
678
- "data-panelid": panelId,
679
- children: [
680
- showHeader && /* @__PURE__ */ jsxs("div", { draggable: props.canMove, className: `panel__header`, children: [
681
- /* @__PURE__ */ jsxs(
682
- "div",
683
- {
684
- className: "panel__header__left",
685
- sx: {
686
- maxWidth: "80%",
687
- overflow: "hidden",
688
- whiteSpace: "nowrap"
689
- },
690
- children: [
691
- panelImage && !panelImage.match("(^.+null$)") && /* @__PURE__ */ jsx("img", { src: panelImage, className: "panel__icon" }),
692
- /* @__PURE__ */ jsxs(AutoEllipsis, { children: [
693
- props.showTitle && /* @__PURE__ */ jsx(
694
- "span",
695
- {
696
- className: "panel__title",
697
- title: panelTitleDescription ?? title,
698
- children: title
699
- }
700
- ),
701
- /* @__PURE__ */ jsx(NetworkState, { title })
702
- ] })
703
- ]
704
- }
705
- ),
706
- /* @__PURE__ */ jsx("div", { className: `panel__header__buttons`, children: /* @__PURE__ */ jsx(PanelButtons, { ...props, id: panelId }) })
707
- ] }),
708
- /* @__PURE__ */ jsx("div", { className: "panel__content", children }),
709
- /* @__PURE__ */ jsx(PanelFooter, { isRefreshable: props.isRefreshable, ...footerProps })
710
- ]
711
- }
712
- ) });
713
- }
714
- );
551
+ const DefaultPanelWrapper = ({ children, ...props }) => {
552
+ const { panelId, panelName, panelType } = usePanelIdentity();
553
+ const { contextValue, title, ref, ...footerProps } = useMakePanelContext(props);
554
+ const panelTitleDescription = usePanelTitleDescription();
555
+ const panelImage = usePanelImage() ?? props.image;
556
+ const showHeader = props.showTitle || props.isConfigurable || props.isRefreshable || panelImage;
557
+ const isLoading = usePanelIsLoading();
558
+ return /* @__PURE__ */ jsx(Box, { ...getVariant("layout.common.dashboards.panel"), children: /* @__PURE__ */ jsx(PanelContextProvider, { value: contextValue, children: /* @__PURE__ */ jsxs(
559
+ "div",
560
+ {
561
+ ref,
562
+ className: `panel__container ${isLoading ? "isLoading" : ""}`,
563
+ "data-panelname": panelName,
564
+ "data-paneltype": panelType,
565
+ "data-panelid": panelId,
566
+ children: [
567
+ showHeader && /* @__PURE__ */ jsxs("div", { draggable: props.canMove, className: `panel__header`, children: [
568
+ /* @__PURE__ */ jsxs(
569
+ "div",
570
+ {
571
+ className: "panel__header__left",
572
+ sx: {
573
+ maxWidth: "80%",
574
+ overflow: "hidden",
575
+ whiteSpace: "nowrap"
576
+ },
577
+ children: [
578
+ panelImage && !panelImage.match("(^.+null$)") && /* @__PURE__ */ jsx("img", { src: panelImage, className: "panel__icon" }),
579
+ /* @__PURE__ */ jsxs(AutoEllipsis, { children: [
580
+ props.showTitle && /* @__PURE__ */ jsx(
581
+ "span",
582
+ {
583
+ className: "panel__title",
584
+ title: panelTitleDescription ?? title,
585
+ children: title
586
+ }
587
+ ),
588
+ /* @__PURE__ */ jsx(NetworkState, { title })
589
+ ] })
590
+ ]
591
+ }
592
+ ),
593
+ /* @__PURE__ */ jsx("div", { className: `panel__header__buttons`, children: /* @__PURE__ */ jsx(PanelButtons, { ...props, id: panelId }) })
594
+ ] }),
595
+ /* @__PURE__ */ jsx("div", { className: "panel__content", children }),
596
+ /* @__PURE__ */ jsx(PanelFooter, { isRefreshable: props.isRefreshable, ...footerProps })
597
+ ]
598
+ }
599
+ ) }) });
600
+ };
715
601
 
716
602
  var __defProp$5 = Object.defineProperty;
717
603
  var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -845,13 +731,43 @@ _removeSkeletons = new WeakMap();
845
731
 
846
732
  const PanelNotFound = () => {
847
733
  const props = usePanelIdentity();
734
+ useYieldPanelIsReady();
848
735
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(Heading, { children: [
849
736
  "Panel not found: ",
850
737
  props.panelType
851
738
  ] }) });
852
739
  };
853
740
 
741
+ const ContainerNotFound = () => {
742
+ const props = usePanelIdentity();
743
+ return /* @__PURE__ */ jsxs(Heading, { children: [
744
+ "Container not found for panel: ",
745
+ props.panelName
746
+ ] });
747
+ };
748
+
749
+ const importedContainers = {};
854
750
  const importedPanels = {};
751
+ function importContainer(path) {
752
+ if (!importedContainers[path])
753
+ importedContainers[path] = lazy(() => {
754
+ return new Promise((resolve) => {
755
+ import(
756
+ /* webpackChunkName: "[request]" */
757
+ /* webpackInclude: /\.tsx?$/ */
758
+ /* webpackPreload: true */
759
+ `/containers/${path}`
760
+ ).then((result) => {
761
+ resolve(result.default);
762
+ }).catch(() => {
763
+ resolve({
764
+ default: ContainerNotFound
765
+ });
766
+ });
767
+ });
768
+ });
769
+ return importedContainers[path];
770
+ }
855
771
  function importPanel(path) {
856
772
  if (!importedPanels[path])
857
773
  importedPanels[path] = lazy(() => {
@@ -984,10 +900,7 @@ class DashboardPanel extends EventEmitter {
984
900
  __privateGet$3(this, _loaders).props();
985
901
  },
986
902
  initialData: () => {
987
- const panel = this.getContainer();
988
- const panelContent = panel.querySelector(
989
- ".panel__content"
990
- );
903
+ const panelContent = this.getContainer();
991
904
  const xml = panelContent.innerHTML.replaceAll("&lt;", "<").replaceAll("&gt;", ">").replaceAll("&amp;", "&");
992
905
  panelContent.innerHTML = "";
993
906
  this.initialData = parseXmlAsync(xml.replace(/<!--?[^>]+>/, ""));
@@ -1085,7 +998,7 @@ class DashboardPanel extends EventEmitter {
1085
998
  this.dashboard.bootstrapper.SuspendPanelUntilDashbordReady,
1086
999
  {
1087
1000
  panelId: this.id,
1088
- children: /* @__PURE__ */ jsx(PanelErrorBoundary, { children: isVisible ? /* @__PURE__ */ jsx(Element, { initialData: resolvedInitialData.initialData }) : null })
1001
+ children: /* @__PURE__ */ jsx(PanelErrorBoundary, { children: isVisible ? /* @__PURE__ */ jsx(Element, { initialData: resolvedInitialData }) : null })
1089
1002
  }
1090
1003
  )
1091
1004
  }
@@ -1102,7 +1015,7 @@ class DashboardPanel extends EventEmitter {
1102
1015
  Element: importPanel(this.props.type)
1103
1016
  }
1104
1017
  ),
1105
- this.getContainer().querySelector(".panel__content"),
1018
+ this.getContainer(),
1106
1019
  this.id
1107
1020
  );
1108
1021
  }
@@ -1765,9 +1678,14 @@ class Dashboard extends EventEmitter {
1765
1678
  "[data-panel]"
1766
1679
  );
1767
1680
  Array.from(panelsElements).forEach((current) => {
1681
+ let container = __privateGet(this, _PanelContainer);
1682
+ const customContainer = current.dataset.panelContainer;
1683
+ if (customContainer) {
1684
+ container = importContainer(current.dataset.panelContainer);
1685
+ }
1768
1686
  const panel = new DashboardPanel({
1769
1687
  dashboard: this,
1770
- PanelContainer: __privateGet(this, _PanelContainer),
1688
+ PanelContainer: container,
1771
1689
  id: current.dataset.id
1772
1690
  });
1773
1691
  let panelPath = panel.getParameters().PAR_SPA_PATH || "*";
@@ -1811,14 +1729,12 @@ class Dashboard extends EventEmitter {
1811
1729
  {
1812
1730
  route: new RegExp(`(?:/spa)?/(\\w+)`),
1813
1731
  callback: (result) => {
1814
- console.log("Dashboard", { scene: result[1] });
1815
1732
  this.loadScene(result[1]);
1816
1733
  }
1817
1734
  },
1818
1735
  {
1819
1736
  route: new RegExp(`/`),
1820
1737
  callback: () => {
1821
- console.log("Dashboard", { noScene: "/" });
1822
1738
  this.loadScene("/");
1823
1739
  }
1824
1740
  }
@@ -1952,7 +1868,7 @@ function firePanelAction(panelId, action, parameters, options) {
1952
1868
  startTransition(() => {
1953
1869
  if (result?.data?.title) {
1954
1870
  changePanelTitle(
1955
- panelId,
1871
+ { panelId },
1956
1872
  result?.data?.title
1957
1873
  );
1958
1874
  }
@@ -1965,9 +1881,7 @@ function firePanelAction(panelId, action, parameters, options) {
1965
1881
  if (result?.data?.titleAction) {
1966
1882
  setPanelTitleAction(panelId, result?.data?.titleAction);
1967
1883
  }
1968
- if (result?.data?.image) {
1969
- setPanelImageAction(panelId, result?.data?.image);
1970
- }
1884
+ setPanelImageAction(panelId, result?.data?.image ?? "");
1971
1885
  if (result?.data?.titleDescription) {
1972
1886
  setPanelTitleDescritpion(
1973
1887
  panelId,
@@ -1992,7 +1906,7 @@ function firePanelAction(panelId, action, parameters, options) {
1992
1906
  });
1993
1907
  }
1994
1908
 
1995
- function handleAction(panelId, event, action) {
1909
+ function handleAction(panelIdentifier, event, action) {
1996
1910
  if (event.type === "dblclick" && action.actionSource === "DOUBLE_CLICK" || (event.type === "click" || event.type === "mousedown") && action.actionSource === "CLICK" || event.type === "keydown" && event.code === "Enter") {
1997
1911
  if (action?.action) {
1998
1912
  switch (action.actionBehavior) {
@@ -2006,20 +1920,28 @@ function handleAction(panelId, event, action) {
2006
1920
  break;
2007
1921
  case "OPEN_TAB":
2008
1922
  window.top?.tabsController.openTabByUrl(
2009
- action.actionNewTabTitle || action.text,
1923
+ action.additionalData || action.text,
2010
1924
  action.action
2011
1925
  );
2012
1926
  break;
2013
1927
  case "RUN_ACTION":
2014
1928
  firePanelAction(
2015
- panelId,
1929
+ panelIdentifier.panelId,
2016
1930
  action.action,
2017
1931
  {},
2018
- { requestConfig: {
2019
- handleLoad: true
2020
- } }
1932
+ { requestConfig: { handleLoad: true } }
2021
1933
  );
2022
1934
  break;
1935
+ case "FIRE_EVENT":
1936
+ eventsController.fireEvent(
1937
+ panelIdentifier,
1938
+ action.action,
1939
+ JSON.parse(action.additionalData)
1940
+ );
1941
+ break;
1942
+ case "DOWNLOAD":
1943
+ downloadUrl(action.action);
1944
+ break;
2023
1945
  default:
2024
1946
  console.error("Unknown action behavior: ", action);
2025
1947
  }
@@ -2044,6 +1966,41 @@ function usePanelIsLoading() {
2044
1966
  return isLoading;
2045
1967
  }
2046
1968
 
1969
+ const useActionEventHandlers = () => {
1970
+ const identifier = usePanelIdentity();
1971
+ const onClick = useCallback(
1972
+ (ev) => {
1973
+ return (action) => {
1974
+ if (action.actionSource !== "CLICK")
1975
+ return;
1976
+ handleAction(identifier, ev, action);
1977
+ };
1978
+ },
1979
+ [identifier]
1980
+ );
1981
+ const onDoubleClick = useCallback(
1982
+ (ev) => {
1983
+ return (action) => {
1984
+ if (action.actionSource !== "DOUBLE_CLICK")
1985
+ return;
1986
+ handleAction(identifier, ev, action);
1987
+ };
1988
+ },
1989
+ [identifier]
1990
+ );
1991
+ const onKeyDown = useCallback(
1992
+ (ev) => {
1993
+ return (action) => {
1994
+ if (ev.code !== "Enter")
1995
+ return;
1996
+ handleAction(identifier, ev, action);
1997
+ };
1998
+ },
1999
+ [identifier]
2000
+ );
2001
+ return { onClick, onDoubleClick, onKeyDown };
2002
+ };
2003
+
2047
2004
  const NetworkState = ({ title }) => {
2048
2005
  const isConnected = usePanelNetworkState();
2049
2006
  return /* @__PURE__ */ jsx(Fragment, { children: !isConnected && /* @__PURE__ */ jsx(
@@ -2070,10 +2027,7 @@ const LandingPagePanelWrapper = ({
2070
2027
  ...props
2071
2028
  }) => {
2072
2029
  const { panelId, panelName, panelType } = usePanelIdentity();
2073
- const { contextValue, title, ref, ...footerProps } = useMakePanelContext(
2074
- panelId,
2075
- props
2076
- );
2030
+ const { contextValue, title, ref, ...footerProps } = useMakePanelContext(props);
2077
2031
  const panelTitleAction = usePanelTitleAction();
2078
2032
  const panelTitleDescription = usePanelTitleDescription();
2079
2033
  const dashboard = useDashboardContext();
@@ -2107,6 +2061,11 @@ const LandingPagePanelWrapper = ({
2107
2061
  ) });
2108
2062
  };
2109
2063
 
2064
+ const EmptyPanelWrapper = (props) => {
2065
+ const { contextValue } = useMakePanelContext(props);
2066
+ return /* @__PURE__ */ jsx(PanelContextProvider, { value: contextValue, children: props.children });
2067
+ };
2068
+
2110
2069
  const reducers = {};
2111
2070
  function initPanelTypeUpdater(panelType) {
2112
2071
  if (!reducers[panelType]) {
@@ -2235,5 +2194,5 @@ function createPanelStore(panelType, initialState, reducers) {
2235
2194
  return [usePanelDispatcher, useSelector];
2236
2195
  }
2237
2196
 
2238
- export { Dashboard, LandingPagePanelWrapper, PanelIdentifier, PanelIdentifierContext, changePanelTitle, createPanelStore, eventsController, externalFirePanelAction, handleAction, store as parametersStore, saveParameters, useDashboardContext, useDashboardPanel, usePanelActions, usePanelChangeTitle, usePanelContext, usePanelFireEvent, usePanelIdentity, usePanelIsLoading, usePanelNetworkState, usePanelOnEvent, usePanelParametersSelector, usePanelPosition, useYieldPanelIsReady };
2197
+ export { Dashboard, EmptyPanelWrapper, LandingPagePanelWrapper, NetworkState, PanelButtons, PanelContextProvider, PanelFooter, PanelIdentifier, PanelIdentifierContext, changePanelTitle, createPanelStore, eventsController, externalFirePanelAction, handleAction, store as parametersStore, saveParameters, useActionEventHandlers, useDashboardContext, useDashboardPanel, useMakePanelContext, usePanelActions, usePanelChangeTitle, usePanelContext, usePanelFireEvent, usePanelIdentity, usePanelImage, usePanelIsLoading, usePanelNetworkState, usePanelOnEvent, usePanelParametersSelector, usePanelPosition, usePanelTitleDescription, useYieldPanelIsReady };
2239
2198
  //# sourceMappingURL=index.js.map