@siemens/element-ng 48.1.0 → 48.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +5 -0
  2. package/card/index.d.ts +68 -29
  3. package/common/index.d.ts +11 -0
  4. package/dashboard/index.d.ts +1 -0
  5. package/datepicker/index.d.ts +30 -34
  6. package/fesm2022/siemens-element-ng-breadcrumb.mjs +2 -2
  7. package/fesm2022/siemens-element-ng-breadcrumb.mjs.map +1 -1
  8. package/fesm2022/siemens-element-ng-card.mjs +103 -37
  9. package/fesm2022/siemens-element-ng-card.mjs.map +1 -1
  10. package/fesm2022/siemens-element-ng-common.mjs +6 -0
  11. package/fesm2022/siemens-element-ng-common.mjs.map +1 -1
  12. package/fesm2022/siemens-element-ng-connection-strength.mjs +2 -2
  13. package/fesm2022/siemens-element-ng-connection-strength.mjs.map +1 -1
  14. package/fesm2022/siemens-element-ng-content-action-bar.mjs +2 -2
  15. package/fesm2022/siemens-element-ng-content-action-bar.mjs.map +1 -1
  16. package/fesm2022/siemens-element-ng-dashboard.mjs +10 -8
  17. package/fesm2022/siemens-element-ng-dashboard.mjs.map +1 -1
  18. package/fesm2022/siemens-element-ng-datatable.mjs +5 -0
  19. package/fesm2022/siemens-element-ng-datatable.mjs.map +1 -1
  20. package/fesm2022/siemens-element-ng-date-range-filter.mjs +1 -1
  21. package/fesm2022/siemens-element-ng-date-range-filter.mjs.map +1 -1
  22. package/fesm2022/siemens-element-ng-datepicker.mjs +173 -151
  23. package/fesm2022/siemens-element-ng-datepicker.mjs.map +1 -1
  24. package/fesm2022/siemens-element-ng-file-uploader.mjs +2 -2
  25. package/fesm2022/siemens-element-ng-file-uploader.mjs.map +1 -1
  26. package/fesm2022/siemens-element-ng-filter-bar.mjs +5 -5
  27. package/fesm2022/siemens-element-ng-filter-bar.mjs.map +1 -1
  28. package/fesm2022/siemens-element-ng-filtered-search.mjs +15 -3
  29. package/fesm2022/siemens-element-ng-filtered-search.mjs.map +1 -1
  30. package/fesm2022/siemens-element-ng-form.mjs +7 -1
  31. package/fesm2022/siemens-element-ng-form.mjs.map +1 -1
  32. package/fesm2022/siemens-element-ng-formly.mjs +2 -2
  33. package/fesm2022/siemens-element-ng-formly.mjs.map +1 -1
  34. package/fesm2022/siemens-element-ng-header-dropdown.mjs +13 -1
  35. package/fesm2022/siemens-element-ng-header-dropdown.mjs.map +1 -1
  36. package/fesm2022/siemens-element-ng-ip-input.mjs +62 -28
  37. package/fesm2022/siemens-element-ng-ip-input.mjs.map +1 -1
  38. package/fesm2022/siemens-element-ng-language-switcher.mjs +1 -1
  39. package/fesm2022/siemens-element-ng-language-switcher.mjs.map +1 -1
  40. package/fesm2022/siemens-element-ng-list-details.mjs +2 -2
  41. package/fesm2022/siemens-element-ng-list-details.mjs.map +1 -1
  42. package/fesm2022/siemens-element-ng-navbar-vertical.mjs +1 -1
  43. package/fesm2022/siemens-element-ng-navbar-vertical.mjs.map +1 -1
  44. package/fesm2022/siemens-element-ng-pagination.mjs +2 -2
  45. package/fesm2022/siemens-element-ng-pagination.mjs.map +1 -1
  46. package/fesm2022/siemens-element-ng-photo-upload.mjs +1 -1
  47. package/fesm2022/siemens-element-ng-photo-upload.mjs.map +1 -1
  48. package/fesm2022/siemens-element-ng-search-bar.mjs +14 -4
  49. package/fesm2022/siemens-element-ng-search-bar.mjs.map +1 -1
  50. package/fesm2022/siemens-element-ng-side-panel.mjs +2 -2
  51. package/fesm2022/siemens-element-ng-side-panel.mjs.map +1 -1
  52. package/fesm2022/siemens-element-ng-status-bar.mjs +2 -2
  53. package/fesm2022/siemens-element-ng-status-bar.mjs.map +1 -1
  54. package/fesm2022/siemens-element-ng-tabs-legacy.mjs +2 -2
  55. package/fesm2022/siemens-element-ng-tabs-legacy.mjs.map +1 -1
  56. package/fesm2022/siemens-element-ng-tabs.mjs +5 -5
  57. package/fesm2022/siemens-element-ng-tabs.mjs.map +1 -1
  58. package/fesm2022/siemens-element-ng-tooltip.mjs +5 -6
  59. package/fesm2022/siemens-element-ng-tooltip.mjs.map +1 -1
  60. package/fesm2022/siemens-element-ng-translate.mjs.map +1 -1
  61. package/fesm2022/siemens-element-ng-tree-view.mjs +4 -4
  62. package/fesm2022/siemens-element-ng-tree-view.mjs.map +1 -1
  63. package/fesm2022/siemens-element-ng-typeahead.mjs +329 -257
  64. package/fesm2022/siemens-element-ng-typeahead.mjs.map +1 -1
  65. package/filter-bar/index.d.ts +9 -3
  66. package/header-dropdown/index.d.ts +7 -0
  67. package/ip-input/index.d.ts +42 -5
  68. package/package.json +23 -19
  69. package/schematics/collection.json +34 -0
  70. package/schematics/migrations/action-modal-migration/action-modal-migration.js +121 -0
  71. package/schematics/migrations/action-modal-migration/action-modal.mappings.js +98 -0
  72. package/schematics/migrations/action-modal-migration/index.js +5 -0
  73. package/schematics/migrations/index.js +13 -0
  74. package/schematics/migrations/schema.json +16 -0
  75. package/schematics/migrations/to-legacy-migration/to-legacy-migration.js +55 -0
  76. package/schematics/migrations/to-legacy-migration/to-legacy-replacement.js +35 -0
  77. package/schematics/ng-add/index.js +16 -0
  78. package/schematics/ng-add/schema.json +16 -0
  79. package/schematics/scss-import-to-siemens-migration/index.js +101 -0
  80. package/schematics/scss-import-to-siemens-migration/schema.json +16 -0
  81. package/schematics/scss-import-to-siemens-migration/style-mappings.js +46 -0
  82. package/schematics/simpl-siemens-migration/index.js +18 -0
  83. package/schematics/simpl-siemens-migration/schema.json +16 -0
  84. package/schematics/ts-import-to-siemens-migration/index.js +118 -0
  85. package/schematics/ts-import-to-siemens-migration/mappings/charts-ng-mappings.js +70 -0
  86. package/schematics/ts-import-to-siemens-migration/mappings/dashboards-ng-mappings.js +52 -0
  87. package/schematics/ts-import-to-siemens-migration/mappings/element-ng-mappings.js +651 -0
  88. package/schematics/ts-import-to-siemens-migration/mappings/element-translate-ng-mappings.js +21 -0
  89. package/schematics/ts-import-to-siemens-migration/mappings/index.js +9 -0
  90. package/schematics/ts-import-to-siemens-migration/mappings/maps-ng-mappings.js +46 -0
  91. package/schematics/ts-import-to-siemens-migration/model.js +4 -0
  92. package/schematics/ts-import-to-siemens-migration/schema.json +16 -0
  93. package/schematics/utils/html-utils.js +72 -0
  94. package/schematics/utils/index.js +10 -0
  95. package/schematics/utils/project-utils.js +75 -0
  96. package/schematics/utils/schematics-file-system.js +22 -0
  97. package/schematics/utils/template-utils.js +114 -0
  98. package/schematics/utils/testing.js +41 -0
  99. package/schematics/utils/ts-utils.js +195 -0
  100. package/search-bar/index.d.ts +11 -1
  101. package/template-i18n.json +7 -0
  102. package/tooltip/index.d.ts +1 -1
  103. package/translate/index.d.ts +7 -0
  104. package/typeahead/index.d.ts +85 -4
@@ -1,18 +1,18 @@
1
1
  import { getLocaleDayPeriods, FormStyle, TranslationWidth, getLocaleId, getLocaleDateTimeFormat, FormatWidth, getLocaleTimeFormat, getLocaleDateFormat, formatDate, NgClass, DatePipe, NgTemplateOutlet, getLocaleFirstDayOfWeek, WeekDay } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { input, model, output, booleanAttribute, computed, signal, inject, LOCALE_ID, HostListener, Directive, ElementRef, viewChildren, Component, ChangeDetectionStrategy, viewChild, HostAttributeToken, ChangeDetectorRef, SimpleChange, DOCUMENT, DestroyRef, contentChild, NgModule } from '@angular/core';
4
- import * as i1 from '@angular/forms';
5
- import { Validators, NG_VALUE_ACCESSOR, NG_VALIDATORS, FormsModule, NgControl } from '@angular/forms';
3
+ import { input, model, output, booleanAttribute, computed, signal, inject, LOCALE_ID, HostListener, Directive, ElementRef, viewChildren, Component, ChangeDetectionStrategy, viewChild, HostAttributeToken, effect, ChangeDetectorRef, SimpleChange, DOCUMENT, DestroyRef, contentChild, NgModule } from '@angular/core';
4
+ import * as i2 from '@angular/forms';
5
+ import { Validators, NG_VALUE_ACCESSOR, NG_VALIDATORS, FormBuilder, ReactiveFormsModule, FormControl, FormsModule, NgControl } from '@angular/forms';
6
6
  import { SI_FORM_ITEM_CONTROL } from '@siemens/element-ng/form';
7
7
  import { MediaMatcher, BreakpointObserver } from '@angular/cdk/layout';
8
8
  import { Overlay } from '@angular/cdk/overlay';
9
9
  import { ComponentPortal } from '@angular/cdk/portal';
10
10
  import { takeUntilDestroyed, outputToObservable } from '@angular/core/rxjs-interop';
11
- import { isRTL, getOverlayPositions, positionBottomCenter, positionBottomStart, positionBottomEnd, positionTopCenter, positionTopStart, positionTopEnd } from '@siemens/element-ng/common';
11
+ import { isRTL, positionBottomCenter, positionBottomStart, positionBottomEnd, positionTopCenter, positionTopStart, positionTopEnd } from '@siemens/element-ng/common';
12
12
  import { BOOTSTRAP_BREAKPOINTS } from '@siemens/element-ng/resize-observer';
13
13
  import { Subject, merge } from 'rxjs';
14
14
  import { takeUntil, skip, map, filter, tap } from 'rxjs/operators';
15
- import * as i2 from '@angular/cdk/a11y';
15
+ import * as i1 from '@angular/cdk/a11y';
16
16
  import { A11yModule, FocusMonitor, ConfigurableFocusTrapFactory } from '@angular/cdk/a11y';
17
17
  import { SiTranslatePipe, t } from '@siemens/element-translate-ng/translate';
18
18
  import { addIcons, elementRight2, elementLeft2, SiIconComponent, elementCalendar } from '@siemens/element-ng/icon';
