From 15cba559b97e3e2bd756645d06d6b188b8c0979e Mon Sep 17 00:00:00 2001
From: Dimitri Mitropoulos
Date: Thu, 20 Feb 2020 21:10:54 -0500
Subject: [PATCH] converts all DatePicker family of components to TypeScript
---
...te_picker.test.js => date_picker.test.tsx} | 0
.../{date_picker.js => date_picker.tsx} | 225 +++++--------
...nge.test.js => date_picker_range.test.tsx} | 0
..._picker_range.js => date_picker_range.tsx} | 66 ++--
src/components/date_picker/index.d.ts | 104 ------
src/components/date_picker/index.js | 10 -
src/components/date_picker/index.ts | 25 ++
.../date_picker/react-datepicker.d.ts | 75 ++++-
.../super_date_picker/async_interval.js | 22 --
...nterval.test.js => async_interval.test.ts} | 13 +-
.../super_date_picker/async_interval.ts | 25 ++
.../{date_modes.js => date_modes.ts} | 18 +-
.../date_popover/absolute_tab.js | 101 ------
.../date_popover/absolute_tab.tsx | 125 +++++++
...over_button.js => date_popover_button.tsx} | 48 +--
...er_content.js => date_popover_content.tsx} | 47 +--
.../super_date_picker/date_popover/index.ts | 10 +
.../{relative_tab.js => relative_tab.tsx} | 105 +++---
.../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} | 34 +-
...anges.js => commonly_used_time_ranges.tsx} | 32 +-
.../quick_select_popover/index.ts | 14 +
...k_select.test.js => quick_select.test.tsx} | 0
.../{quick_select.js => quick_select.tsx} | 99 +++---
....test.js => quick_select_popover.test.tsx} | 7 +-
...ct_popover.js => quick_select_popover.tsx} | 62 ++--
.../{recently_used.js => recently_used.tsx} | 29 +-
...fresh_interval.js => refresh_interval.tsx} | 123 +++----
.../super_date_picker/relative_options.ts | 13 +-
...e_utils.test.js => relative_utils.test.ts} | 0
.../{relative_utils.js => relative_utils.ts} | 21 +-
...ker.test.js => super_date_picker.test.tsx} | 0
...r_date_picker.js => super_date_picker.tsx} | 315 ++++++++++--------
...n.test.js => super_update_button.test.tsx} | 0
...date_button.js => super_update_button.tsx} | 39 ++-
.../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 | 70 ++++
src/components/index.d.ts | 1 -
42 files changed, 1060 insertions(+), 895 deletions(-)
rename src/components/date_picker/{date_picker.test.js => date_picker.test.tsx} (100%)
rename src/components/date_picker/{date_picker.js => date_picker.tsx} (69%)
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} (72%)
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
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} (91%)
create mode 100644 src/components/date_picker/super_date_picker/async_interval.ts
rename src/components/date_picker/super_date_picker/{date_modes.js => date_modes.ts} (60%)
delete mode 100644 src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
create mode 100644 src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx
rename src/components/date_picker/super_date_picker/date_popover/{date_popover_button.js => date_popover_button.tsx} (63%)
rename src/components/date_picker/super_date_picker/date_popover/{date_popover_content.js => date_popover_content.tsx} (74%)
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} (62%)
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} (75%)
rename src/components/date_picker/super_date_picker/quick_select_popover/{commonly_used_time_ranges.js => commonly_used_time_ranges.tsx} (69%)
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} (77%)
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} (80%)
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} (59%)
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} (74%)
rename src/components/date_picker/super_date_picker/{super_date_picker.test.js => super_date_picker.test.tsx} (100%)
rename src/components/date_picker/super_date_picker/{super_date_picker.js => super_date_picker.tsx} (66%)
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} (79%)
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/src/components/date_picker/date_picker.test.js b/src/components/date_picker/date_picker.test.tsx
similarity index 100%
rename from src/components/date_picker/date_picker.test.js
rename to src/components/date_picker/date_picker.test.tsx
diff --git a/src/components/date_picker/date_picker.js b/src/components/date_picker/date_picker.tsx
similarity index 69%
rename from src/components/date_picker/date_picker.js
rename to src/components/date_picker/date_picker.tsx
index 6d97c77acf55..b2fb9843da0b 100644
--- a/src/components/date_picker/date_picker.js
+++ b/src/components/date_picker/date_picker.tsx
@@ -1,8 +1,7 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
+import React, { Component, MouseEventHandler } from 'react';
import classNames from 'classnames';
-import moment from 'moment';
+import { Moment } from 'moment'; // eslint-disable-line import/named
import { ReactDatePicker as DatePicker } from '../../../packages';
import { EuiFormControlLayout } from '../form/form_control_layout';
@@ -12,11 +11,86 @@ import { EuiValidatableControl } from '../form/validatable_control';
import { EuiErrorBoundary } from '../error_boundary';
import { EuiI18nConsumer } from '../context';
+import { CommonProps } from '../common';
+
+import ReactDatePicker, { ReactDatePickerProps } from './react-datepicker'; // eslint-disable-line import/no-unresolved
+import { EuiFormControlLayoutIconsProps } from '../form/form_control_layout/form_control_layout_icons';
export const euiDatePickerDefaultDateFormat = 'MM/DD/YYYY';
export const euiDatePickerDefaultTimeFormat = 'hh:mm A';
-export class EuiDatePicker extends Component {
+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;
+
+ /**
+ * Adds additional times to the time selector other then :30 increments
+ */
+ injectTimes?: Moment[]; // added here because the type is missing in @types/react-datepicker@1.8.0
+
+ /**
+ * Applies ref to the input
+ */
+ inputRef?: React.Ref;
+
+ /**
+ * 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 {
+ defaultProps = {
+ adjustDateOnChange: true,
+ dateFormat: euiDatePickerDefaultDateFormat,
+ fullWidth: false,
+ isLoading: false,
+ shadow: true,
+ shouldCloseOnSelect: true,
+ showIcon: true,
+ showTimeSelect: false,
+ timeFormat: euiDatePickerDefaultTimeFormat,
+ };
+
render() {
const {
adjustDateOnChange,
@@ -27,7 +101,7 @@ export class EuiDatePicker extends Component {
dayClassName,
disabled,
excludeDates,
- filterDates,
+ filterDate,
fullWidth,
injectTimes,
inline,
@@ -72,9 +146,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 +204,7 @@ export class EuiDatePicker extends Component {
@@ -145,7 +219,7 @@ export class EuiDatePicker extends Component {
dayClassName={dayClassName}
disabled={disabled}
excludeDates={excludeDates}
- filterDates={filterDates}
+ filterDate={filterDate}
injectTimes={injectTimes}
inline={inline}
locale={locale || contextLocale}
@@ -180,136 +254,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 72%
rename from src/components/date_picker/date_picker_range.js
rename to src/components/date_picker/date_picker_range.tsx
index ac8997fb7220..9a45ad1f78f8 100644
--- a/src/components/date_picker/date_picker_range.js
+++ b/src/components/date_picker/date_picker_range.tsx
@@ -1,16 +1,41 @@
-import React, { cloneElement, Fragment } from 'react';
-import PropTypes from 'prop-types';
+import React, { cloneElement, Fragment, FC, 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 & {
+ /**
+ * The end date `EuiDatePicker` element
+ */
+ endDateControl: ReactElement;
+ 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: ReactElement;
+};
+
+export const EuiDatePickerRange: FC = ({
children,
className,
startDateControl,
endDateControl,
- iconType,
+ iconType = true,
fullWidth,
isCustom,
readOnly,
@@ -75,34 +100,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 ff810cec0beb..000000000000
--- 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 69a0ec433e7d..000000000000
--- 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 000000000000..dae3008b8aec
--- /dev/null
+++ b/src/components/date_picker/index.ts
@@ -0,0 +1,25 @@
+export * from './super_date_picker';
+
+export { EuiDatePicker, EuiDatePickerProps } from './date_picker';
+
+export {
+ EuiDatePickerRange,
+ EuiDatePickerRangeProps,
+} from './date_picker_range';
+
+export {
+ DurationRange,
+ TimeUnitId,
+ TimeUnitFromNowId,
+ TimeUnitLabel,
+ TimeUnitLabelPlural,
+ AbsoluteDateMode,
+ RelativeDateMode,
+ NowDateMode,
+ DateMode,
+ ShortDate,
+ RelativeParts,
+ RelativeOption,
+ QuickSelect,
+ QuickSelectPanel,
+} from './types';
diff --git a/src/components/date_picker/react-datepicker.d.ts b/src/components/date_picker/react-datepicker.d.ts
index 81f19ce3cb1a..d8afa119ef99 100644
--- a/src/components/date_picker/react-datepicker.d.ts
+++ b/src/components/date_picker/react-datepicker.d.ts
@@ -15,15 +15,34 @@ 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;
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;
@@ -43,17 +62,41 @@ export interface ReactDatePickerProps {
includeTimes?: moment.Moment[];
inline?: boolean;
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 +116,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 +128,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 +159,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/async_interval.js b/src/components/date_picker/super_date_picker/async_interval.js
deleted file mode 100644
index 952add571ab7..000000000000
--- a/src/components/date_picker/super_date_picker/async_interval.js
+++ /dev/null
@@ -1,22 +0,0 @@
-export class AsyncInterval {
- timeoutId = null;
- isStopped = false;
-
- constructor(fn, refreshInterval) {
- this.setAsyncInterval(fn, refreshInterval);
- }
-
- setAsyncInterval = (fn, ms) => {
- 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 91%
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 327267a61389..ab377540ab38 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
@@ -14,9 +14,12 @@ 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 = times(Math.floor(ms / 100));
- const remainder = ms % 100;
+ async function andvanceTimerAndAwaitFn(
+ instance: AsyncInterval,
+ milliseconds: number
+ ) {
+ const iterations = times(Math.floor(milliseconds / 100));
+ const remainder = milliseconds % 100;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const item of iterations) {
await instance.__pendingFn;
@@ -28,7 +31,7 @@ describe('AsyncInterval', () => {
}
describe('when creating a 1000ms interval', async () => {
- let instance;
+ let instance: AsyncInterval;
let spy;
beforeEach(() => {
spy = jest.fn();
@@ -65,7 +68,7 @@ describe('AsyncInterval', () => {
});
describe('when creating a 1000ms interval that calls a fn that takes 2000ms to complete', async () => {
- let instance;
+ let instance: AsyncInterval;
let spy;
beforeEach(() => {
spy = jest.fn(async () => await sleep(2000));
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 000000000000..00a3f78d1d7c
--- /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.js b/src/components/date_picker/super_date_picker/date_modes.ts
similarity index 60%
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 16f9924bf0a5..c8a1a1ba5e94 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) {
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.js
deleted file mode 100644
index ee106752024c..000000000000
--- a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
+++ /dev/null
@@ -1,101 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-
-import moment from 'moment';
-
-import dateMath from '@elastic/datemath';
-
-import { EuiDatePicker } from '../../date_picker';
-import { EuiFormRow, EuiFieldText, EuiFormLabel } from '../../../form';
-import { toSentenceCase } from '../../../../services/string/to_case';
-
-export class EuiAbsoluteTab extends Component {
- constructor(props) {
- super(props);
-
- const parsedValue = dateMath.parse(props.value, { roundUp: props.roundUp });
- const valueAsMoment =
- parsedValue && parsedValue.isValid() ? parsedValue : moment();
- const sentenceCasedPosition = toSentenceCase(props.position);
-
- this.state = {
- valueAsMoment,
- textInputValue: valueAsMoment
- .locale(this.props.locale || 'en')
- .format(this.props.dateFormat),
- isTextInvalid: false,
- sentenceCasedPosition,
- };
- }
-
- handleChange = date => {
- this.props.onChange(date.toISOString());
- this.setState({
- valueAsMoment: date,
- textInputValue: date.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;
- }
-
- this.setState(updatedState);
- };
-
- render() {
- return (
-
-
-
-
- {this.state.sentenceCasedPosition} date
-
- }
- />
-
-
- );
- }
-}
-
-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/absolute_tab.tsx b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx
new file mode 100644
index 000000000000..ccd36bf0d80b
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.tsx
@@ -0,0 +1,125 @@
+import React, { Component, ChangeEventHandler } from 'react';
+
+import moment, { Moment, LocaleSpecifier } from 'moment'; // eslint-disable-line import/named
+
+import dateMath from '@elastic/datemath';
+
+import { EuiDatePicker } from '../../date_picker';
+import { EuiFormRow } from '../../../form/form_row';
+import { EuiFieldText } from '../../../form/field_text';
+import { EuiFormLabel } from '../../../form/form_label';
+import { toSentenceCase } from '../../../../services/string/to_case';
+import { ReactDatePickerProps } from '../../react-datepicker'; // eslint-disable-line import/no-unresolved
+
+export interface EuiAbsoluteTabProps {
+ dateFormat: string;
+ timeFormat: string;
+ locale?: LocaleSpecifier;
+ value: string;
+ onChange: ReactDatePickerProps['onChange'];
+ 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 textInputValue = valueAsMoment
+ .locale(this.props.locale || 'en')
+ .format(this.props.dateFormat);
+
+ this.state = {
+ isTextInvalid: false,
+ sentenceCasedPosition,
+ textInputValue,
+ valueAsMoment,
+ };
+ }
+
+ handleChange: ReactDatePickerProps['onChange'] = (date, event) => {
+ if (date === null) {
+ return;
+ }
+ const dateMoment = moment(date);
+ this.props.onChange(date, event);
+ this.setState({
+ valueAsMoment: dateMoment,
+ textInputValue: dateMoment.format(this.props.dateFormat),
+ isTextInvalid: false,
+ });
+ };
+
+ handleTextChange: ChangeEventHandler = event => {
+ const valueAsMoment = moment(
+ event.target.value,
+ this.props.dateFormat,
+ true
+ );
+ const dateIsValid = valueAsMoment.isValid();
+ if (dateIsValid) {
+ this.props.onChange(valueAsMoment, event);
+ }
+ this.setState({
+ textInputValue: event.target.value as string,
+ isTextInvalid: !dateIsValid,
+ valueAsMoment: dateIsValid ? valueAsMoment : null,
+ });
+ };
+
+ render() {
+ return (
+
+
+
+
+ {this.state.sentenceCasedPosition} date
+
+ }
+ />
+
+
+ );
+ }
+}
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 63%
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 74868cb75854..5b17806cc1d1 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,34 @@
-import PropTypes from 'prop-types';
-import React from 'react';
+import React, { FC, 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: EuiDatePopoverContentProps['onChange'];
+ onPopoverClose: EuiPopoverProps['closePopover'];
+ onPopoverToggle: MouseEventHandler;
+ position: 'start' | 'end';
+ roundUp?: boolean;
+ timeFormat: string;
+ value: string;
+}
+
+export const EuiDatePopoverButton: FC = props => {
const {
position,
isDisabled,
@@ -77,19 +98,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 74%
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 c9a101204ce4..9fe14c451e40 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, { FC } from 'react';
-import { EuiTabbedContent } from '../../../tabs';
+import { EuiTabbedContent, EuiTabbedContentProps } from '../../../tabs';
import { EuiText } from '../../../text';
import { EuiButton } from '../../../button';
@@ -14,17 +13,29 @@ import {
toAbsoluteString,
toRelativeString,
} from '../date_modes';
+import { LocaleSpecifier } from 'moment'; // eslint-disable-line import/named
+import { ReactDatePickerProps } from '../../react-datepicker';
-export function EuiDatePopoverContent({
+export interface EuiDatePopoverContentProps {
+ value: string;
+ onChange: ReactDatePickerProps['onChange'];
+ roundUp?: boolean;
+ dateFormat: string;
+ timeFormat: string;
+ locale?: LocaleSpecifier;
+ position: 'start' | 'end';
+}
+
+export const EuiDatePopoverContent: FC = ({
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));
@@ -105,24 +116,16 @@ export function EuiDatePopoverContent({
className="euiDatePopoverContent"
tabs={renderTabs()}
autoFocus="selected"
- initialSelectedTab={{ id: getDateMode(value) }}
+ initialSelectedTab={{
+ // NOTE_TO_SELF(dimitri): behavior change?
+ content: ,
+ id: getDateMode(value),
+ // NOTE_TO_SELF(dimitri): behavior change?
+ name: '',
+ }}
onTabClick={onTabClick}
size="s"
expand
/>
);
-}
-
-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,
};
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 000000000000..4f86a5e3e623
--- /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 62%
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 2fe03b16a7b6..375b456ea7b9 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,18 +1,16 @@
-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';
import { EuiFlexGroup, EuiFlexItem } from '../../../flex';
-import {
- EuiForm,
- EuiFormRow,
- EuiSelect,
- EuiFieldNumber,
- EuiFieldText,
- EuiSwitch,
- EuiFormLabel,
-} from '../../../form';
+// @ts-ignore
+import { EuiForm } from '../../../form/form';
+import { EuiFormRow } from '../../../form/form_row';
+import { EuiSelect } from '../../../form/select';
+import { EuiFieldNumber } from '../../../form/field_number';
+import { EuiFieldText } from '../../../form/field_text';
+import { EuiSwitch, EuiSwitchEvent } from '../../../form/switch';
+import { EuiFormLabel } from '../../../form/form_label';
import { EuiSpacer } from '../../../spacer';
import { timeUnits } from '../time_units';
@@ -23,58 +21,82 @@ 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: ReactDatePickerProps['onChange'];
+ roundUp?: boolean;
+ position: 'start' | 'end';
+}
- this.state = {
- ...parseRelativeParts(this.props.value),
- sentenceCasedPosition,
- };
- }
+interface EuiRelativeTabState
+ extends Pick {
+ count: number | null;
+ 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) ? null : 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;
+ if (count === null || count < 0) {
return;
}
- this.props.onChange(toRelativeStringFromParts(this.state));
+ const date = toRelativeStringFromParts({
+ count,
+ round,
+ roundUnit,
+ unit,
+ });
+ this.props.onChange(date);
};
render() {
+ const { count, unit } = this.state;
const relativeDateInputNumberDescriptionId = this.generateId();
- const isInvalid = this.state.count < 0;
+ const isInvalid = count !== null && count < 0;
const parsedValue = dateMath.parse(this.props.value, {
roundUp: this.props.roundUp,
});
@@ -94,7 +116,7 @@ export class EuiRelativeTab extends Component {
'euiRelativeTab.numberInputLabel',
]}
defaults={['Must be >= 0', 'Time span amount']}>
- {([numberInputError, numberInputLabel]) => (
+ {([numberInputError, numberInputLabel]: string[]) => (
@@ -103,7 +125,7 @@ export class EuiRelativeTab extends Component {
aria-label={numberInputLabel}
aria-describedby={relativeDateInputNumberDescriptionId}
data-test-subj={'superDatePickerRelativeDateInputNumber'}
- value={this.state.count}
+ value={count || undefined}
onChange={this.onCountChange}
isInvalid={isInvalid}
/>
@@ -115,14 +137,14 @@ export class EuiRelativeTab extends Component {
- {unitInputLabel => (
+ {(unitInputLabel: string) => (
@@ -134,8 +156,8 @@ export class EuiRelativeTab extends Component {
- {roundingLabel => (
+ values={{ unit: timeUnits[unit.substring(0, 1) as TimeUnitId] }}>
+ {(roundingLabel: string) => (
@@ -173,12 +195,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 978ec874cc60..000000000000
--- 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 000000000000..b7143ade4e9c
--- /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 75%
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 21a49ce872ff..246c11453b53 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,14 +82,16 @@ 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) {
- text += ` rounded to the ${timeUnits[relativeParts.roundUnit]}`;
+ if (relativeParts.roundUnit) {
+ text += ` rounded to the ${timeUnits[relativeParts.roundUnit]}`;
+ }
}
return text;
}
@@ -91,7 +99,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/commonly_used_time_ranges.js b/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used_time_ranges.tsx
similarity index 69%
rename from src/components/date_picker/super_date_picker/quick_select_popover/commonly_used_time_ranges.js
rename to src/components/date_picker/super_date_picker/quick_select_popover/commonly_used_time_ranges.tsx
index 3331ab150234..4d58aa2aa8c2 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used_time_ranges.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used_time_ranges.tsx
@@ -1,32 +1,37 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import { commonlyUsedRangeShape } from '../types';
+import React, { FC } from 'react';
import { EuiI18n } from '../../../i18n';
import { EuiFlexGrid, EuiFlexItem } from '../../../flex';
import { EuiTitle } from '../../../title';
import { EuiLink } from '../../../link';
import { EuiHorizontalRule } from '../../../horizontal_rule';
import { htmlIdGenerator } from '../../../../services';
+import { DurationRange, ApplyTime } from '../../types';
const generateId = htmlIdGenerator();
-export function EuiCommonlyUsedTimeRanges({ applyTime, commonlyUsedRanges }) {
+export interface EuiCommonlyUsedTimeRangesProps {
+ applyTime: ApplyTime;
+ commonlyUsedRanges: DurationRange[];
+}
+
+export const EuiCommonlyUsedTimeRanges: FC = ({
+ 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 +62,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 000000000000..d5bacaf91638
--- /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
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 77%
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 082760bd7bcd..d9437d85e1c6 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,17 +1,19 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
+import React, { Component, ChangeEventHandler } from 'react';
import moment from 'moment';
import dateMath from '@elastic/datemath';
import { htmlIdGenerator } from '../../../../services';
import { EuiButton, EuiButtonIcon } from '../../../button';
import { EuiFlexGroup, EuiFlexItem } from '../../../flex';
import { EuiSpacer } from '../../../spacer';
-import { EuiSelect, EuiFieldNumber } from '../../../form';
+import { EuiSelect } from '../../../form/select';
+import { EuiFieldNumber } from '../../../form/field_number';
import { EuiToolTip } from '../../../tool_tip';
import { EuiHorizontalRule } from '../../../horizontal_rule';
import { EuiI18n } from '../../../i18n';
import { timeUnits } from '../time_units';
import { EuiScreenReaderOnly } from '../../../accessibility';
+import { ApplyTime, QuickSelect, TimeUnitId } from '../../types';
+import { keysOf } from '../../../common';
const LAST = 'last';
const NEXT = 'next';
@@ -20,40 +22,60 @@ 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);
+type EuiQuickSelectState = QuickSelect;
- const { timeTense, timeValue, timeUnits } = this.props.prevQuickSelect;
- this.state = {
- timeTense: timeTense ? timeTense : LAST,
- timeValue: timeValue ? timeValue : 15,
- timeUnits: timeUnits ? timeUnits : 'm',
- };
- }
+export interface EuiQuickSelectProps {
+ applyTime: ApplyTime;
+ start: string;
+ end: string;
+ prevQuickSelect?: EuiQuickSelectState;
+}
+
+export class EuiQuickSelect extends Component<
+ EuiQuickSelectProps,
+ EuiQuickSelectState
+> {
+ defaultProps = {
+ prevQuickSelect: {},
+ };
+
+ state: EuiQuickSelectState = {
+ timeTense:
+ this.props.prevQuickSelect && this.props.prevQuickSelect.timeTense
+ ? this.props.prevQuickSelect.timeTense
+ : LAST,
+ timeValue:
+ this.props.prevQuickSelect && this.props.prevQuickSelect.timeValue
+ ? this.props.prevQuickSelect.timeValue
+ : 15,
+ timeUnits:
+ this.props.prevQuickSelect && this.props.prevQuickSelect.timeUnits
+ ? this.props.prevQuickSelect.timeUnits
+ : 'm',
+ };
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,
});
};
@@ -120,13 +142,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 (