UNPKG

@angular/material

Version:
1 lines 71.5 kB
{"version":3,"file":"timepicker.mjs","sources":["../../../../../k8-fastbuild-ST-46c76129e412/bin/src/material/timepicker/util.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/src/material/timepicker/timepicker.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/src/material/timepicker/timepicker.html","../../../../../k8-fastbuild-ST-46c76129e412/bin/src/material/timepicker/timepicker-input.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/src/material/timepicker/timepicker-toggle.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/src/material/timepicker/timepicker-toggle.html","../../../../../k8-fastbuild-ST-46c76129e412/bin/src/material/timepicker/timepicker-module.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport {InjectionToken} from '@angular/core';\nimport {DateAdapter, MatDateFormats} from '../core';\n\n/** Pattern that interval strings have to match. */\nconst INTERVAL_PATTERN = /^(\\d*\\.?\\d+)\\s*(h|hour|hours|m|min|minute|minutes|s|second|seconds)?$/i;\n\n/**\n * Object that can be used to configure the default options for the timepicker component.\n */\nexport interface MatTimepickerConfig {\n /** Default interval for all time pickers. */\n interval?: string | number;\n\n /** Whether ripples inside the timepicker should be disabled by default. */\n disableRipple?: boolean;\n}\n\n/**\n * Injection token that can be used to configure the default options for the timepicker component.\n */\nexport const MAT_TIMEPICKER_CONFIG = new InjectionToken<MatTimepickerConfig>(\n 'MAT_TIMEPICKER_CONFIG',\n);\n\n/**\n * Time selection option that can be displayed within a `mat-timepicker`.\n */\nexport interface MatTimepickerOption<D = unknown> {\n /** Date value of the option. */\n value: D;\n\n /** Label to show to the user. */\n label: string;\n}\n\n/** Parses an interval value into seconds. */\nexport function parseInterval(value: number | string | null): number | null {\n let result: number;\n\n if (value === null) {\n return null;\n } else if (typeof value === 'number') {\n result = value;\n } else {\n if (value.trim().length === 0) {\n return null;\n }\n\n const parsed = value.match(INTERVAL_PATTERN);\n const amount = parsed ? parseFloat(parsed[1]) : null;\n const unit = parsed?.[2]?.toLowerCase() || null;\n\n if (!parsed || amount === null || isNaN(amount)) {\n return null;\n }\n\n if (unit === 'h' || unit === 'hour' || unit === 'hours') {\n result = amount * 3600;\n } else if (unit === 'm' || unit === 'min' || unit === 'minute' || unit === 'minutes') {\n result = amount * 60;\n } else {\n result = amount;\n }\n }\n\n return result;\n}\n\n/**\n * Generates the options to show in a timepicker.\n * @param adapter Date adapter to be used to generate the options.\n * @param formats Formatting config to use when displaying the options.\n * @param min Time from which to start generating the options.\n * @param max Time at which to stop generating the options.\n * @param interval Amount of seconds between each option.\n */\nexport function generateOptions<D>(\n adapter: DateAdapter<D>,\n formats: MatDateFormats,\n min: D,\n max: D,\n interval: number,\n): MatTimepickerOption<D>[] {\n const options: MatTimepickerOption<D>[] = [];\n let current = adapter.compareTime(min, max) < 1 ? min : max;\n\n while (\n adapter.sameDate(current, min) &&\n adapter.compareTime(current, max) < 1 &&\n adapter.isValid(current)\n ) {\n options.push({value: current, label: adapter.format(current, formats.display.timeOptionLabel)});\n current = adapter.addSeconds(current, interval);\n }\n\n return options;\n}\n\n/** Checks whether a date adapter is set up correctly for use with the timepicker. */\nexport function validateAdapter(\n adapter: DateAdapter<unknown> | null,\n formats: MatDateFormats | null,\n) {\n function missingAdapterError(provider: string) {\n return Error(\n `MatTimepicker: No provider found for ${provider}. You must add one of the following ` +\n `to your app config: provideNativeDateAdapter, provideDateFnsAdapter, ` +\n `provideLuxonDateAdapter, provideMomentDateAdapter, or provide a custom implementation.`,\n );\n }\n\n if (!adapter) {\n throw missingAdapterError('DateAdapter');\n }\n\n if (!formats) {\n throw missingAdapterError('MAT_DATE_FORMATS');\n }\n\n if (\n formats.display.timeInput === undefined ||\n formats.display.timeOptionLabel === undefined ||\n formats.parse.timeInput === undefined\n ) {\n throw new Error(\n 'MatTimepicker: Incomplete `MAT_DATE_FORMATS` has been provided. ' +\n '`MAT_DATE_FORMATS` must provide `display.timeInput`, `display.timeOptionLabel` ' +\n 'and `parse.timeInput` formats in order to be compatible with MatTimepicker.',\n );\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport {\n afterNextRender,\n AfterRenderRef,\n ANIMATION_MODULE_TYPE,\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n ElementRef,\n inject,\n InjectionToken,\n Injector,\n input,\n InputSignal,\n InputSignalWithTransform,\n OnDestroy,\n output,\n OutputEmitterRef,\n Signal,\n signal,\n TemplateRef,\n untracked,\n viewChild,\n viewChildren,\n ViewContainerRef,\n ViewEncapsulation,\n} from '@angular/core';\nimport {\n DateAdapter,\n MAT_DATE_FORMATS,\n MAT_OPTION_PARENT_COMPONENT,\n MatOption,\n MatOptionParentComponent,\n} from '../core';\nimport {Directionality} from '@angular/cdk/bidi';\nimport {Overlay, OverlayRef, ScrollStrategy} from '@angular/cdk/overlay';\nimport {TemplatePortal} from '@angular/cdk/portal';\nimport {_getEventTarget} from '@angular/cdk/platform';\nimport {ENTER, ESCAPE, hasModifierKey, TAB} from '@angular/cdk/keycodes';\nimport {_IdGenerator, ActiveDescendantKeyManager} from '@angular/cdk/a11y';\nimport type {MatTimepickerInput} from './timepicker-input';\nimport {\n generateOptions,\n MAT_TIMEPICKER_CONFIG,\n MatTimepickerOption,\n parseInterval,\n validateAdapter,\n} from './util';\nimport {Subscription} from 'rxjs';\n\n/** Event emitted when a value is selected in the timepicker. */\nexport interface MatTimepickerSelected<D> {\n value: D;\n source: MatTimepicker<D>;\n}\n\n/** Injection token used to configure the behavior of the timepicker dropdown while scrolling. */\nexport const MAT_TIMEPICKER_SCROLL_STRATEGY = new InjectionToken<() => ScrollStrategy>(\n 'MAT_TIMEPICKER_SCROLL_STRATEGY',\n {\n providedIn: 'root',\n factory: () => {\n const overlay = inject(Overlay);\n return () => overlay.scrollStrategies.reposition();\n },\n },\n);\n\n/**\n * Renders out a listbox that can be used to select a time of day.\n * Intended to be used together with `MatTimepickerInput`.\n */\n@Component({\n selector: 'mat-timepicker',\n exportAs: 'matTimepicker',\n templateUrl: 'timepicker.html',\n styleUrl: 'timepicker.css',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [MatOption],\n providers: [\n {\n provide: MAT_OPTION_PARENT_COMPONENT,\n useExisting: MatTimepicker,\n },\n ],\n})\nexport class MatTimepicker<D> implements OnDestroy, MatOptionParentComponent {\n private _overlay = inject(Overlay);\n private _dir = inject(Directionality, {optional: true});\n private _viewContainerRef = inject(ViewContainerRef);\n private _injector = inject(Injector);\n private _defaultConfig = inject(MAT_TIMEPICKER_CONFIG, {optional: true});\n private _dateAdapter = inject<DateAdapter<D>>(DateAdapter, {optional: true})!;\n private _dateFormats = inject(MAT_DATE_FORMATS, {optional: true})!;\n private _scrollStrategyFactory = inject(MAT_TIMEPICKER_SCROLL_STRATEGY);\n protected _animationsDisabled =\n inject(ANIMATION_MODULE_TYPE, {optional: true}) === 'NoopAnimations';\n\n private _isOpen = signal(false);\n private _activeDescendant = signal<string | null>(null);\n\n private _input = signal<MatTimepickerInput<D> | null>(null);\n private _overlayRef: OverlayRef | null = null;\n private _portal: TemplatePortal<unknown> | null = null;\n private _optionsCacheKey: string | null = null;\n private _localeChanges: Subscription;\n private _onOpenRender: AfterRenderRef | null = null;\n\n protected _panelTemplate = viewChild.required<TemplateRef<unknown>>('panelTemplate');\n protected _timeOptions: readonly MatTimepickerOption<D>[] = [];\n protected _options = viewChildren(MatOption);\n\n private _keyManager = new ActiveDescendantKeyManager(this._options, this._injector)\n .withHomeAndEnd(true)\n .withPageUpDown(true)\n .withVerticalOrientation(true);\n\n /**\n * Interval between each option in the timepicker. The value can either be an amount of\n * seconds (e.g. 90) or a number with a unit (e.g. 45m). Supported units are `s` for seconds,\n * `m` for minutes or `h` for hours.\n */\n readonly interval: InputSignalWithTransform<number | null, number | string | null> = input(\n parseInterval(this._defaultConfig?.interval || null),\n {transform: parseInterval},\n );\n\n /**\n * Array of pre-defined options that the user can select from, as an alternative to using the\n * `interval` input. An error will be thrown if both `options` and `interval` are specified.\n */\n readonly options: InputSignal<readonly MatTimepickerOption<D>[] | null> = input<\n readonly MatTimepickerOption<D>[] | null\n >(null);\n\n /** Whether the timepicker is open. */\n readonly isOpen: Signal<boolean> = this._isOpen.asReadonly();\n\n /** Emits when the user selects a time. */\n readonly selected: OutputEmitterRef<MatTimepickerSelected<D>> = output();\n\n /** Emits when the timepicker is opened. */\n readonly opened: OutputEmitterRef<void> = output();\n\n /** Emits when the timepicker is closed. */\n readonly closed: OutputEmitterRef<void> = output();\n\n /** ID of the active descendant option. */\n readonly activeDescendant: Signal<string | null> = this._activeDescendant.asReadonly();\n\n /** Unique ID of the timepicker's panel */\n readonly panelId: string = inject(_IdGenerator).getId('mat-timepicker-panel-');\n\n /** Whether ripples within the timepicker should be disabled. */\n readonly disableRipple: InputSignalWithTransform<boolean, unknown> = input(\n this._defaultConfig?.disableRipple ?? false,\n {\n transform: booleanAttribute,\n },\n );\n\n /** ARIA label for the timepicker panel. */\n readonly ariaLabel: InputSignal<string | null> = input<string | null>(null, {\n alias: 'aria-label',\n });\n\n /** ID of the label element for the timepicker panel. */\n readonly ariaLabelledby: InputSignal<string | null> = input<string | null>(null, {\n alias: 'aria-labelledby',\n });\n\n /** Whether the timepicker is currently disabled. */\n readonly disabled: Signal<boolean> = computed(() => !!this._input()?.disabled());\n\n constructor() {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n validateAdapter(this._dateAdapter, this._dateFormats);\n\n effect(() => {\n const options = this.options();\n const interval = this.interval();\n\n if (options !== null && interval !== null) {\n throw new Error(\n 'Cannot specify both the `options` and `interval` inputs at the same time',\n );\n } else if (options?.length === 0) {\n throw new Error('Value of `options` input cannot be an empty array');\n }\n });\n }\n\n // Since the panel ID is static, we can set it once without having to maintain a host binding.\n const element = inject<ElementRef<HTMLElement>>(ElementRef);\n element.nativeElement.setAttribute('mat-timepicker-panel-id', this.panelId);\n this._handleLocaleChanges();\n this._handleInputStateChanges();\n this._keyManager.change.subscribe(() =>\n this._activeDescendant.set(this._keyManager.activeItem?.id || null),\n );\n }\n\n /** Opens the timepicker. */\n open(): void {\n const input = this._input();\n\n if (!input) {\n return;\n }\n\n // Focus should already be on the input, but this call is in case the timepicker is opened\n // programmatically. We need to call this even if the timepicker is already open, because\n // the user might be clicking the toggle.\n input.focus();\n\n if (this._isOpen()) {\n return;\n }\n\n this._isOpen.set(true);\n this._generateOptions();\n const overlayRef = this._getOverlayRef();\n overlayRef.updateSize({width: input.getOverlayOrigin().nativeElement.offsetWidth});\n this._portal ??= new TemplatePortal(this._panelTemplate(), this._viewContainerRef);\n\n // We need to check this in case `isOpen` was flipped, but change detection hasn't\n // had a chance to run yet. See https://github.com/angular/components/issues/30637\n if (!overlayRef.hasAttached()) {\n overlayRef.attach(this._portal);\n }\n\n this._onOpenRender?.destroy();\n this._onOpenRender = afterNextRender(\n () => {\n const options = this._options();\n this._syncSelectedState(input.value(), options, options[0]);\n this._onOpenRender = null;\n },\n {injector: this._injector},\n );\n\n this.opened.emit();\n }\n\n /** Closes the timepicker. */\n close(): void {\n if (this._isOpen()) {\n this._isOpen.set(false);\n this.closed.emit();\n\n if (this._animationsDisabled) {\n this._overlayRef?.detach();\n }\n }\n }\n\n /** Registers an input with the timepicker. */\n registerInput(input: MatTimepickerInput<D>): void {\n const currentInput = this._input();\n\n if (currentInput && input !== currentInput && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n throw new Error('MatTimepicker can only be registered with one input at a time');\n }\n\n this._input.set(input);\n }\n\n ngOnDestroy(): void {\n this._keyManager.destroy();\n this._localeChanges.unsubscribe();\n this._onOpenRender?.destroy();\n this._overlayRef?.dispose();\n }\n\n /** Selects a specific time value. */\n protected _selectValue(option: MatOption<D>) {\n this.close();\n this._keyManager.setActiveItem(option);\n this._options().forEach(current => {\n // This is primarily here so we don't show two selected options while animating away.\n if (current !== option) {\n current.deselect(false);\n }\n });\n this.selected.emit({value: option.value, source: this});\n this._input()?.focus();\n }\n\n /** Gets the value of the `aria-labelledby` attribute. */\n protected _getAriaLabelledby(): string | null {\n if (this.ariaLabel()) {\n return null;\n }\n return this.ariaLabelledby() || this._input()?._getLabelId() || null;\n }\n\n /** Handles animation events coming from the panel. */\n protected _handleAnimationEnd(event: AnimationEvent) {\n if (event.animationName === '_mat-timepicker-exit') {\n this._overlayRef?.detach();\n }\n }\n\n /** Creates an overlay reference for the timepicker panel. */\n private _getOverlayRef(): OverlayRef {\n if (this._overlayRef) {\n return this._overlayRef;\n }\n\n const positionStrategy = this._overlay\n .position()\n .flexibleConnectedTo(this._input()!.getOverlayOrigin())\n .withFlexibleDimensions(false)\n .withPush(false)\n .withTransformOriginOn('.mat-timepicker-panel')\n .withPositions([\n {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'top',\n },\n {\n originX: 'start',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'bottom',\n panelClass: 'mat-timepicker-above',\n },\n ]);\n\n this._overlayRef = this._overlay.create({\n positionStrategy,\n scrollStrategy: this._scrollStrategyFactory(),\n direction: this._dir || 'ltr',\n hasBackdrop: false,\n });\n\n this._overlayRef.detachments().subscribe(() => this.close());\n this._overlayRef.keydownEvents().subscribe(event => this._handleKeydown(event));\n this._overlayRef.outsidePointerEvents().subscribe(event => {\n const target = _getEventTarget(event) as HTMLElement;\n const origin = this._input()?.getOverlayOrigin().nativeElement;\n\n if (target && origin && target !== origin && !origin.contains(target)) {\n this.close();\n }\n });\n\n return this._overlayRef;\n }\n\n /** Generates the list of options from which the user can select.. */\n private _generateOptions(): void {\n // Default the interval to 30 minutes.\n const interval = this.interval() ?? 30 * 60;\n const options = this.options();\n\n if (options !== null) {\n this._timeOptions = options;\n } else {\n const input = this._input();\n const adapter = this._dateAdapter;\n const timeFormat = this._dateFormats.display.timeInput;\n const min = input?.min() || adapter.setTime(adapter.today(), 0, 0, 0);\n const max = input?.max() || adapter.setTime(adapter.today(), 23, 59, 0);\n const cacheKey =\n interval + '/' + adapter.format(min, timeFormat) + '/' + adapter.format(max, timeFormat);\n\n // Don't re-generate the options if the inputs haven't changed.\n if (cacheKey !== this._optionsCacheKey) {\n this._optionsCacheKey = cacheKey;\n this._timeOptions = generateOptions(adapter, this._dateFormats, min, max, interval);\n }\n }\n }\n\n /**\n * Synchronizes the internal state of the component based on a specific selected date.\n * @param value Currently selected date.\n * @param options Options rendered out in the timepicker.\n * @param fallback Option to set as active if no option is selected.\n */\n private _syncSelectedState(\n value: D | null,\n options: readonly MatOption[],\n fallback: MatOption | null,\n ): void {\n let hasSelected = false;\n\n for (const option of options) {\n if (value && this._dateAdapter.sameTime(option.value, value)) {\n option.select(false);\n scrollOptionIntoView(option, 'center');\n untracked(() => this._keyManager.setActiveItem(option));\n hasSelected = true;\n } else {\n option.deselect(false);\n }\n }\n\n // If no option was selected, we need to reset the key manager since\n // it might be holding onto an option that no longer exists.\n if (!hasSelected) {\n if (fallback) {\n untracked(() => this._keyManager.setActiveItem(fallback));\n scrollOptionIntoView(fallback, 'center');\n } else {\n untracked(() => this._keyManager.setActiveItem(-1));\n }\n }\n }\n\n /** Handles keyboard events while the overlay is open. */\n private _handleKeydown(event: KeyboardEvent): void {\n const keyCode = event.keyCode;\n\n if (keyCode === TAB) {\n this.close();\n } else if (keyCode === ESCAPE && !hasModifierKey(event)) {\n event.preventDefault();\n this.close();\n } else if (keyCode === ENTER) {\n event.preventDefault();\n\n if (this._keyManager.activeItem) {\n this._selectValue(this._keyManager.activeItem);\n } else {\n this.close();\n }\n } else {\n const previousActive = this._keyManager.activeItem;\n this._keyManager.onKeydown(event);\n const currentActive = this._keyManager.activeItem;\n\n if (currentActive && currentActive !== previousActive) {\n scrollOptionIntoView(currentActive, 'nearest');\n }\n }\n }\n\n /** Sets up the logic that updates the timepicker when the locale changes. */\n private _handleLocaleChanges(): void {\n // Re-generate the options list if the locale changes.\n this._localeChanges = this._dateAdapter.localeChanges.subscribe(() => {\n this._optionsCacheKey = null;\n\n if (this.isOpen()) {\n this._generateOptions();\n }\n });\n }\n\n /**\n * Sets up the logic that updates the timepicker when the state of the connected input changes.\n */\n private _handleInputStateChanges(): void {\n effect(() => {\n const input = this._input();\n const options = this._options();\n\n if (this._isOpen() && input) {\n this._syncSelectedState(input.value(), options, null);\n }\n });\n }\n}\n\n/**\n * Scrolls an option into view.\n * @param option Option to be scrolled into view.\n * @param position Position to which to align the option relative to the scrollable container.\n */\nfunction scrollOptionIntoView(option: MatOption, position: ScrollLogicalPosition) {\n option._getHostElement().scrollIntoView({block: position, inline: position});\n}\n","<ng-template #panelTemplate>\n <div\n role=\"listbox\"\n class=\"mat-timepicker-panel\"\n [class.mat-timepicker-panel-animations-enabled]=\"!_animationsDisabled\"\n [class.mat-timepicker-panel-exit]=\"!isOpen()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"_getAriaLabelledby()\"\n [id]=\"panelId\"\n (animationend)=\"_handleAnimationEnd($event)\">\n @for (option of _timeOptions; track option.value) {\n <mat-option\n [value]=\"option.value\"\n (onSelectionChange)=\"_selectValue($event.source)\">{{option.label}}</mat-option>\n }\n </div>\n</ng-template>\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport {\n booleanAttribute,\n computed,\n Directive,\n effect,\n ElementRef,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n model,\n ModelSignal,\n OnDestroy,\n OutputRefSubscription,\n Renderer2,\n Signal,\n signal,\n} from '@angular/core';\nimport {DateAdapter, MAT_DATE_FORMATS} from '../core';\nimport {\n AbstractControl,\n ControlValueAccessor,\n NG_VALIDATORS,\n NG_VALUE_ACCESSOR,\n ValidationErrors,\n Validator,\n ValidatorFn,\n Validators,\n} from '@angular/forms';\nimport {MAT_FORM_FIELD} from '../form-field';\nimport {MatTimepicker} from './timepicker';\nimport {MAT_INPUT_VALUE_ACCESSOR} from '../input';\nimport {Subscription} from 'rxjs';\nimport {DOWN_ARROW, ESCAPE, hasModifierKey, UP_ARROW} from '@angular/cdk/keycodes';\nimport {validateAdapter} from './util';\nimport {_getFocusedElementPierceShadowDom} from '@angular/cdk/platform';\n\n/**\n * Input that can be used to enter time and connect to a `mat-timepicker`.\n */\n@Directive({\n selector: 'input[matTimepicker]',\n exportAs: 'matTimepickerInput',\n host: {\n 'class': 'mat-timepicker-input',\n 'role': 'combobox',\n 'type': 'text',\n 'aria-haspopup': 'listbox',\n '[attr.aria-activedescendant]': '_ariaActiveDescendant()',\n '[attr.aria-expanded]': '_ariaExpanded()',\n '[attr.aria-controls]': '_ariaControls()',\n '[attr.mat-timepicker-id]': 'timepicker()?.panelId',\n '[disabled]': 'disabled()',\n '(blur)': '_handleBlur()',\n '(input)': '_handleInput($event.target.value)',\n '(keydown)': '_handleKeydown($event)',\n },\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: MatTimepickerInput,\n multi: true,\n },\n {\n provide: NG_VALIDATORS,\n useExisting: MatTimepickerInput,\n multi: true,\n },\n {\n provide: MAT_INPUT_VALUE_ACCESSOR,\n useExisting: MatTimepickerInput,\n },\n ],\n})\nexport class MatTimepickerInput<D> implements ControlValueAccessor, Validator, OnDestroy {\n private _elementRef = inject<ElementRef<HTMLInputElement>>(ElementRef);\n private _dateAdapter = inject<DateAdapter<D>>(DateAdapter, {optional: true})!;\n private _dateFormats = inject(MAT_DATE_FORMATS, {optional: true})!;\n private _formField = inject(MAT_FORM_FIELD, {optional: true});\n\n private _onChange: ((value: any) => void) | undefined;\n private _onTouched: (() => void) | undefined;\n private _validatorOnChange: (() => void) | undefined;\n private _cleanupClick: () => void;\n private _accessorDisabled = signal(false);\n private _localeSubscription: Subscription;\n private _timepickerSubscription: OutputRefSubscription | undefined;\n private _validator: ValidatorFn;\n private _lastValueValid = true;\n private _lastValidDate: D | null = null;\n\n /** Value of the `aria-activedescendant` attribute. */\n protected readonly _ariaActiveDescendant = computed(() => {\n const timepicker = this.timepicker();\n const isOpen = timepicker.isOpen();\n const activeDescendant = timepicker.activeDescendant();\n return isOpen && activeDescendant ? activeDescendant : null;\n });\n\n /** Value of the `aria-expanded` attribute. */\n protected readonly _ariaExpanded = computed(() => this.timepicker().isOpen() + '');\n\n /** Value of the `aria-controls` attribute. */\n protected readonly _ariaControls = computed(() => {\n const timepicker = this.timepicker();\n return timepicker.isOpen() ? timepicker.panelId : null;\n });\n\n /** Current value of the input. */\n readonly value: ModelSignal<D | null> = model<D | null>(null);\n\n /** Timepicker that the input is associated with. */\n readonly timepicker: InputSignal<MatTimepicker<D>> = input.required<MatTimepicker<D>>({\n alias: 'matTimepicker',\n });\n\n /**\n * Minimum time that can be selected or typed in. Can be either\n * a date object (only time will be used) or a valid time string.\n */\n readonly min: InputSignalWithTransform<D | null, unknown> = input(null, {\n alias: 'matTimepickerMin',\n transform: (value: unknown) => this._transformDateInput<D>(value),\n });\n\n /**\n * Maximum time that can be selected or typed in. Can be either\n * a date object (only time will be used) or a valid time string.\n */\n readonly max: InputSignalWithTransform<D | null, unknown> = input(null, {\n alias: 'matTimepickerMax',\n transform: (value: unknown) => this._transformDateInput<D>(value),\n });\n\n /** Whether the input is disabled. */\n readonly disabled: Signal<boolean> = computed(\n () => this.disabledInput() || this._accessorDisabled(),\n );\n\n /**\n * Whether the input should be disabled through the template.\n * @docs-private\n */\n readonly disabledInput: InputSignalWithTransform<boolean, unknown> = input(false, {\n transform: booleanAttribute,\n alias: 'disabled',\n });\n\n constructor() {\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n validateAdapter(this._dateAdapter, this._dateFormats);\n }\n\n const renderer = inject(Renderer2);\n this._validator = this._getValidator();\n this._respondToValueChanges();\n this._respondToMinMaxChanges();\n this._registerTimepicker();\n this._localeSubscription = this._dateAdapter.localeChanges.subscribe(() => {\n if (!this._hasFocus()) {\n this._formatValue(this.value());\n }\n });\n\n // Bind the click listener manually to the overlay origin, because we want the entire\n // form field to be clickable, if the timepicker is used in `mat-form-field`.\n this._cleanupClick = renderer.listen(\n this.getOverlayOrigin().nativeElement,\n 'click',\n this._handleClick,\n );\n }\n\n /**\n * Implemented as a part of `ControlValueAccessor`.\n * @docs-private\n */\n writeValue(value: any): void {\n // Note that we need to deserialize here, rather than depend on the value change effect,\n // because `getValidDateOrNull` will clobber the value if it's parseable, but not created by\n // the current adapter (see #30140).\n const deserialized = this._dateAdapter.deserialize(value);\n this.value.set(this._dateAdapter.getValidDateOrNull(deserialized));\n }\n\n /**\n * Implemented as a part of `ControlValueAccessor`.\n * @docs-private\n */\n registerOnChange(fn: (value: any) => void): void {\n this._onChange = fn;\n }\n\n /**\n * Implemented as a part of `ControlValueAccessor`.\n * @docs-private\n */\n registerOnTouched(fn: () => void): void {\n this._onTouched = fn;\n }\n\n /**\n * Implemented as a part of `ControlValueAccessor`.\n * @docs-private\n */\n setDisabledState(isDisabled: boolean): void {\n this._accessorDisabled.set(isDisabled);\n }\n\n /**\n * Implemented as a part of `Validator`.\n * @docs-private\n */\n validate(control: AbstractControl): ValidationErrors | null {\n return this._validator(control);\n }\n\n /**\n * Implemented as a part of `Validator`.\n * @docs-private\n */\n registerOnValidatorChange(fn: () => void): void {\n this._validatorOnChange = fn;\n }\n\n /** Gets the element to which the timepicker popup should be attached. */\n getOverlayOrigin(): ElementRef<HTMLElement> {\n return this._formField?.getConnectedOverlayOrigin() || this._elementRef;\n }\n\n /** Focuses the input. */\n focus(): void {\n this._elementRef.nativeElement.focus();\n }\n\n ngOnDestroy(): void {\n this._cleanupClick();\n this._timepickerSubscription?.unsubscribe();\n this._localeSubscription.unsubscribe();\n }\n\n /** Gets the ID of the input's label. */\n _getLabelId(): string | null {\n return this._formField?.getLabelId() || null;\n }\n\n /** Handles clicks on the input or the containing form field. */\n private _handleClick = (): void => {\n if (!this.disabled()) {\n this.timepicker().open();\n }\n };\n\n /** Handles the `input` event. */\n protected _handleInput(value: string) {\n const currentValue = this.value();\n const date = this._dateAdapter.parseTime(value, this._dateFormats.parse.timeInput);\n const hasChanged = !this._dateAdapter.sameTime(date, currentValue);\n\n if (!date || hasChanged || !!(value && !currentValue)) {\n // We need to fire the CVA change event for all nulls, otherwise the validators won't run.\n this._assignUserSelection(date, true);\n } else {\n // Call the validator even if the value hasn't changed since\n // some fields change depending on what the user has entered.\n this._validatorOnChange?.();\n }\n }\n\n /** Handles the `blur` event. */\n protected _handleBlur() {\n const value = this.value();\n\n // Only reformat on blur so the value doesn't change while the user is interacting.\n if (value && this._isValid(value)) {\n this._formatValue(value);\n }\n\n if (!this.timepicker().isOpen()) {\n this._onTouched?.();\n }\n }\n\n /** Handles the `keydown` event. */\n protected _handleKeydown(event: KeyboardEvent) {\n // All keyboard events while open are handled through the timepicker.\n if (this.timepicker().isOpen() || this.disabled()) {\n return;\n }\n\n if (event.keyCode === ESCAPE && !hasModifierKey(event) && this.value() !== null) {\n event.preventDefault();\n this.value.set(null);\n this._formatValue(null);\n } else if (event.keyCode === DOWN_ARROW || event.keyCode === UP_ARROW) {\n event.preventDefault();\n this.timepicker().open();\n }\n }\n\n /** Sets up the code that watches for changes in the value and adjusts the input. */\n private _respondToValueChanges(): void {\n effect(() => {\n const value = this._dateAdapter.deserialize(this.value());\n const wasValid = this._lastValueValid;\n this._lastValueValid = this._isValid(value);\n\n // Reformat the value if it changes while the user isn't interacting.\n if (!this._hasFocus()) {\n this._formatValue(value);\n }\n\n if (value && this._lastValueValid) {\n this._lastValidDate = value;\n }\n\n // Trigger the validator if the state changed.\n if (wasValid !== this._lastValueValid) {\n this._validatorOnChange?.();\n }\n });\n }\n\n /** Sets up the logic that registers the input with the timepicker. */\n private _registerTimepicker(): void {\n effect(() => {\n const timepicker = this.timepicker();\n timepicker.registerInput(this);\n timepicker.closed.subscribe(() => this._onTouched?.());\n timepicker.selected.subscribe(({value}) => {\n if (!this._dateAdapter.sameTime(value, this.value())) {\n this._assignUserSelection(value, true);\n this._formatValue(value);\n }\n });\n });\n }\n\n /** Sets up the logic that adjusts the input if the min/max changes. */\n private _respondToMinMaxChanges(): void {\n effect(() => {\n // Read the min/max so the effect knows when to fire.\n this.min();\n this.max();\n this._validatorOnChange?.();\n });\n }\n\n /**\n * Assigns a value set by the user to the input's model.\n * @param selection Time selected by the user that should be assigned.\n * @param propagateToAccessor Whether the value should be propagated to the ControlValueAccessor.\n */\n private _assignUserSelection(selection: D | null, propagateToAccessor: boolean) {\n if (selection == null || !this._isValid(selection)) {\n this.value.set(selection);\n } else {\n // If a datepicker and timepicker are writing to the same object and the user enters an\n // invalid time into the timepicker, we may end up clearing their selection from the\n // datepicker. If the user enters a valid time afterwards, the datepicker's selection will\n // have been lost. This logic restores the previously-valid date and sets its time to\n // the newly-selected time.\n const adapter = this._dateAdapter;\n const target = adapter.getValidDateOrNull(this._lastValidDate || this.value());\n const hours = adapter.getHours(selection);\n const minutes = adapter.getMinutes(selection);\n const seconds = adapter.getSeconds(selection);\n this.value.set(target ? adapter.setTime(target, hours, minutes, seconds) : selection);\n }\n\n if (propagateToAccessor) {\n this._onChange?.(this.value());\n }\n }\n\n /** Formats the current value and assigns it to the input. */\n private _formatValue(value: D | null): void {\n value = this._dateAdapter.getValidDateOrNull(value);\n this._elementRef.nativeElement.value =\n value == null ? '' : this._dateAdapter.format(value, this._dateFormats.display.timeInput);\n }\n\n /** Checks whether a value is valid. */\n private _isValid(value: D | null): boolean {\n return !value || this._dateAdapter.isValid(value);\n }\n\n /** Transforms an arbitrary value into a value that can be assigned to a date-based input. */\n private _transformDateInput<D>(value: unknown): D | null {\n const date =\n typeof value === 'string'\n ? this._dateAdapter.parseTime(value, this._dateFormats.parse.timeInput)\n : this._dateAdapter.deserialize(value);\n return date && this._dateAdapter.isValid(date) ? (date as D) : null;\n }\n\n /** Whether the input is currently focused. */\n private _hasFocus(): boolean {\n return _getFocusedElementPierceShadowDom() === this._elementRef.nativeElement;\n }\n\n /** Gets a function that can be used to validate the input. */\n private _getValidator(): ValidatorFn {\n return Validators.compose([\n () =>\n this._lastValueValid\n ? null\n : {'matTimepickerParse': {'text': this._elementRef.nativeElement.value}},\n control => {\n const controlValue = this._dateAdapter.getValidDateOrNull(\n this._dateAdapter.deserialize(control.value),\n );\n const min = this.min();\n return !min || !controlValue || this._dateAdapter.compareTime(min, controlValue) <= 0\n ? null\n : {'matTimepickerMin': {'min': min, 'actual': controlValue}};\n },\n control => {\n const controlValue = this._dateAdapter.getValidDateOrNull(\n this._dateAdapter.deserialize(control.value),\n );\n const max = this.max();\n return !max || !controlValue || this._dateAdapter.compareTime(max, controlValue) >= 0\n ? null\n : {'matTimepickerMax': {'max': max, 'actual': controlValue}};\n },\n ])!;\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n HostAttributeToken,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n ViewEncapsulation,\n} from '@angular/core';\nimport {MatIconButton} from '../button';\nimport {MAT_TIMEPICKER_CONFIG} from './util';\nimport type {MatTimepicker} from './timepicker';\n\n/** Button that can be used to open a `mat-timepicker`. */\n@Component({\n selector: 'mat-timepicker-toggle',\n templateUrl: 'timepicker-toggle.html',\n host: {\n 'class': 'mat-timepicker-toggle',\n '[attr.tabindex]': 'null',\n // Bind the `click` on the host, rather than the inner `button`, so that we can call\n // `stopPropagation` on it without affecting the user's `click` handlers. We need to stop\n // it so that the input doesn't get focused automatically by the form field (See #21836).\n '(click)': '_open($event)',\n },\n exportAs: 'matTimepickerToggle',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [MatIconButton],\n})\nexport class MatTimepickerToggle<D> {\n private _defaultConfig = inject(MAT_TIMEPICKER_CONFIG, {optional: true});\n private _defaultTabIndex = (() => {\n const value = inject(new HostAttributeToken('tabindex'), {optional: true});\n const parsed = Number(value);\n return isNaN(parsed) ? null : parsed;\n })();\n\n protected _isDisabled = computed(() => {\n const timepicker = this.timepicker();\n return this.disabled() || timepicker.disabled();\n });\n\n /** Timepicker instance that the button will toggle. */\n readonly timepicker: InputSignal<MatTimepicker<D>> = input.required<MatTimepicker<D>>({\n alias: 'for',\n });\n\n /** Screen-reader label for the button. */\n readonly ariaLabel = input<string | undefined>(undefined, {\n alias: 'aria-label',\n });\n\n /** Screen-reader labelled by id for the button. */\n readonly ariaLabelledby = input<string | undefined>(undefined, {\n alias: 'aria-labelledby',\n });\n\n /** Default aria-label for the toggle if none is provided. */\n private readonly _defaultAriaLabel = 'Open timepicker options';\n\n /** Whether the toggle button is disabled. */\n readonly disabled: InputSignalWithTransform<boolean, unknown> = input(false, {\n transform: booleanAttribute,\n alias: 'disabled',\n });\n\n /** Tabindex for the toggle. */\n readonly tabIndex: InputSignal<number | null> = input(this._defaultTabIndex);\n\n /** Whether ripples on the toggle should be disabled. */\n readonly disableRipple: InputSignalWithTransform<boolean, unknown> = input(\n this._defaultConfig?.disableRipple ?? false,\n {transform: booleanAttribute},\n );\n\n /** Opens the connected timepicker. */\n protected _open(event: Event): void {\n if (this.timepicker() && !this._isDisabled()) {\n this.timepicker().open();\n event.stopPropagation();\n }\n }\n\n /**\n * Checks for ariaLabelledby and if empty uses custom\n * aria-label or defaultAriaLabel if neither is provided.\n */\n getAriaLabel(): string | null {\n return this.ariaLabelledby() ? null : this.ariaLabel() || this._defaultAriaLabel;\n }\n}\n","<button\n mat-icon-button\n type=\"button\"\n aria-haspopup=\"listbox\"\n [attr.aria-label]=\"getAriaLabel()\"\n [attr.aria-labelledby]=\"ariaLabelledby()\"\n [attr.aria-expanded]=\"timepicker().isOpen()\"\n [attr.tabindex]=\"_isDisabled() ? -1 : tabIndex()\"\n [disabled]=\"_isDisabled()\"\n [disableRipple]=\"disableRipple()\">\n\n <ng-content select=\"[matTimepickerToggleIcon]\">\n <svg\n class=\"mat-timepicker-toggle-default-icon\"\n height=\"24px\"\n width=\"24px\"\n viewBox=\"0 -960 960 960\"\n fill=\"currentColor\"\n focusable=\"false\"\n aria-hidden=\"true\">\n <path d=\"m612-292 56-56-148-148v-184h-80v216l172 172ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-400Zm0 320q133 0 226.5-93.5T800-480q0-133-93.5-226.5T480-800q-133 0-226.5 93.5T160-480q0 133 93.5 226.5T480-160Z\"/>\n </svg>\n </ng-content>\n</button>\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport {NgModule} from '@angular/core';\nimport {CdkScrollableModule} from '@angular/cdk/scrolling';\nimport {MatTimepicker} from './timepicker';\nimport {MatTimepickerInput} from './timepicker-input';\nimport {MatTimepickerToggle} from './timepicker-toggle';\n\n@NgModule({\n imports: [MatTimepicker, MatTimepickerInput, MatTimepickerToggle],\n exports: [CdkScrollableModule, MatTimepicker, MatTimepickerInput, MatTimepickerToggle],\n})\nexport class MatTimepickerModule {}\n"],"names":[],"mappings":"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