@tuturuuu/ui 0.7.0 → 0.8.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 (67) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/package.json +8 -8
  3. package/src/components/ui/currency-input.test.tsx +43 -0
  4. package/src/components/ui/currency-input.tsx +1 -1
  5. package/src/components/ui/custom/workspace-access/workspace-access-default-role-card.tsx +60 -35
  6. package/src/components/ui/custom/workspace-access/workspace-access-member-row.tsx +176 -167
  7. package/src/components/ui/custom/workspace-access/workspace-access-members.tsx +16 -10
  8. package/src/components/ui/custom/workspace-access/workspace-access-page-header.tsx +75 -36
  9. package/src/components/ui/custom/workspace-access/workspace-access-page.tsx +39 -42
  10. package/src/components/ui/custom/workspace-access/workspace-access-people-filters.tsx +1 -1
  11. package/src/components/ui/custom/workspace-access/workspace-access-roles.tsx +113 -91
  12. package/src/components/ui/custom/workspace-access/workspace-access-tabs-toolbar.tsx +73 -32
  13. package/src/components/ui/finance/transactions/form-types.ts +2 -0
  14. package/src/components/ui/finance/transactions/transaction-card.tsx +21 -9
  15. package/src/components/ui/money-input.test.tsx +64 -0
  16. package/src/components/ui/money-input.tsx +63 -0
  17. package/src/components/ui/storefront/cart-summary.tsx +114 -29
  18. package/src/components/ui/storefront/checkout-overlay.tsx +27 -0
  19. package/src/components/ui/storefront/hero-panel.tsx +2 -8
  20. package/src/components/ui/storefront/image-panel.tsx +6 -0
  21. package/src/components/ui/storefront/index.ts +11 -0
  22. package/src/components/ui/storefront/listing-card.tsx +84 -22
  23. package/src/components/ui/storefront/product-detail.tsx +289 -0
  24. package/src/components/ui/storefront/product-dialog.tsx +72 -0
  25. package/src/components/ui/storefront/storefront-surface.test.tsx +124 -1
  26. package/src/components/ui/storefront/storefront-surface.tsx +333 -133
  27. package/src/components/ui/storefront/types.ts +23 -1
  28. package/src/components/ui/storefront/utils.ts +111 -27
  29. package/src/components/ui/text-editor/__tests__/content-migration.test.ts +32 -0
  30. package/src/components/ui/text-editor/__tests__/image-extension.test.ts +69 -1
  31. package/src/components/ui/text-editor/__tests__/video-extension.test.ts +47 -0
  32. package/src/components/ui/text-editor/content-migration.ts +41 -18
  33. package/src/components/ui/text-editor/extensions.ts +1 -1
  34. package/src/components/ui/text-editor/image-extension.ts +40 -18
  35. package/src/components/ui/text-editor/video-extension.ts +11 -2
  36. package/src/components/ui/tu-do/boards/__tests__/workspace-projects-client-page.test.tsx +70 -1
  37. package/src/components/ui/tu-do/boards/boardId/board-column-external-retry.test.tsx +127 -0
  38. package/src/components/ui/tu-do/boards/boardId/board-column.tsx +1 -3
  39. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/task-drag-cache.ts +13 -0
  40. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/use-kanban-dnd.test.ts +63 -0
  41. package/src/components/ui/tu-do/boards/boardId/kanban/dnd/use-kanban-dnd.ts +46 -8
  42. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.test.tsx +13 -2
  43. package/src/components/ui/tu-do/boards/boardId/kanban/rendering/kanban-columns.tsx +3 -1
  44. package/src/components/ui/tu-do/boards/boardId/task-board-server-page.test.tsx +164 -0
  45. package/src/components/ui/tu-do/boards/boardId/task-board-server-page.tsx +56 -2
  46. package/src/components/ui/tu-do/boards/boardId/timeline/timeline-display.ts +9 -0
  47. package/src/components/ui/tu-do/boards/boardId/timeline/timeline-grid.tsx +8 -16
  48. package/src/components/ui/tu-do/boards/boardId/timeline/timeline-task-row.tsx +5 -25
  49. package/src/components/ui/tu-do/boards/boardId/timeline/timeline-utils.test.ts +36 -1
  50. package/src/components/ui/tu-do/boards/boardId/timeline/timeline-utils.ts +51 -2
  51. package/src/components/ui/tu-do/boards/workspace-projects-client-page.tsx +13 -3
  52. package/src/components/ui/tu-do/shared/__tests__/board-views.test.tsx +34 -1
  53. package/src/components/ui/tu-do/shared/board-header.tsx +39 -0
  54. package/src/components/ui/tu-do/shared/board-views.tsx +9 -7
  55. package/src/components/ui/tu-do/shared/cursor-overlay-multi-wrapper.tsx +53 -12
  56. package/src/components/ui/tu-do/shared/task-dialog-presentation.test.ts +53 -0
  57. package/src/components/ui/tu-do/shared/task-dialog-presentation.ts +19 -0
  58. package/src/components/ui/tu-do/shared/task-edit-dialog/components/compact-task-create-popover.test.tsx +57 -0
  59. package/src/components/ui/tu-do/shared/task-edit-dialog/components/compact-task-create-popover.tsx +136 -111
  60. package/src/components/ui/tu-do/shared/task-edit-dialog/components/task-description-editor.tsx +3 -1
  61. package/src/components/ui/tu-do/shared/task-edit-dialog.tsx +42 -14
  62. package/src/hooks/__tests__/useBoardRealtime.test.tsx +2 -2
  63. package/src/hooks/__tests__/useCursorTracking.test.tsx +212 -0
  64. package/src/hooks/useBoardRealtime.ts +6 -3
  65. package/src/hooks/useBoardRealtime.types.ts +11 -0
  66. package/src/hooks/useCursorTracking.ts +91 -27
  67. package/src/hooks/useTaskUserRealtime.ts +5 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.0](https://github.com/tutur3u/platform/compare/ui-v0.7.0...ui-v0.8.0) (2026-06-17)
4
+
5
+
6
+ ### Features
7
+
8
+ * **inventory:** fix Polar checkout currency, add 2-way product sync, cache + redesign storefront ([de2f6fd](https://github.com/tutur3u/platform/commit/de2f6fd6e06ce5242a150a35d3989798f52b9ee9))
9
+ * **inventory:** per-variant SKUs + storefront cart, dialog & instant checkout ([9662b85](https://github.com/tutur3u/platform/commit/9662b8501bcab51033edde79b44991c8ba648a37))
10
+ * **inventory:** store commerce money in minor units and harden Polar sync ([3f7ee1d](https://github.com/tutur3u/platform/commit/3f7ee1da9335732854037e7e79fca9d5d2a381d0))
11
+ * **storefront-ui:** dedicated product page, richer cart, loading skeleton ([d4a67f8](https://github.com/tutur3u/platform/commit/d4a67f8e6097d51aab6ca983245529725fcaba5c))
12
+ * **storefront-ui:** polish checkout layout and order-status page ([ead94ed](https://github.com/tutur3u/platform/commit/ead94edaa2ac6e79f9e56fd9f48d7a098487f2de))
13
+ * **storefront:** dedicated checkout page with buyer details + order-placed success ([258014d](https://github.com/tutur3u/platform/commit/258014d642e7cf99164e92fec44cd32114ecf68d))
14
+ * **storefront:** make the storefront accent color visibly prominent ([f2b5289](https://github.com/tutur3u/platform/commit/f2b5289506fd8e289f4bfb2bb6755cbc10ea2430))
15
+ * **storefront:** polish checkout cart experience ([cfdccfa](https://github.com/tutur3u/platform/commit/cfdccfa089703d9dde4357eeef8e52c00ccf6d4b))
16
+ * **tasks:** add per-board default list for new tasks ([2d1d308](https://github.com/tutur3u/platform/commit/2d1d3082422bdd4813accb258fee79b322ce647b))
17
+ * **web:** consolidate workspace roles into members and redesign access UI ([4a16407](https://github.com/tutur3u/platform/commit/4a164070e1fe020a834ce4fe77ff4ae371e4e366))
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * **ci:** format storefront files and harden upstash scan wrapper ([4c82444](https://github.com/tutur3u/platform/commit/4c824446725dc280edde3e54f946bf386a52952d))
23
+ * **ci:** sort tailwind classes in storefront product-detail (biome lint) ([809c3b9](https://github.com/tutur3u/platform/commit/809c3b9b1e514fb218b58941c9542c75bd723f2d))
24
+ * **deps:** keep lodash on latest reviewed artifact ([19909b3](https://github.com/tutur3u/platform/commit/19909b334581d3b58cdcd19e9b2fde553f7ad60a))
25
+ * **deps:** pin reviewed lodash artifact ([dfcf585](https://github.com/tutur3u/platform/commit/dfcf585fab9cc0b425cac5d60c5bccc997340be5))
26
+ * **editor:** clear stale upload handlers ([ed34408](https://github.com/tutur3u/platform/commit/ed34408e9e48ee13bf7e69c2a8ba222d75c67253))
27
+ * **epm:** validate summary editor content ([bd87c77](https://github.com/tutur3u/platform/commit/bd87c770690c75a125fe2a727f3ad39aa925b5fd))
28
+ * **finance:** harden transaction enrichment ([eddd93b](https://github.com/tutur3u/platform/commit/eddd93bd11fb451a7fa5da2e4ab2892fad931ab5))
29
+ * **inventory:** block unsafe storefront section links ([870ce76](https://github.com/tutur3u/platform/commit/870ce760237f43ca2a3d1221359c4a06d1bc7653))
30
+ * **storefront-ui:** prevent horizontal overflow and cap cart height ([5825c49](https://github.com/tutur3u/platform/commit/5825c49fb9b77c859cda4ec6bbb6ba382925e519))
31
+ * **storefront-ui:** show an empty-cart state instead of "no listings" in the cart ([00bdb40](https://github.com/tutur3u/platform/commit/00bdb40eb344b17c3727fda1ea0c042508c63901))
32
+ * **tasks:** authorize board page before workspace ([9b1f740](https://github.com/tutur3u/platform/commit/9b1f74096a4a889b7733b6ffe37d4d16f442d974))
33
+ * **tasks:** cap timeline rendering work ([f2722ee](https://github.com/tutur3u/platform/commit/f2722ee0c3778153e1b014280bc1513305c5be7a))
34
+ * **tasks:** gate boards data access ([6daf363](https://github.com/tutur3u/platform/commit/6daf363b1c73593a233371a6cf079a3a4a015daa))
35
+ * **tasks:** ignore stale drag rollbacks ([c60131f](https://github.com/tutur3u/platform/commit/c60131f9f0930c81d3d2ccc6f2f9e918968d4b77))
36
+ * **tasks:** refine document task dialog presentation ([ca10735](https://github.com/tutur3u/platform/commit/ca10735f086a24be065eded03b8bc6e9382e2c5f))
37
+ * **tasks:** secure cursor realtime channels ([a0ec120](https://github.com/tutur3u/platform/commit/a0ec120d912b7998fe43c90b675a09d0d3798dfe))
38
+ * **tasks:** secure realtime task channels ([6d98d16](https://github.com/tutur3u/platform/commit/6d98d16baa9ecf68bdd47ce3ce6dc1ff2e2bca84))
39
+ * **tasks:** secure realtime task channels ([03dc6d6](https://github.com/tutur3u/platform/commit/03dc6d66666d1d3ae422f91cb94285367a8c1071))
40
+ * **tasks:** stop external lane retry loops ([713c327](https://github.com/tutur3u/platform/commit/713c327a613b018e72e376c03324517c6ee673c3))
41
+ * **tu-do:** center compact task edit dialog instead of anchoring to bottom ([67f38aa](https://github.com/tutur3u/platform/commit/67f38aaab1eab4b5340dfe049eed9c1e224c83b1))
42
+ * **tu-do:** preserve newlines and dim compact description preview ([ee01f40](https://github.com/tutur3u/platform/commit/ee01f40ab5ae800bf8aa1c59f19eb4f2bd69c256))
43
+ * **ui:** keep locale decimals in currency input ([3cd2420](https://github.com/tutur3u/platform/commit/3cd242026c3afe51eedabc3ec070093d0a94523f))
44
+ * **web:** stop new-workspace setup from trapping users on "Preparing Workspace" ([3f7ee1d](https://github.com/tutur3u/platform/commit/3f7ee1da9335732854037e7e79fca9d5d2a381d0))
45
+
46
+
47
+ ### Performance Improvements
48
+
49
+ * **storefront-ui:** lazy-load product images, eager-load above-the-fold ([6da600e](https://github.com/tutur3u/platform/commit/6da600eec0ce964ac61ae7890cf4574ada6aef3e))
50
+
3
51
  ## [0.7.0](https://github.com/tutur3u/platform/compare/ui-v0.6.2...ui-v0.7.0) (2026-06-15)
4
52
 
5
53
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuturuuu/ui",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -83,12 +83,12 @@
83
83
  "@tiptap/react": "3.26.1",
84
84
  "@tiptap/starter-kit": "3.26.1",
85
85
  "@tuturuuu/ai": "0.2.2",
86
- "@tuturuuu/apis": "0.4.2",
86
+ "@tuturuuu/apis": "0.5.0",
87
87
  "@tuturuuu/hooks": "0.0.2",
88
88
  "@tuturuuu/icons": "0.0.6",
89
- "@tuturuuu/internal-api": "0.8.0",
90
- "@tuturuuu/supabase": "0.3.3",
91
- "@tuturuuu/utils": "0.7.0",
89
+ "@tuturuuu/internal-api": "0.9.0",
90
+ "@tuturuuu/supabase": "0.3.4",
91
+ "@tuturuuu/utils": "0.8.0",
92
92
  "@types/debug": "^4.1.13",
93
93
  "browser-image-compression": "^2.0.2",
94
94
  "class-variance-authority": "^0.7.1",
@@ -105,7 +105,7 @@
105
105
  "html2canvas-pro": "^2.0.2",
106
106
  "input-otp": "^1.4.2",
107
107
  "katex": "^0.17.0",
108
- "lodash": "^4.18.1",
108
+ "lodash": "4.18.1",
109
109
  "moment": "^2.30.1",
110
110
  "motion": "^12.40.0",
111
111
  "next": "^16.2.9",
@@ -135,7 +135,7 @@
135
135
  "tiptap-extension-resize-image": "^1.4.3",
136
136
  "use-debounce": "^10.1.1",
137
137
  "vaul": "^1.1.2",
138
- "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
138
+ "xlsx": "file:vendor/xlsx-0.20.3.tgz",
139
139
  "y-protocols": "^1.0.7",
140
140
  "yjs": "^13.6.31",
141
141
  "zod": "^4.4.3"
@@ -147,7 +147,7 @@
147
147
  "@tanstack/react-table": "^8.21.3",
148
148
  "@testing-library/jest-dom": "^6.9.1",
149
149
  "@testing-library/react": "^16.3.2",
150
- "@tuturuuu/types": "0.9.0",
150
+ "@tuturuuu/types": "0.10.0",
151
151
  "@tuturuuu/typescript-config": "0.1.1",
152
152
  "@types/html2canvas": "^1.0.0",
153
153
  "@types/lodash": "^4.17.24",
@@ -0,0 +1,43 @@
1
+ import { fireEvent, render, screen } from '@testing-library/react';
2
+ import { describe, expect, it, vi } from 'vitest';
3
+ import { CurrencyInput } from './currency-input';
4
+
5
+ describe('CurrencyInput', () => {
6
+ it('keeps locale decimal separators while editing', () => {
7
+ const onChange = vi.fn();
8
+
9
+ render(
10
+ <CurrencyInput
11
+ aria-label="Amount"
12
+ hideHelpers
13
+ locale="vi-VN"
14
+ maximumFractionDigits={2}
15
+ onChange={onChange}
16
+ value={undefined}
17
+ />
18
+ );
19
+
20
+ const input = screen.getByLabelText('Amount') as HTMLInputElement;
21
+
22
+ fireEvent.focus(input);
23
+ fireEvent.change(input, {
24
+ target: {
25
+ selectionStart: 3,
26
+ value: '1,2',
27
+ },
28
+ });
29
+
30
+ expect(input).toHaveValue('1,2');
31
+ expect(onChange).toHaveBeenLastCalledWith(1.2);
32
+
33
+ fireEvent.change(input, {
34
+ target: {
35
+ selectionStart: input.value.length + 1,
36
+ value: `${input.value}3`,
37
+ },
38
+ });
39
+
40
+ expect(input).toHaveValue('1,23');
41
+ expect(onChange).toHaveBeenLastCalledWith(1.23);
42
+ });
43
+ });
@@ -197,7 +197,7 @@ export const CurrencyInput = forwardRef<HTMLInputElement, CurrencyInputProps>(
197
197
  // Build final formatted string
198
198
  let formatted = formattedInteger;
199
199
  if (hasDecimal) {
200
- formatted += `.${decimalPart}`;
200
+ formatted += `${localeSeparators.decimal}${decimalPart}`;
201
201
  }
202
202
 
203
203
  // Calculate new cursor position
@@ -1,15 +1,8 @@
1
1
  'use client';
2
2
 
3
- import { Pencil } from '@tuturuuu/icons';
3
+ import { KeyRound, Pencil, ShieldUser } from '@tuturuuu/icons';
4
4
  import type { WorkspaceDefaultPermissionMemberType } from '@tuturuuu/types';
5
5
  import { Button } from '@tuturuuu/ui/button';
6
- import {
7
- Card,
8
- CardContent,
9
- CardDescription,
10
- CardHeader,
11
- CardTitle,
12
- } from '@tuturuuu/ui/card';
13
6
  import { Skeleton } from '@tuturuuu/ui/skeleton';
14
7
  import { useTranslations } from 'next-intl';
15
8
  import type { WorkspaceAccessRole } from './types';
@@ -37,45 +30,77 @@ export function WorkspaceAccessDefaultRoleCard({
37
30
  }) {
38
31
  const t = useTranslations() as (key: string) => string;
39
32
  const isGuest = memberType === 'GUEST';
33
+ const enabled = enabledPermissionCount(role);
34
+ const pct =
35
+ permissionCount > 0 ? Math.round((enabled / permissionCount) * 100) : 0;
36
+ const accent = isGuest
37
+ ? 'border-dynamic-blue/30 bg-dynamic-blue/10 text-dynamic-blue'
38
+ : 'border-dynamic-green/30 bg-dynamic-green/10 text-dynamic-green';
39
+ const barColor = isGuest ? 'bg-dynamic-blue' : 'bg-dynamic-green';
40
40
 
41
41
  return (
42
- <Card className="shadow-none">
43
- <CardHeader>
44
- <div className="flex flex-wrap items-start justify-between gap-3">
45
- <div className="space-y-1">
46
- <CardTitle className="text-base">
42
+ <div className="rounded-xl border border-border bg-background p-5">
43
+ <div className="flex flex-wrap items-start justify-between gap-3">
44
+ <div className="flex min-w-0 gap-3">
45
+ <div
46
+ className={`flex h-10 w-10 shrink-0 items-center justify-center rounded-lg border ${accent}`}
47
+ >
48
+ {isGuest ? (
49
+ <KeyRound className="h-5 w-5" />
50
+ ) : (
51
+ <ShieldUser className="h-5 w-5" />
52
+ )}
53
+ </div>
54
+ <div className="min-w-0">
55
+ <div className="font-semibold text-base">
47
56
  {isGuest
48
57
  ? t('ws-roles.guest_defaults')
49
58
  : t('ws-roles.member_defaults')}
50
- </CardTitle>
51
- <CardDescription>
59
+ </div>
60
+ <p className="mt-0.5 max-w-md text-muted-foreground text-sm">
52
61
  {isGuest
53
62
  ? t('ws-roles.guest_defaults_description')
54
63
  : t('ws-roles.member_defaults_description')}
55
- </CardDescription>
64
+ </p>
56
65
  </div>
57
- {canManageRoles ? (
58
- <Button
59
- variant="outline"
60
- size="sm"
61
- onClick={() => onEdit(memberType)}
62
- >
63
- <Pencil className="mr-2 h-4 w-4" />
64
- {t('common.edit')}
65
- </Button>
66
- ) : null}
67
66
  </div>
68
- </CardHeader>
69
- <CardContent className="space-y-3">
67
+ {canManageRoles ? (
68
+ <Button
69
+ variant="outline"
70
+ size="sm"
71
+ onClick={() => onEdit(memberType)}
72
+ >
73
+ <Pencil className="mr-2 h-4 w-4" />
74
+ {t('common.edit')}
75
+ </Button>
76
+ ) : null}
77
+ </div>
78
+
79
+ <div className="mt-4 space-y-3">
70
80
  {isLoading ? (
71
81
  <Skeleton className="h-24 rounded-lg" />
72
82
  ) : (
73
83
  <>
74
- <div className="font-semibold text-2xl tabular-nums">
75
- {enabledPermissionCount(role)}
76
- <span className="ml-1 font-normal text-base text-muted-foreground">
77
- / {permissionCount}
78
- </span>
84
+ <div>
85
+ <div className="flex items-baseline justify-between gap-1.5">
86
+ <div className="flex items-baseline gap-1.5">
87
+ <span className="font-bold text-2xl tabular-nums">
88
+ {enabled}
89
+ </span>
90
+ <span className="text-base text-muted-foreground">
91
+ / {permissionCount}
92
+ </span>
93
+ </div>
94
+ <span className="text-muted-foreground text-sm">
95
+ {t('ws-roles.permissions')}
96
+ </span>
97
+ </div>
98
+ <div className="mt-2 h-1.5 max-w-md overflow-hidden rounded-full bg-foreground/10">
99
+ <div
100
+ className={`h-full rounded-full ${barColor}`}
101
+ style={{ width: `${pct}%` }}
102
+ />
103
+ </div>
79
104
  </div>
80
105
  <div className="flex flex-wrap gap-2">
81
106
  <WorkspaceAccessPermissionPreview
@@ -86,7 +111,7 @@ export function WorkspaceAccessDefaultRoleCard({
86
111
  </div>
87
112
  </>
88
113
  )}
89
- </CardContent>
90
- </Card>
114
+ </div>
115
+ </div>
91
116
  );
92
117
  }