@grafana/ui
Version:
Grafana Components Library
263 lines (260 loc) • 9.4 kB
JavaScript
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
import { cx, css } from '@emotion/css';
import { useDialog } from '@react-aria/dialog';
import { FocusScope } from '@react-aria/focus';
import { useOverlay } from '@react-aria/overlays';
import { useState, useEffect, createRef, memo } from 'react';
import { getTimeZoneInfo, dateTimeFormat, timeZoneFormatUserFriendly, rangeUtil, dateMath } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { t, Trans } from '@grafana/i18n';
import { useStyles2 } from '../../themes/ThemeContext.mjs';
import { ButtonGroup } from '../Button/ButtonGroup.mjs';
import { getModalStyles } from '../Modal/getModalStyles.mjs';
import { getPortalContainer } from '../Portal/Portal.mjs';
import { ToolbarButton } from '../ToolbarButton/ToolbarButton.mjs';
import { Tooltip } from '../Tooltip/Tooltip.mjs';
import { TimePickerContent } from './TimeRangePicker/TimePickerContent.mjs';
import { TimeZoneDescription } from './TimeZonePicker/TimeZoneDescription.mjs';
import { getQuickOptions } from './options.mjs';
import { useTimeSync } from './utils/useTimeSync.mjs';
"use strict";
function TimeRangePicker(props) {
var _a;
const [isOpen, setOpen] = useState(false);
const {
value,
onMoveBackward,
onMoveForward,
moveForwardTooltip,
moveBackwardTooltip,
onZoom,
onError,
timeZone,
fiscalYearStartMonth,
history,
onChangeTimeZone,
onChangeFiscalYearStartMonth,
quickRanges,
hideQuickRanges,
widthOverride,
isOnCanvas,
onToolbarTimePickerClick,
weekStart,
initialIsSynced
} = props;
const { onChangeWithSync, isSynced, timeSyncButton } = useTimeSync({
initialIsSynced,
value,
onChangeProp: props.onChange,
isSyncedProp: props.isSynced,
timeSyncButtonProp: props.timeSyncButton
});
const onChange = (timeRange) => {
onChangeWithSync(timeRange);
setOpen(false);
};
useEffect(() => {
if (isOpen && onToolbarTimePickerClick) {
onToolbarTimePickerClick();
}
}, [isOpen, onToolbarTimePickerClick]);
const onToolbarButtonSwitch = () => {
setOpen((prevState) => !prevState);
};
const onClose = () => {
setOpen(false);
};
const overlayRef = createRef();
const buttonRef = createRef();
const { overlayProps, underlayProps } = useOverlay(
{
onClose,
isDismissable: true,
isOpen,
shouldCloseOnInteractOutside: (element) => {
var _a2;
const portalContainer = getPortalContainer();
return !((_a2 = buttonRef.current) == null ? void 0 : _a2.contains(element)) && !portalContainer.contains(element);
}
},
overlayRef
);
const { dialogProps } = useDialog({}, overlayRef);
const styles = useStyles2(getStyles);
const { modalBackdrop } = useStyles2(getModalStyles);
const variant = isSynced ? "active" : isOnCanvas ? "canvas" : "default";
const isFromAfterTo = (_a = value == null ? void 0 : value.to) == null ? void 0 : _a.isBefore(value.from);
const timePickerIcon = isFromAfterTo ? "exclamation-triangle" : "clock-nine";
const currentTimeRange = formattedRange(value, timeZone, quickRanges);
return /* @__PURE__ */ jsxs(ButtonGroup, { className: styles.container, children: [
/* @__PURE__ */ jsx(
ToolbarButton,
{
variant,
onClick: onMoveBackward,
icon: "angle-double-left",
type: "button",
iconSize: "xl",
tooltip: moveBackwardTooltip != null ? moveBackwardTooltip : t("time-picker.range-picker.backwards-time-aria-label", "Move time range backwards"),
narrow: true
}
),
/* @__PURE__ */ jsx(
Tooltip,
{
ref: buttonRef,
content: /* @__PURE__ */ jsx(TimePickerTooltip, { timeRange: value, timeZone }),
placement: "bottom",
interactive: true,
children: /* @__PURE__ */ jsx(
ToolbarButton,
{
"data-testid": selectors.components.TimePicker.openButton,
"aria-label": t("time-picker.range-picker.current-time-selected", "Time range selected: {{currentTimeRange}}", {
currentTimeRange
}),
"aria-controls": "TimePickerContent",
onClick: onToolbarButtonSwitch,
icon: timePickerIcon,
isOpen,
type: "button",
variant,
children: /* @__PURE__ */ jsx(TimePickerButtonLabel, { ...props })
}
)
}
),
isOpen && /* @__PURE__ */ jsxs("div", { "data-testid": selectors.components.TimePicker.overlayContent, children: [
/* @__PURE__ */ jsx("div", { role: "presentation", className: cx(modalBackdrop, styles.backdrop), ...underlayProps }),
/* @__PURE__ */ jsx(FocusScope, { contain: true, autoFocus: true, restoreFocus: true, children: /* @__PURE__ */ jsx("section", { className: styles.content, ref: overlayRef, ...overlayProps, ...dialogProps, children: /* @__PURE__ */ jsx(
TimePickerContent,
{
timeZone,
fiscalYearStartMonth,
value,
onChange,
quickOptions: quickRanges || getQuickOptions(),
history,
showHistory: true,
widthOverride,
onChangeTimeZone,
onChangeFiscalYearStartMonth,
hideQuickRanges,
onError,
weekStart
}
) }) })
] }),
timeSyncButton,
/* @__PURE__ */ jsx(
ToolbarButton,
{
onClick: onMoveForward,
icon: "angle-double-right",
type: "button",
variant,
iconSize: "xl",
tooltip: moveForwardTooltip != null ? moveForwardTooltip : t("time-picker.range-picker.forwards-time-aria-label", "Move time range forwards"),
narrow: true
}
),
/* @__PURE__ */ jsx(Tooltip, { content: ZoomOutTooltip, placement: "bottom", children: /* @__PURE__ */ jsx(
ToolbarButton,
{
"aria-label": t("time-picker.range-picker.zoom-out-button", "Zoom out time range"),
onClick: onZoom,
icon: "search-minus",
type: "button",
variant
}
) })
] });
}
TimeRangePicker.displayName = "TimeRangePicker";
const ZoomOutTooltip = () => /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(Trans, { i18nKey: "time-picker.range-picker.zoom-out-tooltip", children: [
"Time range zoom out ",
/* @__PURE__ */ jsx("br", {}),
" CTRL+Z"
] }) });
const TimePickerTooltip = ({ timeRange, timeZone }) => {
const styles = useStyles2(getLabelStyles);
const now = Date.now();
const timeZoneInfo = timeZone ? getTimeZoneInfo(timeZone, now) : void 0;
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
dateTimeFormat(timeRange.from, { timeZone }),
/* @__PURE__ */ jsx("div", { className: "text-center", children: /* @__PURE__ */ jsx(Trans, { i18nKey: "time-picker.range-picker.to", children: "to" }) }),
dateTimeFormat(timeRange.to, { timeZone })
] }),
/* @__PURE__ */ jsxs("div", { className: styles.container, children: [
/* @__PURE__ */ jsx("span", { className: styles.utc, children: timeZoneFormatUserFriendly(timeZone) }),
/* @__PURE__ */ jsx(TimeZoneDescription, { info: timeZoneInfo })
] })
] });
};
const TimePickerButtonLabel = memo(({ hideText, value, timeZone, quickRanges }) => {
const styles = useStyles2(getLabelStyles);
if (hideText) {
return null;
}
return /* @__PURE__ */ jsxs("span", { className: styles.container, "aria-live": "polite", "aria-atomic": "true", children: [
/* @__PURE__ */ jsx("span", { children: formattedRange(value, timeZone, quickRanges) }),
/* @__PURE__ */ jsx("span", { className: styles.utc, children: rangeUtil.describeTimeRangeAbbreviation(value, timeZone) })
] });
});
TimePickerButtonLabel.displayName = "TimePickerButtonLabel";
const formattedRange = (value, timeZone, quickRanges) => {
const adjustedTimeRange = {
to: dateMath.isMathString(value.raw.to) ? value.raw.to : value.to,
from: dateMath.isMathString(value.raw.from) ? value.raw.from : value.from
};
return rangeUtil.describeTimeRange(adjustedTimeRange, timeZone, quickRanges);
};
const getStyles = (theme) => {
return {
container: css({
position: "relative",
display: "flex",
verticalAlign: "middle"
}),
backdrop: css({
display: "none",
[theme.breakpoints.down("sm")]: {
display: "block"
}
}),
content: css({
position: "absolute",
right: 0,
top: "116%",
zIndex: theme.zIndex.dropdown,
[theme.breakpoints.down("sm")]: {
position: "fixed",
right: "50%",
top: "50%",
transform: "translate(50%, -50%)",
zIndex: theme.zIndex.modal
}
})
};
};
const getLabelStyles = (theme) => {
return {
container: css({
display: "flex",
alignItems: "center",
whiteSpace: "nowrap",
columnGap: theme.spacing(0.5)
}),
utc: css({
color: theme.v1.palette.orange,
fontSize: theme.typography.size.sm,
paddingLeft: "6px",
lineHeight: "28px",
verticalAlign: "bottom",
fontWeight: theme.typography.fontWeightMedium
})
};
};
export { TimePickerButtonLabel, TimePickerTooltip, TimeRangePicker };
//# sourceMappingURL=TimeRangePicker.mjs.map