@tuturuuu/ui 0.14.0 → 0.16.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 (86) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/biome.json +1 -1
  3. package/package.json +62 -62
  4. package/src/components/ui/custom/__tests__/settings-dialog-shell.test.tsx +12 -0
  5. package/src/components/ui/custom/__tests__/sidebar-context.test.tsx +93 -6
  6. package/src/components/ui/custom/loading-statistic-card.tsx +18 -0
  7. package/src/components/ui/custom/notification-popover-client.tsx +5 -1
  8. package/src/components/ui/custom/settings/keyboard-shortcuts-settings.test.tsx +34 -0
  9. package/src/components/ui/custom/settings/keyboard-shortcuts-settings.tsx +106 -0
  10. package/src/components/ui/custom/settings/sidebar-settings.tsx +18 -6
  11. package/src/components/ui/custom/settings-dialog-shell.tsx +18 -12
  12. package/src/components/ui/custom/sidebar-context.tsx +58 -3
  13. package/src/components/ui/custom/sidebar-remote-behavior-bridge.tsx +5 -3
  14. package/src/components/ui/custom/statistic-card.tsx +104 -0
  15. package/src/components/ui/custom/structure.test.tsx +29 -0
  16. package/src/components/ui/custom/structure.tsx +103 -88
  17. package/src/components/ui/finance/invoices/civil-month.ts +224 -0
  18. package/src/components/ui/finance/invoices/components/subscription-invoice-proposal.test.tsx +49 -0
  19. package/src/components/ui/finance/invoices/components/subscription-invoice-proposal.tsx +81 -0
  20. package/src/components/ui/finance/invoices/hooks/use-subscription-auto-selection.ts +8 -2
  21. package/src/components/ui/finance/invoices/new-invoice-page.test.tsx +90 -2
  22. package/src/components/ui/finance/invoices/new-invoice-page.tsx +40 -4
  23. package/src/components/ui/finance/invoices/pending-columns.test.ts +26 -0
  24. package/src/components/ui/finance/invoices/pending-columns.tsx +45 -14
  25. package/src/components/ui/finance/invoices/standard-invoice.test.ts +31 -0
  26. package/src/components/ui/finance/invoices/standard-invoice.tsx +33 -16
  27. package/src/components/ui/finance/invoices/subscription-invoice.test.tsx +331 -0
  28. package/src/components/ui/finance/invoices/subscription-invoice.tsx +53 -28
  29. package/src/components/ui/finance/invoices/utils.test.ts +84 -0
  30. package/src/components/ui/finance/invoices/utils.ts +56 -134
  31. package/src/components/ui/resizable.test.ts +15 -0
  32. package/src/components/ui/resizable.tsx +28 -6
  33. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/__tests__/bulk-mutations-move.test.tsx +62 -0
  34. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/use-kanban-dnd.test.ts +48 -0
  35. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/use-kanban-dnd.ts +32 -2
  36. package/src/components/ui/tu-do/boards/boardId/menus/__tests__/task-menus.test.tsx +41 -3
  37. package/src/components/ui/tu-do/boards/boardId/menus/task-due-date-menu.tsx +31 -10
  38. package/src/components/ui/tu-do/boards/boardId/menus/task-priority-menu.tsx +7 -5
  39. package/src/components/ui/tu-do/boards/boardId/menus/task-scheduling-menu.tsx +7 -5
  40. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-archive-visibility.test.ts +44 -0
  41. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-archive-visibility.ts +17 -0
  42. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.test.ts +2 -0
  43. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.ts +7 -0
  44. package/src/components/ui/tu-do/boards/boardId/task-card/task-card.tsx +44 -30
  45. package/src/components/ui/tu-do/my-tasks/__tests__/use-task-context-actions.test.ts +54 -0
  46. package/src/components/ui/tu-do/my-tasks/task-list-with-completion.tsx +43 -1
  47. package/src/components/ui/tu-do/my-tasks/use-task-context-actions.ts +33 -15
  48. package/src/components/ui/tu-do/progress/task-progress-leaderboards-panel.tsx +3 -3
  49. package/src/components/ui/tu-do/progress/task-progress-page.tsx +74 -28
  50. package/src/components/ui/tu-do/progress/task-progress-panels.tsx +12 -10
  51. package/src/components/ui/tu-do/projects/components/project-grid-card.tsx +22 -6
  52. package/src/components/ui/tu-do/projects/components/project-list-item.tsx +24 -8
  53. package/src/components/ui/tu-do/projects/projectId/components/__tests__/tasks-tab-layout.test.tsx +6 -0
  54. package/src/components/ui/tu-do/projects/projectId/components/tasks-tab.tsx +3 -1
  55. package/src/components/ui/tu-do/projects/projectId/task-project-detail-page-client.tsx +11 -3
  56. package/src/components/ui/tu-do/projects/projectId/task-project-detail.tsx +2 -0
  57. package/src/components/ui/tu-do/projects/projectId/types.ts +1 -0
  58. package/src/components/ui/tu-do/projects/task-projects-client.tsx +45 -1
  59. package/src/components/ui/tu-do/projects/types.ts +4 -1
  60. package/src/components/ui/tu-do/providers/task-dialog-provider.tsx +10 -0
  61. package/src/components/ui/tu-do/shared/__tests__/board-client.test.tsx +7 -1
  62. package/src/components/ui/tu-do/shared/__tests__/board-header.test.tsx +87 -2
  63. package/src/components/ui/tu-do/shared/__tests__/task-board-loading-state.test.tsx +27 -3
  64. package/src/components/ui/tu-do/shared/__tests__/task-dialog-manager.test.tsx +41 -3
  65. package/src/components/ui/tu-do/shared/__tests__/use-progressive-board-loader.test.tsx +54 -0
  66. package/src/components/ui/tu-do/shared/board-header.tsx +20 -0
  67. package/src/components/ui/tu-do/shared/task-board-loading-state.tsx +4 -4
  68. package/src/components/ui/tu-do/shared/task-dialog-manager.tsx +2 -0
  69. package/src/components/ui/tu-do/shared/task-edit-dialog/components/task-dialog-header.tsx +7 -0
  70. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/__tests__/use-task-mutations.test.tsx +231 -0
  71. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-mutations.ts +139 -68
  72. package/src/components/ui/tu-do/shared/task-edit-dialog/task-dialog-actions.test.tsx +68 -0
  73. package/src/components/ui/tu-do/shared/task-edit-dialog/task-dialog-actions.tsx +17 -0
  74. package/src/components/ui/tu-do/shared/task-edit-dialog.tsx +45 -23
  75. package/src/components/ui/tu-do/shared/task-row-actions-menu.test.tsx +138 -0
  76. package/src/components/ui/tu-do/shared/task-row-actions-menu.tsx +15 -9
  77. package/src/components/ui/tu-do/templates/client.tsx +97 -78
  78. package/src/components/ui/tu-do/templates/marketplace/client.tsx +171 -135
  79. package/src/components/ui/tu-do/templates/task-templates-hub.tsx +3 -0
  80. package/src/components/ui/tu-do/templates/templateId/client.tsx +24 -9
  81. package/src/components/ui/tu-do/templates/templateId/task-template-detail-page-client.tsx +8 -2
  82. package/src/hooks/__tests__/use-notifications-subscription.test.tsx +34 -0
  83. package/src/hooks/__tests__/use-task-actions.test.tsx +14 -39
  84. package/src/hooks/task-actions-personal-external.ts +12 -6
  85. package/src/hooks/use-notifications.ts +14 -2
  86. package/vitest.config.ts +4 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,83 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.16.0](https://github.com/tutur3u/platform/compare/ui-v0.15.0...ui-v0.16.0) (2026-07-11)
4
+
5
+
6
+ ### Features
7
+
8
+ * **contacts:** migrate reports + groups and complete the users cutover ([2ee89cd](https://github.com/tutur3u/platform/commit/2ee89cd2257c2a9824df53d4be99436416d85c13))
9
+ * **finance:** support prepaid subscription invoice ranges ([fa0f338](https://github.com/tutur3u/platform/commit/fa0f3388dfb3d3ea539a8d8bdc3f100f268542c6))
10
+ * **inventory:** add revenue share and category bundles ([20b2e1e](https://github.com/tutur3u/platform/commit/20b2e1e5302d1db275766b7b4b92d9bdf69de04a))
11
+ * **satellite:** open settings on Cmd/Ctrl+, in satellite apps ([841f425](https://github.com/tutur3u/platform/commit/841f42557dd49eb31fd797900b1ec6ade6642dba))
12
+ * **settings:** lazy load searchable settings availability ([78091c0](https://github.com/tutur3u/platform/commit/78091c0acd16609c695be80b7c47f7840a34d74a))
13
+ * **settings:** open settings dialog from sidebar ([f3d223f](https://github.com/tutur3u/platform/commit/f3d223fbe3b4ecc7c37b6f19645f6122ddfdf5b9))
14
+ * **tasks:** add board header loading skeleton ([73f1242](https://github.com/tutur3u/platform/commit/73f12421a9cd50c035a1c9940e152354b1974f26))
15
+ * **tasks:** add quick-create targeting and edge autoscroll ([f03e932](https://github.com/tutur3u/platform/commit/f03e9324b0cce18e9f9974cc8fe251bb58b686bd))
16
+ * **tasks:** add task templates ([8d0700a](https://github.com/tutur3u/platform/commit/8d0700ad255c7b5874bfa065575df6b1cde34063))
17
+ * **tasks:** allow archiving document tasks ([0c51941](https://github.com/tutur3u/platform/commit/0c519414101a3a21b4e33548517eef05143fdf8e))
18
+ * **tasks:** consolidate task settings ([982e0b9](https://github.com/tutur3u/platform/commit/982e0b927358a5d566a5e33e092bd387ec0a7b50))
19
+ * **tasks:** consolidate tasks entry and sidebar controls ([56e80eb](https://github.com/tutur3u/platform/commit/56e80eb5c60d4b4e56f2953c7978038f1ebe9c08))
20
+ * **tasks:** stabilize shared board realtime collaboration ([6028caf](https://github.com/tutur3u/platform/commit/6028caf50432fd4dcebdaa5a59284e50972b1aa3))
21
+
22
+
23
+ ### Bug Fixes
24
+
25
+ * **auth:** share account preference cookies ([8c1848a](https://github.com/tutur3u/platform/commit/8c1848a941c1b3f91337104c975e4bc0d8f68fc9))
26
+ * **cli:** preserve markdown tables in task descriptions ([9faf8ba](https://github.com/tutur3u/platform/commit/9faf8ba44b92565a9dfc2949c496654fc1fea9b3))
27
+ * **finance:** apply invoice defaults and i18n coverage ([a5a7a26](https://github.com/tutur3u/platform/commit/a5a7a26c5cf9f6479010624ace6a18dbeb87f0dd))
28
+ * **finance:** apply invoice defaults and i18n coverage ([97fabad](https://github.com/tutur3u/platform/commit/97fabad7b0815da7afa009fea6a5d1abb983c040))
29
+ * **finance:** stabilize subscription invoice checkout ([742c163](https://github.com/tutur3u/platform/commit/742c163bc8fa94acf3de03feb4ff3ef026419a4e))
30
+ * **mail:** stabilize layout and managed sender identity ([a22205e](https://github.com/tutur3u/platform/commit/a22205e98a8671ffb628586107de09a7ba8dd1c4))
31
+ * **settings:** resolve lazy search import for docker build ([8a6dc1b](https://github.com/tutur3u/platform/commit/8a6dc1b39fd675daaa9f9b24c60b975b044db724))
32
+ * **tasks:** compact due date menu summaries ([473ca52](https://github.com/tutur3u/platform/commit/473ca52acd752b16032d1635120063d250ba9bd0))
33
+ * **tasks:** default task boards to kanban ([477c12a](https://github.com/tutur3u/platform/commit/477c12aeee7644a28e6266f9c339e7ef5c3228bf))
34
+ * **tasks:** harden satellite task route hydration ([9d51a38](https://github.com/tutur3u/platform/commit/9d51a38ad948ebb398bec794f082f2bbf8d466cc))
35
+ * **tasks:** keep personal board moves on workspace route ([60e29b0](https://github.com/tutur3u/platform/commit/60e29b093314b3b185f3f63a69042a665644ed3d))
36
+ * **tasks:** keep personal moves off placement API ([d8c41d7](https://github.com/tutur3u/platform/commit/d8c41d790f5edbe637b9ce71bbd5040b7fddbfa5))
37
+ * **tasks:** match board name input surface ([2552733](https://github.com/tutur3u/platform/commit/2552733942f720bb1df0566f27753eb226115f3e))
38
+ * **tasks:** pad board header skeleton ([b0c5c0f](https://github.com/tutur3u/platform/commit/b0c5c0fea8871cac2603da6239b980c752b1c9f6))
39
+ * **tasks:** prevent description wipes during yjs hydration ([947f38c](https://github.com/tutur3u/platform/commit/947f38c6474d07b1fac1c44e166638bfc87260c0))
40
+ * **tasks:** refresh task template placeholders ([0c3c309](https://github.com/tutur3u/platform/commit/0c3c30935f67e3e64d548c8a13584fd597e887b8))
41
+ * **tasks:** repair settings data and i18n ([0159488](https://github.com/tutur3u/platform/commit/0159488ae5de1c4d98a7d804d47bf1d479ae60c9))
42
+ * **tasks:** resolve personal placement board from list ([ed52667](https://github.com/tutur3u/platform/commit/ed5266740092e2c5fd2e7be19d5015a63705bea1))
43
+ * **tasks:** resolve personal placement board from list ([14335af](https://github.com/tutur3u/platform/commit/14335af944f77b923be66c871c31f5fea79d61a4))
44
+ * **tasks:** restore satellite resource access ([ec5e0a8](https://github.com/tutur3u/platform/commit/ec5e0a8d75398047e0151ae2ac3cd9a25a4fd675))
45
+ * **tasks:** restore task dialog app-session requests ([69f83cb](https://github.com/tutur3u/platform/commit/69f83cb8730eaeb4d39c186bbf8593c73e3deb47))
46
+ * **tasks:** restore tracked task descriptions ([f892ae2](https://github.com/tutur3u/platform/commit/f892ae23dfec41c2d25649b97a628d8cdcd1fa5d))
47
+ * **tasks:** route native personal task moves normally ([5bbba3c](https://github.com/tutur3u/platform/commit/5bbba3c3f193e722cc87cdfe2eb2734f61442cd0))
48
+ * **tasks:** scroll kanban board at drag edges ([1053f6c](https://github.com/tutur3u/platform/commit/1053f6cc6db9788b7e184ed8bc7febdb2adacf97))
49
+ * **tasks:** support personal external terminal defaults ([50434cb](https://github.com/tutur3u/platform/commit/50434cb9849a65dd8c77f6b030b27a4bd76125e4))
50
+ * **tasks:** unify board loading skeleton ([eaf2b65](https://github.com/tutur3u/platform/commit/eaf2b65242201573b930d4df4695488d0a669f30))
51
+ * **ui:** preserve personal external task edits ([8e537e3](https://github.com/tutur3u/platform/commit/8e537e3787ad6854c0efe7792e9487647d73854e))
52
+ * **ui:** stabilize task property popover handoff ([8fb2e62](https://github.com/tutur3u/platform/commit/8fb2e62904d34a3ae7894bfbbb66c285fcf1a1bd))
53
+
54
+ ## [0.15.0](https://github.com/tutur3u/platform/compare/ui-v0.14.0...ui-v0.15.0) (2026-07-11)
55
+
56
+
57
+ ### Features
58
+
59
+ * **contacts:** migrate reports + groups and complete the users cutover ([2ee89cd](https://github.com/tutur3u/platform/commit/2ee89cd2257c2a9824df53d4be99436416d85c13))
60
+ * **tasks:** allow archiving document tasks ([0c51941](https://github.com/tutur3u/platform/commit/0c519414101a3a21b4e33548517eef05143fdf8e))
61
+ * **tasks:** consolidate task settings ([982e0b9](https://github.com/tutur3u/platform/commit/982e0b927358a5d566a5e33e092bd387ec0a7b50))
62
+ * **tasks:** consolidate tasks entry and sidebar controls ([56e80eb](https://github.com/tutur3u/platform/commit/56e80eb5c60d4b4e56f2953c7978038f1ebe9c08))
63
+
64
+
65
+ ### Bug Fixes
66
+
67
+ * **auth:** share account preference cookies ([8c1848a](https://github.com/tutur3u/platform/commit/8c1848a941c1b3f91337104c975e4bc0d8f68fc9))
68
+ * **finance:** apply invoice defaults and i18n coverage ([a5a7a26](https://github.com/tutur3u/platform/commit/a5a7a26c5cf9f6479010624ace6a18dbeb87f0dd))
69
+ * **finance:** apply invoice defaults and i18n coverage ([97fabad](https://github.com/tutur3u/platform/commit/97fabad7b0815da7afa009fea6a5d1abb983c040))
70
+ * **finance:** stabilize subscription invoice checkout ([742c163](https://github.com/tutur3u/platform/commit/742c163bc8fa94acf3de03feb4ff3ef026419a4e))
71
+ * **mail:** stabilize layout and managed sender identity ([a22205e](https://github.com/tutur3u/platform/commit/a22205e98a8671ffb628586107de09a7ba8dd1c4))
72
+ * **tasks:** compact due date menu summaries ([473ca52](https://github.com/tutur3u/platform/commit/473ca52acd752b16032d1635120063d250ba9bd0))
73
+ * **tasks:** repair settings data and i18n ([0159488](https://github.com/tutur3u/platform/commit/0159488ae5de1c4d98a7d804d47bf1d479ae60c9))
74
+ * **tasks:** resolve personal placement board from list ([ed52667](https://github.com/tutur3u/platform/commit/ed5266740092e2c5fd2e7be19d5015a63705bea1))
75
+ * **tasks:** resolve personal placement board from list ([14335af](https://github.com/tutur3u/platform/commit/14335af944f77b923be66c871c31f5fea79d61a4))
76
+ * **tasks:** restore task dialog app-session requests ([69f83cb](https://github.com/tutur3u/platform/commit/69f83cb8730eaeb4d39c186bbf8593c73e3deb47))
77
+ * **tasks:** support personal external terminal defaults ([50434cb](https://github.com/tutur3u/platform/commit/50434cb9849a65dd8c77f6b030b27a4bd76125e4))
78
+ * **tasks:** unify board loading skeleton ([eaf2b65](https://github.com/tutur3u/platform/commit/eaf2b65242201573b930d4df4695488d0a669f30))
79
+ * **ui:** preserve personal external task edits ([8e537e3](https://github.com/tutur3u/platform/commit/8e537e3787ad6854c0efe7792e9487647d73854e))
80
+
3
81
  ## [0.14.0](https://github.com/tutur3u/platform/compare/ui-v0.13.0...ui-v0.14.0) (2026-07-06)
4
82
 
5
83
 
package/biome.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "root": false,
3
- "$schema": "https://biomejs.dev/schemas/2.5.1/schema.json",
3
+ "$schema": "https://biomejs.dev/schemas/2.5.3/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.14.0",
3
+ "version": "0.16.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,33 +24,33 @@
24
24
  "@hookform/resolvers": "^5.4.0",
25
25
  "@json-render/core": "^0.19.0",
26
26
  "@json-render/react": "^0.19.0",
27
- "@radix-ui/react-accordion": "^1.2.15",
28
- "@radix-ui/react-alert-dialog": "^1.1.18",
27
+ "@radix-ui/react-accordion": "^1.2.16",
28
+ "@radix-ui/react-alert-dialog": "^1.1.19",
29
29
  "@radix-ui/react-aspect-ratio": "^1.1.11",
30
- "@radix-ui/react-avatar": "^1.2.1",
31
- "@radix-ui/react-checkbox": "^1.3.6",
32
- "@radix-ui/react-collapsible": "^1.1.15",
33
- "@radix-ui/react-context-menu": "^2.3.2",
34
- "@radix-ui/react-dialog": "^1.1.18",
35
- "@radix-ui/react-dropdown-menu": "^2.1.19",
36
- "@radix-ui/react-hover-card": "^1.1.18",
30
+ "@radix-ui/react-avatar": "^1.2.2",
31
+ "@radix-ui/react-checkbox": "^1.3.7",
32
+ "@radix-ui/react-collapsible": "^1.1.16",
33
+ "@radix-ui/react-context-menu": "^2.3.3",
34
+ "@radix-ui/react-dialog": "^1.1.19",
35
+ "@radix-ui/react-dropdown-menu": "^2.1.20",
36
+ "@radix-ui/react-hover-card": "^1.1.19",
37
37
  "@radix-ui/react-label": "^2.1.11",
38
- "@radix-ui/react-menubar": "^1.1.19",
39
- "@radix-ui/react-navigation-menu": "^1.2.17",
40
- "@radix-ui/react-popover": "^1.1.18",
41
- "@radix-ui/react-progress": "^1.1.11",
42
- "@radix-ui/react-radio-group": "^1.4.2",
43
- "@radix-ui/react-scroll-area": "^1.2.13",
44
- "@radix-ui/react-select": "^2.3.2",
38
+ "@radix-ui/react-menubar": "^1.1.20",
39
+ "@radix-ui/react-navigation-menu": "^1.2.18",
40
+ "@radix-ui/react-popover": "^1.1.19",
41
+ "@radix-ui/react-progress": "^1.1.12",
42
+ "@radix-ui/react-radio-group": "^1.4.3",
43
+ "@radix-ui/react-scroll-area": "^1.2.14",
44
+ "@radix-ui/react-select": "^2.3.3",
45
45
  "@radix-ui/react-separator": "^1.1.11",
46
- "@radix-ui/react-slider": "^1.4.2",
46
+ "@radix-ui/react-slider": "^1.4.3",
47
47
  "@radix-ui/react-slot": "^1.3.0",
48
- "@radix-ui/react-switch": "^1.3.2",
49
- "@radix-ui/react-tabs": "^1.1.16",
50
- "@radix-ui/react-toast": "^1.2.18",
51
- "@radix-ui/react-toggle": "^1.1.13",
52
- "@radix-ui/react-toggle-group": "^1.1.14",
53
- "@radix-ui/react-tooltip": "^1.2.11",
48
+ "@radix-ui/react-switch": "^1.3.3",
49
+ "@radix-ui/react-tabs": "^1.1.17",
50
+ "@radix-ui/react-toast": "^1.2.19",
51
+ "@radix-ui/react-toggle": "^1.1.14",
52
+ "@radix-ui/react-toggle-group": "^1.1.15",
53
+ "@radix-ui/react-tooltip": "^1.2.12",
54
54
  "@streamdown/cjk": "^1.0.3",
55
55
  "@streamdown/code": "^1.1.1",
56
56
  "@streamdown/math": "^1.0.2",
@@ -60,37 +60,37 @@
60
60
  "@tanstack/react-query": "^5.101.2",
61
61
  "@tanstack/react-table": "^8.21.3",
62
62
  "@tanstack/react-virtual": "^3.14.5",
63
- "@tiptap/core": "3.27.1",
64
- "@tiptap/extension-collaboration": "3.27.1",
65
- "@tiptap/extension-collaboration-caret": "3.27.1",
66
- "@tiptap/extension-color": "3.27.1",
67
- "@tiptap/extension-drag-handle-react": "3.27.1",
68
- "@tiptap/extension-highlight": "3.27.1",
69
- "@tiptap/extension-horizontal-rule": "3.27.1",
70
- "@tiptap/extension-image": "3.27.1",
71
- "@tiptap/extension-link": "3.27.1",
72
- "@tiptap/extension-list": "3.27.1",
73
- "@tiptap/extension-placeholder": "3.27.1",
74
- "@tiptap/extension-strike": "3.27.1",
75
- "@tiptap/extension-subscript": "3.27.1",
76
- "@tiptap/extension-superscript": "3.27.1",
77
- "@tiptap/extension-table": "3.27.1",
78
- "@tiptap/extension-table-cell": "3.27.1",
79
- "@tiptap/extension-table-header": "3.27.1",
80
- "@tiptap/extension-table-row": "3.27.1",
81
- "@tiptap/extension-text-align": "3.27.1",
82
- "@tiptap/extension-text-style": "3.27.1",
83
- "@tiptap/extension-youtube": "3.27.1",
84
- "@tiptap/pm": "3.27.1",
85
- "@tiptap/react": "3.27.1",
86
- "@tiptap/starter-kit": "3.27.1",
63
+ "@tiptap/core": "3.27.3",
64
+ "@tiptap/extension-collaboration": "3.27.3",
65
+ "@tiptap/extension-collaboration-caret": "3.27.3",
66
+ "@tiptap/extension-color": "3.27.3",
67
+ "@tiptap/extension-drag-handle-react": "3.27.3",
68
+ "@tiptap/extension-highlight": "3.27.3",
69
+ "@tiptap/extension-horizontal-rule": "3.27.3",
70
+ "@tiptap/extension-image": "3.27.3",
71
+ "@tiptap/extension-link": "3.27.3",
72
+ "@tiptap/extension-list": "3.27.3",
73
+ "@tiptap/extension-placeholder": "3.27.3",
74
+ "@tiptap/extension-strike": "3.27.3",
75
+ "@tiptap/extension-subscript": "3.27.3",
76
+ "@tiptap/extension-superscript": "3.27.3",
77
+ "@tiptap/extension-table": "3.27.3",
78
+ "@tiptap/extension-table-cell": "3.27.3",
79
+ "@tiptap/extension-table-header": "3.27.3",
80
+ "@tiptap/extension-table-row": "3.27.3",
81
+ "@tiptap/extension-text-align": "3.27.3",
82
+ "@tiptap/extension-text-style": "3.27.3",
83
+ "@tiptap/extension-youtube": "3.27.3",
84
+ "@tiptap/pm": "3.27.3",
85
+ "@tiptap/react": "3.27.3",
86
+ "@tiptap/starter-kit": "3.27.3",
87
87
  "@tuturuuu/ai": "0.2.2",
88
- "@tuturuuu/apis": "0.7.2",
88
+ "@tuturuuu/apis": "0.9.0",
89
89
  "@tuturuuu/hooks": "0.0.2",
90
90
  "@tuturuuu/icons": "0.0.6",
91
- "@tuturuuu/internal-api": "0.15.0",
91
+ "@tuturuuu/internal-api": "0.17.0",
92
92
  "@tuturuuu/supabase": "0.4.0",
93
- "@tuturuuu/utils": "0.13.0",
93
+ "@tuturuuu/utils": "0.15.0",
94
94
  "@types/debug": "^4.1.13",
95
95
  "browser-image-compression": "^2.0.2",
96
96
  "class-variance-authority": "^0.7.1",
@@ -104,14 +104,14 @@
104
104
  "eventemitter3": "^5.0.4",
105
105
  "framer-motion": "^12.42.2",
106
106
  "gsap": "^3.15.0",
107
- "html2canvas-pro": "^2.2.1",
107
+ "html2canvas-pro": "^2.2.3",
108
108
  "input-otp": "^1.4.2",
109
109
  "katex": "^0.17.0",
110
110
  "lodash": "4.18.1",
111
111
  "moment": "^2.30.1",
112
112
  "motion": "^12.42.2",
113
113
  "next": "^16.3.0-preview.5",
114
- "next-intl": "^4.13.1",
114
+ "next-intl": "^4.13.2",
115
115
  "next-themes": "^0.4.6",
116
116
  "nuqs": "^2.9.0",
117
117
  "prosemirror-state": "^1.4.4",
@@ -121,20 +121,20 @@
121
121
  "react-day-picker": "^10.0.1",
122
122
  "react-dom": "^19.2.7",
123
123
  "react-dropzone": "^15.0.0",
124
- "react-hook-form": "^7.80.0",
124
+ "react-hook-form": "^7.81.0",
125
125
  "react-markdown": "^10.1.0",
126
126
  "react-papaparse": "^4.4.0",
127
127
  "react-pdf": "^10.4.1",
128
128
  "react-resizable": "^4.0.2",
129
- "react-resizable-panels": "^4.12.0",
129
+ "react-resizable-panels": "^4.12.1",
130
130
  "react-syntax-highlighter": "^16.1.1",
131
- "recharts": "3.9.1",
131
+ "recharts": "3.9.2",
132
132
  "sonner": "^2.0.7",
133
133
  "streamdown": "^2.5.0",
134
134
  "tailwind-scrollbar": "^4.0.2",
135
135
  "tailwind-scrollbar-hide": "^4.0.0",
136
136
  "tailwindcss-animate": "^1.0.7",
137
- "tiptap-extension-resize-image": "^1.4.3",
137
+ "tiptap-extension-resize-image": "^1.4.4",
138
138
  "use-debounce": "^10.1.1",
139
139
  "vaul": "^1.1.2",
140
140
  "xlsx": "file:vendor/xlsx-0.20.3.tgz",
@@ -149,11 +149,11 @@
149
149
  "@tanstack/react-table": "^8.21.3",
150
150
  "@testing-library/jest-dom": "^6.9.1",
151
151
  "@testing-library/react": "^16.3.2",
152
- "@tuturuuu/types": "0.14.0",
152
+ "@tuturuuu/types": "0.16.0",
153
153
  "@tuturuuu/typescript-config": "0.1.1",
154
154
  "@types/html2canvas": "^1.0.0",
155
155
  "@types/lodash": "^4.17.24",
156
- "@types/node": "^26.0.1",
156
+ "@types/node": "^26.1.1",
157
157
  "@types/react": "^19.2.17",
158
158
  "@types/react-dom": "^19.2.3",
159
159
  "@types/react-resizable": "^4.0.0",
@@ -162,12 +162,12 @@
162
162
  "@vitejs/plugin-react": "^6.0.3",
163
163
  "autoprefixer": "^10.5.2",
164
164
  "jsdom": "^29.1.1",
165
- "postcss": "^8.5.16",
165
+ "postcss": "^8.5.17",
166
166
  "postcss-load-config": "^6.0.1",
167
167
  "tailwindcss": "^4.3.2",
168
- "typescript": "7.0.1-rc",
168
+ "typescript": "7.0.2",
169
169
  "uuid": "^14.0.1",
170
- "vitest": "^4.1.9"
170
+ "vitest": "^4.1.10"
171
171
  },
172
172
  "peerDependencies": {
173
173
  "@tanstack/react-query": "^5.101.2",
@@ -46,6 +46,7 @@ const navItems: SettingsNavGroup[] = [
46
46
  },
47
47
  {
48
48
  description: 'Forms settings',
49
+ hideContentHeader: true,
49
50
  icon: TestIcon,
50
51
  label: 'Forms',
51
52
  name: 'forms',
@@ -167,4 +168,15 @@ describe('SettingsDialogShell keyboard navigation', () => {
167
168
 
168
169
  expect(screen.getByTestId('active-tab')).toHaveTextContent('profile');
169
170
  });
171
+
172
+ it('can hide the shell content header for page-like settings sections', () => {
173
+ renderShell();
174
+
175
+ const dialog = screen.getByRole('dialog');
176
+ fireEvent.keyDown(dialog, { altKey: true, key: 'End' });
177
+
178
+ expect(screen.getByTestId('active-tab')).toHaveTextContent('forms');
179
+ expect(screen.getAllByText('Forms').length).toBeGreaterThan(0);
180
+ expect(screen.queryByText('Forms settings')).not.toBeInTheDocument();
181
+ });
170
182
  });
@@ -1,9 +1,9 @@
1
1
  import { fireEvent, render, screen, waitFor } from '@testing-library/react';
2
2
  import { afterEach, describe, expect, it, vi } from 'vitest';
3
3
  import {
4
+ getSidebarCookieOptions,
4
5
  SIDEBAR_BEHAVIOR_COOKIE_NAME,
5
6
  SIDEBAR_BEHAVIOR_UPDATED_AT_COOKIE_NAME,
6
- SIDEBAR_COOKIE_OPTIONS,
7
7
  SidebarProvider,
8
8
  useSidebar,
9
9
  } from '../sidebar-context';
@@ -24,9 +24,12 @@ function SidebarHarness() {
24
24
  const { behavior, handleBehaviorChange } = useSidebar();
25
25
 
26
26
  return (
27
- <button type="button" onClick={() => handleBehaviorChange('collapsed')}>
28
- {behavior}
29
- </button>
27
+ <div>
28
+ <button type="button" onClick={() => handleBehaviorChange('collapsed')}>
29
+ {behavior}
30
+ </button>
31
+ <input aria-label="editable target" />
32
+ </div>
30
33
  );
31
34
  }
32
35
 
@@ -53,12 +56,96 @@ describe('SidebarProvider', () => {
53
56
  expect(mockSetCookie).toHaveBeenCalledWith(
54
57
  SIDEBAR_BEHAVIOR_COOKIE_NAME,
55
58
  'collapsed',
56
- SIDEBAR_COOKIE_OPTIONS
59
+ getSidebarCookieOptions()
57
60
  );
58
61
  expect(mockSetCookie).toHaveBeenCalledWith(
59
62
  SIDEBAR_BEHAVIOR_UPDATED_AT_COOKIE_NAME,
60
63
  '1234567890',
61
- SIDEBAR_COOKIE_OPTIONS
64
+ getSidebarCookieOptions()
65
+ );
66
+ });
67
+
68
+ it('toggles expanded and collapsed with Cmd/Ctrl+B', async () => {
69
+ vi.spyOn(Date, 'now').mockReturnValue(1_234_567_891);
70
+
71
+ render(
72
+ <SidebarProvider initialBehavior="expanded">
73
+ <SidebarHarness />
74
+ </SidebarProvider>
75
+ );
76
+
77
+ fireEvent.keyDown(window, { key: 'b', ctrlKey: true });
78
+
79
+ await waitFor(() =>
80
+ expect(screen.getByRole('button', { name: 'collapsed' })).toBeVisible()
81
+ );
82
+ expect(mockSetCookie).toHaveBeenCalledWith(
83
+ SIDEBAR_BEHAVIOR_COOKIE_NAME,
84
+ 'collapsed',
85
+ getSidebarCookieOptions()
86
+ );
87
+
88
+ fireEvent.keyDown(window, { key: 'b', metaKey: true });
89
+
90
+ await waitFor(() =>
91
+ expect(screen.getByRole('button', { name: 'expanded' })).toBeVisible()
92
+ );
93
+ });
94
+
95
+ it('hides the sidebar with Cmd/Ctrl+Alt+B', async () => {
96
+ vi.spyOn(Date, 'now').mockReturnValue(1_234_567_892);
97
+
98
+ render(
99
+ <SidebarProvider initialBehavior="expanded">
100
+ <SidebarHarness />
101
+ </SidebarProvider>
102
+ );
103
+
104
+ fireEvent.keyDown(window, { key: 'b', altKey: true, ctrlKey: true });
105
+
106
+ await waitFor(() =>
107
+ expect(screen.getByRole('button', { name: 'hidden' })).toBeVisible()
108
+ );
109
+ expect(mockSetCookie).toHaveBeenCalledWith(
110
+ SIDEBAR_BEHAVIOR_COOKIE_NAME,
111
+ 'hidden',
112
+ getSidebarCookieOptions()
113
+ );
114
+ });
115
+
116
+ it('changes hidden to collapsed with Cmd/Ctrl+B', async () => {
117
+ vi.spyOn(Date, 'now').mockReturnValue(1_234_567_893);
118
+
119
+ render(
120
+ <SidebarProvider initialBehavior="hidden">
121
+ <SidebarHarness />
122
+ </SidebarProvider>
123
+ );
124
+
125
+ fireEvent.keyDown(window, { key: 'b', ctrlKey: true });
126
+
127
+ await waitFor(() =>
128
+ expect(screen.getByRole('button', { name: 'collapsed' })).toBeVisible()
129
+ );
130
+ });
131
+
132
+ it('ignores sidebar hotkeys from editable targets', () => {
133
+ render(
134
+ <SidebarProvider initialBehavior="expanded">
135
+ <SidebarHarness />
136
+ </SidebarProvider>
137
+ );
138
+
139
+ fireEvent.keyDown(screen.getByLabelText('editable target'), {
140
+ key: 'b',
141
+ ctrlKey: true,
142
+ });
143
+
144
+ expect(screen.getByRole('button', { name: 'expanded' })).toBeVisible();
145
+ expect(mockSetCookie).not.toHaveBeenCalledWith(
146
+ SIDEBAR_BEHAVIOR_COOKIE_NAME,
147
+ 'collapsed',
148
+ expect.anything()
62
149
  );
63
150
  });
64
151
  });
@@ -0,0 +1,18 @@
1
+ import { cn } from '@tuturuuu/utils/format';
2
+
3
+ interface Props {
4
+ className?: string;
5
+ }
6
+
7
+ export default function LoadingStatisticCard({ className }: Props) {
8
+ return (
9
+ <div className={cn('group animate-pulse rounded-lg border', className)}>
10
+ <div className="p-1 text-center font-semibold text-lg text-transparent">
11
+ ...
12
+ </div>
13
+ <div className="m-2 mt-0 flex items-center justify-center rounded border border-foreground/5 bg-foreground/5 p-4 font-bold text-2xl text-transparent">
14
+ ...
15
+ </div>
16
+ </div>
17
+ );
18
+ }
@@ -110,19 +110,23 @@ export default function NotificationPopoverClient({
110
110
  : undefined;
111
111
 
112
112
  // Accurate unread count from dedicated endpoint
113
- const { data: unreadCount = 0 } = useUnreadCount(wsIdForFiltering);
113
+ const { data: unreadCount = 0 } = useUnreadCount(wsIdForFiltering, {
114
+ enabled: Boolean(userId),
115
+ });
114
116
 
115
117
  // Infinite scroll for inbox (unread) and archive (read)
116
118
  const inboxQuery = useInfiniteNotifications({
117
119
  wsId: wsIdForFiltering,
118
120
  unreadOnly: true,
119
121
  pageSize: 15,
122
+ enabled: Boolean(userId) && open && activeTab === 'inbox',
120
123
  });
121
124
 
122
125
  const archiveQuery = useInfiniteNotifications({
123
126
  wsId: wsIdForFiltering,
124
127
  readOnly: true,
125
128
  pageSize: 15,
129
+ enabled: Boolean(userId) && open && activeTab === 'archive',
126
130
  });
127
131
 
128
132
  const markAllAsRead = useMarkAllAsRead();
@@ -0,0 +1,34 @@
1
+ import '@testing-library/jest-dom';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { describe, expect, it, vi } from 'vitest';
4
+ import { KeyboardShortcutsSettings } from './keyboard-shortcuts-settings';
5
+
6
+ vi.mock('next-intl', () => ({
7
+ useTranslations:
8
+ (namespace?: string) =>
9
+ (key: string): string =>
10
+ namespace ? `${namespace}.${key}` : key,
11
+ }));
12
+
13
+ vi.mock('@tuturuuu/utils/hooks/use-platform', () => ({
14
+ usePlatform: () => ({
15
+ modKey: 'Ctrl',
16
+ modKeyAlt: 'Alt',
17
+ }),
18
+ }));
19
+
20
+ describe('KeyboardShortcutsSettings', () => {
21
+ it('renders sidebar shortcut rows with platform-aware key labels', () => {
22
+ render(<KeyboardShortcutsSettings />);
23
+
24
+ expect(
25
+ screen.getByText('settings.keyboard_shortcuts.toggle_sidebar')
26
+ ).toBeInTheDocument();
27
+ expect(
28
+ screen.getByText('settings.keyboard_shortcuts.hide_sidebar')
29
+ ).toBeInTheDocument();
30
+ expect(screen.getAllByText('Ctrl').length).toBeGreaterThanOrEqual(3);
31
+ expect(screen.getAllByText('Alt').length).toBeGreaterThanOrEqual(1);
32
+ expect(screen.getAllByText('B')).toHaveLength(2);
33
+ });
34
+ });
@@ -0,0 +1,106 @@
1
+ 'use client';
2
+
3
+ import { Kbd } from '@tuturuuu/ui/kbd';
4
+ import { usePlatform } from '@tuturuuu/utils/hooks/use-platform';
5
+ import { useTranslations } from 'next-intl';
6
+
7
+ interface ShortcutRow {
8
+ label: string;
9
+ keys: string[][];
10
+ }
11
+
12
+ function ShortcutKeys({ sequences }: { sequences: string[][] }) {
13
+ return (
14
+ <div className="flex flex-wrap items-center justify-end gap-2">
15
+ {sequences.map((sequence) => (
16
+ <div
17
+ className="inline-flex items-center gap-1"
18
+ key={sequence.join('+')}
19
+ >
20
+ {sequence.map((key) => (
21
+ <Kbd key={key}>{key}</Kbd>
22
+ ))}
23
+ </div>
24
+ ))}
25
+ </div>
26
+ );
27
+ }
28
+
29
+ function ShortcutGroup({
30
+ rows,
31
+ title,
32
+ }: {
33
+ rows: ShortcutRow[];
34
+ title: string;
35
+ }) {
36
+ return (
37
+ <section className="space-y-3">
38
+ <h3 className="font-medium text-sm">{title}</h3>
39
+ <div className="divide-y rounded-md border">
40
+ {rows.map((row) => (
41
+ <div
42
+ className="grid min-h-12 grid-cols-[minmax(0,1fr)_auto] items-center gap-4 px-3 py-2"
43
+ key={row.label}
44
+ >
45
+ <span className="text-sm">{row.label}</span>
46
+ <ShortcutKeys sequences={row.keys} />
47
+ </div>
48
+ ))}
49
+ </div>
50
+ </section>
51
+ );
52
+ }
53
+
54
+ export function KeyboardShortcutsSettings() {
55
+ const t = useTranslations('settings.keyboard_shortcuts');
56
+ const { modKey, modKeyAlt } = usePlatform();
57
+
58
+ const globalRows: ShortcutRow[] = [
59
+ {
60
+ label: t('open_settings'),
61
+ keys: [[modKey, ',']],
62
+ },
63
+ {
64
+ label: t('toggle_sidebar'),
65
+ keys: [[modKey, 'B']],
66
+ },
67
+ {
68
+ label: t('hide_sidebar'),
69
+ keys: [[modKey, modKeyAlt, 'B']],
70
+ },
71
+ ];
72
+
73
+ const dialogRows: ShortcutRow[] = [
74
+ {
75
+ label: t('search_settings'),
76
+ keys: [[modKey, 'F'], ['/']],
77
+ },
78
+ {
79
+ label: t('next_section'),
80
+ keys: [[modKeyAlt, 'Arrow Down']],
81
+ },
82
+ {
83
+ label: t('previous_section'),
84
+ keys: [[modKeyAlt, 'Arrow Up']],
85
+ },
86
+ {
87
+ label: t('first_section'),
88
+ keys: [[modKeyAlt, 'Home']],
89
+ },
90
+ {
91
+ label: t('last_section'),
92
+ keys: [[modKeyAlt, 'End']],
93
+ },
94
+ {
95
+ label: t('close_settings'),
96
+ keys: [['Esc']],
97
+ },
98
+ ];
99
+
100
+ return (
101
+ <div className="space-y-6">
102
+ <ShortcutGroup rows={globalRows} title={t('global')} />
103
+ <ShortcutGroup rows={dialogRows} title={t('settings_dialog')} />
104
+ </div>
105
+ );
106
+ }