@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.
Files changed (245) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/biome.json +1 -1
  3. package/package.json +74 -71
  4. package/src/components/ui/accordion.tsx +1 -1
  5. package/src/components/ui/breadcrumb.tsx +1 -1
  6. package/src/components/ui/calendar-app/calendar-page-shell.tsx +4 -0
  7. package/src/components/ui/calendar-app/components/calendar-connections-settings-content.tsx +239 -33
  8. package/src/components/ui/calendar-app/components/load-smart-scheduling-tasks.tsx +143 -0
  9. package/src/components/ui/calendar-app/components/priority-view.tsx +10 -3
  10. package/src/components/ui/calendar-app/components/tasks-sidebar.tsx +4 -116
  11. package/src/components/ui/calendar-app/components/use-calendar-connections-manager.ts +67 -2
  12. package/src/components/ui/calendar.tsx +1 -1
  13. package/src/components/ui/carousel.tsx +1 -1
  14. package/src/components/ui/chat/chat-agent-details-external-thread-panel.test.tsx +1 -1
  15. package/src/components/ui/chat/chat-agent-details-external-thread-panel.tsx +1 -1
  16. package/src/components/ui/chat/chat-agent-details-operations-panel.test.tsx +1 -1
  17. package/src/components/ui/chat/chat-agent-details-operations-panel.tsx +1 -1
  18. package/src/components/ui/chat/chat-agent-details-setup-panel.tsx +1 -1
  19. package/src/components/ui/chat/chat-agent-details-sidebar.test.tsx +1 -1
  20. package/src/components/ui/chat/chat-agent-details-sidebar.tsx +2 -2
  21. package/src/components/ui/chat/chat-agent-details-utils.test.ts +1 -1
  22. package/src/components/ui/chat/chat-agent-details-utils.tsx +1 -1
  23. package/src/components/ui/chat/chat-agent-details-zalo-personal-panel.tsx +2 -2
  24. package/src/components/ui/checkbox.tsx +1 -1
  25. package/src/components/ui/color-picker.tsx +1 -1
  26. package/src/components/ui/command.tsx +1 -1
  27. package/src/components/ui/context-menu.tsx +5 -1
  28. package/src/components/ui/custom/__tests__/settings-dialog-search.test.ts +78 -0
  29. package/src/components/ui/custom/__tests__/settings-dialog-shell-compile-graph.test.ts +76 -0
  30. package/src/components/ui/custom/__tests__/settings-dialog-shell.test.tsx +3 -0
  31. package/src/components/ui/custom/__tests__/workspace-select-helpers.test.ts +46 -1
  32. package/src/components/ui/custom/combobox.test.tsx +195 -0
  33. package/src/components/ui/custom/combobox.tsx +273 -156
  34. package/src/components/ui/custom/education/modules/youtube/delete-link-button.tsx +5 -13
  35. package/src/components/ui/custom/facebook-mockup/facebook-mockup.tsx +7 -1
  36. package/src/components/ui/custom/facebook-mockup/form.tsx +1 -1
  37. package/src/components/ui/custom/facebook-mockup/image-upload-field.tsx +1 -1
  38. package/src/components/ui/custom/facebook-mockup/preview.tsx +1 -1
  39. package/src/components/ui/custom/nav-link.test.tsx +165 -0
  40. package/src/components/ui/custom/nav-link.tsx +69 -11
  41. package/src/components/ui/custom/navigation.tsx +1 -0
  42. package/src/components/ui/custom/settings/task-settings.tsx +104 -0
  43. package/src/components/ui/custom/settings-dialog-search-loader.d.ts +5 -0
  44. package/src/components/ui/custom/settings-dialog-search-loader.js +3 -0
  45. package/src/components/ui/custom/settings-dialog-search.ts +75 -0
  46. package/src/components/ui/custom/settings-dialog-shell.tsx +65 -28
  47. package/src/components/ui/custom/theme-toggle.tsx +1 -1
  48. package/src/components/ui/custom/workspace-select-helpers.ts +23 -0
  49. package/src/components/ui/custom/workspace-select.tsx +25 -19
  50. package/src/components/ui/dialog.test.tsx +52 -0
  51. package/src/components/ui/dialog.tsx +6 -2
  52. package/src/components/ui/dropdown-menu.tsx +5 -1
  53. package/src/components/ui/finance/debts/debt-loan-form.tsx +12 -5
  54. package/src/components/ui/finance/debts/debt-loan-summary.tsx +3 -2
  55. package/src/components/ui/finance/debts/debts-page.test.tsx +54 -5
  56. package/src/components/ui/finance/debts/debts-page.tsx +15 -2
  57. package/src/components/ui/finance/invoices/components/subscription-group-selector.tsx +3 -5
  58. package/src/components/ui/finance/invoices/new-invoice-page.test.tsx +25 -5
  59. package/src/components/ui/finance/invoices/new-invoice-page.tsx +7 -2
  60. package/src/components/ui/finance/invoices/standard-invoice.tsx +4 -2
  61. package/src/components/ui/finance/invoices/subscription-invoice.tsx +4 -2
  62. package/src/components/ui/finance/invoices/utils.ts +3 -1
  63. package/src/components/ui/finance/transactions/form-content-dialog.tsx +3 -0
  64. package/src/components/ui/finance/transactions/form-types.ts +1 -0
  65. package/src/components/ui/finance/transactions/form.tsx +2 -0
  66. package/src/components/ui/finance/transactions/infinite-transactions-list.tsx +2 -0
  67. package/src/components/ui/finance/transactions/period-charts/category-breakdown-dialog.tsx +1 -1
  68. package/src/components/ui/finance/transactions/transaction-edit-dialog.tsx +1 -4
  69. package/src/components/ui/finance/transactions/transactions-create-summary.tsx +3 -0
  70. package/src/components/ui/finance/transactions/transactions-page.tsx +4 -1
  71. package/src/components/ui/finance/wallets/form.test.tsx +51 -3
  72. package/src/components/ui/finance/wallets/form.tsx +15 -4
  73. package/src/components/ui/finance/wallets/walletId/wallet-details-actions.tsx +4 -0
  74. package/src/components/ui/finance/wallets/walletId/wallet-details-page.tsx +4 -2
  75. package/src/components/ui/finance/wallets/wallets-data-table.tsx +1 -0
  76. package/src/components/ui/finance/wallets/wallets-page.tsx +5 -2
  77. package/src/components/ui/input-otp.tsx +1 -1
  78. package/src/components/ui/legacy/calendar/all-day-event-bar.tsx +28 -39
  79. package/src/components/ui/legacy/calendar/calendar-cell.tsx +2 -0
  80. package/src/components/ui/legacy/calendar/calendar-content.tsx +10 -6
  81. package/src/components/ui/legacy/calendar/calendar-header.tsx +23 -3
  82. package/src/components/ui/legacy/calendar/calendar-loading-skeleton.tsx +135 -0
  83. package/src/components/ui/legacy/calendar/calendar-matrix.tsx +175 -237
  84. package/src/components/ui/legacy/calendar/event-card.test.tsx +177 -0
  85. package/src/components/ui/legacy/calendar/event-card.tsx +220 -131
  86. package/src/components/ui/legacy/calendar/event-modal.tsx +17 -17
  87. package/src/components/ui/legacy/calendar/event-provider-display.tsx +69 -0
  88. package/src/components/ui/legacy/calendar/smart-calendar.test.tsx +86 -4
  89. package/src/components/ui/legacy/calendar/smart-calendar.tsx +32 -2
  90. package/src/components/ui/legacy/meet/create-plan-dialog.tsx +19 -10
  91. package/src/components/ui/navigation-menu.tsx +1 -1
  92. package/src/components/ui/pagination.tsx +1 -1
  93. package/src/components/ui/radio-group.tsx +1 -1
  94. package/src/components/ui/select.tsx +5 -1
  95. package/src/components/ui/sheet.tsx +1 -1
  96. package/src/components/ui/sidebar.tsx +1 -1
  97. package/src/components/ui/storefront/cart-popover.tsx +61 -0
  98. package/src/components/ui/storefront/cart-summary-parts.tsx +290 -0
  99. package/src/components/ui/storefront/cart-summary.tsx +93 -154
  100. package/src/components/ui/storefront/checkout-overlay.tsx +4 -5
  101. package/src/components/ui/storefront/listing-card.tsx +1 -1
  102. package/src/components/ui/storefront/merch-sections.tsx +70 -0
  103. package/src/components/ui/storefront/product-detail.tsx +1 -1
  104. package/src/components/ui/storefront/storefront-surface.test.tsx +106 -11
  105. package/src/components/ui/storefront/storefront-surface.tsx +101 -166
  106. package/src/components/ui/storefront/types.ts +4 -0
  107. package/src/components/ui/storefront/utils.ts +6 -0
  108. package/src/components/ui/text-editor/__tests__/extensions.test.ts +123 -0
  109. package/src/components/ui/text-editor/background-color-extension.ts +62 -0
  110. package/src/components/ui/text-editor/color-controls.tsx +284 -0
  111. package/src/components/ui/text-editor/editor.tsx +69 -14
  112. package/src/components/ui/text-editor/extensions.ts +8 -2
  113. package/src/components/ui/text-editor/highlight-extension.ts +22 -0
  114. package/src/components/ui/text-editor/tool-bar.tsx +9 -16
  115. package/src/components/ui/toast.tsx +1 -1
  116. package/src/components/ui/tu-do/boards/__tests__/board-share-dialog.test.tsx +286 -0
  117. package/src/components/ui/tu-do/boards/__tests__/task-board-form.test.tsx +12 -0
  118. package/src/components/ui/tu-do/boards/board-public-link-section.tsx +231 -0
  119. package/src/components/ui/tu-do/boards/board-share-dialog.tsx +15 -226
  120. package/src/components/ui/tu-do/boards/board-share-settings-panel.tsx +351 -0
  121. package/src/components/ui/tu-do/boards/boardId/board-column.tsx +121 -39
  122. package/src/components/ui/tu-do/boards/boardId/enhanced-task-list.tsx +7 -0
  123. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-clear-delete.ts +2 -0
  124. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-move.ts +5 -0
  125. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-mutations-updates.ts +3 -0
  126. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/bulk-operation-types.ts +3 -3
  127. package/src/components/ui/tu-do/boards/boardId/kanban/data/kanban-deadline-query.ts +50 -2
  128. package/src/components/ui/tu-do/boards/boardId/kanban/data/use-bulk-resources.ts +59 -5
  129. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/__tests__/column-reorder.test.ts +17 -0
  130. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/column-reorder.ts +4 -1
  131. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/drag-preview.tsx +20 -1
  132. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-drag-cache.ts +38 -9
  133. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-drag-order.ts +2 -8
  134. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-sort-key.ts +47 -0
  135. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/use-kanban-dnd.ts +81 -30
  136. package/src/components/ui/tu-do/boards/boardId/kanban/planner/__tests__/kanban-planner-island.test.tsx +380 -0
  137. package/src/components/ui/tu-do/boards/boardId/kanban/planner/kanban-planner-dialog.tsx +204 -0
  138. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-digest-panel.tsx +61 -0
  139. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-item-strip.tsx +54 -0
  140. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-plan-toolbar.tsx +251 -0
  141. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-scope-badge.tsx +27 -0
  142. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-section.tsx +58 -0
  143. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-share-dialog.tsx +238 -0
  144. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-target-controls.tsx +143 -0
  145. package/src/components/ui/tu-do/boards/boardId/kanban/planner/planner-utils.ts +65 -0
  146. package/src/components/ui/tu-do/boards/boardId/kanban/planner/use-kanban-planner-state.ts +234 -0
  147. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.test.tsx +642 -5
  148. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.tsx +224 -15
  149. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-deadline-panels.tsx +535 -53
  150. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-skeleton.tsx +101 -33
  151. package/src/components/ui/tu-do/boards/boardId/kanban.tsx +235 -113
  152. package/src/components/ui/tu-do/boards/boardId/task-board-server-page.test.tsx +50 -5
  153. package/src/components/ui/tu-do/boards/boardId/task-board-server-page.tsx +12 -2
  154. package/src/components/ui/tu-do/boards/boardId/task-card/measured-task-card.tsx +10 -1
  155. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-comparator.ts +3 -0
  156. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.test.ts +20 -0
  157. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.ts +10 -0
  158. package/src/components/ui/tu-do/boards/boardId/task-card/task-card.tsx +271 -36
  159. package/src/components/ui/tu-do/boards/boardId/task-filter.test.tsx +152 -0
  160. package/src/components/ui/tu-do/boards/boardId/task-filter.tsx +555 -545
  161. package/src/components/ui/tu-do/boards/boardId/task-list.tsx +22 -0
  162. package/src/components/ui/tu-do/boards/boardId/timeline/timeline-grid.tsx +9 -0
  163. package/src/components/ui/tu-do/boards/boardId/timeline/timeline-task-row.tsx +9 -0
  164. package/src/components/ui/tu-do/boards/boardId/timeline/timeline-toolbar.tsx +9 -0
  165. package/src/components/ui/tu-do/boards/boardId/timeline-board.tsx +35 -3
  166. package/src/components/ui/tu-do/boards/form.tsx +1 -1
  167. package/src/components/ui/tu-do/boards/share-section.tsx +100 -0
  168. package/src/components/ui/tu-do/drafts/draft-convert-dialog.tsx +10 -12
  169. package/src/components/ui/tu-do/drafts/drafts-page.tsx +33 -16
  170. package/src/components/ui/tu-do/hooks/__tests__/useTaskLabelManagement.test.tsx +48 -0
  171. package/src/components/ui/tu-do/hooks/__tests__/useTaskProjectManagement.test.tsx +144 -0
  172. package/src/components/ui/tu-do/hooks/useTaskDialog.ts +7 -0
  173. package/src/components/ui/tu-do/hooks/useTaskLabelManagement.ts +115 -106
  174. package/src/components/ui/tu-do/hooks/useTaskProjectManagement.ts +115 -122
  175. package/src/components/ui/tu-do/initiatives/task-initiatives-client.tsx +56 -88
  176. package/src/components/ui/tu-do/my-tasks/my-tasks-content.tsx +26 -2
  177. package/src/components/ui/tu-do/my-tasks/use-my-tasks-state.ts +55 -8
  178. package/src/components/ui/tu-do/notes/note-edit-dialog.tsx +1 -4
  179. package/src/components/ui/tu-do/progress/task-progress-import-panel.tsx +60 -0
  180. package/src/components/ui/tu-do/progress/task-progress-leaderboards-panel.tsx +156 -0
  181. package/src/components/ui/tu-do/progress/task-progress-page.tsx +348 -0
  182. package/src/components/ui/tu-do/progress/task-progress-panels.tsx +301 -0
  183. package/src/components/ui/tu-do/providers/task-dialog-provider.tsx +26 -0
  184. package/src/components/ui/tu-do/shared/__tests__/assignee-select.test.tsx +81 -10
  185. package/src/components/ui/tu-do/shared/__tests__/board-client.test.tsx +141 -1
  186. package/src/components/ui/tu-do/shared/__tests__/board-header.test.tsx +377 -36
  187. package/src/components/ui/tu-do/shared/__tests__/board-switcher.test.tsx +374 -0
  188. package/src/components/ui/tu-do/shared/__tests__/board-views.test.tsx +419 -5
  189. package/src/components/ui/tu-do/shared/__tests__/task-board-loading-state.test.tsx +38 -0
  190. package/src/components/ui/tu-do/shared/__tests__/task-cache-patches.test.ts +147 -0
  191. package/src/components/ui/tu-do/shared/__tests__/task-legacy-route-recovery.test.tsx +16 -0
  192. package/src/components/ui/tu-do/shared/__tests__/use-progressive-board-loader.test.tsx +3 -0
  193. package/src/components/ui/tu-do/shared/assignee-select.tsx +77 -26
  194. package/src/components/ui/tu-do/shared/board-client.tsx +15 -10
  195. package/src/components/ui/tu-do/shared/board-config-storage.ts +7 -1
  196. package/src/components/ui/tu-do/shared/board-header.tsx +471 -975
  197. package/src/components/ui/tu-do/shared/board-layout-settings.tsx +165 -136
  198. package/src/components/ui/tu-do/shared/board-switcher.tsx +244 -220
  199. package/src/components/ui/tu-do/shared/board-user-presence-avatars.tsx +18 -12
  200. package/src/components/ui/tu-do/shared/board-views.tsx +577 -85
  201. package/src/components/ui/tu-do/shared/list-view.tsx +246 -2
  202. package/src/components/ui/tu-do/shared/recycle-bin-panel.tsx +142 -94
  203. package/src/components/ui/tu-do/shared/special-task-list-pins.ts +51 -0
  204. package/src/components/ui/tu-do/shared/task-board-loading-state.tsx +28 -0
  205. package/src/components/ui/tu-do/shared/task-cache-patches.ts +394 -0
  206. package/src/components/ui/tu-do/shared/task-dialog-manager.tsx +21 -1
  207. package/src/components/ui/tu-do/shared/task-edit-dialog/components/quick-settings-popover.tsx +5 -1
  208. package/src/components/ui/tu-do/shared/task-edit-dialog/components/task-dialog-header.tsx +25 -2
  209. package/src/components/ui/tu-do/shared/task-edit-dialog/components/task-list-selector.tsx +7 -1
  210. package/src/components/ui/tu-do/shared/task-edit-dialog/field-diff-viewer.tsx +3 -2
  211. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-data.ts +79 -10
  212. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-mutations.ts +76 -77
  213. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-relationships.test.tsx +63 -0
  214. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-relationships.ts +78 -69
  215. package/src/components/ui/tu-do/shared/task-edit-dialog/personal-overrides-section.tsx +28 -8
  216. package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/dependencies-section.tsx +14 -3
  217. package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/parent-section.tsx +6 -1
  218. package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/related-section.tsx +6 -1
  219. package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/subtasks-section.tsx +6 -1
  220. package/src/components/ui/tu-do/shared/task-edit-dialog/relationships/types/task-relationships.types.ts +8 -0
  221. package/src/components/ui/tu-do/shared/task-edit-dialog/selective-revert-panel.test.tsx +91 -0
  222. package/src/components/ui/tu-do/shared/task-edit-dialog/selective-revert-panel.tsx +123 -78
  223. package/src/components/ui/tu-do/shared/task-edit-dialog/task-activity-section.tsx +7 -1
  224. package/src/components/ui/tu-do/shared/task-edit-dialog/task-dialog-actions.tsx +8 -1
  225. package/src/components/ui/tu-do/shared/task-edit-dialog/task-properties-section.test.tsx +150 -0
  226. package/src/components/ui/tu-do/shared/task-edit-dialog/task-properties-section.tsx +61 -35
  227. package/src/components/ui/tu-do/shared/task-edit-dialog/task-relationships-properties.tsx +44 -2
  228. package/src/components/ui/tu-do/shared/task-edit-dialog/task-snapshot-dialog.tsx +8 -3
  229. package/src/components/ui/tu-do/shared/task-edit-dialog.tsx +11 -1
  230. package/src/components/ui/tu-do/shared/task-legacy-route-recovery.tsx +2 -9
  231. package/src/components/ui/tu-do/shared/task-row-actions-menu.tsx +11 -0
  232. package/src/components/ui/tu-do/shared/use-progressive-board-loader.ts +2 -0
  233. package/src/declarations.d.ts +1 -0
  234. package/src/hooks/__tests__/use-calendar-readonly.test.tsx +322 -2
  235. package/src/hooks/__tests__/use-calendar-sync.test.tsx +446 -0
  236. package/src/hooks/__tests__/useBoardPresence.test.tsx +191 -0
  237. package/src/hooks/__tests__/useBoardRealtime.test.tsx +24 -144
  238. package/src/hooks/use-calendar-sync.tsx +247 -243
  239. package/src/hooks/use-calendar.tsx +323 -138
  240. package/src/hooks/use-task-actions.ts +24 -0
  241. package/src/hooks/use-user-workspace-config.ts +75 -0
  242. package/src/hooks/use-workspace-currency.ts +8 -3
  243. package/src/hooks/useBoardPresence.ts +364 -0
  244. package/src/hooks/useBoardRealtimeEventHandler.ts +45 -90
  245. package/src/lib/workspace-actions.ts +2 -6
