@apia/dashboard-controller 3.0.9 → 3.0.11

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.d.ts CHANGED
@@ -1,6 +1,7 @@
1
+ import * as _apia_util from '@apia/util';
1
2
  import { TId, EventEmitter } from '@apia/util';
2
3
  import * as react from 'react';
3
- import { FC, ReactNode, KeyboardEvent, MouseEvent, ComponentType, ReactPortal } from 'react';
4
+ import { FC, ReactNode, KeyboardEvent, MouseEvent as MouseEvent$1, ComponentType, ReactPortal } from 'react';
4
5
  import { TSpacingLayout } from '@apia/theme';
5
6
  import { TApiaApiResult, IApiaApiRequestConfig } from '@apia/api';
6
7
  import * as _reduxjs_toolkit_dist_configureStore from '@reduxjs/toolkit/dist/configureStore';
@@ -70,16 +71,42 @@ interface TPanelIdentifierProps {
70
71
  }
71
72
  declare const PanelIdentifier: ({ children, name, id, title, type, }: TPanelIdentifierProps) => react.JSX.Element;
72
73
 
73
- type TActionBehavior = 'DO_NOTHING' | 'NAVIGATE_URL' | 'CALL_AJAX_URL' | 'RUN_ACTION' | 'OPEN_TAB';
74
+ declare const eventsController: {
75
+ callbacks: TPanelEventRegister<any>[];
76
+ broadcast(eventType: string, payload: any): void;
77
+ fireEvent(origin: TPanelIdentifier, eventType: string, payload: any): void;
78
+ onEvent<PayloadEvent>(distinction: Partial<TPanelEventIdentifier>, callback: TPanelEventCallback<PayloadEvent>): () => void;
79
+ };
80
+
81
+ /**
82
+ * Este hook devuelve un método que puede ser llamado para emitir un evento en
83
+ * el panel desde el cual es llamado. Los eventos de panel son emitidos con id
84
+ * de panel, tipo de panel, nombre de panel y tipo de evento y las suscripciones
85
+ * pueden ser realizadas a un conjunto arbitrario de estos identificadores.
86
+ *
87
+ * El segundo parámetro del método fireEvent devuelto es el payload, que puede
88
+ * ser de cualquier tipo.
89
+ */
90
+ declare function usePanelFireEvent(): (eventType: string, payload: any) => void;
91
+
92
+ /**
93
+ * Este hook permite realizar suscripciones a eventos de paneles. Deberá ser
94
+ * llamado una vez por cada suscripción que desee hacerse dentro de un panel y
95
+ * no se deberán ejecutar acciones para romper las suscripciones hechas, ya que
96
+ * este hook maneja esa lógica de forma automática.
97
+ */
98
+ declare function usePanelOnEvent<PayloadEvent>(distinction: Partial<TPanelEventIdentifier>, callback: TPanelEventCallback<PayloadEvent>): void;
99
+
100
+ type TActionBehavior = 'DO_NOTHING' | 'NAVIGATE_URL' | 'CALL_AJAX_URL' | 'RUN_ACTION' | 'OPEN_TAB' | 'FIRE_EVENT' | 'DOWNLOAD';
74
101
  type TActionSource = 'CLICK' | 'DOUBLE_CLICK';
75
102
  type TBasicAction = {
76
103
  action: string;
77
104
  actionBehavior: TActionBehavior;
78
105
  actionSource: TActionSource;
79
- actionNewTabTitle: string;
106
+ additionalData: string;
80
107
  text: string;
81
108
  };
82
- declare function handleAction(panelId: string, event: KeyboardEvent | MouseEvent, action: TBasicAction): void;
109
+ declare function handleAction(panelIdentifier: TPanelIdentifier, event: KeyboardEvent | MouseEvent$1, action: TBasicAction): void;
83
110
 
84
111
  type TOnSucceed = (hasSucceed: boolean, data: TActionResult) => unknown;
