simple-calendar-js 3.0.6 → 3.0.8

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/CHANGELOG.md CHANGED
@@ -9,6 +9,60 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  No unreleased changes yet.
11
11
 
12
+ ## [3.0.8] - 2026-02-25
13
+
14
+ ### Changed
15
+ - Updated framework wrappers (React, Vue, Angular) to v3.0.8
16
+ - Removed `maxEventsPerCell` prop from all framework wrappers (deprecated in v3.0.7)
17
+
18
+ ## [3.0.7] - 2026-02-25
19
+
20
+ ### Breaking Changes
21
+ - **Removed `maxEventsPerCell` option** - Calendar now always automatically calculates optimal event display based on available space
22
+ - Month view cells intelligently adapt to container height
23
+ - Events are automatically limited based on cell height with "+N more" indicator
24
+ - Cells flex naturally when container is resized
25
+ - Simplified API - no manual configuration needed
26
+
27
+ ### Added
28
+ - **Mobile-responsive view switcher** - View buttons transform into compact dropdown menu at screen widths ≤640px
29
+ - Single icon button (⊞) replaces four view buttons to save toolbar space
30
+ - Dropdown includes all view options (Month, Week, Day, List) plus Today button
31
+ - Today button in dropdown shows active state when calendar displays today's date
32
+ - Automatic breakpoint at 640px width
33
+ - **List view toolbar controls** - Navigation and Today buttons now visible in list view but appear disabled (grayed out)
34
+ - Maintains visual consistency across all views
35
+ - Clear indication that navigation doesn't apply to list view
36
+ - Applies to both desktop toolbar and mobile dropdown
37
+
38
+ ### Changed
39
+ - **Toolbar layout system** - Replaced flexbox with CSS Grid for more stable button positioning
40
+ - Three equal columns (left buttons, center title, right buttons)
41
+ - Buttons no longer switch positions or overflow at narrow widths
42
+ - Date title abbreviates with ellipsis instead of wrapping to new line
43
+ - Removed all responsive media queries that caused layout shifts
44
+ - **Uniform row heights in month view** - All week rows maintain consistent height in natural sizing mode
45
+ - Pre-calculates maximum event slots across entire month
46
+ - Empty rows no longer appear shorter than rows with events
47
+ - Improved visual consistency and polish
48
+ - **Overflow management** - Strategic use of `overflow-x: clip` prevents horizontal scrollbars while maintaining tooltip visibility
49
+ - Tooltips can still escape calendar boundaries (via parent `overflow-x: visible`)
50
+ - No unwanted scrollbars in month, week, or day views
51
+ - **Compact toolbar styling** - Reduced button padding and gaps to maximize space efficiency
52
+ - All buttons: 4px vertical × 6px horizontal padding (was 5px × 10px)
53
+ - Toolbar gap: 4px (was 8px)
54
+ - Font sizes: title 14px, buttons 12px
55
+ - Calendar now always uses `height: 100%` to fill parent container
56
+ - Month view cells flex to fit available space instead of using fixed min-height
57
+ - All views consistently respect container dimensions
58
+ - Removed `--cal-cell-min-height` CSS custom property (no longer needed)
59
+
60
+ ### Fixed
61
+ - Toolbar buttons no longer disappear or overflow off-screen at narrow widths
62
+ - Date title no longer jumps to new line when calendar is resized
63
+ - Horizontal scrollbars no longer appear in month/week/day views
64
+ - Tooltips display correctly on all edges without being clipped
65
+
12
66
  ## [3.0.6] - 2026-02-24
13
67
 
