@comitor/ui 1.11.0 → 2.0.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 (59) hide show
  1. package/README.md +10 -2
  2. package/dist/data-grid/data-grid-cell-variants.js +10 -6
  3. package/dist/data-grid/data-grid-cell-variants.js.map +1 -1
  4. package/dist/data-grid/data-grid-column-header.js +4 -2
  5. package/dist/data-grid/data-grid-column-header.js.map +1 -1
  6. package/dist/data-grid/data-grid-context-menu.js +4 -3
  7. package/dist/data-grid/data-grid-context-menu.js.map +1 -1
  8. package/dist/data-grid/data-grid-filter-menu.d.ts +12 -1
  9. package/dist/data-grid/data-grid-filter-menu.js +28 -17
  10. package/dist/data-grid/data-grid-filter-menu.js.map +1 -1
  11. package/dist/data-grid/data-grid-keyboard-shortcuts.d.ts +12 -1
  12. package/dist/data-grid/data-grid-keyboard-shortcuts.js +7 -5
  13. package/dist/data-grid/data-grid-keyboard-shortcuts.js.map +1 -1
  14. package/dist/data-grid/data-grid-locale.d.ts +24 -0
  15. package/dist/data-grid/data-grid-locale.js +25 -0
  16. package/dist/data-grid/data-grid-locale.js.map +1 -0
  17. package/dist/data-grid/data-grid-paste-dialog.js +2 -1
  18. package/dist/data-grid/data-grid-paste-dialog.js.map +1 -1
  19. package/dist/data-grid/data-grid-row-height-menu.d.ts +11 -1
  20. package/dist/data-grid/data-grid-row-height-menu.js +25 -28
  21. package/dist/data-grid/data-grid-row-height-menu.js.map +1 -1
  22. package/dist/data-grid/data-grid-search.js +5 -4
  23. package/dist/data-grid/data-grid-search.js.map +1 -1
  24. package/dist/data-grid/data-grid-select-column.js +3 -1
  25. package/dist/data-grid/data-grid-select-column.js.map +1 -1
  26. package/dist/data-grid/data-grid-sort-menu.d.ts +12 -1
  27. package/dist/data-grid/data-grid-sort-menu.js +25 -13
  28. package/dist/data-grid/data-grid-sort-menu.js.map +1 -1
  29. package/dist/data-grid/data-grid-view-menu.d.ts +12 -1
  30. package/dist/data-grid/data-grid-view-menu.js +12 -4
  31. package/dist/data-grid/data-grid-view-menu.js.map +1 -1
  32. package/dist/data-grid/data-grid.d.ts +14 -2
  33. package/dist/data-grid/data-grid.js +6 -3
  34. package/dist/data-grid/data-grid.js.map +1 -1
  35. package/dist/data-grid/filters.d.ts +17 -21
  36. package/dist/data-grid/filters.js +73 -52
  37. package/dist/data-grid/filters.js.map +1 -1
  38. package/dist/data-grid/index.d.ts +4 -1
  39. package/dist/data-grid/index.js +20 -2
  40. package/dist/data-grid/index.js.map +1 -1
  41. package/dist/data-grid/messages-en.d.ts +294 -0
  42. package/dist/data-grid/messages-en.js +279 -0
  43. package/dist/data-grid/messages-en.js.map +1 -0
  44. package/dist/data-grid/messages-vi.d.ts +12 -0
  45. package/dist/data-grid/messages-vi.js +279 -0
  46. package/dist/data-grid/messages-vi.js.map +1 -0
  47. package/dist/data-grid/messages.d.ts +549 -262
  48. package/dist/data-grid/messages.js +16 -275
  49. package/dist/data-grid/messages.js.map +1 -1
  50. package/dist/data-grid/use-data-grid-undo-redo.d.ts +13 -1
  51. package/dist/data-grid/use-data-grid-undo-redo.js +11 -8
  52. package/dist/data-grid/use-data-grid-undo-redo.js.map +1 -1
  53. package/dist/data-grid/use-data-grid.d.ts +281 -1
  54. package/dist/data-grid/use-data-grid.js +21 -16
  55. package/dist/data-grid/use-data-grid.js.map +1 -1
  56. package/dist/data-grid/utils.d.ts +9 -1
  57. package/dist/data-grid/utils.js +3 -2
  58. package/dist/data-grid/utils.js.map +1 -1
  59. package/package.json +1 -1
