import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
import { cx, css } from '@emotion/css';
import * as React from 'react';
import { useId, useState } from 'react';
import { useToggle, useMeasure } from 'react-use';
import { LoadingState } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { t } from '@grafana/i18n';
import { useTheme2, useStyles2 } from '../../themes/ThemeContext.mjs';
import { getFocusStyles } from '../../themes/mixins.mjs';
import { DelayRender } from '../../utils/DelayRender.mjs';
import { getFeatureToggle } from '../../utils/featureToggle.mjs';
import { usePointerDistance } from '../../utils/usePointerDistance.mjs';
import { useElementSelection } from '../ElementSelectionContext/ElementSelectionContext.mjs';
import { Icon } from '../Icon/Icon.mjs';
import { LoadingBar } from '../LoadingBar/LoadingBar.mjs';
import { Text } from '../Text/Text.mjs';
import { Tooltip } from '../Tooltip/Tooltip.mjs';
import { HoverWidget } from './HoverWidget.mjs';
import { PanelDescription } from './PanelDescription.mjs';
import { PanelMenu } from './PanelMenu.mjs';
import { PanelStatus } from './PanelStatus.mjs';
import { TitleItem } from './TitleItem.mjs';

"use strict";
function PanelChrome({
  width,
  height,
  children,
  padding = "md",
  title = "",
  description = "",
  displayMode = "default",
  titleItems,
  menu,
  dragClass,
  dragClassCancel,
  hoverHeader = false,
  hoverHeaderOffset,
  loadingState,
  statusMessage,
  statusMessageOnClick,
  leftItems,
  actions,
  selectionId,
  onCancelQuery,
  onOpenMenu,
  collapsible = false,
  collapsed,
  onToggleCollapse,
  onFocus,
  onMouseMove,
  onMouseEnter,
  onDragStart,
  showMenuAlways = false
}) {
  const theme = useTheme2();
  const styles = useStyles2(getStyles);
  const panelContentId = useId();
  const panelTitleId = useId().replace(/:/g, "_");
  const { isSelected, onSelect, isSelectable } = useElementSelection(selectionId);
  const pointerDistance = usePointerDistance();
  const hasHeader = !hoverHeader;
  const [isOpen, toggleOpen] = useToggle(true);
  const [selectableHighlight, setSelectableHighlight] = useState(false);
  const onHeaderEnter = React.useCallback(() => setSelectableHighlight(true), []);
  const onHeaderLeave = React.useCallback(() => setSelectableHighlight(false), []);
  if (collapsed === void 0) {
    collapsed = !isOpen;
  }
  const showOnHoverClass = showMenuAlways ? "always-show" : "show-on-hover";
  const isPanelTransparent = displayMode === "transparent";
  const headerHeight = getHeaderHeight(theme, hasHeader);
  const { contentStyle, innerWidth, innerHeight } = getContentStyle(
    padding,
    theme,
    headerHeight,
    collapsed,
    height,
    width
  );
  const headerStyles = {
    height: headerHeight,
    cursor: dragClass ? "move" : "auto"
  };
  const containerStyles = { width, height: collapsed ? void 0 : height };
  const [ref, { width: loadingBarWidth }] = useMeasure();
  if (leftItems) {
    actions = leftItems;
  }
  const testid = typeof title === "string" ? selectors.components.Panels.Panel.title(title) : "Panel";
  const onPointerUp = React.useCallback(
    (evt) => {
      if (pointerDistance.check(evt) || dragClassCancel && evt.target instanceof Element && evt.target.closest(`.${dragClassCancel}`)) {
        return;
      }
      setTimeout(() => onSelect == null ? void 0 : onSelect(evt));
    },
    [dragClassCancel, onSelect, pointerDistance]
  );
  const onPointerDown = React.useCallback(
    (evt) => {
      evt.stopPropagation();
      pointerDistance.set(evt);
      onDragStart == null ? void 0 : onDragStart(evt);
    },
    [pointerDistance, onDragStart]
  );
  const onContentPointerDown = React.useCallback(
    (evt) => {
      if (evt.target instanceof Element && evt.target.closest("button,a,canvas,svg")) {
        return;
      }
      onSelect == null ? void 0 : onSelect(evt);
    },
    [onSelect]
  );
  const headerContent = /* @__PURE__ */ jsxs(Fragment, { children: [
    !collapsible && title && /* @__PURE__ */ jsx("div", { className: styles.title, children: /* @__PURE__ */ jsx(
      Text,
      {
        element: "h2",
        variant: "h6",
        truncate: true,
        title: typeof title === "string" ? title : void 0,
        id: panelTitleId,
        children: title
      }
    ) }),
    collapsible && /* @__PURE__ */ jsx("div", { className: styles.title, children: /* @__PURE__ */ jsx(Text, { element: "h2", variant: "h6", children: /* @__PURE__ */ jsxs(
      "button",
      {
        type: "button",
        className: styles.clearButtonStyles,
        onClick: () => {
          toggleOpen();
          if (onToggleCollapse) {
            onToggleCollapse(!collapsed);
          }
        },
        "aria-expanded": !collapsed,
        "aria-controls": !collapsed ? panelContentId : void 0,
        children: [
          /* @__PURE__ */ jsx(
            Icon,
            {
              name: !collapsed ? "angle-down" : "angle-right",
              "aria-hidden": !!title,
              "aria-label": !title ? t("grafana-ui.panel-chrome.aria-label-toggle-collapse", "toggle collapse panel") : void 0
            }
          ),
          /* @__PURE__ */ jsx(Text, { variant: "h6", truncate: true, id: panelTitleId, children: title })
        ]
      }
    ) }) }),
    /* @__PURE__ */ jsxs("div", { className: cx(styles.titleItems, dragClassCancel), "data-testid": "title-items-container", children: [
      /* @__PURE__ */ jsx(PanelDescription, { description, className: dragClassCancel }),
      titleItems
    ] }),
    loadingState === LoadingState.Streaming && /* @__PURE__ */ jsx(
      Tooltip,
      {
        content: onCancelQuery ? t("grafana-ui.panel-chrome.tooltip-stop-streaming", "Stop streaming") : t("grafana-ui.panel-chrome.tooltip-streaming", "Streaming"),
        children: /* @__PURE__ */ jsx(TitleItem, { className: dragClassCancel, "data-testid": "panel-streaming", onClick: onCancelQuery, children: /* @__PURE__ */ jsx(Icon, { name: "circle-mono", size: "md", className: styles.streaming }) })
      }
    ),
    loadingState === LoadingState.Loading && onCancelQuery && /* @__PURE__ */ jsx(DelayRender, { delay: 2e3, children: /* @__PURE__ */ jsx(Tooltip, { content: t("grafana-ui.panel-chrome.tooltip-cancel", "Cancel query"), children: /* @__PURE__ */ jsx(
      TitleItem,
      {
        className: cx(dragClassCancel, styles.pointer),
        "data-testid": "panel-cancel-query",
        onClick: onCancelQuery,
        children: /* @__PURE__ */ jsx(Icon, { name: "sync-slash", size: "md" })
      }
    ) }) }),
    /* @__PURE__ */ jsx("div", { className: styles.rightAligned, children: actions && /* @__PURE__ */ jsx("div", { className: styles.rightActions, children: itemsRenderer(actions, (item) => item) }) })
  ] });
  return (
    // tabIndex={0} is needed for keyboard accessibility in the plot area
    /* @__PURE__ */ jsxs(
      "section",
      {
        className: cx(
          styles.container,
          isPanelTransparent && styles.transparentContainer,
          isSelected && "dashboard-selected-element",
          !isSelected && isSelectable && selectableHighlight && "dashboard-selectable-element"
        ),
        style: containerStyles,
        "aria-labelledby": !!title ? panelTitleId : void 0,
        "data-testid": testid,
        tabIndex: 0,
        onFocus,
        onMouseMove,
        onMouseEnter,
        ref,
        children: [
          /* @__PURE__ */ jsx("div", { className: styles.loadingBarContainer, children: loadingState === LoadingState.Loading ? /* @__PURE__ */ jsx(
            LoadingBar,
            {
              width: loadingBarWidth,
              ariaLabel: t("grafana-ui.panel-chrome.ariaLabel-panel-loading", "Panel loading bar")
            }
          ) : null }),
          hoverHeader && /* @__PURE__ */ jsxs(Fragment, { children: [
            /* @__PURE__ */ jsx(
              HoverWidget,
              {
                menu,
                title: typeof title === "string" ? title : void 0,
                offset: hoverHeaderOffset,
                dragClass,
                onOpenMenu,
                children: headerContent
              }
            ),
            statusMessage && /* @__PURE__ */ jsx("div", { className: styles.errorContainerFloating, children: /* @__PURE__ */ jsx(
              PanelStatus,
              {
                message: statusMessage,
                onClick: statusMessageOnClick,
                ariaLabel: t("grafana-ui.panel-chrome.ariaLabel-panel-status", "Panel status")
              }
            ) })
          ] }),
          hasHeader && /* @__PURE__ */ jsxs(
            "div",
            {
              className: cx(styles.headerContainer, dragClass),
              style: headerStyles,
              "data-testid": selectors.components.Panels.Panel.headerContainer,
              onPointerDown,
              onMouseEnter: isSelectable ? onHeaderEnter : void 0,
              onMouseLeave: isSelectable ? onHeaderLeave : void 0,
              onPointerUp,
              children: [
                statusMessage && /* @__PURE__ */ jsx("div", { className: dragClassCancel, children: /* @__PURE__ */ jsx(
                  PanelStatus,
                  {
                    message: statusMessage,
                    onClick: statusMessageOnClick,
                    ariaLabel: t("grafana-ui.panel-chrome.ariaLabel-panel-status", "Panel status")
                  }
                ) }),
                headerContent,
                menu && /* @__PURE__ */ jsx(
                  PanelMenu,
                  {
                    menu,
                    title: typeof title === "string" ? title : void 0,
                    placement: "bottom-end",
                    menuButtonClass: cx(styles.menuItem, dragClassCancel, showOnHoverClass),
                    onOpenMenu
                  }
                )
              ]
            }
          ),
          !collapsed && /* @__PURE__ */ jsx(
            "div",
            {
              id: panelContentId,
              "data-testid": selectors.components.Panels.Panel.content,
              className: cx(styles.content, height === void 0 && styles.containNone),
              style: contentStyle,
              onPointerDown: onContentPointerDown,
              children: typeof children === "function" ? children(innerWidth, innerHeight) : children
            }
          )
        ]
      }
    )
  );
}
const itemsRenderer = (items, renderer) => {
  const toRender = React.Children.toArray(items).filter(Boolean);
  return toRender.length > 0 ? renderer(toRender) : null;
};
const getHeaderHeight = (theme, hasHeader) => {
  if (hasHeader) {
    return theme.spacing.gridSize * theme.components.panel.headerHeight;
  }
  return 0;
};
const getContentStyle = (padding, theme, headerHeight, collapsed, height, width) => {
  const chromePadding = (padding === "md" ? theme.components.panel.padding : 0) * theme.spacing.gridSize;
  const panelPadding = chromePadding * 2;
  const panelBorder = 1 * 2;
  let innerWidth = 0;
  if (width) {
    innerWidth = width - panelPadding - panelBorder;
  }
  let innerHeight = 0;
  if (height) {
    innerHeight = height - headerHeight - panelPadding - panelBorder;
  }
  if (collapsed) {
    innerHeight = headerHeight;
  }
  const contentStyle = {
    padding: chromePadding
  };
  return { contentStyle, innerWidth, innerHeight };
};
const getStyles = (theme) => {
  const { background, borderColor, padding } = theme.components.panel;
  return {
    container: css({
      label: "panel-container",
      backgroundColor: background,
      border: `1px solid ${borderColor}`,
      position: "relative",
      borderRadius: theme.shape.radius.default,
      height: "100%",
      display: "flex",
      flexDirection: "column",
      overflow: getFeatureToggle("preventPanelChromeOverflow") ? "hidden" : "initial",
      ".always-show": {
        background: "none",
        "&:focus-visible, &:hover": {
          background: theme.colors.secondary.shade
        }
      },
      ".show-on-hover": {
        opacity: "0",
        visibility: "hidden"
      },
      "&:focus-visible, &:hover": {
        // only show menu icon on hover or focused panel
        ".show-on-hover": {
          opacity: "1",
          visibility: "visible"
        }
      },
      "&:focus-visible": getFocusStyles(theme),
      // The not:(:focus) clause is so that this rule is only applied when decendants are focused (important otherwise the hover header is visible when panel is clicked).
      "&:focus-within:not(:focus)": {
        ".show-on-hover": {
          visibility: "visible",
          opacity: "1"
        }
      }
    }),
    transparentContainer: css({
      label: "panel-transparent-container",
      backgroundColor: "transparent",
      border: "1px solid transparent",
      boxSizing: "border-box",
      "&:hover": {
        border: `1px solid ${borderColor}`
      }
    }),
    loadingBarContainer: css({
      label: "panel-loading-bar-container",
      position: "absolute",
      top: 0,
      width: "100%",
      // this is to force the loading bar container to create a new stacking context
      // otherwise, in webkit browsers on windows/linux, the aliasing of panel text changes when the loading bar is shown
      // see https://github.com/grafana/grafana/issues/88104
      zIndex: 1
    }),
    containNone: css({
      contain: "none"
    }),
    content: css({
      label: "panel-content",
      flexGrow: 1,
      contain: "size layout"
    }),
    headerContainer: css({
      label: "panel-header",
      display: "flex",
      alignItems: "center"
    }),
    pointer: css({
      cursor: "pointer"
    }),
    streaming: css({
      label: "panel-streaming",
      marginRight: 0,
      color: theme.colors.success.text,
      "&:hover": {
        color: theme.colors.success.text
      }
    }),
    title: css({
      label: "panel-title",
      display: "flex",
      padding: theme.spacing(0, padding),
      minWidth: 0,
      "& > h2": {
        minWidth: 0
      }
    }),
    items: css({
      display: "flex"
    }),
    item: css({
      display: "flex",
      justifyContent: "center",
      alignItems: "center"
    }),
    hiddenMenu: css({
      visibility: "hidden"
    }),
    menuItem: css({
      label: "panel-menu",
      border: "none",
      background: theme.colors.secondary.main,
      "&:hover": {
        background: theme.colors.secondary.shade
      }
    }),
    errorContainerFloating: css({
      label: "error-container",
      position: "absolute",
      left: 0,
      top: 0,
      zIndex: 1
    }),
    rightActions: css({
      display: "flex",
      padding: theme.spacing(0, padding),
      gap: theme.spacing(1)
    }),
    rightAligned: css({
      label: "right-aligned-container",
      marginLeft: "auto",
      display: "flex",
      alignItems: "center"
    }),
    titleItems: css({
      display: "flex",
      height: "100%"
    }),
    clearButtonStyles: css({
      alignItems: "center",
      display: "flex",
      gap: theme.spacing(0.5),
      background: "transparent",
      border: "none",
      padding: 0,
      maxWidth: "100%"
    })
  };
};

export { PanelChrome };
//# sourceMappingURL=PanelChrome.mjs.map
