@frame-ui-ng/components 0.2.0-beta.0 → 0.4.0-beta.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 (71) hide show
  1. package/button/src/styles/button.css +20 -4
  2. package/button-group/src/styles/button-group.css +6 -0
  3. package/dropdown-menu/src/styles/_vars.css +1 -1
  4. package/dropdown-menu/src/styles/dropdown-menu-item.css +87 -87
  5. package/fesm2022/frame-ui-ng-components-calendar.mjs +369 -263
  6. package/fesm2022/frame-ui-ng-components-calendar.mjs.map +1 -1
  7. package/fesm2022/frame-ui-ng-components-combobox.mjs +48 -51
  8. package/fesm2022/frame-ui-ng-components-combobox.mjs.map +1 -1
  9. package/fesm2022/frame-ui-ng-components-command.mjs +1 -1
  10. package/fesm2022/frame-ui-ng-components-command.mjs.map +1 -1
  11. package/fesm2022/frame-ui-ng-components-confirm-modal.mjs +162 -0
  12. package/fesm2022/frame-ui-ng-components-confirm-modal.mjs.map +1 -0
  13. package/fesm2022/frame-ui-ng-components-date-picker.mjs +232 -226
  14. package/fesm2022/frame-ui-ng-components-date-picker.mjs.map +1 -1
  15. package/fesm2022/frame-ui-ng-components-dropdown-menu.mjs +45 -22
  16. package/fesm2022/frame-ui-ng-components-dropdown-menu.mjs.map +1 -1
  17. package/fesm2022/frame-ui-ng-components-input-otp.mjs +64 -69
  18. package/fesm2022/frame-ui-ng-components-input-otp.mjs.map +1 -1
  19. package/fesm2022/frame-ui-ng-components-input.mjs +6 -3
  20. package/fesm2022/frame-ui-ng-components-input.mjs.map +1 -1
  21. package/fesm2022/frame-ui-ng-components-modal.mjs +93 -15
  22. package/fesm2022/frame-ui-ng-components-modal.mjs.map +1 -1
  23. package/fesm2022/frame-ui-ng-components-pagination.mjs +37 -36
  24. package/fesm2022/frame-ui-ng-components-pagination.mjs.map +1 -1
  25. package/fesm2022/frame-ui-ng-components-progress.mjs +2 -1
  26. package/fesm2022/frame-ui-ng-components-progress.mjs.map +1 -1
  27. package/fesm2022/frame-ui-ng-components-resizable.mjs +16 -26
  28. package/fesm2022/frame-ui-ng-components-resizable.mjs.map +1 -1
  29. package/fesm2022/frame-ui-ng-components-select.mjs +6 -3
  30. package/fesm2022/frame-ui-ng-components-select.mjs.map +1 -1
  31. package/fesm2022/frame-ui-ng-components-sheet.mjs +19 -16
  32. package/fesm2022/frame-ui-ng-components-sheet.mjs.map +1 -1
  33. package/fesm2022/frame-ui-ng-components-sidebar.mjs +59 -10
  34. package/fesm2022/frame-ui-ng-components-sidebar.mjs.map +1 -1
  35. package/fesm2022/frame-ui-ng-components-slider.mjs +53 -59
  36. package/fesm2022/frame-ui-ng-components-slider.mjs.map +1 -1
  37. package/fesm2022/frame-ui-ng-components-tooltip.mjs +307 -254
  38. package/fesm2022/frame-ui-ng-components-tooltip.mjs.map +1 -1
  39. package/fesm2022/frame-ui-ng-components-utils.mjs +20 -0
  40. package/fesm2022/frame-ui-ng-components-utils.mjs.map +1 -0
  41. package/fesm2022/frame-ui-ng-components-virtual-scroll.mjs +10 -12
  42. package/fesm2022/frame-ui-ng-components-virtual-scroll.mjs.map +1 -1
  43. package/fesm2022/frame-ui-ng-components.mjs +1047 -806
  44. package/fesm2022/frame-ui-ng-components.mjs.map +1 -1
  45. package/input/src/styles/input-group.css +50 -0
  46. package/item/src/styles/item.css +188 -187
  47. package/modal/src/styles/modal.css +10 -1
  48. package/package.json +10 -2
  49. package/select/src/styles/select-trigger.css +7 -36
  50. package/sidebar/src/styles/sidebar.css +10 -4
  51. package/src/styles/blueprint.css +102 -11
  52. package/src/styles/components.css +4 -4
  53. package/styles/blueprint.css +102 -11
  54. package/styles/components.css +4 -4
  55. package/styles.css +4 -4
  56. package/tooltip/src/styles/tooltip.css +7 -13
  57. package/types/frame-ui-ng-components-calendar.d.ts +14 -0
  58. package/types/frame-ui-ng-components-combobox.d.ts +1 -1
  59. package/types/frame-ui-ng-components-confirm-modal.d.ts +48 -0
  60. package/types/frame-ui-ng-components-context-menu.d.ts +2 -2
  61. package/types/frame-ui-ng-components-date-picker.d.ts +3 -1
  62. package/types/frame-ui-ng-components-dropdown-menu.d.ts +3 -3
  63. package/types/frame-ui-ng-components-input-otp.d.ts +1 -1
  64. package/types/frame-ui-ng-components-input.d.ts +6 -3
  65. package/types/frame-ui-ng-components-modal.d.ts +18 -7
  66. package/types/frame-ui-ng-components-select.d.ts +6 -3
  67. package/types/frame-ui-ng-components-sheet.d.ts +2 -0
  68. package/types/frame-ui-ng-components-sidebar.d.ts +8 -1
  69. package/types/frame-ui-ng-components-tooltip.d.ts +48 -73
  70. package/types/frame-ui-ng-components-utils.d.ts +5 -0
  71. package/types/frame-ui-ng-components.d.ts +87 -45
