@koobiq/components 20.2.0 → 20.3.1

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 (213) hide show
  1. package/accordion/_accordion-theme.scss +5 -1
  2. package/accordion/accordion-tokens.scss +2 -0
  3. package/accordion/accordion-trigger.scss +6 -0
  4. package/accordion/accordion.scss +21 -0
  5. package/accordion/index.d.ts +55 -8
  6. package/actions-panel/index.d.ts +25 -13
  7. package/app-switcher/app-switcher-dropdown-app.scss +7 -5
  8. package/app-switcher/app-switcher-dropdown-site.scss +6 -4
  9. package/app-switcher/index.d.ts +41 -4
  10. package/app-switcher/kbq-app-switcher-list-item.scss +6 -8
  11. package/autocomplete/index.d.ts +24 -9
  12. package/breadcrumbs/index.d.ts +1 -1
  13. package/button/index.d.ts +2 -2
  14. package/button-toggle/button-toggle-tokens.scss +2 -0
  15. package/button-toggle/button-toggle.scss +9 -0
  16. package/button-toggle/index.d.ts +5 -0
  17. package/checkbox/index.d.ts +33 -29
  18. package/clamped-text/index.d.ts +1 -1
  19. package/code-block/index.d.ts +24 -19
  20. package/content-panel/index.d.ts +1 -1
  21. package/core/index.d.ts +1125 -199
  22. package/core/option/_action-container-mixins.scss +28 -0
  23. package/core/option/_option-theme.scss +24 -0
  24. package/core/option/action.scss +7 -0
  25. package/core/styles/_koobiq-theme.scss +2 -0
  26. package/core/styles/_tokens.scss +1 -0
  27. package/core/styles/common/_connected-overlay.scss +6 -3
  28. package/core/styles/common/_select.scss +12 -0
  29. package/core/styles/common/_tokens.scss +0 -9
  30. package/core/styles/theming/_index.scss +0 -1
  31. package/core/styles/theming/_theming.scss +34 -5
  32. package/datepicker/index.d.ts +46 -15
  33. package/dl/dl.scss +26 -0
  34. package/dl/index.d.ts +8 -1
  35. package/dropdown/_dropdown-theme.scss +28 -2
  36. package/dropdown/dropdown-item.scss +13 -0
  37. package/dropdown/dropdown.scss +7 -1
  38. package/dropdown/index.d.ts +264 -17
  39. package/dynamic-translation/index.d.ts +1 -1
  40. package/fesm2022/koobiq-components-accordion.mjs +106 -46
  41. package/fesm2022/koobiq-components-accordion.mjs.map +1 -1
  42. package/fesm2022/koobiq-components-actions-panel.mjs +57 -46
  43. package/fesm2022/koobiq-components-actions-panel.mjs.map +1 -1
  44. package/fesm2022/koobiq-components-alert.mjs +16 -16
  45. package/fesm2022/koobiq-components-app-switcher.mjs +233 -38
  46. package/fesm2022/koobiq-components-app-switcher.mjs.map +1 -1
  47. package/fesm2022/koobiq-components-autocomplete.mjs +54 -31
  48. package/fesm2022/koobiq-components-autocomplete.mjs.map +1 -1
  49. package/fesm2022/koobiq-components-badge.mjs +13 -13
  50. package/fesm2022/koobiq-components-breadcrumbs.mjs +25 -25
  51. package/fesm2022/koobiq-components-breadcrumbs.mjs.map +1 -1
  52. package/fesm2022/koobiq-components-button-toggle.mjs +17 -12
  53. package/fesm2022/koobiq-components-button-toggle.mjs.map +1 -1
  54. package/fesm2022/koobiq-components-button.mjs +25 -25
  55. package/fesm2022/koobiq-components-checkbox.mjs +69 -92
  56. package/fesm2022/koobiq-components-checkbox.mjs.map +1 -1
  57. package/fesm2022/koobiq-components-clamped-text.mjs +13 -13
  58. package/fesm2022/koobiq-components-code-block.mjs +56 -69
  59. package/fesm2022/koobiq-components-code-block.mjs.map +1 -1
  60. package/fesm2022/koobiq-components-content-panel.mjs +29 -29
  61. package/fesm2022/koobiq-components-core.mjs +2454 -795
  62. package/fesm2022/koobiq-components-core.mjs.map +1 -1
  63. package/fesm2022/koobiq-components-datepicker.mjs +160 -121
  64. package/fesm2022/koobiq-components-datepicker.mjs.map +1 -1
  65. package/fesm2022/koobiq-components-divider.mjs +7 -7
  66. package/fesm2022/koobiq-components-dl.mjs +23 -15
  67. package/fesm2022/koobiq-components-dl.mjs.map +1 -1
  68. package/fesm2022/koobiq-components-dropdown.mjs +754 -155
  69. package/fesm2022/koobiq-components-dropdown.mjs.map +1 -1
  70. package/fesm2022/koobiq-components-dynamic-translation.mjs +13 -13
  71. package/fesm2022/koobiq-components-ellipsis-center.mjs +7 -7
  72. package/fesm2022/koobiq-components-empty-state.mjs +19 -19
  73. package/fesm2022/koobiq-components-file-upload.mjs +74 -42
  74. package/fesm2022/koobiq-components-file-upload.mjs.map +1 -1
  75. package/fesm2022/koobiq-components-filter-bar.mjs +605 -192
  76. package/fesm2022/koobiq-components-filter-bar.mjs.map +1 -1
  77. package/fesm2022/koobiq-components-flag.mjs +7 -7
  78. package/fesm2022/koobiq-components-form-field.mjs +359 -165
  79. package/fesm2022/koobiq-components-form-field.mjs.map +1 -1
  80. package/fesm2022/koobiq-components-icon.mjs +39 -21
  81. package/fesm2022/koobiq-components-icon.mjs.map +1 -1
  82. package/fesm2022/koobiq-components-inline-edit.mjs +172 -27
  83. package/fesm2022/koobiq-components-inline-edit.mjs.map +1 -1
  84. package/fesm2022/koobiq-components-input.mjs +41 -24
  85. package/fesm2022/koobiq-components-input.mjs.map +1 -1
  86. package/fesm2022/koobiq-components-link.mjs +8 -8
  87. package/fesm2022/koobiq-components-list.mjs +657 -143
  88. package/fesm2022/koobiq-components-list.mjs.map +1 -1
  89. package/fesm2022/koobiq-components-loader-overlay.mjs +16 -16
  90. package/fesm2022/koobiq-components-markdown.mjs +14 -11
  91. package/fesm2022/koobiq-components-markdown.mjs.map +1 -1
  92. package/fesm2022/koobiq-components-modal.mjs +70 -38
  93. package/fesm2022/koobiq-components-modal.mjs.map +1 -1
  94. package/fesm2022/koobiq-components-navbar.mjs +69 -54
  95. package/fesm2022/koobiq-components-navbar.mjs.map +1 -1
  96. package/fesm2022/koobiq-components-notification-center.mjs +23 -22
  97. package/fesm2022/koobiq-components-notification-center.mjs.map +1 -1
  98. package/fesm2022/koobiq-components-overflow-items.mjs +16 -17
  99. package/fesm2022/koobiq-components-overflow-items.mjs.map +1 -1
  100. package/fesm2022/koobiq-components-popover.mjs +26 -21
  101. package/fesm2022/koobiq-components-popover.mjs.map +1 -1
  102. package/fesm2022/koobiq-components-progress-bar.mjs +13 -13
  103. package/fesm2022/koobiq-components-progress-spinner.mjs +13 -13
  104. package/fesm2022/koobiq-components-radio.mjs +10 -10
  105. package/fesm2022/koobiq-components-resizer.mjs +33 -14
  106. package/fesm2022/koobiq-components-resizer.mjs.map +1 -1
  107. package/fesm2022/koobiq-components-scrollbar.mjs +10 -10
  108. package/fesm2022/koobiq-components-search-expandable.mjs +7 -7
  109. package/fesm2022/koobiq-components-search-expandable.mjs.map +1 -1
  110. package/fesm2022/koobiq-components-select.mjs +420 -107
  111. package/fesm2022/koobiq-components-select.mjs.map +1 -1
  112. package/fesm2022/koobiq-components-sidebar.mjs +14 -14
  113. package/fesm2022/koobiq-components-sidepanel.mjs +26 -26
  114. package/fesm2022/koobiq-components-skeleton.mjs +10 -10
  115. package/fesm2022/koobiq-components-split-button.mjs +7 -7
  116. package/fesm2022/koobiq-components-splitter.mjs +17 -17
  117. package/fesm2022/koobiq-components-table.mjs +15 -13
  118. package/fesm2022/koobiq-components-table.mjs.map +1 -1
  119. package/fesm2022/koobiq-components-tabs.mjs +56 -58
  120. package/fesm2022/koobiq-components-tabs.mjs.map +1 -1
  121. package/fesm2022/koobiq-components-tags.mjs +283 -122
  122. package/fesm2022/koobiq-components-tags.mjs.map +1 -1
  123. package/fesm2022/koobiq-components-textarea.mjs +13 -8
  124. package/fesm2022/koobiq-components-textarea.mjs.map +1 -1
  125. package/fesm2022/koobiq-components-time-range.mjs +29 -24
  126. package/fesm2022/koobiq-components-time-range.mjs.map +1 -1
  127. package/fesm2022/koobiq-components-timepicker.mjs +58 -26
  128. package/fesm2022/koobiq-components-timepicker.mjs.map +1 -1
  129. package/fesm2022/koobiq-components-timezone.mjs +76 -39
  130. package/fesm2022/koobiq-components-timezone.mjs.map +1 -1
  131. package/fesm2022/koobiq-components-title.mjs +7 -7
  132. package/fesm2022/koobiq-components-toast.mjs +51 -26
  133. package/fesm2022/koobiq-components-toast.mjs.map +1 -1
  134. package/fesm2022/koobiq-components-toggle.mjs +72 -64
  135. package/fesm2022/koobiq-components-toggle.mjs.map +1 -1
  136. package/fesm2022/koobiq-components-tooltip.mjs +115 -36
  137. package/fesm2022/koobiq-components-tooltip.mjs.map +1 -1
  138. package/fesm2022/koobiq-components-top-bar.mjs +13 -13
  139. package/fesm2022/koobiq-components-tree-select.mjs +190 -56
  140. package/fesm2022/koobiq-components-tree-select.mjs.map +1 -1
  141. package/fesm2022/koobiq-components-tree.mjs +302 -81
  142. package/fesm2022/koobiq-components-tree.mjs.map +1 -1
  143. package/fesm2022/koobiq-components-username.mjs +27 -27
  144. package/file-upload/index.d.ts +25 -6
  145. package/file-upload/multiple-file-upload.component.scss +14 -0
  146. package/filter-bar/_filter-bar-theme.scss +0 -6
  147. package/filter-bar/index.d.ts +222 -9
  148. package/filter-bar/pipes/pipe-multi-tree-select.scss +0 -6
  149. package/filter-bar/pipes/pipe-multiselect.scss +0 -6
  150. package/filter-bar/pipes/pipe-tree-select.scss +0 -6
  151. package/form-field/_form-field-theme.scss +76 -20
  152. package/form-field/fieldset.scss +10 -0
  153. package/form-field/form-field-tokens.scss +15 -1
  154. package/form-field/form-field.scss +15 -19
  155. package/form-field/index.d.ts +148 -68
  156. package/icon/index.d.ts +31 -6
  157. package/inline-edit/index.d.ts +57 -4
  158. package/inline-edit/inline-edit.scss +10 -0
  159. package/input/index.d.ts +17 -2
  160. package/list/_list-theme.scss +42 -10
  161. package/list/index.d.ts +326 -79
  162. package/list/list-tokens.scss +43 -8
  163. package/list/list.scss +186 -12
  164. package/markdown/index.d.ts +1 -1
  165. package/modal/index.d.ts +22 -5
  166. package/modal/modal-tokens.scss +1 -1
  167. package/navbar/index.d.ts +16 -1
  168. package/navbar/navbar-brand.scss +6 -0
  169. package/navbar/vertical-navbar.scss +6 -0
  170. package/notification-center/notification-item.scss +6 -0
  171. package/package.json +3 -6
  172. package/popover/index.d.ts +2 -2
  173. package/prebuilt-themes/dark-theme.css +1 -1
  174. package/prebuilt-themes/light-theme.css +1 -1
  175. package/prebuilt-themes/theme.css +1 -1
  176. package/resizer/index.d.ts +12 -0
  177. package/schematics/migrations/deprecated-icons/README.md +29 -4
  178. package/schematics/migrations/deprecated-icons/data.js +7 -0
  179. package/schematics/migrations/deprecated-icons/index.js +62 -35
  180. package/schematics/migrations/new-icons-pack/README.md +37 -2
  181. package/schematics/migrations/new-icons-pack/data.js +8 -0
  182. package/schematics/migrations/new-icons-pack/index.js +144 -53
  183. package/schematics/ng-add/index.js +3 -3
  184. package/schematics/utils/angular-parsing.js +30 -12
  185. package/schematics/utils/ast.js +31 -0
  186. package/schematics/utils/icon-migration.js +530 -0
  187. package/schematics/utils/typescript.js +44 -0
  188. package/scrollbar/index.d.ts +1 -1
  189. package/select/index.d.ts +163 -18
  190. package/select/select-tokens.scss +0 -1
  191. package/select/select.scss +0 -2
  192. package/splitter/index.d.ts +1 -1
  193. package/table/_table-theme.scss +4 -0
  194. package/table/index.d.ts +2 -1
  195. package/table/table.scss +8 -0
  196. package/tabs/index.d.ts +0 -1
  197. package/tags/index.d.ts +128 -29
  198. package/textarea/index.d.ts +5 -0
  199. package/time-range/index.d.ts +1 -1
  200. package/timepicker/index.d.ts +4 -0
  201. package/timezone/index.d.ts +9 -5
  202. package/toast/index.d.ts +26 -3
  203. package/toggle/index.d.ts +34 -14
  204. package/tooltip/index.d.ts +54 -11
  205. package/tree/_tree-theme.scss +25 -5
  206. package/tree/index.d.ts +71 -3
  207. package/tree/tree-option.scss +2 -8
  208. package/tree-select/_tree-select-theme.scss +22 -0
  209. package/tree-select/index.d.ts +83 -16
  210. package/core/styles/_tokens.kbq.import.scss +0 -4
  211. package/core/styles/theming/_components-theming.scss +0 -1927
  212. package/filter-bar/pipes/pipe-select.scss +0 -5
  213. package/overflow-items/overflow-items.scss +0 -20