85
112
 
@@ -150,6 +177,12 @@ declare function usePanelIsLoading(): boolean;
150
177
  */
151
178
  declare const usePanelNetworkState: () => boolean;
152
179
 
180
+ declare const useActionEventHandlers: () => {
181
+ onClick: (ev: React.MouseEvent<HTMLElement, MouseEvent>) => (action: TBasicAction) => void;
182
+ onDoubleClick: (ev: React.MouseEvent<HTMLElement, MouseEvent>) => (action: TBasicAction) => void;
183
+ onKeyDown: (ev: React.KeyboardEvent<HTMLElement>) => (action: TBasicAction) => void;
184
+ };
185
+
153
186
  type TPanelLayout = TSpacingLayout;
154
187
 
155
188
  /**
@@ -219,9 +252,27 @@ type TPanelContext = {
219
252
  setRef: (el: HTMLElement | null) => void;
220
253
  };
221
254
  declare function usePanelContext(): TPanelContext;
255
+ declare const PanelContextProvider: ({ children, value, }: {
256
+ children: ReactNode;
257
+ value: TPanelContext;
258
+ }) => react.JSX.Element;
259
+ declare function useMakePanelContext(panelProps: Omit<TPanelProps$1, 'children'>): {
260
+ footerContent: ReactNode;
261
+ title: string;
262
+ footer: TBasicAction | null;
263
+ handleFooterClick: (ev: react.MouseEvent<Element, MouseEvent> | react.KeyboardEvent<Element>) => void;
264
+ contextValue: TPanelContext;
265
+ ref: (el: HTMLDivElement) => void;
266
+ };
222
267
 
223
268
  declare const EmptyPanelWrapper: PanelContainer;
224
269
 
270
+ type TUsePanelFooter = {
271
+ footerContent?: ReactNode;
272
+ footer: TFooter | null;
273
+ handleFooterClick: (ev: MouseEvent$1 | KeyboardEvent) => void;
274
+ };
275
+
225
276
  /**
226
277
  * Permite acceder a la identidad del panel actual.
227
278
  */
@@ -373,33 +424,7 @@ declare function useDashboardContext(): Dashboard;
373
424
 
374
425
  declare function useDashboardPanel(): DashboardPanel;
375
426
 
376
- declare const eventsController: {
377
- callbacks: TPanelEventRegister<any>[];
378
- broadcast(eventType: string, payload: any): void;
379
- fireEvent(origin: TPanelIdentifier, eventType: string, payload: any): void;
380
- onEvent<PayloadEvent>(distinction: Partial<TPanelEventIdentifier>, callback: TPanelEventCallback<PayloadEvent>): () => void;
381
- };
382
-
383
- /**
384
- * Este hook devuelve un método que puede ser llamado para emitir un evento en
385
- * el panel desde el cual es llamado. Los eventos de panel son emitidos con id
386
- * de panel, tipo de panel, nombre de panel y tipo de evento y las suscripciones
387
- * pueden ser realizadas a un conjunto arbitrario de estos identificadores.
388
- *
389
- * El segundo parámetro del método fireEvent devuelto es el payload, que puede
390
- * ser de cualquier tipo.
391
- */
392
- declare function usePanelFireEvent(): (eventType: string, payload: any) => void;
393
-
394
- /**
395
- * Este hook permite realizar suscripciones a eventos de paneles. Deberá ser
396
- * llamado una vez por cada suscripción que desee hacerse dentro de un panel y
397
- * no se deberán ejecutar acciones para romper las suscripciones hechas, ya que
398
- * este hook maneja esa lógica de forma automática.
399
- */
400
- declare function usePanelOnEvent<PayloadEvent>(distinction: Partial<TPanelEventIdentifier>, callback: TPanelEventCallback<PayloadEvent>): void;
401
-
402
- declare function changePanelTitle(panelId: string, newTitle: string): void;
427
+ declare function changePanelTitle(identifier: TPanelIdentifier, newTitle: string): void;
403
428
  declare function usePanelChangeTitle(): (newTitle: string) => void;
