@devjuliovilla/jv-ui 1.12.0 → 1.13.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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, computed, Component, inject, signal, Injectable, InjectionToken, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, Directive, contentChild, output, effect, forwardRef, viewChild, contentChildren, HostListener, viewChildren, numberAttribute, afterNextRender, Renderer2, ElementRef } from '@angular/core';
2
+ import { input, computed, Component, inject, signal, Injectable, InjectionToken, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, Directive, contentChild, output, effect, forwardRef, viewChild, untracked, contentChildren, HostListener, viewChildren, numberAttribute, afterNextRender, Renderer2, ElementRef } from '@angular/core';
3
3
  import { DOCUMENT, NgTemplateOutlet, CommonModule } from '@angular/common';
4
4
  import * as i1 from '@angular/forms';
5
5
  import { NG_VALUE_ACCESSOR, FormBuilder, Validators, ReactiveFormsModule, FormsModule } from '@angular/forms';
@@ -18178,6 +18178,8 @@ const ES = {
18178
18178
  'monthCalendar.today': 'Hoy',
18179
18179
  'monthCalendar.prevMonth': 'Mes anterior',
18180
18180
  'monthCalendar.nextMonth': 'Mes siguiente',
18181
+ 'monthCalendar.prevYear': 'Ano anterior',
18182
+ 'monthCalendar.nextYear': 'Ano siguiente',
18181
18183
  'modalSelector.placeholder': 'Seleccione una opcion',
18182
18184
  'modalSelector.searchPlaceholder': 'Buscar',
18183
18185
  'modalSelector.emptyMessage': 'No se encontraron resultados',
@@ -18255,6 +18257,8 @@ const EN = {
18255
18257
  'monthCalendar.today': 'Today',
18256
18258
  'monthCalendar.prevMonth': 'Previous month',
18257
18259
  'monthCalendar.nextMonth': 'Next month',
18260
+ 'monthCalendar.prevYear': 'Previous year',
18261
+ 'monthCalendar.nextYear': 'Next year',
18258
18262
  'modalSelector.placeholder': 'Select an option',
18259
18263
  'modalSelector.searchPlaceholder': 'Search',
18260
18264
  'modalSelector.emptyMessage': 'No results found',
@@ -18843,6 +18847,7 @@ class JvSelectComponent {
18843
18847
  required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
18844
18848
  invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
18845
18849
  describedBy = input('', ...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
18850
+ ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
18846
18851
  inputId = input(`jv-select-${++selectIdSequence}`, ...(ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []));
18847
18852
  modelValue = input('', ...(ngDevMode ? [{ debugName: "modelValue" }] : /* istanbul ignore next */ []));
18848
18853
  selectionChange = output();
@@ -18873,7 +18878,7 @@ class JvSelectComponent {
18873
18878
  this.onTouched();
18874
18879
  }
18875
18880
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
18876
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: JvSelectComponent, isStandalone: true, selector: "jv-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, describedBy: { classPropertyName: "describedBy", publicName: "describedBy", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, modelValue: { classPropertyName: "modelValue", publicName: "modelValue", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, providers: [
18881
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: JvSelectComponent, isStandalone: true, selector: "jv-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, describedBy: { classPropertyName: "describedBy", publicName: "describedBy", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, modelValue: { classPropertyName: "modelValue", publicName: "modelValue", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, providers: [
18877
18882
  {
18878
18883
  provide: NG_VALUE_ACCESSOR,
18879
18884
  useExisting: forwardRef(() => JvSelectComponent),
@@ -18888,16 +18893,16 @@ class JvSelectComponent {
18888
18893
  [required]="required()"
18889
18894
  [attr.aria-invalid]="invalid() ? 'true' : null"
18890
18895
  [attr.aria-describedby]="describedBy() || null"
18891
- [value]="currentValue()"
18896
+ [attr.aria-label]="ariaLabel() || null"
18892
18897
  (change)="handleChange($event)"
18893
18898
  (blur)="handleBlur()"
18894
18899
  >
18895
18900
  @if (placeholder()) {
18896
- <option value="" [disabled]="required()">{{ placeholder() }}</option>
18901
+ <option value="" [disabled]="required()" [selected]="currentValue() === ''">{{ placeholder() }}</option>
18897
18902
  }
18898
18903
 
18899
18904
  @for (option of options(); track option.label + ':' + option.value) {
18900
- <option [value]="option.value" [disabled]="option.disabled ?? false">{{ option.label }}</option>
18905
+ <option [value]="option.value" [disabled]="option.disabled ?? false" [selected]="option.value === currentValue()">{{ option.label }}</option>
18901
18906
  }
18902
18907
  </select>
18903
18908
  `, isInline: true, styles: [".jv-select{width:100%;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);background:var(--jv-color-surface);color:var(--jv-color-foreground)}.jv-select.is-invalid{border-color:var(--jv-color-danger)}\n"] });
@@ -18919,20 +18924,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
18919
18924
  [required]="required()"
18920
18925
  [attr.aria-invalid]="invalid() ? 'true' : null"
18921
18926
  [attr.aria-describedby]="describedBy() || null"
18922
- [value]="currentValue()"
18927
+ [attr.aria-label]="ariaLabel() || null"
18923
18928
  (change)="handleChange($event)"
18924
18929
  (blur)="handleBlur()"
18925
18930
  >
18926
18931
  @if (placeholder()) {
18927
- <option value="" [disabled]="required()">{{ placeholder() }}</option>
18932
+ <option value="" [disabled]="required()" [selected]="currentValue() === ''">{{ placeholder() }}</option>
18928
18933
  }
18929
18934
 
18930
18935
  @for (option of options(); track option.label + ':' + option.value) {
18931
- <option [value]="option.value" [disabled]="option.disabled ?? false">{{ option.label }}</option>
18936
+ <option [value]="option.value" [disabled]="option.disabled ?? false" [selected]="option.value === currentValue()">{{ option.label }}</option>
18932
18937
  }
18933
18938
  </select>
18934
18939
  `, styles: [".jv-select{width:100%;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);background:var(--jv-color-surface);color:var(--jv-color-foreground)}.jv-select.is-invalid{border-color:var(--jv-color-danger)}\n"] }]
18935
- }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], describedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "describedBy", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], modelValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "modelValue", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }] } });
18940
+ }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], describedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "describedBy", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], modelValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "modelValue", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }] } });
18936
18941
 