14
68
  ### Added
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  A lightweight, zero-dependency JavaScript calendar component with internationalization support and framework wrappers for React, Vue, and Angular.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/simple-calendar-js)](https://www.npmjs.com/package/simple-calendar-js)
6
- [![license](https://img.shields.io/npm/l/simple-calendar-js)](LICENSE)
6
+ [![license](https://img.shields.io/npm/l/simple-calendar-js)](https://unpkg.com/simple-calendar-js/LICENSE)
7
7
 
8
8
  ## Features
9
9
 
@@ -17,7 +17,7 @@ A lightweight, zero-dependency JavaScript calendar component with internationali
17
17
  - **Responsive Design** - Adapts to any screen size
18
18
  - **Customizable Styling** - CSS custom properties for easy theming
19
19
  - **Accessible** - Semantic HTML with proper ARIA attributes
20
- - **Small Bundle Size** - ~42KB minified JS + ~20KB CSS (~15KB total gzipped)
20
+ - **Small Bundle Size** - ~45KB minified JS + ~22KB CSS (~16KB total gzipped)
21
21
 
22
22
  ## Installation
23
23
 
@@ -168,7 +168,6 @@ export class CalendarComponent {
168
168
  | `showTimeInItems` | boolean | `true` | Show time in event items |
169
169
  | `showGridLines` | boolean | `true` | Show calendar grid lines |
170
170
  | `showBorder` | boolean | `true` | Show calendar outer border |
171
- | `maxEventsPerCell` | number | `-1` | Maximum events per cell in month view. `-1` = auto-calculate based on cell height (responsive), `0` = unlimited (show all events), `1+` = show exactly that number |
172
171
  | `showToolbar` | boolean | `true` | Show the toolbar |
173
172
  | `showTodayButton` | boolean | `true` | Show "Today" button |
174
173
  | `showNavigation` | boolean | `true` | Show prev/next navigation arrows |
@@ -1125,12 +1124,3 @@ This project is available for personal, educational, and non-commercial use.
1125
1124
  **Commercial use requires a separate license.** See [LICENSE](LICENSE) file for full terms.
1126
1125
 
1127
1126
  For commercial licensing inquiries: simplecalendarjs@gmail.com
1128
-
1129
- ## Links
1130
-
1131
- - **Documentation**: [docs.html](docs.html)
1132
- - **Demo**: [index.html](index.html)
1133
- - **Changelog**: [CHANGELOG.md](CHANGELOG.md)
1134
- - **Repository**: [github.com/pclslopes/SimpleCalendarJs](https://github.com/pclslopes/SimpleCalendarJs)
1135
- - **NPM**: [npmjs.com/package/simple-calendar-js](https://www.npmjs.com/package/simple-calendar-js)
1136
- - **Website**: [simplecalendarjs.com](https://www.simplecalendarjs.com)
@@ -1,5 +1,5 @@
1
1
  /**
2
- * SimpleCalendarJs v3.0.6 — simple-calendar-js.css
2
+ * SimpleCalendarJs v3.0.8 — simple-calendar-js.css
3
3
  * A clean, modern, and feature-rich JavaScript calendar component with zero dependencies
4
4
  *
5
5
  * @author Pedro Lopes <simplecalendarjs@gmail.com>
@@ -9,4 +9,4 @@
9
9
  * All styles scoped under .uc-calendar to prevent leaking.
10
10
  * Override any --cal-* variable in :root or on .uc-calendar.
11
11
  */
12
- :root{--cal-bg:#ffffff;--cal-bg-secondary:#f9fafb;--cal-text:#111827;--cal-text-subtle:#6b7280;--cal-text-muted:#9ca3af;--cal-border:#e5e7eb;--cal-border-strong:#d1d5db;--cal-primary:#4f46e5;--cal-primary-dark:#4338ca;--cal-primary-light:#eef2ff;--cal-event-bg:var(--cal-primary);--cal-event-text:#ffffff;--cal-event-border-radius:3px;--cal-today-bg:#eef2ff;--cal-today-text:var(--cal-primary);--cal-hover:#f9fafb;--cal-hover-strong:#f3f4f6;--cal-selected-bg:#ede9fe;--cal-font-family:inherit;--cal-font-size:13px;--cal-time-col-width:64px;--cal-hour-height:60px;--cal-cell-min-height:112px;--cal-event-height:22px;--cal-event-gap:2px;--cal-header-day-height:30px;--cal-day-name-height:36px;--cal-now-color:#ef4444;--cal-toolbar-bg:var(--cal-bg);--cal-radius:8px;--cal-shadow:0 1px 3px rgba(0,0,0,.08),0 1px 2px rgba(0,0,0,.06);--cal-transition:150ms ease;--cal-tooltip-bg:#1f2937;--cal-tooltip-text:#f9fafb;--cal-tooltip-border:#374151;--cal-tooltip-shadow:0 4px 12px rgba(0, 0, 0, 0.15);--cal-tooltip-max-width:250px;--cal-tooltip-padding:8px 12px;--cal-tooltip-radius:6px;--cal-tooltip-font-size:12px;--cal-tooltip-offset:8px;--cal-loading-bg:rgba(255, 255, 255, 0.7)}.uc-calendar{font-family:var(--cal-font-family);font-size:var(--cal-font-size);color:var(--cal-text);background:var(--cal-bg);border:1px solid var(--cal-border);border-radius:var(--cal-radius);overflow:hidden;display:flex;flex-direction:column;position:relative;-webkit-font-smoothing:antialiased}.uc-calendar *,.uc-calendar ::after,.uc-calendar ::before{box-sizing:border-box;margin:0;padding:0}.uc-toolbar{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 14px;background:var(--cal-toolbar-bg);border-bottom:1px solid var(--cal-border);border-radius:var(--cal-radius) var(--cal-radius) 0 0;flex-shrink:0;flex-wrap:wrap}.uc-toolbar-section{display:flex;align-items:center;gap:4px}.uc-toolbar-center{flex:1;display:flex;justify-content:center;position:relative}.uc-title{font-size:15px;font-weight:600;color:var(--cal-text);white-space:nowrap;letter-spacing:-.01em;display:flex;align-items:baseline;gap:5px}.uc-title-main{text-transform:capitalize}.uc-year-btn{background:0 0;border:none;font:inherit;font-weight:600;font-size:15px;color:var(--cal-primary);cursor:pointer;padding:1px 4px;border-radius:4px;line-height:inherit;text-decoration:underline;text-decoration-style:dotted;text-underline-offset:2px;transition:background var(--cal-transition),color var(--cal-transition)}.uc-year-btn.uc-open,.uc-year-btn:hover{background:var(--cal-primary-light);text-decoration:none}.uc-year-picker{position:absolute;top:calc(100% + 8px);left:50%;transform:translateX(-50%);background:var(--cal-bg);border:1px solid var(--cal-border);border-radius:10px;box-shadow:0 4px 24px rgba(0,0,0,.12);padding:10px;z-index:200;min-width:210px}.uc-year-picker-nav{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.uc-year-range{font-size:12px;font-weight:600;color:var(--cal-text-subtle)}.uc-year-nav-btn{background:0 0;border:none;font-size:18px;line-height:1;color:var(--cal-text);cursor:pointer;padding:2px 7px;border-radius:5px;font-family:inherit;transition:background var(--cal-transition)}.uc-year-nav-btn:hover{background:var(--cal-hover-strong)}.uc-year-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:4px}.uc-year-item{background:0 0;border:none;border-radius:6px;font-size:13px;font-weight:500;font-family:inherit;color:var(--cal-text);cursor:pointer;padding:7px 4px;text-align:center;transition:background var(--cal-transition),color var(--cal-transition)}.uc-year-item:hover{background:var(--cal-hover-strong)}.uc-year-item.uc-today-year{color:var(--cal-primary);font-weight:700}.uc-year-item.uc-active{background:var(--cal-primary);color:#fff;font-weight:700}.uc-btn{display:inline-flex;align-items:center;justify-content:center;gap:4px;border:1px solid var(--cal-border);background:var(--cal-bg);color:var(--cal-text);border-radius:6px;padding:5px 10px;font-size:13px;font-family:inherit;font-weight:500;cursor:pointer;white-space:nowrap;line-height:1.4;transition:background var(--cal-transition),border-color var(--cal-transition),color var(--cal-transition);user-select:none}.uc-btn:hover{background:var(--cal-hover-strong);border-color:var(--cal-border-strong)}.uc-btn:active{background:var(--cal-selected-bg)}.uc-btn:focus-visible{outline:2px solid var(--cal-primary);outline-offset:2px}.uc-nav-btn{font-size:18px;padding:4px 8px;line-height:1;border-color:transparent;background:0 0}.uc-nav-btn:hover{border-color:var(--cal-border)}.uc-today-btn{padding:5px 12px}.uc-today-btn.uc-active{background:var(--cal-primary-light);color:var(--cal-primary);font-weight:600;border-color:transparent}.uc-view-switcher{display:flex;border:1px solid var(--cal-border);border-radius:6px;overflow:hidden}.uc-view-btn{border:none;border-radius:0;border-right:1px solid var(--cal-border);background:0 0;color:var(--cal-text-subtle);font-weight:500;padding:5px 11px}.uc-view-btn:last-child{border-right:none}.uc-view-btn:hover{background:var(--cal-hover-strong);color:var(--cal-text);border-color:transparent}.uc-view-btn.uc-active{background:var(--cal-primary-light);color:var(--cal-primary);font-weight:600}.uc-loading{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:var(--cal-loading-bg);z-index:100;pointer-events:none}.uc-spinner{width:28px;height:28px;border:3px solid var(--cal-border);border-top-color:var(--cal-primary);border-radius:50%;animation:uc-spin .6s linear infinite}@keyframes uc-spin{to{transform:rotate(360deg)}}.uc-view-container{flex:1;overflow:visible;display:flex;flex-direction:column}.uc-view-container:first-child .uc-month-header,.uc-view-container:first-child .uc-week-header{border-radius:var(--cal-radius) var(--cal-radius) 0 0}.uc-month-view{display:flex;flex-direction:column;flex:1;overflow:visible;border-radius:0 0 var(--cal-radius) var(--cal-radius)}.uc-month-header{display:grid;grid-template-columns:repeat(7,1fr);border-bottom:1px solid var(--cal-border);flex-shrink:0}.uc-month-day-name{height:var(--cal-day-name-height,36px);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--cal-text-subtle);user-select:none}.uc-month-body{flex:1;display:flex;flex-direction:column;overflow:visible}.uc-week-row{flex:1;position:relative;min-height:var(--cal-cell-min-height);border-bottom:1px solid var(--cal-border)}.uc-week-row:last-child{border-bottom:none;border-radius:0 0 var(--cal-radius) var(--cal-radius)}.uc-week-cells{position:absolute;inset:0;display:grid;grid-template-columns:repeat(7,1fr);z-index:1}.uc-day-cell{border-right:1px solid var(--cal-border);padding:4px 6px 4px 6px;cursor:pointer;transition:background var(--cal-transition);min-height:var(--cal-cell-min-height)}.uc-day-cell:last-child{border-right:none}.uc-day-cell:hover{background:var(--cal-hover)}.uc-day-cell.uc-today{background:var(--cal-today-bg)}.uc-day-cell.uc-other-month .uc-day-number{color:var(--cal-text-muted)}.uc-day-number{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;font-size:13px;font-weight:500;border-radius:50%;color:var(--cal-text);cursor:pointer;transition:background var(--cal-transition),color var(--cal-transition);line-height:1}.uc-day-number:hover{background:var(--cal-hover-strong)}.uc-today .uc-day-number{background:var(--cal-primary);color:#fff;font-weight:700}.uc-today .uc-day-number:hover{background:var(--cal-primary-dark)}.uc-week-events{position:absolute;inset:0;z-index:2;pointer-events:none;overflow:visible}.uc-event-bar{position:absolute;height:var(--cal-event-height);background:var(--cal-event-bg);color:var(--cal-event-text);border-radius:var(--cal-event-border-radius);display:flex;align-items:center;gap:4px;padding:0 6px;cursor:pointer;pointer-events:auto;white-space:nowrap;font-size:12px;font-weight:500;transition:filter var(--cal-transition),opacity var(--cal-transition);z-index:3}.uc-event-bar:hover{filter:brightness(.92);z-index:1000}.uc-event-bar:active{filter:brightness(.85)}.uc-event-bar.uc-continues-left{border-top-left-radius:0;border-bottom-left-radius:0}.uc-event-bar.uc-continues-right{border-top-right-radius:0;border-bottom-right-radius:0}.uc-event-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}.uc-event-time{font-size:11px;opacity:.85;flex-shrink:0}.uc-more-link{position:absolute;height:16px;display:flex;align-items:center;padding:0 6px;font-size:10px;font-weight:600;color:var(--cal-text-subtle);cursor:pointer;pointer-events:auto;border-radius:var(--cal-event-border-radius);white-space:nowrap;transition:background var(--cal-transition),color var(--cal-transition);z-index:3}.uc-more-link:hover{background:var(--cal-hover-strong);color:var(--cal-text)}.uc-day-view,.uc-week-view{display:flex;flex-direction:column;max-height:650px;overflow:hidden;border-radius:0 0 var(--cal-radius) var(--cal-radius)}.uc-week-header{display:flex;border-bottom:1px solid var(--cal-border);flex-shrink:0;background:var(--cal-bg)}.uc-time-gutter-spacer{width:var(--cal-time-col-width);flex-shrink:0;border-right:1px solid var(--cal-border)}.uc-all-day-label{display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--cal-text-muted);white-space:nowrap}.uc-week-day-headers{flex:1;display:grid;grid-template-columns:repeat(7,1fr)}.uc-week-day-headers.uc-day-header-single{grid-template-columns:1fr}.uc-week-day-header{padding:8px 4px;display:flex;flex-direction:column;align-items:center;gap:2px;border-right:1px solid var(--cal-border);cursor:default}.uc-week-day-header:last-child{border-right:none}.uc-week-day-name{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--cal-text-subtle);user-select:none}.uc-week-day-num{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;font-size:16px;font-weight:600;border-radius:50%;color:var(--cal-text);cursor:pointer;transition:background var(--cal-transition),color var(--cal-transition)}.uc-week-day-num:hover{background:var(--cal-hover-strong)}.uc-week-day-header.uc-today .uc-week-day-name{color:var(--cal-primary)}.uc-week-day-header.uc-today .uc-week-day-num{background:var(--cal-primary);color:#fff}.uc-week-day-header.uc-today .uc-week-day-num:hover{background:var(--cal-primary-dark)}.uc-all-day-section{display:flex;border-bottom:1px solid var(--cal-border);flex-shrink:0;background:var(--cal-bg)}.uc-all-day-events{flex:1;position:relative;min-height:calc(var(--cal-event-height) + 6px);padding:2px 0}.uc-time-body{flex:1;overflow-y:auto;overflow-x:visible;position:relative;border-radius:0 0 var(--cal-radius) var(--cal-radius)}.uc-time-body::-webkit-scrollbar{width:6px}.uc-time-body::-webkit-scrollbar-track{background:0 0}.uc-time-body::-webkit-scrollbar-thumb{background:var(--cal-border-strong);border-radius:3px}.uc-time-grid-inner{display:flex;flex-direction:row;height:calc(24 * var(--cal-hour-height));position:relative}.uc-time-gutter{width:var(--cal-time-col-width);flex-shrink:0;border-right:1px solid var(--cal-border);position:relative}.uc-hour-cell{height:var(--cal-hour-height);position:relative;display:flex;align-items:flex-start;justify-content:flex-end;padding-right:8px}.uc-hour-label{font-size:11px;font-weight:500;color:var(--cal-text-subtle);user-select:none;pointer-events:none;white-space:nowrap;transform:translateY(-50%);margin-top:1px}.uc-time-columns{flex:1;display:grid;grid-template-columns:repeat(var(--uc-col-count,7),1fr);position:relative}.uc-time-col{position:relative;border-right:1px solid var(--cal-border);height:calc(24 * var(--cal-hour-height));cursor:pointer}.uc-time-col:last-child{border-right:none}.uc-time-col.uc-today{background:var(--cal-today-bg)}.uc-hour-row{height:var(--cal-hour-height);border-bottom:1px solid var(--cal-border);position:relative;pointer-events:none}.uc-half-hour-line{position:absolute;top:50%;left:0;right:0;border-top:1px dashed var(--cal-border);pointer-events:none}.uc-timed-event{position:absolute;background:var(--cal-event-bg);color:var(--cal-event-text);border-radius:var(--cal-event-border-radius);padding:3px 6px;cursor:pointer;display:flex;flex-direction:column;gap:1px;font-size:12px;font-weight:500;border-left:3px solid rgba(0,0,0,.15);transition:filter var(--cal-transition),box-shadow var(--cal-transition);z-index:2;min-height:18px}.uc-timed-event:hover{filter:brightness(.92);box-shadow:0 2px 8px rgba(0,0,0,.15);z-index:1000}.uc-timed-event .uc-event-title{font-weight:600;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.uc-timed-event .uc-event-time{font-size:11px;opacity:.85;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.uc-timed-event--short{flex-direction:row;align-items:center;gap:4px}.uc-timed-event--short .uc-event-time{flex-shrink:0}.uc-timed-event--short .uc-event-title{flex:1;min-width:0}.uc-now-indicator{position:absolute;left:0;right:0;pointer-events:none;z-index:10;display:flex;align-items:center}.uc-now-dot{width:10px;height:10px;border-radius:50%;background:var(--cal-now-color);flex-shrink:0;margin-left:-5px}.uc-now-line{flex:1;height:2px;background:var(--cal-now-color)}.uc-list-view{padding:0;max-height:650px;overflow-y:auto;overflow-x:hidden;border-radius:0 0 var(--cal-radius) var(--cal-radius)}.uc-list-view::-webkit-scrollbar{width:6px}.uc-list-view::-webkit-scrollbar-track{background:0 0}.uc-list-view::-webkit-scrollbar-thumb{background:var(--cal-border-strong);border-radius:3px}.uc-list-empty{display:flex;align-items:center;justify-content:center;min-height:300px;color:var(--cal-text-muted);font-size:14px}.uc-list-date-group{margin-bottom:24px;overflow:visible}.uc-list-date-group:last-child{margin-bottom:0}.uc-list-events{background:var(--cal-bg);overflow:visible}.uc-list-event{display:flex;align-items:flex-start;gap:12px;padding:12px 16px;border-bottom:1px solid var(--cal-border);cursor:pointer;transition:background var(--cal-transition);position:relative;overflow:visible}.uc-list-date-header{font-size:14px;font-weight:600;color:var(--cal-text);padding:12px 16px;background:var(--cal-bg-secondary);border-bottom:1px solid var(--cal-border);position:sticky;top:0;z-index:1;overflow:visible}.uc-list-event:hover{background:var(--cal-hover)}.uc-list-event:last-child{border-bottom:none}.uc-list-event-indicator{width:8px;height:8px;border-radius:50%;margin-top:4px;flex-shrink:0}.uc-list-event-time{font-size:13px;font-weight:500;color:var(--cal-text-secondary);min-width:80px;flex-shrink:0}.uc-list-event-content{flex:1;min-width:0}.uc-list-event-title{font-size:14px;font-weight:500;color:var(--cal-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.uc-calendar [data-tooltip]:not([data-tooltip=""]):hover::after,.uc-calendar [data-tooltip]:not([data-tooltip=""]):hover::before{opacity:1;visibility:visible;transition-delay:0.4s}.uc-calendar [data-tooltip]:not([data-tooltip=""])::before{content:attr(data-tooltip);position:absolute;bottom:calc(100% + var(--cal-tooltip-offset));left:50%;transform:translateX(-50%);background:var(--cal-tooltip-bg);color:var(--cal-tooltip-text);border:1px solid var(--cal-tooltip-border);box-shadow:var(--cal-tooltip-shadow);padding:var(--cal-tooltip-padding);border-radius:var(--cal-tooltip-radius);font-size:var(--cal-tooltip-font-size);font-weight:500;line-height:1.4;max-width:var(--cal-tooltip-max-width);width:max-content;white-space:pre-wrap;word-wrap:break-word;text-align:left;z-index:1000;pointer-events:none;opacity:0;visibility:hidden;transition:opacity .2s ease,visibility .2s ease}.uc-calendar [data-tooltip]:not([data-tooltip=""])::after{content:'';position:absolute;bottom:calc(100% + var(--cal-tooltip-offset) - 5px);left:50%;transform:translateX(-50%);width:0;height:0;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid var(--cal-tooltip-bg);z-index:1002;pointer-events:none;opacity:0;visibility:hidden;transition:opacity .2s ease,visibility .2s ease}.uc-calendar [data-tooltip]:not([data-tooltip=""])::before{filter:drop-shadow(0 1px 0 var(--cal-tooltip-border))}.uc-calendar [data-tooltip].uc-tooltip-left::before{left:auto;right:0;transform:translateX(0)}.uc-calendar [data-tooltip].uc-tooltip-left::after{left:auto;right:12px;transform:translateX(0)}.uc-calendar [data-tooltip].uc-tooltip-right::before{left:0;transform:translateX(0)}.uc-calendar [data-tooltip].uc-tooltip-right::after{left:12px;transform:translateX(0)}.uc-calendar [data-tooltip].uc-tooltip-bottom::before{bottom:auto;top:calc(100% + var(--cal-tooltip-offset));filter:drop-shadow(0 -1px 0 var(--cal-tooltip-border))}.uc-calendar [data-tooltip].uc-tooltip-bottom::after{bottom:auto;top:calc(100% + var(--cal-tooltip-offset) - 5px);border-top:5px solid var(--cal-tooltip-bg);border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:none;transform:translateX(-50%) rotate(180deg)}@media (max-width:768px){.uc-toolbar{padding:8px 10px}.uc-title{font-size:14px}.uc-toolbar-center{order:-1;width:100%;flex:none}.uc-toolbar-section{justify-content:center}.uc-view-btn{padding:5px 8px;font-size:12px}:root{--cal-time-col-width:52px;--cal-hour-height:52px;--cal-cell-min-height:88px;--cal-event-height:20px}.uc-week-day-num{width:24px;height:24px;font-size:13px}.uc-week-day-name{font-size:10px}.uc-hour-cell:nth-child(odd) .uc-hour-label{visibility:hidden}}@media (max-width:480px){.uc-today-btn{display:none}.uc-toolbar-section.uc-toolbar-right{gap:2px}}.uc-calendar.uc-no-grid .uc-day-cell,.uc-calendar.uc-no-grid .uc-day-header-row,.uc-calendar.uc-no-grid .uc-day-name-row,.uc-calendar.uc-no-grid .uc-grid-line,.uc-calendar.uc-no-grid .uc-hour-cell,.uc-calendar.uc-no-grid .uc-time-col,.uc-calendar.uc-no-grid .uc-time-gutter,.uc-calendar.uc-no-grid .uc-week-day-header,.uc-calendar.uc-no-grid .uc-week-row{border:none!important}.uc-calendar.uc-no-grid .uc-all-day-section{border-top:none!important;border-left:none!important;border-right:none!important}.uc-calendar.uc-no-border{border:none!important}.uc-calendar.uc-dark,.uc-dark .uc-calendar{--cal-bg:#1f2937;--cal-bg-secondary:#111827;--cal-text:#f9fafb;--cal-text-subtle:#9ca3af;--cal-text-muted:#6b7280;--cal-border:#374151;--cal-border-strong:#4b5563;--cal-hover:#374151;--cal-hover-strong:#4b5563;--cal-selected-bg:#78716c;--cal-today-bg:#57534e;--cal-primary-light:#57534e;--cal-toolbar-bg:#111827;--cal-tooltip-bg:#374151;--cal-tooltip-text:#f9fafb;--cal-tooltip-border:#4b5563;--cal-loading-bg:rgba(31, 41, 55, 0.7)}.uc-calendar.uc-dragging{cursor:grabbing!important;user-select:none;-webkit-user-select:none}.uc-calendar.uc-dragging *{cursor:grabbing!important}.uc-dragging-element{opacity:.8;box-shadow:0 4px 12px rgba(0,0,0,.3);transition:none!important}.uc-calendar[data-drag-enabled] .uc-event-bar,.uc-calendar[data-drag-enabled] .uc-timed-event{cursor:grab}.uc-calendar[data-drag-enabled] .uc-event-bar:active,.uc-calendar[data-drag-enabled] .uc-timed-event:active{cursor:grabbing}.uc-calendar.uc-dark .uc-dragging-element{box-shadow:0 4px 12px rgba(0,0,0,.6)}.uc-resize-handle{position:absolute;bottom:0;left:0;right:0;height:8px;cursor:ns-resize;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s}.uc-resize-handle::after{content:'';width:24px;height:3px;background:rgba(255,255,255,.6);border-radius:2px}.uc-timed-event:hover .uc-resize-handle{opacity:1}.uc-calendar.uc-dragging .uc-resize-handle{cursor:ns-resize!important}.uc-resize-handle-right{position:absolute;top:2px;bottom:2px;right:2px;width:6px;cursor:ew-resize;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s}.uc-resize-handle-right::after{content:'';width:2px;height:12px;background:rgba(255,255,255,.6);border-radius:1px}.uc-event-bar:hover .uc-resize-handle-right{opacity:1}.uc-calendar.uc-dragging .uc-resize-handle-right{cursor:ew-resize!important}.uc-event-bar--list{display:flex;align-items:center;gap:6px;padding:2px 6px;background:0 0!important;overflow:hidden}.uc-event-dot{flex-shrink:0;width:8px;height:8px;border-radius:50%}.uc-event-bar--list .uc-event-time{flex-shrink:0;font-size:11px;font-weight:500;color:var(--cal-text);opacity:.8}.uc-event-bar--list .uc-event-title{flex:1;font-size:12px;color:var(--cal-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.uc-calendar[data-drag-enabled] .uc-event-bar--list{cursor:grab}.uc-calendar[data-drag-enabled] .uc-event-bar--list:active{cursor:grabbing}@media print{.uc-toolbar{display:none}.uc-time-body{overflow:visible}.uc-calendar{border:none}}
12
+ :root{--cal-bg:#ffffff;--cal-bg-secondary:#f9fafb;--cal-text:#111827;--cal-text-subtle:#6b7280;--cal-text-muted:#9ca3af;--cal-border:#e5e7eb;--cal-border-strong:#d1d5db;--cal-primary:#4f46e5;--cal-primary-dark:#4338ca;--cal-primary-light:#eef2ff;--cal-event-bg:var(--cal-primary);--cal-event-text:#ffffff;--cal-event-border-radius:3px;--cal-today-bg:#eef2ff;--cal-today-text:var(--cal-primary);--cal-hover:#f9fafb;--cal-hover-strong:#f3f4f6;--cal-selected-bg:#ede9fe;--cal-font-family:inherit;--cal-font-size:13px;--cal-time-col-width:64px;--cal-hour-height:60px;--cal-event-height:22px;--cal-event-gap:2px;--cal-header-day-height:30px;--cal-day-name-height:36px;--cal-now-color:#ef4444;--cal-toolbar-bg:var(--cal-bg);--cal-radius:8px;--cal-shadow:0 1px 3px rgba(0,0,0,.08),0 1px 2px rgba(0,0,0,.06);--cal-transition:150ms ease;--cal-tooltip-bg:#1f2937;--cal-tooltip-text:#f9fafb;--cal-tooltip-border:#374151;--cal-tooltip-shadow:0 4px 12px rgba(0, 0, 0, 0.15);--cal-tooltip-max-width:250px;--cal-tooltip-padding:8px 12px;--cal-tooltip-radius:6px;--cal-tooltip-font-size:12px;--cal-tooltip-offset:8px;--cal-loading-bg:rgba(255, 255, 255, 0.7)}.uc-calendar{font-family:var(--cal-font-family);font-size:var(--cal-font-size);color:var(--cal-text);background:var(--cal-bg);border:1px solid var(--cal-border);border-radius:var(--cal-radius);overflow-x:visible;overflow-y:hidden;display:flex;flex-direction:column;height:100%;position:relative;-webkit-font-smoothing:antialiased}.uc-calendar *,.uc-calendar ::after,.uc-calendar ::before{box-sizing:border-box;margin:0;padding:0}.uc-toolbar{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) minmax(0,1fr);align-items:center;gap:8px;padding:8px 10px;background:var(--cal-toolbar-bg);border-bottom:1px solid var(--cal-border);border-radius:var(--cal-radius) var(--cal-radius) 0 0;flex-shrink:0}.uc-toolbar-section{display:flex;align-items:center;gap:4px}.uc-toolbar-left{justify-self:start;min-width:0}.uc-toolbar-right{justify-self:end;min-width:0}.uc-toolbar-center{justify-self:center;min-width:0;overflow:hidden}.uc-title{font-size:14px;font-weight:600;color:var(--cal-text);white-space:nowrap;letter-spacing:-.01em;display:inline-flex;align-items:baseline;gap:4px;overflow:hidden;text-overflow:ellipsis;min-width:0}.uc-title-main{text-transform:capitalize;overflow:hidden;text-overflow:ellipsis;flex-shrink:1}.uc-year-btn{background:0 0;border:none;font:inherit;font-weight:600;font-size:14px;color:var(--cal-primary);cursor:pointer;padding:1px 4px;border-radius:4px;line-height:inherit;text-decoration:underline;text-decoration-style:dotted;text-underline-offset:2px;transition:background var(--cal-transition),color var(--cal-transition);flex-shrink:0}.uc-year-btn.uc-open,.uc-year-btn:hover{background:var(--cal-primary-light);text-decoration:none}.uc-year-picker{position:absolute;top:calc(100% + 8px);left:50%;transform:translateX(-50%);background:var(--cal-bg);border:1px solid var(--cal-border);border-radius:10px;box-shadow:0 4px 24px rgba(0,0,0,.12);padding:10px;z-index:200;min-width:210px}.uc-year-picker-nav{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.uc-year-range{font-size:12px;font-weight:600;color:var(--cal-text-subtle)}.uc-year-nav-btn{background:0 0;border:none;font-size:18px;line-height:1;color:var(--cal-text);cursor:pointer;padding:2px 7px;border-radius:5px;font-family:inherit;transition:background var(--cal-transition)}.uc-year-nav-btn:hover{background:var(--cal-hover-strong)}.uc-year-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:4px}.uc-year-item{background:0 0;border:none;border-radius:6px;font-size:13px;font-weight:500;font-family:inherit;color:var(--cal-text);cursor:pointer;padding:7px 4px;text-align:center;transition:background var(--cal-transition),color var(--cal-transition)}.uc-year-item:hover{background:var(--cal-hover-strong)}.uc-year-item.uc-today-year{color:var(--cal-primary);font-weight:700}.uc-year-item.uc-active{background:var(--cal-primary);color:#fff;font-weight:700}.uc-btn{display:inline-flex;align-items:center;justify-content:center;gap:4px;border:1px solid var(--cal-border);background:var(--cal-bg);color:var(--cal-text);border-radius:6px;padding:4px 6px;font-size:12px;font-family:inherit;font-weight:500;cursor:pointer;white-space:nowrap;line-height:1.4;transition:background var(--cal-transition),border-color var(--cal-transition),color var(--cal-transition);user-select:none}.uc-btn:hover{background:var(--cal-hover-strong);border-color:var(--cal-border-strong)}.uc-btn:active{background:var(--cal-selected-bg)}.uc-btn:focus-visible{outline:2px solid var(--cal-primary);outline-offset:2px}.uc-btn:disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.uc-nav-btn{font-size:18px;padding:4px 6px;line-height:1;border-color:transparent;background:0 0}.uc-nav-btn:hover{border-color:var(--cal-border)}.uc-today-btn{padding:4px 6px}.uc-today-btn.uc-active{background:var(--cal-primary-light);color:var(--cal-primary);font-weight:600;border-color:transparent}.uc-view-switcher{display:flex;border:1px solid var(--cal-border);border-radius:6px;overflow:hidden}.uc-view-btn{border:none;border-radius:0;border-right:1px solid var(--cal-border);background:0 0;color:var(--cal-text-subtle);font-weight:500;padding:4px 6px;font-size:12px}.uc-view-btn:last-child{border-right:none}.uc-view-btn:hover{background:var(--cal-hover-strong);color:var(--cal-text);border-color:transparent}.uc-view-btn.uc-active{background:var(--cal-primary-light);color:var(--cal-primary);font-weight:600}.uc-view-dropdown{display:none;position:relative}.uc-view-dropdown-btn{display:flex;align-items:center;justify-content:center;padding:4px 8px;font-size:16px}.uc-view-icon{line-height:1}.uc-dropdown-menu{display:none;position:absolute;top:calc(100% + 4px);right:0;background:var(--cal-bg);border:1px solid var(--cal-border);border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,.15);z-index:1000;min-width:120px;overflow:hidden}.uc-view-dropdown.uc-open .uc-dropdown-menu{display:block}.uc-dropdown-item{display:block;width:100%;padding:8px 12px;background:0 0;border:none;color:var(--cal-text);font-size:13px;font-family:inherit;text-align:left;cursor:pointer;transition:background var(--cal-transition)}.uc-dropdown-item:hover{background:var(--cal-hover-strong)}.uc-dropdown-item.uc-active{background:var(--cal-primary-light);color:var(--cal-primary);font-weight:600}.uc-dropdown-item:disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.uc-dropdown-separator{height:1px;background:var(--cal-border);margin:4px 0}@media (min-width:641px){.uc-view-switcher{display:flex}.uc-view-dropdown{display:none}}@media (max-width:640px){.uc-view-switcher{display:none}.uc-view-dropdown{display:block}.uc-today-btn{display:none}}.uc-loading{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:var(--cal-loading-bg);z-index:100;pointer-events:none}.uc-spinner{width:28px;height:28px;border:3px solid var(--cal-border);border-top-color:var(--cal-primary);border-radius:50%;animation:uc-spin .6s linear infinite}@keyframes uc-spin{to{transform:rotate(360deg)}}.uc-view-container{flex:1;min-height:0;overflow:visible;display:flex;flex-direction:column}.uc-view-container:first-child .uc-month-header,.uc-view-container:first-child .uc-week-header{border-radius:var(--cal-radius) var(--cal-radius) 0 0}.uc-month-view{display:flex;flex-direction:column;flex:1;min-height:0;overflow-x:clip;overflow-y:visible;border-radius:0 0 var(--cal-radius) var(--cal-radius)}.uc-calendar[data-height-constrained=true] .uc-month-body,.uc-calendar[data-height-constrained=true] .uc-month-view{overflow-y:hidden;overflow-x:clip}.uc-month-header{display:grid;grid-template-columns:repeat(7,1fr);border-bottom:1px solid var(--cal-border);flex-shrink:0}.uc-month-day-name{height:var(--cal-day-name-height,36px);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--cal-text-subtle);user-select:none}.uc-month-body{flex:1;display:flex;flex-direction:column;min-height:0;overflow-x:clip;overflow-y:visible}.uc-week-row{flex:1;position:relative;min-height:0;overflow:visible;border-bottom:1px solid var(--cal-border)}.uc-week-row:last-child{border-bottom:none;border-radius:0 0 var(--cal-radius) var(--cal-radius)}.uc-week-cells{position:absolute;inset:0;display:grid;grid-template-columns:repeat(7,1fr);z-index:1;overflow:visible}.uc-day-cell{border-right:1px solid var(--cal-border);padding:4px 6px 4px 6px;cursor:pointer;transition:background var(--cal-transition)}.uc-day-cell:last-child{border-right:none}.uc-day-cell:hover{background:var(--cal-hover)}.uc-day-cell.uc-today{background:var(--cal-today-bg)}.uc-day-cell.uc-other-month .uc-day-number{color:var(--cal-text-muted)}.uc-day-number{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;font-size:13px;font-weight:500;border-radius:50%;color:var(--cal-text);cursor:pointer;transition:background var(--cal-transition),color var(--cal-transition);line-height:1}.uc-day-number:hover{background:var(--cal-hover-strong)}.uc-today .uc-day-number{background:var(--cal-primary);color:#fff;font-weight:700}.uc-today .uc-day-number:hover{background:var(--cal-primary-dark)}.uc-week-events{position:absolute;inset:0;z-index:2;pointer-events:none;overflow:visible}.uc-event-bar{position:absolute;height:var(--cal-event-height);background:var(--cal-event-bg);color:var(--cal-event-text);border-radius:var(--cal-event-border-radius);display:flex;align-items:center;gap:4px;padding:0 6px;cursor:pointer;pointer-events:auto;white-space:nowrap;font-size:12px;font-weight:500;transition:filter var(--cal-transition),opacity var(--cal-transition);z-index:3}.uc-event-bar:hover{filter:brightness(.92);z-index:1000}.uc-event-bar:active{filter:brightness(.85)}.uc-event-bar.uc-continues-left{border-top-left-radius:0;border-bottom-left-radius:0}.uc-event-bar.uc-continues-right{border-top-right-radius:0;border-bottom-right-radius:0}.uc-event-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}.uc-event-time{font-size:11px;opacity:.85;flex-shrink:0}.uc-more-link{position:absolute;height:16px;display:flex;align-items:center;padding:0 6px;font-size:10px;font-weight:600;color:var(--cal-text-subtle);cursor:pointer;pointer-events:auto;border-radius:var(--cal-event-border-radius);white-space:nowrap;transition:background var(--cal-transition),color var(--cal-transition);z-index:3}.uc-more-link:hover{background:var(--cal-hover-strong);color:var(--cal-text)}.uc-day-view,.uc-week-view{display:flex;flex-direction:column;flex:1;min-height:0;overflow-x:clip;overflow-y:visible;border-radius:0 0 var(--cal-radius) var(--cal-radius)}.uc-calendar:not([data-height-constrained=true]) .uc-day-view,.uc-calendar:not([data-height-constrained=true]) .uc-week-view{max-height:650px}.uc-week-header{display:flex;border-bottom:1px solid var(--cal-border);flex-shrink:0;background:var(--cal-bg)}.uc-time-gutter-spacer{width:var(--cal-time-col-width);flex-shrink:0;border-right:1px solid var(--cal-border)}.uc-all-day-label{display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--cal-text-muted);white-space:nowrap}.uc-week-day-headers{flex:1;display:grid;grid-template-columns:repeat(7,1fr)}.uc-week-day-headers.uc-day-header-single{grid-template-columns:1fr}.uc-week-day-header{padding:8px 4px;display:flex;flex-direction:column;align-items:center;gap:2px;border-right:1px solid var(--cal-border);cursor:default}.uc-week-day-header:last-child{border-right:none}.uc-week-day-name{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--cal-text-subtle);user-select:none}.uc-week-day-num{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;font-size:16px;font-weight:600;border-radius:50%;color:var(--cal-text);cursor:pointer;transition:background var(--cal-transition),color var(--cal-transition)}.uc-week-day-num:hover{background:var(--cal-hover-strong)}.uc-week-day-header.uc-today .uc-week-day-name{color:var(--cal-primary)}.uc-week-day-header.uc-today .uc-week-day-num{background:var(--cal-primary);color:#fff}.uc-week-day-header.uc-today .uc-week-day-num:hover{background:var(--cal-primary-dark)}.uc-all-day-section{display:flex;border-bottom:1px solid var(--cal-border);flex-shrink:0;background:var(--cal-bg)}.uc-all-day-events{flex:1;position:relative;min-height:calc(var(--cal-event-height) + 6px);padding:2px 0}.uc-time-body{flex:1;min-height:0;overflow-y:auto;overflow-x:clip;position:relative;border-radius:0 0 var(--cal-radius) var(--cal-radius)}.uc-time-body::-webkit-scrollbar{width:6px}.uc-time-body::-webkit-scrollbar-track{background:0 0}.uc-time-body::-webkit-scrollbar-thumb{background:var(--cal-border-strong);border-radius:3px}.uc-time-grid-inner{display:flex;flex-direction:row;height:calc(24 * var(--cal-hour-height));position:relative;max-width:100%}.uc-time-gutter{width:var(--cal-time-col-width);flex-shrink:0;border-right:1px solid var(--cal-border);position:relative}.uc-hour-cell{height:var(--cal-hour-height);position:relative;display:flex;align-items:flex-start;justify-content:flex-end;padding-right:8px}.uc-hour-label{font-size:11px;font-weight:500;color:var(--cal-text-subtle);user-select:none;pointer-events:none;white-space:nowrap;transform:translateY(-50%);margin-top:1px}.uc-time-columns{flex:1;display:grid;grid-template-columns:repeat(var(--uc-col-count,7),1fr);position:relative}.uc-time-col{position:relative;border-right:1px solid var(--cal-border);height:calc(24 * var(--cal-hour-height));cursor:pointer}.uc-time-col:last-child{border-right:none}.uc-time-col.uc-today{background:var(--cal-today-bg)}.uc-hour-row{height:var(--cal-hour-height);border-bottom:1px solid var(--cal-border);position:relative;pointer-events:none}.uc-half-hour-line{position:absolute;top:50%;left:0;right:0;border-top:1px dashed var(--cal-border);pointer-events:none}.uc-timed-event{position:absolute;background:var(--cal-event-bg);color:var(--cal-event-text);border-radius:var(--cal-event-border-radius);padding:3px 6px;cursor:pointer;display:flex;flex-direction:column;gap:1px;font-size:12px;font-weight:500;border-left:3px solid rgba(0,0,0,.15);transition:filter var(--cal-transition),box-shadow var(--cal-transition);z-index:2;min-height:18px}.uc-timed-event:hover{filter:brightness(.92);box-shadow:0 2px 8px rgba(0,0,0,.15);z-index:1000}.uc-timed-event .uc-event-title{font-weight:600;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.uc-timed-event .uc-event-time{font-size:11px;opacity:.85;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.uc-timed-event--short{flex-direction:row;align-items:center;gap:4px}.uc-timed-event--short .uc-event-time{flex-shrink:0}.uc-timed-event--short .uc-event-title{flex:1;min-width:0}.uc-now-indicator{position:absolute;left:0;right:0;pointer-events:none;z-index:10;display:flex;align-items:center}.uc-now-dot{width:10px;height:10px;border-radius:50%;background:var(--cal-now-color);flex-shrink:0;margin-left:-5px}.uc-now-line{flex:1;height:2px;background:var(--cal-now-color)}.uc-list-view{padding:0;flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;border-radius:0 0 var(--cal-radius) var(--cal-radius)}.uc-calendar:not([data-height-constrained=true]) .uc-list-view{max-height:650px}.uc-list-view::-webkit-scrollbar{width:6px}.uc-list-view::-webkit-scrollbar-track{background:0 0}.uc-list-view::-webkit-scrollbar-thumb{background:var(--cal-border-strong);border-radius:3px}.uc-list-empty{display:flex;align-items:center;justify-content:center;min-height:300px;color:var(--cal-text-muted);font-size:14px}.uc-list-date-group{margin-bottom:24px;overflow:visible}.uc-list-date-group:last-child{margin-bottom:0}.uc-list-events{background:var(--cal-bg);overflow:visible}.uc-list-event{display:flex;align-items:flex-start;gap:12px;padding:12px 16px;border-bottom:1px solid var(--cal-border);cursor:pointer;transition:background var(--cal-transition);position:relative;overflow:visible}.uc-list-date-header{font-size:14px;font-weight:600;color:var(--cal-text);padding:12px 16px;background:var(--cal-bg-secondary);border-bottom:1px solid var(--cal-border);position:sticky;top:0;z-index:1;overflow:visible}.uc-list-event:hover{background:var(--cal-hover)}.uc-list-event:last-child{border-bottom:none}.uc-list-event-indicator{width:8px;height:8px;border-radius:50%;margin-top:4px;flex-shrink:0}.uc-list-event-time{font-size:13px;font-weight:500;color:var(--cal-text-secondary);min-width:80px;flex-shrink:0}.uc-list-event-content{flex:1;min-width:0}.uc-list-event-title{font-size:14px;font-weight:500;color:var(--cal-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.uc-calendar [data-tooltip]:not([data-tooltip=""]):hover::after,.uc-calendar [data-tooltip]:not([data-tooltip=""]):hover::before{opacity:1;visibility:visible;transition-delay:0.4s}.uc-calendar [data-tooltip]:not([data-tooltip=""])::before{content:attr(data-tooltip);position:absolute;bottom:calc(100% + var(--cal-tooltip-offset));left:50%;transform:translateX(-50%);background:var(--cal-tooltip-bg);color:var(--cal-tooltip-text);border:1px solid var(--cal-tooltip-border);box-shadow:var(--cal-tooltip-shadow);padding:var(--cal-tooltip-padding);border-radius:var(--cal-tooltip-radius);font-size:var(--cal-tooltip-font-size);font-weight:500;line-height:1.4;max-width:var(--cal-tooltip-max-width);width:max-content;white-space:pre-wrap;word-wrap:break-word;text-align:left;z-index:99999;pointer-events:none;opacity:0;visibility:hidden;transition:opacity .2s ease,visibility .2s ease}.uc-calendar [data-tooltip]:not([data-tooltip=""])::after{content:'';position:absolute;bottom:calc(100% + var(--cal-tooltip-offset) - 5px);left:50%;transform:translateX(-50%);width:0;height:0;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid var(--cal-tooltip-bg);z-index:1002;pointer-events:none;opacity:0;visibility:hidden;transition:opacity .2s ease,visibility .2s ease}.uc-calendar [data-tooltip]:not([data-tooltip=""])::before{filter:drop-shadow(0 1px 0 var(--cal-tooltip-border))}.uc-calendar [data-tooltip].uc-tooltip-left::before{left:auto;right:0;transform:translateX(0)}.uc-calendar [data-tooltip].uc-tooltip-left::after{left:auto;right:12px;transform:translateX(0)}.uc-calendar [data-tooltip].uc-tooltip-right::before{left:0;transform:translateX(0)}.uc-calendar [data-tooltip].uc-tooltip-right::after{left:12px;transform:translateX(0)}.uc-calendar [data-tooltip].uc-tooltip-bottom::before{bottom:auto;top:calc(100% + var(--cal-tooltip-offset));filter:drop-shadow(0 -1px 0 var(--cal-tooltip-border))}.uc-calendar [data-tooltip].uc-tooltip-bottom::after{bottom:auto;top:calc(100% + var(--cal-tooltip-offset) - 5px);border-top:5px solid var(--cal-tooltip-bg);border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:none;transform:translateX(-50%) rotate(180deg)}@media (max-width:768px){.uc-view-btn{padding:5px 8px;font-size:12px}:root{--cal-time-col-width:52px;--cal-hour-height:52px;--cal-event-height:20px}.uc-week-day-num{width:24px;height:24px;font-size:13px}.uc-week-day-name{font-size:10px}.uc-hour-cell:nth-child(odd) .uc-hour-label{visibility:hidden}}.uc-calendar.uc-no-grid .uc-day-cell,.uc-calendar.uc-no-grid .uc-day-header-row,.uc-calendar.uc-no-grid .uc-day-name-row,.uc-calendar.uc-no-grid .uc-grid-line,.uc-calendar.uc-no-grid .uc-hour-cell,.uc-calendar.uc-no-grid .uc-time-col,.uc-calendar.uc-no-grid .uc-time-gutter,.uc-calendar.uc-no-grid .uc-week-day-header,.uc-calendar.uc-no-grid .uc-week-row{border:none!important}.uc-calendar.uc-no-grid .uc-all-day-section{border-top:none!important;border-left:none!important;border-right:none!important}.uc-calendar.uc-no-border{border:none!important}.uc-calendar.uc-dark,.uc-dark .uc-calendar{--cal-bg:#1f2937;--cal-bg-secondary:#111827;--cal-text:#f9fafb;--cal-text-subtle:#9ca3af;--cal-text-muted:#6b7280;--cal-border:#374151;--cal-border-strong:#4b5563;--cal-hover:#374151;--cal-hover-strong:#4b5563;--cal-selected-bg:#78716c;--cal-today-bg:#57534e;--cal-primary-light:#57534e;--cal-toolbar-bg:#111827;--cal-tooltip-bg:#374151;--cal-tooltip-text:#f9fafb;--cal-tooltip-border:#4b5563;--cal-loading-bg:rgba(31, 41, 55, 0.7)}.uc-calendar.uc-dragging{cursor:grabbing!important;user-select:none;-webkit-user-select:none}.uc-calendar.uc-dragging *{cursor:grabbing!important}.uc-dragging-element{opacity:.8;box-shadow:0 4px 12px rgba(0,0,0,.3);transition:none!important}.uc-calendar[data-drag-enabled] .uc-event-bar,.uc-calendar[data-drag-enabled] .uc-timed-event{cursor:grab}.uc-calendar[data-drag-enabled] .uc-event-bar:active,.uc-calendar[data-drag-enabled] .uc-timed-event:active{cursor:grabbing}.uc-calendar.uc-dark .uc-dragging-element{box-shadow:0 4px 12px rgba(0,0,0,.6)}.uc-resize-handle{position:absolute;bottom:0;left:0;right:0;height:8px;cursor:ns-resize;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s}.uc-resize-handle::after{content:'';width:24px;height:3px;background:rgba(255,255,255,.6);border-radius:2px}.uc-timed-event:hover .uc-resize-handle{opacity:1}.uc-calendar.uc-dragging .uc-resize-handle{cursor:ns-resize!important}.uc-resize-handle-right{position:absolute;top:2px;bottom:2px;right:2px;width:6px;cursor:ew-resize;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s}.uc-resize-handle-right::after{content:'';width:2px;height:12px;background:rgba(255,255,255,.6);border-radius:1px}.uc-event-bar:hover .uc-resize-handle-right{opacity:1}.uc-calendar.uc-dragging .uc-resize-handle-right{cursor:ew-resize!important}.uc-event-bar--list{display:flex;align-items:center;gap:6px;padding:2px 6px;background:0 0!important;overflow:hidden}.uc-event-dot{flex-shrink:0;width:8px;height:8px;border-radius:50%}.uc-event-bar--list .uc-event-time{flex-shrink:0;font-size:11px;font-weight:500;color:var(--cal-text);opacity:.8}.uc-event-bar--list .uc-event-title{flex:1;font-size:12px;color:var(--cal-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.uc-calendar[data-drag-enabled] .uc-event-bar--list{cursor:grab}.uc-calendar[data-drag-enabled] .uc-event-bar--list:active{cursor:grabbing}@media print{.uc-toolbar{display:none}.uc-time-body{overflow:visible}.uc-calendar{border:none}}
@@ -1,14 +1,14 @@
1
1
  /**
2
- * SimpleCalendarJs v3.0.6
2
+ * SimpleCalendarJs v3.0.8
3
3
  * A clean, modern, and feature-rich JavaScript calendar component with zero dependencies
4
4
  *
5
5
  * @author Pedro Lopes <simplecalendarjs@gmail.com>
6
6
  * @homepage https://www.simplecalendarjs.com
7
7
  * @license SEE LICENSE IN LICENSE
8
8
  */
9
- !function(t,e){"undefined"!=typeof module&&module.exports?module.exports=e():"function"==typeof define&&define.amd?define([],e):t.SimpleCalendarJs=e()}("undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:this,function(){"use strict";function t(t){const e=new Date(t);return e.setHours(0,0,0,0),e}function e(t){const e=new Date(t);return e.setHours(23,59,59,999),e}function a(t,e){const a=new Date(t);return a.setDate(a.getDate()+e),a}function s(t,e){return t.getFullYear()===e.getFullYear()&&t.getMonth()===e.getMonth()&&t.getDate()===e.getDate()}function n(t){return s(t,new Date)}function i(e,a){return Math.floor((t(a)-t(e))/864e5)}function o(t){return t instanceof Date?t:new Date(t)}function r(e,s){const n=e.getDay(),i=t(a(e,-((n-s+7)%7)));return Array.from({length:7},(t,e)=>a(i,e))}function l(t,e,s){const n=new Date(t,e,1),i=new Date(t,e+1,0),o=(n.getDay()-s+7)%7,r=7*Math.ceil((o+i.getDate())/7),l=a(n,-o);return Array.from({length:r},(t,e)=>a(l,e))}function d(t,e,a){const s={hour:"numeric",hour12:!a};return 0!==t.getMinutes()&&(s.minute="2-digit"),new Intl.DateTimeFormat(e,s).format(t)}function c(t,e,a){return Array.from({length:7},(s,n)=>{const i=new Date(2025,0,5+(e+n)%7);return new Intl.DateTimeFormat(t,{weekday:a}).format(i)})}function h(t){return String(t).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}const u={"en-US":{today:"Today",month:"Month",week:"Week",day:"Day",list:"List",allDay:"All-Day"},"en-GB":{today:"Today",month:"Month",week:"Week",day:"Day",list:"List",allDay:"All-Day"},"es-ES":{today:"Hoy",month:"Mes",week:"Semana",day:"Día",list:"Lista",allDay:"Todo el día"},"es-MX":{today:"Hoy",month:"Mes",week:"Semana",day:"Día",list:"Lista",allDay:"Todo el día"},"fr-FR":{today:"Aujourd'hui",month:"Mois",week:"Semaine",day:"Jour",list:"Liste",allDay:"Toute la journée"},"fr-CA":{today:"Aujourd'hui",month:"Mois",week:"Semaine",day:"Jour",list:"Liste",allDay:"Toute la journée"},"de-DE":{today:"Heute",month:"Monat",week:"Woche",day:"Tag",list:"Liste",allDay:"Ganztägig"},"it-IT":{today:"Oggi",month:"Mese",week:"Settimana",day:"Giorno",list:"Elenco",allDay:"Tutto il giorno"},"pt-PT":{today:"Hoje",month:"Mês",week:"Semana",day:"Dia",list:"Lista",allDay:"Dia todo"},"pt-BR":{today:"Hoje",month:"Mês",week:"Semana",day:"Dia",list:"Lista",allDay:"Dia todo"},"nl-NL":{today:"Vandaag",month:"Maand",week:"Week",day:"Dag",list:"Lijst",allDay:"Hele dag"},"pl-PL":{today:"Dzisiaj",month:"Miesiąc",week:"Tydzień",day:"Dzień",list:"Lista",allDay:"Cały dzień"},"ru-RU":{today:"Сегодня",month:"Месяц",week:"Неделя",day:"День",list:"Список",allDay:"Весь день"},"tr-TR":{today:"Bugün",month:"Ay",week:"Hafta",day:"Gün",list:"Liste",allDay:"Tüm gün"},"sv-SE":{today:"Idag",month:"Månad",week:"Vecka",day:"Dag",list:"Lista",allDay:"Heldag"},"da-DK":{today:"I dag",month:"Måned",week:"Uge",day:"Dag",list:"Liste",allDay:"Hele dagen"},"fi-FI":{today:"Tänään",month:"Kuukausi",week:"Viikko",day:"Päivä",list:"Lista",allDay:"Koko päivä"},"no-NO":{today:"I dag",month:"Måned",week:"Uke",day:"Dag",list:"Liste",allDay:"Hele dagen"},"cs-CZ":{today:"Dnes",month:"Měsíc",week:"Týden",day:"Den",list:"Seznam",allDay:"Celý den"},"hu-HU":{today:"Ma",month:"Hónap",week:"Hét",day:"Nap",list:"Lista",allDay:"Egész nap"},"ro-RO":{today:"Astăzi",month:"Lună",week:"Săptămână",day:"Zi",list:"Listă",allDay:"Toată ziua"},"el-GR":{today:"Σήμερα",month:"Μήνας",week:"Εβδομάδα",day:"Ημέρα",list:"Λίστα",allDay:"Ολοήμερο"},"ja-JP":{today:"今日",month:"月",week:"週",day:"日",list:"リスト",allDay:"終日"},"ko-KR":{today:"오늘",month:"월",week:"주",day:"일",list:"목록",allDay:"종일"},"zh-CN":{today:"今天",month:"月",week:"周",day:"日",list:"列表",allDay:"全天"},"zh-TW":{today:"今天",month:"月",week:"週",day:"日",list:"列表",allDay:"全天"},"ar-SA":{today:"اليوم",month:"شهر",week:"أسبوع",day:"يوم",list:"قائمة",allDay:"طوال اليوم"},"he-IL":{today:"היום",month:"חודש",week:"שבוע",day:"יום",list:"רשימה",allDay:"כל היום"},"hi-IN":{today:"आज",month:"महीना",week:"सप्ताह",day:"दिन",list:"सूची",allDay:"पूरे दिन"},"th-TH":{today:"วันนี้",month:"เดือน",week:"สัปดาห์",day:"วัน",list:"รายการ",allDay:"ตลอดวัน"},"vi-VN":{today:"Hôm nay",month:"Tháng",week:"Tuần",day:"Ngày",list:"Danh sách",allDay:"Cả ngày"},"id-ID":{today:"Hari ini",month:"Bulan",week:"Minggu",day:"Hari",list:"Daftar",allDay:"Sepanjang hari"},"ms-MY":{today:"Hari ini",month:"Bulan",week:"Minggu",day:"Hari",list:"Senarai",allDay:"Sepanjang hari"},"uk-UA":{today:"Сьогодні",month:"Місяць",week:"Тиждень",day:"День",list:"Список",allDay:"Весь день"}};function _(t,e){const a=t.split("-")[0];return(u[t]||u[a]||u["en-US"])[e]}function v(t){return!!t.allDay||!s(t.start,t.end)}function g(a,n){const o=t(n[0]),r=e(n[n.length-1]),l=a.filter(t=>t.start<=r&&t.end>=o).map(a=>({...a,_visStart:new Date(Math.max(a.start.getTime(),o.getTime())),_visEnd:new Date(Math.min(a.end.getTime(),r.getTime())),_isStart:t(a.start)>=o,_isEnd:e(a.end)<=r}));l.sort((t,e)=>{const a=t.start-e.start;if(0!==a)return a;const s=i(t._visStart,t._visEnd);return i(e._visStart,e._visEnd)-s||(t._origStart||t.start)-(e._origStart||e.start)});const d=[],c=[];for(const t of l){const e=n.findIndex(e=>s(e,t._visStart)),a=n.findIndex(e=>s(e,t._visEnd)),i=-1===e?0:e,o=-1===a?n.length-1:a;let r=d.findIndex(t=>t<=i);-1===r?(r=d.length,d.push(o+1)):d[r]=o+1,c.push({event:t,startCol:i,endCol:o,slot:r,isStart:t._isStart,isEnd:t._isEnd})}return c}
9
+ !function(t,e){"undefined"!=typeof module&&module.exports?module.exports=e():"function"==typeof define&&define.amd?define([],e):t.SimpleCalendarJs=e()}("undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:this,function(){"use strict";function t(t){const e=new Date(t);return e.setHours(0,0,0,0),e}function e(t){const e=new Date(t);return e.setHours(23,59,59,999),e}function a(t,e){const a=new Date(t);return a.setDate(a.getDate()+e),a}function s(t,e){return t.getFullYear()===e.getFullYear()&&t.getMonth()===e.getMonth()&&t.getDate()===e.getDate()}function n(t){return s(t,new Date)}function i(e,a){return Math.floor((t(a)-t(e))/864e5)}function o(t){return t instanceof Date?t:new Date(t)}function r(e,s){const n=e.getDay(),i=t(a(e,-((n-s+7)%7)));return Array.from({length:7},(t,e)=>a(i,e))}function l(t,e,s){const n=new Date(t,e,1),i=new Date(t,e+1,0),o=(n.getDay()-s+7)%7,r=7*Math.ceil((o+i.getDate())/7),l=a(n,-o);return Array.from({length:r},(t,e)=>a(l,e))}function c(t,e,a){const s={hour:"numeric",hour12:!a};return 0!==t.getMinutes()&&(s.minute="2-digit"),new Intl.DateTimeFormat(e,s).format(t)}function d(t,e,a){return Array.from({length:7},(s,n)=>{const i=new Date(2025,0,5+(e+n)%7);return new Intl.DateTimeFormat(t,{weekday:a}).format(i)})}function h(t){return String(t).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}const u={"en-US":{today:"Today",month:"Month",week:"Week",day:"Day",list:"List",allDay:"All-Day"},"en-GB":{today:"Today",month:"Month",week:"Week",day:"Day",list:"List",allDay:"All-Day"},"es-ES":{today:"Hoy",month:"Mes",week:"Semana",day:"Día",list:"Lista",allDay:"Todo el día"},"es-MX":{today:"Hoy",month:"Mes",week:"Semana",day:"Día",list:"Lista",allDay:"Todo el día"},"fr-FR":{today:"Aujourd'hui",month:"Mois",week:"Semaine",day:"Jour",list:"Liste",allDay:"Toute la journée"},"fr-CA":{today:"Aujourd'hui",month:"Mois",week:"Semaine",day:"Jour",list:"Liste",allDay:"Toute la journée"},"de-DE":{today:"Heute",month:"Monat",week:"Woche",day:"Tag",list:"Liste",allDay:"Ganztägig"},"it-IT":{today:"Oggi",month:"Mese",week:"Settimana",day:"Giorno",list:"Elenco",allDay:"Tutto il giorno"},"pt-PT":{today:"Hoje",month:"Mês",week:"Semana",day:"Dia",list:"Lista",allDay:"Dia todo"},"pt-BR":{today:"Hoje",month:"Mês",week:"Semana",day:"Dia",list:"Lista",allDay:"Dia todo"},"nl-NL":{today:"Vandaag",month:"Maand",week:"Week",day:"Dag",list:"Lijst",allDay:"Hele dag"},"pl-PL":{today:"Dzisiaj",month:"Miesiąc",week:"Tydzień",day:"Dzień",list:"Lista",allDay:"Cały dzień"},"ru-RU":{today:"Сегодня",month:"Месяц",week:"Неделя",day:"День",list:"Список",allDay:"Весь день"},"tr-TR":{today:"Bugün",month:"Ay",week:"Hafta",day:"Gün",list:"Liste",allDay:"Tüm gün"},"sv-SE":{today:"Idag",month:"Månad",week:"Vecka",day:"Dag",list:"Lista",allDay:"Heldag"},"da-DK":{today:"I dag",month:"Måned",week:"Uge",day:"Dag",list:"Liste",allDay:"Hele dagen"},"fi-FI":{today:"Tänään",month:"Kuukausi",week:"Viikko",day:"Päivä",list:"Lista",allDay:"Koko päivä"},"no-NO":{today:"I dag",month:"Måned",week:"Uke",day:"Dag",list:"Liste",allDay:"Hele dagen"},"cs-CZ":{today:"Dnes",month:"Měsíc",week:"Týden",day:"Den",list:"Seznam",allDay:"Celý den"},"hu-HU":{today:"Ma",month:"Hónap",week:"Hét",day:"Nap",list:"Lista",allDay:"Egész nap"},"ro-RO":{today:"Astăzi",month:"Lună",week:"Săptămână",day:"Zi",list:"Listă",allDay:"Toată ziua"},"el-GR":{today:"Σήμερα",month:"Μήνας",week:"Εβδομάδα",day:"Ημέρα",list:"Λίστα",allDay:"Ολοήμερο"},"ja-JP":{today:"今日",month:"月",week:"週",day:"日",list:"リスト",allDay:"終日"},"ko-KR":{today:"오늘",month:"월",week:"주",day:"일",list:"목록",allDay:"종일"},"zh-CN":{today:"今天",month:"月",week:"周",day:"日",list:"列表",allDay:"全天"},"zh-TW":{today:"今天",month:"月",week:"週",day:"日",list:"列表",allDay:"全天"},"ar-SA":{today:"اليوم",month:"شهر",week:"أسبوع",day:"يوم",list:"قائمة",allDay:"طوال اليوم"},"he-IL":{today:"היום",month:"חודש",week:"שבוע",day:"יום",list:"רשימה",allDay:"כל היום"},"hi-IN":{today:"आज",month:"महीना",week:"सप्ताह",day:"दिन",list:"सूची",allDay:"पूरे दिन"},"th-TH":{today:"วันนี้",month:"เดือน",week:"สัปดาห์",day:"วัน",list:"รายการ",allDay:"ตลอดวัน"},"vi-VN":{today:"Hôm nay",month:"Tháng",week:"Tuần",day:"Ngày",list:"Danh sách",allDay:"Cả ngày"},"id-ID":{today:"Hari ini",month:"Bulan",week:"Minggu",day:"Hari",list:"Daftar",allDay:"Sepanjang hari"},"ms-MY":{today:"Hari ini",month:"Bulan",week:"Minggu",day:"Hari",list:"Senarai",allDay:"Sepanjang hari"},"uk-UA":{today:"Сьогодні",month:"Місяць",week:"Тиждень",day:"День",list:"Список",allDay:"Весь день"}};function v(t,e){const a=t.split("-")[0];return(u[t]||u[a]||u["en-US"])[e]}function _(t){return!!t.allDay||!s(t.start,t.end)}function g(a,n){const o=t(n[0]),r=e(n[n.length-1]),l=a.filter(t=>t.start<=r&&t.end>=o).map(a=>({...a,_visStart:new Date(Math.max(a.start.getTime(),o.getTime())),_visEnd:new Date(Math.min(a.end.getTime(),r.getTime())),_isStart:t(a.start)>=o,_isEnd:e(a.end)<=r}));l.sort((t,e)=>{const a=t.start-e.start;if(0!==a)return a;const s=i(t._visStart,t._visEnd);return i(e._visStart,e._visEnd)-s||(t._origStart||t.start)-(e._origStart||e.start)});const c=[],d=[];for(const t of l){const e=n.findIndex(e=>s(e,t._visStart)),a=n.findIndex(e=>s(e,t._visEnd)),i=-1===e?0:e,o=-1===a?n.length-1:a;let r=c.findIndex(t=>t<=i);-1===r?(r=c.length,c.push(o+1)):c[r]=o+1,d.push({event:t,startCol:i,endCol:o,slot:r,isStart:t._isStart,isEnd:t._isEnd})}return d}
10
10
  /* ============================================================
11
11
  ES MODULE EXPORT
12
12
  Also available as window.SimpleCalendarJs via the IIFE wrapper.
13
13
  ============================================================ */
14
- return class{constructor(e,a={}){if("string"==typeof e){if(this._el=document.querySelector(e),!this._el)throw new Error(`SimpleCalendarJs: no element for "${e}"`)}else this._el=e;this._opts=Object.assign({defaultView:"month",defaultDate:null,weekStartsOn:0,locale:"default",weekdayFormat:"short",use24Hour:!1,showTimeInItems:!0,showGridLines:!0,monthTimedEventStyle:"list",showToolbar:!0,showTodayButton:!0,showNavigation:!0,showTitle:!0,showYearPicker:!0,showViewSwitcher:!0,showTooltips:!0,showBorder:!0,maxEventsPerCell:-1,listDaysForward:30,enabledViews:["month","week","day"],enableDragDrop:!1,enableResize:!1,fetchEvents:null,onEventClick:null,onSlotClick:null,onViewChange:null,onNavigate:null,onEventDrop:null},a),this._view=this._opts.defaultView,this._date=t(this._opts.defaultDate||new Date),this._events=[],this._cachedRange=null,this._cachedEvents=[],this._nowInterval=null,this._yearPickerOpen=!1,this._yearPickerBase=0,this._yearOutsideHandler=null,this._dragState=null,this._clickSuppressed=!1,this._root=document.createElement("div"),this._root.className="uc-calendar",this._opts.showGridLines||this._root.classList.add("uc-no-grid"),this._opts.showBorder||this._root.classList.add("uc-no-border"),this._el.appendChild(this._root),this._onClick=this._handleClick.bind(this),this._root.addEventListener("click",this._onClick),this._onMouseMove=this._handleTooltipPosition.bind(this),this._root.addEventListener("mouseover",this._onMouseMove),(this._opts.enableDragDrop||this._opts.enableResize)&&(this._onMouseDown=this._handleDragStart.bind(this),this._onMouseMoveGlobal=this._handleDragMove.bind(this),this._onMouseUp=this._handleDragEnd.bind(this),this._onTouchStart=this._handleDragStart.bind(this),this._onTouchMove=this._handleDragMove.bind(this),this._onTouchEnd=this._handleDragEnd.bind(this),this._onKeyDown=this._handleDragKeyDown.bind(this),this._root.addEventListener("mousedown",this._onMouseDown),document.addEventListener("mousemove",this._onMouseMoveGlobal),document.addEventListener("mouseup",this._onMouseUp),this._root.addEventListener("touchstart",this._onTouchStart,{passive:!0}),document.addEventListener("touchmove",this._onTouchMove,{passive:!1}),document.addEventListener("touchend",this._onTouchEnd),document.addEventListener("keydown",this._onKeyDown),this._opts.enableDragDrop&&this._root.setAttribute("data-drag-enabled","true"),this._opts.enableResize&&this._root.setAttribute("data-resize-enabled","true")),this._root.innerHTML=this._buildShell(),this._fetchAndRender(),this._startNowUpdater()}setView(t){t!==this._view&&(this._view=t,this._opts.onViewChange&&this._opts.onViewChange(t),this._fetchAndRender())}navigate(t){const e=new Date(this._date);"month"===this._view?(e.setMonth(e.getMonth()+t),e.setDate(1)):"week"===this._view?e.setDate(e.getDate()+7*t):e.setDate(e.getDate()+t),this._date=e;const a=this._getRange();this._opts.onNavigate&&this._opts.onNavigate(a.start,a.end),this._fetchAndRender()}goToToday(){this._date=t(new Date);const e=this._getRange();this._opts.onNavigate&&this._opts.onNavigate(e.start,e.end),this._fetchAndRender()}goToDate(e){this._date=t(o(e)),this._fetchAndRender()}refresh(){this._cachedRange=null,this._cachedEvents=[],this._fetchAndRender()}destroy(){this._nowInterval&&clearInterval(this._nowInterval),this._yearOutsideHandler&&document.removeEventListener("click",this._yearOutsideHandler),this._root.removeEventListener("click",this._onClick),this._root.removeEventListener("mouseover",this._onMouseMove),(this._opts.enableDragDrop||this._opts.enableResize)&&(this._root.removeEventListener("mousedown",this._onMouseDown),document.removeEventListener("mousemove",this._onMouseMoveGlobal),document.removeEventListener("mouseup",this._onMouseUp),this._root.removeEventListener("touchstart",this._onTouchStart),document.removeEventListener("touchmove",this._onTouchMove),document.removeEventListener("touchend",this._onTouchEnd),document.removeEventListener("keydown",this._onKeyDown)),this._root.remove()}_getRange(){if("month"===this._view){const a=l(this._date.getFullYear(),this._date.getMonth(),this._opts.weekStartsOn);return{start:t(a[0]),end:e(a[a.length-1])}}if("week"===this._view){const a=r(this._date,this._opts.weekStartsOn);return{start:t(a[0]),end:e(a[6])}}if("list"===this._view){const t=new Date,e=new Date(t);return e.setDate(e.getDate()+this._opts.listDaysForward),{start:t,end:e}}return{start:t(this._date),end:e(this._date)}}_getMonthGridRange(){const a=l(this._date.getFullYear(),this._date.getMonth(),this._opts.weekStartsOn);return{start:t(a[0]),end:e(a[a.length-1])}}async _fetchAndRender(){if(this._updateToolbar(),!this._opts.fetchEvents)return void this._renderView();const t=this._getRange();if(this._cachedRange&&this._cachedRange.start<=t.start&&this._cachedRange.end>=t.end)return this._events=this._cachedEvents.filter(e=>e.end>=t.start&&e.start<=t.end),void this._renderView();const e=this._root.querySelector(".uc-loading");e&&(e.style.display="flex");try{let e;e="list"===this._view?t:this._getMonthGridRange();const a=(await this._opts.fetchEvents(e.start,e.end)||[]).map(t=>({...t,start:o(t.start),end:o(t.end)}));this._cachedRange={start:e.start,end:e.end},this._cachedEvents=a,this._events=a.filter(e=>e.end>=t.start&&e.start<=t.end)}catch(t){this._events=[]}e&&(e.style.display="none"),this._renderView()}_renderView(){const t=this._root.querySelector(".uc-view-container");if(t){if(0===this._opts.maxEventsPerCell)this._root.classList.add("uc-unlimited-events"),this._root.style.removeProperty("--cal-cell-min-height");else if(-1===this._opts.maxEventsPerCell)this._root.classList.remove("uc-unlimited-events"),this._root.style.removeProperty("--cal-cell-min-height");else{this._root.classList.remove("uc-unlimited-events");const t=30+24*this._opts.maxEventsPerCell+28;this._root.style.setProperty("--cal-cell-min-height",`${t}px`)}if("month"===this._view)t.innerHTML=this._buildMonthView();else if("week"===this._view){const e=r(this._date,this._opts.weekStartsOn);t.innerHTML=this._buildWeekOrDayView(e),this._scrollToBusinessHours(t)}else"list"===this._view?t.innerHTML=this._buildListView():(t.innerHTML=this._buildWeekOrDayView([this._date]),this._scrollToBusinessHours(t))}}_scrollToBusinessHours(t){requestAnimationFrame(()=>{const e=t.querySelector(".uc-time-body");if(!e)return;const a=parseFloat(getComputedStyle(this._root).getPropertyValue("--cal-hour-height"))||60;e.scrollTop=7*a})}_renderToolbar(){const t=this._root.querySelector(".uc-toolbar");if(!t)return;const e=document.createElement("div");e.innerHTML=this._buildToolbar(),this._root.replaceChild(e.firstElementChild,t)}_buildShell(){return`\n ${this._buildToolbar()}\n <div class="uc-loading" style="display:none">\n <div class="uc-spinner"></div>\n </div>\n <div class="uc-view-container"></div>\n `}_updateToolbar(){const t=this._root.querySelector(".uc-toolbar");if(t){const e=document.createElement("div");e.innerHTML=this._buildToolbar();const a=e.firstElementChild;a&&t.replaceWith(a)}}_buildToolbar(){if(!this._opts.showToolbar)return"";const t=this._date.getFullYear(),e=(new Date).getFullYear();let a,n=!0;if("month"===this._view)a=new Intl.DateTimeFormat(this._opts.locale,{month:"long"}).format(this._date);else if("week"===this._view){const t=r(this._date,this._opts.weekStartsOn);a=function(t,e,a){if(t.getMonth()===e.getMonth()&&t.getFullYear()===e.getFullYear())return`${new Intl.DateTimeFormat(a,{month:"long"}).format(t)} ${t.getDate()}–${e.getDate()}`;const s=t=>new Intl.DateTimeFormat(a,{month:"short",day:"numeric"}).format(t);return`${s(t)} – ${s(e)}`}(t[0],t[6],this._opts.locale)}else if("list"===this._view){const t=new Date,e=new Date(t);e.setDate(e.getDate()+this._opts.listDaysForward),a=function(t,e,a){if(t.getMonth()===e.getMonth()&&t.getFullYear()===e.getFullYear())return`${new Intl.DateTimeFormat(a,{month:"long"}).format(t)} ${t.getDate()}–${e.getDate()}, ${t.getFullYear()}`;const s=t=>new Intl.DateTimeFormat(a,{month:"short",day:"numeric"}).format(t);return`${s(t)} – ${s(e)}, ${e.getFullYear()}`}(t,e,this._opts.locale),n=!1}else a=new Intl.DateTimeFormat(this._opts.locale,{weekday:"long",month:"long",day:"numeric"}).format(this._date);let i="";if(this._opts.showYearPicker&&this._yearPickerOpen){const a=this._yearPickerBase,s=Array.from({length:12},(s,n)=>{const i=a+n,o=i===t;return`<button class="${"uc-year-item"+(o?" uc-active":"")+(i===e&&!o?" uc-today-year":"")}" data-action="select-year" data-year="${i}">${i}</button>`}).join("");i=`\n <div class="uc-year-picker">\n <div class="uc-year-picker-nav">\n <button class="uc-year-nav-btn" data-action="year-prev" aria-label="Previous years">&#8249;</button>\n <span class="uc-year-range">${a} – ${a+11}</span>\n <button class="uc-year-nav-btn" data-action="year-next" aria-label="Next years">&#8250;</button>\n </div>\n <div class="uc-year-grid">${s}</div>\n </div>`}const o=this._opts.locale,l=_(o,"today"),d=_(o,"month"),c=_(o,"week"),u=_(o,"day"),v=_(o,"list");let g="";if((this._opts.showNavigation||this._opts.showTodayButton)&&"list"!==this._view){const t=this._opts.showNavigation?'<button class="uc-btn uc-nav-btn" data-action="prev" aria-label="Previous">&#8249;</button>':"",e=new Date,a=s(this._date,e)?" uc-active":"";g=`\n <div class="uc-toolbar-section uc-toolbar-left">\n ${t}${this._opts.showTodayButton?`<button class="uc-btn uc-today-btn${a}" data-action="today">${h(l)}</button>`:""}${this._opts.showNavigation?'<button class="uc-btn uc-nav-btn" data-action="next" aria-label="Next">&#8250;</button>':""}\n </div>`}let p="";if(this._opts.showTitle){const e=n?this._opts.showYearPicker?`<button class="uc-year-btn${this._yearPickerOpen?" uc-open":""}" data-action="year-pick" aria-label="Select year">${t}</button>`:t:"";p=`\n <div class="uc-toolbar-section uc-toolbar-center">\n <h2 class="uc-title">\n <span class="uc-title-main">${h(a)}</span>\n ${e}\n </h2>\n ${i}\n </div>`}let y="";if(this._opts.showViewSwitcher){const t=this._opts.enabledViews,e=[];t.includes("month")&&e.push(`<button class="uc-btn uc-view-btn${"month"===this._view?" uc-active":""}" data-view="month">${h(d)}</button>`),t.includes("week")&&e.push(`<button class="uc-btn uc-view-btn${"week"===this._view?" uc-active":""}" data-view="week">${h(c)}</button>`),t.includes("day")&&e.push(`<button class="uc-btn uc-view-btn${"day"===this._view?" uc-active":""}" data-view="day">${h(u)}</button>`),t.includes("list")&&e.push(`<button class="uc-btn uc-view-btn${"list"===this._view?" uc-active":""}" data-view="list">${h(v)}</button>`),e.length>0&&(y=`\n <div class="uc-toolbar-section uc-toolbar-right">\n <div class="uc-view-switcher">\n ${e.join("")}\n </div>\n </div>`)}return`\n <div class="uc-toolbar">\n ${g}${p}${y}\n </div>\n `}_buildMonthView(){const{locale:a,weekStartsOn:s}=this._opts,n=l(this._date.getFullYear(),this._date.getMonth(),s),i=c(a,s,this._opts.weekdayFormat),o=this._events.map(a=>({...a,_origStart:a.start,start:v(a)?t(a.start):a.start,end:v(a)?e(a.end):a.end})),r=i.map(t=>`<div class="uc-month-day-name">${h(t)}</div>`).join(""),d=[];for(let t=0;t<n.length;t+=7)d.push(n.slice(t,t+7));return`\n <div class="uc-month-view">\n <div class="uc-month-header">${r}</div>\n <div class="uc-month-body">${d.map(t=>this._buildWeekRow(t,o)).join("")}</div>\n </div>\n `}_buildWeekRow(t,e){const a=this._date.getMonth();let i;if(0===this._opts.maxEventsPerCell)i=1/0;else if(-1===this._opts.maxEventsPerCell){const t=getComputedStyle(this._root),e=parseInt(t.getPropertyValue("--cal-cell-min-height")||"112");i=Math.floor((e-30-28)/24),i=Math.max(1,i)}else i=this._opts.maxEventsPerCell;const o=e.filter(v),r=e.filter(t=>!v(t)),l=g(o,t),c=Array.from({length:7},()=>new Set);for(const{startCol:t,endCol:e,slot:a}of l)for(let s=t;s<=e;s++)c[s].add(a);const u=t.map(t=>r.filter(e=>s(e.start,t)).sort((t,e)=>t.start-e.start)),_=t.map((t,e)=>`\n <div class="uc-day-cell${n(t)?" uc-today":""}${t.getMonth()!==a?" uc-other-month":""}" data-date="${t.toISOString()}" data-action="day-click">\n <span class="uc-day-number" data-action="day-number" data-date="${t.toISOString()}">${t.getDate()}</span>\n </div>`).join("");let p="";for(const{event:t,startCol:e,endCol:a,slot:s,isStart:n,isEnd:o}of l){if(i!==1/0&&s>=i)continue;const r=100/7,l=e*r,d=(a-e+1)*r,c=`calc(var(--cal-header-day-height) + ${s} * (var(--cal-event-height) + var(--cal-event-gap)) + 4px)`,u=t.color||"var(--cal-event-bg)",_=n?"var(--cal-event-border-radius)":"0",v=o?"var(--cal-event-border-radius)":"0",g=n?"":" uc-continues-left",y=o?"":" uc-continues-right",m=this._opts.showTooltips?`data-tooltip="${h(t.tooltip||t.description||t.title)}"`:"",w=this._opts.enableResize&&o?'<div class="uc-resize-handle-right" data-action="resize-handle"></div>':"";p+=`\n <div class="uc-event-bar${g}${y}"\n style="left:calc(${l}% + 2px);width:calc(${d}% - 4px);top:${c};background:${h(u)};border-radius:${_} ${v} ${v} ${_};"\n data-event-id="${h(t.id)}" data-action="event-click"\n ${m}>\n ${n?`<span class="uc-event-title">${h(t.title)}</span>`:"&nbsp;"}\n ${w}\n </div>`}let y=-1;for(let e=0;e<7;e++){const a=100/7,s=e*a,n=t[e],o=[...c[e]],r=o.length>0?Math.max(...o)+1:0,l=u[e];if(i===1/0)l.forEach((t,e)=>{const n=r+e;y=Math.max(y,n);const i=`calc(var(--cal-header-day-height) + ${n} * (var(--cal-event-height) + var(--cal-event-gap)) + 4px)`,o=t.color||"var(--cal-event-bg)",l=d(t.start,this._opts.locale,this._opts.use24Hour),c=this._opts.showTooltips?`data-tooltip="${h(t.tooltip||t.description||t.title)}"`:"";if("list"===this._opts.monthTimedEventStyle){const e=this._opts.showTimeInItems?`<span class="uc-event-time">${h(l)}</span>`:"";p+=`\n <div class="uc-event-bar uc-event-bar--list"\n style="left:calc(${s}% + 2px);width:calc(${a}% - 4px);top:${i};"\n data-event-id="${h(t.id)}" data-action="event-click"\n ${c}>\n <span class="uc-event-dot" style="background:${h(o)};"></span>\n ${e}\n <span class="uc-event-title">${h(t.title)}</span>\n </div>`}else{const e=this._opts.showTimeInItems?`<span class="uc-event-time">${h(l)}</span>`:"";p+=`\n <div class="uc-event-bar"\n style="left:calc(${s}% + 2px);width:calc(${a}% - 4px);top:${i};background:${h(o)};"\n data-event-id="${h(t.id)}" data-action="event-click"\n ${c}>\n ${e}\n <span class="uc-event-title">${h(t.title)}</span>\n </div>`}});else{const t=[...c[e]].filter(t=>t>=i).length,o=[];for(let t=r;t<i;t++)o.push(t);let u=t;if(l.forEach((t,e)=>{if(e<o.length){const n=o[e];y=Math.max(y,n);const i=`calc(var(--cal-header-day-height) + ${n} * (var(--cal-event-height) + var(--cal-event-gap)) + 4px)`,r=t.color||"var(--cal-event-bg)",l=d(t.start,this._opts.locale,this._opts.use24Hour),c=this._opts.showTooltips?`data-tooltip="${h(t.tooltip||t.description||t.title)}"`:"";if("list"===this._opts.monthTimedEventStyle){const e=this._opts.showTimeInItems?`<span class="uc-event-time">${h(l)}</span>`:"";p+=`\n <div class="uc-event-bar uc-event-bar--list"\n style="left:calc(${s}% + 2px);width:calc(${a}% - 4px);top:${i};"\n data-event-id="${h(t.id)}" data-action="event-click"\n ${c}>\n <span class="uc-event-dot" style="background:${h(r)};"></span>\n ${e}\n <span class="uc-event-title">${h(t.title)}</span>\n </div>`}else{const e=this._opts.showTimeInItems?`<span class="uc-event-time">${h(l)}</span>`:"";p+=`\n <div class="uc-event-bar"\n style="left:calc(${s}% + 2px);width:calc(${a}% - 4px);top:${i};background:${h(r)};"\n data-event-id="${h(t.id)}" data-action="event-click"\n ${c}>\n ${e}\n <span class="uc-event-title">${h(t.title)}</span>\n </div>`}}else u++}),u>0){p+=`\n <div class="uc-more-link"\n style="left:calc(${s}% + 2px);width:calc(${a}% - 4px);top:${`calc(var(--cal-header-day-height) + ${i} * (var(--cal-event-height) + var(--cal-event-gap)) + 2px)`};"\n data-date="${n.toISOString()}" data-action="more-click">\n +${u} more\n </div>`}}}for(const{slot:t}of l)(i===1/0||t<i)&&(y=Math.max(y,t));let m="";return i===1/0&&(m=y>=0?` style="min-height: calc(var(--cal-header-day-height) + ${y+1} * (var(--cal-event-height) + var(--cal-event-gap)) + 8px);"`:' style="min-height: 80px;"'),`\n <div class="uc-week-row"${m}>\n <div class="uc-week-cells">${_}</div>\n <div class="uc-week-events">${p}</div>\n </div>`}_buildWeekOrDayView(a){const{locale:i,weekStartsOn:o,use24Hour:r}=this._opts,l=1===a.length,u=l?" uc-day-header-single":"",p=l?[new Intl.DateTimeFormat(i,{weekday:this._opts.weekdayFormat}).format(a[0])]:c(i,o,this._opts.weekdayFormat),y=t(a[0]),m=e(a[a.length-1]),w=this._events.filter(t=>v(t)&&t.start<=m&&e(t.end)>=y).map(a=>({...a,start:t(a.start),end:e(a.end)})),f=this._events.filter(t=>!v(t)&&t.start>=y&&t.start<=m),D=a.map((t,e)=>{const a=n(t)?" uc-today":"",s=t.getDate();return`\n <div class="uc-week-day-header${a}">\n <span class="uc-week-day-name">${h(p[e])}</span>\n <span class="uc-week-day-num" data-action="day-number" data-date="${t.toISOString()}">${s}</span>\n </div>`}).join(""),S=l?w.map((t,e)=>({event:t,startCol:0,endCol:0,slot:e,isStart:!0,isEnd:!0})):g(w,a),k=S.length?Math.max(...S.map(t=>t.slot))+1:0;let $="";for(const{event:t,startCol:e,endCol:s,slot:n,isStart:i,isEnd:o}of S){const r=100/a.length,l=e*r,d=(s-e+1)*r,c=`calc(${n} * (var(--cal-event-height) + 3px) + 2px)`,u=t.color||"var(--cal-event-bg)",_=i?"var(--cal-event-border-radius)":"0",v=o?"var(--cal-event-border-radius)":"0",g=i?"":" uc-continues-left",p=o?"":" uc-continues-right",y=this._opts.showTooltips?`data-tooltip="${h(t.tooltip||t.description||t.title)}"`:"",m=this._opts.enableResize&&o?'<div class="uc-resize-handle-right" data-action="resize-handle"></div>':"";$+=`\n <div class="uc-event-bar${g}${p}"\n style="left:calc(${l}% + 2px);width:calc(${d}% - 4px);top:${c};background:${h(u)};border-radius:${_} ${v} ${v} ${_};"\n data-event-id="${h(t.id)}" data-action="event-click"\n ${y}>\n <span class="uc-event-title">${h(t.title)}</span>\n ${m}\n </div>`}const b=`calc(${Math.max(1,k)} * (var(--cal-event-height) + 3px) + 6px)`,M=new Date,E=60*M.getHours()+M.getMinutes(),T=a.length,x=Array.from({length:24},(t,e)=>`<div class="uc-hour-cell"><span class="uc-hour-label">${h(0===e?"":d(new Date(2e3,0,1,e),"en-US",r))}</span></div>`).join(""),C=a.map(t=>{const e=n(t)?" uc-today":"",a=Array.from({length:24},()=>'<div class="uc-hour-row"><div class="uc-half-hour-line"></div></div>').join(""),o=function(t){if(!t.length)return[];const e=[...t].sort((t,e)=>t.start-e.start||e.end-t.end),a=[],s=[];for(const t of e){let e=a.findIndex(e=>e<=t.start);-1===e?(e=a.length,a.push(t.end)):a[e]=t.end,s.push({event:t,col:e})}return s.map(t=>{const e=s.filter(e=>e.event.start<t.event.end&&e.event.end>t.event.start),a=Math.max(...e.map(t=>t.col))+1;return{...t,totalCols:a}})}(f.filter(e=>s(e.start,t))).map(({event:t,col:e,totalCols:a})=>{const s=60*t.start.getHours()+t.start.getMinutes(),n=60*t.end.getHours()+t.end.getMinutes(),o=`calc(${s} / 60 * var(--cal-hour-height))`,l=`calc(${Math.max(n-s,30)} / 60 * var(--cal-hour-height))`,c=100/a,u=`calc(${e*c}% + 1px)`,_=`calc(${c}% - 2px)`,v=t.color||"var(--cal-event-bg)",g=d(t.start,i,r),p=n-s<=60?" uc-timed-event--short":"",y=this._opts.showTimeInItems?`<span class="uc-event-time">${h(g)}</span>`:"",m=this._opts.showTooltips?`data-tooltip="${h(t.tooltip||t.description||t.title)}"`:"",w=this._opts.enableResize?'<div class="uc-resize-handle" data-action="resize-handle"></div>':"";return`\n <div class="uc-timed-event${p}"\n style="top:${o};height:${l};left:${u};width:${_};background:${h(v)};"\n data-event-id="${h(t.id)}" data-action="event-click"\n ${m}>\n ${y}\n <span class="uc-event-title">${h(t.title)}</span>\n ${w}\n </div>`}).join(""),l=n(t)?`<div class="uc-now-indicator" style="top:calc(${E} / 60 * var(--cal-hour-height));">\n <span class="uc-now-dot"></span>\n <span class="uc-now-line"></span>\n </div>`:"";return`<div class="uc-time-col${e}" data-date="${t.toISOString()}" data-action="slot-col">\n ${a}${o}${l}\n </div>`}).join("");return`\n <div class="${l?"uc-day-view":"uc-week-view"}">\n <div class="uc-week-header">\n <div class="uc-time-gutter-spacer"></div>\n <div class="uc-week-day-headers${u}">${D}</div>\n </div>\n <div class="uc-all-day-section">\n <div class="uc-time-gutter-spacer uc-all-day-label">${_(this._opts.locale,"allDay")}</div>\n <div class="uc-all-day-events" style="min-height:${b}">${$}</div>\n </div>\n <div class="uc-time-body">\n <div class="uc-time-grid-inner">\n <div class="uc-time-gutter">${x}</div>\n <div class="uc-time-columns" style="--uc-col-count:${T}">${C}</div>\n </div>\n </div>\n </div>`}_buildListView(){const e=new Date,a=t(e),s=new Date(a);s.setDate(s.getDate()+this._opts.listDaysForward);const n=this._events.filter(t=>t.end>=e&&t.start<=s);n.sort((e,s)=>{const n=(e.start<a?a:t(e.start))-(s.start<a?a:t(s.start));return 0!==n?n:e.start-s.start});const i=new Map;if(n.forEach(e=>{const s=e.start<a?a:t(e.start),n=`${(o=s).getFullYear()}-${String(o.getMonth()+1).padStart(2,"0")}-${String(o.getDate()).padStart(2,"0")}`;var o;i.has(n)||i.set(n,[]),i.get(n).push(e)}),0===i.size)return'\n <div class="uc-list-view">\n <div class="uc-list-empty">\n <p>No upcoming events</p>\n </div>\n </div>';let r="";return i.forEach((t,e)=>{const a=o(e),s=new Intl.DateTimeFormat(this._opts.locale,{weekday:"long",year:"numeric",month:"long",day:"numeric"}).format(a),n=t.map(t=>{const e=v(t)?"All day":d(t.start,this._opts.locale,this._opts.use24Hour),a=t.color||"var(--cal-event-bg)",s=this._opts.showTooltips?`data-tooltip="${h(t.tooltip||t.description||"")}"`:"";return`\n <div class="uc-list-event" data-event-id="${h(t.id)}" data-action="event-click" ${s}>\n <div class="uc-list-event-indicator" style="background: ${h(a)};"></div>\n <div class="uc-list-event-time">${h(e)}</div>\n <div class="uc-list-event-content">\n <div class="uc-list-event-title">${h(t.title)}</div>\n </div>\n </div>`}).join("");r+=`\n <div class="uc-list-date-group">\n <div class="uc-list-date-header">${h(s)}</div>\n <div class="uc-list-events">${n}</div>\n </div>`}),`<div class="uc-list-view">${r}</div>`}_closeYearPicker(){this._yearOutsideHandler&&(document.removeEventListener("click",this._yearOutsideHandler),this._yearOutsideHandler=null),this._yearPickerOpen=!1,this._renderToolbar()}_handleClick(e){if(this._clickSuppressed)return void(this._clickSuppressed=!1);const a=e.target.closest("[data-view]");if(a)return void this.setView(a.dataset.view);const s=e.target.closest("[data-action]");if(!s)return;switch(s.dataset.action){case"prev":this.navigate(-1);break;case"next":this.navigate(1);break;case"today":this.goToToday();break;case"year-pick":e.stopPropagation(),this._yearPickerOpen?this._closeYearPicker():(this._yearPickerOpen=!0,this._yearPickerBase=this._date.getFullYear()-4,this._renderToolbar(),this._yearOutsideHandler=t=>{t.target.closest(".uc-year-picker")||t.target.closest('[data-action="year-pick"]')||this._closeYearPicker()},setTimeout(()=>document.addEventListener("click",this._yearOutsideHandler),0));break;case"year-prev":e.stopPropagation(),this._yearPickerBase-=12,this._renderToolbar();break;case"year-next":e.stopPropagation(),this._yearPickerBase+=12,this._renderToolbar();break;case"select-year":{e.stopPropagation();const t=parseInt(s.dataset.year,10);this._date=new Date(this._date.getFullYear()!==t?new Date(this._date).setFullYear(t):this._date),this._closeYearPicker();const a=this._getRange();this._opts.onNavigate&&this._opts.onNavigate(a.start,a.end),this._fetchAndRender();break}case"event-click":{e.stopPropagation();const t=s.dataset.eventId,a=this._events.find(e=>String(e.id)===String(t));a&&this._opts.onEventClick&&this._opts.onEventClick(a,e);break}case"day-click":{if(e.target.closest('[data-action="day-number"]'))break;if(e.target.closest('[data-action="event-click"]'))break;const t=new Date(s.dataset.date);this._opts.onSlotClick&&this._opts.onSlotClick(t,e);break}case"day-number":{if(e.stopPropagation(),!this._opts.enabledViews.includes("day"))break;const a=new Date(s.dataset.date);this._date=t(a),this._view="day",this._opts.onViewChange&&this._opts.onViewChange("day"),this._fetchAndRender();break}case"more-click":{if(e.stopPropagation(),!this._opts.enabledViews.includes("day"))break;const a=new Date(s.dataset.date);this._date=t(a),this._view="day",this._opts.onViewChange&&this._opts.onViewChange("day"),this._fetchAndRender();break}case"slot-col":if(e.target.closest('[data-action="event-click"]'))break;if(this._opts.onSlotClick){const t=s,a=t.getBoundingClientRect(),n=e.clientY-a.top,i=parseFloat(getComputedStyle(this._root).getPropertyValue("--cal-hour-height"))||60,o=Math.max(0,Math.floor(n/i*60)),r=Math.floor(o/60)%24,l=15*Math.round(o%60/15),d=new Date(t.dataset.date);d.setHours(r,l,0,0),this._opts.onSlotClick(d,e)}}}_handleTooltipPosition(t){const e=t.target.closest("[data-tooltip]");if(!e||!e.dataset.tooltip)return;if(!e.dataset.tooltip.trim())return;const a=e.getBoundingClientRect(),s=window.innerWidth;e.classList.remove("uc-tooltip-left","uc-tooltip-right","uc-tooltip-bottom");const n=a.width/2-125;a.left+n+250>s-10?e.classList.add("uc-tooltip-left"):a.left+n<10&&e.classList.add("uc-tooltip-right"),a.top<50&&e.classList.add("uc-tooltip-bottom")}_handleDragStart(t){if("list"===this._view)return;const e=t.target.closest('[data-action="resize-handle"]'),a=!!e,s=e&&e.classList.contains("uc-resize-handle-right"),n=e&&e.classList.contains("uc-resize-handle"),i=t.target.closest('[data-event-id][data-action="event-click"]');if(!i)return;if(t.target.closest('.uc-year-picker, [data-action="year-pick"], .uc-toolbar'))return;const o=i.dataset.eventId,r=this._events.find(t=>String(t.id)===String(o));if(!r)return;const l=r.allDay||!1;if(a&&!this._opts.enableResize)return;if(!a&&!this._opts.enableDragDrop)return;if(n&&(l||"week"!==this._view&&"day"!==this._view))return;if(s&&!l)return;const d=this._getEventPosition(t),c=i.getBoundingClientRect(),h=d.x-c.left,u=d.y-c.top;this._dragState={mode:a?"resize":"move",resizeDirection:s?"horizontal":n?"vertical":null,eventId:o,originalEvent:{...r,start:new Date(r.start),end:new Date(r.end)},dragElement:null,startX:d.x,startY:d.y,currentX:d.x,currentY:d.y,offsetX:h,offsetY:u,originalView:this._view,isAllDay:l,hasMoved:!1,startTime:Date.now(),originalElement:i}}_handleDragMove(t){if(!this._dragState)return;const e=this._getEventPosition(t);this._dragState.currentX=e.x,this._dragState.currentY=e.y;const a=e.x-this._dragState.startX,s=e.y-this._dragState.startY,n=Math.sqrt(a*a+s*s);if(!this._dragState.hasMoved){const t=Date.now()-this._dragState.startTime;if(!(n>5||t>150))return;this._dragState.hasMoved=!0,this._createDragElement(),this._root.classList.add("uc-dragging")}if(t.type.startsWith("touch")&&t.preventDefault(),this._dragState.dragElement)if("resize"===this._dragState.mode&&"vertical"===this._dragState.resizeDirection)this._updateResizePreview(e.x,e.y);else if("resize"===this._dragState.mode&&"horizontal"===this._dragState.resizeDirection)this._updateHorizontalResizePreview(e.x);else{const t=this._getSnappedPosition(e.x,e.y);t?(this._dragState.dragElement.style.left=t.x+"px",this._dragState.dragElement.style.top=t.y+"px"):(this._dragState.dragElement.style.left=e.x-this._dragState.offsetX+"px",this._dragState.dragElement.style.top=e.y-this._dragState.offsetY+"px")}}_getSnappedPosition(t,e){if("week"!==this._view&&"day"!==this._view)return null;const a=this._calculateDropPosition(t,e);if(!a)return null;const s=this._dragState.dragElement;if(!s)return null;if(!a.isAllDay){const e=this._root.querySelector(".uc-time-columns");if(!e)return null;const n=e.querySelectorAll(".uc-time-col");let i=null;for(const e of n){const a=e.getBoundingClientRect();if(t>=a.left&&t<a.right){i=e;break}}if(!i)return null;const o=i.getBoundingClientRect(),r=(60*a.date.getHours()+a.date.getMinutes())/60*(parseFloat(getComputedStyle(this._root).getPropertyValue("--cal-hour-height"))||60),l=s.querySelector(".uc-event-time");if(l){const t=d(a.date,this._opts.locale,this._opts.use24Hour);l.textContent=t}return{x:o.left+4,y:o.top+r}}if(a.isAllDay){const e=this._root.querySelector(".uc-all-day-events");if(!e)return null;const a=e.getBoundingClientRect(),s="day"===this._view?[this._date]:r(this._date,this._opts.weekStartsOn),n=a.width/s.length,i=t-a.left,o=Math.floor(i/n);return o<0||o>=s.length?null:{x:a.left+o*n+4,y:a.top+4}}return null}_updateResizePreview(t,e){const a=this._dragState.dragElement,s=this._dragState.originalEvent,n=this._root.querySelector(".uc-time-columns");if(!n)return;const i=n.querySelectorAll(".uc-time-col");let o=null;for(const e of i){const a=e.getBoundingClientRect();if(t>=a.left&&t<a.right){o=e;break}}if(!o)return;const r=o.getBoundingClientRect(),l=Math.max(0,e-r.top),c=parseFloat(getComputedStyle(this._root).getPropertyValue("--cal-hour-height"))||60,h=Math.floor(l/c*60),u=Math.floor(h/60)%24,_=15*Math.round(h%60/15),v=new Date(s.start);v.setHours(u,_,0,0),v<=s.start&&v.setTime(s.start.getTime()+9e5);const g=(v-s.start)/6e4/60*c;a.style.height=g+"px";const p=a.querySelector(".uc-event-time");if(p){const t=d(s.start,this._opts.locale,this._opts.use24Hour),e=d(v,this._opts.locale,this._opts.use24Hour);p.textContent=`${t} - ${e}`}this._dragState.newEndTime=v}_updateHorizontalResizePreview(t){const a=this._dragState.dragElement,s=this._dragState.originalEvent,n=this._dragState.originalElement;if(!n)return;const i=n.getBoundingClientRect(),o=t-i.left;let d;if("month"===this._view){const a=this._root.querySelector(".uc-month-body");if(!a)return;const s=a.getBoundingClientRect(),n=s.width/7,o=t-s.left,r=Math.floor(o/n),c=l(this._date.getFullYear(),this._date.getMonth(),this._opts.weekStartsOn),h=i.top-s.top,u=s.height/Math.ceil(c.length/7),_=7*Math.floor(h/u)+r;_>=0&&_<c.length&&(d=e(c[_]))}else{const a="day"===this._view?[this._date]:r(this._date,this._opts.weekStartsOn),s=this._root.querySelector(".uc-all-day-events");if(!s)return;const n=s.getBoundingClientRect(),i=n.width/a.length,o=t-n.left,l=Math.floor(o/i);l>=0&&l<a.length&&(d=e(a[l]))}if(!d)return;d<s.start&&(d=e(s.start));const c=o+20;a.style.width=Math.max(c,60)+"px",this._dragState.newEndDate=d}_handleDragEnd(t){if(!this._dragState)return;if(this._dragState.hasMoved){if(t.preventDefault(),t.stopPropagation(),this._clickSuppressed=!0,setTimeout(()=>{this._clickSuppressed=!1},10),"resize"===this._dragState.mode&&"vertical"===this._dragState.resizeDirection)this._dragState.newEndTime&&this._performResize(this._dragState.newEndTime);else if("resize"===this._dragState.mode&&"horizontal"===this._dragState.resizeDirection)this._dragState.newEndDate&&this._performHorizontalResize(this._dragState.newEndDate);else{const e=this._getEventPosition(t),a=this._calculateDropPosition(e.x,e.y);a&&this._performDrop(a)}this._cleanupDrag()}else this._dragState=null}_handleDragKeyDown(t){this._dragState&&this._dragState.hasMoved&&"Escape"===t.key&&this._cleanupDrag()}_getEventPosition(t){if(t.type.startsWith("touch")){const e=t.touches[0]||t.changedTouches[0];return{x:e.clientX,y:e.clientY}}return{x:t.clientX,y:t.clientY}}_createDragElement(){const t=this._root.querySelector(`[data-event-id="${this._dragState.eventId}"]`);if(!t)return;const e=t.cloneNode(!0);e.classList.add("uc-dragging-element");const a=t.getBoundingClientRect();e.style.position="fixed",e.style.pointerEvents="none",e.style.zIndex="10000",e.style.opacity="0.8",e.style.width=t.offsetWidth+"px","resize"===this._dragState.mode?(e.style.left=a.left+"px",e.style.top=a.top+"px",e.style.height=t.offsetHeight+"px"):(e.style.left=this._dragState.currentX-this._dragState.offsetX+"px",e.style.top=this._dragState.currentY-this._dragState.offsetY+"px"),document.body.appendChild(e),this._dragState.dragElement=e}_cleanupDrag(){this._dragState&&this._dragState.dragElement&&this._dragState.dragElement.remove(),this._root.classList.remove("uc-dragging"),this._dragState=null}_calculateDropPosition(t,e){if("week"===this._view||"day"===this._view){const a=this._calculateAllDayDropPosition(t,e);if(a)return a;const s=this._calculateTimedDropPosition(t,e);if(s)return s}return"month"===this._view?this._calculateMonthDropPosition(t,e):null}_calculateMonthDropPosition(t,e){const a=this._root.querySelector(".uc-month-body");if(!a)return null;const s=a.getBoundingClientRect(),n=t-s.left,i=e-s.top,o=s.width/7,r=a.querySelectorAll(".uc-week-row").length,d=s.height/r,c=Math.floor(n/o),h=Math.floor(i/d),u=l(this._date.getFullYear(),this._date.getMonth(),this._opts.weekStartsOn),_=7*h+c;return c<0||c>=7||_<0||_>=u.length?null:{date:u[_],isMonthView:!0}}_calculateTimedDropPosition(t,e){const a=this._root.querySelector(".uc-time-columns");if(!a)return null;const s=a.querySelectorAll(".uc-time-col");let n=null;for(const e of s){const a=e.getBoundingClientRect();if(t>=a.left&&t<a.right){n=e;break}}if(!n)return null;const i=n.getBoundingClientRect(),o=Math.max(0,e-i.top),r=parseFloat(getComputedStyle(this._root).getPropertyValue("--cal-hour-height"))||60,l=Math.floor(o/r*60),d=Math.floor(l/60)%24,c=15*Math.round(l%60/15),h=n.dataset.date;if(!h)return null;const u=new Date(h);return u.setHours(d,c,0,0),{date:u,isAllDay:!1}}_calculateAllDayDropPosition(e,a){const s=this._root.querySelector(".uc-all-day-events");if(!s)return null;const n=s.getBoundingClientRect();if(a<n.top||a>n.bottom)return null;const i="day"===this._view?[this._date]:r(this._date,this._opts.weekStartsOn),o=n.width/i.length,l=e-n.left,d=Math.floor(l/o);return d<0||d>=i.length?null:{date:t(i[d]),isAllDay:!0}}_performDrop(s){const n=this._dragState.originalEvent,o=new Date(n.start),r=new Date(n.end);let l,d,c;const h=n.allDay||this._dragState.isAllDay;if(s.isMonthView)if(h){const n=i(o,r);l=t(s.date),d=e(a(s.date,Math.max(0,n))),c=!0}else{const t=r-o;l=new Date(s.date),l.setHours(o.getHours(),o.getMinutes(),o.getSeconds(),o.getMilliseconds()),d=new Date(l.getTime()+t),c=!1}else if(s.isAllDay){const n=Math.max(0,Math.ceil((r-o)/864e5));l=t(s.date),d=e(a(s.date,n)),c=!0}else{if(l=s.date,h)d=new Date(l.getTime()+36e5);else{const t=r-o;d=new Date(l.getTime()+t)}c=!1}const u=this._events.findIndex(t=>String(t.id)===String(this._dragState.eventId));u>=0&&(this._events[u].start=l,this._events[u].end=d,this._events[u].allDay=c);const _=this._cachedEvents.findIndex(t=>String(t.id)===String(this._dragState.eventId));_>=0&&(this._cachedEvents[_].start=l,this._cachedEvents[_].end=d,this._cachedEvents[_].allDay=c),this._opts.onEventDrop&&this._opts.onEventDrop(u>=0?this._events[u]:null,o,r,l,d),this._renderView()}_performResize(t){const e=this._dragState.originalEvent,a=new Date(e.start),s=new Date(e.end),n=a,i=this._events.findIndex(t=>String(t.id)===String(this._dragState.eventId));i>=0&&(this._events[i].end=t);const o=this._cachedEvents.findIndex(t=>String(t.id)===String(this._dragState.eventId));o>=0&&(this._cachedEvents[o].end=t),this._opts.onEventDrop&&this._opts.onEventDrop(i>=0?this._events[i]:null,a,s,n,t),this._renderView()}_performHorizontalResize(t){const e=this._dragState.originalEvent,a=new Date(e.start),s=new Date(e.end),n=a,i=this._events.findIndex(t=>String(t.id)===String(this._dragState.eventId));i>=0&&(this._events[i].end=t);const o=this._cachedEvents.findIndex(t=>String(t.id)===String(this._dragState.eventId));o>=0&&(this._cachedEvents[o].end=t),this._opts.onEventDrop&&this._opts.onEventDrop(i>=0?this._events[i]:null,a,s,n,t),this._renderView()}_startNowUpdater(){this._nowInterval=setInterval(()=>{const t=this._root.querySelectorAll(".uc-now-indicator");if(!t.length)return;const e=new Date,a=`calc(${60*e.getHours()+e.getMinutes()} / 60 * var(--cal-hour-height))`;t.forEach(t=>t.style.top=a)},6e4)}}});
14
+ return class{constructor(e,a={}){if("string"==typeof e){if(this._el=document.querySelector(e),!this._el)throw new Error(`SimpleCalendarJs: no element for "${e}"`)}else this._el=e;this._opts=Object.assign({defaultView:"month",defaultDate:null,weekStartsOn:0,locale:"default",weekdayFormat:"short",use24Hour:!1,showTimeInItems:!0,showGridLines:!0,monthTimedEventStyle:"list",showToolbar:!0,showTodayButton:!0,showNavigation:!0,showTitle:!0,showYearPicker:!0,showViewSwitcher:!0,showTooltips:!0,showBorder:!0,listDaysForward:30,enabledViews:["month","week","day"],enableDragDrop:!1,enableResize:!1,fetchEvents:null,onEventClick:null,onSlotClick:null,onViewChange:null,onNavigate:null,onEventDrop:null},a),this._view=this._opts.defaultView,this._date=t(this._opts.defaultDate||new Date),this._events=[],this._cachedRange=null,this._cachedEvents=[],this._nowInterval=null,this._yearPickerOpen=!1,this._yearPickerBase=0,this._yearOutsideHandler=null,this._dragState=null,this._clickSuppressed=!1,this._root=document.createElement("div"),this._root.className="uc-calendar",this._opts.showGridLines||this._root.classList.add("uc-no-grid"),this._opts.showBorder||this._root.classList.add("uc-no-border"),this._el.appendChild(this._root),this._onClick=this._handleClick.bind(this),this._root.addEventListener("click",this._onClick),this._onMouseMove=this._handleTooltipPosition.bind(this),this._root.addEventListener("mouseover",this._onMouseMove),(this._opts.enableDragDrop||this._opts.enableResize)&&(this._onMouseDown=this._handleDragStart.bind(this),this._onMouseMoveGlobal=this._handleDragMove.bind(this),this._onMouseUp=this._handleDragEnd.bind(this),this._onTouchStart=this._handleDragStart.bind(this),this._onTouchMove=this._handleDragMove.bind(this),this._onTouchEnd=this._handleDragEnd.bind(this),this._onKeyDown=this._handleDragKeyDown.bind(this),this._root.addEventListener("mousedown",this._onMouseDown),document.addEventListener("mousemove",this._onMouseMoveGlobal),document.addEventListener("mouseup",this._onMouseUp),this._root.addEventListener("touchstart",this._onTouchStart,{passive:!0}),document.addEventListener("touchmove",this._onTouchMove,{passive:!1}),document.addEventListener("touchend",this._onTouchEnd),document.addEventListener("keydown",this._onKeyDown),this._opts.enableDragDrop&&this._root.setAttribute("data-drag-enabled","true"),this._opts.enableResize&&this._root.setAttribute("data-resize-enabled","true")),this._root.innerHTML=this._buildShell(),this._resizeObserver=new ResizeObserver(()=>{this._resizeTimeout&&clearTimeout(this._resizeTimeout),this._resizeTimeout=setTimeout(()=>{this._renderView()},100)}),this._resizeObserver.observe(this._root),this._fetchAndRender(),this._startNowUpdater()}setView(t){t!==this._view&&(this._view=t,this._opts.onViewChange&&this._opts.onViewChange(t),this._fetchAndRender())}navigate(t){const e=new Date(this._date);"month"===this._view?(e.setMonth(e.getMonth()+t),e.setDate(1)):"week"===this._view?e.setDate(e.getDate()+7*t):e.setDate(e.getDate()+t),this._date=e;const a=this._getRange();this._opts.onNavigate&&this._opts.onNavigate(a.start,a.end),this._fetchAndRender()}goToToday(){this._date=t(new Date);const e=this._getRange();this._opts.onNavigate&&this._opts.onNavigate(e.start,e.end),this._fetchAndRender()}goToDate(e){this._date=t(o(e)),this._fetchAndRender()}refresh(){this._cachedRange=null,this._cachedEvents=[],this._fetchAndRender()}destroy(){this._nowInterval&&clearInterval(this._nowInterval),this._resizeTimeout&&clearTimeout(this._resizeTimeout),this._resizeObserver&&this._resizeObserver.disconnect(),this._yearOutsideHandler&&document.removeEventListener("click",this._yearOutsideHandler),this._root.removeEventListener("click",this._onClick),this._root.removeEventListener("mouseover",this._onMouseMove),(this._opts.enableDragDrop||this._opts.enableResize)&&(this._root.removeEventListener("mousedown",this._onMouseDown),document.removeEventListener("mousemove",this._onMouseMoveGlobal),document.removeEventListener("mouseup",this._onMouseUp),this._root.removeEventListener("touchstart",this._onTouchStart),document.removeEventListener("touchmove",this._onTouchMove),document.removeEventListener("touchend",this._onTouchEnd),document.removeEventListener("keydown",this._onKeyDown)),this._root.remove()}_getRange(){if("month"===this._view){const a=l(this._date.getFullYear(),this._date.getMonth(),this._opts.weekStartsOn);return{start:t(a[0]),end:e(a[a.length-1])}}if("week"===this._view){const a=r(this._date,this._opts.weekStartsOn);return{start:t(a[0]),end:e(a[6])}}if("list"===this._view){const t=new Date,e=new Date(t);return e.setDate(e.getDate()+this._opts.listDaysForward),{start:t,end:e}}return{start:t(this._date),end:e(this._date)}}_getMonthGridRange(){const a=l(this._date.getFullYear(),this._date.getMonth(),this._opts.weekStartsOn);return{start:t(a[0]),end:e(a[a.length-1])}}async _fetchAndRender(){if(this._updateToolbar(),!this._opts.fetchEvents)return void this._renderView();const t=this._getRange();if(this._cachedRange&&this._cachedRange.start<=t.start&&this._cachedRange.end>=t.end)return this._events=this._cachedEvents.filter(e=>e.end>=t.start&&e.start<=t.end),void this._renderView();const e=this._root.querySelector(".uc-loading");e&&(e.style.display="flex");try{let e;e="list"===this._view?t:this._getMonthGridRange();const a=(await this._opts.fetchEvents(e.start,e.end)||[]).map(t=>({...t,start:o(t.start),end:o(t.end)}));this._cachedRange={start:e.start,end:e.end},this._cachedEvents=a,this._events=a.filter(e=>e.end>=t.start&&e.start<=t.end)}catch(t){this._events=[]}e&&(e.style.display="none"),this._renderView()}_renderView(){const t=this._root.querySelector(".uc-view-container");if(!t)return;const e=this._root.parentElement;if(e&&e.style.height&&"auto"!==e.style.height&&""!==e.style.height?this._root.setAttribute("data-height-constrained","true"):this._root.removeAttribute("data-height-constrained"),"month"===this._view)t.innerHTML=this._buildMonthView();else if("week"===this._view){const e=r(this._date,this._opts.weekStartsOn);t.innerHTML=this._buildWeekOrDayView(e),this._scrollToBusinessHours(t)}else"list"===this._view?t.innerHTML=this._buildListView():(t.innerHTML=this._buildWeekOrDayView([this._date]),this._scrollToBusinessHours(t))}_scrollToBusinessHours(t){requestAnimationFrame(()=>{const e=t.querySelector(".uc-time-body");if(!e)return;const a=parseFloat(getComputedStyle(this._root).getPropertyValue("--cal-hour-height"))||60;e.scrollTop=7*a})}_renderToolbar(){const t=this._root.querySelector(".uc-toolbar");if(!t)return;const e=document.createElement("div");e.innerHTML=this._buildToolbar(),this._root.replaceChild(e.firstElementChild,t)}_buildShell(){return`\n ${this._buildToolbar()}\n <div class="uc-loading" style="display:none">\n <div class="uc-spinner"></div>\n </div>\n <div class="uc-view-container"></div>\n `}_updateToolbar(){const t=this._root.querySelector(".uc-toolbar");if(t){const e=document.createElement("div");e.innerHTML=this._buildToolbar();const a=e.firstElementChild;a&&t.replaceWith(a)}}_buildToolbar(){if(!this._opts.showToolbar)return"";const t=this._date.getFullYear(),e=(new Date).getFullYear();let a,n=!0;if("month"===this._view)a=new Intl.DateTimeFormat(this._opts.locale,{month:"long"}).format(this._date);else if("week"===this._view){const t=r(this._date,this._opts.weekStartsOn);a=function(t,e,a){if(t.getMonth()===e.getMonth()&&t.getFullYear()===e.getFullYear())return`${new Intl.DateTimeFormat(a,{month:"long"}).format(t)} ${t.getDate()}–${e.getDate()}`;const s=t=>new Intl.DateTimeFormat(a,{month:"short",day:"numeric"}).format(t);return`${s(t)} – ${s(e)}`}(t[0],t[6],this._opts.locale)}else if("list"===this._view){const t=new Date,e=new Date(t);e.setDate(e.getDate()+this._opts.listDaysForward),a=function(t,e,a){if(t.getMonth()===e.getMonth()&&t.getFullYear()===e.getFullYear())return`${new Intl.DateTimeFormat(a,{month:"long"}).format(t)} ${t.getDate()}–${e.getDate()}, ${t.getFullYear()}`;const s=t=>new Intl.DateTimeFormat(a,{month:"short",day:"numeric"}).format(t);return`${s(t)} – ${s(e)}, ${e.getFullYear()}`}(t,e,this._opts.locale),n=!1}else a=new Intl.DateTimeFormat(this._opts.locale,{weekday:"long",month:"long",day:"numeric"}).format(this._date);let i="";if(this._opts.showYearPicker&&this._yearPickerOpen){const a=this._yearPickerBase,s=Array.from({length:12},(s,n)=>{const i=a+n,o=i===t;return`<button class="${"uc-year-item"+(o?" uc-active":"")+(i===e&&!o?" uc-today-year":"")}" data-action="select-year" data-year="${i}">${i}</button>`}).join("");i=`\n <div class="uc-year-picker">\n <div class="uc-year-picker-nav">\n <button class="uc-year-nav-btn" data-action="year-prev" aria-label="Previous years">&#8249;</button>\n <span class="uc-year-range">${a} – ${a+11}</span>\n <button class="uc-year-nav-btn" data-action="year-next" aria-label="Next years">&#8250;</button>\n </div>\n <div class="uc-year-grid">${s}</div>\n </div>`}const o=this._opts.locale,l=v(o,"today"),c=v(o,"month"),d=v(o,"week"),u=v(o,"day"),_=v(o,"list");let g="";if(this._opts.showNavigation||this._opts.showTodayButton){const t="list"===this._view?" disabled":"",e=this._opts.showNavigation?`<button class="uc-btn uc-nav-btn" data-action="prev" aria-label="Previous"${t}>&#8249;</button>`:"",a=new Date,n=s(this._date,a)?" uc-active":"";g=`\n <div class="uc-toolbar-section uc-toolbar-left">\n ${e}${this._opts.showTodayButton?`<button class="uc-btn uc-today-btn${n}" data-action="today"${t}>${h(l)}</button>`:""}${this._opts.showNavigation?`<button class="uc-btn uc-nav-btn" data-action="next" aria-label="Next"${t}>&#8250;</button>`:""}\n </div>`}let p="";if(this._opts.showTitle){const e=n?this._opts.showYearPicker?`<button class="uc-year-btn${this._yearPickerOpen?" uc-open":""}" data-action="year-pick" aria-label="Select year">${t}</button>`:t:"";p=`\n <div class="uc-toolbar-section uc-toolbar-center">\n <h2 class="uc-title">\n <span class="uc-title-main">${h(a)}</span>\n ${e}\n </h2>\n ${i}\n </div>`}let y="";if(this._opts.showViewSwitcher){const t=this._opts.enabledViews,e=[],a=[];if(t.includes("month")&&(e.push(`<button class="uc-btn uc-view-btn${"month"===this._view?" uc-active":""}" data-view="month">${h(c)}</button>`),a.push(`<button class="uc-dropdown-item${"month"===this._view?" uc-active":""}" data-view="month">${h(c)}</button>`)),t.includes("week")&&(e.push(`<button class="uc-btn uc-view-btn${"week"===this._view?" uc-active":""}" data-view="week">${h(d)}</button>`),a.push(`<button class="uc-dropdown-item${"week"===this._view?" uc-active":""}" data-view="week">${h(d)}</button>`)),t.includes("day")&&(e.push(`<button class="uc-btn uc-view-btn${"day"===this._view?" uc-active":""}" data-view="day">${h(u)}</button>`),a.push(`<button class="uc-dropdown-item${"day"===this._view?" uc-active":""}" data-view="day">${h(u)}</button>`)),t.includes("list")&&(e.push(`<button class="uc-btn uc-view-btn${"list"===this._view?" uc-active":""}" data-view="list">${h(_)}</button>`),a.push(`<button class="uc-dropdown-item${"list"===this._view?" uc-active":""}" data-view="list">${h(_)}</button>`)),e.length>0){const t=v(o,"today"),n=s(this._date,new Date)?" uc-active":"",i="list"===this._view?" disabled":"";a.push('<div class="uc-dropdown-separator"></div>'),a.push(`<button class="uc-dropdown-item${n}" data-action="today"${i}>${h(t)}</button>`),y=`\n <div class="uc-toolbar-section uc-toolbar-right">\n <div class="uc-view-switcher">\n ${e.join("")}\n </div>\n <div class="uc-view-dropdown">\n <button class="uc-btn uc-view-dropdown-btn" aria-label="View options">\n <span class="uc-view-icon">⊞</span>\n </button>\n <div class="uc-dropdown-menu">\n ${a.join("")}\n </div>\n </div>\n </div>`}}return`\n <div class="uc-toolbar">\n ${g}${p}${y}\n </div>\n `}_buildMonthView(){const{locale:a,weekStartsOn:n}=this._opts,i=l(this._date.getFullYear(),this._date.getMonth(),n),o=d(a,n,this._opts.weekdayFormat),r=this._events.map(a=>({...a,_origStart:a.start,start:_(a)?t(a.start):a.start,end:_(a)?e(a.end):a.end})),c=o.map(t=>`<div class="uc-month-day-name">${h(t)}</div>`).join(""),u=[];for(let t=0;t<i.length;t+=7)u.push(i.slice(t,t+7));let v;const p=this._root.parentElement,y=p&&p.style.height&&"auto"!==p.style.height&&""!==p.style.height;if(y){const t=p.clientHeight,e=this._root.querySelector(".uc-toolbar"),a=this._root.querySelector(".uc-month-header"),s=t-(e?e.offsetHeight:50)-(a?a.offsetHeight:36)-2,n=u.length,i=Math.floor(s/n),o=Math.floor((i-30-28)/24);v=Math.max(0,o)}else v=1/0;const m=y?Math.floor((p.clientHeight-(this._root.querySelector(".uc-toolbar")?.offsetHeight||50)-(this._root.querySelector(".uc-month-header")?.offsetHeight||36)-2)/u.length):null;let w=null;if(!y&&v===1/0){let a=-1;u.forEach(n=>{const i=r.filter(a=>n.some(s=>a.start<=e(s)&&a.end>=t(s))),o=g(i.filter(_),n);o.forEach(({slot:t})=>{a=Math.max(a,t)}),n.forEach(t=>{const e=i.filter(e=>!_(e)&&s(e.start,t)),r=o.filter(e=>{const{startCol:a,endCol:i}=e,o=n.findIndex(e=>s(e,t));return o>=a&&o<=i}).length+e.length;a=Math.max(a,r-1)})}),w=a>=0?`calc(var(--cal-header-day-height) + ${a+1} * (var(--cal-event-height) + var(--cal-event-gap)) + 8px)`:"80px"}return`\n <div class="uc-month-view">\n <div class="uc-month-header">${c}</div>\n <div class="uc-month-body">${u.map(t=>this._buildWeekRow(t,r,v,m,w)).join("")}</div>\n </div>\n `}_buildWeekRow(t,e,a,i=null,o=null){const r=this._date.getMonth(),l=e.filter(_),d=e.filter(t=>!_(t)),u=g(l,t),v=Array.from({length:7},()=>new Set);for(const{startCol:t,endCol:e,slot:a}of u)for(let s=t;s<=e;s++)v[s].add(a);const p=t.map(t=>d.filter(e=>s(e.start,t)).sort((t,e)=>t.start-e.start)),y=t.map((t,e)=>`\n <div class="uc-day-cell${n(t)?" uc-today":""}${t.getMonth()!==r?" uc-other-month":""}" data-date="${t.toISOString()}" data-action="day-click">\n <span class="uc-day-number" data-action="day-number" data-date="${t.toISOString()}">${t.getDate()}</span>\n </div>`).join("");let m="";for(const{event:t,startCol:e,endCol:s,slot:n,isStart:i,isEnd:o}of u){if(a!==1/0&&n>=a)continue;const r=100/7,l=e*r,c=(s-e+1)*r,d=`calc(var(--cal-header-day-height) + ${n} * (var(--cal-event-height) + var(--cal-event-gap)) + 4px)`,u=t.color||"var(--cal-event-bg)",v=i?"var(--cal-event-border-radius)":"0",_=o?"var(--cal-event-border-radius)":"0",g=i?"":" uc-continues-left",p=o?"":" uc-continues-right",y=this._opts.showTooltips?`data-tooltip="${h(t.tooltip||t.description||t.title)}"`:"",w=this._opts.enableResize&&o?'<div class="uc-resize-handle-right" data-action="resize-handle"></div>':"";m+=`\n <div class="uc-event-bar${g}${p}"\n style="left:calc(${l}% + 2px);width:calc(${c}% - 4px);top:${d};background:${h(u)};border-radius:${v} ${_} ${_} ${v};"\n data-event-id="${h(t.id)}" data-action="event-click"\n ${y}>\n ${i?`<span class="uc-event-title">${h(t.title)}</span>`:"&nbsp;"}\n ${w}\n </div>`}let w=-1;for(let e=0;e<7;e++){const s=100/7,n=e*s,i=t[e],o=[...v[e]],r=o.length>0?Math.max(...o)+1:0,l=p[e];if(a===1/0)l.forEach((t,e)=>{const a=r+e;w=Math.max(w,a);const i=`calc(var(--cal-header-day-height) + ${a} * (var(--cal-event-height) + var(--cal-event-gap)) + 4px)`,o=t.color||"var(--cal-event-bg)",l=c(t.start,this._opts.locale,this._opts.use24Hour),d=this._opts.showTooltips?`data-tooltip="${h(t.tooltip||t.description||t.title)}"`:"";if("list"===this._opts.monthTimedEventStyle){const e=this._opts.showTimeInItems?`<span class="uc-event-time">${h(l)}</span>`:"";m+=`\n <div class="uc-event-bar uc-event-bar--list"\n style="left:calc(${n}% + 2px);width:calc(${s}% - 4px);top:${i};"\n data-event-id="${h(t.id)}" data-action="event-click"\n ${d}>\n <span class="uc-event-dot" style="background:${h(o)};"></span>\n ${e}\n <span class="uc-event-title">${h(t.title)}</span>\n </div>`}else{const e=this._opts.showTimeInItems?`<span class="uc-event-time">${h(l)}</span>`:"";m+=`\n <div class="uc-event-bar"\n style="left:calc(${n}% + 2px);width:calc(${s}% - 4px);top:${i};background:${h(o)};"\n data-event-id="${h(t.id)}" data-action="event-click"\n ${d}>\n ${e}\n <span class="uc-event-title">${h(t.title)}</span>\n </div>`}});else{const t=[...v[e]].filter(t=>t>=a).length,o=[];for(let t=r;t<a;t++)o.push(t);let d=t;if(l.forEach((t,e)=>{if(e<o.length){const a=o[e];w=Math.max(w,a);const i=`calc(var(--cal-header-day-height) + ${a} * (var(--cal-event-height) + var(--cal-event-gap)) + 4px)`,r=t.color||"var(--cal-event-bg)",l=c(t.start,this._opts.locale,this._opts.use24Hour),d=this._opts.showTooltips?`data-tooltip="${h(t.tooltip||t.description||t.title)}"`:"";if("list"===this._opts.monthTimedEventStyle){const e=this._opts.showTimeInItems?`<span class="uc-event-time">${h(l)}</span>`:"";m+=`\n <div class="uc-event-bar uc-event-bar--list"\n style="left:calc(${n}% + 2px);width:calc(${s}% - 4px);top:${i};"\n data-event-id="${h(t.id)}" data-action="event-click"\n ${d}>\n <span class="uc-event-dot" style="background:${h(r)};"></span>\n ${e}\n <span class="uc-event-title">${h(t.title)}</span>\n </div>`}else{const e=this._opts.showTimeInItems?`<span class="uc-event-time">${h(l)}</span>`:"";m+=`\n <div class="uc-event-bar"\n style="left:calc(${n}% + 2px);width:calc(${s}% - 4px);top:${i};background:${h(r)};"\n data-event-id="${h(t.id)}" data-action="event-click"\n ${d}>\n ${e}\n <span class="uc-event-title">${h(t.title)}</span>\n </div>`}}else d++}),d>0){m+=`\n <div class="uc-more-link"\n style="left:calc(${n}% + 2px);width:calc(${s}% - 4px);top:${`calc(var(--cal-header-day-height) + ${a} * (var(--cal-event-height) + var(--cal-event-gap)) + 2px)`};"\n data-date="${i.toISOString()}" data-action="more-click">\n +${d} more\n </div>`}}}for(const{slot:t}of u)(a===1/0||t<a)&&(w=Math.max(w,t));let f="";return null!==i?f=` style="height: ${i}px;"`:null!==o&&(f=` style="min-height: ${o};"`),`\n <div class="uc-week-row"${f}>\n <div class="uc-week-cells">${y}</div>\n <div class="uc-week-events">${m}</div>\n </div>`}_buildWeekOrDayView(a){const{locale:i,weekStartsOn:o,use24Hour:r}=this._opts,l=1===a.length,u=l?" uc-day-header-single":"",p=l?[new Intl.DateTimeFormat(i,{weekday:this._opts.weekdayFormat}).format(a[0])]:d(i,o,this._opts.weekdayFormat),y=t(a[0]),m=e(a[a.length-1]),w=this._events.filter(t=>_(t)&&t.start<=m&&e(t.end)>=y).map(a=>({...a,start:t(a.start),end:e(a.end)})),f=this._events.filter(t=>!_(t)&&t.start>=y&&t.start<=m),D=a.map((t,e)=>{const a=n(t)?" uc-today":"",s=t.getDate();return`\n <div class="uc-week-day-header${a}">\n <span class="uc-week-day-name">${h(p[e])}</span>\n <span class="uc-week-day-num" data-action="day-number" data-date="${t.toISOString()}">${s}</span>\n </div>`}).join(""),b=l?w.map((t,e)=>({event:t,startCol:0,endCol:0,slot:e,isStart:!0,isEnd:!0})):g(w,a),$=b.length?Math.max(...b.map(t=>t.slot))+1:0;let S="";for(const{event:t,startCol:e,endCol:s,slot:n,isStart:i,isEnd:o}of b){const r=100/a.length,l=e*r,c=(s-e+1)*r,d=`calc(${n} * (var(--cal-event-height) + 3px) + 2px)`,u=t.color||"var(--cal-event-bg)",v=i?"var(--cal-event-border-radius)":"0",_=o?"var(--cal-event-border-radius)":"0",g=i?"":" uc-continues-left",p=o?"":" uc-continues-right",y=this._opts.showTooltips?`data-tooltip="${h(t.tooltip||t.description||t.title)}"`:"",m=this._opts.enableResize&&o?'<div class="uc-resize-handle-right" data-action="resize-handle"></div>':"";S+=`\n <div class="uc-event-bar${g}${p}"\n style="left:calc(${l}% + 2px);width:calc(${c}% - 4px);top:${d};background:${h(u)};border-radius:${v} ${_} ${_} ${v};"\n data-event-id="${h(t.id)}" data-action="event-click"\n ${y}>\n <span class="uc-event-title">${h(t.title)}</span>\n ${m}\n </div>`}const k=`calc(${Math.max(1,$)} * (var(--cal-event-height) + 3px) + 6px)`,M=new Date,E=60*M.getHours()+M.getMinutes(),T=a.length,x=Array.from({length:24},(t,e)=>`<div class="uc-hour-cell"><span class="uc-hour-label">${h(0===e?"":c(new Date(2e3,0,1,e),"en-US",r))}</span></div>`).join(""),L=a.map(t=>{const e=n(t)?" uc-today":"",a=Array.from({length:24},()=>'<div class="uc-hour-row"><div class="uc-half-hour-line"></div></div>').join(""),o=function(t){if(!t.length)return[];const e=[...t].sort((t,e)=>t.start-e.start||e.end-t.end),a=[],s=[];for(const t of e){let e=a.findIndex(e=>e<=t.start);-1===e?(e=a.length,a.push(t.end)):a[e]=t.end,s.push({event:t,col:e})}return s.map(t=>{const e=s.filter(e=>e.event.start<t.event.end&&e.event.end>t.event.start),a=Math.max(...e.map(t=>t.col))+1;return{...t,totalCols:a}})}(f.filter(e=>s(e.start,t))).map(({event:t,col:e,totalCols:a})=>{const s=60*t.start.getHours()+t.start.getMinutes(),n=60*t.end.getHours()+t.end.getMinutes(),o=`calc(${s} / 60 * var(--cal-hour-height))`,l=`calc(${Math.max(n-s,30)} / 60 * var(--cal-hour-height))`,d=100/a,u=`calc(${e*d}% + 1px)`,v=`calc(${d}% - 2px)`,_=t.color||"var(--cal-event-bg)",g=c(t.start,i,r),p=n-s<=60?" uc-timed-event--short":"",y=this._opts.showTimeInItems?`<span class="uc-event-time">${h(g)}</span>`:"",m=this._opts.showTooltips?`data-tooltip="${h(t.tooltip||t.description||t.title)}"`:"",w=this._opts.enableResize?'<div class="uc-resize-handle" data-action="resize-handle"></div>':"";return`\n <div class="uc-timed-event${p}"\n style="top:${o};height:${l};left:${u};width:${v};background:${h(_)};"\n data-event-id="${h(t.id)}" data-action="event-click"\n ${m}>\n ${y}\n <span class="uc-event-title">${h(t.title)}</span>\n ${w}\n </div>`}).join(""),l=n(t)?`<div class="uc-now-indicator" style="top:calc(${E} / 60 * var(--cal-hour-height));">\n <span class="uc-now-dot"></span>\n <span class="uc-now-line"></span>\n </div>`:"";return`<div class="uc-time-col${e}" data-date="${t.toISOString()}" data-action="slot-col">\n ${a}${o}${l}\n </div>`}).join("");return`\n <div class="${l?"uc-day-view":"uc-week-view"}">\n <div class="uc-week-header">\n <div class="uc-time-gutter-spacer"></div>\n <div class="uc-week-day-headers${u}">${D}</div>\n </div>\n <div class="uc-all-day-section">\n <div class="uc-time-gutter-spacer uc-all-day-label">${v(this._opts.locale,"allDay")}</div>\n <div class="uc-all-day-events" style="min-height:${k}">${S}</div>\n </div>\n <div class="uc-time-body">\n <div class="uc-time-grid-inner">\n <div class="uc-time-gutter">${x}</div>\n <div class="uc-time-columns" style="--uc-col-count:${T}">${L}</div>\n </div>\n </div>\n </div>`}_buildListView(){const e=new Date,a=t(e),s=new Date(a);s.setDate(s.getDate()+this._opts.listDaysForward);const n=this._events.filter(t=>t.end>=e&&t.start<=s);n.sort((e,s)=>{const n=(e.start<a?a:t(e.start))-(s.start<a?a:t(s.start));return 0!==n?n:e.start-s.start});const i=new Map;if(n.forEach(e=>{const s=e.start<a?a:t(e.start),n=`${(o=s).getFullYear()}-${String(o.getMonth()+1).padStart(2,"0")}-${String(o.getDate()).padStart(2,"0")}`;var o;i.has(n)||i.set(n,[]),i.get(n).push(e)}),0===i.size)return'\n <div class="uc-list-view">\n <div class="uc-list-empty">\n <p>No upcoming events</p>\n </div>\n </div>';let r="";return i.forEach((t,e)=>{const a=o(e),s=new Intl.DateTimeFormat(this._opts.locale,{weekday:"long",year:"numeric",month:"long",day:"numeric"}).format(a),n=t.map(t=>{const e=_(t)?"All day":c(t.start,this._opts.locale,this._opts.use24Hour),a=t.color||"var(--cal-event-bg)",s=this._opts.showTooltips?`data-tooltip="${h(t.tooltip||t.description||"")}"`:"";return`\n <div class="uc-list-event" data-event-id="${h(t.id)}" data-action="event-click" ${s}>\n <div class="uc-list-event-indicator" style="background: ${h(a)};"></div>\n <div class="uc-list-event-time">${h(e)}</div>\n <div class="uc-list-event-content">\n <div class="uc-list-event-title">${h(t.title)}</div>\n </div>\n </div>`}).join("");r+=`\n <div class="uc-list-date-group">\n <div class="uc-list-date-header">${h(s)}</div>\n <div class="uc-list-events">${n}</div>\n </div>`}),`<div class="uc-list-view">${r}</div>`}_closeYearPicker(){this._yearOutsideHandler&&(document.removeEventListener("click",this._yearOutsideHandler),this._yearOutsideHandler=null),this._yearPickerOpen=!1,this._renderToolbar()}_handleClick(e){if(this._clickSuppressed)return void(this._clickSuppressed=!1);const a=e.target.closest(".uc-view-dropdown-btn");if(a){e.stopPropagation();const t=a.parentElement,s=t.classList.contains("uc-open");return this._root.querySelectorAll(".uc-view-dropdown.uc-open").forEach(t=>t.classList.remove("uc-open")),void(s||(t.classList.add("uc-open"),this._dropdownOutsideHandler=e=>{e.target.closest(".uc-view-dropdown")||(t.classList.remove("uc-open"),document.removeEventListener("click",this._dropdownOutsideHandler))},setTimeout(()=>document.addEventListener("click",this._dropdownOutsideHandler),0)))}const s=e.target.closest("[data-view]");if(s)return this.setView(s.dataset.view),void this._root.querySelectorAll(".uc-view-dropdown.uc-open").forEach(t=>t.classList.remove("uc-open"));const n=e.target.closest("[data-action]");if(!n)return;switch(n.dataset.action){case"prev":this.navigate(-1);break;case"next":this.navigate(1);break;case"today":this.goToToday(),this._root.querySelectorAll(".uc-view-dropdown.uc-open").forEach(t=>t.classList.remove("uc-open"));break;case"year-pick":e.stopPropagation(),this._yearPickerOpen?this._closeYearPicker():(this._yearPickerOpen=!0,this._yearPickerBase=this._date.getFullYear()-4,this._renderToolbar(),this._yearOutsideHandler=t=>{t.target.closest(".uc-year-picker")||t.target.closest('[data-action="year-pick"]')||this._closeYearPicker()},setTimeout(()=>document.addEventListener("click",this._yearOutsideHandler),0));break;case"year-prev":e.stopPropagation(),this._yearPickerBase-=12,this._renderToolbar();break;case"year-next":e.stopPropagation(),this._yearPickerBase+=12,this._renderToolbar();break;case"select-year":{e.stopPropagation();const t=parseInt(n.dataset.year,10);this._date=new Date(this._date.getFullYear()!==t?new Date(this._date).setFullYear(t):this._date),this._closeYearPicker();const a=this._getRange();this._opts.onNavigate&&this._opts.onNavigate(a.start,a.end),this._fetchAndRender();break}case"event-click":{e.stopPropagation();const t=n.dataset.eventId,a=this._events.find(e=>String(e.id)===String(t));a&&this._opts.onEventClick&&this._opts.onEventClick(a,e);break}case"day-click":{if(e.target.closest('[data-action="day-number"]'))break;if(e.target.closest('[data-action="event-click"]'))break;const t=new Date(n.dataset.date);this._opts.onSlotClick&&this._opts.onSlotClick(t,e);break}case"day-number":{if(e.stopPropagation(),!this._opts.enabledViews.includes("day"))break;const a=new Date(n.dataset.date);this._date=t(a),this._view="day",this._opts.onViewChange&&this._opts.onViewChange("day"),this._fetchAndRender();break}case"more-click":{if(e.stopPropagation(),!this._opts.enabledViews.includes("day"))break;const a=new Date(n.dataset.date);this._date=t(a),this._view="day",this._opts.onViewChange&&this._opts.onViewChange("day"),this._fetchAndRender();break}case"slot-col":if(e.target.closest('[data-action="event-click"]'))break;if(this._opts.onSlotClick){const t=n,a=t.getBoundingClientRect(),s=e.clientY-a.top,i=parseFloat(getComputedStyle(this._root).getPropertyValue("--cal-hour-height"))||60,o=Math.max(0,Math.floor(s/i*60)),r=Math.floor(o/60)%24,l=15*Math.round(o%60/15),c=new Date(t.dataset.date);c.setHours(r,l,0,0),this._opts.onSlotClick(c,e)}}}_handleTooltipPosition(t){const e=t.target.closest("[data-tooltip]");if(!e||!e.dataset.tooltip)return;if(!e.dataset.tooltip.trim())return;const a=e.getBoundingClientRect(),s=window.innerWidth;e.classList.remove("uc-tooltip-left","uc-tooltip-right","uc-tooltip-bottom");const n=a.width/2-125;a.left+n+250>s-10?e.classList.add("uc-tooltip-left"):a.left+n<10&&e.classList.add("uc-tooltip-right"),a.top<50&&e.classList.add("uc-tooltip-bottom")}_handleDragStart(t){if("list"===this._view)return;const e=t.target.closest('[data-action="resize-handle"]'),a=!!e,s=e&&e.classList.contains("uc-resize-handle-right"),n=e&&e.classList.contains("uc-resize-handle"),i=t.target.closest('[data-event-id][data-action="event-click"]');if(!i)return;if(t.target.closest('.uc-year-picker, [data-action="year-pick"], .uc-toolbar'))return;const o=i.dataset.eventId,r=this._events.find(t=>String(t.id)===String(o));if(!r)return;const l=r.allDay||!1;if(a&&!this._opts.enableResize)return;if(!a&&!this._opts.enableDragDrop)return;if(n&&(l||"week"!==this._view&&"day"!==this._view))return;if(s&&!l)return;const c=this._getEventPosition(t),d=i.getBoundingClientRect(),h=c.x-d.left,u=c.y-d.top;this._dragState={mode:a?"resize":"move",resizeDirection:s?"horizontal":n?"vertical":null,eventId:o,originalEvent:{...r,start:new Date(r.start),end:new Date(r.end)},dragElement:null,startX:c.x,startY:c.y,currentX:c.x,currentY:c.y,offsetX:h,offsetY:u,originalView:this._view,isAllDay:l,hasMoved:!1,startTime:Date.now(),originalElement:i}}_handleDragMove(t){if(!this._dragState)return;const e=this._getEventPosition(t);this._dragState.currentX=e.x,this._dragState.currentY=e.y;const a=e.x-this._dragState.startX,s=e.y-this._dragState.startY,n=Math.sqrt(a*a+s*s);if(!this._dragState.hasMoved){const t=Date.now()-this._dragState.startTime;if(!(n>5||t>150))return;this._dragState.hasMoved=!0,this._createDragElement(),this._root.classList.add("uc-dragging")}if(t.type.startsWith("touch")&&t.preventDefault(),this._dragState.dragElement)if("resize"===this._dragState.mode&&"vertical"===this._dragState.resizeDirection)this._updateResizePreview(e.x,e.y);else if("resize"===this._dragState.mode&&"horizontal"===this._dragState.resizeDirection)this._updateHorizontalResizePreview(e.x);else{const t=this._getSnappedPosition(e.x,e.y);t?(this._dragState.dragElement.style.left=t.x+"px",this._dragState.dragElement.style.top=t.y+"px"):(this._dragState.dragElement.style.left=e.x-this._dragState.offsetX+"px",this._dragState.dragElement.style.top=e.y-this._dragState.offsetY+"px")}}_getSnappedPosition(t,e){if("week"!==this._view&&"day"!==this._view)return null;const a=this._calculateDropPosition(t,e);if(!a)return null;const s=this._dragState.dragElement;if(!s)return null;if(!a.isAllDay){const e=this._root.querySelector(".uc-time-columns");if(!e)return null;const n=e.querySelectorAll(".uc-time-col");let i=null;for(const e of n){const a=e.getBoundingClientRect();if(t>=a.left&&t<a.right){i=e;break}}if(!i)return null;const o=i.getBoundingClientRect(),r=(60*a.date.getHours()+a.date.getMinutes())/60*(parseFloat(getComputedStyle(this._root).getPropertyValue("--cal-hour-height"))||60),l=s.querySelector(".uc-event-time");if(l){const t=c(a.date,this._opts.locale,this._opts.use24Hour);l.textContent=t}return{x:o.left+4,y:o.top+r}}if(a.isAllDay){const e=this._root.querySelector(".uc-all-day-events");if(!e)return null;const a=e.getBoundingClientRect(),s="day"===this._view?[this._date]:r(this._date,this._opts.weekStartsOn),n=a.width/s.length,i=t-a.left,o=Math.floor(i/n);return o<0||o>=s.length?null:{x:a.left+o*n+4,y:a.top+4}}return null}_updateResizePreview(t,e){const a=this._dragState.dragElement,s=this._dragState.originalEvent,n=this._root.querySelector(".uc-time-columns");if(!n)return;const i=n.querySelectorAll(".uc-time-col");let o=null;for(const e of i){const a=e.getBoundingClientRect();if(t>=a.left&&t<a.right){o=e;break}}if(!o)return;const r=o.getBoundingClientRect(),l=Math.max(0,e-r.top),d=parseFloat(getComputedStyle(this._root).getPropertyValue("--cal-hour-height"))||60,h=Math.floor(l/d*60),u=Math.floor(h/60)%24,v=15*Math.round(h%60/15),_=new Date(s.start);_.setHours(u,v,0,0),_<=s.start&&_.setTime(s.start.getTime()+9e5);const g=(_-s.start)/6e4/60*d;a.style.height=g+"px";const p=a.querySelector(".uc-event-time");if(p){const t=c(s.start,this._opts.locale,this._opts.use24Hour),e=c(_,this._opts.locale,this._opts.use24Hour);p.textContent=`${t} - ${e}`}this._dragState.newEndTime=_}_updateHorizontalResizePreview(t){const a=this._dragState.dragElement,s=this._dragState.originalEvent,n=this._dragState.originalElement;if(!n)return;const i=n.getBoundingClientRect(),o=t-i.left;let c;if("month"===this._view){const a=this._root.querySelector(".uc-month-body");if(!a)return;const s=a.getBoundingClientRect(),n=s.width/7,o=t-s.left,r=Math.floor(o/n),d=l(this._date.getFullYear(),this._date.getMonth(),this._opts.weekStartsOn),h=i.top-s.top,u=s.height/Math.ceil(d.length/7),v=7*Math.floor(h/u)+r;v>=0&&v<d.length&&(c=e(d[v]))}else{const a="day"===this._view?[this._date]:r(this._date,this._opts.weekStartsOn),s=this._root.querySelector(".uc-all-day-events");if(!s)return;const n=s.getBoundingClientRect(),i=n.width/a.length,o=t-n.left,l=Math.floor(o/i);l>=0&&l<a.length&&(c=e(a[l]))}if(!c)return;c<s.start&&(c=e(s.start));const d=o+20;a.style.width=Math.max(d,60)+"px",this._dragState.newEndDate=c}_handleDragEnd(t){if(!this._dragState)return;if(this._dragState.hasMoved){if(t.preventDefault(),t.stopPropagation(),this._clickSuppressed=!0,setTimeout(()=>{this._clickSuppressed=!1},10),"resize"===this._dragState.mode&&"vertical"===this._dragState.resizeDirection)this._dragState.newEndTime&&this._performResize(this._dragState.newEndTime);else if("resize"===this._dragState.mode&&"horizontal"===this._dragState.resizeDirection)this._dragState.newEndDate&&this._performHorizontalResize(this._dragState.newEndDate);else{const e=this._getEventPosition(t),a=this._calculateDropPosition(e.x,e.y);a&&this._performDrop(a)}this._cleanupDrag()}else this._dragState=null}_handleDragKeyDown(t){this._dragState&&this._dragState.hasMoved&&"Escape"===t.key&&this._cleanupDrag()}_getEventPosition(t){if(t.type.startsWith("touch")){const e=t.touches[0]||t.changedTouches[0];return{x:e.clientX,y:e.clientY}}return{x:t.clientX,y:t.clientY}}_createDragElement(){const t=this._root.querySelector(`[data-event-id="${this._dragState.eventId}"]`);if(!t)return;const e=t.cloneNode(!0);e.classList.add("uc-dragging-element");const a=t.getBoundingClientRect();e.style.position="fixed",e.style.pointerEvents="none",e.style.zIndex="10000",e.style.opacity="0.8",e.style.width=t.offsetWidth+"px","resize"===this._dragState.mode?(e.style.left=a.left+"px",e.style.top=a.top+"px",e.style.height=t.offsetHeight+"px"):(e.style.left=this._dragState.currentX-this._dragState.offsetX+"px",e.style.top=this._dragState.currentY-this._dragState.offsetY+"px"),document.body.appendChild(e),this._dragState.dragElement=e}_cleanupDrag(){this._dragState&&this._dragState.dragElement&&this._dragState.dragElement.remove(),this._root.classList.remove("uc-dragging"),this._dragState=null}_calculateDropPosition(t,e){if("week"===this._view||"day"===this._view){const a=this._calculateAllDayDropPosition(t,e);if(a)return a;const s=this._calculateTimedDropPosition(t,e);if(s)return s}return"month"===this._view?this._calculateMonthDropPosition(t,e):null}_calculateMonthDropPosition(t,e){const a=this._root.querySelector(".uc-month-body");if(!a)return null;const s=a.getBoundingClientRect(),n=t-s.left,i=e-s.top,o=s.width/7,r=a.querySelectorAll(".uc-week-row").length,c=s.height/r,d=Math.floor(n/o),h=Math.floor(i/c),u=l(this._date.getFullYear(),this._date.getMonth(),this._opts.weekStartsOn),v=7*h+d;return d<0||d>=7||v<0||v>=u.length?null:{date:u[v],isMonthView:!0}}_calculateTimedDropPosition(t,e){const a=this._root.querySelector(".uc-time-columns");if(!a)return null;const s=a.querySelectorAll(".uc-time-col");let n=null;for(const e of s){const a=e.getBoundingClientRect();if(t>=a.left&&t<a.right){n=e;break}}if(!n)return null;const i=n.getBoundingClientRect(),o=Math.max(0,e-i.top),r=parseFloat(getComputedStyle(this._root).getPropertyValue("--cal-hour-height"))||60,l=Math.floor(o/r*60),c=Math.floor(l/60)%24,d=15*Math.round(l%60/15),h=n.dataset.date;if(!h)return null;const u=new Date(h);return u.setHours(c,d,0,0),{date:u,isAllDay:!1}}_calculateAllDayDropPosition(e,a){const s=this._root.querySelector(".uc-all-day-events");if(!s)return null;const n=s.getBoundingClientRect();if(a<n.top||a>n.bottom)return null;const i="day"===this._view?[this._date]:r(this._date,this._opts.weekStartsOn),o=n.width/i.length,l=e-n.left,c=Math.floor(l/o);return c<0||c>=i.length?null:{date:t(i[c]),isAllDay:!0}}_performDrop(s){const n=this._dragState.originalEvent,o=new Date(n.start),r=new Date(n.end);let l,c,d;const h=n.allDay||this._dragState.isAllDay;if(s.isMonthView)if(h){const n=i(o,r);l=t(s.date),c=e(a(s.date,Math.max(0,n))),d=!0}else{const t=r-o;l=new Date(s.date),l.setHours(o.getHours(),o.getMinutes(),o.getSeconds(),o.getMilliseconds()),c=new Date(l.getTime()+t),d=!1}else if(s.isAllDay){const n=Math.max(0,Math.ceil((r-o)/864e5));l=t(s.date),c=e(a(s.date,n)),d=!0}else{if(l=s.date,h)c=new Date(l.getTime()+36e5);else{const t=r-o;c=new Date(l.getTime()+t)}d=!1}const u=this._events.findIndex(t=>String(t.id)===String(this._dragState.eventId));u>=0&&(this._events[u].start=l,this._events[u].end=c,this._events[u].allDay=d);const v=this._cachedEvents.findIndex(t=>String(t.id)===String(this._dragState.eventId));v>=0&&(this._cachedEvents[v].start=l,this._cachedEvents[v].end=c,this._cachedEvents[v].allDay=d),this._opts.onEventDrop&&this._opts.onEventDrop(u>=0?this._events[u]:null,o,r,l,c),this._renderView()}_performResize(t){const e=this._dragState.originalEvent,a=new Date(e.start),s=new Date(e.end),n=a,i=this._events.findIndex(t=>String(t.id)===String(this._dragState.eventId));i>=0&&(this._events[i].end=t);const o=this._cachedEvents.findIndex(t=>String(t.id)===String(this._dragState.eventId));o>=0&&(this._cachedEvents[o].end=t),this._opts.onEventDrop&&this._opts.onEventDrop(i>=0?this._events[i]:null,a,s,n,t),this._renderView()}_performHorizontalResize(t){const e=this._dragState.originalEvent,a=new Date(e.start),s=new Date(e.end),n=a,i=this._events.findIndex(t=>String(t.id)===String(this._dragState.eventId));i>=0&&(this._events[i].end=t);const o=this._cachedEvents.findIndex(t=>String(t.id)===String(this._dragState.eventId));o>=0&&(this._cachedEvents[o].end=t),this._opts.onEventDrop&&this._opts.onEventDrop(i>=0?this._events[i]:null,a,s,n,t),this._renderView()}_startNowUpdater(){this._nowInterval=setInterval(()=>{const t=this._root.querySelectorAll(".uc-now-indicator");if(!t.length)return;const e=new Date,a=`calc(${60*e.getHours()+e.getMinutes()} / 60 * var(--cal-hour-height))`;t.forEach(t=>t.style.top=a)},6e4)}}});
@@ -1,5 +1,5 @@
1
1
  /**
2
- * SimpleCalendarJs v3.0.5 — Angular Wrapper
2
+ * SimpleCalendarJs v3.0.8 — Angular Wrapper
3
3
  * A clean, modern, and feature-rich JavaScript calendar component with zero dependencies
4
4
  *
5
5
  * @author Pedro Lopes <simplecalendarjs@gmail.com>
@@ -123,7 +123,6 @@ const INIT_PROPS = [
123
123
  'showViewSwitcher',
124
124
  'showTooltips',
125
125
  'showBorder',
126
- 'maxEventsPerCell',
127
126
  'listDaysForward',
128
127
  'enabledViews',
129
128
  ];
@@ -160,7 +159,6 @@ export class SimpleCalendarJsComponent implements OnInit, OnDestroy, OnChanges,
160
159
  @Input() showViewSwitcher: boolean = true;
161
160
  @Input() showTooltips: boolean = true;
162
161
  @Input() showBorder: boolean = true;
163
- @Input() maxEventsPerCell: number = 3;
164
162
  @Input() listDaysForward: number = 30;
165
163
  @Input() enabledViews: string[] = ['month', 'week', 'day'];
166
164
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * SimpleCalendarJs v3.0.5 — React Wrapper
2
+ * SimpleCalendarJs v3.0.8 — React Wrapper
3
3
  * A clean, modern, and feature-rich JavaScript calendar component with zero dependencies
4
4
  *
5
5
  * @author Pedro Lopes <simplecalendarjs@gmail.com>
@@ -50,7 +50,6 @@ const INIT_PROPS = [
50
50
  'showViewSwitcher',
51
51
  'showTooltips',
52
52
  'showBorder',
53
- 'maxEventsPerCell',
54
53
  'listDaysForward',
55
54
  'enabledViews',
56
55
  ];
@@ -1,5 +1,5 @@
1
1
  /**
2
- * SimpleCalendarJs v3.0.5 — Vue 3 Wrapper
2
+ * SimpleCalendarJs v3.0.8 — Vue 3 Wrapper
3
3
  * A clean, modern, and feature-rich JavaScript calendar component with zero dependencies
4
4
  *
5
5
  * @author Pedro Lopes <simplecalendarjs@gmail.com>
@@ -60,7 +60,6 @@ const INIT_PROPS = [
60
60
  'showViewSwitcher',
61
61
  'showTooltips',
62
62
  'showBorder',
63
- 'maxEventsPerCell',
64
63
  'listDaysForward',
65
64
  'enabledViews',
66
65
  ];
@@ -89,7 +88,6 @@ export default defineComponent({
89
88
  showViewSwitcher: { type: Boolean, default: true },
90
89
  showTooltips: { type: Boolean, default: true },
91
90
  showBorder: { type: Boolean, default: true },
92
- maxEventsPerCell: { type: Number, default: 3 },
93
91
  listDaysForward: { type: Number, default: 30 },
94
92
  enabledViews: { type: Array, default: () => ['month', 'week', 'day'] },
95
93
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simple-calendar-js",
3
- "version": "3.0.6",
3
+ "version": "3.0.8",
4
4
  "description": "A clean, modern, and feature-rich JavaScript calendar component with zero dependencies. Responsive design and intuitive navigation.",
5
5
  "main": "dist/simple-calendar-js.min.js",
6
6
  "style": "dist/simple-calendar-js.min.css",