kalendly 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -62,7 +62,7 @@ npm install kalendly
62
62
  />
63
63
  <script src="https://unpkg.com/kalendly/dist/index.umd.js"></script>
64
64
 
65
- <kal-calendar id="cal" title="My Calendar"></kal-calendar>
65
+ <kal-calendar id="cal" heading="My Calendar"></kal-calendar>
66
66
 
67
67
  <script>
68
68
  const cal = document.getElementById('cal');
@@ -104,7 +104,7 @@ import 'kalendly/styles';
104
104
  function App() {
105
105
  return (
106
106
  <kal-calendar
107
- title="My Calendar"
107
+ heading="My Calendar"
108
108
  events={events}
109
109
  oncal-date-select={e => console.log(e.detail.date)}
110
110
  oncal-month-change={e => console.log(e.detail.year, e.detail.month)}
@@ -198,7 +198,7 @@ Without this the component still renders correctly — Vue falls back to a nativ
198
198
  ```vue
199
199
  <template>
200
200
  <kal-calendar
201
- title="My Calendar"
201
+ heading="My Calendar"
202
202
  :events="events"
203
203
  @cal-date-select="onDateSelect"
204
204
  @cal-month-change="onMonthChange"
@@ -236,7 +236,7 @@ import 'kalendly/styles';
236
236
  ```html
237
237
  <!-- app.component.html -->
238
238
  <kal-calendar
239
- title="My Calendar"
239
+ heading="My Calendar"
240
240
  [events]="events"
241
241
  (cal-date-select)="onDateSelect($event)"
242
242
  (cal-month-change)="onMonthChange($event)"
@@ -280,7 +280,7 @@ import 'kalendly/styles';
280
280
  function App() {
281
281
  return (
282
282
  <kal-calendar
283
- title="My Calendar"
283
+ heading="My Calendar"
284
284
  prop:events={events}
285
285
  on:cal-date-select={e => console.log(e.detail.date)}
286
286
  />
@@ -316,7 +316,7 @@ kalendly uses Light DOM — all standard CSS techniques work:
316
316
  }
317
317
 
318
318
  /* 2. Direct class overrides */
319
- .kalendly-calendar .calendar--card {
319
+ .kalendly-calendar .calendar-card {
320
320
  border-radius: 12px;
321
321
  }
322
322
  ```
@@ -335,8 +335,10 @@ Primitives are set as HTML attributes:
335
335
 
336
336
  | Attribute | Type | Default | Description |
337
337
  | ----------------------- | ---------------- | ---------------- | ------------------------------------------------ |
338
- | `title` | `string` | — | Calendar title |
338
+ | `heading` | `string` | — | Calendar heading |
339
+ | `title` | `string` | — | **Deprecated** — use `heading` |
339
340
  | `initial-date` | `string` | today | ISO date string for initial view |
341
+ | `months` | `"1"\|"2"` | `"1"` | Render two months side by side |
340
342
  | `min-year` | `string` | currentYear - 30 | Minimum year in picker |
341
343
  | `max-year` | `string` | currentYear + 10 | Maximum year in picker |
342
344
  | `week-starts-on` | `"0"\|"1"` | `"0"` | Week start: 0 = Sunday, 1 = Monday |
@@ -349,17 +351,23 @@ Primitives are set as HTML attributes:
349
351
 
350
352
  Rich objects are set as JS properties (not attributes):
351
353
 
352
- | Property | Type | Description |
353
- | ---------------- | ---------------------------------- | ------------------------------------------------- |
354
- | `events` | `CalendarEvent[]` | Events to display |
355
- | `loading` | `boolean` | `true` = render skeleton cells; `false` = restore |
356
- | `theme` | `CalendarTheme` | Custom theme colors |
357
- | `categoryColors` | `CategoryColorMap` | Per-category color overrides |
358
- | `renderEvent` | `(event: CalendarEvent) => string` | Custom event HTML renderer |
359
- | `renderNoEvents` | `() => string` | Custom empty-state HTML renderer |
354
+ | Property | Type | Description |
355
+ | -------------------- | ---------------------------------- | ------------------------------------------------- |
356
+ | `events` | `CalendarEvent[]` | Events to display |
357
+ | `loading` | `boolean` | `true` = render skeleton cells; `false` = restore |
358
+ | `theme` | `CalendarTheme` | Custom theme colors |
359
+ | `categoryColors` | `CategoryColorMap` | Per-category color overrides |
360
+ | `renderEvent` | `(event: CalendarEvent) => string` | Custom event HTML renderer |
361
+ | `renderNoEvents` | `() => string` | Custom empty-state HTML renderer |
362
+ | `availabilityColors` | `Record<string, string>` | Colour per availability bucket |
363
+ | `selectableStatuses` | `string[]` | Buckets a range may start, end or span |
360
364
 
361
365
  > `renderEvent` and `renderNoEvents` are ignored when `availability-mode` is set.
362
366
 
367
+ ### Why `heading` and not `title`
368
+
369
+ `title` is a global HTML attribute, so the browser renders it as a tooltip floating over the whole calendar as well as using it as the heading. `heading` does the same job without the tooltip. `title` still works and warns once per page; it will be removed in a future release.
370
+
363
371
  ## Custom Events
364
372
 
365
373
  | Event | `detail` shape | Description |
@@ -385,7 +393,70 @@ Hides all event details from the end user — only booked/free state is shown. D
385
393
  <kal-calendar availability-mode="day"></kal-calendar>
386
394
  ```
387
395
 
388
- Days with events are tinted red (booked); days without events are tinted green (free). Only cells in the current month are colour-coded — other-month cells remain grayed out. Clicking a day fires no popup and reveals no event details.
396
+ Every event must declare `availabilityStatus`. Three buckets ship built in, coloured as a traffic light:
397
+
398
+ | Bucket | Colour | Meaning |
399
+ | ------------- | ------ | ----------------------------------------- |
400
+ | `open` | green | nothing claims this day |
401
+ | `conditional` | amber | claimed, but not necessarily hard-blocked |
402
+ | `blocked` | red | not available |
403
+
404
+ ```js
405
+ cal.events = [
406
+ { id: 1, date: '2026-03-02', availabilityStatus: 'blocked' },
407
+ { id: 2, date: '2026-03-05', availabilityStatus: 'conditional' },
408
+ ];
409
+ ```
410
+
411
+ Only cells in the current month are colour-coded — other-month cells remain grayed out. Clicking a day fires no popup and reveals no event details.
412
+
413
+ A day holding several events resolves by severity: `blocked` beats `conditional` beats `open`, so a day with both a conditional and a blocked booking reads blocked. Precedence never depends on the order events arrive in.
414
+
415
+ #### Your own buckets
416
+
417
+ `availabilityColors` merges over the built-in three — override one, or add your own:
418
+
419
+ ```js
420
+ cal.availabilityColors = {
421
+ conditional: '#7c3aed', // recolour a built-in
422
+ maintenance: '#0891b2', // add a bucket
423
+ };
424
+ cal.events = [{ id: 3, date: '2026-03-09', availabilityStatus: 'maintenance' }];
425
+ ```
426
+
427
+ A bucket named in `availabilityColors` paints from an inline colour, which takes precedence over the same colour set through `theme`. The built-in three paint from CSS variables and are themeable the usual way.
428
+
429
+ Caller-defined buckets resolve by the order their keys appear in `availabilityColors`.
430
+
431
+ #### Which days are selectable
432
+
433
+ By default only `open` days can start, end or span a range. `selectableStatuses` widens that:
434
+
435
+ ```js
436
+ cal.selectableStatuses = ['open', 'conditional'];
437
+ ```
438
+
439
+ #### Misconfiguration throws
440
+
441
+ An event with no `availabilityStatus`, or one naming a bucket that is neither built in nor declared in `availabilityColors`, throws and names the offending events:
442
+
443
+ ```
444
+ <kal-calendar> availability-mode requires availabilityStatus on every event. Missing on: 7, 9.
445
+ ```
446
+
447
+ Setting `events` throws where you set it. One case cannot: markup parsed before the module defines the element configures the calendar inside a custom element upgrade, and the browser reports exceptions there as uncaught rather than passing them to your code. The failure is kept, so the next call to `getEngine()`, `getCurrentDate()` or `goToDate()` throws it, and correcting `events` or `availabilityColors` clears it.
448
+
449
+ #### Two months side by side
450
+
451
+ ```html
452
+ <kal-calendar
453
+ availability-mode="day"
454
+ months="2"
455
+ selectable="range"
456
+ ></kal-calendar>
457
+ ```
458
+
459
+ Navigation advances one month at a time, so a range spanning a month boundary stays visible. Ranges cross panes freely, and it works in standard and time modes too. Panes stack vertically on narrow screens.
389
460
 
390
461
  <div align="center">
391
462
  <img src="./docs/images/day.png" alt="Availability day view — month grid with red booked cells and green free cells"/>
@@ -489,6 +560,18 @@ cal.getEngine();
489
560
 
490
561
  ## CalendarEvent Interface
491
562
 
563
+ > **Event text renders as text.** `name`, `description`, `location`,
564
+ > `organizer`, `notes`, `tags` and `attendees` are HTML-escaped, so markup in
565
+ > those fields shows as characters rather than being parsed. Use `renderEvent`
566
+ > if you need to emit your own markup. `url` accepts `http:`, `https:`,
567
+ > `mailto:` and relative URLs; anything else becomes `#`. `color` accepts hex
568
+ > values and CSS colour keywords.
569
+
570
+ > **Custom values.** `status`, `category` and `priority` accept any string. An
571
+ > unrecognised value renders as an uppercased badge with a neutral fill, which
572
+ > you can style via `.badge.status-<your-value>` or recolour through
573
+ > `--calendar-badge-bg` / `--calendar-badge-text`.
574
+
492
575
  ```typescript
493
576
  interface CalendarEvent {
494
577
  id: string | number;
@@ -501,18 +584,18 @@ interface CalendarEvent {
501
584
 
502
585
  description?: string;
503
586
  color?: string;
504
- category?:
505
- | 'work'
506
- | 'personal'
507
- | 'meeting'
508
- | 'deadline'
509
- | 'appointment'
510
- | 'other';
587
+ // Known values keep autocomplete; any other string is accepted
588
+ category?: Open<
589
+ 'work' | 'personal' | 'meeting' | 'deadline' | 'appointment' | 'other'
590
+ >;
511
591
  location?: string;
512
592
  url?: string;
513
593
 
514
- status?: 'scheduled' | 'completed' | 'cancelled' | 'tentative';
515
- priority?: 'low' | 'medium' | 'high';
594
+ status?: Open<'scheduled' | 'completed' | 'cancelled' | 'tentative'>;
595
+ priority?: Open<'low' | 'medium' | 'high'>;
596
+
597
+ // Required under availability-mode; see Availability Mode below
598
+ availabilityStatus?: Open<'open' | 'conditional' | 'blocked'>;
516
599
 
517
600
  attendees?: string[];
518
601
  organizer?: string;
@@ -532,26 +615,77 @@ interface CalendarEvent {
532
615
 
533
616
  ## Theming
534
617
 
535
- ### All CSS variables
618
+ ### Design tokens
619
+
620
+ Every colour, size, radius, shadow and spacing step is a custom property. Two
621
+ tiers: `--kal-*` holds the raw palette, `--calendar-*` names what each value is
622
+ for. Override the `--calendar-*` layer — the primitives are internal.
536
623
 
537
624
  ```css
538
625
  :root {
626
+ /* Brand */
539
627
  --calendar-primary-color: #fc8917;
540
628
  --calendar-secondary-color: #fca045;
541
629
  --calendar-tertiary-color: #fdb873;
630
+
631
+ /* Surfaces and text */
542
632
  --calendar-text-color: #2c3e50;
543
633
  --calendar-text-light: #6b7280;
544
- --calendar-border-color: #dee2e6;
545
- --calendar-today-outline: #f7db04;
546
- --calendar-event-indicator: #1890ff;
634
+ --calendar-on-accent: #fff;
547
635
  --calendar-background: #fff;
636
+ --calendar-border-color: #dee2e6;
548
637
  --calendar-cell-hover: #f3f4f6;
638
+ --calendar-header-bg: #f8f9fa;
549
639
  --calendar-selected-bg: #eff6ff;
640
+ --calendar-popup-bg: #fff;
641
+ --calendar-picker-bg: #fff;
642
+ --calendar-today-outline: #f7db04;
643
+ --calendar-event-indicator: #1890ff;
644
+ --calendar-input-invalid: #ef4444;
645
+ --calendar-link: #2563eb;
646
+ --calendar-skeleton-base: #f0f0f0;
647
+ --calendar-skeleton-highlight: #e8e8e8;
648
+
649
+ /* Availability */
650
+ --calendar-open-bg: #dcfce7;
651
+ --calendar-open-fg: #16a34a;
652
+ --calendar-conditional-bg: #fef3c7;
653
+ --calendar-conditional-fg: #d97706;
654
+ --calendar-blocked-bg: #fee2e2;
655
+ --calendar-blocked-fg: #dc2626;
656
+ --calendar-range-bg: #16a34a;
657
+ --calendar-range-outline: #15803d;
658
+ --calendar-in-range-bg: #bbf7d0;
659
+ --calendar-in-range-outline: #86efac;
660
+
661
+ /* Badges — bg/text is the fallback for caller-defined values */
662
+ --calendar-badge-bg: #f3f4f6;
663
+ --calendar-badge-text: #4b5563;
664
+ --calendar-badge-success-bg: #d1fae5;
665
+ --calendar-badge-success-text: #059669;
666
+ --calendar-badge-info-bg: #dbeafe;
667
+ --calendar-badge-info-text: #2563eb;
668
+ --calendar-badge-warning-bg: #fef3c7;
669
+ --calendar-badge-warning-text: #d97706;
670
+ --calendar-badge-danger-bg: #fee2e2;
671
+ --calendar-badge-danger-text: #dc2626;
672
+ --calendar-badge-neutral-bg: #f3f4f6;
673
+ --calendar-badge-neutral-text: #6b7280;
674
+ --calendar-badge-positive-bg: #dcfce7;
675
+ --calendar-badge-positive-text: #16a34a;
676
+ --calendar-badge-tentative-bg: #e0e7ff;
677
+ --calendar-badge-tentative-text: #4f46e5;
550
678
  }
551
679
  ```
552
680
 
681
+ Type, radius, elevation and spacing scales are exposed the same way —
682
+ `--calendar-font-*`, `--calendar-radius-*`, `--calendar-shadow-*` and
683
+ `--calendar-space-*`. See `dist/styles/calendar.css` for the full set.
684
+
553
685
  ### JS theme property (full reference)
554
686
 
687
+ Every `--calendar-*` colour token has a matching camelCase theme key.
688
+
555
689
  ```js
556
690
  cal.theme = {
557
691
  primary: '#3b82f6',
@@ -559,15 +693,54 @@ cal.theme = {
559
693
  tertiary: '#93c5fd',
560
694
  textColor: '#111827',
561
695
  textLight: '#6b7280',
696
+ onAccent: '#ffffff',
562
697
  background: '#ffffff',
563
698
  cellHover: '#f3f4f6',
564
699
  borderColor: '#e5e7eb',
565
700
  todayOutline: '#fbbf24',
566
701
  selectedBg: '#eff6ff',
702
+ headerBg: '#f8f9fa',
703
+ popupBg: '#ffffff',
704
+ pickerBg: '#ffffff',
705
+ pickerShadow: '0 4px 20px rgba(0, 0, 0, 0.15)',
567
706
  eventIndicator: '#10b981',
707
+ link: '#2563eb',
708
+
709
+ // Availability
710
+ openBg: '#dcfce7',
711
+ openFg: '#16a34a',
712
+ conditionalBg: '#fef3c7',
713
+ conditionalFg: '#d97706',
714
+ blockedBg: '#fee2e2',
715
+ blockedFg: '#dc2626',
716
+ rangeBg: '#16a34a',
717
+ rangeOutline: '#15803d',
718
+ inRangeBg: '#bbf7d0',
719
+ inRangeOutline: '#86efac',
720
+
721
+ // Badges
722
+ badgeBg: '#f3f4f6',
723
+ badgeText: '#4b5563',
724
+ badgeSuccessBg: '#d1fae5',
725
+ badgeSuccessText: '#059669',
726
+ badgeInfoBg: '#dbeafe',
727
+ badgeInfoText: '#2563eb',
728
+ badgeWarningBg: '#fef3c7',
729
+ badgeWarningText: '#d97706',
730
+ badgeDangerBg: '#fee2e2',
731
+ badgeDangerText: '#dc2626',
732
+ badgeNeutralBg: '#f3f4f6',
733
+ badgeNeutralText: '#6b7280',
734
+ badgePositiveBg: '#dcfce7',
735
+ badgePositiveText: '#16a34a',
736
+ badgeTentativeBg: '#e0e7ff',
737
+ badgeTentativeText: '#4f46e5',
568
738
  };
569
739
  ```
570
740
 
741
+ > `availabilityColors` writes an inline colour on the cell, so for any bucket it
742
+ > names it takes precedence over the matching `theme` key.
743
+
571
744
  ### Dark theme example
572
745
 
573
746
  ```js
@@ -1,3 +1,4 @@
1
+ type Open<T extends string> = T | (string & {});
1
2
  interface CalendarEvent {
2
3
  id: string | number;
3
4
  name: string;
@@ -7,11 +8,12 @@ interface CalendarEvent {
7
8
  allDay?: boolean;
8
9
  description?: string;
9
10
  color?: string;
10
- category?: 'work' | 'personal' | 'meeting' | 'deadline' | 'appointment' | 'other';
11
+ category?: Open<'work' | 'personal' | 'meeting' | 'deadline' | 'appointment' | 'other'>;
11
12
  location?: string;
12
13
  url?: string;
13
- status?: 'scheduled' | 'completed' | 'cancelled' | 'tentative';
14
- priority?: 'low' | 'medium' | 'high';
14
+ status?: Open<'scheduled' | 'completed' | 'cancelled' | 'tentative'>;
15
+ priority?: Open<'low' | 'medium' | 'high'>;
16
+ availabilityStatus?: Open<'open' | 'conditional' | 'blocked'>;
15
17
  attendees?: string[];
16
18
  organizer?: string;
17
19
  reminders?: number[];
@@ -52,6 +54,13 @@ interface CalendarConfig {
52
54
  maxYear?: number;
53
55
  weekStartsOn?: 0 | 1;
54
56
  categoryColors?: CategoryColorMap;
57
+ monthCount?: number;
58
+ }
59
+ interface CalendarPane {
60
+ year: number;
61
+ month: number;
62
+ monthAndYearText: string;
63
+ calendarDates: CalendarDate[][];
55
64
  }
56
65
  interface CalendarActions {
57
66
  next: () => void;
@@ -62,18 +71,14 @@ interface CalendarActions {
62
71
  selectDate: (date: Date) => void;
63
72
  updateTasks: () => void;
64
73
  }
65
- interface PopupPosition {
66
- class: 'popup-left' | 'popup-right' | 'popup-center-top' | 'popup-center-bottom';
67
- style?: Record<string, string | number>;
68
- }
69
74
  interface CalendarViewModel extends CalendarState {
70
75
  months: string[];
71
76
  days: string[];
72
77
  years: number[];
73
78
  monthAndYearText: string;
74
79
  scheduleDay: string;
80
+ panes: CalendarPane[];
75
81
  calendarDates: CalendarDate[][];
76
- popupPositionClass: string;
77
82
  }
78
83
  type CalendarEventHandler = (event: CalendarEvent) => void;
79
84
  interface CalendarProps {
@@ -100,7 +105,37 @@ interface CalendarTheme {
100
105
  selectedBg?: string;
101
106
  headerBg?: string;
102
107
  popupBg?: string;
108
+ pickerBg?: string;
109
+ pickerShadow?: string;
103
110
  eventIndicator?: string;
111
+ onAccent?: string;
112
+ link?: string;
113
+ openBg?: string;
114
+ openFg?: string;
115
+ conditionalBg?: string;
116
+ conditionalFg?: string;
117
+ blockedBg?: string;
118
+ blockedFg?: string;
119
+ rangeBg?: string;
120
+ rangeOutline?: string;
121
+ inRangeBg?: string;
122
+ inRangeOutline?: string;
123
+ badgeBg?: string;
124
+ badgeText?: string;
125
+ badgeSuccessBg?: string;
126
+ badgeSuccessText?: string;
127
+ badgeInfoBg?: string;
128
+ badgeInfoText?: string;
129
+ badgeWarningBg?: string;
130
+ badgeWarningText?: string;
131
+ badgeDangerBg?: string;
132
+ badgeDangerText?: string;
133
+ badgeNeutralBg?: string;
134
+ badgeNeutralText?: string;
135
+ badgePositiveBg?: string;
136
+ badgePositiveText?: string;
137
+ badgeTentativeBg?: string;
138
+ badgeTentativeText?: string;
104
139
  }
105
140
 
106
141
  declare const MONTHS: string[];
@@ -113,7 +148,6 @@ declare function generateYears(minYear?: number, maxYear?: number): number[];
113
148
  declare function getEventsForDate(events: CalendarEvent[], date: Date): CalendarEvent[];
114
149
  declare function hasEvents(events: CalendarEvent[], date: Date): boolean;
115
150
  declare function generateCalendarDates(year: number, month: number, events?: CalendarEvent[], weekStartsOn?: 0 | 1): CalendarDate[][];
116
- declare function getPopupPositionClass(selectedDayIndex: number | null): string;
117
151
  declare function getCellClasses(calendarDate: CalendarDate): string[];
118
152
  declare function formatDateForDisplay(date: Date): string;
119
153
  declare function getMonthYearText(year: number, month: number): string;
@@ -125,6 +159,10 @@ declare function getDefaultEventColor(category?: string, customColors?: Category
125
159
  declare function mergeCategoryColors(customColors?: CategoryColorMap): CategoryColorMap;
126
160
  declare function isValidHexColor(color: string): boolean;
127
161
  declare function getCategoryColor(category: string, customColors?: CategoryColorMap): string;
162
+ declare function escapeHtml(value: unknown): string;
163
+ declare function slugifyToken(value: string): string;
164
+ declare function safeUrl(value: string): string;
165
+ declare function safeColor(value: string): string;
128
166
 
129
167
  declare class CalendarEngine {
130
168
  private state;
@@ -222,4 +260,4 @@ declare class CalendarEngine {
222
260
  destroy(): void;
223
261
  }
224
262
 
225
- export { type CalendarActions, type CalendarConfig, type CalendarDate, CalendarEngine, type CalendarEvent, type CalendarEventHandler, type CalendarProps, type CalendarState, type CalendarTheme, type CalendarViewModel, type CategoryColorMap, DAYS, DEFAULT_CATEGORY_COLORS, MONTHS, MONTHS_FULL, type PopupPosition, formatAttendees, formatDateForDisplay, formatTimeRange, generateCalendarDates, generateYears, getCategoryColor, getCellClasses, getDefaultEventColor, getEventsForDate, getMonthYearText, getPopupPositionClass, hasEvents, isSameDay, isToday, isValidHexColor, mergeCategoryColors, normalizeDate, sortEventsByTime };
263
+ export { type CalendarActions, type CalendarConfig, type CalendarDate, CalendarEngine, type CalendarEvent, type CalendarEventHandler, type CalendarPane, type CalendarProps, type CalendarState, type CalendarTheme, type CalendarViewModel, type CategoryColorMap, DAYS, DEFAULT_CATEGORY_COLORS, MONTHS, MONTHS_FULL, escapeHtml, formatAttendees, formatDateForDisplay, formatTimeRange, generateCalendarDates, generateYears, getCategoryColor, getCellClasses, getDefaultEventColor, getEventsForDate, getMonthYearText, hasEvents, isSameDay, isToday, isValidHexColor, mergeCategoryColors, normalizeDate, safeColor, safeUrl, slugifyToken, sortEventsByTime };
@@ -1,3 +1,4 @@
1
+ type Open<T extends string> = T | (string & {});
1
2
  interface CalendarEvent {
2
3
  id: string | number;
3
4
  name: string;
@@ -7,11 +8,12 @@ interface CalendarEvent {
7
8
  allDay?: boolean;
8
9
  description?: string;
9
10
  color?: string;
10
- category?: 'work' | 'personal' | 'meeting' | 'deadline' | 'appointment' | 'other';
11
+ category?: Open<'work' | 'personal' | 'meeting' | 'deadline' | 'appointment' | 'other'>;
11
12
  location?: string;
12
13
  url?: string;
13
- status?: 'scheduled' | 'completed' | 'cancelled' | 'tentative';
14
- priority?: 'low' | 'medium' | 'high';
14
+ status?: Open<'scheduled' | 'completed' | 'cancelled' | 'tentative'>;
15
+ priority?: Open<'low' | 'medium' | 'high'>;
16
+ availabilityStatus?: Open<'open' | 'conditional' | 'blocked'>;
15
17
  attendees?: string[];
16
18
  organizer?: string;
17
19
  reminders?: number[];
@@ -52,6 +54,13 @@ interface CalendarConfig {
52
54
  maxYear?: number;
53
55
  weekStartsOn?: 0 | 1;
54
56
  categoryColors?: CategoryColorMap;
57
+ monthCount?: number;
58
+ }
59
+ interface CalendarPane {
60
+ year: number;
61
+ month: number;
62
+ monthAndYearText: string;
63
+ calendarDates: CalendarDate[][];
55
64
  }
56
65
  interface CalendarActions {
57
66
  next: () => void;
@@ -62,18 +71,14 @@ interface CalendarActions {
62
71
  selectDate: (date: Date) => void;
63
72
  updateTasks: () => void;
64
73
  }
65
- interface PopupPosition {
66
- class: 'popup-left' | 'popup-right' | 'popup-center-top' | 'popup-center-bottom';
67
- style?: Record<string, string | number>;
68
- }
69
74
  interface CalendarViewModel extends CalendarState {
70
75
  months: string[];
71
76
  days: string[];
72
77
  years: number[];
73
78
  monthAndYearText: string;
74
79
  scheduleDay: string;
80
+ panes: CalendarPane[];
75
81
  calendarDates: CalendarDate[][];
76
- popupPositionClass: string;
77
82
  }
78
83
  type CalendarEventHandler = (event: CalendarEvent) => void;
79
84
  interface CalendarProps {
@@ -100,7 +105,37 @@ interface CalendarTheme {
100
105
  selectedBg?: string;
101
106
  headerBg?: string;
102
107
  popupBg?: string;
108
+ pickerBg?: string;
109
+ pickerShadow?: string;
103
110
  eventIndicator?: string;
111
+ onAccent?: string;
112
+ link?: string;
113
+ openBg?: string;
114
+ openFg?: string;
115
+ conditionalBg?: string;
116
+ conditionalFg?: string;
117
+ blockedBg?: string;
118
+ blockedFg?: string;
119
+ rangeBg?: string;
120
+ rangeOutline?: string;
121
+ inRangeBg?: string;
122
+ inRangeOutline?: string;
123
+ badgeBg?: string;
124
+ badgeText?: string;
125
+ badgeSuccessBg?: string;
126
+ badgeSuccessText?: string;
127
+ badgeInfoBg?: string;
128
+ badgeInfoText?: string;
129
+ badgeWarningBg?: string;
130
+ badgeWarningText?: string;
131
+ badgeDangerBg?: string;
132
+ badgeDangerText?: string;
133
+ badgeNeutralBg?: string;
134
+ badgeNeutralText?: string;
135
+ badgePositiveBg?: string;
136
+ badgePositiveText?: string;
137
+ badgeTentativeBg?: string;
138
+ badgeTentativeText?: string;
104
139
  }
105
140
 
106
141
  declare const MONTHS: string[];
@@ -113,7 +148,6 @@ declare function generateYears(minYear?: number, maxYear?: number): number[];
113
148
  declare function getEventsForDate(events: CalendarEvent[], date: Date): CalendarEvent[];
114
149
  declare function hasEvents(events: CalendarEvent[], date: Date): boolean;
115
150
  declare function generateCalendarDates(year: number, month: number, events?: CalendarEvent[], weekStartsOn?: 0 | 1): CalendarDate[][];
116
- declare function getPopupPositionClass(selectedDayIndex: number | null): string;
117
151
  declare function getCellClasses(calendarDate: CalendarDate): string[];
118
152
  declare function formatDateForDisplay(date: Date): string;
119
153
  declare function getMonthYearText(year: number, month: number): string;
@@ -125,6 +159,10 @@ declare function getDefaultEventColor(category?: string, customColors?: Category
125
159
  declare function mergeCategoryColors(customColors?: CategoryColorMap): CategoryColorMap;
126
160
  declare function isValidHexColor(color: string): boolean;
127
161
  declare function getCategoryColor(category: string, customColors?: CategoryColorMap): string;
162
+ declare function escapeHtml(value: unknown): string;
163
+ declare function slugifyToken(value: string): string;
164
+ declare function safeUrl(value: string): string;
165
+ declare function safeColor(value: string): string;
128
166
 
129
167
  declare class CalendarEngine {
130
168
  private state;
@@ -222,4 +260,4 @@ declare class CalendarEngine {
222
260
  destroy(): void;
223
261
  }
224
262
 
225
- export { type CalendarActions, type CalendarConfig, type CalendarDate, CalendarEngine, type CalendarEvent, type CalendarEventHandler, type CalendarProps, type CalendarState, type CalendarTheme, type CalendarViewModel, type CategoryColorMap, DAYS, DEFAULT_CATEGORY_COLORS, MONTHS, MONTHS_FULL, type PopupPosition, formatAttendees, formatDateForDisplay, formatTimeRange, generateCalendarDates, generateYears, getCategoryColor, getCellClasses, getDefaultEventColor, getEventsForDate, getMonthYearText, getPopupPositionClass, hasEvents, isSameDay, isToday, isValidHexColor, mergeCategoryColors, normalizeDate, sortEventsByTime };
263
+ export { type CalendarActions, type CalendarConfig, type CalendarDate, CalendarEngine, type CalendarEvent, type CalendarEventHandler, type CalendarPane, type CalendarProps, type CalendarState, type CalendarTheme, type CalendarViewModel, type CategoryColorMap, DAYS, DEFAULT_CATEGORY_COLORS, MONTHS, MONTHS_FULL, escapeHtml, formatAttendees, formatDateForDisplay, formatTimeRange, generateCalendarDates, generateYears, getCategoryColor, getCellClasses, getDefaultEventColor, getEventsForDate, getMonthYearText, hasEvents, isSameDay, isToday, isValidHexColor, mergeCategoryColors, normalizeDate, safeColor, safeUrl, slugifyToken, sortEventsByTime };