mn-angular-lib 1.0.116 → 1.0.117
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.
|
@@ -2938,10 +2938,12 @@ const ARROWS_ZONE_WIDTH = 88;
|
|
|
2938
2938
|
* the gap beside it.
|
|
2939
2939
|
*/
|
|
2940
2940
|
const CONTROLS_ZONE_WIDTH = 150;
|
|
2941
|
-
/**
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2941
|
+
/**
|
|
2942
|
+
* Everything on the controls row that isn't a day tile. The month is a full-width
|
|
2943
|
+
* header on its own line now, so it no longer competes with the days for room —
|
|
2944
|
+
* which is why more of them fit at a given width than they used to.
|
|
2945
|
+
*/
|
|
2946
|
+
const RESERVED_WIDTH = ARROWS_ZONE_WIDTH + CONTROLS_ZONE_WIDTH;
|
|
2945
2947
|
/** Below this the strip can't hold even {@link MIN_TILE_COUNT} days. */
|
|
2946
2948
|
const COMPACT_MAX_WIDTH = MIN_TILE_COUNT * TILE_SLOT_WIDTH + RESERVED_WIDTH;
|
|
2947
2949
|
/** Assumed width before the first measurement (and during server-side rendering). */
|
|
@@ -2951,7 +2953,7 @@ let instanceCounter$1 = 0;
|
|
|
2951
2953
|
/**
|
|
2952
2954
|
* Reusable, responsive date selector bar.
|
|
2953
2955
|
*
|
|
2954
|
-
* Renders a "Today" button, a month
|
|
2956
|
+
* Renders a "Today" button, a month header, previous/next arrows and a strip of
|
|
2955
2957
|
* day tiles. Selecting a tile or pressing "Today" emits the chosen day via
|
|
2956
2958
|
* {@link dateSelected}. The arrows only shift the visible days and never emit.
|
|
2957
2959
|
*
|
|
@@ -3106,31 +3108,32 @@ class MnDateSelectorBar {
|
|
|
3106
3108
|
return tiles;
|
|
3107
3109
|
}, ...(ngDevMode ? [{ debugName: "dayTiles" }] : []));
|
|
3108
3110
|
/**
|
|
3109
|
-
*
|
|
3110
|
-
*
|
|
3111
|
-
* both years when it straddles
|
|
3111
|
+
* The month the strip is currently in, spelled out for the header that titles
|
|
3112
|
+
* the bar — so the days below are never just loose numbers. Reads as a range
|
|
3113
|
+
* when the strip straddles two months, and carries both years when it straddles
|
|
3114
|
+
* two of those.
|
|
3112
3115
|
*/
|
|
3113
3116
|
monthCaption = computed(() => {
|
|
3114
3117
|
const locale = this.effectiveLocale();
|
|
3115
3118
|
const tiles = this.dayTiles();
|
|
3116
|
-
// With no strip to describe — the compact layout — the
|
|
3119
|
+
// With no strip to describe — the compact layout — the header names the
|
|
3117
3120
|
// month the selection sits in, so the bar is never unlabelled.
|
|
3118
3121
|
if (!tiles.length) {
|
|
3119
|
-
return this.selectedDate().toLocaleDateString(locale, { month: '
|
|
3122
|
+
return this.selectedDate().toLocaleDateString(locale, { month: 'long', year: 'numeric' });
|
|
3120
3123
|
}
|
|
3121
3124
|
const first = tiles[0].date;
|
|
3122
3125
|
const last = tiles[tiles.length - 1].date;
|
|
3123
3126
|
if (first.getFullYear() !== last.getFullYear()) {
|
|
3124
|
-
const from = first.toLocaleDateString(locale, { month: '
|
|
3125
|
-
const to = last.toLocaleDateString(locale, { month: '
|
|
3127
|
+
const from = first.toLocaleDateString(locale, { month: 'long', year: 'numeric' });
|
|
3128
|
+
const to = last.toLocaleDateString(locale, { month: 'long', year: 'numeric' });
|
|
3126
3129
|
return `${from} – ${to}`;
|
|
3127
3130
|
}
|
|
3128
3131
|
if (first.getMonth() !== last.getMonth()) {
|
|
3129
|
-
const from = first.toLocaleDateString(locale, { month: '
|
|
3130
|
-
const to = last.toLocaleDateString(locale, { month: '
|
|
3132
|
+
const from = first.toLocaleDateString(locale, { month: 'long' });
|
|
3133
|
+
const to = last.toLocaleDateString(locale, { month: 'long', year: 'numeric' });
|
|
3131
3134
|
return `${from} – ${to}`;
|
|
3132
3135
|
}
|
|
3133
|
-
return first.toLocaleDateString(locale, { month: '
|
|
3136
|
+
return first.toLocaleDateString(locale, { month: 'long', year: 'numeric' });
|
|
3134
3137
|
}, ...(ngDevMode ? [{ debugName: "monthCaption" }] : []));
|
|
3135
3138
|
/** The selected date formatted as YYYY-MM-DD for the date-picker input. */
|
|
3136
3139
|
selectedDateString = computed(() => {
|
|
@@ -3331,7 +3334,7 @@ class MnDateSelectorBar {
|
|
|
3331
3334
|
a.getDate() === b.getDate());
|
|
3332
3335
|
}
|
|
3333
3336
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnDateSelectorBar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3334
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: MnDateSelectorBar, isStandalone: true, selector: "mn-date-selector-bar", inputs: { selectedDate: { classPropertyName: "selectedDate", publicName: "selectedDate", isSignal: true, isRequired: false, transformFunction: null }, todayLabel: { classPropertyName: "todayLabel", publicName: "todayLabel", isSignal: true, isRequired: false, transformFunction: null }, pickDateLabel: { classPropertyName: "pickDateLabel", publicName: "pickDateLabel", isSignal: true, isRequired: false, transformFunction: null }, previousLabel: { classPropertyName: "previousLabel", publicName: "previousLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, dayStripLabel: { classPropertyName: "dayStripLabel", publicName: "dayStripLabel", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateSelected: "dateSelected" }, host: { classAttribute: "block" }, viewQueries: [{ propertyName: "tileButtons", predicate: ["tileButton"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Date selector bar. Layout is driven by the bar's own measured width, so it\n rearranges for the space the bar was given, not for the viewport.
|
|
3337
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: MnDateSelectorBar, isStandalone: true, selector: "mn-date-selector-bar", inputs: { selectedDate: { classPropertyName: "selectedDate", publicName: "selectedDate", isSignal: true, isRequired: false, transformFunction: null }, todayLabel: { classPropertyName: "todayLabel", publicName: "todayLabel", isSignal: true, isRequired: false, transformFunction: null }, pickDateLabel: { classPropertyName: "pickDateLabel", publicName: "pickDateLabel", isSignal: true, isRequired: false, transformFunction: null }, previousLabel: { classPropertyName: "previousLabel", publicName: "previousLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, dayStripLabel: { classPropertyName: "dayStripLabel", publicName: "dayStripLabel", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateSelected: "dateSelected" }, host: { classAttribute: "block" }, viewQueries: [{ propertyName: "tileButtons", predicate: ["tileButton"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Date selector bar. Layout is driven by the bar's own measured width, so it\n rearranges for the space the bar was given, not for the viewport. The strip\n never stacks: as room runs out it shows fewer days, then hands over to the\n picker. Nothing here is boxed \u2014 spacing does the grouping, not borders. -->\n<div class=\"flex flex-col gap-2 px-4 py-3\">\n\n <!-- Month header. Titles the whole bar so the day numbers below are never loose:\n it names the month the strip is in (or, when compact, the month the\n selection sits in), reading as a range where the strip crosses a boundary.\n On its own line it has room to be spelled out, and no longer steals width\n from the days the way the old inline caption did. -->\n <div aria-hidden=\"true\"\n class=\"text-center text-sm font-semibold tracking-wide whitespace-nowrap opacity-80\">\n {{ monthCaption() }}\n </div>\n\n <!-- Controls row. Today and the strip travel together as one centred cluster, so\n Today sits right beside the days instead of stranded against the far edge;\n the gap between them matches the strip's own spacing. When the strip gives\n way to the picker, the picker fills the row and Today anchors its left. -->\n <div class=\"flex items-center justify-center gap-3\">\n\n <!-- Today: returns the strip and the selection to the current day. Outlined\n rather than filled, so the one filled-primary element on the bar is the\n selected day \u2014 Today shares the primary accent without competing with it. -->\n <button (click)=\"goToToday()\"\n [data]=\"{ variant: 'outline', color: 'primary', size: 'md' }\"\n class=\"shrink-0\"\n mnButton\n type=\"button\">\n {{ todayLabel() }}\n </button>\n\n <!-- Too narrow for a usable strip, so the picker takes its place beside Today.\n Every date stays reachable on a phone, in one tap rather than by paging;\n the month header above keeps the compact bar labelled like the wide one. -->\n @if (!showDayStrip()) {\n <mn-lib-datetime (ngModelChange)=\"onDateModelChanged($event)\"\n [ngModel]=\"selectedDateString()\"\n [props]=\"pickerProps()\"\n class=\"block min-w-0 flex-1\"></mn-lib-datetime>\n }\n\n <!-- Arrows and days, sized to their own content so the row can centre them\n together with Today as a single cluster \u2014 rather than the days drifting to\n the middle of the leftover space, away from the button. -->\n @if (showDayStrip()) {\n <div [attr.aria-label]=\"dayStripLabel()\"\n class=\"flex min-w-0 items-center gap-3\"\n role=\"group\">\n <button (click)=\"navigatePrevious()\"\n [attr.aria-label]=\"previousLabel()\"\n [data]=\"{ variant: 'text', size: 'md', color: 'gray' }\"\n class=\"shrink-0\"\n mnButton\n type=\"button\">\n <svg [size]=\"18\" lucideChevronLeft></svg>\n </button>\n\n <!-- Days read on one line so each sits at the same height as the buttons\n either side of it. Roving tabindex: one day is in the tab order, the\n arrow keys move between the rest and page the strip at either end. -->\n <div class=\"flex min-w-0 gap-1\">\n @for (tile of dayTiles(); track tile.date.getTime(); let i = $index) {\n <!-- Selected is the filled pill; today is called out by its number\n alone, tinted primary \u2014 no box, in keeping with a bar that groups\n by spacing rather than borders. When today is also the selected\n day the fill takes over, since there is nothing left to tell apart.\n A month break is marked by extra breathing room rather than a rule,\n so the run of days stays unbroken; the header names both months. -->\n <button #tileButton\n (click)=\"selectDate(tile.date)\"\n (focus)=\"onTileFocus(i)\"\n (keydown)=\"onTileKeydown($event, i)\"\n [attr.aria-current]=\"tile.isToday ? 'date' : null\"\n [attr.aria-label]=\"tile.accessibleLabel\"\n [attr.aria-pressed]=\"tile.isSelected\"\n [attr.tabindex]=\"isTabbable(i) ? 0 : -1\"\n [class.bg-primary]=\"tile.isSelected\"\n [class.hover:bg-base-200]=\"!tile.isSelected\"\n [class.ml-3]=\"tile.startsNewMonth\"\n [class.text-primary-content]=\"tile.isSelected\"\n class=\"flex min-w-16 shrink-0 cursor-pointer items-center justify-center gap-1.5 rounded-lg px-3 py-2 text-sm transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary motion-reduce:transition-none\"\n type=\"button\">\n <span [class.opacity-60]=\"!tile.isSelected\"\n [class.opacity-90]=\"tile.isSelected\"\n aria-hidden=\"true\"\n class=\"text-xs font-medium uppercase\">\n {{ tile.dayName }}\n </span>\n <!-- Today's number carries the primary tint, unless the tile is\n filled \u2014 then it wears the fill's own text colour instead. -->\n <span [class.text-primary]=\"tile.isToday && !tile.isSelected\"\n aria-hidden=\"true\"\n class=\"font-bold tabular-nums\">{{ tile.dayNumber }}</span>\n </button>\n }\n </div>\n\n <button (click)=\"navigateNext()\"\n [attr.aria-label]=\"nextLabel()\"\n [data]=\"{ variant: 'text', size: 'md', color: 'gray' }\"\n class=\"shrink-0\"\n mnButton\n type=\"button\">\n <svg [size]=\"18\" lucideChevronRight></svg>\n </button>\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MnButton, selector: "button[mnButton], a[mnButton]", inputs: ["data"] }, { kind: "component", type: MnDatetime, selector: "mn-lib-datetime", inputs: ["props"] }, { kind: "component", type: LucideChevronLeft, selector: "svg[lucideChevronLeft]" }, { kind: "component", type: LucideChevronRight, selector: "svg[lucideChevronRight]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3335
3338
|
}
|
|
3336
3339
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnDateSelectorBar, decorators: [{
|
|
3337
3340
|
type: Component,
|
|
@@ -3342,7 +3345,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
3342
3345
|
MnDatetime,
|
|
3343
3346
|
LucideChevronLeft,
|
|
3344
3347
|
LucideChevronRight,
|
|
3345
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'block' }, template: "<!-- Date selector bar. Layout is driven by the bar's own measured width, so it\n rearranges for the space the bar was given, not for the viewport.
|
|
3348
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'block' }, template: "<!-- Date selector bar. Layout is driven by the bar's own measured width, so it\n rearranges for the space the bar was given, not for the viewport. The strip\n never stacks: as room runs out it shows fewer days, then hands over to the\n picker. Nothing here is boxed \u2014 spacing does the grouping, not borders. -->\n<div class=\"flex flex-col gap-2 px-4 py-3\">\n\n <!-- Month header. Titles the whole bar so the day numbers below are never loose:\n it names the month the strip is in (or, when compact, the month the\n selection sits in), reading as a range where the strip crosses a boundary.\n On its own line it has room to be spelled out, and no longer steals width\n from the days the way the old inline caption did. -->\n <div aria-hidden=\"true\"\n class=\"text-center text-sm font-semibold tracking-wide whitespace-nowrap opacity-80\">\n {{ monthCaption() }}\n </div>\n\n <!-- Controls row. Today and the strip travel together as one centred cluster, so\n Today sits right beside the days instead of stranded against the far edge;\n the gap between them matches the strip's own spacing. When the strip gives\n way to the picker, the picker fills the row and Today anchors its left. -->\n <div class=\"flex items-center justify-center gap-3\">\n\n <!-- Today: returns the strip and the selection to the current day. Outlined\n rather than filled, so the one filled-primary element on the bar is the\n selected day \u2014 Today shares the primary accent without competing with it. -->\n <button (click)=\"goToToday()\"\n [data]=\"{ variant: 'outline', color: 'primary', size: 'md' }\"\n class=\"shrink-0\"\n mnButton\n type=\"button\">\n {{ todayLabel() }}\n </button>\n\n <!-- Too narrow for a usable strip, so the picker takes its place beside Today.\n Every date stays reachable on a phone, in one tap rather than by paging;\n the month header above keeps the compact bar labelled like the wide one. -->\n @if (!showDayStrip()) {\n <mn-lib-datetime (ngModelChange)=\"onDateModelChanged($event)\"\n [ngModel]=\"selectedDateString()\"\n [props]=\"pickerProps()\"\n class=\"block min-w-0 flex-1\"></mn-lib-datetime>\n }\n\n <!-- Arrows and days, sized to their own content so the row can centre them\n together with Today as a single cluster \u2014 rather than the days drifting to\n the middle of the leftover space, away from the button. -->\n @if (showDayStrip()) {\n <div [attr.aria-label]=\"dayStripLabel()\"\n class=\"flex min-w-0 items-center gap-3\"\n role=\"group\">\n <button (click)=\"navigatePrevious()\"\n [attr.aria-label]=\"previousLabel()\"\n [data]=\"{ variant: 'text', size: 'md', color: 'gray' }\"\n class=\"shrink-0\"\n mnButton\n type=\"button\">\n <svg [size]=\"18\" lucideChevronLeft></svg>\n </button>\n\n <!-- Days read on one line so each sits at the same height as the buttons\n either side of it. Roving tabindex: one day is in the tab order, the\n arrow keys move between the rest and page the strip at either end. -->\n <div class=\"flex min-w-0 gap-1\">\n @for (tile of dayTiles(); track tile.date.getTime(); let i = $index) {\n <!-- Selected is the filled pill; today is called out by its number\n alone, tinted primary \u2014 no box, in keeping with a bar that groups\n by spacing rather than borders. When today is also the selected\n day the fill takes over, since there is nothing left to tell apart.\n A month break is marked by extra breathing room rather than a rule,\n so the run of days stays unbroken; the header names both months. -->\n <button #tileButton\n (click)=\"selectDate(tile.date)\"\n (focus)=\"onTileFocus(i)\"\n (keydown)=\"onTileKeydown($event, i)\"\n [attr.aria-current]=\"tile.isToday ? 'date' : null\"\n [attr.aria-label]=\"tile.accessibleLabel\"\n [attr.aria-pressed]=\"tile.isSelected\"\n [attr.tabindex]=\"isTabbable(i) ? 0 : -1\"\n [class.bg-primary]=\"tile.isSelected\"\n [class.hover:bg-base-200]=\"!tile.isSelected\"\n [class.ml-3]=\"tile.startsNewMonth\"\n [class.text-primary-content]=\"tile.isSelected\"\n class=\"flex min-w-16 shrink-0 cursor-pointer items-center justify-center gap-1.5 rounded-lg px-3 py-2 text-sm transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary motion-reduce:transition-none\"\n type=\"button\">\n <span [class.opacity-60]=\"!tile.isSelected\"\n [class.opacity-90]=\"tile.isSelected\"\n aria-hidden=\"true\"\n class=\"text-xs font-medium uppercase\">\n {{ tile.dayName }}\n </span>\n <!-- Today's number carries the primary tint, unless the tile is\n filled \u2014 then it wears the fill's own text colour instead. -->\n <span [class.text-primary]=\"tile.isToday && !tile.isSelected\"\n aria-hidden=\"true\"\n class=\"font-bold tabular-nums\">{{ tile.dayNumber }}</span>\n </button>\n }\n </div>\n\n <button (click)=\"navigateNext()\"\n [attr.aria-label]=\"nextLabel()\"\n [data]=\"{ variant: 'text', size: 'md', color: 'gray' }\"\n class=\"shrink-0\"\n mnButton\n type=\"button\">\n <svg [size]=\"18\" lucideChevronRight></svg>\n </button>\n </div>\n }\n </div>\n</div>\n" }]
|
|
3346
3349
|
}], propDecorators: { selectedDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedDate", required: false }] }], todayLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "todayLabel", required: false }] }], pickDateLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pickDateLabel", required: false }] }], previousLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousLabel", required: false }] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], dayStripLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dayStripLabel", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], dateSelected: [{ type: i0.Output, args: ["dateSelected"] }], tileButtons: [{ type: i0.ViewChildren, args: ['tileButton', { isSignal: true }] }] } });
|
|
3347
3350
|
|
|
3348
3351
|
const mnMultiSelectVariants = tv({
|