@tuturuuu/ui 0.31.0 → 0.33.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 (79) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/biome.json +1 -1
  3. package/package.json +53 -51
  4. package/src/components/ui/calendar-app/components/calendar-sync-attention-button.tsx +58 -24
  5. package/src/components/ui/calendar-app/components/calendar-sync-recovery.test.tsx +57 -0
  6. package/src/components/ui/calendar-app/components/calendar-sync-recovery.tsx +28 -14
  7. package/src/components/ui/calendar-app/components/refresh-calendar-sync-status.test.tsx +321 -0
  8. package/src/components/ui/calendar-app/components/refresh-calendar-sync-status.ts +182 -0
  9. package/src/components/ui/calendar-app/components/use-calendar-connections-manager.ts +12 -14
  10. package/src/components/ui/chat/ai-message-markdown.tsx +17 -2
  11. package/src/components/ui/chat/ai-message-parts.test.tsx +47 -0
  12. package/src/components/ui/chat/ai-message-parts.tsx +23 -16
  13. package/src/components/ui/chat/ai-message-render-utils.ts +19 -1
  14. package/src/components/ui/commercial-comparison-style.ts +104 -0
  15. package/src/components/ui/commercial-comparison-table.tsx +159 -0
  16. package/src/components/ui/commercial-comparison-toolbar.tsx +205 -0
  17. package/src/components/ui/commercial-comparison.test.tsx +86 -0
  18. package/src/components/ui/commercial-comparison.tsx +224 -0
  19. package/src/components/ui/comparison-value.test.tsx +32 -0
  20. package/src/components/ui/comparison-value.tsx +72 -0
  21. package/src/components/ui/custom/__tests__/report-preview-pagination-progress.test.ts +129 -0
  22. package/src/components/ui/custom/__tests__/report-preview-viewport.test.tsx +56 -0
  23. package/src/components/ui/custom/education/modules/resources/pdf-viewer.tsx +13 -2
  24. package/src/components/ui/custom/report-preview-pagination.ts +5 -3
  25. package/src/components/ui/custom/report-preview-viewport.tsx +40 -0
  26. package/src/components/ui/custom/report-preview.tsx +2 -3
  27. package/src/components/ui/finance/categories-tags-tabs.tsx +3 -0
  28. package/src/components/ui/finance/invoices/columns.tsx +2 -0
  29. package/src/components/ui/finance/invoices/components/invoice-checkout-summary.tsx +6 -3
  30. package/src/components/ui/finance/invoices/components/invoice-data-state.test.tsx +27 -0
  31. package/src/components/ui/finance/invoices/components/invoice-data-state.tsx +34 -0
  32. package/src/components/ui/finance/invoices/hooks/use-invoice-customer-search.test.tsx +89 -0
  33. package/src/components/ui/finance/invoices/hooks/use-invoice-customer-search.ts +117 -0
  34. package/src/components/ui/finance/invoices/hooks.ts +5 -110
  35. package/src/components/ui/finance/invoices/internal-api.test.ts +122 -0
  36. package/src/components/ui/finance/invoices/internal-api.ts +19 -1
  37. package/src/components/ui/finance/invoices/invoice-discount.test.tsx +107 -0
  38. package/src/components/ui/finance/invoices/invoice-discount.ts +12 -0
  39. package/src/components/ui/finance/invoices/invoice-history-filters.tsx +121 -0
  40. package/src/components/ui/finance/invoices/invoice-history-pagination.tsx +81 -0
  41. package/src/components/ui/finance/invoices/invoice-history-row.tsx +159 -0
  42. package/src/components/ui/finance/invoices/invoice-history.test.tsx +170 -0
  43. package/src/components/ui/finance/invoices/invoice-history.tsx +300 -0
  44. package/src/components/ui/finance/invoices/invoice-page.tsx +18 -2
  45. package/src/components/ui/finance/invoices/invoiceId/full-invoice-template.tsx +3 -7
  46. package/src/components/ui/finance/invoices/invoiceId/invoice-details-page.test.tsx +16 -0
  47. package/src/components/ui/finance/invoices/invoiceId/invoice-details-page.tsx +9 -0
  48. package/src/components/ui/finance/invoices/invoices-table.tsx +3 -0
  49. package/src/components/ui/finance/invoices/promotion-form.tsx +5 -4
  50. package/src/components/ui/finance/invoices/query-invalidation.ts +1 -0
  51. package/src/components/ui/finance/invoices/row-actions.tsx +35 -4
  52. package/src/components/ui/finance/invoices/standard-invoice.tsx +27 -16
  53. package/src/components/ui/finance/invoices/subscription-invoice-props.ts +20 -0
  54. package/src/components/ui/finance/invoices/subscription-invoice.test.tsx +71 -4
  55. package/src/components/ui/finance/invoices/subscription-invoice.tsx +44 -45
  56. package/src/components/ui/finance/shared/charts/category-breakdown-chart-body.tsx +73 -80
  57. package/src/components/ui/finance/shared/charts/category-breakdown-chart-controls.tsx +3 -1
  58. package/src/components/ui/finance/shared/charts/category-breakdown-chart-legend.test.tsx +30 -0
  59. package/src/components/ui/finance/shared/charts/category-breakdown-chart-legend.tsx +31 -24
  60. package/src/components/ui/finance/shared/charts/category-breakdown-chart-tooltip.tsx +9 -6
  61. package/src/components/ui/finance/shared/charts/category-breakdown-chart-types.ts +2 -0
  62. package/src/components/ui/finance/shared/charts/category-breakdown-chart-utils.test.ts +59 -0
  63. package/src/components/ui/finance/shared/charts/category-breakdown-chart-utils.ts +51 -37
  64. package/src/components/ui/finance/shared/charts/category-breakdown-chart.tsx +37 -7
  65. package/src/components/ui/public-workspace-prices.tsx +13 -0
  66. package/src/components/ui/pwa-status.test.tsx +13 -2
  67. package/src/components/ui/pwa-status.tsx +15 -3
  68. package/src/components/ui/text-editor/editor-readonly-transition.test.tsx +86 -0
  69. package/src/components/ui/text-editor/editor.tsx +11 -3
  70. package/src/components/ui/text-editor/task-item-checkbox-view.test.tsx +188 -65
  71. package/src/components/ui/text-editor/task-item-checkbox-view.tsx +178 -164
  72. package/src/components/ui/text-editor/task-item-status-picker.tsx +130 -0
  73. package/src/hooks/__tests__/use-calendar-sync.test.tsx +20 -1
  74. package/src/hooks/__tests__/use-notifications-subscription.test.tsx +99 -180
  75. package/src/hooks/calendar-provider-sync.ts +33 -0
  76. package/src/hooks/notification-subscription.ts +74 -0
  77. package/src/hooks/use-calendar-sync.tsx +11 -14
  78. package/src/hooks/use-calendar.tsx +2 -2
  79. package/src/hooks/use-notifications.ts +5 -141
