@skra/ui 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/LICENSE +201 -201
  2. package/NOTICE +7 -7
  3. package/README.md +39 -39
  4. package/consumer-guide/README.md +84 -84
  5. package/consumer-guide/forms-and-binding.md +19 -3
  6. package/consumer-guide/layout.md +19 -0
  7. package/consumer-guide/overlays.md +100 -100
  8. package/consumer-guide/setup-and-gotchas.md +165 -103
  9. package/consumer-guide/theming-and-encapsulation.md +129 -115
  10. package/fesm2022/skra-ui-accordion.mjs +61 -43
  11. package/fesm2022/skra-ui-accordion.mjs.map +1 -1
  12. package/fesm2022/skra-ui-alert.mjs +26 -18
  13. package/fesm2022/skra-ui-alert.mjs.map +1 -1
  14. package/fesm2022/skra-ui-avatar.mjs +12 -8
  15. package/fesm2022/skra-ui-avatar.mjs.map +1 -1
  16. package/fesm2022/skra-ui-badge.mjs +19 -13
  17. package/fesm2022/skra-ui-badge.mjs.map +1 -1
  18. package/fesm2022/skra-ui-button.mjs +28 -19
  19. package/fesm2022/skra-ui-button.mjs.map +1 -1
  20. package/fesm2022/skra-ui-checkbox.mjs +3 -3
  21. package/fesm2022/skra-ui-checkbox.mjs.map +1 -1
  22. package/fesm2022/skra-ui-chip.mjs +15 -11
  23. package/fesm2022/skra-ui-chip.mjs.map +1 -1
  24. package/fesm2022/skra-ui-combobox.mjs +135 -130
  25. package/fesm2022/skra-ui-combobox.mjs.map +1 -1
  26. package/fesm2022/skra-ui-core.mjs +95 -73
  27. package/fesm2022/skra-ui-core.mjs.map +1 -1
  28. package/fesm2022/skra-ui-counter.mjs +9 -6
  29. package/fesm2022/skra-ui-counter.mjs.map +1 -1
  30. package/fesm2022/skra-ui-datepicker.mjs +334 -307
  31. package/fesm2022/skra-ui-datepicker.mjs.map +1 -1
  32. package/fesm2022/skra-ui-dialog.mjs +5 -4
  33. package/fesm2022/skra-ui-dialog.mjs.map +1 -1
  34. package/fesm2022/skra-ui-field.mjs +44 -34
  35. package/fesm2022/skra-ui-field.mjs.map +1 -1
  36. package/fesm2022/skra-ui-icon.mjs +5 -4
  37. package/fesm2022/skra-ui-icon.mjs.map +1 -1
  38. package/fesm2022/skra-ui-input.mjs +53 -12
  39. package/fesm2022/skra-ui-input.mjs.map +1 -1
  40. package/fesm2022/skra-ui-kbd.mjs +3 -3
  41. package/fesm2022/skra-ui-kbd.mjs.map +1 -1
  42. package/fesm2022/skra-ui-layout.mjs +33 -21
  43. package/fesm2022/skra-ui-layout.mjs.map +1 -1
  44. package/fesm2022/skra-ui-link.mjs +3 -3
  45. package/fesm2022/skra-ui-link.mjs.map +1 -1
  46. package/fesm2022/skra-ui-loading-indicator.mjs +3 -3
  47. package/fesm2022/skra-ui-loading-indicator.mjs.map +1 -1
  48. package/fesm2022/skra-ui-menu.mjs +8 -7
  49. package/fesm2022/skra-ui-menu.mjs.map +1 -1
  50. package/fesm2022/skra-ui-multi-select.mjs +102 -98
  51. package/fesm2022/skra-ui-multi-select.mjs.map +1 -1
  52. package/fesm2022/skra-ui-native-select.mjs +35 -17
  53. package/fesm2022/skra-ui-native-select.mjs.map +1 -1
  54. package/fesm2022/skra-ui-popover.mjs +5 -4
  55. package/fesm2022/skra-ui-popover.mjs.map +1 -1
  56. package/fesm2022/skra-ui-progress.mjs +7 -5
  57. package/fesm2022/skra-ui-progress.mjs.map +1 -1
  58. package/fesm2022/skra-ui-radio.mjs +3 -3
  59. package/fesm2022/skra-ui-radio.mjs.map +1 -1
  60. package/fesm2022/skra-ui-rating-display.mjs +14 -9
  61. package/fesm2022/skra-ui-rating-display.mjs.map +1 -1
  62. package/fesm2022/skra-ui-select.mjs +98 -95
  63. package/fesm2022/skra-ui-select.mjs.map +1 -1
  64. package/fesm2022/skra-ui-skeleton.mjs +16 -13
  65. package/fesm2022/skra-ui-skeleton.mjs.map +1 -1
  66. package/fesm2022/skra-ui-star-rating.mjs +18 -11
  67. package/fesm2022/skra-ui-star-rating.mjs.map +1 -1
  68. package/fesm2022/skra-ui-status-dot.mjs +7 -5
  69. package/fesm2022/skra-ui-status-dot.mjs.map +1 -1
  70. package/fesm2022/skra-ui-switch.mjs +3 -3
  71. package/fesm2022/skra-ui-switch.mjs.map +1 -1
  72. package/fesm2022/skra-ui-tabs.mjs +43 -29
  73. package/fesm2022/skra-ui-tabs.mjs.map +1 -1
  74. package/fesm2022/skra-ui-textarea.mjs +41 -15
  75. package/fesm2022/skra-ui-textarea.mjs.map +1 -1
  76. package/fesm2022/skra-ui-toast.mjs +35 -23
  77. package/fesm2022/skra-ui-toast.mjs.map +1 -1
  78. package/fesm2022/skra-ui-tooltip.mjs +12 -9
  79. package/fesm2022/skra-ui-tooltip.mjs.map +1 -1
  80. package/fesm2022/skra-ui-typography.mjs +9 -6
  81. package/fesm2022/skra-ui-typography.mjs.map +1 -1
  82. package/package.json +5 -5
  83. package/types/skra-ui-input.d.ts +24 -1
  84. package/types/skra-ui-input.d.ts.map +1 -1
  85. package/types/skra-ui-native-select.d.ts +9 -1
  86. package/types/skra-ui-native-select.d.ts.map +1 -1
  87. package/types/skra-ui-textarea.d.ts +10 -1
  88. package/types/skra-ui-textarea.d.ts.map +1 -1
