@tuturuuu/ui 0.14.0 → 0.17.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 (101) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/biome.json +1 -1
  3. package/package.json +63 -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/storefront/browse-panel.tsx +161 -0
  34. package/src/components/ui/storefront/bundle-selection-dialog.tsx +1 -1
  35. package/src/components/ui/storefront/cart-popover.tsx +1 -1
  36. package/src/components/ui/storefront/hero-panel.tsx +35 -30
  37. package/src/components/ui/storefront/listing-card.tsx +10 -5
  38. package/src/components/ui/storefront/merch-sections.tsx +7 -5
  39. package/src/components/ui/storefront/product-detail.tsx +79 -6
  40. package/src/components/ui/storefront/product-dialog.tsx +5 -1
  41. package/src/components/ui/storefront/storefront-surface.test.tsx +72 -0
  42. package/src/components/ui/storefront/storefront-surface.tsx +67 -63
  43. package/src/components/ui/storefront/types.ts +28 -0
  44. package/src/components/ui/storefront/utils.ts +4 -5
  45. package/src/components/ui/tu-do/boards/boardId/board-column-external-retry.test.tsx +59 -1
  46. package/src/components/ui/tu-do/boards/boardId/board-column.tsx +37 -8
  47. package/src/components/ui/tu-do/boards/boardId/kanban/bulk/__tests__/bulk-mutations-move.test.tsx +62 -0
  48. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/use-kanban-dnd.test.ts +48 -0
  49. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/use-kanban-dnd.ts +32 -2
  50. package/src/components/ui/tu-do/boards/boardId/menus/__tests__/task-menus.test.tsx +41 -3
  51. package/src/components/ui/tu-do/boards/boardId/menus/task-due-date-menu.tsx +31 -10
  52. package/src/components/ui/tu-do/boards/boardId/menus/task-priority-menu.tsx +7 -5
  53. package/src/components/ui/tu-do/boards/boardId/menus/task-scheduling-menu.tsx +7 -5
  54. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-archive-visibility.test.ts +44 -0
  55. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-archive-visibility.ts +17 -0
  56. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.test.ts +2 -0
  57. package/src/components/ui/tu-do/boards/boardId/task-card/task-card-open-options.ts +7 -0
  58. package/src/components/ui/tu-do/boards/boardId/task-card/task-card.tsx +44 -30
  59. package/src/components/ui/tu-do/my-tasks/__tests__/use-task-context-actions.test.ts +54 -0
  60. package/src/components/ui/tu-do/my-tasks/task-list-with-completion.tsx +43 -1
  61. package/src/components/ui/tu-do/my-tasks/use-task-context-actions.ts +33 -15
  62. package/src/components/ui/tu-do/progress/task-progress-leaderboards-panel.tsx +3 -3
  63. package/src/components/ui/tu-do/progress/task-progress-page.tsx +60 -26
  64. package/src/components/ui/tu-do/progress/task-progress-panels.tsx +12 -10
  65. package/src/components/ui/tu-do/projects/components/project-grid-card.tsx +22 -6
  66. package/src/components/ui/tu-do/projects/components/project-list-item.tsx +24 -8
  67. package/src/components/ui/tu-do/projects/projectId/components/__tests__/tasks-tab-layout.test.tsx +6 -0
  68. package/src/components/ui/tu-do/projects/projectId/components/tasks-tab.tsx +3 -1
  69. package/src/components/ui/tu-do/projects/projectId/task-project-detail-page-client.tsx +11 -3
  70. package/src/components/ui/tu-do/projects/projectId/task-project-detail.tsx +2 -0
  71. package/src/components/ui/tu-do/projects/projectId/types.ts +1 -0
  72. package/src/components/ui/tu-do/projects/task-projects-client.tsx +45 -1
  73. package/src/components/ui/tu-do/projects/types.ts +4 -1
  74. package/src/components/ui/tu-do/providers/task-dialog-provider.tsx +10 -0
  75. package/src/components/ui/tu-do/shared/__tests__/board-client.test.tsx +7 -1
  76. package/src/components/ui/tu-do/shared/__tests__/board-header.test.tsx +87 -2
  77. package/src/components/ui/tu-do/shared/__tests__/task-board-loading-state.test.tsx +27 -3
  78. package/src/components/ui/tu-do/shared/__tests__/task-dialog-manager.test.tsx +41 -3
  79. package/src/components/ui/tu-do/shared/__tests__/use-progressive-board-loader.test.tsx +54 -0
  80. package/src/components/ui/tu-do/shared/board-header.tsx +20 -0
  81. package/src/components/ui/tu-do/shared/task-board-loading-state.tsx +4 -4
  82. package/src/components/ui/tu-do/shared/task-dialog-manager.tsx +2 -0
  83. package/src/components/ui/tu-do/shared/task-edit-dialog/components/task-dialog-header.tsx +7 -0
  84. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/__tests__/use-task-mutations.test.tsx +231 -0
  85. package/src/components/ui/tu-do/shared/task-edit-dialog/hooks/use-task-mutations.ts +139 -68
  86. package/src/components/ui/tu-do/shared/task-edit-dialog/task-dialog-actions.test.tsx +68 -0
  87. package/src/components/ui/tu-do/shared/task-edit-dialog/task-dialog-actions.tsx +17 -0
  88. package/src/components/ui/tu-do/shared/task-edit-dialog.tsx +45 -23
  89. package/src/components/ui/tu-do/shared/task-row-actions-menu.test.tsx +138 -0
  90. package/src/components/ui/tu-do/shared/task-row-actions-menu.tsx +15 -9
  91. package/src/components/ui/tu-do/templates/client.tsx +97 -78
  92. package/src/components/ui/tu-do/templates/marketplace/client.tsx +171 -135
  93. package/src/components/ui/tu-do/templates/task-templates-hub.tsx +3 -0
  94. package/src/components/ui/tu-do/templates/templateId/client.tsx +24 -9
  95. package/src/components/ui/tu-do/templates/templateId/task-template-detail-page-client.tsx +8 -2
  96. package/src/globals.css +1 -0
  97. package/src/hooks/__tests__/use-notifications-subscription.test.tsx +34 -0
  98. package/src/hooks/__tests__/use-task-actions.test.tsx +14 -39
  99. package/src/hooks/task-actions-personal-external.ts +12 -6
  100. package/src/hooks/use-notifications.ts +14 -2
  101. package/vitest.config.ts +4 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,101 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.17.0](https://github.com/tutur3u/platform/compare/ui-v0.16.0...ui-v0.17.0) (2026-07-13)
4
+
5
+
6
+ ### Features
7
+
8
+ * **storefront:** refine the buyer experience ([45d0e76](https://github.com/tutur3u/platform/commit/45d0e763ff2adc858aa7c76024eb4554879b3977))
9
+ * **tasks:** promote progress tracking workspace ([058503a](https://github.com/tutur3u/platform/commit/058503a96c8df10725ecd3f88738d574760fc944))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * **platform:** address attendance and invoice feedback ([8d2a537](https://github.com/tutur3u/platform/commit/8d2a53782d01427839607c7b0d90eaa3ecc5a1d8))
15
+
16
+
17
+ ### Performance Improvements
18
+
19
+ * **web:** reduce dashboard request overhead ([93f4b2b](https://github.com/tutur3u/platform/commit/93f4b2b354286b33c5cf8ff9ee0e54a31b18a022))
20
+
21
+ ## [0.16.0](https://github.com/tutur3u/platform/compare/ui-v0.15.0...ui-v0.16.0) (2026-07-11)
22
+
23
+
24
+ ### Features
25
+
26
+ * **contacts:** migrate reports + groups and complete the users cutover ([2ee89cd](https://github.com/tutur3u/platform/commit/2ee89cd2257c2a9824df53d4be99436416d85c13))
27
+ * **finance:** support prepaid subscription invoice ranges ([fa0f338](https://github.com/tutur3u/platform/commit/fa0f3388dfb3d3ea539a8d8bdc3f100f268542c6))
28
+ * **inventory:** add revenue share and category bundles ([20b2e1e](https://github.com/tutur3u/platform/commit/20b2e1e5302d1db275766b7b4b92d9bdf69de04a))
29
+ * **satellite:** open settings on Cmd/Ctrl+, in satellite apps ([841f425](https://github.com/tutur3u/platform/commit/841f42557dd49eb31fd797900b1ec6ade6642dba))
30
+ * **settings:** lazy load searchable settings availability ([78091c0](https://github.com/tutur3u/platform/commit/78091c0acd16609c695be80b7c47f7840a34d74a))
31
+ * **settings:** open settings dialog from sidebar ([f3d223f](https://github.com/tutur3u/platform/commit/f3d223fbe3b4ecc7c37b6f19645f6122ddfdf5b9))
32
+ * **tasks:** add board header loading skeleton ([73f1242](https://github.com/tutur3u/platform/commit/73f12421a9cd50c035a1c9940e152354b1974f26))
33
+ * **tasks:** add quick-create targeting and edge autoscroll ([f03e932](https://github.com/tutur3u/platform/commit/f03e9324b0cce18e9f9974cc8fe251bb58b686bd))
34
+ * **tasks:** add task templates ([8d0700a](https://github.com/tutur3u/platform/commit/8d0700ad255c7b5874bfa065575df6b1cde34063))
35
+ * **tasks:** allow archiving document tasks ([0c51941](https://github.com/tutur3u/platform/commit/0c519414101a3a21b4e33548517eef05143fdf8e))
36
+ * **tasks:** consolidate task settings ([982e0b9](https://github.com/tutur3u/platform/commit/982e0b927358a5d566a5e33e092bd387ec0a7b50))
37
+ * **tasks:** consolidate tasks entry and sidebar controls ([56e80eb](https://github.com/tutur3u/platform/commit/56e80eb5c60d4b4e56f2953c7978038f1ebe9c08))
38
+ * **tasks:** stabilize shared board realtime collaboration ([6028caf](https://github.com/tutur3u/platform/commit/6028caf50432fd4dcebdaa5a59284e50972b1aa3))
39
+
40
+
41
+ ### Bug Fixes
42
+
43
+ * **auth:** share account preference cookies ([8c1848a](https://github.com/tutur3u/platform/commit/8c1848a941c1b3f91337104c975e4bc0d8f68fc9))
44
+ * **cli:** preserve markdown tables in task descriptions ([9faf8ba](https://github.com/tutur3u/platform/commit/9faf8ba44b92565a9dfc2949c496654fc1fea9b3))
45
+ * **finance:** apply invoice defaults and i18n coverage ([a5a7a26](https://github.com/tutur3u/platform/commit/a5a7a26c5cf9f6479010624ace6a18dbeb87f0dd))
46
+ * **finance:** apply invoice defaults and i18n coverage ([97fabad](https://github.com/tutur3u/platform/commit/97fabad7b0815da7afa009fea6a5d1abb983c040))
47
+ * **finance:** stabilize subscription invoice checkout ([742c163](https://github.com/tutur3u/platform/commit/742c163bc8fa94acf3de03feb4ff3ef026419a4e))
48
+ * **mail:** stabilize layout and managed sender identity ([a22205e](https://github.com/tutur3u/platform/commit/a22205e98a8671ffb628586107de09a7ba8dd1c4))
49
+ * **settings:** resolve lazy search import for docker build ([8a6dc1b](https://github.com/tutur3u/platform/commit/8a6dc1b39fd675daaa9f9b24c60b975b044db724))
50
+ * **tasks:** compact due date menu summaries ([473ca52](https://github.com/tutur3u/platform/commit/473ca52acd752b16032d1635120063d250ba9bd0))
51
+ * **tasks:** default task boards to kanban ([477c12a](https://github.com/tutur3u/platform/commit/477c12aeee7644a28e6266f9c339e7ef5c3228bf))
52
+ * **tasks:** harden satellite task route hydration ([9d51a38](https://github.com/tutur3u/platform/commit/9d51a38ad948ebb398bec794f082f2bbf8d466cc))
53
+ * **tasks:** keep personal board moves on workspace route ([60e29b0](https://github.com/tutur3u/platform/commit/60e29b093314b3b185f3f63a69042a665644ed3d))
54
+ * **tasks:** keep personal moves off placement API ([d8c41d7](https://github.com/tutur3u/platform/commit/d8c41d790f5edbe637b9ce71bbd5040b7fddbfa5))
55
+ * **tasks:** match board name input surface ([2552733](https://github.com/tutur3u/platform/commit/2552733942f720bb1df0566f27753eb226115f3e))
56
+ * **tasks:** pad board header skeleton ([b0c5c0f](https://github.com/tutur3u/platform/commit/b0c5c0fea8871cac2603da6239b980c752b1c9f6))
57
+ * **tasks:** prevent description wipes during yjs hydration ([947f38c](https://github.com/tutur3u/platform/commit/947f38c6474d07b1fac1c44e166638bfc87260c0))
58
+ * **tasks:** refresh task template placeholders ([0c3c309](https://github.com/tutur3u/platform/commit/0c3c30935f67e3e64d548c8a13584fd597e887b8))
59
+ * **tasks:** repair settings data and i18n ([0159488](https://github.com/tutur3u/platform/commit/0159488ae5de1c4d98a7d804d47bf1d479ae60c9))
60
+ * **tasks:** resolve personal placement board from list ([ed52667](https://github.com/tutur3u/platform/commit/ed5266740092e2c5fd2e7be19d5015a63705bea1))
61
+ * **tasks:** resolve personal placement board from list ([14335af](https://github.com/tutur3u/platform/commit/14335af944f77b923be66c871c31f5fea79d61a4))
62
+ * **tasks:** restore satellite resource access ([ec5e0a8](https://github.com/tutur3u/platform/commit/ec5e0a8d75398047e0151ae2ac3cd9a25a4fd675))
63
+ * **tasks:** restore task dialog app-session requests ([69f83cb](https://github.com/tutur3u/platform/commit/69f83cb8730eaeb4d39c186bbf8593c73e3deb47))
64
+ * **tasks:** restore tracked task descriptions ([f892ae2](https://github.com/tutur3u/platform/commit/f892ae23dfec41c2d25649b97a628d8cdcd1fa5d))
65
+ * **tasks:** route native personal task moves normally ([5bbba3c](https://github.com/tutur3u/platform/commit/5bbba3c3f193e722cc87cdfe2eb2734f61442cd0))
66
+ * **tasks:** scroll kanban board at drag edges ([1053f6c](https://github.com/tutur3u/platform/commit/1053f6cc6db9788b7e184ed8bc7febdb2adacf97))
67
+ * **tasks:** support personal external terminal defaults ([50434cb](https://github.com/tutur3u/platform/commit/50434cb9849a65dd8c77f6b030b27a4bd76125e4))
68
+ * **tasks:** unify board loading skeleton ([eaf2b65](https://github.com/tutur3u/platform/commit/eaf2b65242201573b930d4df4695488d0a669f30))
69
+ * **ui:** preserve personal external task edits ([8e537e3](https://github.com/tutur3u/platform/commit/8e537e3787ad6854c0efe7792e9487647d73854e))
70
+ * **ui:** stabilize task property popover handoff ([8fb2e62](https://github.com/tutur3u/platform/commit/8fb2e62904d34a3ae7894bfbbb66c285fcf1a1bd))
71
+
72
+ ## [0.15.0](https://github.com/tutur3u/platform/compare/ui-v0.14.0...ui-v0.15.0) (2026-07-11)
73
+
74
+
75
+ ### Features
76
+
77
+ * **contacts:** migrate reports + groups and complete the users cutover ([2ee89cd](https://github.com/tutur3u/platform/commit/2ee89cd2257c2a9824df53d4be99436416d85c13))
78
+ * **tasks:** allow archiving document tasks ([0c51941](https://github.com/tutur3u/platform/commit/0c519414101a3a21b4e33548517eef05143fdf8e))
79
+ * **tasks:** consolidate task settings ([982e0b9](https://github.com/tutur3u/platform/commit/982e0b927358a5d566a5e33e092bd387ec0a7b50))
80
+ * **tasks:** consolidate tasks entry and sidebar controls ([56e80eb](https://github.com/tutur3u/platform/commit/56e80eb5c60d4b4e56f2953c7978038f1ebe9c08))
81
+
82
+
83
+ ### Bug Fixes
84
+
85
+ * **auth:** share account preference cookies ([8c1848a](https://github.com/tutur3u/platform/commit/8c1848a941c1b3f91337104c975e4bc0d8f68fc9))
86
+ * **finance:** apply invoice defaults and i18n coverage ([a5a7a26](https://github.com/tutur3u/platform/commit/a5a7a26c5cf9f6479010624ace6a18dbeb87f0dd))
87
+ * **finance:** apply invoice defaults and i18n coverage ([97fabad](https://github.com/tutur3u/platform/commit/97fabad7b0815da7afa009fea6a5d1abb983c040))
88
+ * **finance:** stabilize subscription invoice checkout ([742c163](https://github.com/tutur3u/platform/commit/742c163bc8fa94acf3de03feb4ff3ef026419a4e))
89
+ * **mail:** stabilize layout and managed sender identity ([a22205e](https://github.com/tutur3u/platform/commit/a22205e98a8671ffb628586107de09a7ba8dd1c4))
90
+ * **tasks:** compact due date menu summaries ([473ca52](https://github.com/tutur3u/platform/commit/473ca52acd752b16032d1635120063d250ba9bd0))
91
+ * **tasks:** repair settings data and i18n ([0159488](https://github.com/tutur3u/platform/commit/0159488ae5de1c4d98a7d804d47bf1d479ae60c9))
92
+ * **tasks:** resolve personal placement board from list ([ed52667](https://github.com/tutur3u/platform/commit/ed5266740092e2c5fd2e7be19d5015a63705bea1))
93
+ * **tasks:** resolve personal placement board from list ([14335af](https://github.com/tutur3u/platform/commit/14335af944f77b923be66c871c31f5fea79d61a4))
94
+ * **tasks:** restore task dialog app-session requests ([69f83cb](https://github.com/tutur3u/platform/commit/69f83cb8730eaeb4d39c186bbf8593c73e3deb47))
95
+ * **tasks:** support personal external terminal defaults ([50434cb](https://github.com/tutur3u/platform/commit/50434cb9849a65dd8c77f6b030b27a4bd76125e4))
96
+ * **tasks:** unify board loading skeleton ([eaf2b65](https://github.com/tutur3u/platform/commit/eaf2b65242201573b930d4df4695488d0a669f30))
97
+ * **ui:** preserve personal external task edits ([8e537e3](https://github.com/tutur3u/platform/commit/8e537e3787ad6854c0efe7792e9487647d73854e))
98
+
3
99
  ## [0.14.0](https://github.com/tutur3u/platform/compare/ui-v0.13.0...ui-v0.14.0) (2026-07-06)
4
100
 
5
101
 
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.17.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.1",
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.18.0",
92
92
  "@tuturuuu/supabase": "0.4.0",
93
- "@tuturuuu/utils": "0.13.0",
93
+ "@tuturuuu/utils": "0.15.1",
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,21 @@
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
+ "slot-text": "^0.3.3",
132
133
  "sonner": "^2.0.7",
133
134
  "streamdown": "^2.5.0",
134
135
  "tailwind-scrollbar": "^4.0.2",
135
136
  "tailwind-scrollbar-hide": "^4.0.0",
136
137
  "tailwindcss-animate": "^1.0.7",
137
- "tiptap-extension-resize-image": "^1.4.3",
138
+ "tiptap-extension-resize-image": "^1.4.4",
138
139
  "use-debounce": "^10.1.1",
139
140
  "vaul": "^1.1.2",
140
141
  "xlsx": "file:vendor/xlsx-0.20.3.tgz",
@@ -149,11 +150,11 @@
149
150
  "@tanstack/react-table": "^8.21.3",
150
151
  "@testing-library/jest-dom": "^6.9.1",
151
152
  "@testing-library/react": "^16.3.2",
152
- "@tuturuuu/types": "0.14.0",
153
+ "@tuturuuu/types": "0.17.0",
153
154
  "@tuturuuu/typescript-config": "0.1.1",
154
155
  "@types/html2canvas": "^1.0.0",
155
156
  "@types/lodash": "^4.17.24",
156
- "@types/node": "^26.0.1",
157
+ "@types/node": "^26.1.1",
157
158
  "@types/react": "^19.2.17",
158
159
  "@types/react-dom": "^19.2.3",
159
160
  "@types/react-resizable": "^4.0.0",
@@ -162,12 +163,12 @@
162
163
  "@vitejs/plugin-react": "^6.0.3",
163
164
  "autoprefixer": "^10.5.2",
164
165
  "jsdom": "^29.1.1",
165
- "postcss": "^8.5.16",
166
+ "postcss": "^8.5.17",
166
167
  "postcss-load-config": "^6.0.1",
167
168
  "tailwindcss": "^4.3.2",
168
- "typescript": "7.0.1-rc",
169
+ "typescript": "7.0.2",
169
170
  "uuid": "^14.0.1",
170
- "vitest": "^4.1.9"
171
+ "vitest": "^4.1.10"
171
172
  },
172
173
  "peerDependencies": {
173
174
  "@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
+ }