import { type Maybe, type ArrayOrValue, type FilterFunction, type IndexRange, type ISO8601DayString, type IndexNumber, type GetterOrValue } from '@dereekb/util'; import { type DateCell, type DateCellIndex, type DateOrDateCellIndex, type DateCellTiming, type DateCellArrayRef, type DateCellArray, type DateCellTimingRangeInput, type DateCellCollection, type DateCellDurationSpan, type DateCellTimingStartsAt, type DateCellTimingEvent, type DateCellTimingStartsAtEndRange, type FullDateCellTiming } from './date.cell'; import { type DateCellRange, type DateCellRangeWithRange, type DateOrDateRangeOrDateCellIndexOrDateCellRange } from './date.cell.index'; import { type DateRange, type DateRangeStart } from './date.range'; import { type DateTimezoneConversionConfigUseSystemTimezone, type DateTimezoneUtcNormalInstance } from './date.timezone'; /** * Configuration for creating a {@link DateCellRangeOfTimingFactory} that converts dates or indexes * into a bounded {@link DateCellRangeWithRange} relative to a given timing schedule. * * Controls whether the output range is clamped to the timing's bounds and whether * only completed (fully elapsed) indexes are included. */ export interface DateCallIndexRangeFromDatesFactoryConfig { /** * Timing to use relative to the input. */ readonly timing: DateCellTiming; /** * Whether or not to fit the returned range to the timing's range. * * Defaults to true. */ readonly fitToTimingRange?: boolean; /** * Only include the index if the timing is marked as complete for that index. * * If no indexes have been completed, the returned value range will be -1 to -1. * * Defaults to false. */ readonly limitToCompletedIndexes?: boolean; /** * (Optional) now date/getter used to influence the limitToCompletedIndexes calculations. */ readonly now?: GetterOrValue; } /** * Input for {@link DateCellRangeOfTimingFactory}, specifying optional start and end boundaries * as either dates or cell indexes. */ export interface DateCellRangeOfTimingInput { /** * Start date or index */ readonly i?: Maybe; /** * End date or index */ readonly to?: Maybe; } /** * Factory function that produces a clamped {@link DateCellRangeWithRange} from optional start/end input. */ export type DateCellRangeOfTimingFactory = (input?: Maybe) => DateCellRangeWithRange; /** * Creates a {@link DateCellRangeOfTimingFactory} that converts dates or indexes into a clamped * {@link DateCellRangeWithRange} relative to the configured timing. * * When `fitToTimingRange` is true (default), the returned range is clamped to the timing's valid index bounds. * When `limitToCompletedIndexes` is true, only indexes whose timing duration has fully elapsed are included, * with the max boundary lazily refreshed as time passes. * * @param config - Configuration specifying the timing, range fit, and completion constraints. * @returns A factory function that produces a clamped {@link DateCellRangeWithRange} from optional start/end input. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, range, timing, factory, clamp, completed, index * @dbxUtilRelated date-cell-range-of-timing, date-cell-timing-completed-time-range, date-cell-index-range * * @example * ```ts * const timing = dateCellTiming({ startsAt, duration: 60 }, 5); * const factory = dateCellRangeOfTimingFactory({ timing }); * * // Clamp an arbitrary range to the timing's bounds (0..4) * const range = factory({ i: -10, to: 10 }); * // range.i === 0, range.to === 4 * * // With no input, defaults to 0..now * const defaultRange = factory(); * ``` * @__NO_SIDE_EFFECTS__ */ export declare function dateCellRangeOfTimingFactory(config: DateCallIndexRangeFromDatesFactoryConfig): DateCellRangeOfTimingFactory; /** * Computes a {@link DateCellRangeWithRange} from a timing and optional start/end input. * * Shorthand for creating a {@link dateCellRangeOfTimingFactory} and immediately invoking it. * * @param config - A {@link DateCellTiming} or full factory configuration. * @param input - Optional start/end boundaries for the range. * @returns A clamped {@link DateCellRangeWithRange} derived from the timing and input. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, range, timing, clamp, shorthand * @dbxUtilRelated date-cell-range-of-timing-factory, date-cell-timing-completed-time-range */ export declare function dateCellRangeOfTiming(config: DateCellTiming | DateCallIndexRangeFromDatesFactoryConfig, input?: Maybe): DateCellRangeWithRange; /** * Configuration subset for {@link dateCellTimingCompletedTimeRange}. */ export type DateCellTimingCompleteTimeRangeConfig = Pick; /** * Returns a {@link DateCellRangeWithRange} representing only the completed (fully elapsed) portion * of the timing schedule. Useful for determining which days have already finished. * * By default fitToTimingRange is true. * * @param timing - The timing schedule to evaluate. * @param config - Optional configuration for the current time reference and range fitting. * @returns A {@link DateCellRangeWithRange} covering only the completed day indexes. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, timing, completed, range, elapsed, index * @dbxUtilRelated date-cell-timing-latest-completed-index, date-cell-range-of-timing-factory */ export declare function dateCellTimingCompletedTimeRange(timing: DateCellTiming, config?: DateCellTimingCompleteTimeRangeConfig): DateCellRangeWithRange; /** * Returns the latest completed day index for a {@link DateCellTiming}. * * Returns -1 if no days have been completed yet. * * @param timing - The timing schedule to evaluate. * @param now - Optional reference time; defaults to the current time. * @returns The zero-based index of the last fully completed day, or -1 if none. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, timing, latest, completed, index, elapsed * @dbxUtilRelated date-cell-timing-completed-time-range, date-cell-timing-end-index */ export declare function dateCellTimingLatestCompletedIndex(timing: DateCellTiming, now?: Date): IndexNumber; /** * {@link IndexRange} used with DateCells. * * Unlike {@link DateCellRange} (which uses inclusive `to`), this uses an exclusive `maxIndex`, * making it compatible with standard index-range iteration patterns. */ export type DateCellIndexRange = IndexRange; /** * Converts a {@link DateCellRange} (inclusive `to`) to a {@link DateCellIndexRange} (exclusive `maxIndex`). * * @param range - The inclusive date cell range to convert. * @returns A {@link DateCellIndexRange} with exclusive `maxIndex`. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, range, index-range, convert, inclusive, exclusive * @dbxUtilRelated date-cell-index-range-to-date-cell-range, date-cell-index-range */ export declare function dateCellRangeToDateCellIndexRange(range: DateCellRange): DateCellIndexRange; /** * Converts a {@link DateCellIndexRange} (exclusive `maxIndex`) back to a {@link DateCellRangeWithRange} (inclusive `to`). * * @param range - The exclusive date cell index range to convert. * @returns A {@link DateCellRangeWithRange} with inclusive `to`. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, range, index-range, convert, exclusive, inclusive * @dbxUtilRelated date-cell-range-to-date-cell-index-range, date-cell-index-range */ export declare function dateCellIndexRangeToDateCellRange(range: DateCellIndexRange): DateCellRangeWithRange; /** * Generates a {@link DateCellIndexRange} based on the input timing. * * An arbitrary limit can also be applied. When `fitToTimingRange` is true (default), * the limit is intersected with the timing's own range; otherwise the limit is used as-is. * * @param timing - The timing schedule to derive the range from. * @param limit - Optional range input to constrain the output. * @param fitToTimingRange - Whether to intersect the limit with the timing's own range. Defaults to true. * @returns A {@link DateCellIndexRange} representing the computed index bounds. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, index-range, timing, bounds, limit, intersect * @dbxUtilRelated date-cell-range-to-date-cell-index-range, date-cell-index-range-to-date-cell-range */ export declare function dateCellIndexRange(timing: DateCellTiming, limit?: DateCellTimingRangeInput, fitToTimingRange?: boolean): DateCellIndexRange; /** * Expands a {@link DateCellCollection} into an array of {@link DateCellDurationSpan} values * by combining its timing and blocks. * * Shorthand for calling {@link expandDateCellTiming} with `collection.timing` and `collection.blocks`. * * @param collection - Collection whose timing and blocks should be expanded. * @returns Duration spans with concrete start times for each block. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, collection, expand, duration-span, blocks * @dbxUtilRelated expand-date-cell-timing, date-cell-timing-expansion-factory */ export declare function expandDateCellCollection(collection: DateCellCollection): DateCellDurationSpan[]; /** * Expands the given blocks into {@link DateCellDurationSpan} values using the provided timing. * * Shorthand for creating a {@link dateCellTimingExpansionFactory} and immediately invoking it. * * @param timing - Schedule providing start times and duration. * @param blocks - Blocks to expand into concrete duration spans. * @returns Duration spans with concrete start times. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, timing, expand, duration-span, blocks, shorthand * @dbxUtilRelated expand-date-cell-collection, date-cell-timing-expansion-factory */ export declare function expandDateCellTiming(timing: DateCellTiming, blocks: B[]): DateCellDurationSpan[]; /** * Input for a {@link DateCellTimingExpansionFactory}. Accepts either an array of blocks directly * or a reference object containing a `blocks` array. */ export type DateCellTimingExpansionFactoryInput = DateCellArrayRef | DateCellArray; /** * Factory function that converts {@link DateCellTimingExpansionFactoryInput} into an array of * {@link DateCellDurationSpan} values by computing the concrete startsAt date and duration * for each block relative to the configured timing. */ export type DateCellTimingExpansionFactory = (input: DateCellTimingExpansionFactoryInput) => DateCellDurationSpan[]; /** * Configuration for creating a {@link DateCellTimingExpansionFactory}. * * Provides control over range limiting, filtering, and output size limits to efficiently * expand date cell blocks into concrete duration spans. */ export interface DateCellTimingExpansionFactoryConfig { /** * Timing to use in the configuration. */ readonly timing: DateCellTiming; /** * Range to limit duration span output to. * * If not provided, uses the input timing's range. * If false, the timing's range is ignored too, and only the DateCellIndex values are considered. */ readonly rangeLimit?: DateCellTimingRangeInput | false; /** * Additional filter function to filter potential blocks in/out. */ readonly filter?: FilterFunction; /** * (Optional) Additional filter function based on the calcualted DateCellDurationSpan. */ readonly durationSpanFilter?: FilterFunction>; /** * (Optional) Max number of blocks to evaluate. */ readonly blocksEvaluationLimit?: number; /** * (Optional) Max number of DateCellDurationSpan values to return. */ readonly maxDateCellsToReturn?: number; } /** * Creates a {@link DateCellTimingExpansionFactory} that expands date cell blocks into * {@link DateCellDurationSpan} values with concrete start times and durations. * * Blocks with a range (`i` to `to`) are expanded into individual single-index entries. * Filtering is applied both at the block level and at the computed duration span level, * and evaluation can be capped for performance with large datasets. * * @param config - Configuration specifying the timing, range limits, filters, and output caps. * @returns A factory function that expands date cell blocks into {@link DateCellDurationSpan} arrays. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, timing, expansion, factory, blocks, duration-span, filter * @dbxUtilRelated expand-date-cell-collection, expand-date-cell-timing, date-cell-day-timing-info-factory * * @example * ```ts * const timing = dateCellTiming({ startsAt, duration: 60 }, 5); * const expand = dateCellTimingExpansionFactory({ timing }); * * const blocks: DateCell[] = [{ i: 0 }, { i: 1 }, { i: 2 }]; * const spans = expand(blocks); * // Each span has { i, startsAt, duration } with the concrete start time for that day * * // With range blocks: * const rangeBlocks = [{ i: 0, to: 2 }]; * const expandedSpans = expand(rangeBlocks); * // Produces 3 spans, one for each index 0, 1, 2 * ``` * @__NO_SIDE_EFFECTS__ */ export declare function dateCellTimingExpansionFactory(config: DateCellTimingExpansionFactoryConfig): DateCellTimingExpansionFactory; /** * Configuration subset for {@link dateCellDayTimingInfoFactory}, providing the timing * and optional range limit. */ export type DateCellDayTimingInfoFactoryConfig = Pick; /** * Detailed timing information for a specific day relative to a {@link DateCellTiming} schedule. * * Provides the computed index, progress state (in-progress, completed, upcoming), * and the concrete start/end times for the day's timing window. */ export interface DateCellDayTimingInfo { /** * Input date or calculated date if provided a dayIndex. */ readonly date: Date; /** * Index for the day for the input date. */ readonly dayIndex: DateCellIndex; /** * Index for the previous index/current index depending on the TimingInfo's daily execution. * * If the index is currently in progress given the timing, this will return the dayIndex. */ readonly currentIndex: DateCellIndex; /** * Index for the next execution. Does not check if it is in range. * * If the index is currently in progress given the timing, this will return the dayIndex + 1. */ readonly nextIndex: DateCellIndex; /** * Index for the next execution, if in the range, otherwise undefined. * * If the index is currently in progress given the timing, this will return the dayIndex + 1. */ readonly nextIndexInRange: Maybe; /** * Whether or not there are any inProgress or upcoming executions. * * True if nextIndexInRange is undefined and isInProgress is false. */ readonly isComplete: boolean; /** * Whether or not today's timing has already occured in it's entirety. */ readonly hasOccuredToday: boolean; /** * Whether or not a timing is currently in progress. * * This can be true when isInProgressForDayIndex is false for cases where the timing starts at the previous day index and rolls on over into the next day. */ readonly isInProgress: boolean; /** * Whether or not today's timing is currently in progress for the input dayIndex. */ readonly isInProgressForDayIndex: boolean; /** * Whether or not the block is within the configured range. */ readonly isInRange: boolean; /** * Time the timing starts on the input day. */ readonly startsAtOnDay: Date; /** * Time the timing ends on the input day. */ readonly endsAtOnDay: Date; /** * "now" value used for considering current progress. */ readonly now: Date; } /** * Factory that generates {@link DateCellDayTimingInfo} for any date or day index relative to * the configured timing schedule. * * Computes progress state even for dates outside the timing's range, which is useful * for UI elements that need to show timing context beyond the active schedule. * * The optional `now` parameter controls the reference time for in-progress calculations. */ export type DateCellDayTimingInfoFactory = ((date: DateOrDateCellIndex, now?: Date) => DateCellDayTimingInfo) & { readonly _indexFactory: DateCellTimingRelativeIndexFactory; readonly _startsAtFactory: DateCellTimingStartsAtDateFactory; }; /** * Creates a {@link DateCellDayTimingInfoFactory} that computes detailed timing information * (progress state, start/end times, range membership) for any given date or day index. * * The factory handles timezone normalization internally and accounts for edge cases * where a timing window spans midnight into the next day. * * @param config - Configuration providing the timing and optional range limit. * @returns A factory that computes {@link DateCellDayTimingInfo} for any date or day index. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, day, timing, info, factory, progress, in-progress, complete * @dbxUtilRelated date-cell-timing-relative-index-factory, date-cell-timing-expansion-factory, date-cell-timing-completed-time-range * * @example * ```ts * const timing = dateCellTiming({ startsAt, duration: 60 }, 5); * const infoFactory = dateCellDayTimingInfoFactory({ timing }); * * // Get info for day index 2 * const info = infoFactory(2, new Date()); * console.log(info.isInProgress); // whether day 2's window is currently active * console.log(info.startsAtOnDay); // concrete start time for day 2 * console.log(info.isInRange); // whether index 2 is within the timing's range * * // Get info for a specific date * const dateInfo = infoFactory(someDate); * console.log(dateInfo.dayIndex); // which day index this date falls on * ``` * * @__NO_SIDE_EFFECTS__ */ export declare function dateCellDayTimingInfoFactory(config: DateCellDayTimingInfoFactoryConfig): DateCellDayTimingInfoFactory; /** * Accepted input for {@link DateCellTimingRelativeIndexFactory}. Can be a Date (in system timezone), * a numeric DateCellIndex (passed through as-is), or an ISO8601DayString (parsed as UTC). */ export type DateCellTimingRelativeIndexFactoryInput = DateOrDateCellIndex | ISO8601DayString; /** * Factory function that computes the {@link DateCellIndex} of any input date relative to * the configured timing's start date. * * If a numeric index is passed, it is returned as-is. Dates are normalized through * the timing's timezone before computing the day offset. * * Exposes `_timing` and `_normalInstance` for downstream factories that need access * to the original timing configuration and timezone normalization. */ export type DateCellTimingRelativeIndexFactory = ((input: DateCellTimingRelativeIndexFactoryInput) => DateCellIndex) & { readonly _timing: T; readonly _normalInstance: DateTimezoneUtcNormalInstance; }; /** * Type guard that returns true if the input is a {@link DateCellTimingRelativeIndexFactory}. * * Checks for the presence of `_timing` and `_normalInstance` properties on a function. * * @param input - The value to check. * @returns True if the input is a {@link DateCellTimingRelativeIndexFactory}. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, timing, relative-index, factory, type-guard, check * @dbxUtilRelated date-cell-timing-relative-index-factory * @__NO_SIDE_EFFECTS__ */ export declare function isDateCellTimingRelativeIndexFactory(input: unknown): input is DateCellTimingRelativeIndexFactory; /** * Creates a {@link DateCellTimingRelativeIndexFactory} that converts dates, ISO8601 day strings, * or indexes into a zero-based day index relative to the timing's start date. * * If an existing factory is passed, it is returned as-is (idempotent). The factory normalizes * all date inputs through UTC to handle timezone offsets correctly, computing the floor * of the hour difference divided by 24 to determine the day offset. * * @param input - A timing configuration or an existing factory (returned as-is). * @returns A factory that converts dates, ISO8601 day strings, or indexes to zero-based day offsets. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, timing, relative-index, factory, day-offset, iso8601, timezone * @dbxUtilRelated is-date-cell-timing-relative-index-factory, get-relative-index-for-date-cell-timing, date-cell-timing-relative-index-array-factory * * @example * ```ts * const timing = dateCellTiming({ startsAt, duration: 60 }, 5); * const indexFactory = dateCellTimingRelativeIndexFactory(timing); * * // Numeric indexes pass through unchanged * indexFactory(3); // 3 * * // Dates are converted to their day offset from timing start * indexFactory(addDays(startsAt, 2)); // 2 * * // ISO8601 day strings are also supported * indexFactory('2024-01-15'); // day offset from timing start * * // Access the underlying timing and normalizer * indexFactory._timing; // the original timing * indexFactory._normalInstance; // timezone normalizer * ``` * * @__NO_SIDE_EFFECTS__ */ export declare function dateCellTimingRelativeIndexFactory(input: T | DateCellTimingRelativeIndexFactory): DateCellTimingRelativeIndexFactory; /** * Batch-conversion variant of {@link DateCellTimingRelativeIndexFactory} that accepts * multiple Date, DateCellIndex, DateRange, or DateCellRange values and flattens them * into an array of {@link DateCellIndex} values. * * Ranges are expanded into all contained indexes. */ export type DateCellTimingRelativeIndexArrayFactory = ((input: ArrayOrValue) => DateCellIndex[]) & { readonly _indexFactory: DateCellTimingRelativeIndexFactory; }; /** * Creates a {@link DateCellTimingRelativeIndexArrayFactory} that converts mixed arrays of * dates, date ranges, and cell ranges into a flat array of day indexes. * * Date ranges and cell ranges are expanded to include every index within the range. * * @param indexFactory - The relative index factory used for date-to-index conversion. * @returns A factory that flattens mixed date/range arrays into day index arrays. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, timing, relative-index, array, factory, expand, range * @dbxUtilRelated date-cell-timing-relative-index-factory, date-cell-index-range * @__NO_SIDE_EFFECTS__ */ export declare function dateCellTimingRelativeIndexArrayFactory(indexFactory: DateCellTimingRelativeIndexFactory): DateCellTimingRelativeIndexArrayFactory; /** * Convenience function that returns the zero-based day index for a date (or index) * relative to the given timing's start. * * Defaults to the current date/time if no date is provided. * * @param timing - The timing providing the start date and timezone context. * @param date - Moment to convert; defaults to the current date/time. * @returns The zero-based day index relative to the timing's start. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, timing, relative-index, day-offset, shorthand * @dbxUtilRelated date-cell-timing-relative-index-factory, get-relative-date-for-date-cell-timing * * @example * ```ts * const timing: DateCellTimingStartsAt = { startsAt, timezone: 'America/Denver' }; * * // Get today's index relative to the timing * const todayIndex = getRelativeIndexForDateCellTiming(timing); * * // Get the index for a specific date * const index = getRelativeIndexForDateCellTiming(timing, someDate); * ``` */ export declare function getRelativeIndexForDateCellTiming(timing: DateCellTimingStartsAt, date?: DateOrDateCellIndex): DateCellIndex; /** * Inverse of {@link DateCellTimingRelativeIndexFactory}. Given a day index, returns a Date * with the current time-of-day ("now") placed on the calendar date corresponding to that index. * * If a Date is passed instead of an index, it is returned as-is. */ export type DateCellTimingDateFactory = ((input: DateOrDateCellIndex, now?: Date) => Date) & { readonly _timing: T; }; /** * Creates a {@link DateCellTimingDateFactory} that maps day indexes to calendar dates * while preserving the current time-of-day. * * This is useful when you need the actual Date for a given index (e.g., for display or * date arithmetic) but want to retain the hours/minutes of "now" rather than using * the timing's startsAt time. * * @param timing - The timing providing the start date and timezone context. * @returns A factory that maps day indexes to calendar dates preserving the current time-of-day. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, timing, date, factory, day-index, calendar, time-of-day * @dbxUtilRelated date-cell-timing-start-date-factory, date-cell-timing-starts-at-date-factory, get-relative-date-for-date-cell-timing * * @example * ```ts * const timing = dateCellTiming({ startsAt, duration: 60 }, 5); * const dateFactory = dateCellTimingDateFactory(timing); * * // Pass through dates unchanged * dateFactory(someDate); // returns someDate * * // Convert index 3 to a date with current time-of-day * const dateForDay3 = dateFactory(3); * * // Convert index 3 to a date with a specific reference time * const dateForDay3AtNoon = dateFactory(3, noonDate); * ``` * * @__NO_SIDE_EFFECTS__ */ export declare function dateCellTimingDateFactory(timing: T): DateCellTimingDateFactory; /** * Returns the last (maximum) day index for a {@link DateCellTiming} schedule. * * This is the index corresponding to the timing's `end` date, representing the final * day in the schedule. * * @param input - A timing or an existing relative index factory. * @returns The zero-based index of the last day in the schedule. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, timing, end, index, last * @dbxUtilRelated date-cell-timing-relative-index-factory, date-cell-timing-end-date-factory, date-cell-timing-latest-completed-index * * @example * ```ts * const timing = dateCellTiming({ startsAt, duration: 60 }, 5); * const lastIndex = dateCellTimingEndIndex(timing); // 4 (zero-based, 5 days) * ``` */ export declare function dateCellTimingEndIndex(input: DateCellTiming | DateCellTimingRelativeIndexFactory): IndexNumber; /** * Factory function that returns the calendar start-of-day date for a given day index or date input. * * Unlike {@link DateCellTimingStartsAtDateFactory}, this returns the start of the day (midnight-equivalent * in the timing's timezone) rather than the event's startsAt time. */ export type DateCellTimingStartDateFactory = ((input: DateCellTimingRelativeIndexFactoryInput) => Date) & { readonly _indexFactory: DateCellTimingRelativeIndexFactory; }; /** * Configuration that uses the system timezone and skips timezone assertion enforcement. */ export type DateCellTimingUseSystemAndIgnoreEnforcement = DateTimezoneConversionConfigUseSystemTimezone & { /** * Skips the assertion that the timezone matches. This defaults to true if not provided. */ assertTimingMatchesTimezone: false; }; /** * Creates a {@link DateCellTimingStartDateFactory} that computes the calendar start-of-day date * for any day index relative to the timing's start. * * The returned date represents the beginning of the day in the timing's timezone context. * * @param input - A timing or an existing relative index factory. * @returns A factory that maps day indexes to the start-of-day date in the timing's timezone. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, timing, start-of-day, factory, day-index, calendar, timezone * @dbxUtilRelated date-cell-timing-starts-at-date-factory, date-cell-timing-end-date-factory, date-cell-timing-date-factory * @__NO_SIDE_EFFECTS__ */ export declare function dateCellTimingStartDateFactory(input: T | DateCellTimingRelativeIndexFactory): DateCellTimingStartDateFactory; /** * Factory function that returns the concrete `startsAt` time (the event's actual start time * within the day) for a given day index or date input. * * This differs from {@link DateCellTimingStartDateFactory} in that it returns the event time * (e.g., 2:00 PM) rather than the calendar day boundary. */ export type DateCellTimingStartsAtDateFactory = ((input: DateCellTimingRelativeIndexFactoryInput) => Date) & { readonly _indexFactory: DateCellTimingRelativeIndexFactory; }; /** * Creates a {@link DateCellTimingStartsAtDateFactory} that computes the concrete event start time * for any day index relative to the timing's schedule. * * The returned date reflects the actual `startsAt` time-of-day offset to the correct calendar date * for the requested index, with proper timezone normalization. * * @example * ```ts * const timing = dateCellTiming({ startsAt, duration: 60 }, 5); * const startsAtFactory = dateCellTimingStartsAtDateFactory(timing); * * // Get the exact start time for day 3 * const day3Start = startsAtFactory(3); * // Returns a Date with the same time-of-day as startsAt but on day 3's calendar date * * // Also works with dates * const startForDate = startsAtFactory(someDate); * ``` * * @param input - A timing or an existing relative index factory. * @returns A factory that computes the concrete event start time for any day index. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, timing, starts-at, factory, day-index, event-time, calendar * @dbxUtilRelated date-cell-timing-start-date-factory, date-cell-timing-end-date-factory, date-cell-timing-date-factory * @__NO_SIDE_EFFECTS__ */ export declare function dateCellTimingStartsAtDateFactory(input: T | DateCellTimingRelativeIndexFactory): DateCellTimingStartsAtDateFactory; /** * Factory function that returns the end time (startsAt + duration) for a given day index or date input. * * Combines {@link DateCellTimingStartsAtDateFactory} with the timing's duration to compute * when the event window closes on any given day. */ export type DateCellTimingEndDateFactory = ((input: DateCellTimingRelativeIndexFactoryInput) => Date) & { readonly _startsAtDateFactory: DateCellTimingStartsAtDateFactory; }; /** * Creates a {@link DateCellTimingEndDateFactory} that computes the end time * (startsAt + duration) for any day index relative to the timing's schedule. * * @example * ```ts * const timing = dateCellTiming({ startsAt, duration: 60 }, 5); * const endFactory = dateCellTimingEndDateFactory(timing); * * // Get the end time for day 2 (startsAt time + 60 minutes on day 2) * const day2End = endFactory(2); * ``` * * @param input - A timing or an existing relative index factory. * @returns A factory that computes the end time (startsAt + duration) for any day index. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, timing, end, factory, day-index, duration, event-time * @dbxUtilRelated date-cell-timing-starts-at-date-factory, date-cell-timing-start-date-factory * @__NO_SIDE_EFFECTS__ */ export declare function dateCellTimingEndDateFactory(input: T | DateCellTimingRelativeIndexFactory): DateCellTimingEndDateFactory; /** * Convenience function that returns the calendar date for a given day index or date * relative to the timing. Shorthand for creating a {@link dateCellTimingDateFactory} and invoking it. * * @param timing - The timing providing the start date and timezone context. * @param input - Moment or day-index to resolve to a calendar date. * @returns The calendar date corresponding to the input, preserving current time-of-day. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, timing, relative-date, day-index, calendar, shorthand * @dbxUtilRelated date-cell-timing-date-factory, get-relative-index-for-date-cell-timing */ export declare function getRelativeDateForDateCellTiming(timing: DateCellTimingStartsAt, input: DateOrDateCellIndex): Date; /** * Configuration for {@link updateDateCellTimingWithDateCellTimingEvent}. * * Controls which aspects of a timing (start day, start time, end day, duration) * are replaced by values from a {@link DateCellTimingEvent}. */ export interface UpdateDateCellTimingWithDateCellTimingEventInput { /** * Target timing to update. */ readonly timing: DateCellTimingStartsAtEndRange; /** * Event used to update the timing. */ readonly event: DateCellTimingEvent; /** * Custom start date day to use instead of the event's start date. * * It is generated relative to the timing's current startsAt, and not the event's starts at, so index 0 is the first day of the Timing, not the event. * * Ignored if replaceStartDay is not true. */ readonly startDayDate?: DateCellTimingRelativeIndexFactoryInput; /** * Replaces the start date but keeps the startsAt time as-is. * * Can be combined with replaceStartsAt. */ readonly replaceStartDay?: boolean; /** * Replaces the startsAt time, but keeps the initial start date. * * Can be combined with replaceStartDay */ readonly replaceStartsAt?: boolean; /** * Replaces the end day but keeps the same time. */ readonly endOnEvent?: boolean; /** * Replaces the duration but keeps the end day intact. */ readonly replaceDuration?: boolean; } /** * Produces a new {@link FullDateCellTiming} by selectively replacing parts of an existing timing * with values from a {@link DateCellTimingEvent}. * * This is the primary mechanism for updating a timing schedule in response to user edits. * The `replaceStartDay`, `replaceStartsAt`, `endOnEvent`, and `replaceDuration` flags * independently control which aspects of the timing are modified, and can be combined. * * When both `replaceStartDay` and `replaceStartsAt` are true, the event's startsAt is used directly. * When only `replaceStartDay` is true, the day changes but the time-of-day is preserved. * When only `replaceStartsAt` is true, the time-of-day changes but the calendar date is preserved. * * @param input - Configuration specifying the timing to update, the event source, and which aspects to replace. * @returns A new {@link FullDateCellTiming} with the requested aspects replaced. * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, timing, event, update, replace, modify, edit * @dbxUtilRelated date-cell-timing-starts-at-date-factory, date-cell-timing-start-date-factory * * @example * ```ts * const result = updateDateCellTimingWithDateCellTimingEvent({ * timing: existingTiming, * event: { startsAt: newStartTime, duration: 90 }, * replaceStartsAt: true, * replaceDuration: true * }); * // result has the same start day and end day, but new time-of-day and 90-minute duration * ``` */ export declare function updateDateCellTimingWithDateCellTimingEvent(input: UpdateDateCellTimingWithDateCellTimingEventInput): FullDateCellTiming; /** * Union of input types accepted by {@link IsDateWithinDateCellRangeFunction}. * Supports raw dates, indexes, date ranges, and cell ranges for flexible containment checks. */ export type IsDateWithinDateCellRangeInput = DateOrDateCellIndex | DateRangeStart | DateRange | DateCell | DateCellRange; /** * Predicate function that returns true if the input date, index, or range falls entirely * within the configured reference range. */ export type IsDateWithinDateCellRangeFunction = (input: IsDateWithinDateCellRangeInput) => boolean; /** * Configuration for {@link isDateWithinDateCellRangeFunction}. * * The `startsAt` provides timezone context for converting dates to indexes. * If omitted and the range is a single Date, the system timezone is used; * otherwise an error is thrown since date-to-index conversion requires timezone info. */ export interface IsDateWithinDateCellRangeConfig { /** * Optional DateCellTimingStartsAt to make the indexes relative to when converting date values. * * If not provided, defaults to the index in the range if a date is provided with the system timezone, or throws an exception if a date range is input. */ readonly startsAt?: DateCellTimingStartsAt; /** * Range to compare the input to. */ readonly range: IsDateWithinDateCellRangeInput; } /** * Creates a predicate that checks whether a date, index, or range falls within * the configured reference range. * * Converts all date-based inputs to cell indexes using the configured (or inferred) timezone * before performing the containment check. * * @param config - Configuration specifying the reference range and optional timezone context. * @returns A predicate function that checks containment within the configured range. * @throws {Error} If `startsAt` is not provided and cannot be inferred from the range input * (e.g., when a DateRange without a single-date range is used without explicit startsAt). * * @dbxUtil * @dbxUtilCategory date * @dbxUtilTags date, cell, range, contains, within, predicate, factory, check * @dbxUtilRelated date-cell-timing-relative-index-factory, date-cell-index-range * * @example * ```ts * const isInRange = isDateWithinDateCellRangeFunction({ * startsAt: timing, * range: { i: 2, to: 5 } * }); * * isInRange(3); // true - index 3 is within [2, 5] * isInRange(6); // false - index 6 is outside [2, 5] * isInRange(someDate); // converts date to index, then checks containment * ``` * * @__NO_SIDE_EFFECTS__ */ export declare function isDateWithinDateCellRangeFunction(config: IsDateWithinDateCellRangeConfig): IsDateWithinDateCellRangeFunction;