package/README.md CHANGED
@@ -171,13 +171,21 @@ riêng kèm demo, bảng prop và cạm bẫy của nó:
171
171
  | **Tier 2 — composite** · 31 file · `@comitor/ui` | Giá trị thật của gói: pattern lặp ở mọi app, ghép từ nhiều primitive (`DataTable`, `PageHeader`, `Combobox`, `DatePicker`, `StatCard`…) | https://design-system.comitor.ai/composites |
172
172
  | **Tier 3 — shell** · 25 file · `@comitor/ui/shell` | Khung ứng dụng workspace × app: sidebar, header, theme, ba trục hiển thị (tương phản · mật độ · cỡ chữ) | https://design-system.comitor.ai/shell |
173
173
  | **chart** · 4 file · `@comitor/ui/chart` | Lớp shadcn bọc recharts, cùng ba bản dựng sẵn theo brand. ⚠ Ba wrapper `Comitor*Chart` **mặc định TẮT** hiệu ứng vẽ dần (`isAnimationActive = false`) — bật lại là biểu đồ kẹt ở khung đầu: có trục, có lưới, KHÔNG có dữ liệu. Mặc định đó KHÔNG áp cho `<ChartContainer>` + recharts do app tự lắp | https://design-system.comitor.ai/components/chart |
