@comitor/ui 3.11.1 → 3.12.1

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 (75) hide show
  1. package/README.md +10 -5
  2. package/dist/chat/chat-composer.d.ts +36 -0
  3. package/dist/chat/chat-composer.js +85 -0
  4. package/dist/chat/chat-composer.js.map +1 -0
  5. package/dist/chat/chat-constants.d.ts +63 -0
  6. package/dist/chat/chat-constants.js +1 -0
  7. package/dist/chat/chat-constants.js.map +1 -0
  8. package/dist/chat/chat-message.d.ts +51 -0
  9. package/dist/chat/chat-message.js +137 -0
  10. package/dist/chat/chat-message.js.map +1 -0
  11. package/dist/chat/chat-sources.d.ts +25 -0
  12. package/dist/chat/chat-sources.js +97 -0
  13. package/dist/chat/chat-sources.js.map +1 -0
  14. package/dist/chat/chat-steps.d.ts +20 -0
  15. package/dist/chat/chat-steps.js +84 -0
  16. package/dist/chat/chat-steps.js.map +1 -0
  17. package/dist/chat/chat-thread.d.ts +21 -0
  18. package/dist/chat/chat-thread.js +87 -0
  19. package/dist/chat/chat-thread.js.map +1 -0
  20. package/dist/chat/index.d.ts +12 -0
  21. package/dist/chat/index.js +14 -0
  22. package/dist/chat/index.js.map +1 -0
  23. package/dist/components/composite/gantt-constants.d.ts +127 -0
  24. package/dist/components/composite/gantt-constants.js +5 -0
  25. package/dist/components/composite/gantt-constants.js.map +1 -0
  26. package/dist/components/composite/gantt-utils.d.ts +106 -0
  27. package/dist/components/composite/gantt-utils.js +196 -0
  28. package/dist/components/composite/gantt-utils.js.map +1 -0
  29. package/dist/components/composite/gantt.d.ts +93 -0
  30. package/dist/components/composite/gantt.js +1137 -0
  31. package/dist/components/composite/gantt.js.map +1 -0
  32. package/dist/components/composite/stat-card.d.ts +1 -1
  33. package/dist/components/composite/tree-view-constants.d.ts +96 -0
  34. package/dist/components/composite/tree-view-constants.js +85 -0
  35. package/dist/components/composite/tree-view-constants.js.map +1 -0
  36. package/dist/components/composite/tree-view.d.ts +58 -0
  37. package/dist/components/composite/tree-view.js +388 -0
  38. package/dist/components/composite/tree-view.js.map +1 -0
  39. package/dist/components/ui/badge.d.ts +1 -1
  40. package/dist/components/ui/button.d.ts +1 -1
  41. package/dist/editor/bubble-toolbar.d.ts +1 -1
  42. package/dist/editor/editor-core.d.ts +2 -2
  43. package/dist/editor/editor-core.js +6 -0
  44. package/dist/editor/editor-core.js.map +1 -1
  45. package/dist/editor/editor-types.d.ts +1 -1
  46. package/dist/editor/fixed-toolbar.d.ts +1 -1
  47. package/dist/editor/image-upload.d.ts +1 -1
  48. package/dist/editor/index.d.ts +1 -1
  49. package/dist/editor/markdown-editor.d.ts +1 -1
  50. package/dist/editor/markdown-extensions.d.ts +3 -1
  51. package/dist/editor/markdown-extensions.js +3 -1
  52. package/dist/editor/markdown-extensions.js.map +1 -1
  53. package/dist/editor/rich-text-editor.d.ts +1 -1
  54. package/dist/editor/slash-commands.d.ts +1 -1
  55. package/dist/editor/toolbar-actions.d.ts +1 -1
  56. package/dist/{editor-types-CSrMeuSw.d.ts → editor-types-BacXD2VN.d.ts} +7 -1
  57. package/dist/i18n/locale-provider.d.ts +3 -0
  58. package/dist/i18n/messages.d.ts +6 -0
  59. package/dist/i18n/messages.js +11 -2
  60. package/dist/i18n/messages.js.map +1 -1
  61. package/dist/i18n/namespaces/chat.d.ts +8 -0
  62. package/dist/i18n/namespaces/chat.js +47 -0
  63. package/dist/i18n/namespaces/chat.js.map +1 -0
  64. package/dist/i18n/namespaces/gantt.d.ts +10 -0
  65. package/dist/i18n/namespaces/gantt.js +57 -0
  66. package/dist/i18n/namespaces/gantt.js.map +1 -0
  67. package/dist/i18n/namespaces/tree-view.d.ts +8 -0
  68. package/dist/i18n/namespaces/tree-view.js +21 -0
  69. package/dist/i18n/namespaces/tree-view.js.map +1 -0
  70. package/dist/index.d.ts +6 -1
  71. package/dist/index.js +6 -1
  72. package/dist/index.js.map +1 -1
  73. package/dist/lib/avatar-tone.d.ts +4 -0
  74. package/dist/lib/avatar-tone.js.map +1 -1
  75. package/package.json +9 -2
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/i18n/messages.ts"],"sourcesContent":["/**\n * Bảng CHỮ của cả gói — module THUẦN (không directive, không hook), Server Component đọc thẳng\n * được (`verify:directives`, phép kiểm 2 và 3).\n *\n * Cùng khuôn với bảng chuỗi của `DataGrid` (`data-grid/messages.ts`), nay áp cho MỌI component:\n * · `comitorMessagesEn` là BẢN GỐC định nghĩa hình dạng ({@link ComitorMessages}). Tiếng Anh\n * là mặc định từ `3.0.0` — gói phục vụ cả app quốc tế, không chỉ app Comitor.\n * · `comitorMessagesVi` chú thích `: ComitorMessages`, nên thiếu một khoá là typecheck đỏ\n * ngay — không có đường nào để một chuỗi `undefined` lặng lẽ lọt ra giao diện.\n *\n * Mỗi namespace là MỘT component (hoặc một cụm component dùng chung chữ, vd `shell`). Chuỗi có\n * tham số viết thành HÀM, không phải mẫu có chỗ trống — trật tự từ quanh con số khác nhau theo ngôn\n * ngữ, nên mọi cách để gói tự nối chuỗi đều là chỗ chắc chắn dịch sai.\n *\n * Thêm ngôn ngữ thứ ba: app KHÔNG phải sửa gói — truyền cả một bảng qua prop `messages` của\n * `ComitorLocaleProvider` (trải `comitorMessagesEn` ra rồi dịch từng namespace).\n */\nimport { type ComitorLanguage, getComitorLanguage } from \"./locale.js\";\nimport { actionBarEn, actionBarVi } from \"./namespaces/action-bar.js\";\nimport { avatarGroupEn, avatarGroupVi } from \"./namespaces/avatar-group.js\";\nimport { badgeOverflowEn, badgeOverflowVi } from \"./namespaces/badge-overflow.js\";\nimport { bannerEn, bannerVi } from \"./namespaces/banner.js\";\nimport { breadcrumbEn, breadcrumbVi } from \"./namespaces/breadcrumb.js\";\nimport { calendarEn, calendarVi } from \"./namespaces/calendar.js\";\nimport { carouselEn, carouselVi } from \"./namespaces/carousel.js\";\nimport { comboboxEn, comboboxVi } from \"./namespaces/combobox.js\";\nimport { commandEn, commandVi } from \"./namespaces/command.js\";\nimport { commandPaletteEn, commandPaletteVi } from \"./namespaces/command-palette.js\";\nimport { confirmDialogEn, confirmDialogVi } from \"./namespaces/confirm-dialog.js\";\nimport { contrastEn, contrastVi } from \"./namespaces/contrast.js\";\nimport { copyButtonEn, copyButtonVi } from \"./namespaces/copy-button.js\";\nimport { cropperEn, cropperVi } from \"./namespaces/cropper.js\";\nimport { dataTableEn, dataTableVi } from \"./namespaces/data-table.js\";\nimport { datePickerEn, datePickerVi } from \"./namespaces/date-picker.js\";\nimport { dialogEn, dialogVi } from \"./namespaces/dialog.js\";\nimport { displayAxisEn, displayAxisVi } from \"./namespaces/display-axis.js\";\nimport { fileUploadEn, fileUploadVi } from \"./namespaces/file-upload.js\";\nimport { filterChipsEn, filterChipsVi } from \"./namespaces/filter-chips.js\";\nimport { imageUploadFieldEn, imageUploadFieldVi } from \"./namespaces/image-upload-field.js\";\nimport { inlineEditEn, inlineEditVi } from \"./namespaces/inline-edit.js\";\nimport { kanbanEn, kanbanVi } from \"./namespaces/kanban.js\";\nimport { keyValueEn, keyValueVi } from \"./namespaces/key-value.js\";\nimport { keyboardShortcutsEn, keyboardShortcutsVi } from \"./namespaces/keyboard-shortcuts.js\";\nimport { markdownEditorEn, markdownEditorVi } from \"./namespaces/markdown-editor.js\";\nimport { mentionEn, mentionVi } from \"./namespaces/mention.js\";\nimport { paginationEn, paginationVi } from \"./namespaces/pagination.js\";\nimport { phoneInputEn, phoneInputVi } from \"./namespaces/phone-input.js\";\nimport { ratingEn, ratingVi } from \"./namespaces/rating.js\";\nimport { routeTabsEn, routeTabsVi } from \"./namespaces/route-tabs.js\";\nimport { scrollSpyEn, scrollSpyVi } from \"./namespaces/scroll-spy.js\";\nimport { searchFilterBarEn, searchFilterBarVi } from \"./namespaces/search-filter-bar.js\";\nimport { sheetEn, sheetVi } from \"./namespaces/sheet.js\";\nimport { shellEn, shellVi } from \"./namespaces/shell.js\";\nimport { spinnerEn, spinnerVi } from \"./namespaces/spinner.js\";\nimport { stepperEn, stepperVi } from \"./namespaces/stepper.js\";\nimport { tablePaginationEn, tablePaginationVi } from \"./namespaces/table-pagination.js\";\nimport { tagsInputEn, tagsInputVi } from \"./namespaces/tags-input.js\";\nimport { timePickerEn, timePickerVi } from \"./namespaces/time-picker.js\";\nimport { toastEn, toastVi } from \"./namespaces/toast.js\";\nimport { tourEn, tourVi } from \"./namespaces/tour.js\";\n\n/** Bảng tiếng Anh — BẢN GỐC, định nghĩa hình dạng của mọi bảng khác. */\nexport const comitorMessagesEn = {\n actionBar: actionBarEn,\n avatarGroup: avatarGroupEn,\n badgeOverflow: badgeOverflowEn,\n banner: bannerEn,\n breadcrumb: breadcrumbEn,\n calendar: calendarEn,\n carousel: carouselEn,\n combobox: comboboxEn,\n command: commandEn,\n commandPalette: commandPaletteEn,\n confirmDialog: confirmDialogEn,\n contrast: contrastEn,\n copyButton: copyButtonEn,\n cropper: cropperEn,\n dataTable: dataTableEn,\n datePicker: datePickerEn,\n dialog: dialogEn,\n displayAxis: displayAxisEn,\n fileUpload: fileUploadEn,\n filterChips: filterChipsEn,\n imageUploadField: imageUploadFieldEn,\n inlineEdit: inlineEditEn,\n keyboardShortcuts: keyboardShortcutsEn,\n kanban: kanbanEn,\n keyValue: keyValueEn,\n markdownEditor: markdownEditorEn,\n mention: mentionEn,\n pagination: paginationEn,\n phoneInput: phoneInputEn,\n rating: ratingEn,\n routeTabs: routeTabsEn,\n scrollSpy: scrollSpyEn,\n searchFilterBar: searchFilterBarEn,\n sheet: sheetEn,\n shell: shellEn,\n spinner: spinnerEn,\n stepper: stepperEn,\n tablePagination: tablePaginationEn,\n tagsInput: tagsInputEn,\n timePicker: timePickerEn,\n toast: toastEn,\n tour: tourEn\n};\n\n/** Hình dạng của một bảng chữ đầy đủ. Suy từ bảng tiếng Anh, không viết tay lần hai. */\nexport type ComitorMessages = typeof comitorMessagesEn;\n\n/** Bảng tiếng Việt — phải phủ ĐỦ mọi khoá của bảng tiếng Anh. */\nexport const comitorMessagesVi: ComitorMessages = {\n actionBar: actionBarVi,\n avatarGroup: avatarGroupVi,\n badgeOverflow: badgeOverflowVi,\n banner: bannerVi,\n breadcrumb: breadcrumbVi,\n calendar: calendarVi,\n carousel: carouselVi,\n combobox: comboboxVi,\n command: commandVi,\n commandPalette: commandPaletteVi,\n confirmDialog: confirmDialogVi,\n contrast: contrastVi,\n copyButton: copyButtonVi,\n cropper: cropperVi,\n dataTable: dataTableVi,\n datePicker: datePickerVi,\n dialog: dialogVi,\n displayAxis: displayAxisVi,\n fileUpload: fileUploadVi,\n filterChips: filterChipsVi,\n imageUploadField: imageUploadFieldVi,\n inlineEdit: inlineEditVi,\n keyboardShortcuts: keyboardShortcutsVi,\n kanban: kanbanVi,\n keyValue: keyValueVi,\n markdownEditor: markdownEditorVi,\n mention: mentionVi,\n pagination: paginationVi,\n phoneInput: phoneInputVi,\n rating: ratingVi,\n routeTabs: routeTabsVi,\n scrollSpy: scrollSpyVi,\n searchFilterBar: searchFilterBarVi,\n sheet: sheetVi,\n shell: shellVi,\n spinner: spinnerVi,\n stepper: stepperVi,\n tablePagination: tablePaginationVi,\n tagsInput: tagsInputVi,\n timePicker: timePickerVi,\n toast: toastVi,\n tour: tourVi\n};\n\n/** Mọi bảng dựng sẵn, tra theo ngôn ngữ. */\nexport const COMITOR_MESSAGES: Record<ComitorLanguage, ComitorMessages> = {\n en: comitorMessagesEn,\n vi: comitorMessagesVi\n};\n\n/**\n * Ghi đè MỘT PHẦN: theo namespace, và trong mỗi namespace theo khoá. Dùng để đổi vài chữ theo\n * nghiệp vụ (\"Không gian làm việc\" → \"Công ty\"), hoặc để cấp nguyên một bảng cho ngôn ngữ thứ ba.\n */\nexport type ComitorMessagesOverride = {\n [K in keyof ComitorMessages]?: Partial<ComitorMessages[K]>;\n};\n\n/**\n * Trộn phần ghi đè vào một bảng đầy đủ — từng namespace một, nông ở cấp khoá. Không đụng tới bảng\n * gốc (trả về object mới), và namespace không được ghi đè giữ nguyên tham chiếu.\n */\nexport function mergeComitorMessages(base: ComitorMessages, override?: ComitorMessagesOverride): ComitorMessages {\n if (!override) return base;\n const merged = { ...base } as Record<string, object>;\n for (const key of Object.keys(override) as Array<keyof ComitorMessages>) {\n const part = override[key];\n if (part) merged[key] = { ...base[key], ...part };\n }\n return merged as ComitorMessages;\n}\n\n/**\n * Bảng chữ cho một `locale` (+ phần ghi đè) — bản THUẦN của những gì `ComitorLocaleProvider` làm,\n * dành cho nơi không có context: Server Component, email, toast bắn ngoài cây React.\n */\nexport function getComitorMessages(locale?: string | null, override?: ComitorMessagesOverride): ComitorMessages {\n return mergeComitorMessages(COMITOR_MESSAGES[getComitorLanguage(locale)], override);\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/i18n/messages.ts"],"sourcesContent":["/**\n * Bảng CHỮ của cả gói — module THUẦN (không directive, không hook), Server Component đọc thẳng\n * được (`verify:directives`, phép kiểm 2 và 3).\n *\n * Cùng khuôn với bảng chuỗi của `DataGrid` (`data-grid/messages.ts`), nay áp cho MỌI component:\n * · `comitorMessagesEn` là BẢN GỐC định nghĩa hình dạng ({@link ComitorMessages}). Tiếng Anh\n * là mặc định từ `3.0.0` — gói phục vụ cả app quốc tế, không chỉ app Comitor.\n * · `comitorMessagesVi` chú thích `: ComitorMessages`, nên thiếu một khoá là typecheck đỏ\n * ngay — không có đường nào để một chuỗi `undefined` lặng lẽ lọt ra giao diện.\n *\n * Mỗi namespace là MỘT component (hoặc một cụm component dùng chung chữ, vd `shell`). Chuỗi có\n * tham số viết thành HÀM, không phải mẫu có chỗ trống — trật tự từ quanh con số khác nhau theo ngôn\n * ngữ, nên mọi cách để gói tự nối chuỗi đều là chỗ chắc chắn dịch sai.\n *\n * Thêm ngôn ngữ thứ ba: app KHÔNG phải sửa gói — truyền cả một bảng qua prop `messages` của\n * `ComitorLocaleProvider` (trải `comitorMessagesEn` ra rồi dịch từng namespace).\n */\nimport { type ComitorLanguage, getComitorLanguage } from \"./locale.js\";\nimport { actionBarEn, actionBarVi } from \"./namespaces/action-bar.js\";\nimport { avatarGroupEn, avatarGroupVi } from \"./namespaces/avatar-group.js\";\nimport { badgeOverflowEn, badgeOverflowVi } from \"./namespaces/badge-overflow.js\";\nimport { bannerEn, bannerVi } from \"./namespaces/banner.js\";\nimport { breadcrumbEn, breadcrumbVi } from \"./namespaces/breadcrumb.js\";\nimport { calendarEn, calendarVi } from \"./namespaces/calendar.js\";\nimport { carouselEn, carouselVi } from \"./namespaces/carousel.js\";\nimport { chatEn, chatVi } from \"./namespaces/chat.js\";\nimport { comboboxEn, comboboxVi } from \"./namespaces/combobox.js\";\nimport { commandEn, commandVi } from \"./namespaces/command.js\";\nimport { commandPaletteEn, commandPaletteVi } from \"./namespaces/command-palette.js\";\nimport { confirmDialogEn, confirmDialogVi } from \"./namespaces/confirm-dialog.js\";\nimport { contrastEn, contrastVi } from \"./namespaces/contrast.js\";\nimport { copyButtonEn, copyButtonVi } from \"./namespaces/copy-button.js\";\nimport { cropperEn, cropperVi } from \"./namespaces/cropper.js\";\nimport { dataTableEn, dataTableVi } from \"./namespaces/data-table.js\";\nimport { datePickerEn, datePickerVi } from \"./namespaces/date-picker.js\";\nimport { dialogEn, dialogVi } from \"./namespaces/dialog.js\";\nimport { displayAxisEn, displayAxisVi } from \"./namespaces/display-axis.js\";\nimport { fileUploadEn, fileUploadVi } from \"./namespaces/file-upload.js\";\nimport { filterChipsEn, filterChipsVi } from \"./namespaces/filter-chips.js\";\nimport { ganttEn, ganttVi } from \"./namespaces/gantt.js\";\nimport { imageUploadFieldEn, imageUploadFieldVi } from \"./namespaces/image-upload-field.js\";\nimport { inlineEditEn, inlineEditVi } from \"./namespaces/inline-edit.js\";\nimport { kanbanEn, kanbanVi } from \"./namespaces/kanban.js\";\nimport { keyValueEn, keyValueVi } from \"./namespaces/key-value.js\";\nimport { keyboardShortcutsEn, keyboardShortcutsVi } from \"./namespaces/keyboard-shortcuts.js\";\nimport { markdownEditorEn, markdownEditorVi } from \"./namespaces/markdown-editor.js\";\nimport { mentionEn, mentionVi } from \"./namespaces/mention.js\";\nimport { paginationEn, paginationVi } from \"./namespaces/pagination.js\";\nimport { phoneInputEn, phoneInputVi } from \"./namespaces/phone-input.js\";\nimport { ratingEn, ratingVi } from \"./namespaces/rating.js\";\nimport { routeTabsEn, routeTabsVi } from \"./namespaces/route-tabs.js\";\nimport { scrollSpyEn, scrollSpyVi } from \"./namespaces/scroll-spy.js\";\nimport { searchFilterBarEn, searchFilterBarVi } from \"./namespaces/search-filter-bar.js\";\nimport { sheetEn, sheetVi } from \"./namespaces/sheet.js\";\nimport { shellEn, shellVi } from \"./namespaces/shell.js\";\nimport { spinnerEn, spinnerVi } from \"./namespaces/spinner.js\";\nimport { stepperEn, stepperVi } from \"./namespaces/stepper.js\";\nimport { tablePaginationEn, tablePaginationVi } from \"./namespaces/table-pagination.js\";\nimport { tagsInputEn, tagsInputVi } from \"./namespaces/tags-input.js\";\nimport { timePickerEn, timePickerVi } from \"./namespaces/time-picker.js\";\nimport { toastEn, toastVi } from \"./namespaces/toast.js\";\nimport { tourEn, tourVi } from \"./namespaces/tour.js\";\nimport { treeViewEn, treeViewVi } from \"./namespaces/tree-view.js\";\n\n/** Bảng tiếng Anh — BẢN GỐC, định nghĩa hình dạng của mọi bảng khác. */\nexport const comitorMessagesEn = {\n actionBar: actionBarEn,\n avatarGroup: avatarGroupEn,\n badgeOverflow: badgeOverflowEn,\n banner: bannerEn,\n breadcrumb: breadcrumbEn,\n calendar: calendarEn,\n carousel: carouselEn,\n chat: chatEn,\n combobox: comboboxEn,\n command: commandEn,\n commandPalette: commandPaletteEn,\n confirmDialog: confirmDialogEn,\n contrast: contrastEn,\n copyButton: copyButtonEn,\n cropper: cropperEn,\n dataTable: dataTableEn,\n datePicker: datePickerEn,\n dialog: dialogEn,\n displayAxis: displayAxisEn,\n fileUpload: fileUploadEn,\n filterChips: filterChipsEn,\n gantt: ganttEn,\n imageUploadField: imageUploadFieldEn,\n inlineEdit: inlineEditEn,\n keyboardShortcuts: keyboardShortcutsEn,\n kanban: kanbanEn,\n keyValue: keyValueEn,\n markdownEditor: markdownEditorEn,\n mention: mentionEn,\n pagination: paginationEn,\n phoneInput: phoneInputEn,\n rating: ratingEn,\n routeTabs: routeTabsEn,\n scrollSpy: scrollSpyEn,\n searchFilterBar: searchFilterBarEn,\n sheet: sheetEn,\n shell: shellEn,\n spinner: spinnerEn,\n stepper: stepperEn,\n tablePagination: tablePaginationEn,\n tagsInput: tagsInputEn,\n timePicker: timePickerEn,\n toast: toastEn,\n tour: tourEn,\n treeView: treeViewEn\n};\n\n/** Hình dạng của một bảng chữ đầy đủ. Suy từ bảng tiếng Anh, không viết tay lần hai. */\nexport type ComitorMessages = typeof comitorMessagesEn;\n\n/** Bảng tiếng Việt — phải phủ ĐỦ mọi khoá của bảng tiếng Anh. */\nexport const comitorMessagesVi: ComitorMessages = {\n actionBar: actionBarVi,\n avatarGroup: avatarGroupVi,\n badgeOverflow: badgeOverflowVi,\n banner: bannerVi,\n breadcrumb: breadcrumbVi,\n calendar: calendarVi,\n carousel: carouselVi,\n chat: chatVi,\n combobox: comboboxVi,\n command: commandVi,\n commandPalette: commandPaletteVi,\n confirmDialog: confirmDialogVi,\n contrast: contrastVi,\n copyButton: copyButtonVi,\n cropper: cropperVi,\n dataTable: dataTableVi,\n datePicker: datePickerVi,\n dialog: dialogVi,\n displayAxis: displayAxisVi,\n fileUpload: fileUploadVi,\n filterChips: filterChipsVi,\n gantt: ganttVi,\n imageUploadField: imageUploadFieldVi,\n inlineEdit: inlineEditVi,\n keyboardShortcuts: keyboardShortcutsVi,\n kanban: kanbanVi,\n keyValue: keyValueVi,\n markdownEditor: markdownEditorVi,\n mention: mentionVi,\n pagination: paginationVi,\n phoneInput: phoneInputVi,\n rating: ratingVi,\n routeTabs: routeTabsVi,\n scrollSpy: scrollSpyVi,\n searchFilterBar: searchFilterBarVi,\n sheet: sheetVi,\n shell: shellVi,\n spinner: spinnerVi,\n stepper: stepperVi,\n tablePagination: tablePaginationVi,\n tagsInput: tagsInputVi,\n timePicker: timePickerVi,\n toast: toastVi,\n tour: tourVi,\n treeView: treeViewVi\n};\n\n/** Mọi bảng dựng sẵn, tra theo ngôn ngữ. */\nexport const COMITOR_MESSAGES: Record<ComitorLanguage, ComitorMessages> = {\n en: comitorMessagesEn,\n vi: comitorMessagesVi\n};\n\n/**\n * Ghi đè MỘT PHẦN: theo namespace, và trong mỗi namespace theo khoá. Dùng để đổi vài chữ theo\n * nghiệp vụ (\"Không gian làm việc\" → \"Công ty\"), hoặc để cấp nguyên một bảng cho ngôn ngữ thứ ba.\n */\nexport type ComitorMessagesOverride = {\n [K in keyof ComitorMessages]?: Partial<ComitorMessages[K]>;\n};\n\n/**\n * Trộn phần ghi đè vào một bảng đầy đủ — từng namespace một, nông ở cấp khoá. Không đụng tới bảng\n * gốc (trả về object mới), và namespace không được ghi đè giữ nguyên tham chiếu.\n */\nexport function mergeComitorMessages(base: ComitorMessages, override?: ComitorMessagesOverride): ComitorMessages {\n if (!override) return base;\n const merged = { ...base } as Record<string, object>;\n for (const key of Object.keys(override) as Array<keyof ComitorMessages>) {\n const part = override[key];\n if (part) merged[key] = { ...base[key], ...part };\n }\n return merged as ComitorMessages;\n}\n\n/**\n * Bảng chữ cho một `locale` (+ phần ghi đè) — bản THUẦN của những gì `ComitorLocaleProvider` làm,\n * dành cho nơi không có context: Server Component, email, toast bắn ngoài cây React.\n */\nexport function getComitorMessages(locale?: string | null, override?: ComitorMessagesOverride): ComitorMessages {\n return mergeComitorMessages(COMITOR_MESSAGES[getComitorLanguage(locale)], override);\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,8 @@
1
+ import { ChatLabels } from '../../chat/chat-constants.js';
2
+ import 'react';
3
+
4
+ /** Chữ của khung hội thoại (`@comitor/ui/chat`). Hình dạng + chú thích từng khoá: `ChatLabels`. */
5
+ declare const chatEn: ChatLabels;
6
+ declare const chatVi: ChatLabels;
7
+
8
+ export { chatEn, chatVi };
@@ -0,0 +1,47 @@
1
+ const chatEn = {
2
+ log: "Conversation",
3
+ scrollToLatest: "Scroll to latest message",
4
+ aiGenerated: "AI-generated",
5
+ aiGeneratedHint: "Generated by AI. Check important details before relying on them.",
6
+ you: "You",
7
+ assistant: "Assistant",
8
+ thinking: "Thinking\u2026",
9
+ stepsSummary: (done, total) => `${done} of ${total} ${total === 1 ? "step" : "steps"}`,
10
+ stepPending: "Pending",
11
+ stepRunning: "In progress",
12
+ stepDone: "Done",
13
+ stepError: "Failed",
14
+ sources: (count) => `${count} ${count === 1 ? "source" : "sources"}`,
15
+ citation: (index, title) => `Source ${index}: ${title}`,
16
+ opensInNewTab: "(opens in a new tab)",
17
+ composerLabel: "Message",
18
+ composerPlaceholder: "Ask anything\u2026 Type @ to mention",
19
+ send: "Send",
20
+ stop: "Stop generating"
21
+ };
22
+ const chatVi = {
23
+ log: "Cu\u1ED9c tr\xF2 chuy\u1EC7n",
24
+ scrollToLatest: "Cu\u1ED9n t\u1EDBi tin m\u1EDBi nh\u1EA5t",
25
+ aiGenerated: "Do AI t\u1EA1o",
26
+ aiGeneratedHint: "N\u1ED9i dung do AI t\u1EA1o. H\xE3y ki\u1EC3m tra c\xE1c chi ti\u1EBFt quan tr\u1ECDng tr\u01B0\u1EDBc khi d\xF9ng.",
27
+ you: "B\u1EA1n",
28
+ assistant: "Tr\u1EE3 l\xFD",
29
+ thinking: "\u0110ang suy ngh\u0129\u2026",
30
+ stepsSummary: (done, total) => `${done}/${total} b\u01B0\u1EDBc`,
31
+ stepPending: "Ch\u1EDD",
32
+ stepRunning: "\u0110ang l\xE0m",
33
+ stepDone: "Xong",
34
+ stepError: "L\u1ED7i",
35
+ sources: (count) => `${count} ngu\u1ED3n`,
36
+ citation: (index, title) => `Ngu\u1ED3n ${index}: ${title}`,
37
+ opensInNewTab: "(m\u1EDF trong th\u1EBB m\u1EDBi)",
38
+ composerLabel: "Tin nh\u1EAFn",
39
+ composerPlaceholder: "H\u1ECFi b\u1EA5t c\u1EE9 \u0111i\u1EC1u g\xEC\u2026 G\xF5 @ \u0111\u1EC3 nh\u1EAFc t\xEAn",
40
+ send: "G\u1EEDi",
41
+ stop: "D\u1EEBng tr\u1EA3 l\u1EDDi"
42
+ };
43
+ export {
44
+ chatEn,
45
+ chatVi
46
+ };
47
+ //# sourceMappingURL=chat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/i18n/namespaces/chat.ts"],"sourcesContent":["import type { ChatLabels } from \"../../chat/chat-constants.js\";\n\n/** Chữ của khung hội thoại (`@comitor/ui/chat`). Hình dạng + chú thích từng khoá: `ChatLabels`. */\nexport const chatEn: ChatLabels = {\n log: \"Conversation\",\n scrollToLatest: \"Scroll to latest message\",\n aiGenerated: \"AI-generated\",\n aiGeneratedHint: \"Generated by AI. Check important details before relying on them.\",\n you: \"You\",\n assistant: \"Assistant\",\n thinking: \"Thinking…\",\n stepsSummary: (done, total) => `${done} of ${total} ${total === 1 ? \"step\" : \"steps\"}`,\n stepPending: \"Pending\",\n stepRunning: \"In progress\",\n stepDone: \"Done\",\n stepError: \"Failed\",\n sources: (count) => `${count} ${count === 1 ? \"source\" : \"sources\"}`,\n citation: (index, title) => `Source ${index}: ${title}`,\n opensInNewTab: \"(opens in a new tab)\",\n composerLabel: \"Message\",\n composerPlaceholder: \"Ask anything… Type @ to mention\",\n send: \"Send\",\n stop: \"Stop generating\"\n};\n\nexport const chatVi: ChatLabels = {\n log: \"Cuộc trò chuyện\",\n scrollToLatest: \"Cuộn tới tin mới nhất\",\n aiGenerated: \"Do AI tạo\",\n aiGeneratedHint: \"Nội dung do AI tạo. Hãy kiểm tra các chi tiết quan trọng trước khi dùng.\",\n you: \"Bạn\",\n assistant: \"Trợ lý\",\n thinking: \"Đang suy nghĩ…\",\n stepsSummary: (done, total) => `${done}/${total} bước`,\n stepPending: \"Chờ\",\n stepRunning: \"Đang làm\",\n stepDone: \"Xong\",\n stepError: \"Lỗi\",\n sources: (count) => `${count} nguồn`,\n citation: (index, title) => `Nguồn ${index}: ${title}`,\n opensInNewTab: \"(mở trong thẻ mới)\",\n composerLabel: \"Tin nhắn\",\n composerPlaceholder: \"Hỏi bất cứ điều gì… Gõ @ để nhắc tên\",\n send: \"Gửi\",\n stop: \"Dừng trả lời\"\n};\n"],"mappings":"AAGO,MAAM,SAAqB;AAAA,EAChC,KAAK;AAAA,EACL,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,KAAK;AAAA,EACL,WAAW;AAAA,EACX,UAAU;AAAA,EACV,cAAc,CAAC,MAAM,UAAU,GAAG,IAAI,OAAO,KAAK,IAAI,UAAU,IAAI,SAAS,OAAO;AAAA,EACpF,aAAa;AAAA,EACb,aAAa;AAAA,EACb,UAAU;AAAA,EACV,WAAW;AAAA,EACX,SAAS,CAAC,UAAU,GAAG,KAAK,IAAI,UAAU,IAAI,WAAW,SAAS;AAAA,EAClE,UAAU,CAAC,OAAO,UAAU,UAAU,KAAK,KAAK,KAAK;AAAA,EACrD,eAAe;AAAA,EACf,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,MAAM;AAAA,EACN,MAAM;AACR;AAEO,MAAM,SAAqB;AAAA,EAChC,KAAK;AAAA,EACL,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,KAAK;AAAA,EACL,WAAW;AAAA,EACX,UAAU;AAAA,EACV,cAAc,CAAC,MAAM,UAAU,GAAG,IAAI,IAAI,KAAK;AAAA,EAC/C,aAAa;AAAA,EACb,aAAa;AAAA,EACb,UAAU;AAAA,EACV,WAAW;AAAA,EACX,SAAS,CAAC,UAAU,GAAG,KAAK;AAAA,EAC5B,UAAU,CAAC,OAAO,UAAU,cAAS,KAAK,KAAK,KAAK;AAAA,EACpD,eAAe;AAAA,EACf,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,MAAM;AAAA,EACN,MAAM;AACR;","names":[]}
@@ -0,0 +1,10 @@
1
+ import { GanttLabels } from '../../components/composite/gantt-constants.js';
2
+
3
+ /**
4
+ * Chữ của `Gantt`. Hình dạng + chú thích từng khoá: `GanttLabels`. Ngày đưa vào các hàm ở đây ĐÃ
5
+ * được định dạng theo `locale` của provider (`Intl.DateTimeFormat`) — hàm chỉ ghép câu.
6
+ */
7
+ declare const ganttEn: GanttLabels;
8
+ declare const ganttVi: GanttLabels;
9
+
10
+ export { ganttEn, ganttVi };
@@ -0,0 +1,57 @@
1
+ const ganttEn = {
2
+ label: "Timeline",
3
+ sidebarTitle: "Name",
4
+ scaleLabel: "Zoom",
5
+ scaleDay: "Days",
6
+ scaleWeek: "Weeks",
7
+ scaleMonth: "Months",
8
+ scaleQuarter: "Quarters",
9
+ scaleYear: "Years",
10
+ today: "Today",
11
+ quarter: (quarter) => `Q${quarter}`,
12
+ itemRange: (start, end, days) => `${start} \u2013 ${end}, ${days} ${days === 1 ? "day" : "days"}`,
13
+ milestoneDate: (date) => `Milestone on ${date}`,
14
+ progress: (percent) => `${percent}% complete`,
15
+ unscheduled: "No dates",
16
+ critical: "On the critical path",
17
+ conflict: "Starts before a task it depends on",
18
+ instructions: "Use Up and Down arrows to move between rows. Left and Right arrows move the dates by one day; hold Shift to move by a larger step. Alt with Left or Right changes the end date; Alt and Shift changes the start date. Enter opens the item, Space expands or collapses a group.",
19
+ rescheduled: (title, range) => `${title}: ${range}`,
20
+ expand: "Expand",
21
+ collapse: "Collapse",
22
+ scrollToItem: (title) => `Scroll to ${title}`,
23
+ linkHandle: (title) => `Drag to connect ${title} to the next task`,
24
+ dependency: (from, to) => `${from} \u2192 ${to}`,
25
+ scheduleHint: "Click to schedule"
26
+ };
27
+ const ganttVi = {
28
+ label: "Tr\u1EE5c th\u1EDDi gian",
29
+ sidebarTitle: "T\xEAn",
30
+ scaleLabel: "Thu ph\xF3ng",
31
+ scaleDay: "Ng\xE0y",
32
+ scaleWeek: "Tu\u1EA7n",
33
+ scaleMonth: "Th\xE1ng",
34
+ scaleQuarter: "Qu\xFD",
35
+ scaleYear: "N\u0103m",
36
+ today: "H\xF4m nay",
37
+ quarter: (quarter) => `Q${quarter}`,
38
+ itemRange: (start, end, days) => `${start} \u2013 ${end}, ${days} ng\xE0y`,
39
+ milestoneDate: (date) => `M\u1ED1c ng\xE0y ${date}`,
40
+ progress: (percent) => `Ho\xE0n th\xE0nh ${percent}%`,
41
+ unscheduled: "Ch\u01B0a c\xF3 ng\xE0y",
42
+ critical: "N\u1EB1m tr\xEAn \u0111\u01B0\u1EDDng g\u0103ng",
43
+ conflict: "B\u1EAFt \u0111\u1EA7u tr\u01B0\u1EDBc khi vi\u1EC7c ph\u1EE5 thu\u1ED9c xong",
44
+ instructions: "D\xF9ng ph\xEDm m\u0169i t\xEAn l\xEAn, xu\u1ED1ng \u0111\u1EC3 chuy\u1EC3n d\xF2ng. M\u0169i t\xEAn tr\xE1i, ph\u1EA3i d\u1EDDi ng\xE0y \u0111i m\u1ED9t ng\xE0y; gi\u1EEF Shift \u0111\u1EC3 d\u1EDDi m\u1ED9t b\u01B0\u1EDBc l\u1EDBn. Alt c\xF9ng m\u0169i t\xEAn tr\xE1i, ph\u1EA3i \u0111\u1ED5i ng\xE0y k\u1EBFt th\xFAc; Alt v\xE0 Shift \u0111\u1ED5i ng\xE0y b\u1EAFt \u0111\u1EA7u. Enter m\u1EDF m\u1EE5c, Space m\u1EDF ho\u1EB7c thu m\u1ED9t nh\xF3m.",
45
+ rescheduled: (title, range) => `${title}: ${range}`,
46
+ expand: "M\u1EDF r\u1ED9ng",
47
+ collapse: "Thu g\u1ECDn",
48
+ scrollToItem: (title) => `Cu\u1ED9n t\u1EDBi ${title}`,
49
+ linkHandle: (title) => `K\xE9o \u0111\u1EC3 n\u1ED1i ${title} v\u1EDBi vi\u1EC7c sau`,
50
+ dependency: (from, to) => `${from} \u2192 ${to}`,
51
+ scheduleHint: "B\u1EA5m \u0111\u1EC3 x\u1EBFp l\u1ECBch"
52
+ };
53
+ export {
54
+ ganttEn,
55
+ ganttVi
56
+ };
57
+ //# sourceMappingURL=gantt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/i18n/namespaces/gantt.ts"],"sourcesContent":["import type { GanttLabels } from \"../../components/composite/gantt-constants.js\";\n\n/**\n * Chữ của `Gantt`. Hình dạng + chú thích từng khoá: `GanttLabels`. Ngày đưa vào các hàm ở đây ĐÃ\n * được định dạng theo `locale` của provider (`Intl.DateTimeFormat`) — hàm chỉ ghép câu.\n */\nexport const ganttEn: GanttLabels = {\n label: \"Timeline\",\n sidebarTitle: \"Name\",\n scaleLabel: \"Zoom\",\n scaleDay: \"Days\",\n scaleWeek: \"Weeks\",\n scaleMonth: \"Months\",\n scaleQuarter: \"Quarters\",\n scaleYear: \"Years\",\n today: \"Today\",\n quarter: (quarter) => `Q${quarter}`,\n itemRange: (start, end, days) => `${start} – ${end}, ${days} ${days === 1 ? \"day\" : \"days\"}`,\n milestoneDate: (date) => `Milestone on ${date}`,\n progress: (percent) => `${percent}% complete`,\n unscheduled: \"No dates\",\n critical: \"On the critical path\",\n conflict: \"Starts before a task it depends on\",\n instructions:\n \"Use Up and Down arrows to move between rows. Left and Right arrows move the dates by one day; hold Shift to move by a larger step. Alt with Left or Right changes the end date; Alt and Shift changes the start date. Enter opens the item, Space expands or collapses a group.\",\n rescheduled: (title, range) => `${title}: ${range}`,\n expand: \"Expand\",\n collapse: \"Collapse\",\n scrollToItem: (title) => `Scroll to ${title}`,\n linkHandle: (title) => `Drag to connect ${title} to the next task`,\n dependency: (from, to) => `${from} → ${to}`,\n scheduleHint: \"Click to schedule\"\n};\n\nexport const ganttVi: GanttLabels = {\n label: \"Trục thời gian\",\n sidebarTitle: \"Tên\",\n scaleLabel: \"Thu phóng\",\n scaleDay: \"Ngày\",\n scaleWeek: \"Tuần\",\n scaleMonth: \"Tháng\",\n scaleQuarter: \"Quý\",\n scaleYear: \"Năm\",\n today: \"Hôm nay\",\n quarter: (quarter) => `Q${quarter}`,\n itemRange: (start, end, days) => `${start} – ${end}, ${days} ngày`,\n milestoneDate: (date) => `Mốc ngày ${date}`,\n progress: (percent) => `Hoàn thành ${percent}%`,\n unscheduled: \"Chưa có ngày\",\n critical: \"Nằm trên đường găng\",\n conflict: \"Bắt đầu trước khi việc phụ thuộc xong\",\n instructions:\n \"Dùng phím mũi tên lên, xuống để chuyển dòng. Mũi tên trái, phải dời ngày đi một ngày; giữ Shift để dời một bước lớn. Alt cùng mũi tên trái, phải đổi ngày kết thúc; Alt và Shift đổi ngày bắt đầu. Enter mở mục, Space mở hoặc thu một nhóm.\",\n rescheduled: (title, range) => `${title}: ${range}`,\n expand: \"Mở rộng\",\n collapse: \"Thu gọn\",\n scrollToItem: (title) => `Cuộn tới ${title}`,\n linkHandle: (title) => `Kéo để nối ${title} với việc sau`,\n dependency: (from, to) => `${from} → ${to}`,\n scheduleHint: \"Bấm để xếp lịch\"\n};\n"],"mappings":"AAMO,MAAM,UAAuB;AAAA,EAClC,OAAO;AAAA,EACP,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,WAAW;AAAA,EACX,OAAO;AAAA,EACP,SAAS,CAAC,YAAY,IAAI,OAAO;AAAA,EACjC,WAAW,CAAC,OAAO,KAAK,SAAS,GAAG,KAAK,WAAM,GAAG,KAAK,IAAI,IAAI,SAAS,IAAI,QAAQ,MAAM;AAAA,EAC1F,eAAe,CAAC,SAAS,gBAAgB,IAAI;AAAA,EAC7C,UAAU,CAAC,YAAY,GAAG,OAAO;AAAA,EACjC,aAAa;AAAA,EACb,UAAU;AAAA,EACV,UAAU;AAAA,EACV,cACE;AAAA,EACF,aAAa,CAAC,OAAO,UAAU,GAAG,KAAK,KAAK,KAAK;AAAA,EACjD,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,cAAc,CAAC,UAAU,aAAa,KAAK;AAAA,EAC3C,YAAY,CAAC,UAAU,mBAAmB,KAAK;AAAA,EAC/C,YAAY,CAAC,MAAM,OAAO,GAAG,IAAI,WAAM,EAAE;AAAA,EACzC,cAAc;AAChB;AAEO,MAAM,UAAuB;AAAA,EAClC,OAAO;AAAA,EACP,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,WAAW;AAAA,EACX,OAAO;AAAA,EACP,SAAS,CAAC,YAAY,IAAI,OAAO;AAAA,EACjC,WAAW,CAAC,OAAO,KAAK,SAAS,GAAG,KAAK,WAAM,GAAG,KAAK,IAAI;AAAA,EAC3D,eAAe,CAAC,SAAS,oBAAY,IAAI;AAAA,EACzC,UAAU,CAAC,YAAY,oBAAc,OAAO;AAAA,EAC5C,aAAa;AAAA,EACb,UAAU;AAAA,EACV,UAAU;AAAA,EACV,cACE;AAAA,EACF,aAAa,CAAC,OAAO,UAAU,GAAG,KAAK,KAAK,KAAK;AAAA,EACjD,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,cAAc,CAAC,UAAU,sBAAY,KAAK;AAAA,EAC1C,YAAY,CAAC,UAAU,gCAAc,KAAK;AAAA,EAC1C,YAAY,CAAC,MAAM,OAAO,GAAG,IAAI,WAAM,EAAE;AAAA,EACzC,cAAc;AAChB;","names":[]}
@@ -0,0 +1,8 @@
1
+ import { TreeViewLabels } from '../../components/composite/tree-view-constants.js';
2
+ import 'react';
3
+
4
+ /** Chữ của `TreeView`. Hình dạng + chú thích từng khoá: `TreeViewLabels`. */
5
+ declare const treeViewEn: TreeViewLabels;
6
+ declare const treeViewVi: TreeViewLabels;
7
+
8
+ export { treeViewEn, treeViewVi };
@@ -0,0 +1,21 @@
1
+ const treeViewEn = {
2
+ label: "Tree",
3
+ nameHeader: "Name",
4
+ root: "the top level",
5
+ instructions: "Use Up and Down arrows to move between items, Right to expand and Left to collapse. Tab indents the item under the one above it, Shift+Tab outdents it. Alt with Up or Down moves the item among its siblings. Enter opens the item.",
6
+ movedInto: (name, parent, position, total) => `${name} moved into ${parent}, position ${position} of ${total}.`,
7
+ movedTo: (name, position, total) => `${name} moved to position ${position} of ${total}.`
8
+ };
9
+ const treeViewVi = {
10
+ label: "C\xE2y",
11
+ nameHeader: "T\xEAn",
12
+ root: "c\u1EA5p ngo\xE0i c\xF9ng",
13
+ instructions: "D\xF9ng ph\xEDm m\u0169i t\xEAn l\xEAn, xu\u1ED1ng \u0111\u1EC3 chuy\u1EC3n m\u1EE5c, m\u0169i t\xEAn ph\u1EA3i \u0111\u1EC3 m\u1EDF v\xE0 m\u0169i t\xEAn tr\xE1i \u0111\u1EC3 thu nh\xE1nh. Tab \u0111\u01B0a m\u1EE5c v\xE0o l\xE0m con c\u1EE7a m\u1EE5c ph\xEDa tr\xEAn, Shift+Tab \u0111\u01B0a m\u1EE5c ra ngo\xE0i m\u1ED9t c\u1EA5p. Alt c\xF9ng m\u0169i t\xEAn l\xEAn, xu\u1ED1ng \u0111\u1ED5i ch\u1ED7 m\u1EE5c v\u1EDBi c\xE1c m\u1EE5c c\xF9ng c\u1EA5p. Enter m\u1EDF m\u1EE5c.",
14
+ movedInto: (name, parent, position, total) => `\u0110\xE3 chuy\u1EC3n ${name} v\xE0o ${parent}, v\u1ECB tr\xED ${position} tr\xEAn ${total}.`,
15
+ movedTo: (name, position, total) => `\u0110\xE3 chuy\u1EC3n ${name} t\u1EDBi v\u1ECB tr\xED ${position} tr\xEAn ${total}.`
16
+ };
17
+ export {
18
+ treeViewEn,
19
+ treeViewVi
20
+ };
21
+ //# sourceMappingURL=tree-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/i18n/namespaces/tree-view.ts"],"sourcesContent":["import type { TreeViewLabels } from \"../../components/composite/tree-view-constants.js\";\n\n/** Chữ của `TreeView`. Hình dạng + chú thích từng khoá: `TreeViewLabels`. */\nexport const treeViewEn: TreeViewLabels = {\n label: \"Tree\",\n nameHeader: \"Name\",\n root: \"the top level\",\n instructions:\n \"Use Up and Down arrows to move between items, Right to expand and Left to collapse. Tab indents the item under the one above it, Shift+Tab outdents it. Alt with Up or Down moves the item among its siblings. Enter opens the item.\",\n movedInto: (name, parent, position, total) => `${name} moved into ${parent}, position ${position} of ${total}.`,\n movedTo: (name, position, total) => `${name} moved to position ${position} of ${total}.`\n};\n\nexport const treeViewVi: TreeViewLabels = {\n label: \"Cây\",\n nameHeader: \"Tên\",\n root: \"cấp ngoài cùng\",\n instructions:\n \"Dùng phím mũi tên lên, xuống để chuyển mục, mũi tên phải để mở và mũi tên trái để thu nhánh. Tab đưa mục vào làm con của mục phía trên, Shift+Tab đưa mục ra ngoài một cấp. Alt cùng mũi tên lên, xuống đổi chỗ mục với các mục cùng cấp. Enter mở mục.\",\n movedInto: (name, parent, position, total) => `Đã chuyển ${name} vào ${parent}, vị trí ${position} trên ${total}.`,\n movedTo: (name, position, total) => `Đã chuyển ${name} tới vị trí ${position} trên ${total}.`\n};\n"],"mappings":"AAGO,MAAM,aAA6B;AAAA,EACxC,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,cACE;AAAA,EACF,WAAW,CAAC,MAAM,QAAQ,UAAU,UAAU,GAAG,IAAI,eAAe,MAAM,cAAc,QAAQ,OAAO,KAAK;AAAA,EAC5G,SAAS,CAAC,MAAM,UAAU,UAAU,GAAG,IAAI,sBAAsB,QAAQ,OAAO,KAAK;AACvF;AAEO,MAAM,aAA6B;AAAA,EACxC,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,cACE;AAAA,EACF,WAAW,CAAC,MAAM,QAAQ,UAAU,UAAU,0BAAa,IAAI,WAAQ,MAAM,oBAAY,QAAQ,YAAS,KAAK;AAAA,EAC/G,SAAS,CAAC,MAAM,UAAU,UAAU,0BAAa,IAAI,4BAAe,QAAQ,YAAS,KAAK;AAC5F;","names":[]}
package/dist/index.d.ts CHANGED
@@ -13,6 +13,8 @@ export { FilterChipItem, FilterChips, FilterChipsProps } from './components/comp
13
13
  export { FormField, FormFieldColSpan, FormFieldControlProps, FormFieldProps } from './components/composite/form-field.js';
14
14
  export { SELECT_EMPTY_VALUE, fromSelectValue, toSelectValue } from './components/composite/form-field-constants.js';
15
15
  export { FormSection, FormSectionAccent, FormSectionProps } from './components/composite/form-section.js';
16
+ export { Gantt, GanttProps } from './components/composite/gantt.js';
17
+ export { GANTT_SCALES, GanttDependency, GanttDependencyDraft, GanttDependencyType, GanttItem, GanttItemChange, GanttLabels, GanttScale, GanttTone } from './components/composite/gantt-constants.js';
16
18
  export { IconAvatar, IconAvatarIcon, IconAvatarProps } from './components/composite/icon-avatar.js';
17
19
  export { InlineEdit, InlineEditProps } from './components/composite/inline-edit.js';
18
20
  export { KEY_SEQUENCE_TIMEOUT_MS, KeySequence, KeySequenceInput, advanceKeySequence, isEditableTarget, normalizeSequenceKey } from './components/composite/key-sequence.js';
@@ -32,6 +34,8 @@ export { TablePagination, TablePaginationProps } from './components/composite/ta
32
34
  export { DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_TABLE_PAGINATION_LABELS, TablePaginationLabels } from './components/composite/table-pagination-constants.js';
33
35
  export { getVietnameseInitials, truncate } from './components/composite/text-utils.js';
34
36
  export { ToastOptions, ToastVariant, Toaster, ToasterProps, dismissToast, toast, toastPromise } from './components/composite/toast.js';
37
+ export { TreeView, TreeViewProps } from './components/composite/tree-view.js';
38
+ export { TreeViewColumn, TreeViewItem, TreeViewLabels, TreeViewMove, TreeViewRollup, computeTreeNumbering, computeTreeRollup, groupTreeChildren, moveTreeItems } from './components/composite/tree-view-constants.js';
35
39
  export { UseKeySequencesOptions, useKeySequences } from './components/composite/use-key-sequences.js';
36
40
  export { Accordion, AccordionContent, AccordionContentProps, AccordionItem, AccordionItemProps, AccordionProps, AccordionTrigger, AccordionTriggerProps } from './components/ui/accordion.js';
37
41
  export { ActionBar, ActionBarClose, ActionBarCloseProps, ActionBarGroup, ActionBarItem, ActionBarItemProps, ActionBarProps, ActionBarSelection, ActionBarSelectionProps, ActionBarSeparator, ActionBarSeparatorProps } from './components/ui/action-bar.js';
@@ -113,7 +117,7 @@ export { DEFAULT_TOUR_LABELS, TourLabels } from './components/ui/tour-constants.
113
117
  export { ComitorLanguage, DEFAULT_COMITOR_LOCALE, getComitorLanguage } from './i18n/locale.js';
114
118
  export { ComitorLocaleProvider, ComitorLocaleProviderProps, useComitorLocale, useComitorMessages } from './i18n/locale-provider.js';
115
119
  export { COMITOR_MESSAGES, ComitorMessages, ComitorMessagesOverride, comitorMessagesEn, comitorMessagesVi, getComitorMessages, mergeComitorMessages } from './i18n/messages.js';
116
- export { AVATAR_TONE_NAMES, AvatarToneColors, AvatarToneName, getAvatarToneIndex } from './lib/avatar-tone.js';
120
+ export { AVATAR_TONE_NAMES, AvatarToneColors, AvatarToneName, LEGACY_AVATAR_TONE_ALIASES, getAvatarToneIndex } from './lib/avatar-tone.js';
117
121
  export { cn } from './lib/cn.js';
118
122
  export { ThemeMode, accent, accentForeground, accentInk, ash, brandNeutral, chart, getAvatarToneColors, gold, highContrast, layout, semantic, status, typography } from './tokens.js';
119
123
  export { DateRange } from 'react-day-picker';
@@ -182,6 +186,7 @@ import './i18n/namespaces/confirm-dialog.js';
182
186
  import './i18n/namespaces/command-palette.js';
183
187
  import './i18n/namespaces/command.js';
184
188
  import './i18n/namespaces/combobox.js';
189
+ import './chat/chat-constants.js';
185
190
  import './i18n/namespaces/carousel.js';
186
191
  import './i18n/namespaces/calendar.js';
187
192
  import './i18n/namespaces/breadcrumb.js';
package/dist/index.js CHANGED
@@ -13,6 +13,8 @@ export * from "./components/composite/filter-chips.js";
13
13
  export * from "./components/composite/form-field.js";
14
14
  export * from "./components/composite/form-field-constants.js";
15
15
  export * from "./components/composite/form-section.js";
16
+ export * from "./components/composite/gantt.js";
17
+ export * from "./components/composite/gantt-constants.js";
16
18
  import { IconAvatar } from "./components/composite/icon-avatar.js";
17
19
  export * from "./components/composite/inline-edit.js";
18
20
  export * from "./components/composite/key-sequence.js";
@@ -38,6 +40,8 @@ import {
38
40
  truncate
39
41
  } from "./components/composite/text-utils.js";
40
42
  export * from "./components/composite/toast.js";
43
+ export * from "./components/composite/tree-view.js";
44
+ export * from "./components/composite/tree-view-constants.js";
41
45
  export * from "./components/composite/use-key-sequences.js";
42
46
  export * from "./components/ui/accordion.js";
43
47
  export * from "./components/ui/action-bar.js";
@@ -137,7 +141,7 @@ import {
137
141
  getComitorMessages,
138
142
  mergeComitorMessages
139
143
  } from "./i18n/messages.js";
140
- import { AVATAR_TONE_NAMES } from "./lib/avatar-tone.js";
144
+ import { AVATAR_TONE_NAMES, LEGACY_AVATAR_TONE_ALIASES } from "./lib/avatar-tone.js";
141
145
  export * from "./lib/cn.js";
142
146
  export * from "./tokens.js";
143
147
  export {
@@ -146,6 +150,7 @@ export {
146
150
  ComitorLocaleProvider,
147
151
  DEFAULT_COMITOR_LOCALE,
148
152
  IconAvatar,
153
+ LEGACY_AVATAR_TONE_ALIASES,
149
154
  LetterAvatar,
150
155
  MASK_PATTERNS,
151
156
  applyCurrencyMask,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Entry chính \"@comitor/ui\" — Tier 1 (primitive) + Tier 2 (composite) + lib + token.\n *\n * Quy tắc của entry này: **chỉ được phụ thuộc peer BẮT BUỘC** (react, react-dom,\n * lucide-react, tailwindcss). Không `next/*`, không `next-themes`, không `recharts`,\n * không `react-hook-form` — đó đều là peer OPTIONAL. Vì `tsup` chạy `bundle: false`\n * (ESM per-file), chỉ cần barrel này re-export một file có import optional peer là\n * mọi app import \"@comitor/ui\" đều buộc phải cài gói đó, nếu không bundler gãy ở\n * bước resolve. Vì vậy 3 nhánh dưới đây nằm ở entry riêng:\n *\n * - Tier 3 shell (next/*, next-themes) → \"@comitor/ui/shell\"\n * - chart (recharts) → \"@comitor/ui/chart\"\n * - binding react-hook-form → \"@comitor/ui/form\"\n *\n * ⚠ Hai file trong `components/ui/` CỐ Ý không có mặt ở đây:\n * - `form.tsx` → xuất qua \"@comitor/ui/form\" (react-hook-form).\n * - `sonner.tsx` → xuất qua \"@comitor/ui/shell\" dưới tên `SonnerToaster`\n * (nó gọi `useTheme()` của next-themes). Bản dùng hằng ngày là composite\n * `Toaster`/`toast` ở Tier 2 — không phụ thuộc next-themes, có sẵn ở entry này.\n *\n * ⚠ Mọi import nội bộ phải giữ đuôi `.js`: output là ESM per-file, Node ESM thuần\n * không tự suy ra phần mở rộng (bundler thì tha, Node thì không).\n */\n\n/*\n * ⚠ Các file `*-constants` bên dưới — ở CẢ Tier 2 lẫn Tier 1 (từ `2.1.0`: `action-bar`, `cropper`,\n * `kanban`, `key-value`, `mask-input`, `phone-input`, `stepper`, `time-picker`, `tour`) — KHÔNG phải\n * chỗ để gom code cho gọn — chúng là RANH GIỚI SERVER/CLIENT. Component chủ (`command-palette.tsx`,\n * `data-table.tsx`, `kanban.tsx`…) đều mở đầu bằng `\"use client\"`,\n * mà mọi export của một module client đến tay Server Component dưới dạng client-reference proxy:\n * đọc ra `undefined`, KHÔNG throw, KHÔNG warning, trong khi TypeScript vẫn khai kiểu thật. Nhãn mặc\n * định / preset / sentinel là hằng dữ liệu thuần nên phải nằm ngoài ranh giới đó, và barrel này\n * phải xuất chúng THẲNG — re-export vòng qua file client là vô hiệu.\n * Cùng lý do với `chart/chart-colors.ts`; chi tiết ghi ở đầu file đó.\n * `scripts/verify-directives.mjs` canh không cho hằng thuần lọt ngược vào file client.\n */\n\n// ─── Tier 2 — composite (pattern lặp lại ở mọi app Comitor) ───\nexport * from \"./components/composite/avatar-group.js\";\nexport * from \"./components/composite/combobox.js\";\nexport * from \"./components/composite/command-palette.js\";\nexport * from \"./components/composite/command-palette-constants.js\";\nexport * from \"./components/composite/confirm-dialog.js\";\nexport * from \"./components/composite/copy-button.js\";\nexport * from \"./components/composite/data-table.js\";\nexport * from \"./components/composite/data-table-constants.js\";\nexport * from \"./components/composite/date-picker.js\";\nexport * from \"./components/composite/date-picker-constants.js\";\nexport * from \"./components/composite/empty-state.js\";\nexport * from \"./components/composite/filter-chips.js\";\nexport * from \"./components/composite/form-field.js\";\nexport * from \"./components/composite/form-field-constants.js\";\nexport * from \"./components/composite/form-section.js\";\nexport { IconAvatar, type IconAvatarIcon, type IconAvatarProps } from \"./components/composite/icon-avatar.js\";\nexport * from \"./components/composite/inline-edit.js\";\nexport * from \"./components/composite/key-sequence.js\";\nexport * from \"./components/composite/keyboard-hint.js\";\nexport * from \"./components/composite/keyboard-shortcuts-dialog.js\";\nexport type { LetterAvatarProps, LetterAvatarSize } from \"./components/composite/letter-avatar.js\";\n// Xuất CHỌN LỌC (không `export *`): file này còn `AVATAR_TONES` nhập từ `lib/avatar-tone.js`\n// và các helper nội bộ khác. Liệt kê tường minh thì thêm helper riêng tư vào file KHÔNG tự động\n// biến nó thành API công khai — hàng rào mà `export *` không dựng được.\nexport { getAvatarToneClasses, LetterAvatar } from \"./components/composite/letter-avatar.js\";\nexport * from \"./components/composite/page-container.js\";\nexport * from \"./components/composite/page-header.js\";\nexport * from \"./components/composite/relative-time.js\";\nexport * from \"./components/composite/route-tabs.js\";\nexport * from \"./components/composite/search-filter-bar.js\";\nexport * from \"./components/composite/search-filter-bar-constants.js\";\nexport * from \"./components/composite/stat-card.js\";\nexport * from \"./components/composite/status-config.js\";\nexport * from \"./components/composite/status-pill.js\";\nexport * from \"./components/composite/table-pagination.js\";\nexport * from \"./components/composite/table-pagination-constants.js\";\n// Xuất CHỌN LỌC vì cùng lý do với `letter-avatar` ở trên: `text-utils.ts` là chỗ dễ bị thêm\n// helper nội bộ nhất của Tier 2 (0.1.0 từng rò `hashString`/`pickByString` ra API công khai\n// đúng theo đường này). Năm hàm dưới đây là hợp đồng, phần còn lại của file thì không.\nexport {\n getVietnameseInitials,\n matchesSearch,\n normalizeVi,\n removeVietnameseTones,\n truncate\n} from \"./components/composite/text-utils.js\";\nexport * from \"./components/composite/toast.js\";\nexport * from \"./components/composite/use-key-sequences.js\";\n// ─── Tier 1 — primitive (shadcn/ui \"new-york\", đã custom theo brand Comitor) ───\nexport * from \"./components/ui/accordion.js\";\nexport * from \"./components/ui/action-bar.js\";\nexport * from \"./components/ui/action-bar-constants.js\";\nexport * from \"./components/ui/alert.js\";\nexport * from \"./components/ui/alert-dialog.js\";\nexport * from \"./components/ui/aspect-ratio.js\";\nexport * from \"./components/ui/avatar.js\";\nexport * from \"./components/ui/badge.js\";\nexport * from \"./components/ui/badge-overflow.js\";\nexport * from \"./components/ui/banner.js\";\nexport * from \"./components/ui/breadcrumb.js\";\nexport * from \"./components/ui/button.js\";\nexport * from \"./components/ui/button-group.js\";\nexport * from \"./components/ui/calendar.js\";\nexport * from \"./components/ui/card.js\";\nexport * from \"./components/ui/carousel.js\";\nexport * from \"./components/ui/checkbox.js\";\nexport * from \"./components/ui/circular-progress.js\";\nexport * from \"./components/ui/collapsible.js\";\nexport * from \"./components/ui/command.js\";\nexport * from \"./components/ui/context-menu.js\";\nexport * from \"./components/ui/cropper.js\";\nexport * from \"./components/ui/cropper-constants.js\";\nexport * from \"./components/ui/dialog.js\";\nexport * from \"./components/ui/drawer.js\";\nexport * from \"./components/ui/dropdown-menu.js\";\nexport * from \"./components/ui/empty.js\";\nexport * from \"./components/ui/field.js\";\nexport * from \"./components/ui/hover-card.js\";\nexport * from \"./components/ui/input.js\";\nexport * from \"./components/ui/input-group.js\";\nexport * from \"./components/ui/input-otp.js\";\nexport * from \"./components/ui/item.js\";\nexport * from \"./components/ui/kanban.js\";\nexport * from \"./components/ui/kanban-constants.js\";\nexport * from \"./components/ui/kbd.js\";\nexport * from \"./components/ui/key-value.js\";\nexport * from \"./components/ui/key-value-constants.js\";\nexport * from \"./components/ui/label.js\";\nexport * from \"./components/ui/mask-input.js\";\n/*\n * Xuất CHỌN LỌC: `mask-input-constants.ts` giữ cả bộ máy thuần của MaskInput (tách khỏi file\n * \"use client\" để hằng `MASK_PATTERNS` không thành proxy ở Server Component), gồm những helper nội\n * bộ như `DEFAULT_CURRENCY` / `REGEX_CACHE`. Chỉ đúng các tên thượng nguồn Dice UI xuất là API.\n */\nexport {\n applyCurrencyMask,\n applyMask,\n applyPercentageMask,\n fromUnmaskedIndex,\n getUnmaskedValue,\n MASK_PATTERNS,\n type MaskPattern,\n toUnmaskedIndex\n} from \"./components/ui/mask-input-constants.js\";\nexport * from \"./components/ui/mention.js\";\nexport * from \"./components/ui/menubar.js\";\nexport * from \"./components/ui/navigation-menu.js\";\nexport * from \"./components/ui/pagination.js\";\nexport * from \"./components/ui/phone-input.js\";\nexport * from \"./components/ui/phone-input-constants.js\";\nexport * from \"./components/ui/popover.js\";\nexport * from \"./components/ui/progress.js\";\nexport * from \"./components/ui/radio-group.js\";\nexport * from \"./components/ui/rating.js\";\nexport * from \"./components/ui/resizable.js\";\nexport * from \"./components/ui/responsive-dialog.js\";\nexport * from \"./components/ui/scroll-area.js\";\nexport * from \"./components/ui/scroll-spy.js\";\nexport * from \"./components/ui/select.js\";\nexport * from \"./components/ui/separator.js\";\nexport * from \"./components/ui/sheet.js\";\nexport * from \"./components/ui/skeleton.js\";\nexport * from \"./components/ui/slider.js\";\nexport * from \"./components/ui/spinner.js\";\nexport * from \"./components/ui/stepper.js\";\nexport * from \"./components/ui/stepper-constants.js\";\nexport * from \"./components/ui/switch.js\";\nexport * from \"./components/ui/table.js\";\nexport * from \"./components/ui/tabs.js\";\n/* Bảng lớp của Tabs xuất THẲNG từ module thuần — `RouteTabs` và `Tabs` dùng chung nó, và hằng\n dữ liệu đi vòng qua file \"use client\" sẽ thành proxy ở Server Component (CHANGELOG 0.2.2 §2). */\nexport * from \"./components/ui/tabs-variants.js\";\nexport * from \"./components/ui/tags-input.js\";\nexport * from \"./components/ui/textarea.js\";\nexport * from \"./components/ui/time-picker.js\";\nexport * from \"./components/ui/time-picker-constants.js\";\nexport * from \"./components/ui/timeline.js\";\nexport * from \"./components/ui/toggle.js\";\nexport * from \"./components/ui/toggle-group.js\";\nexport * from \"./components/ui/tooltip.js\";\nexport * from \"./components/ui/tour.js\";\nexport * from \"./components/ui/tour-constants.js\";\n// ─── Ngôn ngữ (từ 3.0.0) — một provider cho CẢ gói, mặc định tiếng Anh ───\n/*\n * Xuất CHỌN LỌC: `locale-provider.tsx` còn `useComitorLabels` — hook nội bộ các component dùng để\n * trộn `labels` lên bảng chữ, không phải API. Bảng chữ và hàm thuần xuất THẲNG từ module thuần\n * (`messages.ts`, `locale.ts`) chứ không vòng qua file \"use client\" — cùng lý do với các file\n * `*-constants` bên dưới.\n */\nexport { type ComitorLanguage, DEFAULT_COMITOR_LOCALE, getComitorLanguage } from \"./i18n/locale.js\";\nexport {\n ComitorLocaleProvider,\n type ComitorLocaleProviderProps,\n useComitorLocale,\n useComitorMessages\n} from \"./i18n/locale-provider.js\";\nexport {\n COMITOR_MESSAGES,\n type ComitorMessages,\n type ComitorMessagesOverride,\n comitorMessagesEn,\n comitorMessagesVi,\n getComitorMessages,\n mergeComitorMessages\n} from \"./i18n/messages.js\";\n/*\n * `IconAvatar` — em ruột của `LetterAvatar`, dùng chung bảng tone. Xuất kèm `AVATAR_TONE_NAMES`\n * và kiểu `AvatarToneName` vì prop `tone` chỉ có nghĩa khi chỗ gọi liệt kê được tập chọn (màn\n * quản trị cần dựng một `<Select>` từ đúng tập đó).\n *\n * ⚠ KHÔNG xuất `AVATAR_TONES` lẫn `getAvatarToneIndex` ra entry này: bảng thô và hàm băm vẫn là\n * nội bộ, đúng như `lib/avatar-tone.ts` dặn — xuất chúng là mời app dựng lại phép chọn tone của\n * riêng nó, tức cùng một tên ra hai màu.\n */\nexport { AVATAR_TONE_NAMES, type AvatarToneName } from \"./lib/avatar-tone.js\";\n\n// ─── lib + token ───\nexport * from \"./lib/cn.js\";\nexport * from \"./tokens.js\";\n"],"mappings":"AAsCA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,kBAA6D;AACtE,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAKd,SAAS,sBAAsB,oBAAoB;AACnD,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAId;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,cAAc;AACd,cAAc;AAEd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAMd;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,OACK;AACP,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAQd,SAA+B,wBAAwB,0BAA0B;AACjF;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAUP,SAAS,yBAA8C;AAGvD,cAAc;AACd,cAAc;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Entry chính \"@comitor/ui\" — Tier 1 (primitive) + Tier 2 (composite) + lib + token.\n *\n * Quy tắc của entry này: **chỉ được phụ thuộc peer BẮT BUỘC** (react, react-dom,\n * lucide-react, tailwindcss). Không `next/*`, không `next-themes`, không `recharts`,\n * không `react-hook-form` — đó đều là peer OPTIONAL. Vì `tsup` chạy `bundle: false`\n * (ESM per-file), chỉ cần barrel này re-export một file có import optional peer là\n * mọi app import \"@comitor/ui\" đều buộc phải cài gói đó, nếu không bundler gãy ở\n * bước resolve. Vì vậy 3 nhánh dưới đây nằm ở entry riêng:\n *\n * - Tier 3 shell (next/*, next-themes) → \"@comitor/ui/shell\"\n * - chart (recharts) → \"@comitor/ui/chart\"\n * - binding react-hook-form → \"@comitor/ui/form\"\n *\n * ⚠ Hai file trong `components/ui/` CỐ Ý không có mặt ở đây:\n * - `form.tsx` → xuất qua \"@comitor/ui/form\" (react-hook-form).\n * - `sonner.tsx` → xuất qua \"@comitor/ui/shell\" dưới tên `SonnerToaster`\n * (nó gọi `useTheme()` của next-themes). Bản dùng hằng ngày là composite\n * `Toaster`/`toast` ở Tier 2 — không phụ thuộc next-themes, có sẵn ở entry này.\n *\n * ⚠ Mọi import nội bộ phải giữ đuôi `.js`: output là ESM per-file, Node ESM thuần\n * không tự suy ra phần mở rộng (bundler thì tha, Node thì không).\n */\n\n/*\n * ⚠ Các file `*-constants` bên dưới — ở CẢ Tier 2 lẫn Tier 1 (từ `2.1.0`: `action-bar`, `cropper`,\n * `kanban`, `key-value`, `mask-input`, `phone-input`, `stepper`, `time-picker`, `tour`) — KHÔNG phải\n * chỗ để gom code cho gọn — chúng là RANH GIỚI SERVER/CLIENT. Component chủ (`command-palette.tsx`,\n * `data-table.tsx`, `kanban.tsx`…) đều mở đầu bằng `\"use client\"`,\n * mà mọi export của một module client đến tay Server Component dưới dạng client-reference proxy:\n * đọc ra `undefined`, KHÔNG throw, KHÔNG warning, trong khi TypeScript vẫn khai kiểu thật. Nhãn mặc\n * định / preset / sentinel là hằng dữ liệu thuần nên phải nằm ngoài ranh giới đó, và barrel này\n * phải xuất chúng THẲNG — re-export vòng qua file client là vô hiệu.\n * Cùng lý do với `chart/chart-colors.ts`; chi tiết ghi ở đầu file đó.\n * `scripts/verify-directives.mjs` canh không cho hằng thuần lọt ngược vào file client.\n */\n\n// ─── Tier 2 — composite (pattern lặp lại ở mọi app Comitor) ───\nexport * from \"./components/composite/avatar-group.js\";\nexport * from \"./components/composite/combobox.js\";\nexport * from \"./components/composite/command-palette.js\";\nexport * from \"./components/composite/command-palette-constants.js\";\nexport * from \"./components/composite/confirm-dialog.js\";\nexport * from \"./components/composite/copy-button.js\";\nexport * from \"./components/composite/data-table.js\";\nexport * from \"./components/composite/data-table-constants.js\";\nexport * from \"./components/composite/date-picker.js\";\nexport * from \"./components/composite/date-picker-constants.js\";\nexport * from \"./components/composite/empty-state.js\";\nexport * from \"./components/composite/filter-chips.js\";\nexport * from \"./components/composite/form-field.js\";\nexport * from \"./components/composite/form-field-constants.js\";\nexport * from \"./components/composite/form-section.js\";\nexport * from \"./components/composite/gantt.js\";\nexport * from \"./components/composite/gantt-constants.js\";\nexport { IconAvatar, type IconAvatarIcon, type IconAvatarProps } from \"./components/composite/icon-avatar.js\";\nexport * from \"./components/composite/inline-edit.js\";\nexport * from \"./components/composite/key-sequence.js\";\nexport * from \"./components/composite/keyboard-hint.js\";\nexport * from \"./components/composite/keyboard-shortcuts-dialog.js\";\nexport type { LetterAvatarProps, LetterAvatarSize } from \"./components/composite/letter-avatar.js\";\n// Xuất CHỌN LỌC (không `export *`): file này còn `AVATAR_TONES` nhập từ `lib/avatar-tone.js`\n// và các helper nội bộ khác. Liệt kê tường minh thì thêm helper riêng tư vào file KHÔNG tự động\n// biến nó thành API công khai — hàng rào mà `export *` không dựng được.\nexport { getAvatarToneClasses, LetterAvatar } from \"./components/composite/letter-avatar.js\";\nexport * from \"./components/composite/page-container.js\";\nexport * from \"./components/composite/page-header.js\";\nexport * from \"./components/composite/relative-time.js\";\nexport * from \"./components/composite/route-tabs.js\";\nexport * from \"./components/composite/search-filter-bar.js\";\nexport * from \"./components/composite/search-filter-bar-constants.js\";\nexport * from \"./components/composite/stat-card.js\";\nexport * from \"./components/composite/status-config.js\";\nexport * from \"./components/composite/status-pill.js\";\nexport * from \"./components/composite/table-pagination.js\";\nexport * from \"./components/composite/table-pagination-constants.js\";\n// Xuất CHỌN LỌC vì cùng lý do với `letter-avatar` ở trên: `text-utils.ts` là chỗ dễ bị thêm\n// helper nội bộ nhất của Tier 2 (0.1.0 từng rò `hashString`/`pickByString` ra API công khai\n// đúng theo đường này). Năm hàm dưới đây là hợp đồng, phần còn lại của file thì không.\nexport {\n getVietnameseInitials,\n matchesSearch,\n normalizeVi,\n removeVietnameseTones,\n truncate\n} from \"./components/composite/text-utils.js\";\nexport * from \"./components/composite/toast.js\";\nexport * from \"./components/composite/tree-view.js\";\nexport * from \"./components/composite/tree-view-constants.js\";\nexport * from \"./components/composite/use-key-sequences.js\";\n// ─── Tier 1 — primitive (shadcn/ui \"new-york\", đã custom theo brand Comitor) ───\nexport * from \"./components/ui/accordion.js\";\nexport * from \"./components/ui/action-bar.js\";\nexport * from \"./components/ui/action-bar-constants.js\";\nexport * from \"./components/ui/alert.js\";\nexport * from \"./components/ui/alert-dialog.js\";\nexport * from \"./components/ui/aspect-ratio.js\";\nexport * from \"./components/ui/avatar.js\";\nexport * from \"./components/ui/badge.js\";\nexport * from \"./components/ui/badge-overflow.js\";\nexport * from \"./components/ui/banner.js\";\nexport * from \"./components/ui/breadcrumb.js\";\nexport * from \"./components/ui/button.js\";\nexport * from \"./components/ui/button-group.js\";\nexport * from \"./components/ui/calendar.js\";\nexport * from \"./components/ui/card.js\";\nexport * from \"./components/ui/carousel.js\";\nexport * from \"./components/ui/checkbox.js\";\nexport * from \"./components/ui/circular-progress.js\";\nexport * from \"./components/ui/collapsible.js\";\nexport * from \"./components/ui/command.js\";\nexport * from \"./components/ui/context-menu.js\";\nexport * from \"./components/ui/cropper.js\";\nexport * from \"./components/ui/cropper-constants.js\";\nexport * from \"./components/ui/dialog.js\";\nexport * from \"./components/ui/drawer.js\";\nexport * from \"./components/ui/dropdown-menu.js\";\nexport * from \"./components/ui/empty.js\";\nexport * from \"./components/ui/field.js\";\nexport * from \"./components/ui/hover-card.js\";\nexport * from \"./components/ui/input.js\";\nexport * from \"./components/ui/input-group.js\";\nexport * from \"./components/ui/input-otp.js\";\nexport * from \"./components/ui/item.js\";\nexport * from \"./components/ui/kanban.js\";\nexport * from \"./components/ui/kanban-constants.js\";\nexport * from \"./components/ui/kbd.js\";\nexport * from \"./components/ui/key-value.js\";\nexport * from \"./components/ui/key-value-constants.js\";\nexport * from \"./components/ui/label.js\";\nexport * from \"./components/ui/mask-input.js\";\n/*\n * Xuất CHỌN LỌC: `mask-input-constants.ts` giữ cả bộ máy thuần của MaskInput (tách khỏi file\n * \"use client\" để hằng `MASK_PATTERNS` không thành proxy ở Server Component), gồm những helper nội\n * bộ như `DEFAULT_CURRENCY` / `REGEX_CACHE`. Chỉ đúng các tên thượng nguồn Dice UI xuất là API.\n */\nexport {\n applyCurrencyMask,\n applyMask,\n applyPercentageMask,\n fromUnmaskedIndex,\n getUnmaskedValue,\n MASK_PATTERNS,\n type MaskPattern,\n toUnmaskedIndex\n} from \"./components/ui/mask-input-constants.js\";\nexport * from \"./components/ui/mention.js\";\nexport * from \"./components/ui/menubar.js\";\nexport * from \"./components/ui/navigation-menu.js\";\nexport * from \"./components/ui/pagination.js\";\nexport * from \"./components/ui/phone-input.js\";\nexport * from \"./components/ui/phone-input-constants.js\";\nexport * from \"./components/ui/popover.js\";\nexport * from \"./components/ui/progress.js\";\nexport * from \"./components/ui/radio-group.js\";\nexport * from \"./components/ui/rating.js\";\nexport * from \"./components/ui/resizable.js\";\nexport * from \"./components/ui/responsive-dialog.js\";\nexport * from \"./components/ui/scroll-area.js\";\nexport * from \"./components/ui/scroll-spy.js\";\nexport * from \"./components/ui/select.js\";\nexport * from \"./components/ui/separator.js\";\nexport * from \"./components/ui/sheet.js\";\nexport * from \"./components/ui/skeleton.js\";\nexport * from \"./components/ui/slider.js\";\nexport * from \"./components/ui/spinner.js\";\nexport * from \"./components/ui/stepper.js\";\nexport * from \"./components/ui/stepper-constants.js\";\nexport * from \"./components/ui/switch.js\";\nexport * from \"./components/ui/table.js\";\nexport * from \"./components/ui/tabs.js\";\n/* Bảng lớp của Tabs xuất THẲNG từ module thuần — `RouteTabs` và `Tabs` dùng chung nó, và hằng\n dữ liệu đi vòng qua file \"use client\" sẽ thành proxy ở Server Component (CHANGELOG 0.2.2 §2). */\nexport * from \"./components/ui/tabs-variants.js\";\nexport * from \"./components/ui/tags-input.js\";\nexport * from \"./components/ui/textarea.js\";\nexport * from \"./components/ui/time-picker.js\";\nexport * from \"./components/ui/time-picker-constants.js\";\nexport * from \"./components/ui/timeline.js\";\nexport * from \"./components/ui/toggle.js\";\nexport * from \"./components/ui/toggle-group.js\";\nexport * from \"./components/ui/tooltip.js\";\nexport * from \"./components/ui/tour.js\";\nexport * from \"./components/ui/tour-constants.js\";\n// ─── Ngôn ngữ (từ 3.0.0) — một provider cho CẢ gói, mặc định tiếng Anh ───\n/*\n * Xuất CHỌN LỌC: `locale-provider.tsx` còn `useComitorLabels` — hook nội bộ các component dùng để\n * trộn `labels` lên bảng chữ, không phải API. Bảng chữ và hàm thuần xuất THẲNG từ module thuần\n * (`messages.ts`, `locale.ts`) chứ không vòng qua file \"use client\" — cùng lý do với các file\n * `*-constants` bên dưới.\n */\nexport { type ComitorLanguage, DEFAULT_COMITOR_LOCALE, getComitorLanguage } from \"./i18n/locale.js\";\nexport {\n ComitorLocaleProvider,\n type ComitorLocaleProviderProps,\n useComitorLocale,\n useComitorMessages\n} from \"./i18n/locale-provider.js\";\nexport {\n COMITOR_MESSAGES,\n type ComitorMessages,\n type ComitorMessagesOverride,\n comitorMessagesEn,\n comitorMessagesVi,\n getComitorMessages,\n mergeComitorMessages\n} from \"./i18n/messages.js\";\n/*\n * `IconAvatar` — em ruột của `LetterAvatar`, dùng chung bảng tone. Xuất kèm `AVATAR_TONE_NAMES`\n * và kiểu `AvatarToneName` vì prop `tone` chỉ có nghĩa khi chỗ gọi liệt kê được tập chọn (màn\n * quản trị cần dựng một `<Select>` từ đúng tập đó). `LEGACY_AVATAR_TONE_ALIASES` (tên cũ → tên\n * mới, 3.10.0) đi cùng vì cùng lý do: màn ấy đọc `apps.icon_color` cũ phải ra đúng mục của\n * `<Select>` — CHANGELOG 3.10.0 đã ghi nó là tên mới nhưng tới 3.12.1 mới thật sự xuất ra.\n *\n * ⚠ KHÔNG xuất `AVATAR_TONES` lẫn `getAvatarToneIndex` ra entry này: bảng thô và hàm băm vẫn là\n * nội bộ, đúng như `lib/avatar-tone.ts` dặn — xuất chúng là mời app dựng lại phép chọn tone của\n * riêng nó, tức cùng một tên ra hai màu.\n */\nexport { AVATAR_TONE_NAMES, type AvatarToneName, LEGACY_AVATAR_TONE_ALIASES } from \"./lib/avatar-tone.js\";\n\n// ─── lib + token ───\nexport * from \"./lib/cn.js\";\nexport * from \"./tokens.js\";\n"],"mappings":"AAsCA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,kBAA6D;AACtE,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAKd,SAAS,sBAAsB,oBAAoB;AACnD,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAId;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAEd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAMd;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,OACK;AACP,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAQd,SAA+B,wBAAwB,0BAA0B;AACjF;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAYP,SAAS,mBAAwC,kCAAkC;AAGnF,cAAc;AACd,cAAc;","names":[]}
