@dayflow/plugin-sidebar 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,749 @@
1
+ 'use strict';
2
+
3
+ var preact = require('preact');
4
+ var hooks = require('preact/hooks');
5
+ var core = require('@dayflow/core');
6
+ var blossomColorPicker = require('@dayflow/blossom-color-picker');
7
+
8
+ /******************************************************************************
9
+ Copyright (c) Microsoft Corporation.
10
+
11
+ Permission to use, copy, modify, and/or distribute this software for any
12
+ purpose with or without fee is hereby granted.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
15
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
16
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
17
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
18
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20
+ PERFORMANCE OF THIS SOFTWARE.
21
+ ***************************************************************************** */
22
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
23
+
24
+
25
+ function __awaiter(thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ }
34
+
35
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
36
+ var e = new Error(message);
37
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
38
+ };
39
+
40
+ var f=0;function u(e,t,n,o,i,u){t||(t={});var a,c,p=t;if("ref"in p)for(c in p={},t)"ref"==c?a=t[c]:p[c]=t[c];var l={type:e,props:p,key:n,ref:a,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:--f,__i:-1,__u:0,__source:i,__self:u};if("function"==typeof e&&(a=e.defaultProps))for(c in a) void 0===p[c]&&(p[c]=a[c]);return preact.options.vnode&&preact.options.vnode(l),l}
41
+
42
+ const SidebarHeader = ({ isCollapsed, onCollapseToggle, }) => {
43
+ const { t } = core.useLocale();
44
+ return (u("div", { className: core.sidebarHeader, children: [u("button", { type: "button", "aria-label": isCollapsed ? t('expandSidebar') : t('collapseSidebar'), className: core.sidebarHeaderToggle, onClick: onCollapseToggle, children: isCollapsed ? (u(core.PanelRightClose, { className: "h-4 w-4 text-gray-500 dark:text-gray-400" })) : (u(core.PanelRightOpen, { className: "h-4 w-4 text-gray-500 dark:text-gray-400" })) }), !isCollapsed && (u("div", { className: "flex flex-1 justify-between items-center ml-3", children: u("span", { className: core.sidebarHeaderTitle, children: t('calendars') }) }))] }));
45
+ };
46
+
47
+ const getCalendarInitials = (calendar) => {
48
+ if (calendar.icon) {
49
+ return calendar.icon;
50
+ }
51
+ const name = calendar.name || calendar.id;
52
+ return name.charAt(0).toUpperCase();
53
+ };
54
+ const CalendarList = ({ calendars, onToggleVisibility, onReorder, onRename, onContextMenu, onColorClick, editingId, setEditingId, activeContextMenuCalendarId, isDraggable = true, isEditable = true, }) => {
55
+ const [editingName, setEditingName] = hooks.useState('');
56
+ const editInputRef = hooks.useRef(null);
57
+ const isProcessedRef = hooks.useRef(false);
58
+ // Drag state
59
+ const [draggedCalendarId, setDraggedCalendarId] = hooks.useState(null);
60
+ const [dropTarget, setDropTarget] = hooks.useState(null);
61
+ const handleDragStart = hooks.useCallback((calendar, e) => {
62
+ // Prevent dragging when editing or not draggable
63
+ if (editingId || !isDraggable) {
64
+ e.preventDefault();
65
+ return;
66
+ }
67
+ setDraggedCalendarId(calendar.id);
68
+ // Store calendar data for drop handling
69
+ const dragData = {
70
+ calendarId: calendar.id,
71
+ calendarName: calendar.name,
72
+ calendarColors: calendar.colors,
73
+ calendarIcon: calendar.icon,
74
+ };
75
+ e.dataTransfer.setData('application/x-dayflow-calendar', JSON.stringify(dragData));
76
+ e.dataTransfer.effectAllowed = 'copy';
77
+ }, [editingId]);
78
+ const handleDragEnd = hooks.useCallback(() => {
79
+ setDraggedCalendarId(null);
80
+ setDropTarget(null);
81
+ }, []);
82
+ const handleDragOver = hooks.useCallback((e, targetId) => {
83
+ e.preventDefault();
84
+ if (draggedCalendarId === targetId) {
85
+ setDropTarget(null);
86
+ return;
87
+ }
88
+ const targetIndex = calendars.findIndex(c => c.id === targetId);
89
+ const isLast = targetIndex === calendars.length - 1;
90
+ const rect = e.currentTarget.getBoundingClientRect();
91
+ const isTopHalf = e.clientY < rect.top + rect.height / 2;
92
+ if (isLast) {
93
+ setDropTarget({
94
+ id: targetId,
95
+ position: isTopHalf ? 'top' : 'bottom',
96
+ });
97
+ }
98
+ else {
99
+ setDropTarget({
100
+ id: targetId,
101
+ position: 'top',
102
+ });
103
+ }
104
+ }, [draggedCalendarId, calendars]);
105
+ const handleDragLeave = hooks.useCallback(() => {
106
+ setDropTarget(null);
107
+ }, []);
108
+ const handleDrop = hooks.useCallback((targetCalendar) => {
109
+ if (!draggedCalendarId || !dropTarget)
110
+ return;
111
+ if (draggedCalendarId === targetCalendar.id)
112
+ return;
113
+ const fromIndex = calendars.findIndex(c => c.id === draggedCalendarId);
114
+ let toIndex = calendars.findIndex(c => c.id === targetCalendar.id);
115
+ // Adjust target index based on position
116
+ if (dropTarget.position === 'bottom') {
117
+ toIndex += 1;
118
+ }
119
+ // Adjust for removal of the item
120
+ if (toIndex > fromIndex) {
121
+ toIndex -= 1;
122
+ }
123
+ if (fromIndex !== -1 && toIndex !== -1) {
124
+ onReorder(fromIndex, toIndex);
125
+ }
126
+ setDropTarget(null);
127
+ }, [draggedCalendarId, dropTarget, calendars, onReorder]);
128
+ const handleRenameStart = hooks.useCallback((calendar) => {
129
+ if (!isEditable)
130
+ return;
131
+ isProcessedRef.current = false;
132
+ setEditingId(calendar.id);
133
+ setEditingName(calendar.name);
134
+ }, [setEditingId, isEditable]);
135
+ const handleRenameSave = hooks.useCallback(() => {
136
+ if (isProcessedRef.current)
137
+ return;
138
+ isProcessedRef.current = true;
139
+ if (editingId && editingName.trim()) {
140
+ const calendar = calendars.find(c => c.id === editingId);
141
+ if (calendar && calendar.name !== editingName.trim()) {
142
+ onRename(editingId, editingName.trim());
143
+ }
144
+ }
145
+ setEditingId(null);
146
+ setEditingName('');
147
+ }, [editingId, editingName, calendars, onRename, setEditingId]);
148
+ const handleRenameCancel = hooks.useCallback(() => {
149
+ if (isProcessedRef.current)
150
+ return;
151
+ isProcessedRef.current = true;
152
+ setEditingId(null);
153
+ setEditingName('');
154
+ }, [setEditingId]);
155
+ const handleRenameKeyDown = hooks.useCallback((e) => {
156
+ if (e.key === 'Enter') {
157
+ handleRenameSave();
158
+ }
159
+ else if (e.key === 'Escape') {
160
+ handleRenameCancel();
161
+ }
162
+ }, [handleRenameSave, handleRenameCancel]);
163
+ hooks.useEffect(() => {
164
+ if (editingId && editInputRef.current) {
165
+ editInputRef.current.focus();
166
+ editInputRef.current.select();
167
+ }
168
+ }, [editingId]);
169
+ hooks.useEffect(() => {
170
+ if (editingId) {
171
+ const calendar = calendars.find(c => c.id === editingId);
172
+ if (calendar) {
173
+ setEditingName(calendar.name);
174
+ }
175
+ }
176
+ }, [editingId, calendars]);
177
+ return (u("div", { className: "df-calendar-list flex-1 overflow-y-auto px-2 pb-3", children: u("ul", { className: "space-y-1 relative", children: calendars.map(calendar => {
178
+ var _a;
179
+ const isVisible = calendar.isVisible !== false;
180
+ const calendarColor = ((_a = calendar.colors) === null || _a === void 0 ? void 0 : _a.lineColor) || '#3b82f6';
181
+ const showIcon = Boolean(calendar.icon);
182
+ const isDropTarget = (dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.id) === calendar.id;
183
+ const isActive = activeContextMenuCalendarId === calendar.id ||
184
+ editingId === calendar.id;
185
+ return (u("li", { className: "df-calendar-list-item relative", onDragOver: e => handleDragOver(e, calendar.id), onDragLeave: handleDragLeave, onDrop: () => handleDrop(calendar), onContextMenu: e => onContextMenu(e, calendar.id), children: [isDropTarget && dropTarget.position === 'top' && (u("div", { className: "absolute top-0 left-0 right-0 h-0.5 bg-primary z-10 pointer-events-none" })), u("div", { draggable: isDraggable && !editingId, onDragStart: e => handleDragStart(calendar, e), onDragEnd: handleDragEnd, className: `rounded transition ${draggedCalendarId === calendar.id ? 'opacity-50' : ''} ${isDraggable ? 'cursor-grab' : 'cursor-default'}`, children: u("div", { className: `group flex items-center rounded px-2 py-2 transition hover:bg-gray-100 dark:hover:bg-slate-800 ${isActive ? 'bg-gray-100 dark:bg-slate-800' : ''}`, title: calendar.name, children: [u("input", { type: "checkbox", className: "calendar-checkbox cursor-pointer shrink-0", style: {
186
+ '--checkbox-color': calendarColor,
187
+ }, checked: isVisible, onChange: event => onToggleVisibility(calendar.id, event.target.checked), onClick: e => {
188
+ if (onColorClick && isVisible) {
189
+ e.preventDefault();
190
+ onColorClick(e, calendar.id);
191
+ }
192
+ } }), showIcon && (u("span", { className: "ml-2 flex h-5 w-5 shrink-0 items-center justify-center text-xs font-semibold text-white", "aria-hidden": "true", children: getCalendarInitials(calendar) })), editingId === calendar.id ? (u("input", { ref: editInputRef, type: "text", value: editingName, onChange: e => setEditingName(e.target.value), onBlur: handleRenameSave, onKeyDown: handleRenameKeyDown, className: "ml-2 flex-1 min-w-0 h-5 rounded bg-white px-0 py-0 text-sm text-gray-900 focus:outline-none dark:bg-slate-700 dark:text-gray-100", onClick: e => e.stopPropagation() })) : (u("span", { className: "flex-1 pl-1 truncate text-sm text-gray-700 group-hover:text-gray-900 dark:text-gray-200 dark:group-hover:text-white ml-2", onDblClick: () => handleRenameStart(calendar), children: calendar.name || calendar.id }))] }) }), isDropTarget && dropTarget.position === 'bottom' && (u("div", { className: "absolute bottom-0 left-0 right-0 h-0.5 bg-primary z-10 pointer-events-none" }))] }, calendar.id));
193
+ }) }) }));
194
+ };
195
+
196
+ const MergeMenuItem = ({ calendars, currentCalendarId, onMergeSelect, }) => {
197
+ const { t } = core.useLocale();
198
+ const [isHovered, setIsHovered] = hooks.useState(false);
199
+ const itemRef = hooks.useRef(null);
200
+ const submenuRef = hooks.useRef(null);
201
+ const [position, setPosition] = hooks.useState({ x: 0, y: 0 });
202
+ const timeoutRef = hooks.useRef();
203
+ const handleMouseEnter = () => {
204
+ if (timeoutRef.current)
205
+ clearTimeout(timeoutRef.current);
206
+ if (itemRef.current) {
207
+ const rect = itemRef.current.getBoundingClientRect();
208
+ setPosition({ x: rect.right, y: rect.top });
209
+ }
210
+ setIsHovered(true);
211
+ };
212
+ const handleMouseLeave = () => {
213
+ timeoutRef.current = setTimeout(() => {
214
+ setIsHovered(false);
215
+ }, 100);
216
+ };
217
+ hooks.useEffect(() => {
218
+ const el = submenuRef.current;
219
+ if (el) {
220
+ const stopPropagation = (e) => e.stopPropagation();
221
+ el.addEventListener('mousedown', stopPropagation);
222
+ return () => {
223
+ el.removeEventListener('mousedown', stopPropagation);
224
+ };
225
+ }
226
+ }, [isHovered]);
227
+ const availableCalendars = calendars.filter(c => c.id !== currentCalendarId);
228
+ if (availableCalendars.length === 0)
229
+ return null;
230
+ return (u(preact.Fragment, { children: [u("div", { ref: itemRef, className: "relative flex cursor-default select-none items-center justify-between rounded-sm px-3 py-0.5 text-[12px] outline-none hover:bg-primary hover:text-white dark:text-slate-200 dark:hover:bg-primary dark:hover:text-white transition-colors", onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [u("span", { children: t('merge') }), u(core.ChevronRight, { className: "h-4 w-4" })] }), isHovered &&
231
+ core.createPortal(u("div", { ref: submenuRef, "data-submenu-content": "true", className: "fixed z-60 min-w-48 overflow-hidden rounded-md border border-slate-200 bg-white p-1 shadow-md dark:border-slate-800 dark:bg-slate-950 animate-in fade-in-0 zoom-in-95 duration-100", style: { top: position.y, left: position.x }, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onMouseDown: e => e.stopPropagation(), children: availableCalendars.map(calendar => (u("div", { className: "flex items-center cursor-pointer rounded-sm px-3 py-1 text-[12px] text-slate-900 hover:bg-primary hover:text-white dark:text-slate-50 dark:hover:bg-primary dark:hover:text-white transition-colors", onClick: e => {
232
+ e.stopPropagation();
233
+ onMergeSelect(calendar.id);
234
+ }, children: [u("div", { className: "mr-2 h-3 w-3 rounded-sm shrink-0", style: { backgroundColor: calendar.colors.lineColor } }), u("span", { className: "truncate", children: calendar.name || calendar.id })] }, calendar.id))) }), document.body)] }));
235
+ };
236
+
237
+ const MergeCalendarDialog = ({ sourceName, targetName, onConfirm, onCancel, }) => {
238
+ const { t } = core.useLocale();
239
+ return (u("div", { className: "fixed inset-0 z-100 flex items-center justify-center bg-black/50", children: u("div", { className: "w-full max-w-md rounded-lg p-6 shadow-xl bg-background", children: [u("h2", { className: "text-lg font-semibold text-gray-900 dark:text-white", children: t('mergeConfirmTitle', { sourceName, targetName }) }), u("p", { className: "mt-3 text-sm text-gray-600 dark:text-gray-300", children: t('mergeConfirmMessage', { sourceName, targetName }) }), u("div", { className: "mt-6 flex justify-end gap-3", children: [u("button", { type: "button", onClick: onCancel, className: core.cancelButton, children: t('cancel') }), u("button", { type: "button", onClick: onConfirm, className: "rounded-md bg-destructive px-3 py-2 text-xs font-medium text-destructive-foreground hover:bg-destructive/90", children: t('merge') })] })] }) }));
240
+ };
241
+
242
+ const DeleteCalendarDialog = ({ calendarId, calendarName, calendars, step, onStepChange, onConfirmDelete, onCancel, onMergeSelect, }) => {
243
+ const [showMergeDropdown, setShowMergeDropdown] = hooks.useState(false);
244
+ const { t } = core.useLocale();
245
+ return core.createPortal(u("div", { className: "fixed inset-0 z-[9999] flex items-center justify-center bg-black/50", children: u("div", { className: "w-full max-w-md rounded-lg p-6 shadow-xl bg-background", children: step === 'initial' ? (u(preact.Fragment, { children: [u("h2", { className: "text-lg font-semibold text-gray-900 dark:text-white", children: t('deleteCalendar', { calendarName }) }), u("p", { className: "mt-3 text-sm text-gray-600 dark:text-gray-300", children: t('deleteCalendarMessage', { calendarName }) }), u("div", { className: "mt-6 flex justify-between items-center", children: [u("div", { className: "relative", children: [u("button", { type: "button", onClick: () => setShowMergeDropdown(!showMergeDropdown), className: "flex items-center gap-1 rounded-md border border-gray-300 px-4 py-2 text-xs font-medium text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:text-gray-200 dark:hover:bg-slate-700", children: t('merge') }), showMergeDropdown && (u("div", { className: "absolute left-0 top-full mt-1 min-w-full w-max rounded-md border border-gray-200 bg-background shadow-lg dark:border-slate-700 z-10 max-h-60 overflow-y-auto", children: calendars
246
+ .filter(c => c.id !== calendarId)
247
+ .map(calendar => (u("div", { className: "flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-slate-700 cursor-pointer", onClick: () => {
248
+ onMergeSelect(calendar.id);
249
+ setShowMergeDropdown(false);
250
+ }, children: [u("div", { className: "mr-2 h-3 w-3 rounded-sm shrink-0", style: {
251
+ backgroundColor: calendar.colors.lineColor,
252
+ } }), u("span", { className: "whitespace-nowrap", children: calendar.name || calendar.id })] }, calendar.id))) }))] }), u("div", { className: "flex gap-3", children: [u("button", { type: "button", onClick: onCancel, className: core.cancelButton, children: t('cancel') }), u("button", { type: "button", onClick: () => onStepChange('confirm_delete'), className: "rounded-md bg-destructive px-4 py-2 text-xs font-medium text-destructive-foreground hover:bg-destructive/90", children: t('delete') })] })] })] })) : (u(preact.Fragment, { children: [u("h2", { className: "text-lg font-semibold text-gray-900 dark:text-white", children: t('confirmDeleteTitle', { calendarName }) }), u("p", { className: "mt-3 text-sm text-gray-600 dark:text-gray-300", children: t('confirmDeleteMessage') }), u("div", { className: "mt-6 flex justify-end gap-3", children: [u("button", { type: "button", onClick: onCancel, className: "rounded-md bg-background border border-border px-3 py-2 text-xs font-medium text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-slate-700", children: t('cancel') }), u("button", { type: "button", onClick: onConfirmDelete, className: "rounded-md bg-destructive px-3 py-2 text-xs font-medium text-destructive-foreground hover:bg-destructive/90", children: t('delete') })] })] })) }) }), document.body);
253
+ };
254
+
255
+ const NEW_CALENDAR_ID = 'new-calendar';
256
+ const ImportCalendarDialog = ({ calendars, filename, onConfirm, onCancel, }) => {
257
+ var _a;
258
+ const { t } = core.useLocale();
259
+ const [selectedCalendarId, setSelectedCalendarId] = hooks.useState(((_a = calendars[0]) === null || _a === void 0 ? void 0 : _a.id) || NEW_CALENDAR_ID);
260
+ const [isOpen, setIsOpen] = hooks.useState(false);
261
+ const [shouldRender, setShouldRender] = hooks.useState(false);
262
+ const dropdownRef = hooks.useRef(null);
263
+ const triggerRef = hooks.useRef(null);
264
+ hooks.useEffect(() => {
265
+ if (isOpen) {
266
+ setShouldRender(true);
267
+ }
268
+ else {
269
+ const timer = setTimeout(() => setShouldRender(false), 200);
270
+ return () => clearTimeout(timer);
271
+ }
272
+ }, [isOpen]);
273
+ hooks.useEffect(() => {
274
+ const handleClickOutside = (event) => {
275
+ var _a;
276
+ if (dropdownRef.current &&
277
+ !dropdownRef.current.contains(event.target) &&
278
+ !((_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target))) {
279
+ setIsOpen(false);
280
+ }
281
+ };
282
+ document.addEventListener('mousedown', handleClickOutside);
283
+ return () => document.removeEventListener('mousedown', handleClickOutside);
284
+ }, []);
285
+ const selectedCalendar = calendars.find(c => c.id === selectedCalendarId);
286
+ const isNewSelected = selectedCalendarId === NEW_CALENDAR_ID;
287
+ const handleSelect = (id) => {
288
+ setSelectedCalendarId(id);
289
+ setIsOpen(false);
290
+ };
291
+ const renderDropdown = () => {
292
+ var _a;
293
+ if (!shouldRender)
294
+ return null;
295
+ const rect = (_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
296
+ if (!rect)
297
+ return null;
298
+ return core.createPortal(u("div", { ref: dropdownRef, className: `fixed z-110 mt-1 max-h-60 overflow-y-auto rounded-md bg-white shadow-lg border border-gray-200 dark:border-slate-700 dark:bg-slate-800 transition-all duration-200 origin-top ${isOpen ? 'opacity-100 scale-100' : 'opacity-0 scale-95'}`, style: {
299
+ top: rect.bottom,
300
+ left: rect.left,
301
+ width: rect.width,
302
+ }, children: u("div", { className: "py-1", children: [calendars.map(calendar => (u("div", { className: `flex items-center px-3 py-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-slate-700 ${selectedCalendarId === calendar.id ? 'bg-primary/10' : ''}`, onClick: () => handleSelect(calendar.id), children: [u("div", { className: "mr-3 h-3 w-3 shrink-0 rounded-sm", style: { backgroundColor: calendar.colors.lineColor } }), u("span", { className: `flex-1 text-sm truncate ${selectedCalendarId === calendar.id ? 'font-medium text-primary' : 'text-gray-700 dark:text-gray-200'}`, children: calendar.name || calendar.id }), selectedCalendarId === calendar.id && (u(core.Check, { className: "ml-2 w-4 h-4 text-primary shrink-0" }))] }, calendar.id))), u("div", { className: "border-t border-gray-100 dark:border-slate-700 my-1" }), u("div", { className: `flex items-center px-3 py-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-slate-700 ${isNewSelected ? 'bg-primary/10' : ''}`, onClick: () => handleSelect(NEW_CALENDAR_ID), children: [u("span", { className: `flex-1 text-sm truncate ${isNewSelected ? 'font-medium text-primary' : 'text-gray-700 dark:text-gray-200 pl-6'}`, children: [t('newCalendar') || 'New Calendar', ": ", filename] }), isNewSelected && (u(core.Check, { className: "ml-2 w-4 h-4 text-primary shrink-0" }))] })] }) }), document.body);
303
+ };
304
+ return (u("div", { className: "fixed inset-0 z-100 flex items-center justify-center bg-black/50", children: u("div", { className: "w-full max-w-md rounded-lg bg-white p-6 shadow-xl dark:bg-slate-900", children: [u("h2", { className: "mb-4 text-lg font-semibold text-gray-900 dark:text-white", children: t('addSchedule') || 'Add Schedule' }), u("p", { className: "mb-4 text-sm text-gray-600 dark:text-gray-300", children: t('importCalendarMessage') ||
305
+ 'This calendar contains new events. Please select a target calendar.' }), u("div", { className: "relative", children: [u("button", { ref: triggerRef, type: "button", className: "flex items-center w-full border border-gray-300 dark:border-gray-600 rounded-md px-3 py-2 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors shadow-sm", onClick: () => setIsOpen(!isOpen), children: [!isNewSelected && selectedCalendar && (u("div", { className: "mr-3 h-3 w-3 shrink-0 rounded-sm", style: { backgroundColor: selectedCalendar.colors.lineColor } })), u("span", { className: `text-sm font-medium text-gray-700 dark:text-gray-200 flex-1 text-left truncate ${isNewSelected ? 'pl-0' : ''}`, children: isNewSelected
306
+ ? `${t('newCalendar')}: ${filename}`
307
+ : (selectedCalendar === null || selectedCalendar === void 0 ? void 0 : selectedCalendar.name) || (selectedCalendar === null || selectedCalendar === void 0 ? void 0 : selectedCalendar.id) }), u(core.ChevronsUpDown, { className: "w-4 h-4 text-gray-400 shrink-0 ml-2" })] }), renderDropdown()] }), u("div", { className: "mt-8 flex justify-end gap-3", children: [u("button", { type: "button", onClick: onCancel, className: core.cancelButton, children: t('cancel') || 'Cancel' }), u("button", { type: "button", onClick: () => onConfirm(selectedCalendarId), className: "rounded-md bg-primary px-6 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors shadow-sm", children: t('ok') || 'OK' })] })] }) }));
308
+ };
309
+
310
+ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCollapsed, setCollapsed, renderCalendarContextMenu, editingCalendarId: propEditingCalendarId, setEditingCalendarId: propSetEditingCalendarId, onCreateCalendar, colorPickerMode = 'default', }) => {
311
+ var _a, _b, _c, _d;
312
+ const { t } = core.useLocale();
313
+ const [localEditingCalendarId, setLocalEditingCalendarId] = hooks.useState(null);
314
+ const editingCalendarId = propEditingCalendarId !== undefined
315
+ ? propEditingCalendarId
316
+ : localEditingCalendarId;
317
+ const setEditingCalendarId = propSetEditingCalendarId || setLocalEditingCalendarId;
318
+ // File input ref for import
319
+ const fileInputRef = hooks.useRef(null);
320
+ const contextMenuRef = hooks.useRef(null);
321
+ const handleMonthChange = hooks.useCallback((offset) => {
322
+ const current = app.getVisibleMonth();
323
+ const next = new Date(current.getFullYear(), current.getMonth() + offset, 1);
324
+ app.setVisibleMonth(next);
325
+ }, [app]);
326
+ // Context Menu State
327
+ const [contextMenu, setContextMenu] = hooks.useState(null);
328
+ // Sidebar Context Menu State (Background)
329
+ const [sidebarContextMenu, setSidebarContextMenu] = hooks.useState(null);
330
+ const [customColorPicker, setCustomColorPicker] = hooks.useState(null);
331
+ // Merge Calendar State
332
+ const [mergeState, setMergeState] = hooks.useState(null);
333
+ // Delete Calendar State
334
+ const [deleteState, setDeleteState] = hooks.useState(null);
335
+ // Import Calendar State
336
+ const [importState, setImportState] = hooks.useState(null);
337
+ const handleContextMenu = hooks.useCallback((e, calendarId) => {
338
+ e.preventDefault();
339
+ e.stopPropagation(); // Stop propagation to prevent sidebar context menu
340
+ setContextMenu({
341
+ x: e.clientX,
342
+ y: e.clientY,
343
+ calendarId,
344
+ rowRect: e.currentTarget.getBoundingClientRect(),
345
+ });
346
+ setSidebarContextMenu(null);
347
+ }, []);
348
+ const handleSidebarContextMenu = hooks.useCallback((e) => {
349
+ e.preventDefault();
350
+ setSidebarContextMenu({
351
+ x: e.clientX,
352
+ y: e.clientY,
353
+ });
354
+ setContextMenu(null);
355
+ }, []);
356
+ const handleCloseContextMenu = hooks.useCallback(() => {
357
+ setContextMenu(null);
358
+ }, []);
359
+ const handleCloseSidebarContextMenu = hooks.useCallback(() => {
360
+ setSidebarContextMenu(null);
361
+ }, []);
362
+ const handleColorClick = hooks.useCallback((e, calendarId) => {
363
+ e.preventDefault();
364
+ e.stopPropagation();
365
+ const calendar = calendars.find(c => c.id === calendarId);
366
+ if (calendar) {
367
+ const { l, h } = blossomColorPicker.hexToHsl(calendar.colors.lineColor);
368
+ const sliderValue = blossomColorPicker.lightnessToSliderValue(l);
369
+ const rect = e.currentTarget.getBoundingClientRect();
370
+ setCustomColorPicker({
371
+ x: rect.left + rect.width / 2,
372
+ y: rect.top + rect.height / 2,
373
+ calendarId: calendarId,
374
+ initialColor: {
375
+ hue: h,
376
+ saturation: sliderValue,
377
+ lightness: l,
378
+ alpha: 100,
379
+ layer: 'outer',
380
+ },
381
+ currentColor: calendar.colors.lineColor,
382
+ });
383
+ }
384
+ }, [calendars]);
385
+ const handleDeleteCalendar = hooks.useCallback(() => {
386
+ if (contextMenu) {
387
+ setDeleteState({ calendarId: contextMenu.calendarId, step: 'initial' });
388
+ handleCloseContextMenu();
389
+ }
390
+ }, [contextMenu, handleCloseContextMenu]);
391
+ const handleColorSelect = hooks.useCallback((color) => {
392
+ if (contextMenu) {
393
+ const { colors, darkColors } = core.getCalendarColorsForHex(color);
394
+ app.updateCalendar(contextMenu.calendarId, {
395
+ colors,
396
+ darkColors,
397
+ });
398
+ handleCloseContextMenu();
399
+ }
400
+ }, [app, contextMenu, handleCloseContextMenu]);
401
+ const handleCustomColor = hooks.useCallback(() => {
402
+ if (contextMenu) {
403
+ const calendar = calendars.find(c => c.id === contextMenu.calendarId);
404
+ if (calendar) {
405
+ const { l, h } = blossomColorPicker.hexToHsl(calendar.colors.lineColor);
406
+ // Calculate slider position from lightness
407
+ const sliderValue = blossomColorPicker.lightnessToSliderValue(l);
408
+ let x = contextMenu.x;
409
+ let y = contextMenu.y;
410
+ if (contextMenu.rowRect) {
411
+ // Position it on the row (roughly where the checkbox is)
412
+ x = contextMenu.rowRect.left + 24;
413
+ y = contextMenu.rowRect.top + contextMenu.rowRect.height / 2;
414
+ }
415
+ else if (contextMenuRef.current) {
416
+ const rect = contextMenuRef.current.getBoundingClientRect();
417
+ x = rect.left + rect.width / 2;
418
+ y = rect.top + rect.height / 2;
419
+ }
420
+ setCustomColorPicker({
421
+ x,
422
+ y,
423
+ calendarId: contextMenu.calendarId,
424
+ initialColor: {
425
+ hue: h,
426
+ saturation: sliderValue,
427
+ lightness: l,
428
+ alpha: 100,
429
+ layer: 'outer',
430
+ },
431
+ currentColor: calendar.colors.lineColor,
432
+ });
433
+ }
434
+ handleCloseContextMenu();
435
+ }
436
+ }, [contextMenu, calendars, handleCloseContextMenu]);
437
+ const handleMergeSelect = hooks.useCallback((targetId) => {
438
+ if (contextMenu) {
439
+ setMergeState({
440
+ sourceId: contextMenu.calendarId,
441
+ targetId,
442
+ });
443
+ handleCloseContextMenu();
444
+ }
445
+ }, [contextMenu, handleCloseContextMenu]);
446
+ const handleMergeConfirm = hooks.useCallback(() => {
447
+ if (mergeState) {
448
+ const { sourceId, targetId } = mergeState;
449
+ app.mergeCalendars(sourceId, targetId);
450
+ setMergeState(null);
451
+ }
452
+ }, [app, mergeState]);
453
+ const handleConfirmDelete = hooks.useCallback(() => {
454
+ if (deleteState) {
455
+ app.deleteCalendar(deleteState.calendarId);
456
+ setDeleteState(null);
457
+ }
458
+ }, [app, deleteState]);
459
+ const handleDeleteMergeSelect = hooks.useCallback((targetId) => {
460
+ if (deleteState) {
461
+ setMergeState({
462
+ sourceId: deleteState.calendarId,
463
+ targetId,
464
+ });
465
+ setDeleteState(null);
466
+ }
467
+ }, [deleteState]);
468
+ // Import Calendar handler
469
+ const handleImportClick = hooks.useCallback(() => {
470
+ var _a;
471
+ (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click();
472
+ handleCloseSidebarContextMenu();
473
+ }, [handleCloseSidebarContextMenu]);
474
+ const handleFileChange = hooks.useCallback((e) => __awaiter(void 0, void 0, void 0, function* () {
475
+ var _a;
476
+ const file = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0];
477
+ if (!file)
478
+ return;
479
+ const result = yield core.importICSFile(file);
480
+ // Show dialog if found at least one valid event, even if there were some parsing errors
481
+ if (result.events.length > 0) {
482
+ setImportState({
483
+ events: result.events,
484
+ filename: file.name.replace(/\.[^/.]+$/, ''), // Remove extension
485
+ });
486
+ }
487
+ // Reset file input
488
+ if (fileInputRef.current) {
489
+ fileInputRef.current.value = '';
490
+ }
491
+ }), []);
492
+ const handleImportConfirm = hooks.useCallback((targetCalendarId) => {
493
+ if (importState) {
494
+ let finalCalendarId = targetCalendarId;
495
+ if (targetCalendarId === NEW_CALENDAR_ID) {
496
+ // Create new calendar
497
+ const colors = [
498
+ '#3b82f6',
499
+ '#10b981',
500
+ '#8b5cf6',
501
+ '#f59e0b',
502
+ '#ef4444',
503
+ '#f97316',
504
+ '#ec4899',
505
+ '#14b8a6',
506
+ '#6366f1',
507
+ '#6b7280',
508
+ ];
509
+ const randomColor = colors[Math.floor(Math.random() * colors.length)];
510
+ const { colors: calendarColors, darkColors } = core.getCalendarColorsForHex(randomColor);
511
+ finalCalendarId = core.generateUniKey();
512
+ app.createCalendar({
513
+ id: finalCalendarId,
514
+ name: importState.filename,
515
+ isDefault: false,
516
+ colors: calendarColors,
517
+ darkColors: darkColors,
518
+ isVisible: true,
519
+ });
520
+ }
521
+ importState.events.forEach(event => {
522
+ app.addEvent(Object.assign(Object.assign({}, event), { calendarId: finalCalendarId }));
523
+ });
524
+ setImportState(null);
525
+ }
526
+ }, [app, importState]);
527
+ // Export Calendar handler
528
+ const handleExportCalendar = hooks.useCallback(() => {
529
+ if (contextMenu) {
530
+ const calendar = calendars.find(c => c.id === contextMenu.calendarId);
531
+ if (calendar) {
532
+ const events = app
533
+ .getEvents()
534
+ .filter(e => e.calendarId === calendar.id);
535
+ core.downloadICS(events, {
536
+ calendarName: calendar.name,
537
+ filename: calendar.name || 'calendar',
538
+ });
539
+ }
540
+ handleCloseContextMenu();
541
+ }
542
+ }, [contextMenu, calendars, app, handleCloseContextMenu]);
543
+ const sourceCalendarName = mergeState
544
+ ? ((_a = calendars.find(c => c.id === mergeState.sourceId)) === null || _a === void 0 ? void 0 : _a.name) || 'Unknown'
545
+ : '';
546
+ const targetCalendarName = mergeState
547
+ ? ((_b = calendars.find(c => c.id === mergeState.targetId)) === null || _b === void 0 ? void 0 : _b.name) || 'Unknown'
548
+ : '';
549
+ const deleteCalendarName = deleteState
550
+ ? ((_c = calendars.find(c => c.id === deleteState.calendarId)) === null || _c === void 0 ? void 0 : _c.name) || 'Unknown'
551
+ : '';
552
+ const readOnlyConfig = app.getReadOnlyConfig();
553
+ const isEditable = !app.state.readOnly;
554
+ const isDraggable = readOnlyConfig.draggable !== false;
555
+ return (u("div", { className: core.sidebarContainer, onContextMenu: isEditable ? handleSidebarContextMenu : undefined, children: [u(SidebarHeader, { isCollapsed: isCollapsed, onCollapseToggle: () => setCollapsed(!isCollapsed) }), !isCollapsed ? (u(preact.Fragment, { children: [u(CalendarList, { calendars: calendars, onToggleVisibility: toggleCalendarVisibility, onReorder: isDraggable ? app.reorderCalendars : () => { }, onRename: isEditable
556
+ ? (id, newName) => app.updateCalendar(id, { name: newName })
557
+ : () => { }, onContextMenu: isEditable ? handleContextMenu : () => { }, onColorClick: isEditable ? handleColorClick : undefined, editingId: editingCalendarId, setEditingId: setEditingCalendarId, activeContextMenuCalendarId: contextMenu === null || contextMenu === void 0 ? void 0 : contextMenu.calendarId, isDraggable: isDraggable, isEditable: isEditable }), u("div", { className: "border-t border-gray-200 dark:border-slate-800", children: u(core.MiniCalendar, { visibleMonth: app.getVisibleMonth(), currentDate: app.getCurrentDate(), showHeader: true, onMonthChange: handleMonthChange, onDateSelect: date => app.setCurrentDate(date) }) })] })) : (u(CalendarList, { calendars: calendars, onToggleVisibility: toggleCalendarVisibility, onReorder: isDraggable ? app.reorderCalendars : () => { }, onRename: isEditable
558
+ ? (id, newName) => app.updateCalendar(id, { name: newName })
559
+ : () => { }, onContextMenu: isEditable ? handleContextMenu : () => { }, onColorClick: isEditable ? handleColorClick : undefined, editingId: editingCalendarId, setEditingId: setEditingCalendarId, activeContextMenuCalendarId: contextMenu === null || contextMenu === void 0 ? void 0 : contextMenu.calendarId, isDraggable: isDraggable, isEditable: isEditable })), contextMenu && (u(core.ContextMenu, { ref: contextMenuRef, x: contextMenu.x, y: contextMenu.y, onClose: handleCloseContextMenu, className: "w-64 p-2", children: u(core.ContentSlot, { generatorName: "calendarContextMenu", generatorArgs: {
560
+ calendar: calendars.find(c => c.id === contextMenu.calendarId),
561
+ onClose: handleCloseContextMenu,
562
+ }, defaultContent: renderCalendarContextMenu ? (renderCalendarContextMenu(calendars.find(c => c.id === contextMenu.calendarId), handleCloseContextMenu)) : (u(preact.Fragment, { children: [u(core.ContextMenuLabel, { children: t('calendarOptions') }), u(MergeMenuItem, { calendars: calendars, currentCalendarId: contextMenu.calendarId, onMergeSelect: handleMergeSelect }), u(core.ContextMenuItem, { onClick: handleDeleteCalendar, children: t('delete') }), u(core.ContextMenuItem, { onClick: handleExportCalendar, children: t('exportCalendar') || 'Export Calendar' }), u(core.ContextMenuSeparator, {}), u(core.ContextMenuColorPicker, { selectedColor: (_d = calendars.find(c => c.id === contextMenu.calendarId)) === null || _d === void 0 ? void 0 : _d.colors.lineColor, onSelect: handleColorSelect, onCustomColor: handleCustomColor })] })) }) })), sidebarContextMenu &&
563
+ core.createPortal(u(core.ContextMenu, { x: sidebarContextMenu.x, y: sidebarContextMenu.y, onClose: handleCloseSidebarContextMenu, className: "w-max p-2", children: [u(core.ContextMenuItem, { onClick: () => {
564
+ onCreateCalendar === null || onCreateCalendar === void 0 ? void 0 : onCreateCalendar();
565
+ handleCloseSidebarContextMenu();
566
+ }, children: t('newCalendar') || 'New Calendar' }), u(core.ContextMenuItem, { onClick: handleImportClick, children: t('importCalendar') || 'Import Calendar' }), u(core.ContextMenuItem, { onClick: () => {
567
+ app.triggerRender();
568
+ handleCloseSidebarContextMenu();
569
+ }, children: t('refreshAll') || 'Refresh All' })] }), document.body), u("input", { ref: fileInputRef, type: "file", accept: ".ics", style: { display: 'none' }, onChange: handleFileChange }), importState &&
570
+ core.createPortal(u(ImportCalendarDialog, { calendars: calendars, filename: importState.filename, onConfirm: handleImportConfirm, onCancel: () => setImportState(null) }), document.body), mergeState &&
571
+ core.createPortal(u(MergeCalendarDialog, { sourceName: sourceCalendarName, targetName: targetCalendarName, onConfirm: handleMergeConfirm, onCancel: () => setMergeState(null) }), document.body), deleteState &&
572
+ core.createPortal(u(DeleteCalendarDialog, { calendarId: deleteState.calendarId, calendarName: deleteCalendarName, calendars: calendars, step: deleteState.step, onStepChange: step => setDeleteState(prev => (prev ? Object.assign(Object.assign({}, prev), { step }) : null)), onConfirmDelete: handleConfirmDelete, onCancel: () => setDeleteState(null), onMergeSelect: handleDeleteMergeSelect }), document.body), customColorPicker &&
573
+ core.createPortal(u("div", { className: "fixed inset-0 z-50", onMouseDown: () => {
574
+ app.updateCalendar(customColorPicker.calendarId, {});
575
+ setCustomColorPicker(null);
576
+ }, children: u("div", { className: "absolute flex items-center justify-center", style: {
577
+ top: customColorPicker.y,
578
+ left: customColorPicker.x,
579
+ transform: 'translate(280%, -50%)',
580
+ }, onMouseDown: e => e.stopPropagation(), children: colorPickerMode === 'blossom' ? (u(core.BlossomColorPicker, { defaultValue: customColorPicker.initialColor, coreSize: 28, petalSize: 28, initialExpanded: true, adaptivePositioning: true, openOnHover: false, onChange: color => {
581
+ const { colors, darkColors } = core.getCalendarColorsForHex(color.hex);
582
+ app.updateCalendar(customColorPicker.calendarId, {
583
+ colors,
584
+ darkColors,
585
+ }, true);
586
+ }, onCollapse: () => {
587
+ app.updateCalendar(customColorPicker.calendarId, {});
588
+ setCustomColorPicker(null);
589
+ } })) : (u(core.ContentSlot, { generatorName: "colorPicker", generatorArgs: {
590
+ variant: 'sketch',
591
+ color: customColorPicker.currentColor,
592
+ onChange: (color) => {
593
+ setCustomColorPicker(prev => prev ? Object.assign(Object.assign({}, prev), { currentColor: color.hex }) : null);
594
+ const { colors, darkColors } = core.getCalendarColorsForHex(color.hex);
595
+ app.updateCalendar(customColorPicker.calendarId, {
596
+ colors,
597
+ darkColors,
598
+ }, true);
599
+ },
600
+ onChangeComplete: (color) => {
601
+ const { colors, darkColors } = core.getCalendarColorsForHex(color.hex);
602
+ app.updateCalendar(customColorPicker.calendarId, {
603
+ colors,
604
+ darkColors,
605
+ });
606
+ },
607
+ }, defaultContent: u(core.DefaultColorPicker, { color: customColorPicker.currentColor, onChange: (color, isPending) => {
608
+ setCustomColorPicker(prev => prev ? Object.assign(Object.assign({}, prev), { currentColor: color.hex }) : null);
609
+ const { colors, darkColors } = core.getCalendarColorsForHex(color.hex);
610
+ app.updateCalendar(customColorPicker.calendarId, {
611
+ colors,
612
+ darkColors,
613
+ }, isPending);
614
+ }, onClose: () => {
615
+ app.updateCalendar(customColorPicker.calendarId, {});
616
+ setCustomColorPicker(null);
617
+ } }) })) }) }), document.body)] }));
618
+ };
619
+
620
+ const DEFAULT_SIDEBAR_WIDTH = '240px';
621
+ const COLORS = [
622
+ '#ea426b',
623
+ '#f19a38',
624
+ '#f7cf46',
625
+ '#83d754',
626
+ '#51aaf2',
627
+ '#b672d0',
628
+ '#957e5e',
629
+ ];
630
+ function createSidebarPlugin(config = {}) {
631
+ return {
632
+ name: 'sidebar',
633
+ config,
634
+ install(_app) {
635
+ const sidebarWidth = core.normalizeCssWidth(config.width, DEFAULT_SIDEBAR_WIDTH);
636
+ core.registerSidebarImplementation((app) => {
637
+ var _a, _b;
638
+ const { t } = core.useLocale();
639
+ const [isCollapsed, setIsCollapsed] = hooks.useState((_a = config.initialCollapsed) !== null && _a !== void 0 ? _a : false);
640
+ const [sidebarVersion, setSidebarVersion] = hooks.useState(0);
641
+ const [editingCalendarId, setEditingCalendarId] = hooks.useState(null);
642
+ const [showCreateDialog, setShowCreateDialog] = hooks.useState(false);
643
+ const refreshSidebar = hooks.useCallback(() => {
644
+ setSidebarVersion(prev => prev + 1);
645
+ }, []);
646
+ const calendars = hooks.useMemo(() => app.getCalendars(), [app, sidebarVersion]);
647
+ const handleToggleCalendarVisibility = hooks.useCallback((calendarId, visible) => {
648
+ app.setCalendarVisibility(calendarId, visible);
649
+ refreshSidebar();
650
+ }, [app, refreshSidebar]);
651
+ const handleToggleAllCalendars = hooks.useCallback((visible) => {
652
+ app.setAllCalendarsVisibility(visible);
653
+ refreshSidebar();
654
+ }, [app, refreshSidebar]);
655
+ const handleCreateCalendar = hooks.useCallback(() => {
656
+ const createMode = config.createCalendarMode || 'inline';
657
+ if (createMode === 'modal') {
658
+ setShowCreateDialog(true);
659
+ return;
660
+ }
661
+ const randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
662
+ const { colors, darkColors } = core.getCalendarColorsForHex(randomColor);
663
+ const newId = core.generateUniKey();
664
+ const newCalendar = {
665
+ id: newId,
666
+ name: t('untitled'),
667
+ colors,
668
+ darkColors,
669
+ isVisible: true,
670
+ isDefault: false,
671
+ };
672
+ app.createCalendar(newCalendar);
673
+ setEditingCalendarId(newId);
674
+ refreshSidebar();
675
+ }, [app, t, refreshSidebar]);
676
+ const sidebarProps = hooks.useMemo(() => ({
677
+ app,
678
+ calendars,
679
+ toggleCalendarVisibility: handleToggleCalendarVisibility,
680
+ toggleAll: handleToggleAllCalendars,
681
+ isCollapsed,
682
+ setCollapsed: setIsCollapsed,
683
+ renderCalendarContextMenu: config.renderCalendarContextMenu,
684
+ createCalendarMode: config.createCalendarMode,
685
+ renderCreateCalendarDialog: config.renderCreateCalendarDialog,
686
+ editingCalendarId,
687
+ setEditingCalendarId,
688
+ onCreateCalendar: handleCreateCalendar,
689
+ colorPickerMode: config.colorPickerMode,
690
+ }), [
691
+ app,
692
+ calendars,
693
+ handleToggleCalendarVisibility,
694
+ handleToggleAllCalendars,
695
+ isCollapsed,
696
+ handleCreateCalendar,
697
+ editingCalendarId,
698
+ config,
699
+ ]);
700
+ const renderContent = () => {
701
+ var _a;
702
+ if (config.render) {
703
+ return preact.h(core.ContentSlot, {
704
+ generatorName: 'sidebar',
705
+ generatorArgs: sidebarProps,
706
+ });
707
+ }
708
+ return preact.h(DefaultCalendarSidebar, Object.assign(Object.assign({}, sidebarProps), { colorPickerMode: (_a = config.colorPickerMode) !== null && _a !== void 0 ? _a : sidebarProps.colorPickerMode }));
709
+ };
710
+ const renderExtraContent = () => {
711
+ if (!showCreateDialog)
712
+ return null;
713
+ const onClose = () => setShowCreateDialog(false);
714
+ const onCreate = (newCalendar) => {
715
+ app.createCalendar(newCalendar);
716
+ setShowCreateDialog(false);
717
+ refreshSidebar();
718
+ };
719
+ const generatorArgs = {
720
+ onClose,
721
+ onCreate,
722
+ colorPickerMode: config.colorPickerMode,
723
+ };
724
+ return preact.h(core.ContentSlot, {
725
+ generatorName: 'createCalendarDialog',
726
+ generatorArgs,
727
+ defaultContent: preact.h(core.CreateCalendarDialog, {
728
+ onClose,
729
+ onCreate,
730
+ colorPickerMode: config.colorPickerMode,
731
+ }),
732
+ });
733
+ };
734
+ return {
735
+ enabled: true,
736
+ width: sidebarWidth,
737
+ isCollapsed,
738
+ toggleCollapsed: () => setIsCollapsed(prev => !prev),
739
+ miniWidth: (_b = config.miniWidth) !== null && _b !== void 0 ? _b : '50px',
740
+ content: renderContent(),
741
+ extraContent: renderExtraContent(),
742
+ safeAreaLeft: 0,
743
+ };
744
+ });
745
+ },
746
+ };
747
+ }
748
+
749
+ exports.createSidebarPlugin = createSidebarPlugin;