@razorpay/blade
Version:
The Design System that powers Razorpay
253 lines (242 loc) • 8.65 kB
JavaScript
import { Time } from '@internationalized/date';
/**
* Converts a Date object to TimeValue for React Aria compatibility
* Used internally to bridge between external Date API and React Aria's Time objects
*
* @param date - The Date object to convert, or null
* @returns Time object for React Aria, or null if input is null
*
* @example
* // Convert Date to TimeValue
* const date = new Date('2024-01-01T14:30:00');
* dateToTimeValue(date)
* // → Time { hour: 14, minute: 30 }
*
* @example
* // Handle null input
* dateToTimeValue(null)
* // → null
*/
var dateToTimeValue = function dateToTimeValue(date) {
if (!date) return new Time(0, 0);
return new Time(date.getHours(), date.getMinutes());
};
/**
* Converts a TimeValue to Date object for external API
* Used internally to bridge between React Aria's Time objects and external Date API
*
* @param timeValue - The Time object to convert, or null
* @returns Date object with today's date and specified time, or null if input is null
*
* @example
* // Convert TimeValue to Date
* const timeValue = new Time(14, 30);
* timeValueToDate(timeValue)
* // → Date object with today's date at 2:30 PM
*
* @example
* // Handle null input
* timeValueToDate(null)
* // → null
*/
var timeValueToDate = function timeValueToDate(timeValue) {
if (!timeValue) return null;
var date = new Date();
date.setHours(timeValue.hour, timeValue.minute, 0, 0);
return date;
};
/**
* Extracts individual time components from a Date object
* Converts between 24-hour and 12-hour formats as needed for display
*
* @param time - The Date object to extract components from, or null
* @param timeFormat - Whether to use 12-hour or 24-hour format
* @returns Object with selectedHour, selectedMinute, and selectedPeriod
*
* @example
* // Extract components in 12-hour format
* const date = new Date('2024-01-01T14:30:00');
* getTimeComponents(date, '12h')
* // → { selectedHour: 2, selectedMinute: 30, selectedPeriod: 'PM' }
*
* @example
* // Extract components in 24-hour format
* const date = new Date('2024-01-01T14:30:00');
* getTimeComponents(date, '24h')
* // → { selectedHour: 14, selectedMinute: 30, selectedPeriod: 'AM' }
*
* @example
* // Handle null input (returns default 12:00 AM)
* getTimeComponents(null, '12h')
* // → { selectedHour: 12, selectedMinute: 0, selectedPeriod: 'AM' }
*/
var getTimeComponents = function getTimeComponents(time, timeFormat) {
if (!time) {
return {
selectedHour: 12,
selectedMinute: 0,
selectedPeriod: 'AM'
};
}
var hour = time.getHours();
var minute = time.getMinutes();
if (timeFormat === '12h') {
var period = hour >= 12 ? 'PM' : 'AM';
// Convert 24-hour to 12-hour format
var displayHour;
if (hour === 0) {
displayHour = 12; // Midnight becomes 12 AM
} else if (hour > 12) {
displayHour = hour - 12; // PM hours (1-11 PM)
} else {
displayHour = hour; // AM hours (1-11 AM) and noon (12 PM)
}
return {
selectedHour: displayHour,
selectedMinute: minute,
selectedPeriod: period
};
} else {
return {
selectedHour: hour,
selectedMinute: minute,
selectedPeriod: 'AM' // Not used in 24h format
};
}
};
/**
* Creates a complete Date object from time components
* Validates input values and converts 12-hour format to 24-hour as needed
*
* @param selectedHour - Hour value (1-12 for 12h format, 0-23 for 24h format)
* @param selectedMinute - Minute value (0-59)
* @param selectedPeriod - AM/PM indicator (only used in 12h format)
* @param timeFormat - Whether to use 12-hour or 24-hour format
* @returns Date object with today's date and specified time, or null if validation fails
*
* @example
* // Create time in 12-hour format
* createCompleteTime(2, 30, 'PM', '12h')
* // → Date object with today's date at 2:30 PM (14:30)
*
* @example
* // Create time in 24-hour format
* createCompleteTime(14, 30, 'AM', '24h')
* // → Date object with today's date at 14:30
*
* @example
* // Handle midnight in 12-hour format
* createCompleteTime(12, 0, 'AM', '12h')
* // → Date object with today's date at 00:00
*
* @example
* // Invalid input returns null
* createCompleteTime(25, 30, 'AM', '24h')
* // → null (hour 25 is invalid)
*/
var createCompleteTime = function createCompleteTime(selectedHour, selectedMinute, selectedPeriod, timeFormat) {
// Validate values
if (timeFormat === '12h') {
if (selectedHour < 1 || selectedHour > 12 || selectedMinute < 0 || selectedMinute > 59) return null;
} else if (selectedHour < 0 || selectedHour > 23 || selectedMinute < 0 || selectedMinute > 59) {
return null;
}
var newDate = new Date();
if (timeFormat === '12h') {
// Convert 12-hour format to 24-hour format
var hour24;
if (selectedPeriod === 'AM') {
// AM: 12 becomes 0, all others stay the same
hour24 = selectedHour === 12 ? 0 : selectedHour;
} else {
// PM: 12 stays 12, all others add 12
hour24 = selectedHour === 12 ? 12 : selectedHour + 12;
}
newDate.setHours(hour24, selectedMinute, 0, 0);
} else {
newDate.setHours(selectedHour, selectedMinute, 0, 0);
}
return newDate;
};
/**
* Creates a Date object from time selection with optional parameter overrides
* Used by TimePickerContent when individual wheels change values
* Provides fallback handling to prevent crashes from invalid inputs
*
* @param currentHour - Current hour value (fallback)
* @param currentMinute - Current minute value (fallback)
* @param currentPeriod - Current period value (fallback)
* @param timeFormat - Time format (12h or 24h)
* @param hour - Optional hour override
* @param minute - Optional minute override
* @param period - Optional period override
* @returns Date object with the specified time (never null)
*
* @example
* // Update only the hour
* createDateFromSelection(10, 30, 'AM', '12h', 11)
* // → Date object with 11:30 AM
*
* @example
* // Update only the minute
* createDateFromSelection(10, 30, 'AM', '12h', undefined, 45)
* // → Date object with 10:45 AM
*
* @example
* // Update only the period
* createDateFromSelection(10, 30, 'AM', '12h', undefined, undefined, 'PM')
* // → Date object with 10:30 PM
*
* @example
* // Use all current values (no overrides)
* createDateFromSelection(2, 15, 'PM', '12h')
* // → Date object with 2:15 PM
*/
var createDateFromSelection = function createDateFromSelection(currentHour, currentMinute, currentPeriod, timeFormat, hour, minute, period) {
var useHour = hour !== null && hour !== void 0 ? hour : currentHour;
var useMinute = minute !== null && minute !== void 0 ? minute : currentMinute;
var usePeriod = period !== null && period !== void 0 ? period : currentPeriod;
var result = createCompleteTime(useHour, useMinute, usePeriod, timeFormat);
// createCompleteTime can return null, but in TimePickerContent context we always expect a valid date
// If validation fails, fall back to current time to prevent crashes
return result !== null && result !== void 0 ? result : new Date();
};
/**
* Calculates the nearest step value for dropdown positioning when minuteStep is used
* Allows users to type any minute while dropdown shows nearest valid step
*
* This enables a better UX where typed values are preserved for form submission,
* but the dropdown visually aligns to the nearest step for consistency.
*
* @param actualValue - The actual minute value typed by user (0-59)
* @param step - The minute step interval (1, 5, 15, 30)
* @returns The nearest step value for dropdown positioning
*
* @example
* // 15-minute steps
* getNearestStepValue(17, 15)
* // → 15 (user typed 17, dropdown shows 15)
*
* @example
* // 30-minute steps
* getNearestStepValue(42, 30)
* // → 30 (user typed 42, dropdown shows 30)
*
* @example
* // 5-minute steps
* getNearestStepValue(23, 5)
* // → 25 (user typed 23, dropdown shows 25)
*
* @example
* // 1-minute steps (no change needed)
* getNearestStepValue(17, 1)
* // → 17 (exact match, no rounding)
*/
var getNearestStepValue = function getNearestStepValue(actualValue, step) {
var nearestValue = Math.round(actualValue / step) * step;
// If calculated value is 60 or more, wrap to 0 (since 60 minutes doesn't exist)
var finalValue = nearestValue >= 60 ? 0 : nearestValue;
return String(finalValue).padStart(2, '0');
};
export { createCompleteTime, createDateFromSelection, dateToTimeValue, getNearestStepValue, getTimeComponents, timeValueToDate };
//# sourceMappingURL=utils.js.map