@@ -124,6 +124,10 @@ type AvatarToneName = (typeof AVATAR_TONE_NAMES)[number];
124
124
  * Bí danh thay vì giữ tên cũ cho màu mới: tên là hợp đồng (cột `apps.icon_color` của Account), và
125
125
  * một tên nói dối về màu ("ash" mà tím) còn tệ hơn một lần đổi tên có lối lùi. Bí danh đi theo
126
126
  * cùng VỊ TRÍ, nên hàng database còn ghi tên cũ ra đúng màu mà phép băm cũng sẽ cho ở chỗ đó.
127
+ *
128
+ * Xuất ở `@comitor/ui` từ 3.12.1 — app ánh xạ tên cũ đọc từ database bằng chính bảng này thay vì
129
+ * chép một bản. ⚠ `Record` trần: khoá đến từ dữ liệu ngoài thì tra qua `Object.hasOwn` —
130
+ * `LEGACY_AVATAR_TONE_ALIASES["constructor"]` ra một hàm, không ra `undefined`.
127
131
  */
128
132
  declare const LEGACY_AVATAR_TONE_ALIASES: Readonly<Record<string, AvatarToneName>>;
129
133
  declare const AVATAR_TONES: AvatarToneTable<AvatarTone>;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/avatar-tone.ts"],"sourcesContent":["/**\n * NGUỒN SỰ THẬT DUY NHẤT của màu avatar chữ cái — cả gói chỉ có bảng này.\n *\n * File nội bộ (không nằm trong barrel nào): app không import trực tiếp được, mà đi qua đúng\n * hai cửa tuỳ theo chỗ vẽ:\n * • có Tailwind (DOM) → `getAvatarToneClasses(name)` ở `composite/letter-avatar.tsx`\n * • không có Tailwind (canvas, → `getAvatarToneColors(name, mode)` ở `tokens.ts`\n * email HTML, PDF)\n *\n * Vì sao MỘT bảng chứ không phải hai (một bảng class + một bảng hex \"ảnh chiếu\"): hai bảng viết\n * tay song song thì chỉ cần một lần thêm/xoá/đảo tone là cùng một người ra hai màu khác nhau giữa\n * web và email — mà không có gì báo. Ở đây mỗi tone là MỘT phần tử mang cả chuỗi class lẫn công\n * thức hex tương ứng, nằm sát nhau trên vài dòng liền: thêm tone là thêm cả ba, không quên được.\n * Thứ tự phần tử = chỉ số băm, nên thứ tự cũng chỉ tồn tại ở một chỗ.\n *\n * Vì sao công thức hex là HÀM nhận `palette` chứ không đọc thẳng token: `tokens.ts` là entry\n * `@comitor/ui/tokens`; nếu file này `import { accent } from \"../tokens.js\"` thì thành vòng import\n * (tokens.ts phải import ngược lại bảng này) — vòng có khởi tạo hằng ở giữa là lỗi TDZ lúc chạy.\n * Nhận bảng màu qua tham số thì phụ thuộc chỉ đi MỘT chiều: tokens.ts → file này.\n */\n\n/** Bảy sắc màu phụ mà bảng tone đọc (gold đi riêng qua thang của nó). */\ninterface AvatarToneHues {\n readonly teal: string;\n readonly green: string;\n readonly red: string;\n readonly yellow: string;\n readonly blue: string;\n readonly purple: string;\n readonly pink: string;\n}\n\n/** Đúng 8 tone — chốt ở tầng kiểu: `getAvatarToneIndex` băm theo độ dài này. */\ntype AvatarToneTable<T> = readonly [T, T, T, T, T, T, T, T];\n\n/** Cặp nền + màu chữ (hex đục) của một tone avatar. */\nexport interface AvatarToneColors {\n background: string;\n foreground: string;\n}\n\n/**\n * Các bậc màu mà công thức hex bên dưới đọc vào — `tokens.ts` truyền xuống một bộ cho light,\n * một bộ cho dark. Khai tường minh bằng `string` (không `typeof gold`) vì bản light và bản dark\n * là hai bộ giá trị khác nhau, không cùng một kiểu literal.\n */\nexport interface AvatarTonePalette {\n /** Thang gold — cần bậc 100 · 500 · 600. */\n gold: { readonly 100: string; readonly 500: string; readonly 600: string };\n /** Màu phụ ở vai trò TÔ NỀN (`accent.light` hoặc `accent.dark`). */\n accent: AvatarToneHues;\n /** Cùng màu phụ đó ở vai trò CHỮ trên nền trang (`accentInk.light` hoặc `accentInk.dark`). */\n accentInk: AvatarToneHues;\n /** Nền mà tint hợp thành lên — `--card` của theme. */\n card: string;\n}\n\ninterface AvatarTone {\n /**\n * Tên gọi của tone — để chỗ dùng CHỌN TAY một màu thay vì để hàm băm quyết.\n *\n * ⚠ Tên là một phần của HỢP ĐỒNG: nó đi vào cột database của app (`apps.icon_color` bên\n * `comitor-account`) và vào prop `tone` của `IconAvatar`. Đổi tên một tone là làm mọi hàng đã\n * lưu trỏ vào hư không — và hỏng đó IM LẶNG, vì giá trị lạ chỉ rơi về màu suy theo tên.\n * Thêm tone thì thêm tên mới; đừng đổi tên cũ.\n */\n readonly name: AvatarToneName;\n /** Vai trò DOM: chuỗi class token tĩnh (kèm biến thể `dark:`). */\n readonly classes: string;\n /** Vai trò canvas/email/PDF: đúng những gì `classes` nói, tính ra hex đục ở light. */\n readonly light: (p: AvatarTonePalette) => AvatarToneColors;\n /** Nhánh `dark:` của `classes`. */\n readonly dark: (p: AvatarTonePalette) => AvatarToneColors;\n}\n\n/**\n * Trộn `color` phủ `alpha` lên nền `over`, trả về hex đục.\n *\n * Tái hiện đúng phép mà trình duyệt làm với `bg-teal/15`: Tailwind sinh ra màu CÓ alpha, còn nền\n * phía dưới (`--card`) mới quyết định hex cuối cùng. Nơi không có CSS thì không có gì để hợp\n * thành, nên hex phải mang sẵn kết quả đã trộn.\n */\nfunction tintOver(color: string, over: string, alpha: number): string {\n const channel = (hex: string, i: number) => Number.parseInt(hex.slice(1 + i * 2, 3 + i * 2), 16);\n const mixed = [0, 1, 2].map((i) => Math.round(channel(color, i) * alpha + channel(over, i) * (1 - alpha)));\n return `#${mixed.map((v) => v.toString(16).padStart(2, \"0\")).join(\"\")}`.toUpperCase();\n}\n\n/**\n * 8 tone deterministic. Phía class TẤT CẢ là token tĩnh — không ghép chuỗi lúc chạy (`bg-${c}-100`)\n * vì Tailwind quét tĩnh, class ghép động sẽ không có mặt trong CSS của app; cũng không dùng hex\n * inline vì như vậy là mất dark mode.\n *\n * ─ VÌ SAO LÀ MÀU PHỤ + CHART CHỨ KHÔNG PHẢI TOKEN SEMANTIC ─\n * Đây là màu ĐỊNH DANH (phân biệt người), không phải màu TRẠNG THÁI — gán `--success` cho một con\n * người là sai nghĩa. Bộ màu phụ + bảng chart là nhóm token DUY NHẤT có đủ 8 sắc khác nhau và có\n * bản riêng cho dark, nên vẫn đổi theo theme và app vẫn ghi đè được.\n *\n * ─ TƯƠNG PHẢN: VÌ SAO BA TONE PHẢI HẠ XUỐNG BẬC INK Ở LIGHT ─\n * Chữ initials tuy `aria-hidden` nhưng người sáng mắt vẫn đọc, nên vẫn phải đạt AA 4,5:1. Bản đầu\n * dùng thẳng `text-teal/green/red` trên nền tint 15% và HỎNG ở light (đo theo WCAG, nền tint đã\n * trộn với `--card` trắng):\n *\n * teal #1F8A8B trên bg-teal/15 = 3,44:1 ✗\n * green #2EA56A trên bg-green/15 = 2,69:1 ✗ (dưới cả ngưỡng 3:1)\n * red #D64545 trên bg-red/15 = 3,57:1 ✗\n *\n * Sửa đúng khuôn `Badge`: dùng bậc `--x-ink` cho light, giữ token đã nâng sáng cho dark. Đo lại\n * trên đúng hex mà `getAvatarToneColors` trả ra (styles.css đã đóng băng bậc ink, xem dưới):\n *\n * teal #1A6668 trên #DDEDEE = 5,54:1 ✓ · dark #2DD4BF trên #193435 = 7,12:1 ✓\n * green #216A48 trên #E0F2E9 = 5,60:1 ✓ · dark #4ADE80 trên #1E362C = 7,44:1 ✓\n * red #9A3537 trên #F9E3E3 = 5,83:1 ✓ · dark #F87171 trên #38252A = 5,18:1 ✓\n *\n * (Bộ số 5,56 / 5,58 / 7,10 / 7,47 / 5,17 ghi ở bản trước là kết quả của chuỗi `color-mix` TRƯỚC\n * khi hex được đóng băng vào token — lệch ở chữ, không lệch ở màu.)\n *\n * Class viết thẳng `text-teal-ink` / `text-green-ink` / `text-red-ink` / `text-yellow-ink` chứ\n * KHÔNG nhắc lại chuỗi `color-mix(...)` — hai cách cho ra đúng cùng một hex (styles.css đã đóng\n * băng kết quả: #1A6668 · #216A48 · #9A3537), và ở `.dark` thì `--teal-ink` vốn trỏ về `--teal`\n * nên không cần biến thể `dark:` nào. Nhờ vậy tên trong class khớp đúng tên trong công thức hex\n * ngay bên dưới (`p.accentInk.teal`) — soi hai vế cạnh nhau là thấy lệch ngay.\n */\n/**\n * Tên của 8 tone, ĐÚNG THỨ TỰ bảng bên dưới — thứ tự ấy cũng là chỉ số băm, nên hai thứ không\n * được trôi khỏi nhau. Đây là bảng màu mà chỗ dùng chọn tay khi không muốn để tên quyết định.\n *\n * Tên lấy theo SẮC, không theo vai trò ngữ nghĩa: đây là màu ĐỊNH DANH, không phải màu trạng\n * thái — xem lý do dài ở docblock của `AVATAR_TONES`.\n */\nexport const AVATAR_TONE_NAMES = [\"gold\", \"teal\", \"green\", \"red\", \"yellow\", \"blue\", \"purple\", \"pink\"] as const;\n\nexport type AvatarToneName = (typeof AVATAR_TONE_NAMES)[number];\n\n/**\n * Tên tone CŨ → tên tone hôm nay (3.10.0). Ba tone cuối từng là `navy` · `ash` · `neutral` — cả ba\n * đều là xám ám xanh ở các độ đậm khác nhau, nên ô icon của ba app khác nhau trông như cùng một\n * màu. Chúng được THAY bằng ba sắc thật, đứng ĐÚNG vị trí cũ trong bảng (chỉ số băm giữ nguyên:\n * người/app nào trước ra `navy` thì nay ra `blue`, không ai nhảy sang tone khác).\n *\n * Bí danh thay vì giữ tên cũ cho màu mới: tên là hợp đồng (cột `apps.icon_color` của Account), và\n * một tên nói dối về màu (\"ash\" mà tím) còn tệ hơn một lần đổi tên có lối lùi. Bí danh đi theo\n * cùng VỊ TRÍ, nên hàng database còn ghi tên cũ ra đúng màu mà phép băm cũng sẽ cho ở chỗ đó.\n */\nexport const LEGACY_AVATAR_TONE_ALIASES: Readonly<Record<string, AvatarToneName>> = {\n navy: \"blue\",\n ash: \"purple\",\n neutral: \"pink\"\n};\n\nexport const AVATAR_TONES: AvatarToneTable<AvatarTone> = [\n {\n name: \"gold\",\n classes: \"bg-gold-100 text-gold-600 dark:bg-gold-500/30 dark:text-gold-100\",\n light: (p) => ({ background: p.gold[100], foreground: p.gold[600] }),\n dark: (p) => ({ background: tintOver(p.gold[500], p.card, 0.3), foreground: p.gold[100] })\n },\n {\n name: \"teal\",\n classes: \"bg-teal/15 text-teal-ink\",\n light: (p) => ({ background: tintOver(p.accent.teal, p.card, 0.15), foreground: p.accentInk.teal }),\n dark: (p) => ({ background: tintOver(p.accent.teal, p.card, 0.15), foreground: p.accentInk.teal })\n },\n {\n name: \"green\",\n classes: \"bg-green/15 text-green-ink\",\n light: (p) => ({ background: tintOver(p.accent.green, p.card, 0.15), foreground: p.accentInk.green }),\n dark: (p) => ({ background: tintOver(p.accent.green, p.card, 0.15), foreground: p.accentInk.green })\n },\n {\n name: \"red\",\n classes: \"bg-red/15 text-red-ink\",\n light: (p) => ({ background: tintOver(p.accent.red, p.card, 0.15), foreground: p.accentInk.red }),\n dark: (p) => ({ background: tintOver(p.accent.red, p.card, 0.15), foreground: p.accentInk.red })\n },\n {\n name: \"yellow\",\n classes: \"bg-yellow/25 text-yellow-ink dark:bg-yellow/20\",\n light: (p) => ({ background: tintOver(p.accent.yellow, p.card, 0.25), foreground: p.accentInk.yellow }),\n dark: (p) => ({ background: tintOver(p.accent.yellow, p.card, 0.2), foreground: p.accentInk.yellow })\n },\n {\n // Ba tone cuối: ba sắc ĐỊNH DANH riêng của bảng này (styles.css, khối \"Màu phụ\") — thay navy ·\n // ash · neutral từ 3.10.0, xem `LEGACY_AVATAR_TONE_ALIASES`. Cùng khuôn teal/green/red: tint /15\n // + bậc ink; ở dark `--x-ink` trỏ về bản dark riêng của fill nên một chuỗi class đủ cả hai theme.\n // Chữ trên tint /15: blue 5,67 · purple 5,72 · pink 5,33:1 (light) · 5,76 · 5,17 · 5,37:1 (dark).\n name: \"blue\",\n classes: \"bg-blue/15 text-blue-ink\",\n light: (p) => ({ background: tintOver(p.accent.blue, p.card, 0.15), foreground: p.accentInk.blue }),\n dark: (p) => ({ background: tintOver(p.accent.blue, p.card, 0.15), foreground: p.accentInk.blue })\n },\n {\n name: \"purple\",\n classes: \"bg-purple/15 text-purple-ink\",\n light: (p) => ({ background: tintOver(p.accent.purple, p.card, 0.15), foreground: p.accentInk.purple }),\n dark: (p) => ({ background: tintOver(p.accent.purple, p.card, 0.15), foreground: p.accentInk.purple })\n },\n {\n name: \"pink\",\n classes: \"bg-pink/15 text-pink-ink\",\n light: (p) => ({ background: tintOver(p.accent.pink, p.card, 0.15), foreground: p.accentInk.pink }),\n dark: (p) => ({ background: tintOver(p.accent.pink, p.card, 0.15), foreground: p.accentInk.pink })\n }\n];\n\n/**\n * Hash chuỗi → số nguyên không âm (biến thể FNV-1a 32 bit).\n *\n * Nội bộ, KHÔNG xuất ra API: công dụng duy nhất của nó là chọn tone avatar ngay dưới đây. Xuất\n * một hàm băm ra ngoài chỉ mời app dựng lại phép chọn tone của riêng nó — đúng thứ sinh ra chuyện\n * cùng một người hai màu. Chạy trên code point (không phải byte) để tên có dấu vẫn ổn định giữa\n * server và client.\n */\nfunction hashString(input: string): number {\n let hash = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n hash ^= input.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n return Math.abs(hash | 0);\n}\n\n/**\n * Chỉ số tone theo tên — phép chọn màu avatar DUY NHẤT của cả gói.\n *\n * Khoá băm là **tên hiển thị** đã `trim` + hạ chữ thường theo locale `vi-VN` (không phải\n * email/slug: chỗ nào hiển thị avatar cũng chắc chắn có tên, còn email/slug thì không — lấy khoá\n * khác nhau ở từng chỗ là cách nhanh nhất để cùng một người ra hai màu).\n */\nexport function getAvatarToneIndex(name: string): number {\n return hashString(name.trim().toLocaleLowerCase(\"vi-VN\")) % AVATAR_TONES.length;\n}\n\n/** Tone (cả class lẫn công thức hex) ứng với một tên. */\nexport function getAvatarTone(name: string): AvatarTone {\n // `noUncheckedIndexedAccess` bật → phải có nhánh lùi, dù chỉ số luôn nằm trong [0, 8).\n return AVATAR_TONES[getAvatarToneIndex(name)] ?? AVATAR_TONES[0];\n}\n\n/**\n * Tone theo TÊN — cửa cho chỗ dùng chọn tay một màu.\n *\n * Trả `undefined` cho tên lạ, và nơi gọi hiểu đó là \"rơi về màu suy theo tên\". KHÔNG ném: giá trị\n * này đến từ database (`apps.icon_color`), nơi một hàng cũ hoàn toàn có thể mang tên của một tone\n * đã bị xoá — làm sập cả dải ứng dụng vì một chữ trong một hàng là đổi sai lấy tệ hơn. Tên đã\n * ĐỔI thì đi qua `LEGACY_AVATAR_TONE_ALIASES` trước khi tra.\n *\n * ⚠ `LEGACY_AVATAR_TONE_ALIASES` dùng `Record` trần: `\"constructor\"` tra ra một hàm, không phải\n * tên tone — nhưng hàm thì không bằng `tone.name` nào, nên kết quả vẫn là `undefined`.\n */\nexport function getAvatarToneByName(name: string | null | undefined): AvatarTone | undefined {\n if (!name) return undefined;\n const current = LEGACY_AVATAR_TONE_ALIASES[name] ?? name;\n return AVATAR_TONES.find((tone) => tone.name === current);\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/lib/avatar-tone.ts"],"sourcesContent":["/**\n * NGUỒN SỰ THẬT DUY NHẤT của màu avatar chữ cái — cả gói chỉ có bảng này.\n *\n * File nội bộ (không nằm trong barrel nào): app không import trực tiếp được, mà đi qua đúng\n * hai cửa tuỳ theo chỗ vẽ:\n * • có Tailwind (DOM) → `getAvatarToneClasses(name)` ở `composite/letter-avatar.tsx`\n * • không có Tailwind (canvas, → `getAvatarToneColors(name, mode)` ở `tokens.ts`\n * email HTML, PDF)\n *\n * Vì sao MỘT bảng chứ không phải hai (một bảng class + một bảng hex \"ảnh chiếu\"): hai bảng viết\n * tay song song thì chỉ cần một lần thêm/xoá/đảo tone là cùng một người ra hai màu khác nhau giữa\n * web và email — mà không có gì báo. Ở đây mỗi tone là MỘT phần tử mang cả chuỗi class lẫn công\n * thức hex tương ứng, nằm sát nhau trên vài dòng liền: thêm tone là thêm cả ba, không quên được.\n * Thứ tự phần tử = chỉ số băm, nên thứ tự cũng chỉ tồn tại ở một chỗ.\n *\n * Vì sao công thức hex là HÀM nhận `palette` chứ không đọc thẳng token: `tokens.ts` là entry\n * `@comitor/ui/tokens`; nếu file này `import { accent } from \"../tokens.js\"` thì thành vòng import\n * (tokens.ts phải import ngược lại bảng này) — vòng có khởi tạo hằng ở giữa là lỗi TDZ lúc chạy.\n * Nhận bảng màu qua tham số thì phụ thuộc chỉ đi MỘT chiều: tokens.ts → file này.\n */\n\n/** Bảy sắc màu phụ mà bảng tone đọc (gold đi riêng qua thang của nó). */\ninterface AvatarToneHues {\n readonly teal: string;\n readonly green: string;\n readonly red: string;\n readonly yellow: string;\n readonly blue: string;\n readonly purple: string;\n readonly pink: string;\n}\n\n/** Đúng 8 tone — chốt ở tầng kiểu: `getAvatarToneIndex` băm theo độ dài này. */\ntype AvatarToneTable<T> = readonly [T, T, T, T, T, T, T, T];\n\n/** Cặp nền + màu chữ (hex đục) của một tone avatar. */\nexport interface AvatarToneColors {\n background: string;\n foreground: string;\n}\n\n/**\n * Các bậc màu mà công thức hex bên dưới đọc vào — `tokens.ts` truyền xuống một bộ cho light,\n * một bộ cho dark. Khai tường minh bằng `string` (không `typeof gold`) vì bản light và bản dark\n * là hai bộ giá trị khác nhau, không cùng một kiểu literal.\n */\nexport interface AvatarTonePalette {\n /** Thang gold — cần bậc 100 · 500 · 600. */\n gold: { readonly 100: string; readonly 500: string; readonly 600: string };\n /** Màu phụ ở vai trò TÔ NỀN (`accent.light` hoặc `accent.dark`). */\n accent: AvatarToneHues;\n /** Cùng màu phụ đó ở vai trò CHỮ trên nền trang (`accentInk.light` hoặc `accentInk.dark`). */\n accentInk: AvatarToneHues;\n /** Nền mà tint hợp thành lên — `--card` của theme. */\n card: string;\n}\n\ninterface AvatarTone {\n /**\n * Tên gọi của tone — để chỗ dùng CHỌN TAY một màu thay vì để hàm băm quyết.\n *\n * ⚠ Tên là một phần của HỢP ĐỒNG: nó đi vào cột database của app (`apps.icon_color` bên\n * `comitor-account`) và vào prop `tone` của `IconAvatar`. Đổi tên một tone là làm mọi hàng đã\n * lưu trỏ vào hư không — và hỏng đó IM LẶNG, vì giá trị lạ chỉ rơi về màu suy theo tên.\n * Thêm tone thì thêm tên mới; đừng đổi tên cũ.\n */\n readonly name: AvatarToneName;\n /** Vai trò DOM: chuỗi class token tĩnh (kèm biến thể `dark:`). */\n readonly classes: string;\n /** Vai trò canvas/email/PDF: đúng những gì `classes` nói, tính ra hex đục ở light. */\n readonly light: (p: AvatarTonePalette) => AvatarToneColors;\n /** Nhánh `dark:` của `classes`. */\n readonly dark: (p: AvatarTonePalette) => AvatarToneColors;\n}\n\n/**\n * Trộn `color` phủ `alpha` lên nền `over`, trả về hex đục.\n *\n * Tái hiện đúng phép mà trình duyệt làm với `bg-teal/15`: Tailwind sinh ra màu CÓ alpha, còn nền\n * phía dưới (`--card`) mới quyết định hex cuối cùng. Nơi không có CSS thì không có gì để hợp\n * thành, nên hex phải mang sẵn kết quả đã trộn.\n */\nfunction tintOver(color: string, over: string, alpha: number): string {\n const channel = (hex: string, i: number) => Number.parseInt(hex.slice(1 + i * 2, 3 + i * 2), 16);\n const mixed = [0, 1, 2].map((i) => Math.round(channel(color, i) * alpha + channel(over, i) * (1 - alpha)));\n return `#${mixed.map((v) => v.toString(16).padStart(2, \"0\")).join(\"\")}`.toUpperCase();\n}\n\n/**\n * 8 tone deterministic. Phía class TẤT CẢ là token tĩnh — không ghép chuỗi lúc chạy (`bg-${c}-100`)\n * vì Tailwind quét tĩnh, class ghép động sẽ không có mặt trong CSS của app; cũng không dùng hex\n * inline vì như vậy là mất dark mode.\n *\n * ─ VÌ SAO LÀ MÀU PHỤ + CHART CHỨ KHÔNG PHẢI TOKEN SEMANTIC ─\n * Đây là màu ĐỊNH DANH (phân biệt người), không phải màu TRẠNG THÁI — gán `--success` cho một con\n * người là sai nghĩa. Bộ màu phụ + bảng chart là nhóm token DUY NHẤT có đủ 8 sắc khác nhau và có\n * bản riêng cho dark, nên vẫn đổi theo theme và app vẫn ghi đè được.\n *\n * ─ TƯƠNG PHẢN: VÌ SAO BA TONE PHẢI HẠ XUỐNG BẬC INK Ở LIGHT ─\n * Chữ initials tuy `aria-hidden` nhưng người sáng mắt vẫn đọc, nên vẫn phải đạt AA 4,5:1. Bản đầu\n * dùng thẳng `text-teal/green/red` trên nền tint 15% và HỎNG ở light (đo theo WCAG, nền tint đã\n * trộn với `--card` trắng):\n *\n * teal #1F8A8B trên bg-teal/15 = 3,44:1 ✗\n * green #2EA56A trên bg-green/15 = 2,69:1 ✗ (dưới cả ngưỡng 3:1)\n * red #D64545 trên bg-red/15 = 3,57:1 ✗\n *\n * Sửa đúng khuôn `Badge`: dùng bậc `--x-ink` cho light, giữ token đã nâng sáng cho dark. Đo lại\n * trên đúng hex mà `getAvatarToneColors` trả ra (styles.css đã đóng băng bậc ink, xem dưới):\n *\n * teal #1A6668 trên #DDEDEE = 5,54:1 ✓ · dark #2DD4BF trên #193435 = 7,12:1 ✓\n * green #216A48 trên #E0F2E9 = 5,60:1 ✓ · dark #4ADE80 trên #1E362C = 7,44:1 ✓\n * red #9A3537 trên #F9E3E3 = 5,83:1 ✓ · dark #F87171 trên #38252A = 5,18:1 ✓\n *\n * (Bộ số 5,56 / 5,58 / 7,10 / 7,47 / 5,17 ghi ở bản trước là kết quả của chuỗi `color-mix` TRƯỚC\n * khi hex được đóng băng vào token — lệch ở chữ, không lệch ở màu.)\n *\n * Class viết thẳng `text-teal-ink` / `text-green-ink` / `text-red-ink` / `text-yellow-ink` chứ\n * KHÔNG nhắc lại chuỗi `color-mix(...)` — hai cách cho ra đúng cùng một hex (styles.css đã đóng\n * băng kết quả: #1A6668 · #216A48 · #9A3537), và ở `.dark` thì `--teal-ink` vốn trỏ về `--teal`\n * nên không cần biến thể `dark:` nào. Nhờ vậy tên trong class khớp đúng tên trong công thức hex\n * ngay bên dưới (`p.accentInk.teal`) — soi hai vế cạnh nhau là thấy lệch ngay.\n */\n/**\n * Tên của 8 tone, ĐÚNG THỨ TỰ bảng bên dưới — thứ tự ấy cũng là chỉ số băm, nên hai thứ không\n * được trôi khỏi nhau. Đây là bảng màu mà chỗ dùng chọn tay khi không muốn để tên quyết định.\n *\n * Tên lấy theo SẮC, không theo vai trò ngữ nghĩa: đây là màu ĐỊNH DANH, không phải màu trạng\n * thái — xem lý do dài ở docblock của `AVATAR_TONES`.\n */\nexport const AVATAR_TONE_NAMES = [\"gold\", \"teal\", \"green\", \"red\", \"yellow\", \"blue\", \"purple\", \"pink\"] as const;\n\nexport type AvatarToneName = (typeof AVATAR_TONE_NAMES)[number];\n\n/**\n * Tên tone CŨ → tên tone hôm nay (3.10.0). Ba tone cuối từng là `navy` · `ash` · `neutral` — cả ba\n * đều là xám ám xanh ở các độ đậm khác nhau, nên ô icon của ba app khác nhau trông như cùng một\n * màu. Chúng được THAY bằng ba sắc thật, đứng ĐÚNG vị trí cũ trong bảng (chỉ số băm giữ nguyên:\n * người/app nào trước ra `navy` thì nay ra `blue`, không ai nhảy sang tone khác).\n *\n * Bí danh thay vì giữ tên cũ cho màu mới: tên là hợp đồng (cột `apps.icon_color` của Account), và\n * một tên nói dối về màu (\"ash\" mà tím) còn tệ hơn một lần đổi tên có lối lùi. Bí danh đi theo\n * cùng VỊ TRÍ, nên hàng database còn ghi tên cũ ra đúng màu mà phép băm cũng sẽ cho ở chỗ đó.\n *\n * Xuất ở `@comitor/ui` từ 3.12.1 — app ánh xạ tên cũ đọc từ database bằng chính bảng này thay vì\n * chép một bản. ⚠ `Record` trần: khoá đến từ dữ liệu ngoài thì tra qua `Object.hasOwn` —\n * `LEGACY_AVATAR_TONE_ALIASES[\"constructor\"]` ra một hàm, không ra `undefined`.\n */\nexport const LEGACY_AVATAR_TONE_ALIASES: Readonly<Record<string, AvatarToneName>> = {\n navy: \"blue\",\n ash: \"purple\",\n neutral: \"pink\"\n};\n\nexport const AVATAR_TONES: AvatarToneTable<AvatarTone> = [\n {\n name: \"gold\",\n classes: \"bg-gold-100 text-gold-600 dark:bg-gold-500/30 dark:text-gold-100\",\n light: (p) => ({ background: p.gold[100], foreground: p.gold[600] }),\n dark: (p) => ({ background: tintOver(p.gold[500], p.card, 0.3), foreground: p.gold[100] })\n },\n {\n name: \"teal\",\n classes: \"bg-teal/15 text-teal-ink\",\n light: (p) => ({ background: tintOver(p.accent.teal, p.card, 0.15), foreground: p.accentInk.teal }),\n dark: (p) => ({ background: tintOver(p.accent.teal, p.card, 0.15), foreground: p.accentInk.teal })\n },\n {\n name: \"green\",\n classes: \"bg-green/15 text-green-ink\",\n light: (p) => ({ background: tintOver(p.accent.green, p.card, 0.15), foreground: p.accentInk.green }),\n dark: (p) => ({ background: tintOver(p.accent.green, p.card, 0.15), foreground: p.accentInk.green })\n },\n {\n name: \"red\",\n classes: \"bg-red/15 text-red-ink\",\n light: (p) => ({ background: tintOver(p.accent.red, p.card, 0.15), foreground: p.accentInk.red }),\n dark: (p) => ({ background: tintOver(p.accent.red, p.card, 0.15), foreground: p.accentInk.red })\n },\n {\n name: \"yellow\",\n classes: \"bg-yellow/25 text-yellow-ink dark:bg-yellow/20\",\n light: (p) => ({ background: tintOver(p.accent.yellow, p.card, 0.25), foreground: p.accentInk.yellow }),\n dark: (p) => ({ background: tintOver(p.accent.yellow, p.card, 0.2), foreground: p.accentInk.yellow })\n },\n {\n // Ba tone cuối: ba sắc ĐỊNH DANH riêng của bảng này (styles.css, khối \"Màu phụ\") — thay navy ·\n // ash · neutral từ 3.10.0, xem `LEGACY_AVATAR_TONE_ALIASES`. Cùng khuôn teal/green/red: tint /15\n // + bậc ink; ở dark `--x-ink` trỏ về bản dark riêng của fill nên một chuỗi class đủ cả hai theme.\n // Chữ trên tint /15: blue 5,67 · purple 5,72 · pink 5,33:1 (light) · 5,76 · 5,17 · 5,37:1 (dark).\n name: \"blue\",\n classes: \"bg-blue/15 text-blue-ink\",\n light: (p) => ({ background: tintOver(p.accent.blue, p.card, 0.15), foreground: p.accentInk.blue }),\n dark: (p) => ({ background: tintOver(p.accent.blue, p.card, 0.15), foreground: p.accentInk.blue })\n },\n {\n name: \"purple\",\n classes: \"bg-purple/15 text-purple-ink\",\n light: (p) => ({ background: tintOver(p.accent.purple, p.card, 0.15), foreground: p.accentInk.purple }),\n dark: (p) => ({ background: tintOver(p.accent.purple, p.card, 0.15), foreground: p.accentInk.purple })\n },\n {\n name: \"pink\",\n classes: \"bg-pink/15 text-pink-ink\",\n light: (p) => ({ background: tintOver(p.accent.pink, p.card, 0.15), foreground: p.accentInk.pink }),\n dark: (p) => ({ background: tintOver(p.accent.pink, p.card, 0.15), foreground: p.accentInk.pink })\n }\n];\n\n/**\n * Hash chuỗi → số nguyên không âm (biến thể FNV-1a 32 bit).\n *\n * Nội bộ, KHÔNG xuất ra API: công dụng duy nhất của nó là chọn tone avatar ngay dưới đây. Xuất\n * một hàm băm ra ngoài chỉ mời app dựng lại phép chọn tone của riêng nó — đúng thứ sinh ra chuyện\n * cùng một người hai màu. Chạy trên code point (không phải byte) để tên có dấu vẫn ổn định giữa\n * server và client.\n */\nfunction hashString(input: string): number {\n let hash = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n hash ^= input.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n return Math.abs(hash | 0);\n}\n\n/**\n * Chỉ số tone theo tên — phép chọn màu avatar DUY NHẤT của cả gói.\n *\n * Khoá băm là **tên hiển thị** đã `trim` + hạ chữ thường theo locale `vi-VN` (không phải\n * email/slug: chỗ nào hiển thị avatar cũng chắc chắn có tên, còn email/slug thì không — lấy khoá\n * khác nhau ở từng chỗ là cách nhanh nhất để cùng một người ra hai màu).\n */\nexport function getAvatarToneIndex(name: string): number {\n return hashString(name.trim().toLocaleLowerCase(\"vi-VN\")) % AVATAR_TONES.length;\n}\n\n/** Tone (cả class lẫn công thức hex) ứng với một tên. */\nexport function getAvatarTone(name: string): AvatarTone {\n // `noUncheckedIndexedAccess` bật → phải có nhánh lùi, dù chỉ số luôn nằm trong [0, 8).\n return AVATAR_TONES[getAvatarToneIndex(name)] ?? AVATAR_TONES[0];\n}\n\n/**\n * Tone theo TÊN — cửa cho chỗ dùng chọn tay một màu.\n *\n * Trả `undefined` cho tên lạ, và nơi gọi hiểu đó là \"rơi về màu suy theo tên\". KHÔNG ném: giá trị\n * này đến từ database (`apps.icon_color`), nơi một hàng cũ hoàn toàn có thể mang tên của một tone\n * đã bị xoá — làm sập cả dải ứng dụng vì một chữ trong một hàng là đổi sai lấy tệ hơn. Tên đã\n * ĐỔI thì đi qua `LEGACY_AVATAR_TONE_ALIASES` trước khi tra.\n *\n * ⚠ `LEGACY_AVATAR_TONE_ALIASES` dùng `Record` trần: `\"constructor\"` tra ra một hàm, không phải\n * tên tone — nhưng hàm thì không bằng `tone.name` nào, nên kết quả vẫn là `undefined`.\n */\nexport function getAvatarToneByName(name: string | null | undefined): AvatarTone | undefined {\n if (!name) return undefined;\n const current = LEGACY_AVATAR_TONE_ALIASES[name] ?? name;\n return AVATAR_TONES.find((tone) => tone.name === current);\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comitor/ui",
3
- "version": "3.11.1",
3
+ "version": "3.12.1",
4
4
  "description": "Comitor design system — Shadcn/UI tùy biến theo brand Comitor + component dùng chung cho hệ sinh thái SaaS (Tasks, Chat, CRM, HR…)",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -54,6 +54,10 @@
54
54
  "types": "./dist/editor/index.d.ts",
55
55
  "import": "./dist/editor/index.js"
56
56
  },
