140 lines
4.1 KiB
TypeScript
140 lines
4.1 KiB
TypeScript
|
|
/**
|
||
|
|
* @license
|
||
|
|
* Copyright Google LLC All Rights Reserved.
|
||
|
|
*
|
||
|
|
* Use of this source code is governed by an MIT-style license that can be
|
||
|
|
* found in the LICENSE file at https://angular.dev/license
|
||
|
|
*/
|
||
|
|
|
||
|
|
import {InjectionToken} from '@angular/core';
|
||
|
|
import {DateAdapter, MatDateFormats} from '@angular/material/core';
|
||
|
|
|
||
|
|
/** Pattern that interval strings have to match. */
|
||
|
|
const INTERVAL_PATTERN = /^(\d*\.?\d+)\s*(h|hour|hours|m|min|minute|minutes|s|second|seconds)?$/i;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Object that can be used to configure the default options for the timepicker component.
|
||
|
|
*/
|
||
|
|
export interface MatTimepickerConfig {
|
||
|
|
/** Default interval for all time pickers. */
|
||
|
|
interval?: string | number;
|
||
|
|
|
||
|
|
/** Whether ripples inside the timepicker should be disabled by default. */
|
||
|
|
disableRipple?: boolean;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Injection token that can be used to configure the default options for the timepicker component.
|
||
|
|
*/
|
||
|
|
export const MAT_TIMEPICKER_CONFIG = new InjectionToken<MatTimepickerConfig>(
|
||
|
|
'MAT_TIMEPICKER_CONFIG',
|
||
|
|
);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Time selection option that can be displayed within a `mat-timepicker`.
|
||
|
|
*/
|
||
|
|
export interface MatTimepickerOption<D = unknown> {
|
||
|
|
/** Date value of the option. */
|
||
|
|
value: D;
|
||
|
|
|
||
|
|
/** Label to show to the user. */
|
||
|
|
label: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Parses an interval value into seconds. */
|
||
|
|
export function parseInterval(value: number | string | null): number | null {
|
||
|
|
let result: number;
|
||
|
|
|
||
|
|
if (value === null) {
|
||
|
|
return null;
|
||
|
|
} else if (typeof value === 'number') {
|
||
|
|
result = value;
|
||
|
|
} else {
|
||
|
|
if (value.trim().length === 0) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
const parsed = value.match(INTERVAL_PATTERN);
|
||
|
|
const amount = parsed ? parseFloat(parsed[1]) : null;
|
||
|
|
const unit = parsed?.[2]?.toLowerCase() || null;
|
||
|
|
|
||
|
|
if (!parsed || amount === null || isNaN(amount)) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (unit === 'h' || unit === 'hour' || unit === 'hours') {
|
||
|
|
result = amount * 3600;
|
||
|
|
} else if (unit === 'm' || unit === 'min' || unit === 'minute' || unit === 'minutes') {
|
||
|
|
result = amount * 60;
|
||
|
|
} else {
|
||
|
|
result = amount;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Generates the options to show in a timepicker.
|
||
|
|
* @param adapter Date adapter to be used to generate the options.
|
||
|
|
* @param formats Formatting config to use when displaying the options.
|
||
|
|
* @param min Time from which to start generating the options.
|
||
|
|
* @param max Time at which to stop generating the options.
|
||
|
|
* @param interval Amount of seconds between each option.
|
||
|
|
*/
|
||
|
|
export function generateOptions<D>(
|
||
|
|
adapter: DateAdapter<D>,
|
||
|
|
formats: MatDateFormats,
|
||
|
|
min: D,
|
||
|
|
max: D,
|
||
|
|
interval: number,
|
||
|
|
): MatTimepickerOption<D>[] {
|
||
|
|
const options: MatTimepickerOption<D>[] = [];
|
||
|
|
let current = adapter.compareTime(min, max) < 1 ? min : max;
|
||
|
|
|
||
|
|
while (
|
||
|
|
adapter.sameDate(current, min) &&
|
||
|
|
adapter.compareTime(current, max) < 1 &&
|
||
|
|
adapter.isValid(current)
|
||
|
|
) {
|
||
|
|
options.push({value: current, label: adapter.format(current, formats.display.timeOptionLabel)});
|
||
|
|
current = adapter.addSeconds(current, interval);
|
||
|
|
}
|
||
|
|
|
||
|
|
return options;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Checks whether a date adapter is set up correctly for use with the timepicker. */
|
||
|
|
export function validateAdapter(
|
||
|
|
adapter: DateAdapter<unknown> | null,
|
||
|
|
formats: MatDateFormats | null,
|
||
|
|
) {
|
||
|
|
function missingAdapterError(provider: string) {
|
||
|
|
return Error(
|
||
|
|
`MatTimepicker: No provider found for ${provider}. You must add one of the following ` +
|
||
|
|
`to your app config: provideNativeDateAdapter, provideDateFnsAdapter, ` +
|
||
|
|
`provideLuxonDateAdapter, provideMomentDateAdapter, or provide a custom implementation.`,
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!adapter) {
|
||
|
|
throw missingAdapterError('DateAdapter');
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!formats) {
|
||
|
|
throw missingAdapterError('MAT_DATE_FORMATS');
|
||
|
|
}
|
||
|
|
|
||
|
|
if (
|
||
|
|
formats.display.timeInput === undefined ||
|
||
|
|
formats.display.timeOptionLabel === undefined ||
|
||
|
|
formats.parse.timeInput === undefined
|
||
|
|
) {
|
||
|
|
throw new Error(
|
||
|
|
'MatTimepicker: Incomplete `MAT_DATE_FORMATS` has been provided. ' +
|
||
|
|
'`MAT_DATE_FORMATS` must provide `display.timeInput`, `display.timeOptionLabel` ' +
|
||
|
|
'and `parse.timeInput` formats in order to be compatible with MatTimepicker.',
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|