@@ -1,5 +1,5 @@
1
1
  import '@testing-library/jest-dom';
2
- import { render, screen } from '@testing-library/react';
2
+ import { act, fireEvent, render, screen, within } from '@testing-library/react';
3
3
  import type { Task } from '@tuturuuu/types/primitives/Task';
4
4
  import type { TaskList } from '@tuturuuu/types/primitives/TaskList';
5
5
  import type React from 'react';
@@ -20,8 +20,22 @@ vi.mock('@dnd-kit/sortable', () => ({
20
20
  }));
21
21
 
22
22
  vi.mock('../../board-column', () => ({
23
- BoardColumn: ({ column }: { column: TaskList }) => (
24
- <section data-testid={`column-${column.id}`} />
23
+ BoardColumn: ({
24
+ column,
25
+ specialPinned,
26
+ specialStickyOffset,
27
+ }: {
28
+ column: TaskList;
29
+ specialPinned?: boolean;
30
+ specialStickyOffset?: string;
31
+ }) => (
32
+ <section
33
+ data-kanban-pinned-special={specialStickyOffset ? 'true' : undefined}
34
+ data-kanban-real-column={column.is_external_staging ? undefined : 'true'}
35
+ data-special-pinned={String(specialPinned === true)}
36
+ data-special-sticky-offset={specialStickyOffset}
37
+ data-testid={`column-${column.id}`}
38
+ />
25
39
  ),
26
40
  }));
27
41
 
@@ -114,6 +128,20 @@ function task(overrides: Partial<Task>): Task {
114
128
  };
115
129
  }
