@dayflow/plugin-sidebar 1.2.1 → 1.2.3
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.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AudioLines, useLocale, createPortal, cancelButton, ChevronsUpDown, Check, ChevronRight, sidebarHeader, sidebarHeaderToggle, PanelRightClose, PanelRightOpen, sidebarHeaderTitle, getCalendarColorsForHex, generateUniKey, downloadICS, ContentSlot, MiniCalendar, ContextMenu, ContextMenuLabel, ContextMenuItem, ContextMenuSeparator, ContextMenuColorPicker, DefaultColorPicker, BlossomColorPicker, importICSFile, parseICS, sidebarContainer, normalizeCssWidth, registerSidebarImplementation, CreateCalendarDialog } from '@dayflow/core';
|
|
1
|
+
import { ChevronDown, AudioLines, useLocale, createPortal, cancelButton, ChevronsUpDown, Check, ChevronRight, sidebarHeader, sidebarHeaderToggle, PanelRightClose, PanelRightOpen, sidebarHeaderTitle, getCalendarColorsForHex, generateUniKey, downloadICS, ContentSlot, MiniCalendar, ContextMenu, ContextMenuLabel, ContextMenuItem, ContextMenuSeparator, ContextMenuColorPicker, DefaultColorPicker, BlossomColorPicker, importICSFile, parseICS, sidebarContainer, normalizeCssWidth, registerSidebarImplementation, CreateCalendarDialog } from '@dayflow/core';
|
|
2
2
|
import { options, Fragment, h } from 'preact';
|
|
3
3
|
import { useState, useRef, useCallback, useEffect, useMemo } from 'preact/hooks';
|
|
4
4
|
import { hexToHsl, lightnessToSliderValue } from '@dayflow/blossom-color-picker';
|
|
@@ -44,21 +44,33 @@ const getCalendarInitials = (calendar) => {
|
|
|
44
44
|
const name = calendar.name || calendar.id;
|
|
45
45
|
return name.charAt(0).toUpperCase();
|
|
46
46
|
};
|
|
47
|
+
const CalendarItem = ({ calendar, isDraggable, isEditable: _isEditable, editingId, editingName, setEditingName, editInputRef, draggedCalendarId, dropTarget, activeContextMenuCalendarId, onDragStart, onDragEnd, onDragOver, onDragLeave, onDrop, onContextMenu, onToggleVisibility, onRenameStart, onRenameSave, onRenameKeyDown, }) => {
|
|
48
|
+
var _a;
|
|
49
|
+
const isVisible = calendar.isVisible !== false;
|
|
50
|
+
const calendarColor = ((_a = calendar.colors) === null || _a === void 0 ? void 0 : _a.lineColor) || '#3b82f6';
|
|
51
|
+
const showIcon = Boolean(calendar.icon);
|
|
52
|
+
const isDropTarget = (dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.id) === calendar.id;
|
|
53
|
+
const isActive = activeContextMenuCalendarId === calendar.id || editingId === calendar.id;
|
|
54
|
+
return (u("li", { className: 'df-calendar-list-item relative', onDragOver: e => onDragOver(e, calendar.id), onDragLeave: onDragLeave, onDrop: () => onDrop(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-[var(--df-color-primary)]' })), u("div", { draggable: isDraggable && !editingId, onDragStart: e => onDragStart(calendar, e), onDragEnd: onDragEnd, 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: 'df-calendar-checkbox shrink-0 cursor-pointer', style: {
|
|
55
|
+
'--checkbox-color': calendarColor,
|
|
56
|
+
}, 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: onRenameSave, onKeyDown: onRenameKeyDown, 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(Fragment, { children: [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: () => onRenameStart(calendar), children: calendar.name || calendar.id }), calendar.subscribed && (u(AudioLines, { width: 13, height: 13, className: 'ml-1 shrink-0 text-gray-400 dark:text-gray-500' }))] }))] }) }), isDropTarget && dropTarget.position === 'bottom' && (u("div", { className: 'pointer-events-none absolute right-0 bottom-0 left-0 z-10 h-0.5 bg-[var(--df-color-primary)]' }))] }, calendar.id));
|
|
57
|
+
};
|
|
47
58
|
const CalendarList = ({ calendars, onToggleVisibility, onReorder, onRename, onContextMenu, editingId, setEditingId, activeContextMenuCalendarId, isDraggable = true, isEditable = true, }) => {
|
|
59
|
+
var _a;
|
|
48
60
|
const [editingName, setEditingName] = useState('');
|
|
49
61
|
const editInputRef = useRef(null);
|
|
50
62
|
const isProcessedRef = useRef(false);
|
|
51
63
|
// Drag state
|
|
52
64
|
const [draggedCalendarId, setDraggedCalendarId] = useState(null);
|
|
53
65
|
const [dropTarget, setDropTarget] = useState(null);
|
|
66
|
+
// Collapsed sources state
|
|
67
|
+
const [collapsedSources, setCollapsedSources] = useState({});
|
|
54
68
|
const handleDragStart = useCallback((calendar, e) => {
|
|
55
|
-
// Prevent dragging when editing or not draggable
|
|
56
69
|
if (editingId || !isDraggable) {
|
|
57
70
|
e.preventDefault();
|
|
58
71
|
return;
|
|
59
72
|
}
|
|
60
73
|
setDraggedCalendarId(calendar.id);
|
|
61
|
-
// Store calendar data for drop handling
|
|
62
74
|
const dragData = {
|
|
63
75
|
calendarId: calendar.id,
|
|
64
76
|
calendarName: calendar.name,
|
|
@@ -107,11 +119,9 @@ const CalendarList = ({ calendars, onToggleVisibility, onReorder, onRename, onCo
|
|
|
107
119
|
return;
|
|
108
120
|
const fromIndex = calendars.findIndex(c => c.id === draggedCalendarId);
|
|
109
121
|
let toIndex = calendars.findIndex(c => c.id === targetCalendar.id);
|
|
110
|
-
// Adjust target index based on position
|
|
111
122
|
if (dropTarget.position === 'bottom') {
|
|
112
123
|
toIndex += 1;
|
|
113
124
|
}
|
|
114
|
-
// Adjust for removal of the item
|
|
115
125
|
if (toIndex > fromIndex) {
|
|
116
126
|
toIndex -= 1;
|
|
117
127
|
}
|
|
@@ -169,24 +179,75 @@ const CalendarList = ({ calendars, onToggleVisibility, onReorder, onRename, onCo
|
|
|
169
179
|
}
|
|
170
180
|
}
|
|
171
181
|
}, [editingId, calendars]);
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
182
|
+
const toggleSource = useCallback((source) => {
|
|
183
|
+
setCollapsedSources(prev => (Object.assign(Object.assign({}, prev), { [source]: !prev[source] })));
|
|
184
|
+
}, []);
|
|
185
|
+
// Shared item props (excludes per-item fields)
|
|
186
|
+
const sharedItemProps = {
|
|
187
|
+
isDraggable,
|
|
188
|
+
isEditable,
|
|
189
|
+
editingId,
|
|
190
|
+
editingName,
|
|
191
|
+
setEditingName,
|
|
192
|
+
editInputRef,
|
|
193
|
+
isProcessedRef,
|
|
194
|
+
draggedCalendarId,
|
|
195
|
+
dropTarget,
|
|
196
|
+
activeContextMenuCalendarId,
|
|
197
|
+
onDragStart: handleDragStart,
|
|
198
|
+
onDragEnd: handleDragEnd,
|
|
199
|
+
onDragOver: handleDragOver,
|
|
200
|
+
onDragLeave: handleDragLeave,
|
|
201
|
+
onDrop: handleDrop,
|
|
202
|
+
onContextMenu,
|
|
203
|
+
onToggleVisibility,
|
|
204
|
+
onRenameStart: handleRenameStart,
|
|
205
|
+
onRenameSave: handleRenameSave,
|
|
206
|
+
onRenameKeyDown: handleRenameKeyDown,
|
|
207
|
+
setEditingId,
|
|
208
|
+
};
|
|
209
|
+
// Check if any calendar has a source
|
|
210
|
+
const hasSources = calendars.some(c => c.source);
|
|
211
|
+
if (!hasSources) {
|
|
212
|
+
// Flat list (original behaviour)
|
|
213
|
+
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 => (u(CalendarItem, Object.assign({ calendar: calendar }, sharedItemProps), calendar.id))) }) }));
|
|
214
|
+
}
|
|
215
|
+
// Group calendars by source; calendars without a source go into a null group
|
|
216
|
+
const groups = new Map();
|
|
217
|
+
for (const calendar of calendars) {
|
|
218
|
+
const key = (_a = calendar.source) !== null && _a !== void 0 ? _a : null;
|
|
219
|
+
if (!groups.has(key))
|
|
220
|
+
groups.set(key, []);
|
|
221
|
+
groups.get(key).push(calendar);
|
|
222
|
+
}
|
|
223
|
+
return (u("div", { className: 'df-calendar-list flex-1 overflow-y-auto px-2 pb-3', children: [groups.has(null) && (u("ul", { className: 'relative space-y-1', children: groups.get(null).map(calendar => (u(CalendarItem, Object.assign({ calendar: calendar }, sharedItemProps), calendar.id))) })), Array.from(groups.entries())
|
|
224
|
+
.filter(([source]) => source !== null)
|
|
225
|
+
.map(([source, groupCalendars]) => {
|
|
226
|
+
const isCollapsed = collapsedSources[source];
|
|
227
|
+
return (u("div", { className: 'mt-1', children: [u("button", { type: 'button', className: 'flex w-full items-center justify-between rounded px-2 py-1.5 text-xs font-medium text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-slate-800', onClick: () => toggleSource(source), children: [u("span", { className: 'truncate', children: source }), u(ChevronDown, { width: 13, height: 13, className: `ml-1 shrink-0 transition-transform duration-200 ${isCollapsed ? '-rotate-90' : ''}` })] }), u("div", { style: {
|
|
228
|
+
display: 'grid',
|
|
229
|
+
gridTemplateRows: isCollapsed ? '0fr' : '1fr',
|
|
230
|
+
transition: 'grid-template-rows 200ms ease',
|
|
231
|
+
}, children: u("div", { style: { overflow: 'hidden' }, children: u("ul", { className: 'relative space-y-1', children: groupCalendars.map(calendar => (u(CalendarItem, Object.assign({ calendar: calendar }, sharedItemProps), calendar.id))) }) }) })] }, source));
|
|
232
|
+
})] }));
|
|
184
233
|
};
|
|
185
234
|
|
|
235
|
+
const CalendarChip = ({ name, color }) => (u("span", { className: 'mx-0.5 inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium', style: { backgroundColor: `${color}26`, color }, children: name }));
|
|
236
|
+
|
|
237
|
+
const CAL_SENTINEL = '\u0001C\u0001';
|
|
238
|
+
function renderWithChip(template, name, color) {
|
|
239
|
+
return template
|
|
240
|
+
.split(CAL_SENTINEL)
|
|
241
|
+
.flatMap((part, i) => i === 0
|
|
242
|
+
? [part]
|
|
243
|
+
: [u(CalendarChip, { name: name, color: color }, i), part]);
|
|
244
|
+
}
|
|
186
245
|
const DeleteCalendarDialog = ({ calendarId, calendarName, calendars, step, onStepChange, onConfirmDelete, onCancel, onMergeSelect, }) => {
|
|
246
|
+
var _a, _b;
|
|
187
247
|
const [showMergeDropdown, setShowMergeDropdown] = useState(false);
|
|
188
248
|
const { t } = useLocale();
|
|
189
|
-
|
|
249
|
+
const calendarColor = (_b = (_a = calendars.find(c => c.id === calendarId)) === null || _a === void 0 ? void 0 : _a.colors.lineColor) !== null && _b !== void 0 ? _b : '#6b7280';
|
|
250
|
+
return createPortal(u("div", { className: 'df-portal 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-white p-6 shadow-xl dark:bg-gray-800', 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 flex flex-wrap items-center gap-y-0.5 text-sm text-gray-600 dark:text-gray-300', children: renderWithChip(t('deleteCalendarMessage', { calendarName: CAL_SENTINEL }), calendarName, calendarColor) }), 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-white shadow-lg dark:border-slate-700 dark:bg-gray-800', children: calendars
|
|
190
251
|
.filter(c => c.id !== calendarId)
|
|
191
252
|
.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: () => {
|
|
192
253
|
onMergeSelect(calendar.id);
|
|
@@ -252,9 +313,29 @@ const ImportCalendarDialog = ({ calendars, filename, onConfirm, onCancel, }) =>
|
|
|
252
313
|
: (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' })] })] }) }));
|
|
253
314
|
};
|
|
254
315
|
|
|
255
|
-
const
|
|
316
|
+
const SOURCE_SENTINEL = '\u0001S\u0001';
|
|
317
|
+
const TARGET_SENTINEL = '\u0001T\u0001';
|
|
318
|
+
function renderLine(line, source, target) {
|
|
319
|
+
return line
|
|
320
|
+
.split(new RegExp(`(${SOURCE_SENTINEL}|${TARGET_SENTINEL})`))
|
|
321
|
+
.map((part, i) => {
|
|
322
|
+
if (part === SOURCE_SENTINEL)
|
|
323
|
+
return u(CalendarChip, { name: source.name, color: source.color }, i);
|
|
324
|
+
if (part === TARGET_SENTINEL)
|
|
325
|
+
return u(CalendarChip, { name: target.name, color: target.color }, i);
|
|
326
|
+
return part;
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
const MergeCalendarDialog = ({ sourceName, sourceColor, targetName, targetColor, onConfirm, onCancel, }) => {
|
|
256
330
|
const { t } = useLocale();
|
|
257
|
-
|
|
331
|
+
const source = { name: sourceName, color: sourceColor };
|
|
332
|
+
const target = { name: targetName, color: targetColor };
|
|
333
|
+
const messageTemplate = t('mergeConfirmMessage', {
|
|
334
|
+
sourceName: SOURCE_SENTINEL,
|
|
335
|
+
targetName: TARGET_SENTINEL,
|
|
336
|
+
});
|
|
337
|
+
const messageLines = messageTemplate.split('\n');
|
|
338
|
+
return (u("div", { className: 'df-portal fixed inset-0 z-[9999] flex items-center justify-center bg-black/50', children: u("div", { className: 'rounded-lg bg-white p-6 shadow-xl dark:bg-gray-800', children: [u("h2", { className: 'text-lg font-semibold text-gray-900 dark:text-white', children: t('mergeConfirmTitle', { sourceName, targetName }) }), u("div", { className: 'mt-3 space-y-1 text-sm text-gray-600 dark:text-gray-300', children: messageLines.map((line, i) => (u("p", { className: 'flex flex-wrap items-center gap-y-0.5', children: renderLine(line, source, target) }, i))) }), 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') })] })] }) }));
|
|
258
339
|
};
|
|
259
340
|
|
|
260
341
|
const stopPropagation = (e) => e.stopPropagation();
|
|
@@ -334,7 +415,7 @@ const SubscribeCalendarDialog = ({ onSubscribe, onCancel, }) => {
|
|
|
334
415
|
};
|
|
335
416
|
|
|
336
417
|
const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCollapsed, setCollapsed, renderCalendarContextMenu, renderSidebarHeader, editingCalendarId: propEditingCalendarId, setEditingCalendarId: propSetEditingCalendarId, onCreateCalendar, }) => {
|
|
337
|
-
var _a, _b
|
|
418
|
+
var _a, _b;
|
|
338
419
|
const { t } = useLocale();
|
|
339
420
|
// Detect if custom color picker slot is provided
|
|
340
421
|
const hasCustomPicker = app.state.overrides.includes('colorPicker');
|
|
@@ -592,14 +673,18 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
|
|
|
592
673
|
handleCloseContextMenu();
|
|
593
674
|
}
|
|
594
675
|
}, [contextMenu, calendars, app, handleCloseContextMenu]);
|
|
595
|
-
const
|
|
596
|
-
?
|
|
597
|
-
:
|
|
598
|
-
const
|
|
599
|
-
?
|
|
600
|
-
:
|
|
676
|
+
const sourceCalendar = mergeState
|
|
677
|
+
? calendars.find(c => c.id === mergeState.sourceId)
|
|
678
|
+
: null;
|
|
679
|
+
const targetCalendar = mergeState
|
|
680
|
+
? calendars.find(c => c.id === mergeState.targetId)
|
|
681
|
+
: null;
|
|
682
|
+
const sourceCalendarName = (sourceCalendar === null || sourceCalendar === void 0 ? void 0 : sourceCalendar.name) || 'Unknown';
|
|
683
|
+
const targetCalendarName = (targetCalendar === null || targetCalendar === void 0 ? void 0 : targetCalendar.name) || 'Unknown';
|
|
684
|
+
const sourceCalendarColor = (sourceCalendar === null || sourceCalendar === void 0 ? void 0 : sourceCalendar.colors.lineColor) || '#6b7280';
|
|
685
|
+
const targetCalendarColor = (targetCalendar === null || targetCalendar === void 0 ? void 0 : targetCalendar.colors.lineColor) || '#6b7280';
|
|
601
686
|
const deleteCalendarName = deleteState
|
|
602
|
-
? ((
|
|
687
|
+
? ((_a = calendars.find(c => c.id === deleteState.calendarId)) === null || _a === void 0 ? void 0 : _a.name) || 'Unknown'
|
|
603
688
|
: '';
|
|
604
689
|
const readOnlyConfig = app.getReadOnlyConfig();
|
|
605
690
|
const isEditable = !app.state.readOnly;
|
|
@@ -637,7 +722,7 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
|
|
|
637
722
|
}, 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: {
|
|
638
723
|
calendar: calendars.find(c => c.id === contextMenu.calendarId),
|
|
639
724
|
onClose: handleCloseContextMenu,
|
|
640
|
-
}, 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: (
|
|
725
|
+
}, 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: (_b = calendars.find(c => c.id === contextMenu.calendarId)) === null || _b === void 0 ? void 0 : _b.colors.lineColor, onSelect: handleColorSelect, onCustomColor: handleCustomColor })] })) }) })), sidebarContextMenu &&
|
|
641
726
|
createPortal(u(ContextMenu, { x: sidebarContextMenu.x, y: sidebarContextMenu.y, onClose: handleCloseSidebarContextMenu, className: 'w-max p-2', children: [u(ContextMenuItem, { onClick: () => {
|
|
642
727
|
onCreateCalendar === null || onCreateCalendar === void 0 ? void 0 : onCreateCalendar();
|
|
643
728
|
handleCloseSidebarContextMenu();
|
|
@@ -647,7 +732,7 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
|
|
|
647
732
|
}, children: t('refreshAll') || 'Refresh All' })] }), document.body), u("input", { ref: fileInputRef, type: 'file', accept: '.ics', style: { display: 'none' }, onChange: handleFileChange }), importState &&
|
|
648
733
|
createPortal(u(ImportCalendarDialog, { calendars: calendars, filename: importState.filename, onConfirm: handleImportConfirm, onCancel: () => setImportState(null) }), document.body), subscribeDialogOpen &&
|
|
649
734
|
createPortal(u(SubscribeCalendarDialog, { onSubscribe: handleSubscribeConfirm, onCancel: () => setSubscribeDialogOpen(false) }), document.body), mergeState &&
|
|
650
|
-
createPortal(u(MergeCalendarDialog, { sourceName: sourceCalendarName, targetName: targetCalendarName, onConfirm: handleMergeConfirm, onCancel: () => setMergeState(null) }), document.body), deleteState &&
|
|
735
|
+
createPortal(u(MergeCalendarDialog, { sourceName: sourceCalendarName, sourceColor: sourceCalendarColor, targetName: targetCalendarName, targetColor: targetCalendarColor, onConfirm: handleMergeConfirm, onCancel: () => setMergeState(null) }), document.body), deleteState &&
|
|
651
736
|
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 &&
|
|
652
737
|
createPortal(u("div", { className: 'fixed inset-0 z-50', onMouseDown: () => {
|
|
653
738
|
app.updateCalendar(customColorPicker.calendarId, {});
|
package/dist/index.js
CHANGED
|
@@ -46,21 +46,33 @@ const getCalendarInitials = (calendar) => {
|
|
|
46
46
|
const name = calendar.name || calendar.id;
|
|
47
47
|
return name.charAt(0).toUpperCase();
|
|
48
48
|
};
|
|
49
|
+
const CalendarItem = ({ calendar, isDraggable, isEditable: _isEditable, editingId, editingName, setEditingName, editInputRef, draggedCalendarId, dropTarget, activeContextMenuCalendarId, onDragStart, onDragEnd, onDragOver, onDragLeave, onDrop, onContextMenu, onToggleVisibility, onRenameStart, onRenameSave, onRenameKeyDown, }) => {
|
|
50
|
+
var _a;
|
|
51
|
+
const isVisible = calendar.isVisible !== false;
|
|
52
|
+
const calendarColor = ((_a = calendar.colors) === null || _a === void 0 ? void 0 : _a.lineColor) || '#3b82f6';
|
|
53
|
+
const showIcon = Boolean(calendar.icon);
|
|
54
|
+
const isDropTarget = (dropTarget === null || dropTarget === void 0 ? void 0 : dropTarget.id) === calendar.id;
|
|
55
|
+
const isActive = activeContextMenuCalendarId === calendar.id || editingId === calendar.id;
|
|
56
|
+
return (u("li", { className: 'df-calendar-list-item relative', onDragOver: e => onDragOver(e, calendar.id), onDragLeave: onDragLeave, onDrop: () => onDrop(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-[var(--df-color-primary)]' })), u("div", { draggable: isDraggable && !editingId, onDragStart: e => onDragStart(calendar, e), onDragEnd: onDragEnd, 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: 'df-calendar-checkbox shrink-0 cursor-pointer', style: {
|
|
57
|
+
'--checkbox-color': calendarColor,
|
|
58
|
+
}, 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: onRenameSave, onKeyDown: onRenameKeyDown, 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(preact.Fragment, { children: [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: () => onRenameStart(calendar), children: calendar.name || calendar.id }), calendar.subscribed && (u(core.AudioLines, { width: 13, height: 13, className: 'ml-1 shrink-0 text-gray-400 dark:text-gray-500' }))] }))] }) }), isDropTarget && dropTarget.position === 'bottom' && (u("div", { className: 'pointer-events-none absolute right-0 bottom-0 left-0 z-10 h-0.5 bg-[var(--df-color-primary)]' }))] }, calendar.id));
|
|
59
|
+
};
|
|
49
60
|
const CalendarList = ({ calendars, onToggleVisibility, onReorder, onRename, onContextMenu, editingId, setEditingId, activeContextMenuCalendarId, isDraggable = true, isEditable = true, }) => {
|
|
61
|
+
var _a;
|
|
50
62
|
const [editingName, setEditingName] = hooks.useState('');
|
|
51
63
|
const editInputRef = hooks.useRef(null);
|
|
52
64
|
const isProcessedRef = hooks.useRef(false);
|
|
53
65
|
// Drag state
|
|
54
66
|
const [draggedCalendarId, setDraggedCalendarId] = hooks.useState(null);
|
|
55
67
|
const [dropTarget, setDropTarget] = hooks.useState(null);
|
|
68
|
+
// Collapsed sources state
|
|
69
|
+
const [collapsedSources, setCollapsedSources] = hooks.useState({});
|
|
56
70
|
const handleDragStart = hooks.useCallback((calendar, e) => {
|
|
57
|
-
// Prevent dragging when editing or not draggable
|
|
58
71
|
if (editingId || !isDraggable) {
|
|
59
72
|
e.preventDefault();
|
|
60
73
|
return;
|
|
61
74
|
}
|
|
62
75
|
setDraggedCalendarId(calendar.id);
|
|
63
|
-
// Store calendar data for drop handling
|
|
64
76
|
const dragData = {
|
|
65
77
|
calendarId: calendar.id,
|
|
66
78
|
calendarName: calendar.name,
|
|
@@ -109,11 +121,9 @@ const CalendarList = ({ calendars, onToggleVisibility, onReorder, onRename, onCo
|
|
|
109
121
|
return;
|
|
110
122
|
const fromIndex = calendars.findIndex(c => c.id === draggedCalendarId);
|
|
111
123
|
let toIndex = calendars.findIndex(c => c.id === targetCalendar.id);
|
|
112
|
-
// Adjust target index based on position
|
|
113
124
|
if (dropTarget.position === 'bottom') {
|
|
114
125
|
toIndex += 1;
|
|
115
126
|
}
|
|
116
|
-
// Adjust for removal of the item
|
|
117
127
|
if (toIndex > fromIndex) {
|
|
118
128
|
toIndex -= 1;
|
|
119
129
|
}
|
|
@@ -171,24 +181,75 @@ const CalendarList = ({ calendars, onToggleVisibility, onReorder, onRename, onCo
|
|
|
171
181
|
}
|
|
172
182
|
}
|
|
173
183
|
}, [editingId, calendars]);
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
const toggleSource = hooks.useCallback((source) => {
|
|
185
|
+
setCollapsedSources(prev => (Object.assign(Object.assign({}, prev), { [source]: !prev[source] })));
|
|
186
|
+
}, []);
|
|
187
|
+
// Shared item props (excludes per-item fields)
|
|
188
|
+
const sharedItemProps = {
|
|
189
|
+
isDraggable,
|
|
190
|
+
isEditable,
|
|
191
|
+
editingId,
|
|
192
|
+
editingName,
|
|
193
|
+
setEditingName,
|
|
194
|
+
editInputRef,
|
|
195
|
+
isProcessedRef,
|
|
196
|
+
draggedCalendarId,
|
|
197
|
+
dropTarget,
|
|
198
|
+
activeContextMenuCalendarId,
|
|
199
|
+
onDragStart: handleDragStart,
|
|
200
|
+
onDragEnd: handleDragEnd,
|
|
201
|
+
onDragOver: handleDragOver,
|
|
202
|
+
onDragLeave: handleDragLeave,
|
|
203
|
+
onDrop: handleDrop,
|
|
204
|
+
onContextMenu,
|
|
205
|
+
onToggleVisibility,
|
|
206
|
+
onRenameStart: handleRenameStart,
|
|
207
|
+
onRenameSave: handleRenameSave,
|
|
208
|
+
onRenameKeyDown: handleRenameKeyDown,
|
|
209
|
+
setEditingId,
|
|
210
|
+
};
|
|
211
|
+
// Check if any calendar has a source
|
|
212
|
+
const hasSources = calendars.some(c => c.source);
|
|
213
|
+
if (!hasSources) {
|
|
214
|
+
// Flat list (original behaviour)
|
|
215
|
+
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 => (u(CalendarItem, Object.assign({ calendar: calendar }, sharedItemProps), calendar.id))) }) }));
|
|
216
|
+
}
|
|
217
|
+
// Group calendars by source; calendars without a source go into a null group
|
|
218
|
+
const groups = new Map();
|
|
219
|
+
for (const calendar of calendars) {
|
|
220
|
+
const key = (_a = calendar.source) !== null && _a !== void 0 ? _a : null;
|
|
221
|
+
if (!groups.has(key))
|
|
222
|
+
groups.set(key, []);
|
|
223
|
+
groups.get(key).push(calendar);
|
|
224
|
+
}
|
|
225
|
+
return (u("div", { className: 'df-calendar-list flex-1 overflow-y-auto px-2 pb-3', children: [groups.has(null) && (u("ul", { className: 'relative space-y-1', children: groups.get(null).map(calendar => (u(CalendarItem, Object.assign({ calendar: calendar }, sharedItemProps), calendar.id))) })), Array.from(groups.entries())
|
|
226
|
+
.filter(([source]) => source !== null)
|
|
227
|
+
.map(([source, groupCalendars]) => {
|
|
228
|
+
const isCollapsed = collapsedSources[source];
|
|
229
|
+
return (u("div", { className: 'mt-1', children: [u("button", { type: 'button', className: 'flex w-full items-center justify-between rounded px-2 py-1.5 text-xs font-medium text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-slate-800', onClick: () => toggleSource(source), children: [u("span", { className: 'truncate', children: source }), u(core.ChevronDown, { width: 13, height: 13, className: `ml-1 shrink-0 transition-transform duration-200 ${isCollapsed ? '-rotate-90' : ''}` })] }), u("div", { style: {
|
|
230
|
+
display: 'grid',
|
|
231
|
+
gridTemplateRows: isCollapsed ? '0fr' : '1fr',
|
|
232
|
+
transition: 'grid-template-rows 200ms ease',
|
|
233
|
+
}, children: u("div", { style: { overflow: 'hidden' }, children: u("ul", { className: 'relative space-y-1', children: groupCalendars.map(calendar => (u(CalendarItem, Object.assign({ calendar: calendar }, sharedItemProps), calendar.id))) }) }) })] }, source));
|
|
234
|
+
})] }));
|
|
186
235
|
};
|
|
187
236
|
|
|
237
|
+
const CalendarChip = ({ name, color }) => (u("span", { className: 'mx-0.5 inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium', style: { backgroundColor: `${color}26`, color }, children: name }));
|
|
238
|
+
|
|
239
|
+
const CAL_SENTINEL = '\u0001C\u0001';
|
|
240
|
+
function renderWithChip(template, name, color) {
|
|
241
|
+
return template
|
|
242
|
+
.split(CAL_SENTINEL)
|
|
243
|
+
.flatMap((part, i) => i === 0
|
|
244
|
+
? [part]
|
|
245
|
+
: [u(CalendarChip, { name: name, color: color }, i), part]);
|
|
246
|
+
}
|
|
188
247
|
const DeleteCalendarDialog = ({ calendarId, calendarName, calendars, step, onStepChange, onConfirmDelete, onCancel, onMergeSelect, }) => {
|
|
248
|
+
var _a, _b;
|
|
189
249
|
const [showMergeDropdown, setShowMergeDropdown] = hooks.useState(false);
|
|
190
250
|
const { t } = core.useLocale();
|
|
191
|
-
|
|
251
|
+
const calendarColor = (_b = (_a = calendars.find(c => c.id === calendarId)) === null || _a === void 0 ? void 0 : _a.colors.lineColor) !== null && _b !== void 0 ? _b : '#6b7280';
|
|
252
|
+
return core.createPortal(u("div", { className: 'df-portal 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-white p-6 shadow-xl dark:bg-gray-800', 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 flex flex-wrap items-center gap-y-0.5 text-sm text-gray-600 dark:text-gray-300', children: renderWithChip(t('deleteCalendarMessage', { calendarName: CAL_SENTINEL }), calendarName, calendarColor) }), 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-white shadow-lg dark:border-slate-700 dark:bg-gray-800', children: calendars
|
|
192
253
|
.filter(c => c.id !== calendarId)
|
|
193
254
|
.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: () => {
|
|
194
255
|
onMergeSelect(calendar.id);
|
|
@@ -254,9 +315,29 @@ const ImportCalendarDialog = ({ calendars, filename, onConfirm, onCancel, }) =>
|
|
|
254
315
|
: (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' })] })] }) }));
|
|
255
316
|
};
|
|
256
317
|
|
|
257
|
-
const
|
|
318
|
+
const SOURCE_SENTINEL = '\u0001S\u0001';
|
|
319
|
+
const TARGET_SENTINEL = '\u0001T\u0001';
|
|
320
|
+
function renderLine(line, source, target) {
|
|
321
|
+
return line
|
|
322
|
+
.split(new RegExp(`(${SOURCE_SENTINEL}|${TARGET_SENTINEL})`))
|
|
323
|
+
.map((part, i) => {
|
|
324
|
+
if (part === SOURCE_SENTINEL)
|
|
325
|
+
return u(CalendarChip, { name: source.name, color: source.color }, i);
|
|
326
|
+
if (part === TARGET_SENTINEL)
|
|
327
|
+
return u(CalendarChip, { name: target.name, color: target.color }, i);
|
|
328
|
+
return part;
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
const MergeCalendarDialog = ({ sourceName, sourceColor, targetName, targetColor, onConfirm, onCancel, }) => {
|
|
258
332
|
const { t } = core.useLocale();
|
|
259
|
-
|
|
333
|
+
const source = { name: sourceName, color: sourceColor };
|
|
334
|
+
const target = { name: targetName, color: targetColor };
|
|
335
|
+
const messageTemplate = t('mergeConfirmMessage', {
|
|
336
|
+
sourceName: SOURCE_SENTINEL,
|
|
337
|
+
targetName: TARGET_SENTINEL,
|
|
338
|
+
});
|
|
339
|
+
const messageLines = messageTemplate.split('\n');
|
|
340
|
+
return (u("div", { className: 'df-portal fixed inset-0 z-[9999] flex items-center justify-center bg-black/50', children: u("div", { className: 'rounded-lg bg-white p-6 shadow-xl dark:bg-gray-800', children: [u("h2", { className: 'text-lg font-semibold text-gray-900 dark:text-white', children: t('mergeConfirmTitle', { sourceName, targetName }) }), u("div", { className: 'mt-3 space-y-1 text-sm text-gray-600 dark:text-gray-300', children: messageLines.map((line, i) => (u("p", { className: 'flex flex-wrap items-center gap-y-0.5', children: renderLine(line, source, target) }, i))) }), 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') })] })] }) }));
|
|
260
341
|
};
|
|
261
342
|
|
|
262
343
|
const stopPropagation = (e) => e.stopPropagation();
|
|
@@ -336,7 +417,7 @@ const SubscribeCalendarDialog = ({ onSubscribe, onCancel, }) => {
|
|
|
336
417
|
};
|
|
337
418
|
|
|
338
419
|
const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCollapsed, setCollapsed, renderCalendarContextMenu, renderSidebarHeader, editingCalendarId: propEditingCalendarId, setEditingCalendarId: propSetEditingCalendarId, onCreateCalendar, }) => {
|
|
339
|
-
var _a, _b
|
|
420
|
+
var _a, _b;
|
|
340
421
|
const { t } = core.useLocale();
|
|
341
422
|
// Detect if custom color picker slot is provided
|
|
342
423
|
const hasCustomPicker = app.state.overrides.includes('colorPicker');
|
|
@@ -594,14 +675,18 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
|
|
|
594
675
|
handleCloseContextMenu();
|
|
595
676
|
}
|
|
596
677
|
}, [contextMenu, calendars, app, handleCloseContextMenu]);
|
|
597
|
-
const
|
|
598
|
-
?
|
|
599
|
-
:
|
|
600
|
-
const
|
|
601
|
-
?
|
|
602
|
-
:
|
|
678
|
+
const sourceCalendar = mergeState
|
|
679
|
+
? calendars.find(c => c.id === mergeState.sourceId)
|
|
680
|
+
: null;
|
|
681
|
+
const targetCalendar = mergeState
|
|
682
|
+
? calendars.find(c => c.id === mergeState.targetId)
|
|
683
|
+
: null;
|
|
684
|
+
const sourceCalendarName = (sourceCalendar === null || sourceCalendar === void 0 ? void 0 : sourceCalendar.name) || 'Unknown';
|
|
685
|
+
const targetCalendarName = (targetCalendar === null || targetCalendar === void 0 ? void 0 : targetCalendar.name) || 'Unknown';
|
|
686
|
+
const sourceCalendarColor = (sourceCalendar === null || sourceCalendar === void 0 ? void 0 : sourceCalendar.colors.lineColor) || '#6b7280';
|
|
687
|
+
const targetCalendarColor = (targetCalendar === null || targetCalendar === void 0 ? void 0 : targetCalendar.colors.lineColor) || '#6b7280';
|
|
603
688
|
const deleteCalendarName = deleteState
|
|
604
|
-
? ((
|
|
689
|
+
? ((_a = calendars.find(c => c.id === deleteState.calendarId)) === null || _a === void 0 ? void 0 : _a.name) || 'Unknown'
|
|
605
690
|
: '';
|
|
606
691
|
const readOnlyConfig = app.getReadOnlyConfig();
|
|
607
692
|
const isEditable = !app.state.readOnly;
|
|
@@ -639,7 +724,7 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
|
|
|
639
724
|
}, 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: {
|
|
640
725
|
calendar: calendars.find(c => c.id === contextMenu.calendarId),
|
|
641
726
|
onClose: handleCloseContextMenu,
|
|
642
|
-
}, 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: (
|
|
727
|
+
}, 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: (_b = calendars.find(c => c.id === contextMenu.calendarId)) === null || _b === void 0 ? void 0 : _b.colors.lineColor, onSelect: handleColorSelect, onCustomColor: handleCustomColor })] })) }) })), sidebarContextMenu &&
|
|
643
728
|
core.createPortal(u(core.ContextMenu, { x: sidebarContextMenu.x, y: sidebarContextMenu.y, onClose: handleCloseSidebarContextMenu, className: 'w-max p-2', children: [u(core.ContextMenuItem, { onClick: () => {
|
|
644
729
|
onCreateCalendar === null || onCreateCalendar === void 0 ? void 0 : onCreateCalendar();
|
|
645
730
|
handleCloseSidebarContextMenu();
|
|
@@ -649,7 +734,7 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
|
|
|
649
734
|
}, children: t('refreshAll') || 'Refresh All' })] }), document.body), u("input", { ref: fileInputRef, type: 'file', accept: '.ics', style: { display: 'none' }, onChange: handleFileChange }), importState &&
|
|
650
735
|
core.createPortal(u(ImportCalendarDialog, { calendars: calendars, filename: importState.filename, onConfirm: handleImportConfirm, onCancel: () => setImportState(null) }), document.body), subscribeDialogOpen &&
|
|
651
736
|
core.createPortal(u(SubscribeCalendarDialog, { onSubscribe: handleSubscribeConfirm, onCancel: () => setSubscribeDialogOpen(false) }), document.body), mergeState &&
|
|
652
|
-
core.createPortal(u(MergeCalendarDialog, { sourceName: sourceCalendarName, targetName: targetCalendarName, onConfirm: handleMergeConfirm, onCancel: () => setMergeState(null) }), document.body), deleteState &&
|
|
737
|
+
core.createPortal(u(MergeCalendarDialog, { sourceName: sourceCalendarName, sourceColor: sourceCalendarColor, targetName: targetCalendarName, targetColor: targetCalendarColor, onConfirm: handleMergeConfirm, onCancel: () => setMergeState(null) }), document.body), deleteState &&
|
|
653
738
|
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 &&
|
|
654
739
|
core.createPortal(u("div", { className: 'fixed inset-0 z-50', onMouseDown: () => {
|
|
655
740
|
app.updateCalendar(customColorPicker.calendarId, {});
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
interface MergeCalendarDialogProps {
|
|
2
2
|
sourceName: string;
|
|
3
|
+
sourceColor: string;
|
|
3
4
|
targetName: string;
|
|
5
|
+
targetColor: string;
|
|
4
6
|
onConfirm: () => void;
|
|
5
7
|
onCancel: () => void;
|
|
6
8
|
}
|
|
7
|
-
export declare const MergeCalendarDialog: ({ sourceName, targetName, onConfirm, onCancel, }: MergeCalendarDialogProps) => import("preact").JSX.Element;
|
|
9
|
+
export declare const MergeCalendarDialog: ({ sourceName, sourceColor, targetName, targetColor, onConfirm, onCancel, }: MergeCalendarDialogProps) => import("preact").JSX.Element;
|
|
8
10
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dayflow/plugin-sidebar",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "Sidebar plugin for DayFlow calendar",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"calendar",
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
"rollup-plugin-dts": "^6.3.0",
|
|
38
38
|
"temporal-polyfill": "^0.3.0",
|
|
39
39
|
"typescript": "^5.9.3",
|
|
40
|
-
"@dayflow/core": "3.3.
|
|
40
|
+
"@dayflow/core": "3.3.3"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@dayflow/core": "3.3.
|
|
43
|
+
"@dayflow/core": "3.3.3"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && rollup -c",
|