forty-cdk 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/accordion/README.md +122 -0
  2. package/aspect-ratio/README.md +76 -0
  3. package/avatar/README.md +100 -0
  4. package/breadcrumbs/README.md +49 -0
  5. package/breakpoints/README.md +81 -0
  6. package/button/README.md +49 -0
  7. package/calendar/README.md +458 -0
  8. package/carousel/README.md +358 -0
  9. package/checkbox/README.md +146 -0
  10. package/combobox/README.md +535 -0
  11. package/context-menu/README.md +139 -0
  12. package/date-field/README.md +184 -0
  13. package/date-picker/README.md +338 -0
  14. package/dialog/README.md +388 -0
  15. package/disclosure/README.md +114 -0
  16. package/drag-drop/README.md +359 -0
  17. package/drawer/README.md +560 -0
  18. package/dropdown-menu/README.md +176 -0
  19. package/fesm2022/forty-cdk-accordion.mjs +348 -0
  20. package/fesm2022/forty-cdk-accordion.mjs.map +1 -0
  21. package/fesm2022/forty-cdk-aspect-ratio.mjs +74 -0
  22. package/fesm2022/forty-cdk-aspect-ratio.mjs.map +1 -0
  23. package/fesm2022/forty-cdk-avatar.mjs +308 -0
  24. package/fesm2022/forty-cdk-avatar.mjs.map +1 -0
  25. package/fesm2022/forty-cdk-breadcrumbs.mjs +125 -0
  26. package/fesm2022/forty-cdk-breadcrumbs.mjs.map +1 -0
  27. package/fesm2022/forty-cdk-breakpoints.mjs +117 -0
  28. package/fesm2022/forty-cdk-breakpoints.mjs.map +1 -0
  29. package/fesm2022/forty-cdk-button.mjs +134 -0
  30. package/fesm2022/forty-cdk-button.mjs.map +1 -0
  31. package/fesm2022/forty-cdk-calendar.mjs +2034 -0
  32. package/fesm2022/forty-cdk-calendar.mjs.map +1 -0
  33. package/fesm2022/forty-cdk-carousel.mjs +968 -0
  34. package/fesm2022/forty-cdk-carousel.mjs.map +1 -0
  35. package/fesm2022/forty-cdk-checkbox.mjs +226 -0
  36. package/fesm2022/forty-cdk-checkbox.mjs.map +1 -0
  37. package/fesm2022/forty-cdk-combobox.mjs +2596 -0
  38. package/fesm2022/forty-cdk-combobox.mjs.map +1 -0
  39. package/fesm2022/forty-cdk-context-menu.mjs +413 -0
  40. package/fesm2022/forty-cdk-context-menu.mjs.map +1 -0
  41. package/fesm2022/forty-cdk-core.mjs +9022 -0
  42. package/fesm2022/forty-cdk-core.mjs.map +1 -0
  43. package/fesm2022/forty-cdk-date-field.mjs +744 -0
  44. package/fesm2022/forty-cdk-date-field.mjs.map +1 -0
  45. package/fesm2022/forty-cdk-date-picker.mjs +1011 -0
  46. package/fesm2022/forty-cdk-date-picker.mjs.map +1 -0
  47. package/fesm2022/forty-cdk-dialog.mjs +707 -0
  48. package/fesm2022/forty-cdk-dialog.mjs.map +1 -0
  49. package/fesm2022/forty-cdk-disclosure.mjs +190 -0
  50. package/fesm2022/forty-cdk-disclosure.mjs.map +1 -0
  51. package/fesm2022/forty-cdk-drag-drop.mjs +1180 -0
  52. package/fesm2022/forty-cdk-drag-drop.mjs.map +1 -0
  53. package/fesm2022/forty-cdk-drawer.mjs +1641 -0
  54. package/fesm2022/forty-cdk-drawer.mjs.map +1 -0
  55. package/fesm2022/forty-cdk-dropdown-menu.mjs +350 -0
  56. package/fesm2022/forty-cdk-dropdown-menu.mjs.map +1 -0
  57. package/fesm2022/forty-cdk-field.mjs +425 -0
  58. package/fesm2022/forty-cdk-field.mjs.map +1 -0
  59. package/fesm2022/forty-cdk-fieldset.mjs +164 -0
  60. package/fesm2022/forty-cdk-fieldset.mjs.map +1 -0
  61. package/fesm2022/forty-cdk-file-upload.mjs +221 -0
  62. package/fesm2022/forty-cdk-file-upload.mjs.map +1 -0
  63. package/fesm2022/forty-cdk-hover-card.mjs +496 -0
  64. package/fesm2022/forty-cdk-hover-card.mjs.map +1 -0
  65. package/fesm2022/forty-cdk-input.mjs +274 -0
  66. package/fesm2022/forty-cdk-input.mjs.map +1 -0
  67. package/fesm2022/forty-cdk-internationalized-date.mjs +1 -1
  68. package/fesm2022/forty-cdk-internationalized-date.mjs.map +1 -1
  69. package/fesm2022/forty-cdk-listbox.mjs +1279 -0
  70. package/fesm2022/forty-cdk-listbox.mjs.map +1 -0
  71. package/fesm2022/forty-cdk-menu.mjs +1439 -0
  72. package/fesm2022/forty-cdk-menu.mjs.map +1 -0
  73. package/fesm2022/forty-cdk-menubar.mjs +787 -0
  74. package/fesm2022/forty-cdk-menubar.mjs.map +1 -0
  75. package/fesm2022/forty-cdk-meter.mjs +211 -0
  76. package/fesm2022/forty-cdk-meter.mjs.map +1 -0
  77. package/fesm2022/forty-cdk-navigation-menu.mjs +1145 -0
  78. package/fesm2022/forty-cdk-navigation-menu.mjs.map +1 -0
  79. package/fesm2022/forty-cdk-number-input.mjs +559 -0
  80. package/fesm2022/forty-cdk-number-input.mjs.map +1 -0
  81. package/fesm2022/forty-cdk-otp-input.mjs +527 -0
  82. package/fesm2022/forty-cdk-otp-input.mjs.map +1 -0
  83. package/fesm2022/forty-cdk-pagination.mjs +323 -0
  84. package/fesm2022/forty-cdk-pagination.mjs.map +1 -0
  85. package/fesm2022/forty-cdk-pane-resizer.mjs +297 -0
  86. package/fesm2022/forty-cdk-pane-resizer.mjs.map +1 -0
  87. package/fesm2022/forty-cdk-popover.mjs +698 -0
  88. package/fesm2022/forty-cdk-popover.mjs.map +1 -0
  89. package/fesm2022/forty-cdk-progress.mjs +226 -0
  90. package/fesm2022/forty-cdk-progress.mjs.map +1 -0
  91. package/fesm2022/forty-cdk-radio-group.mjs +378 -0
  92. package/fesm2022/forty-cdk-radio-group.mjs.map +1 -0
  93. package/fesm2022/forty-cdk-scroll-area.mjs +640 -0
  94. package/fesm2022/forty-cdk-scroll-area.mjs.map +1 -0
  95. package/fesm2022/forty-cdk-search.mjs +205 -0
  96. package/fesm2022/forty-cdk-search.mjs.map +1 -0
  97. package/fesm2022/forty-cdk-select.mjs +1661 -0
  98. package/fesm2022/forty-cdk-select.mjs.map +1 -0
  99. package/fesm2022/forty-cdk-separator.mjs +82 -0
  100. package/fesm2022/forty-cdk-separator.mjs.map +1 -0
  101. package/fesm2022/forty-cdk-signal-forms.mjs +97 -0
  102. package/fesm2022/forty-cdk-signal-forms.mjs.map +1 -0
  103. package/fesm2022/forty-cdk-slider.mjs +803 -0
  104. package/fesm2022/forty-cdk-slider.mjs.map +1 -0
  105. package/fesm2022/forty-cdk-stepper.mjs +886 -0
  106. package/fesm2022/forty-cdk-stepper.mjs.map +1 -0
  107. package/fesm2022/forty-cdk-switch.mjs +137 -0
  108. package/fesm2022/forty-cdk-switch.mjs.map +1 -0
  109. package/fesm2022/forty-cdk-table.mjs +1518 -0
  110. package/fesm2022/forty-cdk-table.mjs.map +1 -0
  111. package/fesm2022/forty-cdk-tabs.mjs +400 -0
  112. package/fesm2022/forty-cdk-tabs.mjs.map +1 -0
  113. package/fesm2022/forty-cdk-time-field.mjs +593 -0
  114. package/fesm2022/forty-cdk-time-field.mjs.map +1 -0
  115. package/fesm2022/forty-cdk-time-picker.mjs +1013 -0
  116. package/fesm2022/forty-cdk-time-picker.mjs.map +1 -0
  117. package/fesm2022/forty-cdk-toast.mjs +1153 -0
  118. package/fesm2022/forty-cdk-toast.mjs.map +1 -0
  119. package/fesm2022/forty-cdk-toggle.mjs +516 -0
  120. package/fesm2022/forty-cdk-toggle.mjs.map +1 -0
  121. package/fesm2022/forty-cdk-toolbar.mjs +374 -0
  122. package/fesm2022/forty-cdk-toolbar.mjs.map +1 -0
  123. package/fesm2022/forty-cdk-tooltip.mjs +672 -0
  124. package/fesm2022/forty-cdk-tooltip.mjs.map +1 -0
  125. package/fesm2022/forty-cdk-tree.mjs +2007 -0
  126. package/fesm2022/forty-cdk-tree.mjs.map +1 -0
  127. package/fesm2022/forty-cdk-virtualization.mjs +1 -1
  128. package/fesm2022/forty-cdk-virtualization.mjs.map +1 -1
  129. package/fesm2022/forty-cdk.mjs +0 -43310
  130. package/fesm2022/forty-cdk.mjs.map +1 -1
  131. package/field/README.md +97 -0
  132. package/fieldset/README.md +86 -0
  133. package/file-upload/README.md +73 -0
  134. package/hover-card/README.md +171 -0
  135. package/input/README.md +156 -0
  136. package/listbox/README.md +424 -0
  137. package/menu/README.md +181 -0
  138. package/menubar/README.md +140 -0
  139. package/meter/README.md +128 -0
  140. package/navigation-menu/README.md +253 -0
  141. package/number-input/README.md +171 -0
  142. package/otp-input/README.md +198 -0
  143. package/package.json +213 -1
  144. package/pagination/README.md +61 -0
  145. package/pane-resizer/README.md +136 -0
  146. package/popover/README.md +262 -0
  147. package/progress/README.md +115 -0
  148. package/radio-group/README.md +129 -0
  149. package/scroll-area/README.md +184 -0
  150. package/search/README.md +42 -0
  151. package/select/README.md +488 -0
  152. package/separator/README.md +84 -0
  153. package/signal-forms/README.md +72 -0
  154. package/slider/README.md +152 -0
  155. package/stepper/README.md +292 -0
  156. package/switch/README.md +116 -0
  157. package/table/README.md +769 -0
  158. package/tabs/README.md +130 -0
  159. package/time-field/README.md +157 -0
  160. package/time-picker/README.md +172 -0
  161. package/toast/README.md +398 -0
  162. package/toggle/README.md +224 -0
  163. package/toolbar/README.md +109 -0
  164. package/tooltip/README.md +274 -0
  165. package/tree/README.md +708 -0
  166. package/types/forty-cdk-accordion.d.ts +242 -0
  167. package/types/forty-cdk-aspect-ratio.d.ts +59 -0
  168. package/types/forty-cdk-avatar.d.ts +133 -0
  169. package/types/forty-cdk-breadcrumbs.d.ts +92 -0
  170. package/types/forty-cdk-breakpoints.d.ts +141 -0
  171. package/types/forty-cdk-button.d.ts +80 -0
  172. package/types/forty-cdk-calendar.d.ts +914 -0
  173. package/types/forty-cdk-carousel.d.ts +530 -0
  174. package/types/forty-cdk-checkbox.d.ts +141 -0
  175. package/types/forty-cdk-combobox.d.ts +1259 -0
  176. package/types/forty-cdk-context-menu.d.ts +313 -0
  177. package/types/forty-cdk-core.d.ts +5774 -0
  178. package/types/forty-cdk-date-field.d.ts +307 -0
  179. package/types/forty-cdk-date-picker.d.ts +622 -0
  180. package/types/forty-cdk-dialog.d.ts +546 -0
  181. package/types/forty-cdk-disclosure.d.ts +127 -0
  182. package/types/forty-cdk-drag-drop.d.ts +456 -0
  183. package/types/forty-cdk-drawer.d.ts +871 -0
  184. package/types/forty-cdk-dropdown-menu.d.ts +242 -0
  185. package/types/forty-cdk-field.d.ts +236 -0
  186. package/types/forty-cdk-fieldset.d.ts +119 -0
  187. package/types/forty-cdk-file-upload.d.ts +124 -0
  188. package/types/forty-cdk-hover-card.d.ts +320 -0
  189. package/types/forty-cdk-input.d.ts +169 -0
  190. package/types/forty-cdk-internationalized-date.d.ts +1 -1
  191. package/types/forty-cdk-listbox.d.ts +513 -0
  192. package/types/forty-cdk-menu.d.ts +629 -0
  193. package/types/forty-cdk-menubar.d.ts +451 -0
  194. package/types/forty-cdk-meter.d.ts +122 -0
  195. package/types/forty-cdk-navigation-menu.d.ts +514 -0
  196. package/types/forty-cdk-number-input.d.ts +319 -0
  197. package/types/forty-cdk-otp-input.d.ts +248 -0
  198. package/types/forty-cdk-pagination.d.ts +214 -0
  199. package/types/forty-cdk-pane-resizer.d.ts +145 -0
  200. package/types/forty-cdk-popover.d.ts +509 -0
  201. package/types/forty-cdk-progress.d.ts +143 -0
  202. package/types/forty-cdk-radio-group.d.ts +222 -0
  203. package/types/forty-cdk-scroll-area.d.ts +258 -0
  204. package/types/forty-cdk-search.d.ts +142 -0
  205. package/types/forty-cdk-select.d.ts +899 -0
  206. package/types/forty-cdk-separator.d.ts +59 -0
  207. package/types/forty-cdk-signal-forms.d.ts +58 -0
  208. package/types/forty-cdk-slider.d.ts +379 -0
  209. package/types/forty-cdk-stepper.d.ts +650 -0
  210. package/types/forty-cdk-switch.d.ts +87 -0
  211. package/types/forty-cdk-table.d.ts +723 -0
  212. package/types/forty-cdk-tabs.d.ts +235 -0
  213. package/types/forty-cdk-time-field.d.ts +307 -0
  214. package/types/forty-cdk-time-picker.d.ts +578 -0
  215. package/types/forty-cdk-toast.d.ts +598 -0
  216. package/types/forty-cdk-toggle.d.ts +310 -0
  217. package/types/forty-cdk-toolbar.d.ts +217 -0
  218. package/types/forty-cdk-tooltip.d.ts +436 -0
  219. package/types/forty-cdk-tree.d.ts +688 -0
  220. package/types/forty-cdk.d.ts +1 -19743