@@ -4,22 +4,22 @@ import { TitleCasePipe, DOCUMENT } from '@angular/common';
4
4
  import * as i1 from '@koobiq/components/button';
5
5
  import { KbqButtonModule } from '@koobiq/components/button';
6
6
  import * as i4 from '@koobiq/components/core';
7
- import { DateAdapter, KbqOptionModule, KBQ_CONNECTED_OVERLAY_BELOW_CLASS, KBQ_CONNECTED_OVERLAY_ABOVE_CLASS, ruRULocaleData, validationTooltipShowDelay, validationTooltipHideDelay, KBQ_DATE_FORMATS, KBQ_LOCALE_SERVICE, KbqErrorStateTracker, ErrorStateMatcher, TAB, SPACE, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW, HOME, PAGE_UP, END, PAGE_DOWN, ESCAPE, isLetterKey, hasModifierKey, isVerticalMovement, isHorizontalMovement, DELETE, BACKSPACE } from '@koobiq/components/core';
7
+ import { DateAdapter, KbqOptionModule, KbqDateTimezoneService, KBQ_CONNECTED_OVERLAY_BELOW_CLASS, KBQ_CONNECTED_OVERLAY_ABOVE_CLASS, ruRULocaleData, validationTooltipShowDelay, validationTooltipHideDelay, KBQ_DATE_FORMATS, KBQ_LOCALE_SERVICE, KbqErrorStateTracker, ErrorStateMatcher, TAB, SPACE, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW, HOME, PAGE_UP, END, PAGE_DOWN, ESCAPE, isLetterKey, hasModifierKey, isVerticalMovement, isHorizontalMovement, DELETE, BACKSPACE, kbqRevealSelection, kbqSetSelectionRange, kbqSiblingPopupProvider } from '@koobiq/components/core';
8
8
  import * as i2 from '@koobiq/components/icon';
9
9
  import { KbqIconModule } from '@koobiq/components/icon';
10
10
  import * as i3 from '@koobiq/components/select';
11
11
  import { KbqSelectModule } from '@koobiq/components/select';
12
12
  import { Subject, Subscription, merge } from 'rxjs';
13
- import { trigger, state, transition, style, animate } from '@angular/animations';
13
+ import { takeUntilDestroyed, toObservable, outputToObservable } from '@angular/core/rxjs-interop';
14
+ import { trigger, state, style, transition, animate } from '@angular/animations';
14
15
  import { coerceBooleanProperty } from '@angular/cdk/coercion';
15
- import { takeUntilDestroyed, outputToObservable } from '@angular/core/rxjs-interop';
16
16
  import { NG_VALUE_ACCESSOR, NG_VALIDATORS, Validators, FormGroupDirective, NgForm } from '@angular/forms';
17
- import { KbqFormFieldControl, KbqFormField, KbqFormFieldModule } from '@koobiq/components/form-field';
17
+ import { KbqFormFieldControl, KBQ_FORM_FIELD, KbqFormFieldModule } from '@koobiq/components/form-field';
18
18
  import { Directionality } from '@angular/cdk/bidi';
19
19
  import { Overlay, OverlayConfig, OverlayModule } from '@angular/cdk/overlay';
20
20
  import { _getFocusedElementPierceShadowDom } from '@angular/cdk/platform';
21
21
  import { ComponentPortal, PortalModule } from '@angular/cdk/portal';
22
- import { take } from 'rxjs/operators';
22
+ import { take, filter, switchMap, map } from 'rxjs/operators';
23
23
  import { A11yModule } from '@angular/cdk/a11y';
24
24
 
25
25
  /**
@@ -90,16 +90,30 @@ class KbqCalendarBody {
90
90
  }
91
91
  return cellNumber === this.activeCell();
92
92
  }
93
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqCalendarBody, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
94
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: KbqCalendarBody, isStandalone: true, selector: "[kbq-calendar-body]", inputs: { rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, todayValue: { classPropertyName: "todayValue", publicName: "todayValue", isSignal: true, isRequired: false, transformFunction: null }, selectedValue: { classPropertyName: "selectedValue", publicName: "selectedValue", isSignal: true, isRequired: false, transformFunction: null }, labelMinRequiredCells: { classPropertyName: "labelMinRequiredCells", publicName: "labelMinRequiredCells", isSignal: true, isRequired: false, transformFunction: null }, numCols: { classPropertyName: "numCols", publicName: "numCols", isSignal: true, isRequired: false, transformFunction: null }, activeCell: { classPropertyName: "activeCell", publicName: "activeCell", isSignal: true, isRequired: false, transformFunction: null }, cellAspectRatio: { classPropertyName: "cellAspectRatio", publicName: "cellAspectRatio", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedValueChange: "selectedValueChange" }, host: { classAttribute: "kbq-calendar__body" }, exportAs: ["kbqCalendarBody"], usesOnChanges: true, ngImport: i0, template: "<!-- Create the first row separately so we can include a special spacer cell. -->\n@for (row of rows(); track $index; let rowIndex = $index) {\n <tr>\n <!-- We mark this cell as aria-hidden so it doesn't get read out as one of the days in the week.\n The aspect ratio of the table cells is maintained by setting the top and bottom padding as a\n percentage of the width (a variant of the trick described here:\n https://www.w3schools.com/howto/howto_css_aspect_ratio.asp). -->\n @if (rowIndex === 0 && firstRowOffset) {\n <td class=\"kbq-calendar__body-label\" [attr.colspan]=\"firstRowOffset\"></td>\n }\n @for (item of row; track item.displayValue; let colIndex = $index) {\n <td\n class=\"kbq-calendar__body-cell\"\n [class.kbq-calendar__body_active]=\"isActiveCell(rowIndex, colIndex)\"\n [class]=\"item.cssClasses!\"\n [style.paddingBottom]=\"cellPadding\"\n [style.paddingTop]=\"cellPadding\"\n [style.width]=\"cellWidth\"\n [tabindex]=\"-1\"\n (click)=\"cellClicked(item)\"\n >\n <div\n class=\"kbq-calendar__body-cell-content\"\n [class.kbq-calendar__body-today]=\"todayValue() === item.value\"\n [class.kbq-disabled]=\"!item.enabled\"\n [class.kbq-selected]=\"selectedValue() === item.value\"\n >\n {{ item.displayValue }}\n </div>\n </td>\n }\n </tr>\n}\n", styles: [".kbq-calendar__body-cell{position:relative;height:0;line-height:0;text-align:center;outline:none;cursor:pointer;padding:0}.kbq-disabled{cursor:default}.kbq-calendar__body-cell-content{display:flex;align-items:center;justify-content:center;box-sizing:border-box;height:32px;line-height:1;border-radius:var(--kbq-datepicker-size-grid-cell-border-radius);margin-bottom:var(--kbq-datepicker-size-grid-content-gap-vertical)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
93
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqCalendarBody, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
94
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: KbqCalendarBody, isStandalone: true, selector: "[kbq-calendar-body]", inputs: { rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, todayValue: { classPropertyName: "todayValue", publicName: "todayValue", isSignal: true, isRequired: false, transformFunction: null }, selectedValue: { classPropertyName: "selectedValue", publicName: "selectedValue", isSignal: true, isRequired: false, transformFunction: null }, labelMinRequiredCells: { classPropertyName: "labelMinRequiredCells", publicName: "labelMinRequiredCells", isSignal: true, isRequired: false, transformFunction: null }, numCols: { classPropertyName: "numCols", publicName: "numCols", isSignal: true, isRequired: false, transformFunction: null }, activeCell: { classPropertyName: "activeCell", publicName: "activeCell", isSignal: true, isRequired: false, transformFunction: null }, cellAspectRatio: { classPropertyName: "cellAspectRatio", publicName: "cellAspectRatio", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedValueChange: "selectedValueChange" }, host: { classAttribute: "kbq-calendar__body" }, exportAs: ["kbqCalendarBody"], usesOnChanges: true, ngImport: i0, template: "<!-- Create the first row separately so we can include a special spacer cell. -->\n@for (row of rows(); track $index; let rowIndex = $index) {\n <tr>\n <!-- We mark this cell as aria-hidden so it doesn't get read out as one of the days in the week.\n The aspect ratio of the table cells is maintained by setting the top and bottom padding as a\n percentage of the width (a variant of the trick described here:\n https://www.w3schools.com/howto/howto_css_aspect_ratio.asp). -->\n @if (rowIndex === 0 && firstRowOffset) {\n <td class=\"kbq-calendar__body-label\" [attr.colspan]=\"firstRowOffset\"></td>\n }\n @for (item of row; track item.displayValue; let colIndex = $index) {\n <td\n class=\"kbq-calendar__body-cell\"\n [class.kbq-calendar__body_active]=\"isActiveCell(rowIndex, colIndex)\"\n [class]=\"item.cssClasses!\"\n [style.paddingBottom]=\"cellPadding\"\n [style.paddingTop]=\"cellPadding\"\n [style.width]=\"cellWidth\"\n [tabindex]=\"-1\"\n (click)=\"cellClicked(item)\"\n >\n <div\n class=\"kbq-calendar__body-cell-content\"\n [class.kbq-calendar__body-today]=\"todayValue() === item.value\"\n [class.kbq-disabled]=\"!item.enabled\"\n [class.kbq-selected]=\"selectedValue() === item.value\"\n >\n {{ item.displayValue }}\n </div>\n </td>\n }\n </tr>\n}\n", styles: [".kbq-calendar__body-cell{position:relative;height:0;line-height:0;text-align:center;outline:none;cursor:pointer;padding:0}.kbq-disabled{cursor:default}.kbq-calendar__body-cell-content{display:flex;align-items:center;justify-content:center;box-sizing:border-box;height:32px;line-height:1;border-radius:var(--kbq-datepicker-size-grid-cell-border-radius);margin-bottom:var(--kbq-datepicker-size-grid-content-gap-vertical)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
95
95
  }
96
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqCalendarBody, decorators: [{
96
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqCalendarBody, decorators: [{
97
97
  type: Component,
98
98
  args: [{ selector: '[kbq-calendar-body]', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
99
99
  class: 'kbq-calendar__body'
100
100
  }, exportAs: 'kbqCalendarBody', template: "<!-- Create the first row separately so we can include a special spacer cell. -->\n@for (row of rows(); track $index; let rowIndex = $index) {\n <tr>\n <!-- We mark this cell as aria-hidden so it doesn't get read out as one of the days in the week.\n The aspect ratio of the table cells is maintained by setting the top and bottom padding as a\n percentage of the width (a variant of the trick described here:\n https://www.w3schools.com/howto/howto_css_aspect_ratio.asp). -->\n @if (rowIndex === 0 && firstRowOffset) {\n <td class=\"kbq-calendar__body-label\" [attr.colspan]=\"firstRowOffset\"></td>\n }\n @for (item of row; track item.displayValue; let colIndex = $index) {\n <td\n class=\"kbq-calendar__body-cell\"\n [class.kbq-calendar__body_active]=\"isActiveCell(rowIndex, colIndex)\"\n [class]=\"item.cssClasses!\"\n [style.paddingBottom]=\"cellPadding\"\n [style.paddingTop]=\"cellPadding\"\n [style.width]=\"cellWidth\"\n [tabindex]=\"-1\"\n (click)=\"cellClicked(item)\"\n >\n <div\n class=\"kbq-calendar__body-cell-content\"\n [class.kbq-calendar__body-today]=\"todayValue() === item.value\"\n [class.kbq-disabled]=\"!item.enabled\"\n [class.kbq-selected]=\"selectedValue() === item.value\"\n >\n {{ item.displayValue }}\n </div>\n </td>\n }\n </tr>\n}\n", styles: [".kbq-calendar__body-cell{position:relative;height:0;line-height:0;text-align:center;outline:none;cursor:pointer;padding:0}.kbq-disabled{cursor:default}.kbq-calendar__body-cell-content{display:flex;align-items:center;justify-content:center;box-sizing:border-box;height:32px;line-height:1;border-radius:var(--kbq-datepicker-size-grid-cell-border-radius);margin-bottom:var(--kbq-datepicker-size-grid-content-gap-vertical)}\n"] }]
101
101
  }], propDecorators: { rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], todayValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "todayValue", required: false }] }], selectedValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedValue", required: false }] }], labelMinRequiredCells: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelMinRequiredCells", required: false }] }], numCols: [{ type: i0.Input, args: [{ isSignal: true, alias: "numCols", required: false }] }], activeCell: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeCell", required: false }] }], cellAspectRatio: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellAspectRatio", required: false }] }], selectedValueChange: [{ type: i0.Output, args: ["selectedValueChange"] }] } });
102
102
 
103
+ /** @docs-private */
104
+ function createMissingDateImplError(provider) {
105
+ return Error(`KbqDatepicker: No provider found for ${provider}. You must import one of the existing ` +
106
+ `modules at your application root or provide a custom implementation or use exists ones.`);
107
+ }
108
+ /** Injects `DateAdapter`, naming the missing provider instead of letting DI throw a bare `NullInjectorError`. */
109
+ function injectRequiredDateAdapter() {
110
+ const adapter = inject(DateAdapter, { optional: true });
111
+ if (!adapter) {
112
+ throw createMissingDateImplError('DateAdapter');
113
+ }
114
+ return adapter;
115
+ }
116
+
103
117
  const defaultMinYear = 1900;
