@joewinke/jatui 0.41.0 → 0.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CLAUDE.md +9 -3
  2. package/dist/components/AnimatedNumber.svelte +22 -4
  3. package/dist/components/BookingScheduler.svelte +412 -0
  4. package/dist/components/BookingScheduler.svelte.d.ts +66 -0
  5. package/dist/components/CalendarPicker.svelte +190 -205
  6. package/dist/components/CalendarPicker.svelte.d.ts +19 -1
  7. package/dist/components/DatePicker.svelte +419 -0
  8. package/dist/components/DatePicker.svelte.d.ts +44 -0
  9. package/dist/components/DateRangePicker.svelte +471 -5
  10. package/dist/components/DateRangePicker.svelte.d.ts +32 -3
  11. package/dist/components/EventCalendar.svelte +1324 -0
  12. package/dist/components/EventCalendar.svelte.d.ts +101 -0
  13. package/dist/components/TimeSlotPicker.svelte +174 -108
  14. package/dist/components/TimeSlotPicker.svelte.d.ts +27 -0
  15. package/dist/components/calendar/CalendarHeader.svelte +98 -0
  16. package/dist/components/calendar/CalendarHeader.svelte.d.ts +24 -0
  17. package/dist/components/calendar/MonthGrid.svelte +361 -0
  18. package/dist/components/calendar/MonthGrid.svelte.d.ts +55 -0
  19. package/dist/components/calendar/calendarGrid.d.ts +219 -0
  20. package/dist/components/calendar/calendarGrid.js +494 -0
  21. package/dist/components/calendar/createCalendarGrid.d.ts +25 -0
  22. package/dist/components/calendar/createCalendarGrid.js +57 -0
  23. package/dist/components/calendar/dayOverlap.d.ts +92 -0
  24. package/dist/components/calendar/dayOverlap.js +147 -0
  25. package/dist/components/calendar/eventCalendar.d.ts +75 -0
  26. package/dist/components/calendar/eventCalendar.js +187 -0
  27. package/dist/components/calendar/index.d.ts +32 -0
  28. package/dist/components/calendar/index.js +25 -0
  29. package/dist/components/calendar/monthPacking.d.ts +97 -0
  30. package/dist/components/calendar/monthPacking.js +254 -0
  31. package/dist/components/calendar/timeSlots.d.ts +57 -0
  32. package/dist/components/calendar/timeSlots.js +163 -0
  33. package/dist/index.d.ts +17 -0
  34. package/dist/index.js +11 -0
  35. package/dist/showcase/Globe.svelte +1 -1
  36. package/package.json +6 -1
@@ -5,13 +5,33 @@
5
5
  *
6
6
  * Pass `getAvailability` callback to load availability data for the visible date range.
7
7
  * Pass `isDateEnabled` to control which dates are selectable.
8
+ *
9
+ * Built on the shared calendar grid (jatui-lfxyy): a real `role="grid"` with the
10
+ * APG keyboard model (arrows, Home/End, PageUp/PageDown, Shift+Page for years),
11
+ * locale-aware week start (opt in with `weekStart="locale"`), token-coloured
12
+ * availability dots and a static accent map (the old `hover:bg-${accentColor}`
13
+ * classes were never emitted by Tailwind).
8
14
  */
9
15
 
10
16
  import type { AvailabilityCounts } from '../types/booking';
17
+ import MonthGrid from './calendar/MonthGrid.svelte';
18
+ import CalendarHeader from './calendar/CalendarHeader.svelte';
19
+ import { createCalendarGrid } from './calendar/createCalendarGrid';
20
+ import {
21
+ addDays,
22
+ buildMonthMatrix,
23
+ calendarAccentStyle,
24
+ compareDays,
25
+ formatMonthYear,
26
+ resolveWeekStart,
27
+ startOfDay,
28
+ toIsoDate,
29
+ type Weekday
30
+ } from './calendar/calendarGrid';
11
31
 
12
32
  export type { AvailabilityCounts };
13
33
 
14
- const DAYS_SHORT = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
34
+ type Level = 'none' | 'low' | 'medium' | 'high' | 'full';
15
35
 