package/CHANGELOG.md CHANGED
@@ -1,5 +1,62 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.33.0](https://github.com/tutur3u/platform/compare/ui-v0.32.0...ui-v0.33.0) (2026-09-20)
4
+
5
+
6
+ ### Features
7
+
8
+ * **calendar:** automatically refresh connected calendars ([03584af](https://github.com/tutur3u/platform/commit/03584af0d9b7135b90953e9f81f7e971968679ff)) ([#5311](https://github.com/tutur3u/platform/issues/5311)) ([e52894f](https://github.com/tutur3u/platform/commit/e52894fd746b76fee1c76efab40c9e398c95b5a4))
9
+ * **finance:** add granular invoice audit trail and recovery review ([#5376](https://github.com/tutur3u/platform/issues/5376)) ([b8df666](https://github.com/tutur3u/platform/commit/b8df666804848d96d35ba693d126fe611a3ebf2b))
10
+ * **finance:** add invoice history and recoverable deletion ([3d6dea5](https://github.com/tutur3u/platform/commit/3d6dea5bdbb055073b9b5d5680e391d094874ad2))
11
+ * **finance:** clarify category charts and add promotions management ([88f85ea](https://github.com/tutur3u/platform/commit/88f85eaadb722b42b99537be3c75fabb1715bf09)) ([#5384](https://github.com/tutur3u/platform/issues/5384)) ([b6fd666](https://github.com/tutur3u/platform/commit/b6fd666bccca6aa929166210fb1c6abdb91c1448))
12
+ * **finance:** expand invoice audit review and filters ([c346cac](https://github.com/tutur3u/platform/commit/c346cac5a2dfcdcd944d1fcdfa72f40ec27aa720))
13
+ * **pricing:** add full app comparison and evolving pitch deck ([c967e8d](https://github.com/tutur3u/platform/commit/c967e8d2db75fc65159c7dcb31ed1b27673ae924))
14
+ * **pricing:** compare every app and add an evolving pitch deck ([#5335](https://github.com/tutur3u/platform/issues/5335)) ([962ed75](https://github.com/tutur3u/platform/commit/962ed75e086eb85a06a878720a5d30b747e7ba82))
15
+ * **pricing:** redesign the product comparison experience ([6adc1cf](https://github.com/tutur3u/platform/commit/6adc1cf3388c4f02c4375695377778c25696b775)) ([#5348](https://github.com/tutur3u/platform/issues/5348)) ([2232af1](https://github.com/tutur3u/platform/commit/2232af1738475629d2fb9a8a5b4578f8ce6ec77e))
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * **calendar:** clear recovered sync attention state ([bbf22be](https://github.com/tutur3u/platform/commit/bbf22bed0034518cd62d6dc063c30dd210ed2adb))
21
+ * **calendar:** coordinate sync requests and recovery timing ([a1ddf89](https://github.com/tutur3u/platform/commit/a1ddf89570ec0f917d4bcb3cd0f9a1302e9d72c1))
22
+ * **calendar:** preserve recovery alerts during automatic sync ([04b2a1d](https://github.com/tutur3u/platform/commit/04b2a1d22400d20b922edf8d8372700ab490b9af))
23
+ * **calendar:** refresh cached events after remote synchronization ([f59f126](https://github.com/tutur3u/platform/commit/f59f12646c255bbc8a0944701299102d6ff14fe7))
24
+ * **calendar:** use public calendar API type exports ([ac23511](https://github.com/tutur3u/platform/commit/ac23511863ae7c2713da411651cd6e67fa92d153))
25
+ * **deps:** align React types and published consumer ranges ([3612cd8](https://github.com/tutur3u/platform/commit/3612cd81723fb5a6982152688227ed21bc4095fd))
26
+ * **deps:** preserve React peer compatibility and clarify audit ([777b9ed](https://github.com/tutur3u/platform/commit/777b9ed7f42095bb9361e6bed94d989310c222de))
27
+ * **finance:** complete invoice loading recovery ([5f4cd04](https://github.com/tutur3u/platform/commit/5f4cd049ab462e774d09c7060878bdedda164d12))
28
+ * **finance:** expose audit amount visibility control ([d3ef238](https://github.com/tutur3u/platform/commit/d3ef2389b1fd189f5b7cd327d1e0b65d03b7b136))
29
+ * **finance:** preserve discount display across invoice views ([11eda37](https://github.com/tutur3u/platform/commit/11eda372d53c60041c676e1e8f9ca0ad06809b13))
30
+ * **finance:** preserve discounts in checkout and saved invoice views ([#5378](https://github.com/tutur3u/platform/issues/5378)) ([2297145](https://github.com/tutur3u/platform/commit/2297145c59d6dbec174e5e22bf69f2fd2b54695b))
31
+ * **finance:** recover stalled invoice loading ([e943337](https://github.com/tutur3u/platform/commit/e94333766ddf942f9c44347d6f7fc982f4f828a8)) ([#5310](https://github.com/tutur3u/platform/issues/5310)) ([a5c6a37](https://github.com/tutur3u/platform/commit/a5c6a3765008e1fb503d6e2ceadec9c43b1e23e5))
32
+ * **finance:** retain actors across invoice audit writes ([75e1139](https://github.com/tutur3u/platform/commit/75e11390aa30493ee1f83f95660cfaf7547e13c0)) ([#5383](https://github.com/tutur3u/platform/issues/5383)) ([a1fbb54](https://github.com/tutur3u/platform/commit/a1fbb54532f652116064ab7d7b8d11b217b2b9d4))
33
+ * **finance:** speed up invoice audit history and improve pagination ([b6c165e](https://github.com/tutur3u/platform/commit/b6c165e88e8888facec7744ee16c1d9378bb90e5)) ([#5380](https://github.com/tutur3u/platform/issues/5380)) ([c829653](https://github.com/tutur3u/platform/commit/c8296532b5282324b28c09d3c06a64894694b46c))
34
+ * **mail:** preview and download PDF attachments ([#5339](https://github.com/tutur3u/platform/issues/5339)) ([cc0ca86](https://github.com/tutur3u/platform/commit/cc0ca865269e9a43fbb88a513998a4c6243b773b))
35
+ * **mail:** render PDF previews safely ([7f9f9c9](https://github.com/tutur3u/platform/commit/7f9f9c987523cea173fc96213028ee52e0e488af))
36
+ * **mira:** preserve conversation chronology and open requested artifacts ([f8d4f86](https://github.com/tutur3u/platform/commit/f8d4f8616919baf6f878c6eb71836acc48c8933f)) ([#5331](https://github.com/tutur3u/platform/issues/5331)) ([40155bd](https://github.com/tutur3u/platform/commit/40155bd97ebe23b3c4ccbcde88c998c173b2bf7f))
37
+ * **notifications:** replace denied realtime filters with API refresh ([35293ac](https://github.com/tutur3u/platform/commit/35293ac06517c63689780351facec22a93c8da3b))
38
+ * **notifications:** stop invalid user_id realtime filters ([#5377](https://github.com/tutur3u/platform/issues/5377)) ([1c4ab1f](https://github.com/tutur3u/platform/commit/1c4ab1fe9830cfd18fbe98c10b0fbe1d6de168a3))
39
+ * **pricing:** polish comparison sizing and style types ([404f3f8](https://github.com/tutur3u/platform/commit/404f3f854ef6c59c015f41256687cbf920806a08))
40
+ * **pricing:** reconcile live catalog displays and tier comparisons ([3aa65c2](https://github.com/tutur3u/platform/commit/3aa65c2221d0d099ff5bd50de0c90bb4237d1bbd))
41
+ * **reports:** clarify delivery and streamline review filters ([b790cb3](https://github.com/tutur3u/platform/commit/b790cb38e48cf7429a698d6360977e35a9aa2617)) ([#5314](https://github.com/tutur3u/platform/issues/5314)) ([e9af5a5](https://github.com/tutur3u/platform/commit/e9af5a58f0c133764e91c745b183eae24e512270))
42
+ * **reports:** validate filters and legacy approval states ([d86bd68](https://github.com/tutur3u/platform/commit/d86bd6814986895962fc72dec7dee89570c9269b))
43
+ * **tasks:** keep synced checklists and board state interactive ([63761b5](https://github.com/tutur3u/platform/commit/63761b59aa8abe99c0e48f1694a1fa0573bdcffa)) ([#5379](https://github.com/tutur3u/platform/issues/5379)) ([c647460](https://github.com/tutur3u/platform/commit/c64746019a2e18798e71f0c5cfbf8bff13a58485))
44
+ * **tasks:** restore checklist controls and board drag UX ([72d2495](https://github.com/tutur3u/platform/commit/72d2495717f7550f2ca4c26234abd2ceebbc280c)) ([#5375](https://github.com/tutur3u/platform/issues/5375)) ([fd9ed4e](https://github.com/tutur3u/platform/commit/fd9ed4ef63272cc2a434ad72aa1081fa641055c2))
45
+ * **ui:** ensure report pagination always consumes text ([2f91cb9](https://github.com/tutur3u/platform/commit/2f91cb9e03cf9fd9432daeb76244e33805bb3da6))
46
+ * **ui:** explain offline installation state in settings ([17b8936](https://github.com/tutur3u/platform/commit/17b89364510266d459e8836c92a2b39a6923c4d5))
47
+ * **ui:** move app installation into settings ([ffa82a1](https://github.com/tutur3u/platform/commit/ffa82a12e0eba196cc800cf1c2f1ef78819d5d70)) ([#5327](https://github.com/tutur3u/platform/issues/5327)) ([17034ef](https://github.com/tutur3u/platform/commit/17034efe29de99bdbf4d6ee76ed9bf1c5f1d4ff7))
48
+ * **ui:** prevent report pagination from freezing editors ([#5392](https://github.com/tutur3u/platform/issues/5392)) ([efe6e95](https://github.com/tutur3u/platform/commit/efe6e95205134df4fc5b10b9e48b4dafb7dce52b))
49
+ * **ui:** repair checklist caret and status controls ([a6472ce](https://github.com/tutur3u/platform/commit/a6472ce49c557992966e31ed2e92e2d7cb65b573)) ([#5350](https://github.com/tutur3u/platform/issues/5350)) ([c534362](https://github.com/tutur3u/platform/commit/c534362b5a68965a13403056568f975852213f45))
50
+ * **ui:** reset disabled checklist picker ([c059cae](https://github.com/tutur3u/platform/commit/c059cae8d9c46f4ac15a35ccebac2738eeb1f565))
51
+
52
+ ## [0.32.0](https://github.com/tutur3u/platform/compare/ui-v0.31.0...ui-v0.32.0) (2026-09-09)
53
+
54
+
55
+ ### Features
56
+
57
+ * **meet:** give Mira a distinct identity and refine call panels ([#5269](https://github.com/tutur3u/platform/issues/5269)) ([6ba3f1c](https://github.com/tutur3u/platform/commit/6ba3f1c5e2408ae0a564c97177282978f38b4ce8))
58
+ * **meet:** polish assistant identity and call panels ([2d2098b](https://github.com/tutur3u/platform/commit/2d2098b8923d58f6c094fe02cf1de142178b5433))
59
+
3
60
  ## [0.31.0](https://github.com/tutur3u/platform/compare/ui-v0.30.2...ui-v0.31.0) (2026-09-07)
4
61
 
5
62
 
package/biome.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "root": false,
3
- "$schema": "https://biomejs.dev/schemas/2.5.12/schema.json",
3
+ "$schema": "https://biomejs.dev/schemas/2.5.13/schema.json",
4
4
  "extends": "//"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuturuuu/ui",
3
- "version": "0.31.0",
3
+ "version": "0.33.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -59,41 +59,41 @@
59
59
  "@tanstack/react-pacer": "^0.23.0",
60
60
  "@tanstack/react-query": "^5.102.8",
61
61
  "@tanstack/react-table": "^9.2.3",
62
- "@tanstack/react-virtual": "^3.14.10",
63
- "@tiptap/core": "3.31.2",
64
- "@tiptap/extension-collaboration": "3.31.2",
65
- "@tiptap/extension-collaboration-caret": "3.31.2",
66
- "@tiptap/extension-color": "3.31.2",
67
- "@tiptap/extension-details": "3.31.2",
68
- "@tiptap/extension-drag-handle": "3.31.2",
69
- "@tiptap/extension-drag-handle-react": "3.31.2",
70
- "@tiptap/extension-highlight": "3.31.2",
71
- "@tiptap/extension-horizontal-rule": "3.31.2",
72
- "@tiptap/extension-image": "3.31.2",
73
- "@tiptap/extension-link": "3.31.2",
74
- "@tiptap/extension-list": "3.31.2",
75
- "@tiptap/extension-node-range": "3.31.2",
76
- "@tiptap/extension-placeholder": "3.31.2",
77
- "@tiptap/extension-strike": "3.31.2",
78
- "@tiptap/extension-subscript": "3.31.2",
79
- "@tiptap/extension-superscript": "3.31.2",
80
- "@tiptap/extension-table": "3.31.2",
81
- "@tiptap/extension-table-cell": "3.31.2",
82
- "@tiptap/extension-table-header": "3.31.2",
83
- "@tiptap/extension-table-row": "3.31.2",
84
- "@tiptap/extension-text-align": "3.31.2",
85
- "@tiptap/extension-text-style": "3.31.2",
86
- "@tiptap/extension-youtube": "3.31.2",
87
- "@tiptap/pm": "3.31.2",
88
- "@tiptap/react": "3.31.2",
89
- "@tiptap/starter-kit": "3.31.2",
90
- "@tuturuuu/ai": "0.9.0",
91
- "@tuturuuu/apis": "0.11.3",
92
- "@tuturuuu/hooks": "0.1.1",
93
- "@tuturuuu/icons": "0.1.0",
94
- "@tuturuuu/internal-api": "0.34.0",
95
- "@tuturuuu/supabase": "0.5.1",
96
- "@tuturuuu/utils": "0.28.0",
62
+ "@tanstack/react-virtual": "^3.14.12",
63
+ "@tiptap/core": "3.31.3",
64
+ "@tiptap/extension-collaboration": "3.31.3",
65
+ "@tiptap/extension-collaboration-caret": "3.31.3",
66
+ "@tiptap/extension-color": "3.31.3",
67
+ "@tiptap/extension-details": "3.31.3",
68
+ "@tiptap/extension-drag-handle": "3.31.3",
69
+ "@tiptap/extension-drag-handle-react": "3.31.3",
70
+ "@tiptap/extension-highlight": "3.31.3",
71
+ "@tiptap/extension-horizontal-rule": "3.31.3",
72
+ "@tiptap/extension-image": "3.31.3",
73
+ "@tiptap/extension-link": "3.31.3",
74
+ "@tiptap/extension-list": "3.31.3",
75
+ "@tiptap/extension-node-range": "3.31.3",
76
+ "@tiptap/extension-placeholder": "3.31.3",
77
+ "@tiptap/extension-strike": "3.31.3",
78
+ "@tiptap/extension-subscript": "3.31.3",
79
+ "@tiptap/extension-superscript": "3.31.3",
80
+ "@tiptap/extension-table": "3.31.3",
81
+ "@tiptap/extension-table-cell": "3.31.3",
82
+ "@tiptap/extension-table-header": "3.31.3",
83
+ "@tiptap/extension-table-row": "3.31.3",
84
+ "@tiptap/extension-text-align": "3.31.3",
85
+ "@tiptap/extension-text-style": "3.31.3",
86
+ "@tiptap/extension-youtube": "3.31.3",
87
+ "@tiptap/pm": "3.31.3",
88
+ "@tiptap/react": "3.31.3",
89
+ "@tiptap/starter-kit": "3.31.3",
90
+ "@tuturuuu/ai": "0.14.0",
91
+ "@tuturuuu/apis": "0.11.4",
92
+ "@tuturuuu/hooks": "0.1.2",
93
+ "@tuturuuu/icons": "0.1.1",
94
+ "@tuturuuu/internal-api": "0.39.0",
95
+ "@tuturuuu/supabase": "0.5.2",
96
+ "@tuturuuu/utils": "0.29.0",
97
97
  "@types/debug": "^4.1.13",
98
98
  "browser-image-compression": "^2.0.2",
99
99
  "class-variance-authority": "^0.7.1",
@@ -108,14 +108,14 @@
108
108
  "framer-motion": "^13.2.0",
109
109
  "gsap": "^3.15.0",
110
110
  "html-entities": "^2.6.0",
111
- "html2canvas-pro": "^2.4.1",
111
+ "html2canvas-pro": "^2.4.2",
112
112
  "input-otp": "^1.5.0",
113
- "katex": "^0.18.5",
113
+ "katex": "^0.18.7",
114
114
  "lodash": "4.18.1",
115
115
  "moment": "^2.30.1",
116
116
  "motion": "^13.2.0",
117
- "next": "^16.3.4",
118
- "next-intl": "^4.14.2",
117
+ "next": "^16.3.5",
118
+ "next-intl": "^4.14.4",
119
119
  "next-themes": "^0.4.6",
120
120
  "nuqs": "^2.10.1",
121
121
  "prosemirror-state": "^1.4.4",
@@ -126,12 +126,12 @@
126
126
  "react-day-picker": "^10.0.1",
127
127
  "react-dom": "^19.2.8",
128
128
  "react-dropzone": "^20.1.1",
129
- "react-hook-form": "^7.87.0",
129
+ "react-hook-form": "^7.88.0",
130
130
  "react-markdown": "^10.1.0",
131
131
  "react-papaparse": "^4.4.0",
132
- "react-pdf": "^10.5.0",
132
+ "react-pdf": "^11.0.0",
133
133
  "react-resizable": "^4.0.2",
134
- "react-resizable-panels": "^4.12.3",
134
+ "react-resizable-panels": "^4.12.4",
135
135
  "react-syntax-highlighter": "^16.1.1",
136
136
  "recharts": "3.10.1",
137
137
  "slot-text": "^0.3.4",
@@ -140,12 +140,12 @@
140
140
  "tailwind-scrollbar": "^4.0.2",
141
141
  "tailwind-scrollbar-hide": "^4.0.0",
142
142
  "tailwindcss-animate": "^1.0.7",
143
- "tiptap-extension-resize-image": "^1.4.6",
143
+ "tiptap-extension-resize-image": "^1.4.7",
144
144
  "use-debounce": "^10.1.1",
145
145
  "vaul": "^1.1.2",
146
146
  "y-protocols": "^1.0.7",
147
147
  "yjs": "^13.6.32",
148
- "zod": "^4.5.4"
148
+ "zod": "^4.6.2"
149
149
  },
150
150
  "devDependencies": {
151
151
  "@tailwindcss/postcss": "^4.3.3",
@@ -154,18 +154,18 @@
154
154
  "@tanstack/react-table": "^9.2.4",
155
155
  "@testing-library/jest-dom": "^7.0.1",
156
156
  "@testing-library/react": "^16.3.3",
157
- "@tuturuuu/types": "0.29.0",
157
+ "@tuturuuu/types": "0.31.0",
158
158
  "@tuturuuu/typescript-config": "0.1.2",
159
159
  "@types/html2canvas": "^1.0.0",
160
160
  "@types/lodash": "^4.17.25",
161
- "@types/node": "^26.4.1",
162
- "@types/react": "^19.2.18",
163
- "@types/react-dom": "^19.2.7",
161
+ "@types/node": "^26.5.1",
162
+ "@types/react": "~19.2.18",
163
+ "@types/react-dom": "~19.2.7",
164
164
  "@types/react-resizable": "^4.0.0",
165
165
  "@types/react-syntax-highlighter": "^15.5.13",
166
166
  "@types/uuid": "^11.0.0",
167
167
  "@vitejs/plugin-react": "^6.1.1",
168
- "autoprefixer": "^10.5.4",
168
+ "autoprefixer": "^10.6.0",
169
169
  "jsdom": "^30.0.1",
170
170
  "postcss": "^8.5.28",
171
171
  "postcss-load-config": "^6.0.1",
@@ -493,7 +493,9 @@
493
493
  "./custom/satellite-settings-dialog-shell": "./src/components/ui/custom/satellite-settings-dialog-shell.tsx",
494
494
  "./custom/satellite-onboarding-settings-panel": "./src/components/ui/custom/satellite-onboarding-settings-panel.tsx",
495
495
  "./custom/satellite-notification-popover": "./src/components/ui/custom/satellite-notification-popover.tsx",
496
- "./custom/notification-runtime": "./src/components/ui/custom/notification-runtime.tsx"
496
+ "./custom/notification-runtime": "./src/components/ui/custom/notification-runtime.tsx",
497
+ "./finance/invoices/query-invalidation": "./src/components/ui/finance/invoices/query-invalidation.ts",
498
+ "./finance/shared/charts/use-finance-confidential-visibility": "./src/components/ui/finance/shared/charts/use-finance-confidential-visibility.ts"
497
499
  },
498
500
  "packageManager": "bun@1.4.1"
499
501
  }
@@ -1,4 +1,4 @@
1
- import { AlertTriangle } from '@tuturuuu/icons';
1
+ import { AlertTriangle, CalendarDays, RefreshCw } from '@tuturuuu/icons';
2
2
  import { useState } from 'react';
3
3
  import { Button } from '../../button';
4
4
  import {
@@ -10,7 +10,10 @@ import {
10
10
  DialogTrigger,
11
11
  } from '../../dialog';
12
12
  import { CalendarConnectionsSettingsContent } from './calendar-connections-settings-content';
13
- import { needsCalendarSyncAttention } from './calendar-sync-recovery';
13
+ import {
14
+ isCalendarSyncActive,
15
+ needsCalendarSyncAttention,
16
+ } from './calendar-sync-recovery';
14
17
  import type { CalendarConnectionsManagerState } from './use-calendar-connections-manager';
15
18
 
16
19
  /** Keep recovery visible when the sidebar replaces the header calendar picker. */
@@ -20,28 +23,59 @@ export function CalendarSyncAttentionButton({
20
23
  state: CalendarConnectionsManagerState;
21
24
  }) {
22
25
  const [open, setOpen] = useState(false);
23
- if (!open && !needsCalendarSyncAttention(state)) return null;
26
+ const syncing = isCalendarSyncActive(state);
27
+ const needsAttention = needsCalendarSyncAttention(state);
28
+
24
29
  return (
25
- <Dialog open={open} onOpenChange={setOpen}>
26
- <DialogTrigger asChild>
27
- <Button
28
- variant="outline"
29
- size="sm"
30
- className="gap-1.5 border-dynamic-orange/40 text-dynamic-orange"
31
- >
32
- <AlertTriangle className="size-4 shrink-0" />
33
- {state.t('sync_recovery.attention')}
34
- </Button>
35
- </DialogTrigger>
36
- <DialogContent className="max-h-[85dvh] overflow-y-auto sm:max-w-lg">
37
- <DialogHeader>
38
- <DialogTitle>{state.t('manage_calendar_accounts')}</DialogTitle>
39
- <DialogDescription>
40
- {state.t('manage_calendar_accounts_desc')}
41
- </DialogDescription>
42
- </DialogHeader>
43
- <CalendarConnectionsSettingsContent state={state} />
44
- </DialogContent>
45
- </Dialog>
30
+ <>
31
+ <span role="status" className="sr-only">
32
+ {needsAttention
33
+ ? state.t('sync_recovery.attention')
34
+ : syncing
35
+ ? state.t('syncing_calendars')
36
+ : ''}
37
+ </span>
38
+ {(open || syncing || needsAttention) && (
39
+ <Dialog open={open} onOpenChange={setOpen}>
40
+ <DialogTrigger asChild>
41
+ <Button
42
+ variant="outline"
43
+ size="sm"
44
+ className={
45
+ !needsAttention
46
+ ? 'gap-1.5 text-muted-foreground'
47
+ : 'gap-1.5 border-dynamic-orange/40 text-dynamic-orange'
48
+ }
49
+ >
50
+ {syncing && !needsAttention ? (
51
+ <RefreshCw className="size-4 shrink-0 animate-spin" />
52
+ ) : needsAttention ? (
53
+ <AlertTriangle className="size-4 shrink-0" />
54
+ ) : (
55
+ <CalendarDays className="size-4 shrink-0" />
56
+ )}
57
+ <span>
58
+ {state.t(
59
+ needsAttention
60
+ ? 'sync_recovery.attention'
61
+ : syncing
62
+ ? 'syncing_calendars'
63
+ : 'manage_calendar_accounts'
64
+ )}
65
+ </span>
66
+ </Button>
67
+ </DialogTrigger>
68
+ <DialogContent className="max-h-[85dvh] overflow-y-auto sm:max-w-lg">
69
+ <DialogHeader>
70
+ <DialogTitle>{state.t('manage_calendar_accounts')}</DialogTitle>
71
+ <DialogDescription>
72
+ {state.t('manage_calendar_accounts_desc')}
73
+ </DialogDescription>
74
+ </DialogHeader>
75
+ <CalendarConnectionsSettingsContent state={state} />
76
+ </DialogContent>
77
+ </Dialog>
78
+ )}
79
+ </>
46
80
  );
47
81
  }
@@ -1,11 +1,16 @@
1
1
  import { fireEvent, render, screen } from '@testing-library/react';
2
2
  import { describe, expect, it, vi } from 'vitest';
3
+ import { CalendarSyncAttentionButton } from './calendar-sync-attention-button';
3
4
  import {
4
5
  CalendarSyncRecovery,
5
6
  needsCalendarSyncAttention,
6
7
  } from './calendar-sync-recovery';
7
8
  import type { CalendarConnectionsManagerState } from './use-calendar-connections-manager';
8
9
 
10
+ vi.mock('./calendar-connections-settings-content', () => ({
11
+ CalendarConnectionsSettingsContent: () => <div>Settings</div>,
12
+ }));
13
+
9
14
  function state(overrides: Partial<CalendarConnectionsManagerState> = {}) {
10
15
  return {
11
16
  accounts: [],
@@ -110,3 +115,55 @@ it('can pause an identified calendar during the retry cooldown without deleting
110
115
  );
111
116
  expect(value.syncMutation.mutate).not.toHaveBeenCalled();
112
117
  });
118
+
119
+ it('shows neutral progress for an automatic sync instead of an attention warning', () => {
120
+ const value = state();
121
+ value.syncHealth!.state = 'syncing';
122
+ value.syncHealth!.currentlyRunning = true;
123
+ value.manualSyncDisabled = true;
124
+ render(<CalendarSyncRecovery state={value} />);
125
+ expect(screen.queryByText('sync_recovery.attention')).toBeNull();
126
+ expect(screen.getByRole('status')).toBeVisible();
127
+ expect(screen.queryByRole('alert')).toBeNull();
128
+ expect(screen.getByText('sync_recovery.syncing_description')).toBeVisible();
129
+ expect(
130
+ screen.getByRole('button', { name: 'syncing_calendars' })
131
+ ).toBeDisabled();
132
+ });
133
+
134
+ it('keeps an open settings dialog neutral when automatic syncing finishes', () => {
135
+ const value = state();
136
+ value.syncHealth!.currentlyRunning = true;
137
+ value.syncHealth!.state = 'syncing';
138
+ const view = render(<CalendarSyncAttentionButton state={value} />);
139
+ fireEvent.click(screen.getByRole('button', { name: 'syncing_calendars' }));
140
+ value.syncHealth!.currentlyRunning = false;
141
+ value.syncHealth!.state = 'healthy';
142
+ view.rerender(<CalendarSyncAttentionButton state={value} />);
143
+ expect(screen.getByRole('dialog')).toBeVisible();
144
+ expect(screen.queryByText('sync_recovery.attention')).toBeNull();
145
+ expect(screen.queryByText('syncing_calendars')).toBeNull();
146
+ });
147
+
148
+ it('keeps reconnection warnings prominent while another calendar syncs', () => {
149
+ const value = state({
150
+ providerAccountStatuses: { google: { state: 'reconnect_required' } },
151
+ });
152
+ value.syncHealth!.state = 'syncing';
153
+ value.syncHealth!.currentlyRunning = true;
154
+ render(<CalendarSyncRecovery state={value} />);
155
+ expect(screen.getByRole('alert')).toBeVisible();
156
+ expect(screen.getByText('sync_recovery.attention')).toBeVisible();
157
+ });
158
+
159
+ it('keeps the status live region mounted before syncing starts', () => {
160
+ const value = state();
161
+ value.syncHealth!.state = 'healthy';
162
+ const view = render(<CalendarSyncAttentionButton state={value} />);
163
+ const liveRegion = screen.getByRole('status');
164
+ expect(liveRegion).toHaveTextContent('');
165
+ value.syncHealth!.currentlyRunning = true;
166
+ view.rerender(<CalendarSyncAttentionButton state={value} />);
167
+ expect(screen.getByRole('status')).toBe(liveRegion);
168
+ expect(liveRegion).toHaveTextContent('syncing_calendars');
169
+ });
@@ -42,10 +42,17 @@ export function needsCalendarSyncAttention(
42
42
  );
43
43
  }
44
44
 
45
+ export function isCalendarSyncActive(
46
+ state: Pick<RecoveryState, 'syncMutation' | 'syncHealth'>
47
+ ) {
48
+ return !!(state.syncMutation.isPending || state.syncHealth?.currentlyRunning);
49
+ }
50
+
45
51
  export function CalendarSyncRecovery({ state }: { state: RecoveryState }) {
46
52
  const { t, syncHealth, syncStatusError, providerAccountStatuses } = state;
47
- if (!needsCalendarSyncAttention(state) && !state.syncMutation.isPending)
48
- return null;
53
+ const syncing = isCalendarSyncActive(state);
54
+ const needsAttention = needsCalendarSyncAttention(state);
55
+ if (!needsAttention && !syncing) return null;
49
56
  const reconnectAccounts = state.accounts.filter(
50
57
  (account) =>
51
58
  providerAccountStatuses[account.id]?.state === 'reconnect_required'
@@ -92,15 +99,26 @@ export function CalendarSyncRecovery({ state }: { state: RecoveryState }) {
92
99
  reconnectProviders.add(provider);
93
100
  }
94
101
  return (
95
- <Alert className="border-dynamic-orange/30 bg-dynamic-orange/5 text-foreground">
96
- <AlertTriangle className="size-4 text-dynamic-orange" />
97
- <AlertTitle>{t('sync_recovery.attention')}</AlertTitle>
102
+ <Alert
103
+ role={needsAttention ? 'alert' : 'status'}
104
+ className={
105
+ needsAttention
106
+ ? 'border-dynamic-orange/30 bg-dynamic-orange/5 text-foreground'
107
+ : 'border-border bg-muted/30 text-foreground'
108
+ }
109
+ >
110
+ {!needsAttention ? (
111
+ <RefreshCw className="size-4 animate-spin" />
112
+ ) : (
113
+ <AlertTriangle className="size-4 text-dynamic-orange" />
114
+ )}
115
+ <AlertTitle>
116
+ {t(needsAttention ? 'sync_recovery.attention' : 'syncing_calendars')}
117
+ </AlertTitle>
98
118
  <AlertDescription className="space-y-3">
99
119
  <p>
100
120
  {t(
101
- state.syncMutation.isPending
102
- ? 'sync_recovery.syncing_description'
103
- : description
121
+ needsAttention ? description : 'sync_recovery.syncing_description'
104
122
  )}
105
123
  </p>
106
124
  <p className="text-muted-foreground text-xs">
@@ -163,14 +181,10 @@ export function CalendarSyncRecovery({ state }: { state: RecoveryState }) {
163
181
  : state.syncMutation.mutate()
164
182
  }
165
183
  >
166
- <RefreshCw
167
- className={
168
- state.syncMutation.isPending ? 'size-4 animate-spin' : 'size-4'
169
- }
170
- />
184
+ <RefreshCw className={syncing ? 'size-4 animate-spin' : 'size-4'} />
171
185
  {syncStatusError
172
186
  ? t('sync_recovery.check_again')
173
- : state.syncMutation.isPending
187
+ : syncing
174
188
  ? t('syncing_calendars')
175
189
  : t('sync_now')}
176
190
  </Button>