@@ -678,6 +678,13 @@ const minDate = (first, second) => {
678
678
  const maxDate = (first, second) => {
679
679
  return !!first && !!second ? (first > second ? first : second) : (first ?? second);
680
680
  };
681
+ /**
682
+ * Indicate whether the time use the 12-hour format
683
+ */
684
+ const is12HourFormat = (locale, config) => {
685
+ const dateFormat = getDatepickerFormat(locale, config, true);
686
+ return dateFormat?.includes('a') ?? false;
687
+ };
681
688
 
682
689
  /**
683
690
  * Returns date / datetime format to be used for rendering a date object as text
@@ -1953,10 +1960,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
1953
1960
  * Copyright (c) Siemens 2016 - 2025
1954
1961
  * SPDX-License-Identifier: MIT
1955
1962
  */
1963
+ const dateWithTime = (base, time) => createDate(base, time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds());
1956
1964
  class SiTimepickerComponent {
1957
1965
  static idCounter = 0;
1958
- /** @internal */
1959
- forceInvalid = signal(false);
1966
+ locale = inject(LOCALE_ID).toString();
1967
+ formBuilder = inject(FormBuilder);
1960
1968
  /**
1961
1969
  * @defaultValue
1962
1970
  * ```
@@ -2101,10 +2109,9 @@ class SiTimepickerComponent {
2101
2109
  {
2102
2110
  ariaLabel: this.hoursAriaLabel(),
2103
2111
  label: this.hoursLabel(),
2104
- max: this.isPM() ? 12 : 24,
2112
+ max: this.isPM() ? 12 : 23,
2105
2113
  maxLength: 2,
2106
2114
  name: 'hours',
2107
- pattern: '2[0-4]|[01]?[0-9]',
2108
2115
  placeholder: this.hoursPlaceholder()
2109
2116
  }
2110
2117
  ];
@@ -2112,10 +2119,9 @@ class SiTimepickerComponent {
2112
2119
  config.push({
2113
2120
  ariaLabel: this.minutesAriaLabel(),
2114
2121
  label: this.minutesLabel(),
2115
- max: 60,
2122
+ max: 59,
2116
2123
  maxLength: 2,
2117
2124
  name: 'minutes',
2118
- pattern: '[0-5]?[0-9]',
2119
2125
  placeholder: this.minutesPlaceholder()
2120
2126
  });
2121
2127
  }
@@ -2123,10 +2129,9 @@ class SiTimepickerComponent {
2123
2129
  config.push({
2124
2130
  ariaLabel: this.secondsAriaLabel(),
2125
2131
  label: this.secondsLabel(),
2126
- max: 60,
2132
+ max: 59,
2127
2133
  maxLength: 2,
2128
2134
  name: 'seconds',
2129
- pattern: '[0-5]?[0-9]',
2130
2135
  placeholder: this.secondsPlaceholder()
2131
2136
  });
2132
2137
  }
@@ -2134,10 +2139,9 @@ class SiTimepickerComponent {
2134
2139
  config.push({
2135
2140
  ariaLabel: this.millisecondsAriaLabel(),
2136
2141
  label: this.millisecondsLabel(),
2137
- max: 1000,
2142
+ max: 999,
2138
2143
  maxLength: 3,
2139
2144
  name: 'milliseconds',
2140
- pattern: '[0-9]{1,3}',
2141
2145
  placeholder: this.millisecondsPlaceholder(),
2142
2146
  separator: '.'
2143
2147
  });
@@ -2145,35 +2149,24 @@ class SiTimepickerComponent {
2145
2149
  return config;
2146
2150
  });
2147
2151
  /* Input fields state */
2148
- unitValues = signal({
2149
- hours: '',
2150
- minutes: '',
2151
- seconds: '',
2152
- milliseconds: ''
2152
+ timeControls = this.formBuilder.group({
2153
+ hours: this.formBuilder.nonNullable.control('', [this.validateTime('hours')]),
2154
+ minutes: this.formBuilder.nonNullable.control('', [this.validateTime('minutes')]),
2155
+ seconds: this.formBuilder.nonNullable.control('', [this.validateTime('seconds')]),
2156
+ milliseconds: this.formBuilder.nonNullable.control('', [this.validateTime('milliseconds')])
2153
2157
  });
2154
- /** Validation state of the input fields */
2155
- unitValidation = computed(() => {
2156
- const units = this.units();
2157
- const values = this.unitValues();
2158
- // Only validate if the input fields contain a value.
2159
- const empty = Object.values(values).every(v => v.length === 0);
2160
- const valid = empty || this.isValidLimit(this.max(), this.min());
2161
- const validation = {
2162
- hours: valid,
2163
- minutes: valid,
2164
- seconds: valid,
2165
- milliseconds: valid
2166
- };
2167
- if (!empty && valid) {
2168
- for (const config of units) {
2169
- validation[config.name] =
2170
- values[config.name].length > 0 && !isNaN(this.toNumber(values[config.name], config.max));
2158
+ /** Indicate whether one of the input fields has an invalid value. */
2159
+ hasInvalidUnit() {
2160
+ const values = this.timeControls.value;
2161
+ for (const config of this.units()) {
2162
+ const unit = values[config.name];
2163
+ if (isNaN(this.toNumber(unit, config.max))) {
2164
+ return true;
2171
2165
  }
2172
2166
  }
2173
- return validation;
2174
- });
2167
+ return false;
2168
+ }
2175
2169
  disabledNgControl = signal(false);
2176
- locale = inject(LOCALE_ID).toString();
2177
2170
  /**
2178
2171
  * Holds the time as date object that is presented by this control.
2179
2172
  */
@@ -2181,6 +2174,23 @@ class SiTimepickerComponent {
2181
2174
  periodDefaults;
2182
2175
  constructor() {
2183
2176
  this.periodDefaults = getLocaleDayPeriods(this.locale, FormStyle.Format, TranslationWidth.Short).slice();
2177
+ effect(() => {
2178
+ if (this.disabled()) {
2179
+ this.timeControls.disable({ emitEvent: false, onlySelf: true });
2180
+ }
2181
+ else {
2182
+ this.timeControls.enable({ emitEvent: false, onlySelf: true });
2183
+ }
2184
+ });
2185
+ Object.values(this.timeControls.controls).forEach(control => {
2186
+ control.valueChanges.subscribe(value => {
2187
+ // Enforce digits only
2188
+ const cleaned = value.replace(/\D/g, '');
2189
+ if (cleaned !== value) {
2190
+ control?.setValue(cleaned, { emitEvent: false });
2191
+ }
2192
+ });
2193
+ });
2184
2194
  }
2185
2195
  writeValue(obj) {
2186
2196
  if (this.isValidDate(obj)) {
@@ -2203,16 +2213,19 @@ class SiTimepickerComponent {
2203
2213
  setDisabledState(isDisabled) {
2204
2214
  this.disabledNgControl.set(isDisabled);
2205
2215
  }
2206
- /**
2207
- * Handle input event to remove non-numeric characters.
2208
- */
2209
- handleInput(event) {
2210
- const inputEl = event.target;
2211
- const current = inputEl.value;
2212
- const cleaned = current.replace(/\D/g, '');
2213
- if (current !== cleaned) {
2214
- inputEl.value = cleaned;
2215
- }
2216
+ /** @internal */
2217
+ validate(control) {
2218
+ const childErrors = this.units()
2219
+ .map(u => this.timeControls.controls[u.name].errors)
2220
+ .reduce((prevObj, field) => ({ ...prevObj, ...field }), {});
2221
+ if (childErrors && Object.keys(childErrors).length) {
2222
+ return childErrors;
2223
+ }
2224
+ const errors = {
2225
+ ...this.validateMin(control),
2226
+ ...this.validateMax(control)
2227
+ };
2228
+ return Object.keys(errors).length ? errors : null;
2216
2229
  }
2217
2230
  /**
2218
2231
  * Handle Enter, Arrow up/down and Space key press events.
@@ -2243,15 +2256,12 @@ class SiTimepickerComponent {
2243
2256
  }
2244
2257
  toHtmlInputElement = (target) => target;
2245
2258
  updateField(name, value) {
2246
- const prev = this.unitValues()[name];
2247
- const config = this.units().find(u => u.name === name);
2248
- if (prev !== value) {
2249
- this.unitValues.update(v => ({ ...v, [name]: value.padStart(config.maxLength, '0') }));
2250
- this.updateTime();
2251
- }
2259
+ this.timeControls.get(name)?.setValue(value, { emitEvent: false });
2260
+ this.updateTime();
2261
+ this.onTouched();
2252
2262
  }
2253
2263
  toggleMeridian() {
2254
- const time = this.changeTime(this.time, { hour: 12 });
2264
+ const time = this.changeTime(this.time, { hours: 12 });
2255
2265
  this.setTime(time);
2256
2266
  }
2257
2267
  /**
@@ -2259,7 +2269,7 @@ class SiTimepickerComponent {
2259
2269
  * accordingly, if they UI input values are valid.
2260
2270
  */
2261
2271
  updateTime() {
2262
- if (!this.unitValidation()) {
2272
+ if (this.hasInvalidUnit()) {
2263
2273
  this.isValid.emit(false);
2264
2274
  this.onChange(null);
2265
2275
  return;
@@ -2287,12 +2297,12 @@ class SiTimepickerComponent {
2287
2297
  */
2288
2298
  updateUI(value) {
2289
2299
  if (!value || !this.isValidDate(value)) {
2290
- this.unitValues.set({
2300
+ this.timeControls.setValue({
2291
2301
  hours: '',
2292
2302
  minutes: '',
2293
2303
  seconds: '',
2294
2304
  milliseconds: ''
2295
- });
2305
+ }, { emitEvent: false });
2296
2306
  this.meridian.set('am');
2297
2307
  this.meridianChange.emit(this.meridian());
2298
2308
  }
@@ -2311,12 +2321,12 @@ class SiTimepickerComponent {
2311
2321
  hours = 12;
2312
2322
  }
2313
2323
  }
2314
- this.unitValues.set({
2324
+ this.timeControls.setValue({
2315
2325
  hours: hours.toString().padStart(2, '0'),
2316
2326
  minutes: time.getMinutes().toString().padStart(2, '0'),
2317
2327
  seconds: time.getUTCSeconds().toString().padStart(2, '0'),
2318
2328
  milliseconds: time.getUTCMilliseconds().toString().padStart(3, '0')
2319
- });
2329
+ }, { emitEvent: false });
2320
2330
  }
2321
2331
  }
2322
2332
  isValidDate(value) {
@@ -2338,11 +2348,12 @@ class SiTimepickerComponent {
2338
2348
  return value;
2339
2349
  }
2340
2350
  createDateUpdate(date) {
2341
- const value = this.unitValues();
2342
- let hour = this.toNumber(value.hours, this.isPM() ? 12 : 24);
2343
- const minute = this.toNumber(value.minutes, 60);
2344
- const seconds = this.toNumber(value.seconds, 60) || 0;
2345
- const milliseconds = this.toNumber(value.milliseconds, 1000) || 0;
2351
+ const units = this.units();
2352
+ const value = this.timeControls.value;
2353
+ let hour = this.toNumber(value.hours, units.find(u => u.name === 'hours')?.max);
2354
+ const minute = this.toNumber(value.minutes, units.find(u => u.name === 'minutes')?.max);
2355
+ const seconds = this.toNumber(value.seconds, units.find(u => u.name === 'seconds')?.max) || 0;
2356
+ const milliseconds = this.toNumber(value.milliseconds, units.find(u => u.name === 'milliseconds')?.max) || 0;
2346
2357
  if (this.isPM() && hour !== 12) {
2347
2358
  hour += 12;
2348
2359
  }
@@ -2373,42 +2384,12 @@ class SiTimepickerComponent {
2373
2384
  }
2374
2385
  return value;
2375
2386
  }
2376
- isValidLimit(max, min) {
2377
- const refDate = new Date();
2378
- const newDate = this.createDateUpdate(refDate);
2379
- if (!newDate) {
2380
- return false;
2381
- }
2382
- let refMax;
2383
- if (max) {
2384
- refMax = new Date(refDate);
2385
- refMax.setHours(max.getHours());
2386
- refMax.setMinutes(max.getMinutes());
2387
- refMax.setSeconds(max.getSeconds());
2388
- refMax.setMilliseconds(max.getMilliseconds());
2389
- }
2390
- let refMin;
2391
- if (min) {
2392
- refMin = new Date(refDate);
2393
- refMin.setHours(min.getHours());
2394
- refMin.setMinutes(min.getMinutes());
2395
- refMin.setSeconds(min.getSeconds());
2396
- refMin.setMilliseconds(min.getMilliseconds());
2397
- }
2398
- if (refMax && newDate > refMax) {
2399
- return false;
2400
- }
2401
- else if (refMin && newDate < refMin) {
2402
- return false;
2403
- }
2404
- return true;
2405
- }
2406
2387
  changeTimeComponent(key, up) {
2407
2388
  const change = up ? 1 : -1;
2408
2389
  const date = this.createDateUpdate(new Date());
2409
2390
  switch (key) {
2410
2391
  case 'hours': {
2411
- const newTime = this.changeTime(date, { hour: change });
2392
+ const newTime = this.changeTime(date, { hours: change });
2412
2393
  let hour = newTime.getHours();
2413
2394
  if (this.use12HourClock()) {
2414
2395
  hour = hour % 12;
@@ -2423,7 +2404,7 @@ class SiTimepickerComponent {
2423
2404
  break;
2424
2405
  }
2425
2406
  case 'minutes': {
2426
- const newTime = this.changeTime(date, { minute: change });
2407
+ const newTime = this.changeTime(date, { minutes: change });
2427
2408
  this.updateField('minutes', newTime.getMinutes().toString());
2428
2409
  break;
2429
2410
  }
@@ -2452,11 +2433,11 @@ class SiTimepickerComponent {
2452
2433
  let minutes = value.getMinutes();
2453
2434
  let seconds = value.getSeconds();
2454
2435
  let milliseconds = value.getMilliseconds();
2455
- if (diff.hour) {
2456
- hour = hour + this.toNumber(diff.hour);
2436
+ if (diff.hours) {
2437
+ hour = hour + this.toNumber(diff.hours);
2457
2438
  }
2458
- if (diff.minute) {
2459
- minutes = minutes + this.toNumber(diff.minute);
2439
+ if (diff.minutes) {
2440
+ minutes = minutes + this.toNumber(diff.minutes);
2460
2441
  }
2461
2442
  if (diff.seconds) {
2462
2443
  seconds = seconds + this.toNumber(diff.seconds);
@@ -2491,6 +2472,38 @@ class SiTimepickerComponent {
2491
2472
  this.onTouched();
2492
2473
  }
2493
2474
  }
2475
+ validateMin(control) {
2476
+ const current = control.value;
2477
+ let min = this.min();
2478
+ if (control.value instanceof Date && min) {
2479
+ min = dateWithTime(current, min);
2480
+ if (current < min) {
2481
+ return { minTime: { actual: current, min: min } };
2482
+ }
2483
+ }
2484
+ return null;
2485
+ }
2486
+ validateMax(control) {
2487
+ const error = {};
2488
+ const current = control.value;
2489
+ let max = this.max();
2490
+ if (control.value instanceof Date && max) {
2491
+ max = dateWithTime(current, max);
2492
+ if (current > max) {
2493
+ error.maxTime = { actual: current, max: max };
2494
+ }
2495
+ }
2496
+ return Object.keys(error).length ? error : null;
2497
+ }
2498
+ validateTime(name) {
2499
+ return (c) => {
2500
+ const max = this.units().find(u => u.name === name)?.max;
2501
+ if (max !== undefined && c.value && parseInt(c.value, 10) > max) {
2502
+ return { [name]: { max } };
2503
+ }
2504
+ return null;
2505
+ };
2506
+ }
2494
2507
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: SiTimepickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2495
2508
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: SiTimepickerComponent, isStandalone: true, selector: "si-timepicker", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, disabledInput: { classPropertyName: "disabledInput", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hoursLabel: { classPropertyName: "hoursLabel", publicName: "hoursLabel", isSignal: true, isRequired: false, transformFunction: null }, minutesLabel: { classPropertyName: "minutesLabel", publicName: "minutesLabel", isSignal: true, isRequired: false, transformFunction: null }, secondsLabel: { classPropertyName: "secondsLabel", publicName: "secondsLabel", isSignal: true, isRequired: false, transformFunction: null }, millisecondsLabel: { classPropertyName: "millisecondsLabel", publicName: "millisecondsLabel", isSignal: true, isRequired: false, transformFunction: null }, hideLabels: { classPropertyName: "hideLabels", publicName: "hideLabels", isSignal: true, isRequired: false, transformFunction: null }, hoursAriaLabel: { classPropertyName: "hoursAriaLabel", publicName: "hoursAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, minutesAriaLabel: { classPropertyName: "minutesAriaLabel", publicName: "minutesAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, secondsAriaLabel: { classPropertyName: "secondsAriaLabel", publicName: "secondsAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, millisecondsAriaLabel: { classPropertyName: "millisecondsAriaLabel", publicName: "millisecondsAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, hoursPlaceholder: { classPropertyName: "hoursPlaceholder", publicName: "hoursPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, minutesPlaceholder: { classPropertyName: "minutesPlaceholder", publicName: "minutesPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, secondsPlaceholder: { classPropertyName: "secondsPlaceholder", publicName: "secondsPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, millisecondsPlaceholder: { classPropertyName: "millisecondsPlaceholder", publicName: "millisecondsPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, meridians: { classPropertyName: "meridians", publicName: "meridians", isSignal: true, isRequired: false, transformFunction: null }, meridiansLabel: { classPropertyName: "meridiansLabel", publicName: "meridiansLabel", isSignal: true, isRequired: false, transformFunction: null }, meridiansAriaLabel: { classPropertyName: "meridiansAriaLabel", publicName: "meridiansAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, showMinutes: { classPropertyName: "showMinutes", publicName: "showMinutes", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null }, showMilliseconds: { classPropertyName: "showMilliseconds", publicName: "showMilliseconds", isSignal: true, isRequired: false, transformFunction: null }, showMeridian: { classPropertyName: "showMeridian", publicName: "showMeridian", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, errormessageId: { classPropertyName: "errormessageId", publicName: "errormessageId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isValid: "isValid", meridianChange: "meridianChange", inputCompleted: "inputCompleted" }, host: { attributes: { "role": "group" }, properties: { "class.readonly": "readonly()", "attr.aria-labelledby": "labelledby" }, classAttribute: "form-custom-control" }, providers: [
2496
2509
  {
@@ -2498,20 +2511,30 @@ class SiTimepickerComponent {
2498
2511
  useExisting: SiTimepickerComponent,
2499
2512
  multi: true
2500
2513
  },
2514
+ {
2515
+ provide: NG_VALIDATORS,
2516
+ useExisting: SiTimepickerComponent,
2517
+ multi: true
2518
+ },
2501
2519
  {
2502
2520
  provide: SI_FORM_ITEM_CONTROL,
2503
2521
  useExisting: SiTimepickerComponent
2504
2522
  }
2505
- ], viewQueries: [{ propertyName: "inputParts", predicate: ["inputPart"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"d-flex flex-row flex-wrap\"\n cdkMonitorSubtreeFocus\n (cdkFocusChange)=\"focusChange($event)\"\n>\n @for (config of units(); track $index) {\n @if (!$first) {\n <ng-container *ngTemplateOutlet=\"separator; context: { separator: config.separator }\" />\n }\n <label class=\"min-width\">\n @if (!hideLabels()) {\n <span class=\"form-label\">{{ (config.label | translate) || '&nbsp;' }}</span>\n }\n <input\n #inputPart\n autocomplete=\"off\"\n class=\"form-control hide-feedback-icon\"\n type=\"text\"\n inputmode=\"numeric\"\n [attr.aria-label]=\"config.ariaLabel | translate\"\n [attr.aria-describedby]=\"errormessageId()\"\n [attr.maxlength]=\"config.maxLength\"\n [class.is-invalid]=\"!unitValidation()[config.name] || this.forceInvalid()\"\n [disabled]=\"disabled()\"\n [name]=\"config.name\"\n [pattern]=\"config.pattern\"\n [placeholder]=\"config.placeholder\"\n [readonly]=\"readonly()\"\n [value]=\"unitValues()[config.name]\"\n (change)=\"updateField(config.name, toHtmlInputElement($event.target).value)\"\n (blur)=\"updateField(config.name, toHtmlInputElement($event.target).value)\"\n (input)=\"handleInput($event)\"\n (keydown)=\"handleKeyPressEvent($event)\"\n />\n </label>\n }\n @if (use12HourClock()) {\n <label class=\"ms-2\">\n @if (!hideLabels()) {\n <span class=\"form-label\">{{ (meridiansLabel() | translate) || '&nbsp;' }}</span>\n }\n <select\n #inputPart\n class=\"form-control\"\n [attr.aria-label]=\"meridiansAriaLabel() | translate\"\n [attr.aria-describedby]=\"errormessageId()\"\n [class.readonly]=\"readonly()\"\n [disabled]=\"disabled()\"\n (change)=\"toggleMeridian()\"\n (keydown)=\"handleKeyPressEvent($event)\"\n >\n <option value=\"am\" [selected]=\"meridian() === 'am'\">{{ periods()[0] }}</option>\n <option value=\"pm\" [selected]=\"meridian() === 'pm'\">{{ periods()[1] }}</option>\n </select>\n </label>\n }\n</div>\n\n<ng-template #separator let-separator=\"separator\">\n <div class=\"align-self-end pb-3 px-1\" aria-hidden=\"true\">{{ separator ? separator : ':' }}</div>\n</ng-template>\n", styles: [":host{display:block}.min-width{inline-size:100%;max-inline-size:45px;min-inline-size:35px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "pipe", type: SiTranslatePipe, name: "translate" }, { kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i2.CdkMonitorFocus, selector: "[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]", outputs: ["cdkFocusChange"], exportAs: ["cdkMonitorFocus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2523
+ ], viewQueries: [{ propertyName: "inputParts", predicate: ["inputPart"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"d-flex flex-row flex-wrap\"\n cdkMonitorSubtreeFocus\n (cdkFocusChange)=\"focusChange($event)\"\n>\n @for (config of units(); track $index) {\n @if (!$first) {\n <ng-container *ngTemplateOutlet=\"separator; context: { separator: config.separator }\" />\n }\n <label class=\"min-width\">\n @if (!hideLabels()) {\n <span class=\"form-label\">{{ (config.label | translate) || '&nbsp;' }}</span>\n }\n <input\n #inputPart\n autocomplete=\"off\"\n class=\"form-control hide-feedback-icon\"\n type=\"text\"\n inputmode=\"numeric\"\n [attr.aria-label]=\"config.ariaLabel | translate\"\n [attr.aria-describedby]=\"errormessageId()\"\n [attr.maxlength]=\"config.maxLength\"\n [formControl]=\"timeControls.controls[config.name]\"\n [name]=\"config.name\"\n [placeholder]=\"config.placeholder\"\n [readonly]=\"readonly()\"\n (blur)=\"updateField(config.name, toHtmlInputElement($event.target).value)\"\n (keydown)=\"handleKeyPressEvent($event)\"\n />\n </label>\n }\n @if (use12HourClock()) {\n <label class=\"ms-2\">\n @if (!hideLabels()) {\n <span class=\"form-label\">{{ (meridiansLabel() | translate) || '&nbsp;' }}</span>\n }\n <select\n #inputPart\n class=\"form-control\"\n [attr.aria-label]=\"meridiansAriaLabel() | translate\"\n [attr.aria-describedby]=\"errormessageId()\"\n [class.readonly]=\"readonly()\"\n [disabled]=\"disabled()\"\n (change)=\"toggleMeridian()\"\n (keydown)=\"handleKeyPressEvent($event)\"\n >\n <option value=\"am\" [selected]=\"meridian() === 'am'\">{{ periods()[0] }}</option>\n <option value=\"pm\" [selected]=\"meridian() === 'pm'\">{{ periods()[1] }}</option>\n </select>\n </label>\n }\n</div>\n\n<ng-template #separator let-separator=\"separator\">\n <div class=\"align-self-end pb-3 px-1\" aria-hidden=\"true\">{{ separator ? separator : ':' }}</div>\n</ng-template>\n", styles: [":host{display:block}:host.ng-touched.ng-invalid:not(:has(.ng-touched.ng-invalid)) .form-control{--border-color: var(--element-status-danger)}.min-width{inline-size:100%;max-inline-size:45px;min-inline-size:35px}\n"], dependencies: [{ kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i1.CdkMonitorFocus, selector: "[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]", outputs: ["cdkFocusChange"], exportAs: ["cdkMonitorFocus"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "pipe", type: SiTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2506
2524
  }
2507
2525
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: SiTimepickerComponent, decorators: [{
2508
2526
  type: Component,
2509
- args: [{ selector: 'si-timepicker', imports: [NgTemplateOutlet, FormsModule, SiTranslatePipe, A11yModule], providers: [
2527
+ args: [{ selector: 'si-timepicker', imports: [A11yModule, NgTemplateOutlet, ReactiveFormsModule, SiTranslatePipe], providers: [
2510
2528
  {
2511
2529
  provide: NG_VALUE_ACCESSOR,
2512
2530
  useExisting: SiTimepickerComponent,
2513
2531
  multi: true
2514
2532
  },
2533
+ {
2534
+ provide: NG_VALIDATORS,
2535
+ useExisting: SiTimepickerComponent,
2536
+ multi: true
2537
+ },
2515
2538
  {
2516
2539
  provide: SI_FORM_ITEM_CONTROL,
2517
2540
  useExisting: SiTimepickerComponent
@@ -2521,7 +2544,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
2521
2544
  class: 'form-custom-control',
2522
2545
  '[class.readonly]': 'readonly()',
2523
2546
  '[attr.aria-labelledby]': 'labelledby'
2524
- }, template: "<div\n class=\"d-flex flex-row flex-wrap\"\n cdkMonitorSubtreeFocus\n (cdkFocusChange)=\"focusChange($event)\"\n>\n @for (config of units(); track $index) {\n @if (!$first) {\n <ng-container *ngTemplateOutlet=\"separator; context: { separator: config.separator }\" />\n }\n <label class=\"min-width\">\n @if (!hideLabels()) {\n <span class=\"form-label\">{{ (config.label | translate) || '&nbsp;' }}</span>\n }\n <input\n #inputPart\n autocomplete=\"off\"\n class=\"form-control hide-feedback-icon\"\n type=\"text\"\n inputmode=\"numeric\"\n [attr.aria-label]=\"config.ariaLabel | translate\"\n [attr.aria-describedby]=\"errormessageId()\"\n [attr.maxlength]=\"config.maxLength\"\n [class.is-invalid]=\"!unitValidation()[config.name] || this.forceInvalid()\"\n [disabled]=\"disabled()\"\n [name]=\"config.name\"\n [pattern]=\"config.pattern\"\n [placeholder]=\"config.placeholder\"\n [readonly]=\"readonly()\"\n [value]=\"unitValues()[config.name]\"\n (change)=\"updateField(config.name, toHtmlInputElement($event.target).value)\"\n (blur)=\"updateField(config.name, toHtmlInputElement($event.target).value)\"\n (input)=\"handleInput($event)\"\n (keydown)=\"handleKeyPressEvent($event)\"\n />\n </label>\n }\n @if (use12HourClock()) {\n <label class=\"ms-2\">\n @if (!hideLabels()) {\n <span class=\"form-label\">{{ (meridiansLabel() | translate) || '&nbsp;' }}</span>\n }\n <select\n #inputPart\n class=\"form-control\"\n [attr.aria-label]=\"meridiansAriaLabel() | translate\"\n [attr.aria-describedby]=\"errormessageId()\"\n [class.readonly]=\"readonly()\"\n [disabled]=\"disabled()\"\n (change)=\"toggleMeridian()\"\n (keydown)=\"handleKeyPressEvent($event)\"\n >\n <option value=\"am\" [selected]=\"meridian() === 'am'\">{{ periods()[0] }}</option>\n <option value=\"pm\" [selected]=\"meridian() === 'pm'\">{{ periods()[1] }}</option>\n </select>\n </label>\n }\n</div>\n\n<ng-template #separator let-separator=\"separator\">\n <div class=\"align-self-end pb-3 px-1\" aria-hidden=\"true\">{{ separator ? separator : ':' }}</div>\n</ng-template>\n", styles: [":host{display:block}.min-width{inline-size:100%;max-inline-size:45px;min-inline-size:35px}\n"] }]
2547
+ }, template: "<div\n class=\"d-flex flex-row flex-wrap\"\n cdkMonitorSubtreeFocus\n (cdkFocusChange)=\"focusChange($event)\"\n>\n @for (config of units(); track $index) {\n @if (!$first) {\n <ng-container *ngTemplateOutlet=\"separator; context: { separator: config.separator }\" />\n }\n <label class=\"min-width\">\n @if (!hideLabels()) {\n <span class=\"form-label\">{{ (config.label | translate) || '&nbsp;' }}</span>\n }\n <input\n #inputPart\n autocomplete=\"off\"\n class=\"form-control hide-feedback-icon\"\n type=\"text\"\n inputmode=\"numeric\"\n [attr.aria-label]=\"config.ariaLabel | translate\"\n [attr.aria-describedby]=\"errormessageId()\"\n [attr.maxlength]=\"config.maxLength\"\n [formControl]=\"timeControls.controls[config.name]\"\n [name]=\"config.name\"\n [placeholder]=\"config.placeholder\"\n [readonly]=\"readonly()\"\n (blur)=\"updateField(config.name, toHtmlInputElement($event.target).value)\"\n (keydown)=\"handleKeyPressEvent($event)\"\n />\n </label>\n }\n @if (use12HourClock()) {\n <label class=\"ms-2\">\n @if (!hideLabels()) {\n <span class=\"form-label\">{{ (meridiansLabel() | translate) || '&nbsp;' }}</span>\n }\n <select\n #inputPart\n class=\"form-control\"\n [attr.aria-label]=\"meridiansAriaLabel() | translate\"\n [attr.aria-describedby]=\"errormessageId()\"\n [class.readonly]=\"readonly()\"\n [disabled]=\"disabled()\"\n (change)=\"toggleMeridian()\"\n (keydown)=\"handleKeyPressEvent($event)\"\n >\n <option value=\"am\" [selected]=\"meridian() === 'am'\">{{ periods()[0] }}</option>\n <option value=\"pm\" [selected]=\"meridian() === 'pm'\">{{ periods()[1] }}</option>\n </select>\n </label>\n }\n</div>\n\n<ng-template #separator let-separator=\"separator\">\n <div class=\"align-self-end pb-3 px-1\" aria-hidden=\"true\">{{ separator ? separator : ':' }}</div>\n</ng-template>\n", styles: [":host{display:block}:host.ng-touched.ng-invalid:not(:has(.ng-touched.ng-invalid)) .form-control{--border-color: var(--element-status-danger)}.min-width{inline-size:100%;max-inline-size:45px;min-inline-size:35px}\n"] }]
2525
2548
  }], ctorParameters: () => [] });
2526
2549
 
2527
2550
  /**
@@ -2715,13 +2738,15 @@ class SiDatepickerComponent {
2715
2738
  * in separate objects to not change the date when flipping time.
2716
2739
  * After change, a new date object is created with an adapted time.
2717
2740
  */
2718
- time;
2741
+ time = new FormControl(undefined, {
2742
+ validators: [control => this.validateTime(control)],
2743
+ nonNullable: true
2744
+ });
2719
2745
  /**
2720
2746
  * Used to hold the last time when setting the time to disabled.
2721
2747
  * Value will be reset on enabling the time again.
2722
2748
  */
2723
2749
  previousTime;
2724
- timePicker = viewChild(SiTimepickerComponent);
2725
2750
  /** Reference to the current day selection component. Shown when view === 'week' */
2726
2751
  daySelection = viewChild(SiDaySelectionComponent);
2727
2752
  /** Reference to the current month selection component. Shown when view === 'month' */
@@ -2742,6 +2767,15 @@ class SiDatepickerComponent {
2742
2767
  : weekStart === WeekDay.Saturday
2743
2768
  ? 'saturday'
2744
2769
  : 'monday';
2770
+ effect(() => {
2771
+ if (this.disabledTime()) {
2772
+ this.time.disable({ emitEvent: false });
2773
+ }
2774
+ else {
2775
+ this.time.enable({ emitEvent: false });
2776
+ }
2777
+ });
2778
+ this.time.valueChanges.subscribe((newTime) => this.timeSelected(newTime));
2745
2779
  }
2746
2780
  ngOnChanges(changes) {
2747
2781
  const config = this.config();
@@ -2753,10 +2787,10 @@ class SiDatepickerComponent {
2753
2787
  if (date) {
2754
2788
  if (changes.date.isFirstChange()) {
2755
2789
  this.previousTime = new Date(date);
2756
- this.time = date;
2790
+ this.time.setValue(date, { emitEvent: false });
2757
2791
  }
2758
- if (this.time?.getTime() !== date?.getTime()) {
2759
- this.time = date;
2792
+ if (this.time.value?.getTime() !== date?.getTime()) {
2793
+ this.time.setValue(date, { emitEvent: false });
2760
2794
  }
2761
2795
  this.focusedDate.set(date);
2762
2796
  }
@@ -2800,7 +2834,7 @@ class SiDatepickerComponent {
2800
2834
  const newDate = dateRangeRole === 'START' ? dateRange?.start : dateRange?.end;
2801
2835
  if (newDate && changes.dateRange.isFirstChange()) {
2802
2836
  this.previousTime = new Date(newDate);
2803
- this.time = newDate;
2837
+ this.time.setValue(newDate, { emitEvent: false });
2804
2838
  }
2805
2839
  }
2806
2840
  }
@@ -2872,9 +2906,6 @@ class SiDatepickerComponent {
2872
2906
  // eslint-disable-next-line @angular-eslint/no-lifecycle-call
2873
2907
  this.ngOnChanges({ date: new SimpleChange(undefined, date, true) });
2874
2908
  }
2875
- if (config.enableTimeValidation && this.timePicker() && (config.minDate || config.maxDate)) {
2876
- this.validateTime(newDate);
2877
- }
2878
2909
  this.cdRef.markForCheck();
2879
2910
  }
2880
2911
  /**
@@ -2901,25 +2932,20 @@ class SiDatepickerComponent {
2901
2932
  return true;
2902
2933
  }
2903
2934
  timeSelected(newTime) {
2904
- if (!newTime) {
2905
- return;
2906
- }
2907
- // Break event cycle
2908
- if (this.time?.getTime() === newTime.getTime()) {
2909
- this.validateTime(newTime);
2935
+ if (newTime == null || newTime === this.time.value) {
2910
2936
  return;
2911
2937
  }
2912
- this.previousTime = this.time;
2913
- this.time = newTime;
2938
+ this.previousTime = this.time.value;
2939
+ this.time.setValue(newTime, { emitEvent: false });
2914
2940
  const oldDate = this.getRelevantDate() ?? new Date();
2915
2941
  let newDate;
2916
2942
  if (this.disabledTime()) {
2917
2943
  // if time is disabled, ensure that 00:00:00 is displayed in any timezone
2918
2944
  newDate = createDate(oldDate);
2919
- this.time = newDate;
2945
+ this.time.setValue(newDate, { emitEvent: false });
2920
2946
  }
2921
2947
  else {
2922
- newDate = createDate(oldDate, this.time.getHours(), this.time.getMinutes(), this.time.getSeconds(), this.time.getMilliseconds());
2948
+ newDate = createDate(oldDate, newTime.getHours(), newTime.getMinutes(), newTime.getSeconds(), newTime.getMilliseconds());
2923
2949
  }
2924
2950
  if (!this.config().enableDateRange) {
2925
2951
  this.setDate(newDate);
@@ -2954,27 +2980,26 @@ class SiDatepickerComponent {
2954
2980
  }
2955
2981
  }
2956
2982
  }
2957
- validateTime(date) {
2958
- // wait for a cycle to initialize timepicker
2959
- setTimeout(() => {
2960
- const config = this.config();
2961
- const timePicker = this.timePicker();
2962
- if (!this.disabledTime() &&
2963
- ((config.minDate && date < config.minDate) || (config.maxDate && date > config.maxDate))) {
2964
- timePicker.forceInvalid.set(true);
2983
+ validateTime(control) {
2984
+ const config = this.config();
2985
+ const errors = {};
2986
+ if (!this.disabledTime() && config.enableTimeValidation && control.value) {
2987
+ if (config.minDate && control.value < config.minDate) {
2988
+ errors.minDate = { requiredDate: config.minDate, actual: control.value };
2965
2989
  }
2966
- else {
2967
- timePicker.forceInvalid.set(false);
2990
+ else if (config.maxDate && control.value > config.maxDate) {
2991
+ errors.maxDate = { requiredDate: config.maxDate, actual: control.value };
2968
2992
  }
2969
- this.cdRef.markForCheck();
2970
- });
2993
+ }
2994
+ return Object.keys(errors).length ? errors : null;
2971
2995
  }
2972
2996
  /**
2973
2997
  * Handle selection in the day view.
2974
2998
  * @param selection - selected date.
2975
2999
  */
2976
3000
  selectionChange(selection) {
2977
- const newDate = createDate(selection, this.time?.getHours(), this.time?.getMinutes(), this.time?.getSeconds(), this.time?.getMilliseconds());
3001
+ const time = this.time.value;
3002
+ const newDate = createDate(selection, time?.getHours(), time?.getMinutes(), time?.getSeconds(), time?.getMilliseconds());
2978
3003
  if (this.config().enableDateRange) {
2979
3004
  const rangeType = this.rangeType();
2980
3005
  let newDateRange = !rangeType || rangeType === 'START'
@@ -3043,18 +3068,18 @@ class SiDatepickerComponent {
3043
3068
  this.activeHover.set(event);
3044
3069
  }
3045
3070
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: SiDatepickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3046
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: SiDatepickerComponent, isStandalone: true, selector: "si-datepicker", inputs: { focusedDate: { classPropertyName: "focusedDate", publicName: "focusedDate", isSignal: true, isRequired: false, transformFunction: null }, date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, dateRange: { classPropertyName: "dateRange", publicName: "dateRange", isSignal: true, isRequired: false, transformFunction: null }, dateRangeRole: { classPropertyName: "dateRangeRole", publicName: "dateRangeRole", isSignal: true, isRequired: false, transformFunction: null }, initialFocus: { classPropertyName: "initialFocus", publicName: "initialFocus", isSignal: true, isRequired: false, transformFunction: null }, disabledTime: { classPropertyName: "disabledTime", publicName: "disabledTime", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, previousLabel: { classPropertyName: "previousLabel", publicName: "previousLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, calenderWeekLabel: { classPropertyName: "calenderWeekLabel", publicName: "calenderWeekLabel", isSignal: true, isRequired: false, transformFunction: null }, calendarWeekLabel: { classPropertyName: "calendarWeekLabel", publicName: "calendarWeekLabel", isSignal: true, isRequired: false, transformFunction: null }, time12h: { classPropertyName: "time12h", publicName: "time12h", isSignal: true, isRequired: false, transformFunction: null }, rangeType: { classPropertyName: "rangeType", publicName: "rangeType", isSignal: true, isRequired: false, transformFunction: null }, minMonth: { classPropertyName: "minMonth", publicName: "minMonth", isSignal: true, isRequired: false, transformFunction: null }, maxMonth: { classPropertyName: "maxMonth", publicName: "maxMonth", isSignal: true, isRequired: false, transformFunction: null }, hideTimeToggle: { classPropertyName: "hideTimeToggle", publicName: "hideTimeToggle", isSignal: true, isRequired: false, transformFunction: null }, hideCalendar: { classPropertyName: "hideCalendar", publicName: "hideCalendar", isSignal: true, isRequired: false, transformFunction: null }, timepickerLabel: { classPropertyName: "timepickerLabel", publicName: "timepickerLabel", isSignal: true, isRequired: false, transformFunction: null }, activeHover: { classPropertyName: "activeHover", publicName: "activeHover", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { focusedDate: "focusedDateChange", date: "dateChange", dateRange: "dateRangeChange", disabledTime: "disabledTimeChange", config: "configChange", rangeType: "rangeTypeChange", activeHover: "activeHoverChange" }, viewQueries: [{ propertyName: "timePicker", first: true, predicate: SiTimepickerComponent, descendants: true, isSignal: true }, { propertyName: "daySelection", first: true, predicate: SiDaySelectionComponent, descendants: true, isSignal: true }, { propertyName: "monthSelection", first: true, predicate: SiMonthSelectionComponent, descendants: true, isSignal: true }, { propertyName: "yearSelection", first: true, predicate: SiYearSelectionComponent, descendants: true, isSignal: true }], usesOnChanges: true, ngImport: i0, template: "@if (!hideCalendar()) {\n <div class=\"text-center pb-6 calendar\">\n @switch (view()) {\n @case ('year') {\n <si-year-selection\n [focusedDate]=\"actualFocusedDate()\"\n [startDate]=\"startDate\"\n [endDate]=\"endDate\"\n [minDate]=\"config().minDate\"\n [maxDate]=\"config().maxDate\"\n [minMonth]=\"minMonth()\"\n [maxMonth]=\"maxMonth()\"\n [isRangeSelection]=\"config().enableDateRange!\"\n [previousLabel]=\"previousLabel() | translate\"\n [nextLabel]=\"nextLabel() | translate\"\n (selectedValueChange)=\"activeYearChange($event)\"\n />\n }\n @case ('month') {\n <si-month-selection\n [startDate]=\"startDate\"\n [endDate]=\"endDate\"\n [months]=\"months\"\n [minDate]=\"config().minDate\"\n [maxDate]=\"config().maxDate\"\n [minMonth]=\"minMonth()\"\n [maxMonth]=\"maxMonth()\"\n [isRangeSelection]=\"config().enableDateRange!\"\n [previewRange]=\"rangeType() === 'END'\"\n [previousLabel]=\"previousLabel() | translate\"\n [nextLabel]=\"nextLabel() | translate\"\n [activeHover]=\"activeHover()\"\n [focusedDate]=\"actualFocusedDate()\"\n (activeHoverChange)=\"onActiveHoverChange($event)\"\n (focusedDateChange)=\"focusedDate.set($event)\"\n (selectedValueChange)=\"activeMonthChange($event)\"\n (viewChange)=\"view.set($event)\"\n />\n }\n @case ('week') {\n <si-day-selection\n [initialFocus]=\"forceFocus()\"\n [startDate]=\"startDate\"\n [endDate]=\"dateRange()?.end\"\n [isRangeSelection]=\"config().enableDateRange!\"\n [previewRange]=\"rangeType() === 'END'\"\n [hideWeekNumbers]=\"hideWeekNumbers\"\n [minDate]=\"config().minDate\"\n [maxDate]=\"config().maxDate\"\n [minMonth]=\"minMonth()\"\n [weekStartDay]=\"weekStartDay\"\n [calendarWeekLabel]=\"derivedWeekLabel()\"\n [previousLabel]=\"previousLabel() | translate\"\n [nextLabel]=\"nextLabel() | translate\"\n [todayLabel]=\"config().todayText\"\n [activeHover]=\"activeHover()\"\n [focusedDate]=\"actualFocusedDate()\"\n (activeHoverChange)=\"onActiveHoverChange($event)\"\n (focusedDateChange)=\"focusedDate.set($event)\"\n (selectedValueChange)=\"selectionChange($event!)\"\n (viewChange)=\"view.set($event)\"\n />\n }\n }\n </div>\n}\n@if (this.config().showTime) {\n <div\n class=\"timepicker-container px-9 pb-6\"\n [class.pt-6]=\"!hideCalendar()\"\n [class.border-top]=\"!hideCalendar()\"\n >\n @if (!config().mandatoryTime && !hideTimeToggle()) {\n <div class=\"mb-5 form-check form-switch\">\n <input\n type=\"checkbox\"\n class=\"form-check-input\"\n role=\"switch\"\n [id]=\"switchId\"\n [checked]=\"!disabledTime()\"\n (change)=\"toggleDisabledTime()\"\n />\n <label class=\"form-check-label\" [for]=\"switchId\">{{\n includeTimeLabel() | translate\n }}</label>\n </div>\n }\n <div class=\"mt-auto\">\n @if (timepickerLabel()) {\n <label class=\"form-label\" [for]=\"timepickerId\">{{ timepickerLabel() | translate }}</label>\n }\n <si-timepicker\n #timePicker\n [id]=\"timepickerId\"\n [ngModel]=\"time\"\n [disabled]=\"disabledTime()\"\n [hoursLabel]=\"config().hoursLabel ?? timePicker.hoursLabel()\"\n [minutesLabel]=\"config().minutesLabel ?? timePicker.minutesLabel()\"\n [secondsLabel]=\"config().secondsLabel ?? timePicker.secondsLabel()\"\n [millisecondsLabel]=\"config().millisecondsLabel ?? timePicker.millisecondsLabel()\"\n [hideLabels]=\"config().hideLabels ?? timePicker.hideLabels()\"\n [hoursAriaLabel]=\"config().hoursAriaLabel ?? timePicker.hoursAriaLabel()\"\n [minutesAriaLabel]=\"config().minutesAriaLabel ?? timePicker.minutesAriaLabel()\"\n [secondsAriaLabel]=\"config().secondsAriaLabel ?? timePicker.secondsAriaLabel()\"\n [millisecondsAriaLabel]=\"\n config().millisecondsAriaLabel ?? timePicker.millisecondsAriaLabel()\n \"\n [hoursPlaceholder]=\"config().hoursPlaceholder ?? timePicker.hoursPlaceholder()\"\n [minutesPlaceholder]=\"config().minutesPlaceholder ?? timePicker.minutesPlaceholder()\"\n [secondsPlaceholder]=\"config().secondsPlaceholder ?? timePicker.secondsPlaceholder()\"\n [millisecondsPlaceholder]=\"\n config().millisecondsPlaceholder ?? timePicker.millisecondsPlaceholder()\n \"\n [meridians]=\"config().meridians ?? timePicker.meridians()\"\n [meridiansLabel]=\"config().meridiansLabel ?? timePicker.meridiansLabel()\"\n [meridiansAriaLabel]=\"config().meridiansAriaLabel ?? timePicker.meridiansAriaLabel()\"\n [showMinutes]=\"config().showMinutes ?? true\"\n [showSeconds]=\"config().showSeconds ?? false\"\n [showMilliseconds]=\"config().showMilliseconds ?? false\"\n [showMeridian]=\"time12h()\"\n (ngModelChange)=\"timeSelected($event)\"\n />\n </div>\n </div>\n}\n", styles: [":host ::ng-deep .selection .month:not(.disabled):hover,:host ::ng-deep .selection .year:not(.disabled):hover,:host ::ng-deep .year:not(.disabled):not(.selected):hover,:host ::ng-deep .month:not(.disabled):not(.selected):hover,:host ::ng-deep .day:not(.disabled):not(.selected):hover{background:var(--element-base-1-hover);color:var(--element-ui-0)}:host ::ng-deep .year,:host ::ng-deep .month,:host ::ng-deep .day{block-size:32px;line-height:32px;inline-size:100%}:host ::ng-deep .day{inline-size:32px}:host ::ng-deep .year,:host ::ng-deep .month,:host ::ng-deep .day{margin-inline:auto;position:relative;border:unset;background-color:unset;padding:0;cursor:pointer;border-radius:var(--element-button-radius)}:host{background:var(--element-base-1);border-radius:var(--element-radius-2);display:flex;flex-direction:column;inline-size:348px}:host ::ng-deep .header,:host ::ng-deep .footer{display:flex;align-items:center}:host ::ng-deep .header{padding-block-start:12px;padding-block-end:16px;padding-inline:32px;border-block-end:1px solid var(--element-ui-4)}:host ::ng-deep .header a{text-decoration:none;cursor:pointer}:host ::ng-deep .footer{margin-block-start:4px;text-align:center}:host ::ng-deep table{inline-size:100%;border-collapse:separate;border-spacing:0 3px;table-layout:fixed;margin-block-end:-3px}:host ::ng-deep .day.selected{background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep .month.selected{background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep .year.selected{background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep td[role=gridcell]{text-align:center}:host ::ng-deep th{font-weight:400;text-align:center;block-size:32px}:host ::ng-deep .week-num,:host ::ng-deep th{font-size:.75rem;color:var(--element-text-secondary);inline-size:32px;cursor:default}:host ::ng-deep .today.selected:before{border-color:var(--element-ui-5)}:host ::ng-deep .today:before{position:absolute;content:\"\";inset:1px;border:1px solid var(--element-ui-1);border-radius:var(--element-radius-2);display:inline-block}:host ::ng-deep .selection .month,:host ::ng-deep .selection .year{block-size:30px;line-height:30px;cursor:pointer}:host ::ng-deep .selection .month{inline-size:50%}:host ::ng-deep .selection .year{inline-size:33.3%}:host ::ng-deep .disabled{color:var(--element-text-disabled);font-weight:400!important;cursor:default!important}:host ::ng-deep .range{background-color:var(--element-ui-4)}:host ::ng-deep .range:hover{background:var(--element-base-1-hover)}:host ::ng-deep .range:hover div.si-h4:hover{background:transparent}:host ::ng-deep .range-hover{background-color:var(--element-base-1-hover)}:host ::ng-deep .range-hover-end{border-start-end-radius:var(--element-button-radius);border-end-end-radius:var(--element-button-radius)}:host ::ng-deep td:is(.range-start,.range-end){background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep td:is(.range-start,.range-end) div.si-h4:hover,:host ::ng-deep td:is(.range-start,.range-end) div.si-body-lg:hover{background:transparent;color:var(--element-base-1)}:host ::ng-deep td:is(.range-start,.range-end) .today:before{border-color:var(--element-ui-5)}:host ::ng-deep td.range-start{border-start-start-radius:var(--element-button-radius);border-end-start-radius:var(--element-button-radius)}:host ::ng-deep td.range-end{border-start-end-radius:var(--element-button-radius);border-end-end-radius:var(--element-button-radius)}:host ::ng-deep .calendar-button{font-weight:600;font-size:.875rem;line-height:1.1428571429;color:var(--element-text-active);min-inline-size:0!important}:host ::ng-deep .calendar{block-size:28em}:host ::ng-deep .timepicker-container{display:flex;flex:1 1 auto;flex-direction:column}\n"], dependencies: [{ kind: "component", type: SiYearSelectionComponent, selector: "si-year-selection", inputs: ["focusedDate"], outputs: ["focusedDateChange", "yearRangeChange"] }, { kind: "component", type: SiMonthSelectionComponent, selector: "si-month-selection", inputs: ["months", "focusedDate"], outputs: ["focusedDateChange", "activeMonthChange", "viewChange"] }, { kind: "component", type: SiDaySelectionComponent, selector: "si-day-selection", inputs: ["hideWeekNumbers", "weekStartDay", "focusedDate", "todayLabel", "calendarWeekLabel"], outputs: ["focusedDateChange", "activeMonthChange", "viewChange"] }, { kind: "component", type: SiTimepickerComponent, selector: "si-timepicker", inputs: ["id", "disabled", "hoursLabel", "minutesLabel", "secondsLabel", "millisecondsLabel", "hideLabels", "hoursAriaLabel", "minutesAriaLabel", "secondsAriaLabel", "millisecondsAriaLabel", "hoursPlaceholder", "minutesPlaceholder", "secondsPlaceholder", "millisecondsPlaceholder", "meridians", "meridiansLabel", "meridiansAriaLabel", "showMinutes", "showSeconds", "showMilliseconds", "showMeridian", "min", "max", "readonly", "errormessageId"], outputs: ["isValid", "meridianChange", "inputCompleted"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: SiTranslatePipe, name: "translate" }] });
3071
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: SiDatepickerComponent, isStandalone: true, selector: "si-datepicker", inputs: { focusedDate: { classPropertyName: "focusedDate", publicName: "focusedDate", isSignal: true, isRequired: false, transformFunction: null }, date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, dateRange: { classPropertyName: "dateRange", publicName: "dateRange", isSignal: true, isRequired: false, transformFunction: null }, dateRangeRole: { classPropertyName: "dateRangeRole", publicName: "dateRangeRole", isSignal: true, isRequired: false, transformFunction: null }, initialFocus: { classPropertyName: "initialFocus", publicName: "initialFocus", isSignal: true, isRequired: false, transformFunction: null }, disabledTime: { classPropertyName: "disabledTime", publicName: "disabledTime", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, previousLabel: { classPropertyName: "previousLabel", publicName: "previousLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, calenderWeekLabel: { classPropertyName: "calenderWeekLabel", publicName: "calenderWeekLabel", isSignal: true, isRequired: false, transformFunction: null }, calendarWeekLabel: { classPropertyName: "calendarWeekLabel", publicName: "calendarWeekLabel", isSignal: true, isRequired: false, transformFunction: null }, time12h: { classPropertyName: "time12h", publicName: "time12h", isSignal: true, isRequired: false, transformFunction: null }, rangeType: { classPropertyName: "rangeType", publicName: "rangeType", isSignal: true, isRequired: false, transformFunction: null }, minMonth: { classPropertyName: "minMonth", publicName: "minMonth", isSignal: true, isRequired: false, transformFunction: null }, maxMonth: { classPropertyName: "maxMonth", publicName: "maxMonth", isSignal: true, isRequired: false, transformFunction: null }, hideTimeToggle: { classPropertyName: "hideTimeToggle", publicName: "hideTimeToggle", isSignal: true, isRequired: false, transformFunction: null }, hideCalendar: { classPropertyName: "hideCalendar", publicName: "hideCalendar", isSignal: true, isRequired: false, transformFunction: null }, timepickerLabel: { classPropertyName: "timepickerLabel", publicName: "timepickerLabel", isSignal: true, isRequired: false, transformFunction: null }, activeHover: { classPropertyName: "activeHover", publicName: "activeHover", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { focusedDate: "focusedDateChange", date: "dateChange", dateRange: "dateRangeChange", disabledTime: "disabledTimeChange", config: "configChange", rangeType: "rangeTypeChange", activeHover: "activeHoverChange" }, viewQueries: [{ propertyName: "daySelection", first: true, predicate: SiDaySelectionComponent, descendants: true, isSignal: true }, { propertyName: "monthSelection", first: true, predicate: SiMonthSelectionComponent, descendants: true, isSignal: true }, { propertyName: "yearSelection", first: true, predicate: SiYearSelectionComponent, descendants: true, isSignal: true }], usesOnChanges: true, ngImport: i0, template: "@if (!hideCalendar()) {\n <div class=\"text-center pb-6 calendar\">\n @switch (view()) {\n @case ('year') {\n <si-year-selection\n [focusedDate]=\"actualFocusedDate()\"\n [startDate]=\"startDate\"\n [endDate]=\"endDate\"\n [minDate]=\"config().minDate\"\n [maxDate]=\"config().maxDate\"\n [minMonth]=\"minMonth()\"\n [maxMonth]=\"maxMonth()\"\n [isRangeSelection]=\"config().enableDateRange!\"\n [previousLabel]=\"previousLabel() | translate\"\n [nextLabel]=\"nextLabel() | translate\"\n (selectedValueChange)=\"activeYearChange($event)\"\n />\n }\n @case ('month') {\n <si-month-selection\n [startDate]=\"startDate\"\n [endDate]=\"endDate\"\n [months]=\"months\"\n [minDate]=\"config().minDate\"\n [maxDate]=\"config().maxDate\"\n [minMonth]=\"minMonth()\"\n [maxMonth]=\"maxMonth()\"\n [isRangeSelection]=\"config().enableDateRange!\"\n [previewRange]=\"rangeType() === 'END'\"\n [previousLabel]=\"previousLabel() | translate\"\n [nextLabel]=\"nextLabel() | translate\"\n [activeHover]=\"activeHover()\"\n [focusedDate]=\"actualFocusedDate()\"\n (activeHoverChange)=\"onActiveHoverChange($event)\"\n (focusedDateChange)=\"focusedDate.set($event)\"\n (selectedValueChange)=\"activeMonthChange($event)\"\n (viewChange)=\"view.set($event)\"\n />\n }\n @case ('week') {\n <si-day-selection\n [initialFocus]=\"forceFocus()\"\n [startDate]=\"startDate\"\n [endDate]=\"dateRange()?.end\"\n [isRangeSelection]=\"config().enableDateRange!\"\n [previewRange]=\"rangeType() === 'END'\"\n [hideWeekNumbers]=\"hideWeekNumbers\"\n [minDate]=\"config().minDate\"\n [maxDate]=\"config().maxDate\"\n [minMonth]=\"minMonth()\"\n [weekStartDay]=\"weekStartDay\"\n [calendarWeekLabel]=\"derivedWeekLabel()\"\n [previousLabel]=\"previousLabel() | translate\"\n [nextLabel]=\"nextLabel() | translate\"\n [todayLabel]=\"config().todayText\"\n [activeHover]=\"activeHover()\"\n [focusedDate]=\"actualFocusedDate()\"\n (activeHoverChange)=\"onActiveHoverChange($event)\"\n (focusedDateChange)=\"focusedDate.set($event)\"\n (selectedValueChange)=\"selectionChange($event!)\"\n (viewChange)=\"view.set($event)\"\n />\n }\n }\n </div>\n}\n@if (this.config().showTime) {\n <div\n class=\"timepicker-container px-9 pb-6\"\n [class.pt-6]=\"!hideCalendar()\"\n [class.border-top]=\"!hideCalendar()\"\n >\n @if (!config().mandatoryTime && !hideTimeToggle()) {\n <div class=\"mb-5 form-check form-switch\">\n <input\n type=\"checkbox\"\n class=\"form-check-input\"\n role=\"switch\"\n [id]=\"switchId\"\n [checked]=\"!disabledTime()\"\n (change)=\"toggleDisabledTime()\"\n />\n <label class=\"form-check-label\" [for]=\"switchId\">{{\n includeTimeLabel() | translate\n }}</label>\n </div>\n }\n <div class=\"mt-auto\">\n @if (timepickerLabel()) {\n <label class=\"form-label\" [for]=\"timepickerId\">{{ timepickerLabel() | translate }}</label>\n }\n <si-timepicker\n #timePicker\n [id]=\"timepickerId\"\n [formControl]=\"time\"\n [hoursLabel]=\"config().hoursLabel ?? timePicker.hoursLabel()\"\n [minutesLabel]=\"config().minutesLabel ?? timePicker.minutesLabel()\"\n [secondsLabel]=\"config().secondsLabel ?? timePicker.secondsLabel()\"\n [millisecondsLabel]=\"config().millisecondsLabel ?? timePicker.millisecondsLabel()\"\n [hideLabels]=\"config().hideLabels ?? timePicker.hideLabels()\"\n [hoursAriaLabel]=\"config().hoursAriaLabel ?? timePicker.hoursAriaLabel()\"\n [minutesAriaLabel]=\"config().minutesAriaLabel ?? timePicker.minutesAriaLabel()\"\n [secondsAriaLabel]=\"config().secondsAriaLabel ?? timePicker.secondsAriaLabel()\"\n [millisecondsAriaLabel]=\"\n config().millisecondsAriaLabel ?? timePicker.millisecondsAriaLabel()\n \"\n [hoursPlaceholder]=\"config().hoursPlaceholder ?? timePicker.hoursPlaceholder()\"\n [minutesPlaceholder]=\"config().minutesPlaceholder ?? timePicker.minutesPlaceholder()\"\n [secondsPlaceholder]=\"config().secondsPlaceholder ?? timePicker.secondsPlaceholder()\"\n [millisecondsPlaceholder]=\"\n config().millisecondsPlaceholder ?? timePicker.millisecondsPlaceholder()\n \"\n [meridians]=\"config().meridians ?? timePicker.meridians()\"\n [meridiansLabel]=\"config().meridiansLabel ?? timePicker.meridiansLabel()\"\n [meridiansAriaLabel]=\"config().meridiansAriaLabel ?? timePicker.meridiansAriaLabel()\"\n [showMinutes]=\"config().showMinutes ?? true\"\n [showSeconds]=\"config().showSeconds ?? false\"\n [showMilliseconds]=\"config().showMilliseconds ?? false\"\n [showMeridian]=\"time12h()\"\n />\n </div>\n </div>\n}\n", styles: [":host ::ng-deep .selection .month:not(.disabled):hover,:host ::ng-deep .selection .year:not(.disabled):hover,:host ::ng-deep .year:not(.disabled):not(.selected):hover,:host ::ng-deep .month:not(.disabled):not(.selected):hover,:host ::ng-deep .day:not(.disabled):not(.selected):hover{background:var(--element-base-1-hover);color:var(--element-ui-0)}:host ::ng-deep .year,:host ::ng-deep .month,:host ::ng-deep .day{block-size:32px;line-height:32px;inline-size:100%}:host ::ng-deep .day{inline-size:32px}:host ::ng-deep .year,:host ::ng-deep .month,:host ::ng-deep .day{margin-inline:auto;position:relative;border:unset;background-color:unset;padding:0;cursor:pointer;border-radius:var(--element-button-radius)}:host{background:var(--element-base-1);border-radius:var(--element-radius-2);display:flex;flex-direction:column;inline-size:348px}:host ::ng-deep .header,:host ::ng-deep .footer{display:flex;align-items:center}:host ::ng-deep .header{padding-block-start:12px;padding-block-end:16px;padding-inline:32px;border-block-end:1px solid var(--element-ui-4)}:host ::ng-deep .header a{text-decoration:none;cursor:pointer}:host ::ng-deep .footer{margin-block-start:4px;text-align:center}:host ::ng-deep table{inline-size:100%;border-collapse:separate;border-spacing:0 3px;table-layout:fixed;margin-block-end:-3px}:host ::ng-deep .day.selected{background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep .month.selected{background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep .year.selected{background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep td[role=gridcell]{text-align:center}:host ::ng-deep th{font-weight:400;text-align:center;block-size:32px}:host ::ng-deep .week-num,:host ::ng-deep th{font-size:.75rem;color:var(--element-text-secondary);inline-size:32px;cursor:default}:host ::ng-deep .today.selected:before{border-color:var(--element-ui-5)}:host ::ng-deep .today:before{position:absolute;content:\"\";inset:1px;border:1px solid var(--element-ui-1);border-radius:var(--element-radius-2);display:inline-block}:host ::ng-deep .selection .month,:host ::ng-deep .selection .year{block-size:30px;line-height:30px;cursor:pointer}:host ::ng-deep .selection .month{inline-size:50%}:host ::ng-deep .selection .year{inline-size:33.3%}:host ::ng-deep .disabled{color:var(--element-text-disabled);font-weight:400!important;cursor:default!important}:host ::ng-deep .range{background-color:var(--element-ui-4)}:host ::ng-deep .range:hover{background:var(--element-base-1-hover)}:host ::ng-deep .range:hover div.si-h4:hover{background:transparent}:host ::ng-deep .range-hover{background-color:var(--element-base-1-hover)}:host ::ng-deep .range-hover-end{border-start-end-radius:var(--element-button-radius);border-end-end-radius:var(--element-button-radius)}:host ::ng-deep td:is(.range-start,.range-end){background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep td:is(.range-start,.range-end) div.si-h4:hover,:host ::ng-deep td:is(.range-start,.range-end) div.si-body-lg:hover{background:transparent;color:var(--element-base-1)}:host ::ng-deep td:is(.range-start,.range-end) .today:before{border-color:var(--element-ui-5)}:host ::ng-deep td.range-start{border-start-start-radius:var(--element-button-radius);border-end-start-radius:var(--element-button-radius)}:host ::ng-deep td.range-end{border-start-end-radius:var(--element-button-radius);border-end-end-radius:var(--element-button-radius)}:host ::ng-deep .calendar-button{font-weight:600;font-size:.875rem;line-height:1.1428571429;color:var(--element-text-active);min-inline-size:0!important}:host ::ng-deep .calendar{block-size:28em}:host ::ng-deep .timepicker-container{display:flex;flex:1 1 auto;flex-direction:column}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: SiYearSelectionComponent, selector: "si-year-selection", inputs: ["focusedDate"], outputs: ["focusedDateChange", "yearRangeChange"] }, { kind: "component", type: SiMonthSelectionComponent, selector: "si-month-selection", inputs: ["months", "focusedDate"], outputs: ["focusedDateChange", "activeMonthChange", "viewChange"] }, { kind: "component", type: SiDaySelectionComponent, selector: "si-day-selection", inputs: ["hideWeekNumbers", "weekStartDay", "focusedDate", "todayLabel", "calendarWeekLabel"], outputs: ["focusedDateChange", "activeMonthChange", "viewChange"] }, { kind: "component", type: SiTimepickerComponent, selector: "si-timepicker", inputs: ["id", "disabled", "hoursLabel", "minutesLabel", "secondsLabel", "millisecondsLabel", "hideLabels", "hoursAriaLabel", "minutesAriaLabel", "secondsAriaLabel", "millisecondsAriaLabel", "hoursPlaceholder", "minutesPlaceholder", "secondsPlaceholder", "millisecondsPlaceholder", "meridians", "meridiansLabel", "meridiansAriaLabel", "showMinutes", "showSeconds", "showMilliseconds", "showMeridian", "min", "max", "readonly", "errormessageId"], outputs: ["isValid", "meridianChange", "inputCompleted"] }, { kind: "pipe", type: SiTranslatePipe, name: "translate" }] });
3047
3072
  }
3048
3073
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: SiDatepickerComponent, decorators: [{
3049
3074
  type: Component,
3050
3075
  args: [{ selector: 'si-datepicker', imports: [
3076
+ ReactiveFormsModule,
3051
3077
  SiYearSelectionComponent,
3052
3078
  SiMonthSelectionComponent,
3053
3079
  SiDaySelectionComponent,
3054
3080
  SiTimepickerComponent,
3055
- FormsModule,
3056
3081
  SiTranslatePipe
3057
- ], template: "@if (!hideCalendar()) {\n <div class=\"text-center pb-6 calendar\">\n @switch (view()) {\n @case ('year') {\n <si-year-selection\n [focusedDate]=\"actualFocusedDate()\"\n [startDate]=\"startDate\"\n [endDate]=\"endDate\"\n [minDate]=\"config().minDate\"\n [maxDate]=\"config().maxDate\"\n [minMonth]=\"minMonth()\"\n [maxMonth]=\"maxMonth()\"\n [isRangeSelection]=\"config().enableDateRange!\"\n [previousLabel]=\"previousLabel() | translate\"\n [nextLabel]=\"nextLabel() | translate\"\n (selectedValueChange)=\"activeYearChange($event)\"\n />\n }\n @case ('month') {\n <si-month-selection\n [startDate]=\"startDate\"\n [endDate]=\"endDate\"\n [months]=\"months\"\n [minDate]=\"config().minDate\"\n [maxDate]=\"config().maxDate\"\n [minMonth]=\"minMonth()\"\n [maxMonth]=\"maxMonth()\"\n [isRangeSelection]=\"config().enableDateRange!\"\n [previewRange]=\"rangeType() === 'END'\"\n [previousLabel]=\"previousLabel() | translate\"\n [nextLabel]=\"nextLabel() | translate\"\n [activeHover]=\"activeHover()\"\n [focusedDate]=\"actualFocusedDate()\"\n (activeHoverChange)=\"onActiveHoverChange($event)\"\n (focusedDateChange)=\"focusedDate.set($event)\"\n (selectedValueChange)=\"activeMonthChange($event)\"\n (viewChange)=\"view.set($event)\"\n />\n }\n @case ('week') {\n <si-day-selection\n [initialFocus]=\"forceFocus()\"\n [startDate]=\"startDate\"\n [endDate]=\"dateRange()?.end\"\n [isRangeSelection]=\"config().enableDateRange!\"\n [previewRange]=\"rangeType() === 'END'\"\n [hideWeekNumbers]=\"hideWeekNumbers\"\n [minDate]=\"config().minDate\"\n [maxDate]=\"config().maxDate\"\n [minMonth]=\"minMonth()\"\n [weekStartDay]=\"weekStartDay\"\n [calendarWeekLabel]=\"derivedWeekLabel()\"\n [previousLabel]=\"previousLabel() | translate\"\n [nextLabel]=\"nextLabel() | translate\"\n [todayLabel]=\"config().todayText\"\n [activeHover]=\"activeHover()\"\n [focusedDate]=\"actualFocusedDate()\"\n (activeHoverChange)=\"onActiveHoverChange($event)\"\n (focusedDateChange)=\"focusedDate.set($event)\"\n (selectedValueChange)=\"selectionChange($event!)\"\n (viewChange)=\"view.set($event)\"\n />\n }\n }\n </div>\n}\n@if (this.config().showTime) {\n <div\n class=\"timepicker-container px-9 pb-6\"\n [class.pt-6]=\"!hideCalendar()\"\n [class.border-top]=\"!hideCalendar()\"\n >\n @if (!config().mandatoryTime && !hideTimeToggle()) {\n <div class=\"mb-5 form-check form-switch\">\n <input\n type=\"checkbox\"\n class=\"form-check-input\"\n role=\"switch\"\n [id]=\"switchId\"\n [checked]=\"!disabledTime()\"\n (change)=\"toggleDisabledTime()\"\n />\n <label class=\"form-check-label\" [for]=\"switchId\">{{\n includeTimeLabel() | translate\n }}</label>\n </div>\n }\n <div class=\"mt-auto\">\n @if (timepickerLabel()) {\n <label class=\"form-label\" [for]=\"timepickerId\">{{ timepickerLabel() | translate }}</label>\n }\n <si-timepicker\n #timePicker\n [id]=\"timepickerId\"\n [ngModel]=\"time\"\n [disabled]=\"disabledTime()\"\n [hoursLabel]=\"config().hoursLabel ?? timePicker.hoursLabel()\"\n [minutesLabel]=\"config().minutesLabel ?? timePicker.minutesLabel()\"\n [secondsLabel]=\"config().secondsLabel ?? timePicker.secondsLabel()\"\n [millisecondsLabel]=\"config().millisecondsLabel ?? timePicker.millisecondsLabel()\"\n [hideLabels]=\"config().hideLabels ?? timePicker.hideLabels()\"\n [hoursAriaLabel]=\"config().hoursAriaLabel ?? timePicker.hoursAriaLabel()\"\n [minutesAriaLabel]=\"config().minutesAriaLabel ?? timePicker.minutesAriaLabel()\"\n [secondsAriaLabel]=\"config().secondsAriaLabel ?? timePicker.secondsAriaLabel()\"\n [millisecondsAriaLabel]=\"\n config().millisecondsAriaLabel ?? timePicker.millisecondsAriaLabel()\n \"\n [hoursPlaceholder]=\"config().hoursPlaceholder ?? timePicker.hoursPlaceholder()\"\n [minutesPlaceholder]=\"config().minutesPlaceholder ?? timePicker.minutesPlaceholder()\"\n [secondsPlaceholder]=\"config().secondsPlaceholder ?? timePicker.secondsPlaceholder()\"\n [millisecondsPlaceholder]=\"\n config().millisecondsPlaceholder ?? timePicker.millisecondsPlaceholder()\n \"\n [meridians]=\"config().meridians ?? timePicker.meridians()\"\n [meridiansLabel]=\"config().meridiansLabel ?? timePicker.meridiansLabel()\"\n [meridiansAriaLabel]=\"config().meridiansAriaLabel ?? timePicker.meridiansAriaLabel()\"\n [showMinutes]=\"config().showMinutes ?? true\"\n [showSeconds]=\"config().showSeconds ?? false\"\n [showMilliseconds]=\"config().showMilliseconds ?? false\"\n [showMeridian]=\"time12h()\"\n (ngModelChange)=\"timeSelected($event)\"\n />\n </div>\n </div>\n}\n", styles: [":host ::ng-deep .selection .month:not(.disabled):hover,:host ::ng-deep .selection .year:not(.disabled):hover,:host ::ng-deep .year:not(.disabled):not(.selected):hover,:host ::ng-deep .month:not(.disabled):not(.selected):hover,:host ::ng-deep .day:not(.disabled):not(.selected):hover{background:var(--element-base-1-hover);color:var(--element-ui-0)}:host ::ng-deep .year,:host ::ng-deep .month,:host ::ng-deep .day{block-size:32px;line-height:32px;inline-size:100%}:host ::ng-deep .day{inline-size:32px}:host ::ng-deep .year,:host ::ng-deep .month,:host ::ng-deep .day{margin-inline:auto;position:relative;border:unset;background-color:unset;padding:0;cursor:pointer;border-radius:var(--element-button-radius)}:host{background:var(--element-base-1);border-radius:var(--element-radius-2);display:flex;flex-direction:column;inline-size:348px}:host ::ng-deep .header,:host ::ng-deep .footer{display:flex;align-items:center}:host ::ng-deep .header{padding-block-start:12px;padding-block-end:16px;padding-inline:32px;border-block-end:1px solid var(--element-ui-4)}:host ::ng-deep .header a{text-decoration:none;cursor:pointer}:host ::ng-deep .footer{margin-block-start:4px;text-align:center}:host ::ng-deep table{inline-size:100%;border-collapse:separate;border-spacing:0 3px;table-layout:fixed;margin-block-end:-3px}:host ::ng-deep .day.selected{background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep .month.selected{background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep .year.selected{background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep td[role=gridcell]{text-align:center}:host ::ng-deep th{font-weight:400;text-align:center;block-size:32px}:host ::ng-deep .week-num,:host ::ng-deep th{font-size:.75rem;color:var(--element-text-secondary);inline-size:32px;cursor:default}:host ::ng-deep .today.selected:before{border-color:var(--element-ui-5)}:host ::ng-deep .today:before{position:absolute;content:\"\";inset:1px;border:1px solid var(--element-ui-1);border-radius:var(--element-radius-2);display:inline-block}:host ::ng-deep .selection .month,:host ::ng-deep .selection .year{block-size:30px;line-height:30px;cursor:pointer}:host ::ng-deep .selection .month{inline-size:50%}:host ::ng-deep .selection .year{inline-size:33.3%}:host ::ng-deep .disabled{color:var(--element-text-disabled);font-weight:400!important;cursor:default!important}:host ::ng-deep .range{background-color:var(--element-ui-4)}:host ::ng-deep .range:hover{background:var(--element-base-1-hover)}:host ::ng-deep .range:hover div.si-h4:hover{background:transparent}:host ::ng-deep .range-hover{background-color:var(--element-base-1-hover)}:host ::ng-deep .range-hover-end{border-start-end-radius:var(--element-button-radius);border-end-end-radius:var(--element-button-radius)}:host ::ng-deep td:is(.range-start,.range-end){background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep td:is(.range-start,.range-end) div.si-h4:hover,:host ::ng-deep td:is(.range-start,.range-end) div.si-body-lg:hover{background:transparent;color:var(--element-base-1)}:host ::ng-deep td:is(.range-start,.range-end) .today:before{border-color:var(--element-ui-5)}:host ::ng-deep td.range-start{border-start-start-radius:var(--element-button-radius);border-end-start-radius:var(--element-button-radius)}:host ::ng-deep td.range-end{border-start-end-radius:var(--element-button-radius);border-end-end-radius:var(--element-button-radius)}:host ::ng-deep .calendar-button{font-weight:600;font-size:.875rem;line-height:1.1428571429;color:var(--element-text-active);min-inline-size:0!important}:host ::ng-deep .calendar{block-size:28em}:host ::ng-deep .timepicker-container{display:flex;flex:1 1 auto;flex-direction:column}\n"] }]
3082
+ ], template: "@if (!hideCalendar()) {\n <div class=\"text-center pb-6 calendar\">\n @switch (view()) {\n @case ('year') {\n <si-year-selection\n [focusedDate]=\"actualFocusedDate()\"\n [startDate]=\"startDate\"\n [endDate]=\"endDate\"\n [minDate]=\"config().minDate\"\n [maxDate]=\"config().maxDate\"\n [minMonth]=\"minMonth()\"\n [maxMonth]=\"maxMonth()\"\n [isRangeSelection]=\"config().enableDateRange!\"\n [previousLabel]=\"previousLabel() | translate\"\n [nextLabel]=\"nextLabel() | translate\"\n (selectedValueChange)=\"activeYearChange($event)\"\n />\n }\n @case ('month') {\n <si-month-selection\n [startDate]=\"startDate\"\n [endDate]=\"endDate\"\n [months]=\"months\"\n [minDate]=\"config().minDate\"\n [maxDate]=\"config().maxDate\"\n [minMonth]=\"minMonth()\"\n [maxMonth]=\"maxMonth()\"\n [isRangeSelection]=\"config().enableDateRange!\"\n [previewRange]=\"rangeType() === 'END'\"\n [previousLabel]=\"previousLabel() | translate\"\n [nextLabel]=\"nextLabel() | translate\"\n [activeHover]=\"activeHover()\"\n [focusedDate]=\"actualFocusedDate()\"\n (activeHoverChange)=\"onActiveHoverChange($event)\"\n (focusedDateChange)=\"focusedDate.set($event)\"\n (selectedValueChange)=\"activeMonthChange($event)\"\n (viewChange)=\"view.set($event)\"\n />\n }\n @case ('week') {\n <si-day-selection\n [initialFocus]=\"forceFocus()\"\n [startDate]=\"startDate\"\n [endDate]=\"dateRange()?.end\"\n [isRangeSelection]=\"config().enableDateRange!\"\n [previewRange]=\"rangeType() === 'END'\"\n [hideWeekNumbers]=\"hideWeekNumbers\"\n [minDate]=\"config().minDate\"\n [maxDate]=\"config().maxDate\"\n [minMonth]=\"minMonth()\"\n [weekStartDay]=\"weekStartDay\"\n [calendarWeekLabel]=\"derivedWeekLabel()\"\n [previousLabel]=\"previousLabel() | translate\"\n [nextLabel]=\"nextLabel() | translate\"\n [todayLabel]=\"config().todayText\"\n [activeHover]=\"activeHover()\"\n [focusedDate]=\"actualFocusedDate()\"\n (activeHoverChange)=\"onActiveHoverChange($event)\"\n (focusedDateChange)=\"focusedDate.set($event)\"\n (selectedValueChange)=\"selectionChange($event!)\"\n (viewChange)=\"view.set($event)\"\n />\n }\n }\n </div>\n}\n@if (this.config().showTime) {\n <div\n class=\"timepicker-container px-9 pb-6\"\n [class.pt-6]=\"!hideCalendar()\"\n [class.border-top]=\"!hideCalendar()\"\n >\n @if (!config().mandatoryTime && !hideTimeToggle()) {\n <div class=\"mb-5 form-check form-switch\">\n <input\n type=\"checkbox\"\n class=\"form-check-input\"\n role=\"switch\"\n [id]=\"switchId\"\n [checked]=\"!disabledTime()\"\n (change)=\"toggleDisabledTime()\"\n />\n <label class=\"form-check-label\" [for]=\"switchId\">{{\n includeTimeLabel() | translate\n }}</label>\n </div>\n }\n <div class=\"mt-auto\">\n @if (timepickerLabel()) {\n <label class=\"form-label\" [for]=\"timepickerId\">{{ timepickerLabel() | translate }}</label>\n }\n <si-timepicker\n #timePicker\n [id]=\"timepickerId\"\n [formControl]=\"time\"\n [hoursLabel]=\"config().hoursLabel ?? timePicker.hoursLabel()\"\n [minutesLabel]=\"config().minutesLabel ?? timePicker.minutesLabel()\"\n [secondsLabel]=\"config().secondsLabel ?? timePicker.secondsLabel()\"\n [millisecondsLabel]=\"config().millisecondsLabel ?? timePicker.millisecondsLabel()\"\n [hideLabels]=\"config().hideLabels ?? timePicker.hideLabels()\"\n [hoursAriaLabel]=\"config().hoursAriaLabel ?? timePicker.hoursAriaLabel()\"\n [minutesAriaLabel]=\"config().minutesAriaLabel ?? timePicker.minutesAriaLabel()\"\n [secondsAriaLabel]=\"config().secondsAriaLabel ?? timePicker.secondsAriaLabel()\"\n [millisecondsAriaLabel]=\"\n config().millisecondsAriaLabel ?? timePicker.millisecondsAriaLabel()\n \"\n [hoursPlaceholder]=\"config().hoursPlaceholder ?? timePicker.hoursPlaceholder()\"\n [minutesPlaceholder]=\"config().minutesPlaceholder ?? timePicker.minutesPlaceholder()\"\n [secondsPlaceholder]=\"config().secondsPlaceholder ?? timePicker.secondsPlaceholder()\"\n [millisecondsPlaceholder]=\"\n config().millisecondsPlaceholder ?? timePicker.millisecondsPlaceholder()\n \"\n [meridians]=\"config().meridians ?? timePicker.meridians()\"\n [meridiansLabel]=\"config().meridiansLabel ?? timePicker.meridiansLabel()\"\n [meridiansAriaLabel]=\"config().meridiansAriaLabel ?? timePicker.meridiansAriaLabel()\"\n [showMinutes]=\"config().showMinutes ?? true\"\n [showSeconds]=\"config().showSeconds ?? false\"\n [showMilliseconds]=\"config().showMilliseconds ?? false\"\n [showMeridian]=\"time12h()\"\n />\n </div>\n </div>\n}\n", styles: [":host ::ng-deep .selection .month:not(.disabled):hover,:host ::ng-deep .selection .year:not(.disabled):hover,:host ::ng-deep .year:not(.disabled):not(.selected):hover,:host ::ng-deep .month:not(.disabled):not(.selected):hover,:host ::ng-deep .day:not(.disabled):not(.selected):hover{background:var(--element-base-1-hover);color:var(--element-ui-0)}:host ::ng-deep .year,:host ::ng-deep .month,:host ::ng-deep .day{block-size:32px;line-height:32px;inline-size:100%}:host ::ng-deep .day{inline-size:32px}:host ::ng-deep .year,:host ::ng-deep .month,:host ::ng-deep .day{margin-inline:auto;position:relative;border:unset;background-color:unset;padding:0;cursor:pointer;border-radius:var(--element-button-radius)}:host{background:var(--element-base-1);border-radius:var(--element-radius-2);display:flex;flex-direction:column;inline-size:348px}:host ::ng-deep .header,:host ::ng-deep .footer{display:flex;align-items:center}:host ::ng-deep .header{padding-block-start:12px;padding-block-end:16px;padding-inline:32px;border-block-end:1px solid var(--element-ui-4)}:host ::ng-deep .header a{text-decoration:none;cursor:pointer}:host ::ng-deep .footer{margin-block-start:4px;text-align:center}:host ::ng-deep table{inline-size:100%;border-collapse:separate;border-spacing:0 3px;table-layout:fixed;margin-block-end:-3px}:host ::ng-deep .day.selected{background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep .month.selected{background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep .year.selected{background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep td[role=gridcell]{text-align:center}:host ::ng-deep th{font-weight:400;text-align:center;block-size:32px}:host ::ng-deep .week-num,:host ::ng-deep th{font-size:.75rem;color:var(--element-text-secondary);inline-size:32px;cursor:default}:host ::ng-deep .today.selected:before{border-color:var(--element-ui-5)}:host ::ng-deep .today:before{position:absolute;content:\"\";inset:1px;border:1px solid var(--element-ui-1);border-radius:var(--element-radius-2);display:inline-block}:host ::ng-deep .selection .month,:host ::ng-deep .selection .year{block-size:30px;line-height:30px;cursor:pointer}:host ::ng-deep .selection .month{inline-size:50%}:host ::ng-deep .selection .year{inline-size:33.3%}:host ::ng-deep .disabled{color:var(--element-text-disabled);font-weight:400!important;cursor:default!important}:host ::ng-deep .range{background-color:var(--element-ui-4)}:host ::ng-deep .range:hover{background:var(--element-base-1-hover)}:host ::ng-deep .range:hover div.si-h4:hover{background:transparent}:host ::ng-deep .range-hover{background-color:var(--element-base-1-hover)}:host ::ng-deep .range-hover-end{border-start-end-radius:var(--element-button-radius);border-end-end-radius:var(--element-button-radius)}:host ::ng-deep td:is(.range-start,.range-end){background:var(--element-ui-0);color:var(--element-base-1)}:host ::ng-deep td:is(.range-start,.range-end) div.si-h4:hover,:host ::ng-deep td:is(.range-start,.range-end) div.si-body-lg:hover{background:transparent;color:var(--element-base-1)}:host ::ng-deep td:is(.range-start,.range-end) .today:before{border-color:var(--element-ui-5)}:host ::ng-deep td.range-start{border-start-start-radius:var(--element-button-radius);border-end-start-radius:var(--element-button-radius)}:host ::ng-deep td.range-end{border-start-end-radius:var(--element-button-radius);border-end-end-radius:var(--element-button-radius)}:host ::ng-deep .calendar-button{font-weight:600;font-size:.875rem;line-height:1.1428571429;color:var(--element-text-active);min-inline-size:0!important}:host ::ng-deep .calendar{block-size:28em}:host ::ng-deep .timepicker-container{display:flex;flex:1 1 auto;flex-direction:column}\n"] }]
3058
3083
  }], ctorParameters: () => [] });
3059
3084
 
3060
3085
  /**
@@ -3454,12 +3479,11 @@ class SiDatepickerOverlayDirective {
3454
3479
  });
3455
3480
  }
3456
3481
  createDesktopOverlay() {
3457
- const popoverPositions = getOverlayPositions(this.triggerElementRef, this.placement(), false);
3458
3482
  this.overlayRef = this.overlay.create({
3459
3483
  positionStrategy: this.overlay
3460
3484
  .position()
3461
3485
  .flexibleConnectedTo(this.triggerElementRef)
3462
- .withPositions(popoverPositions)
3486
+ .withPositions(this.placement())
3463
3487
  .withPush(true)
3464
3488
  .withGrowAfterOpen(true)
3465
3489
  .withFlexibleDimensions(true)
@@ -3551,7 +3575,7 @@ class SiDatepickerDirective extends SiDateInputDirective {
3551
3575
  this.subscribeDateChanges(this.overlayToggle.showOverlay(initialFocus, {
3552
3576
  config: this.siDatepickerConfig(),
3553
3577
  date: this.date,
3554
- time12h: this.getTime12h()
3578
+ time12h: is12HourFormat(this.locale, this.siDatepickerConfig() ?? {})
3555
3579
  }));
3556
3580
  }
3557
3581
  /**
@@ -3565,10 +3589,6 @@ class SiDatepickerDirective extends SiDateInputDirective {
3565
3589
  this.show();
3566
3590
  }
3567
3591
  }
3568
- getTime12h() {
3569
- const dateFormat = getDatepickerFormat(this.locale, this.siDatepickerConfig(), true);
3570
- return dateFormat?.includes('a');
3571
- }
3572
3592
  subscribeDateChanges(overlay) {
3573
3593
  this.overlaySubscriptions?.forEach(s => s.unsubscribe());
3574
3594
  overlay?.instance.date.subscribe(d => this.onDateChanged(d));
@@ -3770,6 +3790,7 @@ class SiDateRangeComponent {
3770
3790
  disabled = computed(() => this.disabledInput() || this.disabledNgControl());
3771
3791
  disabledNgControl = signal(false);
3772
3792
  cdRef = inject(ChangeDetectorRef);
3793
+ locale = inject(LOCALE_ID).toString();
3773
3794
  overlayToggle = inject(SiDatepickerOverlayDirective);
3774
3795
  elementRef = inject(ElementRef);
3775
3796
  defaultPlacement = [
@@ -3853,7 +3874,8 @@ class SiDateRangeComponent {
3853
3874
  }
3854
3875
  this.subscribeRangeChanges(this.overlayToggle.showOverlay(true, {
3855
3876
  config: this.siDatepickerConfig(),
3856
- dateRange: this.value()
3877
+ dateRange: this.value(),
3878
+ time12h: is12HourFormat(this.locale, this.siDatepickerConfig())
3857
3879
  }));
3858
3880
  }
3859
3881
  subscribeRangeChanges(overlay) {
@@ -3950,7 +3972,7 @@ class SiDateRangeComponent {
3950
3972
  provide: SI_FORM_ITEM_CONTROL,
3951
3973
  useExisting: SiDateRangeComponent
3952
3974
  }
3953
- ], viewQueries: [{ propertyName: "inputDirectives", predicate: SiDateInputDirective, descendants: true, isSignal: true }, { propertyName: "startInput", first: true, predicate: ["startInput"], descendants: true, isSignal: true }, { propertyName: "endInput", first: true, predicate: ["endInput"], descendants: true, isSignal: true }, { propertyName: "button", first: true, predicate: ["button"], descendants: true, isSignal: true }], usesOnChanges: true, hostDirectives: [{ directive: SiDatepickerOverlayDirective, outputs: ["siDatepickerClose", "siDatepickerClose"] }], ngImport: i0, template: "<input\n #startInput=\"ngModel\"\n type=\"text\"\n class=\"border-0 p-0 focus-none\"\n siDateInput\n [ngModel]=\"value()?.start ?? null\"\n [siDatepickerConfig]=\"siDatepickerConfig()\"\n [placeholder]=\"startDatePlaceholder() | translate\"\n [attr.aria-label]=\"startDatePlaceholder() | translate\"\n [errormessageId]=\"errormessageId()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n (ngModelChange)=\"onInputChanged({ start: $event, end: value()?.end })\"\n/>\n<span class=\"mx-3\">-</span>\n<input\n #endInput=\"ngModel\"\n type=\"text\"\n class=\"border-0 p-0 focus-none text-end\"\n siDateInput\n [ngModel]=\"value()?.end ?? null\"\n [siDatepickerConfig]=\"siDatepickerConfig()\"\n [placeholder]=\"endDatePlaceholder() | translate\"\n [attr.aria-label]=\"endDatePlaceholder() | translate\"\n [errormessageId]=\"errormessageId()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n (ngModelChange)=\"onInputChanged({ start: value()?.start, end: $event })\"\n/>\n<button\n #button\n type=\"button\"\n class=\"btn btn-circle btn-tertiary btn-xs\"\n [attr.aria-label]=\"ariaLabelCalendarButton() | translate\"\n [disabled]=\"disabled() || readonly()\"\n (click)=\"show()\"\n>\n <si-icon [icon]=\"icons.elementCalendar\" />\n</button>\n", styles: [":host{display:block;min-inline-size:237px;--si-action-icon-offset: 22px}:host(:focus-within){outline:var(--element-button-focus-width) solid var(--element-focus-default);outline-offset:var(--element-button-focus-overlay-width)}input{flex-grow:1;background-color:transparent;min-inline-size:80px}input::placeholder{opacity:1;color:var(--element-text-secondary)}input:disabled,input[readonly]{background-color:var(--element-base-1);opacity:1}input:disabled::placeholder{color:transparent}input:not([readonly]):focus::placeholder,input:focus:not([readonly]):focus::placeholder{color:transparent}.disabled,.disabled:hover,.disabled:focus{--border-color: var(--element-ui-3);color:var(--element-text-disabled)}.btn-circle{margin-inline-start:var(--si-feedback-icon-offset, 4px)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: SiDateInputDirective, selector: "input[siDateInput]", inputs: ["id", "siDatepickerConfig", "disabled", "readonly", "errormessageId"], outputs: ["siDatepickerConfigChange", "siDatepickerDisabledTime", "stateChange", "dateChange"], exportAs: ["siDateInput"] }, { kind: "component", type: SiIconComponent, selector: "si-icon", inputs: ["icon"] }, { kind: "pipe", type: SiTranslatePipe, name: "translate" }, { kind: "ngmodule", type: A11yModule }] });
3975
+ ], viewQueries: [{ propertyName: "inputDirectives", predicate: SiDateInputDirective, descendants: true, isSignal: true }, { propertyName: "startInput", first: true, predicate: ["startInput"], descendants: true, isSignal: true }, { propertyName: "endInput", first: true, predicate: ["endInput"], descendants: true, isSignal: true }, { propertyName: "button", first: true, predicate: ["button"], descendants: true, isSignal: true }], usesOnChanges: true, hostDirectives: [{ directive: SiDatepickerOverlayDirective, outputs: ["siDatepickerClose", "siDatepickerClose"] }], ngImport: i0, template: "<input\n #startInput=\"ngModel\"\n type=\"text\"\n class=\"border-0 p-0 focus-none\"\n siDateInput\n [ngModel]=\"value()?.start ?? null\"\n [siDatepickerConfig]=\"siDatepickerConfig()\"\n [placeholder]=\"startDatePlaceholder() | translate\"\n [attr.aria-label]=\"startDatePlaceholder() | translate\"\n [errormessageId]=\"errormessageId()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n (ngModelChange)=\"onInputChanged({ start: $event, end: value()?.end })\"\n/>\n<span class=\"mx-3\">-</span>\n<input\n #endInput=\"ngModel\"\n type=\"text\"\n class=\"border-0 p-0 focus-none text-end\"\n siDateInput\n [ngModel]=\"value()?.end ?? null\"\n [siDatepickerConfig]=\"siDatepickerConfig()\"\n [placeholder]=\"endDatePlaceholder() | translate\"\n [attr.aria-label]=\"endDatePlaceholder() | translate\"\n [errormessageId]=\"errormessageId()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n (ngModelChange)=\"onInputChanged({ start: value()?.start, end: $event })\"\n/>\n<button\n #button\n type=\"button\"\n class=\"btn btn-circle btn-tertiary btn-xs\"\n [attr.aria-label]=\"ariaLabelCalendarButton() | translate\"\n [disabled]=\"disabled() || readonly()\"\n (click)=\"show()\"\n>\n <si-icon [icon]=\"icons.elementCalendar\" />\n</button>\n", styles: [":host{display:block;min-inline-size:237px;--si-action-icon-offset: 22px}:host(:focus-within){outline:var(--element-button-focus-width) solid var(--element-focus-default);outline-offset:var(--element-button-focus-overlay-width)}input{flex-grow:1;background-color:transparent;min-inline-size:80px}input::placeholder{opacity:1;color:var(--element-text-secondary)}input:disabled,input[readonly]{background-color:var(--element-base-1);opacity:1}input:disabled::placeholder{color:transparent}input:not([readonly]):focus::placeholder,input:focus:not([readonly]):focus::placeholder{color:transparent}.disabled,.disabled:hover,.disabled:focus{--border-color: var(--element-ui-3);color:var(--element-text-disabled)}.btn-circle{margin-inline-start:var(--si-feedback-icon-offset, 4px)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: SiDateInputDirective, selector: "input[siDateInput]", inputs: ["id", "siDatepickerConfig", "disabled", "readonly", "errormessageId"], outputs: ["siDatepickerConfigChange", "siDatepickerDisabledTime", "stateChange", "dateChange"], exportAs: ["siDateInput"] }, { kind: "component", type: SiIconComponent, selector: "si-icon", inputs: ["icon"] }, { kind: "pipe", type: SiTranslatePipe, name: "translate" }, { kind: "ngmodule", type: A11yModule }] });
3954
3976
  }
3955
3977
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: SiDateRangeComponent, decorators: [{
3956
3978
  type: Component,
@@ -4143,5 +4165,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
4143
4165
  * Generated bundle index. Do not edit.
4144
4166
  */
4145
4167
 
4146
- export { CloseCause, SiCalendarButtonComponent, SiDateInputDirective, SiDateRangeComponent, SiDatepickerComponent, SiDatepickerDirective, SiDatepickerModule, SiDatepickerOverlayComponent, SiDatepickerOverlayDirective, SiTimepickerComponent, WEEK_START_OFFSET, addDays, addDaysInRange, addMonthsInRange, addYearsInRange, changeDay, compareDate, compareMonth, compareYear, createDate, daysInMonth, getDateSameOrBetween, getDateWithoutTime, getDatepickerFormat, getDayStrings, getDaysOfWeek, getFirstDateInMonth, getFirstDateInYear, getFirstDayInMonth, getLastDateInMonth, getLocaleMonthNames, getMaxDate, getMinDate, getNamedFormat, getStringforDate, getWeekDayOffset, getWeekEndDate, getWeekOfYear, getWeekStartDate, isAfter, isAfterMonth, isAfterYear, isAnotherMonth, isAnotherMonthOrYear, isAnotherYear, isBetween, isBetweenMonth, isBetweenYears, isSameDate, isSameMonth, isSameOrBefore, isSameOrBeforeMonth, isSameOrBeforeYear, isSameOrBetween, isSameOrBetweenMonth, isSameOrBetweenYears, isSameYear, isValid, maxDate, minDate, nextMonth, parseDate, previousMonth, today };
4168
+ export { CloseCause, SiCalendarButtonComponent, SiDateInputDirective, SiDateRangeComponent, SiDatepickerComponent, SiDatepickerDirective, SiDatepickerModule, SiDatepickerOverlayComponent, SiDatepickerOverlayDirective, SiTimepickerComponent, WEEK_START_OFFSET, addDays, addDaysInRange, addMonthsInRange, addYearsInRange, changeDay, compareDate, compareMonth, compareYear, createDate, daysInMonth, getDateSameOrBetween, getDateWithoutTime, getDatepickerFormat, getDayStrings, getDaysOfWeek, getFirstDateInMonth, getFirstDateInYear, getFirstDayInMonth, getLastDateInMonth, getLocaleMonthNames, getMaxDate, getMinDate, getNamedFormat, getStringforDate, getWeekDayOffset, getWeekEndDate, getWeekOfYear, getWeekStartDate, is12HourFormat, isAfter, isAfterMonth, isAfterYear, isAnotherMonth, isAnotherMonthOrYear, isAnotherYear, isBetween, isBetweenMonth, isBetweenYears, isSameDate, isSameMonth, isSameOrBefore, isSameOrBeforeMonth, isSameOrBeforeYear, isSameOrBetween, isSameOrBetweenMonth, isSameOrBetweenYears, isSameYear, isValid, maxDate, minDate, nextMonth, parseDate, previousMonth, today };
4147
4169
  //# sourceMappingURL=siemens-element-ng-datepicker.mjs.map