@tuturuuu/ui 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +69 -0
- package/biome.json +1 -1
- package/package.json +74 -71
- package/src/components/ui/accordion.tsx +1 -1
- package/src/components/ui/breadcrumb.tsx +1 -1
- package/src/components/ui/calendar-app/calendar-page-shell.tsx +4 -0
- package/src/components/ui/calendar-app/components/calendar-connections-settings-content.tsx +239 -33
- package/src/components/ui/calendar-app/components/load-smart-scheduling-tasks.tsx +143 -0
- package/src/components/ui/calendar-app/components/priority-view.tsx +10 -3
- package/src/components/ui/calendar-app/components/tasks-sidebar.tsx +4 -116
- package/src/components/ui/calendar-app/components/use-calendar-connections-manager.ts +67 -2
- package/src/components/ui/calendar.tsx +1 -1
- package/src/components/ui/carousel.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-external-thread-panel.test.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-external-thread-panel.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-operations-panel.test.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-operations-panel.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-setup-panel.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-sidebar.test.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-sidebar.tsx +2 -2
- package/src/components/ui/chat/chat-agent-details-utils.test.ts +1 -1
- package/src/components/ui/chat/chat-agent-details-utils.tsx +1 -1
- package/src/components/ui/chat/chat-agent-details-zalo-personal-panel.tsx +2 -2
- package/src/components/ui/checkbox.tsx +1 -1
- package/src/components/ui/color-picker.tsx +1 -1
- package/src/components/ui/command.tsx +1 -1
- package/src/components/ui/context-menu.tsx +5 -1
- package/src/components/ui/custom/__tests__/settings-dialog-search.test.ts +78 -0
- package/src/components/ui/custom/__tests__/settings-dialog-shell-compile-graph.test.ts +76 -0
- package/src/components/ui/custom/__tests__/settings-dialog-shell.test.tsx +3 -0
- package/src/components/ui/custom/__tests__/workspace-select-helpers.test.ts +46 -1
- package/src/components/ui/custom/combobox.test.tsx +195 -0
- package/src/components/ui/custom/combobox.tsx +273 -156
- package/src/components/ui/custom/education/modules/youtube/delete-link-button.tsx +5 -13
- package/src/components/ui/custom/facebook-mockup/facebook-mockup.tsx +7 -1
- package/src/components/ui/custom/facebook-mockup/form.tsx +1 -1
- package/src/components/ui/custom/facebook-mockup/image-upload-field.tsx +1 -1
- package/src/components/ui/custom/facebook-mockup/preview.tsx +1 -1
- package/src/components/ui/custom/nav-link.test.tsx +165 -0
- package/src/components/ui/custom/nav-link.tsx +69 -11
- package/src/components/ui/custom/navigation.tsx +1 -0
- package/src/components/ui/custom/settings/task-settings.tsx +104 -0
- package/src/components/ui/custom/settings-dialog-search-loader.d.ts +5 -0
- package/src/components/ui/custom/settings-dialog-search-loader.js +3 -0
- package/src/components/ui/custom/settings-dialog-search.ts +75 -0
- package/src/components/ui/custom/settings-dialog-shell.tsx +65 -28
- package/src/components/ui/custom/theme-toggle.tsx +1 -1
- package/src/components/ui/custom/workspace-select-helpers.ts +23 -0
- package/src/components/ui/custom/workspace-select.tsx +25 -19
- package/src/components/ui/dialog.test.tsx +52 -0
- package/src/components/ui/dialog.tsx +6 -2
- package/src/components/ui/dropdown-menu.tsx +5 -1
- package/src/components/ui/finance/debts/debt-loan-form.tsx +12 -5
- package/src/components/ui/finance/debts/debt-loan-summary.tsx +3 -2
- package/src/components/ui/finance/debts/debts-page.test.tsx +54 -5
- package/src/components/ui/finance/debts/debts-page.tsx +15 -2
- package/src/components/ui/finance/invoices/components/subscription-group-selector.tsx +3 -5
- package/src/components/ui/finance/invoices/new-invoice-page.test.tsx +25 -5
- package/src/components/ui/finance/invoices/new-invoice-page.tsx +7 -2
- package/src/components/ui/finance/invoices/standard-invoice.tsx +4 -2
- package/src/components/ui/finance/invoices/subscription-invoice.tsx +4 -2
- package/src/components/ui/finance/invoices/utils.ts +3 -1
- package/src/components/ui/finance/transactions/form-content-dialog.tsx +3 -0
- package/src/components/ui/finance/transactions/form-types.ts +1 -0
- package/src/components/ui/finance/transactions/form.tsx +2 -0
- package/src/components/ui/finance/transactions/infinite-transactions-list.tsx +2 -0
- package/src/components/ui/finance/transactions/period-charts/category-breakdown-dialog.tsx +1 -1
- package/src/components/ui/finance/transactions/transaction-edit-dialog.tsx +1 -4
- package/src/components/ui/finance/transactions/transactions-create-summary.tsx +3 -0
- package/src/components/ui/finance/transactions/transactions-page.tsx +4 -1
- package/src/components/ui/finance/wallets/form.test.tsx +51 -3
- package/src/components/ui/finance/wallets/form.tsx +15 -4
- package/src/components/ui/finance/wallets/walletId/wallet-details-actions.tsx +4 -0
- package/src/components/ui/finance/wallets/walletId/wallet-details-page.tsx +4 -2
- package/src/components/ui/finance/wallets/wallets-data-table.tsx +1 -0
- package/src/components/ui/finance/wallets/wallets-page.tsx +5 -2
- package/src/components/ui/input-otp.tsx +1 -1
- package/src/components/ui/legacy/calendar/all-day-event-bar.tsx +28 -39
- package/src/components/ui/legacy/calendar/calendar-cell.tsx +2 -0
- package/src/components/ui/legacy/calendar/calendar-content.tsx +10 -6
- package/src/components/ui/legacy/calendar/calendar-header.tsx +23 -3
- package/src/components/ui/legacy/calendar/calendar-loading-skeleton.tsx +135 -0
- package/src/components/ui/legacy/calendar/calendar-matrix.tsx +175 -237
- package/src/components/ui/legacy/calendar/event-card.test.tsx +177 -0
- package/src/components/ui/legacy/calendar/event-card.tsx +220 -131
- package/src/components/ui/legacy/calendar/event-modal.tsx +17 -17
- package/src/components/ui/legacy/calendar/event-provider-display.tsx +69 -0
- package/src/components/ui/legacy/calendar/smart-calendar.test.tsx +86 -4
- package/src/components/ui/legacy/calendar/smart-calendar.tsx +32 -2
- package/src/components/ui/legacy/meet/create-plan-dialog.tsx +19 -10
- package/src/components/ui/navigation-menu.tsx +1 -1
- package/src/components/ui/pagination.tsx +1 -1
- package/src/components/ui/radio-group.tsx +1 -1
- package/src/components/ui/select.tsx +5 -1
- package/src/components/ui/sheet.tsx +1 -1
- package/src/components/ui/sidebar.tsx +1 -1
- package/src/components/ui/storefront/cart-popover.tsx +61 -0
- package/src/components/ui/storefront/cart-summary-parts.tsx +290 -0
- package/src/components/ui/storefront/cart-summary.tsx +93 -154
- package/src/components/ui/storefront/checkout-overlay.tsx +4 -5
- package/src/components/ui/storefront/listing-card.tsx +1 -1
- package/src/components/ui/storefront/merch-sections.tsx +70 -0
- package/src/components/ui/storefront/product-detail.tsx +1 -1
- package/src/components/ui/storefront/storefront-surface.test.tsx +106 -11
- package/src/components/ui/storefront/storefront-surface.tsx +101 -166
- package/src/components/ui/storefront/types.ts +4 -0
- package/src/components/ui/storefront/utils.ts +6 -0
- package/src/components/ui/text-editor/__tests__/extensions.test.ts +123 -0
- package/src/components/ui/text-editor/background-color-extension.ts +62 -0
- package/src/components/ui/text-editor/color-controls.tsx +284 -0
- package/src/components/ui/text-editor/editor.tsx +69 -14
- package/src/components/ui/text-editor/extensions.ts +8 -2
- package/src/components/ui/text-editor/highlight-extension.ts +22 -0
- package/src/components/ui/text-editor/tool-bar.tsx +9 -16
- package/src/components/ui/toast.tsx +1 -1
- package/src/components/ui/tu-do/boards/__tests__/board-share-dialog.test.tsx +286 -0
- package/src/components/ui/tu-do/boards/__tests__/task-board-form.test.tsx +12 -0
- package/src/components/ui/tu-do/boards/board-public-link-section.tsx +231 -0
- package/src/components/ui/tu-do/boards/board-share-dialog.tsx +15 -226
- package/src/components/ui/tu-do/boards/board-share-settings-panel.tsx +351 -0
- package/src/components/ui/tu-do/boards/boardId/board-column.tsx +121 -39
- package/src/components/ui/tu-do/boards/boardId/enhanced-task-list.tsx +7 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-clear-delete.ts +2 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-move.ts +5 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-updates.ts +3 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-operation-types.ts +3 -3
- package/src/components/ui/tu-do/boards/boardId/kanban/data/kanban-deadline-query.ts +50 -2
- package/src/components/ui/tu-do/boards/boardId/kanban/data/use-bulk-resources.ts +59 -5
- package/src/components/ui/tu-do/boards/boardId/kanban/dnd/__tests__/column-reorder.test.ts +17 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/dnd/column-reorder.ts +4 -1
- package/src/components/ui/tu-do/boards/boardId/kanban/dnd/drag-preview.tsx +20 -1
- package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-drag-cache.ts +38 -9
- package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-drag-order.ts +2 -8
- package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-sort-key.ts +47 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/dnd/use-kanban-dnd.ts +81 -30
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/__tests__/kanban-planner-island.test.tsx +380 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/kanban-planner-dialog.tsx +204 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-digest-panel.tsx +61 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-item-strip.tsx +54 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-plan-toolbar.tsx +251 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-scope-badge.tsx +27 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-section.tsx +58 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-share-dialog.tsx +238 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-target-controls.tsx +143 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-utils.ts +65 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/planner/use-kanban-planner-state.ts +234 -0
- package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.test.tsx +642 -5
- package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.tsx +224 -15
- package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-deadline-panels.tsx +535 -53
- package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-skeleton.tsx +101 -33
- package/src/components/ui/tu-do/boards/boardId/kanban.tsx +235 -113
- package/src/components/ui/tu-do/boards/boardId/task-board-server-page.test.tsx +50 -5
- package/src/components/ui/tu-do/boards/boardId/task-board-server-page.tsx +12 -2
- package/src/components/ui/tu-do/boards/boardId/task-card/measured-task-card.tsx +10 -1
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card-comparator.ts +3 -0
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.test.ts +20 -0
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.ts +10 -0
- package/src/components/ui/tu-do/boards/boardId/task-card/task-card.tsx +271 -36
- package/src/components/ui/tu-do/boards/boardId/task-filter.test.tsx +152 -0
- package/src/components/ui/tu-do/boards/boardId/task-filter.tsx +555 -545
- package/src/components/ui/tu-do/boards/boardId/task-list.tsx +22 -0
- package/src/components/ui/tu-do/boards/boardId/timeline/timeline-grid.tsx +9 -0
- package/src/components/ui/tu-do/boards/boardId/timeline/timeline-task-row.tsx +9 -0
- package/src/components/ui/tu-do/boards/boardId/timeline/timeline-toolbar.tsx +9 -0
- package/src/components/ui/tu-do/boards/boardId/timeline-board.tsx +35 -3
- package/src/components/ui/tu-do/boards/form.tsx +1 -1
- package/src/components/ui/tu-do/boards/share-section.tsx +100 -0
- package/src/components/ui/tu-do/drafts/draft-convert-dialog.tsx +10 -12
- package/src/components/ui/tu-do/drafts/drafts-page.tsx +33 -16
- package/src/components/ui/tu-do/hooks/__tests__/useTaskLabelManagement.test.tsx +48 -0
- package/src/components/ui/tu-do/hooks/__tests__/useTaskProjectManagement.test.tsx +144 -0
- package/src/components/ui/tu-do/hooks/useTaskDialog.ts +7 -0
- package/src/components/ui/tu-do/hooks/useTaskLabelManagement.ts +115 -106
- package/src/components/ui/tu-do/hooks/useTaskProjectManagement.ts +115 -122
- package/src/components/ui/tu-do/initiatives/task-initiatives-client.tsx +56 -88
- package/src/components/ui/tu-do/my-tasks/my-tasks-content.tsx +26 -2
- package/src/components/ui/tu-do/my-tasks/use-my-tasks-state.ts +55 -8
- package/src/components/ui/tu-do/notes/note-edit-dialog.tsx +1 -4
- package/src/components/ui/tu-do/progress/task-progress-import-panel.tsx +60 -0
- package/src/components/ui/tu-do/progress/task-progress-leaderboards-panel.tsx +156 -0
- package/src/components/ui/tu-do/progress/task-progress-page.tsx +348 -0
- package/src/components/ui/tu-do/progress/task-progress-panels.tsx +301 -0
- package/src/components/ui/tu-do/providers/task-dialog-provider.tsx +26 -0
- package/src/components/ui/tu-do/shared/__tests__/assignee-select.test.tsx +81 -10
- package/src/components/ui/tu-do/shared/__tests__/board-client.test.tsx +141 -1
- package/src/components/ui/tu-do/shared/__tests__/board-header.test.tsx +377 -36
- package/src/components/ui/tu-do/shared/__tests__/board-switcher.test.tsx +374 -0
- package/src/components/ui/tu-do/shared/__tests__/board-views.test.tsx +419 -5
- package/src/components/ui/tu-do/shared/__tests__/task-board-loading-state.test.tsx +38 -0
- package/src/components/ui/tu-do/shared/__tests__/task-cache-patches.test.ts +147 -0
- package/src/components/ui/tu-do/shared/__tests__/task-legacy-route-recovery.test.tsx +16 -0
- package/src/components/ui/tu-do/shared/__tests__/use-progressive-board-loader.test.tsx +3 -0
- package/src/components/ui/tu-do/shared/assignee-select.tsx +77 -26
- package/src/components/ui/tu-do/shared/board-client.tsx +15 -10
- package/src/components/ui/tu-do/shared/board-config-storage.ts +7 -1
- package/src/components/ui/tu-do/shared/board-header.tsx +471 -975
- package/src/components/ui/tu-do/shared/board-layout-settings.tsx +165 -136
- package/src/components/ui/tu-do/shared/board-switcher.tsx +244 -220
- package/src/components/ui/tu-do/shared/board-user-presence-avatars.tsx +18 -12
- package/src/components/ui/tu-do/shared/board-views.tsx +577 -85
- package/src/components/ui/tu-do/shared/list-view.tsx +246 -2
- package/src/components/ui/tu-do/shared/recycle-bin-panel.tsx +142 -94
- package/src/components/ui/tu-do/shared/special-task-list-pins.ts +51 -0
- package/src/components/ui/tu-do/shared/task-board-loading-state.tsx +28 -0
- package/src/components/ui/tu-do/shared/task-cache-patches.ts +394 -0
- package/src/components/ui/tu-do/shared/task-dialog-manager.tsx +21 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/components/quick-settings-popover.tsx +5 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/components/task-dialog-header.tsx +25 -2
- package/src/components/ui/tu-do/shared/task-edit-dialog/components/task-list-selector.tsx +7 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/field-diff-viewer.tsx +3 -2
- package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-data.ts +79 -10
- package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-mutations.ts +76 -77
- package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-relationships.test.tsx +63 -0
- package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-relationships.ts +78 -69
- package/src/components/ui/tu-do/shared/task-edit-dialog/personal-overrides-section.tsx +28 -8
- package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/dependencies-section.tsx +14 -3
- package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/parent-section.tsx +6 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/related-section.tsx +6 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/subtasks-section.tsx +6 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/types/task-relationships.types.ts +8 -0
- package/src/components/ui/tu-do/shared/task-edit-dialog/selective-revert-panel.test.tsx +91 -0
- package/src/components/ui/tu-do/shared/task-edit-dialog/selective-revert-panel.tsx +123 -78
- package/src/components/ui/tu-do/shared/task-edit-dialog/task-activity-section.tsx +7 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/task-dialog-actions.tsx +8 -1
- package/src/components/ui/tu-do/shared/task-edit-dialog/task-properties-section.test.tsx +150 -0
- package/src/components/ui/tu-do/shared/task-edit-dialog/task-properties-section.tsx +61 -35
- package/src/components/ui/tu-do/shared/task-edit-dialog/task-relationships-properties.tsx +44 -2
- package/src/components/ui/tu-do/shared/task-edit-dialog/task-snapshot-dialog.tsx +8 -3
- package/src/components/ui/tu-do/shared/task-edit-dialog.tsx +11 -1
- package/src/components/ui/tu-do/shared/task-legacy-route-recovery.tsx +2 -9
- package/src/components/ui/tu-do/shared/task-row-actions-menu.tsx +11 -0
- package/src/components/ui/tu-do/shared/use-progressive-board-loader.ts +2 -0
- package/src/declarations.d.ts +1 -0
- package/src/hooks/__tests__/use-calendar-readonly.test.tsx +322 -2
- package/src/hooks/__tests__/use-calendar-sync.test.tsx +446 -0
- package/src/hooks/__tests__/useBoardPresence.test.tsx +191 -0
- package/src/hooks/__tests__/useBoardRealtime.test.tsx +24 -144
- package/src/hooks/use-calendar-sync.tsx +247 -243
- package/src/hooks/use-calendar.tsx +323 -138
- package/src/hooks/use-task-actions.ts +24 -0
- package/src/hooks/use-user-workspace-config.ts +75 -0
- package/src/hooks/use-workspace-currency.ts +8 -3
- package/src/hooks/useBoardPresence.ts +364 -0
- package/src/hooks/useBoardRealtimeEventHandler.ts +45 -90
- package/src/lib/workspace-actions.ts +2 -6
|
@@ -9,9 +9,9 @@ import isBetween from 'dayjs/plugin/isBetween';
|
|
|
9
9
|
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
|
|
10
10
|
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
|
|
11
11
|
import timezone from 'dayjs/plugin/timezone';
|
|
12
|
-
import Image from 'next/image';
|
|
13
12
|
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
|
14
13
|
import { MIN_COLUMN_WIDTH } from './config';
|
|
14
|
+
import { CalendarEventProviderIcon } from './event-provider-display';
|
|
15
15
|
import { getLocationType, LocationTimeline } from './location-timeline';
|
|
16
16
|
import { useCalendarSettings } from './settings/settings-context';
|
|
17
17
|
|
|
@@ -68,18 +68,10 @@ interface DragState {
|
|
|
68
68
|
// 1. Extract EventContent component for shared rendering
|
|
69
69
|
const EventContent = ({ event }: { event: CalendarEvent }) => (
|
|
70
70
|
<>
|
|
71
|
-
|
|
72
|
-
event
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
alt="Google Calendar"
|
|
76
|
-
className="mr-1 inline-block h-[1.25em] w-[1.25em] align-middle opacity-80 dark:opacity-90"
|
|
77
|
-
title="Synced from Google Calendar"
|
|
78
|
-
data-testid="google-calendar-logo"
|
|
79
|
-
width={18}
|
|
80
|
-
height={18}
|
|
81
|
-
/>
|
|
82
|
-
)}
|
|
71
|
+
<CalendarEventProviderIcon
|
|
72
|
+
event={event}
|
|
73
|
+
className="mr-1 h-[1.25em] w-[1.25em] opacity-80 dark:opacity-90"
|
|
74
|
+
/>
|
|
83
75
|
<span className="truncate">{event.title}</span>
|
|
84
76
|
</>
|
|
85
77
|
);
|
|
@@ -342,27 +334,6 @@ export const AllDayEventBar = ({ dates }: { dates: Date[] }) => {
|
|
|
342
334
|
eventStart.isBefore(lastVisibleDate.add(1, 'day'), 'day') &&
|
|
343
335
|
eventEnd.isAfter(firstVisibleDate, 'day');
|
|
344
336
|
|
|
345
|
-
// Debug logging for multi-day events
|
|
346
|
-
const eventDurationDays = eventEnd.diff(eventStart, 'day');
|
|
347
|
-
if (eventDurationDays > 0) {
|
|
348
|
-
console.log('Multi-day event processing:', {
|
|
349
|
-
title: event.title,
|
|
350
|
-
eventStart: eventStart.format('YYYY-MM-DD'),
|
|
351
|
-
eventEnd: eventEnd.format('YYYY-MM-DD'),
|
|
352
|
-
durationDays: eventDurationDays,
|
|
353
|
-
isActuallyMultiDay: eventDurationDays > 1,
|
|
354
|
-
firstVisibleDate: firstVisibleDate.format('YYYY-MM-DD'),
|
|
355
|
-
lastVisibleDate: lastVisibleDate.format('YYYY-MM-DD'),
|
|
356
|
-
eventOverlaps,
|
|
357
|
-
wouldShowCutOffStart:
|
|
358
|
-
eventDurationDays > 1 &&
|
|
359
|
-
eventStart.isBefore(firstVisibleDate, 'day'),
|
|
360
|
-
wouldShowCutOffEnd:
|
|
361
|
-
eventDurationDays > 1 &&
|
|
362
|
-
eventEnd.isAfter(lastVisibleDate.add(1, 'day'), 'day'),
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
|
|
366
337
|
if (!eventOverlaps) {
|
|
367
338
|
return; // Skip this event if it doesn't overlap with visible dates
|
|
368
339
|
}
|
|
@@ -680,7 +651,13 @@ export const AllDayEventBar = ({ dates }: { dates: Date[] }) => {
|
|
|
680
651
|
};
|
|
681
652
|
|
|
682
653
|
// Calculate dynamic height based on visible events
|
|
683
|
-
const
|
|
654
|
+
const locationTopOffset =
|
|
655
|
+
locationSpans.length > 0 ? LOCATION_TIMELINE_HEIGHT_REM : 0;
|
|
656
|
+
const regularRowsHeight =
|
|
657
|
+
eventLayout.maxVisibleEventsPerDay > 0
|
|
658
|
+
? eventLayout.maxVisibleEventsPerDay * 1.75
|
|
659
|
+
: 0;
|
|
660
|
+
const barHeight = Math.max(1.9, locationTopOffset + regularRowsHeight);
|
|
684
661
|
|
|
685
662
|
// Enhanced mouse and touch handlers
|
|
686
663
|
const handleEventMouseDown = (e: React.MouseEvent, eventSpan: EventSpan) => {
|
|
@@ -839,7 +816,7 @@ export const AllDayEventBar = ({ dates }: { dates: Date[] }) => {
|
|
|
839
816
|
onClick={() => toggleDateExpansion(dateKey)}
|
|
840
817
|
style={{
|
|
841
818
|
position: 'absolute',
|
|
842
|
-
top: `${MAX_EVENTS_DISPLAY * 1.7}rem`,
|
|
819
|
+
top: `${locationTopOffset + MAX_EVENTS_DISPLAY * 1.7}rem`,
|
|
843
820
|
left: `${(dateIndex * 100) / visibleDates.length}%`,
|
|
844
821
|
width: `${100 / visibleDates.length}%`,
|
|
845
822
|
zIndex: 10,
|
|
@@ -858,7 +835,7 @@ export const AllDayEventBar = ({ dates }: { dates: Date[] }) => {
|
|
|
858
835
|
onClick={() => toggleDateExpansion(dateKey)}
|
|
859
836
|
style={{
|
|
860
837
|
position: 'absolute',
|
|
861
|
-
top: `${dateEvents.length * 1.7}rem`,
|
|
838
|
+
top: `${locationTopOffset + dateEvents.length * 1.7}rem`,
|
|
862
839
|
left: `${(dateIndex * 100) / visibleDates.length}%`,
|
|
863
840
|
width: `${100 / visibleDates.length}%`,
|
|
864
841
|
zIndex: 10,
|
|
@@ -941,8 +918,18 @@ export const AllDayEventBar = ({ dates }: { dates: Date[] }) => {
|
|
|
941
918
|
dragState.isDragging && dragState.draggedEvent?.id === event.id;
|
|
942
919
|
|
|
943
920
|
// Calculate top offset based on location strip presence
|
|
944
|
-
const topOffset =
|
|
945
|
-
|
|
921
|
+
const topOffset = locationTopOffset;
|
|
922
|
+
const optimisticStatus = (
|
|
923
|
+
event as CalendarEvent & {
|
|
924
|
+
_optimisticStatus?:
|
|
925
|
+
| 'creating'
|
|
926
|
+
| 'updating'
|
|
927
|
+
| 'deleting'
|
|
928
|
+
| 'error';
|
|
929
|
+
}
|
|
930
|
+
)._optimisticStatus;
|
|
931
|
+
const isPendingMutation =
|
|
932
|
+
optimisticStatus === 'updating' || optimisticStatus === 'deleting';
|
|
946
933
|
|
|
947
934
|
return (
|
|
948
935
|
<div
|
|
@@ -959,6 +946,8 @@ export const AllDayEventBar = ({ dates }: { dates: Date[] }) => {
|
|
|
959
946
|
bg,
|
|
960
947
|
border,
|
|
961
948
|
text,
|
|
949
|
+
isPendingMutation &&
|
|
950
|
+
'opacity-60 outline outline-dashed outline-1 outline-primary/50',
|
|
962
951
|
// Special styling for cut-off events
|
|
963
952
|
(isCutOffStart || isCutOffEnd) && 'border-dashed'
|
|
964
953
|
)}
|
|
@@ -880,6 +880,8 @@ export const CalendarCell = ({ date, hour }: CalendarCellProps) => {
|
|
|
880
880
|
height: `${HOUR_HEIGHT}px`,
|
|
881
881
|
}}
|
|
882
882
|
onContextMenu={(e) => {
|
|
883
|
+
const target = e.target as HTMLElement | null;
|
|
884
|
+
if (target?.closest('[data-slot="context-menu-trigger"]')) return;
|
|
883
885
|
e.preventDefault();
|
|
884
886
|
}}
|
|
885
887
|
onMouseEnter={() => setIsHovering(true)}
|
|
@@ -9,6 +9,7 @@ import { cn } from '@tuturuuu/utils/format';
|
|
|
9
9
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
10
10
|
import { AgendaView } from './agenda-view';
|
|
11
11
|
import { CalendarHeader } from './calendar-header';
|
|
12
|
+
import { CalendarLoadingSkeleton } from './calendar-loading-skeleton';
|
|
12
13
|
import { CalendarViewWithTrail } from './calendar-view-with-trail';
|
|
13
14
|
import { EventModal } from './event-modal';
|
|
14
15
|
import { EventPreviewPopover } from './event-preview-popover';
|
|
@@ -102,6 +103,7 @@ export const CalendarContent = ({
|
|
|
102
103
|
externalState,
|
|
103
104
|
extras,
|
|
104
105
|
overlay,
|
|
106
|
+
disableBuiltInEventUi,
|
|
105
107
|
}: {
|
|
106
108
|
t: any;
|
|
107
109
|
locale: string;
|
|
@@ -118,10 +120,11 @@ export const CalendarContent = ({
|
|
|
118
120
|
};
|
|
119
121
|
extras?: React.ReactNode;
|
|
120
122
|
overlay?: React.ReactNode;
|
|
123
|
+
disableBuiltInEventUi?: boolean;
|
|
121
124
|
}) => {
|
|
122
125
|
const { transition } = useViewTransition();
|
|
123
126
|
const { settings } = useCalendarSettings();
|
|
124
|
-
const { dates, setDates } = useCalendarSync();
|
|
127
|
+
const { dates, isLoading, setDates } = useCalendarSync();
|
|
125
128
|
|
|
126
129
|
// Use ref to always have the latest settings without causing dependency cascades
|
|
127
130
|
const settingsRef = useRef(settings);
|
|
@@ -191,7 +194,6 @@ export const CalendarContent = ({
|
|
|
191
194
|
handleSetView('4-days');
|
|
192
195
|
setDates(dates);
|
|
193
196
|
});
|
|
194
|
-
console.log('enable4DayView', dates);
|
|
195
197
|
}, [date, transition, handleSetView, setDates]);
|
|
196
198
|
|
|
197
199
|
const enableWeekView = useCallback(() => {
|
|
@@ -578,7 +580,7 @@ export const CalendarContent = ({
|
|
|
578
580
|
return (
|
|
579
581
|
<div
|
|
580
582
|
className={cn(
|
|
581
|
-
'grid h-full w-full',
|
|
583
|
+
'grid h-full min-h-0 w-full',
|
|
582
584
|
view === 'month' || view === 'year'
|
|
583
585
|
? 'grid-rows-[auto_1fr]'
|
|
584
586
|
: 'grid-rows-[auto_auto_1fr]'
|
|
@@ -621,7 +623,7 @@ export const CalendarContent = ({
|
|
|
621
623
|
|
|
622
624
|
<div
|
|
623
625
|
className={cn(
|
|
624
|
-
'scrollbar-none relative flex-1 overflow-auto rounded-lg focus:outline-none',
|
|
626
|
+
'scrollbar-none relative min-h-0 flex-1 overflow-auto rounded-lg focus:outline-none',
|
|
625
627
|
view === 'agenda' ||
|
|
626
628
|
view === 'month' ||
|
|
627
629
|
view === 'year' ||
|
|
@@ -632,7 +634,9 @@ export const CalendarContent = ({
|
|
|
632
634
|
e.currentTarget.focus();
|
|
633
635
|
}}
|
|
634
636
|
>
|
|
635
|
-
{
|
|
637
|
+
{isLoading ? (
|
|
638
|
+
<CalendarLoadingSkeleton dates={dates} view={view} />
|
|
639
|
+
) : view === 'month' && dates?.[0] ? (
|
|
636
640
|
<MonthCalendar
|
|
637
641
|
date={dates[0]}
|
|
638
642
|
workspace={workspace}
|
|
@@ -665,7 +669,7 @@ export const CalendarContent = ({
|
|
|
665
669
|
)}
|
|
666
670
|
</div>
|
|
667
671
|
|
|
668
|
-
{disabled
|
|
672
|
+
{disabled || disableBuiltInEventUi
|
|
669
673
|
? null
|
|
670
674
|
: workspace && (
|
|
671
675
|
<>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AlertTriangle,
|
|
2
3
|
CalendarIcon,
|
|
4
|
+
Check,
|
|
3
5
|
ChevronLeft,
|
|
4
6
|
ChevronRight,
|
|
5
7
|
Moon,
|
|
@@ -81,7 +83,7 @@ export function CalendarHeader({
|
|
|
81
83
|
return newDate;
|
|
82
84
|
});
|
|
83
85
|
|
|
84
|
-
const {
|
|
86
|
+
const { syncStatus } = useCalendarSync();
|
|
85
87
|
const selectToday = () => setDate(new Date());
|
|
86
88
|
const isTodaySelected = () => dayjs(date).isSame(dayjs(), 'day');
|
|
87
89
|
const isCurrentMonth = () =>
|
|
@@ -112,6 +114,14 @@ export function CalendarHeader({
|
|
|
112
114
|
};
|
|
113
115
|
|
|
114
116
|
const LunarIcon = showLunar ? MoonStar : Moon;
|
|
117
|
+
const statusLabel =
|
|
118
|
+
syncStatus.state === 'error'
|
|
119
|
+
? t('failed_to_load_events')
|
|
120
|
+
: syncStatus.lastSyncTime
|
|
121
|
+
? `${t('sync_completed')} ${dayjs(syncStatus.lastSyncTime)
|
|
122
|
+
.locale(locale)
|
|
123
|
+
.format('HH:mm')}`
|
|
124
|
+
: null;
|
|
115
125
|
|
|
116
126
|
return (
|
|
117
127
|
<div className="mb-2 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
|
|
@@ -121,8 +131,18 @@ export function CalendarHeader({
|
|
|
121
131
|
</div>
|
|
122
132
|
<div className="flex flex-col gap-2 md:flex-row md:items-center">
|
|
123
133
|
<div className="flex items-center gap-2">
|
|
124
|
-
{
|
|
125
|
-
<div
|
|
134
|
+
{statusLabel && (
|
|
135
|
+
<div
|
|
136
|
+
aria-live="polite"
|
|
137
|
+
className="hidden min-w-0 items-center gap-1.5 rounded-full border bg-background/80 px-2 py-1 text-muted-foreground text-xs shadow-xs sm:inline-flex"
|
|
138
|
+
>
|
|
139
|
+
{syncStatus.state === 'error' ? (
|
|
140
|
+
<AlertTriangle className="h-3.5 w-3.5 text-dynamic-red" />
|
|
141
|
+
) : (
|
|
142
|
+
<Check className="h-3.5 w-3.5 text-dynamic-green" />
|
|
143
|
+
)}
|
|
144
|
+
<span className="truncate">{statusLabel}</span>
|
|
145
|
+
</div>
|
|
126
146
|
)}
|
|
127
147
|
<div className="flex flex-none items-center justify-center gap-2 md:justify-start">
|
|
128
148
|
<Button
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { cn } from '@tuturuuu/utils/format';
|
|
2
|
+
import type { CalendarView } from '../../../../hooks/use-view-transition';
|
|
3
|
+
import { Skeleton } from '../../skeleton';
|
|
4
|
+
import { DAY_HEIGHT, HOUR_HEIGHT, MIN_COLUMN_WIDTH } from './config';
|
|
5
|
+
|
|
6
|
+
function TimedCalendarSkeleton({ columns }: { columns: number }) {
|
|
7
|
+
const eventPlaceholders = [
|
|
8
|
+
{ column: 0, hour: 2.2, span: 1.4, width: 0.82 },
|
|
9
|
+
{ column: Math.min(1, columns - 1), hour: 5.1, span: 1.1, width: 0.74 },
|
|
10
|
+
{
|
|
11
|
+
column: Math.max(0, columns - 2),
|
|
12
|
+
hour: 8.4,
|
|
13
|
+
span: 1.8,
|
|
14
|
+
width: 0.78,
|
|
15
|
+
},
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div
|
|
20
|
+
className="flex h-full overflow-hidden rounded-b-lg border-border border-b border-l bg-background/50 text-center dark:border-zinc-800"
|
|
21
|
+
style={{ minWidth: `${columns * MIN_COLUMN_WIDTH}px` }}
|
|
22
|
+
aria-hidden="true"
|
|
23
|
+
>
|
|
24
|
+
<div className="w-16 shrink-0 border-r bg-muted/20">
|
|
25
|
+
{Array.from({ length: 8 }).map((_, index) => (
|
|
26
|
+
<Skeleton key={index} className="mx-auto mt-7 h-3 w-9 rounded-sm" />
|
|
27
|
+
))}
|
|
28
|
+
</div>
|
|
29
|
+
<div
|
|
30
|
+
className="relative grid flex-1"
|
|
31
|
+
style={{
|
|
32
|
+
gridTemplateColumns: `repeat(${columns}, minmax(${MIN_COLUMN_WIDTH}px, 1fr))`,
|
|
33
|
+
height: `${DAY_HEIGHT}px`,
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
{Array.from({ length: columns }).map((_, index) => (
|
|
37
|
+
<div
|
|
38
|
+
key={index}
|
|
39
|
+
className="relative border-border/70 border-r last:border-r-0"
|
|
40
|
+
>
|
|
41
|
+
{Array.from({ length: 24 }).map((_, hour) => (
|
|
42
|
+
<div
|
|
43
|
+
key={hour}
|
|
44
|
+
className="border-border/50 border-b"
|
|
45
|
+
style={{ height: `${HOUR_HEIGHT}px` }}
|
|
46
|
+
/>
|
|
47
|
+
))}
|
|
48
|
+
</div>
|
|
49
|
+
))}
|
|
50
|
+
{eventPlaceholders.map((placeholder, index) => (
|
|
51
|
+
<Skeleton
|
|
52
|
+
key={index}
|
|
53
|
+
className="absolute rounded-md"
|
|
54
|
+
style={{
|
|
55
|
+
left: `calc(${(placeholder.column * 100) / columns}% + 6px)`,
|
|
56
|
+
top: `${placeholder.hour * HOUR_HEIGHT}px`,
|
|
57
|
+
width: `calc(${(placeholder.width * 100) / columns}% - 12px)`,
|
|
58
|
+
height: `${placeholder.span * HOUR_HEIGHT}px`,
|
|
59
|
+
}}
|
|
60
|
+
/>
|
|
61
|
+
))}
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function MonthCalendarSkeleton({ columns }: { columns: number }) {
|
|
68
|
+
return (
|
|
69
|
+
<div
|
|
70
|
+
className="grid h-full min-h-[28rem] gap-px overflow-hidden rounded-lg border bg-border"
|
|
71
|
+
style={{ gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))` }}
|
|
72
|
+
aria-hidden="true"
|
|
73
|
+
>
|
|
74
|
+
{Array.from({ length: columns * 5 }).map((_, index) => (
|
|
75
|
+
<div key={index} className="space-y-2 bg-background p-2">
|
|
76
|
+
<Skeleton className="h-3 w-8 rounded-sm" />
|
|
77
|
+
<Skeleton className="h-4 w-4/5 rounded-sm" />
|
|
78
|
+
<Skeleton className="h-4 w-3/5 rounded-sm" />
|
|
79
|
+
</div>
|
|
80
|
+
))}
|
|
81
|
+
</div>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function AgendaCalendarSkeleton() {
|
|
86
|
+
return (
|
|
87
|
+
<div className="space-y-3 rounded-lg border bg-background p-4" aria-hidden>
|
|
88
|
+
{Array.from({ length: 6 }).map((_, index) => (
|
|
89
|
+
<div key={index} className="flex items-center gap-3">
|
|
90
|
+
<Skeleton className="h-10 w-14 rounded-md" />
|
|
91
|
+
<div className="min-w-0 flex-1 space-y-2">
|
|
92
|
+
<Skeleton className="h-4 w-2/5 rounded-sm" />
|
|
93
|
+
<Skeleton className="h-3 w-3/5 rounded-sm" />
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
))}
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function CalendarLoadingSkeleton({
|
|
102
|
+
dates,
|
|
103
|
+
view,
|
|
104
|
+
}: {
|
|
105
|
+
dates: Date[];
|
|
106
|
+
view: CalendarView;
|
|
107
|
+
}) {
|
|
108
|
+
const columns = Math.max(1, dates.length || (view === 'day' ? 1 : 7));
|
|
109
|
+
|
|
110
|
+
if (view === 'month' || view === 'year') {
|
|
111
|
+
return <MonthCalendarSkeleton columns={view === 'year' ? 4 : 7} />;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (view === 'agenda') return <AgendaCalendarSkeleton />;
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<div className="h-full min-h-0 space-y-2" aria-busy="true">
|
|
118
|
+
<div
|
|
119
|
+
className={cn(
|
|
120
|
+
'grid rounded-lg border bg-background/70 p-2',
|
|
121
|
+
columns === 1 && 'max-w-lg'
|
|
122
|
+
)}
|
|
123
|
+
style={{
|
|
124
|
+
gridTemplateColumns: `4rem repeat(${columns}, minmax(${MIN_COLUMN_WIDTH}px, 1fr))`,
|
|
125
|
+
}}
|
|
126
|
+
>
|
|
127
|
+
<Skeleton className="h-5 w-5 self-center justify-self-center rounded-sm" />
|
|
128
|
+
{Array.from({ length: columns }).map((_, index) => (
|
|
129
|
+
<Skeleton key={index} className="mx-1 h-5 rounded-sm" />
|
|
130
|
+
))}
|
|
131
|
+
</div>
|
|
132
|
+
<TimedCalendarSkeleton columns={columns} />
|
|
133
|
+
</div>
|
|
134
|
+
);
|
|
135
|
+
}
|