16
36
  let {
17
37
  onSelect,
@@ -21,6 +41,12 @@
21
41
  minNoticeHours = 24,
22
42
  weekdaysOnly = true,
23
43
  accentColor = 'primary',
44
+ selectedDate = $bindable(null),
45
+ weekStart = 0,
46
+ locale,
47
+ showLegend,
48
+ size = 'md',
49
+ class: className = ''
24
50
  }: {
25
51
  onSelect: (date: Date) => void;
26
52
  getAvailability?: (startDate: Date, endDate: Date) => Promise<AvailabilityCounts>;
@@ -28,263 +54,222 @@
28
54
  maxDaysInAdvance?: number;
29
55
  minNoticeHours?: number;
30
56
  weekdaysOnly?: boolean;
57
+ /** primary | secondary | accent | info | success | warning | error | neutral */
31
58
  accentColor?: string;
59
+ /** The picked day (bindable). Shown as the solid cell. */
60
+ selectedDate?: Date | null;
61
+ /** First column (0 = Sunday, the default) or `'locale'` for the viewer's convention. */
62
+ weekStart?: Weekday | 'locale';
63
+ /** BCP 47 locale for month/weekday names. Defaults to the runtime locale. */
64
+ locale?: string;
65
+ /** Availability legend under the grid. Defaults to on when `getAvailability` is set. */
66
+ showLegend?: boolean;
67
+ size?: 'sm' | 'md' | 'lg';
68
+ class?: string;
32
69
  } = $props();
33
70
 
34
- let viewDate = $state(new Date());
71
+ const firstDay = $derived(resolveWeekStart(weekStart, locale));
35
72
  let availabilityCounts = $state(new Map<string, { available: number; total: number }>());
36
73
  let isLoadingAvailability = $state(false);
74
+ let requestId = 0;
37
75
 
38
- const calendarDays = $derived(() => {
39
- const year = viewDate.getFullYear();
40
- const month = viewDate.getMonth();
41
-
42
- const firstDay = new Date(year, month, 1);
43
- const startDate = new Date(firstDay);
44
- startDate.setDate(startDate.getDate() - startDate.getDay());
45
-
46
- const days: Date[] = [];
47
- const current = new Date(startDate);
76
+ function today(): Date {
77
+ return startOfDay(new Date());
78
+ }
48
79
 
49
- for (let i = 0; i < 42; i++) {
50
- days.push(new Date(current));
51
- current.setDate(current.getDate() + 1);
52
- }
53
-
54
- return days;
55
- });
80
+ const maxDate = $derived(addDays(today(), maxDaysInAdvance));
56
81
 
57
82
  function defaultIsDateEnabled(date: Date): boolean {
58
- const today = new Date();
59
- today.setHours(0, 0, 0, 0);
60
-
61
- if (date < today) return false;
62
-
63
- const maxDate = new Date(today);
64
- maxDate.setDate(maxDate.getDate() + maxDaysInAdvance);
65
- if (date > maxDate) return false;
83
+ const t = today();
84
+ if (compareDays(date, t) < 0) return false;
85
+ if (compareDays(date, maxDate) > 0) return false;
66
86
 
67
87
  const minNoticeDate = new Date();
68
88
  minNoticeDate.setHours(minNoticeDate.getHours() + minNoticeHours);
69
- minNoticeDate.setHours(0, 0, 0, 0);
70
- if (date < minNoticeDate) return false;
89
+ if (compareDays(date, minNoticeDate) < 0) return false;
71
90
 
72
91
  if (weekdaysOnly) {
73
92
  const dayOfWeek = date.getDay();
74
93
  if (dayOfWeek === 0 || dayOfWeek === 6) return false;
75
94
  }
76
-
77
95
  return true;
78
96
  }
79
97
 