18937
18942
  class JvMonthCalendarDayDirective {
18938
18943
  templateRef;
@@ -18956,13 +18961,27 @@ class JvMonthCalendarComponent {
18956
18961
  gridRootRef = viewChild('gridRoot', ...(ngDevMode ? [{ debugName: "gridRootRef" }] : /* istanbul ignore next */ []));
18957
18962
  customDayTemplate = contentChild(JvMonthCalendarDayDirective, ...(ngDevMode ? [{ debugName: "customDayTemplate" }] : /* istanbul ignore next */ []));
18958
18963
  valueInput = input(undefined, { ...(ngDevMode ? { debugName: "valueInput" } : /* istanbul ignore next */ {}), alias: 'value' });
18964
+ visibleMonthInput = input(undefined, { ...(ngDevMode ? { debugName: "visibleMonthInput" } : /* istanbul ignore next */ {}), alias: 'visibleMonth' });
18959
18965
  ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
18966
+ monthLabel = input('', ...(ngDevMode ? [{ debugName: "monthLabel" }] : /* istanbul ignore next */ []));
18967
+ yearLabel = input('', ...(ngDevMode ? [{ debugName: "yearLabel" }] : /* istanbul ignore next */ []));
18968
+ minYear = input(undefined, ...(ngDevMode ? [{ debugName: "minYear" }] : /* istanbul ignore next */ []));
18969
+ maxYear = input(undefined, ...(ngDevMode ? [{ debugName: "maxYear" }] : /* istanbul ignore next */ []));
18970
+ navigation = input(null, ...(ngDevMode ? [{ debugName: "navigation" }] : /* istanbul ignore next */ []));
18960
18971
  dayMeta = input([], ...(ngDevMode ? [{ debugName: "dayMeta" }] : /* istanbul ignore next */ []));
18961
18972
  selectionChange = output();
18962
18973
  visibleMonthChange = output();
18963
18974
  visibleMonth = signal(firstOfMonth$1(new Date()), ...(ngDevMode ? [{ debugName: "visibleMonth" }] : /* istanbul ignore next */ []));
18964
18975
  focusedDate = signal(startOfDay$1(new Date()), ...(ngDevMode ? [{ debugName: "focusedDate" }] : /* istanbul ignore next */ []));
18965
18976
  resolvedAriaLabel = computed(() => this.ariaLabel() || this.translation.translate('monthCalendar.title'), ...(ngDevMode ? [{ debugName: "resolvedAriaLabel" }] : /* istanbul ignore next */ []));
18977
+ resolvedMonthLabel = computed(() => this.monthLabel() || 'Month', ...(ngDevMode ? [{ debugName: "resolvedMonthLabel" }] : /* istanbul ignore next */ []));
18978
+ resolvedYearLabel = computed(() => this.yearLabel() || 'Year', ...(ngDevMode ? [{ debugName: "resolvedYearLabel" }] : /* istanbul ignore next */ []));
18979
+ resolvedNavigation = computed(() => ({
18980
+ previousMonth: this.navigation()?.previousMonth ?? true,
18981
+ nextMonth: this.navigation()?.nextMonth ?? true,
18982
+ previousYear: this.navigation()?.previousYear ?? false,
18983
+ nextYear: this.navigation()?.nextYear ?? false,
18984
+ }), ...(ngDevMode ? [{ debugName: "resolvedNavigation" }] : /* istanbul ignore next */ []));
18966
18985
  monthOptions = computed(() => {
18967
18986
  const formatter = new Intl.DateTimeFormat(this.formatService.formatLocale(), { month: 'long' });
18968
18987
  return Array.from({ length: 12 }, (_, month) => ({
@@ -18971,9 +18990,9 @@ class JvMonthCalendarComponent {
18971
18990
  }));
18972
18991
  }, ...(ngDevMode ? [{ debugName: "monthOptions" }] : /* istanbul ignore next */ []));
18973
18992
  yearOptions = computed(() => {
18974
- const currentYear = new Date().getFullYear();
18975
- return Array.from({ length: 21 }, (_, index) => {
18976
- const year = currentYear - 10 + index;
18993
+ const [startYear, endYear] = this.yearBounds();
18994
+ return Array.from({ length: endYear - startYear + 1 }, (_, index) => {
18995
+ const year = startYear + index;
18977
18996
  return { label: String(year), value: String(year) };
18978
18997
  });
18979
18998
  }, ...(ngDevMode ? [{ debugName: "yearOptions" }] : /* istanbul ignore next */ []));
@@ -19015,9 +19034,22 @@ class JvMonthCalendarComponent {
19015
19034
  });
19016
19035
  }, ...(ngDevMode ? [{ debugName: "calendarCells" }] : /* istanbul ignore next */ []));
19017
19036
  selectedDate = computed(() => normalizeDate(this.valueInput()), ...(ngDevMode ? [{ debugName: "selectedDate" }] : /* istanbul ignore next */ []));
19037
+ visibleMonthValue = computed(() => normalizeMonth(this.visibleMonthInput()), ...(ngDevMode ? [{ debugName: "visibleMonthValue" }] : /* istanbul ignore next */ []));
19038
+ yearBounds = computed(() => {
19039
+ const fallbackYear = new Date().getFullYear();
19040
+ const minYear = this.minYear() ?? fallbackYear - 10;
19041
+ const maxYear = this.maxYear() ?? fallbackYear + 10;
19042
+ return minYear <= maxYear ? [minYear, maxYear] : [maxYear, minYear];
19043
+ }, ...(ngDevMode ? [{ debugName: "yearBounds" }] : /* istanbul ignore next */ []));
19018
19044
  constructor() {
19019
19045
  effect(() => {
19046
+ const explicitVisibleMonth = this.visibleMonthValue();
19020
19047
  const selectedDate = this.selectedDate();
19048
+ if (explicitVisibleMonth) {
19049
+ this.focusedDate.set(this.focusDateForMonth(explicitVisibleMonth, untracked(() => this.focusedDate())));
19050
+ this.visibleMonth.set(explicitVisibleMonth);
19051
+ return;
19052
+ }
19021
19053
  if (!selectedDate) {
19022
19054
  return;
19023
19055
  }
@@ -19035,6 +19067,10 @@ class JvMonthCalendarComponent {
19035
19067
  this.setVisibleMonth(new Date(this.visibleMonth().getFullYear(), this.visibleMonth().getMonth() + offset, 1));
19036
19068
  this.focusDateWithinVisibleMonth(this.focusedDate());
19037
19069
  }
19070
+ shiftYear(offset) {
19071
+ this.setVisibleMonth(new Date(this.visibleMonth().getFullYear() + offset, this.visibleMonth().getMonth(), 1));
19072
+ this.focusDateWithinVisibleMonth(this.focusedDate());
19073
+ }
19038
19074
  handleMonthChange(value) {
19039
19075
  const current = this.visibleMonth();
19040
19076
  this.setVisibleMonth(new Date(current.getFullYear(), Number(value), 1));
@@ -19121,46 +19157,76 @@ class JvMonthCalendarComponent {
19121
19157
  this.visibleMonthChange.emit(month);
19122
19158
  }
19123
19159
  focusDateWithinVisibleMonth(date) {
19124
- const month = this.visibleMonth();
19125
- const nextDate = startOfDay$1(new Date(month.getFullYear(), month.getMonth(), Math.min(date.getDate(), daysInMonth$1(month.getFullYear(), month.getMonth()))));
19160
+ const nextDate = this.focusDateForMonth(this.visibleMonth(), date);
19126
19161
  this.focusedDate.set(nextDate);
19127
19162
  queueMicrotask(() => this.focusDateButton(nextDate));
19128
19163
  }
19164
+ focusDateForMonth(month, date) {
19165
+ return startOfDay$1(new Date(month.getFullYear(), month.getMonth(), Math.min(date.getDate(), daysInMonth$1(month.getFullYear(), month.getMonth()))));
19166
+ }
19129
19167
  focusDateButton(date) {
19130
19168
  const button = this.gridRootRef()?.nativeElement
19131
19169
  .querySelector(`[data-jv-date="${toDateKey(date)}"]`);
19132
19170
  button?.focus();
19133
19171
  }
19134
19172
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvMonthCalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
19135
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: JvMonthCalendarComponent, isStandalone: true, selector: "jv-month-calendar", inputs: { valueInput: { classPropertyName: "valueInput", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, dayMeta: { classPropertyName: "dayMeta", publicName: "dayMeta", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange", visibleMonthChange: "visibleMonthChange" }, queries: [{ propertyName: "customDayTemplate", first: true, predicate: JvMonthCalendarDayDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "gridRootRef", first: true, predicate: ["gridRoot"], descendants: true, isSignal: true }], ngImport: i0, template: `
19173
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: JvMonthCalendarComponent, isStandalone: true, selector: "jv-month-calendar", inputs: { valueInput: { classPropertyName: "valueInput", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, visibleMonthInput: { classPropertyName: "visibleMonthInput", publicName: "visibleMonth", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, monthLabel: { classPropertyName: "monthLabel", publicName: "monthLabel", isSignal: true, isRequired: false, transformFunction: null }, yearLabel: { classPropertyName: "yearLabel", publicName: "yearLabel", isSignal: true, isRequired: false, transformFunction: null }, minYear: { classPropertyName: "minYear", publicName: "minYear", isSignal: true, isRequired: false, transformFunction: null }, maxYear: { classPropertyName: "maxYear", publicName: "maxYear", isSignal: true, isRequired: false, transformFunction: null }, navigation: { classPropertyName: "navigation", publicName: "navigation", isSignal: true, isRequired: false, transformFunction: null }, dayMeta: { classPropertyName: "dayMeta", publicName: "dayMeta", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange", visibleMonthChange: "visibleMonthChange" }, queries: [{ propertyName: "customDayTemplate", first: true, predicate: JvMonthCalendarDayDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "gridRootRef", first: true, predicate: ["gridRoot"], descendants: true, isSignal: true }], ngImport: i0, template: `
19136
19174
  <section class="jv-month-calendar" [attr.aria-label]="resolvedAriaLabel()">
19137
19175
  <div class="jv-month-calendar-toolbar">
19138
- <jv-icon-button
19139
- icon="chevron-left"
19140
- variant="ghost"
19141
- [ariaLabel]="translation.translate('monthCalendar.prevMonth')"
19142
- (click)="shiftMonth(-1)"
19143
- />
19176
+ <div class="jv-month-calendar-nav-group jv-month-calendar-nav-group--start">
19177
+ @if (resolvedNavigation().previousYear) {
19178
+ <jv-icon-button
19179
+ icon="chevrons-left"
19180
+ variant="ghost"
19181
+ [ariaLabel]="translation.translate('monthCalendar.prevYear')"
19182
+ (click)="shiftYear(-1)"
19183
+ />
19184
+ }
19185
+
19186
+ @if (resolvedNavigation().previousMonth) {
19187
+ <jv-icon-button
19188
+ icon="chevron-left"
19189
+ variant="ghost"
19190
+ [ariaLabel]="translation.translate('monthCalendar.prevMonth')"
19191
+ (click)="shiftMonth(-1)"
19192
+ />
19193
+ }
19194
+ </div>
19144
19195
 
19145
19196
  <div class="jv-month-calendar-selects">
19146
19197
  <jv-select
19147
19198
  [options]="monthOptions()"
19199
+ [ariaLabel]="resolvedMonthLabel()"
19148
19200
  [modelValue]="visibleMonth().getMonth().toString()"
19149
19201
  (selectionChange)="handleMonthChange($event)"
19150
19202
  />
19151
19203
  <jv-select
19152
19204
  [options]="yearOptions()"
19205
+ [ariaLabel]="resolvedYearLabel()"
19153
19206
  [modelValue]="visibleMonth().getFullYear().toString()"
19154
19207
  (selectionChange)="handleYearChange($event)"
19155
19208
  />
19156
19209
  </div>
19157
19210
 
19158
- <jv-icon-button
19159
- icon="chevron-right"
19160
- variant="ghost"
19161
- [ariaLabel]="translation.translate('monthCalendar.nextMonth')"
19162
- (click)="shiftMonth(1)"
19163
- />
19211
+ <div class="jv-month-calendar-nav-group jv-month-calendar-nav-group--end">
19212
+ @if (resolvedNavigation().nextMonth) {
19213
+ <jv-icon-button
19214
+ icon="chevron-right"
19215
+ variant="ghost"
19216
+ [ariaLabel]="translation.translate('monthCalendar.nextMonth')"
19217
+ (click)="shiftMonth(1)"
19218
+ />
19219
+ }
19220
+
19221
+ @if (resolvedNavigation().nextYear) {
19222
+ <jv-icon-button
19223
+ icon="chevrons-right"
19224
+ variant="ghost"
19225
+ [ariaLabel]="translation.translate('monthCalendar.nextYear')"
19226
+ (click)="shiftYear(1)"
19227
+ />
19228
+ }
19229
+ </div>
19164
19230
  </div>
19165
19231
 
19166
19232
  <div class="jv-month-calendar-actions">
@@ -19204,39 +19270,67 @@ class JvMonthCalendarComponent {
19204
19270
  }
19205
19271
  </div>
19206
19272
  </section>
19207
- `, isInline: true, styles: [".jv-month-calendar{display:grid;gap:var(--jv-spacing-md);padding:var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-lg);background:var(--jv-color-surface)}.jv-month-calendar-toolbar,.jv-month-calendar-selects,.jv-month-calendar-weekdays,.jv-month-calendar-grid,.jv-month-calendar-actions{display:grid;gap:var(--jv-spacing-sm)}.jv-month-calendar-toolbar{grid-template-columns:auto 1fr auto;align-items:center}.jv-month-calendar-selects{grid-template-columns:1fr 1fr}.jv-month-calendar-actions{justify-content:end}.jv-month-calendar-today{min-height:2.25rem;padding:0 var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:999px;background:var(--jv-color-surface-muted);color:var(--jv-color-foreground);font:inherit;cursor:pointer}.jv-month-calendar-today:hover,.jv-month-calendar-today:focus-visible{border-color:var(--jv-color-primary);outline:none}.jv-month-calendar-weekdays,.jv-month-calendar-grid{grid-template-columns:repeat(7,minmax(0,1fr))}.jv-month-calendar-weekdays span{text-align:center;font-size:.8125rem;font-weight:600;color:var(--jv-color-foreground-muted)}.jv-month-calendar-day{position:relative;min-height:5rem;display:grid;align-content:start;justify-items:start;gap:var(--jv-spacing-xs);padding:var(--jv-spacing-sm);border:1px solid transparent;border-radius:var(--jv-radius-md);background:transparent;color:var(--jv-color-foreground);text-align:left;font:inherit;cursor:pointer;transition:background-color .16s ease,border-color .16s ease,color .16s ease}.jv-month-calendar-day:hover,.jv-month-calendar-day:focus-visible{background:var(--jv-color-surface-muted);outline:none}.jv-month-calendar-day--outside{color:var(--jv-color-foreground-muted)}.jv-month-calendar-day--today{border-color:var(--jv-color-primary)}.jv-month-calendar-day--selected{background:color-mix(in srgb,var(--jv-color-primary) 14%,var(--jv-color-surface));border-color:var(--jv-color-primary)}.jv-month-calendar-day-number{font-weight:700}.jv-month-calendar-day-count,.jv-month-calendar-day-dot{display:inline-flex;align-items:center;justify-content:center;border-radius:999px}.jv-month-calendar-day-count{min-width:1.5rem;min-height:1.5rem;padding:0 .375rem;font-size:.75rem;font-weight:700}.jv-month-calendar-day-dot{width:.5rem;height:.5rem;margin-top:auto}.jv-month-calendar-marker--primary{background:color-mix(in srgb,var(--jv-color-primary) 18%,var(--jv-color-surface));color:var(--jv-color-primary)}.jv-month-calendar-marker--secondary,.jv-month-calendar-marker--neutral{background:var(--jv-color-surface-muted);color:var(--jv-color-foreground)}.jv-month-calendar-marker--success{background:color-mix(in srgb,var(--jv-color-success) 18%,var(--jv-color-surface));color:var(--jv-color-success)}.jv-month-calendar-marker--warning{background:color-mix(in srgb,var(--jv-color-warning) 20%,var(--jv-color-surface));color:#8a4b00}.jv-month-calendar-marker--danger{background:color-mix(in srgb,var(--jv-color-danger) 18%,var(--jv-color-surface));color:var(--jv-color-danger)}.jv-month-calendar-marker--info{background:color-mix(in srgb,var(--jv-color-info) 18%,var(--jv-color-surface));color:var(--jv-color-info)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: JvIconButtonComponent, selector: "jv-icon-button", inputs: ["icon", "ariaLabel", "variant", "disabled"] }, { kind: "component", type: JvSelectComponent, selector: "jv-select", inputs: ["options", "placeholder", "required", "invalid", "describedBy", "inputId", "modelValue"], outputs: ["selectionChange"] }] });
19273
+ `, isInline: true, styles: [".jv-month-calendar{display:grid;gap:var(--jv-spacing-md);padding:var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-lg);background:var(--jv-color-surface)}.jv-month-calendar-toolbar,.jv-month-calendar-nav-group,.jv-month-calendar-selects,.jv-month-calendar-weekdays,.jv-month-calendar-grid,.jv-month-calendar-actions{display:grid;gap:var(--jv-spacing-sm)}.jv-month-calendar-toolbar{grid-template-columns:auto 1fr auto;align-items:center}.jv-month-calendar-nav-group{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-month-calendar-nav-group--end{justify-content:end}.jv-month-calendar-selects{grid-template-columns:1fr 1fr}.jv-month-calendar-actions{justify-content:end}.jv-month-calendar-today{min-height:2.25rem;padding:0 var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:999px;background:var(--jv-color-surface-muted);color:var(--jv-color-foreground);font:inherit;cursor:pointer}.jv-month-calendar-today:hover,.jv-month-calendar-today:focus-visible{border-color:var(--jv-color-primary);outline:none}.jv-month-calendar-weekdays,.jv-month-calendar-grid{grid-template-columns:repeat(7,minmax(0,1fr))}.jv-month-calendar-weekdays span{text-align:center;font-size:.8125rem;font-weight:600;color:var(--jv-color-foreground-muted)}.jv-month-calendar-day{position:relative;min-height:5rem;display:grid;align-content:start;justify-items:start;gap:var(--jv-spacing-xs);padding:var(--jv-spacing-sm);border:1px solid transparent;border-radius:var(--jv-radius-md);background:transparent;color:var(--jv-color-foreground);text-align:left;font:inherit;cursor:pointer;transition:background-color .16s ease,border-color .16s ease,color .16s ease}.jv-month-calendar-day:hover,.jv-month-calendar-day:focus-visible{background:var(--jv-color-surface-muted);outline:none}.jv-month-calendar-day--outside{color:var(--jv-color-foreground-muted)}.jv-month-calendar-day--today{border-color:var(--jv-color-primary)}.jv-month-calendar-day--selected{background:color-mix(in srgb,var(--jv-color-primary) 14%,var(--jv-color-surface));border-color:var(--jv-color-primary)}.jv-month-calendar-day-number{font-weight:700}.jv-month-calendar-day-count,.jv-month-calendar-day-dot{display:inline-flex;align-items:center;justify-content:center;border-radius:999px}.jv-month-calendar-day-count{min-width:1.5rem;min-height:1.5rem;padding:0 .375rem;font-size:.75rem;font-weight:700}.jv-month-calendar-day-dot{width:.5rem;height:.5rem;margin-top:auto}.jv-month-calendar-marker--primary{background:color-mix(in srgb,var(--jv-color-primary) 18%,var(--jv-color-surface));color:var(--jv-color-primary)}.jv-month-calendar-marker--secondary,.jv-month-calendar-marker--neutral{background:var(--jv-color-surface-muted);color:var(--jv-color-foreground)}.jv-month-calendar-marker--success{background:color-mix(in srgb,var(--jv-color-success) 18%,var(--jv-color-surface));color:var(--jv-color-success)}.jv-month-calendar-marker--warning{background:color-mix(in srgb,var(--jv-color-warning) 20%,var(--jv-color-surface));color:#8a4b00}.jv-month-calendar-marker--danger{background:color-mix(in srgb,var(--jv-color-danger) 18%,var(--jv-color-surface));color:var(--jv-color-danger)}.jv-month-calendar-marker--info{background:color-mix(in srgb,var(--jv-color-info) 18%,var(--jv-color-surface));color:var(--jv-color-info)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: JvIconButtonComponent, selector: "jv-icon-button", inputs: ["icon", "ariaLabel", "variant", "disabled"] }, { kind: "component", type: JvSelectComponent, selector: "jv-select", inputs: ["options", "placeholder", "required", "invalid", "describedBy", "ariaLabel", "inputId", "modelValue"], outputs: ["selectionChange"] }] });
19208
19274
  }
19209
19275
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvMonthCalendarComponent, decorators: [{
19210
19276
  type: Component,
19211
19277
  args: [{ selector: 'jv-month-calendar', standalone: true, imports: [NgTemplateOutlet, JvIconButtonComponent, JvSelectComponent], template: `
19212
19278
  <section class="jv-month-calendar" [attr.aria-label]="resolvedAriaLabel()">
19213
19279
  <div class="jv-month-calendar-toolbar">
19214
- <jv-icon-button
19215
- icon="chevron-left"
19216
- variant="ghost"
19217
- [ariaLabel]="translation.translate('monthCalendar.prevMonth')"
19218
- (click)="shiftMonth(-1)"
19219
- />
19280
+ <div class="jv-month-calendar-nav-group jv-month-calendar-nav-group--start">
19281
+ @if (resolvedNavigation().previousYear) {
19282
+ <jv-icon-button
19283
+ icon="chevrons-left"
19284
+ variant="ghost"
19285
+ [ariaLabel]="translation.translate('monthCalendar.prevYear')"
19286
+ (click)="shiftYear(-1)"
19287
+ />
19288
+ }
19289
+
19290
+ @if (resolvedNavigation().previousMonth) {
19291
+ <jv-icon-button
19292
+ icon="chevron-left"
19293
+ variant="ghost"
19294
+ [ariaLabel]="translation.translate('monthCalendar.prevMonth')"
19295
+ (click)="shiftMonth(-1)"
19296
+ />
19297
+ }
19298
+ </div>
19220
19299
 
19221
19300
  <div class="jv-month-calendar-selects">
19222
19301
  <jv-select
19223
19302
  [options]="monthOptions()"
19303
+ [ariaLabel]="resolvedMonthLabel()"
19224
19304
  [modelValue]="visibleMonth().getMonth().toString()"
19225
19305
  (selectionChange)="handleMonthChange($event)"
19226
19306
  />
19227
19307
  <jv-select
19228
19308
  [options]="yearOptions()"
19309
+ [ariaLabel]="resolvedYearLabel()"
19229
19310
  [modelValue]="visibleMonth().getFullYear().toString()"
19230
19311
  (selectionChange)="handleYearChange($event)"
19231
19312
  />
19232
19313
  </div>
19233
19314
 
19234
- <jv-icon-button
19235
- icon="chevron-right"
19236
- variant="ghost"
19237
- [ariaLabel]="translation.translate('monthCalendar.nextMonth')"
19238
- (click)="shiftMonth(1)"
19239
- />
19315
+ <div class="jv-month-calendar-nav-group jv-month-calendar-nav-group--end">
19316
+ @if (resolvedNavigation().nextMonth) {
19317
+ <jv-icon-button
19318
+ icon="chevron-right"
19319
+ variant="ghost"
19320
+ [ariaLabel]="translation.translate('monthCalendar.nextMonth')"
19321
+ (click)="shiftMonth(1)"
19322
+ />
19323
+ }
19324
+
19325
+ @if (resolvedNavigation().nextYear) {
19326
+ <jv-icon-button
19327
+ icon="chevrons-right"
19328
+ variant="ghost"
19329
+ [ariaLabel]="translation.translate('monthCalendar.nextYear')"
19330
+ (click)="shiftYear(1)"
19331
+ />
19332
+ }
19333
+ </div>
19240
19334
  </div>
19241
19335
 
19242
19336
  <div class="jv-month-calendar-actions">
@@ -19280,8 +19374,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
19280
19374
  }
19281
19375
  </div>
19282
19376
  </section>
19283
- `, styles: [".jv-month-calendar{display:grid;gap:var(--jv-spacing-md);padding:var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-lg);background:var(--jv-color-surface)}.jv-month-calendar-toolbar,.jv-month-calendar-selects,.jv-month-calendar-weekdays,.jv-month-calendar-grid,.jv-month-calendar-actions{display:grid;gap:var(--jv-spacing-sm)}.jv-month-calendar-toolbar{grid-template-columns:auto 1fr auto;align-items:center}.jv-month-calendar-selects{grid-template-columns:1fr 1fr}.jv-month-calendar-actions{justify-content:end}.jv-month-calendar-today{min-height:2.25rem;padding:0 var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:999px;background:var(--jv-color-surface-muted);color:var(--jv-color-foreground);font:inherit;cursor:pointer}.jv-month-calendar-today:hover,.jv-month-calendar-today:focus-visible{border-color:var(--jv-color-primary);outline:none}.jv-month-calendar-weekdays,.jv-month-calendar-grid{grid-template-columns:repeat(7,minmax(0,1fr))}.jv-month-calendar-weekdays span{text-align:center;font-size:.8125rem;font-weight:600;color:var(--jv-color-foreground-muted)}.jv-month-calendar-day{position:relative;min-height:5rem;display:grid;align-content:start;justify-items:start;gap:var(--jv-spacing-xs);padding:var(--jv-spacing-sm);border:1px solid transparent;border-radius:var(--jv-radius-md);background:transparent;color:var(--jv-color-foreground);text-align:left;font:inherit;cursor:pointer;transition:background-color .16s ease,border-color .16s ease,color .16s ease}.jv-month-calendar-day:hover,.jv-month-calendar-day:focus-visible{background:var(--jv-color-surface-muted);outline:none}.jv-month-calendar-day--outside{color:var(--jv-color-foreground-muted)}.jv-month-calendar-day--today{border-color:var(--jv-color-primary)}.jv-month-calendar-day--selected{background:color-mix(in srgb,var(--jv-color-primary) 14%,var(--jv-color-surface));border-color:var(--jv-color-primary)}.jv-month-calendar-day-number{font-weight:700}.jv-month-calendar-day-count,.jv-month-calendar-day-dot{display:inline-flex;align-items:center;justify-content:center;border-radius:999px}.jv-month-calendar-day-count{min-width:1.5rem;min-height:1.5rem;padding:0 .375rem;font-size:.75rem;font-weight:700}.jv-month-calendar-day-dot{width:.5rem;height:.5rem;margin-top:auto}.jv-month-calendar-marker--primary{background:color-mix(in srgb,var(--jv-color-primary) 18%,var(--jv-color-surface));color:var(--jv-color-primary)}.jv-month-calendar-marker--secondary,.jv-month-calendar-marker--neutral{background:var(--jv-color-surface-muted);color:var(--jv-color-foreground)}.jv-month-calendar-marker--success{background:color-mix(in srgb,var(--jv-color-success) 18%,var(--jv-color-surface));color:var(--jv-color-success)}.jv-month-calendar-marker--warning{background:color-mix(in srgb,var(--jv-color-warning) 20%,var(--jv-color-surface));color:#8a4b00}.jv-month-calendar-marker--danger{background:color-mix(in srgb,var(--jv-color-danger) 18%,var(--jv-color-surface));color:var(--jv-color-danger)}.jv-month-calendar-marker--info{background:color-mix(in srgb,var(--jv-color-info) 18%,var(--jv-color-surface));color:var(--jv-color-info)}\n"] }]
19284
- }], ctorParameters: () => [], propDecorators: { gridRootRef: [{ type: i0.ViewChild, args: ['gridRoot', { isSignal: true }] }], customDayTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => JvMonthCalendarDayDirective), { isSignal: true }] }], valueInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], dayMeta: [{ type: i0.Input, args: [{ isSignal: true, alias: "dayMeta", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], visibleMonthChange: [{ type: i0.Output, args: ["visibleMonthChange"] }] } });
19377
+ `, styles: [".jv-month-calendar{display:grid;gap:var(--jv-spacing-md);padding:var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-lg);background:var(--jv-color-surface)}.jv-month-calendar-toolbar,.jv-month-calendar-nav-group,.jv-month-calendar-selects,.jv-month-calendar-weekdays,.jv-month-calendar-grid,.jv-month-calendar-actions{display:grid;gap:var(--jv-spacing-sm)}.jv-month-calendar-toolbar{grid-template-columns:auto 1fr auto;align-items:center}.jv-month-calendar-nav-group{display:inline-flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-month-calendar-nav-group--end{justify-content:end}.jv-month-calendar-selects{grid-template-columns:1fr 1fr}.jv-month-calendar-actions{justify-content:end}.jv-month-calendar-today{min-height:2.25rem;padding:0 var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:999px;background:var(--jv-color-surface-muted);color:var(--jv-color-foreground);font:inherit;cursor:pointer}.jv-month-calendar-today:hover,.jv-month-calendar-today:focus-visible{border-color:var(--jv-color-primary);outline:none}.jv-month-calendar-weekdays,.jv-month-calendar-grid{grid-template-columns:repeat(7,minmax(0,1fr))}.jv-month-calendar-weekdays span{text-align:center;font-size:.8125rem;font-weight:600;color:var(--jv-color-foreground-muted)}.jv-month-calendar-day{position:relative;min-height:5rem;display:grid;align-content:start;justify-items:start;gap:var(--jv-spacing-xs);padding:var(--jv-spacing-sm);border:1px solid transparent;border-radius:var(--jv-radius-md);background:transparent;color:var(--jv-color-foreground);text-align:left;font:inherit;cursor:pointer;transition:background-color .16s ease,border-color .16s ease,color .16s ease}.jv-month-calendar-day:hover,.jv-month-calendar-day:focus-visible{background:var(--jv-color-surface-muted);outline:none}.jv-month-calendar-day--outside{color:var(--jv-color-foreground-muted)}.jv-month-calendar-day--today{border-color:var(--jv-color-primary)}.jv-month-calendar-day--selected{background:color-mix(in srgb,var(--jv-color-primary) 14%,var(--jv-color-surface));border-color:var(--jv-color-primary)}.jv-month-calendar-day-number{font-weight:700}.jv-month-calendar-day-count,.jv-month-calendar-day-dot{display:inline-flex;align-items:center;justify-content:center;border-radius:999px}.jv-month-calendar-day-count{min-width:1.5rem;min-height:1.5rem;padding:0 .375rem;font-size:.75rem;font-weight:700}.jv-month-calendar-day-dot{width:.5rem;height:.5rem;margin-top:auto}.jv-month-calendar-marker--primary{background:color-mix(in srgb,var(--jv-color-primary) 18%,var(--jv-color-surface));color:var(--jv-color-primary)}.jv-month-calendar-marker--secondary,.jv-month-calendar-marker--neutral{background:var(--jv-color-surface-muted);color:var(--jv-color-foreground)}.jv-month-calendar-marker--success{background:color-mix(in srgb,var(--jv-color-success) 18%,var(--jv-color-surface));color:var(--jv-color-success)}.jv-month-calendar-marker--warning{background:color-mix(in srgb,var(--jv-color-warning) 20%,var(--jv-color-surface));color:#8a4b00}.jv-month-calendar-marker--danger{background:color-mix(in srgb,var(--jv-color-danger) 18%,var(--jv-color-surface));color:var(--jv-color-danger)}.jv-month-calendar-marker--info{background:color-mix(in srgb,var(--jv-color-info) 18%,var(--jv-color-surface));color:var(--jv-color-info)}\n"] }]
19378
+ }], ctorParameters: () => [], propDecorators: { gridRootRef: [{ type: i0.ViewChild, args: ['gridRoot', { isSignal: true }] }], customDayTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => JvMonthCalendarDayDirective), { isSignal: true }] }], valueInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], visibleMonthInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "visibleMonth", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], monthLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthLabel", required: false }] }], yearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "yearLabel", required: false }] }], minYear: [{ type: i0.Input, args: [{ isSignal: true, alias: "minYear", required: false }] }], maxYear: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxYear", required: false }] }], navigation: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigation", required: false }] }], dayMeta: [{ type: i0.Input, args: [{ isSignal: true, alias: "dayMeta", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], visibleMonthChange: [{ type: i0.Output, args: ["visibleMonthChange"] }] } });
19285
19379
  function normalizeDate(value) {
19286
19380
  if (!value) {
19287
19381
  return null;
@@ -19289,6 +19383,10 @@ function normalizeDate(value) {
19289
19383
  const date = value instanceof Date ? value : new Date(value);
19290
19384
  return Number.isNaN(date.getTime()) ? null : startOfDay$1(date);
19291
19385
  }
19386
+ function normalizeMonth(value) {
19387
+ const date = normalizeDate(value);
19388
+ return date ? firstOfMonth$1(date) : null;
19389
+ }
19292
19390
  function daysInMonth$1(year, month) {
19293
19391
  return new Date(year, month + 1, 0).getDate();
19294
19392
  }
@@ -20533,6 +20631,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
20533
20631
  class JvDialogComponent {
20534
20632
  document = inject(DOCUMENT);
20535
20633
  panelRef = viewChild('panel', ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
20634
+ previouslyFocusedElement = null;
20536
20635
  open = input(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
20537
20636
  title = input('Dialog', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
20538
20637
  closed = output();
@@ -20541,8 +20640,11 @@ class JvDialogComponent {
20541
20640
  constructor() {
20542
20641
  effect(() => {
20543
20642
  if (this.open()) {
20643
+ this.previouslyFocusedElement = this.document.activeElement instanceof HTMLElement ? this.document.activeElement : null;
20544
20644
  queueMicrotask(() => this.focusInitialElement());
20645
+ return;
20545
20646
  }
20647
+ this.restoreFocus();
20546
20648
  });
20547
20649
  }
20548
20650
  handleDocumentKeydown(event) {
@@ -20569,6 +20671,10 @@ class JvDialogComponent {
20569
20671
  backdropClose() {
20570
20672
  this.closed.emit();
20571
20673
  }
20674
+ restoreFocus() {
20675
+ this.previouslyFocusedElement?.focus();
20676
+ this.previouslyFocusedElement = null;
20677
+ }
20572
20678
  trapFocus(event) {
20573
20679
  const focusable = this.getFocusableElements();
20574
20680
  const panel = this.panelRef()?.nativeElement;
@@ -20600,7 +20706,7 @@ class JvDialogComponent {
20600
20706
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: JvDialogComponent, isStandalone: true, selector: "jv-dialog", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { listeners: { "document:keydown": "handleDocumentKeydown($event)" } }, viewQueries: [{ propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }], ngImport: i0, template: `
20601
20707
  @if (open()) {
20602
20708
  <div class="jv-dialog-backdrop" (click)="backdropClose()">
20603
- <div class="jv-dialog-panel" role="dialog" aria-modal="true" tabindex="-1" [attr.aria-labelledby]="titleId" [attr.aria-describedby]="descriptionId" (click)="$event.stopPropagation()" #panel>
20709
+ <div class="jv-dialog-panel" role="dialog" aria-modal="true" tabindex="-1" [attr.aria-labelledby]="titleId" [attr.aria-describedby]="descriptionId" (click)="$event.stopPropagation()" #panel>
20604
20710
  <header class="jv-dialog-header">
20605
20711
  <h2 [id]="titleId">{{ title() }}</h2>
20606
20712
  </header>
@@ -20622,7 +20728,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
20622
20728
  args: [{ selector: 'jv-dialog', standalone: true, template: `
20623
20729
  @if (open()) {
20624
20730
  <div class="jv-dialog-backdrop" (click)="backdropClose()">
20625
- <div class="jv-dialog-panel" role="dialog" aria-modal="true" tabindex="-1" [attr.aria-labelledby]="titleId" [attr.aria-describedby]="descriptionId" (click)="$event.stopPropagation()" #panel>
20731
+ <div class="jv-dialog-panel" role="dialog" aria-modal="true" tabindex="-1" [attr.aria-labelledby]="titleId" [attr.aria-describedby]="descriptionId" (click)="$event.stopPropagation()" #panel>
20626
20732
  <header class="jv-dialog-header">
20627
20733
  <h2 [id]="titleId">{{ title() }}</h2>
20628
20734
  </header>
@@ -20932,7 +21038,7 @@ class JvDatePickerComponent {
20932
21038
  <jv-button variant="outline" (click)="closeDialog()">{{ translation.translate('datePicker.close') }}</jv-button>
20933
21039
  </div>
20934
21040
  </jv-dialog>
20935
- `, isInline: true, styles: [".jv-date-picker-trigger{width:100%;min-height:var(--jv-density-control-height);display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-sm);padding:0 var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);background:var(--jv-color-surface);color:var(--jv-color-foreground);text-align:left;font:inherit;cursor:pointer}.jv-date-picker-trigger.is-invalid{border-color:var(--jv-color-danger)}.jv-date-picker-trigger:disabled{opacity:.7;cursor:not-allowed}.jv-date-picker-trigger:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:1px}.jv-date-picker-placeholder{color:var(--jv-color-foreground-muted)}.jv-date-picker-dialog,.jv-date-picker-actions{display:grid;gap:var(--jv-spacing-md)}.jv-date-picker-toolbar,.jv-date-picker-selects,.jv-date-picker-weekdays,.jv-date-picker-grid{display:grid;gap:var(--jv-spacing-sm)}.jv-date-picker-toolbar{grid-template-columns:auto 1fr auto;align-items:center}.jv-date-picker-selects{grid-template-columns:1fr 1fr}.jv-date-picker-weekdays,.jv-date-picker-grid{grid-template-columns:repeat(7,minmax(0,1fr))}.jv-date-picker-weekdays span{text-align:center;font-size:.8125rem;font-weight:600;color:var(--jv-color-foreground-muted)}.jv-date-picker-day{min-height:2.5rem;border:1px solid transparent;border-radius:var(--jv-radius-md);background:transparent;color:var(--jv-color-foreground);font:inherit;cursor:pointer;transition:background-color .16s ease,border-color .16s ease,color .16s ease}.jv-date-picker-day:hover,.jv-date-picker-day:focus-visible{background:var(--jv-color-surface-muted)}.jv-date-picker-day:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:1px}.jv-date-picker-day--outside{color:var(--jv-color-foreground-muted)}.jv-date-picker-day--today{border-color:var(--jv-color-primary)}.jv-date-picker-day--selected{background:var(--jv-color-primary);color:#fff}\n"], dependencies: [{ kind: "component", type: JvButtonComponent, selector: "jv-button", inputs: ["type", "variant", "icon", "iconPosition", "loading", "disabled"] }, { kind: "component", type: JvDialogComponent, selector: "jv-dialog", inputs: ["open", "title"], outputs: ["closed"] }, { kind: "component", type: JvFormContainerComponent, selector: "jv-form-container", inputs: ["label", "hint", "error", "inputId", "hintId", "errorId", "required", "invalid"] }, { kind: "component", type: JvIconButtonComponent, selector: "jv-icon-button", inputs: ["icon", "ariaLabel", "variant", "disabled"] }, { kind: "component", type: JvIconComponent, selector: "jv-icon", inputs: ["name", "size", "strokeWidth", "decorative", "ariaLabel"] }, { kind: "component", type: JvSelectComponent, selector: "jv-select", inputs: ["options", "placeholder", "required", "invalid", "describedBy", "inputId", "modelValue"], outputs: ["selectionChange"] }] });
21041
+ `, isInline: true, styles: [".jv-date-picker-trigger{width:100%;min-height:var(--jv-density-control-height);display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-sm);padding:0 var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);background:var(--jv-color-surface);color:var(--jv-color-foreground);text-align:left;font:inherit;cursor:pointer}.jv-date-picker-trigger.is-invalid{border-color:var(--jv-color-danger)}.jv-date-picker-trigger:disabled{opacity:.7;cursor:not-allowed}.jv-date-picker-trigger:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:1px}.jv-date-picker-placeholder{color:var(--jv-color-foreground-muted)}.jv-date-picker-dialog,.jv-date-picker-actions{display:grid;gap:var(--jv-spacing-md)}.jv-date-picker-toolbar,.jv-date-picker-selects,.jv-date-picker-weekdays,.jv-date-picker-grid{display:grid;gap:var(--jv-spacing-sm)}.jv-date-picker-toolbar{grid-template-columns:auto 1fr auto;align-items:center}.jv-date-picker-selects{grid-template-columns:1fr 1fr}.jv-date-picker-weekdays,.jv-date-picker-grid{grid-template-columns:repeat(7,minmax(0,1fr))}.jv-date-picker-weekdays span{text-align:center;font-size:.8125rem;font-weight:600;color:var(--jv-color-foreground-muted)}.jv-date-picker-day{min-height:2.5rem;border:1px solid transparent;border-radius:var(--jv-radius-md);background:transparent;color:var(--jv-color-foreground);font:inherit;cursor:pointer;transition:background-color .16s ease,border-color .16s ease,color .16s ease}.jv-date-picker-day:hover,.jv-date-picker-day:focus-visible{background:var(--jv-color-surface-muted)}.jv-date-picker-day:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:1px}.jv-date-picker-day--outside{color:var(--jv-color-foreground-muted)}.jv-date-picker-day--today{border-color:var(--jv-color-primary)}.jv-date-picker-day--selected{background:var(--jv-color-primary);color:#fff}\n"], dependencies: [{ kind: "component", type: JvButtonComponent, selector: "jv-button", inputs: ["type", "variant", "icon", "iconPosition", "loading", "disabled"] }, { kind: "component", type: JvDialogComponent, selector: "jv-dialog", inputs: ["open", "title"], outputs: ["closed"] }, { kind: "component", type: JvFormContainerComponent, selector: "jv-form-container", inputs: ["label", "hint", "error", "inputId", "hintId", "errorId", "required", "invalid"] }, { kind: "component", type: JvIconButtonComponent, selector: "jv-icon-button", inputs: ["icon", "ariaLabel", "variant", "disabled"] }, { kind: "component", type: JvIconComponent, selector: "jv-icon", inputs: ["name", "size", "strokeWidth", "decorative", "ariaLabel"] }, { kind: "component", type: JvSelectComponent, selector: "jv-select", inputs: ["options", "placeholder", "required", "invalid", "describedBy", "ariaLabel", "inputId", "modelValue"], outputs: ["selectionChange"] }] });
20936
21042
  }
20937
21043
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvDatePickerComponent, decorators: [{
20938
21044
  type: Component,
@@ -21212,7 +21318,7 @@ class JvFileInputComponent {
21212
21318
  [class.jv-file-input-dropzone--dragover]="dragActive()"
21213
21319
  [class.jv-file-input-dropzone--invalid]="invalid()"
21214
21320
  role="button"
21215
- tabindex="0"
21321
+ [attr.tabindex]="disabled() ? -1 : 0"
21216
21322
  [attr.aria-disabled]="disabled() ? 'true' : 'false'"
21217
21323
  [attr.aria-label]="dropzoneAriaLabel()"
21218
21324
  (click)="openFileDialog()"
@@ -21287,7 +21393,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
21287
21393
  [class.jv-file-input-dropzone--dragover]="dragActive()"
21288
21394
  [class.jv-file-input-dropzone--invalid]="invalid()"
21289
21395
  role="button"
21290
- tabindex="0"
21396
+ [attr.tabindex]="disabled() ? -1 : 0"
21291
21397
  [attr.aria-disabled]="disabled() ? 'true' : 'false'"
21292
21398
  [attr.aria-label]="dropzoneAriaLabel()"
21293
21399
  (click)="openFileDialog()"
@@ -21335,6 +21441,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
21335
21441
  }], propDecorators: { nativeInputRef: [{ type: i0.ViewChild, args: ['nativeInput', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], describedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "describedBy", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], maxFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFiles", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], filesInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "files", required: false }] }], filesChange: [{ type: i0.Output, args: ["filesChange"] }], filesRejected: [{ type: i0.Output, args: ["filesRejected"] }] } });
21336
21442
 
21337
21443
  class JvListComponent {
21444
+ listId = input('', ...(ngDevMode ? [{ debugName: "listId" }] : /* istanbul ignore next */ []));
21338
21445
  role = input('list', ...(ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []));
21339
21446
  ariaRole = input(null, ...(ngDevMode ? [{ debugName: "ariaRole" }] : /* istanbul ignore next */ []));
21340
21447
  variant = input(null, ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
@@ -21345,13 +21452,14 @@ class JvListComponent {
21345
21452
  }, ...(ngDevMode ? [{ debugName: "variantClass" }] : /* istanbul ignore next */ []));
21346
21453
  resolvedRole = computed(() => this.ariaRole() ?? (this.role() === 'navigation' ? 'list' : null), ...(ngDevMode ? [{ debugName: "resolvedRole" }] : /* istanbul ignore next */ []));
21347
21454
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
21348
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.17", type: JvListComponent, isStandalone: true, selector: "jv-list", inputs: { role: { classPropertyName: "role", publicName: "role", isSignal: true, isRequired: false, transformFunction: null }, ariaRole: { classPropertyName: "ariaRole", publicName: "ariaRole", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
21349
- <ul
21350
- class="jv-list"
21351
- [class]="variantClass()"
21352
- [attr.role]="resolvedRole()"
21353
- [attr.aria-label]="ariaLabel()"
21354
- >
21455
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.17", type: JvListComponent, isStandalone: true, selector: "jv-list", inputs: { listId: { classPropertyName: "listId", publicName: "listId", isSignal: true, isRequired: false, transformFunction: null }, role: { classPropertyName: "role", publicName: "role", isSignal: true, isRequired: false, transformFunction: null }, ariaRole: { classPropertyName: "ariaRole", publicName: "ariaRole", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
21456
+ <ul
21457
+ [id]="listId() || null"
21458
+ class="jv-list"
21459
+ [class]="variantClass()"
21460
+ [attr.role]="resolvedRole()"
21461
+ [attr.aria-label]="ariaLabel()"
21462
+ >
21355
21463
  <ng-content />
21356
21464
  </ul>
21357
21465
  `, isInline: true, styles: [".jv-list{display:block;list-style:none;margin:0;padding:0}.jv-list>:not(:last-child){border-bottom:1px solid var(--jv-color-border)}.jv-list--bordered{border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md)}\n"] });
@@ -21359,16 +21467,17 @@ class JvListComponent {
21359
21467
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvListComponent, decorators: [{
21360
21468
  type: Component,
21361
21469
  args: [{ selector: 'jv-list', standalone: true, template: `
21362
- <ul
21363
- class="jv-list"
21364
- [class]="variantClass()"
21365
- [attr.role]="resolvedRole()"
21366
- [attr.aria-label]="ariaLabel()"
21367
- >
21470
+ <ul
21471
+ [id]="listId() || null"
21472
+ class="jv-list"
21473
+ [class]="variantClass()"
21474
+ [attr.role]="resolvedRole()"
21475
+ [attr.aria-label]="ariaLabel()"
21476
+ >
21368
21477
  <ng-content />
21369
21478
  </ul>
21370
21479
  `, styles: [".jv-list{display:block;list-style:none;margin:0;padding:0}.jv-list>:not(:last-child){border-bottom:1px solid var(--jv-color-border)}.jv-list--bordered{border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md)}\n"] }]
21371
- }], propDecorators: { role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: false }] }], ariaRole: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaRole", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
21480
+ }], propDecorators: { listId: [{ type: i0.Input, args: [{ isSignal: true, alias: "listId", required: false }] }], role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: false }] }], ariaRole: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaRole", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
21372
21481
 
21373
21482
  let modalSelectorIdSequence = 0;
21374
21483
  class JvModalSelectorComponent {
@@ -21398,6 +21507,8 @@ class JvModalSelectorComponent {
21398
21507
  dialogOpen = signal(false, ...(ngDevMode ? [{ debugName: "dialogOpen" }] : /* istanbul ignore next */ []));
21399
21508
  searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : /* istanbul ignore next */ []));
21400
21509
  dialogId = `jv-modal-selector-dialog-${this.instanceId}`;
21510
+ listboxId = `jv-modal-selector-listbox-${this.instanceId}`;
21511
+ resultsId = `jv-modal-selector-results-${this.instanceId}`;
21401
21512
  searchInputId = `jv-modal-selector-search-${this.instanceId}`;
21402
21513
  value = null;
21403
21514
  disabled = false;
@@ -21531,100 +21642,102 @@ class JvModalSelectorComponent {
21531
21642
  useExisting: forwardRef(() => JvModalSelectorComponent),
21532
21643
  multi: true,
21533
21644
  },
21534
- ], viewQueries: [{ propertyName: "triggerButtonRef", first: true, predicate: ["triggerButton"], descendants: true, isSignal: true }, { propertyName: "optionElements", predicate: ["optionElement"], descendants: true, isSignal: true }], ngImport: i0, template: `
21535
- <jv-form-container
21536
- [label]="label()"
21537
- [inputId]="inputId()"
21538
- [required]="required()"
21539
- [invalid]="invalid()"
21540
- [hint]="hint()"
21541
- [error]="error()"
21542
- >
21543
- <button
21544
- #triggerButton
21545
- type="button"
21546
- class="jv-modal-selector-trigger"
21547
- [class.is-invalid]="invalid()"
21548
- [id]="inputId()"
21549
- [disabled]="disabled"
21550
- [attr.aria-haspopup]="'dialog'"
21551
- [attr.aria-expanded]="dialogOpen() ? 'true' : 'false'"
21552
- [attr.aria-controls]="dialogId"
21553
- [attr.aria-invalid]="invalid() ? 'true' : null"
21554
- [attr.aria-describedby]="describedBy() || null"
21555
- [attr.aria-label]="triggerAriaLabel()"
21556
- (click)="openDialog()"
21557
- (blur)="handleBlur()"
21558
- >
21559
- <span class="jv-modal-selector-trigger-copy">
21560
- <span [class.jv-modal-selector-trigger-placeholder]="!selectedOption()">
21561
- {{ selectedOption()?.label ?? resolvedPlaceholder() }}
21562
- </span>
21563
- </span>
21564
- <jv-icon name="chevrons-up-down" [size]="18" />
21565
- </button>
21566
- </jv-form-container>
21567
-
21568
- <jv-dialog [open]="dialogOpen()" [title]="resolvedDialogTitle()" (closed)="closeDialog()">
21569
- <div [id]="dialogId" class="jv-modal-selector-dialog">
21570
- @if (dialogSubtitle()) {
21571
- <p class="jv-modal-selector-subtitle">{{ dialogSubtitle() }}</p>
21572
- }
21573
-
21574
- @if (showSearch()) {
21575
- <jv-input
21576
- type="search"
21577
- [inputId]="searchInputId"
21578
- [placeholder]="searchPlaceholder() || translation.translate('modalSelector.searchPlaceholder')"
21579
- [ngModel]="searchQuery()"
21580
- (ngModelChange)="searchQuery.set($event)"
21581
- />
21582
- }
21583
-
21584
- <p class="jv-modal-selector-results" aria-live="polite">{{ resultsLabel() }}</p>
21585
-
21586
- @if (filteredOptions().length > 0) {
21587
- <jv-list variant="bordered" [ariaRole]="'listbox'" [ariaLabel]="resolvedDialogTitle()">
21588
- @for (option of filteredOptions(); track option.value; let index = $index) {
21589
- <li role="presentation">
21590
- <div
21591
- #optionElement
21592
- class="jv-modal-selector-option"
21593
- [class.jv-modal-selector-option--selected]="isSelected(option)"
21594
- [class.jv-modal-selector-option--disabled]="option.disabled ?? false"
21595
- [id]="optionId(index)"
21596
- role="option"
21597
- [attr.aria-selected]="isSelected(option) ? 'true' : 'false'"
21598
- [attr.tabindex]="getOptionTabIndex(option, index)"
21599
- (click)="selectOption(option)"
21600
- (keydown)="handleOptionKeydown($event, index, option)"
21601
- >
21602
- <div class="jv-modal-selector-option-copy">
21603
- <span class="jv-modal-selector-option-label">{{ option.label }}</span>
21604
- @if (option.description) {
21605
- <span class="jv-modal-selector-option-description">{{ option.description }}</span>
21606
- }
21607
- </div>
21608
- @if (isSelected(option)) {
21609
- <jv-icon name="check" [size]="16" />
21610
- }
21611
- </div>
21612
- </li>
21613
- }
21614
- </jv-list>
21615
- } @else {
21616
- <div class="jv-modal-selector-empty" aria-live="polite">{{ emptyMessage() || translation.translate('modalSelector.emptyMessage') }}</div>
21617
- }
21618
- </div>
21619
-
21620
- <div dialog-actions class="jv-modal-selector-actions">
21621
- @if (selectedOption()) {
21622
- <jv-button variant="ghost" (click)="clearSelection()">{{ clearLabel() || translation.translate('modalSelector.clear') }}</jv-button>
21623
- }
21624
- <jv-button variant="outline" (click)="closeDialog()">{{ closeLabel() || translation.translate('modalSelector.close') }}</jv-button>
21625
- </div>
21626
- </jv-dialog>
21627
- `, isInline: true, styles: [".jv-modal-selector-trigger{width:100%;min-height:var(--jv-density-control-height);display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-sm);padding:0 var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);background:var(--jv-color-surface);color:var(--jv-color-foreground);text-align:left;font:inherit;cursor:pointer}.jv-modal-selector-trigger.is-invalid{border-color:var(--jv-color-danger)}.jv-modal-selector-trigger:disabled{opacity:.7;cursor:not-allowed}.jv-modal-selector-trigger:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:1px}.jv-modal-selector-trigger-copy{min-width:0;flex:1}.jv-modal-selector-trigger-placeholder{color:var(--jv-color-foreground-muted)}.jv-modal-selector-dialog,.jv-modal-selector-actions{display:grid;gap:var(--jv-spacing-md)}.jv-modal-selector-subtitle,.jv-modal-selector-results,.jv-modal-selector-option-description,.jv-modal-selector-empty{margin:0;color:var(--jv-color-foreground-muted)}.jv-modal-selector-empty{padding:var(--jv-spacing-md);border:1px dashed var(--jv-color-border);border-radius:var(--jv-radius-md);text-align:center}.jv-modal-selector-option{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);padding:var(--jv-spacing-md);background:var(--jv-color-surface);cursor:pointer;outline:none;transition:background-color .16s ease}.jv-modal-selector-option:hover,.jv-modal-selector-option:focus-visible{background:var(--jv-color-surface-muted)}.jv-modal-selector-option:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-modal-selector-option--selected{background:color-mix(in srgb,var(--jv-color-primary) 8%,var(--jv-color-surface))}.jv-modal-selector-option--disabled{opacity:.55;cursor:not-allowed;pointer-events:none}.jv-modal-selector-option-copy{min-width:0;display:grid;gap:.25rem}.jv-modal-selector-option-label{font-weight:600;color:var(--jv-color-foreground)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: JvButtonComponent, selector: "jv-button", inputs: ["type", "variant", "icon", "iconPosition", "loading", "disabled"] }, { kind: "component", type: JvDialogComponent, selector: "jv-dialog", inputs: ["open", "title"], outputs: ["closed"] }, { kind: "component", type: JvFormContainerComponent, selector: "jv-form-container", inputs: ["label", "hint", "error", "inputId", "hintId", "errorId", "required", "invalid"] }, { kind: "component", type: JvIconComponent, selector: "jv-icon", inputs: ["name", "size", "strokeWidth", "decorative", "ariaLabel"] }, { kind: "component", type: JvInputComponent, selector: "jv-input", inputs: ["type", "placeholder", "required", "invalid", "describedBy", "inputId"] }, { kind: "component", type: JvListComponent, selector: "jv-list", inputs: ["role", "ariaRole", "variant", "ariaLabel"] }] });
21645
+ ], viewQueries: [{ propertyName: "triggerButtonRef", first: true, predicate: ["triggerButton"], descendants: true, isSignal: true }, { propertyName: "optionElements", predicate: ["optionElement"], descendants: true, isSignal: true }], ngImport: i0, template: `
21646
+ <jv-form-container
21647
+ [label]="label()"
21648
+ [inputId]="inputId()"
21649
+ [required]="required()"
21650
+ [invalid]="invalid()"
21651
+ [hint]="hint()"
21652
+ [error]="error()"
21653
+ >
21654
+ <button
21655
+ #triggerButton
21656
+ type="button"
21657
+ class="jv-modal-selector-trigger"
21658
+ [class.is-invalid]="invalid()"
21659
+ [id]="inputId()"
21660
+ [disabled]="disabled"
21661
+ [attr.aria-haspopup]="'dialog'"
21662
+ [attr.aria-expanded]="dialogOpen() ? 'true' : 'false'"
21663
+ [attr.aria-controls]="dialogId"
21664
+ [attr.aria-invalid]="invalid() ? 'true' : null"
21665
+ [attr.aria-describedby]="describedBy() || null"
21666
+ [attr.aria-label]="triggerAriaLabel()"
21667
+ (click)="openDialog()"
21668
+ (blur)="handleBlur()"
21669
+ >
21670
+ <span class="jv-modal-selector-trigger-copy">
21671
+ <span [class.jv-modal-selector-trigger-placeholder]="!selectedOption()">
21672
+ {{ selectedOption()?.label ?? resolvedPlaceholder() }}
21673
+ </span>
21674
+ </span>
21675
+ <jv-icon name="chevrons-up-down" [size]="18" />
21676
+ </button>
21677
+ </jv-form-container>
21678
+
21679
+ <jv-dialog [open]="dialogOpen()" [title]="resolvedDialogTitle()" (closed)="closeDialog()">
21680
+ <div [id]="dialogId" class="jv-modal-selector-dialog">
21681
+ @if (dialogSubtitle()) {
21682
+ <p class="jv-modal-selector-subtitle">{{ dialogSubtitle() }}</p>
21683
+ }
21684
+
21685
+ @if (showSearch()) {
21686
+ <jv-input
21687
+ type="search"
21688
+ [inputId]="searchInputId"
21689
+ [placeholder]="searchPlaceholder() || translation.translate('modalSelector.searchPlaceholder')"
21690
+ [describedBy]="resultsId"
21691
+ [ngModel]="searchQuery()"
21692
+ (ngModelChange)="searchQuery.set($event)"
21693
+ />
21694
+ }
21695
+
21696
+ <p class="jv-modal-selector-results" [id]="resultsId" aria-live="polite">{{ resultsLabel() }}</p>
21697
+
21698
+ @if (filteredOptions().length > 0) {
21699
+ <jv-list [listId]="listboxId" variant="bordered" [ariaRole]="'listbox'" [ariaLabel]="resolvedDialogTitle()">
21700
+ @for (option of filteredOptions(); track option.value; let index = $index) {
21701
+ <li role="presentation">
21702
+ <div
21703
+ #optionElement
21704
+ class="jv-modal-selector-option"
21705
+ [class.jv-modal-selector-option--selected]="isSelected(option)"
21706
+ [class.jv-modal-selector-option--disabled]="option.disabled ?? false"
21707
+ [id]="optionId(index)"
21708
+ role="option"
21709
+ [attr.aria-selected]="isSelected(option) ? 'true' : 'false'"
21710
+ [attr.aria-disabled]="option.disabled ? 'true' : null"
21711
+ [attr.tabindex]="getOptionTabIndex(option, index)"
21712
+ (click)="selectOption(option)"
21713
+ (keydown)="handleOptionKeydown($event, index, option)"
21714
+ >
21715
+ <div class="jv-modal-selector-option-copy">
21716
+ <span class="jv-modal-selector-option-label">{{ option.label }}</span>
21717
+ @if (option.description) {
21718
+ <span class="jv-modal-selector-option-description">{{ option.description }}</span>
21719
+ }
21720
+ </div>
21721
+ @if (isSelected(option)) {
21722
+ <jv-icon name="check" [size]="16" />
21723
+ }
21724
+ </div>
21725
+ </li>
21726
+ }
21727
+ </jv-list>
21728
+ } @else {
21729
+ <div class="jv-modal-selector-empty" aria-live="polite">{{ emptyMessage() || translation.translate('modalSelector.emptyMessage') }}</div>
21730
+ }
21731
+ </div>
21732
+
21733
+ <div dialog-actions class="jv-modal-selector-actions">
21734
+ @if (selectedOption()) {
21735
+ <jv-button variant="ghost" (click)="clearSelection()">{{ clearLabel() || translation.translate('modalSelector.clear') }}</jv-button>
21736
+ }
21737
+ <jv-button variant="outline" (click)="closeDialog()">{{ closeLabel() || translation.translate('modalSelector.close') }}</jv-button>
21738
+ </div>
21739
+ </jv-dialog>
21740
+ `, isInline: true, styles: [".jv-modal-selector-trigger{width:100%;min-height:var(--jv-density-control-height);display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-sm);padding:0 var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);background:var(--jv-color-surface);color:var(--jv-color-foreground);text-align:left;font:inherit;cursor:pointer}.jv-modal-selector-trigger.is-invalid{border-color:var(--jv-color-danger)}.jv-modal-selector-trigger:disabled{opacity:.7;cursor:not-allowed}.jv-modal-selector-trigger:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:1px}.jv-modal-selector-trigger-copy{min-width:0;flex:1}.jv-modal-selector-trigger-placeholder{color:var(--jv-color-foreground-muted)}.jv-modal-selector-dialog,.jv-modal-selector-actions{display:grid;gap:var(--jv-spacing-md)}.jv-modal-selector-subtitle,.jv-modal-selector-results,.jv-modal-selector-option-description,.jv-modal-selector-empty{margin:0;color:var(--jv-color-foreground-muted)}.jv-modal-selector-empty{padding:var(--jv-spacing-md);border:1px dashed var(--jv-color-border);border-radius:var(--jv-radius-md);text-align:center}.jv-modal-selector-option{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);padding:var(--jv-spacing-md);background:var(--jv-color-surface);cursor:pointer;outline:none;transition:background-color .16s ease}.jv-modal-selector-option:hover,.jv-modal-selector-option:focus-visible{background:var(--jv-color-surface-muted)}.jv-modal-selector-option:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-modal-selector-option--selected{background:color-mix(in srgb,var(--jv-color-primary) 8%,var(--jv-color-surface))}.jv-modal-selector-option--disabled{opacity:.55;cursor:not-allowed;pointer-events:none}.jv-modal-selector-option-copy{min-width:0;display:grid;gap:.25rem}.jv-modal-selector-option-label{font-weight:600;color:var(--jv-color-foreground)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: JvButtonComponent, selector: "jv-button", inputs: ["type", "variant", "icon", "iconPosition", "loading", "disabled"] }, { kind: "component", type: JvDialogComponent, selector: "jv-dialog", inputs: ["open", "title"], outputs: ["closed"] }, { kind: "component", type: JvFormContainerComponent, selector: "jv-form-container", inputs: ["label", "hint", "error", "inputId", "hintId", "errorId", "required", "invalid"] }, { kind: "component", type: JvIconComponent, selector: "jv-icon", inputs: ["name", "size", "strokeWidth", "decorative", "ariaLabel"] }, { kind: "component", type: JvInputComponent, selector: "jv-input", inputs: ["type", "placeholder", "required", "invalid", "describedBy", "inputId"] }, { kind: "component", type: JvListComponent, selector: "jv-list", inputs: ["listId", "role", "ariaRole", "variant", "ariaLabel"] }] });
21628
21741
  }
