@dayflow/plugin-sidebar 1.0.2 → 1.1.1
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 +42 -13
- package/dist/index.d.ts +0 -2
- package/dist/index.esm.js +133 -113
- package/dist/index.js +133 -113
- package/dist/types/DefaultCalendarSidebar.d.ts +2 -1
- package/dist/types/components/CalendarList.d.ts +3 -2
- package/dist/types/plugin.d.ts +0 -2
- package/package.json +24 -22
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
|
|
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
|
[](https://www.npmjs.com/package/@dayflow/core)
|
|
9
8
|
[](https://github.com/dayflow-js/dayflow/pulls)
|
|
@@ -12,21 +11,51 @@ views, and plugin architecture.
|
|
|
12
11
|
|
|
13
12
|
## Features
|
|
14
13
|
|
|
15
|
-
###
|
|
14
|
+
### Daily, Weekly, Monthly and Yearly View Types
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
| --------------------------------------- | -------------------------------------- |
|
|
19
|
-
|  |  |
|
|
16
|
+
#### Day View
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
| ------------------------------------- | ---------------------------------------- |
|
|
23
|
-
|  |  |
|
|
18
|
+

|
|
24
19
|
|
|
25
|
-
|
|
20
|
+
#### Week View
|
|
26
21
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+

|
|
23
|
+
|
|
24
|
+
#### Month View
|
|
25
|
+
|
|
26
|
+

|
|
27
|
+
|
|
28
|
+
#### Year View(Fixed-Week)
|
|
29
|
+
|
|
30
|
+

|
|
31
|
+
|
|
32
|
+
#### Year View(Year-Canvas)
|
|
33
|
+
|
|
34
|
+

|
|
35
|
+
|
|
36
|
+
### Mobile View Support
|
|
37
|
+
|
|
38
|
+
#### Mobile Day & Year View
|
|
39
|
+
|
|
40
|
+

|
|
41
|
+
|
|
42
|
+
#### Mobile Week & Month View
|
|
43
|
+
|
|
44
|
+

|
|
45
|
+
|
|
46
|
+
### Multiple Event Detail Panel options
|
|
47
|
+
|
|
48
|
+
#### Detail Popup
|
|
49
|
+
|
|
50
|
+

|
|
51
|
+
|
|
52
|
+
#### Detail Dialog
|
|
53
|
+
|
|
54
|
+

|
|
55
|
+
|
|
56
|
+
### Dark Mode Support
|
|
57
|
+
|
|
58
|
+

|
|
30
59
|
|
|
31
60
|
### Easy to resize and drag
|
|
32
61
|
|
package/dist/index.d.ts
CHANGED
|
@@ -13,14 +13,12 @@ interface CalendarSidebarRenderProps {
|
|
|
13
13
|
editingCalendarId?: string | null;
|
|
14
14
|
setEditingCalendarId?: (id: string | null) => void;
|
|
15
15
|
onCreateCalendar?: () => void;
|
|
16
|
-
colorPickerMode?: 'default' | 'custom';
|
|
17
16
|
}
|
|
18
17
|
interface SidebarPluginConfig {
|
|
19
18
|
width?: number | string;
|
|
20
19
|
miniWidth?: string;
|
|
21
20
|
initialCollapsed?: boolean;
|
|
22
21
|
createCalendarMode?: 'inline' | 'modal';
|
|
23
|
-
colorPickerMode?: 'default' | 'custom';
|
|
24
22
|
render?: (props: CalendarSidebarRenderProps) => TNode;
|
|
25
23
|
renderCalendarContextMenu?: (calendar: CalendarType, onClose: () => void) => TNode;
|
|
26
24
|
renderCreateCalendarDialog?: (props: CreateCalendarDialogProps) => TNode;
|
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, DefaultColorPicker, BlossomColorPicker, 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
|
|
74
|
-
|
|
75
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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,78 @@ 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
|
|
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:
|
|
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:
|
|
298
|
-
'This calendar contains new events. Please select a target calendar.' }), u("div", { className:
|
|
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:
|
|
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') })] })] }) }));
|
|
301
257
|
};
|
|
302
258
|
|
|
303
|
-
const
|
|
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') }) }))] }));
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCollapsed, setCollapsed, renderCalendarContextMenu, editingCalendarId: propEditingCalendarId, setEditingCalendarId: propSetEditingCalendarId, onCreateCalendar, }) => {
|
|
304
306
|
var _a, _b, _c, _d;
|
|
305
307
|
const { t } = useLocale();
|
|
308
|
+
// Detect if custom color picker slot is provided
|
|
309
|
+
const hasCustomPicker = app.state.overrides.includes('colorPicker');
|
|
306
310
|
const [localEditingCalendarId, setLocalEditingCalendarId] = useState(null);
|
|
307
|
-
const editingCalendarId = propEditingCalendarId
|
|
308
|
-
?
|
|
309
|
-
:
|
|
311
|
+
const editingCalendarId = propEditingCalendarId === undefined
|
|
312
|
+
? localEditingCalendarId
|
|
313
|
+
: propEditingCalendarId;
|
|
310
314
|
const setEditingCalendarId = propSetEditingCalendarId || setLocalEditingCalendarId;
|
|
311
315
|
// File input ref for import
|
|
312
316
|
const fileInputRef = useRef(null);
|
|
@@ -443,7 +447,7 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
|
|
|
443
447
|
}, [handleCloseSidebarContextMenu]);
|
|
444
448
|
const handleFileChange = useCallback((e) => __awaiter(void 0, void 0, void 0, function* () {
|
|
445
449
|
var _a;
|
|
446
|
-
const file = (_a = e.
|
|
450
|
+
const file = (_a = e.currentTarget.files) === null || _a === void 0 ? void 0 : _a[0];
|
|
447
451
|
if (!file)
|
|
448
452
|
return;
|
|
449
453
|
const result = yield importICSFile(file);
|
|
@@ -522,42 +526,53 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
|
|
|
522
526
|
const readOnlyConfig = app.getReadOnlyConfig();
|
|
523
527
|
const isEditable = !app.state.readOnly;
|
|
524
528
|
const isDraggable = readOnlyConfig.draggable !== false;
|
|
525
|
-
return (u("div", { className: sidebarContainer, onContextMenu: isEditable ? handleSidebarContextMenu : undefined, children: [u(SidebarHeader, { isCollapsed: isCollapsed, onCollapseToggle: () => setCollapsed(!isCollapsed) }),
|
|
526
|
-
|
|
527
|
-
|
|
529
|
+
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
|
|
530
|
+
? app.reorderCalendars
|
|
531
|
+
: () => {
|
|
532
|
+
/* noop */
|
|
533
|
+
}, onRename: isEditable
|
|
528
534
|
? (id, newName) => app.updateCalendar(id, { name: newName })
|
|
529
|
-
: () => {
|
|
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(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(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
554
|
calendar: calendars.find(c => c.id === contextMenu.calendarId),
|
|
531
555
|
onClose: handleCloseContextMenu,
|
|
532
556
|
}, 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:
|
|
557
|
+
createPortal(u(ContextMenu, { x: sidebarContextMenu.x, y: sidebarContextMenu.y, onClose: handleCloseSidebarContextMenu, className: 'w-max p-2', children: [u(ContextMenuItem, { onClick: () => {
|
|
534
558
|
onCreateCalendar === null || onCreateCalendar === void 0 ? void 0 : onCreateCalendar();
|
|
535
559
|
handleCloseSidebarContextMenu();
|
|
536
560
|
}, children: t('newCalendar') || 'New Calendar' }), u(ContextMenuItem, { onClick: handleImportClick, children: t('importCalendar') || 'Import Calendar' }), u(ContextMenuItem, { onClick: () => {
|
|
537
561
|
app.triggerRender();
|
|
538
562
|
handleCloseSidebarContextMenu();
|
|
539
|
-
}, children: t('refreshAll') || 'Refresh All' })] }), document.body), u("input", { ref: fileInputRef, type:
|
|
563
|
+
}, children: t('refreshAll') || 'Refresh All' })] }), document.body), u("input", { ref: fileInputRef, type: 'file', accept: '.ics', style: { display: 'none' }, onChange: handleFileChange }), importState &&
|
|
540
564
|
createPortal(u(ImportCalendarDialog, { calendars: calendars, filename: importState.filename, onConfirm: handleImportConfirm, onCancel: () => setImportState(null) }), document.body), mergeState &&
|
|
541
565
|
createPortal(u(MergeCalendarDialog, { sourceName: sourceCalendarName, targetName: targetCalendarName, onConfirm: handleMergeConfirm, onCancel: () => setMergeState(null) }), document.body), deleteState &&
|
|
542
566
|
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:
|
|
567
|
+
createPortal(u("div", { className: 'fixed inset-0 z-50', onMouseDown: () => {
|
|
544
568
|
app.updateCalendar(customColorPicker.calendarId, {});
|
|
545
569
|
setCustomColorPicker(null);
|
|
546
|
-
}, children: u("div", { className:
|
|
570
|
+
}, children: u("div", { className: 'absolute', style: {
|
|
547
571
|
top: customColorPicker.y,
|
|
548
572
|
left: customColorPicker.x,
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
app.updateCalendar(customColorPicker.calendarId, {
|
|
553
|
-
colors,
|
|
554
|
-
darkColors,
|
|
555
|
-
}, true);
|
|
556
|
-
}, onCollapse: () => {
|
|
557
|
-
app.updateCalendar(customColorPicker.calendarId, {});
|
|
558
|
-
setCustomColorPicker(null);
|
|
559
|
-
} })) : (u(ContentSlot, { generatorName: "colorPicker", generatorArgs: {
|
|
560
|
-
variant: 'sketch', // TODO: change name
|
|
573
|
+
zIndex: 10002,
|
|
574
|
+
transform: 'translate(40px, -50%)', // Move it to the right of the checkbox/dot
|
|
575
|
+
}, onMouseDown: e => e.stopPropagation(), children: hasCustomPicker ? (u(ContentSlot, { generatorName: 'colorPicker', generatorArgs: {
|
|
561
576
|
color: customColorPicker.currentColor,
|
|
562
577
|
onChange: (color) => {
|
|
563
578
|
setCustomColorPicker(prev => prev ? Object.assign(Object.assign({}, prev), { currentColor: color.hex }) : null);
|
|
@@ -574,17 +589,26 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
|
|
|
574
589
|
darkColors,
|
|
575
590
|
});
|
|
576
591
|
},
|
|
577
|
-
}, defaultContent: u(DefaultColorPicker, { color: customColorPicker.currentColor, onChange: (color, isPending) => {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
592
|
+
}, defaultContent: u("div", { className: 'rounded-lg border border-gray-200 bg-white p-3 shadow-xl dark:border-gray-700 dark:bg-slate-900', children: u(DefaultColorPicker, { color: customColorPicker.currentColor, onChange: (color, isPending) => {
|
|
593
|
+
setCustomColorPicker(prev => prev ? Object.assign(Object.assign({}, prev), { currentColor: color.hex }) : null);
|
|
594
|
+
const { colors, darkColors } = getCalendarColorsForHex(color.hex);
|
|
595
|
+
app.updateCalendar(customColorPicker.calendarId, {
|
|
596
|
+
colors,
|
|
597
|
+
darkColors,
|
|
598
|
+
}, isPending);
|
|
599
|
+
}, onClose: () => {
|
|
600
|
+
app.updateCalendar(customColorPicker.calendarId, {});
|
|
601
|
+
setCustomColorPicker(null);
|
|
602
|
+
} }) }) })) : (u(BlossomColorPicker, { defaultValue: customColorPicker.initialColor, coreSize: 28, petalSize: 28, initialExpanded: true, adaptivePositioning: true, openOnHover: false, onChange: color => {
|
|
603
|
+
const { colors, darkColors } = getCalendarColorsForHex(color.hex);
|
|
604
|
+
app.updateCalendar(customColorPicker.calendarId, {
|
|
605
|
+
colors,
|
|
606
|
+
darkColors,
|
|
607
|
+
}, true);
|
|
608
|
+
}, onCollapse: () => {
|
|
609
|
+
app.updateCalendar(customColorPicker.calendarId, {});
|
|
610
|
+
setCustomColorPicker(null);
|
|
611
|
+
} })) }) }), document.body)] }));
|
|
588
612
|
};
|
|
589
613
|
|
|
590
614
|
const DEFAULT_SIDEBAR_WIDTH = '240px';
|
|
@@ -613,11 +637,9 @@ function createSidebarPlugin(config = {}) {
|
|
|
613
637
|
const refreshSidebar = useCallback(() => {
|
|
614
638
|
setSidebarVersion(prev => prev + 1);
|
|
615
639
|
}, []);
|
|
616
|
-
useEffect(() => {
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
});
|
|
620
|
-
}, [app, refreshSidebar]);
|
|
640
|
+
useEffect(() => app.subscribe(() => {
|
|
641
|
+
refreshSidebar();
|
|
642
|
+
}), [app, refreshSidebar]);
|
|
621
643
|
const calendars = useMemo(() => app.getCalendars(), [app, sidebarVersion]);
|
|
622
644
|
const handleToggleCalendarVisibility = useCallback((calendarId, visible) => {
|
|
623
645
|
app.setCalendarVisibility(calendarId, visible);
|
|
@@ -661,7 +683,6 @@ function createSidebarPlugin(config = {}) {
|
|
|
661
683
|
editingCalendarId,
|
|
662
684
|
setEditingCalendarId,
|
|
663
685
|
onCreateCalendar: handleCreateCalendar,
|
|
664
|
-
colorPickerMode: config.colorPickerMode,
|
|
665
686
|
}), [
|
|
666
687
|
app,
|
|
667
688
|
calendars,
|
|
@@ -673,14 +694,13 @@ function createSidebarPlugin(config = {}) {
|
|
|
673
694
|
config,
|
|
674
695
|
]);
|
|
675
696
|
const renderContent = () => {
|
|
676
|
-
var _a;
|
|
677
697
|
if (config.render) {
|
|
678
698
|
return h(ContentSlot, {
|
|
679
699
|
generatorName: 'sidebar',
|
|
680
700
|
generatorArgs: sidebarProps,
|
|
681
701
|
});
|
|
682
702
|
}
|
|
683
|
-
return h(DefaultCalendarSidebar, Object.assign(
|
|
703
|
+
return h(DefaultCalendarSidebar, Object.assign({}, sidebarProps));
|
|
684
704
|
};
|
|
685
705
|
const renderExtraContent = () => {
|
|
686
706
|
if (!showCreateDialog)
|
|
@@ -694,7 +714,7 @@ function createSidebarPlugin(config = {}) {
|
|
|
694
714
|
const generatorArgs = {
|
|
695
715
|
onClose,
|
|
696
716
|
onCreate,
|
|
697
|
-
|
|
717
|
+
app,
|
|
698
718
|
};
|
|
699
719
|
return h(ContentSlot, {
|
|
700
720
|
generatorName: 'createCalendarDialog',
|
|
@@ -702,7 +722,7 @@ function createSidebarPlugin(config = {}) {
|
|
|
702
722
|
defaultContent: h(CreateCalendarDialog, {
|
|
703
723
|
onClose,
|
|
704
724
|
onCreate,
|
|
705
|
-
|
|
725
|
+
app,
|
|
706
726
|
}),
|
|
707
727
|
});
|
|
708
728
|
};
|
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
|
|
76
|
-
|
|
77
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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,78 @@ 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
|
|
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:
|
|
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:
|
|
300
|
-
'This calendar contains new events. Please select a target calendar.' }), u("div", { className:
|
|
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:
|
|
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') })] })] }) }));
|
|
303
259
|
};
|
|
304
260
|
|
|
305
|
-
const
|
|
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') }) }))] }));
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCollapsed, setCollapsed, renderCalendarContextMenu, editingCalendarId: propEditingCalendarId, setEditingCalendarId: propSetEditingCalendarId, onCreateCalendar, }) => {
|
|
306
308
|
var _a, _b, _c, _d;
|
|
307
309
|
const { t } = core.useLocale();
|
|
310
|
+
// Detect if custom color picker slot is provided
|
|
311
|
+
const hasCustomPicker = app.state.overrides.includes('colorPicker');
|
|
308
312
|
const [localEditingCalendarId, setLocalEditingCalendarId] = hooks.useState(null);
|
|
309
|
-
const editingCalendarId = propEditingCalendarId
|
|
310
|
-
?
|
|
311
|
-
:
|
|
313
|
+
const editingCalendarId = propEditingCalendarId === undefined
|
|
314
|
+
? localEditingCalendarId
|
|
315
|
+
: propEditingCalendarId;
|
|
312
316
|
const setEditingCalendarId = propSetEditingCalendarId || setLocalEditingCalendarId;
|
|
313
317
|
// File input ref for import
|
|
314
318
|
const fileInputRef = hooks.useRef(null);
|
|
@@ -445,7 +449,7 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
|
|
|
445
449
|
}, [handleCloseSidebarContextMenu]);
|
|
446
450
|
const handleFileChange = hooks.useCallback((e) => __awaiter(void 0, void 0, void 0, function* () {
|
|
447
451
|
var _a;
|
|
448
|
-
const file = (_a = e.
|
|
452
|
+
const file = (_a = e.currentTarget.files) === null || _a === void 0 ? void 0 : _a[0];
|
|
449
453
|
if (!file)
|
|
450
454
|
return;
|
|
451
455
|
const result = yield core.importICSFile(file);
|
|
@@ -524,42 +528,53 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
|
|
|
524
528
|
const readOnlyConfig = app.getReadOnlyConfig();
|
|
525
529
|
const isEditable = !app.state.readOnly;
|
|
526
530
|
const isDraggable = readOnlyConfig.draggable !== false;
|
|
527
|
-
return (u("div", { className: core.sidebarContainer, onContextMenu: isEditable ? handleSidebarContextMenu : undefined, children: [u(SidebarHeader, { isCollapsed: isCollapsed, onCollapseToggle: () => setCollapsed(!isCollapsed) }),
|
|
528
|
-
|
|
529
|
-
|
|
531
|
+
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
|
|
532
|
+
? app.reorderCalendars
|
|
533
|
+
: () => {
|
|
534
|
+
/* noop */
|
|
535
|
+
}, onRename: isEditable
|
|
530
536
|
? (id, newName) => app.updateCalendar(id, { name: newName })
|
|
531
|
-
: () => {
|
|
537
|
+
: () => {
|
|
538
|
+
/* noop */
|
|
539
|
+
}, onContextMenu: isEditable
|
|
540
|
+
? handleContextMenu
|
|
541
|
+
: () => {
|
|
542
|
+
/* noop */
|
|
543
|
+
}, 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
|
|
544
|
+
? app.reorderCalendars
|
|
545
|
+
: () => {
|
|
546
|
+
/* noop */
|
|
547
|
+
}, onRename: isEditable
|
|
548
|
+
? (id, newName) => app.updateCalendar(id, { name: newName })
|
|
549
|
+
: () => {
|
|
550
|
+
/* noop */
|
|
551
|
+
}, onContextMenu: isEditable
|
|
552
|
+
? handleContextMenu
|
|
553
|
+
: () => {
|
|
554
|
+
/* noop */
|
|
555
|
+
}, 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
556
|
calendar: calendars.find(c => c.id === contextMenu.calendarId),
|
|
533
557
|
onClose: handleCloseContextMenu,
|
|
534
558
|
}, 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:
|
|
559
|
+
core.createPortal(u(core.ContextMenu, { x: sidebarContextMenu.x, y: sidebarContextMenu.y, onClose: handleCloseSidebarContextMenu, className: 'w-max p-2', children: [u(core.ContextMenuItem, { onClick: () => {
|
|
536
560
|
onCreateCalendar === null || onCreateCalendar === void 0 ? void 0 : onCreateCalendar();
|
|
537
561
|
handleCloseSidebarContextMenu();
|
|
538
562
|
}, children: t('newCalendar') || 'New Calendar' }), u(core.ContextMenuItem, { onClick: handleImportClick, children: t('importCalendar') || 'Import Calendar' }), u(core.ContextMenuItem, { onClick: () => {
|
|
539
563
|
app.triggerRender();
|
|
540
564
|
handleCloseSidebarContextMenu();
|
|
541
|
-
}, children: t('refreshAll') || 'Refresh All' })] }), document.body), u("input", { ref: fileInputRef, type:
|
|
565
|
+
}, children: t('refreshAll') || 'Refresh All' })] }), document.body), u("input", { ref: fileInputRef, type: 'file', accept: '.ics', style: { display: 'none' }, onChange: handleFileChange }), importState &&
|
|
542
566
|
core.createPortal(u(ImportCalendarDialog, { calendars: calendars, filename: importState.filename, onConfirm: handleImportConfirm, onCancel: () => setImportState(null) }), document.body), mergeState &&
|
|
543
567
|
core.createPortal(u(MergeCalendarDialog, { sourceName: sourceCalendarName, targetName: targetCalendarName, onConfirm: handleMergeConfirm, onCancel: () => setMergeState(null) }), document.body), deleteState &&
|
|
544
568
|
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:
|
|
569
|
+
core.createPortal(u("div", { className: 'fixed inset-0 z-50', onMouseDown: () => {
|
|
546
570
|
app.updateCalendar(customColorPicker.calendarId, {});
|
|
547
571
|
setCustomColorPicker(null);
|
|
548
|
-
}, children: u("div", { className:
|
|
572
|
+
}, children: u("div", { className: 'absolute', style: {
|
|
549
573
|
top: customColorPicker.y,
|
|
550
574
|
left: customColorPicker.x,
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
app.updateCalendar(customColorPicker.calendarId, {
|
|
555
|
-
colors,
|
|
556
|
-
darkColors,
|
|
557
|
-
}, true);
|
|
558
|
-
}, onCollapse: () => {
|
|
559
|
-
app.updateCalendar(customColorPicker.calendarId, {});
|
|
560
|
-
setCustomColorPicker(null);
|
|
561
|
-
} })) : (u(core.ContentSlot, { generatorName: "colorPicker", generatorArgs: {
|
|
562
|
-
variant: 'sketch', // TODO: change name
|
|
575
|
+
zIndex: 10002,
|
|
576
|
+
transform: 'translate(40px, -50%)', // Move it to the right of the checkbox/dot
|
|
577
|
+
}, onMouseDown: e => e.stopPropagation(), children: hasCustomPicker ? (u(core.ContentSlot, { generatorName: 'colorPicker', generatorArgs: {
|
|
563
578
|
color: customColorPicker.currentColor,
|
|
564
579
|
onChange: (color) => {
|
|
565
580
|
setCustomColorPicker(prev => prev ? Object.assign(Object.assign({}, prev), { currentColor: color.hex }) : null);
|
|
@@ -576,17 +591,26 @@ const DefaultCalendarSidebar = ({ app, calendars, toggleCalendarVisibility, isCo
|
|
|
576
591
|
darkColors,
|
|
577
592
|
});
|
|
578
593
|
},
|
|
579
|
-
}, defaultContent: u(core.DefaultColorPicker, { color: customColorPicker.currentColor, onChange: (color, isPending) => {
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
594
|
+
}, defaultContent: u("div", { className: 'rounded-lg border border-gray-200 bg-white p-3 shadow-xl dark:border-gray-700 dark:bg-slate-900', children: u(core.DefaultColorPicker, { color: customColorPicker.currentColor, onChange: (color, isPending) => {
|
|
595
|
+
setCustomColorPicker(prev => prev ? Object.assign(Object.assign({}, prev), { currentColor: color.hex }) : null);
|
|
596
|
+
const { colors, darkColors } = core.getCalendarColorsForHex(color.hex);
|
|
597
|
+
app.updateCalendar(customColorPicker.calendarId, {
|
|
598
|
+
colors,
|
|
599
|
+
darkColors,
|
|
600
|
+
}, isPending);
|
|
601
|
+
}, onClose: () => {
|
|
602
|
+
app.updateCalendar(customColorPicker.calendarId, {});
|
|
603
|
+
setCustomColorPicker(null);
|
|
604
|
+
} }) }) })) : (u(core.BlossomColorPicker, { defaultValue: customColorPicker.initialColor, coreSize: 28, petalSize: 28, initialExpanded: true, adaptivePositioning: true, openOnHover: false, onChange: color => {
|
|
605
|
+
const { colors, darkColors } = core.getCalendarColorsForHex(color.hex);
|
|
606
|
+
app.updateCalendar(customColorPicker.calendarId, {
|
|
607
|
+
colors,
|
|
608
|
+
darkColors,
|
|
609
|
+
}, true);
|
|
610
|
+
}, onCollapse: () => {
|
|
611
|
+
app.updateCalendar(customColorPicker.calendarId, {});
|
|
612
|
+
setCustomColorPicker(null);
|
|
613
|
+
} })) }) }), document.body)] }));
|
|
590
614
|
};
|
|
591
615
|
|
|
592
616
|
const DEFAULT_SIDEBAR_WIDTH = '240px';
|
|
@@ -615,11 +639,9 @@ function createSidebarPlugin(config = {}) {
|
|
|
615
639
|
const refreshSidebar = hooks.useCallback(() => {
|
|
616
640
|
setSidebarVersion(prev => prev + 1);
|
|
617
641
|
}, []);
|
|
618
|
-
hooks.useEffect(() => {
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
});
|
|
622
|
-
}, [app, refreshSidebar]);
|
|
642
|
+
hooks.useEffect(() => app.subscribe(() => {
|
|
643
|
+
refreshSidebar();
|
|
644
|
+
}), [app, refreshSidebar]);
|
|
623
645
|
const calendars = hooks.useMemo(() => app.getCalendars(), [app, sidebarVersion]);
|
|
624
646
|
const handleToggleCalendarVisibility = hooks.useCallback((calendarId, visible) => {
|
|
625
647
|
app.setCalendarVisibility(calendarId, visible);
|
|
@@ -663,7 +685,6 @@ function createSidebarPlugin(config = {}) {
|
|
|
663
685
|
editingCalendarId,
|
|
664
686
|
setEditingCalendarId,
|
|
665
687
|
onCreateCalendar: handleCreateCalendar,
|
|
666
|
-
colorPickerMode: config.colorPickerMode,
|
|
667
688
|
}), [
|
|
668
689
|
app,
|
|
669
690
|
calendars,
|
|
@@ -675,14 +696,13 @@ function createSidebarPlugin(config = {}) {
|
|
|
675
696
|
config,
|
|
676
697
|
]);
|
|
677
698
|
const renderContent = () => {
|
|
678
|
-
var _a;
|
|
679
699
|
if (config.render) {
|
|
680
700
|
return preact.h(core.ContentSlot, {
|
|
681
701
|
generatorName: 'sidebar',
|
|
682
702
|
generatorArgs: sidebarProps,
|
|
683
703
|
});
|
|
684
704
|
}
|
|
685
|
-
return preact.h(DefaultCalendarSidebar, Object.assign(
|
|
705
|
+
return preact.h(DefaultCalendarSidebar, Object.assign({}, sidebarProps));
|
|
686
706
|
};
|
|
687
707
|
const renderExtraContent = () => {
|
|
688
708
|
if (!showCreateDialog)
|
|
@@ -696,7 +716,7 @@ function createSidebarPlugin(config = {}) {
|
|
|
696
716
|
const generatorArgs = {
|
|
697
717
|
onClose,
|
|
698
718
|
onCreate,
|
|
699
|
-
|
|
719
|
+
app,
|
|
700
720
|
};
|
|
701
721
|
return preact.h(core.ContentSlot, {
|
|
702
722
|
generatorName: 'createCalendarDialog',
|
|
@@ -704,7 +724,7 @@ function createSidebarPlugin(config = {}) {
|
|
|
704
724
|
defaultContent: preact.h(core.CreateCalendarDialog, {
|
|
705
725
|
onClose,
|
|
706
726
|
onCreate,
|
|
707
|
-
|
|
727
|
+
app,
|
|
708
728
|
}),
|
|
709
729
|
});
|
|
710
730
|
};
|
|
@@ -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,
|
|
3
|
+
declare const DefaultCalendarSidebar: ({ app, calendars, toggleCalendarVisibility, isCollapsed, setCollapsed, renderCalendarContextMenu, editingCalendarId: propEditingCalendarId, setEditingCalendarId: propSetEditingCalendarId, onCreateCalendar, }: 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:
|
|
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) =>
|
|
15
|
+
export declare const CalendarList: ({ calendars, onToggleVisibility, onReorder, onRename, onContextMenu, editingId, setEditingId, activeContextMenuCalendarId, isDraggable, isEditable, }: CalendarListProps) => JSX.Element;
|
|
15
16
|
export {};
|
package/dist/types/plugin.d.ts
CHANGED
|
@@ -12,14 +12,12 @@ export interface CalendarSidebarRenderProps {
|
|
|
12
12
|
editingCalendarId?: string | null;
|
|
13
13
|
setEditingCalendarId?: (id: string | null) => void;
|
|
14
14
|
onCreateCalendar?: () => void;
|
|
15
|
-
colorPickerMode?: 'default' | 'custom';
|
|
16
15
|
}
|
|
17
16
|
export interface SidebarPluginConfig {
|
|
18
17
|
width?: number | string;
|
|
19
18
|
miniWidth?: string;
|
|
20
19
|
initialCollapsed?: boolean;
|
|
21
20
|
createCalendarMode?: 'inline' | 'modal';
|
|
22
|
-
colorPickerMode?: 'default' | 'custom';
|
|
23
21
|
render?: (props: CalendarSidebarRenderProps) => TNode;
|
|
24
22
|
renderCalendarContextMenu?: (calendar: CalendarType, onClose: () => void) => TNode;
|
|
25
23
|
renderCreateCalendarDialog?: (props: CreateCalendarDialogProps) => TNode;
|
package/package.json
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dayflow/plugin-sidebar",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"type": "module",
|
|
3
|
+
"version": "1.1.1",
|
|
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.
|
|
42
|
-
"@dayflow/core": "3.1
|
|
39
|
+
"typescript": "^5.9.3",
|
|
40
|
+
"@dayflow/core": "3.2.1"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"@dayflow/core": "3.2.1"
|
|
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
|
}
|