104
118
  const defaultMaxYear = 2099;
105
119
  /** Default header for KbqCalendar */
@@ -149,7 +163,7 @@ class KbqCalendarHeader {
149
163
  return this.compareDate(this.activeDate, this.maxDate) >= 0;
150
164
  }
151
165
  constructor() {
152
- this.adapter = inject(DateAdapter);
166
+ this.adapter = injectRequiredDateAdapter();
153
167
  this.years = [];
154
168
  this._maxDate = this.adapter.createDate(defaultMaxYear, 11);
155
169
  this._minDate = this.adapter.createDate(defaultMinYear, 1);
@@ -239,10 +253,10 @@ class KbqCalendarHeader {
239
253
  this.monthNames.forEach((month) => (month.disabled = false));
240
254
  }
241
255
  }
242
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqCalendarHeader, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
243
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: KbqCalendarHeader, isStandalone: true, selector: "kbq-calendar-header", inputs: { activeDate: "activeDate", maxDate: "maxDate", minDate: "minDate" }, outputs: { activeDateChange: "activeDateChange", monthSelected: "monthSelected", yearSelected: "yearSelected" }, host: { classAttribute: "kbq-calendar-header" }, exportAs: ["kbqCalendarHeader"], ngImport: i0, template: "<div class=\"kbq-calendar-header__select-group\">\n <kbq-select\n #monthSelect=\"kbqSelect\"\n class=\"kbq-calendar-header__select\"\n [panelClass]=\"'kbq-calendar-select-panel'\"\n [tabIndex]=\"-1\"\n [value]=\"selectedMonth\"\n (selectionChange)=\"onMonthSelected($event.value)\"\n >\n <button\n kbq-button\n kbq-select-matcher\n class=\"layout-padding-right-xs\"\n [class.kbq-active]=\"monthSelect.panelOpen\"\n [color]=\"'contrast'\"\n [kbqStyle]=\"'transparent'\"\n >\n {{ monthNames[selectedMonth].nameShort | titlecase }}\n\n <i kbq-icon=\"kbq-chevron-down-s_16\" class=\"layout-padding-left-3xs\" [color]=\"'contrast'\"></i>\n </button>\n\n @for (month of monthNames; track month.nameShort) {\n <kbq-option [disabled]=\"month.disabled\" [kbqTooltipDisabled]=\"true\" [value]=\"month.value\">\n {{ month.name }}\n </kbq-option>\n }\n </kbq-select>\n\n <kbq-select\n #yearSelect=\"kbqSelect\"\n [panelClass]=\"'kbq-calendar-select-panel'\"\n [tabIndex]=\"-1\"\n [value]=\"selectedYear\"\n (selectionChange)=\"onYearSelected($event.value)\"\n >\n <button\n kbq-button\n kbq-select-matcher\n class=\"layout-padding-right-xs\"\n [class.kbq-active]=\"yearSelect.panelOpen\"\n [color]=\"'contrast'\"\n [kbqStyle]=\"'transparent'\"\n >\n {{ selectedYear }}\n\n <i kbq-icon=\"kbq-chevron-down-s_16\" class=\"layout-padding-left-3xs\"></i>\n </button>\n\n @for (year of years; track year) {\n <kbq-option [kbqTooltipDisabled]=\"true\" [value]=\"year\">\n {{ year }}\n </kbq-option>\n }\n </kbq-select>\n</div>\n\n<div class=\"kbq-calendar-header__button-group\">\n <button\n kbq-button\n class=\"kbq-calendar-header__previous-button\"\n [color]=\"'contrast'\"\n [disabled]=\"previousDisabled\"\n [kbqStyle]=\"'transparent'\"\n [tabindex]=\"-1\"\n (click)=\"selectPreviousMonth()\"\n >\n <i kbq-icon=\"kbq-chevron-left_16\"></i>\n </button>\n\n <button\n kbq-button\n [color]=\"'contrast'\"\n [disabled]=\"currentDisabled\"\n [kbqStyle]=\"'transparent'\"\n [tabindex]=\"-1\"\n (click)=\"selectCurrentDate()\"\n >\n <i kbq-icon=\"kbq-circle-xs_16\"></i>\n </button>\n\n <button\n kbq-button\n class=\"kbq-calendar-header__next-button\"\n [color]=\"'contrast'\"\n [disabled]=\"nextDisabled\"\n [kbqStyle]=\"'transparent'\"\n [tabindex]=\"-1\"\n (click)=\"selectNextMonth()\"\n >\n <i kbq-icon=\"kbq-chevron-right_16\"></i>\n </button>\n</div>\n", styles: [".kbq-calendar-header{display:flex;flex-direction:row;justify-content:space-between;padding-right:var(--kbq-datepicker-size-header-padding-horizontal);padding-left:var(--kbq-datepicker-size-header-padding-horizontal);margin-bottom:var(--kbq-datepicker-size-header-margin-bottom)}.kbq-calendar-header__select{width:auto!important}.kbq-calendar-header__button-group,.kbq-calendar-header__select-group{display:flex;flex-direction:row}.kbq-calendar-select-panel{margin-top:2px;min-width:98%!important}.kbq-calendar-select-panel .kbq-select__content{max-height:384px;overflow-x:hidden;scrollbar-gutter:auto}.kbq-calendar-select-panel .kbq-select__content .kbq-option{min-width:65px}\n"], dependencies: [{ kind: "ngmodule", type: KbqButtonModule }, { kind: "component", type: i1.KbqButton, selector: "[kbq-button]", inputs: ["kbqStyle", "disabled", "tabIndex"] }, { kind: "directive", type: i1.KbqButtonCssStyler, selector: "[kbq-button]" }, { kind: "ngmodule", type: KbqIconModule }, { kind: "component", type: i2.KbqIcon, selector: "[kbq-icon]", inputs: ["small", "autoColor", "kbq-icon"] }, { kind: "ngmodule", type: KbqSelectModule }, { kind: "component", type: i3.KbqSelect, selector: "kbq-select", inputs: ["hiddenItemsText", "showPreselectedValues", "triggerValuesLimit", "panelClass", "backdropClass", "errorStateMatcher", "sortComparator", "multiline", "searchMinOptionsThreshold", "scrolledToBottomOffset", "hasBackdrop", "placeholder", "required", "multiple", "compareWith", "virtualOptionFactory", "selectAllToggle", "selectAllHandler", "panelWidth", "panelMinWidth", "panelMaxWidth", "value", "id", "tabIndex", "disabled", "hiddenItemsTextFormatter"], outputs: ["openedChange", "beforeOpened", "opened", "closed", "selectionChange", "onSelectAll", "valueChange", "scrolledToBottom"], exportAs: ["kbqSelect"] }, { kind: "directive", type: i3.KbqOptionTooltip, selector: "kbq-option" }, { kind: "component", type: i4.KbqOption, selector: "kbq-option", inputs: ["value", "selectable", "userSelect", "showCheckbox", "viewValue", "disabled"], outputs: ["onSelectionChange"], exportAs: ["kbqOption"] }, { kind: "directive", type: i4.KbqSelectMatcher, selector: "kbq-select-matcher, [kbq-select-matcher]", inputs: ["useDefaultHandlers"] }, { kind: "ngmodule", type: KbqOptionModule }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
256
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqCalendarHeader, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
257
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: KbqCalendarHeader, isStandalone: true, selector: "kbq-calendar-header", inputs: { activeDate: "activeDate", maxDate: "maxDate", minDate: "minDate" }, outputs: { activeDateChange: "activeDateChange", monthSelected: "monthSelected", yearSelected: "yearSelected" }, host: { classAttribute: "kbq-calendar-header" }, exportAs: ["kbqCalendarHeader"], ngImport: i0, template: "<div class=\"kbq-calendar-header__select-group\">\n <kbq-select\n #monthSelect=\"kbqSelect\"\n class=\"kbq-calendar-header__select\"\n [panelClass]=\"'kbq-calendar-select-panel'\"\n [tabIndex]=\"-1\"\n [value]=\"selectedMonth\"\n (selectionChange)=\"onMonthSelected($event.value)\"\n >\n <button\n kbq-button\n kbq-select-matcher\n class=\"layout-padding-right-xs\"\n [class.kbq-active]=\"monthSelect.panelOpen\"\n [color]=\"'contrast'\"\n [kbqStyle]=\"'transparent'\"\n >\n {{ monthNames[selectedMonth].nameShort | titlecase }}\n\n <i kbq-icon=\"kbq-chevron-down-s_16\" class=\"layout-padding-left-3xs\" [color]=\"'contrast'\"></i>\n </button>\n\n @for (month of monthNames; track month.nameShort) {\n <kbq-option [disabled]=\"month.disabled\" [kbqTooltipDisabled]=\"true\" [value]=\"month.value\">\n {{ month.name }}\n </kbq-option>\n }\n </kbq-select>\n\n <kbq-select\n #yearSelect=\"kbqSelect\"\n [panelClass]=\"'kbq-calendar-select-panel'\"\n [tabIndex]=\"-1\"\n [value]=\"selectedYear\"\n (selectionChange)=\"onYearSelected($event.value)\"\n >\n <button\n kbq-button\n kbq-select-matcher\n class=\"layout-padding-right-xs\"\n [class.kbq-active]=\"yearSelect.panelOpen\"\n [color]=\"'contrast'\"\n [kbqStyle]=\"'transparent'\"\n >\n {{ selectedYear }}\n\n <i kbq-icon=\"kbq-chevron-down-s_16\" class=\"layout-padding-left-3xs\"></i>\n </button>\n\n @for (year of years; track year) {\n <kbq-option [kbqTooltipDisabled]=\"true\" [value]=\"year\">\n {{ year }}\n </kbq-option>\n }\n </kbq-select>\n</div>\n\n<div class=\"kbq-calendar-header__button-group\">\n <button\n kbq-button\n class=\"kbq-calendar-header__previous-button\"\n [color]=\"'contrast'\"\n [disabled]=\"previousDisabled\"\n [kbqStyle]=\"'transparent'\"\n [tabindex]=\"-1\"\n (click)=\"selectPreviousMonth()\"\n >\n <i kbq-icon=\"kbq-chevron-left_16\"></i>\n </button>\n\n <button\n kbq-button\n [color]=\"'contrast'\"\n [disabled]=\"currentDisabled\"\n [kbqStyle]=\"'transparent'\"\n [tabindex]=\"-1\"\n (click)=\"selectCurrentDate()\"\n >\n <i kbq-icon=\"kbq-circle-xs_16\"></i>\n </button>\n\n <button\n kbq-button\n class=\"kbq-calendar-header__next-button\"\n [color]=\"'contrast'\"\n [disabled]=\"nextDisabled\"\n [kbqStyle]=\"'transparent'\"\n [tabindex]=\"-1\"\n (click)=\"selectNextMonth()\"\n >\n <i kbq-icon=\"kbq-chevron-right_16\"></i>\n </button>\n</div>\n", styles: [".kbq-calendar-header{display:flex;flex-direction:row;justify-content:space-between;padding-right:var(--kbq-datepicker-size-header-padding-horizontal);padding-left:var(--kbq-datepicker-size-header-padding-horizontal);margin-bottom:var(--kbq-datepicker-size-header-margin-bottom)}.kbq-calendar-header__select{width:auto!important}.kbq-calendar-header__button-group,.kbq-calendar-header__select-group{display:flex;flex-direction:row}.kbq-calendar-select-panel{margin-top:2px;min-width:98%!important}.kbq-calendar-select-panel .kbq-select__content{max-height:384px;overflow-x:hidden;scrollbar-gutter:auto}.kbq-calendar-select-panel .kbq-select__content .kbq-option{min-width:65px}\n"], dependencies: [{ kind: "ngmodule", type: KbqButtonModule }, { kind: "component", type: i1.KbqButton, selector: "[kbq-button]", inputs: ["kbqStyle", "disabled", "tabIndex"] }, { kind: "directive", type: i1.KbqButtonCssStyler, selector: "[kbq-button]" }, { kind: "ngmodule", type: KbqIconModule }, { kind: "component", type: i2.KbqIcon, selector: "[kbq-icon]", inputs: ["small", "autoColor", "kbq-icon"] }, { kind: "ngmodule", type: KbqSelectModule }, { kind: "component", type: i3.KbqSelect, selector: "kbq-select", inputs: ["hiddenItemsText", "showPreselectedValues", "triggerValuesLimit", "panelClass", "backdropClass", "errorStateMatcher", "sortComparator", "multiline", "searchMinOptionsThreshold", "scrolledToBottomOffset", "hasBackdrop", "placeholder", "required", "multiple", "compareWith", "virtualOptionFactory", "selectAllToggle", "selectAll", "selectAllHandler", "panelWidth", "panelMinWidth", "panelMaxWidth", "panelMaxHeight", "value", "id", "tabIndex", "disabled", "hiddenItemsTextFormatter"], outputs: ["openedChange", "beforeOpened", "opened", "closed", "selectionChange", "onSelectAll", "valueChange", "scrolledToBottom"], exportAs: ["kbqSelect"] }, { kind: "directive", type: i3.KbqOptionTooltip, selector: "kbq-option" }, { kind: "component", type: i4.KbqOption, selector: "kbq-option", inputs: ["value", "selectable", "userSelect", "showCheckbox", "viewValue", "disabled"], outputs: ["onSelectionChange"], exportAs: ["kbqOption"] }, { kind: "directive", type: i4.KbqSelectMatcher, selector: "kbq-select-matcher, [kbq-select-matcher]", inputs: ["useDefaultHandlers"] }, { kind: "ngmodule", type: KbqOptionModule }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
244
258
  }
245
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqCalendarHeader, decorators: [{
259
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqCalendarHeader, decorators: [{
246
260
  type: Component,
247
261
  args: [{ selector: 'kbq-calendar-header', imports: [
248
262
  TitleCasePipe,
@@ -261,12 +275,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
261
275
  type: Input
262
276
  }], activeDateChange: [{ type: i0.Output, args: ["activeDateChange"] }], monthSelected: [{ type: i0.Output, args: ["monthSelected"] }], yearSelected: [{ type: i0.Output, args: ["yearSelected"] }] } });
263
277
 
264
- /** @docs-private */
265
- function createMissingDateImplError(provider) {
266
- return Error(`KbqDatepicker: No provider found for ${provider}. You must import one of the existing ` +
267
- `modules at your application root or provide a custom implementation or use exists ones.`);
268
- }
269
-
270
278
  /** Datepicker data that requires internationalization. */
271
279
  class KbqDatepickerIntl {
272
280
  constructor() {
@@ -296,10 +304,10 @@ class KbqDatepickerIntl {
296
304
  /** A label for the 'switch to year view' button (used by screen readers). */
297
305
  this.switchToMultiYearViewLabel = 'Choose month and year';
298
306
  }
299
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepickerIntl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
300
- /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepickerIntl, providedIn: 'root' }); }
307
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepickerIntl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
308
+ /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepickerIntl, providedIn: 'root' }); }
301
309
  }
