@lifecorner/angular-ui-kit 3.29.0 → 3.30.1
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/fesm2022/lifecorner-angular-ui-kit-combobox.mjs +17 -4
- package/fesm2022/lifecorner-angular-ui-kit-combobox.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-datepicker.mjs +31 -8
- package/fesm2022/lifecorner-angular-ui-kit-datepicker.mjs.map +1 -1
- package/package.json +1 -1
- package/src/styles/theme-contrast.spec.ts +58 -0
- package/types/lifecorner-angular-ui-kit-combobox.d.ts +9 -0
- package/types/lifecorner-angular-ui-kit-datepicker.d.ts +32 -4
|
@@ -194,6 +194,19 @@ var ComboboxComponent = class ComboboxComponent {
|
|
|
194
194
|
this.clear();
|
|
195
195
|
this.inputEl()?.nativeElement.focus();
|
|
196
196
|
}
|
|
197
|
+
hitsFrameControl(event) {
|
|
198
|
+
const target = event.target;
|
|
199
|
+
if (!target || target === this.inputEl()?.nativeElement) return true;
|
|
200
|
+
const button = target.closest("button");
|
|
201
|
+
return !!button && event.currentTarget.contains(button);
|
|
202
|
+
}
|
|
203
|
+
onFrameMousedown(event) {
|
|
204
|
+
if (!this.hitsFrameControl(event)) event.preventDefault();
|
|
205
|
+
}
|
|
206
|
+
onFrameClick(event) {
|
|
207
|
+
if (this.isDisabled() || this.hitsFrameControl(event)) return;
|
|
208
|
+
this.inputEl()?.nativeElement.focus();
|
|
209
|
+
}
|
|
197
210
|
onInputChange(event) {
|
|
198
211
|
const value = event.target.value;
|
|
199
212
|
this.query.set(value);
|
|
@@ -451,8 +464,8 @@ var ComboboxComponent = class ComboboxComponent {
|
|
|
451
464
|
isSignal: true
|
|
452
465
|
}],
|
|
453
466
|
ngImport: i0,
|
|
454
|
-
template: "<div [class]=\"containerClasses()\">\n @if (label()) {\n <label class=\"lc-combobox__label\" [for]=\"inputId\">{{ label() }}</label>\n }\n\n <div
|
|
455
|
-
styles: [".lc-combobox{display:flex;flex-direction:column;gap:.25rem;position:relative;font-family:var(--font-family-sans)}.lc-combobox__label{font-size:var(--font-size-sm, .875rem);font-weight:500;color:var(--color-text-primary);margin-bottom:.125rem}.lc-combobox__input-wrapper{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem;border:1px solid var(--color-field-border);border-radius:var(--border-radius-md, .375rem);background-color:var(--color-surface-2);padding:.25rem .5rem;transition:border-color .15s,box-shadow .15s;cursor:text}.lc-combobox__input-wrapper:hover{border-color:var(--color-text-secondary)}.lc-combobox__input-wrapper:focus-within{border-color:var(--color-primary-500);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary-500) 20%,transparent)}.lc-combobox--error .lc-combobox__input-wrapper{border-color:var(--color-error-default)}.lc-combobox--error .lc-combobox__input-wrapper:focus-within{outline:2px solid var(--color-error-default);outline-offset:0;box-shadow:none}.lc-combobox--disabled .lc-combobox__input-wrapper{opacity:.6;cursor:not-allowed;background-color:var(--color-surface-muted)}.lc-combobox--disabled .lc-combobox__input-wrapper:hover{border-color:var(--color-border)}.lc-combobox__input{flex:1;min-width:80px;border:none;outline:none;background:transparent;color:var(--color-text-primary);font-family:inherit}.lc-combobox__input::placeholder{color:var(--color-text-tertiary)}.lc-combobox__input:disabled{cursor:not-allowed}.lc-combobox--xs .lc-combobox__input{font-size:var(--font-size-xs, .75rem);height:1.5rem}.lc-combobox--sm .lc-combobox__input{font-size:var(--font-size-sm, .875rem);height:1.75rem}.lc-combobox--md .lc-combobox__input{font-size:var(--font-size-base, 1rem);height:2rem}.lc-combobox--lg .lc-combobox__input{font-size:var(--font-size-lg, 1.125rem);height:2.25rem}.lc-combobox__spinner{flex-shrink:0}.lc-combobox__clear{display:inline-flex;align-items:center;justify-content:center;width:
|
|
467
|
+
template: "<div [class]=\"containerClasses()\">\n @if (label()) {\n <label class=\"lc-combobox__label\" [for]=\"inputId\">{{ label() }}</label>\n }\n\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- pointer shortcut; the input is the keyboard target -->\n <div\n #inputWrapper\n class=\"lc-combobox__input-wrapper\"\n (mousedown)=\"onFrameMousedown($event)\"\n (click)=\"onFrameClick($event)\"\n >\n <!-- Selected chips (multiple mode) -->\n @if (multiple()) {\n @for (sel of selectedMultiple(); track sel.value) {\n <lc-chip\n [removable]=\"!isDisabled()\"\n size=\"sm\"\n (remove)=\"removeSelected(sel)\"\n >{{ sel.label }}</lc-chip>\n }\n }\n\n <input\n #inputEl\n type=\"text\"\n class=\"lc-combobox__input\"\n [id]=\"inputId\"\n [placeholder]=\"multiple() && selectedMultiple().length > 0 ? '' : placeholder()\"\n [value]=\"query()\"\n [disabled]=\"isDisabled()\"\n role=\"combobox\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-invalid]=\"error() ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n autocomplete=\"off\"\n (input)=\"onInputChange($event)\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n\n @if (isLoading() || loading()) {\n <lc-spinner size=\"sm\" class=\"lc-combobox__spinner\" />\n } @else if (!multiple() && selectedSingle()) {\n <button\n type=\"button\"\n class=\"lc-combobox__clear\"\n [disabled]=\"isDisabled()\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"onClearClick()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <lc-icon name=\"x-mark\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n\n <!-- Dropdown: rendered in the CDK overlay container so overflow-hidden\n ancestors cannot clip it. Focus stays in the input (mousedown is\n prevented on the panel), keyboard nav uses aria-activedescendant. -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"inputWrapper\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayMatchWidth]=\"true\"\n (detach)=\"isOpen.set(false)\"\n >\n <div\n #dropdownEl\n class=\"lc-combobox__dropdown\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\n (mousedown)=\"$event.preventDefault()\"\n >\n @for (group of groupedOptions(); track group.label) {\n @if (group.label) {\n <div class=\"lc-combobox__group-header\" role=\"presentation\">{{ group.label }}</div>\n }\n @for (option of group.items; track option.value) {\n @let idx = flatOptions().indexOf(option);\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays in the input, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-combobox__option\"\n [class.lc-combobox__option--highlighted]=\"idx === highlightedIndex()\"\n [class.lc-combobox__option--disabled]=\"option.disabled\"\n role=\"option\"\n [id]=\"optionId(idx)\"\n [attr.aria-selected]=\"idx === highlightedIndex()\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"!option.disabled && selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(idx)\"\n >\n @if (option.icon) {\n <lc-icon [name]=\"option.icon\" size=\"sm\" class=\"lc-combobox__option-icon\" [decorative]=\"true\" />\n }\n <div class=\"lc-combobox__option-content\">\n <span class=\"lc-combobox__option-label\">{{ option.label }}</span>\n @if (option.description) {\n <span class=\"lc-combobox__option-desc\">{{ option.description }}</span>\n }\n </div>\n </div>\n }\n }\n\n @if (showCreateOption()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays in the input, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-combobox__option lc-combobox__option--create\"\n [class.lc-combobox__option--highlighted]=\"highlightedIndex() === flatOptions().length\"\n role=\"option\"\n [id]=\"createOptionId\"\n [attr.aria-selected]=\"highlightedIndex() === flatOptions().length\"\n (click)=\"onCreateNew()\"\n (mouseenter)=\"highlightedIndex.set(flatOptions().length)\"\n >\n <lc-icon name=\"plus\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ createOptionLabel() }} \"{{ query() }}\"</span>\n </div>\n }\n\n @if (visibleOptions().length === 0 && !showCreateOption() && !isLoading() && !loading()) {\n <div class=\"lc-combobox__empty\">{{ emptyMessage() }}</div>\n }\n </div>\n </ng-template>\n\n @if (helperText() && !error()) {\n <span class=\"lc-combobox__helper\" [id]=\"inputId + '-helper'\">{{ helperText() }}</span>\n }\n @if (error()) {\n <span class=\"lc-combobox__error\" [id]=\"inputId + '-error'\" role=\"alert\">{{ error() }}</span>\n }\n</div>\n",
|
|
468
|
+
styles: [".lc-combobox{display:flex;flex-direction:column;gap:.25rem;position:relative;font-family:var(--font-family-sans)}.lc-combobox__label{font-size:var(--font-size-sm, .875rem);font-weight:500;color:var(--color-text-primary);margin-bottom:.125rem}.lc-combobox__input-wrapper{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem;border:1px solid var(--color-field-border);border-radius:var(--border-radius-md, .375rem);background-color:var(--color-surface-2);padding:.25rem .5rem;transition:border-color .15s,box-shadow .15s;cursor:text}.lc-combobox__input-wrapper:hover{border-color:var(--color-text-secondary)}.lc-combobox__input-wrapper:focus-within{border-color:var(--color-primary-500);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary-500) 20%,transparent)}.lc-combobox--error .lc-combobox__input-wrapper{border-color:var(--color-error-default)}.lc-combobox--error .lc-combobox__input-wrapper:focus-within{outline:2px solid var(--color-error-default);outline-offset:0;box-shadow:none}.lc-combobox--disabled .lc-combobox__input-wrapper{opacity:.6;cursor:not-allowed;background-color:var(--color-surface-muted)}.lc-combobox--disabled .lc-combobox__input-wrapper:hover{border-color:var(--color-border)}.lc-combobox__input{flex:1;min-width:80px;border:none;outline:none;background:transparent;color:var(--color-text-primary);font-family:inherit}.lc-combobox__input::placeholder{color:var(--color-text-tertiary)}.lc-combobox__input:disabled{cursor:not-allowed}.lc-combobox--xs .lc-combobox__input{font-size:var(--font-size-xs, .75rem);height:1.5rem}.lc-combobox--sm .lc-combobox__input{font-size:var(--font-size-sm, .875rem);height:1.75rem}.lc-combobox--md .lc-combobox__input{font-size:var(--font-size-base, 1rem);height:2rem}.lc-combobox--lg .lc-combobox__input{font-size:var(--font-size-lg, 1.125rem);height:2.75rem;margin-block:-.25rem}.lc-combobox__spinner{flex-shrink:0}.lc-combobox__clear{position:relative;display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin:-.125rem;padding:.125rem;border:none;background:transparent;background-clip:content-box;cursor:pointer;color:var(--color-text-tertiary);border-radius:calc(var(--border-radius-sm) + .125rem);flex-shrink:0}.lc-combobox__clear:hover:not(:disabled){color:var(--color-text-primary);background-color:var(--color-surface-hover)}.lc-combobox__clear:disabled{cursor:not-allowed}.lc-combobox__clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:0}.lc-combobox--lg .lc-combobox__clear{margin-inline-start:.625rem}.lc-combobox--lg .lc-combobox__clear:before{content:\"\";position:absolute;inset:-.625rem -.375rem -.625rem -.875rem}.lc-combobox__dropdown{margin-top:.25rem;max-height:240px;overflow-y:auto;background-color:var(--color-surface-raised);border:1px solid var(--color-border-strong);border-radius:var(--border-radius-md, .375rem);box-shadow:var(--elevation-3)}.lc-combobox__group-header{padding:.375rem .75rem;font-size:var(--font-size-xs, .75rem);font-weight:600;color:var(--color-text-tertiary);text-transform:uppercase;letter-spacing:.05em;margin-top:.25rem}.lc-combobox__group-header:first-child{margin-top:0}.lc-combobox__option{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;cursor:pointer;transition:background-color .1s}.lc-combobox__option--highlighted{background-color:var(--color-surface-hover)}.lc-combobox__option--disabled{opacity:.5;cursor:not-allowed}.lc-combobox__option--create{color:var(--color-primary-600);font-weight:500;border-top:1px solid var(--color-divider)}.lc-combobox__option-icon{flex-shrink:0;color:var(--color-text-tertiary)}.lc-combobox__option-content{display:flex;flex-direction:column;min-width:0}.lc-combobox__option-label{font-size:var(--font-size-sm, .875rem);color:var(--color-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-combobox__option-desc{font-size:var(--font-size-xs, .75rem);color:var(--color-text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-combobox__empty{padding:.75rem;text-align:center;color:var(--color-text-tertiary);font-size:var(--font-size-sm, .875rem)}.lc-combobox__helper{font-size:var(--font-size-xs, .75rem);color:var(--color-text-secondary)}.lc-combobox__error{font-size:var(--font-size-xs, .75rem);color:var(--color-text-error)}@media(forced-colors:active){.lc-combobox--error .lc-combobox__input-wrapper:focus-within{outline-color:Highlight}.lc-combobox__clear:focus-visible{outline-color:Highlight}}\n"],
|
|
456
469
|
dependencies: [
|
|
457
470
|
{
|
|
458
471
|
kind: "ngmodule",
|
|
@@ -566,8 +579,8 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
566
579
|
useExisting: forwardRef(() => ComboboxComponent),
|
|
567
580
|
multi: true
|
|
568
581
|
}],
|
|
569
|
-
template: "<div [class]=\"containerClasses()\">\n @if (label()) {\n <label class=\"lc-combobox__label\" [for]=\"inputId\">{{ label() }}</label>\n }\n\n <div
|
|
570
|
-
styles: [".lc-combobox{display:flex;flex-direction:column;gap:.25rem;position:relative;font-family:var(--font-family-sans)}.lc-combobox__label{font-size:var(--font-size-sm, .875rem);font-weight:500;color:var(--color-text-primary);margin-bottom:.125rem}.lc-combobox__input-wrapper{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem;border:1px solid var(--color-field-border);border-radius:var(--border-radius-md, .375rem);background-color:var(--color-surface-2);padding:.25rem .5rem;transition:border-color .15s,box-shadow .15s;cursor:text}.lc-combobox__input-wrapper:hover{border-color:var(--color-text-secondary)}.lc-combobox__input-wrapper:focus-within{border-color:var(--color-primary-500);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary-500) 20%,transparent)}.lc-combobox--error .lc-combobox__input-wrapper{border-color:var(--color-error-default)}.lc-combobox--error .lc-combobox__input-wrapper:focus-within{outline:2px solid var(--color-error-default);outline-offset:0;box-shadow:none}.lc-combobox--disabled .lc-combobox__input-wrapper{opacity:.6;cursor:not-allowed;background-color:var(--color-surface-muted)}.lc-combobox--disabled .lc-combobox__input-wrapper:hover{border-color:var(--color-border)}.lc-combobox__input{flex:1;min-width:80px;border:none;outline:none;background:transparent;color:var(--color-text-primary);font-family:inherit}.lc-combobox__input::placeholder{color:var(--color-text-tertiary)}.lc-combobox__input:disabled{cursor:not-allowed}.lc-combobox--xs .lc-combobox__input{font-size:var(--font-size-xs, .75rem);height:1.5rem}.lc-combobox--sm .lc-combobox__input{font-size:var(--font-size-sm, .875rem);height:1.75rem}.lc-combobox--md .lc-combobox__input{font-size:var(--font-size-base, 1rem);height:2rem}.lc-combobox--lg .lc-combobox__input{font-size:var(--font-size-lg, 1.125rem);height:2.25rem}.lc-combobox__spinner{flex-shrink:0}.lc-combobox__clear{display:inline-flex;align-items:center;justify-content:center;width:
|
|
582
|
+
template: "<div [class]=\"containerClasses()\">\n @if (label()) {\n <label class=\"lc-combobox__label\" [for]=\"inputId\">{{ label() }}</label>\n }\n\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- pointer shortcut; the input is the keyboard target -->\n <div\n #inputWrapper\n class=\"lc-combobox__input-wrapper\"\n (mousedown)=\"onFrameMousedown($event)\"\n (click)=\"onFrameClick($event)\"\n >\n <!-- Selected chips (multiple mode) -->\n @if (multiple()) {\n @for (sel of selectedMultiple(); track sel.value) {\n <lc-chip\n [removable]=\"!isDisabled()\"\n size=\"sm\"\n (remove)=\"removeSelected(sel)\"\n >{{ sel.label }}</lc-chip>\n }\n }\n\n <input\n #inputEl\n type=\"text\"\n class=\"lc-combobox__input\"\n [id]=\"inputId\"\n [placeholder]=\"multiple() && selectedMultiple().length > 0 ? '' : placeholder()\"\n [value]=\"query()\"\n [disabled]=\"isDisabled()\"\n role=\"combobox\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-invalid]=\"error() ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n autocomplete=\"off\"\n (input)=\"onInputChange($event)\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n\n @if (isLoading() || loading()) {\n <lc-spinner size=\"sm\" class=\"lc-combobox__spinner\" />\n } @else if (!multiple() && selectedSingle()) {\n <button\n type=\"button\"\n class=\"lc-combobox__clear\"\n [disabled]=\"isDisabled()\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"onClearClick()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <lc-icon name=\"x-mark\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n\n <!-- Dropdown: rendered in the CDK overlay container so overflow-hidden\n ancestors cannot clip it. Focus stays in the input (mousedown is\n prevented on the panel), keyboard nav uses aria-activedescendant. -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"inputWrapper\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayMatchWidth]=\"true\"\n (detach)=\"isOpen.set(false)\"\n >\n <div\n #dropdownEl\n class=\"lc-combobox__dropdown\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\n (mousedown)=\"$event.preventDefault()\"\n >\n @for (group of groupedOptions(); track group.label) {\n @if (group.label) {\n <div class=\"lc-combobox__group-header\" role=\"presentation\">{{ group.label }}</div>\n }\n @for (option of group.items; track option.value) {\n @let idx = flatOptions().indexOf(option);\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays in the input, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-combobox__option\"\n [class.lc-combobox__option--highlighted]=\"idx === highlightedIndex()\"\n [class.lc-combobox__option--disabled]=\"option.disabled\"\n role=\"option\"\n [id]=\"optionId(idx)\"\n [attr.aria-selected]=\"idx === highlightedIndex()\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"!option.disabled && selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(idx)\"\n >\n @if (option.icon) {\n <lc-icon [name]=\"option.icon\" size=\"sm\" class=\"lc-combobox__option-icon\" [decorative]=\"true\" />\n }\n <div class=\"lc-combobox__option-content\">\n <span class=\"lc-combobox__option-label\">{{ option.label }}</span>\n @if (option.description) {\n <span class=\"lc-combobox__option-desc\">{{ option.description }}</span>\n }\n </div>\n </div>\n }\n }\n\n @if (showCreateOption()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays in the input, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-combobox__option lc-combobox__option--create\"\n [class.lc-combobox__option--highlighted]=\"highlightedIndex() === flatOptions().length\"\n role=\"option\"\n [id]=\"createOptionId\"\n [attr.aria-selected]=\"highlightedIndex() === flatOptions().length\"\n (click)=\"onCreateNew()\"\n (mouseenter)=\"highlightedIndex.set(flatOptions().length)\"\n >\n <lc-icon name=\"plus\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ createOptionLabel() }} \"{{ query() }}\"</span>\n </div>\n }\n\n @if (visibleOptions().length === 0 && !showCreateOption() && !isLoading() && !loading()) {\n <div class=\"lc-combobox__empty\">{{ emptyMessage() }}</div>\n }\n </div>\n </ng-template>\n\n @if (helperText() && !error()) {\n <span class=\"lc-combobox__helper\" [id]=\"inputId + '-helper'\">{{ helperText() }}</span>\n }\n @if (error()) {\n <span class=\"lc-combobox__error\" [id]=\"inputId + '-error'\" role=\"alert\">{{ error() }}</span>\n }\n</div>\n",
|
|
583
|
+
styles: [".lc-combobox{display:flex;flex-direction:column;gap:.25rem;position:relative;font-family:var(--font-family-sans)}.lc-combobox__label{font-size:var(--font-size-sm, .875rem);font-weight:500;color:var(--color-text-primary);margin-bottom:.125rem}.lc-combobox__input-wrapper{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem;border:1px solid var(--color-field-border);border-radius:var(--border-radius-md, .375rem);background-color:var(--color-surface-2);padding:.25rem .5rem;transition:border-color .15s,box-shadow .15s;cursor:text}.lc-combobox__input-wrapper:hover{border-color:var(--color-text-secondary)}.lc-combobox__input-wrapper:focus-within{border-color:var(--color-primary-500);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary-500) 20%,transparent)}.lc-combobox--error .lc-combobox__input-wrapper{border-color:var(--color-error-default)}.lc-combobox--error .lc-combobox__input-wrapper:focus-within{outline:2px solid var(--color-error-default);outline-offset:0;box-shadow:none}.lc-combobox--disabled .lc-combobox__input-wrapper{opacity:.6;cursor:not-allowed;background-color:var(--color-surface-muted)}.lc-combobox--disabled .lc-combobox__input-wrapper:hover{border-color:var(--color-border)}.lc-combobox__input{flex:1;min-width:80px;border:none;outline:none;background:transparent;color:var(--color-text-primary);font-family:inherit}.lc-combobox__input::placeholder{color:var(--color-text-tertiary)}.lc-combobox__input:disabled{cursor:not-allowed}.lc-combobox--xs .lc-combobox__input{font-size:var(--font-size-xs, .75rem);height:1.5rem}.lc-combobox--sm .lc-combobox__input{font-size:var(--font-size-sm, .875rem);height:1.75rem}.lc-combobox--md .lc-combobox__input{font-size:var(--font-size-base, 1rem);height:2rem}.lc-combobox--lg .lc-combobox__input{font-size:var(--font-size-lg, 1.125rem);height:2.75rem;margin-block:-.25rem}.lc-combobox__spinner{flex-shrink:0}.lc-combobox__clear{position:relative;display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin:-.125rem;padding:.125rem;border:none;background:transparent;background-clip:content-box;cursor:pointer;color:var(--color-text-tertiary);border-radius:calc(var(--border-radius-sm) + .125rem);flex-shrink:0}.lc-combobox__clear:hover:not(:disabled){color:var(--color-text-primary);background-color:var(--color-surface-hover)}.lc-combobox__clear:disabled{cursor:not-allowed}.lc-combobox__clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:0}.lc-combobox--lg .lc-combobox__clear{margin-inline-start:.625rem}.lc-combobox--lg .lc-combobox__clear:before{content:\"\";position:absolute;inset:-.625rem -.375rem -.625rem -.875rem}.lc-combobox__dropdown{margin-top:.25rem;max-height:240px;overflow-y:auto;background-color:var(--color-surface-raised);border:1px solid var(--color-border-strong);border-radius:var(--border-radius-md, .375rem);box-shadow:var(--elevation-3)}.lc-combobox__group-header{padding:.375rem .75rem;font-size:var(--font-size-xs, .75rem);font-weight:600;color:var(--color-text-tertiary);text-transform:uppercase;letter-spacing:.05em;margin-top:.25rem}.lc-combobox__group-header:first-child{margin-top:0}.lc-combobox__option{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;cursor:pointer;transition:background-color .1s}.lc-combobox__option--highlighted{background-color:var(--color-surface-hover)}.lc-combobox__option--disabled{opacity:.5;cursor:not-allowed}.lc-combobox__option--create{color:var(--color-primary-600);font-weight:500;border-top:1px solid var(--color-divider)}.lc-combobox__option-icon{flex-shrink:0;color:var(--color-text-tertiary)}.lc-combobox__option-content{display:flex;flex-direction:column;min-width:0}.lc-combobox__option-label{font-size:var(--font-size-sm, .875rem);color:var(--color-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-combobox__option-desc{font-size:var(--font-size-xs, .75rem);color:var(--color-text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-combobox__empty{padding:.75rem;text-align:center;color:var(--color-text-tertiary);font-size:var(--font-size-sm, .875rem)}.lc-combobox__helper{font-size:var(--font-size-xs, .75rem);color:var(--color-text-secondary)}.lc-combobox__error{font-size:var(--font-size-xs, .75rem);color:var(--color-text-error)}@media(forced-colors:active){.lc-combobox--error .lc-combobox__input-wrapper:focus-within{outline-color:Highlight}.lc-combobox__clear:focus-visible{outline-color:Highlight}}\n"]
|
|
571
584
|
}]
|
|
572
585
|
}],
|
|
573
586
|
ctorParameters: () => [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-combobox.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/combobox/combobox.component.ts","../../../../libs/angular-ui-kit/src/lib/combobox/combobox.component.html"],"sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n input,\n output,\n signal,\n computed,\n afterRenderEffect,\n effect,\n forwardRef,\n ElementRef,\n viewChild,\n HostListener,\n inject,\n isDevMode,\n model,\n untracked,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\nimport { OverlayModule } from '@angular/cdk/overlay';\nimport { Observable, Subject, catchError, debounce, defer, of, switchMap, timer } from 'rxjs';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_PLUS, ICON_X_MARK } from '@lifecorner/angular-ui-kit/icons';\nimport { SpinnerComponent } from '@lifecorner/angular-ui-kit/spinner';\nimport { ChipComponent } from '@lifecorner/angular-ui-kit/chip';\n\nexport interface ComboboxOption {\n value: string;\n label: string;\n description?: string;\n icon?: string;\n group?: string;\n disabled?: boolean;\n}\n\nexport type ComboboxValue = ComboboxOption | ComboboxOption[] | null;\n\nexport type ComboboxSize = 'xs' | 'sm' | 'md' | 'lg';\n\n/**\n * Combobox / async autocomplete component.\n *\n * Supports free-text input with sync/async option suggestions,\n * single/multiple selection, create new entries, and keyboard navigation.\n * The suggestion list is rendered in a CDK overlay so it is never clipped\n * by `overflow: hidden` ancestors (cards, modals, table cells).\n *\n * The selection is two-way bindable by an option's `value` string\n * (`[(selectedValue)]`, single mode), next to the `valueChange` output with\n * the option object and the forms binding.\n *\n * @example\n * ```html\n * <lc-combobox\n * label=\"Assign to user\"\n * [loadOptions]=\"searchUsers\"\n * [(selectedValue)]=\"assigneeId\"\n * allowCreate\n * />\n * ```\n */\n@Component({\n selector: 'lc-combobox',\n standalone: true,\n imports: [OverlayModule, IconComponent, SpinnerComponent, ChipComponent],\n viewProviders: [ɵprovideKitIcons([ICON_X_MARK, ICON_PLUS])],\n templateUrl: './combobox.component.html',\n styleUrls: ['./combobox.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => ComboboxComponent),\n multi: true,\n },\n ],\n})\nexport class ComboboxComponent implements ControlValueAccessor {\n private static nextId = 0;\n\n /** Per-instance ids so label/listbox/options can be linked via ARIA */\n readonly inputId = `lc-combobox-${++ComboboxComponent.nextId}`;\n readonly listboxId = `${this.inputId}-listbox`;\n protected readonly createOptionId = `${this.listboxId}-create`;\n\n private readonly inputEl = viewChild<ElementRef<HTMLInputElement>>('inputEl');\n private readonly dropdownEl = viewChild<ElementRef<HTMLElement>>('dropdownEl');\n\n private readonly elRef = inject(ElementRef);\n private readonly querySubject = new Subject<string>();\n\n /** Sync options */\n readonly options = input<ComboboxOption[]>([]);\n\n /** Async option loader */\n readonly loadOptions = input<((query: string) => Observable<ComboboxOption[]>)>();\n\n /** Debounce for async queries */\n readonly debounceMs = input<number>(250);\n\n /** Minimum characters before triggering search */\n readonly minChars = input<number>(1);\n\n /** Placeholder text */\n readonly placeholder = input<string>('Search…');\n\n /** Label */\n readonly label = input<string>();\n\n /** Helper text */\n readonly helperText = input<string>();\n\n /** Error message */\n readonly error = input<string>();\n\n /** Disabled state */\n readonly disabled = input<boolean>(false);\n\n /** Allow multiple selections */\n readonly multiple = input<boolean>(false);\n\n /** Allow creating new entries */\n readonly allowCreate = input<boolean>(false);\n\n /** Show loading spinner (controlled) */\n readonly loading = input<boolean>(false);\n\n /** Empty state message */\n readonly emptyMessage = input<string>('No results');\n\n /** Accessible name of the clear button. */\n readonly clearAriaLabel = input('Clear');\n\n /** Label before the query in the \"create\" option (`allowCreate`): `Create \"query\"`. */\n readonly createOptionLabel = input('Create');\n\n /** Size */\n readonly size = input<ComboboxSize>('md');\n\n /**\n * The `value` of the selected option, two-way (3.29, regeln row 2):\n * `[(selectedValue)]=\"month\"`. Shows the matching option's label (from\n * `options`, or the current selection); an unknown value shows an empty\n * field and is filled in when `options` with it arrive. Page writes\n * (including back to `null`) select or clear silently: no\n * `selectedValueChange`, no `valueChange`, no forms `onChange`. Every user\n * choice or clear emits `selectedValueChange`, next to the unchanged\n * `valueChange` (the option object). Single mode only: ignored with\n * `multiple` (a dev warning). Use it or a forms binding, not both.\n * @default null\n */\n readonly selectedValue = model<string | null>(null);\n\n /** Value change event */\n readonly valueChange = output<ComboboxValue>();\n\n /** Query change event */\n readonly queryChange = output<string>();\n\n /** Option selected event */\n readonly optionSelected = output<ComboboxOption>();\n\n /** Created event (allowCreate) */\n readonly created = output<string>();\n\n /** Internal state */\n protected query = signal('');\n protected isOpen = signal(false);\n protected highlightedIndex = signal(-1);\n protected asyncOptions = signal<ComboboxOption[]>([]);\n protected isLoading = signal(false);\n\n /** Disabled via `setDisabledState` (reactive forms) */\n private readonly formDisabled = signal(false);\n\n /** Effective disabled state: `disabled` input OR form control disabled */\n protected readonly isDisabled = computed(() => this.disabled() || this.formDisabled());\n\n /** Selected values */\n protected selectedSingle = signal<ComboboxOption | null>(null);\n protected selectedMultiple = signal<ComboboxOption[]>([]);\n\n /** The last `selectedValue` the component applied or emitted: a different one is a page write. */\n private seenSelectedValue: string | null = null;\n\n /** A page-written `selectedValue` no option matched yet: selected silently once `options` hold it. */\n private pendingSelectedValue: string | null = null;\n\n /** Resolved visible options */\n protected visibleOptions = computed(() => {\n const q = this.query().toLowerCase();\n const loader = this.loadOptions();\n\n let opts: ComboboxOption[];\n if (loader) {\n opts = this.asyncOptions();\n } else {\n opts = this.options();\n if (q.length >= this.minChars()) {\n opts = opts.filter(\n (o) =>\n o.label.toLowerCase().includes(q) ||\n o.value.toLowerCase().includes(q) ||\n (o.description && o.description.toLowerCase().includes(q))\n );\n }\n }\n\n // Remove already selected in multiple mode\n if (this.multiple()) {\n const selected = new Set(this.selectedMultiple().map((s) => s.value));\n opts = opts.filter((o) => !selected.has(o.value));\n }\n\n return opts;\n });\n\n /** Grouped options */\n protected groupedOptions = computed(() => {\n const opts = this.visibleOptions();\n const groups = new Map<string, ComboboxOption[]>();\n\n for (const opt of opts) {\n const group = opt.group || '';\n if (!groups.has(group)) groups.set(group, []);\n groups.get(group)!.push(opt);\n }\n\n return Array.from(groups.entries()).map(([label, items]) => ({\n label,\n items,\n }));\n });\n\n /** Flat list for keyboard nav */\n protected flatOptions = computed(() => {\n return this.groupedOptions().flatMap((g) => g.items);\n });\n\n /** Whether to show \"Create\" option */\n protected showCreateOption = computed(() => {\n if (!this.allowCreate()) return false;\n const q = this.query().trim();\n if (!q) return false;\n const exact = this.visibleOptions().some(\n (o) => o.label.toLowerCase() === q.toLowerCase()\n );\n return !exact;\n });\n\n /** id of the highlighted option — announced via aria-activedescendant */\n protected readonly activeDescendantId = computed(() => {\n if (!this.isOpen()) return null;\n const i = this.highlightedIndex();\n if (i < 0) return null;\n if (i === this.flatOptions().length) {\n return this.showCreateOption() ? this.createOptionId : null;\n }\n return i < this.flatOptions().length ? this.optionId(i) : null;\n });\n\n /** ids referenced by aria-describedby (helper / error) */\n protected readonly describedBy = computed(() => {\n if (this.error()) return `${this.inputId}-error`;\n if (this.helperText()) return `${this.inputId}-helper`;\n return null;\n });\n\n /** Container classes */\n protected containerClasses = computed(() => {\n const classes = [`lc-combobox`, `lc-combobox--${this.size()}`];\n if (this.isDisabled()) classes.push('lc-combobox--disabled');\n if (this.error()) classes.push('lc-combobox--error');\n if (this.isOpen()) classes.push('lc-combobox--open');\n return classes.join(' ');\n });\n\n protected optionId(index: number): string {\n return `${this.listboxId}-opt-${index}`;\n }\n\n // ControlValueAccessor\n private onChange: (value: ComboboxValue) => void = () => { /* set by registerOnChange */ };\n private onTouched: () => void = () => { /* set by registerOnTouched */ };\n\n constructor() {\n // Async loading pipe. `debounce` (not `debounceTime`) reads the signal per\n // emission, so `debounceMs` is honoured after inputs are populated.\n this.querySubject\n .pipe(\n debounce(() => timer(this.debounceMs())),\n switchMap((q) => {\n const loader = this.loadOptions();\n if (!loader || q.length < this.minChars()) {\n return of([] as ComboboxOption[]);\n }\n this.isLoading.set(true);\n // `defer` turns a synchronously throwing loader into an error\n // notification; `catchError` keeps the pipe alive for the next query.\n return defer(() => loader(q)).pipe(catchError(() => of([] as ComboboxOption[])));\n }),\n takeUntilDestroyed()\n )\n .subscribe((results) => {\n this.asyncOptions.set(results);\n this.isLoading.set(false);\n });\n\n // Keep the highlighted option visible while navigating with the keyboard\n // (after render, so the option element exists in the overlay pane).\n afterRenderEffect(() => {\n const id = this.activeDescendantId();\n if (!id) return;\n untracked(() => {\n // ids are generated from a counter, so no CSS escaping is needed\n this.dropdownEl()\n ?.nativeElement.querySelector<HTMLElement>(`#${id}`)\n ?.scrollIntoView?.({ block: 'nearest' });\n });\n });\n\n // `selectedValue` (3.29): a page write selects or clears silently; an\n // unknown value waits for `options` that hold it. The component's own\n // writes (user choice, clear) are already applied, so they are skipped.\n effect(() => {\n const value = this.selectedValue();\n const options = this.options();\n untracked(() => {\n if (value !== this.seenSelectedValue) {\n this.seenSelectedValue = value;\n if (!this.multiple()) {\n this.applySelectedValue(value, options);\n } else if (value !== null && isDevMode()) {\n console.warn('[lc-combobox] selectedValue is ignored with multiple');\n }\n } else if (this.pendingSelectedValue !== null && !this.multiple()) {\n this.applySelectedValue(this.pendingSelectedValue, options);\n }\n });\n });\n }\n\n /** Shows the option with `value` (or clears for `null`) without emitting anything. */\n private applySelectedValue(value: string | null, options: ComboboxOption[]): void {\n this.pendingSelectedValue = null;\n if (value === null) {\n this.selectedSingle.set(null);\n this.query.set('');\n return;\n }\n if (this.selectedSingle()?.value === value) return;\n const match = options.find((o) => o.value === value) ?? null;\n if (!match) this.pendingSelectedValue = value;\n this.selectedSingle.set(match);\n this.query.set(match ? match.label : '');\n }\n\n /** Emits a user's single choice or clear through `selectedValueChange` (not in `multiple` mode). */\n private emitSelectedValue(value: string | null): void {\n if (this.multiple()) return;\n this.pendingSelectedValue = null;\n this.seenSelectedValue = value;\n this.selectedValue.set(value);\n }\n\n writeValue(value: ComboboxValue): void {\n if (this.multiple()) {\n this.selectedMultiple.set(Array.isArray(value) ? value : []);\n } else {\n const single = value && !Array.isArray(value) ? value : null;\n this.pendingSelectedValue = null;\n this.selectedSingle.set(single);\n this.query.set(single ? single.label : '');\n }\n }\n\n registerOnChange(fn: (value: ComboboxValue) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n if (isDisabled) this.isOpen.set(false);\n }\n\n /**\n * Clear the current selection and query. Emits `null` (single) or `[]`\n * (multiple) exactly once, like a user-initiated deselect.\n */\n clear(): void {\n this.query.set('');\n this.highlightedIndex.set(-1);\n this.isOpen.set(false);\n const value: ComboboxValue = this.multiple() ? [] : null;\n if (this.multiple()) {\n this.selectedMultiple.set([]);\n } else {\n this.selectedSingle.set(null);\n }\n this.onChange(value);\n this.valueChange.emit(value);\n this.emitSelectedValue(null);\n }\n\n protected onClearClick(): void {\n if (this.isDisabled()) return;\n this.clear();\n this.inputEl()?.nativeElement.focus();\n }\n\n protected onInputChange(event: Event): void {\n const value = (event.target as HTMLInputElement).value;\n this.query.set(value);\n this.queryChange.emit(value);\n this.highlightedIndex.set(-1);\n\n if (this.loadOptions()) {\n this.querySubject.next(value);\n }\n\n if (value.length >= this.minChars()) {\n this.isOpen.set(true);\n }\n }\n\n protected onInputFocus(): void {\n if (this.query().length >= this.minChars() || this.options().length > 0) {\n this.isOpen.set(true);\n }\n }\n\n protected onInputBlur(): void {\n this.onTouched();\n // Delay to allow click on dropdown\n setTimeout(() => this.isOpen.set(false), 200);\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n const flat = this.flatOptions();\n const total = flat.length + (this.showCreateOption() ? 1 : 0);\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n this.isOpen.set(true);\n if (total > 0) this.highlightedIndex.update((i) => (i + 1) % total);\n break;\n case 'ArrowUp':\n event.preventDefault();\n if (total > 0) this.highlightedIndex.update((i) => (i - 1 + total) % total);\n break;\n case 'Enter':\n event.preventDefault();\n if (this.highlightedIndex() >= 0) {\n if (this.highlightedIndex() === flat.length && this.showCreateOption()) {\n this.onCreateNew();\n } else {\n const opt = flat[this.highlightedIndex()];\n if (opt && !opt.disabled) {\n this.selectOption(opt);\n }\n }\n } else if (this.showCreateOption()) {\n this.onCreateNew();\n }\n break;\n case 'Escape':\n if (this.isOpen()) {\n this.isOpen.set(false);\n this.highlightedIndex.set(-1);\n // Escape consumed by the list — an enclosing modal must not close too.\n event.stopPropagation();\n }\n break;\n case 'Tab':\n if (this.highlightedIndex() >= 0 && this.isOpen()) {\n const opt = flat[this.highlightedIndex()];\n if (opt && !opt.disabled) {\n this.selectOption(opt);\n }\n }\n this.isOpen.set(false);\n break;\n case 'Backspace':\n if (this.multiple() && !this.query() && this.selectedMultiple().length > 0) {\n this.removeSelected(this.selectedMultiple()[this.selectedMultiple().length - 1]);\n }\n break;\n }\n }\n\n protected selectOption(option: ComboboxOption): void {\n if (this.multiple()) {\n this.selectedMultiple.update((sel) => [...sel, option]);\n this.query.set('');\n const value = this.selectedMultiple();\n this.onChange(value);\n this.valueChange.emit(value);\n } else {\n this.selectedSingle.set(option);\n this.query.set(option.label);\n this.onChange(option);\n this.valueChange.emit(option);\n this.emitSelectedValue(option.value);\n }\n this.optionSelected.emit(option);\n this.isOpen.set(false);\n this.highlightedIndex.set(-1);\n }\n\n protected removeSelected(option: ComboboxOption): void {\n if (this.isDisabled()) return;\n this.selectedMultiple.update((sel) =>\n sel.filter((s) => s.value !== option.value)\n );\n const value = this.selectedMultiple();\n this.onChange(value);\n this.valueChange.emit(value);\n this.inputEl()?.nativeElement.focus();\n }\n\n protected onCreateNew(): void {\n const q = this.query().trim();\n if (!q) return;\n const newOption: ComboboxOption = { value: q, label: q };\n this.created.emit(q);\n this.selectOption(newOption);\n }\n\n @HostListener('document:click', ['$event'])\n protected onDocumentClick(event: MouseEvent): void {\n const target = event.target as Node | null;\n // The dropdown lives in the CDK overlay container, outside the host element.\n if (\n !this.elRef.nativeElement.contains(target) &&\n !this.dropdownEl()?.nativeElement.contains(target)\n ) {\n this.isOpen.set(false);\n }\n }\n}\n","<div [class]=\"containerClasses()\">\n @if (label()) {\n <label class=\"lc-combobox__label\" [for]=\"inputId\">{{ label() }}</label>\n }\n\n <div #inputWrapper class=\"lc-combobox__input-wrapper\">\n <!-- Selected chips (multiple mode) -->\n @if (multiple()) {\n @for (sel of selectedMultiple(); track sel.value) {\n <lc-chip\n [removable]=\"!isDisabled()\"\n size=\"sm\"\n (remove)=\"removeSelected(sel)\"\n >{{ sel.label }}</lc-chip>\n }\n }\n\n <input\n #inputEl\n type=\"text\"\n class=\"lc-combobox__input\"\n [id]=\"inputId\"\n [placeholder]=\"multiple() && selectedMultiple().length > 0 ? '' : placeholder()\"\n [value]=\"query()\"\n [disabled]=\"isDisabled()\"\n role=\"combobox\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-invalid]=\"error() ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n autocomplete=\"off\"\n (input)=\"onInputChange($event)\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n\n @if (isLoading() || loading()) {\n <lc-spinner size=\"sm\" class=\"lc-combobox__spinner\" />\n } @else if (!multiple() && selectedSingle()) {\n <button\n type=\"button\"\n class=\"lc-combobox__clear\"\n [disabled]=\"isDisabled()\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"onClearClick()\"\n tabindex=\"-1\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <lc-icon name=\"x-mark\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n\n <!-- Dropdown: rendered in the CDK overlay container so overflow-hidden\n ancestors cannot clip it. Focus stays in the input (mousedown is\n prevented on the panel), keyboard nav uses aria-activedescendant. -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"inputWrapper\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayMatchWidth]=\"true\"\n (detach)=\"isOpen.set(false)\"\n >\n <div\n #dropdownEl\n class=\"lc-combobox__dropdown\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\n (mousedown)=\"$event.preventDefault()\"\n >\n @for (group of groupedOptions(); track group.label) {\n @if (group.label) {\n <div class=\"lc-combobox__group-header\" role=\"presentation\">{{ group.label }}</div>\n }\n @for (option of group.items; track option.value) {\n @let idx = flatOptions().indexOf(option);\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays in the input, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-combobox__option\"\n [class.lc-combobox__option--highlighted]=\"idx === highlightedIndex()\"\n [class.lc-combobox__option--disabled]=\"option.disabled\"\n role=\"option\"\n [id]=\"optionId(idx)\"\n [attr.aria-selected]=\"idx === highlightedIndex()\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"!option.disabled && selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(idx)\"\n >\n @if (option.icon) {\n <lc-icon [name]=\"option.icon\" size=\"sm\" class=\"lc-combobox__option-icon\" [decorative]=\"true\" />\n }\n <div class=\"lc-combobox__option-content\">\n <span class=\"lc-combobox__option-label\">{{ option.label }}</span>\n @if (option.description) {\n <span class=\"lc-combobox__option-desc\">{{ option.description }}</span>\n }\n </div>\n </div>\n }\n }\n\n @if (showCreateOption()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays in the input, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-combobox__option lc-combobox__option--create\"\n [class.lc-combobox__option--highlighted]=\"highlightedIndex() === flatOptions().length\"\n role=\"option\"\n [id]=\"createOptionId\"\n [attr.aria-selected]=\"highlightedIndex() === flatOptions().length\"\n (click)=\"onCreateNew()\"\n (mouseenter)=\"highlightedIndex.set(flatOptions().length)\"\n >\n <lc-icon name=\"plus\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ createOptionLabel() }} \"{{ query() }}\"</span>\n </div>\n }\n\n @if (visibleOptions().length === 0 && !showCreateOption() && !isLoading() && !loading()) {\n <div class=\"lc-combobox__empty\">{{ emptyMessage() }}</div>\n }\n </div>\n </ng-template>\n\n @if (helperText() && !error()) {\n <span class=\"lc-combobox__helper\" [id]=\"inputId + '-helper'\">{{ helperText() }}</span>\n }\n @if (error()) {\n <span class=\"lc-combobox__error\" [id]=\"inputId + '-error'\" role=\"alert\">{{ error() }}</span>\n }\n</div>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-combobox.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/combobox/combobox.component.ts","../../../../libs/angular-ui-kit/src/lib/combobox/combobox.component.html"],"sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n input,\n output,\n signal,\n computed,\n afterRenderEffect,\n effect,\n forwardRef,\n ElementRef,\n viewChild,\n HostListener,\n inject,\n isDevMode,\n model,\n untracked,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\nimport { OverlayModule } from '@angular/cdk/overlay';\nimport { Observable, Subject, catchError, debounce, defer, of, switchMap, timer } from 'rxjs';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_PLUS, ICON_X_MARK } from '@lifecorner/angular-ui-kit/icons';\nimport { SpinnerComponent } from '@lifecorner/angular-ui-kit/spinner';\nimport { ChipComponent } from '@lifecorner/angular-ui-kit/chip';\n\nexport interface ComboboxOption {\n value: string;\n label: string;\n description?: string;\n icon?: string;\n group?: string;\n disabled?: boolean;\n}\n\nexport type ComboboxValue = ComboboxOption | ComboboxOption[] | null;\n\nexport type ComboboxSize = 'xs' | 'sm' | 'md' | 'lg';\n\n/**\n * Combobox / async autocomplete component.\n *\n * Supports free-text input with sync/async option suggestions,\n * single/multiple selection, create new entries, and keyboard navigation.\n * The suggestion list is rendered in a CDK overlay so it is never clipped\n * by `overflow: hidden` ancestors (cards, modals, table cells).\n *\n * The selection is two-way bindable by an option's `value` string\n * (`[(selectedValue)]`, single mode), next to the `valueChange` output with\n * the option object and the forms binding.\n *\n * @example\n * ```html\n * <lc-combobox\n * label=\"Assign to user\"\n * [loadOptions]=\"searchUsers\"\n * [(selectedValue)]=\"assigneeId\"\n * allowCreate\n * />\n * ```\n */\n@Component({\n selector: 'lc-combobox',\n standalone: true,\n imports: [OverlayModule, IconComponent, SpinnerComponent, ChipComponent],\n viewProviders: [ɵprovideKitIcons([ICON_X_MARK, ICON_PLUS])],\n templateUrl: './combobox.component.html',\n styleUrls: ['./combobox.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => ComboboxComponent),\n multi: true,\n },\n ],\n})\nexport class ComboboxComponent implements ControlValueAccessor {\n private static nextId = 0;\n\n /** Per-instance ids so label/listbox/options can be linked via ARIA */\n readonly inputId = `lc-combobox-${++ComboboxComponent.nextId}`;\n readonly listboxId = `${this.inputId}-listbox`;\n protected readonly createOptionId = `${this.listboxId}-create`;\n\n private readonly inputEl = viewChild<ElementRef<HTMLInputElement>>('inputEl');\n private readonly dropdownEl = viewChild<ElementRef<HTMLElement>>('dropdownEl');\n\n private readonly elRef = inject(ElementRef);\n private readonly querySubject = new Subject<string>();\n\n /** Sync options */\n readonly options = input<ComboboxOption[]>([]);\n\n /** Async option loader */\n readonly loadOptions = input<((query: string) => Observable<ComboboxOption[]>)>();\n\n /** Debounce for async queries */\n readonly debounceMs = input<number>(250);\n\n /** Minimum characters before triggering search */\n readonly minChars = input<number>(1);\n\n /** Placeholder text */\n readonly placeholder = input<string>('Search…');\n\n /** Label */\n readonly label = input<string>();\n\n /** Helper text */\n readonly helperText = input<string>();\n\n /** Error message */\n readonly error = input<string>();\n\n /** Disabled state */\n readonly disabled = input<boolean>(false);\n\n /** Allow multiple selections */\n readonly multiple = input<boolean>(false);\n\n /** Allow creating new entries */\n readonly allowCreate = input<boolean>(false);\n\n /** Show loading spinner (controlled) */\n readonly loading = input<boolean>(false);\n\n /** Empty state message */\n readonly emptyMessage = input<string>('No results');\n\n /** Accessible name of the clear button. */\n readonly clearAriaLabel = input('Clear');\n\n /** Label before the query in the \"create\" option (`allowCreate`): `Create \"query\"`. */\n readonly createOptionLabel = input('Create');\n\n /** Size */\n readonly size = input<ComboboxSize>('md');\n\n /**\n * The `value` of the selected option, two-way (3.29, regeln row 2):\n * `[(selectedValue)]=\"month\"`. Shows the matching option's label (from\n * `options`, or the current selection); an unknown value shows an empty\n * field and is filled in when `options` with it arrive. Page writes\n * (including back to `null`) select or clear silently: no\n * `selectedValueChange`, no `valueChange`, no forms `onChange`. Every user\n * choice or clear emits `selectedValueChange`, next to the unchanged\n * `valueChange` (the option object). Single mode only: ignored with\n * `multiple` (a dev warning). Use it or a forms binding, not both.\n * @default null\n */\n readonly selectedValue = model<string | null>(null);\n\n /** Value change event */\n readonly valueChange = output<ComboboxValue>();\n\n /** Query change event */\n readonly queryChange = output<string>();\n\n /** Option selected event */\n readonly optionSelected = output<ComboboxOption>();\n\n /** Created event (allowCreate) */\n readonly created = output<string>();\n\n /** Internal state */\n protected query = signal('');\n protected isOpen = signal(false);\n protected highlightedIndex = signal(-1);\n protected asyncOptions = signal<ComboboxOption[]>([]);\n protected isLoading = signal(false);\n\n /** Disabled via `setDisabledState` (reactive forms) */\n private readonly formDisabled = signal(false);\n\n /** Effective disabled state: `disabled` input OR form control disabled */\n protected readonly isDisabled = computed(() => this.disabled() || this.formDisabled());\n\n /** Selected values */\n protected selectedSingle = signal<ComboboxOption | null>(null);\n protected selectedMultiple = signal<ComboboxOption[]>([]);\n\n /** The last `selectedValue` the component applied or emitted: a different one is a page write. */\n private seenSelectedValue: string | null = null;\n\n /** A page-written `selectedValue` no option matched yet: selected silently once `options` hold it. */\n private pendingSelectedValue: string | null = null;\n\n /** Resolved visible options */\n protected visibleOptions = computed(() => {\n const q = this.query().toLowerCase();\n const loader = this.loadOptions();\n\n let opts: ComboboxOption[];\n if (loader) {\n opts = this.asyncOptions();\n } else {\n opts = this.options();\n if (q.length >= this.minChars()) {\n opts = opts.filter(\n (o) =>\n o.label.toLowerCase().includes(q) ||\n o.value.toLowerCase().includes(q) ||\n (o.description && o.description.toLowerCase().includes(q))\n );\n }\n }\n\n // Remove already selected in multiple mode\n if (this.multiple()) {\n const selected = new Set(this.selectedMultiple().map((s) => s.value));\n opts = opts.filter((o) => !selected.has(o.value));\n }\n\n return opts;\n });\n\n /** Grouped options */\n protected groupedOptions = computed(() => {\n const opts = this.visibleOptions();\n const groups = new Map<string, ComboboxOption[]>();\n\n for (const opt of opts) {\n const group = opt.group || '';\n if (!groups.has(group)) groups.set(group, []);\n groups.get(group)!.push(opt);\n }\n\n return Array.from(groups.entries()).map(([label, items]) => ({\n label,\n items,\n }));\n });\n\n /** Flat list for keyboard nav */\n protected flatOptions = computed(() => {\n return this.groupedOptions().flatMap((g) => g.items);\n });\n\n /** Whether to show \"Create\" option */\n protected showCreateOption = computed(() => {\n if (!this.allowCreate()) return false;\n const q = this.query().trim();\n if (!q) return false;\n const exact = this.visibleOptions().some(\n (o) => o.label.toLowerCase() === q.toLowerCase()\n );\n return !exact;\n });\n\n /** id of the highlighted option — announced via aria-activedescendant */\n protected readonly activeDescendantId = computed(() => {\n if (!this.isOpen()) return null;\n const i = this.highlightedIndex();\n if (i < 0) return null;\n if (i === this.flatOptions().length) {\n return this.showCreateOption() ? this.createOptionId : null;\n }\n return i < this.flatOptions().length ? this.optionId(i) : null;\n });\n\n /** ids referenced by aria-describedby (helper / error) */\n protected readonly describedBy = computed(() => {\n if (this.error()) return `${this.inputId}-error`;\n if (this.helperText()) return `${this.inputId}-helper`;\n return null;\n });\n\n /** Container classes */\n protected containerClasses = computed(() => {\n const classes = [`lc-combobox`, `lc-combobox--${this.size()}`];\n if (this.isDisabled()) classes.push('lc-combobox--disabled');\n if (this.error()) classes.push('lc-combobox--error');\n if (this.isOpen()) classes.push('lc-combobox--open');\n return classes.join(' ');\n });\n\n protected optionId(index: number): string {\n return `${this.listboxId}-opt-${index}`;\n }\n\n // ControlValueAccessor\n private onChange: (value: ComboboxValue) => void = () => { /* set by registerOnChange */ };\n private onTouched: () => void = () => { /* set by registerOnTouched */ };\n\n constructor() {\n // Async loading pipe. `debounce` (not `debounceTime`) reads the signal per\n // emission, so `debounceMs` is honoured after inputs are populated.\n this.querySubject\n .pipe(\n debounce(() => timer(this.debounceMs())),\n switchMap((q) => {\n const loader = this.loadOptions();\n if (!loader || q.length < this.minChars()) {\n return of([] as ComboboxOption[]);\n }\n this.isLoading.set(true);\n // `defer` turns a synchronously throwing loader into an error\n // notification; `catchError` keeps the pipe alive for the next query.\n return defer(() => loader(q)).pipe(catchError(() => of([] as ComboboxOption[])));\n }),\n takeUntilDestroyed()\n )\n .subscribe((results) => {\n this.asyncOptions.set(results);\n this.isLoading.set(false);\n });\n\n // Keep the highlighted option visible while navigating with the keyboard\n // (after render, so the option element exists in the overlay pane).\n afterRenderEffect(() => {\n const id = this.activeDescendantId();\n if (!id) return;\n untracked(() => {\n // ids are generated from a counter, so no CSS escaping is needed\n this.dropdownEl()\n ?.nativeElement.querySelector<HTMLElement>(`#${id}`)\n ?.scrollIntoView?.({ block: 'nearest' });\n });\n });\n\n // `selectedValue` (3.29): a page write selects or clears silently; an\n // unknown value waits for `options` that hold it. The component's own\n // writes (user choice, clear) are already applied, so they are skipped.\n effect(() => {\n const value = this.selectedValue();\n const options = this.options();\n untracked(() => {\n if (value !== this.seenSelectedValue) {\n this.seenSelectedValue = value;\n if (!this.multiple()) {\n this.applySelectedValue(value, options);\n } else if (value !== null && isDevMode()) {\n console.warn('[lc-combobox] selectedValue is ignored with multiple');\n }\n } else if (this.pendingSelectedValue !== null && !this.multiple()) {\n this.applySelectedValue(this.pendingSelectedValue, options);\n }\n });\n });\n }\n\n /** Shows the option with `value` (or clears for `null`) without emitting anything. */\n private applySelectedValue(value: string | null, options: ComboboxOption[]): void {\n this.pendingSelectedValue = null;\n if (value === null) {\n this.selectedSingle.set(null);\n this.query.set('');\n return;\n }\n if (this.selectedSingle()?.value === value) return;\n const match = options.find((o) => o.value === value) ?? null;\n if (!match) this.pendingSelectedValue = value;\n this.selectedSingle.set(match);\n this.query.set(match ? match.label : '');\n }\n\n /** Emits a user's single choice or clear through `selectedValueChange` (not in `multiple` mode). */\n private emitSelectedValue(value: string | null): void {\n if (this.multiple()) return;\n this.pendingSelectedValue = null;\n this.seenSelectedValue = value;\n this.selectedValue.set(value);\n }\n\n writeValue(value: ComboboxValue): void {\n if (this.multiple()) {\n this.selectedMultiple.set(Array.isArray(value) ? value : []);\n } else {\n const single = value && !Array.isArray(value) ? value : null;\n this.pendingSelectedValue = null;\n this.selectedSingle.set(single);\n this.query.set(single ? single.label : '');\n }\n }\n\n registerOnChange(fn: (value: ComboboxValue) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n if (isDisabled) this.isOpen.set(false);\n }\n\n /**\n * Clear the current selection and query. Emits `null` (single) or `[]`\n * (multiple) exactly once, like a user-initiated deselect.\n */\n clear(): void {\n this.query.set('');\n this.highlightedIndex.set(-1);\n this.isOpen.set(false);\n const value: ComboboxValue = this.multiple() ? [] : null;\n if (this.multiple()) {\n this.selectedMultiple.set([]);\n } else {\n this.selectedSingle.set(null);\n }\n this.onChange(value);\n this.valueChange.emit(value);\n this.emitSelectedValue(null);\n }\n\n protected onClearClick(): void {\n if (this.isDisabled()) return;\n this.clear();\n this.inputEl()?.nativeElement.focus();\n }\n\n /** Whether a pointer event on the frame hit the input or a button in it (chip ×, clear). */\n private hitsFrameControl(event: MouseEvent): boolean {\n const target = event.target as Element | null;\n if (!target || target === this.inputEl()?.nativeElement) return true;\n const button = target.closest('button');\n return !!button && (event.currentTarget as Element).contains(button);\n }\n\n /**\n * 3.30 (request 047, regeln row 6): a press on the frame beside the input\n * and its buttons keeps focus where it is (no blur, so the list stays open).\n */\n protected onFrameMousedown(event: MouseEvent): void {\n if (!this.hitsFrameControl(event)) event.preventDefault();\n }\n\n /** A click on the frame beside the input and its buttons focuses the input. */\n protected onFrameClick(event: MouseEvent): void {\n if (this.isDisabled() || this.hitsFrameControl(event)) return;\n this.inputEl()?.nativeElement.focus();\n }\n\n protected onInputChange(event: Event): void {\n const value = (event.target as HTMLInputElement).value;\n this.query.set(value);\n this.queryChange.emit(value);\n this.highlightedIndex.set(-1);\n\n if (this.loadOptions()) {\n this.querySubject.next(value);\n }\n\n if (value.length >= this.minChars()) {\n this.isOpen.set(true);\n }\n }\n\n protected onInputFocus(): void {\n if (this.query().length >= this.minChars() || this.options().length > 0) {\n this.isOpen.set(true);\n }\n }\n\n protected onInputBlur(): void {\n this.onTouched();\n // Delay to allow click on dropdown\n setTimeout(() => this.isOpen.set(false), 200);\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n const flat = this.flatOptions();\n const total = flat.length + (this.showCreateOption() ? 1 : 0);\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n this.isOpen.set(true);\n if (total > 0) this.highlightedIndex.update((i) => (i + 1) % total);\n break;\n case 'ArrowUp':\n event.preventDefault();\n if (total > 0) this.highlightedIndex.update((i) => (i - 1 + total) % total);\n break;\n case 'Enter':\n event.preventDefault();\n if (this.highlightedIndex() >= 0) {\n if (this.highlightedIndex() === flat.length && this.showCreateOption()) {\n this.onCreateNew();\n } else {\n const opt = flat[this.highlightedIndex()];\n if (opt && !opt.disabled) {\n this.selectOption(opt);\n }\n }\n } else if (this.showCreateOption()) {\n this.onCreateNew();\n }\n break;\n case 'Escape':\n if (this.isOpen()) {\n this.isOpen.set(false);\n this.highlightedIndex.set(-1);\n // Escape consumed by the list — an enclosing modal must not close too.\n event.stopPropagation();\n }\n break;\n case 'Tab':\n if (this.highlightedIndex() >= 0 && this.isOpen()) {\n const opt = flat[this.highlightedIndex()];\n if (opt && !opt.disabled) {\n this.selectOption(opt);\n }\n }\n this.isOpen.set(false);\n break;\n case 'Backspace':\n if (this.multiple() && !this.query() && this.selectedMultiple().length > 0) {\n this.removeSelected(this.selectedMultiple()[this.selectedMultiple().length - 1]);\n }\n break;\n }\n }\n\n protected selectOption(option: ComboboxOption): void {\n if (this.multiple()) {\n this.selectedMultiple.update((sel) => [...sel, option]);\n this.query.set('');\n const value = this.selectedMultiple();\n this.onChange(value);\n this.valueChange.emit(value);\n } else {\n this.selectedSingle.set(option);\n this.query.set(option.label);\n this.onChange(option);\n this.valueChange.emit(option);\n this.emitSelectedValue(option.value);\n }\n this.optionSelected.emit(option);\n this.isOpen.set(false);\n this.highlightedIndex.set(-1);\n }\n\n protected removeSelected(option: ComboboxOption): void {\n if (this.isDisabled()) return;\n this.selectedMultiple.update((sel) =>\n sel.filter((s) => s.value !== option.value)\n );\n const value = this.selectedMultiple();\n this.onChange(value);\n this.valueChange.emit(value);\n this.inputEl()?.nativeElement.focus();\n }\n\n protected onCreateNew(): void {\n const q = this.query().trim();\n if (!q) return;\n const newOption: ComboboxOption = { value: q, label: q };\n this.created.emit(q);\n this.selectOption(newOption);\n }\n\n @HostListener('document:click', ['$event'])\n protected onDocumentClick(event: MouseEvent): void {\n const target = event.target as Node | null;\n // The dropdown lives in the CDK overlay container, outside the host element.\n if (\n !this.elRef.nativeElement.contains(target) &&\n !this.dropdownEl()?.nativeElement.contains(target)\n ) {\n this.isOpen.set(false);\n }\n }\n}\n","<div [class]=\"containerClasses()\">\n @if (label()) {\n <label class=\"lc-combobox__label\" [for]=\"inputId\">{{ label() }}</label>\n }\n\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- pointer shortcut; the input is the keyboard target -->\n <div\n #inputWrapper\n class=\"lc-combobox__input-wrapper\"\n (mousedown)=\"onFrameMousedown($event)\"\n (click)=\"onFrameClick($event)\"\n >\n <!-- Selected chips (multiple mode) -->\n @if (multiple()) {\n @for (sel of selectedMultiple(); track sel.value) {\n <lc-chip\n [removable]=\"!isDisabled()\"\n size=\"sm\"\n (remove)=\"removeSelected(sel)\"\n >{{ sel.label }}</lc-chip>\n }\n }\n\n <input\n #inputEl\n type=\"text\"\n class=\"lc-combobox__input\"\n [id]=\"inputId\"\n [placeholder]=\"multiple() && selectedMultiple().length > 0 ? '' : placeholder()\"\n [value]=\"query()\"\n [disabled]=\"isDisabled()\"\n role=\"combobox\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-invalid]=\"error() ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n autocomplete=\"off\"\n (input)=\"onInputChange($event)\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n\n @if (isLoading() || loading()) {\n <lc-spinner size=\"sm\" class=\"lc-combobox__spinner\" />\n } @else if (!multiple() && selectedSingle()) {\n <button\n type=\"button\"\n class=\"lc-combobox__clear\"\n [disabled]=\"isDisabled()\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"onClearClick()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <lc-icon name=\"x-mark\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n\n <!-- Dropdown: rendered in the CDK overlay container so overflow-hidden\n ancestors cannot clip it. Focus stays in the input (mousedown is\n prevented on the panel), keyboard nav uses aria-activedescendant. -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"inputWrapper\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayMatchWidth]=\"true\"\n (detach)=\"isOpen.set(false)\"\n >\n <div\n #dropdownEl\n class=\"lc-combobox__dropdown\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\n (mousedown)=\"$event.preventDefault()\"\n >\n @for (group of groupedOptions(); track group.label) {\n @if (group.label) {\n <div class=\"lc-combobox__group-header\" role=\"presentation\">{{ group.label }}</div>\n }\n @for (option of group.items; track option.value) {\n @let idx = flatOptions().indexOf(option);\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays in the input, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-combobox__option\"\n [class.lc-combobox__option--highlighted]=\"idx === highlightedIndex()\"\n [class.lc-combobox__option--disabled]=\"option.disabled\"\n role=\"option\"\n [id]=\"optionId(idx)\"\n [attr.aria-selected]=\"idx === highlightedIndex()\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"!option.disabled && selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(idx)\"\n >\n @if (option.icon) {\n <lc-icon [name]=\"option.icon\" size=\"sm\" class=\"lc-combobox__option-icon\" [decorative]=\"true\" />\n }\n <div class=\"lc-combobox__option-content\">\n <span class=\"lc-combobox__option-label\">{{ option.label }}</span>\n @if (option.description) {\n <span class=\"lc-combobox__option-desc\">{{ option.description }}</span>\n }\n </div>\n </div>\n }\n }\n\n @if (showCreateOption()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays in the input, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-combobox__option lc-combobox__option--create\"\n [class.lc-combobox__option--highlighted]=\"highlightedIndex() === flatOptions().length\"\n role=\"option\"\n [id]=\"createOptionId\"\n [attr.aria-selected]=\"highlightedIndex() === flatOptions().length\"\n (click)=\"onCreateNew()\"\n (mouseenter)=\"highlightedIndex.set(flatOptions().length)\"\n >\n <lc-icon name=\"plus\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ createOptionLabel() }} \"{{ query() }}\"</span>\n </div>\n }\n\n @if (visibleOptions().length === 0 && !showCreateOption() && !isLoading() && !loading()) {\n <div class=\"lc-combobox__empty\">{{ emptyMessage() }}</div>\n }\n </div>\n </ng-template>\n\n @if (helperText() && !error()) {\n <span class=\"lc-combobox__helper\" [id]=\"inputId + '-helper'\">{{ helperText() }}</span>\n }\n @if (error()) {\n <span class=\"lc-combobox__error\" [id]=\"inputId + '-error'\" role=\"alert\">{{ error() }}</span>\n }\n</div>\n"],"mappings":"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"}
|
|
@@ -18,6 +18,7 @@ var DatepickerComponent = class DatepickerComponent {
|
|
|
18
18
|
helperText = input("", ...ngDevMode ? [{ debugName: "helperText" }] : /* istanbul ignore next */ []);
|
|
19
19
|
errorMessage = input("", ...ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []);
|
|
20
20
|
ariaLabel = input(void 0, ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
|
|
21
|
+
label = input("", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
|
|
21
22
|
format = input("YYYY-MM-DD", ...ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []);
|
|
22
23
|
minDate = input(void 0, ...ngDevMode ? [{ debugName: "minDate" }] : /* istanbul ignore next */ []);
|
|
23
24
|
maxDate = input(void 0, ...ngDevMode ? [{ debugName: "maxDate" }] : /* istanbul ignore next */ []);
|
|
@@ -168,6 +169,11 @@ var DatepickerComponent = class DatepickerComponent {
|
|
|
168
169
|
this.onChange(null);
|
|
169
170
|
this.dateChange.emit(null);
|
|
170
171
|
}
|
|
172
|
+
onClearClick(event) {
|
|
173
|
+
event.stopPropagation();
|
|
174
|
+
this.clear();
|
|
175
|
+
this.datepickerInput()?.nativeElement.focus();
|
|
176
|
+
}
|
|
171
177
|
isDateDisabled(date) {
|
|
172
178
|
const day = this.startOfDay(date);
|
|
173
179
|
const min = this.minDate();
|
|
@@ -186,13 +192,12 @@ var DatepickerComponent = class DatepickerComponent {
|
|
|
186
192
|
return this.isSameDate(date, today);
|
|
187
193
|
}
|
|
188
194
|
dayAriaLabel(date) {
|
|
189
|
-
const
|
|
190
|
-
const name = locale ? date.toLocaleDateString(locale, {
|
|
195
|
+
const name = date.toLocaleDateString(this.locale() || "en-US", {
|
|
191
196
|
weekday: "long",
|
|
192
197
|
day: "numeric",
|
|
193
198
|
month: "long",
|
|
194
199
|
year: "numeric"
|
|
195
|
-
})
|
|
200
|
+
});
|
|
196
201
|
return this.isSelectedDate(date) ? `${name}, ${this.selectedAriaLabel()}` : name;
|
|
197
202
|
}
|
|
198
203
|
isSelectedDate(date) {
|
|
@@ -402,7 +407,10 @@ var DatepickerComponent = class DatepickerComponent {
|
|
|
402
407
|
break;
|
|
403
408
|
case "Enter":
|
|
404
409
|
event.preventDefault();
|
|
405
|
-
if (this.selectedDate())
|
|
410
|
+
if (this.selectedDate()) {
|
|
411
|
+
this.inputValue.set(this.formattedDate());
|
|
412
|
+
this.close();
|
|
413
|
+
}
|
|
406
414
|
}
|
|
407
415
|
}
|
|
408
416
|
isMonthDisabled(year, month) {
|
|
@@ -584,6 +592,13 @@ var DatepickerComponent = class DatepickerComponent {
|
|
|
584
592
|
isRequired: false,
|
|
585
593
|
transformFunction: null
|
|
586
594
|
},
|
|
595
|
+
label: {
|
|
596
|
+
classPropertyName: "label",
|
|
597
|
+
publicName: "label",
|
|
598
|
+
isSignal: true,
|
|
599
|
+
isRequired: false,
|
|
600
|
+
transformFunction: null
|
|
601
|
+
},
|
|
587
602
|
format: {
|
|
588
603
|
classPropertyName: "format",
|
|
589
604
|
publicName: "format",
|
|
@@ -735,8 +750,8 @@ var DatepickerComponent = class DatepickerComponent {
|
|
|
735
750
|
isSignal: true
|
|
736
751
|
}],
|
|
737
752
|
ngImport: i0,
|
|
738
|
-
template: "<div class=\"lc-datepicker-wrapper\">\n <div class=\"lc-datepicker-input-wrapper\">\n <input\n #datepickerInput\n type=\"text\"\n [id]=\"inputId\"\n [class]=\"datepickerClasses()\"\n role=\"combobox\"\n aria-haspopup=\"dialog\"\n autocomplete=\"off\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? inputId + '-calendar' : null\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [readonly]=\"readonly()\"\n [disabled]=\"isDisabled()\"\n [placeholder]=\"placeholder()\"\n [value]=\"inputValue()\"\n (input)=\"onInputChange(getInputValue($event))\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n />\n <div class=\"lc-datepicker-icons\">\n @if (selectedDate() && !isDisabled() && !readonly()) {\n <button\n type=\"button\"\n class=\"lc-datepicker-clear\"\n (click)=\"
|
|
739
|
-
styles: [".lc-datepicker-wrapper{display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%;position:relative}.lc-datepicker-input-wrapper{position:relative;width:100%}.lc-datepicker{width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background-color:var(--color-surface);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease);cursor:text}.lc-datepicker::placeholder{color:var(--color-text-secondary)}.lc-datepicker:hover:not(:disabled):not([readonly]):not(.lc-datepicker--error):not(:focus){border-color:var(--color-text-secondary)}.lc-datepicker:focus{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.lc-datepicker:disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.lc-datepicker[readonly]{background-color:var(--color-surface-muted);cursor:default}.lc-datepicker.lc-datepicker--error{border-color:var(--color-error-600)}.lc-datepicker.lc-datepicker--error:focus{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.lc-datepicker.lc-datepicker--xs{height:var(--size-interactive-xs-height);padding:var(--size-interactive-xs-padding);padding-right:var(--spacing-10);font-size:var(--size-interactive-xs-font-size)}.lc-datepicker.lc-datepicker--sm{height:var(--size-interactive-sm-height);padding:var(--size-interactive-sm-padding);padding-right:var(--spacing-12);font-size:var(--size-interactive-sm-font-size)}.lc-datepicker.lc-datepicker--md{height:var(--size-interactive-md-height);padding:var(--size-interactive-md-padding);padding-right:var(--spacing-14);font-size:var(--size-interactive-md-font-size)}.lc-datepicker.lc-datepicker--lg{height:var(--size-interactive-lg-height);padding:var(--size-interactive-lg-padding);padding-right:var(--spacing-16);font-size:var(--size-interactive-lg-font-size)}.lc-datepicker.lc-datepicker--filled{background-color:var(--color-surface-sunken);border-color:var(--color-field-border)}.lc-datepicker.lc-datepicker--filled:hover:not(:disabled):not([readonly]):not(.lc-datepicker--error):not(:focus){background-color:var(--color-surface-hover);border-color:var(--color-text-secondary)}.lc-datepicker.lc-datepicker--filled:focus{background-color:var(--color-surface);border-color:var(--color-primary-500)}.lc-datepicker.lc-datepicker--filled:disabled{background-color:var(--color-surface-muted);border-color:var(--color-border)}.lc-datepicker.lc-datepicker--filled.lc-datepicker--error{border-color:var(--color-error-600)}.lc-datepicker-icons{position:absolute;right:var(--spacing-3);top:50%;transform:translateY(-50%);display:flex;align-items:center;gap:var(--spacing-1);pointer-events:none}.lc-datepicker-calendar-icon{width:1.25rem;height:1.25rem;color:var(--color-text-secondary)}.lc-datepicker-clear{pointer-events:auto;display:flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;padding:0;background:none;border:none;border-radius:var(--border-radius-sm);color:var(--color-text-secondary);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-clear:hover{color:var(--color-text-primary);background-color:var(--color-surface-hover)}.lc-datepicker-clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:1px}.lc-datepicker-clear svg{width:1rem;height:1rem}.lc-datepicker-calendar{position:absolute;z-index:1000;margin-top:var(--spacing-1);padding:var(--lc-density-padding-md, var(--spacing-4));background-color:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--border-radius-lg);box-shadow:var(--elevation-3);min-width:280px;opacity:0;transform:translateY(-8px);transition:all var(--animation-duration-base) var(--animation-timing-ease);pointer-events:none}.lc-datepicker-calendar.lc-datepicker-calendar--open{opacity:1;transform:translateY(0);pointer-events:auto}.lc-datepicker-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--spacing-4)}.lc-datepicker-month-year{font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}.lc-datepicker-nav-button{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;background:none;border:none;border-radius:var(--border-radius-md);color:var(--color-text-secondary);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-nav-button:hover{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-datepicker-nav-button:active{background-color:var(--color-surface-sunken)}.lc-datepicker-nav-button:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:1px}.lc-datepicker-nav-button svg{width:1.25rem;height:1.25rem}.lc-datepicker-quick-actions{display:flex;justify-content:center;margin-bottom:var(--spacing-3)}.lc-datepicker-today-button{padding:var(--spacing-1) var(--spacing-3);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-primary-600);background:none;border:1px solid var(--color-primary-200);border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-today-button:hover{background-color:var(--color-primary-50);border-color:var(--color-primary-300)}.lc-datepicker-today-button:active{background-color:var(--color-primary-100)}.lc-datepicker-today-button:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:1px}.lc-datepicker-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--spacing-1);margin-bottom:var(--spacing-2)}.lc-datepicker-weekday{font-size:var(--font-size-xs);font-weight:var(--font-weight-semibold);color:var(--color-text-secondary);text-align:center;padding:var(--spacing-1)}.lc-datepicker-days{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--spacing-1)}.lc-datepicker-day{display:flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;padding:0;font-size:var(--font-size-sm);font-weight:var(--font-weight-regular);color:var(--color-text-primary);background:none;border:none;border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-day:hover:not(:disabled){background-color:var(--color-surface-hover)}.lc-datepicker-day.lc-datepicker-day--other-month{color:var(--color-text-tertiary)}.lc-datepicker-day.lc-datepicker-day--today{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-datepicker-day.lc-datepicker-day--selected{font-weight:var(--font-weight-semibold);color:var(--color-on-primary);background-color:var(--color-primary-fill)}.lc-datepicker-day.lc-datepicker-day--selected:hover{background-color:var(--color-primary-fill-hover)}.lc-datepicker-day.lc-datepicker-day--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-datepicker-day.lc-datepicker-day--disabled:hover{background:none}.lc-datepicker-day:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.lc-datepicker-calendar--month .lc-datepicker-nav-button{width:2.75rem;height:2.75rem}.lc-datepicker-calendar--month .lc-datepicker-today-button{min-height:2.75rem}.lc-datepicker-months{display:flex;flex-direction:column;gap:var(--spacing-2);inline-size:17.25rem;max-inline-size:calc(100vw - 4.125rem)}.lc-datepicker-month-row{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--spacing-2)}.lc-datepicker-month{display:flex;align-items:center;justify-content:center;min-height:2.75rem;padding:0 var(--spacing-1);font-size:var(--font-size-sm);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);text-align:center;overflow-wrap:anywhere;hyphens:auto;color:var(--color-text-primary);border-radius:var(--border-radius-md);cursor:pointer}.lc-datepicker-month:hover:not(.lc-datepicker-month--disabled):not(.lc-datepicker-month--selected){background-color:var(--color-surface-hover)}.lc-datepicker-month.lc-datepicker-month--current{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-datepicker-month.lc-datepicker-month--selected{font-weight:var(--font-weight-semibold);color:var(--color-on-primary);background-color:var(--color-primary-fill);box-shadow:inset 0 0 0 2px var(--color-primary-500)}.lc-datepicker-month.lc-datepicker-month--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-datepicker-month:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}@media(forced-colors:active){.lc-datepicker-month:focus-visible{outline-color:Highlight}.lc-datepicker-month.lc-datepicker-month--selected{forced-color-adjust:none;background-color:Highlight;color:HighlightText}.lc-datepicker-month.lc-datepicker-month--current{text-decoration:underline}.lc-datepicker-month.lc-datepicker-month--disabled{color:GrayText}}.lc-datepicker__error{font-size:var(--font-size-xs);color:var(--color-error-600);margin-top:var(--spacing-1)}.lc-datepicker__helper{font-size:var(--font-size-xs);color:var(--color-text-secondary);margin-top:var(--spacing-1)}\n"],
|
|
753
|
+
template: "<div class=\"lc-datepicker-wrapper\">\n @if (label()) {\n <label class=\"lc-datepicker__label\" [for]=\"inputId\">{{ label() }}</label>\n }\n <div class=\"lc-datepicker-input-wrapper\">\n <input\n #datepickerInput\n type=\"text\"\n [id]=\"inputId\"\n [class]=\"datepickerClasses()\"\n role=\"combobox\"\n aria-haspopup=\"dialog\"\n autocomplete=\"off\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? inputId + '-calendar' : null\"\n [attr.aria-label]=\"label() ? null : (ariaLabel() || null)\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [readonly]=\"readonly()\"\n [disabled]=\"isDisabled()\"\n [placeholder]=\"placeholder()\"\n [value]=\"inputValue()\"\n (input)=\"onInputChange(getInputValue($event))\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n />\n <div class=\"lc-datepicker-icons\">\n @if (selectedDate() && !isDisabled() && !readonly()) {\n <button\n type=\"button\"\n class=\"lc-datepicker-clear\"\n (click)=\"onClearClick($event)\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\"\n />\n </svg>\n </button>\n }\n <svg\n class=\"lc-datepicker-calendar-icon\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M5.25 12a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H6a.75.75 0 01-.75-.75V12zM6 13.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V14a.75.75 0 00-.75-.75H6zM7.25 12a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H8a.75.75 0 01-.75-.75V12zM8 13.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V14a.75.75 0 00-.75-.75H8zM9.25 10a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H10a.75.75 0 01-.75-.75V10zM10 11.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V12a.75.75 0 00-.75-.75H10zM9.25 14a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H10a.75.75 0 01-.75-.75V14zM12 9.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V10a.75.75 0 00-.75-.75H12zM11.25 12a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H12a.75.75 0 01-.75-.75V12zM12 13.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V14a.75.75 0 00-.75-.75H12zM13.25 10a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H14a.75.75 0 01-.75-.75V10zM14 11.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V12a.75.75 0 00-.75-.75H14z\"\n />\n <path\n fill-rule=\"evenodd\"\n d=\"M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </div>\n\n <!-- Calendar Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"datepickerInput\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayViewportMargin]=\"8\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n (backdropClick)=\"onClickOutside()\"\n (detach)=\"close()\"\n >\n <div\n #calendarPanel\n class=\"lc-datepicker-calendar\"\n [class.lc-datepicker-calendar--open]=\"isOpen()\"\n [class.lc-datepicker-calendar--month]=\"isMonthMode()\"\n [id]=\"inputId + '-calendar'\"\n role=\"dialog\"\n [attr.aria-label]=\"isMonthMode() ? monthDialogAriaLabel() : dialogAriaLabel()\"\n >\n <!-- Calendar Header (month mode, 3.29: the year and year buttons) -->\n <div class=\"lc-datepicker-header\">\n <button\n type=\"button\"\n class=\"lc-datepicker-nav-button\"\n (click)=\"isMonthMode() ? previousYear() : previousMonth()\"\n [attr.aria-label]=\"isMonthMode() ? previousYearAriaLabel() : previousMonthAriaLabel()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n fill-rule=\"evenodd\"\n d=\"M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </button>\n \n <div class=\"lc-datepicker-month-year\" aria-live=\"polite\" [attr.id]=\"isMonthMode() ? inputId + '-year' : null\">\n {{ headerTitle() }}\n </div>\n\n <button\n type=\"button\"\n class=\"lc-datepicker-nav-button\"\n (click)=\"isMonthMode() ? nextYear() : nextMonth()\"\n [attr.aria-label]=\"isMonthMode() ? nextYearAriaLabel() : nextMonthAriaLabel()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </button>\n </div>\n\n <!-- Quick Actions -->\n <div class=\"lc-datepicker-quick-actions\">\n <button\n type=\"button\"\n class=\"lc-datepicker-today-button\"\n (click)=\"isMonthMode() ? showCurrentYear() : goToToday()\"\n >\n {{ isMonthMode() ? currentMonthLabel() : todayLabel() }}\n </button>\n </div>\n\n @if (isMonthMode()) {\n <!-- Month grid (3.29): APG grid, one roving tab stop, named by the year title -->\n <div class=\"lc-datepicker-months\" role=\"grid\" [attr.aria-labelledby]=\"inputId + '-year'\">\n @for (row of monthRows(); track $index) {\n <div class=\"lc-datepicker-month-row\" role=\"row\">\n @for (cell of row; track cell.month) {\n <div\n role=\"gridcell\"\n class=\"lc-datepicker-month\"\n [class.lc-datepicker-month--current]=\"cell.current\"\n [class.lc-datepicker-month--selected]=\"cell.selected\"\n [class.lc-datepicker-month--disabled]=\"cell.disabled\"\n [attr.tabindex]=\"cell.month === monthTabStop() ? 0 : -1\"\n [attr.aria-selected]=\"cell.selected ? 'true' : null\"\n [attr.aria-current]=\"cell.current ? 'date' : null\"\n [attr.aria-disabled]=\"cell.disabled ? 'true' : null\"\n [attr.aria-label]=\"cell.label\"\n (click)=\"selectMonth(cell.month)\"\n (keydown)=\"onMonthKeydown($event, cell.month)\"\n >{{ cell.name }}</div>\n }\n </div>\n }\n </div>\n } @else {\n <!-- Weekday Headers -->\n <div class=\"lc-datepicker-weekdays\" aria-hidden=\"true\">\n @for (day of weekdayLabels(); track $index) {\n <div class=\"lc-datepicker-weekday\">{{ day }}</div>\n }\n </div>\n\n <!-- Calendar Days -->\n <div class=\"lc-datepicker-days\">\n @for (date of generateCalendarDays(); track date.getTime()) {\n <button\n type=\"button\"\n class=\"lc-datepicker-day\"\n [class.lc-datepicker-day--other-month]=\"!isCurrentMonth(date)\"\n [class.lc-datepicker-day--today]=\"isToday(date)\"\n [class.lc-datepicker-day--selected]=\"isSelectedDate(date)\"\n [class.lc-datepicker-day--disabled]=\"isDateDisabled(date)\"\n [disabled]=\"isDateDisabled(date)\"\n [attr.aria-current]=\"isToday(date) ? 'date' : null\"\n [attr.aria-label]=\"dayAriaLabel(date)\"\n (click)=\"selectDate(date)\"\n >\n {{ date.getDate() }}\n </button>\n }\n </div>\n }\n </div>\n </ng-template>\n\n <!-- Helper/Error Text -->\n @if (error() && errorMessage()) {\n <div class=\"lc-datepicker__error\" [id]=\"inputId + '-error'\" role=\"alert\">\n {{ errorMessage() }}\n </div>\n } @else if (helperText()) {\n <div class=\"lc-datepicker__helper\" [id]=\"inputId + '-helper'\">\n {{ helperText() }}\n </div>\n }\n</div>\n",
|
|
754
|
+
styles: [".lc-datepicker-wrapper{display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%;position:relative}.lc-datepicker__label{display:block;margin-bottom:.125rem;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:var(--line-height-normal);color:var(--color-text-primary);overflow-wrap:break-word;hyphens:auto;hyphenate-limit-chars:12 4 3}.lc-datepicker-input-wrapper{position:relative;width:100%}.lc-datepicker{width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background-color:var(--color-surface);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease);cursor:text}.lc-datepicker::placeholder{color:var(--color-text-secondary)}.lc-datepicker:hover:not(:disabled):not([readonly]):not(.lc-datepicker--error):not(:focus){border-color:var(--color-text-secondary)}.lc-datepicker:focus{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.lc-datepicker:disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.lc-datepicker[readonly]{background-color:var(--color-surface-muted);cursor:default}.lc-datepicker.lc-datepicker--error{border-color:var(--color-error-600)}.lc-datepicker.lc-datepicker--error:focus{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.lc-datepicker.lc-datepicker--xs{height:var(--size-interactive-xs-height);padding:var(--size-interactive-xs-padding);padding-right:var(--spacing-10);font-size:var(--size-interactive-xs-font-size)}.lc-datepicker.lc-datepicker--sm{height:var(--size-interactive-sm-height);padding:var(--size-interactive-sm-padding);padding-right:var(--spacing-12);font-size:var(--size-interactive-sm-font-size)}.lc-datepicker.lc-datepicker--md{height:var(--size-interactive-md-height);padding:var(--size-interactive-md-padding);padding-right:var(--spacing-14);font-size:var(--size-interactive-md-font-size)}.lc-datepicker.lc-datepicker--lg{height:var(--size-interactive-lg-height);padding:var(--size-interactive-lg-padding);padding-right:var(--spacing-16);font-size:var(--size-interactive-lg-font-size)}.lc-datepicker.lc-datepicker--filled{background-color:var(--color-surface-sunken);border-color:var(--color-field-border)}.lc-datepicker.lc-datepicker--filled:hover:not(:disabled):not([readonly]):not(.lc-datepicker--error):not(:focus){background-color:var(--color-surface-hover);border-color:var(--color-text-secondary)}.lc-datepicker.lc-datepicker--filled:focus{background-color:var(--color-surface);border-color:var(--color-primary-500)}.lc-datepicker.lc-datepicker--filled:disabled{background-color:var(--color-surface-muted);border-color:var(--color-border)}.lc-datepicker.lc-datepicker--filled.lc-datepicker--error{border-color:var(--color-error-600)}.lc-datepicker-icons{position:absolute;right:var(--spacing-3);top:50%;transform:translateY(-50%);display:flex;align-items:center;gap:var(--spacing-1);pointer-events:none}.lc-datepicker-calendar-icon{width:1.25rem;height:1.25rem;color:var(--color-text-secondary)}.lc-datepicker-clear{position:relative;pointer-events:auto;display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin:-.125rem;padding:.125rem;background:none;background-clip:content-box;border:none;border-radius:calc(var(--border-radius-sm) + .125rem);color:var(--color-text-secondary);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-clear:hover{color:var(--color-text-primary);background-color:var(--color-surface-hover)}.lc-datepicker-clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:-1px}.lc-datepicker-clear svg{width:1rem;height:1rem}.lc-datepicker--md~.lc-datepicker-icons .lc-datepicker-clear:before,.lc-datepicker--lg~.lc-datepicker-icons .lc-datepicker-clear:before{content:\"\";position:absolute;inset:-.625rem -.125rem -.625rem -1.125rem}.lc-datepicker-calendar{position:relative;z-index:1000;margin-top:var(--spacing-1);padding:var(--lc-density-padding-md, var(--spacing-4));background-color:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--border-radius-lg);box-shadow:var(--elevation-3);min-width:280px;opacity:0;transform:translateY(-8px);transition:all var(--animation-duration-base) var(--animation-timing-ease);pointer-events:none}.lc-datepicker-calendar.lc-datepicker-calendar--open{opacity:1;transform:translateY(0);pointer-events:auto}.lc-datepicker-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--spacing-4)}.lc-datepicker-month-year{font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}.lc-datepicker-nav-button{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;background:none;border:none;border-radius:var(--border-radius-md);color:var(--color-text-secondary);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-nav-button:hover{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-datepicker-nav-button:active{background-color:var(--color-surface-sunken)}.lc-datepicker-nav-button:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:1px}.lc-datepicker-nav-button svg{width:1.25rem;height:1.25rem}.lc-datepicker-quick-actions{display:flex;justify-content:center;margin-bottom:var(--spacing-3)}.lc-datepicker-today-button{padding:var(--spacing-1) var(--spacing-3);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-primary-600);background:none;border:1px solid var(--color-primary-200);border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-today-button:hover{background-color:var(--color-primary-50);border-color:var(--color-primary-300)}.lc-datepicker-today-button:active{background-color:var(--color-primary-100)}.lc-datepicker-today-button:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:1px}.lc-datepicker-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--spacing-1);margin-bottom:var(--spacing-2)}.lc-datepicker-weekday{font-size:var(--font-size-xs);font-weight:var(--font-weight-semibold);color:var(--color-text-secondary);text-align:center;padding:var(--spacing-1)}.lc-datepicker-days{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--spacing-1)}.lc-datepicker-day{display:flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;padding:0;font-size:var(--font-size-sm);font-weight:var(--font-weight-regular);color:var(--color-text-primary);background:none;border:none;border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-day:hover:not(:disabled){background-color:var(--color-surface-hover)}.lc-datepicker-day.lc-datepicker-day--other-month{color:var(--color-text-tertiary)}.lc-datepicker-day.lc-datepicker-day--today{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-datepicker-day.lc-datepicker-day--selected{font-weight:var(--font-weight-semibold);color:var(--color-on-primary);background-color:var(--color-primary-fill);box-shadow:inset 0 0 0 2px var(--color-primary-500)}.lc-datepicker-day.lc-datepicker-day--selected:hover{background-color:var(--color-primary-fill-hover)}.lc-datepicker-day.lc-datepicker-day--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-datepicker-day.lc-datepicker-day--disabled:hover{background:none}.lc-datepicker-day:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}@media(max-width:1023.98px){.lc-datepicker-nav-button{width:2.75rem;height:2.75rem}.lc-datepicker-today-button{min-height:2.75rem}.lc-datepicker-weekdays,.lc-datepicker-days{gap:0;grid-template-columns:repeat(7,minmax(0,1fr));inline-size:19.25rem;max-inline-size:calc(100vw - 3.125rem)}.lc-datepicker-day{width:100%;height:auto;aspect-ratio:1}}.lc-datepicker-calendar--month .lc-datepicker-nav-button{width:2.75rem;height:2.75rem}.lc-datepicker-calendar--month .lc-datepicker-today-button{min-height:2.75rem}.lc-datepicker-months{display:flex;flex-direction:column;gap:var(--spacing-2);inline-size:17.25rem;max-inline-size:calc(100vw - 4.125rem)}.lc-datepicker-month-row{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--spacing-2)}.lc-datepicker-month{display:flex;align-items:center;justify-content:center;min-height:2.75rem;padding:0 var(--spacing-1);font-size:var(--font-size-sm);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);text-align:center;overflow-wrap:anywhere;hyphens:auto;color:var(--color-text-primary);border-radius:var(--border-radius-md);cursor:pointer}.lc-datepicker-month:hover:not(.lc-datepicker-month--disabled):not(.lc-datepicker-month--selected){background-color:var(--color-surface-hover)}.lc-datepicker-month.lc-datepicker-month--current{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-datepicker-month.lc-datepicker-month--selected{font-weight:var(--font-weight-semibold);color:var(--color-on-primary);background-color:var(--color-primary-fill);box-shadow:inset 0 0 0 2px var(--color-primary-500)}.lc-datepicker-month.lc-datepicker-month--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-datepicker-month:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}@media(forced-colors:active){.lc-datepicker-month:focus-visible{outline-color:Highlight}.lc-datepicker-month.lc-datepicker-month--selected{forced-color-adjust:none;background-color:Highlight;color:HighlightText}.lc-datepicker-month.lc-datepicker-month--current{text-decoration:underline}.lc-datepicker-month.lc-datepicker-month--disabled{color:GrayText}.lc-datepicker-clear:focus-visible,.lc-datepicker-day:focus-visible{outline-color:Highlight}.lc-datepicker-day.lc-datepicker-day--selected,.lc-datepicker-day.lc-datepicker-day--selected:hover{forced-color-adjust:none;background-color:Highlight;color:HighlightText}.lc-datepicker-day.lc-datepicker-day--today{text-decoration:underline}.lc-datepicker-day.lc-datepicker-day--disabled{color:GrayText}}.lc-datepicker__error{font-size:var(--font-size-xs);color:var(--color-error-600);margin-top:var(--spacing-1)}.lc-datepicker__helper{font-size:var(--font-size-xs);color:var(--color-text-secondary);margin-top:var(--spacing-1)}\n"],
|
|
740
755
|
dependencies: [{
|
|
741
756
|
kind: "ngmodule",
|
|
742
757
|
type: OverlayModule
|
|
@@ -801,8 +816,8 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
801
816
|
useExisting: forwardRef(() => DatepickerComponent),
|
|
802
817
|
multi: true
|
|
803
818
|
}],
|
|
804
|
-
template: "<div class=\"lc-datepicker-wrapper\">\n <div class=\"lc-datepicker-input-wrapper\">\n <input\n #datepickerInput\n type=\"text\"\n [id]=\"inputId\"\n [class]=\"datepickerClasses()\"\n role=\"combobox\"\n aria-haspopup=\"dialog\"\n autocomplete=\"off\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? inputId + '-calendar' : null\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [readonly]=\"readonly()\"\n [disabled]=\"isDisabled()\"\n [placeholder]=\"placeholder()\"\n [value]=\"inputValue()\"\n (input)=\"onInputChange(getInputValue($event))\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n />\n <div class=\"lc-datepicker-icons\">\n @if (selectedDate() && !isDisabled() && !readonly()) {\n <button\n type=\"button\"\n class=\"lc-datepicker-clear\"\n (click)=\"
|
|
805
|
-
styles: [".lc-datepicker-wrapper{display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%;position:relative}.lc-datepicker-input-wrapper{position:relative;width:100%}.lc-datepicker{width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background-color:var(--color-surface);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease);cursor:text}.lc-datepicker::placeholder{color:var(--color-text-secondary)}.lc-datepicker:hover:not(:disabled):not([readonly]):not(.lc-datepicker--error):not(:focus){border-color:var(--color-text-secondary)}.lc-datepicker:focus{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.lc-datepicker:disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.lc-datepicker[readonly]{background-color:var(--color-surface-muted);cursor:default}.lc-datepicker.lc-datepicker--error{border-color:var(--color-error-600)}.lc-datepicker.lc-datepicker--error:focus{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.lc-datepicker.lc-datepicker--xs{height:var(--size-interactive-xs-height);padding:var(--size-interactive-xs-padding);padding-right:var(--spacing-10);font-size:var(--size-interactive-xs-font-size)}.lc-datepicker.lc-datepicker--sm{height:var(--size-interactive-sm-height);padding:var(--size-interactive-sm-padding);padding-right:var(--spacing-12);font-size:var(--size-interactive-sm-font-size)}.lc-datepicker.lc-datepicker--md{height:var(--size-interactive-md-height);padding:var(--size-interactive-md-padding);padding-right:var(--spacing-14);font-size:var(--size-interactive-md-font-size)}.lc-datepicker.lc-datepicker--lg{height:var(--size-interactive-lg-height);padding:var(--size-interactive-lg-padding);padding-right:var(--spacing-16);font-size:var(--size-interactive-lg-font-size)}.lc-datepicker.lc-datepicker--filled{background-color:var(--color-surface-sunken);border-color:var(--color-field-border)}.lc-datepicker.lc-datepicker--filled:hover:not(:disabled):not([readonly]):not(.lc-datepicker--error):not(:focus){background-color:var(--color-surface-hover);border-color:var(--color-text-secondary)}.lc-datepicker.lc-datepicker--filled:focus{background-color:var(--color-surface);border-color:var(--color-primary-500)}.lc-datepicker.lc-datepicker--filled:disabled{background-color:var(--color-surface-muted);border-color:var(--color-border)}.lc-datepicker.lc-datepicker--filled.lc-datepicker--error{border-color:var(--color-error-600)}.lc-datepicker-icons{position:absolute;right:var(--spacing-3);top:50%;transform:translateY(-50%);display:flex;align-items:center;gap:var(--spacing-1);pointer-events:none}.lc-datepicker-calendar-icon{width:1.25rem;height:1.25rem;color:var(--color-text-secondary)}.lc-datepicker-clear{pointer-events:auto;display:flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;padding:0;background:none;border:none;border-radius:var(--border-radius-sm);color:var(--color-text-secondary);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-clear:hover{color:var(--color-text-primary);background-color:var(--color-surface-hover)}.lc-datepicker-clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:1px}.lc-datepicker-clear svg{width:1rem;height:1rem}.lc-datepicker-calendar{position:absolute;z-index:1000;margin-top:var(--spacing-1);padding:var(--lc-density-padding-md, var(--spacing-4));background-color:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--border-radius-lg);box-shadow:var(--elevation-3);min-width:280px;opacity:0;transform:translateY(-8px);transition:all var(--animation-duration-base) var(--animation-timing-ease);pointer-events:none}.lc-datepicker-calendar.lc-datepicker-calendar--open{opacity:1;transform:translateY(0);pointer-events:auto}.lc-datepicker-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--spacing-4)}.lc-datepicker-month-year{font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}.lc-datepicker-nav-button{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;background:none;border:none;border-radius:var(--border-radius-md);color:var(--color-text-secondary);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-nav-button:hover{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-datepicker-nav-button:active{background-color:var(--color-surface-sunken)}.lc-datepicker-nav-button:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:1px}.lc-datepicker-nav-button svg{width:1.25rem;height:1.25rem}.lc-datepicker-quick-actions{display:flex;justify-content:center;margin-bottom:var(--spacing-3)}.lc-datepicker-today-button{padding:var(--spacing-1) var(--spacing-3);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-primary-600);background:none;border:1px solid var(--color-primary-200);border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-today-button:hover{background-color:var(--color-primary-50);border-color:var(--color-primary-300)}.lc-datepicker-today-button:active{background-color:var(--color-primary-100)}.lc-datepicker-today-button:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:1px}.lc-datepicker-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--spacing-1);margin-bottom:var(--spacing-2)}.lc-datepicker-weekday{font-size:var(--font-size-xs);font-weight:var(--font-weight-semibold);color:var(--color-text-secondary);text-align:center;padding:var(--spacing-1)}.lc-datepicker-days{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--spacing-1)}.lc-datepicker-day{display:flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;padding:0;font-size:var(--font-size-sm);font-weight:var(--font-weight-regular);color:var(--color-text-primary);background:none;border:none;border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-day:hover:not(:disabled){background-color:var(--color-surface-hover)}.lc-datepicker-day.lc-datepicker-day--other-month{color:var(--color-text-tertiary)}.lc-datepicker-day.lc-datepicker-day--today{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-datepicker-day.lc-datepicker-day--selected{font-weight:var(--font-weight-semibold);color:var(--color-on-primary);background-color:var(--color-primary-fill)}.lc-datepicker-day.lc-datepicker-day--selected:hover{background-color:var(--color-primary-fill-hover)}.lc-datepicker-day.lc-datepicker-day--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-datepicker-day.lc-datepicker-day--disabled:hover{background:none}.lc-datepicker-day:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.lc-datepicker-calendar--month .lc-datepicker-nav-button{width:2.75rem;height:2.75rem}.lc-datepicker-calendar--month .lc-datepicker-today-button{min-height:2.75rem}.lc-datepicker-months{display:flex;flex-direction:column;gap:var(--spacing-2);inline-size:17.25rem;max-inline-size:calc(100vw - 4.125rem)}.lc-datepicker-month-row{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--spacing-2)}.lc-datepicker-month{display:flex;align-items:center;justify-content:center;min-height:2.75rem;padding:0 var(--spacing-1);font-size:var(--font-size-sm);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);text-align:center;overflow-wrap:anywhere;hyphens:auto;color:var(--color-text-primary);border-radius:var(--border-radius-md);cursor:pointer}.lc-datepicker-month:hover:not(.lc-datepicker-month--disabled):not(.lc-datepicker-month--selected){background-color:var(--color-surface-hover)}.lc-datepicker-month.lc-datepicker-month--current{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-datepicker-month.lc-datepicker-month--selected{font-weight:var(--font-weight-semibold);color:var(--color-on-primary);background-color:var(--color-primary-fill);box-shadow:inset 0 0 0 2px var(--color-primary-500)}.lc-datepicker-month.lc-datepicker-month--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-datepicker-month:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}@media(forced-colors:active){.lc-datepicker-month:focus-visible{outline-color:Highlight}.lc-datepicker-month.lc-datepicker-month--selected{forced-color-adjust:none;background-color:Highlight;color:HighlightText}.lc-datepicker-month.lc-datepicker-month--current{text-decoration:underline}.lc-datepicker-month.lc-datepicker-month--disabled{color:GrayText}}.lc-datepicker__error{font-size:var(--font-size-xs);color:var(--color-error-600);margin-top:var(--spacing-1)}.lc-datepicker__helper{font-size:var(--font-size-xs);color:var(--color-text-secondary);margin-top:var(--spacing-1)}\n"]
|
|
819
|
+
template: "<div class=\"lc-datepicker-wrapper\">\n @if (label()) {\n <label class=\"lc-datepicker__label\" [for]=\"inputId\">{{ label() }}</label>\n }\n <div class=\"lc-datepicker-input-wrapper\">\n <input\n #datepickerInput\n type=\"text\"\n [id]=\"inputId\"\n [class]=\"datepickerClasses()\"\n role=\"combobox\"\n aria-haspopup=\"dialog\"\n autocomplete=\"off\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? inputId + '-calendar' : null\"\n [attr.aria-label]=\"label() ? null : (ariaLabel() || null)\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [readonly]=\"readonly()\"\n [disabled]=\"isDisabled()\"\n [placeholder]=\"placeholder()\"\n [value]=\"inputValue()\"\n (input)=\"onInputChange(getInputValue($event))\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n />\n <div class=\"lc-datepicker-icons\">\n @if (selectedDate() && !isDisabled() && !readonly()) {\n <button\n type=\"button\"\n class=\"lc-datepicker-clear\"\n (click)=\"onClearClick($event)\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\"\n />\n </svg>\n </button>\n }\n <svg\n class=\"lc-datepicker-calendar-icon\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M5.25 12a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H6a.75.75 0 01-.75-.75V12zM6 13.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V14a.75.75 0 00-.75-.75H6zM7.25 12a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H8a.75.75 0 01-.75-.75V12zM8 13.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V14a.75.75 0 00-.75-.75H8zM9.25 10a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H10a.75.75 0 01-.75-.75V10zM10 11.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V12a.75.75 0 00-.75-.75H10zM9.25 14a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H10a.75.75 0 01-.75-.75V14zM12 9.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V10a.75.75 0 00-.75-.75H12zM11.25 12a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H12a.75.75 0 01-.75-.75V12zM12 13.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V14a.75.75 0 00-.75-.75H12zM13.25 10a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H14a.75.75 0 01-.75-.75V10zM14 11.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V12a.75.75 0 00-.75-.75H14z\"\n />\n <path\n fill-rule=\"evenodd\"\n d=\"M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </div>\n\n <!-- Calendar Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"datepickerInput\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayViewportMargin]=\"8\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n (backdropClick)=\"onClickOutside()\"\n (detach)=\"close()\"\n >\n <div\n #calendarPanel\n class=\"lc-datepicker-calendar\"\n [class.lc-datepicker-calendar--open]=\"isOpen()\"\n [class.lc-datepicker-calendar--month]=\"isMonthMode()\"\n [id]=\"inputId + '-calendar'\"\n role=\"dialog\"\n [attr.aria-label]=\"isMonthMode() ? monthDialogAriaLabel() : dialogAriaLabel()\"\n >\n <!-- Calendar Header (month mode, 3.29: the year and year buttons) -->\n <div class=\"lc-datepicker-header\">\n <button\n type=\"button\"\n class=\"lc-datepicker-nav-button\"\n (click)=\"isMonthMode() ? previousYear() : previousMonth()\"\n [attr.aria-label]=\"isMonthMode() ? previousYearAriaLabel() : previousMonthAriaLabel()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n fill-rule=\"evenodd\"\n d=\"M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </button>\n \n <div class=\"lc-datepicker-month-year\" aria-live=\"polite\" [attr.id]=\"isMonthMode() ? inputId + '-year' : null\">\n {{ headerTitle() }}\n </div>\n\n <button\n type=\"button\"\n class=\"lc-datepicker-nav-button\"\n (click)=\"isMonthMode() ? nextYear() : nextMonth()\"\n [attr.aria-label]=\"isMonthMode() ? nextYearAriaLabel() : nextMonthAriaLabel()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </button>\n </div>\n\n <!-- Quick Actions -->\n <div class=\"lc-datepicker-quick-actions\">\n <button\n type=\"button\"\n class=\"lc-datepicker-today-button\"\n (click)=\"isMonthMode() ? showCurrentYear() : goToToday()\"\n >\n {{ isMonthMode() ? currentMonthLabel() : todayLabel() }}\n </button>\n </div>\n\n @if (isMonthMode()) {\n <!-- Month grid (3.29): APG grid, one roving tab stop, named by the year title -->\n <div class=\"lc-datepicker-months\" role=\"grid\" [attr.aria-labelledby]=\"inputId + '-year'\">\n @for (row of monthRows(); track $index) {\n <div class=\"lc-datepicker-month-row\" role=\"row\">\n @for (cell of row; track cell.month) {\n <div\n role=\"gridcell\"\n class=\"lc-datepicker-month\"\n [class.lc-datepicker-month--current]=\"cell.current\"\n [class.lc-datepicker-month--selected]=\"cell.selected\"\n [class.lc-datepicker-month--disabled]=\"cell.disabled\"\n [attr.tabindex]=\"cell.month === monthTabStop() ? 0 : -1\"\n [attr.aria-selected]=\"cell.selected ? 'true' : null\"\n [attr.aria-current]=\"cell.current ? 'date' : null\"\n [attr.aria-disabled]=\"cell.disabled ? 'true' : null\"\n [attr.aria-label]=\"cell.label\"\n (click)=\"selectMonth(cell.month)\"\n (keydown)=\"onMonthKeydown($event, cell.month)\"\n >{{ cell.name }}</div>\n }\n </div>\n }\n </div>\n } @else {\n <!-- Weekday Headers -->\n <div class=\"lc-datepicker-weekdays\" aria-hidden=\"true\">\n @for (day of weekdayLabels(); track $index) {\n <div class=\"lc-datepicker-weekday\">{{ day }}</div>\n }\n </div>\n\n <!-- Calendar Days -->\n <div class=\"lc-datepicker-days\">\n @for (date of generateCalendarDays(); track date.getTime()) {\n <button\n type=\"button\"\n class=\"lc-datepicker-day\"\n [class.lc-datepicker-day--other-month]=\"!isCurrentMonth(date)\"\n [class.lc-datepicker-day--today]=\"isToday(date)\"\n [class.lc-datepicker-day--selected]=\"isSelectedDate(date)\"\n [class.lc-datepicker-day--disabled]=\"isDateDisabled(date)\"\n [disabled]=\"isDateDisabled(date)\"\n [attr.aria-current]=\"isToday(date) ? 'date' : null\"\n [attr.aria-label]=\"dayAriaLabel(date)\"\n (click)=\"selectDate(date)\"\n >\n {{ date.getDate() }}\n </button>\n }\n </div>\n }\n </div>\n </ng-template>\n\n <!-- Helper/Error Text -->\n @if (error() && errorMessage()) {\n <div class=\"lc-datepicker__error\" [id]=\"inputId + '-error'\" role=\"alert\">\n {{ errorMessage() }}\n </div>\n } @else if (helperText()) {\n <div class=\"lc-datepicker__helper\" [id]=\"inputId + '-helper'\">\n {{ helperText() }}\n </div>\n }\n</div>\n",
|
|
820
|
+
styles: [".lc-datepicker-wrapper{display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%;position:relative}.lc-datepicker__label{display:block;margin-bottom:.125rem;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:var(--line-height-normal);color:var(--color-text-primary);overflow-wrap:break-word;hyphens:auto;hyphenate-limit-chars:12 4 3}.lc-datepicker-input-wrapper{position:relative;width:100%}.lc-datepicker{width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background-color:var(--color-surface);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease);cursor:text}.lc-datepicker::placeholder{color:var(--color-text-secondary)}.lc-datepicker:hover:not(:disabled):not([readonly]):not(.lc-datepicker--error):not(:focus){border-color:var(--color-text-secondary)}.lc-datepicker:focus{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.lc-datepicker:disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.lc-datepicker[readonly]{background-color:var(--color-surface-muted);cursor:default}.lc-datepicker.lc-datepicker--error{border-color:var(--color-error-600)}.lc-datepicker.lc-datepicker--error:focus{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.lc-datepicker.lc-datepicker--xs{height:var(--size-interactive-xs-height);padding:var(--size-interactive-xs-padding);padding-right:var(--spacing-10);font-size:var(--size-interactive-xs-font-size)}.lc-datepicker.lc-datepicker--sm{height:var(--size-interactive-sm-height);padding:var(--size-interactive-sm-padding);padding-right:var(--spacing-12);font-size:var(--size-interactive-sm-font-size)}.lc-datepicker.lc-datepicker--md{height:var(--size-interactive-md-height);padding:var(--size-interactive-md-padding);padding-right:var(--spacing-14);font-size:var(--size-interactive-md-font-size)}.lc-datepicker.lc-datepicker--lg{height:var(--size-interactive-lg-height);padding:var(--size-interactive-lg-padding);padding-right:var(--spacing-16);font-size:var(--size-interactive-lg-font-size)}.lc-datepicker.lc-datepicker--filled{background-color:var(--color-surface-sunken);border-color:var(--color-field-border)}.lc-datepicker.lc-datepicker--filled:hover:not(:disabled):not([readonly]):not(.lc-datepicker--error):not(:focus){background-color:var(--color-surface-hover);border-color:var(--color-text-secondary)}.lc-datepicker.lc-datepicker--filled:focus{background-color:var(--color-surface);border-color:var(--color-primary-500)}.lc-datepicker.lc-datepicker--filled:disabled{background-color:var(--color-surface-muted);border-color:var(--color-border)}.lc-datepicker.lc-datepicker--filled.lc-datepicker--error{border-color:var(--color-error-600)}.lc-datepicker-icons{position:absolute;right:var(--spacing-3);top:50%;transform:translateY(-50%);display:flex;align-items:center;gap:var(--spacing-1);pointer-events:none}.lc-datepicker-calendar-icon{width:1.25rem;height:1.25rem;color:var(--color-text-secondary)}.lc-datepicker-clear{position:relative;pointer-events:auto;display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin:-.125rem;padding:.125rem;background:none;background-clip:content-box;border:none;border-radius:calc(var(--border-radius-sm) + .125rem);color:var(--color-text-secondary);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-clear:hover{color:var(--color-text-primary);background-color:var(--color-surface-hover)}.lc-datepicker-clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:-1px}.lc-datepicker-clear svg{width:1rem;height:1rem}.lc-datepicker--md~.lc-datepicker-icons .lc-datepicker-clear:before,.lc-datepicker--lg~.lc-datepicker-icons .lc-datepicker-clear:before{content:\"\";position:absolute;inset:-.625rem -.125rem -.625rem -1.125rem}.lc-datepicker-calendar{position:relative;z-index:1000;margin-top:var(--spacing-1);padding:var(--lc-density-padding-md, var(--spacing-4));background-color:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--border-radius-lg);box-shadow:var(--elevation-3);min-width:280px;opacity:0;transform:translateY(-8px);transition:all var(--animation-duration-base) var(--animation-timing-ease);pointer-events:none}.lc-datepicker-calendar.lc-datepicker-calendar--open{opacity:1;transform:translateY(0);pointer-events:auto}.lc-datepicker-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--spacing-4)}.lc-datepicker-month-year{font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}.lc-datepicker-nav-button{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;background:none;border:none;border-radius:var(--border-radius-md);color:var(--color-text-secondary);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-nav-button:hover{background-color:var(--color-surface-hover);color:var(--color-text-primary)}.lc-datepicker-nav-button:active{background-color:var(--color-surface-sunken)}.lc-datepicker-nav-button:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:1px}.lc-datepicker-nav-button svg{width:1.25rem;height:1.25rem}.lc-datepicker-quick-actions{display:flex;justify-content:center;margin-bottom:var(--spacing-3)}.lc-datepicker-today-button{padding:var(--spacing-1) var(--spacing-3);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-primary-600);background:none;border:1px solid var(--color-primary-200);border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-today-button:hover{background-color:var(--color-primary-50);border-color:var(--color-primary-300)}.lc-datepicker-today-button:active{background-color:var(--color-primary-100)}.lc-datepicker-today-button:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:1px}.lc-datepicker-weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--spacing-1);margin-bottom:var(--spacing-2)}.lc-datepicker-weekday{font-size:var(--font-size-xs);font-weight:var(--font-weight-semibold);color:var(--color-text-secondary);text-align:center;padding:var(--spacing-1)}.lc-datepicker-days{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--spacing-1)}.lc-datepicker-day{display:flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;padding:0;font-size:var(--font-size-sm);font-weight:var(--font-weight-regular);color:var(--color-text-primary);background:none;border:none;border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-datepicker-day:hover:not(:disabled){background-color:var(--color-surface-hover)}.lc-datepicker-day.lc-datepicker-day--other-month{color:var(--color-text-tertiary)}.lc-datepicker-day.lc-datepicker-day--today{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-datepicker-day.lc-datepicker-day--selected{font-weight:var(--font-weight-semibold);color:var(--color-on-primary);background-color:var(--color-primary-fill);box-shadow:inset 0 0 0 2px var(--color-primary-500)}.lc-datepicker-day.lc-datepicker-day--selected:hover{background-color:var(--color-primary-fill-hover)}.lc-datepicker-day.lc-datepicker-day--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-datepicker-day.lc-datepicker-day--disabled:hover{background:none}.lc-datepicker-day:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}@media(max-width:1023.98px){.lc-datepicker-nav-button{width:2.75rem;height:2.75rem}.lc-datepicker-today-button{min-height:2.75rem}.lc-datepicker-weekdays,.lc-datepicker-days{gap:0;grid-template-columns:repeat(7,minmax(0,1fr));inline-size:19.25rem;max-inline-size:calc(100vw - 3.125rem)}.lc-datepicker-day{width:100%;height:auto;aspect-ratio:1}}.lc-datepicker-calendar--month .lc-datepicker-nav-button{width:2.75rem;height:2.75rem}.lc-datepicker-calendar--month .lc-datepicker-today-button{min-height:2.75rem}.lc-datepicker-months{display:flex;flex-direction:column;gap:var(--spacing-2);inline-size:17.25rem;max-inline-size:calc(100vw - 4.125rem)}.lc-datepicker-month-row{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--spacing-2)}.lc-datepicker-month{display:flex;align-items:center;justify-content:center;min-height:2.75rem;padding:0 var(--spacing-1);font-size:var(--font-size-sm);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);text-align:center;overflow-wrap:anywhere;hyphens:auto;color:var(--color-text-primary);border-radius:var(--border-radius-md);cursor:pointer}.lc-datepicker-month:hover:not(.lc-datepicker-month--disabled):not(.lc-datepicker-month--selected){background-color:var(--color-surface-hover)}.lc-datepicker-month.lc-datepicker-month--current{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-datepicker-month.lc-datepicker-month--selected{font-weight:var(--font-weight-semibold);color:var(--color-on-primary);background-color:var(--color-primary-fill);box-shadow:inset 0 0 0 2px var(--color-primary-500)}.lc-datepicker-month.lc-datepicker-month--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-datepicker-month:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}@media(forced-colors:active){.lc-datepicker-month:focus-visible{outline-color:Highlight}.lc-datepicker-month.lc-datepicker-month--selected{forced-color-adjust:none;background-color:Highlight;color:HighlightText}.lc-datepicker-month.lc-datepicker-month--current{text-decoration:underline}.lc-datepicker-month.lc-datepicker-month--disabled{color:GrayText}.lc-datepicker-clear:focus-visible,.lc-datepicker-day:focus-visible{outline-color:Highlight}.lc-datepicker-day.lc-datepicker-day--selected,.lc-datepicker-day.lc-datepicker-day--selected:hover{forced-color-adjust:none;background-color:Highlight;color:HighlightText}.lc-datepicker-day.lc-datepicker-day--today{text-decoration:underline}.lc-datepicker-day.lc-datepicker-day--disabled{color:GrayText}}.lc-datepicker__error{font-size:var(--font-size-xs);color:var(--color-error-600);margin-top:var(--spacing-1)}.lc-datepicker__helper{font-size:var(--font-size-xs);color:var(--color-text-secondary);margin-top:var(--spacing-1)}\n"]
|
|
806
821
|
}]
|
|
807
822
|
}],
|
|
808
823
|
propDecorators: {
|
|
@@ -894,6 +909,14 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
894
909
|
required: false
|
|
895
910
|
}]
|
|
896
911
|
}],
|
|
912
|
+
label: [{
|
|
913
|
+
type: i0.Input,
|
|
914
|
+
args: [{
|
|
915
|
+
isSignal: true,
|
|
916
|
+
alias: "label",
|
|
917
|
+
required: false
|
|
918
|
+
}]
|
|
919
|
+
}],
|
|
897
920
|
format: [{
|
|
898
921
|
type: i0.Input,
|
|
899
922
|
args: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-datepicker.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/datepicker/datepicker.component.ts","../../../../libs/angular-ui-kit/src/lib/datepicker/datepicker.component.html"],"sourcesContent":["import {\n Component,\n input,\n output,\n signal,\n computed,\n linkedSignal,\n ChangeDetectionStrategy,\n forwardRef,\n ElementRef,\n viewChild,\n inject,\n DOCUMENT,\n Injector,\n afterNextRender,\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\nimport { OverlayModule } from '@angular/cdk/overlay';\n\nexport type DateValue = Date | string | null;\n\n/** What `lc-datepicker` picks: a day (`'day'`) or a month (`'month'`). */\nexport type DatepickerGranularity = 'day' | 'month';\n\n/** One cell of the month grid (`granularity=\"month\"`). */\ninterface MonthCell {\n /** 0–11. */\n month: number;\n /** Visible name („Juli“). */\n name: string;\n /** Accessible name with the year („Juli 2026“). */\n label: string;\n selected: boolean;\n current: boolean;\n disabled: boolean;\n}\n\n/**\n * Datepicker component for date selection with calendar overlay.\n *\n * Features:\n * - Calendar popup with month and year navigation\n * - Month granularity (3.29): `granularity=\"month\"` picks a month in a\n * 12-month grid with year navigation and emits its first day\n * - Manual date entry in the configured format\n * - Min/max date constraints\n * - Disabled specific dates and weekends\n * - Configurable date format string\n * - Variant styles (outline, filled)\n * - Size presets (xs, sm, md, lg)\n * - Disabled and readonly states\n * - ControlValueAccessor integration for reactive forms\n *\n * @example\n * ```html\n * <lc-datepicker placeholder=\"Select date\" [(ngModel)]=\"selectedDate\" />\n * <lc-datepicker granularity=\"month\" format=\"YYYY-MM\" placeholder=\"Select a month\" [(ngModel)]=\"validFrom\" />\n * ```\n */\n@Component({\n selector: 'lc-datepicker',\n standalone: true,\n imports: [OverlayModule],\n templateUrl: './datepicker.component.html',\n styleUrl: './datepicker.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => DatepickerComponent),\n multi: true,\n },\n ],\n})\nexport class DatepickerComponent implements ControlValueAccessor {\n private static nextId = 0;\n\n /** Per-instance id for the input; helper/error text ids derive from it. */\n readonly inputId = `lc-datepicker-${++DatepickerComponent.nextId}`;\n\n private readonly datepickerInput = viewChild<ElementRef<HTMLInputElement>>('datepickerInput');\n private readonly calendarPanel = viewChild<ElementRef<HTMLElement>>('calendarPanel');\n\n /**\n * Visual variant of the datepicker\n */\n readonly variant = input<'outline' | 'filled'>('outline');\n\n /**\n * Size of the datepicker\n */\n readonly size = input<'xs' | 'sm' | 'md' | 'lg'>('md');\n\n /**\n * Whether the datepicker is disabled\n */\n readonly disabled = input<boolean>(false);\n\n /**\n * Whether the datepicker is in error state\n */\n readonly error = input<boolean>(false);\n\n /**\n * Whether the datepicker is required\n */\n readonly required = input<boolean>(false);\n\n /**\n * Whether the datepicker is readonly\n */\n readonly readonly = input<boolean>(false);\n\n /**\n * Placeholder text\n */\n readonly placeholder = input<string>('Select a date');\n\n /**\n * Helper text displayed below the datepicker\n */\n readonly helperText = input<string>('');\n\n /**\n * Error message displayed when error is true\n */\n readonly errorMessage = input<string>('');\n\n /**\n * ARIA label for accessibility\n */\n readonly ariaLabel = input<string | undefined>(undefined);\n\n /**\n * Date format string (e.g., 'YYYY-MM-DD', 'MM/DD/YYYY')\n */\n readonly format = input<string>('YYYY-MM-DD');\n\n /**\n * Minimum selectable date (compared by calendar day, time of day is ignored)\n */\n readonly minDate = input<Date | undefined>(undefined);\n\n /**\n * Maximum selectable date (compared by calendar day, time of day is ignored)\n */\n readonly maxDate = input<Date | undefined>(undefined);\n\n /**\n * Array of disabled dates\n */\n readonly disabledDates = input<Date[]>([]);\n\n /**\n * Whether to disable weekends\n */\n readonly disableWeekends = input<boolean>(false);\n\n /** BCP 47 locale for month and weekday names and the day buttons' accessible names (e.g. `'de-DE'`). Empty keeps the built-in English names. */\n readonly locale = input('');\n\n /** First column of the grid: 0 Sunday (default) … 6 Saturday — 1 for Monday. */\n readonly firstDayOfWeek = input(0);\n\n /** Accessible name of the clear button. */\n readonly clearAriaLabel = input('Clear date');\n\n /** Accessible name of the calendar dialog. */\n readonly dialogAriaLabel = input('Choose date');\n\n /** Accessible name of the previous-month button. */\n readonly previousMonthAriaLabel = input('Previous month');\n\n /** Accessible name of the next-month button. */\n readonly nextMonthAriaLabel = input('Next month');\n\n /** Label of the \"go to today\" button. */\n readonly todayLabel = input('Today');\n\n /** Appended to the selected day's accessible name (`…, selected`). */\n readonly selectedAriaLabel = input('selected');\n\n /**\n * Pick a day (`'day'`) or a month (`'month'`, 3.29, regeln row 1). Month:\n * a 12-month grid with year navigation; `dateChange` and the forms value\n * are the 1st of the month (local midnight, as day mode); `format` should\n * be a month format (`'YYYY-MM'`; a `DD` token shows `01`), and typing\n * „2026-07“ commits like a day. `minDate`/`maxDate` keep a month\n * selectable when any of its days is in range; a `disabledDates` entry\n * disables its whole month; `disableWeekends` is ignored. Set\n * `placeholder` (e.g. \"Select a month\"). Keys in the grid: arrows move by\n * month and row, PageUp/PageDown by year, Home/End to the first/last month\n * of the year, Enter/Space select, Escape closes.\n * @default 'day'\n */\n readonly granularity = input<DatepickerGranularity>('day');\n\n /**\n * Accessible name of the previous-year button (month mode).\n * @default 'Previous year'\n */\n readonly previousYearAriaLabel = input('Previous year');\n\n /**\n * Accessible name of the next-year button (month mode).\n * @default 'Next year'\n */\n readonly nextYearAriaLabel = input('Next year');\n\n /**\n * Accessible name of the month dialog (month mode; `dialogAriaLabel`\n * stays the day dialog's).\n * @default 'Choose month'\n */\n readonly monthDialogAriaLabel = input('Choose month');\n\n /**\n * Label of the quick action that shows the current year (month mode; day\n * mode keeps `todayLabel`).\n * @default 'This month'\n */\n readonly currentMonthLabel = input('This month');\n\n /**\n * Emitted when date selection changes\n */\n readonly dateChange = output<Date | null>();\n\n /**\n * Emitted when calendar opens\n */\n readonly opened = output<void>();\n\n /**\n * Emitted when calendar closes\n */\n readonly closed = output<void>();\n\n // Internal state\n readonly selectedDate = signal<Date | null>(null);\n readonly isOpen = signal<boolean>(false);\n readonly currentMonth = signal<number>(new Date().getMonth());\n readonly currentYear = signal<number>(new Date().getFullYear());\n\n /** Disabled state pushed in by the forms API (setDisabledState). */\n private readonly formDisabled = signal<boolean>(false);\n\n /** Effective disabled state: the `disabled` input OR the form control's disabled state. */\n readonly isDisabled = computed(() => this.disabled() || this.formDisabled());\n\n /** Month granularity (3.29). */\n protected readonly isMonthMode = computed(() => this.granularity() === 'month');\n\n // Computed values\n readonly formattedDate = computed(() => {\n const date = this.selectedDate();\n if (!date) return '';\n // Month mode shows the month: a `DD` token is the 1st.\n const shown = this.isMonthMode() ? new Date(date.getFullYear(), date.getMonth(), 1) : date;\n return this.formatDate(shown, this.format());\n });\n\n /**\n * Text currently shown in the input. Follows the selected date, but the user\n * can type freely; only a complete, valid date is committed to the model.\n */\n readonly inputValue = linkedSignal(() => this.formattedDate());\n\n weekDays = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];\n\n monthNames = [\n 'January',\n 'February',\n 'March',\n 'April',\n 'May',\n 'June',\n 'July',\n 'August',\n 'September',\n 'October',\n 'November',\n 'December',\n ];\n\n /** Month name in the header: `locale` when set, the English names otherwise. */\n readonly currentMonthName = computed(() => {\n const locale = this.locale();\n return locale\n ? new Date(this.currentYear(), this.currentMonth(), 1).toLocaleDateString(locale, { month: 'long' })\n : this.monthNames[this.currentMonth()];\n });\n\n /** Weekday headers in grid order, starting at `firstDayOfWeek`. */\n readonly weekdayLabels = computed(() => {\n const locale = this.locale();\n const first = this.gridStart();\n // 1 Jan 2023 was a Sunday, so day d of that week has getDay() === d.\n const names = locale\n ? Array.from({ length: 7 }, (_, d) =>\n new Date(2023, 0, 1 + d).toLocaleDateString(locale, { weekday: 'short' }).replace(/\\.$/, ''),\n )\n : this.weekDays;\n return Array.from({ length: 7 }, (_, i) => names[(first + i) % 7]);\n });\n\n /** Header title: „July 2026“ (day mode) or the year „2026“ (month mode). */\n protected readonly headerTitle = computed(() =>\n this.isMonthMode() ? String(this.currentYear()) : `${this.currentMonthName()} ${this.currentYear()}`,\n );\n\n /** The twelve months of the shown year (month mode). */\n protected readonly monthCells = computed<MonthCell[]>(() => {\n const year = this.currentYear();\n const locale = this.locale();\n const selected = this.selectedDate();\n const today = new Date();\n return Array.from({ length: 12 }, (_, month) => {\n const first = new Date(year, month, 1);\n return {\n month,\n name: locale ? first.toLocaleDateString(locale, { month: 'long' }) : this.monthNames[month],\n label: first.toLocaleDateString(locale || 'en-US', { month: 'long', year: 'numeric' }),\n selected: !!selected && selected.getFullYear() === year && selected.getMonth() === month,\n current: today.getFullYear() === year && today.getMonth() === month,\n disabled: this.isMonthDisabled(year, month),\n };\n });\n });\n\n /** The month grid's four rows of three. */\n protected readonly monthRows = computed(() => [0, 3, 6, 9].map((i) => this.monthCells().slice(i, i + 3)));\n\n /**\n * The month cell that is the grid's one tab stop (roving `tabindex`): the\n * selected month in the shown year, else the current month, else the first\n * enabled one; `-1` when the whole year is disabled. Keys move it.\n */\n protected readonly monthTabStop = linkedSignal(() => this.defaultMonthTabStop());\n\n /** `firstDayOfWeek` clamped to 0–6. */\n private readonly gridStart = computed(() => {\n const day = Math.trunc(Number(this.firstDayOfWeek()));\n return Number.isFinite(day) ? ((day % 7) + 7) % 7 : 0;\n });\n\n /** id of the helper/error text the input is described by (aria-describedby) */\n readonly describedBy = computed(() => {\n if (this.error() && this.errorMessage()) {\n return `${this.inputId}-error`;\n }\n return this.helperText() ? `${this.inputId}-helper` : null;\n });\n\n /**\n * Computed classes for the datepicker input element\n */\n readonly datepickerClasses = computed(() => {\n const classes = [\n 'lc-datepicker',\n `lc-datepicker--${this.variant()}`,\n `lc-datepicker--${this.size()}`,\n ];\n\n if (this.isDisabled()) {\n classes.push('lc-datepicker--disabled');\n }\n\n if (this.error()) {\n classes.push('lc-datepicker--error');\n }\n\n if (this.readonly()) {\n classes.push('lc-datepicker--readonly');\n }\n\n if (this.isOpen()) {\n classes.push('lc-datepicker--open');\n }\n\n return classes.join(' ');\n });\n\n // Private properties\n private readonly document = inject(DOCUMENT);\n private readonly injector = inject(Injector);\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private onChange: (value: Date | null) => void = () => {};\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private onTouched: () => void = () => {};\n\n // Public methods\n /**\n * Toggle calendar open/closed\n */\n toggle(): void {\n if (this.isDisabled() || this.readonly()) {\n return;\n }\n if (this.isOpen()) {\n this.close();\n } else {\n this.open();\n }\n }\n\n /**\n * Open calendar\n */\n open(): void {\n if (this.isDisabled() || this.readonly() || this.isOpen()) {\n return;\n }\n this.isOpen.set(true);\n\n // Set calendar to selected date's month/year or current\n const date = this.selectedDate();\n if (date) {\n this.showMonthOf(date);\n }\n // Month mode: the grid's tab stop starts on the selected (or current) month again.\n if (this.isMonthMode()) {\n this.monthTabStop.set(this.defaultMonthTabStop());\n }\n\n this.opened.emit();\n }\n\n /**\n * Close calendar. Idempotent: the overlay's `detach` re-enters here after\n * `isOpen` flips, and that second call must not emit `closed` again.\n */\n close(): void {\n if (!this.isOpen()) {\n return;\n }\n // A day button inside the panel may hold focus; it is about to be removed,\n // so hand focus back to the input instead of letting it drop to <body>.\n this.restoreFocusFromPanel();\n this.isOpen.set(false);\n this.closed.emit();\n }\n\n /**\n * Select a date\n */\n selectDate(date: Date): void {\n if (this.isDisabled() || this.readonly() || this.isDateDisabled(date)) {\n return;\n }\n\n this.commitDate(date);\n this.close();\n }\n\n /**\n * Clear selected date\n */\n clear(): void {\n this.selectedDate.set(null);\n this.inputValue.set('');\n this.onChange(null);\n this.dateChange.emit(null);\n }\n\n /**\n * Check if a date is disabled\n */\n isDateDisabled(date: Date): boolean {\n // min/max are compared by calendar day: consumers typically pass `new Date()`\n // (which carries the current time) while calendar cells sit at midnight.\n const day = this.startOfDay(date);\n\n const min = this.minDate();\n if (min && day < this.startOfDay(min)) {\n return true;\n }\n\n const max = this.maxDate();\n if (max && day > this.startOfDay(max)) {\n return true;\n }\n\n // Check disabled dates\n if (this.disabledDates().some((d) => this.isSameDate(d, date))) {\n return true;\n }\n\n // Check weekends\n if (this.disableWeekends()) {\n const weekday = date.getDay();\n if (weekday === 0 || weekday === 6) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Check if date is today\n */\n isToday(date: Date): boolean {\n const today = new Date();\n return this.isSameDate(date, today);\n }\n\n /** Accessible name of a day button: the full date, plus `selectedAriaLabel` when selected. */\n protected dayAriaLabel(date: Date): string {\n const locale = this.locale();\n const name = locale\n ? date.toLocaleDateString(locale, { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' })\n : date.toDateString();\n return this.isSelectedDate(date) ? `${name}, ${this.selectedAriaLabel()}` : name;\n }\n\n /**\n * Check if date is selected\n */\n isSelectedDate(date: Date): boolean {\n const selected = this.selectedDate();\n return selected ? this.isSameDate(date, selected) : false;\n }\n\n /**\n * Generate calendar days for current month\n */\n generateCalendarDays(): Date[] {\n const year = this.currentYear();\n const month = this.currentMonth();\n\n const firstDay = new Date(year, month, 1);\n const lastDay = new Date(year, month + 1, 0);\n\n const days: Date[] = [];\n\n // Add previous month's days, so the first column is `firstDayOfWeek`.\n const leadingDays = (firstDay.getDay() - this.gridStart() + 7) % 7;\n for (let i = leadingDays - 1; i >= 0; i--) {\n const date = new Date(year, month, -i);\n days.push(date);\n }\n\n // Add current month's days\n for (let i = 1; i <= lastDay.getDate(); i++) {\n days.push(new Date(year, month, i));\n }\n\n // Add next month's days to complete the grid\n const remainingDays = 42 - days.length; // 6 weeks * 7 days\n for (let i = 1; i <= remainingDays; i++) {\n days.push(new Date(year, month + 1, i));\n }\n\n return days.slice(0, 42); // Ensure exactly 42 days (6 weeks)\n }\n\n /**\n * Navigate to next month\n */\n nextMonth(): void {\n if (this.currentMonth() === 11) {\n this.currentMonth.set(0);\n this.currentYear.set(this.currentYear() + 1);\n } else {\n this.currentMonth.set(this.currentMonth() + 1);\n }\n }\n\n /**\n * Navigate to previous month\n */\n previousMonth(): void {\n if (this.currentMonth() === 0) {\n this.currentMonth.set(11);\n this.currentYear.set(this.currentYear() - 1);\n } else {\n this.currentMonth.set(this.currentMonth() - 1);\n }\n }\n\n /**\n * Navigate to today\n */\n goToToday(): void {\n this.showMonthOf(new Date());\n }\n\n /** Month mode: show the previous year. */\n protected previousYear(): void {\n this.currentYear.update((year) => year - 1);\n }\n\n /** Month mode: show the next year. */\n protected nextYear(): void {\n this.currentYear.update((year) => year + 1);\n }\n\n /** Month mode's quick action: show the current year. */\n protected showCurrentYear(): void {\n this.currentYear.set(new Date().getFullYear());\n }\n\n /** Month mode: select `month` of the shown year (its 1st), emit, close and focus the field. */\n protected selectMonth(month: number): void {\n const year = this.currentYear();\n if (this.isDisabled() || this.readonly() || this.isMonthDisabled(year, month)) {\n return;\n }\n this.commitDate(new Date(year, month, 1));\n this.close();\n }\n\n /**\n * Keys on a month cell (APG date grid): arrows ±1 month and ±3 (a row),\n * PageUp/PageDown ±1 year (the nearest enabled month of that year),\n * Home/End the first/last enabled month of the year; disabled months are\n * skipped, and with none left focus stays. Enter/Space select, Escape\n * closes. Arrows only move focus.\n */\n protected onMonthKeydown(event: KeyboardEvent, month: number): void {\n const year = this.currentYear();\n const at = year * 12 + month;\n let target: number | null;\n switch (event.key) {\n case 'ArrowLeft':\n target = this.nextEnabledMonth(at, -1);\n break;\n case 'ArrowRight':\n target = this.nextEnabledMonth(at, 1);\n break;\n case 'ArrowUp':\n target = this.nextEnabledMonth(at, -3);\n break;\n case 'ArrowDown':\n target = this.nextEnabledMonth(at, 3);\n break;\n case 'PageUp':\n target = this.nearestEnabledMonth(year - 1, month);\n break;\n case 'PageDown':\n target = this.nearestEnabledMonth(year + 1, month);\n break;\n case 'Home':\n target = this.edgeEnabledMonth(year, 1);\n break;\n case 'End':\n target = this.edgeEnabledMonth(year, -1);\n break;\n case 'Enter':\n case ' ':\n event.preventDefault();\n this.selectMonth(month);\n return;\n case 'Escape':\n event.preventDefault();\n // Only this datepicker should react; keep the key from reaching enclosing overlays.\n event.stopPropagation();\n this.close();\n return;\n default:\n return;\n }\n event.preventDefault();\n if (target !== null) {\n this.moveMonthFocus(target);\n }\n }\n\n /**\n * Handle input change (manual date entry). Partial input is kept as text\n * only; the model changes once the text is a complete, valid, selectable date.\n */\n onInputChange(value: string): void {\n this.inputValue.set(value);\n\n if (value.trim() === '') {\n if (this.selectedDate() !== null) {\n this.clear();\n }\n return;\n }\n\n const date = this.parseDate(value, this.format());\n if (date && !this.isUnavailable(date) && !this.isSameSelection(date)) {\n this.commitDate(date);\n this.showMonthOf(date);\n }\n }\n\n /**\n * Handle keyboard navigation\n */\n onKeyDown(event: KeyboardEvent): void {\n if (this.isDisabled() || this.readonly()) {\n return;\n }\n\n if (\n !this.isOpen() &&\n (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ')\n ) {\n this.open();\n event.preventDefault();\n // Month mode: the keys work in the grid, so focus moves there once it is rendered.\n if (this.isMonthMode()) {\n afterNextRender(() => this.focusMonthCell(this.monthTabStop()), { injector: this.injector });\n }\n return;\n }\n\n if (!this.isOpen()) return;\n\n if (this.isMonthMode()) {\n this.onMonthFieldKeyDown(event);\n return;\n }\n\n // While the text differs from the model the user is mid-edit: arrows must\n // move the caret, not the calendar selection.\n const editing = this.inputValue() !== this.formattedDate();\n const currentDate = this.selectedDate() || new Date();\n let newDate: Date | null = null;\n\n switch (event.key) {\n case 'Escape':\n this.close();\n event.preventDefault();\n // Only this datepicker should react; keep the key from reaching enclosing overlays.\n event.stopPropagation();\n break;\n\n case 'ArrowRight':\n if (editing) break;\n newDate = new Date(currentDate);\n newDate.setDate(currentDate.getDate() + 1);\n event.preventDefault();\n break;\n\n case 'ArrowLeft':\n if (editing) break;\n newDate = new Date(currentDate);\n newDate.setDate(currentDate.getDate() - 1);\n event.preventDefault();\n break;\n\n case 'ArrowDown':\n if (editing) break;\n newDate = new Date(currentDate);\n newDate.setDate(currentDate.getDate() + 7);\n event.preventDefault();\n break;\n\n case 'ArrowUp':\n if (editing) break;\n newDate = new Date(currentDate);\n newDate.setDate(currentDate.getDate() - 7);\n event.preventDefault();\n break;\n\n case 'Enter': {\n const selected = this.selectedDate();\n if (selected) {\n this.selectDate(selected);\n }\n event.preventDefault();\n break;\n }\n }\n\n if (newDate && !this.isDateDisabled(newDate)) {\n this.selectedDate.set(newDate);\n this.showMonthOf(newDate);\n }\n }\n\n /**\n * Handle blur event: mark touched and drop any partial text that never became a date.\n */\n onBlur(): void {\n this.onTouched();\n this.inputValue.set(this.formattedDate());\n }\n\n /**\n * Handle click outside\n */\n onClickOutside(): void {\n this.close();\n }\n\n // ControlValueAccessor implementation\n writeValue(value: DateValue): void {\n let date: Date | null = null;\n if (value instanceof Date) {\n date = isNaN(value.getTime()) ? null : value;\n } else if (typeof value === 'string') {\n date = this.parseDate(value, this.format());\n }\n this.selectedDate.set(date);\n this.inputValue.set(this.formattedDate());\n }\n\n registerOnChange(fn: (value: Date | null) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n }\n\n /**\n * Check if date is in current month\n */\n isCurrentMonth(date: Date): boolean {\n return date.getMonth() === this.currentMonth() && date.getFullYear() === this.currentYear();\n }\n\n // Private helper methods\n\n /** The selected month of the shown year, else the current month, else the first enabled one; `-1` if none. */\n private defaultMonthTabStop(): number {\n const cells = this.monthCells().filter((c) => !c.disabled);\n return (cells.find((c) => c.selected) ?? cells.find((c) => c.current) ?? cells[0])?.month ?? -1;\n }\n\n /**\n * Keys in the field while the month panel is open: ArrowDown moves focus\n * into the grid, Escape closes, Enter closes when a month is selected;\n * the other keys stay with the text (caret, typing „2026-07“).\n */\n private onMonthFieldKeyDown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n this.focusMonthCell(this.monthTabStop());\n break;\n case 'Escape':\n this.close();\n event.preventDefault();\n // Only this datepicker should react; keep the key from reaching enclosing overlays.\n event.stopPropagation();\n break;\n case 'Enter':\n event.preventDefault();\n if (this.selectedDate()) {\n this.close();\n }\n break;\n }\n }\n\n /**\n * Month mode: a month is disabled when all its days are before `minDate`\n * or after `maxDate` (compared by day), or when `disabledDates` holds one\n * of its days. `disableWeekends` does not apply.\n */\n private isMonthDisabled(year: number, month: number): boolean {\n const min = this.minDate();\n if (min && new Date(year, month + 1, 0).getTime() < this.startOfDay(min)) {\n return true;\n }\n const max = this.maxDate();\n if (max && new Date(year, month, 1).getTime() > this.startOfDay(max)) {\n return true;\n }\n return this.disabledDates().some((d) => d.getFullYear() === year && d.getMonth() === month);\n }\n\n /** A typed date that cannot be committed: its day (day mode) or its month (month mode) is disabled. */\n private isUnavailable(date: Date): boolean {\n return this.isMonthMode() ? this.isMonthDisabled(date.getFullYear(), date.getMonth()) : this.isDateDisabled(date);\n }\n\n /** Whether `date` is the current selection: the same day, or in month mode the same month. */\n private isSameSelection(date: Date): boolean {\n if (!this.isMonthMode()) return this.isSelectedDate(date);\n const selected = this.selectedDate();\n return !!selected && selected.getFullYear() === date.getFullYear() && selected.getMonth() === date.getMonth();\n }\n\n /** Year and month (0–11) of a month index `year * 12 + month`. */\n private monthAt(index: number): { year: number; month: number } {\n return { year: Math.floor(index / 12), month: ((index % 12) + 12) % 12 };\n }\n\n /** The next enabled month from `index` in steps of `step` (up to ten years), or `null`. */\n private nextEnabledMonth(index: number, step: number): number | null {\n for (let i = 1; i * Math.abs(step) <= 120; i++) {\n const { year, month } = this.monthAt(index + step * i);\n if (!this.isMonthDisabled(year, month)) return index + step * i;\n }\n return null;\n }\n\n /** `month` of `year` if enabled, else the enabled month of that year nearest to it, or `null`. */\n private nearestEnabledMonth(year: number, month: number): number | null {\n for (let d = 0; d < 12; d++) {\n for (const m of d === 0 ? [month] : [month - d, month + d]) {\n if (m >= 0 && m < 12 && !this.isMonthDisabled(year, m)) return year * 12 + m;\n }\n }\n return null;\n }\n\n /** The first (`dir` 1) or last (`dir` -1) enabled month of `year`, or `null`. */\n private edgeEnabledMonth(year: number, dir: 1 | -1): number | null {\n for (let i = 0; i < 12; i++) {\n const month = dir === 1 ? i : 11 - i;\n if (!this.isMonthDisabled(year, month)) return year * 12 + month;\n }\n return null;\n }\n\n /** Moves the grid's tab stop and focus to the month `index`; the shown year follows. */\n private moveMonthFocus(index: number): void {\n const { year, month } = this.monthAt(index);\n if (year !== this.currentYear()) {\n this.currentYear.set(year);\n }\n this.monthTabStop.set(month);\n this.focusMonthCell(month);\n }\n\n /** Focuses the month cell `month` (0–11) of the open panel; the cells are kept across years. */\n private focusMonthCell(month: number): void {\n if (month < 0) return;\n this.calendarPanel()\n ?.nativeElement.querySelectorAll<HTMLElement>('.lc-datepicker-month')\n [month]?.focus();\n }\n\n private commitDate(date: Date): void {\n this.selectedDate.set(date);\n this.inputValue.set(this.formatDate(date, this.format()));\n this.onChange(date);\n this.dateChange.emit(date);\n }\n\n private showMonthOf(date: Date): void {\n this.currentMonth.set(date.getMonth());\n this.currentYear.set(date.getFullYear());\n }\n\n private restoreFocusFromPanel(): void {\n const panel = this.calendarPanel()?.nativeElement;\n const active = this.document.activeElement;\n if (panel && active && panel.contains(active)) {\n this.datepickerInput()?.nativeElement.focus();\n }\n }\n\n private startOfDay(date: Date): number {\n return new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();\n }\n\n /**\n * Check if two dates are the same day\n */\n private isSameDate(date1: Date, date2: Date): boolean {\n return (\n date1.getFullYear() === date2.getFullYear() &&\n date1.getMonth() === date2.getMonth() &&\n date1.getDate() === date2.getDate()\n );\n }\n\n private formatDate(date: Date, format: string): string {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n return format.replace('YYYY', String(year)).replace('MM', month).replace('DD', day);\n }\n\n /**\n * Strict parse: the text must match the format's length, carry digits at the\n * YYYY/MM/DD positions and round-trip through formatDate (which rejects\n * things like month 13 or Feb 31 that `new Date` would silently roll over).\n * Returns null for partial or invalid input. Month mode also takes a format\n * without `DD` (`YYYY-MM`) and returns the 1st of the month.\n */\n private parseDate(value: string, format: string): Date | null {\n if (value.length !== format.length) {\n return null;\n }\n\n const monthMode = this.isMonthMode();\n const yearIndex = format.indexOf('YYYY');\n const monthIndex = format.indexOf('MM');\n const dayIndex = format.indexOf('DD');\n if (yearIndex < 0 || monthIndex < 0 || (dayIndex < 0 && !monthMode)) {\n return null;\n }\n\n const yearText = value.substring(yearIndex, yearIndex + 4);\n const monthText = value.substring(monthIndex, monthIndex + 2);\n const dayText = dayIndex < 0 ? '01' : value.substring(dayIndex, dayIndex + 2);\n if (!/^\\d{4}$/.test(yearText) || !/^\\d{2}$/.test(monthText) || !/^\\d{2}$/.test(dayText)) {\n return null;\n }\n\n const date = new Date(Number(yearText), Number(monthText) - 1, Number(dayText));\n if (this.formatDate(date, format) !== value) {\n return null;\n }\n return monthMode ? new Date(date.getFullYear(), date.getMonth(), 1) : date;\n }\n\n protected getInputValue(event: Event): string {\n return (event.target as HTMLInputElement).value;\n }\n}\n","<div class=\"lc-datepicker-wrapper\">\n <div class=\"lc-datepicker-input-wrapper\">\n <input\n #datepickerInput\n type=\"text\"\n [id]=\"inputId\"\n [class]=\"datepickerClasses()\"\n role=\"combobox\"\n aria-haspopup=\"dialog\"\n autocomplete=\"off\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? inputId + '-calendar' : null\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [readonly]=\"readonly()\"\n [disabled]=\"isDisabled()\"\n [placeholder]=\"placeholder()\"\n [value]=\"inputValue()\"\n (input)=\"onInputChange(getInputValue($event))\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n />\n <div class=\"lc-datepicker-icons\">\n @if (selectedDate() && !isDisabled() && !readonly()) {\n <button\n type=\"button\"\n class=\"lc-datepicker-clear\"\n (click)=\"clear(); $event.stopPropagation()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\"\n />\n </svg>\n </button>\n }\n <svg\n class=\"lc-datepicker-calendar-icon\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M5.25 12a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H6a.75.75 0 01-.75-.75V12zM6 13.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V14a.75.75 0 00-.75-.75H6zM7.25 12a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H8a.75.75 0 01-.75-.75V12zM8 13.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V14a.75.75 0 00-.75-.75H8zM9.25 10a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H10a.75.75 0 01-.75-.75V10zM10 11.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V12a.75.75 0 00-.75-.75H10zM9.25 14a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H10a.75.75 0 01-.75-.75V14zM12 9.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V10a.75.75 0 00-.75-.75H12zM11.25 12a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H12a.75.75 0 01-.75-.75V12zM12 13.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V14a.75.75 0 00-.75-.75H12zM13.25 10a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H14a.75.75 0 01-.75-.75V10zM14 11.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V12a.75.75 0 00-.75-.75H14z\"\n />\n <path\n fill-rule=\"evenodd\"\n d=\"M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </div>\n\n <!-- Calendar Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"datepickerInput\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n (backdropClick)=\"onClickOutside()\"\n (detach)=\"close()\"\n >\n <div\n #calendarPanel\n class=\"lc-datepicker-calendar\"\n [class.lc-datepicker-calendar--open]=\"isOpen()\"\n [class.lc-datepicker-calendar--month]=\"isMonthMode()\"\n [id]=\"inputId + '-calendar'\"\n role=\"dialog\"\n [attr.aria-label]=\"isMonthMode() ? monthDialogAriaLabel() : dialogAriaLabel()\"\n >\n <!-- Calendar Header (month mode, 3.29: the year and year buttons) -->\n <div class=\"lc-datepicker-header\">\n <button\n type=\"button\"\n class=\"lc-datepicker-nav-button\"\n (click)=\"isMonthMode() ? previousYear() : previousMonth()\"\n [attr.aria-label]=\"isMonthMode() ? previousYearAriaLabel() : previousMonthAriaLabel()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n fill-rule=\"evenodd\"\n d=\"M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </button>\n \n <div class=\"lc-datepicker-month-year\" aria-live=\"polite\" [attr.id]=\"isMonthMode() ? inputId + '-year' : null\">\n {{ headerTitle() }}\n </div>\n\n <button\n type=\"button\"\n class=\"lc-datepicker-nav-button\"\n (click)=\"isMonthMode() ? nextYear() : nextMonth()\"\n [attr.aria-label]=\"isMonthMode() ? nextYearAriaLabel() : nextMonthAriaLabel()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </button>\n </div>\n\n <!-- Quick Actions -->\n <div class=\"lc-datepicker-quick-actions\">\n <button\n type=\"button\"\n class=\"lc-datepicker-today-button\"\n (click)=\"isMonthMode() ? showCurrentYear() : goToToday()\"\n >\n {{ isMonthMode() ? currentMonthLabel() : todayLabel() }}\n </button>\n </div>\n\n @if (isMonthMode()) {\n <!-- Month grid (3.29): APG grid, one roving tab stop, named by the year title -->\n <div class=\"lc-datepicker-months\" role=\"grid\" [attr.aria-labelledby]=\"inputId + '-year'\">\n @for (row of monthRows(); track $index) {\n <div class=\"lc-datepicker-month-row\" role=\"row\">\n @for (cell of row; track cell.month) {\n <div\n role=\"gridcell\"\n class=\"lc-datepicker-month\"\n [class.lc-datepicker-month--current]=\"cell.current\"\n [class.lc-datepicker-month--selected]=\"cell.selected\"\n [class.lc-datepicker-month--disabled]=\"cell.disabled\"\n [attr.tabindex]=\"cell.month === monthTabStop() ? 0 : -1\"\n [attr.aria-selected]=\"cell.selected ? 'true' : null\"\n [attr.aria-current]=\"cell.current ? 'date' : null\"\n [attr.aria-disabled]=\"cell.disabled ? 'true' : null\"\n [attr.aria-label]=\"cell.label\"\n (click)=\"selectMonth(cell.month)\"\n (keydown)=\"onMonthKeydown($event, cell.month)\"\n >{{ cell.name }}</div>\n }\n </div>\n }\n </div>\n } @else {\n <!-- Weekday Headers -->\n <div class=\"lc-datepicker-weekdays\" aria-hidden=\"true\">\n @for (day of weekdayLabels(); track $index) {\n <div class=\"lc-datepicker-weekday\">{{ day }}</div>\n }\n </div>\n\n <!-- Calendar Days -->\n <div class=\"lc-datepicker-days\">\n @for (date of generateCalendarDays(); track date.getTime()) {\n <button\n type=\"button\"\n class=\"lc-datepicker-day\"\n [class.lc-datepicker-day--other-month]=\"!isCurrentMonth(date)\"\n [class.lc-datepicker-day--today]=\"isToday(date)\"\n [class.lc-datepicker-day--selected]=\"isSelectedDate(date)\"\n [class.lc-datepicker-day--disabled]=\"isDateDisabled(date)\"\n [disabled]=\"isDateDisabled(date)\"\n [attr.aria-current]=\"isToday(date) ? 'date' : null\"\n [attr.aria-label]=\"dayAriaLabel(date)\"\n (click)=\"selectDate(date)\"\n >\n {{ date.getDate() }}\n </button>\n }\n </div>\n }\n </div>\n </ng-template>\n\n <!-- Helper/Error Text -->\n @if (error() && errorMessage()) {\n <div class=\"lc-datepicker__error\" [id]=\"inputId + '-error'\" role=\"alert\">\n {{ errorMessage() }}\n </div>\n } @else if (helperText()) {\n <div class=\"lc-datepicker__helper\" [id]=\"inputId + '-helper'\">\n {{ helperText() }}\n </div>\n }\n</div>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-datepicker.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/datepicker/datepicker.component.ts","../../../../libs/angular-ui-kit/src/lib/datepicker/datepicker.component.html"],"sourcesContent":["import {\n Component,\n input,\n output,\n signal,\n computed,\n linkedSignal,\n ChangeDetectionStrategy,\n forwardRef,\n ElementRef,\n viewChild,\n inject,\n DOCUMENT,\n Injector,\n afterNextRender,\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\nimport { OverlayModule } from '@angular/cdk/overlay';\n\nexport type DateValue = Date | string | null;\n\n/** What `lc-datepicker` picks: a day (`'day'`) or a month (`'month'`). */\nexport type DatepickerGranularity = 'day' | 'month';\n\n/** One cell of the month grid (`granularity=\"month\"`). */\ninterface MonthCell {\n /** 0–11. */\n month: number;\n /** Visible name („Juli“). */\n name: string;\n /** Accessible name with the year („Juli 2026“). */\n label: string;\n selected: boolean;\n current: boolean;\n disabled: boolean;\n}\n\n/**\n * Datepicker component for date selection with calendar overlay.\n *\n * Features:\n * - Calendar popup with month and year navigation\n * - Month granularity (3.29): `granularity=\"month\"` picks a month in a\n * 12-month grid with year navigation and emits its first day\n * - Manual date entry in the configured format\n * - Min/max date constraints\n * - Disabled specific dates and weekends\n * - Configurable date format string\n * - Variant styles (outline, filled)\n * - Size presets (xs, sm, md, lg)\n * - Disabled and readonly states\n * - ControlValueAccessor integration for reactive forms\n *\n * @example\n * ```html\n * <lc-datepicker placeholder=\"Select date\" [(ngModel)]=\"selectedDate\" />\n * <lc-datepicker granularity=\"month\" format=\"YYYY-MM\" placeholder=\"Select a month\" [(ngModel)]=\"validFrom\" />\n * ```\n */\n@Component({\n selector: 'lc-datepicker',\n standalone: true,\n imports: [OverlayModule],\n templateUrl: './datepicker.component.html',\n styleUrl: './datepicker.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => DatepickerComponent),\n multi: true,\n },\n ],\n})\nexport class DatepickerComponent implements ControlValueAccessor {\n private static nextId = 0;\n\n /** Per-instance id for the input; helper/error text ids derive from it. */\n readonly inputId = `lc-datepicker-${++DatepickerComponent.nextId}`;\n\n private readonly datepickerInput = viewChild<ElementRef<HTMLInputElement>>('datepickerInput');\n private readonly calendarPanel = viewChild<ElementRef<HTMLElement>>('calendarPanel');\n\n /**\n * Visual variant of the datepicker\n */\n readonly variant = input<'outline' | 'filled'>('outline');\n\n /**\n * Size of the datepicker\n */\n readonly size = input<'xs' | 'sm' | 'md' | 'lg'>('md');\n\n /**\n * Whether the datepicker is disabled\n */\n readonly disabled = input<boolean>(false);\n\n /**\n * Whether the datepicker is in error state\n */\n readonly error = input<boolean>(false);\n\n /**\n * Whether the datepicker is required\n */\n readonly required = input<boolean>(false);\n\n /**\n * Whether the datepicker is readonly\n */\n readonly readonly = input<boolean>(false);\n\n /**\n * Placeholder text\n */\n readonly placeholder = input<string>('Select a date');\n\n /**\n * Helper text displayed below the datepicker\n */\n readonly helperText = input<string>('');\n\n /**\n * Error message displayed when error is true\n */\n readonly errorMessage = input<string>('');\n\n /**\n * ARIA label for accessibility. Ignored while `label` is set.\n * @default undefined\n */\n readonly ariaLabel = input<string | undefined>(undefined);\n\n /**\n * Visible label above the field (3.30, regeln row 7): a `<label for>` in\n * day and month mode that names the field, so `ariaLabel` is not used\n * while it is set. Empty: no label element, as before.\n * @default ''\n */\n readonly label = input<string>('');\n\n /**\n * Date format string (e.g., 'YYYY-MM-DD', 'MM/DD/YYYY')\n */\n readonly format = input<string>('YYYY-MM-DD');\n\n /**\n * Minimum selectable date (compared by calendar day, time of day is ignored)\n */\n readonly minDate = input<Date | undefined>(undefined);\n\n /**\n * Maximum selectable date (compared by calendar day, time of day is ignored)\n */\n readonly maxDate = input<Date | undefined>(undefined);\n\n /**\n * Array of disabled dates\n */\n readonly disabledDates = input<Date[]>([]);\n\n /**\n * Whether to disable weekends\n */\n readonly disableWeekends = input<boolean>(false);\n\n /**\n * BCP 47 locale for month and weekday names and the day buttons' accessible\n * names (e.g. `'de-DE'`). Empty keeps the built-in English names; the days\n * are then named in `en-US` (\"Wednesday, July 1, 2026\").\n * @default ''\n */\n readonly locale = input('');\n\n /** First column of the grid: 0 Sunday (default) … 6 Saturday — 1 for Monday. */\n readonly firstDayOfWeek = input(0);\n\n /** Accessible name of the clear button. */\n readonly clearAriaLabel = input('Clear date');\n\n /** Accessible name of the calendar dialog. */\n readonly dialogAriaLabel = input('Choose date');\n\n /** Accessible name of the previous-month button. */\n readonly previousMonthAriaLabel = input('Previous month');\n\n /** Accessible name of the next-month button. */\n readonly nextMonthAriaLabel = input('Next month');\n\n /** Label of the \"go to today\" button. */\n readonly todayLabel = input('Today');\n\n /** Appended to the selected day's accessible name (`…, selected`). */\n readonly selectedAriaLabel = input('selected');\n\n /**\n * Pick a day (`'day'`) or a month (`'month'`, 3.29, regeln row 1). Month:\n * a 12-month grid with year navigation; `dateChange` and the forms value\n * are the 1st of the month (local midnight, as day mode); `format` should\n * be a month format (`'YYYY-MM'`; a `DD` token shows `01`), and typing\n * „2026-07“ commits like a day. `minDate`/`maxDate` keep a month\n * selectable when any of its days is in range; a `disabledDates` entry\n * disables its whole month; `disableWeekends` is ignored. Set\n * `placeholder` (e.g. \"Select a month\"). Keys in the grid: arrows move by\n * month and row, PageUp/PageDown by year, Home/End to the first/last month\n * of the year, Enter/Space select, Escape closes.\n * @default 'day'\n */\n readonly granularity = input<DatepickerGranularity>('day');\n\n /**\n * Accessible name of the previous-year button (month mode).\n * @default 'Previous year'\n */\n readonly previousYearAriaLabel = input('Previous year');\n\n /**\n * Accessible name of the next-year button (month mode).\n * @default 'Next year'\n */\n readonly nextYearAriaLabel = input('Next year');\n\n /**\n * Accessible name of the month dialog (month mode; `dialogAriaLabel`\n * stays the day dialog's).\n * @default 'Choose month'\n */\n readonly monthDialogAriaLabel = input('Choose month');\n\n /**\n * Label of the quick action that shows the current year (month mode; day\n * mode keeps `todayLabel`).\n * @default 'This month'\n */\n readonly currentMonthLabel = input('This month');\n\n /**\n * Emitted when date selection changes\n */\n readonly dateChange = output<Date | null>();\n\n /**\n * Emitted when calendar opens\n */\n readonly opened = output<void>();\n\n /**\n * Emitted when calendar closes\n */\n readonly closed = output<void>();\n\n // Internal state\n readonly selectedDate = signal<Date | null>(null);\n readonly isOpen = signal<boolean>(false);\n readonly currentMonth = signal<number>(new Date().getMonth());\n readonly currentYear = signal<number>(new Date().getFullYear());\n\n /** Disabled state pushed in by the forms API (setDisabledState). */\n private readonly formDisabled = signal<boolean>(false);\n\n /** Effective disabled state: the `disabled` input OR the form control's disabled state. */\n readonly isDisabled = computed(() => this.disabled() || this.formDisabled());\n\n /** Month granularity (3.29). */\n protected readonly isMonthMode = computed(() => this.granularity() === 'month');\n\n // Computed values\n readonly formattedDate = computed(() => {\n const date = this.selectedDate();\n if (!date) return '';\n // Month mode shows the month: a `DD` token is the 1st.\n const shown = this.isMonthMode() ? new Date(date.getFullYear(), date.getMonth(), 1) : date;\n return this.formatDate(shown, this.format());\n });\n\n /**\n * Text currently shown in the input. Follows the selected date, but the user\n * can type freely; only a complete, valid date is committed to the model.\n */\n readonly inputValue = linkedSignal(() => this.formattedDate());\n\n weekDays = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];\n\n monthNames = [\n 'January',\n 'February',\n 'March',\n 'April',\n 'May',\n 'June',\n 'July',\n 'August',\n 'September',\n 'October',\n 'November',\n 'December',\n ];\n\n /** Month name in the header: `locale` when set, the English names otherwise. */\n readonly currentMonthName = computed(() => {\n const locale = this.locale();\n return locale\n ? new Date(this.currentYear(), this.currentMonth(), 1).toLocaleDateString(locale, { month: 'long' })\n : this.monthNames[this.currentMonth()];\n });\n\n /** Weekday headers in grid order, starting at `firstDayOfWeek`. */\n readonly weekdayLabels = computed(() => {\n const locale = this.locale();\n const first = this.gridStart();\n // 1 Jan 2023 was a Sunday, so day d of that week has getDay() === d.\n const names = locale\n ? Array.from({ length: 7 }, (_, d) =>\n new Date(2023, 0, 1 + d).toLocaleDateString(locale, { weekday: 'short' }).replace(/\\.$/, ''),\n )\n : this.weekDays;\n return Array.from({ length: 7 }, (_, i) => names[(first + i) % 7]);\n });\n\n /** Header title: „July 2026“ (day mode) or the year „2026“ (month mode). */\n protected readonly headerTitle = computed(() =>\n this.isMonthMode() ? String(this.currentYear()) : `${this.currentMonthName()} ${this.currentYear()}`,\n );\n\n /** The twelve months of the shown year (month mode). */\n protected readonly monthCells = computed<MonthCell[]>(() => {\n const year = this.currentYear();\n const locale = this.locale();\n const selected = this.selectedDate();\n const today = new Date();\n return Array.from({ length: 12 }, (_, month) => {\n const first = new Date(year, month, 1);\n return {\n month,\n name: locale ? first.toLocaleDateString(locale, { month: 'long' }) : this.monthNames[month],\n label: first.toLocaleDateString(locale || 'en-US', { month: 'long', year: 'numeric' }),\n selected: !!selected && selected.getFullYear() === year && selected.getMonth() === month,\n current: today.getFullYear() === year && today.getMonth() === month,\n disabled: this.isMonthDisabled(year, month),\n };\n });\n });\n\n /** The month grid's four rows of three. */\n protected readonly monthRows = computed(() => [0, 3, 6, 9].map((i) => this.monthCells().slice(i, i + 3)));\n\n /**\n * The month cell that is the grid's one tab stop (roving `tabindex`): the\n * selected month in the shown year, else the current month, else the first\n * enabled one; `-1` when the whole year is disabled. Keys move it.\n */\n protected readonly monthTabStop = linkedSignal(() => this.defaultMonthTabStop());\n\n /** `firstDayOfWeek` clamped to 0–6. */\n private readonly gridStart = computed(() => {\n const day = Math.trunc(Number(this.firstDayOfWeek()));\n return Number.isFinite(day) ? ((day % 7) + 7) % 7 : 0;\n });\n\n /** id of the helper/error text the input is described by (aria-describedby) */\n readonly describedBy = computed(() => {\n if (this.error() && this.errorMessage()) {\n return `${this.inputId}-error`;\n }\n return this.helperText() ? `${this.inputId}-helper` : null;\n });\n\n /**\n * Computed classes for the datepicker input element\n */\n readonly datepickerClasses = computed(() => {\n const classes = [\n 'lc-datepicker',\n `lc-datepicker--${this.variant()}`,\n `lc-datepicker--${this.size()}`,\n ];\n\n if (this.isDisabled()) {\n classes.push('lc-datepicker--disabled');\n }\n\n if (this.error()) {\n classes.push('lc-datepicker--error');\n }\n\n if (this.readonly()) {\n classes.push('lc-datepicker--readonly');\n }\n\n if (this.isOpen()) {\n classes.push('lc-datepicker--open');\n }\n\n return classes.join(' ');\n });\n\n // Private properties\n private readonly document = inject(DOCUMENT);\n private readonly injector = inject(Injector);\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private onChange: (value: Date | null) => void = () => {};\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private onTouched: () => void = () => {};\n\n // Public methods\n /**\n * Toggle calendar open/closed\n */\n toggle(): void {\n if (this.isDisabled() || this.readonly()) {\n return;\n }\n if (this.isOpen()) {\n this.close();\n } else {\n this.open();\n }\n }\n\n /**\n * Open calendar\n */\n open(): void {\n if (this.isDisabled() || this.readonly() || this.isOpen()) {\n return;\n }\n this.isOpen.set(true);\n\n // Set calendar to selected date's month/year or current\n const date = this.selectedDate();\n if (date) {\n this.showMonthOf(date);\n }\n // Month mode: the grid's tab stop starts on the selected (or current) month again.\n if (this.isMonthMode()) {\n this.monthTabStop.set(this.defaultMonthTabStop());\n }\n\n this.opened.emit();\n }\n\n /**\n * Close calendar. Idempotent: the overlay's `detach` re-enters here after\n * `isOpen` flips, and that second call must not emit `closed` again.\n */\n close(): void {\n if (!this.isOpen()) {\n return;\n }\n // A day button inside the panel may hold focus; it is about to be removed,\n // so hand focus back to the input instead of letting it drop to <body>.\n this.restoreFocusFromPanel();\n this.isOpen.set(false);\n this.closed.emit();\n }\n\n /**\n * Select a date\n */\n selectDate(date: Date): void {\n if (this.isDisabled() || this.readonly() || this.isDateDisabled(date)) {\n return;\n }\n\n this.commitDate(date);\n this.close();\n }\n\n /**\n * Clear selected date\n */\n clear(): void {\n this.selectedDate.set(null);\n this.inputValue.set('');\n this.onChange(null);\n this.dateChange.emit(null);\n }\n\n /**\n * The clear button (3.30, request 047): clears and moves focus to the\n * field, since the button leaves the DOM (focus dropped to `<body>`).\n */\n protected onClearClick(event: Event): void {\n event.stopPropagation();\n this.clear();\n this.datepickerInput()?.nativeElement.focus();\n }\n\n /**\n * Check if a date is disabled\n */\n isDateDisabled(date: Date): boolean {\n // min/max are compared by calendar day: consumers typically pass `new Date()`\n // (which carries the current time) while calendar cells sit at midnight.\n const day = this.startOfDay(date);\n\n const min = this.minDate();\n if (min && day < this.startOfDay(min)) {\n return true;\n }\n\n const max = this.maxDate();\n if (max && day > this.startOfDay(max)) {\n return true;\n }\n\n // Check disabled dates\n if (this.disabledDates().some((d) => this.isSameDate(d, date))) {\n return true;\n }\n\n // Check weekends\n if (this.disableWeekends()) {\n const weekday = date.getDay();\n if (weekday === 0 || weekday === 6) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Check if date is today\n */\n isToday(date: Date): boolean {\n const today = new Date();\n return this.isSameDate(date, today);\n }\n\n /**\n * Accessible name of a day button: the long `Intl` date in `locale`, else\n * `en-US` (3.30.1, 047-f2: contains the visible day number, WCAG 2.5.3),\n * plus `selectedAriaLabel` when selected.\n */\n protected dayAriaLabel(date: Date): string {\n const name = date.toLocaleDateString(this.locale() || 'en-US', {\n weekday: 'long',\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n });\n return this.isSelectedDate(date) ? `${name}, ${this.selectedAriaLabel()}` : name;\n }\n\n /**\n * Check if date is selected\n */\n isSelectedDate(date: Date): boolean {\n const selected = this.selectedDate();\n return selected ? this.isSameDate(date, selected) : false;\n }\n\n /**\n * Generate calendar days for current month\n */\n generateCalendarDays(): Date[] {\n const year = this.currentYear();\n const month = this.currentMonth();\n\n const firstDay = new Date(year, month, 1);\n const lastDay = new Date(year, month + 1, 0);\n\n const days: Date[] = [];\n\n // Add previous month's days, so the first column is `firstDayOfWeek`.\n const leadingDays = (firstDay.getDay() - this.gridStart() + 7) % 7;\n for (let i = leadingDays - 1; i >= 0; i--) {\n const date = new Date(year, month, -i);\n days.push(date);\n }\n\n // Add current month's days\n for (let i = 1; i <= lastDay.getDate(); i++) {\n days.push(new Date(year, month, i));\n }\n\n // Add next month's days to complete the grid\n const remainingDays = 42 - days.length; // 6 weeks * 7 days\n for (let i = 1; i <= remainingDays; i++) {\n days.push(new Date(year, month + 1, i));\n }\n\n return days.slice(0, 42); // Ensure exactly 42 days (6 weeks)\n }\n\n /**\n * Navigate to next month\n */\n nextMonth(): void {\n if (this.currentMonth() === 11) {\n this.currentMonth.set(0);\n this.currentYear.set(this.currentYear() + 1);\n } else {\n this.currentMonth.set(this.currentMonth() + 1);\n }\n }\n\n /**\n * Navigate to previous month\n */\n previousMonth(): void {\n if (this.currentMonth() === 0) {\n this.currentMonth.set(11);\n this.currentYear.set(this.currentYear() - 1);\n } else {\n this.currentMonth.set(this.currentMonth() - 1);\n }\n }\n\n /**\n * Navigate to today\n */\n goToToday(): void {\n this.showMonthOf(new Date());\n }\n\n /** Month mode: show the previous year. */\n protected previousYear(): void {\n this.currentYear.update((year) => year - 1);\n }\n\n /** Month mode: show the next year. */\n protected nextYear(): void {\n this.currentYear.update((year) => year + 1);\n }\n\n /** Month mode's quick action: show the current year. */\n protected showCurrentYear(): void {\n this.currentYear.set(new Date().getFullYear());\n }\n\n /** Month mode: select `month` of the shown year (its 1st), emit, close and focus the field. */\n protected selectMonth(month: number): void {\n const year = this.currentYear();\n if (this.isDisabled() || this.readonly() || this.isMonthDisabled(year, month)) {\n return;\n }\n this.commitDate(new Date(year, month, 1));\n this.close();\n }\n\n /**\n * Keys on a month cell (APG date grid): arrows ±1 month and ±3 (a row),\n * PageUp/PageDown ±1 year (the nearest enabled month of that year),\n * Home/End the first/last enabled month of the year; disabled months are\n * skipped, and with none left focus stays. Enter/Space select, Escape\n * closes. Arrows only move focus.\n */\n protected onMonthKeydown(event: KeyboardEvent, month: number): void {\n const year = this.currentYear();\n const at = year * 12 + month;\n let target: number | null;\n switch (event.key) {\n case 'ArrowLeft':\n target = this.nextEnabledMonth(at, -1);\n break;\n case 'ArrowRight':\n target = this.nextEnabledMonth(at, 1);\n break;\n case 'ArrowUp':\n target = this.nextEnabledMonth(at, -3);\n break;\n case 'ArrowDown':\n target = this.nextEnabledMonth(at, 3);\n break;\n case 'PageUp':\n target = this.nearestEnabledMonth(year - 1, month);\n break;\n case 'PageDown':\n target = this.nearestEnabledMonth(year + 1, month);\n break;\n case 'Home':\n target = this.edgeEnabledMonth(year, 1);\n break;\n case 'End':\n target = this.edgeEnabledMonth(year, -1);\n break;\n case 'Enter':\n case ' ':\n event.preventDefault();\n this.selectMonth(month);\n return;\n case 'Escape':\n event.preventDefault();\n // Only this datepicker should react; keep the key from reaching enclosing overlays.\n event.stopPropagation();\n this.close();\n return;\n default:\n return;\n }\n event.preventDefault();\n if (target !== null) {\n this.moveMonthFocus(target);\n }\n }\n\n /**\n * Handle input change (manual date entry). Partial input is kept as text\n * only; the model changes once the text is a complete, valid, selectable date.\n */\n onInputChange(value: string): void {\n this.inputValue.set(value);\n\n if (value.trim() === '') {\n if (this.selectedDate() !== null) {\n this.clear();\n }\n return;\n }\n\n const date = this.parseDate(value, this.format());\n if (date && !this.isUnavailable(date) && !this.isSameSelection(date)) {\n this.commitDate(date);\n this.showMonthOf(date);\n }\n }\n\n /**\n * Handle keyboard navigation\n */\n onKeyDown(event: KeyboardEvent): void {\n if (this.isDisabled() || this.readonly()) {\n return;\n }\n\n if (\n !this.isOpen() &&\n (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ')\n ) {\n this.open();\n event.preventDefault();\n // Month mode: the keys work in the grid, so focus moves there once it is rendered.\n if (this.isMonthMode()) {\n afterNextRender(() => this.focusMonthCell(this.monthTabStop()), { injector: this.injector });\n }\n return;\n }\n\n if (!this.isOpen()) return;\n\n if (this.isMonthMode()) {\n this.onMonthFieldKeyDown(event);\n return;\n }\n\n // While the text differs from the model the user is mid-edit: arrows must\n // move the caret, not the calendar selection.\n const editing = this.inputValue() !== this.formattedDate();\n const currentDate = this.selectedDate() || new Date();\n let newDate: Date | null = null;\n\n switch (event.key) {\n case 'Escape':\n this.close();\n event.preventDefault();\n // Only this datepicker should react; keep the key from reaching enclosing overlays.\n event.stopPropagation();\n break;\n\n case 'ArrowRight':\n if (editing) break;\n newDate = new Date(currentDate);\n newDate.setDate(currentDate.getDate() + 1);\n event.preventDefault();\n break;\n\n case 'ArrowLeft':\n if (editing) break;\n newDate = new Date(currentDate);\n newDate.setDate(currentDate.getDate() - 1);\n event.preventDefault();\n break;\n\n case 'ArrowDown':\n if (editing) break;\n newDate = new Date(currentDate);\n newDate.setDate(currentDate.getDate() + 7);\n event.preventDefault();\n break;\n\n case 'ArrowUp':\n if (editing) break;\n newDate = new Date(currentDate);\n newDate.setDate(currentDate.getDate() - 7);\n event.preventDefault();\n break;\n\n case 'Enter': {\n const selected = this.selectedDate();\n if (selected) {\n this.selectDate(selected);\n }\n event.preventDefault();\n break;\n }\n }\n\n if (newDate && !this.isDateDisabled(newDate)) {\n this.selectedDate.set(newDate);\n this.showMonthOf(newDate);\n }\n }\n\n /**\n * Handle blur event: mark touched and drop any partial text that never became a date.\n */\n onBlur(): void {\n this.onTouched();\n this.inputValue.set(this.formattedDate());\n }\n\n /**\n * Handle click outside\n */\n onClickOutside(): void {\n this.close();\n }\n\n // ControlValueAccessor implementation\n writeValue(value: DateValue): void {\n let date: Date | null = null;\n if (value instanceof Date) {\n date = isNaN(value.getTime()) ? null : value;\n } else if (typeof value === 'string') {\n date = this.parseDate(value, this.format());\n }\n this.selectedDate.set(date);\n this.inputValue.set(this.formattedDate());\n }\n\n registerOnChange(fn: (value: Date | null) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n }\n\n /**\n * Check if date is in current month\n */\n isCurrentMonth(date: Date): boolean {\n return date.getMonth() === this.currentMonth() && date.getFullYear() === this.currentYear();\n }\n\n // Private helper methods\n\n /** The selected month of the shown year, else the current month, else the first enabled one; `-1` if none. */\n private defaultMonthTabStop(): number {\n const cells = this.monthCells().filter((c) => !c.disabled);\n return (cells.find((c) => c.selected) ?? cells.find((c) => c.current) ?? cells[0])?.month ?? -1;\n }\n\n /**\n * Keys in the field while the month panel is open: ArrowDown moves focus\n * into the grid, Escape closes, Enter closes when a month is selected and\n * shows its text again over half-typed text (3.30, 046-n4, as day mode);\n * the other keys stay with the text (caret, typing „2026-07“).\n */\n private onMonthFieldKeyDown(event: KeyboardEvent): void {\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n this.focusMonthCell(this.monthTabStop());\n break;\n case 'Escape':\n this.close();\n event.preventDefault();\n // Only this datepicker should react; keep the key from reaching enclosing overlays.\n event.stopPropagation();\n break;\n case 'Enter':\n event.preventDefault();\n if (this.selectedDate()) {\n this.inputValue.set(this.formattedDate());\n this.close();\n }\n break;\n }\n }\n\n /**\n * Month mode: a month is disabled when all its days are before `minDate`\n * or after `maxDate` (compared by day), or when `disabledDates` holds one\n * of its days. `disableWeekends` does not apply.\n */\n private isMonthDisabled(year: number, month: number): boolean {\n const min = this.minDate();\n if (min && new Date(year, month + 1, 0).getTime() < this.startOfDay(min)) {\n return true;\n }\n const max = this.maxDate();\n if (max && new Date(year, month, 1).getTime() > this.startOfDay(max)) {\n return true;\n }\n return this.disabledDates().some((d) => d.getFullYear() === year && d.getMonth() === month);\n }\n\n /** A typed date that cannot be committed: its day (day mode) or its month (month mode) is disabled. */\n private isUnavailable(date: Date): boolean {\n return this.isMonthMode() ? this.isMonthDisabled(date.getFullYear(), date.getMonth()) : this.isDateDisabled(date);\n }\n\n /** Whether `date` is the current selection: the same day, or in month mode the same month. */\n private isSameSelection(date: Date): boolean {\n if (!this.isMonthMode()) return this.isSelectedDate(date);\n const selected = this.selectedDate();\n return !!selected && selected.getFullYear() === date.getFullYear() && selected.getMonth() === date.getMonth();\n }\n\n /** Year and month (0–11) of a month index `year * 12 + month`. */\n private monthAt(index: number): { year: number; month: number } {\n return { year: Math.floor(index / 12), month: ((index % 12) + 12) % 12 };\n }\n\n /** The next enabled month from `index` in steps of `step` (up to ten years), or `null`. */\n private nextEnabledMonth(index: number, step: number): number | null {\n for (let i = 1; i * Math.abs(step) <= 120; i++) {\n const { year, month } = this.monthAt(index + step * i);\n if (!this.isMonthDisabled(year, month)) return index + step * i;\n }\n return null;\n }\n\n /** `month` of `year` if enabled, else the enabled month of that year nearest to it, or `null`. */\n private nearestEnabledMonth(year: number, month: number): number | null {\n for (let d = 0; d < 12; d++) {\n for (const m of d === 0 ? [month] : [month - d, month + d]) {\n if (m >= 0 && m < 12 && !this.isMonthDisabled(year, m)) return year * 12 + m;\n }\n }\n return null;\n }\n\n /** The first (`dir` 1) or last (`dir` -1) enabled month of `year`, or `null`. */\n private edgeEnabledMonth(year: number, dir: 1 | -1): number | null {\n for (let i = 0; i < 12; i++) {\n const month = dir === 1 ? i : 11 - i;\n if (!this.isMonthDisabled(year, month)) return year * 12 + month;\n }\n return null;\n }\n\n /** Moves the grid's tab stop and focus to the month `index`; the shown year follows. */\n private moveMonthFocus(index: number): void {\n const { year, month } = this.monthAt(index);\n if (year !== this.currentYear()) {\n this.currentYear.set(year);\n }\n this.monthTabStop.set(month);\n this.focusMonthCell(month);\n }\n\n /** Focuses the month cell `month` (0–11) of the open panel; the cells are kept across years. */\n private focusMonthCell(month: number): void {\n if (month < 0) return;\n this.calendarPanel()\n ?.nativeElement.querySelectorAll<HTMLElement>('.lc-datepicker-month')\n [month]?.focus();\n }\n\n private commitDate(date: Date): void {\n this.selectedDate.set(date);\n this.inputValue.set(this.formatDate(date, this.format()));\n this.onChange(date);\n this.dateChange.emit(date);\n }\n\n private showMonthOf(date: Date): void {\n this.currentMonth.set(date.getMonth());\n this.currentYear.set(date.getFullYear());\n }\n\n private restoreFocusFromPanel(): void {\n const panel = this.calendarPanel()?.nativeElement;\n const active = this.document.activeElement;\n if (panel && active && panel.contains(active)) {\n this.datepickerInput()?.nativeElement.focus();\n }\n }\n\n private startOfDay(date: Date): number {\n return new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();\n }\n\n /**\n * Check if two dates are the same day\n */\n private isSameDate(date1: Date, date2: Date): boolean {\n return (\n date1.getFullYear() === date2.getFullYear() &&\n date1.getMonth() === date2.getMonth() &&\n date1.getDate() === date2.getDate()\n );\n }\n\n private formatDate(date: Date, format: string): string {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n return format.replace('YYYY', String(year)).replace('MM', month).replace('DD', day);\n }\n\n /**\n * Strict parse: the text must match the format's length, carry digits at the\n * YYYY/MM/DD positions and round-trip through formatDate (which rejects\n * things like month 13 or Feb 31 that `new Date` would silently roll over).\n * Returns null for partial or invalid input. Month mode also takes a format\n * without `DD` (`YYYY-MM`) and returns the 1st of the month.\n */\n private parseDate(value: string, format: string): Date | null {\n if (value.length !== format.length) {\n return null;\n }\n\n const monthMode = this.isMonthMode();\n const yearIndex = format.indexOf('YYYY');\n const monthIndex = format.indexOf('MM');\n const dayIndex = format.indexOf('DD');\n if (yearIndex < 0 || monthIndex < 0 || (dayIndex < 0 && !monthMode)) {\n return null;\n }\n\n const yearText = value.substring(yearIndex, yearIndex + 4);\n const monthText = value.substring(monthIndex, monthIndex + 2);\n const dayText = dayIndex < 0 ? '01' : value.substring(dayIndex, dayIndex + 2);\n if (!/^\\d{4}$/.test(yearText) || !/^\\d{2}$/.test(monthText) || !/^\\d{2}$/.test(dayText)) {\n return null;\n }\n\n const date = new Date(Number(yearText), Number(monthText) - 1, Number(dayText));\n if (this.formatDate(date, format) !== value) {\n return null;\n }\n return monthMode ? new Date(date.getFullYear(), date.getMonth(), 1) : date;\n }\n\n protected getInputValue(event: Event): string {\n return (event.target as HTMLInputElement).value;\n }\n}\n","<div class=\"lc-datepicker-wrapper\">\n @if (label()) {\n <label class=\"lc-datepicker__label\" [for]=\"inputId\">{{ label() }}</label>\n }\n <div class=\"lc-datepicker-input-wrapper\">\n <input\n #datepickerInput\n type=\"text\"\n [id]=\"inputId\"\n [class]=\"datepickerClasses()\"\n role=\"combobox\"\n aria-haspopup=\"dialog\"\n autocomplete=\"off\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? inputId + '-calendar' : null\"\n [attr.aria-label]=\"label() ? null : (ariaLabel() || null)\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [readonly]=\"readonly()\"\n [disabled]=\"isDisabled()\"\n [placeholder]=\"placeholder()\"\n [value]=\"inputValue()\"\n (input)=\"onInputChange(getInputValue($event))\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n />\n <div class=\"lc-datepicker-icons\">\n @if (selectedDate() && !isDisabled() && !readonly()) {\n <button\n type=\"button\"\n class=\"lc-datepicker-clear\"\n (click)=\"onClearClick($event)\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\"\n />\n </svg>\n </button>\n }\n <svg\n class=\"lc-datepicker-calendar-icon\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M5.25 12a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H6a.75.75 0 01-.75-.75V12zM6 13.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V14a.75.75 0 00-.75-.75H6zM7.25 12a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H8a.75.75 0 01-.75-.75V12zM8 13.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V14a.75.75 0 00-.75-.75H8zM9.25 10a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H10a.75.75 0 01-.75-.75V10zM10 11.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V12a.75.75 0 00-.75-.75H10zM9.25 14a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H10a.75.75 0 01-.75-.75V14zM12 9.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V10a.75.75 0 00-.75-.75H12zM11.25 12a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H12a.75.75 0 01-.75-.75V12zM12 13.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V14a.75.75 0 00-.75-.75H12zM13.25 10a.75.75 0 01.75-.75h.01a.75.75 0 01.75.75v.01a.75.75 0 01-.75.75H14a.75.75 0 01-.75-.75V10zM14 11.25a.75.75 0 00-.75.75v.01c0 .414.336.75.75.75h.01a.75.75 0 00.75-.75V12a.75.75 0 00-.75-.75H14z\"\n />\n <path\n fill-rule=\"evenodd\"\n d=\"M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </div>\n\n <!-- Calendar Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"datepickerInput\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayViewportMargin]=\"8\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n (backdropClick)=\"onClickOutside()\"\n (detach)=\"close()\"\n >\n <div\n #calendarPanel\n class=\"lc-datepicker-calendar\"\n [class.lc-datepicker-calendar--open]=\"isOpen()\"\n [class.lc-datepicker-calendar--month]=\"isMonthMode()\"\n [id]=\"inputId + '-calendar'\"\n role=\"dialog\"\n [attr.aria-label]=\"isMonthMode() ? monthDialogAriaLabel() : dialogAriaLabel()\"\n >\n <!-- Calendar Header (month mode, 3.29: the year and year buttons) -->\n <div class=\"lc-datepicker-header\">\n <button\n type=\"button\"\n class=\"lc-datepicker-nav-button\"\n (click)=\"isMonthMode() ? previousYear() : previousMonth()\"\n [attr.aria-label]=\"isMonthMode() ? previousYearAriaLabel() : previousMonthAriaLabel()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n fill-rule=\"evenodd\"\n d=\"M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </button>\n \n <div class=\"lc-datepicker-month-year\" aria-live=\"polite\" [attr.id]=\"isMonthMode() ? inputId + '-year' : null\">\n {{ headerTitle() }}\n </div>\n\n <button\n type=\"button\"\n class=\"lc-datepicker-nav-button\"\n (click)=\"isMonthMode() ? nextYear() : nextMonth()\"\n [attr.aria-label]=\"isMonthMode() ? nextYearAriaLabel() : nextMonthAriaLabel()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </button>\n </div>\n\n <!-- Quick Actions -->\n <div class=\"lc-datepicker-quick-actions\">\n <button\n type=\"button\"\n class=\"lc-datepicker-today-button\"\n (click)=\"isMonthMode() ? showCurrentYear() : goToToday()\"\n >\n {{ isMonthMode() ? currentMonthLabel() : todayLabel() }}\n </button>\n </div>\n\n @if (isMonthMode()) {\n <!-- Month grid (3.29): APG grid, one roving tab stop, named by the year title -->\n <div class=\"lc-datepicker-months\" role=\"grid\" [attr.aria-labelledby]=\"inputId + '-year'\">\n @for (row of monthRows(); track $index) {\n <div class=\"lc-datepicker-month-row\" role=\"row\">\n @for (cell of row; track cell.month) {\n <div\n role=\"gridcell\"\n class=\"lc-datepicker-month\"\n [class.lc-datepicker-month--current]=\"cell.current\"\n [class.lc-datepicker-month--selected]=\"cell.selected\"\n [class.lc-datepicker-month--disabled]=\"cell.disabled\"\n [attr.tabindex]=\"cell.month === monthTabStop() ? 0 : -1\"\n [attr.aria-selected]=\"cell.selected ? 'true' : null\"\n [attr.aria-current]=\"cell.current ? 'date' : null\"\n [attr.aria-disabled]=\"cell.disabled ? 'true' : null\"\n [attr.aria-label]=\"cell.label\"\n (click)=\"selectMonth(cell.month)\"\n (keydown)=\"onMonthKeydown($event, cell.month)\"\n >{{ cell.name }}</div>\n }\n </div>\n }\n </div>\n } @else {\n <!-- Weekday Headers -->\n <div class=\"lc-datepicker-weekdays\" aria-hidden=\"true\">\n @for (day of weekdayLabels(); track $index) {\n <div class=\"lc-datepicker-weekday\">{{ day }}</div>\n }\n </div>\n\n <!-- Calendar Days -->\n <div class=\"lc-datepicker-days\">\n @for (date of generateCalendarDays(); track date.getTime()) {\n <button\n type=\"button\"\n class=\"lc-datepicker-day\"\n [class.lc-datepicker-day--other-month]=\"!isCurrentMonth(date)\"\n [class.lc-datepicker-day--today]=\"isToday(date)\"\n [class.lc-datepicker-day--selected]=\"isSelectedDate(date)\"\n [class.lc-datepicker-day--disabled]=\"isDateDisabled(date)\"\n [disabled]=\"isDateDisabled(date)\"\n [attr.aria-current]=\"isToday(date) ? 'date' : null\"\n [attr.aria-label]=\"dayAriaLabel(date)\"\n (click)=\"selectDate(date)\"\n >\n {{ date.getDate() }}\n </button>\n }\n </div>\n }\n </div>\n </ng-template>\n\n <!-- Helper/Error Text -->\n @if (error() && errorMessage()) {\n <div class=\"lc-datepicker__error\" [id]=\"inputId + '-error'\" role=\"alert\">\n {{ errorMessage() }}\n </div>\n } @else if (helperText()) {\n <div class=\"lc-datepicker__helper\" [id]=\"inputId + '-helper'\">\n {{ helperText() }}\n </div>\n }\n</div>\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1892,3 +1892,61 @@ describe('Component pairings of 3.27.2 (request 044)', () => {
|
|
|
1892
1892
|
});
|
|
1893
1893
|
});
|
|
1894
1894
|
});
|
|
1895
|
+
|
|
1896
|
+
/**
|
|
1897
|
+
* Request 047 (3.30, 046-f2, design 047 §5): the selected day carries the
|
|
1898
|
+
* month cell's inset --color-primary-500 ring, since its fill alone is
|
|
1899
|
+
* 2.78:1 on the dark panel (WCAG 1.4.11); the new combobox clear ring sits
|
|
1900
|
+
* on the field fill (--color-surface-2).
|
|
1901
|
+
*/
|
|
1902
|
+
describe('Component pairings of 3.30 (request 047)', () => {
|
|
1903
|
+
const lib = (path: string) => resolve(__dirname, '../lib', path);
|
|
1904
|
+
const sheets = {
|
|
1905
|
+
datepicker: compile(lib('datepicker/datepicker.component.scss')).css,
|
|
1906
|
+
combobox: compile(lib('combobox/combobox.component.scss')).css,
|
|
1907
|
+
};
|
|
1908
|
+
const body = (sheet: keyof typeof sheets, selector: string) => {
|
|
1909
|
+
const css = sheets[sheet];
|
|
1910
|
+
const at = css.indexOf(`\n${selector} {`);
|
|
1911
|
+
expect([selector, at > -1]).toEqual([selector, true]);
|
|
1912
|
+
return css.slice(at, css.indexOf('}', at));
|
|
1913
|
+
};
|
|
1914
|
+
const floor = (n: number) => Math.floor(n * 100) / 100;
|
|
1915
|
+
|
|
1916
|
+
it('AC-2, AC-3: the rules pair these tokens', () => {
|
|
1917
|
+
expect(body('datepicker', '.lc-datepicker-calendar')).toContain('background-color: var(--color-surface)');
|
|
1918
|
+
const selected = body('datepicker', '.lc-datepicker-day.lc-datepicker-day--selected');
|
|
1919
|
+
expect(selected).toContain('box-shadow: inset 0 0 0 2px var(--color-primary-500)');
|
|
1920
|
+
expect(selected).toContain('background-color: var(--color-primary-fill)');
|
|
1921
|
+
expect(selected).toContain('color: var(--color-on-primary)');
|
|
1922
|
+
expect(body('combobox', '.lc-combobox__input-wrapper')).toContain('background-color: var(--color-surface-2)');
|
|
1923
|
+
expect(body('combobox', '.lc-combobox__clear:focus-visible')).toContain('outline: 2px solid var(--color-primary-500)');
|
|
1924
|
+
});
|
|
1925
|
+
|
|
1926
|
+
// [light, dark], floored; design 047 §5 quotes the browser's rounded
|
|
1927
|
+
// values (ring 4.37 / 9.13, clear ring 4.18 / 7.58).
|
|
1928
|
+
const expected = {
|
|
1929
|
+
ringOnPanel: [4.36, 9.12],
|
|
1930
|
+
textOnFill: [6.21, 6.21],
|
|
1931
|
+
textOnHoverFill: [9.13, 9.13],
|
|
1932
|
+
fillOnPanel: [6.21, 2.78],
|
|
1933
|
+
clearRingOnField: [4.17, 7.57],
|
|
1934
|
+
};
|
|
1935
|
+
|
|
1936
|
+
it.each(palettes.map(([name, tokens], i) => [name, tokens, i] as const))('AC-2, AC-3: %s palette: the design 047 §5 ratios', (_palette, tokens, i) => {
|
|
1937
|
+
const c = (name: string) => color(tokens, name);
|
|
1938
|
+
const on = (ink: string, base: string) => floor(ratio(over(c(ink), c(base)), c(base)));
|
|
1939
|
+
const got = {
|
|
1940
|
+
ringOnPanel: on('--color-primary-500', '--color-surface'),
|
|
1941
|
+
textOnFill: on('--color-on-primary', '--color-primary-fill'),
|
|
1942
|
+
textOnHoverFill: on('--color-on-primary', '--color-primary-fill-hover'),
|
|
1943
|
+
fillOnPanel: on('--color-primary-fill', '--color-surface'),
|
|
1944
|
+
clearRingOnField: on('--color-primary-500', '--color-surface-2'),
|
|
1945
|
+
};
|
|
1946
|
+
expect(got).toEqual(Object.fromEntries(Object.entries(expected).map(([key, pair]) => [key, pair[i]])));
|
|
1947
|
+
// The state is carried by the ring in both themes (the dark fill is not).
|
|
1948
|
+
expect(got.ringOnPanel).toBeGreaterThanOrEqual(3);
|
|
1949
|
+
expect(got.clearRingOnField).toBeGreaterThanOrEqual(3);
|
|
1950
|
+
expect(Math.min(got.textOnFill, got.textOnHoverFill)).toBeGreaterThanOrEqual(4.5);
|
|
1951
|
+
});
|
|
1952
|
+
});
|
|
@@ -148,6 +148,15 @@ export declare class ComboboxComponent implements ControlValueAccessor {
|
|
|
148
148
|
*/
|
|
149
149
|
clear(): void;
|
|
150
150
|
protected onClearClick(): void;
|
|
151
|
+
/** Whether a pointer event on the frame hit the input or a button in it (chip ×, clear). */
|
|
152
|
+
private hitsFrameControl;
|
|
153
|
+
/**
|
|
154
|
+
* 3.30 (request 047, regeln row 6): a press on the frame beside the input
|
|
155
|
+
* and its buttons keeps focus where it is (no blur, so the list stays open).
|
|
156
|
+
*/
|
|
157
|
+
protected onFrameMousedown(event: MouseEvent): void;
|
|
158
|
+
/** A click on the frame beside the input and its buttons focuses the input. */
|
|
159
|
+
protected onFrameClick(event: MouseEvent): void;
|
|
151
160
|
protected onInputChange(event: Event): void;
|
|
152
161
|
protected onInputFocus(): void;
|
|
153
162
|
protected onInputBlur(): void;
|
|
@@ -80,9 +80,17 @@ export declare class DatepickerComponent implements ControlValueAccessor {
|
|
|
80
80
|
*/
|
|
81
81
|
readonly errorMessage: import("@angular/core").InputSignal<string>;
|
|
82
82
|
/**
|
|
83
|
-
* ARIA label for accessibility
|
|
83
|
+
* ARIA label for accessibility. Ignored while `label` is set.
|
|
84
|
+
* @default undefined
|
|
84
85
|
*/
|
|
85
86
|
readonly ariaLabel: import("@angular/core").InputSignal<string | undefined>;
|
|
87
|
+
/**
|
|
88
|
+
* Visible label above the field (3.30, regeln row 7): a `<label for>` in
|
|
89
|
+
* day and month mode that names the field, so `ariaLabel` is not used
|
|
90
|
+
* while it is set. Empty: no label element, as before.
|
|
91
|
+
* @default ''
|
|
92
|
+
*/
|
|
93
|
+
readonly label: import("@angular/core").InputSignal<string>;
|
|
86
94
|
/**
|
|
87
95
|
* Date format string (e.g., 'YYYY-MM-DD', 'MM/DD/YYYY')
|
|
88
96
|
*/
|
|
@@ -103,7 +111,12 @@ export declare class DatepickerComponent implements ControlValueAccessor {
|
|
|
103
111
|
* Whether to disable weekends
|
|
104
112
|
*/
|
|
105
113
|
readonly disableWeekends: import("@angular/core").InputSignal<boolean>;
|
|
106
|
-
/**
|
|
114
|
+
/**
|
|
115
|
+
* BCP 47 locale for month and weekday names and the day buttons' accessible
|
|
116
|
+
* names (e.g. `'de-DE'`). Empty keeps the built-in English names; the days
|
|
117
|
+
* are then named in `en-US` ("Wednesday, July 1, 2026").
|
|
118
|
+
* @default ''
|
|
119
|
+
*/
|
|
107
120
|
readonly locale: import("@angular/core").InputSignal<string>;
|
|
108
121
|
/** First column of the grid: 0 Sunday (default) … 6 Saturday — 1 for Monday. */
|
|
109
122
|
readonly firstDayOfWeek: import("@angular/core").InputSignal<number>;
|
|
@@ -234,6 +247,11 @@ export declare class DatepickerComponent implements ControlValueAccessor {
|
|
|
234
247
|
* Clear selected date
|
|
235
248
|
*/
|
|
236
249
|
clear(): void;
|
|
250
|
+
/**
|
|
251
|
+
* The clear button (3.30, request 047): clears and moves focus to the
|
|
252
|
+
* field, since the button leaves the DOM (focus dropped to `<body>`).
|
|
253
|
+
*/
|
|
254
|
+
protected onClearClick(event: Event): void;
|
|
237
255
|
/**
|
|
238
256
|
* Check if a date is disabled
|
|
239
257
|
*/
|
|
@@ -242,7 +260,11 @@ export declare class DatepickerComponent implements ControlValueAccessor {
|
|
|
242
260
|
* Check if date is today
|
|
243
261
|
*/
|
|
244
262
|
isToday(date: Date): boolean;
|
|
245
|
-
/**
|
|
263
|
+
/**
|
|
264
|
+
* Accessible name of a day button: the long `Intl` date in `locale`, else
|
|
265
|
+
* `en-US` (3.30.1, 047-f2: contains the visible day number, WCAG 2.5.3),
|
|
266
|
+
* plus `selectedAriaLabel` when selected.
|
|
267
|
+
*/
|
|
246
268
|
protected dayAriaLabel(date: Date): string;
|
|
247
269
|
/**
|
|
248
270
|
* Check if date is selected
|
|
@@ -309,7 +331,8 @@ export declare class DatepickerComponent implements ControlValueAccessor {
|
|
|
309
331
|
private defaultMonthTabStop;
|
|
310
332
|
/**
|
|
311
333
|
* Keys in the field while the month panel is open: ArrowDown moves focus
|
|
312
|
-
* into the grid, Escape closes, Enter closes when a month is selected
|
|
334
|
+
* into the grid, Escape closes, Enter closes when a month is selected and
|
|
335
|
+
* shows its text again over half-typed text (3.30, 046-n4, as day mode);
|
|
313
336
|
* the other keys stay with the text (caret, typing „2026-07“).
|
|
314
337
|
*/
|
|
315
338
|
private onMonthFieldKeyDown;
|
|
@@ -405,6 +428,11 @@ export declare class DatepickerComponent implements ControlValueAccessor {
|
|
|
405
428
|
"required": false;
|
|
406
429
|
"isSignal": true;
|
|
407
430
|
};
|
|
431
|
+
"label": {
|
|
432
|
+
"alias": "label";
|
|
433
|
+
"required": false;
|
|
434
|
+
"isSignal": true;
|
|
435
|
+
};
|
|
408
436
|
"format": {
|
|
409
437
|
"alias": "format";
|
|
410
438
|
"required": false;
|