@@ -1,6 +1,6 @@
1
1
  import { NgTemplateOutlet } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { forwardRef, input, booleanAttribute, output, signal, computed, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
3
+ import { forwardRef, input, booleanAttribute, output, signal, inject, ElementRef, computed, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
4
4
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
5
5
 
6
6
  const VALUE_ACCESSOR = {
@@ -35,9 +35,11 @@ class FrCalendar {
35
35
  selected = input(undefined, ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
36
36
  selectedChange = output();
37
37
  monthChange = output();
38
+ focusedDate = signal(null, ...(ngDevMode ? [{ debugName: "focusedDate" }] : /* istanbul ignore next */ []));
38
39
  navigatedMonth = signal(null, ...(ngDevMode ? [{ debugName: "navigatedMonth" }] : /* istanbul ignore next */ []));
39
40
  internalValue = signal(null, ...(ngDevMode ? [{ debugName: "internalValue" }] : /* istanbul ignore next */ []));
40
41
  cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : /* istanbul ignore next */ []));
42
+ host = inject((ElementRef));
41
43
  currentMonth = computed(() => startOfMonth(this.navigatedMonth() ?? this.month() ?? new Date()), ...(ngDevMode ? [{ debugName: "currentMonth" }] : /* istanbul ignore next */ []));
42
44
  isDisabled = computed(() => this.disabled() || this.cvaDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
43
45
  value = computed(() => {
@@ -54,6 +56,7 @@ class FrCalendar {
54
56
  })), ...(ngDevMode ? [{ debugName: "monthOptions" }] : /* istanbul ignore next */ []));
55
57
  yearOptions = computed(() => Array.from({ length: Math.max(0, this.toYear() - this.fromYear() + 1) }, (_, index) => this.fromYear() + index), ...(ngDevMode ? [{ debugName: "yearOptions" }] : /* istanbul ignore next */ []));
56
58
  months = computed(() => Array.from({ length: Math.max(1, this.numberOfMonths()) }, (_, index) => this.buildMonth(addMonths(this.currentMonth(), index))), ...(ngDevMode ? [{ debugName: "months" }] : /* istanbul ignore next */ []));
59
+ activeDate = computed(() => this.resolveActiveDate(), ...(ngDevMode ? [{ debugName: "activeDate" }] : /* istanbul ignore next */ []));
57
60
  onTouched = () => undefined;
58
61
  onChange = () => undefined;
59
62
  writeValue(value) {
@@ -98,6 +101,25 @@ class FrCalendar {
98
101
  this.onChange(nextValue);
99
102
  this.selectedChange.emit(nextValue);
100
103
  }
104
+ handleDayKeydown(event, day) {
105
+ const offset = this.navigationOffset(event.key);
106
+ if (offset === null || this.isDisabled()) {
107
+ return;
108
+ }
109
+ event.preventDefault();
110
+ const next = addDays(day.date, offset);
111
+ this.focusedDate.set(next);
112
+ if (!this.isDateVisible(next)) {
113
+ this.updateMonth(startOfMonth(next));
114
+ }
115
+ this.focusDay(next);
116
+ }
117
+ dayTabIndex(day) {
118
+ return sameDate(day.date, this.activeDate()) ? 0 : -1;
119
+ }
120
+ focusActiveDate() {
121
+ this.focusDay(this.activeDate());
122
+ }
101
123
  monthLabel(date) {
102
124
  return new Intl.DateTimeFormat(this.locale(), {
103
125
  month: 'long',
@@ -114,6 +136,78 @@ class FrCalendar {
114
136
  weekNumber(date) {
115
137
  return isoWeekNumber(date).toString().padStart(2, '0');
116
138
  }
139
+ navigationOffset(key) {
140
+ switch (key) {
141
+ case 'ArrowLeft':
142
+ return this.dir() === 'rtl' ? 1 : -1;
143
+ case 'ArrowRight':
144
+ return this.dir() === 'rtl' ? -1 : 1;
145
+ case 'ArrowUp':
146
+ return -7;
147
+ case 'ArrowDown':
148
+ return 7;
149
+ default:
150
+ return null;
151
+ }
152
+ }
153
+ resolveActiveDate() {
154
+ const focused = this.focusedDate();
155
+ if (focused && this.findDay(focused) && !this.isDayDisabled(focused)) {
156
+ return cloneDate(focused);
157
+ }
158
+ const selected = this.selectedDate();
159
+ if (selected && this.findDay(selected) && !this.isDayDisabled(selected)) {
160
+ return cloneDate(selected);
161
+ }
162
+ const today = new Date();
163
+ if (this.findDay(today) && !this.isDayDisabled(today)) {
164
+ return cloneDate(today);
165
+ }
166
+ const firstEnabled = this.months()
167
+ .flatMap((month) => month.weeks.flat())
168
+ .find((day) => !day.disabled);
169
+ return firstEnabled ? cloneDate(firstEnabled.date) : cloneDate(this.currentMonth());
170
+ }
171
+ selectedDate() {
172
+ const value = this.value();
173
+ if (value instanceof Date) {
174
+ return value;
175
+ }
176
+ if (isRange(value)) {
177
+ return value.from ?? value.to;
178
+ }
179
+ return null;
180
+ }
181
+ isDateVisible(date) {
182
+ return this.months().some((month) => month.weeks.some((week) => week.some((day) => sameDate(day.date, date))));
183
+ }
184
+ findDay(date) {
185
+ for (const month of this.months()) {
186
+ for (const week of month.weeks) {
187
+ const day = week.find((item) => sameDate(item.date, date));
188
+ if (day) {
189
+ return day;
190
+ }
191
+ }
192
+ }
193
+ return null;
194
+ }
195
+ isDayDisabled(date) {
196
+ return this.findDay(date)?.disabled ?? true;
197
+ }
198
+ focusDay(date) {
199
+ if (this.focusDayElement(date)) {
200
+ return;
201
+ }
202
+ setTimeout(() => {
203
+ this.focusDayElement(date);
204
+ });
205
+ }
206
+ focusDayElement(date) {
207
+ const button = this.host.nativeElement.querySelector(`.frame-calendar__day[data-date="${dateKey(date)}"]`);
208
+ button?.focus();
209
+ return !!button;
210
+ }
117
211
  updateMonth(month) {
118
212
  const next = startOfMonth(month);
119
213
  this.navigatedMonth.set(next);
@@ -156,137 +250,143 @@ class FrCalendar {
156
250
  };
157
251
  }
158
252
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrCalendar, deps: [], target: i0.ɵɵFactoryTarget.Component });
159
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: FrCalendar, isStandalone: true, selector: "frame-calendar", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, captionLayout: { classPropertyName: "captionLayout", publicName: "captionLayout", isSignal: true, isRequired: false, transformFunction: null }, numberOfMonths: { classPropertyName: "numberOfMonths", publicName: "numberOfMonths", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, timeZone: { classPropertyName: "timeZone", publicName: "timeZone", isSignal: true, isRequired: false, transformFunction: null }, dir: { classPropertyName: "dir", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, fromYear: { classPropertyName: "fromYear", publicName: "fromYear", isSignal: true, isRequired: false, transformFunction: null }, toYear: { classPropertyName: "toYear", publicName: "toYear", isSignal: true, isRequired: false, transformFunction: null }, showOutsideDays: { classPropertyName: "showOutsideDays", publicName: "showOutsideDays", isSignal: true, isRequired: false, transformFunction: null }, showWeekNumber: { classPropertyName: "showWeekNumber", publicName: "showWeekNumber", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, disabledDates: { classPropertyName: "disabledDates", publicName: "disabledDates", isSignal: true, isRequired: false, transformFunction: null }, dateLabels: { classPropertyName: "dateLabels", publicName: "dateLabels", isSignal: true, isRequired: false, transformFunction: null }, disabledMatcher: { classPropertyName: "disabledMatcher", publicName: "disabledMatcher", isSignal: true, isRequired: false, transformFunction: null }, cellTemplate: { classPropertyName: "cellTemplate", publicName: "cellTemplate", isSignal: true, isRequired: false, transformFunction: null }, previousMonthTemplate: { classPropertyName: "previousMonthTemplate", publicName: "previousMonthTemplate", isSignal: true, isRequired: false, transformFunction: null }, nextMonthTemplate: { classPropertyName: "nextMonthTemplate", publicName: "nextMonthTemplate", isSignal: true, isRequired: false, transformFunction: null }, previousMonthIcon: { classPropertyName: "previousMonthIcon", publicName: "previousMonthIcon", isSignal: true, isRequired: false, transformFunction: null }, nextMonthIcon: { classPropertyName: "nextMonthIcon", publicName: "nextMonthIcon", isSignal: true, isRequired: false, transformFunction: null }, previousMonthLabel: { classPropertyName: "previousMonthLabel", publicName: "previousMonthLabel", isSignal: true, isRequired: false, transformFunction: null }, nextMonthLabel: { classPropertyName: "nextMonthLabel", publicName: "nextMonthLabel", isSignal: true, isRequired: false, transformFunction: null }, month: { classPropertyName: "month", publicName: "month", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedChange: "selectedChange", monthChange: "monthChange" }, host: { properties: { "attr.data-mode": "mode()", "attr.data-caption-layout": "captionLayout()", "attr.data-disabled": "isDisabled() ? \"\" : null", "attr.dir": "dir()" }, classAttribute: "frame-calendar" }, providers: [VALUE_ACCESSOR], ngImport: i0, template: `
160
- <div class="frame-calendar__header">
161
- <button
162
- class="frame-calendar__nav-button"
163
- type="button"
164
- [disabled]="isDisabled()"
165
- (click)="previousMonth()"
166
- [attr.aria-label]="previousMonthLabel()"
167
- >
168
- @if (previousMonthTemplate(); as template) {
169
- <ng-container [ngTemplateOutlet]="template" />
170
- } @else {
171
- {{ previousMonthIcon() }}
172
- }
173
- </button>
174
-
175
- @if (captionLayout() === 'dropdown') {
176
- <div class="frame-calendar__caption-controls">
177
- <select
178
- class="frame-calendar__select"
179
- [disabled]="isDisabled()"
180
- [value]="currentMonth().getMonth()"
181
- aria-label="Month"
182
- (change)="setMonth($any($event.target).value)"
183
- >
184
- @for (month of monthOptions(); track month.value) {
185
- <option [value]="month.value" [selected]="month.value === currentMonth().getMonth()">
186
- {{ month.label }}
187
- </option>
188
- }
189
- </select>
190
-
191
- <select
192
- class="frame-calendar__select"
193
- [disabled]="isDisabled()"
194
- [value]="currentMonth().getFullYear()"
195
- aria-label="Year"
196
- (change)="setYear($any($event.target).value)"
197
- >
198
- @for (year of yearOptions(); track year) {
199
- <option [value]="year" [selected]="year === currentMonth().getFullYear()">
200
- {{ year }}
201
- </option>
202
- }
203
- </select>
204
- </div>
205
- } @else {
206
- <div class="frame-calendar__caption" aria-live="polite">
207
- {{ monthLabel(currentMonth()) }}
208
- </div>
209
- }
210
-
211
- <button
212
- class="frame-calendar__nav-button"
213
- type="button"
214
- [disabled]="isDisabled()"
215
- (click)="nextMonth()"
216
- [attr.aria-label]="nextMonthLabel()"
217
- >
218
- @if (nextMonthTemplate(); as template) {
219
- <ng-container [ngTemplateOutlet]="template" />
220
- } @else {
221
- {{ nextMonthIcon() }}
222
- }
223
- </button>
224
- </div>
225
-
226
- <div class="frame-calendar__months">
227
- @for (month of months(); track month.key) {
228
- <section class="frame-calendar__month" [attr.aria-label]="month.label">
229
- @if (numberOfMonths() > 1 || captionLayout() === 'dropdown') {
230
- <h3 class="frame-calendar__month-caption">{{ month.label }}</h3>
231
- }
232
-
233
- <table class="frame-calendar__table">
234
- <thead>
235
- <tr>
236
- @if (showWeekNumber()) {
237
- <th class="frame-calendar__week-number-header" scope="col">Wk</th>
238
- }
239
- @for (weekday of weekdayLabels(); track weekday) {
240
- <th class="frame-calendar__weekday" scope="col">{{ weekday }}</th>
241
- }
242
- </tr>
243
- </thead>
244
- <tbody>
245
- @for (week of month.weeks; track week[0].key) {
246
- <tr>
247
- @if (showWeekNumber()) {
248
- <td class="frame-calendar__week-number">{{ weekNumber(week[0].date) }}</td>
249
- }
250
- @for (day of week; track day.key) {
251
- <td
252
- class="frame-calendar__cell"
253
- [attr.data-outside]="day.outside ? '' : null"
254
- [attr.data-selected]="day.selected ? '' : null"
255
- [attr.data-range-start]="day.rangeStart ? '' : null"
256
- [attr.data-range-middle]="day.rangeMiddle ? '' : null"
257
- [attr.data-range-end]="day.rangeEnd ? '' : null"
258
- [attr.data-today]="day.today ? '' : null"
259
- [attr.data-disabled-date]="day.disabledDate ? '' : null"
260
- >
261
- <button
262
- class="frame-calendar__day"
263
- type="button"
264
- [disabled]="isDisabled() || day.disabled"
265
- [attr.aria-label]="dayLabel(day.date)"
266
- [attr.aria-pressed]="day.selected ? 'true' : 'false'"
267
- (click)="selectDay(day)"
268
- >
269
- @if (cellTemplate(); as template) {
270
- <ng-container
271
- [ngTemplateOutlet]="template"
272
- [ngTemplateOutletContext]="day"
273
- />
274
- } @else {
275
- <span class="frame-calendar__day-number">{{ day.day }}</span>
276
- @if (day.dateLabel) {
277
- <span class="frame-calendar__day-meta">{{ day.dateLabel }}</span>
278
- }
279
- }
280
- </button>
281
- </td>
282
- }
283
- </tr>
284
- }
285
- </tbody>
286
- </table>
287
- </section>
288
- }
289
- </div>
253
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: FrCalendar, isStandalone: true, selector: "frame-calendar", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, captionLayout: { classPropertyName: "captionLayout", publicName: "captionLayout", isSignal: true, isRequired: false, transformFunction: null }, numberOfMonths: { classPropertyName: "numberOfMonths", publicName: "numberOfMonths", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, timeZone: { classPropertyName: "timeZone", publicName: "timeZone", isSignal: true, isRequired: false, transformFunction: null }, dir: { classPropertyName: "dir", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, fromYear: { classPropertyName: "fromYear", publicName: "fromYear", isSignal: true, isRequired: false, transformFunction: null }, toYear: { classPropertyName: "toYear", publicName: "toYear", isSignal: true, isRequired: false, transformFunction: null }, showOutsideDays: { classPropertyName: "showOutsideDays", publicName: "showOutsideDays", isSignal: true, isRequired: false, transformFunction: null }, showWeekNumber: { classPropertyName: "showWeekNumber", publicName: "showWeekNumber", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, disabledDates: { classPropertyName: "disabledDates", publicName: "disabledDates", isSignal: true, isRequired: false, transformFunction: null }, dateLabels: { classPropertyName: "dateLabels", publicName: "dateLabels", isSignal: true, isRequired: false, transformFunction: null }, disabledMatcher: { classPropertyName: "disabledMatcher", publicName: "disabledMatcher", isSignal: true, isRequired: false, transformFunction: null }, cellTemplate: { classPropertyName: "cellTemplate", publicName: "cellTemplate", isSignal: true, isRequired: false, transformFunction: null }, previousMonthTemplate: { classPropertyName: "previousMonthTemplate", publicName: "previousMonthTemplate", isSignal: true, isRequired: false, transformFunction: null }, nextMonthTemplate: { classPropertyName: "nextMonthTemplate", publicName: "nextMonthTemplate", isSignal: true, isRequired: false, transformFunction: null }, previousMonthIcon: { classPropertyName: "previousMonthIcon", publicName: "previousMonthIcon", isSignal: true, isRequired: false, transformFunction: null }, nextMonthIcon: { classPropertyName: "nextMonthIcon", publicName: "nextMonthIcon", isSignal: true, isRequired: false, transformFunction: null }, previousMonthLabel: { classPropertyName: "previousMonthLabel", publicName: "previousMonthLabel", isSignal: true, isRequired: false, transformFunction: null }, nextMonthLabel: { classPropertyName: "nextMonthLabel", publicName: "nextMonthLabel", isSignal: true, isRequired: false, transformFunction: null }, month: { classPropertyName: "month", publicName: "month", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedChange: "selectedChange", monthChange: "monthChange" }, host: { properties: { "attr.data-mode": "mode()", "attr.data-caption-layout": "captionLayout()", "attr.data-disabled": "isDisabled() ? \"\" : null", "attr.dir": "dir()" }, classAttribute: "frame-calendar" }, providers: [VALUE_ACCESSOR], ngImport: i0, template: `
254
+ <div class="frame-calendar__header">
255
+ <button
256
+ class="frame-calendar__nav-button"
257
+ type="button"
258
+ [disabled]="isDisabled()"
259
+ (click)="previousMonth()"
260
+ [attr.aria-label]="previousMonthLabel()"
261
+ >
262
+ @if (previousMonthTemplate(); as template) {
263
+ <ng-container [ngTemplateOutlet]="template" />
264
+ } @else {
265
+ {{ previousMonthIcon() }}
266
+ }
267
+ </button>
268
+
269
+ @if (captionLayout() === 'dropdown') {
270
+ <div class="frame-calendar__caption-controls">
271
+ <select
272
+ class="frame-calendar__select"
273
+ [disabled]="isDisabled()"
274
+ [value]="currentMonth().getMonth()"
275
+ aria-label="Month"
276
+ (change)="setMonth($any($event.target).value)"
277
+ >
278
+ @for (month of monthOptions(); track month.value) {
279
+ <option [value]="month.value" [selected]="month.value === currentMonth().getMonth()">
280
+ {{ month.label }}
281
+ </option>
282
+ }
283
+ </select>
284
+
285
+ <select
286
+ class="frame-calendar__select"
287
+ [disabled]="isDisabled()"
288
+ [value]="currentMonth().getFullYear()"
289
+ aria-label="Year"
290
+ (change)="setYear($any($event.target).value)"
291
+ >
292
+ @for (year of yearOptions(); track year) {
293
+ <option [value]="year" [selected]="year === currentMonth().getFullYear()">
294
+ {{ year }}
295
+ </option>
296
+ }
297
+ </select>
298
+ </div>
299
+ } @else {
300
+ <div class="frame-calendar__caption" aria-live="polite">
301
+ {{ monthLabel(currentMonth()) }}
302
+ </div>
303
+ }
304
+
305
+ <button
306
+ class="frame-calendar__nav-button"
307
+ type="button"
308
+ [disabled]="isDisabled()"
309
+ (click)="nextMonth()"
310
+ [attr.aria-label]="nextMonthLabel()"
311
+ >
312
+ @if (nextMonthTemplate(); as template) {
313
+ <ng-container [ngTemplateOutlet]="template" />
314
+ } @else {
315
+ {{ nextMonthIcon() }}
316
+ }
317
+ </button>
318
+ </div>
319
+
320
+ <div class="frame-calendar__months">
321
+ @for (month of months(); track month.key) {
322
+ <section class="frame-calendar__month" [attr.aria-label]="month.label">
323
+ @if (numberOfMonths() > 1 || captionLayout() === 'dropdown') {
324
+ <h3 class="frame-calendar__month-caption">{{ month.label }}</h3>
325
+ }
326
+
327
+ <table class="frame-calendar__table" role="grid" [attr.aria-readonly]="true">
328
+ <thead>
329
+ <tr>
330
+ @if (showWeekNumber()) {
331
+ <th class="frame-calendar__week-number-header" scope="col">Wk</th>
332
+ }
333
+ @for (weekday of weekdayLabels(); track weekday) {
334
+ <th class="frame-calendar__weekday" scope="col">{{ weekday }}</th>
335
+ }
336
+ </tr>
337
+ </thead>
338
+ <tbody>
339
+ @for (week of month.weeks; track week[0].key) {
340
+ <tr>
341
+ @if (showWeekNumber()) {
342
+ <td class="frame-calendar__week-number">{{ weekNumber(week[0].date) }}</td>
343
+ }
344
+ @for (day of week; track day.key) {
345
+ <td
346
+ class="frame-calendar__cell"
347
+ [attr.data-outside]="day.outside ? '' : null"
348
+ [attr.data-selected]="day.selected ? '' : null"
349
+ [attr.data-range-start]="day.rangeStart ? '' : null"
350
+ [attr.data-range-middle]="day.rangeMiddle ? '' : null"
351
+ [attr.data-range-end]="day.rangeEnd ? '' : null"
352
+ [attr.data-today]="day.today ? '' : null"
353
+ [attr.data-disabled-date]="day.disabledDate ? '' : null"
354
+ >
355
+ <button
356
+ class="frame-calendar__day"
357
+ type="button"
358
+ [disabled]="isDisabled() || day.disabled"
359
+ [attr.data-date]="day.key"
360
+ [attr.tabindex]="dayTabIndex(day)"
361
+ [attr.aria-label]="dayLabel(day.date)"
362
+ [attr.aria-pressed]="day.selected ? 'true' : 'false'"
363
+ [attr.aria-selected]="day.selected ? 'true' : 'false'"
364
+ [attr.aria-current]="day.today ? 'date' : null"
365
+ (click)="selectDay(day)"
366
+ (focus)="focusedDate.set(day.date)"
367
+ (keydown)="handleDayKeydown($event, day)"
368
+ >
369
+ @if (cellTemplate(); as template) {
370
+ <ng-container
371
+ [ngTemplateOutlet]="template"
372
+ [ngTemplateOutletContext]="day"
373
+ />
374
+ } @else {
375
+ <span class="frame-calendar__day-number">{{ day.day }}</span>
376
+ @if (day.dateLabel) {
377
+ <span class="frame-calendar__day-meta">{{ day.dateLabel }}</span>
378
+ }
379
+ }
380
+ </button>
381
+ </td>
382
+ }
383
+ </tr>
384
+ }
385
+ </tbody>
386
+ </table>
387
+ </section>
388
+ }
389
+ </div>
290
390
  `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
291
391
  }
292
392
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FrCalendar, decorators: [{
@@ -303,137 +403,143 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
303
403
  '[attr.data-disabled]': 'isDisabled() ? "" : null',
304
404
  '[attr.dir]': 'dir()',
305
405
  },
306
- template: `
307
- <div class="frame-calendar__header">
308
- <button
309
- class="frame-calendar__nav-button"
310
- type="button"
311
- [disabled]="isDisabled()"
312
- (click)="previousMonth()"
313
- [attr.aria-label]="previousMonthLabel()"
314
- >
315
- @if (previousMonthTemplate(); as template) {
316
- <ng-container [ngTemplateOutlet]="template" />
317
- } @else {
318
- {{ previousMonthIcon() }}
319
- }
320
- </button>
321
-
322
- @if (captionLayout() === 'dropdown') {
323
- <div class="frame-calendar__caption-controls">
324
- <select
325
- class="frame-calendar__select"
326
- [disabled]="isDisabled()"
327
- [value]="currentMonth().getMonth()"
328
- aria-label="Month"
329
- (change)="setMonth($any($event.target).value)"
330
- >
331
- @for (month of monthOptions(); track month.value) {
332
- <option [value]="month.value" [selected]="month.value === currentMonth().getMonth()">
333
- {{ month.label }}
334
- </option>
335
- }
336
- </select>
337
-
338
- <select
339
- class="frame-calendar__select"
340
- [disabled]="isDisabled()"
341
- [value]="currentMonth().getFullYear()"
342
- aria-label="Year"
343
- (change)="setYear($any($event.target).value)"
344
- >
345
- @for (year of yearOptions(); track year) {
346
- <option [value]="year" [selected]="year === currentMonth().getFullYear()">
347
- {{ year }}
348
- </option>
349
- }
350
- </select>
351
- </div>
352
- } @else {
353
- <div class="frame-calendar__caption" aria-live="polite">
354
- {{ monthLabel(currentMonth()) }}
355
- </div>
356
- }
357
-
358
- <button
359
- class="frame-calendar__nav-button"
360
- type="button"
361
- [disabled]="isDisabled()"
362
- (click)="nextMonth()"
363
- [attr.aria-label]="nextMonthLabel()"
364
- >
365
- @if (nextMonthTemplate(); as template) {
366
- <ng-container [ngTemplateOutlet]="template" />
367
- } @else {
368
- {{ nextMonthIcon() }}
369
- }
370
- </button>
371
- </div>
372
-
373
- <div class="frame-calendar__months">
374
- @for (month of months(); track month.key) {
375
- <section class="frame-calendar__month" [attr.aria-label]="month.label">
376
- @if (numberOfMonths() > 1 || captionLayout() === 'dropdown') {
377
- <h3 class="frame-calendar__month-caption">{{ month.label }}</h3>
378
- }
379
-
380
- <table class="frame-calendar__table">
381
- <thead>
382
- <tr>
383
- @if (showWeekNumber()) {
384
- <th class="frame-calendar__week-number-header" scope="col">Wk</th>
385
- }
386
- @for (weekday of weekdayLabels(); track weekday) {
387
- <th class="frame-calendar__weekday" scope="col">{{ weekday }}</th>
388
- }
389
- </tr>
390
- </thead>
391
- <tbody>
392
- @for (week of month.weeks; track week[0].key) {
393
- <tr>
394
- @if (showWeekNumber()) {
395
- <td class="frame-calendar__week-number">{{ weekNumber(week[0].date) }}</td>
396
- }
397
- @for (day of week; track day.key) {
398
- <td
399
- class="frame-calendar__cell"
400
- [attr.data-outside]="day.outside ? '' : null"
401
- [attr.data-selected]="day.selected ? '' : null"
402
- [attr.data-range-start]="day.rangeStart ? '' : null"
403
- [attr.data-range-middle]="day.rangeMiddle ? '' : null"
404
- [attr.data-range-end]="day.rangeEnd ? '' : null"
405
- [attr.data-today]="day.today ? '' : null"
406
- [attr.data-disabled-date]="day.disabledDate ? '' : null"
407
- >
408
- <button
409
- class="frame-calendar__day"
410
- type="button"
411
- [disabled]="isDisabled() || day.disabled"
412
- [attr.aria-label]="dayLabel(day.date)"
413
- [attr.aria-pressed]="day.selected ? 'true' : 'false'"
414
- (click)="selectDay(day)"
415
- >
416
- @if (cellTemplate(); as template) {
417
- <ng-container
418
- [ngTemplateOutlet]="template"
419
- [ngTemplateOutletContext]="day"
420
- />
421
- } @else {
422
- <span class="frame-calendar__day-number">{{ day.day }}</span>
423
- @if (day.dateLabel) {
424
- <span class="frame-calendar__day-meta">{{ day.dateLabel }}</span>
425
- }
426
- }
427
- </button>
428
- </td>
429
- }
430
- </tr>
431
- }
432
- </tbody>
433
- </table>
434
- </section>
435
- }
436
- </div>
406
+ template: `
407
+ <div class="frame-calendar__header">
408
+ <button
409
+ class="frame-calendar__nav-button"
410
+ type="button"
411
+ [disabled]="isDisabled()"
412
+ (click)="previousMonth()"
413
+ [attr.aria-label]="previousMonthLabel()"
414
+ >
415
+ @if (previousMonthTemplate(); as template) {
416
+ <ng-container [ngTemplateOutlet]="template" />
417
+ } @else {
418
+ {{ previousMonthIcon() }}
419
+ }
420
+ </button>
421
+
422
+ @if (captionLayout() === 'dropdown') {
423
+ <div class="frame-calendar__caption-controls">
424
+ <select
425
+ class="frame-calendar__select"
426
+ [disabled]="isDisabled()"
427
+ [value]="currentMonth().getMonth()"
428
+ aria-label="Month"
429
+ (change)="setMonth($any($event.target).value)"
430
+ >
431
+ @for (month of monthOptions(); track month.value) {
432
+ <option [value]="month.value" [selected]="month.value === currentMonth().getMonth()">
433
+ {{ month.label }}
434
+ </option>
435
+ }
436
+ </select>
437
+
438
+ <select
439
+ class="frame-calendar__select"
440
+ [disabled]="isDisabled()"
441
+ [value]="currentMonth().getFullYear()"
442
+ aria-label="Year"
443
+ (change)="setYear($any($event.target).value)"
444
+ >
445
+ @for (year of yearOptions(); track year) {
446
+ <option [value]="year" [selected]="year === currentMonth().getFullYear()">
447
+ {{ year }}
448
+ </option>
449
+ }
450
+ </select>
451
+ </div>
452
+ } @else {
453
+ <div class="frame-calendar__caption" aria-live="polite">
454
+ {{ monthLabel(currentMonth()) }}
455
+ </div>
456
+ }
457
+
458
+ <button
459
+ class="frame-calendar__nav-button"
460
+ type="button"
461
+ [disabled]="isDisabled()"
462
+ (click)="nextMonth()"
463
+ [attr.aria-label]="nextMonthLabel()"
464
+ >
465
+ @if (nextMonthTemplate(); as template) {
466
+ <ng-container [ngTemplateOutlet]="template" />
467
+ } @else {
468
+ {{ nextMonthIcon() }}
469
+ }
470
+ </button>
471
+ </div>
472
+
473
+ <div class="frame-calendar__months">
474
+ @for (month of months(); track month.key) {
475
+ <section class="frame-calendar__month" [attr.aria-label]="month.label">
476
+ @if (numberOfMonths() > 1 || captionLayout() === 'dropdown') {
477
+ <h3 class="frame-calendar__month-caption">{{ month.label }}</h3>
478
+ }
479
+
480
+ <table class="frame-calendar__table" role="grid" [attr.aria-readonly]="true">
481
+ <thead>
482
+ <tr>
483
+ @if (showWeekNumber()) {
484
+ <th class="frame-calendar__week-number-header" scope="col">Wk</th>
485
+ }
486
+ @for (weekday of weekdayLabels(); track weekday) {
487
+ <th class="frame-calendar__weekday" scope="col">{{ weekday }}</th>
488
+ }
489
+ </tr>
490
+ </thead>
491
+ <tbody>
492
+ @for (week of month.weeks; track week[0].key) {
493
+ <tr>
494
+ @if (showWeekNumber()) {
495
+ <td class="frame-calendar__week-number">{{ weekNumber(week[0].date) }}</td>
496
+ }
497
+ @for (day of week; track day.key) {
498
+ <td
499
+ class="frame-calendar__cell"
500
+ [attr.data-outside]="day.outside ? '' : null"
501
+ [attr.data-selected]="day.selected ? '' : null"
502
+ [attr.data-range-start]="day.rangeStart ? '' : null"
503
+ [attr.data-range-middle]="day.rangeMiddle ? '' : null"
504
+ [attr.data-range-end]="day.rangeEnd ? '' : null"
505
+ [attr.data-today]="day.today ? '' : null"
506
+ [attr.data-disabled-date]="day.disabledDate ? '' : null"
507
+ >
508
+ <button
509
+ class="frame-calendar__day"
510
+ type="button"
511
+ [disabled]="isDisabled() || day.disabled"
512
+ [attr.data-date]="day.key"
513
+ [attr.tabindex]="dayTabIndex(day)"
514
+ [attr.aria-label]="dayLabel(day.date)"
515
+ [attr.aria-pressed]="day.selected ? 'true' : 'false'"
516
+ [attr.aria-selected]="day.selected ? 'true' : 'false'"
517
+ [attr.aria-current]="day.today ? 'date' : null"
518
+ (click)="selectDay(day)"
519
+ (focus)="focusedDate.set(day.date)"
520
+ (keydown)="handleDayKeydown($event, day)"
521
+ >
522
+ @if (cellTemplate(); as template) {
523
+ <ng-container
524
+ [ngTemplateOutlet]="template"
525
+ [ngTemplateOutletContext]="day"
526
+ />
527
+ } @else {
528
+ <span class="frame-calendar__day-number">{{ day.day }}</span>
529
+ @if (day.dateLabel) {
530
+ <span class="frame-calendar__day-meta">{{ day.dateLabel }}</span>
531
+ }
532
+ }
533
+ </button>
534
+ </td>
535
+ }
536
+ </tr>
537
+ }
538
+ </tbody>
539
+ </table>
540
+ </section>
541
+ }
542
+ </div>
437
543
  `,
438
544
  }]
439
545
  }], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], captionLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionLayout", required: false }] }], numberOfMonths: [{ type: i0.Input, args: [{ isSignal: true, alias: "numberOfMonths", required: false }] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], timeZone: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeZone", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], fromYear: [{ type: i0.Input, args: [{ isSignal: true, alias: "fromYear", required: false }] }], toYear: [{ type: i0.Input, args: [{ isSignal: true, alias: "toYear", required: false }] }], showOutsideDays: [{ type: i0.Input, args: [{ isSignal: true, alias: "showOutsideDays", required: false }] }], showWeekNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "showWeekNumber", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], disabledDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledDates", required: false }] }], dateLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateLabels", required: false }] }], disabledMatcher: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledMatcher", required: false }] }], cellTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellTemplate", required: false }] }], previousMonthTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousMonthTemplate", required: false }] }], nextMonthTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextMonthTemplate", required: false }] }], previousMonthIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousMonthIcon", required: false }] }], nextMonthIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextMonthIcon", required: false }] }], previousMonthLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousMonthLabel", required: false }] }], nextMonthLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextMonthLabel", required: false }] }], month: [{ type: i0.Input, args: [{ isSignal: true, alias: "month", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], selectedChange: [{ type: i0.Output, args: ["selectedChange"] }], monthChange: [{ type: i0.Output, args: ["monthChange"] }] } });