302
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepickerIntl, decorators: [{
310
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepickerIntl, decorators: [{
303
311
  type: Injectable,
304
312
  args: [{ providedIn: 'root' }]
305
313
  }] });
@@ -337,7 +345,8 @@ class KbqMonthView {
337
345
  }
338
346
  constructor() {
339
347
  this.changeDetectorRef = inject(ChangeDetectorRef);
340
- this.adapter = inject(DateAdapter, { optional: true });
348
+ this.timezoneService = inject(KbqDateTimezoneService);
349
+ this.adapter = injectRequiredDateAdapter();
341
350
  /** The minimum selectable date. */
342
351
  this.minDate = input(undefined, ...(ngDevMode ? [{ debugName: "minDate" }] : []));
343
352
  /** The maximum selectable date. */
@@ -354,9 +363,6 @@ class KbqMonthView {
354
363
  this.activeDateChange = output();
355
364
  /** The body of calendar table */
356
365
  this.kbqCalendarBody = viewChild.required(KbqCalendarBody);
357
- if (!this.adapter) {
358
- throw createMissingDateImplError('DateAdapter');
359
- }
360
366
  const firstDayOfWeek = this.adapter.getFirstDayOfWeek();
361
367
  const narrowWeekdays = this.adapter.getDayOfWeekNames('short');
362
368
  const longWeekdays = this.adapter.getDayOfWeekNames('long');
@@ -366,6 +372,12 @@ class KbqMonthView {
366
372
  });
367
373
  this.weekdays = weekdays.slice(firstDayOfWeek).concat(weekdays.slice(0, firstDayOfWeek));
368
374
  this._activeDate = this.adapter.today();
375
+ this.timezoneService.changes.pipe(takeUntilDestroyed()).subscribe(() => {
376
+ // `todayDate` and the cell dates are resolved once, in `init()`, against the zone that was
377
+ // active then; a new one can move which cell is today.
378
+ this.init();
379
+ this.changeDetectorRef.markForCheck();
380
+ });
369
381
  }
370
382
  ngAfterContentInit() {
371
383
  this.init();
@@ -433,10 +445,10 @@ class KbqMonthView {
433
445
  this.adapter.getMonth(d1) === this.adapter.getMonth(d2) &&
434
446
  this.adapter.getYear(d1) === this.adapter.getYear(d2));
435
447
  }
