@xui/date-range-picker 2.0.0-alpha.16 → 2.0.0-alpha.17

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/README.md CHANGED
@@ -127,7 +127,7 @@ The full token reference, rendered in both themes, is the **Design tokens** page
127
127
 
128
128
  **Date & time** — [`@xui/date-input`](https://www.npmjs.com/package/@xui/date-input) · [`@xui/date-picker`](https://www.npmjs.com/package/@xui/date-picker) · [`@xui/date-range-input`](https://www.npmjs.com/package/@xui/date-range-input) · [`@xui/date-range-picker`](https://www.npmjs.com/package/@xui/date-range-picker) · [`@xui/time-picker`](https://www.npmjs.com/package/@xui/time-picker) · [`@xui/timezone-select`](https://www.npmjs.com/package/@xui/timezone-select)
129
129
 
130
- **Data display** — [`@xui/avatar`](https://www.npmjs.com/package/@xui/avatar) · [`@xui/badge`](https://www.npmjs.com/package/@xui/badge) · [`@xui/card`](https://www.npmjs.com/package/@xui/card) · [`@xui/card-list`](https://www.npmjs.com/package/@xui/card-list) · [`@xui/carousel`](https://www.npmjs.com/package/@xui/carousel) · [`@xui/data-table`](https://www.npmjs.com/package/@xui/data-table) · [`@xui/descriptions`](https://www.npmjs.com/package/@xui/descriptions) · [`@xui/entity-title`](https://www.npmjs.com/package/@xui/entity-title) · [`@xui/kbd`](https://www.npmjs.com/package/@xui/kbd) · [`@xui/statistic`](https://www.npmjs.com/package/@xui/statistic) · [`@xui/status`](https://www.npmjs.com/package/@xui/status) · [`@xui/table`](https://www.npmjs.com/package/@xui/table) · [`@xui/tag`](https://www.npmjs.com/package/@xui/tag) · [`@xui/timeline`](https://www.npmjs.com/package/@xui/timeline) · [`@xui/tree`](https://www.npmjs.com/package/@xui/tree)
130
+ **Data display** — [`@xui/avatar`](https://www.npmjs.com/package/@xui/avatar) · [`@xui/card`](https://www.npmjs.com/package/@xui/card) · [`@xui/card-list`](https://www.npmjs.com/package/@xui/card-list) · [`@xui/carousel`](https://www.npmjs.com/package/@xui/carousel) · [`@xui/data-table`](https://www.npmjs.com/package/@xui/data-table) · [`@xui/descriptions`](https://www.npmjs.com/package/@xui/descriptions) · [`@xui/entity-title`](https://www.npmjs.com/package/@xui/entity-title) · [`@xui/kbd`](https://www.npmjs.com/package/@xui/kbd) · [`@xui/statistic`](https://www.npmjs.com/package/@xui/statistic) · [`@xui/status`](https://www.npmjs.com/package/@xui/status) · [`@xui/table`](https://www.npmjs.com/package/@xui/table) · [`@xui/tag`](https://www.npmjs.com/package/@xui/tag) · [`@xui/timeline`](https://www.npmjs.com/package/@xui/timeline) · [`@xui/tree`](https://www.npmjs.com/package/@xui/tree)
131
131
 
132
132
  **Navigation** — [`@xui/breadcrumb`](https://www.npmjs.com/package/@xui/breadcrumb) · [`@xui/menubar`](https://www.npmjs.com/package/@xui/menubar) · [`@xui/navbar`](https://www.npmjs.com/package/@xui/navbar) · [`@xui/navigation-menu`](https://www.npmjs.com/package/@xui/navigation-menu) · [`@xui/pagination`](https://www.npmjs.com/package/@xui/pagination) · [`@xui/panel-stack`](https://www.npmjs.com/package/@xui/panel-stack) · [`@xui/steps`](https://www.npmjs.com/package/@xui/steps) · [`@xui/tabs`](https://www.npmjs.com/package/@xui/tabs)
133
133
 
@@ -87,9 +87,41 @@ class XuiDateRangePicker {
87
87
  return (!this.adapter.isBefore(date, this.adapter.startOfDay(lo)) &&
88
88
  !this.adapter.isAfter(date, this.adapter.startOfDay(hi)));
89
89
  }
90
+ /**
91
+ * The band behind the days inside the range, endpoints included.
92
+ *
93
+ * Its ends are rounded to the day circle's own radius, so the band finishes on the same
94
+ * silhouette the circle draws. Squaring them off left a tinted corner poking out past the curve
95
+ * at each end — the band read as a box drawn around the selection rather than a line joining it.
96
+ */
90
97
  cellClass(day) {
91
- // A continuous highlight strip behind the days that fall inside the range.
92
- return xui('p-0 text-center', this.inRange(day.date) && !this.isEndpoint(day.date) && 'bg-primary/10');
98
+ const side = this.endpointSide(day.date);
99
+ return xui('p-0 text-center', side !== null || (this.spansDays() && this.inRange(day.date)) ? 'bg-primary/10' : '', side === 'start' && 'rounded-s-full', side === 'end' && 'rounded-e-full');
100
+ }
101
+ /** The range's two ends as `[earlier, later]`, or null while it is still incomplete. */
102
+ bounds() {
103
+ const { start } = this.value();
104
+ const end = this.effectiveEnd();
105
+ if (start == null || end == null) {
106
+ return null;
107
+ }
108
+ return this.adapter.isAfter(start, end) ? [end, start] : [start, end];
109
+ }
110
+ /** Whether the range covers more than a single day — a one-day range has nothing to join up. */
111
+ spansDays() {
112
+ const bounds = this.bounds();
113
+ return bounds != null && !this.adapter.isSameDay(bounds[0], bounds[1]);
114
+ }
115
+ /** Which end of the range a day sits at, once the range covers more than one day. */
116
+ endpointSide(date) {
117
+ const bounds = this.bounds();
118
+ if (!bounds || !this.spansDays()) {
119
+ return null;
120
+ }
121
+ if (this.adapter.isSameDay(date, bounds[0])) {
122
+ return 'start';
123
+ }
124
+ return this.adapter.isSameDay(date, bounds[1]) ? 'end' : null;
93
125
  }
94
126
  dayClass(day) {
95
127
  return xui('flex size-8 items-center justify-center rounded-full text-sm transition-colors', day.inCurrentMonth ? 'text-foreground' : 'text-foreground-subtle', !day.disabled && 'hover:bg-surface-inset cursor-pointer', day.disabled && 'cursor-not-allowed opacity-40', day.isToday && !this.isEndpoint(day.date) && 'ring-border-strong ring-1', this.isEndpoint(day.date) && 'bg-primary text-primary-foreground hover:bg-primary');
@@ -165,7 +197,10 @@ class XuiDateRangePicker {
165
197
  }
166
198
  </div>
167
199
 
168
- <table role="grid" class="border-collapse">
200
+ <!-- Separated, with the spacing taken back out: the collapsed model has browsers ignore
201
+ border-radius on a cell, which is what rounds the ends of the range band. The zero
202
+ spacing keeps the grid laid out exactly as the collapsed model did. -->
203
+ <table role="grid" class="border-separate border-spacing-0">
169
204
  <thead>
170
205
  <tr>
171
206
  @for (label of weekdays(); track $index) {
@@ -177,18 +212,25 @@ class XuiDateRangePicker {
177
212
  @for (week of grids()[offset]; track $index) {
178
213
  <tr>
179
214
  @for (day of week; track $index) {
180
- <!-- Selection belongs on the gridcell, not the button. -->
181
- <td [class]="cellClass(day)" [attr.aria-selected]="isEndpoint(day.date)">
182
- <button
183
- type="button"
184
- [class]="dayClass(day)"
185
- [disabled]="day.disabled || isDisabled()"
186
- (click)="onClick(day.date)"
187
- (mouseenter)="hover.set(day.date)"
188
- >
189
- {{ day.label }}
190
- </button>
191
- </td>
215
+ <!-- A day belonging to a neighbouring month is left blank: with the months
216
+ side by side it is already on screen in its own grid, and drawing it twice
217
+ gave a selected endpoint two circles. -->
218
+ @if (!day.inCurrentMonth) {
219
+ <td class="p-0"></td>
220
+ } @else {
221
+ <!-- Selection belongs on the gridcell, not the button. -->
222
+ <td [class]="cellClass(day)" [attr.aria-selected]="isEndpoint(day.date)">
223
+ <button
224
+ type="button"
225
+ [class]="dayClass(day)"
226
+ [disabled]="day.disabled || isDisabled()"
227
+ (click)="onClick(day.date)"
228
+ (mouseenter)="hover.set(day.date)"
229
+ >
230
+ {{ day.label }}
231
+ </button>
232
+ </td>
233
+ }
192
234
  }
193
235
  </tr>
194
236
  }
@@ -239,7 +281,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
239
281
  }
240
282
  </div>
241
283
 
242
- <table role="grid" class="border-collapse">
284
+ <!-- Separated, with the spacing taken back out: the collapsed model has browsers ignore
285
+ border-radius on a cell, which is what rounds the ends of the range band. The zero
286
+ spacing keeps the grid laid out exactly as the collapsed model did. -->
287
+ <table role="grid" class="border-separate border-spacing-0">
243
288
  <thead>
244
289
  <tr>
245
290
  @for (label of weekdays(); track $index) {
@@ -251,18 +296,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
251
296
  @for (week of grids()[offset]; track $index) {
252
297
  <tr>
253
298
  @for (day of week; track $index) {
254
- <!-- Selection belongs on the gridcell, not the button. -->
255
- <td [class]="cellClass(day)" [attr.aria-selected]="isEndpoint(day.date)">
256
- <button
257
- type="button"
258
- [class]="dayClass(day)"
259
- [disabled]="day.disabled || isDisabled()"
260
- (click)="onClick(day.date)"
261
- (mouseenter)="hover.set(day.date)"
262
- >
263
- {{ day.label }}
264
- </button>
265
- </td>
299
+ <!-- A day belonging to a neighbouring month is left blank: with the months
300
+ side by side it is already on screen in its own grid, and drawing it twice
301
+ gave a selected endpoint two circles. -->
302
+ @if (!day.inCurrentMonth) {
303
+ <td class="p-0"></td>
304
+ } @else {
305
+ <!-- Selection belongs on the gridcell, not the button. -->
306
+ <td [class]="cellClass(day)" [attr.aria-selected]="isEndpoint(day.date)">
307
+ <button
308
+ type="button"
309
+ [class]="dayClass(day)"
310
+ [disabled]="day.disabled || isDisabled()"
311
+ (click)="onClick(day.date)"
312
+ (mouseenter)="hover.set(day.date)"
313
+ >
314
+ {{ day.label }}
315
+ </button>
316
+ </td>
317
+ }
266
318
  }
267
319
  </tr>
268
320
  }
@@ -1 +1 @@
1
- {"version":3,"file":"xui-date-range-picker.mjs","sources":["../../../../../../libs/ui/date-range-picker/xui/src/lib/date-range-picker.ts","../../../../../../libs/ui/date-range-picker/xui/src/index.ts","../../../../../../libs/ui/date-range-picker/xui/src/xui-date-range-picker.ts"],"sourcesContent":["import { BooleanInput, NumberInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n inject,\n input,\n linkedSignal,\n model,\n numberAttribute,\n signal,\n ViewEncapsulation\n} from '@angular/core';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { matChevronLeftRound, matChevronRightRound } from '@ng-icons/material-icons/round';\nimport { xui } from '@xui/core';\nimport { buildMonthGrid, monthYearLabel, weekdayLabels, type XCalendarDay } from '@xui/core/calendar';\nimport { injectXDateAdapter, type XDateAdapter } from '@xui/core/date-time';\nimport { createXValueAccessor, provideXValueAccessor } from '@xui/core/forms';\nimport { XuiIcon } from '@xui/icon';\nimport type { ClassValue } from 'clsx';\n\n/** A `[start, end]` date range; either end may be `null` while selecting. */\nexport interface XuiDateRange<T> {\n start: T | null;\n end: T | null;\n}\n\n/**\n * A multi-month calendar for choosing a date range. The first click sets the\n * start, the second the end (hovering previews the span); clicking again starts a\n * new range. `[(value)]` two-way binding; `T` is the active `DateAdapter`'s type.\n * It is a full `ControlValueAccessor`, so `ngModel`/`formControl` bind to it\n * directly.\n */\n@Component({\n selector: 'xui-date-range-picker',\n imports: [NgIcon, XuiIcon],\n providers: [provideXValueAccessor(() => XuiDateRangePicker)],\n template: `\n <div class=\"flex gap-6\">\n @for (offset of monthOffsets(); track offset) {\n <div>\n <div class=\"mb-2 flex items-center justify-between\">\n @if (offset === 0) {\n <button\n type=\"button\"\n [class]=\"navClass()\"\n aria-label=\"Previous month\"\n [disabled]=\"isDisabled()\"\n (click)=\"shiftMonth(-1)\"\n >\n <ng-icon xui name=\"matChevronLeftRound\" size=\"sm\" />\n </button>\n } @else {\n <span class=\"size-7\"></span>\n }\n <div class=\"text-foreground text-sm font-semibold\">{{ monthLabel(offset) }}</div>\n @if (offset === monthOffsets().length - 1) {\n <button\n type=\"button\"\n [class]=\"navClass()\"\n aria-label=\"Next month\"\n [disabled]=\"isDisabled()\"\n (click)=\"shiftMonth(1)\"\n >\n <ng-icon xui name=\"matChevronRightRound\" size=\"sm\" />\n </button>\n } @else {\n <span class=\"size-7\"></span>\n }\n </div>\n\n <table role=\"grid\" class=\"border-collapse\">\n <thead>\n <tr>\n @for (label of weekdays(); track $index) {\n <th class=\"text-foreground-muted pb-1 text-center text-xs font-medium\">{{ label }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (week of grids()[offset]; track $index) {\n <tr>\n @for (day of week; track $index) {\n <!-- Selection belongs on the gridcell, not the button. -->\n <td [class]=\"cellClass(day)\" [attr.aria-selected]=\"isEndpoint(day.date)\">\n <button\n type=\"button\"\n [class]=\"dayClass(day)\"\n [disabled]=\"day.disabled || isDisabled()\"\n (click)=\"onClick(day.date)\"\n (mouseenter)=\"hover.set(day.date)\"\n >\n {{ day.label }}\n </button>\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n `,\n host: {\n '[class]': 'computedClass()',\n '(focusout)': 'onFocusOut($event)'\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n viewProviders: [provideIcons({ matChevronLeftRound, matChevronRightRound })]\n})\nexport class XuiDateRangePicker<T = Date> implements ControlValueAccessor {\n private readonly adapter: XDateAdapter<T> = injectXDateAdapter<T>();\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n\n readonly class = input<ClassValue>('');\n\n /** The chosen range. Two-way bindable with `[(value)]`. */\n readonly value = model<XuiDateRange<T>>({ start: null, end: null });\n\n readonly min = input<T | null>(null);\n readonly max = input<T | null>(null);\n readonly dateFilter = input<((date: T) => boolean) | null>(null);\n readonly firstDayOfWeek = input<number, NumberInput>(0, { transform: numberAttribute });\n readonly locale = input<string | undefined>(undefined);\n\n /** How many contiguous months to show (1 or 2). */\n readonly months = input<number, NumberInput>(2, { transform: numberAttribute });\n\n /** Allow the start and end to be the same day. */\n readonly allowSingleDayRange = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n readonly disabled = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n protected readonly cva = createXValueAccessor<XuiDateRange<T> | null>({\n onWrite: range => this.value.set(range ?? { start: null, end: null }),\n disabled: this.disabled\n });\n protected readonly isDisabled = this.cva.disabled;\n\n protected readonly hover = signal<T | null>(null);\n\n // The left-most month on screen, seeded from the range start (or today).\n private readonly viewDate = linkedSignal<XuiDateRange<T>, T>({\n source: this.value,\n computation: (range, previous) => range.start ?? previous?.value ?? this.adapter.now()\n });\n\n protected readonly monthOffsets = computed(() => Array.from({ length: Math.max(1, this.months()) }, (_, i) => i));\n protected readonly weekdays = computed(() => weekdayLabels(this.firstDayOfWeek(), this.locale()));\n\n protected readonly grids = computed(() =>\n this.monthOffsets().map(offset =>\n buildMonthGrid(this.adapter, this.adapter.add(this.viewDate(), { months: offset }), {\n min: this.min(),\n max: this.max(),\n dateFilter: this.dateFilter(),\n firstDayOfWeek: this.firstDayOfWeek()\n })\n )\n );\n\n protected readonly computedClass = computed(() =>\n xui(\n 'bg-surface-raised border-border inline-block rounded-lg border p-3',\n this.isDisabled() && 'opacity-50',\n this.class()\n )\n );\n protected readonly navClass = computed(() =>\n xui(\n 'text-foreground-muted hover:bg-surface-inset hover:text-foreground flex size-7 items-center justify-center rounded'\n )\n );\n\n protected monthLabel(offset: number): string {\n return monthYearLabel(this.adapter, this.adapter.add(this.viewDate(), { months: offset }), this.locale());\n }\n\n protected isEndpoint(date: T): boolean {\n const { start, end } = this.value();\n return (start != null && this.adapter.isSameDay(date, start)) || (end != null && this.adapter.isSameDay(date, end));\n }\n\n /** The provisional end while only a start is chosen (uses the hovered day). */\n private effectiveEnd(): T | null {\n const { start, end } = this.value();\n if (end != null) {\n return end;\n }\n return start != null ? this.hover() : null;\n }\n\n private inRange(date: T): boolean {\n const { start } = this.value();\n const end = this.effectiveEnd();\n if (start == null || end == null) {\n return false;\n }\n\n const [lo, hi] = this.adapter.isAfter(start, end) ? [end, start] : [start, end];\n return (\n !this.adapter.isBefore(date, this.adapter.startOfDay(lo)) &&\n !this.adapter.isAfter(date, this.adapter.startOfDay(hi))\n );\n }\n\n protected cellClass(day: XCalendarDay<T>): string {\n // A continuous highlight strip behind the days that fall inside the range.\n return xui('p-0 text-center', this.inRange(day.date) && !this.isEndpoint(day.date) && 'bg-primary/10');\n }\n\n protected dayClass(day: XCalendarDay<T>): string {\n return xui(\n 'flex size-8 items-center justify-center rounded-full text-sm transition-colors',\n day.inCurrentMonth ? 'text-foreground' : 'text-foreground-subtle',\n !day.disabled && 'hover:bg-surface-inset cursor-pointer',\n day.disabled && 'cursor-not-allowed opacity-40',\n day.isToday && !this.isEndpoint(day.date) && 'ring-border-strong ring-1',\n this.isEndpoint(day.date) && 'bg-primary text-primary-foreground hover:bg-primary'\n );\n }\n\n protected shiftMonth(delta: number): void {\n this.viewDate.set(this.adapter.add(this.viewDate(), { months: delta }));\n }\n\n protected onClick(date: T): void {\n if (this.isDisabled()) {\n return;\n }\n\n const { start, end } = this.value();\n\n // Start a fresh range if there's no start, both ends are set, or the click is\n // before the current start.\n if (start == null || end != null || this.adapter.isBefore(date, start)) {\n this.commit({ start: date, end: null });\n return;\n }\n\n // Second click: complete the range (guard single-day unless allowed).\n if (this.adapter.isSameDay(date, start) && !this.allowSingleDayRange()) {\n return;\n }\n\n this.commit({ start, end: date });\n }\n\n private commit(range: XuiDateRange<T>): void {\n // `model.set` emits `valueChange` for `[(value)]` / `(valueChange)` consumers.\n this.value.set(range);\n this.cva.notifyChange(range);\n }\n\n /** Touched fires when focus leaves the calendar, not while moving inside it. */\n protected onFocusOut(event: FocusEvent): void {\n const next = event.relatedTarget as Node | null;\n if (!next || !this.host.nativeElement.contains(next)) {\n this.cva.markTouched();\n }\n }\n\n readonly writeValue = this.cva.writeValue;\n readonly registerOnChange = this.cva.registerOnChange;\n readonly registerOnTouched = this.cva.registerOnTouched;\n readonly setDisabledState = this.cva.setDisabledState;\n}\n","import { XuiDateRangePicker } from './lib/date-range-picker';\n\nexport * from './lib/date-range-picker';\n\nexport const XuiDateRangePickerImports = [XuiDateRangePicker] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"xui-date-range-picker.mjs","sources":["../../../../../../libs/ui/date-range-picker/xui/src/lib/date-range-picker.ts","../../../../../../libs/ui/date-range-picker/xui/src/index.ts","../../../../../../libs/ui/date-range-picker/xui/src/xui-date-range-picker.ts"],"sourcesContent":["import { BooleanInput, NumberInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n inject,\n input,\n linkedSignal,\n model,\n numberAttribute,\n signal,\n ViewEncapsulation\n} from '@angular/core';\nimport { ControlValueAccessor } from '@angular/forms';\nimport { NgIcon, provideIcons } from '@ng-icons/core';\nimport { matChevronLeftRound, matChevronRightRound } from '@ng-icons/material-icons/round';\nimport { xui } from '@xui/core';\nimport { buildMonthGrid, monthYearLabel, weekdayLabels, type XCalendarDay } from '@xui/core/calendar';\nimport { injectXDateAdapter, type XDateAdapter } from '@xui/core/date-time';\nimport { createXValueAccessor, provideXValueAccessor } from '@xui/core/forms';\nimport { XuiIcon } from '@xui/icon';\nimport type { ClassValue } from 'clsx';\n\n/** A `[start, end]` date range; either end may be `null` while selecting. */\nexport interface XuiDateRange<T> {\n start: T | null;\n end: T | null;\n}\n\n/**\n * A multi-month calendar for choosing a date range. The first click sets the\n * start, the second the end (hovering previews the span); clicking again starts a\n * new range. `[(value)]` two-way binding; `T` is the active `DateAdapter`'s type.\n * It is a full `ControlValueAccessor`, so `ngModel`/`formControl` bind to it\n * directly.\n */\n@Component({\n selector: 'xui-date-range-picker',\n imports: [NgIcon, XuiIcon],\n providers: [provideXValueAccessor(() => XuiDateRangePicker)],\n template: `\n <div class=\"flex gap-6\">\n @for (offset of monthOffsets(); track offset) {\n <div>\n <div class=\"mb-2 flex items-center justify-between\">\n @if (offset === 0) {\n <button\n type=\"button\"\n [class]=\"navClass()\"\n aria-label=\"Previous month\"\n [disabled]=\"isDisabled()\"\n (click)=\"shiftMonth(-1)\"\n >\n <ng-icon xui name=\"matChevronLeftRound\" size=\"sm\" />\n </button>\n } @else {\n <span class=\"size-7\"></span>\n }\n <div class=\"text-foreground text-sm font-semibold\">{{ monthLabel(offset) }}</div>\n @if (offset === monthOffsets().length - 1) {\n <button\n type=\"button\"\n [class]=\"navClass()\"\n aria-label=\"Next month\"\n [disabled]=\"isDisabled()\"\n (click)=\"shiftMonth(1)\"\n >\n <ng-icon xui name=\"matChevronRightRound\" size=\"sm\" />\n </button>\n } @else {\n <span class=\"size-7\"></span>\n }\n </div>\n\n <!-- Separated, with the spacing taken back out: the collapsed model has browsers ignore\n border-radius on a cell, which is what rounds the ends of the range band. The zero\n spacing keeps the grid laid out exactly as the collapsed model did. -->\n <table role=\"grid\" class=\"border-separate border-spacing-0\">\n <thead>\n <tr>\n @for (label of weekdays(); track $index) {\n <th class=\"text-foreground-muted pb-1 text-center text-xs font-medium\">{{ label }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (week of grids()[offset]; track $index) {\n <tr>\n @for (day of week; track $index) {\n <!-- A day belonging to a neighbouring month is left blank: with the months\n side by side it is already on screen in its own grid, and drawing it twice\n gave a selected endpoint two circles. -->\n @if (!day.inCurrentMonth) {\n <td class=\"p-0\"></td>\n } @else {\n <!-- Selection belongs on the gridcell, not the button. -->\n <td [class]=\"cellClass(day)\" [attr.aria-selected]=\"isEndpoint(day.date)\">\n <button\n type=\"button\"\n [class]=\"dayClass(day)\"\n [disabled]=\"day.disabled || isDisabled()\"\n (click)=\"onClick(day.date)\"\n (mouseenter)=\"hover.set(day.date)\"\n >\n {{ day.label }}\n </button>\n </td>\n }\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n `,\n host: {\n '[class]': 'computedClass()',\n '(focusout)': 'onFocusOut($event)'\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n viewProviders: [provideIcons({ matChevronLeftRound, matChevronRightRound })]\n})\nexport class XuiDateRangePicker<T = Date> implements ControlValueAccessor {\n private readonly adapter: XDateAdapter<T> = injectXDateAdapter<T>();\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n\n readonly class = input<ClassValue>('');\n\n /** The chosen range. Two-way bindable with `[(value)]`. */\n readonly value = model<XuiDateRange<T>>({ start: null, end: null });\n\n readonly min = input<T | null>(null);\n readonly max = input<T | null>(null);\n readonly dateFilter = input<((date: T) => boolean) | null>(null);\n readonly firstDayOfWeek = input<number, NumberInput>(0, { transform: numberAttribute });\n readonly locale = input<string | undefined>(undefined);\n\n /** How many contiguous months to show (1 or 2). */\n readonly months = input<number, NumberInput>(2, { transform: numberAttribute });\n\n /** Allow the start and end to be the same day. */\n readonly allowSingleDayRange = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n readonly disabled = input<boolean, BooleanInput>(false, { transform: booleanAttribute });\n\n protected readonly cva = createXValueAccessor<XuiDateRange<T> | null>({\n onWrite: range => this.value.set(range ?? { start: null, end: null }),\n disabled: this.disabled\n });\n protected readonly isDisabled = this.cva.disabled;\n\n protected readonly hover = signal<T | null>(null);\n\n // The left-most month on screen, seeded from the range start (or today).\n private readonly viewDate = linkedSignal<XuiDateRange<T>, T>({\n source: this.value,\n computation: (range, previous) => range.start ?? previous?.value ?? this.adapter.now()\n });\n\n protected readonly monthOffsets = computed(() => Array.from({ length: Math.max(1, this.months()) }, (_, i) => i));\n protected readonly weekdays = computed(() => weekdayLabels(this.firstDayOfWeek(), this.locale()));\n\n protected readonly grids = computed(() =>\n this.monthOffsets().map(offset =>\n buildMonthGrid(this.adapter, this.adapter.add(this.viewDate(), { months: offset }), {\n min: this.min(),\n max: this.max(),\n dateFilter: this.dateFilter(),\n firstDayOfWeek: this.firstDayOfWeek()\n })\n )\n );\n\n protected readonly computedClass = computed(() =>\n xui(\n 'bg-surface-raised border-border inline-block rounded-lg border p-3',\n this.isDisabled() && 'opacity-50',\n this.class()\n )\n );\n protected readonly navClass = computed(() =>\n xui(\n 'text-foreground-muted hover:bg-surface-inset hover:text-foreground flex size-7 items-center justify-center rounded'\n )\n );\n\n protected monthLabel(offset: number): string {\n return monthYearLabel(this.adapter, this.adapter.add(this.viewDate(), { months: offset }), this.locale());\n }\n\n protected isEndpoint(date: T): boolean {\n const { start, end } = this.value();\n return (start != null && this.adapter.isSameDay(date, start)) || (end != null && this.adapter.isSameDay(date, end));\n }\n\n /** The provisional end while only a start is chosen (uses the hovered day). */\n private effectiveEnd(): T | null {\n const { start, end } = this.value();\n if (end != null) {\n return end;\n }\n return start != null ? this.hover() : null;\n }\n\n private inRange(date: T): boolean {\n const { start } = this.value();\n const end = this.effectiveEnd();\n if (start == null || end == null) {\n return false;\n }\n\n const [lo, hi] = this.adapter.isAfter(start, end) ? [end, start] : [start, end];\n return (\n !this.adapter.isBefore(date, this.adapter.startOfDay(lo)) &&\n !this.adapter.isAfter(date, this.adapter.startOfDay(hi))\n );\n }\n\n /**\n * The band behind the days inside the range, endpoints included.\n *\n * Its ends are rounded to the day circle's own radius, so the band finishes on the same\n * silhouette the circle draws. Squaring them off left a tinted corner poking out past the curve\n * at each end — the band read as a box drawn around the selection rather than a line joining it.\n */\n protected cellClass(day: XCalendarDay<T>): string {\n const side = this.endpointSide(day.date);\n\n return xui(\n 'p-0 text-center',\n side !== null || (this.spansDays() && this.inRange(day.date)) ? 'bg-primary/10' : '',\n side === 'start' && 'rounded-s-full',\n side === 'end' && 'rounded-e-full'\n );\n }\n\n /** The range's two ends as `[earlier, later]`, or null while it is still incomplete. */\n private bounds(): [T, T] | null {\n const { start } = this.value();\n const end = this.effectiveEnd();\n\n if (start == null || end == null) {\n return null;\n }\n\n return this.adapter.isAfter(start, end) ? [end, start] : [start, end];\n }\n\n /** Whether the range covers more than a single day — a one-day range has nothing to join up. */\n private spansDays(): boolean {\n const bounds = this.bounds();\n\n return bounds != null && !this.adapter.isSameDay(bounds[0], bounds[1]);\n }\n\n /** Which end of the range a day sits at, once the range covers more than one day. */\n private endpointSide(date: T): 'start' | 'end' | null {\n const bounds = this.bounds();\n\n if (!bounds || !this.spansDays()) {\n return null;\n }\n\n if (this.adapter.isSameDay(date, bounds[0])) {\n return 'start';\n }\n\n return this.adapter.isSameDay(date, bounds[1]) ? 'end' : null;\n }\n\n protected dayClass(day: XCalendarDay<T>): string {\n return xui(\n 'flex size-8 items-center justify-center rounded-full text-sm transition-colors',\n day.inCurrentMonth ? 'text-foreground' : 'text-foreground-subtle',\n !day.disabled && 'hover:bg-surface-inset cursor-pointer',\n day.disabled && 'cursor-not-allowed opacity-40',\n day.isToday && !this.isEndpoint(day.date) && 'ring-border-strong ring-1',\n this.isEndpoint(day.date) && 'bg-primary text-primary-foreground hover:bg-primary'\n );\n }\n\n protected shiftMonth(delta: number): void {\n this.viewDate.set(this.adapter.add(this.viewDate(), { months: delta }));\n }\n\n protected onClick(date: T): void {\n if (this.isDisabled()) {\n return;\n }\n\n const { start, end } = this.value();\n\n // Start a fresh range if there's no start, both ends are set, or the click is\n // before the current start.\n if (start == null || end != null || this.adapter.isBefore(date, start)) {\n this.commit({ start: date, end: null });\n return;\n }\n\n // Second click: complete the range (guard single-day unless allowed).\n if (this.adapter.isSameDay(date, start) && !this.allowSingleDayRange()) {\n return;\n }\n\n this.commit({ start, end: date });\n }\n\n private commit(range: XuiDateRange<T>): void {\n // `model.set` emits `valueChange` for `[(value)]` / `(valueChange)` consumers.\n this.value.set(range);\n this.cva.notifyChange(range);\n }\n\n /** Touched fires when focus leaves the calendar, not while moving inside it. */\n protected onFocusOut(event: FocusEvent): void {\n const next = event.relatedTarget as Node | null;\n if (!next || !this.host.nativeElement.contains(next)) {\n this.cva.markTouched();\n }\n }\n\n readonly writeValue = this.cva.writeValue;\n readonly registerOnChange = this.cva.registerOnChange;\n readonly registerOnTouched = this.cva.registerOnTouched;\n readonly setDisabledState = this.cva.setDisabledState;\n}\n","import { XuiDateRangePicker } from './lib/date-range-picker';\n\nexport * from './lib/date-range-picker';\n\nexport const XuiDateRangePickerImports = [XuiDateRangePicker] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;;AA+BA;;;;;;AAMG;MA0FU,kBAAkB,CAAA;IACZ,OAAO,GAAoB,kBAAkB,EAAK;AAClD,IAAA,IAAI,GAAG,MAAM,CAA0B,UAAU,CAAC;IAE1D,KAAK,GAAG,KAAK,CAAa,EAAE;8EAAC;;IAG7B,KAAK,GAAG,KAAK,CAAkB,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE;8EAAC;IAE1D,GAAG,GAAG,KAAK,CAAW,IAAI;4EAAC;IAC3B,GAAG,GAAG,KAAK,CAAW,IAAI;4EAAC;IAC3B,UAAU,GAAG,KAAK,CAAgC,IAAI;mFAAC;IACvD,cAAc,GAAG,KAAK,CAAsB,CAAC,sFAAI,SAAS,EAAE,eAAe,EAAA,CAAG;IAC9E,MAAM,GAAG,KAAK,CAAqB,SAAS;+EAAC;;IAG7C,MAAM,GAAG,KAAK,CAAsB,CAAC,8EAAI,SAAS,EAAE,eAAe,EAAA,CAAG;;IAGtE,mBAAmB,GAAG,KAAK,CAAwB,KAAK,2FAAI,SAAS,EAAE,gBAAgB,EAAA,CAAG;IAE1F,QAAQ,GAAG,KAAK,CAAwB,KAAK,gFAAI,SAAS,EAAE,gBAAgB,EAAA,CAAG;IAErE,GAAG,GAAG,oBAAoB,CAAyB;QACpE,OAAO,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;QACrE,QAAQ,EAAE,IAAI,CAAC;AAChB,KAAA,CAAC;AACiB,IAAA,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ;IAE9B,KAAK,GAAG,MAAM,CAAW,IAAI;8EAAC;;AAGhC,IAAA,QAAQ,GAAG,YAAY,CAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,UAAA,EAAA,8BAAA,EAAA,CAAA,EACtC,MAAM,EAAE,IAAI,CAAC,KAAK;QAClB,WAAW,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,KAAK,CAAC,KAAK,IAAI,QAAQ,EAAE,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAA,CACtF;AAEiB,IAAA,YAAY,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;qFAAC;AAC9F,IAAA,QAAQ,GAAG,QAAQ,CAAC,MAAM,aAAa,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;iFAAC;AAE9E,IAAA,KAAK,GAAG,QAAQ,CAAC,MAClC,IAAI,CAAC,YAAY,EAAE,CAAC,GAAG,CAAC,MAAM,IAC5B,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE;AAClF,QAAA,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE;AACf,QAAA,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE;AACf,QAAA,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE;AAC7B,QAAA,cAAc,EAAE,IAAI,CAAC,cAAc;AACpC,KAAA,CAAC,CACH;8EACF;IAEkB,aAAa,GAAG,QAAQ,CAAC,MAC1C,GAAG,CACD,oEAAoE,EACpE,IAAI,CAAC,UAAU,EAAE,IAAI,YAAY,EACjC,IAAI,CAAC,KAAK,EAAE,CACb;sFACF;IACkB,QAAQ,GAAG,QAAQ,CAAC,MACrC,GAAG,CACD,oHAAoH,CACrH;iFACF;AAES,IAAA,UAAU,CAAC,MAAc,EAAA;AACjC,QAAA,OAAO,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;IAC3G;AAEU,IAAA,UAAU,CAAC,IAAO,EAAA;QAC1B,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE;AACnC,QAAA,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACrH;;IAGQ,YAAY,GAAA;QAClB,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE;AACnC,QAAA,IAAI,GAAG,IAAI,IAAI,EAAE;AACf,YAAA,OAAO,GAAG;QACZ;AACA,QAAA,OAAO,KAAK,IAAI,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI;IAC5C;AAEQ,IAAA,OAAO,CAAC,IAAO,EAAA;QACrB,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE;AAC9B,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,EAAE;QAC/B,IAAI,KAAK,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE;AAChC,YAAA,OAAO,KAAK;QACd;AAEA,QAAA,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC;AAC/E,QAAA,QACE,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;AACzD,YAAA,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAE5D;AAEA;;;;;;AAMG;AACO,IAAA,SAAS,CAAC,GAAoB,EAAA;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;QAExC,OAAO,GAAG,CACR,iBAAiB,EACjB,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,eAAe,GAAG,EAAE,EACpF,IAAI,KAAK,OAAO,IAAI,gBAAgB,EACpC,IAAI,KAAK,KAAK,IAAI,gBAAgB,CACnC;IACH;;IAGQ,MAAM,GAAA;QACZ,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE;AAC9B,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,EAAE;QAE/B,IAAI,KAAK,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE;AAChC,YAAA,OAAO,IAAI;QACb;QAEA,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC;IACvE;;IAGQ,SAAS,GAAA;AACf,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE;QAE5B,OAAO,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACxE;;AAGQ,IAAA,YAAY,CAAC,IAAO,EAAA;AAC1B,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE;QAE5B,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE;AAChC,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;AAC3C,YAAA,OAAO,OAAO;QAChB;QAEA,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI;IAC/D;AAEU,IAAA,QAAQ,CAAC,GAAoB,EAAA;QACrC,OAAO,GAAG,CACR,gFAAgF,EAChF,GAAG,CAAC,cAAc,GAAG,iBAAiB,GAAG,wBAAwB,EACjE,CAAC,GAAG,CAAC,QAAQ,IAAI,uCAAuC,EACxD,GAAG,CAAC,QAAQ,IAAI,+BAA+B,EAC/C,GAAG,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,2BAA2B,EACxE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,qDAAqD,CACnF;IACH;AAEU,IAAA,UAAU,CAAC,KAAa,EAAA;QAChC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACzE;AAEU,IAAA,OAAO,CAAC,IAAO,EAAA;AACvB,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;YACrB;QACF;QAEA,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE;;;AAInC,QAAA,IAAI,KAAK,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE;AACtE,YAAA,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;YACvC;QACF;;AAGA,QAAA,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,EAAE;YACtE;QACF;QAEA,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;IACnC;AAEQ,IAAA,MAAM,CAAC,KAAsB,EAAA;;AAEnC,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC;AACrB,QAAA,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC;IAC9B;;AAGU,IAAA,UAAU,CAAC,KAAiB,EAAA;AACpC,QAAA,MAAM,IAAI,GAAG,KAAK,CAAC,aAA4B;AAC/C,QAAA,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;AACpD,YAAA,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE;QACxB;IACF;AAES,IAAA,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU;AAChC,IAAA,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB;AAC5C,IAAA,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB;AAC9C,IAAA,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB;0HA1M1C,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;8GAAlB,kBAAkB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,uBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,GAAA,EAAA,EAAA,iBAAA,EAAA,KAAA,EAAA,UAAA,EAAA,KAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,GAAA,EAAA,EAAA,iBAAA,EAAA,KAAA,EAAA,UAAA,EAAA,KAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,EAAA,iBAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,mBAAA,EAAA,EAAA,iBAAA,EAAA,qBAAA,EAAA,UAAA,EAAA,qBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,KAAA,EAAA,aAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,UAAA,EAAA,oBAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,iBAAA,EAAA,EAAA,EAAA,SAAA,EAtFlB,CAAC,qBAAqB,EAAC,MAAM,kBAAkB,EAAC,CAAC,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4ET,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EA9ES,MAAM,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,KAAA,EAAA,MAAA,EAAA,aAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,OAAO,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,CAAA,EAAA,aAAA,EAqFV,CAAC,YAAY,CAAC,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,CAAC,CAAC,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAEjE,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAzF9B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,uBAAuB;AACjC,oBAAA,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;oBAC1B,SAAS,EAAE,CAAC,qBAAqB,EAAC,MAAK,kBAAmB,EAAC,CAAC;AAC5D,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4ET,EAAA,CAAA;AACD,oBAAA,IAAI,EAAE;AACJ,wBAAA,SAAS,EAAE,iBAAiB;AAC5B,wBAAA,YAAY,EAAE;AACf,qBAAA;oBACD,eAAe,EAAE,uBAAuB,CAAC,MAAM;oBAC/C,aAAa,EAAE,iBAAiB,CAAC,IAAI;oBACrC,aAAa,EAAE,CAAC,YAAY,CAAC,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,CAAC;AAC5E,iBAAA;;;AC1HM,MAAM,yBAAyB,GAAG,CAAC,kBAAkB;;ACJ5D;;AAEG;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xui/date-range-picker",
3
- "version": "2.0.0-alpha.16",
3
+ "version": "2.0.0-alpha.17",
4
4
  "description": "Modern Angular 22 UI Library based on TailwindCSS",
5
5
  "keywords": [
6
6
  "angular",
@@ -41,8 +41,8 @@
41
41
  "@angular/forms": "22",
42
42
  "@ng-icons/core": "34",
43
43
  "@ng-icons/material-icons": "34",
44
- "@xui/core": "2.0.0-alpha.16",
45
- "@xui/icon": "2.0.0-alpha.16",
44
+ "@xui/core": "2.0.0-alpha.17",
45
+ "@xui/icon": "2.0.0-alpha.17",
46
46
  "clsx": "^2.1.1"
47
47
  },
48
48
  "publishConfig": {
@@ -47,7 +47,20 @@ declare class XuiDateRangePicker<T = Date> implements ControlValueAccessor {
47
47
  /** The provisional end while only a start is chosen (uses the hovered day). */
48
48
  private effectiveEnd;
49
49
  private inRange;
50
+ /**
51
+ * The band behind the days inside the range, endpoints included.
52
+ *
53
+ * Its ends are rounded to the day circle's own radius, so the band finishes on the same
54
+ * silhouette the circle draws. Squaring them off left a tinted corner poking out past the curve
55
+ * at each end — the band read as a box drawn around the selection rather than a line joining it.
56
+ */
50
57
  protected cellClass(day: XCalendarDay<T>): string;
58
+ /** The range's two ends as `[earlier, later]`, or null while it is still incomplete. */
59
+ private bounds;
60
+ /** Whether the range covers more than a single day — a one-day range has nothing to join up. */
61
+ private spansDays;
62
+ /** Which end of the range a day sits at, once the range covers more than one day. */
63
+ private endpointSide;
51
64
  protected dayClass(day: XCalendarDay<T>): string;
52
65
  protected shiftMonth(delta: number): void;
53
66
  protected onClick(date: T): void;