174
- | **data-grid** · 33 file · `@comitor/ui/data-grid` | `DataGrid` — lưới sửa trực tiếp kiểu bảng tính, cho màn nhập liệu hàng loạt. Port từ [tablecn](https://www.tablecn.com/data-grid) (MIT) sang primitive + token của gói. ⚠ Là tầng DUY NHẤT có peer **`@tanstack/react-table`**, và mọi thứ trong nó là client component | [docs/data-grid.md](docs/data-grid.md) |
174
+ | **data-grid** · 36 file · `@comitor/ui/data-grid` | `DataGrid` — lưới sửa trực tiếp kiểu bảng tính, cho màn nhập liệu hàng loạt. Port từ [tablecn](https://www.tablecn.com/data-grid) (MIT) sang primitive + token của gói. ⚠ Là tầng DUY NHẤT có peer **`@tanstack/react-table`**, tầng duy nhất mặc định **tiếng Anh** (prop `locale`, xem dưới), và mọi thứ trong nó là client component | [docs/data-grid.md](docs/data-grid.md) |
175
175
  | **uploader** · 5 file · `@comitor/ui/uploader` | `FileUpload` (tệp) · `ImageUploadField` (ảnh) · `useFileUpload` — kéo thả, xem trước, tiến độ. Peer optional: `@uppy/core` + `@uppy/xhr-upload` | https://design-system.comitor.ai/components |
176
176
  | **form** · `@comitor/ui/form` | Binding shadcn ⇄ react-hook-form | https://design-system.comitor.ai/components/form |
177
177
 
178
178
  **Cơ chế `labels` — đổi ngôn ngữ mà không fork component.** Chuỗi hiển thị mặc định của gói là **tiếng
179
179
  Việt**, kể cả chuỗi chỉ trình đọc màn hình nghe thấy (`aria-label`, `sr-only`); app dùng ngôn ngữ khác
180
- override qua prop `labels`. Kiểu là `Partial<>` và component luôn trải `{ ...DEFAULT_*, ...labels }`,
180
+ override qua prop `labels`.
181
+
182
+ ⚠ **`DataGrid` là ngoại lệ, ở cả hai vế.** Nó mặc định **tiếng Anh**, và nó không dùng `labels` mà
183
+ dùng prop **`locale`** — `"en"` · `"vi"`, hoặc cả một object `DataGridMessages` tự soạn. Lý do:
184
+ phần lớn chuỗi của nó là chuỗi gốc của tablecn, nên giữ tiếng Anh làm bản gốc thì đối chiếu ngược
185
+ với thượng nguồn là so trực tiếp. Muốn tiếng Việt thì khai một lần bằng `DataGridLocaleProvider`,
186
+ và nhớ truyền `locale` cho cả `useDataGrid` — thanh công cụ nằm ngoài `<DataGrid>` nên nó KHÔNG
187
+ nhận được prop của lưới, còn hook thì bắn toast ở ngoài cây DOM của lưới nên nó không đọc được
188
+ provider. Chi tiết: [docs/data-grid.md](docs/data-grid.md) §11. Kiểu là `Partial<>` và component luôn trải `{ ...DEFAULT_*, ...labels }`,
181
189
  nên truyền một khoá không làm mất phần còn lại. Component chỉ có một hai chuỗi thì mở bằng **prop
182
190
  rời** thay cho cả một object — `clearLabel`, `pendingLabel`, `overflowLabel`, `placeholder`,
183
191
  `emptyText`: cùng cơ chế, chỉ khác hình dạng. ⚠ Khoá có số/đơn vị chèn vào là **HÀM**, không phải
@@ -22,7 +22,7 @@ import { Skeleton } from "../components/ui/skeleton.js";
22
22
  import { Textarea } from "../components/ui/textarea.js";
23
23
  import { cn } from "../lib/cn.js";
24
24
  import { DataGridCellWrapper } from "./data-grid-cell-wrapper.js";
25
- import { msg } from "./messages.js";
25
+ import { useDataGridMessages } from "./data-grid-locale.js";
26
26
  import { toastError, toastMessage } from "./toast.js";
27
27
  import { useBadgeOverflow } from "./use-badge-overflow.js";
28
28
  import { useDebouncedCallback } from "./use-debounced-callback.js";
@@ -191,6 +191,7 @@ function LongTextCell({
191
191
  isActiveSearchMatch,
192
192
  readOnly
193
193
  }) {
194
+ const msg = useDataGridMessages();
194
195
  const initialValue = cell.getValue();
195
196
  const [value, setValue] = React.useState(initialValue ?? "");
196
197
  const textareaRef = React.useRef(null);
@@ -468,6 +469,7 @@ function UrlCell({
468
469
  isActiveSearchMatch,
469
470
  readOnly
470
471
  }) {
472
+ const msg = useDataGridMessages();
471
473
  const initialValue = cell.getValue();
472
474
  const [value, setValue] = React.useState(initialValue ?? "");
473
475
  const cellRef = React.useRef(null);
@@ -559,7 +561,7 @@ function UrlCell({
559
561
  }
560
562
  event.stopPropagation();
561
563
  },
562
- [isEditing, value]
564
+ [isEditing, value, msg]
563
565
  );
564
566
  React.useEffect(() => {
565
567
  const wasEditing = prevIsEditingRef.current;
@@ -839,6 +841,7 @@ function MultiSelectCell({
839
841
  isActiveSearchMatch,
840
842
  readOnly
841
843
  }) {
844
+ const msg = useDataGridMessages();
842
845
  const cellValue = React.useMemo(() => {
843
846
  const value = cell.getValue();
844
847
  return value ?? [];
@@ -1169,6 +1172,7 @@ function FileCell({
1169
1172
  isActiveSearchMatch,
1170
1173
  readOnly
1171
1174
  }) {
1175
+ const msg = useDataGridMessages();
1172
1176
  const cellValue = React.useMemo(() => cell.getValue() ?? [], [cell]);
1173
1177
  const cellKey = getCellKey(rowIndex, columnId);
1174
1178
  const prevCellKeyRef = React.useRef(cellKey);
@@ -1232,7 +1236,7 @@ function FileCell({
1232
1236
  }
1233
1237
  return null;
1234
1238
  },
1235
- [maxFileSize, acceptedTypes]
1239
+ [maxFileSize, acceptedTypes, msg]
1236
1240
  );
1237
1241
  const addFiles = React.useCallback(
1238
1242
  async (newFiles, skipUpload = false) => {
@@ -1335,7 +1339,7 @@ function FileCell({
1335
1339
  }
1336
1340
  }
1337
1341
  },
1338
- [files, maxFiles, validateFile, tableMeta, rowIndex, columnId, readOnly, isPending]
1342
+ [files, maxFiles, validateFile, tableMeta, rowIndex, columnId, readOnly, isPending, msg]
1339
1343
  );
1340
1344
  const removeFile = React.useCallback(
1341
1345
  async (fileId) => {
@@ -1373,7 +1377,7 @@ function FileCell({
1373
1377
  });
1374
1378
  tableMeta?.onDataUpdate?.({ rowIndex, columnId, value: updatedFiles });
1375
1379
  },
1376
- [files, tableMeta, rowIndex, columnId, readOnly, isPending]
1380
+ [files, tableMeta, rowIndex, columnId, readOnly, isPending, msg]
1377
1381
  );
1378
1382
  const clearAll = React.useCallback(async () => {
1379
1383
  if (readOnly || isPending) return;
@@ -1401,7 +1405,7 @@ function FileCell({
1401
1405
  setFiles([]);
1402
1406
  setDeletingFiles(/* @__PURE__ */ new Set());
1403
1407
  tableMeta?.onDataUpdate?.({ rowIndex, columnId, value: [] });
1404
- }, [files, tableMeta, rowIndex, columnId, readOnly, isPending]);
1408
+ }, [files, tableMeta, rowIndex, columnId, readOnly, isPending, msg]);
1405
1409
  const onCellDragEnter = React.useCallback((event) => {
1406
1410
  event.preventDefault();
1407
1411
  event.stopPropagation();