116
130
 
131
+ function getMockRect(left: number, right: number) {
132
+ return {
133
+ bottom: 0,
134
+ height: 0,
135
+ left,
136
+ right,
137
+ toJSON: () => ({}),
138
+ top: 0,
139
+ width: right - left,
140
+ x: left,
141
+ y: 0,
142
+ } as DOMRect;
143
+ }
144
+
117
145
  describe('KanbanColumns', () => {
118
146
  beforeEach(() => {
119
147
  cursorOverlayMock.mockClear();
@@ -317,10 +345,18 @@ describe('KanbanColumns', () => {
317
345
  );
318
346
 
319
347
  const deadlinePanels = screen.getByTestId('kanban-deadline-panels');
348
+ const overdueSection = screen.getByTestId(
349
+ 'kanban-deadline-section-overdue'
350
+ );
351
+ const overdueCount = screen.getByTestId(
352
+ 'kanban-deadline-section-overdue-count'
353
+ );
320
354
  const firstColumn = screen.getByTestId('column-list-1');
321
355
  const sharedTaskCard = screen.getByTestId('shared-task-card-overdue-task');
322
356
 
357
+ expect(overdueSection).toHaveClass('border-dashed');
323
358
  expect(deadlinePanels).toHaveTextContent('Overdue');
359
+ expect(overdueCount).toHaveTextContent('1');
324
360
  expect(sharedTaskCard).toHaveTextContent('Overdue task');
325
361
  expect(deadlinePanels.compareDocumentPosition(firstColumn)).toBe(
326
362
  Node.DOCUMENT_POSITION_FOLLOWING
@@ -347,6 +383,332 @@ describe('KanbanColumns', () => {
347
383
  ).toEqual(['list-1', 'list-2']);
348
384
  });
349
385
 
386
+ it('filters deadline cards by document and external source controls', () => {
387
+ render(
388
+ <KanbanColumns
389
+ columns={[...lists, externalList]}
390
+ tasks={[]}
391
+ boardId="board-1"
392
+ workspaceId="ws-1"
393
+ isPersonalWorkspace
394
+ disableSort={false}
395
+ selectedTasks={new Set()}
396
+ isMultiSelectMode={false}
397
+ setIsMultiSelectMode={vi.fn()}
398
+ onTaskSelect={vi.fn()}
399
+ onClearSelection={vi.fn()}
400
+ onUpdate={vi.fn()}
401
+ createTask={vi.fn()}
402
+ taskHeightsRef={{ current: new Map() }}
403
+ optimisticUpdateInProgress={new Set()}
404
+ bulkUpdateCustomDueDate={vi.fn()}
405
+ boardRef={{ current: null }}
406
+ columnsId={[...lists, externalList].map((list) => list.id)}
407
+ deadlineLabels={{
408
+ filter: 'Filters',
409
+ overdue: 'Overdue',
410
+ showDocuments: 'Show document-list tasks',
411
+ showExternalTasks: 'External tasks',
412
+ upcoming: 'Upcoming',
413
+ }}
414
+ deadlineSections={{
415
+ overdue: [],
416
+ upcoming: [
417
+ task({
418
+ end_date: '2026-06-01T00:00:00.000Z',
419
+ id: 'regular-deadline',
420
+ list_id: 'list-1',
421
+ name: 'Regular deadline task',
422
+ }),
423
+ task({
424
+ end_date: '2026-06-02T00:00:00.000Z',
425
+ id: 'document-deadline',
426
+ list_id: 'list-1',
427
+ name: 'Document deadline task',
428
+ source_list_status: 'documents',
429
+ }),
430
+ task({
431
+ end_date: '2026-06-03T00:00:00.000Z',
432
+ id: 'external-deadline',
433
+ list_id: 'external-list',
434
+ name: 'External deadline task',
435
+ source_workspace_id: 'source-ws',
436
+ }),
437
+ ],
438
+ }}
439
+ />
440
+ );
441
+
442
+ const upcomingSection = screen.getByTestId(
443
+ 'kanban-deadline-section-upcoming'
444
+ );
445
+
446
+ expect(
447
+ screen.getByTestId('shared-task-card-regular-deadline')
448
+ ).toBeInTheDocument();
449
+ expect(
450
+ screen.getByTestId('shared-task-card-document-deadline')
451
+ ).toBeInTheDocument();
452
+ expect(
453
+ screen.getByTestId('shared-task-card-external-deadline')
454
+ ).toBeInTheDocument();
455
+
456
+ fireEvent.pointerDown(
457
+ within(upcomingSection).getByRole('button', { name: 'Filters' }),
458
+ { button: 0, ctrlKey: false }
459
+ );
460
+ fireEvent.click(
461
+ screen.getByRole('menuitemcheckbox', {
462
+ name: 'Show document-list tasks',
463
+ })
464
+ );
465
+ fireEvent.click(
466
+ screen.getByRole('menuitemcheckbox', { name: 'External tasks' })
467
+ );
468
+
469
+ expect(
470
+ screen.getByTestId('shared-task-card-regular-deadline')
471
+ ).toBeInTheDocument();
472
+ expect(
473
+ screen.queryByTestId('shared-task-card-document-deadline')
474
+ ).not.toBeInTheDocument();
475
+ expect(
476
+ screen.queryByTestId('shared-task-card-external-deadline')
477
+ ).not.toBeInTheDocument();
478
+ expect(
479
+ screen.getByTestId('kanban-deadline-section-upcoming-count')
480
+ ).toHaveTextContent('1');
481
+ });
482
+
483
+ it('sorts deadline cards using local deadline sort controls', () => {
484
+ render(
485
+ <KanbanColumns
486
+ columns={lists}
487
+ tasks={[]}
488
+ boardId="board-1"
489
+ workspaceId="ws-1"
490
+ isPersonalWorkspace={false}
491
+ disableSort={false}
492
+ selectedTasks={new Set()}
493
+ isMultiSelectMode={false}
494
+ setIsMultiSelectMode={vi.fn()}
495
+ onTaskSelect={vi.fn()}
496
+ onClearSelection={vi.fn()}
497
+ onUpdate={vi.fn()}
498
+ createTask={vi.fn()}
499
+ taskHeightsRef={{ current: new Map() }}
500
+ optimisticUpdateInProgress={new Set()}
501
+ bulkUpdateCustomDueDate={vi.fn()}
502
+ boardRef={{ current: null }}
503
+ columnsId={lists.map((list) => list.id)}
504
+ deadlineLabels={{
505
+ overdue: 'Overdue',
506
+ sort: 'Sort',
507
+ sortNameAsc: 'Task name',
508
+ upcoming: 'Upcoming',
509
+ }}
510
+ deadlineSections={{
511
+ overdue: [],
512
+ upcoming: [
513
+ task({
514
+ end_date: '2026-06-02T00:00:00.000Z',
515
+ id: 'z-deadline',
516
+ list_id: 'list-1',
517
+ name: 'Zulu task',
518
+ }),
519
+ task({
520
+ end_date: '2026-06-03T00:00:00.000Z',
521
+ id: 'a-deadline',
522
+ list_id: 'list-1',
523
+ name: 'Alpha task',
524
+ }),
525
+ ],
526
+ }}
527
+ />
528
+ );
529
+
530
+ const upcomingSection = screen.getByTestId(
531
+ 'kanban-deadline-section-upcoming'
532
+ );
533
+
534
+ expect(
535
+ within(upcomingSection)
536
+ .getAllByTestId(/shared-task-card-/)
537
+ .map((item) => item.textContent)
538
+ ).toEqual(['Zulu task', 'Alpha task']);
539
+
540
+ fireEvent.pointerDown(
541
+ within(upcomingSection).getByRole('button', { name: 'Sort' }),
542
+ { button: 0, ctrlKey: false }
543
+ );
544
+ fireEvent.click(screen.getByRole('menuitemradio', { name: 'Task name' }));
545
+
546
+ expect(
547
+ within(upcomingSection)
548
+ .getAllByTestId(/shared-task-card-/)
549
+ .map((item) => item.textContent)
550
+ ).toEqual(['Alpha task', 'Zulu task']);
551
+ });
552
+
553
+ it('anchors the first load on the first real task list when empty special columns render to the left', () => {
554
+ const frameCallbacks: FrameRequestCallback[] = [];
555
+ const originalRequestAnimationFrame = window.requestAnimationFrame;
556
+ const originalCancelAnimationFrame = window.cancelAnimationFrame;
557
+
558
+ window.requestAnimationFrame = vi.fn((callback: FrameRequestCallback) => {
559
+ frameCallbacks.push(callback);
560
+ return frameCallbacks.length;
561
+ });
562
+ window.cancelAnimationFrame = vi.fn();
563
+
564
+ try {
565
+ const { container, rerender } = render(
566
+ <KanbanColumns
567
+ columns={[externalList, ...lists]}
568
+ tasks={[]}
569
+ boardId="board-1"
570
+ workspaceId="ws-1"
571
+ isPersonalWorkspace
572
+ disableSort={false}
573
+ selectedTasks={new Set()}
574
+ isMultiSelectMode={false}
575
+ setIsMultiSelectMode={vi.fn()}
576
+ onTaskSelect={vi.fn()}
577
+ onClearSelection={vi.fn()}
578
+ onUpdate={vi.fn()}
579
+ createTask={vi.fn()}
580
+ taskHeightsRef={{ current: new Map() }}
581
+ optimisticUpdateInProgress={new Set()}
582
+ bulkUpdateCustomDueDate={vi.fn()}
583
+ boardRef={{ current: null }}
584
+ columnsId={[externalList, ...lists].map((list) => list.id)}
585
+ deadlineLabels={{
586
+ overdue: 'Overdue',
587
+ upcoming: 'Upcoming',
588
+ }}
589
+ deadlineSections={{
590
+ overdue: [],
591
+ upcoming: [],
592
+ }}
593
+ deadlineSectionsLoading
594
+ />
595
+ );
596
+ const scrollContainer = container.firstElementChild as HTMLElement;
597
+ const firstRealColumn = screen.getByTestId('column-list-1');
598
+ Object.defineProperty(firstRealColumn, 'offsetLeft', {
599
+ configurable: true,
600
+ value: 320,
601
+ });
602
+
603
+ act(() => {
604
+ for (const callback of frameCallbacks) callback(0);
605
+ });
606
+
607
+ expect(scrollContainer.scrollLeft).toBe(312);
608
+
609
+ scrollContainer.scrollLeft = 64;
610
+ rerender(
611
+ <KanbanColumns
612
+ columns={[externalList, ...lists]}
613
+ tasks={[]}
614
+ boardId="board-1"
615
+ workspaceId="ws-1"
616
+ isPersonalWorkspace
617
+ disableSort={false}
618
+ selectedTasks={new Set()}
619
+ isMultiSelectMode={false}
620
+ setIsMultiSelectMode={vi.fn()}
621
+ onTaskSelect={vi.fn()}
622
+ onClearSelection={vi.fn()}
623
+ onUpdate={vi.fn()}
624
+ createTask={vi.fn()}
625
+ taskHeightsRef={{ current: new Map() }}
626
+ optimisticUpdateInProgress={new Set()}
627
+ bulkUpdateCustomDueDate={vi.fn()}
628
+ boardRef={{ current: null }}
629
+ columnsId={[externalList, ...lists].map((list) => list.id)}
630
+ deadlineLabels={{
631
+ overdue: 'Overdue',
632
+ upcoming: 'Upcoming',
633
+ }}
634
+ deadlineSections={{
635
+ overdue: [],
636
+ upcoming: [],
637
+ }}
638
+ deadlineSectionsLoading
639
+ />
640
+ );
641
+
642
+ expect(scrollContainer.scrollLeft).toBe(64);
643
+ } finally {
644
+ window.requestAnimationFrame = originalRequestAnimationFrame;
645
+ window.cancelAnimationFrame = originalCancelAnimationFrame;
646
+ }
647
+ });
648
+
649
+ it('keeps the first real task list visible when pinned special lists are sticky', () => {
650
+ const frameCallbacks: FrameRequestCallback[] = [];
651
+ const originalRequestAnimationFrame = window.requestAnimationFrame;
652
+ const originalCancelAnimationFrame = window.cancelAnimationFrame;
653
+ const collapsedExternalList = {
654
+ ...externalList,
655
+ is_external_collapsed: true,
656
+ };
657
+
658
+ window.requestAnimationFrame = vi.fn((callback: FrameRequestCallback) => {
659
+ frameCallbacks.push(callback);
660
+ return frameCallbacks.length;
661
+ });
662
+ window.cancelAnimationFrame = vi.fn();
663
+
664
+ try {
665
+ const { container } = render(
666
+ <KanbanColumns
667
+ columns={[collapsedExternalList, ...lists]}
668
+ tasks={[]}
669
+ boardId="board-1"
670
+ workspaceId="ws-1"
671
+ isPersonalWorkspace
672
+ disableSort={false}
673
+ selectedTasks={new Set()}
674
+ isMultiSelectMode={false}
675
+ setIsMultiSelectMode={vi.fn()}
676
+ onTaskSelect={vi.fn()}
677
+ onClearSelection={vi.fn()}
678
+ onUpdate={vi.fn()}
679
+ createTask={vi.fn()}
680
+ taskHeightsRef={{ current: new Map() }}
681
+ optimisticUpdateInProgress={new Set()}
682
+ bulkUpdateCustomDueDate={vi.fn()}
683
+ boardRef={{ current: null }}
684
+ columnsId={[collapsedExternalList, ...lists].map((list) => list.id)}
685
+ specialTaskListPins={{ external_tasks: true }}
686
+ />
687
+ );
688
+ const scrollContainer = container.firstElementChild as HTMLElement;
689
+ const firstRealColumn = screen.getByTestId('column-list-1');
690
+ const pinnedExternalColumn = screen.getByTestId('column-external-list');
691
+
692
+ Object.defineProperty(firstRealColumn, 'offsetLeft', {
693
+ configurable: true,
694
+ value: 320,
695
+ });
696
+ Object.defineProperty(pinnedExternalColumn, 'getBoundingClientRect', {
697
+ configurable: true,
698
+ value: () => getMockRect(8, 64),
699
+ });
700
+
701
+ act(() => {
702
+ for (const callback of frameCallbacks) callback(0);
703
+ });
704
+
705
+ expect(scrollContainer.scrollLeft).toBe(256);
706
+ } finally {
707
+ window.requestAnimationFrame = originalRequestAnimationFrame;
708
+ window.cancelAnimationFrame = originalCancelAnimationFrame;
709
+ }
710
+ });
711
+
350
712
  it('renders external deadline cards with their staging list context without exposing the staging list as a move target', () => {
351
713
  render(
352
714
  <KanbanColumns
@@ -403,9 +765,14 @@ describe('KanbanColumns', () => {
403
765
  expect(
404
766
  externalCardProps.availableLists.map((list: TaskList) => list.id)
405
767
  ).toEqual(['list-1', 'list-2']);
768
+ expect(externalCardProps).toEqual(
769
+ expect.objectContaining({
770
+ deadlineContext: 'upcoming',
771
+ })
772
+ );
406
773
  });
407
774
 
408
- it('omits deadline panels when both deadline sections are empty', () => {
775
+ it('renders collapsed deadline sections with counts and expand labels', () => {
409
776
  render(
410
777
  <KanbanColumns
411
778
  columns={lists}
@@ -426,15 +793,285 @@ describe('KanbanColumns', () => {
426
793
  bulkUpdateCustomDueDate={vi.fn()}
427
794
  boardRef={{ current: null }}
428
795
  columnsId={lists.map((list) => list.id)}
796
+ deadlineLabels={{
797
+ expandSection: (name) => `Expand ${name}`,
798
+ overdue: 'Overdue',
799
+ upcoming: 'Upcoming',
800
+ }}
801
+ deadlineSections={{
802
+ overdue: [
803
+ task({
804
+ end_date: '2026-05-06T00:00:00.000Z',
805
+ id: 'overdue-task',
806
+ list_id: 'list-1',
807
+ name: 'Overdue task',
808
+ }),
809
+ ],
810
+ upcoming: [],
811
+ }}
812
+ deadlineSectionsCollapsed={{ overdue: true }}
813
+ />
814
+ );
815
+
816
+ const collapsedOverdue = screen.getByTestId(
817
+ 'kanban-deadline-section-overdue-collapsed'
818
+ );
819
+
820
+ expect(collapsedOverdue).toHaveTextContent('Overdue');
821
+ expect(collapsedOverdue).toHaveTextContent('1');
822
+ expect(
823
+ screen.getByRole('button', { name: 'Expand Overdue' })
824
+ ).toBeInTheDocument();
825
+ });
826
+
827
+ it('keeps pinned deadline sections sticky without forcing them expanded', () => {
828
+ render(
829
+ <KanbanColumns
830
+ columns={lists}
831
+ tasks={[]}
832
+ boardId="board-1"
833
+ workspaceId="ws-1"
834
+ isPersonalWorkspace={false}
835
+ disableSort={false}
836
+ selectedTasks={new Set()}
837
+ isMultiSelectMode={false}
838
+ setIsMultiSelectMode={vi.fn()}
839
+ onTaskSelect={vi.fn()}
840
+ onClearSelection={vi.fn()}
841
+ onUpdate={vi.fn()}
842
+ createTask={vi.fn()}
843
+ taskHeightsRef={{ current: new Map() }}
844
+ optimisticUpdateInProgress={new Set()}
845
+ bulkUpdateCustomDueDate={vi.fn()}
846
+ boardRef={{ current: null }}
847
+ columnsId={lists.map((list) => list.id)}
848
+ deadlineLabels={{
849
+ overdue: 'Overdue',
850
+ upcoming: 'Upcoming',
851
+ }}
852
+ deadlineSections={{
853
+ overdue: [],
854
+ upcoming: [],
855
+ }}
856
+ deadlineSectionsCollapsed={{ overdue: true }}
857
+ specialTaskListPins={{ overdue: true, upcoming: true }}
858
+ />
859
+ );
860
+
861
+ const collapsedOverdue = screen.getByTestId(
862
+ 'kanban-deadline-section-overdue-collapsed'
863
+ );
864
+ const upcoming = screen.getByTestId('kanban-deadline-section-upcoming');
865
+
866
+ expect(collapsedOverdue).toHaveAttribute(
867
+ 'data-kanban-pinned-special',
868
+ 'true'
869
+ );
870
+ expect(collapsedOverdue).toHaveClass('sticky');
871
+ expect(collapsedOverdue.style.left).toBe(
872
+ 'calc(var(--kanban-snap-left-padding) + 0px)'
873
+ );
874
+ expect(upcoming).toHaveAttribute('data-kanban-pinned-special', 'true');
875
+ expect(upcoming).toHaveClass('sticky');
876
+ expect(upcoming.style.left).toBe(
877
+ 'calc(var(--kanban-snap-left-padding) + calc(3.5rem + 0.75rem))'
878
+ );
879
+ });
880
+
881
+ it('assigns sticky offsets to pinned external and closed task lists', () => {
882
+ const collapsedExternalList = {
883
+ ...externalList,
884
+ is_external_collapsed: true,
885
+ };
886
+
887
+ render(
888
+ <KanbanColumns
889
+ columns={[collapsedExternalList, ...lists, collapsedClosedList]}
890
+ tasks={[]}
891
+ boardId="board-1"
892
+ workspaceId="ws-1"
893
+ isPersonalWorkspace
894
+ disableSort={false}
895
+ selectedTasks={new Set()}
896
+ isMultiSelectMode={false}
897
+ setIsMultiSelectMode={vi.fn()}
898
+ onTaskSelect={vi.fn()}
899
+ onClearSelection={vi.fn()}
900
+ onUpdate={vi.fn()}
901
+ createTask={vi.fn()}
902
+ taskHeightsRef={{ current: new Map() }}
903
+ optimisticUpdateInProgress={new Set()}
904
+ bulkUpdateCustomDueDate={vi.fn()}
905
+ boardRef={{ current: null }}
906
+ columnsId={[collapsedExternalList, ...lists, collapsedClosedList].map(
907
+ (list) => list.id
908
+ )}
909
+ specialTaskListPins={{ closed_tasks: true, external_tasks: true }}
910
+ />
911
+ );
912
+
913
+ expect(screen.getByTestId('column-external-list')).toHaveAttribute(
914
+ 'data-special-pinned',
915
+ 'true'
916
+ );
917
+ expect(screen.getByTestId('column-external-list')).toHaveAttribute(
918
+ 'data-special-sticky-offset',
919
+ '0px'
920
+ );
921
+ expect(screen.getByTestId('column-closed-list')).toHaveAttribute(
922
+ 'data-special-pinned',
923
+ 'true'
924
+ );
925
+ expect(screen.getByTestId('column-closed-list')).toHaveAttribute(
926
+ 'data-special-sticky-offset',
927
+ 'calc(3.5rem + 0.75rem)'
928
+ );
929
+ });
930
+
931
+ it('passes deadline tick props to upcoming deadline cards', () => {
932
+ render(
933
+ <KanbanColumns
934
+ columns={lists}
935
+ tasks={[]}
936
+ boardId="board-1"
937
+ workspaceId="ws-1"
938
+ isPersonalWorkspace={false}
939
+ disableSort={false}
940
+ selectedTasks={new Set()}
941
+ isMultiSelectMode={false}
942
+ setIsMultiSelectMode={vi.fn()}
943
+ onTaskSelect={vi.fn()}
944
+ onClearSelection={vi.fn()}
945
+ onUpdate={vi.fn()}
946
+ createTask={vi.fn()}
947
+ taskHeightsRef={{ current: new Map() }}
948
+ optimisticUpdateInProgress={new Set()}
949
+ bulkUpdateCustomDueDate={vi.fn()}
950
+ boardRef={{ current: null }}
951
+ columnsId={lists.map((list) => list.id)}
952
+ deadlineLabels={{
953
+ overdue: 'Overdue',
954
+ upcoming: 'Upcoming',
955
+ }}
956
+ deadlineNow={1_779_840_000_000}
957
+ deadlineSections={{
958
+ overdue: [],
959
+ upcoming: [
960
+ task({
961
+ end_date: '2026-06-01T00:00:00.000Z',
962
+ id: 'upcoming-task',
963
+ list_id: 'list-1',
964
+ name: 'Upcoming task',
965
+ }),
966
+ ],
967
+ }}
968
+ />
969
+ );
970
+
971
+ const upcomingCardProps = taskCardMock.mock.calls.find(
972
+ ([props]) => props.task.id === 'upcoming-task'
973
+ )?.[0];
974
+
975
+ expect(upcomingCardProps).toEqual(
976
+ expect.objectContaining({
977
+ deadlineContext: 'upcoming',
978
+ deadlineNow: 1_779_840_000_000,
979
+ })
980
+ );
981
+ });
982
+
983
+ it('reserves empty deadline panels before deadline tasks load', () => {
984
+ const { container, rerender } = render(
985
+ <KanbanColumns
986
+ columns={lists}
987
+ tasks={[]}
988
+ boardId="board-1"
989
+ workspaceId="ws-1"
990
+ isPersonalWorkspace={false}
991
+ disableSort={false}
992
+ selectedTasks={new Set()}
993
+ isMultiSelectMode={false}
994
+ setIsMultiSelectMode={vi.fn()}
995
+ onTaskSelect={vi.fn()}
996
+ onClearSelection={vi.fn()}
997
+ onUpdate={vi.fn()}
998
+ createTask={vi.fn()}
999
+ taskHeightsRef={{ current: new Map() }}
1000
+ optimisticUpdateInProgress={new Set()}
1001
+ bulkUpdateCustomDueDate={vi.fn()}
1002
+ boardRef={{ current: null }}
1003
+ columnsId={lists.map((list) => list.id)}
1004
+ listStatusFilter="all"
429
1005
  deadlineLabels={{
430
1006
  overdue: 'Overdue',
431
1007
  upcoming: 'Upcoming',
432
1008
  }}
433
1009
  deadlineSections={{ overdue: [], upcoming: [] }}
1010
+ deadlineSectionsLoading
434
1011
  />
435
1012
  );
436
1013
 
437
- expect(screen.queryByTestId('kanban-deadline-panels')).toBeNull();
1014
+ expect(screen.getByTestId('kanban-deadline-panels')).toBeInTheDocument();
1015
+ expect(
1016
+ screen.getByTestId('kanban-deadline-section-overdue')
1017
+ ).toBeInTheDocument();
1018
+ expect(
1019
+ screen.getByTestId('kanban-deadline-section-upcoming')
1020
+ ).toBeInTheDocument();
1021
+ expect(
1022
+ screen.getByTestId('kanban-deadline-section-overdue-count')
1023
+ ).toHaveTextContent('0');
1024
+ expect(
1025
+ screen.getByTestId('kanban-deadline-section-upcoming-count')
1026
+ ).toHaveTextContent('0');
1027
+ expect(
1028
+ screen.getByTestId('kanban-deadline-section-overdue-loading')
1029
+ ).toBeInTheDocument();
1030
+ expect(
1031
+ screen.getByTestId('kanban-deadline-section-upcoming-loading')
1032
+ ).toBeInTheDocument();
1033
+ expect(
1034
+ (container.firstElementChild as HTMLElement).style.getPropertyValue(
1035
+ '--kanban-column-width'
1036
+ )
1037
+ ).toContain('/ 4');
438
1038
  expect(screen.getByTestId('column-list-1')).toBeInTheDocument();
1039
+
1040
+ rerender(
1041
+ <KanbanColumns
1042
+ columns={lists}
1043
+ tasks={[]}
1044
+ boardId="board-1"
1045
+ workspaceId="ws-1"
1046
+ isPersonalWorkspace={false}
1047
+ disableSort={false}
1048
+ selectedTasks={new Set()}
1049
+ isMultiSelectMode={false}
1050
+ setIsMultiSelectMode={vi.fn()}
1051
+ onTaskSelect={vi.fn()}
1052
+ onClearSelection={vi.fn()}
1053
+ onUpdate={vi.fn()}
1054
+ createTask={vi.fn()}
1055
+ taskHeightsRef={{ current: new Map() }}
1056
+ optimisticUpdateInProgress={new Set()}
1057
+ bulkUpdateCustomDueDate={vi.fn()}
1058
+ boardRef={{ current: null }}
1059
+ columnsId={lists.map((list) => list.id)}
1060
+ listStatusFilter="all"
1061
+ deadlineLabels={{
1062
+ overdue: 'Overdue',
1063
+ upcoming: 'Upcoming',
1064
+ }}
1065
+ deadlineSections={{ overdue: [], upcoming: [] }}
1066
+ />
1067
+ );
1068
+
1069
+ expect(screen.getByTestId('kanban-deadline-panels')).toBeInTheDocument();
1070
+ expect(
1071
+ screen.queryByTestId('kanban-deadline-section-overdue-loading')
1072
+ ).not.toBeInTheDocument();
1073
+ expect(
1074
+ screen.queryByTestId('kanban-deadline-section-upcoming-loading')
1075
+ ).not.toBeInTheDocument();
439
1076
  });
440
1077
  });