404
429
 
405
430
  declare type ActionCreatorForCaseReducer<CR> = CR extends (state: any, action: infer Action) => any ? Action extends {
@@ -413,5 +438,20 @@ declare function createPanelStore<PanelState = any, Reducers extends SliceCaseRe
413
438
  <Selected>(panelName: TPanelName, selector: (state: PanelState) => Selected, comparator?: (a: Selected, b: Selected) => boolean) => Selected
414
439
  ];
415
440
 
416
- export { Dashboard, EmptyPanelWrapper, LandingPagePanelWrapper, type PanelContainer, PanelIdentifier, PanelIdentifierContext, type TActionBehavior, type TActionDispatcher, type TActionResult, type TActionSource, type TBasicAction, type TFooter, type TPanelContext, type TPanelEvent, type TPanelEventCallback, type TPanelEventIdentifier, type TPanelEventRegister, type TPanelIdentifier, type TParamsStore, changePanelTitle, createPanelStore, eventsController, externalFirePanelAction, handleAction, store as parametersStore, saveParameters, useDashboardContext, useDashboardPanel, usePanelActions, usePanelChangeTitle, usePanelContext, usePanelFireEvent, usePanelIdentity, usePanelIsLoading, usePanelNetworkState, usePanelOnEvent, usePanelParametersSelector, usePanelPosition, useYieldPanelIsReady };
441
+ declare function usePanelImage(): string;
442
+ declare function usePanelTitleDescription(): string;
443
+
444
+ declare const PanelButtons: react.FC<Omit<TPanelProps$1, "children" | "initialData"> & {
445
+ id: _apia_util.TId;
446
+ }>;
447
+
448
+ declare const PanelFooter: ({ footerContent, isRefreshable, footer, handleFooterClick, }: TUsePanelFooter & {
449
+ isRefreshable: boolean;
450
+ }) => react.JSX.Element;
451
+
452
+ declare const NetworkState: ({ title }: {
453
+ title: string;
454
+ }) => react.JSX.Element;
455
+
456
+ export { Dashboard, EmptyPanelWrapper, LandingPagePanelWrapper, NetworkState, PanelButtons, type PanelContainer, PanelContextProvider, PanelFooter, PanelIdentifier, PanelIdentifierContext, type TActionBehavior, type TActionDispatcher, type TActionResult, type TActionSource, type TBasicAction, type TFooter, type TPanelContext, type TPanelEvent, type TPanelEventCallback, type TPanelEventIdentifier, type TPanelEventRegister, type TPanelIdentifier, type TParamsStore, type TUsePanelFooter, 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 };
417
457
  //# sourceMappingURL=index.d.ts.map
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;
@@ -852,6 +738,14 @@ const PanelNotFound = () => {
852
738
  ] }) });
853
739
  };
854
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
+
855
749
  const importedContainers = {};
856
750
  const importedPanels = {};
857
751
  function importContainer(path) {
@@ -867,7 +761,7 @@ function importContainer(path) {
867
761
  resolve(result.default);
868
762
  }).catch(() => {
869
763
  resolve({
870
- default: PanelNotFound
764
+ default: ContainerNotFound
871
765
  });
872
766
  });
873
767
  });
