From 39cc70a0abcea3b23ae52be63dd9b0a8074124ac Mon Sep 17 00:00:00 2001
From: Dimitri Mitropoulos
Date: Tue, 7 Apr 2020 20:08:19 -0400
Subject: [PATCH 01/10] converts all DatePicker family of components to
TypeScript
---
CHANGELOG.md | 1 +
...test.js.snap => date_picker.test.tsx.snap} | 1 -
...s.snap => date_picker_range.test.tsx.snap} | 0
...te_picker.test.js => date_picker.test.tsx} | 8 +-
.../{date_picker.js => date_picker.tsx} | 232 +++++-------
...nge.test.js => date_picker_range.test.tsx} | 0
..._picker_range.js => date_picker_range.tsx} | 103 ++---
src/components/date_picker/index.d.ts | 104 -----
src/components/date_picker/index.js | 10 -
src/components/date_picker/index.ts | 27 ++
.../date_picker/react-datepicker.d.ts | 81 +++-
...s.snap => super_date_picker.test.tsx.snap} | 1 -
...snap => super_update_button.test.tsx.snap} | 0
.../super_date_picker/async_interval.js | 22 --
...nterval.test.js => async_interval.test.ts} | 21 +-
.../super_date_picker/async_interval.ts | 25 ++
...{date_modes.test.js => date_modes.test.ts} | 2 +-
.../{date_modes.js => date_modes.ts} | 18 +-
.../{absolute_tab.js => absolute_tab.tsx} | 94 +++--
...over_button.js => date_popover_button.tsx} | 54 ++-
...er_content.js => date_popover_content.tsx} | 52 +--
.../super_date_picker/date_popover/index.ts | 10 +
.../{relative_tab.js => relative_tab.tsx} | 94 +++--
.../date_picker/super_date_picker/index.js | 5 -
.../date_picker/super_date_picker/index.ts | 15 +
...ration.test.js => pretty_duration.test.ts} | 0
...{pretty_duration.js => pretty_duration.ts} | 32 +-
...est.js.snap => quick_select.test.tsx.snap} | 16 +-
...nap => quick_select_popover.test.tsx.snap} | 8 +-
...anges.js => commonly_used_time_ranges.tsx} | 31 +-
.../quick_select_popover/index.ts | 14 +
...k_select.test.js => quick_select.test.tsx} | 4 +-
.../{quick_select.js => quick_select.tsx} | 122 +++---
....test.js => quick_select_popover.test.tsx} | 7 +-
...ct_popover.js => quick_select_popover.tsx} | 120 +++---
...ils.test.js => quick_select_utils.test.ts} | 24 +-
..._select_utils.js => quick_select_utils.ts} | 68 ++--
.../{recently_used.js => recently_used.tsx} | 29 +-
...fresh_interval.js => refresh_interval.tsx} | 131 ++++---
.../super_date_picker/relative_options.ts | 17 +-
...e_utils.test.js => relative_utils.test.ts} | 0
.../{relative_utils.js => relative_utils.ts} | 21 +-
...ker.test.js => super_date_picker.test.tsx} | 26 +-
...r_date_picker.js => super_date_picker.tsx} | 356 ++++++++++--------
...n.test.js => super_update_button.test.tsx} | 0
...date_button.js => super_update_button.tsx} | 55 +--
.../super_date_picker/time_units.js | 19 -
.../super_date_picker/time_units.ts | 21 ++
.../date_picker/super_date_picker/types.js | 17 -
src/components/date_picker/types.ts | 72 ++++
src/components/index.d.ts | 3 -
51 files changed, 1215 insertions(+), 978 deletions(-)
rename src/components/date_picker/__snapshots__/{date_picker.test.js.snap => date_picker.test.tsx.snap} (99%)
rename src/components/date_picker/__snapshots__/{date_picker_range.test.js.snap => date_picker_range.test.tsx.snap} (100%)
rename src/components/date_picker/{date_picker.test.js => date_picker.test.tsx} (84%)
rename src/components/date_picker/{date_picker.js => date_picker.tsx} (65%)
rename src/components/date_picker/{date_picker_range.test.js => date_picker_range.test.tsx} (100%)
rename src/components/date_picker/{date_picker_range.js => date_picker_range.tsx} (61%)
delete mode 100644 src/components/date_picker/index.d.ts
delete mode 100644 src/components/date_picker/index.js
create mode 100644 src/components/date_picker/index.ts
rename src/components/date_picker/super_date_picker/__snapshots__/{super_date_picker.test.js.snap => super_date_picker.test.tsx.snap} (98%)
rename src/components/date_picker/super_date_picker/__snapshots__/{super_update_button.test.js.snap => super_update_button.test.tsx.snap} (100%)
delete mode 100644 src/components/date_picker/super_date_picker/async_interval.js
rename src/components/date_picker/super_date_picker/{async_interval.test.js => async_interval.test.ts} (85%)
create mode 100644 src/components/date_picker/super_date_picker/async_interval.ts
rename src/components/date_picker/super_date_picker/{date_modes.test.js => date_modes.test.ts} (97%)
rename src/components/date_picker/super_date_picker/{date_modes.js => date_modes.ts} (59%)
rename src/components/date_picker/super_date_picker/date_popover/{absolute_tab.js => absolute_tab.tsx} (50%)
rename src/components/date_picker/super_date_picker/date_popover/{date_popover_button.js => date_popover_button.tsx} (61%)
rename src/components/date_picker/super_date_picker/date_popover/{date_popover_content.js => date_popover_content.tsx} (70%)
create mode 100644 src/components/date_picker/super_date_picker/date_popover/index.ts
rename src/components/date_picker/super_date_picker/date_popover/{relative_tab.js => relative_tab.tsx} (65%)
delete mode 100644 src/components/date_picker/super_date_picker/index.js
create mode 100644 src/components/date_picker/super_date_picker/index.ts
rename src/components/date_picker/super_date_picker/{pretty_duration.test.js => pretty_duration.test.ts} (100%)
rename src/components/date_picker/super_date_picker/{pretty_duration.js => pretty_duration.ts} (77%)
rename src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/{quick_select.test.js.snap => quick_select.test.tsx.snap} (97%)
rename src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/{quick_select_popover.test.js.snap => quick_select_popover.test.tsx.snap} (95%)
rename src/components/date_picker/super_date_picker/quick_select_popover/{commonly_used_time_ranges.js => commonly_used_time_ranges.tsx} (68%)
create mode 100644 src/components/date_picker/super_date_picker/quick_select_popover/index.ts
rename src/components/date_picker/super_date_picker/quick_select_popover/{quick_select.test.js => quick_select.test.tsx} (100%)
rename src/components/date_picker/super_date_picker/quick_select_popover/{quick_select.js => quick_select.tsx} (75%)
rename src/components/date_picker/super_date_picker/quick_select_popover/{quick_select_popover.test.js => quick_select_popover.test.tsx} (85%)
rename src/components/date_picker/super_date_picker/quick_select_popover/{quick_select_popover.js => quick_select_popover.tsx} (59%)
rename src/components/date_picker/super_date_picker/quick_select_popover/{quick_select_utils.test.js => quick_select_utils.test.ts} (71%)
rename src/components/date_picker/super_date_picker/quick_select_popover/{quick_select_utils.js => quick_select_utils.ts} (52%)
rename src/components/date_picker/super_date_picker/quick_select_popover/{recently_used.js => recently_used.tsx} (70%)
rename src/components/date_picker/super_date_picker/quick_select_popover/{refresh_interval.js => refresh_interval.tsx} (62%)
rename src/components/date_picker/super_date_picker/{relative_utils.test.js => relative_utils.test.ts} (100%)
rename src/components/date_picker/super_date_picker/{relative_utils.js => relative_utils.ts} (72%)
rename src/components/date_picker/super_date_picker/{super_date_picker.test.js => super_date_picker.test.tsx} (77%)
rename src/components/date_picker/super_date_picker/{super_date_picker.js => super_date_picker.tsx} (61%)
rename src/components/date_picker/super_date_picker/{super_update_button.test.js => super_update_button.test.tsx} (100%)
rename src/components/date_picker/super_date_picker/{super_update_button.js => super_update_button.tsx} (75%)
delete mode 100644 src/components/date_picker/super_date_picker/time_units.js
create mode 100644 src/components/date_picker/super_date_picker/time_units.ts
delete mode 100644 src/components/date_picker/super_date_picker/types.js
create mode 100644 src/components/date_picker/types.ts
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 89ef9741b53..7fdc4c4b4c0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,6 @@
## [`master`](https://github.com/elastic/eui/tree/master)
+- Converted `EuiDatePicker`, `EuiDatePickerRange`, `EuiSuperDatePicker`, and `EuiSuperUpdateButton` to TypeScript ([#2891](https://github.com/elastic/eui/pull/2891))
No public interface changes since `22.5.0`.
## [`22.5.0`](https://github.com/elastic/eui/tree/v22.5.0)
diff --git a/src/components/date_picker/__snapshots__/date_picker.test.js.snap b/src/components/date_picker/__snapshots__/date_picker.test.tsx.snap
similarity index 99%
rename from src/components/date_picker/__snapshots__/date_picker.test.js.snap
rename to src/components/date_picker/__snapshots__/date_picker.test.tsx.snap
index 0d50659bbed..473823bf096 100644
--- a/src/components/date_picker/__snapshots__/date_picker.test.js.snap
+++ b/src/components/date_picker/__snapshots__/date_picker.test.tsx.snap
@@ -6,7 +6,6 @@ exports[`EuiDatePicker is rendered 1`] = `
className="euiDatePicker euiDatePicker--shadow"
>
{
test('is rendered', () => {
- const component = shallow();
+ const component = shallow(
+
+ );
expect(component).toMatchSnapshot(); // snapshot of wrapping dom
expect(component.find('ContextConsumer').shallow()).toMatchSnapshot(); // snapshot of DatePicker usage
});
describe('localization', () => {
- const selectedDate = new Moment('2019-07-01T00:00:00-0700').locale('fr');
+ const selectedDate = moment('2019-07-01T00:00:00-0700').locale('fr');
test('accepts the locale prop', () => {
const component = mount(
diff --git a/src/components/date_picker/date_picker.js b/src/components/date_picker/date_picker.tsx
similarity index 65%
rename from src/components/date_picker/date_picker.js
rename to src/components/date_picker/date_picker.tsx
index 6d97c77acf5..9ab82556e08 100644
--- a/src/components/date_picker/date_picker.js
+++ b/src/components/date_picker/date_picker.tsx
@@ -1,22 +1,93 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
+import React, { Component, MouseEventHandler, RefCallback } from 'react';
import classNames from 'classnames';
-import moment from 'moment';
-import { ReactDatePicker as DatePicker } from '../../../packages';
+import { Moment } from 'moment'; // eslint-disable-line import/named
-import { EuiFormControlLayout } from '../form/form_control_layout';
-
-import { EuiValidatableControl } from '../form/validatable_control';
+import { EuiFormControlLayout, EuiValidatableControl } from '../form';
+import { EuiFormControlLayoutIconsProps } from '../form/form_control_layout/form_control_layout_icons';
import { EuiErrorBoundary } from '../error_boundary';
import { EuiI18nConsumer } from '../context';
+import { CommonProps } from '../common';
+
+// @ts-ignore the type is provided by react-datepicker.d.ts
+import { ReactDatePicker as _ReactDatePicker } from '../../../packages';
+import ReactDatePicker, { ReactDatePickerProps } from './react-datepicker'; // eslint-disable-line import/no-unresolved
export const euiDatePickerDefaultDateFormat = 'MM/DD/YYYY';
export const euiDatePickerDefaultTimeFormat = 'hh:mm A';
-export class EuiDatePicker extends Component {
+const DatePicker = _ReactDatePicker as typeof ReactDatePicker;
+
+interface EuiExtendedDatePickerProps extends ReactDatePickerProps {
+ /**
+ * Applies classes to the numbered days provided. Check docs for example.
+ */
+ dayClassName?: (date: Moment) => string | null;
+
+ /**
+ * Makes the input full width
+ */
+ fullWidth?: boolean;
+
+ /**
+ * ref for the ReactDatePicker instance
+ */
+ inputRef: RefCallback>;
+
+ /**
+ * Provides styling to the input when invalid
+ */
+ isInvalid?: boolean;
+
+ /**
+ * Provides styling to the input when loading
+ */
+ isLoading?: boolean;
+
+ /**
+ * What to do when the input is cleared by the x icon
+ */
+ onClear?: MouseEventHandler;
+
+ /**
+ * Opens to this date (in moment format) on first press, regardless of selection
+ */
+ openToDate?: Moment;
+
+ /**
+ * Shows only when no date is selected
+ */
+ placeholder?: string;
+
+ /**
+ * Can turn the shadow off if using the inline prop
+ */
+ shadow?: boolean;
+
+ /**
+ * Show the icon in input
+ */
+ showIcon?: boolean;
+}
+
+export type EuiDatePickerProps = CommonProps & EuiExtendedDatePickerProps;
+
+export class EuiDatePicker extends Component {
+ static defaultProps = {
+ adjustDateOnChange: true,
+ dateFormat: euiDatePickerDefaultDateFormat,
+ fullWidth: false,
+ inputRef: () => {},
+ isLoading: false,
+ shadow: true,
+ shouldCloseOnSelect: true,
+ showIcon: true,
+ showTimeSelect: false,
+ timeFormat: euiDatePickerDefaultTimeFormat,
+ };
+
render() {
const {
adjustDateOnChange,
@@ -27,7 +98,7 @@ export class EuiDatePicker extends Component {
dayClassName,
disabled,
excludeDates,
- filterDates,
+ filterDate,
fullWidth,
injectTimes,
inline,
@@ -72,9 +143,9 @@ export class EuiDatePicker extends Component {
className
);
- let optionalIcon;
+ let optionalIcon: EuiFormControlLayoutIconsProps['icon'];
if (inline || customInput || !showIcon) {
- optionalIcon = null;
+ optionalIcon = undefined;
} else if (showTimeSelectOnly) {
optionalIcon = 'clock';
} else {
@@ -130,7 +201,7 @@ export class EuiDatePicker extends Component {
@@ -145,7 +216,7 @@ export class EuiDatePicker extends Component {
dayClassName={dayClassName}
disabled={disabled}
excludeDates={excludeDates}
- filterDates={filterDates}
+ filterDate={filterDate}
injectTimes={injectTimes}
inline={inline}
locale={locale || contextLocale}
@@ -167,7 +238,7 @@ export class EuiDatePicker extends Component {
timeFormat={timeFormat}
utcOffset={utcOffset}
yearDropdownItemNumber={7}
- accessibleMode={true}
+ accessibleMode
{...rest}
/>
);
@@ -180,136 +251,3 @@ export class EuiDatePicker extends Component {
);
}
}
-
-EuiDatePicker.propTypes = {
- /**
- * Whether changes to Year and Month (via dropdowns) should trigger `onChange`
- */
- adjustDateOnChange: PropTypes.bool,
- /**
- * Optional class added to the calendar portion of datepicker
- */
- calendarClassName: PropTypes.string,
-
- /**
- * Added to the actual input of the calendar
- */
- className: PropTypes.string,
- /**
- * Replaces the input with any node, like a button
- */
- customInput: PropTypes.node,
- /**
- * Accepts any moment format string
- */
- dateFormat: PropTypes.string,
- /**
- * Applies classes to the numbered days provided. Check docs for example.
- */
- dayClassName: PropTypes.func,
-
- /**
- * Array of dates allowed. Check docs for example.
- */
- filterDates: PropTypes.array,
- /**
- * Makes the input full width
- */
- fullWidth: PropTypes.bool,
- /**
- * Adds additional times to the time selector other then :30 increments
- */
- injectTimes: PropTypes.array,
- /**
- * Applies ref to the input
- */
- inputRef: PropTypes.func,
- /**
- * Provides styling to the input when invalid
- */
- isInvalid: PropTypes.bool,
- /**
- * Provides styling to the input when loading
- */
- isLoading: PropTypes.bool,
- /**
- * Switches the locale / display. "en-us", "zn-ch"...etc
- */
- locale: PropTypes.string,
- /**
- * The max date accepted (in moment format) as a selection
- */
- maxDate: PropTypes.instanceOf(moment),
- /**
- * The max time accepted (in moment format) as a selection
- */
- maxTime: PropTypes.instanceOf(moment),
- /**
- * The min date accepted (in moment format) as a selection
- */
- minDate: PropTypes.instanceOf(moment),
- /**
- * The min time accepted (in moment format) as a selection
- */
- minTime: PropTypes.instanceOf(moment),
- /**
- * What to do when the input changes
- */
- onChange: PropTypes.func,
- /**
- * What to do when the input is cleared by the x icon
- */
- onClear: PropTypes.func,
- /**
- * Opens to this date (in moment format) on first press, regardless of selection
- */
- openToDate: PropTypes.instanceOf(moment),
- /**
- * Shows only when no date is selected
- */
- placeholder: PropTypes.string,
- /**
- * Class applied to the popup, when inline is false
- */
- popperClassName: PropTypes.string,
- /**
- * The selected datetime (in moment format)
- */
- selected: PropTypes.instanceOf(moment),
- /**
- * Can turn the shadow off if using the inline prop
- */
- shadow: PropTypes.bool,
- /**
- * Will close the popup on selection
- */
- shouldCloseOnSelect: PropTypes.bool,
- /**
- * Show the icon in input
- */
- showIcon: PropTypes.bool,
- /**
- * Show the time selection alongside the calendar
- */
- showTimeSelect: PropTypes.bool,
- /**
- * Only show the time selector, not the calendar
- */
- showTimeSelectOnly: PropTypes.bool,
- /**
- * The format of the time within the selector, in moment notation
- */
- timeFormat: PropTypes.string,
-};
-
-EuiDatePicker.defaultProps = {
- adjustDateOnChange: true,
- dateFormat: euiDatePickerDefaultDateFormat,
- fullWidth: false,
- isLoading: false,
- shadow: true,
- shouldCloseOnSelect: true,
- showIcon: true,
- showTimeSelect: false,
- timeFormat: euiDatePickerDefaultTimeFormat,
-};
diff --git a/src/components/date_picker/date_picker_range.test.js b/src/components/date_picker/date_picker_range.test.tsx
similarity index 100%
rename from src/components/date_picker/date_picker_range.test.js
rename to src/components/date_picker/date_picker_range.test.tsx
diff --git a/src/components/date_picker/date_picker_range.js b/src/components/date_picker/date_picker_range.tsx
similarity index 61%
rename from src/components/date_picker/date_picker_range.js
rename to src/components/date_picker/date_picker_range.tsx
index ac8997fb722..f48e2337ebc 100644
--- a/src/components/date_picker/date_picker_range.js
+++ b/src/components/date_picker/date_picker_range.tsx
@@ -1,16 +1,52 @@
-import React, { cloneElement, Fragment } from 'react';
-import PropTypes from 'prop-types';
+import React, {
+ Fragment,
+ FunctionComponent,
+ ReactNode,
+ cloneElement,
+ ReactElement,
+} from 'react';
import classNames from 'classnames';
import { EuiText } from '../text';
-import { EuiIcon } from '../icon';
+import { EuiIcon, IconType } from '../icon';
+import { CommonProps } from '../common';
+import { EuiDatePickerProps } from './date_picker';
-export const EuiDatePickerRange = ({
+export type EuiDatePickerRangeProps = CommonProps & {
+ /**
+ * Including any children will replace all innerds with the provided children
+ */
+ children?: ReactNode;
+
+ /**
+ * The end date `EuiDatePicker` element
+ */
+ endDateControl: ReactNode;
+ fullWidth?: boolean;
+
+ /**
+ * Pass either an icon type or set to `false` to remove icon entirely
+ */
+ iconType?: boolean | IconType;
+
+ /**
+ * Won't apply any additional props to start and end date components
+ */
+ isCustom?: boolean;
+ readOnly?: boolean;
+
+ /**
+ * The start date `EuiDatePicker` element
+ */
+ startDateControl: ReactNode;
+};
+
+export const EuiDatePickerRange: FunctionComponent = ({
children,
className,
startDateControl,
endDateControl,
- iconType,
+ iconType = true,
fullWidth,
isCustom,
readOnly,
@@ -42,17 +78,23 @@ export const EuiDatePickerRange = ({
let endControl = endDateControl;
if (!isCustom) {
- startControl = cloneElement(startDateControl, {
- showIcon: false,
- fullWidth: fullWidth,
- readOnly: readOnly,
- });
+ startControl = cloneElement(
+ startDateControl as ReactElement,
+ {
+ showIcon: false,
+ fullWidth: fullWidth,
+ readOnly: readOnly,
+ }
+ );
- endControl = cloneElement(endDateControl, {
- showIcon: false,
- fullWidth: fullWidth,
- readOnly: readOnly,
- });
+ endControl = cloneElement(
+ endDateControl as ReactElement,
+ {
+ showIcon: false,
+ fullWidth: fullWidth,
+ readOnly: readOnly,
+ }
+ );
}
return (
@@ -75,34 +117,3 @@ export const EuiDatePickerRange = ({
);
};
-
-EuiDatePickerRange.propTypes = {
- /**
- * The start date `EuiDatePicker` element
- */
- startDateControl: PropTypes.node.isRequired,
- /**
- * The end date `EuiDatePicker` element
- */
- endDateControl: PropTypes.node.isRequired,
- /**
- * Pass either an icon type or set to `false` to remove icon entirely
- */
- iconType: PropTypes.oneOfType([
- PropTypes.bool,
- PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
- ]),
- fullWidth: PropTypes.bool,
- /**
- * Won't apply any additional props to start and end date components
- */
- isCustom: PropTypes.bool,
- /**
- * Including any children will replace all innerds with the provided children
- */
- children: PropTypes.node,
-};
-
-EuiDatePickerRange.defaultProps = {
- iconType: true,
-};
diff --git a/src/components/date_picker/index.d.ts b/src/components/date_picker/index.d.ts
deleted file mode 100644
index ff810cec0be..00000000000
--- a/src/components/date_picker/index.d.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-import React from 'react';
-import { CommonProps } from '../common';
-import { IconType } from '../icon';
-import _ReactDatePicker, {
- ReactDatePickerProps as _ReactDatePickerProps,
-} from './react-datepicker'; // eslint-disable-line import/no-unresolved
-import { Moment } from 'moment'; // eslint-disable-line import/named
-
-declare module '@elastic/eui' {
- interface OnTimeChangeProps {
- start: string;
- end: string;
- isInvalid: boolean;
- isQuickSelection: boolean;
- }
-
- interface OnRefreshProps {
- start: string;
- end: string;
- refreshInterval: number;
- }
-
- interface OnRefreshChangeProps {
- isPaused: boolean;
- refreshInterval: number;
- }
-
- interface EuiExtendedDatePickerProps extends _ReactDatePickerProps {
- fullWidth?: boolean;
- isInvalid?: boolean;
- isLoading?: boolean;
- injectTimes?: Moment[]; // added here because the type is missing in @types/react-datepicker@1.8.0
- inputRef?: React.Ref;
- placeholder?: string;
- shadow?: boolean;
- showIcon?: boolean;
- }
-
- export type EuiDatePickerProps = CommonProps & EuiExtendedDatePickerProps;
- export const EuiDatePicker: React.SFC;
-
- export type EuiDatePickerRangeProps = CommonProps & {
- startDateControl: React.ReactElement;
- endDateControl: React.ReactElement;
- iconType?: boolean | IconType;
- fullWidth?: boolean;
- isCustom?: boolean;
- };
-
- export const EuiDatePickerRange: React.SFC;
-
- export interface EuiSuperDatePickerCommonRange {
- start: string;
- end: string;
- label: string;
- }
-
- export interface EuiSuperDatePickerRecentRange {
- start: string;
- end: string;
- }
-
- export interface EuiSuperDatePickerQuickSelectPanel {
- title: string;
- content: React.ReactNode;
- }
-
- export type EuiSuperDatePickerProps = CommonProps & {
- isLoading?: boolean;
- start?: string;
- end?: string;
- isPaused?: boolean;
- refreshInterval?: number;
- onTimeChange: (props: OnTimeChangeProps) => void;
- onRefresh?: (props: OnRefreshProps) => void;
- onRefreshChange?: (props: OnRefreshChangeProps) => void;
- commonlyUsedRanges?: EuiSuperDatePickerCommonRange[];
- dateFormat?: string;
- recentlyUsedRanges?: EuiSuperDatePickerRecentRange[];
- showUpdateButton?: boolean;
- isAutoRefreshOnly?: boolean;
- customQuickSelectPanels?: EuiSuperDatePickerQuickSelectPanel[];
- };
-
- export const EuiSuperDatePicker: React.SFC;
-
- export const ReactDatePicker: typeof _ReactDatePicker;
- export const ReactDatePickerProps: _ReactDatePickerProps;
-
- interface DurationRange {
- start: string;
- end: string;
- label: string;
- }
-
- export const commonDurationRanges: DurationRange[];
-
- export function prettyDuration(
- timeFrom: string,
- timeTo: string,
- quickRanges: DurationRange[],
- dateFormat: string
- ): string;
-}
diff --git a/src/components/date_picker/index.js b/src/components/date_picker/index.js
deleted file mode 100644
index 69a0ec433e7..00000000000
--- a/src/components/date_picker/index.js
+++ /dev/null
@@ -1,10 +0,0 @@
-export { EuiDatePicker } from './date_picker';
-
-export { EuiDatePickerRange } from './date_picker_range';
-
-export {
- EuiSuperDatePicker,
- EuiSuperUpdateButton,
- prettyDuration,
- commonDurationRanges,
-} from './super_date_picker';
diff --git a/src/components/date_picker/index.ts b/src/components/date_picker/index.ts
new file mode 100644
index 00000000000..d21663b3dce
--- /dev/null
+++ b/src/components/date_picker/index.ts
@@ -0,0 +1,27 @@
+export * from './super_date_picker';
+
+export { EuiDatePicker, EuiDatePickerProps } from './date_picker';
+
+export {
+ EuiDatePickerRange,
+ EuiDatePickerRangeProps,
+} from './date_picker_range';
+
+export {
+ DurationRange as EuiSuperDatePickerCommonRange,
+ DurationRange as EuiSuperDatePickerDurationRange,
+ DurationRange as EuiSuperDatePickerRecentRange,
+ TimeUnitId,
+ TimeUnitFromNowId,
+ TimeUnitLabel,
+ TimeUnitLabelPlural,
+ AbsoluteDateMode,
+ RelativeDateMode,
+ NowDateMode,
+ DateMode,
+ ShortDate,
+ RelativeParts,
+ RelativeOption,
+ QuickSelect,
+ QuickSelectPanel as EuiSuperDatePickerQuickSelectPanel,
+} from './types';
diff --git a/src/components/date_picker/react-datepicker.d.ts b/src/components/date_picker/react-datepicker.d.ts
index 81f19ce3cb1..8bb40f060d0 100644
--- a/src/components/date_picker/react-datepicker.d.ts
+++ b/src/components/date_picker/react-datepicker.d.ts
@@ -15,15 +15,35 @@ import * as React from 'react';
import * as moment from 'moment';
export interface ReactDatePickerProps {
+ /**
+ * Whether changes to Year and Month (via dropdowns) should trigger `onChange`
+ */
adjustDateOnChange?: boolean;
+ accessibleMode?: boolean;
allowSameDay?: boolean;
autoComplete?: string;
autoFocus?: boolean;
+
+ /**
+ * Optional class added to the calendar portion of datepicker
+ */
calendarClassName?: string;
children?: React.ReactNode;
+
+ /**
+ * Added to the actual input of the calendar
+ */
className?: string;
+
+ /**
+ * Replaces the input with any node, like a button
+ */
customInput?: React.ReactNode;
customInputRef?: string;
+
+ /**
+ * Accepts any moment format string
+ */
dateFormat?: string | string[];
dateFormatCalendar?: string;
dayClassName?(date: moment.Moment): string | null;
@@ -42,18 +62,47 @@ export interface ReactDatePickerProps {
includeDates?: moment.Moment[];
includeTimes?: moment.Moment[];
inline?: boolean;
+
+ /**
+ * Adds additional times to the time selector other then :30 increments
+ */
+ injectTimes?: moment.Moment[];
isClearable?: boolean;
- locale?: string;
+
+ /**
+ * Switches the locale / display. "en-us", "zn-ch"...etc
+ */
+ locale?: moment.LocaleSpecifier;
+
+ /**
+ * The max date accepted (in moment format) as a selection
+ */
maxDate?: moment.Moment;
+
+ /**
+ * The max time accepted (in moment format) as a selection
+ */
maxTime?: moment.Moment;
+
+ /**
+ * The min date accepted (in moment format) as a selection
+ */
minDate?: moment.Moment;
+
+ /**
+ * The min time accepted (in moment format) as a selection
+ */
minTime?: moment.Moment;
monthsShown?: number;
name?: string;
onBlur?(event: React.FocusEvent): void;
- onChange(
- date: moment.Moment | null,
- event: React.SyntheticEvent | undefined
+
+ /**
+ * What to do when the input changes
+ */
+ onChange?(
+ date: moment.Moment | string | null,
+ event?: React.SyntheticEvent | undefined
): void;
onChangeRaw?(event: React.FocusEvent): void;
onClickOutside?(event: React.MouseEvent): void;
@@ -73,6 +122,10 @@ export interface ReactDatePickerProps {
openToDate?: moment.Moment;
peekNextMonth?: boolean;
placeholderText?: string;
+
+ /**
+ * Class applied to the popup, when inline is false
+ */
popperClassName?: string;
popperContainer?(props: { children: React.ReactNode[] }): React.ReactNode;
popperPlacement?: string;
@@ -81,14 +134,30 @@ export interface ReactDatePickerProps {
required?: boolean;
scrollableMonthYearDropdown?: boolean;
scrollableYearDropdown?: boolean;
+
+ /**
+ * The selected datetime (in moment format)
+ */
selected?: moment.Moment | null;
selectsEnd?: boolean;
selectsStart?: boolean;
+
+ /**
+ * Will close the popup on selection
+ */
shouldCloseOnSelect?: boolean;
showDisabledMonthNavigation?: boolean;
showMonthDropdown?: boolean;
showMonthYearDropdown?: boolean;
+
+ /**
+ * Show the time selection alongside the calendar
+ */
showTimeSelect?: boolean;
+
+ /**
+ * Only show the time selector, not the calendar
+ */
showTimeSelectOnly?: boolean;
showWeekNumbers?: boolean;
showYearDropdown?: boolean;
@@ -96,6 +165,10 @@ export interface ReactDatePickerProps {
startOpen?: boolean;
tabIndex?: number;
timeCaption?: string;
+
+ /**
+ * The format of the time within the selector, in moment notation
+ */
timeFormat?: string;
timeIntervals?: number;
title?: string;
diff --git a/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.js.snap b/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.tsx.snap
similarity index 98%
rename from src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.js.snap
rename to src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.tsx.snap
index 802d4d7dc3b..629084f893c 100644
--- a/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.js.snap
+++ b/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.tsx.snap
@@ -12,7 +12,6 @@ exports[`EuiSuperDatePicker is rendered 1`] = `
isDisabled={false}
prepend={
{
- if (!this.isStopped) {
- this.timeoutId = window.setTimeout(async () => {
- this.__pendingFn = await fn();
- this.setAsyncInterval(fn, ms);
- }, ms);
- }
- };
-
- stop = () => {
- this.isStopped = true;
- window.clearTimeout(this.timeoutId);
- };
-}
diff --git a/src/components/date_picker/super_date_picker/async_interval.test.js b/src/components/date_picker/super_date_picker/async_interval.test.ts
similarity index 85%
rename from src/components/date_picker/super_date_picker/async_interval.test.js
rename to src/components/date_picker/super_date_picker/async_interval.test.ts
index 7f660070b85..db2bb0af173 100644
--- a/src/components/date_picker/super_date_picker/async_interval.test.js
+++ b/src/components/date_picker/super_date_picker/async_interval.test.ts
@@ -13,11 +13,16 @@ describe('AsyncInterval', () => {
// Advances time and awaits any pending promises after every 100ms
// This helper makes it easier to advance time without worrying
// whether tasks are still lingering on the event loop
- async function andvanceTimerAndAwaitFn(instance, ms) {
- const iterations = [...Array(Math.floor(ms / 100)).keys()];
- const remainder = ms % 100;
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ async function andvanceTimerAndAwaitFn(
+ instance: AsyncInterval,
+ milliseconds: number
+ ) {
+ const iterations = [...Array(Math.floor(milliseconds / 100)).keys()];
+ const remainder = milliseconds % 100;
+ /* eslint-disable @typescript-eslint/no-unused-vars */
+ // @ts-ignore
for (const item of iterations) {
+ /* eslint-enable @typescript-eslint/no-unused-vars */
await instance.__pendingFn;
jest.advanceTimersByTime(100);
await instance.__pendingFn;
@@ -27,8 +32,8 @@ describe('AsyncInterval', () => {
}
describe('when creating a 1000ms interval', async () => {
- let instance;
- let spy;
+ let instance: AsyncInterval;
+ let spy: jest.Mock;
beforeEach(() => {
spy = jest.fn();
instance = new AsyncInterval(spy, 1000);
@@ -64,8 +69,8 @@ describe('AsyncInterval', () => {
});
describe('when creating a 1000ms interval that calls a fn that takes 2000ms to complete', async () => {
- let instance;
- let spy;
+ let instance: AsyncInterval;
+ let spy: jest.Mock;
beforeEach(() => {
spy = jest.fn(async () => await sleep(2000));
instance = new AsyncInterval(spy, 1000);
diff --git a/src/components/date_picker/super_date_picker/async_interval.ts b/src/components/date_picker/super_date_picker/async_interval.ts
new file mode 100644
index 00000000000..00a3f78d1d7
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/async_interval.ts
@@ -0,0 +1,25 @@
+export class AsyncInterval {
+ timeoutId: number | null = null;
+ isStopped = false;
+ __pendingFn: Function = () => {};
+
+ constructor(fn: Function, refreshInterval: number) {
+ this.setAsyncInterval(fn, refreshInterval);
+ }
+
+ setAsyncInterval = (fn: Function, milliseconds: number) => {
+ if (!this.isStopped) {
+ this.timeoutId = window.setTimeout(async () => {
+ this.__pendingFn = await fn();
+ this.setAsyncInterval(fn, milliseconds);
+ }, milliseconds);
+ }
+ };
+
+ stop = () => {
+ this.isStopped = true;
+ if (this.timeoutId !== null) {
+ window.clearTimeout(this.timeoutId);
+ }
+ };
+}
diff --git a/src/components/date_picker/super_date_picker/date_modes.test.js b/src/components/date_picker/super_date_picker/date_modes.test.ts
similarity index 97%
rename from src/components/date_picker/super_date_picker/date_modes.test.js
rename to src/components/date_picker/super_date_picker/date_modes.test.ts
index e37eb42970f..ac506442433 100644
--- a/src/components/date_picker/super_date_picker/date_modes.test.js
+++ b/src/components/date_picker/super_date_picker/date_modes.test.ts
@@ -10,7 +10,7 @@ jest.mock('@elastic/datemath', () => {
moment.now = () => offset + Date.now();
return {
...datemath,
- parse: (text, options) =>
+ parse: (text: string, options: any) =>
datemath.parse(text, {
forceNow: anchoredDate, // For `toAbsoluteString`
momentInstance: moment, // For `toRelativeString`
diff --git a/src/components/date_picker/super_date_picker/date_modes.js b/src/components/date_picker/super_date_picker/date_modes.ts
similarity index 59%
rename from src/components/date_picker/super_date_picker/date_modes.js
rename to src/components/date_picker/super_date_picker/date_modes.ts
index 16f9924bf0a..f2db4a24b90 100644
--- a/src/components/date_picker/super_date_picker/date_modes.js
+++ b/src/components/date_picker/super_date_picker/date_modes.ts
@@ -3,14 +3,24 @@ import {
parseRelativeParts,
toRelativeStringFromParts,
} from './relative_utils';
+import {
+ AbsoluteDateMode,
+ RelativeDateMode,
+ NowDateMode,
+ ShortDate,
+} from '../types';
-export const DATE_MODES = {
+export const DATE_MODES: {
+ ABSOLUTE: AbsoluteDateMode;
+ RELATIVE: RelativeDateMode;
+ NOW: NowDateMode;
+} = {
ABSOLUTE: 'absolute',
RELATIVE: 'relative',
NOW: 'now',
};
-export function getDateMode(value) {
+export function getDateMode(value: ShortDate) {
if (value === 'now') {
return DATE_MODES.NOW;
}
@@ -22,7 +32,7 @@ export function getDateMode(value) {
return DATE_MODES.ABSOLUTE;
}
-export function toAbsoluteString(value, roundUp) {
+export function toAbsoluteString(value: string, roundUp: boolean = false) {
const valueAsMoment = dateMath.parse(value, { roundUp });
if (!valueAsMoment) {
return value;
@@ -30,6 +40,6 @@ export function toAbsoluteString(value, roundUp) {
return valueAsMoment.toISOString();
}
-export function toRelativeString(value) {
+export function toRelativeString(value: string) {
return toRelativeStringFromParts(parseRelativeParts(value));
}
diff --git a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx
similarity index 50%
rename from src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
rename to src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx
index ee106752024..a0a28766ab4 100644
--- a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
+++ b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx
@@ -1,54 +1,88 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
+import React, { Component, ChangeEventHandler } from 'react';
-import moment from 'moment';
+import moment, { Moment, LocaleSpecifier } from 'moment'; // eslint-disable-line import/named
import dateMath from '@elastic/datemath';
import { EuiDatePicker } from '../../date_picker';
import { EuiFormRow, EuiFieldText, EuiFormLabel } from '../../../form';
import { toSentenceCase } from '../../../../services/string/to_case';
+import { ReactDatePickerProps } from '../../react-datepicker'; // eslint-disable-line import/no-unresolved
-export class EuiAbsoluteTab extends Component {
- constructor(props) {
+export interface EuiAbsoluteTabProps {
+ dateFormat: string;
+ timeFormat: string;
+ locale?: LocaleSpecifier;
+ value: string;
+ onChange: NonNullable;
+ roundUp: boolean;
+ position: 'start' | 'end';
+}
+
+interface EuiAbsoluteTabState {
+ isTextInvalid: boolean;
+ sentenceCasedPosition: string;
+ textInputValue: string;
+ valueAsMoment: Moment | null;
+}
+
+export class EuiAbsoluteTab extends Component<
+ EuiAbsoluteTabProps,
+ EuiAbsoluteTabState
+> {
+ state: EuiAbsoluteTabState;
+
+ constructor(props: EuiAbsoluteTabProps) {
super(props);
+ const sentenceCasedPosition = toSentenceCase(props.position);
+
const parsedValue = dateMath.parse(props.value, { roundUp: props.roundUp });
const valueAsMoment =
parsedValue && parsedValue.isValid() ? parsedValue : moment();
- const sentenceCasedPosition = toSentenceCase(props.position);
+
+ const textInputValue = valueAsMoment
+ .locale(this.props.locale || 'en')
+ .format(this.props.dateFormat);
this.state = {
- valueAsMoment,
- textInputValue: valueAsMoment
- .locale(this.props.locale || 'en')
- .format(this.props.dateFormat),
isTextInvalid: false,
sentenceCasedPosition,
+ textInputValue,
+ valueAsMoment,
};
}
- handleChange = date => {
- this.props.onChange(date.toISOString());
+ handleChange: ReactDatePickerProps['onChange'] = (date, event) => {
+ const { onChange } = this.props;
+ if (date === null) {
+ return;
+ }
+ const dateMoment = moment(date);
+ onChange(date, event);
this.setState({
- valueAsMoment: date,
- textInputValue: date.format(this.props.dateFormat),
+ valueAsMoment: dateMoment,
+ textInputValue: dateMoment.format(this.props.dateFormat),
isTextInvalid: false,
});
};
- handleTextChange = evt => {
- const date = moment(evt.target.value, this.props.dateFormat, true);
- const updatedState = {
- textInputValue: evt.target.value,
- isTextInvalid: !date.isValid(),
- };
- if (date.isValid()) {
- this.props.onChange(date.toISOString());
- updatedState.valueAsMoment = date;
+ handleTextChange: ChangeEventHandler = event => {
+ const { onChange } = this.props;
+ const valueAsMoment = moment(
+ event.target.value,
+ this.props.dateFormat,
+ true
+ );
+ const dateIsValid = valueAsMoment.isValid();
+ if (dateIsValid) {
+ onChange(valueAsMoment, event);
}
-
- this.setState(updatedState);
+ this.setState({
+ textInputValue: event.target.value as string,
+ isTextInvalid: !dateIsValid,
+ valueAsMoment: dateIsValid ? valueAsMoment : null,
+ });
};
render() {
@@ -89,13 +123,3 @@ export class EuiAbsoluteTab extends Component {
);
}
}
-
-EuiAbsoluteTab.propTypes = {
- dateFormat: PropTypes.string.isRequired,
- timeFormat: PropTypes.string.isRequired,
- locale: PropTypes.string,
- value: PropTypes.string.isRequired,
- onChange: PropTypes.func.isRequired,
- roundUp: PropTypes.bool.isRequired,
- position: PropTypes.oneOf(['start', 'end']),
-};
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.tsx
similarity index 61%
rename from src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
rename to src/components/date_picker/super_date_picker/date_popover/date_popover_button.tsx
index 74868cb7585..48c9be68407 100644
--- a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.tsx
@@ -1,13 +1,40 @@
-import PropTypes from 'prop-types';
-import React from 'react';
+import React, {
+ FunctionComponent,
+ ButtonHTMLAttributes,
+ MouseEventHandler,
+} from 'react';
import classNames from 'classnames';
-import { EuiPopover } from '../../../popover';
+import { EuiPopover, EuiPopoverProps } from '../../../popover';
import { formatTimeString } from '../pretty_duration';
-import { EuiDatePopoverContent } from './date_popover_content';
+import {
+ EuiDatePopoverContent,
+ EuiDatePopoverContentProps,
+} from './date_popover_content';
+import { LocaleSpecifier } from 'moment'; // eslint-disable-line import/named
-export function EuiDatePopoverButton(props) {
+export interface EuiDatePopoverButtonProps {
+ className?: string;
+ buttonProps?: ButtonHTMLAttributes;
+ dateFormat: string;
+ isDisabled?: boolean;
+ isInvalid?: boolean;
+ isOpen: boolean;
+ needsUpdating?: boolean;
+ locale?: LocaleSpecifier;
+ onChange: NonNullable;
+ onPopoverClose: EuiPopoverProps['closePopover'];
+ onPopoverToggle: MouseEventHandler;
+ position: 'start' | 'end';
+ roundUp?: boolean;
+ timeFormat: string;
+ value: string;
+}
+
+export const EuiDatePopoverButton: FunctionComponent<
+ EuiDatePopoverButtonProps
+> = props => {
const {
position,
isDisabled,
@@ -77,19 +104,6 @@ export function EuiDatePopoverButton(props) {
/>
);
-}
-
-EuiDatePopoverButton.propTypes = {
- position: PropTypes.oneOf(['start', 'end']),
- isInvalid: PropTypes.bool,
- isDisabled: PropTypes.bool,
- needsUpdating: PropTypes.bool,
- value: PropTypes.string.isRequired,
- onChange: PropTypes.func.isRequired,
- dateFormat: PropTypes.string.isRequired,
- timeFormat: PropTypes.string.isRequired,
- roundUp: PropTypes.bool,
- isOpen: PropTypes.bool.isRequired,
- onPopoverToggle: PropTypes.func.isRequired,
- onPopoverClose: PropTypes.func.isRequired,
};
+
+EuiDatePopoverButton.displayName = 'EuiDatePopoverButton';
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js b/src/components/date_picker/super_date_picker/date_popover/date_popover_content.tsx
similarity index 70%
rename from src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
rename to src/components/date_picker/super_date_picker/date_popover/date_popover_content.tsx
index 333bc2071af..1f3786d62b3 100644
--- a/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_content.tsx
@@ -1,7 +1,6 @@
-import PropTypes from 'prop-types';
-import React from 'react';
+import React, { FunctionComponent } from 'react';
-import { EuiTabbedContent } from '../../../tabs';
+import { EuiTabbedContent, EuiTabbedContentProps } from '../../../tabs';
import { EuiText } from '../../../text';
import { EuiButton } from '../../../button';
@@ -14,17 +13,31 @@ import {
toAbsoluteString,
toRelativeString,
} from '../date_modes';
+import { LocaleSpecifier } from 'moment'; // eslint-disable-line import/named
+import { ReactDatePickerProps } from '../../react-datepicker'; // eslint-disable-line import/no-unresolved
-export function EuiDatePopoverContent({
+export interface EuiDatePopoverContentProps {
+ value: string;
+ onChange: NonNullable;
+ roundUp?: boolean;
+ dateFormat: string;
+ timeFormat: string;
+ locale?: LocaleSpecifier;
+ position: 'start' | 'end';
+}
+
+export const EuiDatePopoverContent: FunctionComponent<
+ EuiDatePopoverContentProps
+> = ({
value,
- roundUp,
+ roundUp = false,
onChange,
dateFormat,
timeFormat,
locale,
position,
-}) {
- const onTabClick = selectedTab => {
+}) => {
+ const onTabClick: EuiTabbedContentProps['onTabClick'] = selectedTab => {
switch (selectedTab.id) {
case DATE_MODES.ABSOLUTE:
onChange(toAbsoluteString(value, roundUp));
@@ -85,7 +98,9 @@ export function EuiDatePopoverContent({
onChange('now')}
+ onClick={() => {
+ onChange('now');
+ }}
fullWidth
size="s"
fill>
@@ -98,32 +113,21 @@ export function EuiDatePopoverContent({
},
];
- const initialSelectedTab = () =>
- renderTabs.filter(tabs => tabs.id === getDateMode(value))[0];
+ const initialSelectedTab = renderTabs.find(
+ tab => tab.id === getDateMode(value)
+ );
return (
);
-}
-
-EuiDatePopoverContent.propTypes = {
- value: PropTypes.string.isRequired,
- onChange: PropTypes.func.isRequired,
- roundUp: PropTypes.bool,
- dateFormat: PropTypes.string.isRequired,
- timeFormat: PropTypes.string.isRequired,
- locale: PropTypes.string,
- position: PropTypes.oneOf(['start', 'end']),
};
-EuiDatePopoverContent.defaultProps = {
- roundUp: false,
-};
+EuiDatePopoverContent.displayName = 'EuiDatePopoverContent';
diff --git a/src/components/date_picker/super_date_picker/date_popover/index.ts b/src/components/date_picker/super_date_picker/date_popover/index.ts
new file mode 100644
index 00000000000..4f86a5e3e62
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/date_popover/index.ts
@@ -0,0 +1,10 @@
+export { EuiAbsoluteTab, EuiAbsoluteTabProps } from './absolute_tab';
+export {
+ EuiDatePopoverButton,
+ EuiDatePopoverButtonProps,
+} from './date_popover_button';
+export {
+ EuiDatePopoverContent,
+ EuiDatePopoverContentProps,
+} from './date_popover_content';
+export { EuiRelativeTab, EuiRelativeTabProps } from './relative_tab';
diff --git a/src/components/date_picker/super_date_picker/date_popover/relative_tab.js b/src/components/date_picker/super_date_picker/date_popover/relative_tab.tsx
similarity index 65%
rename from src/components/date_picker/super_date_picker/date_popover/relative_tab.js
rename to src/components/date_picker/super_date_picker/date_popover/relative_tab.tsx
index 2fe03b16a7b..67289d5e525 100644
--- a/src/components/date_picker/super_date_picker/date_popover/relative_tab.js
+++ b/src/components/date_picker/super_date_picker/date_popover/relative_tab.tsx
@@ -1,5 +1,4 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
+import React, { Component, ChangeEventHandler } from 'react';
import dateMath from '@elastic/datemath';
import { toSentenceCase } from '../../../../services/string/to_case';
import { htmlIdGenerator } from '../../../../services';
@@ -12,6 +11,7 @@ import {
EuiFieldText,
EuiSwitch,
EuiFormLabel,
+ EuiSwitchEvent,
} from '../../../form';
import { EuiSpacer } from '../../../spacer';
@@ -23,58 +23,83 @@ import {
} from '../relative_utils';
import { EuiScreenReaderOnly } from '../../../accessibility';
import { EuiI18n } from '../../../i18n';
+import { RelativeParts, TimeUnitId } from '../../types';
+import { LocaleSpecifier } from 'moment'; // eslint-disable-line import/named
+import { ReactDatePickerProps } from '../../react-datepicker'; // eslint-disable-line import/no-unresolved
-export class EuiRelativeTab extends Component {
- constructor(props) {
- super(props);
- const sentenceCasedPosition = toSentenceCase(props.position);
+export interface EuiRelativeTabProps {
+ dateFormat: string;
+ locale?: LocaleSpecifier;
+ value: string;
+ onChange: NonNullable;
+ roundUp?: boolean;
+ position: 'start' | 'end';
+}
- this.state = {
- ...parseRelativeParts(this.props.value),
- sentenceCasedPosition,
- };
- }
+interface EuiRelativeTabState
+ extends Pick {
+ count: number | undefined;
+ sentenceCasedPosition: string;
+}
+
+export class EuiRelativeTab extends Component<
+ EuiRelativeTabProps,
+ EuiRelativeTabState
+> {
+ state: EuiRelativeTabState = {
+ ...parseRelativeParts(this.props.value),
+ sentenceCasedPosition: toSentenceCase(this.props.position),
+ };
generateId = htmlIdGenerator();
- onCountChange = evt => {
- const sanitizedValue = parseInt(evt.target.value, 10);
+ onCountChange: ChangeEventHandler = event => {
+ const sanitizedValue = parseInt(event.target.value, 10);
this.setState(
{
- count: isNaN(sanitizedValue) ? '' : sanitizedValue,
+ count: isNaN(sanitizedValue) ? undefined : sanitizedValue,
},
this.handleChange
);
};
- onUnitChange = evt => {
+ onUnitChange: ChangeEventHandler = event => {
this.setState(
{
- unit: evt.target.value,
+ unit: event.target.value,
},
this.handleChange
);
};
- onRoundChange = evt => {
+ onRoundChange = (event: EuiSwitchEvent) => {
this.setState(
{
- round: evt.target.checked,
+ round: event.target.checked,
},
this.handleChange
);
};
handleChange = () => {
- if (this.state.count === '' || this.state.count < 0) {
+ const { count, round, roundUnit, unit } = this.state;
+ const { onChange } = this.props;
+ if (count === undefined || count < 0) {
return;
}
- this.props.onChange(toRelativeStringFromParts(this.state));
+ const date = toRelativeStringFromParts({
+ count,
+ round,
+ roundUnit,
+ unit,
+ });
+ onChange(date);
};
render() {
+ const { count, unit } = this.state;
const relativeDateInputNumberDescriptionId = this.generateId();
- const isInvalid = this.state.count < 0;
+ const isInvalid = count === undefined || count < 0;
const parsedValue = dateMath.parse(this.props.value, {
roundUp: this.props.roundUp,
});
@@ -94,7 +119,7 @@ export class EuiRelativeTab extends Component {
'euiRelativeTab.numberInputLabel',
]}
defaults={['Must be >= 0', 'Time span amount']}>
- {([numberInputError, numberInputLabel]) => (
+ {([numberInputError, numberInputLabel]: string[]) => (
@@ -103,7 +128,7 @@ export class EuiRelativeTab extends Component {
aria-label={numberInputLabel}
aria-describedby={relativeDateInputNumberDescriptionId}
data-test-subj={'superDatePickerRelativeDateInputNumber'}
- value={this.state.count}
+ value={count}
onChange={this.onCountChange}
isInvalid={isInvalid}
/>
@@ -115,14 +140,14 @@ export class EuiRelativeTab extends Component {
- {unitInputLabel => (
+ {(unitInputLabel: string) => (
@@ -134,8 +159,8 @@ export class EuiRelativeTab extends Component {
- {roundingLabel => (
+ values={{ unit: timeUnits[unit.substring(0, 1) as TimeUnitId] }}>
+ {(roundingLabel: string) => (
}
/>
-
-
+
+
@@ -173,12 +198,3 @@ export class EuiRelativeTab extends Component {
);
}
}
-
-EuiRelativeTab.propTypes = {
- dateFormat: PropTypes.string.isRequired,
- locale: PropTypes.string,
- value: PropTypes.string.isRequired,
- onChange: PropTypes.func.isRequired,
- roundUp: PropTypes.bool,
- position: PropTypes.oneOf(['start', 'end']),
-};
diff --git a/src/components/date_picker/super_date_picker/index.js b/src/components/date_picker/super_date_picker/index.js
deleted file mode 100644
index 978ec874cc6..00000000000
--- a/src/components/date_picker/super_date_picker/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export { EuiSuperDatePicker } from './super_date_picker';
-
-export { EuiSuperUpdateButton } from './super_update_button';
-
-export { prettyDuration, commonDurationRanges } from './pretty_duration';
diff --git a/src/components/date_picker/super_date_picker/index.ts b/src/components/date_picker/super_date_picker/index.ts
new file mode 100644
index 00000000000..b7143ade4e9
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/index.ts
@@ -0,0 +1,15 @@
+export * from './date_popover';
+export * from './quick_select_popover';
+export { AsyncInterval } from './async_interval';
+
+export {
+ EuiSuperDatePicker,
+ EuiSuperDatePickerProps,
+} from './super_date_picker';
+
+export {
+ EuiSuperUpdateButton,
+ EuiSuperUpdateButtonProps,
+} from './super_update_button';
+
+export { prettyDuration, commonDurationRanges } from './pretty_duration';
diff --git a/src/components/date_picker/super_date_picker/pretty_duration.test.js b/src/components/date_picker/super_date_picker/pretty_duration.test.ts
similarity index 100%
rename from src/components/date_picker/super_date_picker/pretty_duration.test.js
rename to src/components/date_picker/super_date_picker/pretty_duration.test.ts
diff --git a/src/components/date_picker/super_date_picker/pretty_duration.js b/src/components/date_picker/super_date_picker/pretty_duration.ts
similarity index 77%
rename from src/components/date_picker/super_date_picker/pretty_duration.js
rename to src/components/date_picker/super_date_picker/pretty_duration.ts
index 21a49ce872f..5f2c208507a 100644
--- a/src/components/date_picker/super_date_picker/pretty_duration.js
+++ b/src/components/date_picker/super_date_picker/pretty_duration.ts
@@ -1,12 +1,13 @@
import dateMath from '@elastic/datemath';
-import moment from 'moment';
+import moment, { LocaleSpecifier } from 'moment'; // eslint-disable-line import/named
import { timeUnits, timeUnitsPlural } from './time_units';
import { getDateMode, DATE_MODES } from './date_modes';
import { parseRelativeParts } from './relative_utils';
+import { DurationRange, TimeUnitId, ShortDate } from '../types';
const ISO_FORMAT = 'YYYY-MM-DDTHH:mm:ss.SSSZ';
-export const commonDurationRanges = [
+export const commonDurationRanges: DurationRange[] = [
{ start: 'now/d', end: 'now/d', label: 'Today' },
{ start: 'now/w', end: 'now/w', label: 'This week' },
{ start: 'now/M', end: 'now/M', label: 'This month' },
@@ -17,13 +18,13 @@ export const commonDurationRanges = [
{ start: 'now/y', end: 'now', label: 'Year to date' },
];
-function cantLookup(timeFrom, timeTo, dateFormat) {
+function cantLookup(timeFrom: string, timeTo: string, dateFormat: string) {
const displayFrom = formatTimeString(timeFrom, dateFormat);
const displayTo = formatTimeString(timeTo, dateFormat, true);
return `${displayFrom} to ${displayTo}`;
}
-function isRelativeToNow(timeFrom, timeTo) {
+function isRelativeToNow(timeFrom: ShortDate, timeTo: ShortDate) {
const fromDateMode = getDateMode(timeFrom);
const toDateMode = getDateMode(timeTo);
const isLast =
@@ -34,10 +35,10 @@ function isRelativeToNow(timeFrom, timeTo) {
}
export function formatTimeString(
- timeString,
- dateFormat,
+ timeString: string,
+ dateFormat: string,
roundUp = false,
- locale = 'en'
+ locale: LocaleSpecifier = 'en'
) {
const timeAsMoment = moment(timeString, ISO_FORMAT, true);
if (timeAsMoment.isValid()) {
@@ -56,7 +57,12 @@ export function formatTimeString(
return timeString;
}
-export function prettyDuration(timeFrom, timeTo, quickRanges = [], dateFormat) {
+export function prettyDuration(
+ timeFrom: ShortDate,
+ timeTo: ShortDate,
+ quickRanges: DurationRange[] = [],
+ dateFormat: string
+) {
const matchingQuickRange = quickRanges.find(
({ start: quickFrom, end: quickTo }) => {
return timeFrom === quickFrom && timeTo === quickTo;
@@ -76,13 +82,13 @@ export function prettyDuration(timeFrom, timeTo, quickRanges = [], dateFormat) {
timeTense = 'Next';
relativeParts = parseRelativeParts(timeTo);
}
- const countTimeUnit = relativeParts.unit.substring(0, 1);
+ const countTimeUnit = relativeParts.unit.substring(0, 1) as TimeUnitId;
const countTimeUnitFullName =
relativeParts.count > 1
? timeUnitsPlural[countTimeUnit]
: timeUnits[countTimeUnit];
let text = `${timeTense} ${relativeParts.count} ${countTimeUnitFullName}`;
- if (relativeParts.round) {
+ if (relativeParts.round && relativeParts.roundUnit) {
text += ` rounded to the ${timeUnits[relativeParts.roundUnit]}`;
}
return text;
@@ -91,7 +97,11 @@ export function prettyDuration(timeFrom, timeTo, quickRanges = [], dateFormat) {
return cantLookup(timeFrom, timeTo, dateFormat);
}
-export function showPrettyDuration(timeFrom, timeTo, quickRanges = []) {
+export function showPrettyDuration(
+ timeFrom: ShortDate,
+ timeTo: ShortDate,
+ quickRanges: DurationRange[] = []
+) {
const matchingQuickRange = quickRanges.find(
({ start: quickFrom, end: quickTo }) => {
return timeFrom === quickFrom && timeTo === quickTo;
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select.test.js.snap b/src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select.test.tsx.snap
similarity index 97%
rename from src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select.test.js.snap
rename to src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select.test.tsx.snap
index 5edeb5a2be3..f8a9171643f 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select.test.js.snap
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select.test.tsx.snap
@@ -106,10 +106,10 @@ exports[`EuiQuickSelect is rendered 1`] = `
-
-
+
+
-
-
+
+
= ({ applyTime, commonlyUsedRanges }) => {
const legendId = generateId();
const links = commonlyUsedRanges.map(({ start, end, label }) => {
const applyCommonlyUsed = () => {
applyTime({ start, end });
};
+ const dataTestSubj = label
+ ? `superDatePickerCommonlyUsed_${label.replace(' ', '_')}`
+ : undefined;
return (
-
+
{label}
@@ -57,9 +61,6 @@ export function EuiCommonlyUsedTimeRanges({ applyTime, commonlyUsedRanges }) {
);
-}
-
-EuiCommonlyUsedTimeRanges.propTypes = {
- applyTime: PropTypes.func.isRequired,
- commonlyUsedRanges: PropTypes.arrayOf(commonlyUsedRangeShape).isRequired,
};
+
+EuiCommonlyUsedTimeRanges.displayName = 'EuiCommonlyUsedTimeRanges';
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/index.ts b/src/components/date_picker/super_date_picker/quick_select_popover/index.ts
new file mode 100644
index 00000000000..d5bacaf9163
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/index.ts
@@ -0,0 +1,14 @@
+export {
+ EuiCommonlyUsedTimeRanges,
+ EuiCommonlyUsedTimeRangesProps,
+} from './commonly_used_time_ranges';
+export {
+ EuiQuickSelectPopover,
+ EuiQuickSelectPopoverProps,
+} from './quick_select_popover';
+export { EuiQuickSelect, EuiQuickSelectProps } from './quick_select';
+export { EuiRecentlyUsed, EuiRecentlyUsedProps } from './recently_used';
+export {
+ EuiRefreshInterval,
+ EuiRefreshIntervalProps,
+} from './refresh_interval';
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.test.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.test.tsx
similarity index 100%
rename from src/components/date_picker/super_date_picker/quick_select_popover/quick_select.test.js
rename to src/components/date_picker/super_date_picker/quick_select_popover/quick_select.test.tsx
index f5b950bbee8..9c319f06ebf 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.test.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.test.tsx
@@ -6,8 +6,8 @@ import { EuiQuickSelect } from './quick_select';
const noop = () => {};
const defaultProps = {
applyTime: noop,
- start: 'now-15m',
end: 'now',
+ start: 'now-15m',
};
// Mock the htmlIdGenerator to generate predictable ids for snapshot tests
@@ -28,8 +28,8 @@ describe('EuiQuickSelect', () => {
{...defaultProps}
prevQuickSelect={{
timeTense: 'Next',
- timeValue: 32,
timeUnits: 'M',
+ timeValue: 32,
}}
/>
);
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.tsx
similarity index 75%
rename from src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
rename to src/components/date_picker/super_date_picker/quick_select_popover/quick_select.tsx
index 5e7de8ff3f5..f792c027c69 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.tsx
@@ -1,5 +1,8 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
+import React, {
+ Component,
+ ChangeEventHandler,
+ KeyboardEventHandler,
+} from 'react';
import moment from 'moment';
import dateMath from '@elastic/datemath';
import { htmlIdGenerator } from '../../../../services';
@@ -12,7 +15,8 @@ import { EuiHorizontalRule } from '../../../horizontal_rule';
import { EuiI18n } from '../../../i18n';
import { timeUnits } from '../time_units';
import { EuiScreenReaderOnly } from '../../../accessibility';
-import { parseTimeParts } from './quick_select_utils';
+import { ApplyTime, QuickSelect, TimeUnitId } from '../../types';
+import { keysOf } from '../../../common';
const LAST = 'last';
const NEXT = 'next';
@@ -21,50 +25,73 @@ const timeTenseOptions = [
{ value: LAST, text: 'Last' },
{ value: NEXT, text: 'Next' },
];
-const timeUnitsOptions = Object.keys(timeUnits).map(key => {
+const timeUnitsOptions = keysOf(timeUnits).map(key => {
return { value: key, text: `${timeUnits[key]}s` };
});
-export class EuiQuickSelect extends Component {
- constructor(props) {
- super(props);
+const defaultQuickSelect: QuickSelect = {
+ timeTense: LAST,
+ timeValue: 15,
+ timeUnits: 'm',
+};
- const { timeTense, timeValue, timeUnits } = this.props.prevQuickSelect;
- const {
- timeTenseDefault,
- timeValueDefault,
- timeUnitsDefault,
- } = parseTimeParts(this.props.start, this.props.end);
- this.state = {
- timeTense: timeTense ? timeTense : timeTenseDefault,
- timeValue: timeValue ? timeValue : timeValueDefault,
- timeUnits: timeUnits ? timeUnits : timeUnitsDefault,
- };
- }
+type EuiQuickSelectState = QuickSelect;
+
+export interface EuiQuickSelectProps {
+ applyTime: ApplyTime;
+ start: string;
+ end: string;
+ prevQuickSelect: EuiQuickSelectState;
+}
+
+export class EuiQuickSelect extends Component<
+ EuiQuickSelectProps,
+ EuiQuickSelectState
+> {
+ static defaultProps = {
+ prevQuickSelect: defaultQuickSelect,
+ };
+
+ state: EuiQuickSelectState = {
+ timeTense:
+ this.props.prevQuickSelect && this.props.prevQuickSelect.timeTense
+ ? this.props.prevQuickSelect.timeTense
+ : defaultQuickSelect.timeTense,
+ timeValue:
+ this.props.prevQuickSelect && this.props.prevQuickSelect.timeValue
+ ? this.props.prevQuickSelect.timeValue
+ : defaultQuickSelect.timeValue,
+ timeUnits:
+ this.props.prevQuickSelect && this.props.prevQuickSelect.timeUnits
+ ? this.props.prevQuickSelect.timeUnits
+ : defaultQuickSelect.timeUnits,
+ };
generateId = htmlIdGenerator();
- onTimeTenseChange = evt => {
+ onTimeTenseChange: ChangeEventHandler = event => {
this.setState({
- timeTense: evt.target.value,
+ timeTense: event.target.value,
});
};
- onTimeValueChange = evt => {
- const sanitizedValue = parseInt(evt.target.value, 10);
+ onTimeValueChange: ChangeEventHandler = event => {
+ const sanitizedValue = parseInt(event.target.value, 10);
this.setState({
- timeValue: isNaN(sanitizedValue) ? '' : sanitizedValue,
+ timeValue: isNaN(sanitizedValue) ? 0 : sanitizedValue,
});
};
- onTimeUnitsChange = evt => {
+ onTimeUnitsChange: ChangeEventHandler = event => {
this.setState({
- timeUnits: evt.target.value,
+ timeUnits: event.target.value as TimeUnitId,
});
};
- handleKeyDown = ({ key }) => {
- if (key === 'Enter') this.applyQuickSelect();
+ handleKeyDown: KeyboardEventHandler = ({ key }) => {
+ if (key === 'Enter') {
+ this.applyQuickSelect();
+ }
};
applyQuickSelect = () => {
@@ -130,13 +157,17 @@ export class EuiQuickSelect extends Component {
const { timeTense, timeValue, timeUnits } = this.state;
const timeSelectionId = this.generateId();
const legendId = this.generateId();
+ const matchedTimeUnit = timeUnitsOptions.find(
+ ({ value }) => value === timeUnits
+ );
+ const timeUnit = matchedTimeUnit ? matchedTimeUnit.text : '';
return (
-
-
+
+
option.value === timeUnits
- ).text,
+ timeUnit,
}}
/>
@@ -274,14 +303,3 @@ export class EuiQuickSelect extends Component {
);
}
}
-
-EuiQuickSelect.propTypes = {
- applyTime: PropTypes.func.isRequired,
- start: PropTypes.string.isRequired,
- end: PropTypes.string.isRequired,
- prevQuickSelect: PropTypes.object,
-};
-
-EuiQuickSelect.defaultProps = {
- prevQuickSelect: {},
-};
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.test.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.test.tsx
similarity index 85%
rename from src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.test.js
rename to src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.test.tsx
index 20a5f4952f2..dd0275db6d0 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.test.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.test.tsx
@@ -1,11 +1,14 @@
import React from 'react';
import { shallow } from 'enzyme';
-import { EuiQuickSelectPopover } from './quick_select_popover';
+import {
+ EuiQuickSelectPopover,
+ EuiQuickSelectPopoverProps,
+} from './quick_select_popover';
const noop = () => {};
-const defaultProps = {
+const defaultProps: EuiQuickSelectPopoverProps = {
applyTime: noop,
applyRefreshInterval: noop,
start: 'now-15m',
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.tsx
similarity index 59%
rename from src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
rename to src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.tsx
index 1b26436902f..080c0000497 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.tsx
@@ -1,10 +1,4 @@
-import PropTypes from 'prop-types';
import React, { Component, Fragment } from 'react';
-import {
- commonlyUsedRangeShape,
- recentlyUsedRangeShape,
- quickSelectPanelShape,
-} from '../types';
import { EuiButtonEmpty } from '../../../button';
import { EuiIcon } from '../../../icon';
@@ -18,9 +12,39 @@ import { EuiQuickSelect } from './quick_select';
import { EuiCommonlyUsedTimeRanges } from './commonly_used_time_ranges';
import { EuiRecentlyUsed } from './recently_used';
import { EuiRefreshInterval } from './refresh_interval';
+import {
+ DurationRange,
+ ApplyRefreshInterval,
+ ApplyTime,
+ QuickSelect,
+ QuickSelectPanel,
+} from '../../types';
+
+export interface EuiQuickSelectPopoverProps {
+ applyRefreshInterval?: ApplyRefreshInterval;
+ applyTime: ApplyTime;
+ commonlyUsedRanges: DurationRange[];
+ customQuickSelectPanels?: QuickSelectPanel[];
+ dateFormat: string;
+ end: string;
+ isAutoRefreshOnly: boolean;
+ isDisabled: boolean;
+ isPaused: boolean;
+ recentlyUsedRanges: DurationRange[];
+ refreshInterval: number;
+ start: string;
+}
+
+interface EuiQuickSelectPopoverState {
+ isOpen: boolean;
+ prevQuickSelect?: QuickSelect;
+}
-export class EuiQuickSelectPopover extends Component {
- state = {
+export class EuiQuickSelectPopover extends Component<
+ EuiQuickSelectPopoverProps,
+ EuiQuickSelectPopoverState
+> {
+ state: EuiQuickSelectPopoverState = {
isOpen: false,
};
@@ -34,7 +58,12 @@ export class EuiQuickSelectPopover extends Component {
}));
};
- applyTime = ({ start, end, quickSelect, keepPopoverOpen = false }) => {
+ applyTime: ApplyTime = ({
+ start,
+ end,
+ quickSelect,
+ keepPopoverOpen = false,
+ }) => {
this.props.applyTime({
start,
end,
@@ -48,7 +77,17 @@ export class EuiQuickSelectPopover extends Component {
};
renderDateTimeSections = () => {
- if (this.props.isAutoRefreshOnly) {
+ const {
+ commonlyUsedRanges,
+ dateFormat,
+ end,
+ isAutoRefreshOnly,
+ recentlyUsedRanges,
+ start,
+ } = this.props;
+ const { prevQuickSelect } = this.state;
+
+ if (isAutoRefreshOnly) {
return null;
}
@@ -56,19 +95,19 @@ export class EuiQuickSelectPopover extends Component {
{this.renderCustomQuickSelectPanels()}
@@ -76,11 +115,12 @@ export class EuiQuickSelectPopover extends Component {
};
renderCustomQuickSelectPanels = () => {
- if (!this.props.customQuickSelectPanels) {
+ const { customQuickSelectPanels } = this.props;
+ if (!customQuickSelectPanels) {
return null;
}
- return this.props.customQuickSelectPanels.map(({ title, content }) => {
+ return customQuickSelectPanels.map(({ title, content }) => {
return (
@@ -97,6 +137,15 @@ export class EuiQuickSelectPopover extends Component {
};
render() {
+ const {
+ applyRefreshInterval,
+ isAutoRefreshOnly,
+ isDisabled,
+ isPaused,
+ refreshInterval,
+ } = this.props;
+ const { isOpen } = this.state;
+
const quickSelectButton = (
-
+
);
@@ -122,7 +165,7 @@ export class EuiQuickSelectPopover extends Component {
{this.renderDateTimeSections()}
);
}
}
-
-EuiQuickSelectPopover.propTypes = {
- applyTime: PropTypes.func.isRequired,
- start: PropTypes.string.isRequired,
- end: PropTypes.string.isRequired,
- applyRefreshInterval: PropTypes.func,
- isDisabled: PropTypes.bool.isRequired,
- isPaused: PropTypes.bool.isRequired,
- refreshInterval: PropTypes.number.isRequired,
- commonlyUsedRanges: PropTypes.arrayOf(commonlyUsedRangeShape).isRequired,
- dateFormat: PropTypes.string.isRequired,
- recentlyUsedRanges: PropTypes.arrayOf(recentlyUsedRangeShape).isRequired,
- isAutoRefreshOnly: PropTypes.bool.isRequired,
- customQuickSelectPanels: PropTypes.arrayOf(quickSelectPanelShape),
-};
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_utils.test.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_utils.test.ts
similarity index 71%
rename from src/components/date_picker/super_date_picker/quick_select_popover/quick_select_utils.test.js
rename to src/components/date_picker/super_date_picker/quick_select_popover/quick_select_utils.test.ts
index 1a104afd8ef..c4990762cf9 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_utils.test.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_utils.test.ts
@@ -5,27 +5,27 @@ describe('parseTimeParts', () => {
it('should parse now', () => {
const out = parseTimeParts('now', 'now+5m');
expect(out).toEqual({
- timeValueDefault: 5,
- timeUnitsDefault: 'm',
- timeTenseDefault: 'next',
+ timeTense: 'next',
+ timeUnits: 'm',
+ timeValue: 5,
});
});
it('should parse now-2h', () => {
const out = parseTimeParts('now-2h', 'now+5m');
expect(out).toEqual({
- timeValueDefault: 2,
- timeUnitsDefault: 'h',
- timeTenseDefault: 'last',
+ timeTense: 'last',
+ timeUnits: 'h',
+ timeValue: 2,
});
});
it('should parse now+2h', () => {
const out = parseTimeParts('now+2h', 'now+5m');
expect(out).toEqual({
- timeValueDefault: 2,
- timeUnitsDefault: 'h',
- timeTenseDefault: 'next',
+ timeTense: 'next',
+ timeUnits: 'h',
+ timeValue: 2,
});
});
@@ -42,9 +42,9 @@ describe('parseTimeParts', () => {
it('should parse now/d', () => {
const out = parseTimeParts('now/d', 'now+5m');
expect(out).toEqual({
- timeValueDefault: 6,
- timeUnitsDefault: 'h',
- timeTenseDefault: 'last',
+ timeTense: 'last',
+ timeUnits: 'h',
+ timeValue: 6,
});
});
});
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_utils.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_utils.ts
similarity index 52%
rename from src/components/date_picker/super_date_picker/quick_select_popover/quick_select_utils.js
rename to src/components/date_picker/super_date_picker/quick_select_popover/quick_select_utils.ts
index 8b88f7ebb62..db44c410ae3 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_utils.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_utils.ts
@@ -1,34 +1,31 @@
-/**
- * This function returns time value, time unit and time tense for a given time string.
- * For example: for `now-40m` it will parse output as time value to `40`
- * time unit to `m` and time unit to `last`.
- * If given a datetime string it will return a default value.
- * If the given string is in the format such as `now/d` it will parse the string to moment object
- * and find the time value, time unit and time tense using moment
- * This function accepts two strings start and end time. I the start value is now then it uses
- * the end value to parse.
- *
- * @param {string} start start time
- * @param {string} start end time
- * @returns {object} time value, time unit and time tense
- */
-
import moment from 'moment';
import dateMath from '@elastic/datemath';
import { isString } from '../../../../services/predicate';
import { relativeUnitsFromLargestToSmallest } from '../relative_options';
import { DATE_MODES } from '../date_modes';
+import { QuickSelect, TimeUnitId } from '../../types';
const LAST = 'last';
const NEXT = 'next';
-const isNow = value => value === DATE_MODES.NOW;
+const isNow = (value: string) => value === DATE_MODES.NOW;
-export const parseTimeParts = (start, end) => {
- const results = {
- timeValueDefault: 15,
- timeUnitsDefault: 'm',
- timeTenseDefault: LAST,
+/**
+ * This function returns time value, time unit and time tense for a given time string.
+ *
+ * For example: for `now-40m` it will parse output as time value to `40` time unit to `m` and time unit to `last`.
+ *
+ * If given a datetime string it will return a default value.
+ *
+ * If the given string is in the format such as `now/d` it will parse the string to moment object and find the time value, time unit and time tense using moment
+ *
+ * This function accepts two strings start and end time. I the start value is now then it uses the end value to parse.
+ */
+export const parseTimeParts = (start: string, end: string): QuickSelect => {
+ const results: QuickSelect = {
+ timeTense: LAST,
+ timeUnits: 'm',
+ timeValue: 15,
};
const value = isNow(start) ? end : start;
@@ -42,17 +39,14 @@ export const parseTimeParts = (start, end) => {
}
const operator = matches[2];
- const timeValue = matches[3];
- const timeUnitsDefault = matches[4];
-
- if (timeValue && timeUnitsDefault && operator) {
- const timeValueDefault = parseInt(timeValue, 10);
- const timeTenseDefault = operator === '+' ? NEXT : LAST;
+ const matchedTimeValue = matches[3];
+ const timeUnits = matches[4] as TimeUnitId;
+ if (matchedTimeValue && timeUnits && operator) {
return {
- timeValueDefault,
- timeUnitsDefault,
- timeTenseDefault,
+ timeTense: operator === '+' ? NEXT : LAST,
+ timeUnits,
+ timeValue: parseInt(matchedTimeValue, 10),
};
}
@@ -60,13 +54,17 @@ export const parseTimeParts = (start, end) => {
let unitOp = '';
for (let i = 0; i < relativeUnitsFromLargestToSmallest.length; i++) {
const as = duration.as(relativeUnitsFromLargestToSmallest[i]);
- if (as < 0) unitOp = '+';
+ if (as < 0) {
+ unitOp = '+';
+ }
if (Math.abs(as) > 1) {
- results.timeValueDefault = Math.round(Math.abs(as));
- results.timeUnitsDefault = relativeUnitsFromLargestToSmallest[i];
- results.timeTenseDefault = unitOp === '+' ? NEXT : LAST;
- break;
+ return {
+ timeValue: Math.round(Math.abs(as)),
+ timeUnits: relativeUnitsFromLargestToSmallest[i],
+ timeTense: unitOp === '+' ? NEXT : LAST,
+ };
}
}
+
return results;
};
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/recently_used.js b/src/components/date_picker/super_date_picker/quick_select_popover/recently_used.tsx
similarity index 70%
rename from src/components/date_picker/super_date_picker/quick_select_popover/recently_used.js
rename to src/components/date_picker/super_date_picker/quick_select_popover/recently_used.tsx
index b949f596bf0..397bd564678 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/recently_used.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/recently_used.tsx
@@ -1,6 +1,4 @@
-import PropTypes from 'prop-types';
-import React, { Fragment } from 'react';
-import { commonlyUsedRangeShape, recentlyUsedRangeShape } from '../types';
+import React, { Fragment, FunctionComponent } from 'react';
import { prettyDuration } from '../pretty_duration';
import { EuiFlexGroup, EuiFlexItem } from '../../../flex';
@@ -9,13 +7,21 @@ import { EuiSpacer } from '../../../spacer';
import { EuiLink } from '../../../link';
import { EuiText } from '../../../text';
import { EuiHorizontalRule } from '../../../horizontal_rule';
+import { DurationRange, ApplyTime } from '../../types';
-export function EuiRecentlyUsed({
+export interface EuiRecentlyUsedProps {
+ applyTime: ApplyTime;
+ commonlyUsedRanges: DurationRange[];
+ dateFormat: string;
+ recentlyUsedRanges?: DurationRange[];
+}
+
+export const EuiRecentlyUsed: FunctionComponent = ({
applyTime,
commonlyUsedRanges,
dateFormat,
- recentlyUsedRanges,
-}) {
+ recentlyUsedRanges = [],
+}) => {
if (recentlyUsedRanges.length === 0) {
return null;
}
@@ -47,15 +53,6 @@ export function EuiRecentlyUsed({
);
-}
-
-EuiRecentlyUsed.propTypes = {
- applyTime: PropTypes.func.isRequired,
- commonlyUsedRanges: PropTypes.arrayOf(commonlyUsedRangeShape).isRequired,
- dateFormat: PropTypes.string.isRequired,
- recentlyUsedRanges: PropTypes.arrayOf(recentlyUsedRangeShape),
};
-EuiRecentlyUsed.defaultProps = {
- recentlyUsedRanges: [],
-};
+EuiRecentlyUsed.displayName = 'EuiRecentlyUsed';
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js b/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.tsx
similarity index 62%
rename from src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js
rename to src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.tsx
index 0ddabdf1f66..b25617a684c 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.tsx
@@ -1,5 +1,8 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
+import React, {
+ Component,
+ ChangeEventHandler,
+ KeyboardEventHandler,
+} from 'react';
import { timeUnits, timeUnitsPlural } from '../time_units';
import { EuiI18n } from '../../../i18n';
import { EuiFlexGroup, EuiFlexItem } from '../../../flex';
@@ -9,23 +12,24 @@ import { EuiSelect, EuiFieldNumber } from '../../../form';
import { EuiButton } from '../../../button';
import { htmlIdGenerator } from '../../../../services';
import { EuiScreenReaderOnly } from '../../../accessibility';
-
-const refreshUnitsOptions = Object.keys(timeUnits)
- .filter(timeUnit => {
- return timeUnit === 'h' || timeUnit === 'm' || timeUnit === 's';
- })
- .map(timeUnit => {
- return { value: timeUnit, text: timeUnitsPlural[timeUnit] };
- });
+import {
+ Milliseconds,
+ TimeUnitId,
+ RelativeOption,
+ ApplyRefreshInterval,
+} from '../../types';
+import { keysOf } from '../../../common';
+
+const refreshUnitsOptions: RelativeOption[] = keysOf(timeUnits)
+ .filter(timeUnit => timeUnit === 'h' || timeUnit === 'm' || timeUnit === 's')
+ .map(timeUnit => ({ value: timeUnit, text: timeUnitsPlural[timeUnit] }));
const MILLISECONDS_IN_SECOND = 1000;
const MILLISECONDS_IN_MINUTE = MILLISECONDS_IN_SECOND * 60;
const MILLISECONDS_IN_HOUR = MILLISECONDS_IN_MINUTE * 60;
-function fromMilliseconds(milliseconds) {
- function round(value) {
- return parseFloat(value.toFixed(2));
- }
+function fromMilliseconds(milliseconds: Milliseconds): EuiRefreshIntervalState {
+ const round = (value: number) => parseFloat(value.toFixed(2));
if (milliseconds > MILLISECONDS_IN_HOUR) {
return {
units: 'h',
@@ -46,7 +50,7 @@ function fromMilliseconds(milliseconds) {
};
}
-function toMilliseconds(units, value) {
+function toMilliseconds(units: TimeUnitId, value: Milliseconds) {
switch (units) {
case 'h':
return Math.round(value * MILLISECONDS_IN_HOUR);
@@ -58,21 +62,27 @@ function toMilliseconds(units, value) {
}
}
-export class EuiRefreshInterval extends Component {
- constructor(props) {
- super(props);
+export interface EuiRefreshIntervalProps {
+ applyRefreshInterval?: ApplyRefreshInterval;
+ isPaused: boolean;
+ refreshInterval: Milliseconds;
+}
- const { value, units } = fromMilliseconds(props.refreshInterval);
- this.state = {
- value,
- units,
- };
- }
+interface EuiRefreshIntervalState {
+ value: number | '';
+ units: TimeUnitId;
+}
+
+export class EuiRefreshInterval extends Component<
+ EuiRefreshIntervalProps,
+ EuiRefreshIntervalState
+> {
+ state: EuiRefreshIntervalState = fromMilliseconds(this.props.refreshInterval);
generateId = htmlIdGenerator();
- onValueChange = evt => {
- const sanitizedValue = parseFloat(evt.target.value);
+ onValueChange: ChangeEventHandler = event => {
+ const sanitizedValue = parseFloat(event.target.value);
this.setState(
{
value: isNaN(sanitizedValue) ? '' : sanitizedValue,
@@ -81,64 +91,77 @@ export class EuiRefreshInterval extends Component {
);
};
- onUnitsChange = evt => {
+ onUnitsChange: ChangeEventHandler = event => {
this.setState(
{
- units: evt.target.value,
+ units: event.target.value as TimeUnitId,
},
this.applyRefreshInterval
);
};
startRefresh = () => {
+ const { applyRefreshInterval } = this.props;
const { value, units } = this.state;
- const isValid = value !== '' && value > 0;
- if (isValid) {
- this.props.applyRefreshInterval({
+
+ if (value !== '' && value > 0 && applyRefreshInterval !== undefined) {
+ applyRefreshInterval({
refreshInterval: toMilliseconds(units, value),
isPaused: false,
});
}
};
- handleKeyDown = ({ key }) => {
+ handleKeyDown: KeyboardEventHandler = ({ key }) => {
if (key === 'Enter') {
this.startRefresh();
}
};
applyRefreshInterval = () => {
- if (this.state.value === '') {
+ const { applyRefreshInterval, isPaused } = this.props;
+ const { units, value } = this.state;
+ if (value === '') {
+ return;
+ }
+ if (!applyRefreshInterval) {
return;
}
- const valueInMilliSeconds = toMilliseconds(
- this.state.units,
- this.state.value
- );
+ const refreshInterval = toMilliseconds(units, value);
- this.props.applyRefreshInterval({
- refreshInterval: valueInMilliSeconds,
- isPaused: valueInMilliSeconds <= 0 ? true : this.props.isPaused,
+ applyRefreshInterval({
+ refreshInterval,
+ isPaused: refreshInterval <= 0 ? true : isPaused,
});
};
toggleRefresh = () => {
- this.props.applyRefreshInterval({
- refreshInterval: toMilliseconds(this.state.units, this.state.value),
- isPaused: !this.props.isPaused,
+ const { applyRefreshInterval, isPaused } = this.props;
+ const { units, value } = this.state;
+
+ if (!applyRefreshInterval || value === '') {
+ return;
+ }
+ applyRefreshInterval({
+ refreshInterval: toMilliseconds(units, value),
+ isPaused: !isPaused,
});
};
render() {
+ const { applyRefreshInterval, isPaused } = this.props;
+ const { value, units } = this.state;
const legendId = this.generateId();
const refreshSelectionId = this.generateId();
- const { value, units } = this.state;
- if (!this.props.applyRefreshInterval) {
+ if (!applyRefreshInterval) {
return null;
}
+ const options = refreshUnitsOptions.find(({ value }) => value === units);
+ const optionText = options ? options.text : '';
+
return (