@kelvininc/ui-components
Version:
Kelvin UI Components
558 lines (553 loc) • 22.3 kB
JavaScript
'use strict';
var wizard_types = require('./wizard.types-C9Yhv1tt.js');
var date_helper = require('./date.helper-C8Apy5Qj.js');
/**
* Configuration mapping for all relative time range keys.
*
* @remarks
* Defines how each `ERelativeTimeRangeKey` should be calculated:
* - Simple offsets add/subtract units from current time
* - Unit reference offsets align to start/end of time units
*
* @see {RelativeTimeOffsetConfig}
* @see {getRelativeTimeCalculation}
*/
const RELATIVE_TIME_OFFSETS = {
[wizard_types.ERelativeTimeRangeKey.Last_5_m]: {
offset: -5,
unit: 'minutes'
},
[wizard_types.ERelativeTimeRangeKey.Last_10_m]: {
offset: -10,
unit: 'minutes'
},
[wizard_types.ERelativeTimeRangeKey.Last_15_m]: {
offset: -15,
unit: 'minutes'
},
[wizard_types.ERelativeTimeRangeKey.Last_30_m]: {
offset: -30,
unit: 'minutes'
},
[wizard_types.ERelativeTimeRangeKey.Last_1_H]: {
offset: -1,
unit: 'hours'
},
[wizard_types.ERelativeTimeRangeKey.Last_3_H]: {
offset: -3,
unit: 'hours'
},
[wizard_types.ERelativeTimeRangeKey.Last_6_H]: {
offset: -6,
unit: 'hours'
},
[wizard_types.ERelativeTimeRangeKey.Last_12_H]: {
offset: -12,
unit: 'hours'
},
[wizard_types.ERelativeTimeRangeKey.Last_24_H]: {
offset: -24,
unit: 'hours'
},
[wizard_types.ERelativeTimeRangeKey.Last_48_H]: {
offset: -48,
unit: 'hours'
},
[wizard_types.ERelativeTimeRangeKey.Last_72_H]: {
offset: -72,
unit: 'hours'
},
[wizard_types.ERelativeTimeRangeKey.Last_3_D]: {
offset: -3,
unit: 'days'
},
[wizard_types.ERelativeTimeRangeKey.Last_7_D]: {
offset: -7,
unit: 'days'
},
[wizard_types.ERelativeTimeRangeKey.Last_14_D]: {
offset: -14,
unit: 'days'
},
[wizard_types.ERelativeTimeRangeKey.Last_30_D]: {
offset: -30,
unit: 'days'
},
[wizard_types.ERelativeTimeRangeKey.Last_90_D]: {
offset: -90,
unit: 'days'
},
[wizard_types.ERelativeTimeRangeKey.Last_1_M]: {
offset: -1,
unit: 'months'
},
[wizard_types.ERelativeTimeRangeKey.Last_6_M]: {
offset: -6,
unit: 'months'
},
[wizard_types.ERelativeTimeRangeKey.Last_1_Y]: {
offset: -1,
unit: 'years'
},
[wizard_types.ERelativeTimeRangeKey.Last_2_Y]: {
offset: -2,
unit: 'years'
},
[wizard_types.ERelativeTimeRangeKey.Last_5_Y]: {
offset: -5,
unit: 'years'
},
[wizard_types.ERelativeTimeRangeKey.Last_365_D]: {
offset: -365,
unit: 'days'
},
// Special - Unit-based references
[wizard_types.ERelativeTimeRangeKey.Today]: {
offset: 0,
unit: 'day',
unitReference: wizard_types.EUnitReference.StartOfUnit
},
[wizard_types.ERelativeTimeRangeKey.Yesterday]: {
offset: -1,
unit: 'day',
unitReference: wizard_types.EUnitReference.StartOfUnit
},
[wizard_types.ERelativeTimeRangeKey.Yesterday_End]: {
offset: -1,
unit: 'day',
unitReference: wizard_types.EUnitReference.EndOfUnit
},
// "So far" ranges (from start of unit to now)
[wizard_types.ERelativeTimeRangeKey.This_Week_So_Far]: {
offset: 0,
unit: 'week',
unitReference: wizard_types.EUnitReference.StartOfUnit
},
[wizard_types.ERelativeTimeRangeKey.This_Month_So_Far]: {
offset: 0,
unit: 'month',
unitReference: wizard_types.EUnitReference.StartOfUnit
},
[wizard_types.ERelativeTimeRangeKey.This_Quarter_So_Far]: {
offset: 0,
unit: 'quarter',
unitReference: wizard_types.EUnitReference.StartOfUnit
},
[wizard_types.ERelativeTimeRangeKey.This_Year_So_Far]: {
offset: 0,
unit: 'year',
unitReference: wizard_types.EUnitReference.StartOfUnit
},
[wizard_types.ERelativeTimeRangeKey.Next_5_M]: {
offset: 5,
unit: 'minutes'
},
[wizard_types.ERelativeTimeRangeKey.Next_10_M]: {
offset: 10,
unit: 'minutes'
},
[wizard_types.ERelativeTimeRangeKey.Next_15_M]: {
offset: 15,
unit: 'minutes'
},
[wizard_types.ERelativeTimeRangeKey.Next_30_M]: {
offset: 30,
unit: 'minutes'
},
[wizard_types.ERelativeTimeRangeKey.Next_1_H]: {
offset: 1,
unit: 'hours'
},
[wizard_types.ERelativeTimeRangeKey.Next_6_H]: {
offset: 6,
unit: 'hours'
},
[wizard_types.ERelativeTimeRangeKey.Next_12_H]: {
offset: 12,
unit: 'hours'
},
[wizard_types.ERelativeTimeRangeKey.Next_24_H]: {
offset: 24,
unit: 'hours'
},
[wizard_types.ERelativeTimeRangeKey.Next_48_H]: {
offset: 48,
unit: 'hours'
},
[wizard_types.ERelativeTimeRangeKey.Next_72_H]: {
offset: 72,
unit: 'hours'
},
[wizard_types.ERelativeTimeRangeKey.Next_7_D]: {
offset: 7,
unit: 'days'
},
[wizard_types.ERelativeTimeRangeKey.Next_2_W]: {
offset: 2,
unit: 'weeks'
},
[wizard_types.ERelativeTimeRangeKey.Next_1_M]: {
offset: 1,
unit: 'months'
}
};
/** Date range builders */
const buildOptionRange = (option, timeZone) => {
switch (option.comparisonConfig) {
case wizard_types.ERelativeTimeComparisonConfig.StartDateEndDate:
return buildStartDateEndDateConfigRange(option, timeZone);
case wizard_types.ERelativeTimeComparisonConfig.StartDate || wizard_types.ERelativeTimeComparisonConfig.EndDate:
return buildSingleDateConfigRange(option, timeZone);
case wizard_types.ERelativeTimeComparisonConfig.AbsoluteAmountOfUnits:
return buildAbsoluteAmountOfUnitsConfigRange(option, timeZone);
default:
return buildRelativeAmountOfUnitsConfigRange(option, timeZone);
}
};
// Build date from config with start and end date
const buildStartDateEndDateConfigRange = (option, timeZone) => {
const startDateTime = date_helper.newTimezoneDateFromFormat(timeZone, option.startDate.dateFormat, option.startDate.date);
const endDateTime = date_helper.newTimezoneDateFromFormat(timeZone, option.endDate.dateFormat, option.endDate.date);
return buildDayjsRange(startDateTime, endDateTime);
};
// Build date from config with start or end date
const buildSingleDateConfigRange = (option, timeZone) => {
const nowDateTime = date_helper.newTimezoneDate(timeZone);
const calculatedDate = date_helper.newTimezoneDateFromFormat(timeZone, option.startDate.dateFormat, option.startDate.date);
return buildDayjsRange(nowDateTime, calculatedDate);
};
// Build date with both start and end date relative to now timestamp
const buildAbsoluteAmountOfUnitsConfigRange = (option, timeZone) => {
const nowDateTime = date_helper.newTimezoneDate(timeZone);
const { unit: startDateUnit, amount: startDateAmount, unitReference: startUnitReference } = option.startDate;
const { unit: endDateUnit, amount: endDateAmount, unitReference: endUnitReference } = option.endDate;
const startDateTime = calculateOffsetDateWithUnitReference(date_helper.calculateOffsetDate(nowDateTime, startDateAmount, startDateUnit), startDateUnit, startUnitReference);
const endDateTime = calculateOffsetDateWithUnitReference(date_helper.calculateOffsetDate(nowDateTime, endDateAmount, endDateUnit), endDateUnit, endUnitReference);
return buildDayjsRange(startDateTime, endDateTime);
};
// Build date with start date relative to now timestamp
const buildRelativeAmountOfUnitsConfigRange = (option, timeZone) => {
const nowDateTime = date_helper.newTimezoneDate(timeZone);
const { amount, unit, unitReference } = option.startDate;
const calculatedDate = calculateOffsetDateWithUnitReference(date_helper.calculateOffsetDate(nowDateTime, amount, unit), unit, unitReference);
return buildDayjsRange(nowDateTime, calculatedDate);
};
const calculateOffsetDateWithUnitReference = (date, unit, unitReference) => {
if (!unitReference) {
return date;
}
return unitReference === wizard_types.EUnitReference.StartOfUnit ? date.startOf(unit) : date.endOf(unit);
};
/**
* Builds the range of the start and end date and returns the range array, ordering the dates if needed
* @param dateA date (start or end)
* @param dateB date (start or end)
* @returns range containing start date and end date ordered
*/
const buildDayjsRange = (dateA, dateB) => {
return date_helper.isDateTimeBefore(dateA, dateB) ? [dateA, dateB] : [dateB, dateA];
};
const buildTimestampRange = ([startDate, endDate]) => [startDate.valueOf(), endDate.valueOf()];
/**
* Finds a relative time option by its key from the provided options groups.
*
* @param key - The option key to search for
* @param options - Optional: The option groups to search in (defaults to DEFAULT_RELATIVE_TIME_OPTIONS_GROUPS)
* @returns The matching option or undefined
*/
const getRelativeTimeOption = (key, options) => (options !== null && options !== void 0 ? options : DEFAULT_RELATIVE_TIME_OPTIONS_GROUPS).flat().find(option => option.value === key);
/**
* Derives DateTimeCalculation configuration from a relative time range key.
* This eliminates manual duplication of offset data.
*
* @param key - The relative time range key
* @returns DateTimeCalculation object ready for use in IRelativeTimePickerOption
*
* @example
* ```typescript
* // Simple offset
* getRelativeTimeCalculation(ERelativeTimeRangeKey.Last_5_m)
* // Returns: { amount: -5, unit: 'minutes' }
* ```
*
* @example
* ```typescript
* // Unit reference offset
* getRelativeTimeCalculation(ERelativeTimeRangeKey.Today)
* // Returns: { amount: 0, unit: 'day', unitReference: EUnitReference.StartOfUnit }
* ```
*
* @throws {Error} If no configuration is found for the provided key
*/
const getRelativeTimeCalculation = (key) => {
const config = RELATIVE_TIME_OFFSETS[key];
if (config === undefined) {
throw new Error(`No offset configuration found for key: ${key}`);
}
return Object.assign({ amount: config.offset, unit: config.unit }, (config.unitReference !== undefined && { unitReference: config.unitReference }));
};
/**
* Builder function to create IRelativeTimePickerOption with automatic
* startDate/endDate derivation from RELATIVE_TIME_OFFSETS.
*
* @param label - Display label for the option
* @param value - Relative time range key
* @param comparisonConfig - How the time calculation should be performed
* @param labelRangeFormatter - Optional formatter for date range display
* @param endDateKey - Optional: If provided, derives endDate from this key
* @returns Complete IRelativeTimePickerOption
*
* @example
* ```typescript
* // Simple option
* buildRelativeTimeOption(
* 'Last 5 minutes',
* ERelativeTimeRangeKey.Last_5_m,
* ERelativeTimeComparisonConfig.RelativeAmountOfUnits,
* {
* startDateFormatter: 'HH:mm',
* separator: 'to',
* endDateFormatter: 'HH:mm'
* }
* )
* ```
*
* @example
* ```typescript
* // Option with endDate
* buildRelativeTimeOption(
* 'Yesterday',
* ERelativeTimeRangeKey.Yesterday,
* ERelativeTimeComparisonConfig.AbsoluteAmountOfUnits,
* { startDateFormatter: 'D MMM' },
* ERelativeTimeRangeKey.Yesterday_End
* )
* ```
*/
const buildRelativeTimeOption = (label, value, comparisonConfig, labelRangeFormatter, endDateKey) => {
const option = Object.assign({ label,
value,
comparisonConfig, startDate: getRelativeTimeCalculation(value) }, (labelRangeFormatter !== undefined && { labelRangeFormatter }));
if (endDateKey !== undefined) {
option.endDate = getRelativeTimeCalculation(endDateKey);
}
return option;
};
/**
* Validates that all keys in RELATIVE_TIME_OFFSETS are valid enum values.
* Useful for development/testing to ensure consistency.
*
* @returns true if all keys are valid
* @throws {Error} If any invalid keys are found
*
* @example
* ```typescript
* // In tests or development
* validateRelativeTimeOffsets(); // throws if config is invalid
* ```
*/
const validateRelativeTimeOffsets = () => {
const enumValues = Object.values(wizard_types.ERelativeTimeRangeKey);
const offsetKeys = Object.keys(RELATIVE_TIME_OFFSETS);
const invalidKeys = offsetKeys.filter(key => !enumValues.includes(key));
if (invalidKeys.length > 0) {
throw new Error(`Invalid keys in RELATIVE_TIME_OFFSETS: ${invalidKeys.join(', ')}`);
}
return true;
};
/**
* Default relative time option groups for the time picker component.
*
* @remarks
* This configuration is built using the `buildRelativeTimeOption` helper to ensure
* consistency with `RELATIVE_TIME_OFFSETS` and avoid data duplication.
*
* Organized into 5 groups:
* 1. Today/Yesterday
* 2. Day/Month ranges (24h, 48h, 7d, 30d, 90d, 6M)
* 3. Minute/Hour ranges (5m, 15m, 30m, 1h, 3h, 6h, 12h)
* 4. Long-term ranges (365d, 2y)
* 5. "So far" ranges (week, month, quarter, year)
*/
const DEFAULT_RELATIVE_TIME_OPTIONS_GROUPS = [
[
buildRelativeTimeOption('Today', wizard_types.ERelativeTimeRangeKey.Today, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM',
separator: 'until',
endDateFormatter: 'HH:mm'
}),
buildRelativeTimeOption('Yesterday', wizard_types.ERelativeTimeRangeKey.Yesterday, wizard_types.ERelativeTimeComparisonConfig.AbsoluteAmountOfUnits, {
startDateFormatter: 'D MMM'
}, wizard_types.ERelativeTimeRangeKey.Yesterday_End)
],
[
buildRelativeTimeOption('Last 24 hours', wizard_types.ERelativeTimeRangeKey.Last_24_H, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM HH:mm',
separator: 'to',
endDateFormatter: 'D MMM HH:mm'
}),
buildRelativeTimeOption('Last 48 hours', wizard_types.ERelativeTimeRangeKey.Last_48_H, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM HH:mm',
separator: 'to',
endDateFormatter: 'D MMM HH:mm'
}),
buildRelativeTimeOption('Last 7 days', wizard_types.ERelativeTimeRangeKey.Last_7_D, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM',
separator: 'to',
endDateFormatter: 'D MMM'
}),
buildRelativeTimeOption('Last 30 days', wizard_types.ERelativeTimeRangeKey.Last_30_D, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM',
separator: 'to',
endDateFormatter: 'D MMM'
}),
buildRelativeTimeOption('Last 90 days', wizard_types.ERelativeTimeRangeKey.Last_90_D, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM',
separator: 'to',
endDateFormatter: 'D MMM'
}),
buildRelativeTimeOption('Last 6 months', wizard_types.ERelativeTimeRangeKey.Last_6_M, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM',
separator: 'to',
endDateFormatter: 'D MMM'
})
],
[
buildRelativeTimeOption('Last 5 minutes', wizard_types.ERelativeTimeRangeKey.Last_5_m, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'HH:mm',
separator: 'to',
endDateFormatter: 'HH:mm'
}),
buildRelativeTimeOption('Last 15 minutes', wizard_types.ERelativeTimeRangeKey.Last_15_m, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'HH:mm',
separator: 'to',
endDateFormatter: 'HH:mm'
}),
buildRelativeTimeOption('Last 30 minutes', wizard_types.ERelativeTimeRangeKey.Last_30_m, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'HH:mm',
separator: 'to',
endDateFormatter: 'HH:mm'
}),
buildRelativeTimeOption('Last 1 hour', wizard_types.ERelativeTimeRangeKey.Last_1_H, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'HH:mm',
separator: 'to',
endDateFormatter: 'HH:mm'
}),
buildRelativeTimeOption('Last 3 hours', wizard_types.ERelativeTimeRangeKey.Last_3_H, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'HH:mm',
separator: 'to',
endDateFormatter: 'HH:mm'
}),
buildRelativeTimeOption('Last 6 hours', wizard_types.ERelativeTimeRangeKey.Last_6_H, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'HH:mm',
separator: 'to',
endDateFormatter: 'HH:mm'
}),
buildRelativeTimeOption('Last 12 hours', wizard_types.ERelativeTimeRangeKey.Last_12_H, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'HH:mm',
separator: 'to',
endDateFormatter: 'HH:mm'
})
],
[
buildRelativeTimeOption('Last 365 days', wizard_types.ERelativeTimeRangeKey.Last_365_D, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM YYYY',
separator: 'to',
endDateFormatter: 'D MMM YYYY'
}),
buildRelativeTimeOption('Last 2 years', wizard_types.ERelativeTimeRangeKey.Last_2_Y, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM YYYY',
separator: 'to',
endDateFormatter: 'D MMM YYYY'
})
],
[
buildRelativeTimeOption('This week so far', wizard_types.ERelativeTimeRangeKey.This_Week_So_Far, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM HH:mm',
separator: 'to',
endDateFormatter: 'D MMM HH:mm'
}),
buildRelativeTimeOption('This month so far', wizard_types.ERelativeTimeRangeKey.This_Month_So_Far, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM HH:mm',
separator: 'to',
endDateFormatter: 'D MMM HH:mm'
}),
buildRelativeTimeOption('This quarter so far', wizard_types.ERelativeTimeRangeKey.This_Quarter_So_Far, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM HH:mm',
separator: 'to',
endDateFormatter: 'D MMM HH:mm'
}),
buildRelativeTimeOption('This year so far', wizard_types.ERelativeTimeRangeKey.This_Year_So_Far, wizard_types.ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM HH:mm',
separator: 'to',
endDateFormatter: 'D MMM HH:mm'
})
]
];
/**
* Base helper function to calculate relative time range.
* @param key the relative time key
* @param cursor the relative timestamp cursor (as dayjs instance)
* @returns DayjsTimeRange with start and end dates
* @private
*/
const getRelativeTimeRange = (key, cursor) => {
const { offset, unit } = RELATIVE_TIME_OFFSETS[key];
let startDate;
let endDate;
if (offset < 0) {
startDate = date_helper.calculateOffsetDate(cursor, offset, unit);
endDate = cursor;
}
else {
endDate = date_helper.calculateOffsetDate(cursor, offset, unit);
startDate = cursor;
}
return [startDate, endDate];
};
/**
* Returns a start and end time according to a relative time range in utc.
* @param key the relative time key
* @param cursor the relative timestamp cursor
* @returns an array with datetime strings
*/
const getRelativeTimeRangeISO = (key, cursor = date_helper.newDate().toISOString()) => {
const cursorDate = date_helper.newDate(cursor);
const [startDate, endDate] = getRelativeTimeRange(key, cursorDate);
return [startDate.toISOString(), endDate.toISOString()];
};
/**
* Returns a start and end time according to a relative time range as timestamps.
* @param key the relative time key
* @param cursor the relative timestamp cursor
* @returns an array with timestamps
*/
const getRelativeTimeRangeTimestamp = (key, cursor = date_helper.newDate()) => {
const [startDate, endDate] = getRelativeTimeRange(key, cursor);
return [startDate.valueOf(), endDate.valueOf()];
};
/**
* Returns the provided range in utc.
* @range the absolute time range
* @offset the timezone offset
* @returns an array with datetime strings
*/
const getAbsoluteTimeRange = (range, offset = 0) => {
return range.map(date => date_helper.calculateOffsetDate(date, offset, 'minutes').toISOString());
};
exports.DEFAULT_RELATIVE_TIME_OPTIONS_GROUPS = DEFAULT_RELATIVE_TIME_OPTIONS_GROUPS;
exports.RELATIVE_TIME_OFFSETS = RELATIVE_TIME_OFFSETS;
exports.buildAbsoluteAmountOfUnitsConfigRange = buildAbsoluteAmountOfUnitsConfigRange;
exports.buildDayjsRange = buildDayjsRange;
exports.buildOptionRange = buildOptionRange;
exports.buildRelativeAmountOfUnitsConfigRange = buildRelativeAmountOfUnitsConfigRange;
exports.buildRelativeTimeOption = buildRelativeTimeOption;
exports.buildSingleDateConfigRange = buildSingleDateConfigRange;
exports.buildStartDateEndDateConfigRange = buildStartDateEndDateConfigRange;
exports.buildTimestampRange = buildTimestampRange;
exports.getAbsoluteTimeRange = getAbsoluteTimeRange;
exports.getRelativeTimeCalculation = getRelativeTimeCalculation;
exports.getRelativeTimeOption = getRelativeTimeOption;
exports.getRelativeTimeRangeISO = getRelativeTimeRangeISO;
exports.getRelativeTimeRangeTimestamp = getRelativeTimeRangeTimestamp;
exports.validateRelativeTimeOffsets = validateRelativeTimeOffsets;