57
+ "./chat": {
58
+ "types": "./dist/chat/index.d.ts",
59
+ "import": "./dist/chat/index.js"
60
+ },
57
61
  "./form": {
58
62
  "types": "./dist/form.d.ts",
59
63
  "import": "./dist/form.js"
@@ -76,10 +80,11 @@
76
80
  "test:nav-active": "node scripts/check-nav-active.mjs",
77
81
  "test:grid-render": "node scripts/check-data-grid-render.mjs",
78
82
  "test:editor-markdown": "node scripts/check-editor-markdown.mjs",
83
+ "test:gantt-tree": "node scripts/check-gantt-tree.mjs",
79
84
  "verify:directives": "node scripts/verify-directives.mjs",
80
85
  "smoke:entries": "node scripts/smoke-entries.mjs",
81
86
  "check:exports": "publint --strict && attw --pack . --profile esm-only --exclude-entrypoints styles.css",
82
- "prepublishOnly": "pnpm run typecheck && pnpm run test:i18n && pnpm run build && pnpm run verify:directives && pnpm run smoke:entries && pnpm run check:exports && pnpm run test:nav-active && pnpm run test:grid-contract && pnpm run test:grid-render && pnpm run test:editor-markdown && pnpm run test:a11y-gate && pnpm run lint:a11y",
87
+ "prepublishOnly": "pnpm run typecheck && pnpm run test:i18n && pnpm run build && pnpm run verify:directives && pnpm run smoke:entries && pnpm run check:exports && pnpm run test:nav-active && pnpm run test:grid-contract && pnpm run test:grid-render && pnpm run test:editor-markdown && pnpm run test:gantt-tree && pnpm run test:a11y-gate && pnpm run lint:a11y",
83
88
  "test:grid-contract": "node scripts/check-grid-contract.mjs",
84
89
  "test:i18n": "node scripts/check-i18n.mjs --self-test && node scripts/check-i18n.mjs"
85
90
  },
@@ -185,6 +190,8 @@
185
190
  "@dnd-kit/utilities": "^3.2.2",
186
191
  "@floating-ui/react": "^0.27.20",
187
192
  "@floating-ui/react-dom": "^2.1.9",
193
+ "@headless-tree/core": "^1.8.0",
194
+ "@headless-tree/react": "^1.8.0",
188
195
  "@radix-ui/react-accordion": "1.2.12",
189
196
  "@radix-ui/react-alert-dialog": "1.1.15",
190
197
  "@radix-ui/react-aspect-ratio": "1.1.8",