21629
21742
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvModalSelectorComponent, decorators: [{
21630
21743
  type: Component,
@@ -21634,99 +21747,101 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
21634
21747
  useExisting: forwardRef(() => JvModalSelectorComponent),
21635
21748
  multi: true,
21636
21749
  },
21637
- ], template: `
21638
- <jv-form-container
21639
- [label]="label()"
21640
- [inputId]="inputId()"
21641
- [required]="required()"
21642
- [invalid]="invalid()"
21643
- [hint]="hint()"
21644
- [error]="error()"
21645
- >
21646
- <button
21647
- #triggerButton
21648
- type="button"
21649
- class="jv-modal-selector-trigger"
21650
- [class.is-invalid]="invalid()"
21651
- [id]="inputId()"
21652
- [disabled]="disabled"
21653
- [attr.aria-haspopup]="'dialog'"
21654
- [attr.aria-expanded]="dialogOpen() ? 'true' : 'false'"
21655
- [attr.aria-controls]="dialogId"
21656
- [attr.aria-invalid]="invalid() ? 'true' : null"
21657
- [attr.aria-describedby]="describedBy() || null"
21658
- [attr.aria-label]="triggerAriaLabel()"
21659
- (click)="openDialog()"
21660
- (blur)="handleBlur()"
21661
- >
21662
- <span class="jv-modal-selector-trigger-copy">
21663
- <span [class.jv-modal-selector-trigger-placeholder]="!selectedOption()">
21664
- {{ selectedOption()?.label ?? resolvedPlaceholder() }}
21665
- </span>
21666
- </span>
21667
- <jv-icon name="chevrons-up-down" [size]="18" />
21668
- </button>
21669
- </jv-form-container>
21670
-
21671
- <jv-dialog [open]="dialogOpen()" [title]="resolvedDialogTitle()" (closed)="closeDialog()">
21672
- <div [id]="dialogId" class="jv-modal-selector-dialog">
21673
- @if (dialogSubtitle()) {
21674
- <p class="jv-modal-selector-subtitle">{{ dialogSubtitle() }}</p>
21675
- }
21676
-
21677
- @if (showSearch()) {
21678
- <jv-input
21679
- type="search"
21680
- [inputId]="searchInputId"
21681
- [placeholder]="searchPlaceholder() || translation.translate('modalSelector.searchPlaceholder')"
21682
- [ngModel]="searchQuery()"
21683
- (ngModelChange)="searchQuery.set($event)"
21684
- />
21685
- }
21686
-
21687
- <p class="jv-modal-selector-results" aria-live="polite">{{ resultsLabel() }}</p>
21688
-
21689
- @if (filteredOptions().length > 0) {
21690
- <jv-list variant="bordered" [ariaRole]="'listbox'" [ariaLabel]="resolvedDialogTitle()">
21691
- @for (option of filteredOptions(); track option.value; let index = $index) {
21692
- <li role="presentation">
21693
- <div
21694
- #optionElement
21695
- class="jv-modal-selector-option"
21696
- [class.jv-modal-selector-option--selected]="isSelected(option)"
21697
- [class.jv-modal-selector-option--disabled]="option.disabled ?? false"
21698
- [id]="optionId(index)"
21699
- role="option"
21700
- [attr.aria-selected]="isSelected(option) ? 'true' : 'false'"
21701
- [attr.tabindex]="getOptionTabIndex(option, index)"
21702
- (click)="selectOption(option)"
21703
- (keydown)="handleOptionKeydown($event, index, option)"
21704
- >
21705
- <div class="jv-modal-selector-option-copy">
21706
- <span class="jv-modal-selector-option-label">{{ option.label }}</span>
21707
- @if (option.description) {
21708
- <span class="jv-modal-selector-option-description">{{ option.description }}</span>
21709
- }
21710
- </div>
21711
- @if (isSelected(option)) {
21712
- <jv-icon name="check" [size]="16" />
21713
- }
21714
- </div>
21715
- </li>
21716
- }
21717
- </jv-list>
21718
- } @else {
21719
- <div class="jv-modal-selector-empty" aria-live="polite">{{ emptyMessage() || translation.translate('modalSelector.emptyMessage') }}</div>
21720
- }
21721
- </div>
21722
-
21723
- <div dialog-actions class="jv-modal-selector-actions">
21724
- @if (selectedOption()) {
21725
- <jv-button variant="ghost" (click)="clearSelection()">{{ clearLabel() || translation.translate('modalSelector.clear') }}</jv-button>
21726
- }
21727
- <jv-button variant="outline" (click)="closeDialog()">{{ closeLabel() || translation.translate('modalSelector.close') }}</jv-button>
21728
- </div>
21729
- </jv-dialog>
21750
+ ], template: `
21751
+ <jv-form-container
21752
+ [label]="label()"
21753
+ [inputId]="inputId()"
21754
+ [required]="required()"
21755
+ [invalid]="invalid()"
21756
+ [hint]="hint()"
21757
+ [error]="error()"
21758
+ >
21759
+ <button
21760
+ #triggerButton
21761
+ type="button"
21762
+ class="jv-modal-selector-trigger"
21763
+ [class.is-invalid]="invalid()"
21764
+ [id]="inputId()"
21765
+ [disabled]="disabled"
21766
+ [attr.aria-haspopup]="'dialog'"
21767
+ [attr.aria-expanded]="dialogOpen() ? 'true' : 'false'"
21768
+ [attr.aria-controls]="dialogId"
21769
+ [attr.aria-invalid]="invalid() ? 'true' : null"
21770
+ [attr.aria-describedby]="describedBy() || null"
21771
+ [attr.aria-label]="triggerAriaLabel()"
21772
+ (click)="openDialog()"
21773
+ (blur)="handleBlur()"
21774
+ >
21775
+ <span class="jv-modal-selector-trigger-copy">
21776
+ <span [class.jv-modal-selector-trigger-placeholder]="!selectedOption()">
21777
+ {{ selectedOption()?.label ?? resolvedPlaceholder() }}
21778
+ </span>
21779
+ </span>
21780
+ <jv-icon name="chevrons-up-down" [size]="18" />
21781
+ </button>
21782
+ </jv-form-container>
21783
+
21784
+ <jv-dialog [open]="dialogOpen()" [title]="resolvedDialogTitle()" (closed)="closeDialog()">
21785
+ <div [id]="dialogId" class="jv-modal-selector-dialog">
21786
+ @if (dialogSubtitle()) {
21787
+ <p class="jv-modal-selector-subtitle">{{ dialogSubtitle() }}</p>
21788
+ }
21789
+
21790
+ @if (showSearch()) {
21791
+ <jv-input
21792
+ type="search"
21793
+ [inputId]="searchInputId"
21794
+ [placeholder]="searchPlaceholder() || translation.translate('modalSelector.searchPlaceholder')"
21795
+ [describedBy]="resultsId"
21796
+ [ngModel]="searchQuery()"
21797
+ (ngModelChange)="searchQuery.set($event)"
21798
+ />
21799
+ }
21800
+
21801
+ <p class="jv-modal-selector-results" [id]="resultsId" aria-live="polite">{{ resultsLabel() }}</p>
21802
+
21803
+ @if (filteredOptions().length > 0) {
21804
+ <jv-list [listId]="listboxId" variant="bordered" [ariaRole]="'listbox'" [ariaLabel]="resolvedDialogTitle()">
21805
+ @for (option of filteredOptions(); track option.value; let index = $index) {
21806
+ <li role="presentation">
21807
+ <div
21808
+ #optionElement
21809
+ class="jv-modal-selector-option"
21810
+ [class.jv-modal-selector-option--selected]="isSelected(option)"
21811
+ [class.jv-modal-selector-option--disabled]="option.disabled ?? false"
21812
+ [id]="optionId(index)"
21813
+ role="option"
21814
+ [attr.aria-selected]="isSelected(option) ? 'true' : 'false'"
21815
+ [attr.aria-disabled]="option.disabled ? 'true' : null"
21816
+ [attr.tabindex]="getOptionTabIndex(option, index)"
21817
+ (click)="selectOption(option)"
21818
+ (keydown)="handleOptionKeydown($event, index, option)"
21819
+ >
21820
+ <div class="jv-modal-selector-option-copy">
21821
+ <span class="jv-modal-selector-option-label">{{ option.label }}</span>
21822
+ @if (option.description) {
21823
+ <span class="jv-modal-selector-option-description">{{ option.description }}</span>
21824
+ }
21825
+ </div>
21826
+ @if (isSelected(option)) {
21827
+ <jv-icon name="check" [size]="16" />
21828
+ }
21829
+ </div>
21830
+ </li>
21831
+ }
21832
+ </jv-list>
21833
+ } @else {
21834
+ <div class="jv-modal-selector-empty" aria-live="polite">{{ emptyMessage() || translation.translate('modalSelector.emptyMessage') }}</div>
21835
+ }
21836
+ </div>
21837
+
21838
+ <div dialog-actions class="jv-modal-selector-actions">
21839
+ @if (selectedOption()) {
21840
+ <jv-button variant="ghost" (click)="clearSelection()">{{ clearLabel() || translation.translate('modalSelector.clear') }}</jv-button>
21841
+ }
21842
+ <jv-button variant="outline" (click)="closeDialog()">{{ closeLabel() || translation.translate('modalSelector.close') }}</jv-button>
21843
+ </div>
21844
+ </jv-dialog>
21730
21845
  `, styles: [".jv-modal-selector-trigger{width:100%;min-height:var(--jv-density-control-height);display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-sm);padding:0 var(--jv-spacing-md);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);background:var(--jv-color-surface);color:var(--jv-color-foreground);text-align:left;font:inherit;cursor:pointer}.jv-modal-selector-trigger.is-invalid{border-color:var(--jv-color-danger)}.jv-modal-selector-trigger:disabled{opacity:.7;cursor:not-allowed}.jv-modal-selector-trigger:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:1px}.jv-modal-selector-trigger-copy{min-width:0;flex:1}.jv-modal-selector-trigger-placeholder{color:var(--jv-color-foreground-muted)}.jv-modal-selector-dialog,.jv-modal-selector-actions{display:grid;gap:var(--jv-spacing-md)}.jv-modal-selector-subtitle,.jv-modal-selector-results,.jv-modal-selector-option-description,.jv-modal-selector-empty{margin:0;color:var(--jv-color-foreground-muted)}.jv-modal-selector-empty{padding:var(--jv-spacing-md);border:1px dashed var(--jv-color-border);border-radius:var(--jv-radius-md);text-align:center}.jv-modal-selector-option{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);padding:var(--jv-spacing-md);background:var(--jv-color-surface);cursor:pointer;outline:none;transition:background-color .16s ease}.jv-modal-selector-option:hover,.jv-modal-selector-option:focus-visible{background:var(--jv-color-surface-muted)}.jv-modal-selector-option:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-modal-selector-option--selected{background:color-mix(in srgb,var(--jv-color-primary) 8%,var(--jv-color-surface))}.jv-modal-selector-option--disabled{opacity:.55;cursor:not-allowed;pointer-events:none}.jv-modal-selector-option-copy{min-width:0;display:grid;gap:.25rem}.jv-modal-selector-option-label{font-weight:600;color:var(--jv-color-foreground)}\n"] }]
21731
21846
  }], propDecorators: { triggerButtonRef: [{ type: i0.ViewChild, args: ['triggerButton', { isSignal: true }] }], optionElements: [{ type: i0.ViewChildren, args: ['optionElement', { isSignal: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], dialogTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "dialogTitle", required: false }] }], dialogSubtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "dialogSubtitle", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], showSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSearch", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], describedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "describedBy", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], valueInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }] } });
21732
21847
 
@@ -23532,8 +23647,9 @@ class JvListItemComponent {
23532
23647
  class="jv-list-item"
23533
23648
  [class.jv-list-item--disabled]="disabled()"
23534
23649
  [class.jv-list-item--active]="active()"
23535
- tabindex="0"
23650
+ [attr.tabindex]="disabled() ? -1 : 0"
23536
23651
  role="listitem"
23652
+ [attr.aria-disabled]="disabled() ? 'true' : null"
23537
23653
  (click)="onActivate()"
23538
23654
  (keydown.enter)="onActivate()"
23539
23655
  (keydown.space)="onActivate(); $event.preventDefault()"
@@ -23560,8 +23676,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
23560
23676
  class="jv-list-item"
23561
23677
  [class.jv-list-item--disabled]="disabled()"
23562
23678
  [class.jv-list-item--active]="active()"
23563
- tabindex="0"
23679
+ [attr.tabindex]="disabled() ? -1 : 0"
23564
23680
  role="listitem"
23681
+ [attr.aria-disabled]="disabled() ? 'true' : null"
23565
23682
  (click)="onActivate()"
23566
23683
  (keydown.enter)="onActivate()"
23567
23684
  (keydown.space)="onActivate(); $event.preventDefault()"
@@ -23797,11 +23914,23 @@ class JvTabsComponent {
23797
23914
  </div>
23798
23915
 
23799
23916
  @if (showScrollLeft() || showScrollRight()) {
23800
- <div class="jv-tabs-controls" aria-hidden="true">
23801
- <button type="button" class="jv-tabs-scroll-button" [disabled]="!showScrollLeft()" (click)="scrollTabs(-1)">
23917
+ <div class="jv-tabs-controls">
23918
+ <button
23919
+ type="button"
23920
+ class="jv-tabs-scroll-button"
23921
+ aria-label="Scroll tabs backward"
23922
+ [disabled]="!showScrollLeft()"
23923
+ (click)="scrollTabs(-1)"
23924
+ >
23802
23925
  <jv-icon name="chevron-left" [size]="16" />
23803
23926
  </button>
23804
- <button type="button" class="jv-tabs-scroll-button" [disabled]="!showScrollRight()" (click)="scrollTabs(1)">
23927
+ <button
23928
+ type="button"
23929
+ class="jv-tabs-scroll-button"
23930
+ aria-label="Scroll tabs forward"
23931
+ [disabled]="!showScrollRight()"
23932
+ (click)="scrollTabs(1)"
23933
+ >
23805
23934
  <jv-icon name="chevron-right" [size]="16" />
23806
23935
  </button>
23807
23936
  </div>
@@ -23892,11 +24021,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
23892
24021
  </div>
23893
24022
 
23894
24023
  @if (showScrollLeft() || showScrollRight()) {
23895
- <div class="jv-tabs-controls" aria-hidden="true">
23896
- <button type="button" class="jv-tabs-scroll-button" [disabled]="!showScrollLeft()" (click)="scrollTabs(-1)">
24024
+ <div class="jv-tabs-controls">
24025
+ <button
24026
+ type="button"
24027
+ class="jv-tabs-scroll-button"
24028
+ aria-label="Scroll tabs backward"
24029
+ [disabled]="!showScrollLeft()"
24030
+ (click)="scrollTabs(-1)"
24031
+ >
23897
24032
  <jv-icon name="chevron-left" [size]="16" />
23898
24033
  </button>
23899
- <button type="button" class="jv-tabs-scroll-button" [disabled]="!showScrollRight()" (click)="scrollTabs(1)">
24034
+ <button
24035
+ type="button"
24036
+ class="jv-tabs-scroll-button"
24037
+ aria-label="Scroll tabs forward"
24038
+ [disabled]="!showScrollRight()"
24039
+ (click)="scrollTabs(1)"
24040
+ >
23900
24041
  <jv-icon name="chevron-right" [size]="16" />
23901
24042
  </button>
23902
24043
  </div>
@@ -23969,6 +24110,7 @@ class JvTooltipDirective {
23969
24110
  showTimeout = null;
23970
24111
  hideTimeout = null;
23971
24112
  tooltipId = `jv-tooltip-${++tooltipSequence}`;
24113
+ originalDescribedBy = null;
23972
24114
  text = input.required({ ...(ngDevMode ? { debugName: "text" } : /* istanbul ignore next */ {}), alias: 'jvTooltip' });
23973
24115
  position = input('top', { ...(ngDevMode ? { debugName: "position" } : /* istanbul ignore next */ {}), alias: 'jvTooltipPosition' });
23974
24116
  show() {
@@ -23982,7 +24124,7 @@ class JvTooltipDirective {
23982
24124
  this.showTimeout = setTimeout(() => {
23983
24125
  this.renderTooltip();
23984
24126
  this.positionTooltip();
23985
- this.renderer.setAttribute(this.anchorElement(), 'aria-describedby', this.tooltipId);
24127
+ this.attachTooltipDescription();
23986
24128
  }, 120);
23987
24129
  }
23988
24130
  hide() {
@@ -24069,10 +24211,29 @@ class JvTooltipDirective {
24069
24211
  if (!this.tooltipElement) {
24070
24212
  return;
24071
24213
  }
24072
- this.renderer.removeAttribute(this.anchorElement(), 'aria-describedby');
24214
+ this.restoreTooltipDescription();
24073
24215
  this.renderer.removeChild(this.document.body, this.tooltipElement);
24074
24216
  this.tooltipElement = null;
24075
24217
  }
24218
+ attachTooltipDescription() {
24219
+ const anchor = this.anchorElement();
24220
+ this.originalDescribedBy ??= anchor.getAttribute('aria-describedby');
24221
+ const describedBy = [this.originalDescribedBy, this.tooltipId]
24222
+ .filter((value) => !!value)
24223
+ .join(' ')
24224
+ .trim();
24225
+ this.renderer.setAttribute(anchor, 'aria-describedby', describedBy);
24226
+ }
24227
+ restoreTooltipDescription() {
24228
+ const anchor = this.anchorElement();
24229
+ if (this.originalDescribedBy) {
24230
+ this.renderer.setAttribute(anchor, 'aria-describedby', this.originalDescribedBy);
24231
+ }
24232
+ else {
24233
+ this.renderer.removeAttribute(anchor, 'aria-describedby');
24234
+ }
24235
+ this.originalDescribedBy = null;
24236
+ }
24076
24237
  anchorElement() {
24077
24238
  const host = this.hostRef.nativeElement;
24078
24239
  if (isInteractiveElement(host)) {
@@ -24432,6 +24593,7 @@ function exportGridToExcel(header, rows, filename = 'export.xlsx') {
24432
24593
  let gridIdSequence = 0;
24433
24594
  class JvGridComponent {
24434
24595
  gridId = `jv-grid-${++gridIdSequence}`;
24596
+ gridSearchInputId = `${this.gridId}-search`;
24435
24597
  formatService = inject(JvFormatService);
24436
24598
  translationService = inject(JvTranslationService);
24437
24599
  data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
@@ -24975,7 +25137,7 @@ class JvGridComponent {
24975
25137
  <div class="jv-grid-search">
24976
25138
  <jv-icon name="search" [size]="16" />
24977
25139
  <jv-input
24978
- inputId="grid-search"
25140
+ [inputId]="gridSearchInputId"
24979
25141
  [placeholder]="t('grid.searchPlaceholder')"
24980
25142
  [ngModel]="searchTerm()"
24981
25143
  (ngModelChange)="onSearchInput($event)"
@@ -25314,7 +25476,7 @@ class JvGridComponent {
25314
25476
  </nav>
25315
25477
  }
25316
25478
  </div>
25317
- `, isInline: true, styles: [".jv-grid{display:flex;flex-direction:column;gap:var(--jv-spacing-md)}.jv-grid-toolbar{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-grid-search{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-grid-export-actions{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-table-wrap{overflow-x:auto;overflow-y:auto;-webkit-overflow-scrolling:touch;border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);position:relative}.jv-grid-virtual{max-height:600px}.jv-grid-virtual-spacer{pointer-events:none}.jv-grid-table{width:100%;border-collapse:collapse;background:var(--jv-color-surface)}.jv-grid-thead{background:var(--jv-color-surface-muted)}.jv-grid-th{padding:var(--jv-spacing-sm) var(--jv-spacing-md);font-weight:600;font-size:.875rem;color:var(--jv-color-foreground-muted);text-align:start;white-space:nowrap;border-bottom:1px solid var(--jv-color-border);-webkit-user-select:none;user-select:none;position:relative}.jv-grid-th-sortable{cursor:pointer}.jv-grid-th-sortable:hover{background:var(--jv-color-surface)}.jv-grid-th-reorderable{cursor:grab}.jv-grid-th-reorderable:active{cursor:grabbing}.jv-grid-th-sticky-left{position:sticky;left:0;z-index:2;background:var(--jv-color-surface-muted);border-right:1px solid var(--jv-color-border)}.jv-grid-th-sticky-right{position:sticky;right:0;z-index:2;background:var(--jv-color-surface-muted);border-left:1px solid var(--jv-color-border)}.jv-grid-th-content{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-sort-icon{font-size:.75rem;line-height:1}.jv-grid-th-select,.jv-grid-td-select{width:3rem;text-align:center}.jv-grid-th-actions,.jv-grid-td-actions{width:1%;white-space:nowrap}.jv-grid-td{padding:var(--jv-spacing-sm) var(--jv-spacing-md);color:var(--jv-color-foreground);font-size:var(--jv-density-font-size);border-bottom:1px solid var(--jv-color-border)}.jv-grid-td-sticky-left{position:sticky;left:0;z-index:1;background:var(--jv-color-surface);border-right:1px solid var(--jv-color-border)}.jv-grid-td-sticky-right{position:sticky;right:0;z-index:1;background:var(--jv-color-surface);border-left:1px solid var(--jv-color-border)}.jv-grid-t:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-tr{transition:background-color .12s ease}.jv-grid-tr:hover{background:var(--jv-color-surface-muted)}.jv-grid-tr:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-tr-editing{background:var(--jv-color-surface-highlight, rgba(59, 130, 246, .05))}.jv-grid-tr-selected{background:var(--jv-color-primary-light, rgba(59, 130, 246, .08))}.jv-grid-checkbox{width:1rem;height:1rem;accent-color:var(--jv-color-primary);cursor:pointer}.jv-grid-boolean{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:999px;font-size:.75rem;font-weight:700}.jv-grid-boolean-true{background:var(--jv-color-success);color:#fff}.jv-grid-boolean-false{background:var(--jv-color-danger);color:#fff}.jv-grid-empty{padding:var(--jv-spacing-xl) var(--jv-spacing-md);text-align:center;color:var(--jv-color-foreground-muted);font-style:italic}.jv-grid-actions-group{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-loading{display:flex;align-items:center;justify-content:center;gap:var(--jv-spacing-md);padding:var(--jv-spacing-xl);color:var(--jv-color-foreground-muted)}.jv-grid-spinner{width:1.25rem;height:1.25rem;border:2px solid var(--jv-color-border);border-right-color:var(--jv-color-primary);border-radius:999px;animation:jv-grid-spin .8s linear infinite}@keyframes jv-grid-spin{to{transform:rotate(360deg)}}.jv-grid-pagination{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-grid-pagination-info{font-size:.875rem;color:var(--jv-color-foreground-muted)}.jv-grid-pagination-controls{display:flex;align-items:center;gap:var(--jv-spacing-xs);flex-wrap:wrap}@media(max-width:640px){.jv-grid-pagination{flex-direction:column;align-items:stretch;gap:var(--jv-spacing-sm)}.jv-grid-pagination-info{text-align:center}.jv-grid-pagination-controls{justify-content:center}.jv-grid-toolbar{flex-direction:column;align-items:stretch}.jv-grid-search{width:100%}.jv-grid-export-actions{justify-content:stretch}.jv-grid-export-actions jv-button{flex:1}}.jv-grid-resize-handle{position:absolute;top:0;right:0;width:4px;height:100%;cursor:col-resize;background:transparent;z-index:3}.jv-grid-resize-handle:hover,.jv-grid-resize-handle:active{background:var(--jv-color-primary)}.jv-grid-filter-row .jv-grid-th{padding:var(--jv-spacing-xs) var(--jv-spacing-sm)}.jv-grid-filter-input{width:100%;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-sm);background:var(--jv-color-surface);color:var(--jv-color-foreground);font-size:.8rem;box-sizing:border-box}.jv-grid-td-editable{cursor:pointer}.jv-grid-td-editable:hover{box-shadow:inset 0 0 0 1px var(--jv-color-primary)}.jv-grid-edit-input{width:100%;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border:1px solid var(--jv-color-primary);border-radius:var(--jv-radius-sm);background:var(--jv-color-surface);color:var(--jv-color-foreground);font-size:var(--jv-density-font-size);box-sizing:border-box}.jv-grid-edit-input:focus{outline:2px solid var(--jv-color-primary);outline-offset:-1px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: JvButtonComponent, selector: "jv-button", inputs: ["type", "variant", "icon", "iconPosition", "loading", "disabled"] }, { kind: "component", type: JvIconComponent, selector: "jv-icon", inputs: ["name", "size", "strokeWidth", "decorative", "ariaLabel"] }, { kind: "component", type: JvInputComponent, selector: "jv-input", inputs: ["type", "placeholder", "required", "invalid", "describedBy", "inputId"] }, { kind: "component", type: JvSelectComponent, selector: "jv-select", inputs: ["options", "placeholder", "required", "invalid", "describedBy", "inputId", "modelValue"], outputs: ["selectionChange"] }] });
25479
+ `, isInline: true, styles: [".jv-grid{display:flex;flex-direction:column;gap:var(--jv-spacing-md)}.jv-grid-toolbar{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-grid-search{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-grid-export-actions{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-table-wrap{overflow-x:auto;overflow-y:auto;-webkit-overflow-scrolling:touch;border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-md);position:relative}.jv-grid-virtual{max-height:600px}.jv-grid-virtual-spacer{pointer-events:none}.jv-grid-table{width:100%;border-collapse:collapse;background:var(--jv-color-surface)}.jv-grid-thead{background:var(--jv-color-surface-muted)}.jv-grid-th{padding:var(--jv-spacing-sm) var(--jv-spacing-md);font-weight:600;font-size:.875rem;color:var(--jv-color-foreground-muted);text-align:start;white-space:nowrap;border-bottom:1px solid var(--jv-color-border);-webkit-user-select:none;user-select:none;position:relative}.jv-grid-th-sortable{cursor:pointer}.jv-grid-th-sortable:hover{background:var(--jv-color-surface)}.jv-grid-th-reorderable{cursor:grab}.jv-grid-th-reorderable:active{cursor:grabbing}.jv-grid-th-sticky-left{position:sticky;left:0;z-index:2;background:var(--jv-color-surface-muted);border-right:1px solid var(--jv-color-border)}.jv-grid-th-sticky-right{position:sticky;right:0;z-index:2;background:var(--jv-color-surface-muted);border-left:1px solid var(--jv-color-border)}.jv-grid-th-content{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-sort-icon{font-size:.75rem;line-height:1}.jv-grid-th-select,.jv-grid-td-select{width:3rem;text-align:center}.jv-grid-th-actions,.jv-grid-td-actions{width:1%;white-space:nowrap}.jv-grid-td{padding:var(--jv-spacing-sm) var(--jv-spacing-md);color:var(--jv-color-foreground);font-size:var(--jv-density-font-size);border-bottom:1px solid var(--jv-color-border)}.jv-grid-td-sticky-left{position:sticky;left:0;z-index:1;background:var(--jv-color-surface);border-right:1px solid var(--jv-color-border)}.jv-grid-td-sticky-right{position:sticky;right:0;z-index:1;background:var(--jv-color-surface);border-left:1px solid var(--jv-color-border)}.jv-grid-t:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-tr{transition:background-color .12s ease}.jv-grid-tr:hover{background:var(--jv-color-surface-muted)}.jv-grid-tr:focus-visible{outline:2px solid var(--jv-color-primary);outline-offset:-2px}.jv-grid-tr-editing{background:var(--jv-color-surface-highlight, rgba(59, 130, 246, .05))}.jv-grid-tr-selected{background:var(--jv-color-primary-light, rgba(59, 130, 246, .08))}.jv-grid-checkbox{width:1rem;height:1rem;accent-color:var(--jv-color-primary);cursor:pointer}.jv-grid-boolean{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:999px;font-size:.75rem;font-weight:700}.jv-grid-boolean-true{background:var(--jv-color-success);color:#fff}.jv-grid-boolean-false{background:var(--jv-color-danger);color:#fff}.jv-grid-empty{padding:var(--jv-spacing-xl) var(--jv-spacing-md);text-align:center;color:var(--jv-color-foreground-muted);font-style:italic}.jv-grid-actions-group{display:flex;align-items:center;gap:var(--jv-spacing-xs)}.jv-grid-loading{display:flex;align-items:center;justify-content:center;gap:var(--jv-spacing-md);padding:var(--jv-spacing-xl);color:var(--jv-color-foreground-muted)}.jv-grid-spinner{width:1.25rem;height:1.25rem;border:2px solid var(--jv-color-border);border-right-color:var(--jv-color-primary);border-radius:999px;animation:jv-grid-spin .8s linear infinite}@keyframes jv-grid-spin{to{transform:rotate(360deg)}}.jv-grid-pagination{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-grid-pagination-info{font-size:.875rem;color:var(--jv-color-foreground-muted)}.jv-grid-pagination-controls{display:flex;align-items:center;gap:var(--jv-spacing-xs);flex-wrap:wrap}@media(max-width:640px){.jv-grid-pagination{flex-direction:column;align-items:stretch;gap:var(--jv-spacing-sm)}.jv-grid-pagination-info{text-align:center}.jv-grid-pagination-controls{justify-content:center}.jv-grid-toolbar{flex-direction:column;align-items:stretch}.jv-grid-search{width:100%}.jv-grid-export-actions{justify-content:stretch}.jv-grid-export-actions jv-button{flex:1}}.jv-grid-resize-handle{position:absolute;top:0;right:0;width:4px;height:100%;cursor:col-resize;background:transparent;z-index:3}.jv-grid-resize-handle:hover,.jv-grid-resize-handle:active{background:var(--jv-color-primary)}.jv-grid-filter-row .jv-grid-th{padding:var(--jv-spacing-xs) var(--jv-spacing-sm)}.jv-grid-filter-input{width:100%;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border:1px solid var(--jv-color-border);border-radius:var(--jv-radius-sm);background:var(--jv-color-surface);color:var(--jv-color-foreground);font-size:.8rem;box-sizing:border-box}.jv-grid-td-editable{cursor:pointer}.jv-grid-td-editable:hover{box-shadow:inset 0 0 0 1px var(--jv-color-primary)}.jv-grid-edit-input{width:100%;min-height:var(--jv-density-control-height);padding:0 var(--jv-spacing-sm);border:1px solid var(--jv-color-primary);border-radius:var(--jv-radius-sm);background:var(--jv-color-surface);color:var(--jv-color-foreground);font-size:var(--jv-density-font-size);box-sizing:border-box}.jv-grid-edit-input:focus{outline:2px solid var(--jv-color-primary);outline-offset:-1px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: JvButtonComponent, selector: "jv-button", inputs: ["type", "variant", "icon", "iconPosition", "loading", "disabled"] }, { kind: "component", type: JvIconComponent, selector: "jv-icon", inputs: ["name", "size", "strokeWidth", "decorative", "ariaLabel"] }, { kind: "component", type: JvInputComponent, selector: "jv-input", inputs: ["type", "placeholder", "required", "invalid", "describedBy", "inputId"] }, { kind: "component", type: JvSelectComponent, selector: "jv-select", inputs: ["options", "placeholder", "required", "invalid", "describedBy", "ariaLabel", "inputId", "modelValue"], outputs: ["selectionChange"] }] });
25318
25480
  }
25319
25481
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvGridComponent, decorators: [{
25320
25482
  type: Component,
@@ -25326,7 +25488,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
25326
25488
  <div class="jv-grid-search">
25327
25489
  <jv-icon name="search" [size]="16" />
25328
25490
  <jv-input
25329
- inputId="grid-search"
25491
+ [inputId]="gridSearchInputId"
25330
25492
  [placeholder]="t('grid.searchPlaceholder')"
25331
25493
  [ngModel]="searchTerm()"
25332
25494
  (ngModelChange)="onSearchInput($event)"
@@ -25765,7 +25927,7 @@ class JvPaginationComponent {
25765
25927
  </div>
25766
25928
  </div>
25767
25929
  </nav>
25768
- `, isInline: true, styles: [".jv-pagination{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-pagination-info{font-size:.875rem;color:var(--jv-color-foreground-muted)}.jv-pagination-controls{display:flex;align-items:center;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-pagination-size{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-pagination-size-label{font-size:.875rem;color:var(--jv-color-foreground-muted);white-space:nowrap}.jv-pagination-size jv-select{width:auto;min-width:4.5rem}.jv-pagination-buttons{display:flex;align-items:center;gap:var(--jv-spacing-xs)}\n"], dependencies: [{ kind: "component", type: JvButtonComponent, selector: "jv-button", inputs: ["type", "variant", "icon", "iconPosition", "loading", "disabled"] }, { kind: "component", type: JvSelectComponent, selector: "jv-select", inputs: ["options", "placeholder", "required", "invalid", "describedBy", "inputId", "modelValue"], outputs: ["selectionChange"] }] });
25930
+ `, isInline: true, styles: [".jv-pagination{display:flex;align-items:center;justify-content:space-between;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-pagination-info{font-size:.875rem;color:var(--jv-color-foreground-muted)}.jv-pagination-controls{display:flex;align-items:center;gap:var(--jv-spacing-md);flex-wrap:wrap}.jv-pagination-size{display:flex;align-items:center;gap:var(--jv-spacing-sm)}.jv-pagination-size-label{font-size:.875rem;color:var(--jv-color-foreground-muted);white-space:nowrap}.jv-pagination-size jv-select{width:auto;min-width:4.5rem}.jv-pagination-buttons{display:flex;align-items:center;gap:var(--jv-spacing-xs)}\n"], dependencies: [{ kind: "component", type: JvButtonComponent, selector: "jv-button", inputs: ["type", "variant", "icon", "iconPosition", "loading", "disabled"] }, { kind: "component", type: JvSelectComponent, selector: "jv-select", inputs: ["options", "placeholder", "required", "invalid", "describedBy", "ariaLabel", "inputId", "modelValue"], outputs: ["selectionChange"] }] });
25769
25931
  }
25770
25932
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: JvPaginationComponent, decorators: [{
25771
25933
  type: Component,