@elastic/eui
Version:
Elastic UI Component Library
256 lines (250 loc) • 11.6 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ZOOM_FACTOR_DEFAULT = exports.ZOOM_DELTA_FALLBACK_MS = exports.EuiTimeWindowButtons = void 0;
exports.useEuiTimeWindow = useEuiTimeWindow;
var _react = _interopRequireDefault(require("react"));
var _datemath = _interopRequireDefault(require("@elastic/datemath"));
var _moment = _interopRequireDefault(require("moment"));
var _pretty_interval = require("./pretty_interval");
var _relative_utils = require("./relative_utils");
var _button_group_button = require("../../button/button_group/button_group_button");
var _button_group = require("../../button/button_group/button_group.styles");
var _services = require("../../../services");
var _i18n = require("../../i18n");
var _react2 = require("@emotion/react");
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
var ZOOM_FACTOR_DEFAULT = exports.ZOOM_FACTOR_DEFAULT = 0.5;
var ZOOM_DELTA_FALLBACK_MS = exports.ZOOM_DELTA_FALLBACK_MS = 500;
/**
* Button group with time window controls for shifting the time window
* forwards and backwards, and zooming out.
*/
var EuiTimeWindowButtons = exports.EuiTimeWindowButtons = function EuiTimeWindowButtons(_ref) {
var applyTime = _ref.applyTime,
start = _ref.start,
end = _ref.end,
compressed = _ref.compressed,
isDisabled = _ref.isDisabled,
_ref$showZoomOut = _ref.showZoomOut,
showZoomOut = _ref$showZoomOut === void 0 ? true : _ref$showZoomOut,
_ref$showZoomIn = _ref.showZoomIn,
showZoomIn = _ref$showZoomIn === void 0 ? false : _ref$showZoomIn,
_ref$showShiftArrows = _ref.showShiftArrows,
showShiftArrows = _ref$showShiftArrows === void 0 ? true : _ref$showShiftArrows,
_ref$zoomFactor = _ref.zoomFactor,
zoomFactor = _ref$zoomFactor === void 0 ? ZOOM_FACTOR_DEFAULT : _ref$zoomFactor;
var buttonColor = 'text';
var buttonSize = compressed ? 's' : 'm';
var iconSize = 'm';
var styles = (0, _services.useEuiMemoizedStyles)(_button_group.euiButtonGroupButtonsStyles);
var _useEuiTimeWindow = useEuiTimeWindow(start, end, applyTime, {
zoomFactor: zoomFactor
}),
displayInterval = _useEuiTimeWindow.displayInterval,
isInvalid = _useEuiTimeWindow.isInvalid,
stepForward = _useEuiTimeWindow.stepForward,
stepBackward = _useEuiTimeWindow.stepBackward,
expandWindow = _useEuiTimeWindow.expandWindow,
shrinkWindow = _useEuiTimeWindow.shrinkWindow,
isWindowDurationZero = _useEuiTimeWindow.isWindowDurationZero;
var previousDescription = (0, _i18n.useEuiI18n)('euiTimeWindowButtons.previousDescription', 'Previous {displayInterval}', {
displayInterval: displayInterval
});
var nextDescription = (0, _i18n.useEuiI18n)('euiTimeWindowButtons.nextDescription', 'Next {displayInterval}', {
displayInterval: displayInterval
});
var invalidShiftDescription = (0, _i18n.useEuiI18n)('euiTimeWindowButtons.invalidShiftLabel', 'Cannot shift invalid time window');
var invalidZoomInDescription = (0, _i18n.useEuiI18n)('euiTimeWindowButtons.invalidZoomInLabel', 'Cannot zoom in invalid time window');
var cannotZoomInDescription = (0, _i18n.useEuiI18n)('euiTimeWindowButtons.cannotZoomInLabel', 'Cannot zoom in any further');
var invalidZoomOutDescription = (0, _i18n.useEuiI18n)('euiTimeWindowButtons.invalidZoomOutLabel', 'Cannot zoom out invalid time window');
var previousId = (0, _services.useGeneratedHtmlId)({
prefix: 'previous'
});
var previousLabel = (0, _i18n.useEuiI18n)('euiTimeWindowButtons.previousLabel', 'Previous');
var previousTooltipContent = isInvalid ? invalidShiftDescription : previousDescription;
var zoomInId = (0, _services.useGeneratedHtmlId)({
prefix: 'zoom_in'
});
var zoomInLabel = (0, _i18n.useEuiI18n)('euiTimeWindowButtons.zoomInLabel', 'Zoom in');
var zoomInTooltipContent = isInvalid ? invalidZoomInDescription : isWindowDurationZero ? cannotZoomInDescription : zoomInLabel;
var zoomOutId = (0, _services.useGeneratedHtmlId)({
prefix: 'zoom_out'
});
var zoomOutLabel = (0, _i18n.useEuiI18n)('euiTimeWindowButtons.zoomOutLabel', 'Zoom out');
var zoomOutTooltipContent = isInvalid ? invalidZoomOutDescription : zoomOutLabel;
var nextId = (0, _services.useGeneratedHtmlId)({
prefix: 'next'
});
var nextLabel = (0, _i18n.useEuiI18n)('euiTimeWindowButtons.nextLabel', 'Next');
var nextTooltipContent = isInvalid ? invalidShiftDescription : nextDescription;
if (!showZoomIn && !showZoomOut && !showShiftArrows) return null;
return (0, _react2.jsx)("div", {
className: "euiSuperDatePicker__timeWindowButtons",
css: [styles.euiButtonGroup__buttons, styles[buttonSize], ";label:EuiTimeWindowButtons;"],
"data-test-subj": "timeWindowButtons"
}, showShiftArrows && (0, _react2.jsx)(_button_group_button.EuiButtonGroupButton, {
id: previousId,
"data-test-subj": "timeWindowButtonsPrevious",
label: previousLabel,
title: "",
toolTipContent: !isDisabled && previousTooltipContent,
color: buttonColor,
size: buttonSize,
iconType: "chevronSingleLeft",
iconSize: iconSize,
isIconOnly: true,
isDisabled: isWindowDurationZero || isDisabled,
onClick: stepBackward
}), showZoomIn && (0, _react2.jsx)(_button_group_button.EuiButtonGroupButton, {
id: zoomInId,
"data-test-subj": "timeWindowButtonsZoomIn",
label: zoomInLabel,
title: "",
toolTipContent: !isDisabled && zoomInTooltipContent,
toolTipProps: {
disableScreenReaderOutput: zoomInLabel === zoomInTooltipContent
},
color: buttonColor,
size: buttonSize,
iconType: "magnifyPlus",
iconSize: iconSize,
isIconOnly: true,
isDisabled: isWindowDurationZero || isDisabled,
onClick: shrinkWindow
}), showZoomOut && (0, _react2.jsx)(_button_group_button.EuiButtonGroupButton, {
id: zoomOutId,
"data-test-subj": "timeWindowButtonsZoomOut",
label: zoomOutLabel,
title: "",
toolTipContent: !isDisabled && zoomOutTooltipContent,
toolTipProps: {
disableScreenReaderOutput: zoomOutLabel === zoomOutTooltipContent
},
color: buttonColor,
size: buttonSize,
iconType: "magnifyMinus",
iconSize: iconSize,
isIconOnly: true,
isDisabled: isDisabled,
onClick: expandWindow
}), showShiftArrows && (0, _react2.jsx)(_button_group_button.EuiButtonGroupButton, {
id: nextId,
"data-test-subj": "timeWindowButtonsNext",
label: nextLabel,
title: "",
toolTipContent: !isDisabled && nextTooltipContent,
color: buttonColor,
size: buttonSize,
iconType: "chevronSingleRight",
iconSize: iconSize,
isIconOnly: true,
isDisabled: isWindowDurationZero || isDisabled,
onClick: stepForward
}));
};
/**
* Partly adapted from date_picker/super_date_picker/quick_select_popover/quick_select.tsx
*/
function useEuiTimeWindow(start, end, apply, options) {
var _options$zoomFactor;
var min = _datemath.default.parse(start);
/* `roundUp: true` will result in an "inclusive" time (e.g. 23:59:59.999 for 'now/d').
It only changes the value for relative expressions (e.g. 'now/d') but not absolute ISO strings. */
var max = _datemath.default.parse(end, {
roundUp: true
});
var isInvalid = !min || !min.isValid() || !max || !max.isValid();
/* An end at .999ms is always considered an inclusive boundary (either as result of `roundUp: true`
or entered manually).
To avoid a 1ms drift on every time window or zoom step, windowDuration has to be increased by 1ms.
This ensures the window is always at a clean boundary (e.g. 00:00:00.000 - 23:59:59.999). */
var isInclusiveBoundary = !isInvalid && max.milliseconds() === 999;
var endBoundary = !isInvalid ? isInclusiveBoundary ? (0, _moment.default)(max).add(1, 'ms') : (0, _moment.default)(max) : null;
var windowDuration = isInvalid || !endBoundary ? -1 : endBoundary.diff(min);
var isWindowDurationZero = windowDuration === 0;
var zoomFactor = getPercentageMultiplier((_options$zoomFactor = options === null || options === void 0 ? void 0 : options.zoomFactor) !== null && _options$zoomFactor !== void 0 ? _options$zoomFactor : ZOOM_FACTOR_DEFAULT);
var zoomDelta = windowDuration * (zoomFactor / 2); // Gets added to each end, that's why it's split in half
var prettyInterval = (0, _pretty_interval.usePrettyInterval)(false, windowDuration);
var displayInterval = isInvalid ? '' : prettyInterval;
if (!isInvalid && !(0, _relative_utils.isRelativeToNow)(start, end) && !isExactMinuteRange(windowDuration)) {
displayInterval = "~".concat(displayInterval);
}
return {
displayInterval: displayInterval,
isInvalid: isInvalid,
stepForward: stepForward,
stepBackward: stepBackward,
expandWindow: expandWindow,
shrinkWindow: shrinkWindow,
isWindowDurationZero: isWindowDurationZero
};
function stepForward() {
if (isInvalid || isWindowDurationZero) return;
apply({
/* Prevent 1ms drifts for inclusive boundaries by using the exclusive max (+ 1ms)
as the start of the next window (e.g. 00:00:00.000 instead of 23:59:59.999) */
start: (isInclusiveBoundary ? endBoundary // `!` is safe here because we early return on `isInvalid`
: (0, _moment.default)(max)).toISOString(),
end: (0, _moment.default)(max).add(windowDuration, 'ms').toISOString()
});
}
function stepBackward() {
if (isInvalid || isWindowDurationZero) return;
apply({
start: (0, _moment.default)(min).subtract(windowDuration, 'ms').toISOString(),
/* Prevent 1ms drifts for inclusive boundaries by using the exclusive min (- 1ms)
as the end of the previous window (e.g. 23:59:59.999 instead of 00:00:00.000) */
end: (isInclusiveBoundary ? (0, _moment.default)(min).subtract(1, 'ms') : (0, _moment.default)(min)).toISOString()
});
}
function expandWindow() {
if (isInvalid) return;
// when the window is 0 it'll remain 0 unless we help it a little
var addition = zoomDelta === 0 ? ZOOM_DELTA_FALLBACK_MS : zoomDelta;
apply({
start: (0, _moment.default)(min).subtract(addition, 'ms').toISOString(),
end: (0, _moment.default)(max).add(addition, 'ms').toISOString()
});
}
function shrinkWindow() {
if (isInvalid || isWindowDurationZero) return;
apply({
start: (0, _moment.default)(min).add(zoomDelta, 'ms').toISOString(),
end: (0, _moment.default)(max).subtract(zoomDelta, 'ms').toISOString()
});
}
}
/**
* Convert strings with % to a multiplier e.g. "50%" = 0.5
* Strings without % are returned as-is as number
*/
function getPercentageMultiplier(value) {
if (typeof value === 'string' && value.includes('%')) {
var parsed = parseFloat(value.replace('%', '').trim());
if (isNaN(parsed)) {
throw new TypeError('Invalid percentage string');
}
return parsed / 100;
}
var result = typeof value === 'number' ? value : parseFloat(String(value));
if (isNaN(result)) {
throw new TypeError('Please provide a valid number or percentage string e.g. "25%"');
}
return result;
}
/**
* Useful to determine whether to show the tilde in the display
*/
function isExactMinuteRange(diffMs) {
// 60 * 1000 = ms per minute
return diffMs % (60 * 1000) === 0;
}