80
- function checkDateEnabled(date: Date): boolean {
81
- if (isDateEnabled) return isDateEnabled(date);
82
- return defaultIsDateEnabled(date);
98
+ function isDisabled(date: Date): boolean {
99
+ return isDateEnabled ? !isDateEnabled(date) : !defaultIsDateEnabled(date);
83
100
  }
84
101
 
85
- function isToday(date: Date): boolean {
86
- const today = new Date();
87
- return (
88
- date.getDate() === today.getDate() &&
89
- date.getMonth() === today.getMonth() &&
90
- date.getFullYear() === today.getFullYear()
91
- );
92
- }
102
+ // Past months and months beyond the booking window are not reachable — but a
103
+ // custom `isDateEnabled` owns its own rules, so only the defaults clamp.
104
+ const minNav = $derived(isDateEnabled ? null : today());
105
+ const maxNav = $derived(isDateEnabled ? null : maxDate);
106
+ const cal = createCalendarGrid({ initial: () => selectedDate, min: () => minNav, max: () => maxNav });
93
107
 
94
- function isCurrentMonth(date: Date): boolean {
95
- return date.getMonth() === viewDate.getMonth();
108
+ function handleSelect(date: Date) {
109
+ selectedDate = date;
110
+ onSelect(date);
96
111
  }
97
112
 
98
- function prevMonth() {
99
- const newDate = new Date(viewDate);
100
- newDate.setMonth(newDate.getMonth() - 1);
101
- viewDate = newDate;
102
- }
103
-
104
- function nextMonth() {
105
- const newDate = new Date(viewDate);
106
- newDate.setMonth(newDate.getMonth() + 1);
107
- viewDate = newDate;
108
- }
109
-
110
- function handleDateClick(date: Date) {
111
- if (checkDateEnabled(date)) {
112
- onSelect(date);
113
- }
114
- }
115
-
116
- const canGoPrev = $derived(() => {
117
- const today = new Date();
118
- return (
119
- viewDate.getMonth() > today.getMonth() ||
120
- viewDate.getFullYear() > today.getFullYear()
121
- );
122
- });
123
-
124
- const canGoNext = $derived(() => {
125
- const today = new Date();
126
- const maxDate = new Date(today);
127
- maxDate.setDate(maxDate.getDate() + maxDaysInAdvance);
128
- return (
129
- viewDate.getMonth() < maxDate.getMonth() ||
130
- viewDate.getFullYear() < maxDate.getFullYear()
131
- );
132
- });
133
-
134
- async function loadAvailability() {
113
+ async function loadAvailability(month: Date) {
135
114
  if (!getAvailability) return;
136
-
115
+ const id = ++requestId;
137
116
  isLoadingAvailability = true;
138
117
  try {
139
- const days = calendarDays();
140
- const startDate = days[0];
141
- const endDate = days[days.length - 1];
142
-
143
- const counts = await getAvailability(startDate, endDate);
118
+ // Always the full six-week matrix, as before — callers size their query on it.
119
+ const days = buildMonthMatrix(month, firstDay, true).flat();
120
+ const counts = await getAvailability(days[0].date, days[days.length - 1].date);
121
+ if (id !== requestId) return; // a newer month won the race
144
122
  // AvailabilityCounts is a Map, but tolerate plain-object returns too —
145
123
  // Object.entries(aMap) is [] and silently kills the dots.
146
- const entries =
147
- counts instanceof Map ? counts.entries() : Object.entries(counts ?? {});
124
+ const entries = counts instanceof Map ? counts.entries() : Object.entries(counts ?? {});
148
125
  const map = new Map<string, { available: number; total: number }>();
149
- for (const [key, value] of entries) {
150
- map.set(key, value);
151
- }
126
+ for (const [key, value] of entries) map.set(key, value);
152
127
  availabilityCounts = map;
153
128
  } catch {
154
129
  // Silently ignore — dots won't show
155
130
  } finally {
156
- isLoadingAvailability = false;
131
+ if (id === requestId) isLoadingAvailability = false;
157
132
  }
158
133
  }
159
134
 
160
135
  $effect(() => {
161
- const _ = viewDate.getMonth();
162
- loadAvailability();
136
+ void loadAvailability(cal.viewMonth);
163
137
  });
164
138
 
165
- function getAvailabilityLevel(date: Date): 'none' | 'low' | 'medium' | 'high' | 'full' {
139
+ function getAvailabilityLevel(date: Date): Level {
166
140
  // Key by LOCAL calendar date — toISOString() shifts to UTC and is off by
167
141
  // one day for positive-offset timezones (calendar days are local midnights).
168
- const dateStr = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
169
- const counts = availabilityCounts.get(dateStr);
170
-
142
+ const counts = availabilityCounts.get(toIsoDate(date));
171
143
  if (!counts || counts.total === 0) return 'none';
172
-
173
144
  const ratio = counts.available / counts.total;
174
145
  if (ratio === 0) return 'full';
175
146
  if (ratio <= 0.25) return 'low';
176
147
  if (ratio <= 0.6) return 'medium';
177
148
  return 'high';
178
149
  }
179
- </script>
180
150
 
181
- <div class="calendar-picker">
182
- <!-- Month Navigation -->
183
- <div class="flex items-center justify-between mb-6">
184
- <button
185
- onclick={prevMonth}
186
- disabled={!canGoPrev()}
187
- class="btn btn-ghost btn-sm btn-circle disabled:opacity-30"
188
- aria-label="Previous month"
189
- >
190
- <!-- ChevronLeft -->
191
- <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
192
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
193
- </svg>
194
- </button>
151
+ const DOTS: Record<Level, { n: number; tone: string; label: string }> = {
152
+ high: { n: 3, tone: 'positive', label: 'many slots' },
153
+ medium: { n: 2, tone: 'caution', label: 'some slots' },
154
+ low: { n: 1, tone: 'negative', label: 'few slots' },
155
+ full: { n: 1, tone: 'neutral', label: 'fully booked' },
156
+ none: { n: 0, tone: 'neutral', label: '' }
157
+ };
195
158
 
196
- <h3 class="text-lg font-semibold">
197
- {viewDate.toLocaleDateString('en-US', { month: 'long', year: 'numeric' })}
198
- </h3>
199
-
200
- <button
201
- onclick={nextMonth}
202
- disabled={!canGoNext()}
203
- class="btn btn-ghost btn-sm btn-circle disabled:opacity-30"
204
- aria-label="Next month"
205
- >
206
- <!-- ChevronRight -->
207
- <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
208
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
209
- </svg>
210
- </button>
211
- </div>
212
-
213
- <!-- Day Headers -->
214
- <div class="grid grid-cols-7 gap-1 mb-2">
215
- {#each DAYS_SHORT as day}
216
- <div class="text-center text-[0.8125rem] text-base-content/45 py-2">
217
- {day}
218
- </div>
219
- {/each}
220
- </div>
221
-
222
- <!-- Calendar Grid -->
223
- <div class="grid grid-cols-7 gap-1">
224
- {#each calendarDays() as date}
225
- {@const available = checkDateEnabled(date)}
226
- {@const today = isToday(date)}
227
- {@const currentMonth = isCurrentMonth(date)}
228
- {@const availLevel = getAvailabilityLevel(date)}
229
-
230
- <button
231
- onclick={() => handleDateClick(date)}
232
- disabled={!available}
233
- class="aspect-square flex flex-col items-center justify-center rounded-lg text-[0.9375rem] font-medium
234
- transition-all duration-200 relative
235
- {currentMonth ? '' : 'opacity-30'}
236
- {available
237
- ? `hover:bg-${accentColor} hover:text-${accentColor}-content cursor-pointer bg-${accentColor}/15 text-${accentColor}`
238
- : 'text-base-content/30 cursor-not-allowed'}
239
- {today ? `ring-2 ring-${accentColor} ring-offset-2 ring-offset-base-100` : ''}"
240
- >
241
- <span>{date.getDate()}</span>
242
- {#if currentMonth && available && !isLoadingAvailability}
243
- <div class="flex gap-0.5 mt-0.5">
244
- {#if availLevel === 'high'}
245
- <span class="w-1.5 h-1.5 rounded-full bg-emerald-400"></span>
246
- <span class="w-1.5 h-1.5 rounded-full bg-emerald-400"></span>
247
- <span class="w-1.5 h-1.5 rounded-full bg-emerald-400"></span>
248
- {:else if availLevel === 'medium'}
249
- <span class="w-1.5 h-1.5 rounded-full bg-amber-400"></span>
250
- <span class="w-1.5 h-1.5 rounded-full bg-amber-400"></span>
251
- {:else if availLevel === 'low'}
252
- <span class="w-1.5 h-1.5 rounded-full bg-rose-400"></span>
253
- {:else if availLevel === 'full'}
254
- <span class="w-1.5 h-1.5 rounded-full bg-base-content/20"></span>
255
- {/if}
256
- </div>
257
- {/if}
258
- </button>
259
- {/each}
260
- </div>
159
+ const legendOn = $derived(showLegend ?? !!getAvailability);
160
+ </script>
261
161
 
262
- <!-- Legend -->
263
- {#if getAvailability}
264
- <div class="flex flex-wrap items-center gap-x-5 gap-y-2 mt-6 pt-4 border-t border-base-300 text-[0.75rem]">
265
- <div class="flex items-center gap-2">
266
- <div class="flex gap-0.5">
267
- <span class="w-1.5 h-1.5 rounded-full bg-emerald-400"></span>
268
- <span class="w-1.5 h-1.5 rounded-full bg-emerald-400"></span>
269
- <span class="w-1.5 h-1.5 rounded-full bg-emerald-400"></span>
270
- </div>
271
- <span class="text-base-content/60">Many slots</span>
272
- </div>
273
- <div class="flex items-center gap-2">
274
- <div class="flex gap-0.5">
275
- <span class="w-1.5 h-1.5 rounded-full bg-amber-400"></span>
276
- <span class="w-1.5 h-1.5 rounded-full bg-amber-400"></span>
277
- </div>
278
- <span class="text-base-content/60">Some slots</span>
279
- </div>
280
- <div class="flex items-center gap-2">
281
- <span class="w-1.5 h-1.5 rounded-full bg-rose-400"></span>
282
- <span class="text-base-content/60">Few slots</span>
283
- </div>
284
- <div class="flex items-center gap-2">
285
- <div class="w-4 h-4 rounded ring-2 ring-{accentColor}"></div>
286
- <span class="text-base-content/60">Today</span>
287
- </div>
162
+ <div class="calendar-picker {className}" data-calendar-root style={calendarAccentStyle(accentColor)}>
163
+ <CalendarHeader
164
+ label={formatMonthYear(cal.viewMonth, locale)}
165
+ onPrev={() => cal.shift(-1)}
166
+ onNext={() => cal.shift(1)}
167
+ canPrev={cal.canPrev}
168
+ canNext={cal.canNext}
169
+ size={size === 'sm' ? 'sm' : 'md'}
170
+ />
171
+
172
+ <MonthGrid
173
+ month={cal.viewMonth}
174
+ focusedDate={cal.focusedDate}
175
+ weekStart={firstDay}
176
+ {locale}
177
+ selected={selectedDate}
178
+ {isDisabled}
179
+ min={minNav}
180
+ max={maxNav}
181
+ fixedWeeks
182
+ highlightEnabled
183
+ {size}
184
+ onSelect={handleSelect}
185
+ onFocusDate={cal.focus}
186
+ describeDay={(date) => (isLoadingAvailability || isDisabled(date) ? undefined : DOTS[getAvailabilityLevel(date)].label || undefined)}
187
+ >
188
+ {#snippet day(d)}
189
+ {@const level = d.inMonth && !d.disabled && !isLoadingAvailability ? getAvailabilityLevel(d.date) : 'none'}
190
+ {#if DOTS[level].n > 0}
191
+ <span class="calendar-picker__dots" data-tone={DOTS[level].tone}>
192
+ {#each { length: DOTS[level].n } as _, i (i)}
193
+ <span class="calendar-picker__dot"></span>
194
+ {/each}
195
+ </span>
196
+ {/if}
197
+ {/snippet}
198
+ </MonthGrid>
199
+
200
+ {#if legendOn}
201
+ <div class="calendar-picker__legend">
202
+ <span class="calendar-picker__legend-item">
203
+ <span class="calendar-picker__dots" data-tone="positive" aria-hidden="true">
204
+ <span class="calendar-picker__dot"></span><span class="calendar-picker__dot"></span><span class="calendar-picker__dot"></span>
205
+ </span>
206
+ Many slots
207
+ </span>
208
+ <span class="calendar-picker__legend-item">
209
+ <span class="calendar-picker__dots" data-tone="caution" aria-hidden="true">
210
+ <span class="calendar-picker__dot"></span><span class="calendar-picker__dot"></span>
211
+ </span>
212
+ Some slots
213
+ </span>
214
+ <span class="calendar-picker__legend-item">
215
+ <span class="calendar-picker__dots" data-tone="negative" aria-hidden="true"><span class="calendar-picker__dot"></span></span>
216
+ Few slots
217
+ </span>
218
+ <span class="calendar-picker__legend-item">
219
+ <span class="calendar-picker__today-swatch" aria-hidden="true"></span>
220
+ Today
221
+ </span>
288
222
  </div>
289
223
  {/if}
290
224
  </div>
225
+
226
+ <style>
227
+ .calendar-picker__dots {
228
+ display: inline-flex;
229
+ gap: 2px;
230
+ --_dot: var(--jatui-status-neutral, color-mix(in oklab, var(--color-base-content) 40%, transparent));
231
+ }
232
+ .calendar-picker__dots[data-tone='positive'] {
233
+ --_dot: var(--jatui-status-positive, var(--color-success));
234
+ }
235
+ .calendar-picker__dots[data-tone='caution'] {
236
+ --_dot: var(--jatui-status-caution, var(--color-warning));
237
+ }
238
+ .calendar-picker__dots[data-tone='negative'] {
239
+ --_dot: var(--jatui-status-negative, var(--color-error));
240
+ }
241
+ .calendar-picker__dot {
242
+ width: 0.3125rem;
243
+ height: 0.3125rem;
244
+ border-radius: 9999px;
245
+ background: var(--_dot);
246
+ }
247
+ /* On the solid (picked) day the dots take the accent's content colour. */
248
+ :global(.jatui-month-grid__day.is-solid) .calendar-picker__dot {
249
+ background: currentColor;
250
+ opacity: 0.85;
251
+ }
252
+ .calendar-picker__legend {
253
+ display: flex;
254
+ flex-wrap: wrap;
255
+ align-items: center;
256
+ gap: 0.5rem 1.25rem;
257
+ margin-block-start: 1rem;
258
+ padding-block-start: 0.75rem;
259
+ border-block-start: 1px solid var(--jatui-separator, var(--color-base-300));
260
+ font-size: 0.75rem;
261
+ color: color-mix(in oklab, var(--color-base-content) 60%, transparent);
262
+ }
263
+ .calendar-picker__legend-item {
264
+ display: inline-flex;
265
+ align-items: center;
266
+ gap: 0.5rem;
267
+ }
268
+ .calendar-picker__today-swatch {
269
+ width: 0.875rem;
270
+ height: 0.875rem;
271
+ border-radius: var(--radius-field, 0.25rem);
272
+ box-shadow: inset 0 0 0 1px
273
+ color-mix(in oklab, var(--jatui-cal-accent, var(--jatui-selection-solid, var(--color-primary))) 55%, transparent);
274
+ }
275
+ </style>
@@ -4,8 +4,15 @@
4
4
  *
5
5
  * Pass `getAvailability` callback to load availability data for the visible date range.
6
6
  * Pass `isDateEnabled` to control which dates are selectable.
7
+ *
8
+ * Built on the shared calendar grid (jatui-lfxyy): a real `role="grid"` with the
9
+ * APG keyboard model (arrows, Home/End, PageUp/PageDown, Shift+Page for years),
10
+ * locale-aware week start (opt in with `weekStart="locale"`), token-coloured
11
+ * availability dots and a static accent map (the old `hover:bg-${accentColor}`
12
+ * classes were never emitted by Tailwind).
7
13
  */
8
14
  import type { AvailabilityCounts } from '../types/booking';
15
+ import { type Weekday } from './calendar/calendarGrid';
9
16
  type $$ComponentProps = {
10
17
  onSelect: (date: Date) => void;
11
18
  getAvailability?: (startDate: Date, endDate: Date) => Promise<AvailabilityCounts>;
@@ -13,10 +20,21 @@ type $$ComponentProps = {
13
20
  maxDaysInAdvance?: number;
14
21
  minNoticeHours?: number;
15
22
  weekdaysOnly?: boolean;
23
+ /** primary | secondary | accent | info | success | warning | error | neutral */
16
24
  accentColor?: string;
25
+ /** The picked day (bindable). Shown as the solid cell. */
26
+ selectedDate?: Date | null;
27
+ /** First column (0 = Sunday, the default) or `'locale'` for the viewer's convention. */
28
+ weekStart?: Weekday | 'locale';
29
+ /** BCP 47 locale for month/weekday names. Defaults to the runtime locale. */
30
+ locale?: string;
31
+ /** Availability legend under the grid. Defaults to on when `getAvailability` is set. */
32
+ showLegend?: boolean;
33
+ size?: 'sm' | 'md' | 'lg';
34
+ class?: string;
17
35
  };
18
36
  declare const CalendarPicker: import("svelte").Component<$$ComponentProps, {
19
37
  AvailabilityCounts: typeof AvailabilityCounts;
20
- }, "">;
38
+ }, "selectedDate">;
21
39
  type CalendarPicker = ReturnType<typeof CalendarPicker>;
22
40
  export default CalendarPicker;