436
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqMonthView, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
437
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: KbqMonthView, isStandalone: true, selector: "kbq-month-view", inputs: { activeDate: { classPropertyName: "activeDate", publicName: "activeDate", isSignal: false, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: false, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, dateFilter: { classPropertyName: "dateFilter", publicName: "dateFilter", isSignal: true, isRequired: false, transformFunction: null }, dateClass: { classPropertyName: "dateClass", publicName: "dateClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedChange: "selectedChange", userSelection: "userSelection", activeDateChange: "activeDateChange" }, viewQueries: [{ propertyName: "kbqCalendarBody", first: true, predicate: KbqCalendarBody, descendants: true, isSignal: true }], exportAs: ["kbqMonthView"], ngImport: i0, template: "<table class=\"kbq-calendar__table\">\n <thead class=\"kbq-calendar__table-header\">\n <tr>\n @for (day of weekdays; track day) {\n <th [attr.aria-label]=\"day.long\">\n {{ day.narrow }}\n </th>\n }\n </tr>\n <tr>\n <th colspan=\"7\" class=\"kbq-calendar__table-header-divider\"></th>\n </tr>\n </thead>\n <tbody\n kbq-calendar-body\n [activeCell]=\"adapter.getDate(activeDate) - 1\"\n [labelMinRequiredCells]=\"3\"\n [rows]=\"weeks\"\n [selectedValue]=\"selectedDate!\"\n [todayValue]=\"todayDate!\"\n (selectedValueChange)=\"dateSelected($event)\"\n ></tbody>\n</table>\n", dependencies: [{ kind: "component", type: KbqCalendarBody, selector: "[kbq-calendar-body]", inputs: ["rows", "todayValue", "selectedValue", "labelMinRequiredCells", "numCols", "activeCell", "cellAspectRatio"], outputs: ["selectedValueChange"], exportAs: ["kbqCalendarBody"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
448
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqMonthView, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
449
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.30", type: KbqMonthView, isStandalone: true, selector: "kbq-month-view", inputs: { activeDate: { classPropertyName: "activeDate", publicName: "activeDate", isSignal: false, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: false, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, dateFilter: { classPropertyName: "dateFilter", publicName: "dateFilter", isSignal: true, isRequired: false, transformFunction: null }, dateClass: { classPropertyName: "dateClass", publicName: "dateClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedChange: "selectedChange", userSelection: "userSelection", activeDateChange: "activeDateChange" }, viewQueries: [{ propertyName: "kbqCalendarBody", first: true, predicate: KbqCalendarBody, descendants: true, isSignal: true }], exportAs: ["kbqMonthView"], ngImport: i0, template: "<table class=\"kbq-calendar__table\">\n <thead class=\"kbq-calendar__table-header\">\n <tr>\n @for (day of weekdays; track day) {\n <th [attr.aria-label]=\"day.long\">\n {{ day.narrow }}\n </th>\n }\n </tr>\n <tr>\n <th colspan=\"7\" class=\"kbq-calendar__table-header-divider\"></th>\n </tr>\n </thead>\n <tbody\n kbq-calendar-body\n [activeCell]=\"adapter.getDate(activeDate) - 1\"\n [labelMinRequiredCells]=\"3\"\n [rows]=\"weeks\"\n [selectedValue]=\"selectedDate!\"\n [todayValue]=\"todayDate!\"\n (selectedValueChange)=\"dateSelected($event)\"\n ></tbody>\n</table>\n", dependencies: [{ kind: "component", type: KbqCalendarBody, selector: "[kbq-calendar-body]", inputs: ["rows", "todayValue", "selectedValue", "labelMinRequiredCells", "numCols", "activeCell", "cellAspectRatio"], outputs: ["selectedValueChange"], exportAs: ["kbqCalendarBody"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
438
450
  }
439
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqMonthView, decorators: [{
451
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqMonthView, decorators: [{
440
452
  type: Component,
441
453
  args: [{ selector: 'kbq-month-view', imports: [
442
454
  KbqCalendarBody
@@ -504,7 +516,7 @@ class KbqCalendar {
504
516
  this.stateChanges.next();
505
517
  }
506
518
  constructor() {
507
- this.adapter = inject(DateAdapter, { optional: true });
519
+ this.adapter = injectRequiredDateAdapter();
508
520
  this.changeDetectorRef = inject(ChangeDetectorRef);
509
521
  /** Function used to filter which dates are selectable. */
510
522
  this.dateFilter = input(undefined, ...(ngDevMode ? [{ debugName: "dateFilter" }] : []));
@@ -534,9 +546,6 @@ class KbqCalendar {
534
546
  this.inputSubscription = Subscription.EMPTY;
535
547
  const intl = inject(KbqDatepickerIntl);
536
548
  const changeDetectorRef = this.changeDetectorRef;
537
- if (!this.adapter) {
538
- throw createMissingDateImplError('DateAdapter');
539
- }
540
549
  this.intlChanges = intl.changes.subscribe(() => {
541
550
  changeDetectorRef.markForCheck();
542
551
  this.stateChanges.next();
@@ -604,10 +613,10 @@ class KbqCalendar {
604
613
  getActiveDateDefault() {
605
614
  return this.startAt || this.adapter.today();
606
615
  }
607
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqCalendar, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
608
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.25", type: KbqCalendar, isStandalone: true, selector: "kbq-calendar", inputs: { startAt: { classPropertyName: "startAt", publicName: "startAt", isSignal: false, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: false, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: false, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: false, isRequired: false, transformFunction: null }, dateFilter: { classPropertyName: "dateFilter", publicName: "dateFilter", isSignal: true, isRequired: false, transformFunction: null }, dateClass: { classPropertyName: "dateClass", publicName: "dateClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedChange: "selectedChange", yearSelected: "yearSelected", monthSelected: "monthSelected", userSelection: "userSelection" }, host: { classAttribute: "kbq-calendar" }, viewQueries: [{ propertyName: "monthView", first: true, predicate: KbqMonthView, descendants: true, isSignal: true }], exportAs: ["kbqCalendar"], usesOnChanges: true, ngImport: i0, template: "<kbq-calendar-header\n [maxDate]=\"maxDate\"\n [minDate]=\"minDate\"\n [(activeDate)]=\"activeDate\"\n (monthSelected)=\"monthSelected.emit(activeDate)\"\n (yearSelected)=\"yearSelected.emit(activeDate)\"\n/>\n\n<div class=\"kbq-calendar__content\">\n <kbq-month-view\n [dateClass]=\"dateClass()\"\n [dateFilter]=\"dateFilter()\"\n [maxDate]=\"maxDate\"\n [minDate]=\"minDate\"\n [selected]=\"selected\"\n [(activeDate)]=\"activeDate\"\n (selectedChange)=\"dateSelected($event!)\"\n (userSelection)=\"userSelected()\"\n />\n</div>\n", styles: [".kbq-calendar{display:block;box-sizing:initial}.kbq-calendar__content{padding-right:var(--kbq-datepicker-size-grid-padding-horizontal);padding-left:var(--kbq-datepicker-size-grid-padding-horizontal);outline:none}.kbq-calendar__table{border-spacing:0;border-collapse:collapse;width:100%}.kbq-calendar__table-header th{text-align:center;height:30px}.kbq-calendar__table-header th.kbq-calendar__table-header-divider{position:relative;box-sizing:border-box;height:var(--kbq-datepicker-size-grid-content-gap-vertical)}.kbq-calendar__table-header th.kbq-calendar__table-header-divider:after{content:\"\";position:absolute;top:0;left:calc(-1 * var(--kbq-datepicker-size-grid-padding-horizontal));right:calc(-1 * var(--kbq-datepicker-size-grid-padding-horizontal));height:var(--kbq-datepicker-size-grid-divider-height)}\n"], dependencies: [{ kind: "component", type: KbqCalendarHeader, selector: "kbq-calendar-header", inputs: ["activeDate", "maxDate", "minDate"], outputs: ["activeDateChange", "monthSelected", "yearSelected"], exportAs: ["kbqCalendarHeader"] }, { kind: "component", type: KbqMonthView, selector: "kbq-month-view", inputs: ["activeDate", "selected", "minDate", "maxDate", "dateFilter", "dateClass"], outputs: ["selectedChange", "userSelection", "activeDateChange"], exportAs: ["kbqMonthView"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
616
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqCalendar, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
617
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.30", type: KbqCalendar, isStandalone: true, selector: "kbq-calendar", inputs: { startAt: { classPropertyName: "startAt", publicName: "startAt", isSignal: false, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: false, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: false, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: false, isRequired: false, transformFunction: null }, dateFilter: { classPropertyName: "dateFilter", publicName: "dateFilter", isSignal: true, isRequired: false, transformFunction: null }, dateClass: { classPropertyName: "dateClass", publicName: "dateClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedChange: "selectedChange", yearSelected: "yearSelected", monthSelected: "monthSelected", userSelection: "userSelection" }, host: { classAttribute: "kbq-calendar" }, viewQueries: [{ propertyName: "monthView", first: true, predicate: KbqMonthView, descendants: true, isSignal: true }], exportAs: ["kbqCalendar"], usesOnChanges: true, ngImport: i0, template: "<kbq-calendar-header\n [maxDate]=\"maxDate\"\n [minDate]=\"minDate\"\n [(activeDate)]=\"activeDate\"\n (monthSelected)=\"monthSelected.emit(activeDate)\"\n (yearSelected)=\"yearSelected.emit(activeDate)\"\n/>\n\n<div class=\"kbq-calendar__content\">\n <kbq-month-view\n [dateClass]=\"dateClass()\"\n [dateFilter]=\"dateFilter()\"\n [maxDate]=\"maxDate\"\n [minDate]=\"minDate\"\n [selected]=\"selected\"\n [(activeDate)]=\"activeDate\"\n (selectedChange)=\"dateSelected($event!)\"\n (userSelection)=\"userSelected()\"\n />\n</div>\n", styles: [".kbq-calendar{display:block;box-sizing:initial}.kbq-calendar__content{padding-right:var(--kbq-datepicker-size-grid-padding-horizontal);padding-left:var(--kbq-datepicker-size-grid-padding-horizontal);outline:none}.kbq-calendar__table{border-spacing:0;border-collapse:collapse;width:100%}.kbq-calendar__table-header th{text-align:center;height:30px}.kbq-calendar__table-header th.kbq-calendar__table-header-divider{position:relative;box-sizing:border-box;height:var(--kbq-datepicker-size-grid-content-gap-vertical)}.kbq-calendar__table-header th.kbq-calendar__table-header-divider:after{content:\"\";position:absolute;top:0;left:calc(-1 * var(--kbq-datepicker-size-grid-padding-horizontal));right:calc(-1 * var(--kbq-datepicker-size-grid-padding-horizontal));height:var(--kbq-datepicker-size-grid-divider-height)}\n"], dependencies: [{ kind: "component", type: KbqCalendarHeader, selector: "kbq-calendar-header", inputs: ["activeDate", "maxDate", "minDate"], outputs: ["activeDateChange", "monthSelected", "yearSelected"], exportAs: ["kbqCalendarHeader"] }, { kind: "component", type: KbqMonthView, selector: "kbq-month-view", inputs: ["activeDate", "selected", "minDate", "maxDate", "dateFilter", "dateClass"], outputs: ["selectedChange", "userSelection", "activeDateChange"], exportAs: ["kbqMonthView"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
609
618
  }
610
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqCalendar, decorators: [{
619
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqCalendar, decorators: [{
611
620
  type: Component,
612
621
  args: [{ selector: 'kbq-calendar', imports: [
613
622
  KbqCalendarHeader,
@@ -653,8 +662,14 @@ const kbqDatepickerAnimations = {
653
662
 
654
663
  /** Used to generate a unique ID for each datepicker instance. */
655
664
  let datepickerUid = 0;
656
- /** Injection token that determines the scroll handling while the calendar is open. */
657
- const KBQ_DATEPICKER_SCROLL_STRATEGY = new InjectionToken('kbq-datepicker-scroll-strategy');
665
+ /**
666
+ * Injection token that determines the scroll handling while the calendar is open. The root default keeps the
667
+ * datepicker usable outside `KbqDatepickerModule`'s injector; providing the token anywhere still wins over it.
668
+ */
669
+ const KBQ_DATEPICKER_SCROLL_STRATEGY = new InjectionToken('kbq-datepicker-scroll-strategy', {
670
+ providedIn: 'root',
671
+ factory: () => KBQ_DATEPICKER_SCROLL_STRATEGY_FACTORY(inject(Overlay))
672
+ });
658
673
  /** @docs-private */
659
674
  function KBQ_DATEPICKER_SCROLL_STRATEGY_FACTORY(overlay) {
660
675
  return () => overlay.scrollStrategies.reposition();
@@ -694,13 +709,13 @@ class KbqDatepickerContent {
694
709
  this.animationState = 'void';
695
710
  this.changeDetectorRef.markForCheck();
696
711
  }
697
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepickerContent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
698
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.25", type: KbqDatepickerContent, isStandalone: true, selector: "kbq-datepicker__content", host: { listeners: { "@transformPanel.done": "animationDone.next()" }, properties: { "@transformPanel": "animationState" }, classAttribute: "kbq-datepicker__content" }, viewQueries: [{ propertyName: "calendar", first: true, predicate: KbqCalendar, descendants: true, isSignal: true }], exportAs: ["kbqDatepickerContent"], ngImport: i0, template: "<kbq-calendar\n [dateClass]=\"datepicker.dateClass()\"\n [dateFilter]=\"datepicker.dateFilter\"\n [id]=\"datepicker.id\"\n [maxDate]=\"datepicker.maxDate()\"\n [minDate]=\"datepicker.minDate()\"\n [class]=\"datepicker.panelClass()\"\n [selected]=\"datepicker.selected\"\n [startAt]=\"datepicker.startAt\"\n [@fadeInCalendar]=\"'enter'\"\n (monthSelected)=\"datepicker.selectMonth($event)\"\n (selectedChange)=\"datepicker.select($event)\"\n (userSelection)=\"datepicker.close()\"\n (yearSelected)=\"datepicker.selectYear($event)\"\n/>\n", styles: [".kbq-datepicker__content{display:block;border-radius:var(--kbq-datepicker-size-container-border-radius)}.kbq-datepicker__content .kbq-calendar{width:calc(280px + var(--kbq-datepicker-size-grid-padding-horizontal) * 2);height:270px;padding-top:var(--kbq-datepicker-size-container-padding-vertical);padding-bottom:var(--kbq-datepicker-size-container-padding-vertical)}.kbq-datepicker__content{background:var(--kbq-datepicker-container-background);box-shadow:var(--kbq-datepicker-container-shadow)}.kbq-calendar__table-header{color:var(--kbq-datepicker-header-text)}.kbq-calendar__table-header-divider:after{background:var(--kbq-datepicker-header-divider)}.kbq-calendar__body-cell-content{background:var(--kbq-datepicker-grid-cell-default-background);color:var(--kbq-datepicker-grid-cell-default-text)}.kbq-calendar__body-cell-content.kbq-calendar__body-today{background:var(--kbq-datepicker-grid-cell-today-background);color:var(--kbq-datepicker-grid-cell-today-text)}.kbq-calendar__body-cell-content:hover:not(.kbq-disabled){background:var(--kbq-datepicker-grid-cell-states-hover-background)}.kbq-calendar__body-cell-content:active:not(.kbq-disabled){background:var(--kbq-datepicker-grid-cell-states-active-background)}.kbq-calendar__body-cell-content.kbq-selected:not(.kbq-disabled){background:var(--kbq-datepicker-grid-cell-states-selected-background);color:var(--kbq-datepicker-grid-cell-states-selected-text)}.kbq-calendar__body-cell-content.kbq-selected:not(.kbq-disabled):hover{background:var(--kbq-datepicker-grid-cell-states-selected-hover-background)}.kbq-calendar__body-cell-content.kbq-disabled{color:var(--kbq-datepicker-grid-cell-states-disabled-text);background:var(--kbq-datepicker-grid-cell-states-disabled-background)}.kbq-calendar,.kbq-calendar__table-header th{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}\n", ".kbq-datepicker__content{--kbq-datepicker-size-container-padding-vertical: var(--kbq-size-m);--kbq-datepicker-size-container-border-radius: var(--kbq-size-s);--kbq-datepicker-size-header-padding-horizontal: var(--kbq-size-xxs);--kbq-datepicker-size-header-margin-bottom: var(--kbq-size-3xs);--kbq-datepicker-size-grid-padding-horizontal: var(--kbq-size-m);--kbq-datepicker-size-grid-content-gap-vertical: var(--kbq-size-3xs);--kbq-datepicker-size-grid-divider-height: 1px;--kbq-datepicker-size-grid-cell-padding-horizontal: var(--kbq-size-s);--kbq-datepicker-size-grid-cell-padding-vertical: var(--kbq-size-s);--kbq-datepicker-size-grid-cell-border-radius: var(--kbq-size-s);--kbq-datepicker-container-background: var(--kbq-background-card);--kbq-datepicker-container-shadow: var(--kbq-shadow-popup);--kbq-datepicker-header-text: var(--kbq-foreground-contrast-tertiary);--kbq-datepicker-header-divider: var(--kbq-line-contrast-less);--kbq-datepicker-grid-cell-default-background: transparent;--kbq-datepicker-grid-cell-default-text: var(--kbq-foreground-contrast);--kbq-datepicker-grid-cell-today-background: transparent;--kbq-datepicker-grid-cell-today-text: var(--kbq-foreground-theme);--kbq-datepicker-grid-cell-states-hover-background: var(--kbq-states-background-transparent-hover);--kbq-datepicker-grid-cell-states-active-background: var(--kbq-states-background-transparent-active);--kbq-datepicker-grid-cell-states-selected-background: var(--kbq-background-contrast);--kbq-datepicker-grid-cell-states-selected-text: var(--kbq-foreground-on-contrast);--kbq-datepicker-grid-cell-states-selected-hover-background: var(--kbq-states-background-contrast-active);--kbq-datepicker-grid-cell-states-disabled-background: transparent;--kbq-datepicker-grid-cell-states-disabled-text: var(--kbq-states-foreground-disabled)}\n"], dependencies: [{ kind: "component", type: KbqCalendar, selector: "kbq-calendar", inputs: ["startAt", "selected", "minDate", "maxDate", "dateFilter", "dateClass"], outputs: ["selectedChange", "yearSelected", "monthSelected", "userSelection"], exportAs: ["kbqCalendar"] }], animations: [
712
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepickerContent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
713
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.30", type: KbqDatepickerContent, isStandalone: true, selector: "kbq-datepicker__content", host: { listeners: { "@transformPanel.done": "animationDone.next()" }, properties: { "@transformPanel": "animationState" }, classAttribute: "kbq-datepicker__content" }, viewQueries: [{ propertyName: "calendar", first: true, predicate: KbqCalendar, descendants: true, isSignal: true }], exportAs: ["kbqDatepickerContent"], ngImport: i0, template: "<kbq-calendar\n [dateClass]=\"datepicker.dateClass()\"\n [dateFilter]=\"datepicker.dateFilter\"\n [id]=\"datepicker.id\"\n [maxDate]=\"datepicker.maxDate()\"\n [minDate]=\"datepicker.minDate()\"\n [class]=\"datepicker.panelClass()\"\n [selected]=\"datepicker.selected\"\n [startAt]=\"datepicker.startAt\"\n [@fadeInCalendar]=\"'enter'\"\n (monthSelected)=\"datepicker.selectMonth($event)\"\n (selectedChange)=\"datepicker.select($event)\"\n (userSelection)=\"datepicker.close()\"\n (yearSelected)=\"datepicker.selectYear($event)\"\n/>\n", styles: [".kbq-datepicker__content{display:block;border-radius:var(--kbq-datepicker-size-container-border-radius)}.kbq-datepicker__content .kbq-calendar{width:calc(280px + var(--kbq-datepicker-size-grid-padding-horizontal) * 2);height:270px;padding-top:var(--kbq-datepicker-size-container-padding-vertical);padding-bottom:var(--kbq-datepicker-size-container-padding-vertical)}.kbq-datepicker__content{background:var(--kbq-datepicker-container-background);box-shadow:var(--kbq-datepicker-container-shadow)}.kbq-calendar__table-header{color:var(--kbq-datepicker-header-text)}.kbq-calendar__table-header-divider:after{background:var(--kbq-datepicker-header-divider)}.kbq-calendar__body-cell-content{background:var(--kbq-datepicker-grid-cell-default-background);color:var(--kbq-datepicker-grid-cell-default-text)}.kbq-calendar__body-cell-content.kbq-calendar__body-today{background:var(--kbq-datepicker-grid-cell-today-background);color:var(--kbq-datepicker-grid-cell-today-text)}.kbq-calendar__body-cell-content:hover:not(.kbq-disabled){background:var(--kbq-datepicker-grid-cell-states-hover-background)}.kbq-calendar__body-cell-content:active:not(.kbq-disabled){background:var(--kbq-datepicker-grid-cell-states-active-background)}.kbq-calendar__body-cell-content.kbq-selected:not(.kbq-disabled){background:var(--kbq-datepicker-grid-cell-states-selected-background);color:var(--kbq-datepicker-grid-cell-states-selected-text)}.kbq-calendar__body-cell-content.kbq-selected:not(.kbq-disabled):hover{background:var(--kbq-datepicker-grid-cell-states-selected-hover-background)}.kbq-calendar__body-cell-content.kbq-disabled{color:var(--kbq-datepicker-grid-cell-states-disabled-text);background:var(--kbq-datepicker-grid-cell-states-disabled-background)}.kbq-calendar,.kbq-calendar__table-header th{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}\n", ".kbq-datepicker__content{--kbq-datepicker-size-container-padding-vertical: var(--kbq-size-m);--kbq-datepicker-size-container-border-radius: var(--kbq-size-s);--kbq-datepicker-size-header-padding-horizontal: var(--kbq-size-xxs);--kbq-datepicker-size-header-margin-bottom: var(--kbq-size-3xs);--kbq-datepicker-size-grid-padding-horizontal: var(--kbq-size-m);--kbq-datepicker-size-grid-content-gap-vertical: var(--kbq-size-3xs);--kbq-datepicker-size-grid-divider-height: 1px;--kbq-datepicker-size-grid-cell-padding-horizontal: var(--kbq-size-s);--kbq-datepicker-size-grid-cell-padding-vertical: var(--kbq-size-s);--kbq-datepicker-size-grid-cell-border-radius: var(--kbq-size-s);--kbq-datepicker-container-background: var(--kbq-background-card);--kbq-datepicker-container-shadow: var(--kbq-shadow-popup);--kbq-datepicker-header-text: var(--kbq-foreground-contrast-tertiary);--kbq-datepicker-header-divider: var(--kbq-line-contrast-less);--kbq-datepicker-grid-cell-default-background: transparent;--kbq-datepicker-grid-cell-default-text: var(--kbq-foreground-contrast);--kbq-datepicker-grid-cell-today-background: transparent;--kbq-datepicker-grid-cell-today-text: var(--kbq-foreground-theme);--kbq-datepicker-grid-cell-states-hover-background: var(--kbq-states-background-transparent-hover);--kbq-datepicker-grid-cell-states-active-background: var(--kbq-states-background-transparent-active);--kbq-datepicker-grid-cell-states-selected-background: var(--kbq-background-contrast);--kbq-datepicker-grid-cell-states-selected-text: var(--kbq-foreground-on-contrast);--kbq-datepicker-grid-cell-states-selected-hover-background: var(--kbq-states-background-contrast-active);--kbq-datepicker-grid-cell-states-disabled-background: transparent;--kbq-datepicker-grid-cell-states-disabled-text: var(--kbq-states-foreground-disabled)}\n"], dependencies: [{ kind: "component", type: KbqCalendar, selector: "kbq-calendar", inputs: ["startAt", "selected", "minDate", "maxDate", "dateFilter", "dateClass"], outputs: ["selectedChange", "yearSelected", "monthSelected", "userSelection"], exportAs: ["kbqCalendar"] }], animations: [
699
714
  kbqDatepickerAnimations.transformPanel,
700
715
  kbqDatepickerAnimations.fadeInCalendar
701
716
  ], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
702
717
  }
703
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepickerContent, decorators: [{
718
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepickerContent, decorators: [{
704
719
  type: Component,
705
720
  args: [{ selector: 'kbq-datepicker__content', imports: [
706
721
  KbqCalendar
@@ -785,7 +800,7 @@ class KbqDatepicker {
785
800
  this.overlay = inject(Overlay);
786
801
  this.ngZone = inject(NgZone);
787
802
  this.viewContainerRef = inject(ViewContainerRef);
788
- this.dateAdapter = inject(DateAdapter, { optional: true });
803
+ this.dateAdapter = injectRequiredDateAdapter();
789
804
  this.dir = inject(Directionality, { optional: true });
790
805
  this.document = inject(DOCUMENT);
791
806
  this._hasBackdrop = false;
@@ -826,11 +841,7 @@ class KbqDatepicker {
826
841
  /** Subscription to value changes in the associated input element. */
827
842
  this.inputSubscription = Subscription.EMPTY;
828
843
  this.closeSubscription = Subscription.EMPTY;
829
- const scrollStrategy = inject(KBQ_DATEPICKER_SCROLL_STRATEGY);
830
- if (!this.dateAdapter) {
831
- throw createMissingDateImplError('DateAdapter');
832
- }
833
- this.scrollStrategy = scrollStrategy;
844
+ this.scrollStrategy = inject(KBQ_DATEPICKER_SCROLL_STRATEGY);
834
845
  }
835
846
  ngOnDestroy() {
836
847
  this.close();
@@ -1003,10 +1014,10 @@ class KbqDatepicker {
1003
1014
  }
1004
1015
  ]));
1005
1016
  }
1006
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepicker, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1007
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.25", type: KbqDatepicker, isStandalone: true, selector: "kbq-datepicker", inputs: { hasBackdrop: { classPropertyName: "hasBackdrop", publicName: "hasBackdrop", isSignal: false, isRequired: false, transformFunction: null }, startAt: { classPropertyName: "startAt", publicName: "startAt", isSignal: false, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, opened: { classPropertyName: "opened", publicName: "opened", isSignal: false, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, dateClass: { classPropertyName: "dateClass", publicName: "dateClass", isSignal: true, isRequired: false, transformFunction: null }, backdropClass: { classPropertyName: "backdropClass", publicName: "backdropClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { yearSelected: "yearSelected", monthSelected: "monthSelected", openedStream: "opened", closedStream: "closed" }, providers: [{ provide: KbqFormFieldControl, useExisting: KbqDatepicker }], exportAs: ["kbqDatepicker"], ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1017
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepicker, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1018
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.30", type: KbqDatepicker, isStandalone: true, selector: "kbq-datepicker", inputs: { hasBackdrop: { classPropertyName: "hasBackdrop", publicName: "hasBackdrop", isSignal: false, isRequired: false, transformFunction: null }, startAt: { classPropertyName: "startAt", publicName: "startAt", isSignal: false, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, opened: { classPropertyName: "opened", publicName: "opened", isSignal: false, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, dateClass: { classPropertyName: "dateClass", publicName: "dateClass", isSignal: true, isRequired: false, transformFunction: null }, backdropClass: { classPropertyName: "backdropClass", publicName: "backdropClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { yearSelected: "yearSelected", monthSelected: "monthSelected", openedStream: "opened", closedStream: "closed" }, providers: [{ provide: KbqFormFieldControl, useExisting: KbqDatepicker }], exportAs: ["kbqDatepicker"], ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
1008
1019
  }
1009
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepicker, decorators: [{
1020
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepicker, decorators: [{
1010
1021
  type: Component,
1011
1022
  args: [{
1012
1023
  selector: 'kbq-datepicker',
@@ -1220,24 +1231,40 @@ class KbqDatepickerInput {
1220
1231
  this.valueChange.emit(newValue);
1221
1232
  }
1222
1233
  }
1223
- /** The minimum valid date. */
1234
+ /**
1235
+ * The minimum valid date. Drives validation only — including dates typed or pasted into the
1236
+ * input — and reports `kbqDatepickerMin`. The calendar is restricted separately, by `minDate`
1237
+ * on the associated `<kbq-datepicker>`.
1238
+ *
1239
+ * Compared down to the millisecond, not by calendar day: the input keeps the time part of the
1240
+ * value it parses, and the comparison is made on wall-clock components rather than on absolute
1241
+ * time.
1242
+ */
1224
1243
  // TODO: Skipped for migration because:
1225
1244
  // Accessor inputs cannot be migrated as they are too complex.
1226
1245
  get min() {
1227
1246
  return this._min;
1228
1247
  }
1229
1248
  set min(value) {
1230
- this._min = this.adapter.deserialize(value);
1249
+ this._min = this.getValidDateOrNull(this.adapter.deserialize(value));
1231
1250
  this.validatorOnChange();
1232
1251
  }
1233
- /** The maximum valid date. */
1252
+ /**
1253
+ * The maximum valid date. Drives validation only — including dates typed or pasted into the
1254
+ * input — and reports `kbqDatepickerMax`. The calendar is restricted separately, by `maxDate`
1255
+ * on the associated `<kbq-datepicker>`.
1256
+ *
1257
+ * Compared down to the millisecond, not by calendar day: the input keeps the time part of the
1258
+ * value it parses, so an upper bound meant to include its whole day has to be the end of that
1259
+ * day.
1260
+ */
1234
1261
  // TODO: Skipped for migration because:
1235
1262
  // Accessor inputs cannot be migrated as they are too complex.
1236
1263
  get max() {
1237
1264
  return this._max;
1238
1265
  }
1239
1266
  set max(value) {
1240
- this._max = this.adapter.deserialize(value);
1267
+ this._max = this.getValidDateOrNull(this.adapter.deserialize(value));
1241
1268
  this.validatorOnChange();
1242
1269
  }
1243
1270
  /** Whether the datepicker-input is disabled. */
@@ -1313,22 +1340,17 @@ class KbqDatepickerInput {
1313
1340
  get selectionStart() {
1314
1341
  return this.elementRef.nativeElement.selectionStart;
1315
1342
  }
1316
- set selectionStart(value) {
1317
- this.elementRef.nativeElement.selectionStart = value;
1318
- }
1319
1343
  get selectionEnd() {
1320
1344
  return this.elementRef.nativeElement.selectionEnd;
1321
1345
  }
1322
- set selectionEnd(value) {
1323
- this.elementRef.nativeElement.selectionEnd = value;
1324
- }
1325
1346
  constructor() {
1326
1347
  this.elementRef = inject(ElementRef);
1327
1348
  this.renderer = inject(Renderer2);
1328
- this.adapter = inject(DateAdapter, { optional: true });
1349
+ this.adapter = injectRequiredDateAdapter();
1350
+ this.timezoneService = inject(KbqDateTimezoneService);
1329
1351
  this.dateFormats = inject(KBQ_DATE_FORMATS, { optional: true });
1330
1352
  /** @docs-private */
1331
- this.formField = inject(KbqFormField, { optional: true, host: true });
1353
+ this.formField = inject(KBQ_FORM_FIELD, { optional: true, host: true });
1332
1354
  /** @docs-private */
1333
1355
  this.localeService = inject(KBQ_LOCALE_SERVICE, { optional: true });
1334
1356
  /** @docs-private */
@@ -1355,7 +1377,7 @@ class KbqDatepickerInput {
1355
1377
  this.thirdDigit = null;
1356
1378
  this.onTouched = () => { };
1357
1379
  this.onInput = () => {
1358
- this.correctCursorPosition();
1380
+ const cursorPosition = this.correctedCursorPosition();
1359
1381
  const formattedValue = this.replaceSymbols(this.viewValue);
1360
1382
  const newTimeObj = this.getDateFromString(formattedValue);
1361
1383
  this.lastValueValid = !!newTimeObj;
@@ -1365,12 +1387,12 @@ class KbqDatepickerInput {
1365
1387
  this.updateValue(newTimeObj);
1366
1388
  }
1367
1389
  else {
1368
- this.control.updateValueAndValidity();
1390
+ this.control?.updateValueAndValidity();
1369
1391
  }
1370
1392
  return;
1371
1393
  }
1372
1394
  this.setViewValue(this.getTimeStringFromDate(newTimeObj, this.dateInputFormat), true);
1373
- this.selectNextDigitByCursor(this.selectionStart);
1395
+ this.selectNextDigitByCursor(cursorPosition);
1374
1396
  this.updateValue(newTimeObj);
1375
1397
  };
1376
1398
  this.parseOnBlur = () => {
@@ -1386,7 +1408,7 @@ class KbqDatepickerInput {
1386
1408
  if (viewDigits.length !== 3) {
1387
1409
  this.lastValueValid = false;
1388
1410
  this._value = null;
1389
- return setTimeout(() => this.control.updateValueAndValidity());
1411
+ return setTimeout(() => this.control?.updateValueAndValidity());
1390
1412
  }
1391
1413
  date[this.firstDigit.fullName] = this.firstDigit.parse(firsViewDigit);
1392
1414
  date[this.secondDigit.fullName] = this.secondDigit.parse(secondViewDigit);
@@ -1398,14 +1420,14 @@ class KbqDatepickerInput {
1398
1420
  else if (viewDigitWithYear.length < digitWithYear.length) {
1399
1421
  this.lastValueValid = false;
1400
1422
  this._value = null;
1401
- return setTimeout(() => this.control.updateValueAndValidity());
1423
+ return setTimeout(() => this.control?.updateValueAndValidity());
1402
1424
  }
1403
1425
  const newTimeObj = this.createDateTime(date);
1404
1426
  if (!newTimeObj) {
1405
1427
  this.lastValueValid = false;
1406
1428
  this._value = null;
1407
1429
  this.cvaOnChange(null);
1408
- return setTimeout(() => this.control.updateValueAndValidity());
1430
+ return setTimeout(() => this.control?.updateValueAndValidity());
1409
1431
  }
1410
1432
  /* Check if the number of days entered does not match the entered month */
1411
1433
  if (!this.getValidDateOrNull(newTimeObj)) {
@@ -1430,14 +1452,16 @@ class KbqDatepickerInput {
1430
1452
  };
1431
1453
  /** The form control validator for the min date. */
1432
1454
  this.minValidator = (control) => {
1433
- const controlValue = this.adapter.deserialize(control.value);
1455
+ // An unparseable value compares as NaN against any bound, which fails both `<= 0` and
1456
+ // `>= 0` and would report the value as simultaneously too early and too late.
1457
+ const controlValue = this.getValidDateOrNull(this.adapter.deserialize(control.value));
1434
1458
  return !this.min || !controlValue || this.adapter.compareDateTime(this.min, controlValue) <= 0
1435
1459
  ? null
1436
1460
  : { kbqDatepickerMin: { min: this.min, actual: controlValue } };
1437
1461
  };
1438
1462
  /** The form control validator for the max date. */
1439
1463
  this.maxValidator = (control) => {
1440
- const controlValue = this.adapter.deserialize(control.value);
1464
+ const controlValue = this.getValidDateOrNull(this.adapter.deserialize(control.value));
1441
1465
  return !this.max || !controlValue || this.adapter.compareDateTime(this.max, controlValue) >= 0
1442
1466
  ? null
1443
1467
  : { kbqDatepickerMax: { max: this.max, actual: controlValue } };
@@ -1455,9 +1479,6 @@ class KbqDatepickerInput {
1455
1479
  this.maxValidator,
1456
1480
  this.filterValidator
1457
1481
  ]);
1458
- if (!this.adapter) {
1459
- throw createMissingDateImplError('DateAdapter');
1460
- }
1461
1482
  this.errorStateTracker = new KbqErrorStateTracker(inject(ErrorStateMatcher),
1462
1483
  // update ngControl later, so it will be initialized
1463
1484
  null, inject(FormGroupDirective, { optional: true }), inject(NgForm, { optional: true }), this.stateChanges);
@@ -1466,6 +1487,11 @@ class KbqDatepickerInput {
1466
1487
  if (!this.localeService) {
1467
1488
  this.initDefaultParams();
1468
1489
  }
1490
+ this.timezoneService.changes.pipe(takeUntilDestroyed()).subscribe(() => {
1491
+ // The rendered text names a wall clock in the zone it was formatted in. Left as it is, the
1492
+ // next keystroke re-parses it against the new zone and emits a different instant.
1493
+ this.value = this.value;
1494
+ });
1469
1495
  }
1470
1496
  ngDoCheck() {
1471
1497
  if (this.ngControl) {
@@ -1638,9 +1664,11 @@ class KbqDatepickerInput {
1638
1664
  this.configuration = this.externalConfiguration || KBQ_DATEPICKER_DEFAULT_CONFIGURATION;
1639
1665
  }
1640
1666
  setFormat(format) {
1641
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1642
- // @ts-ignore
1643
- this.separator = format.match(/[aA-zZ]+(?<separator>\W|\D)[aA-zZ]+/).groups.separator;
1667
+ // `[a-zA-Z]`, not `[aA-zZ]`: the latter reads as `a`, the range `A-z` and `Z`, and that range
1668
+ // takes in the six characters ASCII puts between the two alphabets — opening bracket,
1669
+ // backslash, closing bracket, caret, underscore and backtick. A format escaping a literal in
1670
+ // brackets could therefore have had that bracket counted as part of a placeholder.
1671
+ this.separator = format.match(/[a-zA-Z]+(?<separator>\W|\D)[a-zA-Z]+/).groups.separator;
1644
1672
  this.separatorPositions = format
1645
1673
  .split('')
1646
1674
  .reduce((acc, item, index) => (this.separator === item ? [...acc, index + 1] : acc), []);
@@ -1672,30 +1700,36 @@ class KbqDatepickerInput {
1672
1700
  }
1673
1701
  spaceKeyHandler(event) {
1674
1702
  event.preventDefault();
1675
- if (this.selectionStart === this.selectionEnd) {
1676
- const value = this.getNewValue(event.key, this.selectionStart);
1677
- this.setViewValue(value);
1678
- setTimeout(this.onInput);
1679
- }
1680
- else if (this.selectionStart !== this.selectionEnd) {
1681
- this.selectNextDigit(this.selectionStart, true);
1703
+ const position = this.selectionStart;
1704
+ // Right after a separator the digit group is empty, so a space cannot stand in for one:
1705
+ // advance instead of inserting a character the value can never be parsed with.
1706
+ if (this.selectionStart !== this.selectionEnd || this.separatorPositions.includes(position)) {
1707
+ this.selectNextDigit(position, true);
1708
+ return;
1682
1709
  }
1710
+ this.setViewValue(this.getNewValue(event.key, position));
1711
+ setTimeout(this.onInput);
1683
1712
  }
1684
1713
  getNewValue(key, position) {
1685
1714
  return [this.viewValue.slice(0, position), key, this.viewValue.slice(position)].join('');
1686
1715
  }
1687
1716
  setViewValue(value, savePosition = false) {
1717
+ const element = this.elementRef.nativeElement;
1718
+ const selectionStart = this.selectionStart ?? 0;
1719
+ const selectionEnd = this.selectionEnd ?? 0;
1720
+ this.renderer.setProperty(element, 'value', value);
1688
1721
  if (savePosition) {
1689
- const selectionStart = this.selectionStart;
1690
- const selectionEnd = this.selectionEnd;
1691
- this.renderer.setProperty(this.elementRef.nativeElement, 'value', value);
1692
- this.selectionStart = selectionStart;
1693
- this.selectionEnd = selectionEnd;
1722
+ this.setSelection(selectionStart, selectionEnd);
1694
1723
  }
1695
1724
  else {
1696
- this.renderer.setProperty(this.elementRef.nativeElement, 'value', value);
1725
+ // A paste, a model write or a calendar pick replaces the whole value, and the offset the
1726
+ // previous one was left at has to go with it.
1727
+ kbqRevealSelection(element);
1697
1728
  }
1698
1729
  }
1730
+ setSelection(start, end) {
1731
+ kbqSetSelectionRange(this.elementRef.nativeElement, start, end);
1732
+ }
1699
1733
  replaceSymbols(value) {
1700
1734
  return value
1701
1735
  .split(this.separator)
@@ -1940,8 +1974,7 @@ class KbqDatepickerInput {
1940
1974
  changedTime = this.decrementDate(this.value, modifiedTimePart);
1941
1975
  }
1942
1976
  this.value = changedTime;
1943
- this.selectionStart = selectionStart;
1944
- this.selectionEnd = selectionEnd;
1977
+ this.setSelection(selectionStart, selectionEnd);
1945
1978
  this.cvaOnChange(changedTime);
1946
1979
  this.onChange();
1947
1980
  this.stateChanges.next();
@@ -1983,16 +2016,14 @@ class KbqDatepickerInput {
1983
2016
  selectDigitByCursor(cursorPos) {
1984
2017
  setTimeout(() => {
1985
2018
  const [, selectionStart, selectionEnd] = this.getDateEditMetrics(cursorPos);
1986
- this.selectionStart = selectionStart;
1987
- this.selectionEnd = selectionEnd;
2019
+ this.setSelection(selectionStart, selectionEnd);
1988
2020
  });
1989
2021
  }
1990
2022
  selectNextDigitByCursor(cursorPos) {
1991
2023
  setTimeout(() => {
1992
2024
  const [, , endPositionOfCurrentDigit] = this.getDateEditMetrics(cursorPos);
1993
2025
  const [, selectionStart, selectionEnd] = this.getDateEditMetrics(endPositionOfCurrentDigit + 1);
1994
- this.selectionStart = selectionStart;
1995
- this.selectionEnd = selectionEnd;
2026
+ this.setSelection(selectionStart, selectionEnd);
1996
2027
  });
1997
2028
  }
1998
2029
  selectNextDigit(cursorPos, cycle = false) {
@@ -2001,8 +2032,7 @@ class KbqDatepickerInput {
2001
2032
  const nextSeparatorPos = this.viewValue.indexOf(this.separator, cursorPos);
2002
2033
  const newCursorPos = nextSeparatorPos > 0 ? nextSeparatorPos + 1 : lastValue;
2003
2034
  const [, selectionStart, selectionEnd] = this.getDateEditMetrics(newCursorPos);
2004
- this.selectionStart = selectionStart;
2005
- this.selectionEnd = selectionEnd;
2035
+ this.setSelection(selectionStart, selectionEnd);
2006
2036
  });
2007
2037
  }
2008
2038
  /** Checks whether the input is invalid based on the native validation. */
@@ -2066,19 +2096,21 @@ class KbqDatepickerInput {
2066
2096
  }
2067
2097
  return this.adapter.createDateTime(value.year, value.month - 1, value.date, value.hours, value.minutes, value.seconds, value.milliseconds);
2068
2098
  }
2069
- correctCursorPosition() {
2070
- if (this.selectionStart && this.separatorPositions.includes(this.selectionStart)) {
2071
- this.selectionStart = this.selectionStart - 1;
2072
- }
2099
+ // The position to advance from, with a caret that landed just past a separator pulled back onto
2100
+ // the digit before it. Returned rather than applied to the field: on the paths where the value
2101
+ // cannot be parsed, a moved caret would survive into the next keystroke and change what it does.
2102
+ correctedCursorPosition() {
2103
+ const position = this.selectionStart ?? 0;
2104
+ return this.separatorPositions.includes(position) ? position - 1 : position;
2073
2105
  }
2074
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepickerInput, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2075
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.25", type: KbqDatepickerInput, isStandalone: true, selector: "input[kbqDatepicker], input[kbqCalendar]", inputs: { errorStateMatcher: "errorStateMatcher", placeholder: "placeholder", required: "required", kbqDatepicker: "kbqDatepicker", kbqCalendar: "kbqCalendar", kbqDatepickerFilter: "kbqDatepickerFilter", value: "value", min: "min", max: "max", disabled: "disabled", id: "id", kbqValidationTooltip: "kbqValidationTooltip" }, outputs: { incorrectInput: "incorrectInput", dateChange: "dateChange", dateInput: "dateInput" }, host: { listeners: { "paste": "onPaste($event)", "change": "onChange()", "focus": "focusChanged(true)", "blur": "onBlur()", "keydown": "onKeyDown($event)" }, properties: { "attr.placeholder": "placeholder", "attr.required": "required", "attr.disabled": "disabled || null", "attr.min": "min ? toISO8601(min) : null", "attr.max": "max ? toISO8601(max) : null", "attr.autocomplete": "\"off\"" }, classAttribute: "kbq-input kbq-datepicker" }, providers: [
2106
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepickerInput, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2107
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.30", type: KbqDatepickerInput, isStandalone: true, selector: "input[kbqDatepicker], input[kbqCalendar]", inputs: { errorStateMatcher: "errorStateMatcher", placeholder: "placeholder", required: "required", kbqDatepicker: "kbqDatepicker", kbqCalendar: "kbqCalendar", kbqDatepickerFilter: "kbqDatepickerFilter", value: "value", min: "min", max: "max", disabled: "disabled", id: "id", kbqValidationTooltip: "kbqValidationTooltip" }, outputs: { incorrectInput: "incorrectInput", dateChange: "dateChange", dateInput: "dateInput" }, host: { listeners: { "paste": "onPaste($event)", "change": "onChange()", "focus": "focusChanged(true)", "blur": "onBlur()", "keydown": "onKeyDown($event)" }, properties: { "attr.placeholder": "placeholder", "attr.required": "required", "attr.disabled": "disabled || null", "attr.min": "min ? toISO8601(min) : null", "attr.max": "max ? toISO8601(max) : null", "attr.autocomplete": "\"off\"" }, classAttribute: "kbq-input kbq-datepicker" }, providers: [
2076
2108
  KBQ_DATEPICKER_VALUE_ACCESSOR,
2077
2109
  KBQ_DATEPICKER_VALIDATORS,
2078
2110
  { provide: KbqFormFieldControl, useExisting: KbqDatepickerInput }
2079
2111
  ], exportAs: ["kbqDatepickerInput"], ngImport: i0 }); }
2080
2112
  }
2081
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepickerInput, decorators: [{
2113
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepickerInput, decorators: [{
2082
2114
  type: Directive,
2083
2115
  args: [{
2084
2116
  selector: 'input[kbqDatepicker], input[kbqCalendar]',
@@ -2131,10 +2163,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
2131
2163
 
2132
2164
  /** Can be used to override the icon of a `kbqDatepickerToggle`. */
2133
2165
  class KbqDatepickerToggleIcon {
2134
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepickerToggleIcon, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2135
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.25", type: KbqDatepickerToggleIcon, isStandalone: true, selector: "[kbqDatepickerToggleIcon]", ngImport: i0 }); }
2166
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepickerToggleIcon, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2167
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.30", type: KbqDatepickerToggleIcon, isStandalone: true, selector: "[kbqDatepickerToggleIcon]", ngImport: i0 }); }
2136
2168
  }
2137
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepickerToggleIcon, decorators: [{
2169
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepickerToggleIcon, decorators: [{
2138
2170
  type: Directive,
2139
2171
  args: [{
2140
2172
  selector: '[kbqDatepickerToggleIcon]'
@@ -2145,6 +2177,15 @@ class KbqDatepickerToggleIconComponent {
2145
2177
  this._disabled = false;
2146
2178
  /** Datepicker instance that the button will toggle. */
2147
2179
  this.datepicker = input(undefined, ...(ngDevMode ? [{ debugName: "datepicker", alias: 'for' }] : [{ alias: 'for' }]));
2180
+ /**
2181
+ * Emits `true` when the calendar opens and `false` when it closes. Part of the `KbqSiblingPopup`
2182
+ * contract.
2183
+ *
2184
+ * Built on top of the `datepicker` signal rather than read once, because the instance is bound after the
2185
+ * consumers of this stream (a tooltip on the same element subscribes in its constructor) and may be
2186
+ * swapped later — the same reason `watchStateChanges` is re-run from `ngOnChanges`.
2187
+ */
2188
+ this.openedChange = toObservable(this.datepicker).pipe(filter(Boolean), switchMap((datepicker) => merge(outputToObservable(datepicker.openedStream).pipe(map(() => true)), outputToObservable(datepicker.closedStream).pipe(map(() => false)))));
2148
2189
  this.destroyRef = inject(DestroyRef);
2149
2190
  this.cdr = inject(ChangeDetectorRef);
2150
2191
  this.stateChangesSubscription = Subscription.EMPTY;
@@ -2158,6 +2199,10 @@ class KbqDatepickerToggleIconComponent {
2158
2199
  set disabled(value) {
2159
2200
  this._disabled = coerceBooleanProperty(value);
2160
2201
  }
2202
+ /** Whether the calendar is currently on screen. Part of the `KbqSiblingPopup` contract. */
2203
+ get isAttached() {
2204
+ return !!this.datepicker()?.opened;
2205
+ }
2161
2206
  ngOnChanges(changes) {
2162
2207
  if (changes.datepicker && !changes.datepicker.firstChange) {
2163
2208
  this.watchStateChanges();
@@ -2186,8 +2231,8 @@ class KbqDatepickerToggleIconComponent {
2186
2231
  .pipe(takeUntilDestroyed(this.destroyRef))
2187
2232
  .subscribe(() => this.cdr.markForCheck());
2188
2233
  }
2189
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepickerToggleIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2190
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.25", type: KbqDatepickerToggleIconComponent, isStandalone: true, selector: "kbq-datepicker-toggle-icon", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, datepicker: { classPropertyName: "datepicker", publicName: "for", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "open($event)" }, properties: { "attr.aria-expanded": "datepicker().opened", "attr.aria-disabled": "disabled" }, classAttribute: "kbq-datepicker-toggle-icon" }, usesOnChanges: true, ngImport: i0, template: `
2234
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepickerToggleIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2235
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.30", type: KbqDatepickerToggleIconComponent, isStandalone: true, selector: "kbq-datepicker-toggle-icon", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, datepicker: { classPropertyName: "datepicker", publicName: "for", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "open($event)" }, properties: { "attr.aria-expanded": "datepicker().opened", "attr.aria-disabled": "disabled" }, classAttribute: "kbq-datepicker-toggle-icon" }, providers: [kbqSiblingPopupProvider(KbqDatepickerToggleIconComponent)], usesOnChanges: true, ngImport: i0, template: `
2191
2236
  <ng-content select="[kbqDatepickerToggleIcon]">
2192
2237
  <i
2193
2238
  color="contrast-fade"
@@ -2200,7 +2245,7 @@ class KbqDatepickerToggleIconComponent {
2200
2245
  </ng-content>
2201
2246
  `, isInline: true, styles: [".kbq-datepicker-toggle-icon{display:inline-flex;justify-content:center;align-items:center}.kbq-datepicker-toggle:focus{outline:0}.kbq-datepicker-toggle__button.kbq-button-icon{width:var(--kbq-datepicker-toggle-size-width, var(--kbq-size-3xl));height:var(--kbq-datepicker-toggle-size-height, var(--kbq-size-3xl));margin-left:2px}.kbq-form-field-appearance-legacy .kbq-form-field-prefix .kbq-datepicker-toggle__default-icon,.kbq-form-field-appearance-legacy .kbq-form-field-suffix .kbq-datepicker-toggle__default-icon{width:1em}.kbq-form-field:not(.kbq-form-field-appearance-legacy) .kbq-form-field-prefix .kbq-datepicker-toggle__default-icon,.kbq-form-field:not(.kbq-form-field-appearance-legacy) .kbq-form-field-suffix .kbq-datepicker-toggle__default-icon{display:block;width:1.5em;height:1.5em}.kbq-form-field:not(.kbq-form-field-appearance-legacy) .kbq-form-field-prefix .kbq-button-icon .kbq-datepicker-toggle__default-icon,.kbq-form-field:not(.kbq-form-field-appearance-legacy) .kbq-form-field-suffix .kbq-button-icon .kbq-datepicker-toggle__default-icon{margin:auto}\n"], dependencies: [{ kind: "ngmodule", type: KbqIconModule }, { kind: "component", type: i2.KbqIconButton, selector: "[kbq-icon-button]", inputs: ["size", "small", "kbq-icon-button", "tabindex", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
2202
2247
  }
2203
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepickerToggleIconComponent, decorators: [{
2248
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepickerToggleIconComponent, decorators: [{
2204
2249
  type: Component,
2205
2250
  args: [{ selector: 'kbq-datepicker-toggle-icon', imports: [KbqIconModule], template: `
2206
2251
  <ng-content select="[kbqDatepickerToggleIcon]">
@@ -2213,7 +2258,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
2213
2258
  [autoColor]="true"
2214
2259
  ></i>
2215
2260
  </ng-content>
2216
- `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
2261
+ `, providers: [kbqSiblingPopupProvider(KbqDatepickerToggleIconComponent)], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
2217
2262
  class: 'kbq-datepicker-toggle-icon',
2218
2263
  '[attr.aria-expanded]': 'datepicker().opened',
2219
2264
  '[attr.aria-disabled]': 'disabled',
@@ -2224,8 +2269,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
2224
2269
  }], datepicker: [{ type: i0.Input, args: [{ isSignal: true, alias: "for", required: false }] }] } });
2225
2270
 
2226
2271
  class KbqDatepickerModule {
2227
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
2228
- /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepickerModule, imports: [KbqButtonModule,
2272
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
2273
+ /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepickerModule, imports: [KbqButtonModule,
2229
2274
  OverlayModule,
2230
2275
  A11yModule,
2231
2276
  PortalModule,
@@ -2250,10 +2295,7 @@ class KbqDatepickerModule {
2250
2295
  KbqMonthView,
2251
2296
  KbqCalendarHeader,
2252
2297
  KbqFormFieldModule] }); }
2253
- /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepickerModule, providers: [
2254
- KbqDatepickerIntl,
2255
- KBQ_DATEPICKER_SCROLL_STRATEGY_FACTORY_PROVIDER
2256
- ], imports: [KbqButtonModule,
2298
+ /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepickerModule, providers: [KbqDatepickerIntl], imports: [KbqButtonModule,
2257
2299
  OverlayModule,
2258
2300
  A11yModule,
2259
2301
  PortalModule,
@@ -2264,7 +2306,7 @@ class KbqDatepickerModule {
2264
2306
  KbqDatepickerContent,
2265
2307
  KbqCalendarHeader, KbqFormFieldModule] }); }
2266
2308
  }
2267
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqDatepickerModule, decorators: [{
2309
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqDatepickerModule, decorators: [{
2268
2310
  type: NgModule,
2269
2311
  args: [{
2270
2312
  imports: [
@@ -2285,10 +2327,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
2285
2327
  KbqMonthView,
2286
2328
  KbqCalendarHeader
2287
2329
  ],
2288
- providers: [
2289
- KbqDatepickerIntl,
2290
- KBQ_DATEPICKER_SCROLL_STRATEGY_FACTORY_PROVIDER
2291
- ],
2330
+ providers: [KbqDatepickerIntl],
2292
2331
  exports: [
2293
2332
  KbqCalendar,
2294
2333
  KbqCalendarBody,