@@ -0,0 +1,1013 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, inject, computed, model, input, numberAttribute, booleanAttribute, output, Directive, ElementRef, effect, signal } from '@angular/core';
3
+ import { secondsOfDay, createDefaults, FormUiControlBase, IdGenerator, assertTimeCapable, injectDateAdapter, injectTextDirection, ListboxOverlayController, timeSentinel, injectHiddenInput, serializeISOTime, FOR_TIME_VALUE_SOURCE, registerHandle, reflectDisabled, injectModalShell, injectOverlayShell, hostId, resolveListNavigation } from 'forty-cdk/core';
4
+
5
+ function timeOfDaySeconds(adapter, d, granularity) {
6
+ const h = adapter.getHours(d);
7
+ if (granularity === 'hour') {
8
+ return h * 3600;
9
+ }
10
+ if (granularity === 'minute') {
11
+ return h * 3600 + adapter.getMinutes(d) * 60;
12
+ }
13
+ return secondsOfDay(adapter, d);
14
+ }
15
+ /**
16
+ * Generates the full-day slot list for a {@link ForTimePicker}.
17
+ *
18
+ * Slots span the full 24-hour day (00:00:00 up to but not past 24:00). Each slot's
19
+ * `disabled` flag is `true` when its time-of-day falls outside `[minTime, maxTime]`
20
+ * — slots are never omitted, following the WAI-ARIA option convention for disabled
21
+ * items.
22
+ *
23
+ * Pure function: no signals, no DOM, no side effects.
24
+ */
25
+ function buildTimeSlots(config) {
26
+ const { adapter, anchor, selected, minTime, maxTime, step, granularity, formatOptions } = config;
27
+ const stepSeconds = Math.max(1, Math.round(step)) * 60;
28
+ const minSec = minTime !== null ? timeOfDaySeconds(adapter, minTime, 'second') : null;
29
+ const maxSec = maxTime !== null ? timeOfDaySeconds(adapter, maxTime, 'second') : null;
30
+ const slots = [];
31
+ for (let t = 0; t < 86400; t += stepSeconds) {
32
+ const h = Math.floor(t / 3600);
33
+ const m = Math.floor((t % 3600) / 60);
34
+ const s = t % 60;
35
+ const value = adapter.setTime(anchor, h, m, s);
36
+ const label = adapter.format(value, formatOptions);
37
+ const slotGranularSec = timeOfDaySeconds(adapter, value, granularity);
38
+ const slotFullSec = h * 3600 + m * 60 + s;
39
+ const isSelected = selected !== null && slotGranularSec === timeOfDaySeconds(adapter, selected, granularity);
40
+ const disabled = (minSec !== null && slotFullSec < minSec) || (maxSec !== null && slotFullSec > maxSec);
41
+ slots.push({ id: `slot-${t}`, value, label, selected: isSelected, disabled });
42
+ }
43
+ return slots;
44
+ }
45
+
46
+ const FOR_TIME_PICKER_CONTEXT = new InjectionToken('FOR_TIME_PICKER_CONTEXT');
47
+ function injectTimePickerContext(piece) {
48
+ const ctx = inject(FOR_TIME_PICKER_CONTEXT, { optional: true });
49
+ if (!ctx) {
50
+ throw new Error(`[forty-cdk/time-picker] ${piece} must be used inside a [forTimePicker] element. ` +
51
+ "If it is declared inside an ng-template, DI resolves at the template's declaration site — " +
52
+ 'not where it is stamped (e.g. via ngTemplateOutlet) — so declare the template inside the ' +
53
+ '[forTimePicker] root.');
54
+ }
55
+ return ctx;
56
+ }
57
+ function injectTimePickerTriggerContext(explicitRoot) {
58
+ const injected = inject(FOR_TIME_PICKER_CONTEXT, { optional: true });
59
+ return computed(() => {
60
+ const explicit = explicitRoot();
61
+ if (explicit !== '') {
62
+ return explicit;
63
+ }
64
+ if (injected) {
65
+ return injected;
66
+ }
67
+ throw new Error('[forty-cdk/time-picker] ForTimePickerTrigger could not resolve its [forTimePicker] root: ' +
68
+ 'no FOR_TIME_PICKER_CONTEXT provider is visible and no explicit root reference was passed. ' +
69
+ "If this trigger is declared inside an ng-template, DI resolves at the template's declaration " +
70
+ 'site — not where it is stamped — so either declare the template inside the root or pass the ' +
71
+ 'root explicitly: [forTimePickerTrigger]="root" with #root="forTimePicker".');
72
+ });
73
+ }
74
+
75
+ /**
76
+ * Library fallback for time picker defaults, read at the root injector when no
77
+ * consumer has called `provideForTimePickerDefaults`. Exported for the shared
78
+ * defaults contract spec; not re-exported from the primitive's public entry.
79
+ */
80
+ const FOR_TIME_PICKER_FALLBACK_DEFAULTS = {
81
+ sideOffset: 4,
82
+ collisionPadding: 8,
83
+ };
84
+ const { token, provideDefaults } = createDefaults('FOR_TIME_PICKER_DEFAULTS', FOR_TIME_PICKER_FALLBACK_DEFAULTS);
85
+ /** Token holding the resolved time picker defaults for the current scope. */
86
+ const FOR_TIME_PICKER_DEFAULTS = token;
87
+ /**
88
+ * Configures forty-cdk time picker defaults for this injector scope. Partial
89
+ * overrides inherit unspecified keys from the parent scope (or library defaults
90
+ * at the root).
91
+ */
92
+ function provideForTimePickerDefaults(defaults = {}) {
93
+ return provideDefaults(defaults);
94
+ }
95
+
96
+ /**
97
+ * Root of the headless time picker, implementing the
98
+ * [WAI-ARIA Listbox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/)
99
+ * for a slot-based time selection. Generates a full-day list of time slots at
100
+ * a configurable `step` (in minutes), displayed in a floating listbox.
101
+ *
102
+ * Implements `FormValueControl<D | null>` from `@angular/forms/signals` for
103
+ * `[formField]` auto-wiring. Requires a time-capable adapter
104
+ * (`provideNativeDateAdapter()` or `provideInternationalizedDateTimeAdapter()`).
105
+ *
106
+ * @typeParam D The adapter's immutable date-time type.
107
+ */
108
+ class ForTimePicker extends FormUiControlBase {
109
+ #idGen = inject(IdGenerator);
110
+ #defaults = inject(FOR_TIME_PICKER_DEFAULTS);
111
+ /**
112
+ * The active, time-capable date adapter. Throws when the provided adapter is
113
+ * day-only.
114
+ */
115
+ adapter = assertTimeCapable(injectDateAdapter('ForTimePicker'), 'ForTimePicker');
116
+ /**
117
+ * Two-way bindable selected time, or `null`. Required by
118
+ * `FormValueControl<D | null>`. The `model()` change emitter
119
+ * (`(valueChange)`) fires only on internal selection changes, never on
120
+ * consumer writes via `[(value)]`.
121
+ */
122
+ value = model(null, /* @ts-ignore */
123
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
124
+ /**
125
+ * Two-way bindable. Whether the listbox is currently shown. The `model()`
126
+ * change emitter (`(openChange)`) fires only on internal transitions, never
127
+ * on consumer writes via `[(open)]`.
128
+ */
129
+ open = model(false, /* @ts-ignore */
130
+ ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
131
+ /**
132
+ * Earliest selectable time-of-day (inclusive). Slots earlier in the day are
133
+ * disabled. Named `minTime` (not `min`) because `FormUiControl.min` is
134
+ * reserved for a numeric validator.
135
+ */
136
+ minTime = input(null, /* @ts-ignore */
137
+ ...(ngDevMode ? [{ debugName: "minTime" }] : /* istanbul ignore next */ []));
138
+ /**
139
+ * Latest selectable time-of-day (inclusive). Slots later in the day are
140
+ * disabled. Named `maxTime` for the same reason as {@link minTime}.
141
+ */
142
+ maxTime = input(null, /* @ts-ignore */
143
+ ...(ngDevMode ? [{ debugName: "maxTime" }] : /* istanbul ignore next */ []));
144
+ /**
145
+ * Slot interval in whole minutes. Default `30`. Clamped to ≥ 1 internally.
146
+ * Use `60` for hourly slots, `15` for quarter-hour slots.
147
+ */
148
+ step = input(30, { ...(ngDevMode ? { debugName: "step" } : /* istanbul ignore next */ {}), transform: numberAttribute });
149
+ /**
150
+ * Finest time unit compared when determining if a slot is selected.
151
+ * Default `'minute'`. Use `'second'` when the value carries seconds.
152
+ */
153
+ granularity = input('minute', /* @ts-ignore */
154
+ ...(ngDevMode ? [{ debugName: "granularity" }] : /* istanbul ignore next */ []));
155
+ /**
156
+ * 12- or 24-hour cycle for slot label formatting. When `null` (default) it
157
+ * is derived from the runtime locale.
158
+ */
159
+ hourCycle = input(null, /* @ts-ignore */
160
+ ...(ngDevMode ? [{ debugName: "hourCycle" }] : /* istanbul ignore next */ []));
161
+ /**
162
+ * BCP 47 locale driving slot label formatting. Defaults to the runtime locale.
163
+ */
164
+ locale = input(null, /* @ts-ignore */
165
+ ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
166
+ /**
167
+ * Close the listbox after a slot is selected. Default `true`.
168
+ */
169
+ closeOnSelect = input(true, { ...(ngDevMode ? { debugName: "closeOnSelect" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
170
+ /**
171
+ * When `true`, the listbox mounts as a trapped / inert / scroll-locked modal
172
+ * surface instead of the default anchored popover. Read once when the content
173
+ * mounts.
174
+ */
175
+ modal = input(false, { ...(ngDevMode ? { debugName: "modal" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
176
+ /** When `true` (default), Escape, pointer-down outside, and focus outside close the listbox. */
177
+ dismissible = input(true, { ...(ngDevMode ? { debugName: "dismissible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
178
+ /** When `true` (default), focus returns to the trigger on close. */
179
+ returnFocus = input(true, { ...(ngDevMode ? { debugName: "returnFocus" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
180
+ /** Placeholder shown by `[forTimePickerValue]` when no time is selected. */
181
+ placeholder = input('', /* @ts-ignore */
182
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
183
+ /**
184
+ * `Intl.DateTimeFormat` options driving slot label formatting. When none of
185
+ * `hour` / `minute` / `second` are specified, sensible defaults are filled in
186
+ * automatically based on `granularity` and `hourCycle`.
187
+ */
188
+ formatOptions = input({}, /* @ts-ignore */
189
+ ...(ngDevMode ? [{ debugName: "formatOptions" }] : /* istanbul ignore next */ []));
190
+ /** Manual `aria-label` on `[forTimePickerContent]` when the trigger isn't a meaningful name. */
191
+ ariaLabel = input(null, /* @ts-ignore */
192
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
193
+ /** When `true` (default), keyboard navigation wraps at the ends of the option list. */
194
+ loop = input(true, { ...(ngDevMode ? { debugName: "loop" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
195
+ /** Orientation of the listbox for keyboard navigation. Default `'vertical'`. */
196
+ orientation = input('vertical', /* @ts-ignore */
197
+ ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
198
+ /**
199
+ * Side the listbox is anchored to. Defaults to `'bottom'`. Ignored in
200
+ * `modal` mode.
201
+ */
202
+ side = input('bottom', /* @ts-ignore */
203
+ ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
204
+ /** Alignment along the chosen `side`. Defaults to `'start'`. */
205
+ align = input('start', /* @ts-ignore */
206
+ ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
207
+ /**
208
+ * Gap (px) between trigger and listbox along the main axis. Default `4`.
209
+ * The default is read from `provideForTimePickerDefaults` for the surrounding
210
+ * scope.
211
+ */
212
+ sideOffset = input(this.#defaults.sideOffset, { ...(ngDevMode ? { debugName: "sideOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
213
+ /** Gap (px) along the cross axis. Default `0`. */
214
+ alignOffset = input(0, { ...(ngDevMode ? { debugName: "alignOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
215
+ /** When `true` (default), `flip` and `shift` keep the listbox inside the viewport. */
216
+ avoidCollisions = input(true, { ...(ngDevMode ? { debugName: "avoidCollisions" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
217
+ /**
218
+ * Padding (px) applied uniformly to flip / shift / size. Default `8`.
219
+ * The default is read from `provideForTimePickerDefaults` for the surrounding
220
+ * scope.
221
+ */
222
+ collisionPadding = input(this.#defaults.collisionPadding, { ...(ngDevMode ? { debugName: "collisionPadding" } : /* istanbul ignore next */ {}), transform: numberAttribute });
223
+ /** Padding (px) for the `arrow` middleware. Default `0`. */
224
+ arrowPadding = input(0, { ...(ngDevMode ? { debugName: "arrowPadding" } : /* istanbul ignore next */ {}), transform: numberAttribute });
225
+ /** Stickiness behaviour for `shift`. Default `'partial'`. */
226
+ sticky = input('partial', /* @ts-ignore */
227
+ ...(ngDevMode ? [{ debugName: "sticky" }] : /* istanbul ignore next */ []));
228
+ /** When `true`, sets `data-detached=""` while the trigger is scrolled off-screen. */
229
+ hideWhenDetached = input(false, { ...(ngDevMode ? { debugName: "hideWhenDetached" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
230
+ /**
231
+ * When `true` (default), the content is clipped until floating-ui resolves
232
+ * its first position, preventing a flash at the viewport corner.
233
+ */
234
+ clipUntilPositioned = input(true, { ...(ngDevMode ? { debugName: "clipUntilPositioned" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
235
+ /**
236
+ * Writing direction. When unset (default `null`), the inherited ambient
237
+ * direction is resolved from the nearest ancestor carrying a `dir` attribute
238
+ * (or `<html dir>`), defaulting to `'ltr'`. An explicit `[dir]` always wins.
239
+ */
240
+ _dirInput = input(null, { ...(ngDevMode ? { debugName: "_dirInput" } : /* istanbul ignore next */ {}), alias: 'dir' });
241
+ dir = injectTextDirection(this._dirInput);
242
+ /**
243
+ * Fires when the user presses Escape while this listbox is the topmost
244
+ * dismissable layer. Call `preventDefault()` on the veto to suppress the
245
+ * automatic close.
246
+ */
247
+ escapeKeyDown = output();
248
+ /** Fires when a pointer goes down outside the listbox. Vetoable. */
249
+ pointerDownOutside = output();
250
+ /** Fires when focus moves outside the listbox. Vetoable. */
251
+ focusOutside = output();
252
+ /** Composite event: shares veto state with `pointerDownOutside` / `focusOutside`. */
253
+ interactOutside = output();
254
+ /**
255
+ * Fires just before the listbox sends focus to the selected slot (or first
256
+ * enabled) on open. Call `preventDefault()` on the veto to skip the focus
257
+ * move.
258
+ */
259
+ autoFocusOnOpen = output();
260
+ /**
261
+ * Fires just before focus returns to the trigger on close. Call
262
+ * `preventDefault()` on the veto to suppress the return-focus.
263
+ */
264
+ autoFocusOnClose = output();
265
+ /**
266
+ * Shared overlay-listbox state machine: option collection, trigger / anchor /
267
+ * content registries + ids, DOM-focus navigation, the open / close machine,
268
+ * the initial-focus / close-reason state, and the dismiss / auto-focus emit
269
+ * forwarders. The value-specific behaviour (`isSelected`, `activate`,
270
+ * `focusSelectedOption`, `commitOnTab`) stays in this root.
271
+ */
272
+ #controller = new ListboxOverlayController(this.#idGen, {
273
+ idPrefix: 'for-time-picker',
274
+ multipleAnchorsError: '[forty-cdk/time-picker] Multiple [forTimePickerAnchor] inside the same [forTimePicker]; only one is allowed.',
275
+ defaultInitialFocus: 'selected',
276
+ effectiveDisabled: this.effectiveDisabled,
277
+ setOpen: (open) => this.open.set(open),
278
+ isOpen: () => this.open(),
279
+ emit: {
280
+ escapeKeyDown: this.escapeKeyDown,
281
+ pointerDownOutside: this.pointerDownOutside,
282
+ focusOutside: this.focusOutside,
283
+ interactOutside: this.interactOutside,
284
+ autoFocusOnOpen: this.autoFocusOnOpen,
285
+ autoFocusOnClose: this.autoFocusOnClose,
286
+ },
287
+ markTouched: () => this.markTouched(),
288
+ });
289
+ triggerId = this.#controller.triggerId;
290
+ contentId = this.#controller.contentId;
291
+ initialFocus = this.#controller.initialFocus;
292
+ lastCloseReason = this.#controller.lastCloseReason;
293
+ trigger = this.#controller.trigger;
294
+ /**
295
+ * Element floating-ui anchors the listbox against. Prefers an optional
296
+ * `[forTimePickerAnchor]` when registered, otherwise falls back to the
297
+ * trigger so existing pickers without an anchor keep their behavior.
298
+ * Decoupled from `trigger` so the trigger keeps driving `aria-controls`, the
299
+ * click toggle, focus return, and its dismissal exemption regardless of where
300
+ * the listbox paints.
301
+ */
302
+ anchor = this.#controller.anchor;
303
+ content = this.#controller.content;
304
+ options = this.#controller.options;
305
+ #sentinel = computed(() => timeSentinel(this.adapter), /* @ts-ignore */
306
+ ...(ngDevMode ? [{ debugName: "#sentinel" }] : /* istanbul ignore next */ []));
307
+ #effectiveFormatOptions = computed(() => {
308
+ const options = this.formatOptions();
309
+ if (options.hour !== undefined ||
310
+ options.minute !== undefined ||
311
+ options.second !== undefined) {
312
+ return options;
313
+ }
314
+ const cycle = this.hourCycle();
315
+ const granularity = this.granularity();
316
+ return {
317
+ ...options,
318
+ hour: 'numeric',
319
+ minute: '2-digit',
320
+ ...(granularity === 'second' ? { second: '2-digit' } : {}),
321
+ ...(cycle !== null ? { hour12: cycle === 12 } : {}),
322
+ };
323
+ }, /* @ts-ignore */
324
+ ...(ngDevMode ? [{ debugName: "#effectiveFormatOptions" }] : /* istanbul ignore next */ []));
325
+ /**
326
+ * The generated list of time slots for the full day. Each slot's `value` is
327
+ * anchored to the current `value()` date (or a sentinel), so selecting a
328
+ * slot preserves the calendar date when used inside a date-time picker.
329
+ *
330
+ * Pure derivation — never written from inside an `effect()`.
331
+ */
332
+ slots = computed(() => {
333
+ const anchor = this.value() ?? this.#sentinel();
334
+ return buildTimeSlots({
335
+ adapter: this.adapter,
336
+ anchor,
337
+ selected: this.value(),
338
+ minTime: this.minTime(),
339
+ maxTime: this.maxTime(),
340
+ step: this.step(),
341
+ granularity: this.granularity(),
342
+ formatOptions: this.#effectiveFormatOptions(),
343
+ });
344
+ }, /* @ts-ignore */
345
+ ...(ngDevMode ? [{ debugName: "slots" }] : /* istanbul ignore next */ []));
346
+ /** Formatted display of the current value, or `null` when empty. */
347
+ formattedValue = computed(() => {
348
+ const v = this.value();
349
+ return v === null ? null : this.adapter.format(v, this.#effectiveFormatOptions());
350
+ }, /* @ts-ignore */
351
+ ...(ngDevMode ? [{ debugName: "formattedValue" }] : /* istanbul ignore next */ []));
352
+ fieldLabelledElement() {
353
+ return this.trigger();
354
+ }
355
+ fieldLabelledElementId() {
356
+ return this.triggerId();
357
+ }
358
+ constructor() {
359
+ super();
360
+ injectHiddenInput({
361
+ name: this.name,
362
+ values: computed(() => {
363
+ const current = this.value();
364
+ if (current === null) {
365
+ return [];
366
+ }
367
+ return [serializeISOTime(this.adapter, current, this.granularity())];
368
+ }),
369
+ disabled: this.effectiveDisabled,
370
+ });
371
+ }
372
+ setInitialFocus(target) {
373
+ this.#controller.setInitialFocus(target);
374
+ }
375
+ registerTrigger(el) {
376
+ this.#controller.registerTrigger(el);
377
+ }
378
+ unregisterTrigger(el) {
379
+ this.#controller.unregisterTrigger(el);
380
+ }
381
+ registerAnchor(el) {
382
+ this.#controller.registerAnchor(el);
383
+ }
384
+ unregisterAnchor(el) {
385
+ this.#controller.unregisterAnchor(el);
386
+ }
387
+ registerContent(el) {
388
+ this.#controller.registerContent(el);
389
+ }
390
+ unregisterContent(el) {
391
+ this.#controller.unregisterContent(el);
392
+ }
393
+ registerOption(handle) {
394
+ this.#controller.registerOption(handle);
395
+ }
396
+ unregisterOption(handle) {
397
+ this.#controller.unregisterOption(handle);
398
+ }
399
+ #sameTimeOfDay(a, b) {
400
+ const g = this.granularity();
401
+ const secA = this.adapter.getHours(a) * 3600 +
402
+ (g !== 'hour' ? this.adapter.getMinutes(a) * 60 : 0) +
403
+ (g === 'second' ? this.adapter.getSeconds(a) : 0);
404
+ const secB = this.adapter.getHours(b) * 3600 +
405
+ (g !== 'hour' ? this.adapter.getMinutes(b) * 60 : 0) +
406
+ (g === 'second' ? this.adapter.getSeconds(b) : 0);
407
+ return secA === secB;
408
+ }
409
+ isSelected(v) {
410
+ const current = this.value();
411
+ if (current === null) {
412
+ return false;
413
+ }
414
+ return this.#sameTimeOfDay(v, current);
415
+ }
416
+ activate(v) {
417
+ if (this.effectiveDisabled() || this.readonly()) {
418
+ return;
419
+ }
420
+ this.value.set(v);
421
+ if (this.closeOnSelect()) {
422
+ this.closeMenu('select');
423
+ }
424
+ }
425
+ navigate(currentOption, action) {
426
+ this.#controller.navigate(currentOption, action, this.loop());
427
+ }
428
+ focusFirstEnabledOption() {
429
+ return this.#controller.focusFirstEnabledOption();
430
+ }
431
+ focusLastEnabledOption() {
432
+ return this.#controller.focusLastEnabledOption();
433
+ }
434
+ focusSelectedOption() {
435
+ const current = this.value();
436
+ if (current === null) {
437
+ return false;
438
+ }
439
+ const items = this.options();
440
+ const opt = items.find((o) => {
441
+ if (o.disabled()) {
442
+ return false;
443
+ }
444
+ const v = o.value();
445
+ return this.#sameTimeOfDay(v, current);
446
+ });
447
+ if (opt) {
448
+ opt.host.focus();
449
+ return true;
450
+ }
451
+ return false;
452
+ }
453
+ toggle(initialFocus = 'selected') {
454
+ this.#controller.toggle(initialFocus);
455
+ }
456
+ openMenu(initialFocus = 'selected') {
457
+ this.#controller.openMenu(initialFocus);
458
+ }
459
+ closeMenu(reason) {
460
+ this.#controller.closeMenu(reason);
461
+ }
462
+ commitOnTab(value) {
463
+ if (this.effectiveDisabled()) {
464
+ return;
465
+ }
466
+ if (!this.readonly()) {
467
+ this.value.set(value);
468
+ }
469
+ this.#controller.focusTrigger();
470
+ this.closeMenu('tab');
471
+ }
472
+ emitEscapeKeyDown(event) {
473
+ this.#controller.emitEscapeKeyDown(event, this.dismissible(), 'escape');
474
+ }
475
+ emitPointerDownOutside(veto) {
476
+ this.#controller.emitPointerDownOutside(veto);
477
+ }
478
+ emitFocusOutside(veto) {
479
+ this.#controller.emitFocusOutside(veto);
480
+ }
481
+ emitInteractOutside(veto) {
482
+ this.#controller.emitInteractOutside(veto);
483
+ }
484
+ forwardEscapeKeyDown(veto) {
485
+ this.#controller.forwardEscapeKeyDown(veto);
486
+ }
487
+ requestClose(reason) {
488
+ this.#controller.requestClose(reason);
489
+ }
490
+ emitAutoFocusOnOpen() {
491
+ return this.#controller.emitAutoFocusOnOpen();
492
+ }
493
+ emitAutoFocusOnClose() {
494
+ return this.#controller.emitAutoFocusOnClose();
495
+ }
496
+ markTouched() {
497
+ super.markTouched();
498
+ }
499
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForTimePicker, deps: [], target: i0.ɵɵFactoryTarget.Directive });
500
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: ForTimePicker, isStandalone: true, selector: "[forTimePicker]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, minTime: { classPropertyName: "minTime", publicName: "minTime", isSignal: true, isRequired: false, transformFunction: null }, maxTime: { classPropertyName: "maxTime", publicName: "maxTime", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, granularity: { classPropertyName: "granularity", publicName: "granularity", isSignal: true, isRequired: false, transformFunction: null }, hourCycle: { classPropertyName: "hourCycle", publicName: "hourCycle", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, closeOnSelect: { classPropertyName: "closeOnSelect", publicName: "closeOnSelect", isSignal: true, isRequired: false, transformFunction: null }, modal: { classPropertyName: "modal", publicName: "modal", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, returnFocus: { classPropertyName: "returnFocus", publicName: "returnFocus", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, formatOptions: { classPropertyName: "formatOptions", publicName: "formatOptions", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, loop: { classPropertyName: "loop", publicName: "loop", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, sideOffset: { classPropertyName: "sideOffset", publicName: "sideOffset", isSignal: true, isRequired: false, transformFunction: null }, alignOffset: { classPropertyName: "alignOffset", publicName: "alignOffset", isSignal: true, isRequired: false, transformFunction: null }, avoidCollisions: { classPropertyName: "avoidCollisions", publicName: "avoidCollisions", isSignal: true, isRequired: false, transformFunction: null }, collisionPadding: { classPropertyName: "collisionPadding", publicName: "collisionPadding", isSignal: true, isRequired: false, transformFunction: null }, arrowPadding: { classPropertyName: "arrowPadding", publicName: "arrowPadding", isSignal: true, isRequired: false, transformFunction: null }, sticky: { classPropertyName: "sticky", publicName: "sticky", isSignal: true, isRequired: false, transformFunction: null }, hideWhenDetached: { classPropertyName: "hideWhenDetached", publicName: "hideWhenDetached", isSignal: true, isRequired: false, transformFunction: null }, clipUntilPositioned: { classPropertyName: "clipUntilPositioned", publicName: "clipUntilPositioned", isSignal: true, isRequired: false, transformFunction: null }, _dirInput: { classPropertyName: "_dirInput", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", open: "openChange", escapeKeyDown: "escapeKeyDown", pointerDownOutside: "pointerDownOutside", focusOutside: "focusOutside", interactOutside: "interactOutside", autoFocusOnOpen: "autoFocusOnOpen", autoFocusOnClose: "autoFocusOnClose" }, host: { properties: { "attr.data-state": "open() ? \"open\" : \"closed\"", "attr.data-disabled": "effectiveDisabled() ? \"\" : null", "attr.dir": "dir()" } }, providers: [
501
+ { provide: FOR_TIME_PICKER_CONTEXT, useExisting: ForTimePicker },
502
+ { provide: FOR_TIME_VALUE_SOURCE, useExisting: ForTimePicker },
503
+ ], exportAs: ["forTimePicker"], usesInheritance: true, ngImport: i0 });
504
+ }
505
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForTimePicker, decorators: [{
506
+ type: Directive,
507
+ args: [{
508
+ selector: '[forTimePicker]',
509
+ exportAs: 'forTimePicker',
510
+ host: {
511
+ '[attr.data-state]': 'open() ? "open" : "closed"',
512
+ '[attr.data-disabled]': 'effectiveDisabled() ? "" : null',
513
+ '[attr.dir]': 'dir()',
514
+ },
515
+ providers: [
516
+ { provide: FOR_TIME_PICKER_CONTEXT, useExisting: ForTimePicker },
517
+ { provide: FOR_TIME_VALUE_SOURCE, useExisting: ForTimePicker },
518
+ ],
519
+ }]
520
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], minTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "minTime", required: false }] }], maxTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxTime", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], granularity: [{ type: i0.Input, args: [{ isSignal: true, alias: "granularity", required: false }] }], hourCycle: [{ type: i0.Input, args: [{ isSignal: true, alias: "hourCycle", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], closeOnSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnSelect", required: false }] }], modal: [{ type: i0.Input, args: [{ isSignal: true, alias: "modal", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], returnFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "returnFocus", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], formatOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatOptions", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], loop: [{ type: i0.Input, args: [{ isSignal: true, alias: "loop", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], sideOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "sideOffset", required: false }] }], alignOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "alignOffset", required: false }] }], avoidCollisions: [{ type: i0.Input, args: [{ isSignal: true, alias: "avoidCollisions", required: false }] }], collisionPadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "collisionPadding", required: false }] }], arrowPadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "arrowPadding", required: false }] }], sticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "sticky", required: false }] }], hideWhenDetached: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideWhenDetached", required: false }] }], clipUntilPositioned: [{ type: i0.Input, args: [{ isSignal: true, alias: "clipUntilPositioned", required: false }] }], _dirInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], escapeKeyDown: [{ type: i0.Output, args: ["escapeKeyDown"] }], pointerDownOutside: [{ type: i0.Output, args: ["pointerDownOutside"] }], focusOutside: [{ type: i0.Output, args: ["focusOutside"] }], interactOutside: [{ type: i0.Output, args: ["interactOutside"] }], autoFocusOnOpen: [{ type: i0.Output, args: ["autoFocusOnOpen"] }], autoFocusOnClose: [{ type: i0.Output, args: ["autoFocusOnClose"] }] } });
521
+
522
+ /**
523
+ * Optional positioning anchor. When present, `[forTimePickerContent]` is
524
+ * positioned against this element instead of `[forTimePickerTrigger]` — useful
525
+ * when the trigger lives inside a decorated field box (padding, prefix icon,
526
+ * clear / chevron buttons) and the listbox should align to the visible field
527
+ * rather than the inner button.
528
+ *
529
+ * Only positioning changes: the trigger still owns `aria-controls`,
530
+ * `aria-expanded`, the click toggle, focus return on close, and its exemption
531
+ * from outside-pointer dismissal. If no anchor is registered the listbox falls
532
+ * back to anchoring against the trigger, so existing usages are unaffected.
533
+ *
534
+ * At most one `[forTimePickerAnchor]` may be registered per `[forTimePicker]`;
535
+ * a second one throws.
536
+ *
537
+ * ```html
538
+ * <div forTimePicker [(value)]="time">
539
+ * <div forTimePickerAnchor class="field-box">
540
+ * <icon />
541
+ * <button forTimePickerTrigger><span forTimePickerValue>…</span></button>
542
+ * <button class="clear">×</button>
543
+ * </div>
544
+ * @if (open()) {
545
+ * <div forTimePickerContent>…</div>
546
+ * }
547
+ * </div>
548
+ * ```
549
+ */
550
+ class ForTimePickerAnchor {
551
+ #ctx = injectTimePickerContext('ForTimePickerAnchor');
552
+ #host = inject(ElementRef);
553
+ constructor() {
554
+ registerHandle(this.#host.nativeElement, (el) => this.#ctx.registerAnchor(el), (el) => this.#ctx.unregisterAnchor(el));
555
+ }
556
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForTimePickerAnchor, deps: [], target: i0.ɵɵFactoryTarget.Directive });
557
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.2", type: ForTimePickerAnchor, isStandalone: true, selector: "[forTimePickerAnchor]", exportAs: ["forTimePickerAnchor"], ngImport: i0 });
558
+ }
559
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForTimePickerAnchor, decorators: [{
560
+ type: Directive,
561
+ args: [{
562
+ selector: '[forTimePickerAnchor]',
563
+ exportAs: 'forTimePickerAnchor',
564
+ }]
565
+ }], ctorParameters: () => [] });
566
+
567
+ /**
568
+ * Combobox button that opens the time picker listbox. Apply on a `<button>` so
569
+ * Space / Enter dispatch native click events that toggle via `(click)`.
570
+ *
571
+ * Wires APG select-only combobox attributes: `role="combobox"`,
572
+ * `aria-haspopup="listbox"`, `aria-expanded`, and `aria-controls` pointing to
573
+ * the listbox. The button is exempt from the listbox's dismissable layer so
574
+ * clicks on it toggle without dismissal racing.
575
+ *
576
+ * Keyboard:
577
+ * - **Click / Enter / Space** — toggle (open focuses the selected slot, or first).
578
+ * - **ArrowDown** — open + focus selected slot (or first).
579
+ * - **ArrowUp** — open + focus selected slot (or last when none selected).
580
+ */
581
+ class ForTimePickerTrigger {
582
+ #host = inject(ElementRef);
583
+ /**
584
+ * Optional explicit reference to the `[forTimePicker]` root, named after the
585
+ * selector `routerLink`-style. The bare valueless attribute keeps resolving
586
+ * the enclosing root via DI; pass the root explicitly
587
+ * (`[forTimePickerTrigger]="root"`, with `#root="forTimePicker"`) when the
588
+ * trigger is declared in an `ng-template` stamped inside the root.
589
+ */
590
+ forTimePickerTrigger = input('', /* @ts-ignore */
591
+ ...(ngDevMode ? [{ debugName: "forTimePickerTrigger" }] : /* istanbul ignore next */ []));
592
+ ctx = injectTimePickerTriggerContext(this.forTimePickerTrigger);
593
+ constructor() {
594
+ const el = this.#host.nativeElement;
595
+ effect((onCleanup) => {
596
+ const ctx = this.ctx();
597
+ ctx.registerTrigger(el);
598
+ onCleanup(() => ctx.unregisterTrigger(el));
599
+ });
600
+ reflectDisabled(computed(() => this.ctx().effectiveDisabled()));
601
+ }
602
+ onClick() {
603
+ this.ctx().toggle('selected');
604
+ }
605
+ onKeyDown(event) {
606
+ if (this.ctx().effectiveDisabled()) {
607
+ return;
608
+ }
609
+ if (event.key === 'ArrowDown') {
610
+ event.preventDefault();
611
+ this.ctx().openMenu('selected');
612
+ return;
613
+ }
614
+ if (event.key === 'ArrowUp') {
615
+ event.preventDefault();
616
+ this.ctx().openMenu(this.ctx().value() !== null ? 'selected' : 'last');
617
+ }
618
+ }
619
+ onFocusOut(event) {
620
+ const next = event.relatedTarget;
621
+ if (next) {
622
+ const content = this.ctx().content();
623
+ if (content && content.contains(next)) {
624
+ return;
625
+ }
626
+ if (this.#host.nativeElement.contains(next)) {
627
+ return;
628
+ }
629
+ }
630
+ this.ctx().markTouched();
631
+ }
632
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForTimePickerTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive });
633
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: ForTimePickerTrigger, isStandalone: true, selector: "[forTimePickerTrigger]", inputs: { forTimePickerTrigger: { classPropertyName: "forTimePickerTrigger", publicName: "forTimePickerTrigger", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "type": "button", "role": "combobox" }, listeners: { "click": "onClick()", "keydown": "onKeyDown($event)", "focusout": "onFocusOut($event)" }, properties: { "id": "ctx().triggerId()", "attr.aria-haspopup": "\"listbox\"", "attr.aria-expanded": "ctx().open() ? \"true\" : \"false\"", "attr.aria-controls": "ctx().open() ? ctx().contentId() : null", "attr.aria-disabled": "ctx().effectiveDisabled() ? \"true\" : null", "attr.aria-readonly": "ctx().readonly() ? \"true\" : null", "attr.aria-required": "ctx().required() ? \"true\" : null", "attr.aria-invalid": "ctx().invalid() ? \"true\" : null", "attr.aria-busy": "ctx().pending() ? \"true\" : null", "attr.data-state": "ctx().open() ? \"open\" : \"closed\"", "attr.data-disabled": "ctx().effectiveDisabled() ? \"\" : null" } }, exportAs: ["forTimePickerTrigger"], ngImport: i0 });
634
+ }
635
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForTimePickerTrigger, decorators: [{
636
+ type: Directive,
637
+ args: [{
638
+ selector: '[forTimePickerTrigger]',
639
+ exportAs: 'forTimePickerTrigger',
640
+ host: {
641
+ type: 'button',
642
+ role: 'combobox',
643
+ '[id]': 'ctx().triggerId()',
644
+ '[attr.aria-haspopup]': '"listbox"',
645
+ '[attr.aria-expanded]': 'ctx().open() ? "true" : "false"',
646
+ '[attr.aria-controls]': 'ctx().open() ? ctx().contentId() : null',
647
+ '[attr.aria-disabled]': 'ctx().effectiveDisabled() ? "true" : null',
648
+ '[attr.aria-readonly]': 'ctx().readonly() ? "true" : null',
649
+ '[attr.aria-required]': 'ctx().required() ? "true" : null',
650
+ '[attr.aria-invalid]': 'ctx().invalid() ? "true" : null',
651
+ '[attr.aria-busy]': 'ctx().pending() ? "true" : null',
652
+ '[attr.data-state]': 'ctx().open() ? "open" : "closed"',
653
+ '[attr.data-disabled]': 'ctx().effectiveDisabled() ? "" : null',
654
+ '(click)': 'onClick()',
655
+ '(keydown)': 'onKeyDown($event)',
656
+ '(focusout)': 'onFocusOut($event)',
657
+ },
658
+ }]
659
+ }], ctorParameters: () => [], propDecorators: { forTimePickerTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "forTimePickerTrigger", required: false }] }] } });
660
+
661
+ /**
662
+ * Renders the currently selected time slot's label — or the configured
663
+ * placeholder when nothing is selected — into its host element via
664
+ * `textContent`. Apply on a `<span>` (or any inline element) inside
665
+ * `[forTimePickerTrigger]`:
666
+ *
667
+ * ```html
668
+ * <button forTimePickerTrigger>
669
+ * <span forTimePickerValue placeholder="Select a time…"></span>
670
+ * </button>
671
+ * ```
672
+ */
673
+ class ForTimePickerValue {
674
+ #ctx = injectTimePickerContext('ForTimePickerValue');
675
+ /** Text shown when nothing is selected. Falls back to `[forTimePicker][placeholder]`. */
676
+ placeholder = input('', /* @ts-ignore */
677
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
678
+ isPlaceholder = computed(() => this.#ctx.value() === null, /* @ts-ignore */
679
+ ...(ngDevMode ? [{ debugName: "isPlaceholder" }] : /* istanbul ignore next */ []));
680
+ displayText = computed(() => this.#ctx.formattedValue() ?? (this.placeholder() || this.#ctx.placeholder()), /* @ts-ignore */
681
+ ...(ngDevMode ? [{ debugName: "displayText" }] : /* istanbul ignore next */ []));
682
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForTimePickerValue, deps: [], target: i0.ɵɵFactoryTarget.Directive });
683
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: ForTimePickerValue, isStandalone: true, selector: "[forTimePickerValue]", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "textContent": "displayText()", "attr.data-placeholder": "isPlaceholder() ? \"\" : null" } }, exportAs: ["forTimePickerValue"], ngImport: i0 });
684
+ }
685
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForTimePickerValue, decorators: [{
686
+ type: Directive,
687
+ args: [{
688
+ selector: '[forTimePickerValue]',
689
+ exportAs: 'forTimePickerValue',
690
+ host: {
691
+ '[textContent]': 'displayText()',
692
+ '[attr.data-placeholder]': 'isPlaceholder() ? "" : null',
693
+ },
694
+ }]
695
+ }], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }] } });
696
+
697
+ /**
698
+ * The listbox surface of the time picker. Carries `role="listbox"`, is
699
+ * portaled to `document.body`, and is positioned by `@floating-ui/dom`
700
+ * against the trigger.
701
+ *
702
+ * Mount/unmount of the visible content is the consumer's responsibility —
703
+ * wrap with `@if (open())` so `animate.enter` / `animate.leave` fire on the
704
+ * natural mount cycle. While mounted, a `DismissableLayer` activates (Escape,
705
+ * pointer-down outside, focus outside); the trigger element is exempt from
706
+ * outside-pointer checks so trigger clicks toggle without dismissal racing.
707
+ *
708
+ * Initial focus is sent to the selected slot (`'selected'`), the first
709
+ * enabled slot (`'first'`), or the last enabled slot (`'last'`) according to
710
+ * the trigger's hint. On destroy, focus returns to the trigger when
711
+ * `returnFocus` is true.
712
+ */
713
+ class ForTimePickerContent {
714
+ ctx = injectTimePickerContext('ForTimePickerContent');
715
+ #host = inject(ElementRef);
716
+ constructor() {
717
+ const ctx = this.ctx;
718
+ registerHandle(this.#host.nativeElement, (el) => ctx.registerContent(el), (el) => ctx.unregisterContent(el));
719
+ const focusInitial = () => {
720
+ const target = ctx.initialFocus();
721
+ if (target === 'selected') {
722
+ return ctx.focusSelectedOption() || ctx.focusFirstEnabledOption();
723
+ }
724
+ if (target === 'last') {
725
+ return ctx.focusLastEnabledOption();
726
+ }
727
+ return ctx.focusFirstEnabledOption();
728
+ };
729
+ if (ctx.modal()) {
730
+ injectModalShell({
731
+ modal: ctx.modal,
732
+ returnFocus: ctx.returnFocus,
733
+ initialFocus: {
734
+ move: focusInitial,
735
+ veto: () => ctx.emitAutoFocusOnOpen(),
736
+ },
737
+ autoFocusOnClose: () => (event) => {
738
+ if (ctx.emitAutoFocusOnClose()) {
739
+ event.preventDefault();
740
+ }
741
+ },
742
+ dismiss: {
743
+ dismissible: ctx.dismissible,
744
+ requestClose: (reason) => {
745
+ ctx.markTouched();
746
+ ctx.closeMenu(reason);
747
+ },
748
+ emitEscapeKeyDown: (veto) => ctx.forwardEscapeKeyDown(veto),
749
+ emitPointerDownOutside: (veto) => ctx.emitPointerDownOutside(veto),
750
+ emitFocusOutside: (veto) => ctx.emitFocusOutside(veto),
751
+ emitInteractOutside: (veto) => ctx.emitInteractOutside(veto),
752
+ },
753
+ });
754
+ return;
755
+ }
756
+ injectOverlayShell({
757
+ positioner: {
758
+ kind: 'floating',
759
+ reference: ctx.anchor,
760
+ open: ctx.open,
761
+ side: ctx.side,
762
+ align: ctx.align,
763
+ sideOffset: ctx.sideOffset,
764
+ alignOffset: ctx.alignOffset,
765
+ avoidCollisions: ctx.avoidCollisions,
766
+ collisionPadding: ctx.collisionPadding,
767
+ arrowPadding: ctx.arrowPadding,
768
+ sticky: ctx.sticky,
769
+ hideWhenDetached: ctx.hideWhenDetached,
770
+ clipUntilPositioned: ctx.clipUntilPositioned,
771
+ },
772
+ dismiss: {
773
+ dismissible: ctx.dismissible,
774
+ requestClose: (reason) => {
775
+ ctx.markTouched();
776
+ ctx.closeMenu(reason);
777
+ },
778
+ emitEscapeKeyDown: (event) => ctx.emitEscapeKeyDown(event),
779
+ emitPointerDownOutside: (veto) => ctx.emitPointerDownOutside(veto),
780
+ emitFocusOutside: (veto) => ctx.emitFocusOutside(veto),
781
+ emitInteractOutside: (veto) => ctx.emitInteractOutside(veto),
782
+ exemptElements: () => {
783
+ const t = ctx.trigger();
784
+ return t ? [t] : [];
785
+ },
786
+ },
787
+ initialFocus: {
788
+ move: focusInitial,
789
+ veto: () => ctx.emitAutoFocusOnOpen(),
790
+ },
791
+ returnFocus: {
792
+ enabled: ctx.returnFocus,
793
+ target: () => ctx.trigger(),
794
+ veto: () => ctx.emitAutoFocusOnClose(),
795
+ skip: () => ctx.lastCloseReason() === 'tab',
796
+ },
797
+ });
798
+ }
799
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForTimePickerContent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
800
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.2", type: ForTimePickerContent, isStandalone: true, selector: "[forTimePickerContent]", host: { attributes: { "role": "listbox", "tabindex": "-1" }, properties: { "id": "ctx.contentId()", "attr.aria-labelledby": "ctx.ariaLabel() ? null : ctx.triggerId()", "attr.aria-label": "ctx.ariaLabel()", "attr.aria-modal": "ctx.modal() ? \"true\" : null", "attr.aria-orientation": "ctx.orientation()", "attr.data-state": "ctx.open() ? \"open\" : \"closed\"", "attr.data-orientation": "ctx.orientation()" } }, exportAs: ["forTimePickerContent"], ngImport: i0 });
801
+ }
802
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForTimePickerContent, decorators: [{
803
+ type: Directive,
804
+ args: [{
805
+ selector: '[forTimePickerContent]',
806
+ exportAs: 'forTimePickerContent',
807
+ host: {
808
+ role: 'listbox',
809
+ tabindex: '-1',
810
+ '[id]': 'ctx.contentId()',
811
+ '[attr.aria-labelledby]': 'ctx.ariaLabel() ? null : ctx.triggerId()',
812
+ '[attr.aria-label]': 'ctx.ariaLabel()',
813
+ '[attr.aria-modal]': 'ctx.modal() ? "true" : null',
814
+ '[attr.aria-orientation]': 'ctx.orientation()',
815
+ '[attr.data-state]': 'ctx.open() ? "open" : "closed"',
816
+ '[attr.data-orientation]': 'ctx.orientation()',
817
+ },
818
+ }]
819
+ }], ctorParameters: () => [] });
820
+
821
+ /**
822
+ * One option inside a `[forTimePickerContent]`. Apply on a `<div>` (or any
823
+ * non-button element) — the option handles Enter/Space activation itself in its
824
+ * keydown handler because a `<div>` has no native keyboard click.
825
+ *
826
+ * @typeParam D The adapter's date-time type (inferred from `[value]`).
827
+ *
828
+ * Keyboard while focused:
829
+ * - **Enter / Space** — activate (select the slot).
830
+ * - **ArrowDown / ArrowUp / Home / End** — move focus inside the listbox.
831
+ * - **Tab / Shift+Tab** — commit the focused slot and let the browser advance
832
+ * focus to the next / previous focusable.
833
+ * - **Escape** — routed through the content's keydown to close the listbox.
834
+ */
835
+ class ForTimePickerOption {
836
+ #ctx = injectTimePickerContext('ForTimePickerOption');
837
+ #host = inject(ElementRef);
838
+ /**
839
+ * The date-time value this option represents. Provided by the parent
840
+ * `[forTimePicker]`'s `slots()` computed.
841
+ */
842
+ value = input.required(/* @ts-ignore */
843
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
844
+ /** When `true`, this option cannot be selected. */
845
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
846
+ id = hostId('for-time-picker-option');
847
+ selected = computed(() => this.#ctx.value() !== null && this.#ctx.isSelected(this.value()), /* @ts-ignore */
848
+ ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
849
+ effectiveDisabled = computed(() => this.disabled() || this.#ctx.effectiveDisabled(), /* @ts-ignore */
850
+ ...(ngDevMode ? [{ debugName: "effectiveDisabled" }] : /* istanbul ignore next */ []));
851
+ #highlighted = signal(false, /* @ts-ignore */
852
+ ...(ngDevMode ? [{ debugName: "#highlighted" }] : /* istanbul ignore next */ []));
853
+ /** True while this option has DOM focus. Reflected as `data-highlighted`. */
854
+ highlighted = this.#highlighted.asReadonly();
855
+ constructor() {
856
+ const handle = {
857
+ host: this.#host.nativeElement,
858
+ value: this.value,
859
+ disabled: this.effectiveDisabled,
860
+ };
861
+ registerHandle(handle, (h) => this.#ctx.registerOption(h), (h) => this.#ctx.unregisterOption(h));
862
+ }
863
+ onClick() {
864
+ if (this.effectiveDisabled() || this.#ctx.readonly()) {
865
+ return;
866
+ }
867
+ this.#ctx.activate(this.value());
868
+ }
869
+ onFocus() {
870
+ this.#highlighted.set(true);
871
+ this.#host.nativeElement.scrollIntoView?.({ block: 'nearest' });
872
+ }
873
+ onBlur() {
874
+ this.#highlighted.set(false);
875
+ }
876
+ onKeyDown(event) {
877
+ if (this.effectiveDisabled()) {
878
+ return;
879
+ }
880
+ if (event.key === 'Enter' || event.key === ' ') {
881
+ event.preventDefault();
882
+ this.#ctx.activate(this.value());
883
+ return;
884
+ }
885
+ if (event.key === 'Tab') {
886
+ if (this.#ctx.modal()) {
887
+ return;
888
+ }
889
+ this.#ctx.commitOnTab(this.value());
890
+ return;
891
+ }
892
+ const action = resolveListNavigation(event, {
893
+ orientation: this.#ctx.orientation(),
894
+ dir: this.#ctx.dir(),
895
+ });
896
+ if (action) {
897
+ event.preventDefault();
898
+ this.#ctx.navigate(this.#host.nativeElement, action);
899
+ }
900
+ }
901
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForTimePickerOption, deps: [], target: i0.ɵɵFactoryTarget.Directive });
902
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: ForTimePickerOption, isStandalone: true, selector: "[forTimePickerOption]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "option", "tabindex": "-1" }, listeners: { "click": "onClick()", "keydown": "onKeyDown($event)", "focus": "onFocus()", "blur": "onBlur()" }, properties: { "id": "id()", "attr.aria-selected": "selected() ? \"true\" : \"false\"", "attr.aria-disabled": "effectiveDisabled() ? \"true\" : null", "attr.data-state": "selected() ? \"checked\" : \"unchecked\"", "attr.data-disabled": "effectiveDisabled() ? \"\" : null", "attr.data-highlighted": "highlighted() ? \"\" : null" } }, exportAs: ["forTimePickerOption"], ngImport: i0 });
903
+ }
904
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForTimePickerOption, decorators: [{
905
+ type: Directive,
906
+ args: [{
907
+ selector: '[forTimePickerOption]',
908
+ exportAs: 'forTimePickerOption',
909
+ host: {
910
+ role: 'option',
911
+ tabindex: '-1',
912
+ '[id]': 'id()',
913
+ '[attr.aria-selected]': 'selected() ? "true" : "false"',
914
+ '[attr.aria-disabled]': 'effectiveDisabled() ? "true" : null',
915
+ '[attr.data-state]': 'selected() ? "checked" : "unchecked"',
916
+ '[attr.data-disabled]': 'effectiveDisabled() ? "" : null',
917
+ '[attr.data-highlighted]': 'highlighted() ? "" : null',
918
+ '(click)': 'onClick()',
919
+ '(keydown)': 'onKeyDown($event)',
920
+ '(focus)': 'onFocus()',
921
+ '(blur)': 'onBlur()',
922
+ },
923
+ }]
924
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
925
+
926
+ /**
927
+ * Exact public names of every `ForTimePicker` input, its models included.
928
+ * Spread it into the `inputs` array of a `hostDirectives` entry so a wrapper
929
+ * component re-exposes the primitive's full surface — the Signal Forms members
930
+ * `[formField]` binds among them — without hand-maintaining the list. Always
931
+ * spread into an inline object literal so the entry is statically analyzable.
932
+ * An anti-drift spec fails when this list no longer matches the directive's
933
+ * actual API.
934
+ *
935
+ * @example
936
+ * ```ts
937
+ * @Component({
938
+ * selector: 'div[myTimePicker]',
939
+ * template: '',
940
+ * hostDirectives: [
941
+ * {
942
+ * directive: ForTimePicker,
943
+ * inputs: [...FOR_TIME_PICKER_HOST_DIRECTIVE_INPUTS],
944
+ * outputs: [...FOR_TIME_PICKER_HOST_DIRECTIVE_OUTPUTS],
945
+ * },
946
+ * ],
947
+ * })
948
+ * export class MyTimePicker {}
949
+ * ```
950
+ */
951
+ const FOR_TIME_PICKER_HOST_DIRECTIVE_INPUTS = [
952
+ 'value',
953
+ 'open',
954
+ 'align',
955
+ 'alignOffset',
956
+ 'ariaLabel',
957
+ 'arrowPadding',
958
+ 'avoidCollisions',
959
+ 'clipUntilPositioned',
960
+ 'closeOnSelect',
961
+ 'collisionPadding',
962
+ 'dir',
963
+ 'dirty',
964
+ 'disabled',
965
+ 'dismissible',
966
+ 'errors',
967
+ 'formatOptions',
968
+ 'granularity',
969
+ 'hideWhenDetached',
970
+ 'hourCycle',
971
+ 'invalid',
972
+ 'locale',
973
+ 'loop',
974
+ 'maxTime',
975
+ 'minTime',
976
+ 'modal',
977
+ 'name',
978
+ 'orientation',
979
+ 'pending',
980
+ 'placeholder',
981
+ 'readonly',
982
+ 'required',
983
+ 'returnFocus',
984
+ 'side',
985
+ 'sideOffset',
986
+ 'step',
987
+ 'sticky',
988
+ 'touched',
989
+ ];
990
+ /**
991
+ * Exact public names of every `ForTimePicker` output, the Signal Forms `touch`
992
+ * output included. Spread it into the `outputs` array of the same
993
+ * `hostDirectives` entry as {@link FOR_TIME_PICKER_HOST_DIRECTIVE_INPUTS}.
994
+ */
995
+ const FOR_TIME_PICKER_HOST_DIRECTIVE_OUTPUTS = [
996
+ 'valueChange',
997
+ 'openChange',
998
+ 'escapeKeyDown',
999
+ 'pointerDownOutside',
1000
+ 'focusOutside',
1001
+ 'interactOutside',
1002
+ 'autoFocusOnOpen',
1003
+ 'autoFocusOnClose',
1004
+ 'touchedChange',
1005
+ 'touch',
1006
+ ];
1007
+
1008
+ /**
1009
+ * Generated bundle index. Do not edit.
1010
+ */
1011
+
1012
+ export { FOR_TIME_PICKER_CONTEXT, FOR_TIME_PICKER_DEFAULTS, FOR_TIME_PICKER_HOST_DIRECTIVE_INPUTS, FOR_TIME_PICKER_HOST_DIRECTIVE_OUTPUTS, ForTimePicker, ForTimePickerAnchor, ForTimePickerContent, ForTimePickerOption, ForTimePickerTrigger, ForTimePickerValue, buildTimeSlots, provideForTimePickerDefaults };
1013
+ //# sourceMappingURL=forty-cdk-time-picker.mjs.map