@dayflow/plugin-sidebar 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  **English** | [中文](README.zh.md) | [日本語](README.ja.md) | [Getting Started & Contributing](CONTRIBUTING.md)
4
4
 
5
- A flexible and feature-rich calendar component library for React applications with drag-and-drop support, multiple
6
- views, and plugin architecture.
5
+ A flexible and feature-rich calendar component library for **React, Vue, Angular, and Svelte** with drag-and-drop support, multiple views, and plugin architecture.
7
6
 
8
7
  [![npm](https://img.shields.io/npm/v/@dayflow/core?logo=npm&color=blue&label=version)](https://www.npmjs.com/package/@dayflow/core)
9
8
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen?logo=github)](https://github.com/dayflow-js/dayflow/pulls)
@@ -12,21 +11,51 @@ views, and plugin architecture.
12
11
 
13
12
  ## Features
14
13
 
15
- ### Monthly, Weekly, Daily and Various View Types
14
+ ### Daily, Weekly, Monthly and Yearly View Types
16
15
 
17
- | Monthly | Weekly |
18
- | --------------------------------------- | -------------------------------------- |
19
- | ![image](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/MonthView.png) | ![image](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/WeekView.png) |
16
+ #### Day View
20
17
 
21
- | Daily | Event Stack Level |
22
- | ------------------------------------- | ---------------------------------------- |
23
- | ![image](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/DayView.png) | ![image](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/stackLevel.png) |
18
+ ![Day View](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/DayView.png)
24
19
 
25
- ### Default Panel (with multiple Event Detail Panel options available)
20
+ #### Week View
26
21
 
27
- | Detail Popup | Detail Dialog |
28
- | ----------------------------------- | ------------------------------------ |
29
- | ![image](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/popup.png) | ![image](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/dialog.png) |
22
+ ![Week View](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/WeekView.png)
23
+
24
+ #### Month View
25
+
26
+ ![Month View](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/MonthView.png)
27
+
28
+ #### Year View(Fixed-Week)
29
+
30
+ ![Year View](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/Year-Fixed-Week.png)
31
+
32
+ #### Year View(Year-Canvas)
33
+
34
+ ![Year Canvas View](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/Year-Canvas.png)
35
+
36
+ ### Mobile View Support
37
+
38
+ #### Mobile Day & Year View
39
+
40
+ ![Mobile Day and Year View](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/Mobile-Day-Year.png)
41
+
42
+ #### Mobile Week & Month View
43
+
44
+ ![Mobile Week and Month View](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/Mobile-Week-Month.png)
45
+
46
+ ### Multiple Event Detail Panel options
47
+
48
+ #### Detail Popup
49
+
50
+ ![Popup](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/popup.png)
51
+
52
+ #### Detail Dialog
53
+
54
+ ![Dialog](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/dialog.png)
55
+
56
+ ### Dark Mode Support
57
+
58
+ ![Dark Mode](https://raw.githubusercontent.com/dayflow-js/calendar/main/assets/images/DarkMode.png)
30
59
 
31
60
  ### Easy to resize and drag
32
61
 
package/dist/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
+ import { useLocale, createPortal, cancelButton, ChevronsUpDown, Check, ChevronRight, sidebarHeader, sidebarHeaderToggle, PanelRightClose, PanelRightOpen, sidebarHeaderTitle, getCalendarColorsForHex, generateUniKey, downloadICS, MiniCalendar, ContextMenu, ContentSlot, ContextMenuLabel, ContextMenuItem, ContextMenuSeparator, ContextMenuColorPicker, BlossomColorPicker, DefaultColorPicker, importICSFile, sidebarContainer, normalizeCssWidth, registerSidebarImplementation, CreateCalendarDialog } from '@dayflow/core';
1
2
  import { options, Fragment, h } from 'preact';
2
3
  import { useState, useRef, useCallback, useEffect, useMemo } from 'preact/hooks';
3
- import { useLocale, sidebarHeader, sidebarHeaderToggle, PanelRightClose, PanelRightOpen, sidebarHeaderTitle, ChevronRight, createPortal, cancelButton, ChevronsUpDown, Check, getCalendarColorsForHex, generateUniKey, downloadICS, MiniCalendar, ContextMenu, ContentSlot, ContextMenuLabel, ContextMenuItem, ContextMenuSeparator, ContextMenuColorPicker, BlossomColorPicker, DefaultColorPicker, importICSFile, sidebarContainer, normalizeCssWidth, registerSidebarImplementation, CreateCalendarDialog } from '@dayflow/core';
4
4
  import { hexToHsl, lightnessToSliderValue } from '@dayflow/blossom-color-picker';
5
5
 
6
6
  /******************************************************************************
@@ -37,11 +37,6 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
37
37
 
38
38
  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 options.vnode&&options.vnode(l),l}
39
39
 
40
- const SidebarHeader = ({ isCollapsed, onCollapseToggle, }) => {
41
- const { t } = useLocale();
42
- return (u("div", { className: sidebarHeader, children: [u("button", { type: "button", "aria-label": isCollapsed ? t('expandSidebar') : t('collapseSidebar'), className: sidebarHeaderToggle, onClick: onCollapseToggle, children: isCollapsed ? (u(PanelRightClose, { className: "h-4 w-4 text-gray-500 dark:text-gray-400" })) : (u(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: sidebarHeaderTitle, children: t('calendars') }) }))] }));
43
- };
44
-
45
40
  const getCalendarInitials = (calendar) => {
46
41
  if (calendar.icon) {
47
42
  return calendar.icon;
@@ -70,9 +65,11 @@ const CalendarList = ({ calendars, onToggleVisibility, onReorder, onRename, onCo
70
65
  calendarColors: calendar.colors,
71
66
  calendarIcon: calendar.icon,
72
67
  };
73
- e.dataTransfer.setData('application/x-dayflow-calendar', JSON.stringify(dragData));
74
- e.dataTransfer.effectAllowed = 'copy';
75
- }, [editingId]);
68
+ if (e.dataTransfer) {
69
+ e.dataTransfer.setData('application/x-dayflow-calendar', JSON.stringify(dragData));
70
+ e.dataTransfer.effectAllowed = 'copy';
71
+ }
72
+ }, [editingId, isDraggable]);
76
73
  const handleDragEnd = useCallback(() => {
77
74
  setDraggedCalendarId(null);
78
75
  setDropTarget(null);
@@ -172,7 +169,7 @@ const CalendarList = ({ calendars, onToggleVisibility, onReorder, onRename, onCo
172
169
  }
173
170
  }
174
171
  }, [editingId, calendars]);
175
- 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 => {
172
+ return (u("div", { className: 'df-calendar-list flex-1 overflow-y-auto px-2 pb-3', children: u("ul", { className: 'relative space-y-1', children: calendars.map(calendar => {
176
173
  var _a;
177
174
  const isVisible = calendar.isVisible !== false;
178
175
  const calendarColor = ((_a = calendar.colors) === null || _a === void 0 ? void 0 : _a.lineColor) || '#3b82f6';
@@ -180,69 +177,23 @@ const CalendarList = ({ calendars, onToggleVisibility, onReorder, onRename, onCo
180
177
  const isDropTarget = (dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.id) === calendar.id;
181
178
  const isActive = activeContextMenuCalendarId === calendar.id ||
182
179
  editingId === calendar.id;
183
- 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: {
180
+ 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: 'pointer-events-none absolute top-0 right-0 left-0 z-10 h-0.5 bg-primary' })), 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 shrink-0 cursor-pointer', style: {
184
181
  '--checkbox-color': calendarColor,
185
- }, checked: isVisible, onChange: event => onToggleVisibility(calendar.id, event.target.checked) }), 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));
182
+ }, checked: isVisible, onChange: event => onToggleVisibility(calendar.id, event.target.checked) }), 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 h-5 min-w-0 flex-1 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: 'ml-2 flex-1 truncate pl-1 text-sm text-gray-700 group-hover:text-gray-900 dark:text-gray-200 dark:group-hover:text-white', onDblClick: () => handleRenameStart(calendar), children: calendar.name || calendar.id }))] }) }), isDropTarget && dropTarget.position === 'bottom' && (u("div", { className: 'pointer-events-none absolute right-0 bottom-0 left-0 z-10 h-0.5 bg-primary' }))] }, calendar.id));
186
183
  }) }) }));
187
184
  };
188
185
 
189
- const MergeMenuItem = ({ calendars, currentCalendarId, onMergeSelect, }) => {
190
- const { t } = useLocale();
191
- const [isHovered, setIsHovered] = useState(false);
192
- const itemRef = useRef(null);
193
- const submenuRef = useRef(null);
194
- const [position, setPosition] = useState({ x: 0, y: 0 });
195
- const timeoutRef = useRef();
196
- const handleMouseEnter = () => {
197
- if (timeoutRef.current)
198
- clearTimeout(timeoutRef.current);
199
- if (itemRef.current) {
200
- const rect = itemRef.current.getBoundingClientRect();
201
- setPosition({ x: rect.right, y: rect.top });
202
- }
203
- setIsHovered(true);
204
- };
205
- const handleMouseLeave = () => {
206
- timeoutRef.current = setTimeout(() => {
207
- setIsHovered(false);
208
- }, 100);
209
- };
210
- useEffect(() => {
211
- const el = submenuRef.current;
212
- if (el) {
213
- const stopPropagation = (e) => e.stopPropagation();
214
- el.addEventListener('mousedown', stopPropagation);
215
- return () => {
216
- el.removeEventListener('mousedown', stopPropagation);
217
- };
218
- }
219
- }, [isHovered]);
220
- const availableCalendars = calendars.filter(c => c.id !== currentCalendarId);
221
- if (availableCalendars.length === 0)
222
- return null;
223
- return (u(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(ChevronRight, { className: "h-4 w-4" })] }), isHovered &&
224
- 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 => {
225
- e.stopPropagation();
226
- onMergeSelect(calendar.id);
227
- }, 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)] }));
228
- };
229
-
230
- const MergeCalendarDialog = ({ sourceName, targetName, onConfirm, onCancel, }) => {
231
- const { t } = useLocale();
232
- 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: 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') })] })] }) }));
233
- };
234
-
235
186
  const DeleteCalendarDialog = ({ calendarId, calendarName, calendars, step, onStepChange, onConfirmDelete, onCancel, onMergeSelect, }) => {
236
187
  const [showMergeDropdown, setShowMergeDropdown] = useState(false);
237
188
  const { t } = useLocale();
238
- return 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(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
189
+ return 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 bg-background p-6 shadow-xl', children: step === 'initial' ? (u(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 items-center justify-between', 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 top-full left-0 z-10 mt-1 max-h-60 w-max min-w-full overflow-y-auto rounded-md border border-gray-200 bg-background shadow-lg dark:border-slate-700', children: calendars
239
190
  .filter(c => c.id !== calendarId)
240
- .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: () => {
191
+ .map(calendar => (u("div", { className: 'flex cursor-pointer items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-slate-700', onClick: () => {
241
192
  onMergeSelect(calendar.id);
242
193
  setShowMergeDropdown(false);
243
- }, children: [u("div", { className: "mr-2 h-3 w-3 rounded-sm shrink-0", style: {
194
+ }, children: [u("div", { className: 'mr-2 h-3 w-3 shrink-0 rounded-sm', style: {
244
195
  backgroundColor: calendar.colors.lineColor,
245
- } }), 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: 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(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);
196
+ } }), 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: 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(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 border border-border bg-background 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);
246
197
  };
247
198
 
248
199
  const NEW_CALENDAR_ID = 'new-calendar';
@@ -288,25 +239,76 @@ const ImportCalendarDialog = ({ calendars, filename, onConfirm, onCancel, }) =>
288
239
  const rect = (_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
289
240
  if (!rect)
290
241
  return null;
291
- return 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: {
242
+ return createPortal(u("div", { ref: dropdownRef, className: `fixed z-110 mt-1 max-h-60 origin-top overflow-y-auto rounded-md border border-gray-200 bg-white shadow-lg transition-all duration-200 dark:border-slate-700 dark:bg-slate-800 ${isOpen ? 'scale-100 opacity-100' : 'scale-95 opacity-0'}`, style: {
292
243
  top: rect.bottom,
293
244
  left: rect.left,
294
245
  width: rect.width,
295
- }, 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(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(Check, { className: "ml-2 w-4 h-4 text-primary shrink-0" }))] })] }) }), document.body);
246
+ }, children: u("div", { className: 'py-1', children: [calendars.map(calendar => (u("div", { className: `flex cursor-pointer items-center px-3 py-2 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 truncate text-sm ${selectedCalendarId === calendar.id ? 'font-medium text-primary' : 'text-gray-700 dark:text-gray-200'}`, children: calendar.name || calendar.id }), selectedCalendarId === calendar.id && (u(Check, { className: 'ml-2 h-4 w-4 shrink-0 text-primary' }))] }, calendar.id))), u("div", { className: 'my-1 border-t border-gray-100 dark:border-slate-700' }), u("div", { className: `flex cursor-pointer items-center px-3 py-2 hover:bg-gray-100 dark:hover:bg-slate-700 ${isNewSelected ? 'bg-primary/10' : ''}`, onClick: () => handleSelect(NEW_CALENDAR_ID), children: [u("span", { className: `flex-1 truncate text-sm ${isNewSelected ? 'font-medium text-primary' : 'pl-6 text-gray-700 dark:text-gray-200'}`, children: [t('newCalendar') || 'New Calendar', ": ", filename] }), isNewSelected && (u(Check, { className: 'ml-2 h-4 w-4 shrink-0 text-primary' }))] })] }) }), document.body);
296
247
  };
297
- 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') ||
298
- '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
248
+ 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') ||
249
+ 'This calendar contains new events. Please select a target calendar.' }), u("div", { className: 'relative', children: [u("button", { ref: triggerRef, type: 'button', className: 'flex w-full items-center rounded-md border border-gray-300 px-3 py-2 shadow-sm transition-colors hover:bg-gray-50 dark:border-gray-600 dark:hover:bg-gray-800', 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: `flex-1 truncate text-left text-sm font-medium text-gray-700 dark:text-gray-200 ${isNewSelected ? 'pl-0' : ''}`, children: isNewSelected
299
250
  ? `${t('newCalendar')}: ${filename}`
300
- : (selectedCalendar === null || selectedCalendar === void 0 ? void 0 : selectedCalendar.name) || (selectedCalendar === null || selectedCalendar === void 0 ? void 0 : selectedCalendar.id) }), u(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: 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' })] })] }) }));
251
+ : (selectedCalendar === null || selectedCalendar === void 0 ? void 0 : selectedCalendar.name) || (selectedCalendar === null || selectedCalendar === void 0 ? void 0 : selectedCalendar.id) }), u(ChevronsUpDown, { className: 'ml-2 h-4 w-4 shrink-0 text-gray-400' })] }), renderDropdown()] }), u("div", { className: 'mt-8 flex justify-end gap-3', children: [u("button", { type: 'button', onClick: onCancel, className: 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 shadow-sm transition-colors hover:bg-primary/90', children: t('ok') || 'OK' })] })] }) }));
252
+ };
253
+
254
+ const MergeCalendarDialog = ({ sourceName, targetName, onConfirm, onCancel, }) => {
255
+ const { t } = useLocale();
256
+ 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-background p-6 shadow-xl', 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: 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') })] })] }) }));
257
+ };
258
+
259
+ const stopPropagation = (e) => e.stopPropagation();
260
+ const MergeMenuItem = ({ calendars, currentCalendarId, onMergeSelect, }) => {
261
+ const { t } = useLocale();
262
+ const [isHovered, setIsHovered] = useState(false);
263
+ const itemRef = useRef(null);
264
+ const submenuRef = useRef(null);
265
+ const [position, setPosition] = useState({ x: 0, y: 0 });
266
+ const timeoutRef = useRef();
267
+ const handleMouseEnter = () => {
268
+ if (timeoutRef.current)
269
+ clearTimeout(timeoutRef.current);
270
+ if (itemRef.current) {
271
+ const rect = itemRef.current.getBoundingClientRect();
272
+ setPosition({ x: rect.right, y: rect.top });
273
+ }
274
+ setIsHovered(true);
275
+ };
276
+ const handleMouseLeave = () => {
277
+ timeoutRef.current = setTimeout(() => {
278
+ setIsHovered(false);
279
+ }, 100);
280
+ };
281
+ useEffect(() => {
282
+ const el = submenuRef.current;
283
+ if (el) {
284
+ el.addEventListener('mousedown', stopPropagation);
285
+ return () => {
286
+ el.removeEventListener('mousedown', stopPropagation);
287
+ };
288
+ }
289
+ }, [isHovered]);
290
+ const availableCalendars = calendars.filter(c => c.id !== currentCalendarId);
291
+ if (availableCalendars.length === 0)
292
+ return null;
293
+ return (u(Fragment, { children: [u("div", { ref: itemRef, className: 'relative flex cursor-default items-center justify-between rounded-sm px-3 py-0.5 text-[12px] transition-colors outline-none select-none hover:bg-primary hover:text-white dark:text-slate-200 dark:hover:bg-primary dark:hover:text-white', onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [u("span", { children: t('merge') }), u(ChevronRight, { className: 'h-4 w-4' })] }), isHovered &&
294
+ createPortal(u("div", { ref: submenuRef, "data-submenu-content": 'true', className: 'animate-in fade-in-0 zoom-in-95 fixed z-60 min-w-48 overflow-hidden rounded-md border border-slate-200 bg-white p-1 shadow-md duration-100 dark:border-slate-800 dark:bg-slate-950', style: { top: position.y, left: position.x }, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onMouseDown: e => e.stopPropagation(), children: availableCalendars.map(calendar => (u("div", { className: 'flex cursor-pointer items-center rounded-sm px-3 py-1 text-[12px] text-slate-900 transition-colors hover:bg-primary hover:text-white dark:text-slate-50 dark:hover:bg-primary dark:hover:text-white', onClick: e => {
295
+ e.stopPropagation();
296
+ onMergeSelect(calendar.id);
297
+ }, children: [u("div", { className: 'mr-2 h-3 w-3 shrink-0 rounded-sm', style: { backgroundColor: calendar.colors.lineColor } }), u("span", { className: 'truncate', children: calendar.name || calendar.id })] }, calendar.id))) }), document.body)] }));
298
+ };
299
+
300
+ const SidebarHeader = ({ isCollapsed, onCollapseToggle, }) => {
301
+ const { t } = useLocale();
302
+ return (u("div", { className: sidebarHeader, children: [u("button", { type: 'button', "aria-label": isCollapsed ? t('expandSidebar') : t('collapseSidebar'), className: sidebarHeaderToggle, onClick: onCollapseToggle, children: isCollapsed ? (u(PanelRightClose, { className: 'h-4 w-4 text-gray-500 dark:text-gray-400' })) : (u(PanelRightOpen, { className: 'h-4 w-4 text-gray-500 dark:text-gray-400' })) }), !isCollapsed && (u("div", { className: 'ml-3 flex flex-1 items-center justify-between', children: u("span", { className: sidebarHeaderTitle, children: t('calendars') }) }))] }));
301
303
  };
302
304
 
303
305
  const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCollapsed, setCollapsed, renderCalendarContextMenu, editingCalendarId: propEditingCalendarId, setEditingCalendarId: propSetEditingCalendarId, onCreateCalendar, colorPickerMode = 'default', }) => {
304
306
  var _a, _b, _c, _d;
305
307
  const { t } = useLocale();
306
308
  const [localEditingCalendarId, setLocalEditingCalendarId] = useState(null);
307
- const editingCalendarId = propEditingCalendarId !== undefined
308
- ? propEditingCalendarId
309
- : localEditingCalendarId;
309
+ const editingCalendarId = propEditingCalendarId === undefined
310
+ ? localEditingCalendarId
311
+ : propEditingCalendarId;
310
312
  const setEditingCalendarId = propSetEditingCalendarId || setLocalEditingCalendarId;
311
313
  // File input ref for import
312
314
  const fileInputRef = useRef(null);
@@ -443,7 +445,7 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
443
445
  }, [handleCloseSidebarContextMenu]);
444
446
  const handleFileChange = useCallback((e) => __awaiter(void 0, void 0, void 0, function* () {
445
447
  var _a;
446
- const file = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0];
448
+ const file = (_a = e.currentTarget.files) === null || _a === void 0 ? void 0 : _a[0];
447
449
  if (!file)
448
450
  return;
449
451
  const result = yield importICSFile(file);
@@ -522,28 +524,48 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
522
524
  const readOnlyConfig = app.getReadOnlyConfig();
523
525
  const isEditable = !app.state.readOnly;
524
526
  const isDraggable = readOnlyConfig.draggable !== false;
525
- return (u("div", { className: sidebarContainer, onContextMenu: isEditable ? handleSidebarContextMenu : undefined, children: [u(SidebarHeader, { isCollapsed: isCollapsed, onCollapseToggle: () => setCollapsed(!isCollapsed) }), !isCollapsed ? (u(Fragment, { children: [u(CalendarList, { calendars: calendars, onToggleVisibility: toggleCalendarVisibility, onReorder: isDraggable ? app.reorderCalendars : () => { }, onRename: isEditable
526
- ? (id, newName) => app.updateCalendar(id, { name: newName })
527
- : () => { }, onContextMenu: isEditable ? handleContextMenu : () => { }, 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(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
527
+ return (u("div", { className: sidebarContainer, onContextMenu: isEditable ? handleSidebarContextMenu : undefined, children: [u(SidebarHeader, { isCollapsed: isCollapsed, onCollapseToggle: () => setCollapsed(!isCollapsed) }), isCollapsed ? (u(CalendarList, { calendars: calendars, onToggleVisibility: toggleCalendarVisibility, onReorder: isDraggable
528
+ ? app.reorderCalendars
529
+ : () => {
530
+ /* noop */
531
+ }, onRename: isEditable
528
532
  ? (id, newName) => app.updateCalendar(id, { name: newName })
529
- : () => { }, onContextMenu: isEditable ? handleContextMenu : () => { }, editingId: editingCalendarId, setEditingId: setEditingCalendarId, activeContextMenuCalendarId: contextMenu === null || contextMenu === void 0 ? void 0 : contextMenu.calendarId, isDraggable: isDraggable, isEditable: isEditable })), contextMenu && (u(ContextMenu, { ref: contextMenuRef, x: contextMenu.x, y: contextMenu.y, onClose: handleCloseContextMenu, className: "w-64 p-2", children: u(ContentSlot, { generatorName: "calendarContextMenu", generatorArgs: {
533
+ : () => {
534
+ /* noop */
535
+ }, onContextMenu: isEditable
536
+ ? handleContextMenu
537
+ : () => {
538
+ /* noop */
539
+ }, editingId: editingCalendarId, setEditingId: setEditingCalendarId, activeContextMenuCalendarId: contextMenu === null || contextMenu === void 0 ? void 0 : contextMenu.calendarId, isDraggable: isDraggable, isEditable: isEditable })) : (u(Fragment, { children: [u(CalendarList, { calendars: calendars, onToggleVisibility: toggleCalendarVisibility, onReorder: isDraggable
540
+ ? app.reorderCalendars
541
+ : () => {
542
+ /* noop */
543
+ }, onRename: isEditable
544
+ ? (id, newName) => app.updateCalendar(id, { name: newName })
545
+ : () => {
546
+ /* noop */
547
+ }, onContextMenu: isEditable
548
+ ? handleContextMenu
549
+ : () => {
550
+ /* noop */
551
+ }, 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(MiniCalendar, { visibleMonth: app.getVisibleMonth(), currentDate: app.getCurrentDate(), showHeader: true, onMonthChange: handleMonthChange, onDateSelect: date => app.setCurrentDate(date) }) })] })), contextMenu && (u(ContextMenu, { ref: contextMenuRef, x: contextMenu.x, y: contextMenu.y, onClose: handleCloseContextMenu, className: 'w-64 p-2', children: u(ContentSlot, { generatorName: 'calendarContextMenu', generatorArgs: {
530
552
  calendar: calendars.find(c => c.id === contextMenu.calendarId),
531
553
  onClose: handleCloseContextMenu,
532
554
  }, defaultContent: renderCalendarContextMenu ? (renderCalendarContextMenu(calendars.find(c => c.id === contextMenu.calendarId), handleCloseContextMenu)) : (u(Fragment, { children: [u(ContextMenuLabel, { children: t('calendarOptions') }), u(MergeMenuItem, { calendars: calendars, currentCalendarId: contextMenu.calendarId, onMergeSelect: handleMergeSelect }), u(ContextMenuItem, { onClick: handleDeleteCalendar, children: t('delete') }), u(ContextMenuItem, { onClick: handleExportCalendar, children: t('exportCalendar') || 'Export Calendar' }), u(ContextMenuSeparator, {}), u(ContextMenuColorPicker, { selectedColor: (_d = calendars.find(c => c.id === contextMenu.calendarId)) === null || _d === void 0 ? void 0 : _d.colors.lineColor, onSelect: handleColorSelect, onCustomColor: handleCustomColor })] })) }) })), sidebarContextMenu &&
533
- createPortal(u(ContextMenu, { x: sidebarContextMenu.x, y: sidebarContextMenu.y, onClose: handleCloseSidebarContextMenu, className: "w-max p-2", children: [u(ContextMenuItem, { onClick: () => {
555
+ createPortal(u(ContextMenu, { x: sidebarContextMenu.x, y: sidebarContextMenu.y, onClose: handleCloseSidebarContextMenu, className: 'w-max p-2', children: [u(ContextMenuItem, { onClick: () => {
534
556
  onCreateCalendar === null || onCreateCalendar === void 0 ? void 0 : onCreateCalendar();
535
557
  handleCloseSidebarContextMenu();
536
558
  }, children: t('newCalendar') || 'New Calendar' }), u(ContextMenuItem, { onClick: handleImportClick, children: t('importCalendar') || 'Import Calendar' }), u(ContextMenuItem, { onClick: () => {
537
559
  app.triggerRender();
538
560
  handleCloseSidebarContextMenu();
539
- }, children: t('refreshAll') || 'Refresh All' })] }), document.body), u("input", { ref: fileInputRef, type: "file", accept: ".ics", style: { display: 'none' }, onChange: handleFileChange }), importState &&
561
+ }, children: t('refreshAll') || 'Refresh All' })] }), document.body), u("input", { ref: fileInputRef, type: 'file', accept: '.ics', style: { display: 'none' }, onChange: handleFileChange }), importState &&
540
562
  createPortal(u(ImportCalendarDialog, { calendars: calendars, filename: importState.filename, onConfirm: handleImportConfirm, onCancel: () => setImportState(null) }), document.body), mergeState &&
541
563
  createPortal(u(MergeCalendarDialog, { sourceName: sourceCalendarName, targetName: targetCalendarName, onConfirm: handleMergeConfirm, onCancel: () => setMergeState(null) }), document.body), deleteState &&
542
564
  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 &&
543
- createPortal(u("div", { className: "fixed inset-0 z-50", onMouseDown: () => {
565
+ createPortal(u("div", { className: 'fixed inset-0 z-50', onMouseDown: () => {
544
566
  app.updateCalendar(customColorPicker.calendarId, {});
545
567
  setCustomColorPicker(null);
546
- }, children: u("div", { className: "absolute flex items-center justify-center", style: {
568
+ }, children: u("div", { className: 'absolute flex items-center justify-center', style: {
547
569
  top: customColorPicker.y,
548
570
  left: customColorPicker.x,
549
571
  transform: 'translate(280%, -50%)',
@@ -556,8 +578,8 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
556
578
  }, onCollapse: () => {
557
579
  app.updateCalendar(customColorPicker.calendarId, {});
558
580
  setCustomColorPicker(null);
559
- } })) : (u(ContentSlot, { generatorName: "colorPicker", generatorArgs: {
560
- variant: 'sketch', // TODO: change name
581
+ } })) : (u(ContentSlot, { generatorName: 'colorPicker', generatorArgs: {
582
+ variant: 'sketch', // Pending: change name
561
583
  color: customColorPicker.currentColor,
562
584
  onChange: (color) => {
563
585
  setCustomColorPicker(prev => prev ? Object.assign(Object.assign({}, prev), { currentColor: color.hex }) : null);
@@ -613,11 +635,9 @@ function createSidebarPlugin(config = {}) {
613
635
  const refreshSidebar = useCallback(() => {
614
636
  setSidebarVersion(prev => prev + 1);
615
637
  }, []);
616
- useEffect(() => {
617
- return app.subscribe(() => {
618
- refreshSidebar();
619
- });
620
- }, [app, refreshSidebar]);
638
+ useEffect(() => app.subscribe(() => {
639
+ refreshSidebar();
640
+ }), [app, refreshSidebar]);
621
641
  const calendars = useMemo(() => app.getCalendars(), [app, sidebarVersion]);
622
642
  const handleToggleCalendarVisibility = useCallback((calendarId, visible) => {
623
643
  app.setCalendarVisibility(calendarId, visible);
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
+ var core = require('@dayflow/core');
3
4
  var preact = require('preact');
4
5
  var hooks = require('preact/hooks');
5
- var core = require('@dayflow/core');
6
6
  var blossomColorPicker = require('@dayflow/blossom-color-picker');
7
7
 
8
8
  /******************************************************************************
@@ -39,11 +39,6 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
39
39
 
40
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
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
42
  const getCalendarInitials = (calendar) => {
48
43
  if (calendar.icon) {
49
44
  return calendar.icon;
@@ -72,9 +67,11 @@ const CalendarList = ({ calendars, onToggleVisibility, onReorder, onRename, onCo
72
67
  calendarColors: calendar.colors,
73
68
  calendarIcon: calendar.icon,
74
69
  };
75
- e.dataTransfer.setData('application/x-dayflow-calendar', JSON.stringify(dragData));
76
- e.dataTransfer.effectAllowed = 'copy';
77
- }, [editingId]);
70
+ if (e.dataTransfer) {
71
+ e.dataTransfer.setData('application/x-dayflow-calendar', JSON.stringify(dragData));
72
+ e.dataTransfer.effectAllowed = 'copy';
73
+ }
74
+ }, [editingId, isDraggable]);
78
75
  const handleDragEnd = hooks.useCallback(() => {
79
76
  setDraggedCalendarId(null);
80
77
  setDropTarget(null);
@@ -174,7 +171,7 @@ const CalendarList = ({ calendars, onToggleVisibility, onReorder, onRename, onCo
174
171
  }
175
172
  }
176
173
  }, [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 => {
174
+ return (u("div", { className: 'df-calendar-list flex-1 overflow-y-auto px-2 pb-3', children: u("ul", { className: 'relative space-y-1', children: calendars.map(calendar => {
178
175
  var _a;
179
176
  const isVisible = calendar.isVisible !== false;
180
177
  const calendarColor = ((_a = calendar.colors) === null || _a === void 0 ? void 0 : _a.lineColor) || '#3b82f6';
@@ -182,69 +179,23 @@ const CalendarList = ({ calendars, onToggleVisibility, onReorder, onRename, onCo
182
179
  const isDropTarget = (dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.id) === calendar.id;
183
180
  const isActive = activeContextMenuCalendarId === calendar.id ||
184
181
  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: {
182
+ 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: 'pointer-events-none absolute top-0 right-0 left-0 z-10 h-0.5 bg-primary' })), 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 shrink-0 cursor-pointer', style: {
186
183
  '--checkbox-color': calendarColor,
187
- }, checked: isVisible, onChange: event => onToggleVisibility(calendar.id, event.target.checked) }), 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));
184
+ }, checked: isVisible, onChange: event => onToggleVisibility(calendar.id, event.target.checked) }), 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 h-5 min-w-0 flex-1 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: 'ml-2 flex-1 truncate pl-1 text-sm text-gray-700 group-hover:text-gray-900 dark:text-gray-200 dark:group-hover:text-white', onDblClick: () => handleRenameStart(calendar), children: calendar.name || calendar.id }))] }) }), isDropTarget && dropTarget.position === 'bottom' && (u("div", { className: 'pointer-events-none absolute right-0 bottom-0 left-0 z-10 h-0.5 bg-primary' }))] }, calendar.id));
188
185
  }) }) }));
189
186
  };
190
187
 
191
- const MergeMenuItem = ({ calendars, currentCalendarId, onMergeSelect, }) => {
192
- const { t } = core.useLocale();
193
- const [isHovered, setIsHovered] = hooks.useState(false);
194
- const itemRef = hooks.useRef(null);
195
- const submenuRef = hooks.useRef(null);
196
- const [position, setPosition] = hooks.useState({ x: 0, y: 0 });
197
- const timeoutRef = hooks.useRef();
198
- const handleMouseEnter = () => {
199
- if (timeoutRef.current)
200
- clearTimeout(timeoutRef.current);
201
- if (itemRef.current) {
202
- const rect = itemRef.current.getBoundingClientRect();
203
- setPosition({ x: rect.right, y: rect.top });
204
- }
205
- setIsHovered(true);
206
- };
207
- const handleMouseLeave = () => {
208
- timeoutRef.current = setTimeout(() => {
209
- setIsHovered(false);
210
- }, 100);
211
- };
212
- hooks.useEffect(() => {
213
- const el = submenuRef.current;
214
- if (el) {
215
- const stopPropagation = (e) => e.stopPropagation();
216
- el.addEventListener('mousedown', stopPropagation);
217
- return () => {
218
- el.removeEventListener('mousedown', stopPropagation);
219
- };
220
- }
221
- }, [isHovered]);
222
- const availableCalendars = calendars.filter(c => c.id !== currentCalendarId);
223
- if (availableCalendars.length === 0)
224
- return null;
225
- 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 &&
226
- 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 => {
227
- e.stopPropagation();
228
- onMergeSelect(calendar.id);
229
- }, 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)] }));
230
- };
231
-
232
- const MergeCalendarDialog = ({ sourceName, targetName, onConfirm, onCancel, }) => {
233
- const { t } = core.useLocale();
234
- 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') })] })] }) }));
235
- };
236
-
237
188
  const DeleteCalendarDialog = ({ calendarId, calendarName, calendars, step, onStepChange, onConfirmDelete, onCancel, onMergeSelect, }) => {
238
189
  const [showMergeDropdown, setShowMergeDropdown] = hooks.useState(false);
239
190
  const { t } = core.useLocale();
240
- 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
191
+ 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 bg-background p-6 shadow-xl', 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 items-center justify-between', 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 top-full left-0 z-10 mt-1 max-h-60 w-max min-w-full overflow-y-auto rounded-md border border-gray-200 bg-background shadow-lg dark:border-slate-700', children: calendars
241
192
  .filter(c => c.id !== calendarId)
242
- .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: () => {
193
+ .map(calendar => (u("div", { className: 'flex cursor-pointer items-center px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-slate-700', onClick: () => {
243
194
  onMergeSelect(calendar.id);
244
195
  setShowMergeDropdown(false);
245
- }, children: [u("div", { className: "mr-2 h-3 w-3 rounded-sm shrink-0", style: {
196
+ }, children: [u("div", { className: 'mr-2 h-3 w-3 shrink-0 rounded-sm', style: {
246
197
  backgroundColor: calendar.colors.lineColor,
247
- } }), 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);
198
+ } }), 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 border border-border bg-background 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);
248
199
  };
249
200
 
250
201
  const NEW_CALENDAR_ID = 'new-calendar';
@@ -290,25 +241,76 @@ const ImportCalendarDialog = ({ calendars, filename, onConfirm, onCancel, }) =>
290
241
  const rect = (_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
291
242
  if (!rect)
292
243
  return null;
293
- 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: {
244
+ return core.createPortal(u("div", { ref: dropdownRef, className: `fixed z-110 mt-1 max-h-60 origin-top overflow-y-auto rounded-md border border-gray-200 bg-white shadow-lg transition-all duration-200 dark:border-slate-700 dark:bg-slate-800 ${isOpen ? 'scale-100 opacity-100' : 'scale-95 opacity-0'}`, style: {
294
245
  top: rect.bottom,
295
246
  left: rect.left,
296
247
  width: rect.width,
297
- }, 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);
248
+ }, children: u("div", { className: 'py-1', children: [calendars.map(calendar => (u("div", { className: `flex cursor-pointer items-center px-3 py-2 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 truncate text-sm ${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 h-4 w-4 shrink-0 text-primary' }))] }, calendar.id))), u("div", { className: 'my-1 border-t border-gray-100 dark:border-slate-700' }), u("div", { className: `flex cursor-pointer items-center px-3 py-2 hover:bg-gray-100 dark:hover:bg-slate-700 ${isNewSelected ? 'bg-primary/10' : ''}`, onClick: () => handleSelect(NEW_CALENDAR_ID), children: [u("span", { className: `flex-1 truncate text-sm ${isNewSelected ? 'font-medium text-primary' : 'pl-6 text-gray-700 dark:text-gray-200'}`, children: [t('newCalendar') || 'New Calendar', ": ", filename] }), isNewSelected && (u(core.Check, { className: 'ml-2 h-4 w-4 shrink-0 text-primary' }))] })] }) }), document.body);
298
249
  };
299
- 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') ||
300
- '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
250
+ 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') ||
251
+ 'This calendar contains new events. Please select a target calendar.' }), u("div", { className: 'relative', children: [u("button", { ref: triggerRef, type: 'button', className: 'flex w-full items-center rounded-md border border-gray-300 px-3 py-2 shadow-sm transition-colors hover:bg-gray-50 dark:border-gray-600 dark:hover:bg-gray-800', 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: `flex-1 truncate text-left text-sm font-medium text-gray-700 dark:text-gray-200 ${isNewSelected ? 'pl-0' : ''}`, children: isNewSelected
301
252
  ? `${t('newCalendar')}: ${filename}`
302
- : (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' })] })] }) }));
253
+ : (selectedCalendar === null || selectedCalendar === void 0 ? void 0 : selectedCalendar.name) || (selectedCalendar === null || selectedCalendar === void 0 ? void 0 : selectedCalendar.id) }), u(core.ChevronsUpDown, { className: 'ml-2 h-4 w-4 shrink-0 text-gray-400' })] }), 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 shadow-sm transition-colors hover:bg-primary/90', children: t('ok') || 'OK' })] })] }) }));
254
+ };
255
+
256
+ const MergeCalendarDialog = ({ sourceName, targetName, onConfirm, onCancel, }) => {
257
+ const { t } = core.useLocale();
258
+ 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-background p-6 shadow-xl', 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') })] })] }) }));
259
+ };
260
+
261
+ const stopPropagation = (e) => e.stopPropagation();
262
+ const MergeMenuItem = ({ calendars, currentCalendarId, onMergeSelect, }) => {
263
+ const { t } = core.useLocale();
264
+ const [isHovered, setIsHovered] = hooks.useState(false);
265
+ const itemRef = hooks.useRef(null);
266
+ const submenuRef = hooks.useRef(null);
267
+ const [position, setPosition] = hooks.useState({ x: 0, y: 0 });
268
+ const timeoutRef = hooks.useRef();
269
+ const handleMouseEnter = () => {
270
+ if (timeoutRef.current)
271
+ clearTimeout(timeoutRef.current);
272
+ if (itemRef.current) {
273
+ const rect = itemRef.current.getBoundingClientRect();
274
+ setPosition({ x: rect.right, y: rect.top });
275
+ }
276
+ setIsHovered(true);
277
+ };
278
+ const handleMouseLeave = () => {
279
+ timeoutRef.current = setTimeout(() => {
280
+ setIsHovered(false);
281
+ }, 100);
282
+ };
283
+ hooks.useEffect(() => {
284
+ const el = submenuRef.current;
285
+ if (el) {
286
+ el.addEventListener('mousedown', stopPropagation);
287
+ return () => {
288
+ el.removeEventListener('mousedown', stopPropagation);
289
+ };
290
+ }
291
+ }, [isHovered]);
292
+ const availableCalendars = calendars.filter(c => c.id !== currentCalendarId);
293
+ if (availableCalendars.length === 0)
294
+ return null;
295
+ return (u(preact.Fragment, { children: [u("div", { ref: itemRef, className: 'relative flex cursor-default items-center justify-between rounded-sm px-3 py-0.5 text-[12px] transition-colors outline-none select-none hover:bg-primary hover:text-white dark:text-slate-200 dark:hover:bg-primary dark:hover:text-white', onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [u("span", { children: t('merge') }), u(core.ChevronRight, { className: 'h-4 w-4' })] }), isHovered &&
296
+ core.createPortal(u("div", { ref: submenuRef, "data-submenu-content": 'true', className: 'animate-in fade-in-0 zoom-in-95 fixed z-60 min-w-48 overflow-hidden rounded-md border border-slate-200 bg-white p-1 shadow-md duration-100 dark:border-slate-800 dark:bg-slate-950', style: { top: position.y, left: position.x }, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onMouseDown: e => e.stopPropagation(), children: availableCalendars.map(calendar => (u("div", { className: 'flex cursor-pointer items-center rounded-sm px-3 py-1 text-[12px] text-slate-900 transition-colors hover:bg-primary hover:text-white dark:text-slate-50 dark:hover:bg-primary dark:hover:text-white', onClick: e => {
297
+ e.stopPropagation();
298
+ onMergeSelect(calendar.id);
299
+ }, children: [u("div", { className: 'mr-2 h-3 w-3 shrink-0 rounded-sm', style: { backgroundColor: calendar.colors.lineColor } }), u("span", { className: 'truncate', children: calendar.name || calendar.id })] }, calendar.id))) }), document.body)] }));
300
+ };
301
+
302
+ const SidebarHeader = ({ isCollapsed, onCollapseToggle, }) => {
303
+ const { t } = core.useLocale();
304
+ 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: 'ml-3 flex flex-1 items-center justify-between', children: u("span", { className: core.sidebarHeaderTitle, children: t('calendars') }) }))] }));
303
305
  };
304
306
 
305
307
  const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCollapsed, setCollapsed, renderCalendarContextMenu, editingCalendarId: propEditingCalendarId, setEditingCalendarId: propSetEditingCalendarId, onCreateCalendar, colorPickerMode = 'default', }) => {
306
308
  var _a, _b, _c, _d;
307
309
  const { t } = core.useLocale();
308
310
  const [localEditingCalendarId, setLocalEditingCalendarId] = hooks.useState(null);
309
- const editingCalendarId = propEditingCalendarId !== undefined
310
- ? propEditingCalendarId
311
- : localEditingCalendarId;
311
+ const editingCalendarId = propEditingCalendarId === undefined
312
+ ? localEditingCalendarId
313
+ : propEditingCalendarId;
312
314
  const setEditingCalendarId = propSetEditingCalendarId || setLocalEditingCalendarId;
313
315
  // File input ref for import
314
316
  const fileInputRef = hooks.useRef(null);
@@ -445,7 +447,7 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
445
447
  }, [handleCloseSidebarContextMenu]);
446
448
  const handleFileChange = hooks.useCallback((e) => __awaiter(void 0, void 0, void 0, function* () {
447
449
  var _a;
448
- const file = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0];
450
+ const file = (_a = e.currentTarget.files) === null || _a === void 0 ? void 0 : _a[0];
449
451
  if (!file)
450
452
  return;
451
453
  const result = yield core.importICSFile(file);
@@ -524,28 +526,48 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
524
526
  const readOnlyConfig = app.getReadOnlyConfig();
525
527
  const isEditable = !app.state.readOnly;
526
528
  const isDraggable = readOnlyConfig.draggable !== false;
527
- 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
528
- ? (id, newName) => app.updateCalendar(id, { name: newName })
529
- : () => { }, onContextMenu: isEditable ? handleContextMenu : () => { }, 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
529
+ return (u("div", { className: core.sidebarContainer, onContextMenu: isEditable ? handleSidebarContextMenu : undefined, children: [u(SidebarHeader, { isCollapsed: isCollapsed, onCollapseToggle: () => setCollapsed(!isCollapsed) }), isCollapsed ? (u(CalendarList, { calendars: calendars, onToggleVisibility: toggleCalendarVisibility, onReorder: isDraggable
530
+ ? app.reorderCalendars
531
+ : () => {
532
+ /* noop */
533
+ }, onRename: isEditable
530
534
  ? (id, newName) => app.updateCalendar(id, { name: newName })
531
- : () => { }, onContextMenu: isEditable ? handleContextMenu : () => { }, 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: {
535
+ : () => {
536
+ /* noop */
537
+ }, onContextMenu: isEditable
538
+ ? handleContextMenu
539
+ : () => {
540
+ /* noop */
541
+ }, editingId: editingCalendarId, setEditingId: setEditingCalendarId, activeContextMenuCalendarId: contextMenu === null || contextMenu === void 0 ? void 0 : contextMenu.calendarId, isDraggable: isDraggable, isEditable: isEditable })) : (u(preact.Fragment, { children: [u(CalendarList, { calendars: calendars, onToggleVisibility: toggleCalendarVisibility, onReorder: isDraggable
542
+ ? app.reorderCalendars
543
+ : () => {
544
+ /* noop */
545
+ }, onRename: isEditable
546
+ ? (id, newName) => app.updateCalendar(id, { name: newName })
547
+ : () => {
548
+ /* noop */
549
+ }, onContextMenu: isEditable
550
+ ? handleContextMenu
551
+ : () => {
552
+ /* noop */
553
+ }, 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) }) })] })), 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: {
532
554
  calendar: calendars.find(c => c.id === contextMenu.calendarId),
533
555
  onClose: handleCloseContextMenu,
534
556
  }, 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 &&
535
- core.createPortal(u(core.ContextMenu, { x: sidebarContextMenu.x, y: sidebarContextMenu.y, onClose: handleCloseSidebarContextMenu, className: "w-max p-2", children: [u(core.ContextMenuItem, { onClick: () => {
557
+ core.createPortal(u(core.ContextMenu, { x: sidebarContextMenu.x, y: sidebarContextMenu.y, onClose: handleCloseSidebarContextMenu, className: 'w-max p-2', children: [u(core.ContextMenuItem, { onClick: () => {
536
558
  onCreateCalendar === null || onCreateCalendar === void 0 ? void 0 : onCreateCalendar();
537
559
  handleCloseSidebarContextMenu();
538
560
  }, children: t('newCalendar') || 'New Calendar' }), u(core.ContextMenuItem, { onClick: handleImportClick, children: t('importCalendar') || 'Import Calendar' }), u(core.ContextMenuItem, { onClick: () => {
539
561
  app.triggerRender();
540
562
  handleCloseSidebarContextMenu();
541
- }, children: t('refreshAll') || 'Refresh All' })] }), document.body), u("input", { ref: fileInputRef, type: "file", accept: ".ics", style: { display: 'none' }, onChange: handleFileChange }), importState &&
563
+ }, children: t('refreshAll') || 'Refresh All' })] }), document.body), u("input", { ref: fileInputRef, type: 'file', accept: '.ics', style: { display: 'none' }, onChange: handleFileChange }), importState &&
542
564
  core.createPortal(u(ImportCalendarDialog, { calendars: calendars, filename: importState.filename, onConfirm: handleImportConfirm, onCancel: () => setImportState(null) }), document.body), mergeState &&
543
565
  core.createPortal(u(MergeCalendarDialog, { sourceName: sourceCalendarName, targetName: targetCalendarName, onConfirm: handleMergeConfirm, onCancel: () => setMergeState(null) }), document.body), deleteState &&
544
566
  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 &&
545
- core.createPortal(u("div", { className: "fixed inset-0 z-50", onMouseDown: () => {
567
+ core.createPortal(u("div", { className: 'fixed inset-0 z-50', onMouseDown: () => {
546
568
  app.updateCalendar(customColorPicker.calendarId, {});
547
569
  setCustomColorPicker(null);
548
- }, children: u("div", { className: "absolute flex items-center justify-center", style: {
570
+ }, children: u("div", { className: 'absolute flex items-center justify-center', style: {
549
571
  top: customColorPicker.y,
550
572
  left: customColorPicker.x,
551
573
  transform: 'translate(280%, -50%)',
@@ -558,8 +580,8 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
558
580
  }, onCollapse: () => {
559
581
  app.updateCalendar(customColorPicker.calendarId, {});
560
582
  setCustomColorPicker(null);
561
- } })) : (u(core.ContentSlot, { generatorName: "colorPicker", generatorArgs: {
562
- variant: 'sketch', // TODO: change name
583
+ } })) : (u(core.ContentSlot, { generatorName: 'colorPicker', generatorArgs: {
584
+ variant: 'sketch', // Pending: change name
563
585
  color: customColorPicker.currentColor,
564
586
  onChange: (color) => {
565
587
  setCustomColorPicker(prev => prev ? Object.assign(Object.assign({}, prev), { currentColor: color.hex }) : null);
@@ -615,11 +637,9 @@ function createSidebarPlugin(config = {}) {
615
637
  const refreshSidebar = hooks.useCallback(() => {
616
638
  setSidebarVersion(prev => prev + 1);
617
639
  }, []);
618
- hooks.useEffect(() => {
619
- return app.subscribe(() => {
620
- refreshSidebar();
621
- });
622
- }, [app, refreshSidebar]);
640
+ hooks.useEffect(() => app.subscribe(() => {
641
+ refreshSidebar();
642
+ }), [app, refreshSidebar]);
623
643
  const calendars = hooks.useMemo(() => app.getCalendars(), [app, sidebarVersion]);
624
644
  const handleToggleCalendarVisibility = hooks.useCallback((calendarId, visible) => {
625
645
  app.setCalendarVisibility(calendarId, visible);
@@ -1,3 +1,4 @@
1
+ import { JSX } from 'preact';
1
2
  import type { CalendarSidebarRenderProps } from './plugin';
2
- declare const DefaultCalendarSidebar: ({ app, calendars, toggleCalendarVisibility, isCollapsed, setCollapsed, renderCalendarContextMenu, editingCalendarId: propEditingCalendarId, setEditingCalendarId: propSetEditingCalendarId, onCreateCalendar, colorPickerMode, }: CalendarSidebarRenderProps) => import("preact").JSX.Element;
3
+ declare const DefaultCalendarSidebar: ({ app, calendars, toggleCalendarVisibility, isCollapsed, setCollapsed, renderCalendarContextMenu, editingCalendarId: propEditingCalendarId, setEditingCalendarId: propSetEditingCalendarId, onCreateCalendar, colorPickerMode, }: CalendarSidebarRenderProps) => JSX.Element;
3
4
  export default DefaultCalendarSidebar;
@@ -1,15 +1,16 @@
1
1
  import { CalendarType } from '@dayflow/core';
2
+ import { JSX } from 'preact';
2
3
  interface CalendarListProps {
3
4
  calendars: CalendarType[];
4
5
  onToggleVisibility: (id: string, visible: boolean) => void;
5
6
  onReorder: (fromIndex: number, toIndex: number) => void;
6
7
  onRename: (id: string, newName: string) => void;
7
- onContextMenu: (e: any, id: string) => void;
8
+ onContextMenu: (e: JSX.TargetedMouseEvent<HTMLElement>, id: string) => void;
8
9
  editingId: string | null;
9
10
  setEditingId: (id: string | null) => void;
10
11
  activeContextMenuCalendarId?: string | null;
11
12
  isDraggable?: boolean;
12
13
  isEditable?: boolean;
13
14
  }
14
- export declare const CalendarList: ({ calendars, onToggleVisibility, onReorder, onRename, onContextMenu, editingId, setEditingId, activeContextMenuCalendarId, isDraggable, isEditable, }: CalendarListProps) => import("preact").JSX.Element;
15
+ export declare const CalendarList: ({ calendars, onToggleVisibility, onReorder, onRename, onContextMenu, editingId, setEditingId, activeContextMenuCalendarId, isDraggable, isEditable, }: CalendarListProps) => JSX.Element;
15
16
  export {};
package/package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "name": "@dayflow/plugin-sidebar",
3
- "version": "1.0.2",
4
- "type": "module",
3
+ "version": "1.1.0",
5
4
  "description": "Sidebar plugin for DayFlow calendar",
5
+ "keywords": [
6
+ "calendar",
7
+ "dayflow",
8
+ "plugin",
9
+ "sidebar"
10
+ ],
11
+ "license": "MIT",
12
+ "author": "Jayce Li",
13
+ "files": [
14
+ "dist",
15
+ "README.md",
16
+ "LICENSE"
17
+ ],
18
+ "type": "module",
6
19
  "main": "dist/index.js",
7
20
  "module": "dist/index.esm.js",
8
21
  "types": "dist/index.d.ts",
@@ -13,36 +26,25 @@
13
26
  "require": "./dist/index.js"
14
27
  }
15
28
  },
16
- "files": [
17
- "dist",
18
- "README.md",
19
- "LICENSE"
20
- ],
21
- "keywords": [
22
- "calendar",
23
- "sidebar",
24
- "dayflow",
25
- "plugin"
26
- ],
27
- "author": "Jayce Li",
28
- "license": "MIT",
29
- "peerDependencies": {
30
- "@dayflow/core": "3.1.2"
31
- },
32
29
  "devDependencies": {
33
30
  "@dayflow/blossom-color-picker": "^2.0.1",
34
31
  "@rollup/plugin-commonjs": "^28.0.2",
35
32
  "@rollup/plugin-node-resolve": "^16.0.0",
36
33
  "@rollup/plugin-typescript": "^12.1.2",
34
+ "preact": "^10.28.3",
35
+ "rimraf": "^6.1.2",
37
36
  "rollup": "^4.29.1",
38
37
  "rollup-plugin-dts": "^6.3.0",
39
- "preact": "^10.25.4",
40
38
  "temporal-polyfill": "^0.3.0",
41
- "typescript": "^5.7.2",
42
- "@dayflow/core": "3.1.2"
39
+ "typescript": "^5.9.3",
40
+ "@dayflow/core": "3.2.0"
41
+ },
42
+ "peerDependencies": {
43
+ "@dayflow/core": "3.2.0"
43
44
  },
44
45
  "scripts": {
45
- "build": "tsc -p tsconfig.build.json && rollup -c",
46
+ "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && rollup -c",
47
+ "clean": "rimraf dist node_modules",
46
48
  "typecheck": "tsc --noEmit"
47
49
  }
48
50
  }