@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.
- package/LICENSE +201 -201
- package/NOTICE +7 -7
- package/README.md +39 -39
- package/consumer-guide/README.md +84 -84
- package/consumer-guide/forms-and-binding.md +19 -3
- package/consumer-guide/layout.md +19 -0
- package/consumer-guide/overlays.md +100 -100
- package/consumer-guide/setup-and-gotchas.md +165 -103
- package/consumer-guide/theming-and-encapsulation.md +129 -115
- package/fesm2022/skra-ui-accordion.mjs +61 -43
- package/fesm2022/skra-ui-accordion.mjs.map +1 -1
- package/fesm2022/skra-ui-alert.mjs +26 -18
- package/fesm2022/skra-ui-alert.mjs.map +1 -1
- package/fesm2022/skra-ui-avatar.mjs +12 -8
- package/fesm2022/skra-ui-avatar.mjs.map +1 -1
- package/fesm2022/skra-ui-badge.mjs +19 -13
- package/fesm2022/skra-ui-badge.mjs.map +1 -1
- package/fesm2022/skra-ui-button.mjs +28 -19
- package/fesm2022/skra-ui-button.mjs.map +1 -1
- package/fesm2022/skra-ui-checkbox.mjs +3 -3
- package/fesm2022/skra-ui-checkbox.mjs.map +1 -1
- package/fesm2022/skra-ui-chip.mjs +15 -11
- package/fesm2022/skra-ui-chip.mjs.map +1 -1
- package/fesm2022/skra-ui-combobox.mjs +135 -130
- package/fesm2022/skra-ui-combobox.mjs.map +1 -1
- package/fesm2022/skra-ui-core.mjs +95 -73
- package/fesm2022/skra-ui-core.mjs.map +1 -1
- package/fesm2022/skra-ui-counter.mjs +9 -6
- package/fesm2022/skra-ui-counter.mjs.map +1 -1
- package/fesm2022/skra-ui-datepicker.mjs +334 -307
- package/fesm2022/skra-ui-datepicker.mjs.map +1 -1
- package/fesm2022/skra-ui-dialog.mjs +5 -4
- package/fesm2022/skra-ui-dialog.mjs.map +1 -1
- package/fesm2022/skra-ui-field.mjs +44 -34
- package/fesm2022/skra-ui-field.mjs.map +1 -1
- package/fesm2022/skra-ui-icon.mjs +5 -4
- package/fesm2022/skra-ui-icon.mjs.map +1 -1
- package/fesm2022/skra-ui-input.mjs +53 -12
- package/fesm2022/skra-ui-input.mjs.map +1 -1
- package/fesm2022/skra-ui-kbd.mjs +3 -3
- package/fesm2022/skra-ui-kbd.mjs.map +1 -1
- package/fesm2022/skra-ui-layout.mjs +33 -21
- package/fesm2022/skra-ui-layout.mjs.map +1 -1
- package/fesm2022/skra-ui-link.mjs +3 -3
- package/fesm2022/skra-ui-link.mjs.map +1 -1
- package/fesm2022/skra-ui-loading-indicator.mjs +3 -3
- package/fesm2022/skra-ui-loading-indicator.mjs.map +1 -1
- package/fesm2022/skra-ui-menu.mjs +8 -7
- package/fesm2022/skra-ui-menu.mjs.map +1 -1
- package/fesm2022/skra-ui-multi-select.mjs +102 -98
- package/fesm2022/skra-ui-multi-select.mjs.map +1 -1
- package/fesm2022/skra-ui-native-select.mjs +35 -17
- package/fesm2022/skra-ui-native-select.mjs.map +1 -1
- package/fesm2022/skra-ui-popover.mjs +5 -4
- package/fesm2022/skra-ui-popover.mjs.map +1 -1
- package/fesm2022/skra-ui-progress.mjs +7 -5
- package/fesm2022/skra-ui-progress.mjs.map +1 -1
- package/fesm2022/skra-ui-radio.mjs +3 -3
- package/fesm2022/skra-ui-radio.mjs.map +1 -1
- package/fesm2022/skra-ui-rating-display.mjs +14 -9
- package/fesm2022/skra-ui-rating-display.mjs.map +1 -1
- package/fesm2022/skra-ui-select.mjs +98 -95
- package/fesm2022/skra-ui-select.mjs.map +1 -1
- package/fesm2022/skra-ui-skeleton.mjs +16 -13
- package/fesm2022/skra-ui-skeleton.mjs.map +1 -1
- package/fesm2022/skra-ui-star-rating.mjs +18 -11
- package/fesm2022/skra-ui-star-rating.mjs.map +1 -1
- package/fesm2022/skra-ui-status-dot.mjs +7 -5
- package/fesm2022/skra-ui-status-dot.mjs.map +1 -1
- package/fesm2022/skra-ui-switch.mjs +3 -3
- package/fesm2022/skra-ui-switch.mjs.map +1 -1
- package/fesm2022/skra-ui-tabs.mjs +43 -29
- package/fesm2022/skra-ui-tabs.mjs.map +1 -1
- package/fesm2022/skra-ui-textarea.mjs +41 -15
- package/fesm2022/skra-ui-textarea.mjs.map +1 -1
- package/fesm2022/skra-ui-toast.mjs +35 -23
- package/fesm2022/skra-ui-toast.mjs.map +1 -1
- package/fesm2022/skra-ui-tooltip.mjs +12 -9
- package/fesm2022/skra-ui-tooltip.mjs.map +1 -1
- package/fesm2022/skra-ui-typography.mjs +9 -6
- package/fesm2022/skra-ui-typography.mjs.map +1 -1
- package/package.json +5 -5
- package/types/skra-ui-input.d.ts +24 -1
- package/types/skra-ui-input.d.ts.map +1 -1
- package/types/skra-ui-native-select.d.ts +9 -1
- package/types/skra-ui-native-select.d.ts.map +1 -1
- package/types/skra-ui-textarea.d.ts +10 -1
- 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('',
|
|
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('',
|
|
333
|
+
min = input('', /* @ts-ignore */
|
|
334
|
+
...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
|
|
333
335
|
/** Inclusive upper bound (ISO); `''` = unbounded. */
|
|
334
|
-
max = input('',
|
|
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,
|
|
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,
|
|
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('',
|
|
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',
|
|
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',
|
|
349
|
-
|
|
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,
|
|
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,
|
|
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(),
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
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
|
-
},
|
|
376
|
-
|
|
377
|
-
|
|
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
|
-
},
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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
|
-
},
|
|
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
|
-
},
|
|
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: "
|
|
573
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
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: "
|
|
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',
|