@kelvininc/ui-components
Version:
Kelvin UI Components
541 lines (537 loc) • 20.5 kB
JavaScript
import { a as EUnitReference, E as ERelativeTimeRangeKey, v as ERelativeTimeComparisonConfig } from './p-BP5CxQcH.js';
import { F as newTimezoneDate, c as calculateOffsetDate, G as newTimezoneDateFromFormat, C as isDateTimeBefore, E as newDate } from './p-BS8xGxWJ.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 = {
[ERelativeTimeRangeKey.Last_5_m]: {
offset: -5,
unit: 'minutes'
},
[ERelativeTimeRangeKey.Last_10_m]: {
offset: -10,
unit: 'minutes'
},
[ERelativeTimeRangeKey.Last_15_m]: {
offset: -15,
unit: 'minutes'
},
[ERelativeTimeRangeKey.Last_30_m]: {
offset: -30,
unit: 'minutes'
},
[ERelativeTimeRangeKey.Last_1_H]: {
offset: -1,
unit: 'hours'
},
[ERelativeTimeRangeKey.Last_3_H]: {
offset: -3,
unit: 'hours'
},
[ERelativeTimeRangeKey.Last_6_H]: {
offset: -6,
unit: 'hours'
},
[ERelativeTimeRangeKey.Last_12_H]: {
offset: -12,
unit: 'hours'
},
[ERelativeTimeRangeKey.Last_24_H]: {
offset: -24,
unit: 'hours'
},
[ERelativeTimeRangeKey.Last_48_H]: {
offset: -48,
unit: 'hours'
},
[ERelativeTimeRangeKey.Last_72_H]: {
offset: -72,
unit: 'hours'
},
[ERelativeTimeRangeKey.Last_3_D]: {
offset: -3,
unit: 'days'
},
[ERelativeTimeRangeKey.Last_7_D]: {
offset: -7,
unit: 'days'
},
[ERelativeTimeRangeKey.Last_14_D]: {
offset: -14,
unit: 'days'
},
[ERelativeTimeRangeKey.Last_30_D]: {
offset: -30,
unit: 'days'
},
[ERelativeTimeRangeKey.Last_90_D]: {
offset: -90,
unit: 'days'
},
[ERelativeTimeRangeKey.Last_1_M]: {
offset: -1,
unit: 'months'
},
[ERelativeTimeRangeKey.Last_6_M]: {
offset: -6,
unit: 'months'
},
[ERelativeTimeRangeKey.Last_1_Y]: {
offset: -1,
unit: 'years'
},
[ERelativeTimeRangeKey.Last_2_Y]: {
offset: -2,
unit: 'years'
},
[ERelativeTimeRangeKey.Last_5_Y]: {
offset: -5,
unit: 'years'
},
[ERelativeTimeRangeKey.Last_365_D]: {
offset: -365,
unit: 'days'
},
// Special - Unit-based references
[ERelativeTimeRangeKey.Today]: {
offset: 0,
unit: 'day',
unitReference: EUnitReference.StartOfUnit
},
[ERelativeTimeRangeKey.Yesterday]: {
offset: -1,
unit: 'day',
unitReference: EUnitReference.StartOfUnit
},
[ERelativeTimeRangeKey.Yesterday_End]: {
offset: -1,
unit: 'day',
unitReference: EUnitReference.EndOfUnit
},
// "So far" ranges (from start of unit to now)
[ERelativeTimeRangeKey.This_Week_So_Far]: {
offset: 0,
unit: 'week',
unitReference: EUnitReference.StartOfUnit
},
[ERelativeTimeRangeKey.This_Month_So_Far]: {
offset: 0,
unit: 'month',
unitReference: EUnitReference.StartOfUnit
},
[ERelativeTimeRangeKey.This_Quarter_So_Far]: {
offset: 0,
unit: 'quarter',
unitReference: EUnitReference.StartOfUnit
},
[ERelativeTimeRangeKey.This_Year_So_Far]: {
offset: 0,
unit: 'year',
unitReference: EUnitReference.StartOfUnit
},
[ERelativeTimeRangeKey.Next_5_M]: {
offset: 5,
unit: 'minutes'
},
[ERelativeTimeRangeKey.Next_10_M]: {
offset: 10,
unit: 'minutes'
},
[ERelativeTimeRangeKey.Next_15_M]: {
offset: 15,
unit: 'minutes'
},
[ERelativeTimeRangeKey.Next_30_M]: {
offset: 30,
unit: 'minutes'
},
[ERelativeTimeRangeKey.Next_1_H]: {
offset: 1,
unit: 'hours'
},
[ERelativeTimeRangeKey.Next_6_H]: {
offset: 6,
unit: 'hours'
},
[ERelativeTimeRangeKey.Next_12_H]: {
offset: 12,
unit: 'hours'
},
[ERelativeTimeRangeKey.Next_24_H]: {
offset: 24,
unit: 'hours'
},
[ERelativeTimeRangeKey.Next_48_H]: {
offset: 48,
unit: 'hours'
},
[ERelativeTimeRangeKey.Next_72_H]: {
offset: 72,
unit: 'hours'
},
[ERelativeTimeRangeKey.Next_7_D]: {
offset: 7,
unit: 'days'
},
[ERelativeTimeRangeKey.Next_2_W]: {
offset: 2,
unit: 'weeks'
},
[ERelativeTimeRangeKey.Next_1_M]: {
offset: 1,
unit: 'months'
}
};
/** Date range builders */
const buildOptionRange = (option, timeZone) => {
switch (option.comparisonConfig) {
case ERelativeTimeComparisonConfig.StartDateEndDate:
return buildStartDateEndDateConfigRange(option, timeZone);
case ERelativeTimeComparisonConfig.StartDate || ERelativeTimeComparisonConfig.EndDate:
return buildSingleDateConfigRange(option, timeZone);
case 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 = newTimezoneDateFromFormat(timeZone, option.startDate.dateFormat, option.startDate.date);
const endDateTime = 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 = newTimezoneDate(timeZone);
const calculatedDate = 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 = newTimezoneDate(timeZone);
const { unit: startDateUnit, amount: startDateAmount, unitReference: startUnitReference } = option.startDate;
const { unit: endDateUnit, amount: endDateAmount, unitReference: endUnitReference } = option.endDate;
const startDateTime = calculateOffsetDateWithUnitReference(calculateOffsetDate(nowDateTime, startDateAmount, startDateUnit), startDateUnit, startUnitReference);
const endDateTime = calculateOffsetDateWithUnitReference(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 = newTimezoneDate(timeZone);
const { amount, unit, unitReference } = option.startDate;
const calculatedDate = calculateOffsetDateWithUnitReference(calculateOffsetDate(nowDateTime, amount, unit), unit, unitReference);
return buildDayjsRange(nowDateTime, calculatedDate);
};
const calculateOffsetDateWithUnitReference = (date, unit, unitReference) => {
if (!unitReference) {
return date;
}
return unitReference === 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 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(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', ERelativeTimeRangeKey.Today, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM',
separator: 'until',
endDateFormatter: 'HH:mm'
}),
buildRelativeTimeOption('Yesterday', ERelativeTimeRangeKey.Yesterday, ERelativeTimeComparisonConfig.AbsoluteAmountOfUnits, {
startDateFormatter: 'D MMM'
}, ERelativeTimeRangeKey.Yesterday_End)
],
[
buildRelativeTimeOption('Last 24 hours', ERelativeTimeRangeKey.Last_24_H, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM HH:mm',
separator: 'to',
endDateFormatter: 'D MMM HH:mm'
}),
buildRelativeTimeOption('Last 48 hours', ERelativeTimeRangeKey.Last_48_H, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM HH:mm',
separator: 'to',
endDateFormatter: 'D MMM HH:mm'
}),
buildRelativeTimeOption('Last 7 days', ERelativeTimeRangeKey.Last_7_D, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM',
separator: 'to',
endDateFormatter: 'D MMM'
}),
buildRelativeTimeOption('Last 30 days', ERelativeTimeRangeKey.Last_30_D, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM',
separator: 'to',
endDateFormatter: 'D MMM'
}),
buildRelativeTimeOption('Last 90 days', ERelativeTimeRangeKey.Last_90_D, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM',
separator: 'to',
endDateFormatter: 'D MMM'
}),
buildRelativeTimeOption('Last 6 months', ERelativeTimeRangeKey.Last_6_M, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM',
separator: 'to',
endDateFormatter: 'D MMM'
})
],
[
buildRelativeTimeOption('Last 5 minutes', ERelativeTimeRangeKey.Last_5_m, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'HH:mm',
separator: 'to',
endDateFormatter: 'HH:mm'
}),
buildRelativeTimeOption('Last 15 minutes', ERelativeTimeRangeKey.Last_15_m, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'HH:mm',
separator: 'to',
endDateFormatter: 'HH:mm'
}),
buildRelativeTimeOption('Last 30 minutes', ERelativeTimeRangeKey.Last_30_m, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'HH:mm',
separator: 'to',
endDateFormatter: 'HH:mm'
}),
buildRelativeTimeOption('Last 1 hour', ERelativeTimeRangeKey.Last_1_H, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'HH:mm',
separator: 'to',
endDateFormatter: 'HH:mm'
}),
buildRelativeTimeOption('Last 3 hours', ERelativeTimeRangeKey.Last_3_H, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'HH:mm',
separator: 'to',
endDateFormatter: 'HH:mm'
}),
buildRelativeTimeOption('Last 6 hours', ERelativeTimeRangeKey.Last_6_H, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'HH:mm',
separator: 'to',
endDateFormatter: 'HH:mm'
}),
buildRelativeTimeOption('Last 12 hours', ERelativeTimeRangeKey.Last_12_H, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'HH:mm',
separator: 'to',
endDateFormatter: 'HH:mm'
})
],
[
buildRelativeTimeOption('Last 365 days', ERelativeTimeRangeKey.Last_365_D, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM YYYY',
separator: 'to',
endDateFormatter: 'D MMM YYYY'
}),
buildRelativeTimeOption('Last 2 years', ERelativeTimeRangeKey.Last_2_Y, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM YYYY',
separator: 'to',
endDateFormatter: 'D MMM YYYY'
})
],
[
buildRelativeTimeOption('This week so far', ERelativeTimeRangeKey.This_Week_So_Far, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM HH:mm',
separator: 'to',
endDateFormatter: 'D MMM HH:mm'
}),
buildRelativeTimeOption('This month so far', ERelativeTimeRangeKey.This_Month_So_Far, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM HH:mm',
separator: 'to',
endDateFormatter: 'D MMM HH:mm'
}),
buildRelativeTimeOption('This quarter so far', ERelativeTimeRangeKey.This_Quarter_So_Far, ERelativeTimeComparisonConfig.RelativeAmountOfUnits, {
startDateFormatter: 'D MMM HH:mm',
separator: 'to',
endDateFormatter: 'D MMM HH:mm'
}),
buildRelativeTimeOption('This year so far', ERelativeTimeRangeKey.This_Year_So_Far, 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 = calculateOffsetDate(cursor, offset, unit);
endDate = cursor;
}
else {
endDate = 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 = newDate().toISOString()) => {
const cursorDate = 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 = 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 => calculateOffsetDate(date, offset, 'minutes').toISOString());
};
export { DEFAULT_RELATIVE_TIME_OPTIONS_GROUPS as D, RELATIVE_TIME_OFFSETS as R, buildDayjsRange as a, buildAbsoluteAmountOfUnitsConfigRange as b, buildOptionRange as c, buildRelativeAmountOfUnitsConfigRange as d, buildRelativeTimeOption as e, buildSingleDateConfigRange as f, buildStartDateEndDateConfigRange as g, buildTimestampRange as h, getAbsoluteTimeRange as i, getRelativeTimeCalculation as j, getRelativeTimeOption as k, getRelativeTimeRangeISO as l, getRelativeTimeRangeTimestamp as m, validateRelativeTimeOffsets as v };