@@ -1835,14 +1729,12 @@ class Dashboard extends EventEmitter {
1835
1729
  {
1836
1730
  route: new RegExp(`(?:/spa)?/(\\w+)`),
1837
1731
  callback: (result) => {
1838
- console.log("Dashboard", { scene: result[1] });
1839
1732
  this.loadScene(result[1]);
1840
1733
  }
1841
1734
  },
1842
1735
  {
1843
1736
  route: new RegExp(`/`),
1844
1737
  callback: () => {
1845
- console.log("Dashboard", { noScene: "/" });
1846
1738
  this.loadScene("/");
1847
1739
  }
1848
1740
  }
@@ -1976,7 +1868,7 @@ function firePanelAction(panelId, action, parameters, options) {
1976
1868
  startTransition(() => {
1977
1869
  if (result?.data?.title) {
1978
1870
  changePanelTitle(
1979
- panelId,
1871
+ { panelId },
1980
1872
  result?.data?.title
1981
1873
  );
1982
1874
  }
@@ -2014,7 +1906,7 @@ function firePanelAction(panelId, action, parameters, options) {
2014
1906
  });
2015
1907
  }
2016
1908
 
2017
- function handleAction(panelId, event, action) {
1909
+ function handleAction(panelIdentifier, event, action) {
2018
1910
  if (event.type === "dblclick" && action.actionSource === "DOUBLE_CLICK" || (event.type === "click" || event.type === "mousedown") && action.actionSource === "CLICK" || event.type === "keydown" && event.code === "Enter") {
2019
1911
  if (action?.action) {
2020
1912
  switch (action.actionBehavior) {
@@ -2028,20 +1920,28 @@ function handleAction(panelId, event, action) {
2028
1920
  break;
2029
1921
  case "OPEN_TAB":
2030
1922
  window.top?.tabsController.openTabByUrl(
2031
- action.actionNewTabTitle || action.text,
1923
+ action.additionalData || action.text,
2032
1924
  action.action
2033
1925
  );
2034
1926
  break;
2035
1927
  case "RUN_ACTION":
2036
1928
  firePanelAction(
2037
- panelId,
1929
+ panelIdentifier.panelId,
2038
1930
  action.action,
2039
1931
  {},
2040
- { requestConfig: {
2041
- handleLoad: true
2042
- } }
1932
+ { requestConfig: { handleLoad: true } }
2043
1933
  );
2044
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;
2045
1945
  default:
2046
1946
  console.error("Unknown action behavior: ", action);
2047
1947
  }
@@ -2066,6 +1966,41 @@ function usePanelIsLoading() {
2066
1966
  return isLoading;
2067
1967
  }
2068
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
+
2069
2004
  const NetworkState = ({ title }) => {
2070
2005
  const isConnected = usePanelNetworkState();
2071
2006
  return /* @__PURE__ */ jsx(Fragment, { children: !isConnected && /* @__PURE__ */ jsx(
@@ -2092,10 +2027,7 @@ const LandingPagePanelWrapper = ({
2092
2027
  ...props
2093
2028
  }) => {
2094
2029
  const { panelId, panelName, panelType } = usePanelIdentity();
2095
- const { contextValue, title, ref, ...footerProps } = useMakePanelContext(
2096
- panelId,
2097
- props
2098
- );
2030
+ const { contextValue, title, ref, ...footerProps } = useMakePanelContext(props);
2099
2031
  const panelTitleAction = usePanelTitleAction();
2100
2032
  const panelTitleDescription = usePanelTitleDescription();
2101
2033
  const dashboard = useDashboardContext();
@@ -2130,8 +2062,7 @@ const LandingPagePanelWrapper = ({
2130
2062
  };
2131
2063
 
2132
2064
  const EmptyPanelWrapper = (props) => {
2133
- const { panelId } = usePanelIdentity();
2134
- const { contextValue } = useMakePanelContext(panelId, props);
2065
+ const { contextValue } = useMakePanelContext(props);
2135
2066
  return /* @__PURE__ */ jsx(PanelContextProvider, { value: contextValue, children: props.children });
2136
2067
  };
2137
2068
 
@@ -2263,5 +2194,5 @@ function createPanelStore(panelType, initialState, reducers) {
2263
2194
  return [usePanelDispatcher, useSelector];
2264
2195
  }
2265
2196
 
2266
- export { Dashboard, EmptyPanelWrapper, 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 };
2267
2198
  //# sourceMappingURL=index.js.map