@@ -327,63 +327,88 @@ let nextDatePickerId = 0;
327
327
  */
328
328
  class SkraDatePicker {
329
329
  /** Consumer-owned value: ISO 8601 date-only (`YYYY-MM-DD`); `''` = unset. NEVER a Date (ADR 0050/037). */
330
- value = input('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
330
+ value = input('', /* @ts-ignore */
331
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
331
332
  /** Inclusive lower bound (ISO); `''` = unbounded (ADR 0050 §2). */
332
- min = input('', ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
333
+ min = input('', /* @ts-ignore */
334
+ ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
333
335
  /** Inclusive upper bound (ISO); `''` = unbounded. */
334
- max = input('', ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
336
+ max = input('', /* @ts-ignore */
337
+ ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
335
338
  /** `Intl` locale (BCP-47); `undefined` → host default (ADR 0050 §5). */
336
- locale = input(undefined, ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
339
+ locale = input(undefined, /* @ts-ignore */
340
+ ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
337
341
  /** First day of week, ISO 1=Mon … 7=Sun; overrides `Intl.getWeekInfo` (the MVP safety valve, ADR 0050 §5). */
338
- firstDayOfWeek = input(undefined, ...(ngDevMode ? [{ debugName: "firstDayOfWeek" }] : /* istanbul ignore next */ []));
342
+ firstDayOfWeek = input(undefined, /* @ts-ignore */
343
+ ...(ngDevMode ? [{ debugName: "firstDayOfWeek" }] : /* istanbul ignore next */ []));
339
344
  /** Value-empty hint in the trigger (NOT the accessible name — ADR 033). */
340
- placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
345
+ placeholder = input('', /* @ts-ignore */
346
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
341
347
  /** Placement intent; flip/shift adjust at runtime. */
342
- placement = input('bottom', ...(ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []));
348
+ placement = input('bottom', /* @ts-ignore */
349
+ ...(ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []));
343
350
  /** Standalone availability source — `SkraFieldContext` wins when present. */
344
351
  disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
345
352
  readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
346
353
  /** Fires ONLY on user date selection — never on a programmatic `value()` change (ADR 037/0050). */
347
354
  valueChange = output();
348
- triggerRef = viewChild('trigger', ...(ngDevMode ? [{ debugName: "triggerRef" }] : /* istanbul ignore next */ []));
349
- panelRef = viewChild('panel', ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
355
+ triggerRef = viewChild('trigger', /* @ts-ignore */
356
+ ...(ngDevMode ? [{ debugName: "triggerRef" }] : /* istanbul ignore next */ []));
357
+ panelRef = viewChild('panel', /* @ts-ignore */
358
+ ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
350
359
  context = inject(SkraFieldContext, { optional: true });
351
360
  injector = inject(Injector);
352
361
  keyboard = new SkraCalendarKeyboard();
353
362
  panelId = `skra-datepicker-${nextDatePickerId}`;
354
363
  monthYearId = `skra-datepicker-monthyear-${nextDatePickerId++}`;
355
- isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
364
+ isOpen = signal(false, /* @ts-ignore */
365
+ ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
356
366
  /** Today's LOCAL date (ADR 0050 §3) — stable for the session. */
357
367
  todayIso = today();
358
368
  /** The roving-focus day; SINGLE source of truth for what the grid shows AND which cell is focusable. */
359
- focusedIso = signal(this.todayIso, ...(ngDevMode ? [{ debugName: "focusedIso" }] : /* istanbul ignore next */ []));
369
+ focusedIso = signal(this.todayIso, /* @ts-ignore */
370
+ ...(ngDevMode ? [{ debugName: "focusedIso" }] : /* istanbul ignore next */ []));
360
371
  positioner;
361
372
  /** Set when a close should return focus to the trigger (keyboard/select), not on outside-click. */
362
373
  returnFocus = false;
363
374
  // ── Availability / validation (SkraFieldContext, ADR 013, with standalone fallbacks) ──
364
- isDisabled = computed(() => this.context?.isDisabled() ?? this.disabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
365
- isReadonly = computed(() => this.context?.isReadonly() ?? this.readonly(), ...(ngDevMode ? [{ debugName: "isReadonly" }] : /* istanbul ignore next */ []));
366
- hasError = computed(() => this.context?.hasError() ?? false, ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
367
- isRequired = computed(() => this.context?.isRequired() ?? false, ...(ngDevMode ? [{ debugName: "isRequired" }] : /* istanbul ignore next */ []));
368
- triggerId = computed(() => this.context?.fieldId() || null, ...(ngDevMode ? [{ debugName: "triggerId" }] : /* istanbul ignore next */ []));
369
- describedBy = computed(() => this.context?.describedByIds() ?? null, ...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
375
+ isDisabled = computed(() => this.context?.isDisabled() ?? this.disabled(), /* @ts-ignore */
376
+ ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
377
+ isReadonly = computed(() => this.context?.isReadonly() ?? this.readonly(), /* @ts-ignore */
378
+ ...(ngDevMode ? [{ debugName: "isReadonly" }] : /* istanbul ignore next */ []));
379
+ hasError = computed(() => this.context?.hasError() ?? false, /* @ts-ignore */
380
+ ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
381
+ isRequired = computed(() => this.context?.isRequired() ?? false, /* @ts-ignore */
382
+ ...(ngDevMode ? [{ debugName: "isRequired" }] : /* istanbul ignore next */ []));
383
+ triggerId = computed(() => this.context?.fieldId() || null, /* @ts-ignore */
384
+ ...(ngDevMode ? [{ debugName: "triggerId" }] : /* istanbul ignore next */ []));
385
+ describedBy = computed(() => this.context?.describedByIds() ?? null, /* @ts-ignore */
386
+ ...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
370
387
  // ── Derived calendar state ──
371
388
  /** The committed value, defensively normalized: invalid/out-of-range → `''` for display (ADR 0050 §1). */
372
389
  selectedIso = computed(() => {
373
390
  const v = this.value();
374
391
  return isValidIso(v) && isInRange(v, this.min(), this.max()) ? v : '';
375
- }, ...(ngDevMode ? [{ debugName: "selectedIso" }] : /* istanbul ignore next */ []));
376
- formattedValue = computed(() => formatValue(this.selectedIso(), this.locale()), ...(ngDevMode ? [{ debugName: "formattedValue" }] : /* istanbul ignore next */ []));
377
- firstDow = computed(() => resolveFirstDayOfWeek(this.firstDayOfWeek(), this.locale()), ...(ngDevMode ? [{ debugName: "firstDow" }] : /* istanbul ignore next */ []));
392
+ }, /* @ts-ignore */
393
+ ...(ngDevMode ? [{ debugName: "selectedIso" }] : /* istanbul ignore next */ []));
394
+ formattedValue = computed(() => formatValue(this.selectedIso(), this.locale()), /* @ts-ignore */
395
+ ...(ngDevMode ? [{ debugName: "formattedValue" }] : /* istanbul ignore next */ []));
396
+ firstDow = computed(() => resolveFirstDayOfWeek(this.firstDayOfWeek(), this.locale()), /* @ts-ignore */
397
+ ...(ngDevMode ? [{ debugName: "firstDow" }] : /* istanbul ignore next */ []));
378
398
  /** The month being shown — always the focused day's month (keeps the roving tabindex valid). */
379
399
  displayedMonth = computed(() => {
380
400
  const p = parseIso(this.focusedIso()) ?? parseIso(this.todayIso);
381
401
  return { y: p.y, m: p.m };
382
- }, ...(ngDevMode ? [{ debugName: "displayedMonth" }] : /* istanbul ignore next */ []));
383
- monthYearLabel = computed(() => formatMonthYear(this.displayedMonth().y, this.displayedMonth().m, this.locale()), ...(ngDevMode ? [{ debugName: "monthYearLabel" }] : /* istanbul ignore next */ []));
384
- prevMonthLabel = computed(() => this.monthOffsetLabel(-1), ...(ngDevMode ? [{ debugName: "prevMonthLabel" }] : /* istanbul ignore next */ []));
385
- nextMonthLabel = computed(() => this.monthOffsetLabel(1), ...(ngDevMode ? [{ debugName: "nextMonthLabel" }] : /* istanbul ignore next */ []));
386
- weekdayHeadersView = computed(() => weekdayHeaders(this.firstDow(), this.locale()), ...(ngDevMode ? [{ debugName: "weekdayHeadersView" }] : /* istanbul ignore next */ []));
402
+ }, /* @ts-ignore */
403
+ ...(ngDevMode ? [{ debugName: "displayedMonth" }] : /* istanbul ignore next */ []));
404
+ monthYearLabel = computed(() => formatMonthYear(this.displayedMonth().y, this.displayedMonth().m, this.locale()), /* @ts-ignore */
405
+ ...(ngDevMode ? [{ debugName: "monthYearLabel" }] : /* istanbul ignore next */ []));
406
+ prevMonthLabel = computed(() => this.monthOffsetLabel(-1), /* @ts-ignore */
407
+ ...(ngDevMode ? [{ debugName: "prevMonthLabel" }] : /* istanbul ignore next */ []));
408
+ nextMonthLabel = computed(() => this.monthOffsetLabel(1), /* @ts-ignore */
409
+ ...(ngDevMode ? [{ debugName: "nextMonthLabel" }] : /* istanbul ignore next */ []));
410
+ weekdayHeadersView = computed(() => weekdayHeaders(this.firstDow(), this.locale()), /* @ts-ignore */
411
+ ...(ngDevMode ? [{ debugName: "weekdayHeadersView" }] : /* istanbul ignore next */ []));
387
412
  weeks = computed(() => {
388
413
  const { y, m } = this.displayedMonth();
389
414
  const loc = this.locale();
@@ -406,7 +431,8 @@ class SkraDatePicker {
406
431
  focused: iso === foc,
407
432
  }),
408
433
  }));
409
- }, ...(ngDevMode ? [{ debugName: "weeks" }] : /* istanbul ignore next */ []));
434
+ }, /* @ts-ignore */
435
+ ...(ngDevMode ? [{ debugName: "weeks" }] : /* istanbul ignore next */ []));
410
436
  constructor() {
411
437
  inject(DestroyRef).onDestroy(() => this.positioner?.destroy());
412
438
  if (typeof ngDevMode !== 'undefined' && ngDevMode) {
@@ -420,7 +446,8 @@ class SkraDatePicker {
420
446
  compareIso(this.min(), this.max()) > 0)
421
447
  return `skra-datepicker: min "${this.min()}" is after max "${this.max()}" — every day is disabled.`;
422
448
  return null;
423
- }, ...(ngDevMode ? [{ debugName: "warn" }] : /* istanbul ignore next */ []));
449
+ }, /* @ts-ignore */
450
+ ...(ngDevMode ? [{ debugName: "warn" }] : /* istanbul ignore next */ []));
424
451
  afterNextRender(() => {
425
452
  const message = warn();
426
453
  if (message)
@@ -569,289 +596,289 @@ class SkraDatePicker {
569
596
  }
570
597
  return parseFloat(raw) || 0;
571
598
  }
572
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraDatePicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
573
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.7", type: SkraDatePicker, isStandalone: true, selector: "skra-datepicker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { properties: { "attr.data-skra-disabled": "isDisabled() ? \"\" : null", "attr.data-skra-readonly": "isReadonly() ? \"\" : null", "attr.data-skra-validation": "hasError() ? \"invalid\" : null" } }, viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["trigger"], descendants: true, isSignal: true }, { propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }], exportAs: ["skraDatePicker"], ngImport: i0, template: `
574
- <button
575
- #trigger
576
- class="skra-datepicker-trigger"
577
- type="button"
578
- role="combobox"
579
- aria-haspopup="dialog"
580
- [attr.id]="triggerId()"
581
- [attr.popovertarget]="panelId"
582
- [attr.aria-controls]="panelId"
583
- [attr.aria-expanded]="isOpen()"
584
- [attr.aria-describedby]="describedBy()"
585
- [attr.aria-invalid]="hasError() ? 'true' : null"
586
- [attr.aria-required]="isRequired() ? 'true' : null"
587
- [attr.aria-readonly]="isReadonly() ? 'true' : null"
588
- [disabled]="isDisabled()"
589
- (click)="onTriggerClick($event)"
590
- (keydown)="onTriggerKeydown($event)"
591
- >
592
- @if (formattedValue(); as label) {
593
- <span class="skra-datepicker-value">{{ label }}</span>
594
- } @else {
595
- <span class="skra-datepicker-placeholder">{{ placeholder() }}</span>
596
- }
597
- <svg
598
- class="skra-datepicker-icon"
599
- aria-hidden="true"
600
- viewBox="0 0 24 24"
601
- fill="none"
602
- stroke="currentColor"
603
- stroke-width="2"
604
- >
605
- <rect x="3" y="4" width="18" height="17" rx="2" />
606
- <path d="M3 9h18M8 2v4M16 2v4" />
607
- </svg>
608
- </button>
609
-
610
- <div
611
- #panel
612
- class="skra-datepicker-panel"
613
- [id]="panelId"
614
- popover="auto"
615
- role="dialog"
616
- aria-modal="false"
617
- [attr.aria-labelledby]="monthYearId"
618
- (toggle)="onPanelToggle($event)"
619
- >
620
- <div class="skra-datepicker-header">
621
- <button
622
- type="button"
623
- class="skra-datepicker-nav"
624
- tabindex="-1"
625
- [attr.aria-label]="prevMonthLabel()"
626
- (click)="goToPreviousMonth()"
627
- >
628
- <svg
629
- viewBox="0 0 24 24"
630
- fill="none"
631
- stroke="currentColor"
632
- stroke-width="2"
633
- aria-hidden="true"
634
- >
635
- <path d="M15 6l-6 6 6 6" />
636
- </svg>
637
- </button>
638
- <span
639
- class="skra-datepicker-monthyear"
640
- [id]="monthYearId"
641
- aria-live="polite"
642
- >{{ monthYearLabel() }}</span
643
- >
644
- <button
645
- type="button"
646
- class="skra-datepicker-nav"
647
- tabindex="-1"
648
- [attr.aria-label]="nextMonthLabel()"
649
- (click)="goToNextMonth()"
650
- >
651
- <svg
652
- viewBox="0 0 24 24"
653
- fill="none"
654
- stroke="currentColor"
655
- stroke-width="2"
656
- aria-hidden="true"
657
- >
658
- <path d="M9 6l6 6-6 6" />
659
- </svg>
660
- </button>
661
- </div>
662
-
663
- <table
664
- class="skra-datepicker-grid"
665
- role="grid"
666
- [attr.aria-labelledby]="monthYearId"
667
- >
668
- <thead>
669
- <tr>
670
- @for (wd of weekdayHeadersView(); track wd.key) {
671
- <th scope="col" class="skra-datepicker-weekday">
672
- <abbr [title]="wd.long">{{ wd.short }}</abbr>
673
- </th>
674
- }
675
- </tr>
676
- </thead>
677
- <tbody>
678
- @for (week of weeks(); track week.key) {
679
- <tr>
680
- @for (cell of week.days; track cell.key) {
681
- @if (cell.iso) {
682
- <td
683
- role="gridcell"
684
- [attr.aria-selected]="cell.selected ? 'true' : null"
685
- >
686
- <button
687
- type="button"
688
- class="skra-datepicker-day"
689
- [attr.tabindex]="cell.focused ? 0 : -1"
690
- [attr.aria-current]="cell.today ? 'date' : null"
691
- [attr.aria-disabled]="cell.disabled ? 'true' : null"
692
- [attr.data-skra-selected]="cell.selected ? '' : null"
693
- [attr.data-skra-today]="cell.today ? '' : null"
694
- (click)="selectDate(cell.iso)"
695
- (keydown)="onGridKeydown($event)"
696
- >
697
- {{ cell.dayNum
698
- }}<span class="skra-datepicker-day-sr" skra-sr-only>{{
699
- cell.srName
700
- }}</span>
701
- </button>
702
- </td>
703
- } @else {
704
- <td class="skra-datepicker-day-empty" aria-hidden="true"></td>
705
- }
706
- }
707
- </tr>
708
- }
709
- </tbody>
710
- </table>
711
- </div>
599
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraDatePicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
600
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: SkraDatePicker, isStandalone: true, selector: "skra-datepicker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { properties: { "attr.data-skra-disabled": "isDisabled() ? \"\" : null", "attr.data-skra-readonly": "isReadonly() ? \"\" : null", "attr.data-skra-validation": "hasError() ? \"invalid\" : null" } }, viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["trigger"], descendants: true, isSignal: true }, { propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }], exportAs: ["skraDatePicker"], ngImport: i0, template: `
601
+ <button
602
+ #trigger
603
+ class="skra-datepicker-trigger"
604
+ type="button"
605
+ role="combobox"
606
+ aria-haspopup="dialog"
607
+ [attr.id]="triggerId()"
608
+ [attr.popovertarget]="panelId"
609
+ [attr.aria-controls]="panelId"
610
+ [attr.aria-expanded]="isOpen()"
611
+ [attr.aria-describedby]="describedBy()"
612
+ [attr.aria-invalid]="hasError() ? 'true' : null"
613
+ [attr.aria-required]="isRequired() ? 'true' : null"
614
+ [attr.aria-readonly]="isReadonly() ? 'true' : null"
615
+ [disabled]="isDisabled()"
616
+ (click)="onTriggerClick($event)"
617
+ (keydown)="onTriggerKeydown($event)"
618
+ >
619
+ @if (formattedValue(); as label) {
620
+ <span class="skra-datepicker-value">{{ label }}</span>
621
+ } @else {
622
+ <span class="skra-datepicker-placeholder">{{ placeholder() }}</span>
623
+ }
624
+ <svg
625
+ class="skra-datepicker-icon"
626
+ aria-hidden="true"
627
+ viewBox="0 0 24 24"
628
+ fill="none"
629
+ stroke="currentColor"
630
+ stroke-width="2"
631
+ >
632
+ <rect x="3" y="4" width="18" height="17" rx="2" />
633
+ <path d="M3 9h18M8 2v4M16 2v4" />
634
+ </svg>
635
+ </button>
636
+
637
+ <div
638
+ #panel
639
+ class="skra-datepicker-panel"
640
+ [id]="panelId"
641
+ popover="auto"
642
+ role="dialog"
643
+ aria-modal="false"
644
+ [attr.aria-labelledby]="monthYearId"
645
+ (toggle)="onPanelToggle($event)"
646
+ >
647
+ <div class="skra-datepicker-header">
648
+ <button
649
+ type="button"
650
+ class="skra-datepicker-nav"
651
+ tabindex="-1"
652
+ [attr.aria-label]="prevMonthLabel()"
653
+ (click)="goToPreviousMonth()"
654
+ >
655
+ <svg
656
+ viewBox="0 0 24 24"
657
+ fill="none"
658
+ stroke="currentColor"
659
+ stroke-width="2"
660
+ aria-hidden="true"
661
+ >
662
+ <path d="M15 6l-6 6 6 6" />
663
+ </svg>
664
+ </button>
665
+ <span
666
+ class="skra-datepicker-monthyear"
667
+ [id]="monthYearId"
668
+ aria-live="polite"
669
+ >{{ monthYearLabel() }}</span
670
+ >
671
+ <button
672
+ type="button"
673
+ class="skra-datepicker-nav"
674
+ tabindex="-1"
675
+ [attr.aria-label]="nextMonthLabel()"
676
+ (click)="goToNextMonth()"
677
+ >
678
+ <svg
679
+ viewBox="0 0 24 24"
680
+ fill="none"
681
+ stroke="currentColor"
682
+ stroke-width="2"
683
+ aria-hidden="true"
684
+ >
685
+ <path d="M9 6l6 6-6 6" />
686
+ </svg>
687
+ </button>
688
+ </div>
689
+
690
+ <table
691
+ class="skra-datepicker-grid"
692
+ role="grid"
693
+ [attr.aria-labelledby]="monthYearId"
694
+ >
695
+ <thead>
696
+ <tr>
697
+ @for (wd of weekdayHeadersView(); track wd.key) {
698
+ <th scope="col" class="skra-datepicker-weekday">
699
+ <abbr [title]="wd.long">{{ wd.short }}</abbr>
700
+ </th>
701
+ }
702
+ </tr>
703
+ </thead>
704
+ <tbody>
705
+ @for (week of weeks(); track week.key) {
706
+ <tr>
707
+ @for (cell of week.days; track cell.key) {
708
+ @if (cell.iso) {
709
+ <td
710
+ role="gridcell"
711
+ [attr.aria-selected]="cell.selected ? 'true' : null"
712
+ >
713
+ <button
714
+ type="button"
715
+ class="skra-datepicker-day"
716
+ [attr.tabindex]="cell.focused ? 0 : -1"
717
+ [attr.aria-current]="cell.today ? 'date' : null"
718
+ [attr.aria-disabled]="cell.disabled ? 'true' : null"
719
+ [attr.data-skra-selected]="cell.selected ? '' : null"
720
+ [attr.data-skra-today]="cell.today ? '' : null"
721
+ (click)="selectDate(cell.iso)"
722
+ (keydown)="onGridKeydown($event)"
723
+ >
724
+ {{ cell.dayNum
725
+ }}<span class="skra-datepicker-day-sr" skra-sr-only>{{
726
+ cell.srName
727
+ }}</span>
728
+ </button>
729
+ </td>
730
+ } @else {
731
+ <td class="skra-datepicker-day-empty" aria-hidden="true"></td>
732
+ }
733
+ }
734
+ </tr>
735
+ }
736
+ </tbody>
737
+ </table>
738
+ </div>
712
739
  `, isInline: true, styles: ["@charset \"UTF-8\";:host{display:inline-block;box-sizing:border-box;margin:0}.skra-datepicker-trigger{display:flex;align-items:center;gap:var(--skra-comp-datepicker-gap);inline-size:100%;min-block-size:var(--skra-comp-datepicker-min-block-size);box-sizing:border-box;margin:0;padding-block:var(--skra-comp-datepicker-padding-block);padding-inline:var(--skra-comp-datepicker-padding-inline);text-align:start;cursor:pointer;background:var(--skra-comp-datepicker-background);color:var(--skra-comp-datepicker-foreground);border-color:var(--skra-comp-datepicker-border-color);border-width:var(--skra-comp-datepicker-border-width);border-style:var(--skra-comp-datepicker-border-style);border-radius:var(--skra-comp-datepicker-radius);box-shadow:var(--skra-comp-datepicker-shadow);font-family:var(--skra-sys-typography-role-body-medium-font-family);font-size:var(--skra-sys-typography-role-body-medium-font-size);font-weight:var(--skra-sys-typography-role-body-medium-font-weight);line-height:var(--skra-sys-typography-role-body-medium-line-height);letter-spacing:var(--skra-sys-typography-role-body-medium-letter-spacing);transition:background-color var(--skra-comp-datepicker-motion-duration) var(--skra-comp-datepicker-motion-easing),border-color var(--skra-comp-datepicker-motion-duration) var(--skra-comp-datepicker-motion-easing)}.skra-datepicker-trigger:focus-visible{outline:var(--skra-comp-datepicker-focus-ring-width) solid var(--skra-comp-datepicker-focus-ring-color);outline-offset:.125rem}.skra-datepicker-trigger:disabled{background:var(--skra-comp-datepicker-background-disabled);color:var(--skra-comp-datepicker-foreground-disabled);cursor:not-allowed}.skra-datepicker-trigger[aria-readonly=true]{background:var(--skra-comp-datepicker-background-readonly);cursor:default}.skra-datepicker-trigger[aria-invalid=true]{border-color:var(--skra-comp-datepicker-border-color-validation-invalid)}.skra-datepicker-value{flex:1 1 auto;min-inline-size:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.skra-datepicker-placeholder{flex:1 1 auto;color:var(--skra-comp-datepicker-foreground-disabled)}.skra-datepicker-icon{flex:none;inline-size:var(--skra-comp-datepicker-icon-size);block-size:var(--skra-comp-datepicker-icon-size);color:var(--skra-comp-datepicker-icon-color)}.skra-datepicker-panel{position:fixed;margin:0;inset:auto;box-sizing:border-box;inline-size:max-content;padding:var(--skra-comp-datepicker-panel-padding);background:var(--skra-comp-datepicker-panel-background);color:var(--skra-comp-datepicker-panel-foreground);border:var(--skra-comp-datepicker-border-width) solid var(--skra-comp-datepicker-panel-border-color);border-radius:var(--skra-comp-datepicker-panel-radius);box-shadow:var(--skra-comp-datepicker-panel-shadow);opacity:0;transition:opacity var(--skra-comp-datepicker-motion-duration) var(--skra-comp-datepicker-motion-easing),display var(--skra-comp-datepicker-motion-duration) allow-discrete,overlay var(--skra-comp-datepicker-motion-duration) allow-discrete}.skra-datepicker-panel:popover-open{display:block;opacity:1}@starting-style{.skra-datepicker-panel:popover-open{opacity:0}}.skra-datepicker-header{display:flex;align-items:center;justify-content:space-between;gap:var(--skra-comp-datepicker-gap);margin-block-end:var(--skra-comp-datepicker-panel-padding)}.skra-datepicker-monthyear{flex:1 1 auto;text-align:center;color:var(--skra-comp-datepicker-header-foreground);font-family:var(--skra-sys-typography-role-body-medium-font-family);font-size:var(--skra-sys-typography-role-body-medium-font-size);font-weight:var(--skra-sys-typography-role-body-medium-font-weight);line-height:var(--skra-sys-typography-role-body-medium-line-height);letter-spacing:var(--skra-sys-typography-role-body-medium-letter-spacing)}.skra-datepicker-nav{flex:none;display:inline-flex;align-items:center;justify-content:center;inline-size:var(--skra-comp-datepicker-nav-icon-size);block-size:var(--skra-comp-datepicker-nav-icon-size);margin:0;padding:0;background:transparent;border:0;color:var(--skra-comp-datepicker-nav-color);cursor:pointer}.skra-datepicker-nav svg{inline-size:100%;block-size:100%}.skra-datepicker-nav:hover{color:var(--skra-comp-datepicker-nav-color-hover)}.skra-datepicker-nav:focus-visible{outline:var(--skra-comp-datepicker-focus-ring-width) solid var(--skra-comp-datepicker-focus-ring-color);outline-offset:.125rem}.skra-datepicker-grid{border-collapse:collapse}.skra-datepicker-weekday{inline-size:var(--skra-comp-datepicker-day-size);padding:0;color:var(--skra-comp-datepicker-weekday-foreground);font-family:var(--skra-sys-typography-role-body-small-font-family);font-size:var(--skra-sys-typography-role-body-small-font-size);font-weight:var(--skra-sys-typography-role-body-small-font-weight);line-height:var(--skra-sys-typography-role-body-small-line-height);letter-spacing:var(--skra-sys-typography-role-body-small-letter-spacing)}.skra-datepicker-weekday abbr{text-decoration:none}.skra-datepicker-day-empty{padding:0}.skra-datepicker-day{display:inline-flex;align-items:center;justify-content:center;inline-size:var(--skra-comp-datepicker-day-size);block-size:var(--skra-comp-datepicker-day-size);margin:0;padding:0;background:transparent;border:0;border-radius:var(--skra-comp-datepicker-day-radius);color:var(--skra-comp-datepicker-day-foreground);cursor:pointer;font-family:var(--skra-sys-typography-role-body-medium-font-family);font-size:var(--skra-sys-typography-role-body-medium-font-size);font-weight:var(--skra-sys-typography-role-body-medium-font-weight);line-height:var(--skra-sys-typography-role-body-medium-line-height);letter-spacing:var(--skra-sys-typography-role-body-medium-letter-spacing);transition:background-color var(--skra-comp-datepicker-motion-duration) var(--skra-comp-datepicker-motion-easing)}.skra-datepicker-day:hover:not([aria-disabled=true]){background:var(--skra-comp-datepicker-day-background-hover)}.skra-datepicker-day:focus-visible{outline:var(--skra-comp-datepicker-focus-ring-width) solid var(--skra-comp-datepicker-focus-ring-color);outline-offset:-.0625rem}.skra-datepicker-day[data-skra-today]{box-shadow:inset 0 0 0 .125rem var(--skra-comp-datepicker-day-today-indicator-color)}.skra-datepicker-day[data-skra-selected]{background:var(--skra-comp-datepicker-day-background-selected);color:var(--skra-comp-datepicker-day-foreground-selected)}.skra-datepicker-day[aria-disabled=true]{color:var(--skra-comp-datepicker-day-foreground-disabled);cursor:default}@media(prefers-reduced-motion:reduce){.skra-datepicker-trigger,.skra-datepicker-panel,.skra-datepicker-day{transition-duration:0ms}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
713
740
  }
714
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: SkraDatePicker, decorators: [{
741
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: SkraDatePicker, decorators: [{
715
742
  type: Component,
716
- args: [{ selector: 'skra-datepicker', standalone: true, exportAs: 'skraDatePicker', template: `
717
- <button
718
- #trigger
719
- class="skra-datepicker-trigger"
720
- type="button"
721
- role="combobox"
722
- aria-haspopup="dialog"
723
- [attr.id]="triggerId()"
724
- [attr.popovertarget]="panelId"
725
- [attr.aria-controls]="panelId"
726
- [attr.aria-expanded]="isOpen()"
727
- [attr.aria-describedby]="describedBy()"
728
- [attr.aria-invalid]="hasError() ? 'true' : null"
729
- [attr.aria-required]="isRequired() ? 'true' : null"
730
- [attr.aria-readonly]="isReadonly() ? 'true' : null"
731
- [disabled]="isDisabled()"
732
- (click)="onTriggerClick($event)"
733
- (keydown)="onTriggerKeydown($event)"
734
- >
735
- @if (formattedValue(); as label) {
736
- <span class="skra-datepicker-value">{{ label }}</span>
737
- } @else {
738
- <span class="skra-datepicker-placeholder">{{ placeholder() }}</span>
739
- }
740
- <svg
741
- class="skra-datepicker-icon"
742
- aria-hidden="true"
743
- viewBox="0 0 24 24"
744
- fill="none"
745
- stroke="currentColor"
746
- stroke-width="2"
747
- >
748
- <rect x="3" y="4" width="18" height="17" rx="2" />
749
- <path d="M3 9h18M8 2v4M16 2v4" />
750
- </svg>
751
- </button>
752
-
753
- <div
754
- #panel
755
- class="skra-datepicker-panel"
756
- [id]="panelId"
757
- popover="auto"
758
- role="dialog"
759
- aria-modal="false"
760
- [attr.aria-labelledby]="monthYearId"
761
- (toggle)="onPanelToggle($event)"
762
- >
763
- <div class="skra-datepicker-header">
764
- <button
765
- type="button"
766
- class="skra-datepicker-nav"
767
- tabindex="-1"
768
- [attr.aria-label]="prevMonthLabel()"
769
- (click)="goToPreviousMonth()"
770
- >
771
- <svg
772
- viewBox="0 0 24 24"
773
- fill="none"
774
- stroke="currentColor"
775
- stroke-width="2"
776
- aria-hidden="true"
777
- >
778
- <path d="M15 6l-6 6 6 6" />
779
- </svg>
780
- </button>
781
- <span
782
- class="skra-datepicker-monthyear"
783
- [id]="monthYearId"
784
- aria-live="polite"
785
- >{{ monthYearLabel() }}</span
786
- >
787
- <button
788
- type="button"
789
- class="skra-datepicker-nav"
790
- tabindex="-1"
791
- [attr.aria-label]="nextMonthLabel()"
792
- (click)="goToNextMonth()"
793
- >
794
- <svg
795
- viewBox="0 0 24 24"
796
- fill="none"
797
- stroke="currentColor"
798
- stroke-width="2"
799
- aria-hidden="true"
800
- >
801
- <path d="M9 6l6 6-6 6" />
802
- </svg>
803
- </button>
804
- </div>
805
-
806
- <table
807
- class="skra-datepicker-grid"
808
- role="grid"
809
- [attr.aria-labelledby]="monthYearId"
810
- >
811
- <thead>
812
- <tr>
813
- @for (wd of weekdayHeadersView(); track wd.key) {
814
- <th scope="col" class="skra-datepicker-weekday">
815
- <abbr [title]="wd.long">{{ wd.short }}</abbr>
816
- </th>
817
- }
818
- </tr>
819
- </thead>
820
- <tbody>
821
- @for (week of weeks(); track week.key) {
822
- <tr>
823
- @for (cell of week.days; track cell.key) {
824
- @if (cell.iso) {
825
- <td
826
- role="gridcell"
827
- [attr.aria-selected]="cell.selected ? 'true' : null"
828
- >
829
- <button
830
- type="button"
831
- class="skra-datepicker-day"
832
- [attr.tabindex]="cell.focused ? 0 : -1"
833
- [attr.aria-current]="cell.today ? 'date' : null"
834
- [attr.aria-disabled]="cell.disabled ? 'true' : null"
835
- [attr.data-skra-selected]="cell.selected ? '' : null"
836
- [attr.data-skra-today]="cell.today ? '' : null"
837
- (click)="selectDate(cell.iso)"
838
- (keydown)="onGridKeydown($event)"
839
- >
840
- {{ cell.dayNum
841
- }}<span class="skra-datepicker-day-sr" skra-sr-only>{{
842
- cell.srName
843
- }}</span>
844
- </button>
845
- </td>
846
- } @else {
847
- <td class="skra-datepicker-day-empty" aria-hidden="true"></td>
848
- }
849
- }
850
- </tr>
851
- }
852
- </tbody>
853
- </table>
854
- </div>
743
+ args: [{ selector: 'skra-datepicker', standalone: true, exportAs: 'skraDatePicker', template: `
744
+ <button
745
+ #trigger
746
+ class="skra-datepicker-trigger"
747
+ type="button"
748
+ role="combobox"
749
+ aria-haspopup="dialog"
750
+ [attr.id]="triggerId()"
751
+ [attr.popovertarget]="panelId"
752
+ [attr.aria-controls]="panelId"
753
+ [attr.aria-expanded]="isOpen()"
754
+ [attr.aria-describedby]="describedBy()"
755
+ [attr.aria-invalid]="hasError() ? 'true' : null"
756
+ [attr.aria-required]="isRequired() ? 'true' : null"
757
+ [attr.aria-readonly]="isReadonly() ? 'true' : null"
758
+ [disabled]="isDisabled()"
759
+ (click)="onTriggerClick($event)"
760
+ (keydown)="onTriggerKeydown($event)"
761
+ >
762
+ @if (formattedValue(); as label) {
763
+ <span class="skra-datepicker-value">{{ label }}</span>
764
+ } @else {
765
+ <span class="skra-datepicker-placeholder">{{ placeholder() }}</span>
766
+ }
767
+ <svg
768
+ class="skra-datepicker-icon"
769
+ aria-hidden="true"
770
+ viewBox="0 0 24 24"
771
+ fill="none"
772
+ stroke="currentColor"
773
+ stroke-width="2"
774
+ >
775
+ <rect x="3" y="4" width="18" height="17" rx="2" />
776
+ <path d="M3 9h18M8 2v4M16 2v4" />
777
+ </svg>
778
+ </button>
779
+
780
+ <div
781
+ #panel
782
+ class="skra-datepicker-panel"
783
+ [id]="panelId"
784
+ popover="auto"
785
+ role="dialog"
786
+ aria-modal="false"
787
+ [attr.aria-labelledby]="monthYearId"
788
+ (toggle)="onPanelToggle($event)"
789
+ >
790
+ <div class="skra-datepicker-header">
791
+ <button
792
+ type="button"
793
+ class="skra-datepicker-nav"
794
+ tabindex="-1"
795
+ [attr.aria-label]="prevMonthLabel()"
796
+ (click)="goToPreviousMonth()"
797
+ >
798
+ <svg
799
+ viewBox="0 0 24 24"
800
+ fill="none"
801
+ stroke="currentColor"
802
+ stroke-width="2"
803
+ aria-hidden="true"
804
+ >
805
+ <path d="M15 6l-6 6 6 6" />
806
+ </svg>
807
+ </button>
808
+ <span
809
+ class="skra-datepicker-monthyear"
810
+ [id]="monthYearId"
811
+ aria-live="polite"
812
+ >{{ monthYearLabel() }}</span
813
+ >
814
+ <button
815
+ type="button"
816
+ class="skra-datepicker-nav"
817
+ tabindex="-1"
818
+ [attr.aria-label]="nextMonthLabel()"
819
+ (click)="goToNextMonth()"
820
+ >
821
+ <svg
822
+ viewBox="0 0 24 24"
823
+ fill="none"
824
+ stroke="currentColor"
825
+ stroke-width="2"
826
+ aria-hidden="true"
827
+ >
828
+ <path d="M9 6l6 6-6 6" />
829
+ </svg>
830
+ </button>
831
+ </div>
832
+
833
+ <table
834
+ class="skra-datepicker-grid"
835
+ role="grid"
836
+ [attr.aria-labelledby]="monthYearId"
837
+ >
838
+ <thead>
839
+ <tr>
840
+ @for (wd of weekdayHeadersView(); track wd.key) {
841
+ <th scope="col" class="skra-datepicker-weekday">
842
+ <abbr [title]="wd.long">{{ wd.short }}</abbr>
843
+ </th>
844
+ }
845
+ </tr>
846
+ </thead>
847
+ <tbody>
848
+ @for (week of weeks(); track week.key) {
849
+ <tr>
850
+ @for (cell of week.days; track cell.key) {
851
+ @if (cell.iso) {
852
+ <td
853
+ role="gridcell"
854
+ [attr.aria-selected]="cell.selected ? 'true' : null"
855
+ >
856
+ <button
857
+ type="button"
858
+ class="skra-datepicker-day"
859
+ [attr.tabindex]="cell.focused ? 0 : -1"
860
+ [attr.aria-current]="cell.today ? 'date' : null"
861
+ [attr.aria-disabled]="cell.disabled ? 'true' : null"
862
+ [attr.data-skra-selected]="cell.selected ? '' : null"
863
+ [attr.data-skra-today]="cell.today ? '' : null"
864
+ (click)="selectDate(cell.iso)"
865
+ (keydown)="onGridKeydown($event)"
866
+ >
867
+ {{ cell.dayNum
868
+ }}<span class="skra-datepicker-day-sr" skra-sr-only>{{
869
+ cell.srName
870
+ }}</span>
871
+ </button>
872
+ </td>
873
+ } @else {
874
+ <td class="skra-datepicker-day-empty" aria-hidden="true"></td>
875
+ }
876
+ }
877
+ </tr>
878
+ }
879
+ </tbody>
880
+ </table>
881
+ </div>
855
882
  `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, host: {
856
883
  '[attr.data-skra-disabled]': 'isDisabled() ? "" : null',
857
884
  '[attr.data-skra-readonly]': 'isReadonly() ? "" : null',