@comitor/ui 3.6.2 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/components/composite/combobox.d.ts +9 -0
- package/dist/components/composite/combobox.js +16 -3
- package/dist/components/composite/combobox.js.map +1 -1
- package/dist/components/composite/inline-edit.d.ts +7 -1
- package/dist/components/composite/inline-edit.js +10 -1
- package/dist/components/composite/inline-edit.js.map +1 -1
- package/dist/components/composite/key-sequence.d.ts +44 -0
- package/dist/components/composite/key-sequence.js +32 -0
- package/dist/components/composite/key-sequence.js.map +1 -0
- package/dist/components/composite/keyboard-shortcuts-dialog.d.ts +39 -0
- package/dist/components/composite/keyboard-shortcuts-dialog.js +78 -0
- package/dist/components/composite/keyboard-shortcuts-dialog.js.map +1 -0
- package/dist/components/composite/use-key-sequences.d.ts +28 -0
- package/dist/components/composite/use-key-sequences.js +44 -0
- package/dist/components/composite/use-key-sequences.js.map +1 -0
- package/dist/components/ui/badge.d.ts +19 -2
- package/dist/components/ui/badge.js +44 -4
- package/dist/components/ui/badge.js.map +1 -1
- package/dist/components/ui/item.d.ts +1 -1
- package/dist/components/ui/item.js +13 -2
- package/dist/components/ui/item.js.map +1 -1
- package/dist/editor/bubble-toolbar.d.ts +2 -1
- package/dist/editor/editor-core.d.ts +2 -1
- package/dist/editor/editor-core.js +6 -4
- package/dist/editor/editor-core.js.map +1 -1
- package/dist/editor/editor-types.d.ts +3 -1
- package/dist/editor/fixed-toolbar.d.ts +2 -1
- package/dist/editor/image-upload.d.ts +3 -1
- package/dist/editor/index.d.ts +2 -1
- package/dist/editor/markdown-editor-classes.js +3 -1
- package/dist/editor/markdown-editor-classes.js.map +1 -1
- package/dist/editor/markdown-editor.d.ts +2 -1
- package/dist/editor/markdown-extensions.d.ts +9 -3
- package/dist/editor/markdown-extensions.js +28 -5
- package/dist/editor/markdown-extensions.js.map +1 -1
- package/dist/editor/markdown-syntax.d.ts +3 -1
- package/dist/editor/markdown-syntax.js +10 -4
- package/dist/editor/markdown-syntax.js.map +1 -1
- package/dist/editor/rich-text-editor.d.ts +2 -1
- package/dist/editor/slash-commands.d.ts +3 -1
- package/dist/editor/toolbar-actions.d.ts +3 -1
- package/dist/{editor-types-BMST7-VR.d.ts → editor-types-CSrMeuSw.d.ts} +20 -3
- package/dist/i18n/locale-provider.d.ts +1 -0
- package/dist/i18n/messages.d.ts +2 -0
- package/dist/i18n/messages.js +3 -0
- package/dist/i18n/messages.js.map +1 -1
- package/dist/i18n/namespaces/keyboard-shortcuts.d.ts +13 -0
- package/dist/i18n/namespaces/keyboard-shortcuts.js +15 -0
- package/dist/i18n/namespaces/keyboard-shortcuts.js.map +1 -0
- package/dist/i18n/namespaces/shell.js +4 -2
- package/dist/i18n/namespaces/shell.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/shell/app-shell.d.ts +14 -1
- package/dist/shell/app-shell.js +24 -2
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/display-prefs-seed.d.ts +64 -0
- package/dist/shell/display-prefs-seed.js +58 -0
- package/dist/shell/display-prefs-seed.js.map +1 -0
- package/dist/shell/index.d.ts +1 -0
- package/dist/shell/index.js +1 -0
- package/dist/shell/index.js.map +1 -1
- package/dist/shell/types.d.ts +2 -0
- package/dist/shell/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -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 { 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 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 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 { 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":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Chữ của `KeyboardShortcutsDialog` (bảng `?`). */
|
|
2
|
+
interface KeyboardShortcutsMessages {
|
|
3
|
+
/** Tiêu đề hộp thoại */
|
|
4
|
+
title: string;
|
|
5
|
+
/** Dòng mô tả dưới tiêu đề */
|
|
6
|
+
description: string;
|
|
7
|
+
/** Chữ nối hai phím của một CHUỖI ("G rồi M") — hiện giữa hai ô phím, và đọc cho trình đọc màn hình */
|
|
8
|
+
sequenceJoiner: string;
|
|
9
|
+
}
|
|
10
|
+
declare const keyboardShortcutsEn: KeyboardShortcutsMessages;
|
|
11
|
+
declare const keyboardShortcutsVi: KeyboardShortcutsMessages;
|
|
12
|
+
|
|
13
|
+
export { type KeyboardShortcutsMessages, keyboardShortcutsEn, keyboardShortcutsVi };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const keyboardShortcutsEn = {
|
|
2
|
+
title: "Keyboard shortcuts",
|
|
3
|
+
description: "Press the keys one after another. Shortcuts are off while you type in a field.",
|
|
4
|
+
sequenceJoiner: "then"
|
|
5
|
+
};
|
|
6
|
+
const keyboardShortcutsVi = {
|
|
7
|
+
title: "Ph\xEDm t\u1EAFt",
|
|
8
|
+
description: "B\u1EA5m l\u1EA7n l\u01B0\u1EE3t t\u1EEBng ph\xEDm. Ph\xEDm t\u1EAFt kh\xF4ng ch\u1EA1y khi \u0111ang g\xF5 trong m\u1ED9t \xF4.",
|
|
9
|
+
sequenceJoiner: "r\u1ED3i"
|
|
10
|
+
};
|
|
11
|
+
export {
|
|
12
|
+
keyboardShortcutsEn,
|
|
13
|
+
keyboardShortcutsVi
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=keyboard-shortcuts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/i18n/namespaces/keyboard-shortcuts.ts"],"sourcesContent":["/** Chữ của `KeyboardShortcutsDialog` (bảng `?`). */\nexport interface KeyboardShortcutsMessages {\n /** Tiêu đề hộp thoại */\n title: string;\n /** Dòng mô tả dưới tiêu đề */\n description: string;\n /** Chữ nối hai phím của một CHUỖI (\"G rồi M\") — hiện giữa hai ô phím, và đọc cho trình đọc màn hình */\n sequenceJoiner: string;\n}\n\nexport const keyboardShortcutsEn: KeyboardShortcutsMessages = {\n title: \"Keyboard shortcuts\",\n description: \"Press the keys one after another. Shortcuts are off while you type in a field.\",\n sequenceJoiner: \"then\"\n};\n\nexport const keyboardShortcutsVi: KeyboardShortcutsMessages = {\n title: \"Phím tắt\",\n description: \"Bấm lần lượt từng phím. Phím tắt không chạy khi đang gõ trong một ô.\",\n sequenceJoiner: \"rồi\"\n};\n"],"mappings":"AAUO,MAAM,sBAAiD;AAAA,EAC5D,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAClB;AAEO,MAAM,sBAAiD;AAAA,EAC5D,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAClB;","names":[]}
|
|
@@ -31,7 +31,8 @@ const shellEn = {
|
|
|
31
31
|
themeLight: "Light",
|
|
32
32
|
themeDark: "Dark",
|
|
33
33
|
themeSystem: "System",
|
|
34
|
-
toggleTheme: "Toggle theme"
|
|
34
|
+
toggleTheme: "Toggle theme",
|
|
35
|
+
skipToContent: "Skip to main content"
|
|
35
36
|
};
|
|
36
37
|
const shellVi = {
|
|
37
38
|
collapseSidebar: "Thu g\u1ECDn thanh b\xEAn",
|
|
@@ -66,7 +67,8 @@ const shellVi = {
|
|
|
66
67
|
themeLight: "S\xE1ng",
|
|
67
68
|
themeDark: "T\u1ED1i",
|
|
68
69
|
themeSystem: "H\u1EC7 th\u1ED1ng",
|
|
69
|
-
toggleTheme: "\u0110\u1ED5i giao di\u1EC7n"
|
|
70
|
+
toggleTheme: "\u0110\u1ED5i giao di\u1EC7n",
|
|
71
|
+
skipToContent: "B\u1ECF qua \u0111i\u1EC1u h\u01B0\u1EDBng, sang n\u1ED9i dung ch\xEDnh"
|
|
70
72
|
};
|
|
71
73
|
export {
|
|
72
74
|
shellEn,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/i18n/namespaces/shell.ts"],"sourcesContent":["import type { ShellLabels } from \"../../shell/types.js\";\n\n/**\n * Chữ của cả tầng shell — `ShellProvider`/`AppShell` và mọi thứ đọc `useShell().labels`\n * (`Sidebar`, `AppHeader`, `MobileMenu`, `WorkspaceSwitcher`, `AppLauncher`, `UserMenu`), cộng\n * `ThemeToggle` và `NotificationsButton` khi đứng ngoài shell. Hình dạng + chú thích từng khoá:\n * `ShellLabels`.\n *\n * ⚠ `collapseSidebarShort` PHẢI là một phần của `collapseSidebar` ở MỌI ngôn ngữ (WCAG 2.5.3):\n * \"Collapse\" ⊂ \"Collapse sidebar\", \"Thu gọn\" ⊂ \"Thu gọn thanh bên\".\n * ⚠ Cùng luật cho cặp `apps` (tooltip HIỆN RA của nút mở launcher) ⊂ `appLauncherLabel` (tên cho\n * trình đọc màn hình): \"Ứng dụng\" ⊂ \"Mở danh sách ứng dụng\". Bảng tiếng Anh của `3.0.0` hỏng đúng\n * chỗ này — \"Apps\" không nằm trong \"Open app launcher\", nên người điều khiển bằng giọng nói đọc\n * chữ họ THẤY (\"click Apps\") mà không khớp nút nào. Sửa ở `3.0.1`.\n */\nexport const shellEn: ShellLabels = {\n collapseSidebar: \"Collapse sidebar\",\n collapseSidebarShort: \"Collapse\",\n expandSidebar: \"Expand sidebar\",\n openMenu: \"Open menu\",\n closeMenu: \"Close menu\",\n search: \"Search\",\n searchPlaceholder: \"Search…\",\n notifications: \"Notifications\",\n navigationLabel: \"Main navigation\",\n workspace: \"Workspace\",\n workspaceSwitcherLabel: \"Switch workspace\",\n workspaceSearchPlaceholder: \"Search workspaces…\",\n workspaceEmpty: \"No workspaces found\",\n createWorkspace: \"Create workspace\",\n workspaceSettings: \"Workspace settings\",\n inviteMembers: \"Invite members\",\n members: (count) => `${count} ${count === 1 ? \"member\" : \"members\"}`,\n apps: \"Apps\",\n appLauncherLabel: \"Open apps list\",\n myApps: \"Your apps\",\n discoverApps: \"Discover more\",\n locked: \"Locked\",\n lockedHint: \"Not included in your current plan\",\n account: \"Account\",\n profile: \"Profile\",\n settings: \"Settings\",\n appearance: \"Appearance\",\n help: \"Help\",\n logout: \"Log out\",\n themeLight: \"Light\",\n themeDark: \"Dark\",\n themeSystem: \"System\",\n toggleTheme: \"Toggle theme\"\n};\n\nexport const shellVi: ShellLabels = {\n collapseSidebar: \"Thu gọn thanh bên\",\n collapseSidebarShort: \"Thu gọn\",\n expandSidebar: \"Mở rộng thanh bên\",\n openMenu: \"Mở menu\",\n closeMenu: \"Đóng menu\",\n search: \"Tìm kiếm\",\n searchPlaceholder: \"Tìm kiếm…\",\n notifications: \"Thông báo\",\n navigationLabel: \"Điều hướng chính\",\n workspace: \"Không gian làm việc\",\n workspaceSwitcherLabel: \"Đổi không gian làm việc\",\n workspaceSearchPlaceholder: \"Tìm không gian làm việc…\",\n workspaceEmpty: \"Không tìm thấy không gian làm việc\",\n createWorkspace: \"Tạo không gian làm việc\",\n workspaceSettings: \"Cài đặt không gian làm việc\",\n inviteMembers: \"Mời thành viên\",\n members: (count) => `${count} thành viên`,\n apps: \"Ứng dụng\",\n appLauncherLabel: \"Mở danh sách ứng dụng\",\n myApps: \"Ứng dụng của bạn\",\n discoverApps: \"Khám phá thêm\",\n locked: \"Chưa mở khoá\",\n lockedHint: \"Ứng dụng chưa có trong gói hiện tại\",\n account: \"Tài khoản\",\n profile: \"Hồ sơ\",\n settings: \"Cài đặt\",\n appearance: \"Giao diện\",\n help: \"Trợ giúp\",\n logout: \"Đăng xuất\",\n themeLight: \"Sáng\",\n themeDark: \"Tối\",\n themeSystem: \"Hệ thống\",\n toggleTheme: \"Đổi giao diện\"\n};\n"],"mappings":"AAeO,MAAM,UAAuB;AAAA,EAClC,iBAAiB;AAAA,EACjB,sBAAsB;AAAA,EACtB,eAAe;AAAA,EACf,UAAU;AAAA,EACV,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,mBAAmB;AAAA,EACnB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,wBAAwB;AAAA,EACxB,4BAA4B;AAAA,EAC5B,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,eAAe;AAAA,EACf,SAAS,CAAC,UAAU,GAAG,KAAK,IAAI,UAAU,IAAI,WAAW,SAAS;AAAA,EAClE,MAAM;AAAA,EACN,kBAAkB;AAAA,EAClB,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,SAAS;AAAA,EACT,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,aAAa;AAAA,EACb,aAAa;
|
|
1
|
+
{"version":3,"sources":["../../../src/i18n/namespaces/shell.ts"],"sourcesContent":["import type { ShellLabels } from \"../../shell/types.js\";\n\n/**\n * Chữ của cả tầng shell — `ShellProvider`/`AppShell` và mọi thứ đọc `useShell().labels`\n * (`Sidebar`, `AppHeader`, `MobileMenu`, `WorkspaceSwitcher`, `AppLauncher`, `UserMenu`), cộng\n * `ThemeToggle` và `NotificationsButton` khi đứng ngoài shell. Hình dạng + chú thích từng khoá:\n * `ShellLabels`.\n *\n * ⚠ `collapseSidebarShort` PHẢI là một phần của `collapseSidebar` ở MỌI ngôn ngữ (WCAG 2.5.3):\n * \"Collapse\" ⊂ \"Collapse sidebar\", \"Thu gọn\" ⊂ \"Thu gọn thanh bên\".\n * ⚠ Cùng luật cho cặp `apps` (tooltip HIỆN RA của nút mở launcher) ⊂ `appLauncherLabel` (tên cho\n * trình đọc màn hình): \"Ứng dụng\" ⊂ \"Mở danh sách ứng dụng\". Bảng tiếng Anh của `3.0.0` hỏng đúng\n * chỗ này — \"Apps\" không nằm trong \"Open app launcher\", nên người điều khiển bằng giọng nói đọc\n * chữ họ THẤY (\"click Apps\") mà không khớp nút nào. Sửa ở `3.0.1`.\n */\nexport const shellEn: ShellLabels = {\n collapseSidebar: \"Collapse sidebar\",\n collapseSidebarShort: \"Collapse\",\n expandSidebar: \"Expand sidebar\",\n openMenu: \"Open menu\",\n closeMenu: \"Close menu\",\n search: \"Search\",\n searchPlaceholder: \"Search…\",\n notifications: \"Notifications\",\n navigationLabel: \"Main navigation\",\n workspace: \"Workspace\",\n workspaceSwitcherLabel: \"Switch workspace\",\n workspaceSearchPlaceholder: \"Search workspaces…\",\n workspaceEmpty: \"No workspaces found\",\n createWorkspace: \"Create workspace\",\n workspaceSettings: \"Workspace settings\",\n inviteMembers: \"Invite members\",\n members: (count) => `${count} ${count === 1 ? \"member\" : \"members\"}`,\n apps: \"Apps\",\n appLauncherLabel: \"Open apps list\",\n myApps: \"Your apps\",\n discoverApps: \"Discover more\",\n locked: \"Locked\",\n lockedHint: \"Not included in your current plan\",\n account: \"Account\",\n profile: \"Profile\",\n settings: \"Settings\",\n appearance: \"Appearance\",\n help: \"Help\",\n logout: \"Log out\",\n themeLight: \"Light\",\n themeDark: \"Dark\",\n themeSystem: \"System\",\n toggleTheme: \"Toggle theme\",\n skipToContent: \"Skip to main content\"\n};\n\nexport const shellVi: ShellLabels = {\n collapseSidebar: \"Thu gọn thanh bên\",\n collapseSidebarShort: \"Thu gọn\",\n expandSidebar: \"Mở rộng thanh bên\",\n openMenu: \"Mở menu\",\n closeMenu: \"Đóng menu\",\n search: \"Tìm kiếm\",\n searchPlaceholder: \"Tìm kiếm…\",\n notifications: \"Thông báo\",\n navigationLabel: \"Điều hướng chính\",\n workspace: \"Không gian làm việc\",\n workspaceSwitcherLabel: \"Đổi không gian làm việc\",\n workspaceSearchPlaceholder: \"Tìm không gian làm việc…\",\n workspaceEmpty: \"Không tìm thấy không gian làm việc\",\n createWorkspace: \"Tạo không gian làm việc\",\n workspaceSettings: \"Cài đặt không gian làm việc\",\n inviteMembers: \"Mời thành viên\",\n members: (count) => `${count} thành viên`,\n apps: \"Ứng dụng\",\n appLauncherLabel: \"Mở danh sách ứng dụng\",\n myApps: \"Ứng dụng của bạn\",\n discoverApps: \"Khám phá thêm\",\n locked: \"Chưa mở khoá\",\n lockedHint: \"Ứng dụng chưa có trong gói hiện tại\",\n account: \"Tài khoản\",\n profile: \"Hồ sơ\",\n settings: \"Cài đặt\",\n appearance: \"Giao diện\",\n help: \"Trợ giúp\",\n logout: \"Đăng xuất\",\n themeLight: \"Sáng\",\n themeDark: \"Tối\",\n themeSystem: \"Hệ thống\",\n toggleTheme: \"Đổi giao diện\",\n skipToContent: \"Bỏ qua điều hướng, sang nội dung chính\"\n};\n"],"mappings":"AAeO,MAAM,UAAuB;AAAA,EAClC,iBAAiB;AAAA,EACjB,sBAAsB;AAAA,EACtB,eAAe;AAAA,EACf,UAAU;AAAA,EACV,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,mBAAmB;AAAA,EACnB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,wBAAwB;AAAA,EACxB,4BAA4B;AAAA,EAC5B,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,eAAe;AAAA,EACf,SAAS,CAAC,UAAU,GAAG,KAAK,IAAI,UAAU,IAAI,WAAW,SAAS;AAAA,EAClE,MAAM;AAAA,EACN,kBAAkB;AAAA,EAClB,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,SAAS;AAAA,EACT,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAe;AACjB;AAEO,MAAM,UAAuB;AAAA,EAClC,iBAAiB;AAAA,EACjB,sBAAsB;AAAA,EACtB,eAAe;AAAA,EACf,UAAU;AAAA,EACV,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,mBAAmB;AAAA,EACnB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,wBAAwB;AAAA,EACxB,4BAA4B;AAAA,EAC5B,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,eAAe;AAAA,EACf,SAAS,CAAC,UAAU,GAAG,KAAK;AAAA,EAC5B,MAAM;AAAA,EACN,kBAAkB;AAAA,EAClB,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,SAAS;AAAA,EACT,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,aAAa;AAAA,EACb,aAAa;AAAA,EACb,eAAe;AACjB;","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -15,7 +15,9 @@ export { SELECT_EMPTY_VALUE, fromSelectValue, toSelectValue } from './components
|
|
|
15
15
|
export { FormSection, FormSectionAccent, FormSectionProps } from './components/composite/form-section.js';
|
|
16
16
|
export { IconAvatar, IconAvatarIcon, IconAvatarProps } from './components/composite/icon-avatar.js';
|
|
17
17
|
export { InlineEdit, InlineEditProps } from './components/composite/inline-edit.js';
|
|
18
|
+
export { KEY_SEQUENCE_TIMEOUT_MS, KeySequence, KeySequenceInput, advanceKeySequence, isEditableTarget, normalizeSequenceKey } from './components/composite/key-sequence.js';
|
|
18
19
|
export { KeyboardHint, KeyboardHintProps, useIsMac } from './components/composite/keyboard-hint.js';
|
|
20
|
+
export { KeyboardShortcutItem, KeyboardShortcutSection, KeyboardShortcutsDialog, KeyboardShortcutsDialogProps } from './components/composite/keyboard-shortcuts-dialog.js';
|
|
19
21
|
export { LetterAvatar, LetterAvatarProps, LetterAvatarSize, getAvatarToneClasses } from './components/composite/letter-avatar.js';
|
|
20
22
|
export { PageContainer, PageContainerProps, PageContainerWidth } from './components/composite/page-container.js';
|
|
21
23
|
export { PageHeader, PageHeaderBreadcrumbItem, PageHeaderLinkProps, PageHeaderProps } from './components/composite/page-header.js';
|
|
@@ -30,6 +32,7 @@ export { TablePagination, TablePaginationProps } from './components/composite/ta
|
|
|
30
32
|
export { DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_TABLE_PAGINATION_LABELS, TablePaginationLabels } from './components/composite/table-pagination-constants.js';
|
|
31
33
|
export { getVietnameseInitials, truncate } from './components/composite/text-utils.js';
|
|
32
34
|
export { ToastOptions, ToastVariant, Toaster, ToasterProps, dismissToast, toast, toastPromise } from './components/composite/toast.js';
|
|
35
|
+
export { UseKeySequencesOptions, useKeySequences } from './components/composite/use-key-sequences.js';
|
|
33
36
|
export { Accordion, AccordionContent, AccordionContentProps, AccordionItem, AccordionItemProps, AccordionProps, AccordionTrigger, AccordionTriggerProps } from './components/ui/accordion.js';
|
|
34
37
|
export { ActionBar, ActionBarClose, ActionBarCloseProps, ActionBarGroup, ActionBarItem, ActionBarItemProps, ActionBarProps, ActionBarSelection, ActionBarSelectionProps, ActionBarSeparator, ActionBarSeparatorProps } from './components/ui/action-bar.js';
|
|
35
38
|
export { ActionBarLabels, DEFAULT_ACTION_BAR_LABELS } from './components/ui/action-bar-constants.js';
|
|
@@ -166,6 +169,7 @@ import './i18n/namespaces/rating.js';
|
|
|
166
169
|
import './i18n/namespaces/pagination.js';
|
|
167
170
|
import './i18n/namespaces/mention.js';
|
|
168
171
|
import './editor/markdown-editor-constants.js';
|
|
172
|
+
import './i18n/namespaces/keyboard-shortcuts.js';
|
|
169
173
|
import './i18n/namespaces/inline-edit.js';
|
|
170
174
|
import './i18n/namespaces/filter-chips.js';
|
|
171
175
|
import './uploader/file-upload-constants.js';
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,9 @@ export * from "./components/composite/form-field-constants.js";
|
|
|
15
15
|
export * from "./components/composite/form-section.js";
|
|
16
16
|
import { IconAvatar } from "./components/composite/icon-avatar.js";
|
|
17
17
|
export * from "./components/composite/inline-edit.js";
|
|
18
|
+
export * from "./components/composite/key-sequence.js";
|
|
18
19
|
export * from "./components/composite/keyboard-hint.js";
|
|
20
|
+
export * from "./components/composite/keyboard-shortcuts-dialog.js";
|
|
19
21
|
import { getAvatarToneClasses, LetterAvatar } from "./components/composite/letter-avatar.js";
|
|
20
22
|
export * from "./components/composite/page-container.js";
|
|
21
23
|
export * from "./components/composite/page-header.js";
|
|
@@ -36,6 +38,7 @@ import {
|
|
|
36
38
|
truncate
|
|
37
39
|
} from "./components/composite/text-utils.js";
|
|
38
40
|
export * from "./components/composite/toast.js";
|
|
41
|
+
export * from "./components/composite/use-key-sequences.js";
|
|
39
42
|
export * from "./components/ui/accordion.js";
|
|
40
43
|
export * from "./components/ui/action-bar.js";
|
|
41
44
|
export * from "./components/ui/action-bar-constants.js";
|
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/keyboard-hint.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\";\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;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;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 { 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":[]}
|
|
@@ -47,6 +47,19 @@ interface AppShellProps extends ShellProviderProps {
|
|
|
47
47
|
* (mất trạng thái). Giữ nó luôn có hoặc luôn vắng.
|
|
48
48
|
*/
|
|
49
49
|
locale?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Skip link đầu khung (mặc định `true`) — WCAG 2.4.1, mức A. Một khung có thanh bên bắt người dùng bàn
|
|
52
|
+
* phím Tab qua toàn bộ điều hướng trước khi chạm nội dung; giải MỘT lần ở khung thì mọi app thừa hưởng.
|
|
53
|
+
* Link vô hình (`sr-only`) cho tới khi nhận focus nên không tốn pixel nào của thiết kế. Chữ: khoá
|
|
54
|
+
* `skipToContent` của namespace `shell`.
|
|
55
|
+
*/
|
|
56
|
+
skipLink?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* `id` của `<main>` — đích của skip link (mặc định `"main-content"`). `<main>` mang `tabIndex={-1}` để
|
|
59
|
+
* nhận được focus khi nhảy tới: không có nó, trình duyệt cuộn tới nhưng focus ở lại link, và Tab kế
|
|
60
|
+
* tiếp quay về đầu thanh bên.
|
|
61
|
+
*/
|
|
62
|
+
mainId?: string;
|
|
50
63
|
className?: string;
|
|
51
64
|
contentClassName?: string;
|
|
52
65
|
}
|
|
@@ -60,6 +73,6 @@ interface AppShellProps extends ShellProviderProps {
|
|
|
60
73
|
* Có `"use client"`: mọi callback (`onLogout`, `onWorkspaceChange`…) là hàm nên nơi
|
|
61
74
|
* render `<AppShell>` phải là client component.
|
|
62
75
|
*/
|
|
63
|
-
declare function AppShell({ layout, showSidebar, headerProps, sidebarProps, mobileMenuProps, commandPaletteSlot, locale, className, contentClassName, children, ...providerProps }: AppShellProps): React.JSX.Element;
|
|
76
|
+
declare function AppShell({ layout, showSidebar, headerProps, sidebarProps, mobileMenuProps, commandPaletteSlot, locale, skipLink, mainId, className, contentClassName, children, ...providerProps }: AppShellProps): React.JSX.Element;
|
|
64
77
|
|
|
65
78
|
export { AppShell, type AppShellLayout, type AppShellProps };
|
package/dist/shell/app-shell.js
CHANGED
|
@@ -16,6 +16,8 @@ function AppShell({
|
|
|
16
16
|
mobileMenuProps,
|
|
17
17
|
commandPaletteSlot,
|
|
18
18
|
locale,
|
|
19
|
+
skipLink = true,
|
|
20
|
+
mainId = "main-content",
|
|
19
21
|
className,
|
|
20
22
|
contentClassName,
|
|
21
23
|
children,
|
|
@@ -30,6 +32,8 @@ function AppShell({
|
|
|
30
32
|
sidebarProps,
|
|
31
33
|
mobileMenuProps,
|
|
32
34
|
commandPaletteSlot,
|
|
35
|
+
skipLink,
|
|
36
|
+
mainId,
|
|
33
37
|
className,
|
|
34
38
|
contentClassName,
|
|
35
39
|
children
|
|
@@ -44,11 +48,13 @@ function AppShellFrame({
|
|
|
44
48
|
sidebarProps,
|
|
45
49
|
mobileMenuProps,
|
|
46
50
|
commandPaletteSlot,
|
|
51
|
+
skipLink = true,
|
|
52
|
+
mainId = "main-content",
|
|
47
53
|
className,
|
|
48
54
|
contentClassName,
|
|
49
55
|
children
|
|
50
56
|
}) {
|
|
51
|
-
const { currentApp } = useShell();
|
|
57
|
+
const { currentApp, labels } = useShell();
|
|
52
58
|
const headerFirst = layout === "header-first";
|
|
53
59
|
const header = /* @__PURE__ */ jsx(
|
|
54
60
|
AppHeader,
|
|
@@ -66,7 +72,15 @@ function AppShellFrame({
|
|
|
66
72
|
showCollapseButton: sidebarProps?.showCollapseButton ?? !headerFirst
|
|
67
73
|
}
|
|
68
74
|
) : null;
|
|
69
|
-
const main = /* @__PURE__ */ jsx(
|
|
75
|
+
const main = /* @__PURE__ */ jsx(
|
|
76
|
+
"main",
|
|
77
|
+
{
|
|
78
|
+
id: mainId,
|
|
79
|
+
tabIndex: -1,
|
|
80
|
+
className: cn("relative flex-1 overflow-y-auto bg-background outline-none", contentClassName),
|
|
81
|
+
children
|
|
82
|
+
}
|
|
83
|
+
);
|
|
70
84
|
return /* @__PURE__ */ jsxs(
|
|
71
85
|
"div",
|
|
72
86
|
{
|
|
@@ -77,6 +91,14 @@ function AppShellFrame({
|
|
|
77
91
|
className
|
|
78
92
|
),
|
|
79
93
|
children: [
|
|
94
|
+
skipLink ? /* @__PURE__ */ jsx(
|
|
95
|
+
"a",
|
|
96
|
+
{
|
|
97
|
+
href: `#${mainId}`,
|
|
98
|
+
className: "sr-only rounded-md bg-primary text-sm font-medium text-primary-foreground focus:not-sr-only focus:absolute focus:left-4 focus:top-4 focus:z-50 focus:px-4 focus:py-2 focus:outline-none focus:ring-2 focus:ring-ring/50",
|
|
99
|
+
children: labels.skipToContent
|
|
100
|
+
}
|
|
101
|
+
) : null,
|
|
80
102
|
headerFirst ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
81
103
|
header,
|
|
82
104
|
/* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1", children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/shell/app-shell.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport { ComitorLocaleProvider } from \"../i18n/locale-provider.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { AppHeader, type AppHeaderProps } from \"./app-header.js\";\nimport { MobileMenu, type MobileMenuProps } from \"./mobile-menu.js\";\nimport { ShellProvider, type ShellProviderProps, useShell } from \"./shell-context.js\";\nimport { Sidebar, type SidebarProps } from \"./sidebar.js\";\nimport { appAccentStyle } from \"./utils.js\";\nimport { WorkspaceSwitcher } from \"./workspace-switcher.js\";\n\nexport type AppShellLayout = \"sidebar-first\" | \"header-first\";\n\nexport interface AppShellProps extends ShellProviderProps {\n /**\n * \"sidebar-first\" (mặc định) — sidebar cao hết màn hình, header nằm bên phải nó\n * (WorkspaceSwitcher ở đỉnh sidebar).\n * \"header-first\" — header full width trên cùng, sidebar nằm dưới\n * (WorkspaceSwitcher chuyển lên header).\n */\n layout?: AppShellLayout;\n /** Ẩn sidebar hoàn toàn (app một khu, chỉ có header). */\n showSidebar?: boolean;\n headerProps?: AppHeaderProps;\n sidebarProps?: SidebarProps;\n mobileMenuProps?: MobileMenuProps;\n /**\n * Slot Command Palette — app tự render (dữ liệu tìm kiếm là của app),\n * đọc/ghi trạng thái qua `useShell().commandPaletteOpen`.\n */\n commandPaletteSlot?: ReactNode;\n /**\n * Ngôn ngữ của cả cây shell (mã BCP 47: `\"vi\"`, `\"en\"`, `\"en-GB\"`…) — TIỆN ÍCH, không phải chỗ\n * khuyên dùng.\n *\n * Chỗ đúng là `<ComitorLocaleProvider locale={…}>` ở ROOT layout: nó phủ cả những trang KHÔNG\n * nằm trong shell (đăng nhập, trang lỗi, trang công khai) và mọi component của gói đọc theo nó.\n * Prop này chỉ dành cho app không có root layout riêng để đặt provider.\n *\n * Có truyền → `AppShell` bọc cây của nó trong `ComitorLocaleProvider locale={locale}`. Bỏ trống →\n * không bọc gì, mọi thứ đọc provider gần nhất bên ngoài (không có thì tiếng Anh).\n *\n * ⚠ Provider dựng ở đây là provider MỚI: nó KHÔNG kế thừa `messages` (ghi đè chữ) hay\n * `dateFnsLocale` của provider bên ngoài. Cần những thứ đó thì đặt provider ở root layout.\n * ⚠ Đổi qua lại giữa có và không truyền prop này đổi hình dạng cây — cả shell dựng lại từ đầu\n * (mất trạng thái). Giữ nó luôn có hoặc luôn vắng.\n */\n locale?: string;\n className?: string;\n contentClassName?: string;\n}\n\n/**\n * Khung ứng dụng lắp sẵn: `ShellProvider` + `Sidebar` + `AppHeader` + `<main>` + `MobileMenu`.\n *\n * ⚠ Bọc app bằng `<ThemeProvider>` ở **root layout**, NGOÀI `<AppShell>` — next-themes\n * cần nằm trên cùng để tránh nháy theme lúc hydrate. `<ComitorLocaleProvider>` cũng nên ở đó\n * (ngôn ngữ của cả gói, kể cả trang ngoài shell); prop `locale` chỉ là lối tắt.\n *\n * Có `\"use client\"`: mọi callback (`onLogout`, `onWorkspaceChange`…) là hàm nên nơi\n * render `<AppShell>` phải là client component.\n */\nexport function AppShell({\n layout = \"sidebar-first\",\n showSidebar = true,\n headerProps,\n sidebarProps,\n mobileMenuProps,\n commandPaletteSlot,\n locale,\n className,\n contentClassName,\n children,\n ...providerProps\n}: AppShellProps) {\n const shell = (\n <ShellProvider {...providerProps}>\n <AppShellFrame\n layout={layout}\n showSidebar={showSidebar}\n headerProps={headerProps}\n sidebarProps={sidebarProps}\n mobileMenuProps={mobileMenuProps}\n commandPaletteSlot={commandPaletteSlot}\n className={className}\n contentClassName={contentClassName}\n >\n {children}\n </AppShellFrame>\n </ShellProvider>\n );\n\n // Provider ở NGOÀI `ShellProvider`: chính `ShellProvider` đọc namespace `shell` để dựng `labels`.\n return locale === undefined ? shell : <ComitorLocaleProvider locale={locale}>{shell}</ComitorLocaleProvider>;\n}\n\ntype AppShellFrameProps = Pick<\n AppShellProps,\n | \"layout\"\n | \"showSidebar\"\n | \"headerProps\"\n | \"sidebarProps\"\n | \"mobileMenuProps\"\n | \"commandPaletteSlot\"\n | \"className\"\n | \"contentClassName\"\n> & { children: ReactNode };\n\n/**\n * Phần khung thật sự — tách khỏi `AppShell` vì cần `useShell()` (phải ở TRONG provider)\n * để gán `--app-accent` của app đang mở cho cả cây.\n */\nfunction AppShellFrame({\n layout = \"sidebar-first\",\n showSidebar = true,\n headerProps,\n sidebarProps,\n mobileMenuProps,\n commandPaletteSlot,\n className,\n contentClassName,\n children\n}: AppShellFrameProps) {\n const { currentApp } = useShell();\n const headerFirst = layout === \"header-first\";\n\n // Ở header-first, bộ chuyển workspace chuyển lên header — nếu để cả hai chỗ\n // thì người dùng thấy hai nút giống hệt nhau.\n // Spread TRƯỚC rồi mới đặt giá trị mặc định, nếu không `{...headerProps}` sẽ ghi đè\n // bằng `undefined` và giá trị mặc định tính ở trên thành công cốc.\n const header = (\n <AppHeader\n {...headerProps}\n showSidebarToggle={headerProps?.showSidebarToggle ?? headerFirst}\n logo={headerProps?.logo ?? (headerFirst ? <WorkspaceSwitcher className=\"w-56 shrink-0\" /> : undefined)}\n />\n );\n\n const sidebar = showSidebar ? (\n <Sidebar\n {...sidebarProps}\n showWorkspaceSwitcher={sidebarProps?.showWorkspaceSwitcher ?? !headerFirst}\n showCollapseButton={sidebarProps?.showCollapseButton ?? !headerFirst}\n />\n ) : null;\n\n /*\n * ─ VÌ SAO <main> PHẢI CÓ `relative` ─\n *\n * `overflow-y-auto` KHÔNG cắt phần tử `position: absolute` nếu chính nó không được định vị:\n * containing block của những phần tử đó nhảy lên tới `body`/ICB, nên chúng nằm ngoài tầm cắt\n * của `main` và **kéo dài vùng cuộn của cả TÀI LIỆU**. Khung shell là `h-dvh overflow-hidden`\n * nên phần kéo dài đó không có gì để vẽ: người dùng cuộn xuống và thấy một khoảng TRẮNG lớn\n * dưới đáy trang.\n *\n * Không phải lỗi lý thuyết — hai nguồn sinh ra nó có mặt trong chính gói này:\n * • `sr-only` của Tailwind là `position: absolute` không có `top/left`, nên nó đứng ở vị trí\n * tĩnh của mình. Trong `TablePagination`, bốn nhãn ẩn (\"Trang đầu/trước/sau/cuối\") nằm\n * trong `<Button>` — mà `Button` không `relative`.\n * • Radix để `<input>`/`<select>` gốc ẩn bằng `position: absolute` (RadioGroup, Select).\n *\n * Đo trên trang `/cong-viec` trước khi vá: `documentElement.scrollHeight` = 1531 trong khi\n * `clientHeight` = 900 → 631px trắng. Trang `/bieu-mau`: 1792 / 900 → 892px. Trang ngắn hoặc\n * trang có các phần tử đó nằm TRÊN nếp gấp thì không lộ ra — đó là lý do lỗi trông như chỉ dính\n * vài trang.\n *\n * `relative` đưa containing block về đúng `main`, và `overflow-y-auto` cắt được như mong đợi.\n * ⚠ Đừng đổi sang `contain: paint`: nó cũng chữa được nhưng kéo theo containment về sơn/bố cục\n * mà không ai cần ở đây.\n */\n const main = (\n <main className={cn(\"relative flex-1 overflow-y-auto bg-background\", contentClassName)}>{children}</main>\n );\n\n return (\n <div\n style={appAccentStyle(currentApp)}\n className={cn(\n \"flex h-dvh w-full overflow-hidden bg-background\",\n headerFirst ? \"flex-col\" : \"flex-row\",\n className\n )}\n >\n {headerFirst ? (\n <>\n {header}\n <div className=\"flex min-h-0 flex-1\">\n {sidebar}\n {main}\n </div>\n </>\n ) : (\n <>\n {sidebar}\n <div className=\"flex min-w-0 flex-1 flex-col\">\n {header}\n {main}\n </div>\n </>\n )}\n\n <MobileMenu {...mobileMenuProps} />\n {commandPaletteSlot}\n </div>\n );\n}\n"],"mappings":";AA8EM,SA2GE,UA3GF,KA6GI,YA7GJ;AA3EN,SAAS,6BAA6B;AACtC,SAAS,UAAU;AACnB,SAAS,iBAAsC;AAC/C,SAAS,kBAAwC;AACjD,SAAS,eAAwC,gBAAgB;AACjE,SAAS,eAAkC;AAC3C,SAAS,sBAAsB;AAC/B,SAAS,yBAAyB;AAqD3B,SAAS,SAAS;AAAA,EACvB,SAAS;AAAA,EACT,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAkB;AAChB,QAAM,QACJ,oBAAC,iBAAe,GAAG,eACjB;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH,GACF;AAIF,SAAO,WAAW,SAAY,QAAQ,oBAAC,yBAAsB,QAAiB,iBAAM;AACtF;AAkBA,SAAS,cAAc;AAAA,EACrB,SAAS;AAAA,EACT,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuB;AACrB,QAAM,EAAE,WAAW,IAAI,SAAS;AAChC,QAAM,cAAc,WAAW;AAM/B,QAAM,SACJ;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,mBAAmB,aAAa,qBAAqB;AAAA,MACrD,MAAM,aAAa,SAAS,cAAc,oBAAC,qBAAkB,WAAU,iBAAgB,IAAK;AAAA;AAAA,EAC9F;AAGF,QAAM,UAAU,cACd;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,uBAAuB,cAAc,yBAAyB,CAAC;AAAA,MAC/D,oBAAoB,cAAc,sBAAsB,CAAC;AAAA;AAAA,EAC3D,IACE;AA0BJ,QAAM,OACJ,oBAAC,UAAK,WAAW,GAAG,iDAAiD,gBAAgB,GAAI,UAAS;AAGpG,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,eAAe,UAAU;AAAA,MAChC,WAAW;AAAA,QACT;AAAA,QACA,cAAc,aAAa;AAAA,QAC3B;AAAA,MACF;AAAA,MAEC;AAAA,sBACC,iCACG;AAAA;AAAA,UACD,qBAAC,SAAI,WAAU,uBACZ;AAAA;AAAA,YACA;AAAA,aACH;AAAA,WACF,IAEA,iCACG;AAAA;AAAA,UACD,qBAAC,SAAI,WAAU,gCACZ;AAAA;AAAA,YACA;AAAA,aACH;AAAA,WACF;AAAA,QAGF,oBAAC,cAAY,GAAG,iBAAiB;AAAA,QAChC;AAAA;AAAA;AAAA,EACH;AAEJ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/shell/app-shell.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport { ComitorLocaleProvider } from \"../i18n/locale-provider.js\";\nimport { cn } from \"../lib/cn.js\";\nimport { AppHeader, type AppHeaderProps } from \"./app-header.js\";\nimport { MobileMenu, type MobileMenuProps } from \"./mobile-menu.js\";\nimport { ShellProvider, type ShellProviderProps, useShell } from \"./shell-context.js\";\nimport { Sidebar, type SidebarProps } from \"./sidebar.js\";\nimport { appAccentStyle } from \"./utils.js\";\nimport { WorkspaceSwitcher } from \"./workspace-switcher.js\";\n\nexport type AppShellLayout = \"sidebar-first\" | \"header-first\";\n\nexport interface AppShellProps extends ShellProviderProps {\n /**\n * \"sidebar-first\" (mặc định) — sidebar cao hết màn hình, header nằm bên phải nó\n * (WorkspaceSwitcher ở đỉnh sidebar).\n * \"header-first\" — header full width trên cùng, sidebar nằm dưới\n * (WorkspaceSwitcher chuyển lên header).\n */\n layout?: AppShellLayout;\n /** Ẩn sidebar hoàn toàn (app một khu, chỉ có header). */\n showSidebar?: boolean;\n headerProps?: AppHeaderProps;\n sidebarProps?: SidebarProps;\n mobileMenuProps?: MobileMenuProps;\n /**\n * Slot Command Palette — app tự render (dữ liệu tìm kiếm là của app),\n * đọc/ghi trạng thái qua `useShell().commandPaletteOpen`.\n */\n commandPaletteSlot?: ReactNode;\n /**\n * Ngôn ngữ của cả cây shell (mã BCP 47: `\"vi\"`, `\"en\"`, `\"en-GB\"`…) — TIỆN ÍCH, không phải chỗ\n * khuyên dùng.\n *\n * Chỗ đúng là `<ComitorLocaleProvider locale={…}>` ở ROOT layout: nó phủ cả những trang KHÔNG\n * nằm trong shell (đăng nhập, trang lỗi, trang công khai) và mọi component của gói đọc theo nó.\n * Prop này chỉ dành cho app không có root layout riêng để đặt provider.\n *\n * Có truyền → `AppShell` bọc cây của nó trong `ComitorLocaleProvider locale={locale}`. Bỏ trống →\n * không bọc gì, mọi thứ đọc provider gần nhất bên ngoài (không có thì tiếng Anh).\n *\n * ⚠ Provider dựng ở đây là provider MỚI: nó KHÔNG kế thừa `messages` (ghi đè chữ) hay\n * `dateFnsLocale` của provider bên ngoài. Cần những thứ đó thì đặt provider ở root layout.\n * ⚠ Đổi qua lại giữa có và không truyền prop này đổi hình dạng cây — cả shell dựng lại từ đầu\n * (mất trạng thái). Giữ nó luôn có hoặc luôn vắng.\n */\n locale?: string;\n /**\n * Skip link đầu khung (mặc định `true`) — WCAG 2.4.1, mức A. Một khung có thanh bên bắt người dùng bàn\n * phím Tab qua toàn bộ điều hướng trước khi chạm nội dung; giải MỘT lần ở khung thì mọi app thừa hưởng.\n * Link vô hình (`sr-only`) cho tới khi nhận focus nên không tốn pixel nào của thiết kế. Chữ: khoá\n * `skipToContent` của namespace `shell`.\n */\n skipLink?: boolean;\n /**\n * `id` của `<main>` — đích của skip link (mặc định `\"main-content\"`). `<main>` mang `tabIndex={-1}` để\n * nhận được focus khi nhảy tới: không có nó, trình duyệt cuộn tới nhưng focus ở lại link, và Tab kế\n * tiếp quay về đầu thanh bên.\n */\n mainId?: string;\n className?: string;\n contentClassName?: string;\n}\n\n/**\n * Khung ứng dụng lắp sẵn: `ShellProvider` + `Sidebar` + `AppHeader` + `<main>` + `MobileMenu`.\n *\n * ⚠ Bọc app bằng `<ThemeProvider>` ở **root layout**, NGOÀI `<AppShell>` — next-themes\n * cần nằm trên cùng để tránh nháy theme lúc hydrate. `<ComitorLocaleProvider>` cũng nên ở đó\n * (ngôn ngữ của cả gói, kể cả trang ngoài shell); prop `locale` chỉ là lối tắt.\n *\n * Có `\"use client\"`: mọi callback (`onLogout`, `onWorkspaceChange`…) là hàm nên nơi\n * render `<AppShell>` phải là client component.\n */\nexport function AppShell({\n layout = \"sidebar-first\",\n showSidebar = true,\n headerProps,\n sidebarProps,\n mobileMenuProps,\n commandPaletteSlot,\n locale,\n skipLink = true,\n mainId = \"main-content\",\n className,\n contentClassName,\n children,\n ...providerProps\n}: AppShellProps) {\n const shell = (\n <ShellProvider {...providerProps}>\n <AppShellFrame\n layout={layout}\n showSidebar={showSidebar}\n headerProps={headerProps}\n sidebarProps={sidebarProps}\n mobileMenuProps={mobileMenuProps}\n commandPaletteSlot={commandPaletteSlot}\n skipLink={skipLink}\n mainId={mainId}\n className={className}\n contentClassName={contentClassName}\n >\n {children}\n </AppShellFrame>\n </ShellProvider>\n );\n\n // Provider ở NGOÀI `ShellProvider`: chính `ShellProvider` đọc namespace `shell` để dựng `labels`.\n return locale === undefined ? shell : <ComitorLocaleProvider locale={locale}>{shell}</ComitorLocaleProvider>;\n}\n\ntype AppShellFrameProps = Pick<\n AppShellProps,\n | \"layout\"\n | \"showSidebar\"\n | \"headerProps\"\n | \"sidebarProps\"\n | \"mobileMenuProps\"\n | \"commandPaletteSlot\"\n | \"skipLink\"\n | \"mainId\"\n | \"className\"\n | \"contentClassName\"\n> & { children: ReactNode };\n\n/**\n * Phần khung thật sự — tách khỏi `AppShell` vì cần `useShell()` (phải ở TRONG provider)\n * để gán `--app-accent` của app đang mở cho cả cây.\n */\nfunction AppShellFrame({\n layout = \"sidebar-first\",\n showSidebar = true,\n headerProps,\n sidebarProps,\n mobileMenuProps,\n commandPaletteSlot,\n skipLink = true,\n mainId = \"main-content\",\n className,\n contentClassName,\n children\n}: AppShellFrameProps) {\n const { currentApp, labels } = useShell();\n const headerFirst = layout === \"header-first\";\n\n // Ở header-first, bộ chuyển workspace chuyển lên header — nếu để cả hai chỗ\n // thì người dùng thấy hai nút giống hệt nhau.\n // Spread TRƯỚC rồi mới đặt giá trị mặc định, nếu không `{...headerProps}` sẽ ghi đè\n // bằng `undefined` và giá trị mặc định tính ở trên thành công cốc.\n const header = (\n <AppHeader\n {...headerProps}\n showSidebarToggle={headerProps?.showSidebarToggle ?? headerFirst}\n logo={headerProps?.logo ?? (headerFirst ? <WorkspaceSwitcher className=\"w-56 shrink-0\" /> : undefined)}\n />\n );\n\n const sidebar = showSidebar ? (\n <Sidebar\n {...sidebarProps}\n showWorkspaceSwitcher={sidebarProps?.showWorkspaceSwitcher ?? !headerFirst}\n showCollapseButton={sidebarProps?.showCollapseButton ?? !headerFirst}\n />\n ) : null;\n\n /*\n * ─ VÌ SAO <main> PHẢI CÓ `relative` ─\n *\n * `overflow-y-auto` KHÔNG cắt phần tử `position: absolute` nếu chính nó không được định vị:\n * containing block của những phần tử đó nhảy lên tới `body`/ICB, nên chúng nằm ngoài tầm cắt\n * của `main` và **kéo dài vùng cuộn của cả TÀI LIỆU**. Khung shell là `h-dvh overflow-hidden`\n * nên phần kéo dài đó không có gì để vẽ: người dùng cuộn xuống và thấy một khoảng TRẮNG lớn\n * dưới đáy trang.\n *\n * Không phải lỗi lý thuyết — hai nguồn sinh ra nó có mặt trong chính gói này:\n * • `sr-only` của Tailwind là `position: absolute` không có `top/left`, nên nó đứng ở vị trí\n * tĩnh của mình. Trong `TablePagination`, bốn nhãn ẩn (\"Trang đầu/trước/sau/cuối\") nằm\n * trong `<Button>` — mà `Button` không `relative`.\n * • Radix để `<input>`/`<select>` gốc ẩn bằng `position: absolute` (RadioGroup, Select).\n *\n * Đo trên trang `/cong-viec` trước khi vá: `documentElement.scrollHeight` = 1531 trong khi\n * `clientHeight` = 900 → 631px trắng. Trang `/bieu-mau`: 1792 / 900 → 892px. Trang ngắn hoặc\n * trang có các phần tử đó nằm TRÊN nếp gấp thì không lộ ra — đó là lý do lỗi trông như chỉ dính\n * vài trang.\n *\n * `relative` đưa containing block về đúng `main`, và `overflow-y-auto` cắt được như mong đợi.\n * ⚠ Đừng đổi sang `contain: paint`: nó cũng chữa được nhưng kéo theo containment về sơn/bố cục\n * mà không ai cần ở đây.\n */\n const main = (\n <main\n id={mainId}\n tabIndex={-1}\n className={cn(\"relative flex-1 overflow-y-auto bg-background outline-none\", contentClassName)}\n >\n {children}\n </main>\n );\n\n return (\n <div\n style={appAccentStyle(currentApp)}\n className={cn(\n \"flex h-dvh w-full overflow-hidden bg-background\",\n headerFirst ? \"flex-col\" : \"flex-row\",\n className\n )}\n >\n {skipLink ? (\n <a\n href={`#${mainId}`}\n /*\n * `focus:px-4 focus:py-2` chứ không `px-4 py-2` trần: `not-sr-only` của Tailwind đặt `padding: 0`, nên\n * đệm thường bị nó đè lúc nhận focus — link hiện ra cao 20px, chữ sát mép. Đo trên Comitor Tasks.\n */\n className=\"sr-only rounded-md bg-primary text-sm font-medium text-primary-foreground focus:not-sr-only focus:absolute focus:left-4 focus:top-4 focus:z-50 focus:px-4 focus:py-2 focus:outline-none focus:ring-2 focus:ring-ring/50\"\n >\n {labels.skipToContent}\n </a>\n ) : null}\n {headerFirst ? (\n <>\n {header}\n <div className=\"flex min-h-0 flex-1\">\n {sidebar}\n {main}\n </div>\n </>\n ) : (\n <>\n {sidebar}\n <div className=\"flex min-w-0 flex-1 flex-col\">\n {header}\n {main}\n </div>\n </>\n )}\n\n <MobileMenu {...mobileMenuProps} />\n {commandPaletteSlot}\n </div>\n );\n}\n"],"mappings":";AA6FM,SAmIE,UAnIF,KAqII,YArIJ;AA1FN,SAAS,6BAA6B;AACtC,SAAS,UAAU;AACnB,SAAS,iBAAsC;AAC/C,SAAS,kBAAwC;AACjD,SAAS,eAAwC,gBAAgB;AACjE,SAAS,eAAkC;AAC3C,SAAS,sBAAsB;AAC/B,SAAS,yBAAyB;AAkE3B,SAAS,SAAS;AAAA,EACvB,SAAS;AAAA,EACT,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAkB;AAChB,QAAM,QACJ,oBAAC,iBAAe,GAAG,eACjB;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEC;AAAA;AAAA,EACH,GACF;AAIF,SAAO,WAAW,SAAY,QAAQ,oBAAC,yBAAsB,QAAiB,iBAAM;AACtF;AAoBA,SAAS,cAAc;AAAA,EACrB,SAAS;AAAA,EACT,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AACF,GAAuB;AACrB,QAAM,EAAE,YAAY,OAAO,IAAI,SAAS;AACxC,QAAM,cAAc,WAAW;AAM/B,QAAM,SACJ;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,mBAAmB,aAAa,qBAAqB;AAAA,MACrD,MAAM,aAAa,SAAS,cAAc,oBAAC,qBAAkB,WAAU,iBAAgB,IAAK;AAAA;AAAA,EAC9F;AAGF,QAAM,UAAU,cACd;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,uBAAuB,cAAc,yBAAyB,CAAC;AAAA,MAC/D,oBAAoB,cAAc,sBAAsB,CAAC;AAAA;AAAA,EAC3D,IACE;AA0BJ,QAAM,OACJ;AAAA,IAAC;AAAA;AAAA,MACC,IAAI;AAAA,MACJ,UAAU;AAAA,MACV,WAAW,GAAG,8DAA8D,gBAAgB;AAAA,MAE3F;AAAA;AAAA,EACH;AAGF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,eAAe,UAAU;AAAA,MAChC,WAAW;AAAA,QACT;AAAA,QACA,cAAc,aAAa;AAAA,QAC3B;AAAA,MACF;AAAA,MAEC;AAAA,mBACC;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,IAAI,MAAM;AAAA,YAKhB,WAAU;AAAA,YAET,iBAAO;AAAA;AAAA,QACV,IACE;AAAA,QACH,cACC,iCACG;AAAA;AAAA,UACD,qBAAC,SAAI,WAAU,uBACZ;AAAA;AAAA,YACA;AAAA,aACH;AAAA,WACF,IAEA,iCACG;AAAA;AAAA,UACD,qBAAC,SAAI,WAAU,gCACZ;AAAA;AAAA,YACA;AAAA,aACH;AAAA,WACF;AAAA,QAGF,oBAAC,cAAY,GAAG,iBAAiB;AAAA,QAChC;AAAA;AAAA;AAAA,EACH;AAEJ;","names":[]}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ContrastMode } from './contrast-constants.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Gieo MẶC ĐỊNH của bốn trục hiển thị (thường là tuỳ chọn trong hồ sơ tài khoản) vào `localStorage`,
|
|
6
|
+
* **trước lượt sơn đầu tiên** — để bốn script chống nháy của gói đọc ra đúng giá trị ngay khung hình đầu.
|
|
7
|
+
*
|
|
8
|
+
* ── VÌ SAO KHÔNG PHẢI PROP `defaultValue` CỦA PROVIDER ─────────────────────────────────────────────
|
|
9
|
+
* Script chống nháy của mỗi provider chỉ đọc `localStorage` và so với HẰNG mặc định của gói; prop
|
|
10
|
+
* `defaultValue`/`defaultContrast` chỉ nuôi `useState` + một `useEffect`, tức tới SAU lượt sơn. Truyền
|
|
11
|
+
* mặc định của tài khoản qua prop = nháy giao diện, tệ nhất ở hai trục trợ năng (tương phản, cỡ chữ).
|
|
12
|
+
*
|
|
13
|
+
* ── LUẬT GIEO: ĐI THEO TÀI KHOẢN, TRỪ KHI ĐÃ TỰ ĐỔI TRÊN THIẾT BỊ NÀY ───────────────────────────────
|
|
14
|
+
* Cạnh mỗi khoá có một khoá DẤU (`<khoá>-seeded`) giữ giá trị đã gieo lần trước:
|
|
15
|
+
* · chưa có giá trị → gieo;
|
|
16
|
+
* · tài khoản đổi, giá trị tại chỗ vẫn bằng dấu cũ → gieo (người dùng chưa từng đè lên);
|
|
17
|
+
* · giá trị tại chỗ KHÁC dấu → GIỮ — họ đã tự chọn trên máy này.
|
|
18
|
+
* Dấu luôn được cập nhật, kể cả ở nhánh thứ ba — không thì lần đổi bị bỏ qua bị hỏi lại mãi.
|
|
19
|
+
* Phép so phải nằm TRONG script: giá trị đang có hiệu lực nằm ở `localStorage`, máy chủ không đọc được.
|
|
20
|
+
*
|
|
21
|
+
* ── ⚠ BỀ MẶT TẤN CÔNG, VÀ NÓ ĐƯỢC ĐÓNG THẾ NÀO ──────────────────────────────────────────────────────
|
|
22
|
+
* Script mang `nonce` = trình duyệt tin TUYỆT ĐỐI. Giá trị gieo thường đến từ cookie (client sửa được),
|
|
23
|
+
* nên component này KHÔNG tin đầu vào: mỗi giá trị được đối chiếu với tập ĐÓNG của gói và thứ đi vào
|
|
24
|
+
* chuỗi script là PHẦN TỬ CỦA MẢNG HẰNG, không phải chuỗi được truyền vào. Khoá `localStorage` cũng là
|
|
25
|
+
* hằng (không có prop `storageKey`). App không phải tự lọc — nhưng lọc thêm thì vô hại.
|
|
26
|
+
*
|
|
27
|
+
* Đặt: con ĐẦU TIÊN của `<body>`, TRÊN `ThemeProvider` và ba provider kia — thứ tự trong tài liệu là
|
|
28
|
+
* thứ tự chạy của script đồng bộ. Không có gì để gieo thì không render gì (một `<script>` rỗng vẫn là
|
|
29
|
+
* một script CSP phải duyệt).
|
|
30
|
+
*
|
|
31
|
+
* Không directive: render được thẳng ở root layout (Server Component), không tốn một đảo client.
|
|
32
|
+
*/
|
|
33
|
+
/** Tập giá trị hợp lệ của từng trục — `theme` khớp `ThemeProvider` (next-themes, `enableSystem`). */
|
|
34
|
+
declare const DISPLAY_PREF_VALUES: {
|
|
35
|
+
readonly theme: readonly ["light", "dark", "system"];
|
|
36
|
+
readonly contrast: readonly ContrastMode[];
|
|
37
|
+
readonly density: readonly ["comfortable", "compact"];
|
|
38
|
+
readonly fontSize: readonly ["sm", "md", "lg"];
|
|
39
|
+
};
|
|
40
|
+
type DisplayPrefKey = keyof typeof DISPLAY_PREF_VALUES;
|
|
41
|
+
/** Mặc định cần gieo — trục nào không có thì không đụng tới. */
|
|
42
|
+
type DisplayPrefsSeed = {
|
|
43
|
+
[K in DisplayPrefKey]?: (typeof DISPLAY_PREF_VALUES)[K][number];
|
|
44
|
+
};
|
|
45
|
+
/** Khoá `localStorage` của từng trục — đúng khoá mà provider của gói đọc. */
|
|
46
|
+
declare const DISPLAY_PREF_STORAGE_KEYS: Record<DisplayPrefKey, string>;
|
|
47
|
+
/**
|
|
48
|
+
* Lọc một giá trị BẤT KỲ (JSON từ cookie, hồ sơ tài khoản…) về `DisplayPrefsSeed`: chỉ khoá có thật, chỉ
|
|
49
|
+
* giá trị nằm trong tập đóng, và giá trị trả về là phần tử của mảng hằng. Không bao giờ ném.
|
|
50
|
+
*/
|
|
51
|
+
declare function parseDisplayPrefsSeed(raw: unknown): DisplayPrefsSeed;
|
|
52
|
+
interface DisplayPrefsSeedScriptProps {
|
|
53
|
+
/**
|
|
54
|
+
* Mặc định của tài khoản. Kiểu RỘNG (chuỗi bất kỳ) có chủ ý: component LỌC LẠI bên trong — xem "Bề mặt
|
|
55
|
+
* tấn công" ở đầu file — nên app truyền thẳng được giá trị đọc từ cookie mà không phải ép kiểu.
|
|
56
|
+
*/
|
|
57
|
+
seed: Readonly<Partial<Record<DisplayPrefKey, string | null>>> | null | undefined;
|
|
58
|
+
/** Nonce của CSP (cùng giá trị truyền cho bốn provider). */
|
|
59
|
+
nonce?: string;
|
|
60
|
+
}
|
|
61
|
+
/** Script gieo — xem chú thích đầu file. */
|
|
62
|
+
declare function DisplayPrefsSeedScript({ seed, nonce }: DisplayPrefsSeedScriptProps): React.JSX.Element | null;
|
|
63
|
+
|
|
64
|
+
export { DISPLAY_PREF_STORAGE_KEYS, DISPLAY_PREF_VALUES, type DisplayPrefKey, type DisplayPrefsSeed, DisplayPrefsSeedScript, type DisplayPrefsSeedScriptProps, parseDisplayPrefsSeed };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { CONTRAST_MODES, CONTRAST_STORAGE_KEY } from "./contrast-constants.js";
|
|
3
|
+
import {
|
|
4
|
+
DENSITY_MODES,
|
|
5
|
+
DENSITY_STORAGE_KEY,
|
|
6
|
+
FONT_SIZE_MODES,
|
|
7
|
+
FONT_SIZE_STORAGE_KEY
|
|
8
|
+
} from "./display-axis-constants.js";
|
|
9
|
+
const DISPLAY_PREF_VALUES = {
|
|
10
|
+
theme: ["light", "dark", "system"],
|
|
11
|
+
contrast: CONTRAST_MODES,
|
|
12
|
+
density: DENSITY_MODES,
|
|
13
|
+
fontSize: FONT_SIZE_MODES
|
|
14
|
+
};
|
|
15
|
+
const DISPLAY_PREF_STORAGE_KEYS = {
|
|
16
|
+
theme: "comitor-theme",
|
|
17
|
+
contrast: CONTRAST_STORAGE_KEY,
|
|
18
|
+
density: DENSITY_STORAGE_KEY,
|
|
19
|
+
fontSize: FONT_SIZE_STORAGE_KEY
|
|
20
|
+
};
|
|
21
|
+
const DISPLAY_PREF_KEYS = Object.keys(DISPLAY_PREF_VALUES);
|
|
22
|
+
function parseDisplayPrefsSeed(raw) {
|
|
23
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return {};
|
|
24
|
+
const input = raw;
|
|
25
|
+
const out = {};
|
|
26
|
+
for (const key of DISPLAY_PREF_KEYS) {
|
|
27
|
+
if (!Object.hasOwn(input, key)) continue;
|
|
28
|
+
const value = input[key];
|
|
29
|
+
const allowed = DISPLAY_PREF_VALUES[key].find((candidate) => candidate === value);
|
|
30
|
+
if (allowed) out[key] = allowed;
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
function DisplayPrefsSeedScript({ seed, nonce }) {
|
|
35
|
+
const clean = parseDisplayPrefsSeed(seed);
|
|
36
|
+
const entries = {};
|
|
37
|
+
for (const key of DISPLAY_PREF_KEYS) {
|
|
38
|
+
const value = clean[key];
|
|
39
|
+
if (value) entries[DISPLAY_PREF_STORAGE_KEYS[key]] = value;
|
|
40
|
+
}
|
|
41
|
+
if (Object.keys(entries).length === 0) return null;
|
|
42
|
+
const script = `(function(){try{var s=${JSON.stringify(entries)},k,c,m;for(k in s){m=k+"-seeded";c=localStorage.getItem(k);if(c===null||c===localStorage.getItem(m)){if(c!==s[k])localStorage.setItem(k,s[k]);}localStorage.setItem(m,s[k]);}}catch(e){}})();`;
|
|
43
|
+
return /* @__PURE__ */ jsx(
|
|
44
|
+
"script",
|
|
45
|
+
{
|
|
46
|
+
suppressHydrationWarning: true,
|
|
47
|
+
nonce,
|
|
48
|
+
dangerouslySetInnerHTML: { __html: script }
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
DISPLAY_PREF_STORAGE_KEYS,
|
|
54
|
+
DISPLAY_PREF_VALUES,
|
|
55
|
+
DisplayPrefsSeedScript,
|
|
56
|
+
parseDisplayPrefsSeed
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=display-prefs-seed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/shell/display-prefs-seed.tsx"],"sourcesContent":["import { CONTRAST_MODES, CONTRAST_STORAGE_KEY } from \"./contrast-constants.js\";\nimport {\n DENSITY_MODES,\n DENSITY_STORAGE_KEY,\n FONT_SIZE_MODES,\n FONT_SIZE_STORAGE_KEY\n} from \"./display-axis-constants.js\";\n\n/**\n * Gieo MẶC ĐỊNH của bốn trục hiển thị (thường là tuỳ chọn trong hồ sơ tài khoản) vào `localStorage`,\n * **trước lượt sơn đầu tiên** — để bốn script chống nháy của gói đọc ra đúng giá trị ngay khung hình đầu.\n *\n * ── VÌ SAO KHÔNG PHẢI PROP `defaultValue` CỦA PROVIDER ─────────────────────────────────────────────\n * Script chống nháy của mỗi provider chỉ đọc `localStorage` và so với HẰNG mặc định của gói; prop\n * `defaultValue`/`defaultContrast` chỉ nuôi `useState` + một `useEffect`, tức tới SAU lượt sơn. Truyền\n * mặc định của tài khoản qua prop = nháy giao diện, tệ nhất ở hai trục trợ năng (tương phản, cỡ chữ).\n *\n * ── LUẬT GIEO: ĐI THEO TÀI KHOẢN, TRỪ KHI ĐÃ TỰ ĐỔI TRÊN THIẾT BỊ NÀY ───────────────────────────────\n * Cạnh mỗi khoá có một khoá DẤU (`<khoá>-seeded`) giữ giá trị đã gieo lần trước:\n * · chưa có giá trị → gieo;\n * · tài khoản đổi, giá trị tại chỗ vẫn bằng dấu cũ → gieo (người dùng chưa từng đè lên);\n * · giá trị tại chỗ KHÁC dấu → GIỮ — họ đã tự chọn trên máy này.\n * Dấu luôn được cập nhật, kể cả ở nhánh thứ ba — không thì lần đổi bị bỏ qua bị hỏi lại mãi.\n * Phép so phải nằm TRONG script: giá trị đang có hiệu lực nằm ở `localStorage`, máy chủ không đọc được.\n *\n * ── ⚠ BỀ MẶT TẤN CÔNG, VÀ NÓ ĐƯỢC ĐÓNG THẾ NÀO ──────────────────────────────────────────────────────\n * Script mang `nonce` = trình duyệt tin TUYỆT ĐỐI. Giá trị gieo thường đến từ cookie (client sửa được),\n * nên component này KHÔNG tin đầu vào: mỗi giá trị được đối chiếu với tập ĐÓNG của gói và thứ đi vào\n * chuỗi script là PHẦN TỬ CỦA MẢNG HẰNG, không phải chuỗi được truyền vào. Khoá `localStorage` cũng là\n * hằng (không có prop `storageKey`). App không phải tự lọc — nhưng lọc thêm thì vô hại.\n *\n * Đặt: con ĐẦU TIÊN của `<body>`, TRÊN `ThemeProvider` và ba provider kia — thứ tự trong tài liệu là\n * thứ tự chạy của script đồng bộ. Không có gì để gieo thì không render gì (một `<script>` rỗng vẫn là\n * một script CSP phải duyệt).\n *\n * Không directive: render được thẳng ở root layout (Server Component), không tốn một đảo client.\n */\n\n/** Tập giá trị hợp lệ của từng trục — `theme` khớp `ThemeProvider` (next-themes, `enableSystem`). */\nexport const DISPLAY_PREF_VALUES = {\n theme: [\"light\", \"dark\", \"system\"],\n contrast: CONTRAST_MODES,\n density: DENSITY_MODES,\n fontSize: FONT_SIZE_MODES\n} as const;\n\nexport type DisplayPrefKey = keyof typeof DISPLAY_PREF_VALUES;\n\n/** Mặc định cần gieo — trục nào không có thì không đụng tới. */\nexport type DisplayPrefsSeed = { [K in DisplayPrefKey]?: (typeof DISPLAY_PREF_VALUES)[K][number] };\n\n/** Khoá `localStorage` của từng trục — đúng khoá mà provider của gói đọc. */\nexport const DISPLAY_PREF_STORAGE_KEYS: Record<DisplayPrefKey, string> = {\n theme: \"comitor-theme\",\n contrast: CONTRAST_STORAGE_KEY,\n density: DENSITY_STORAGE_KEY,\n fontSize: FONT_SIZE_STORAGE_KEY\n};\n\nconst DISPLAY_PREF_KEYS = Object.keys(DISPLAY_PREF_VALUES) as DisplayPrefKey[];\n\n/**\n * Lọc một giá trị BẤT KỲ (JSON từ cookie, hồ sơ tài khoản…) về `DisplayPrefsSeed`: chỉ khoá có thật, chỉ\n * giá trị nằm trong tập đóng, và giá trị trả về là phần tử của mảng hằng. Không bao giờ ném.\n */\nexport function parseDisplayPrefsSeed(raw: unknown): DisplayPrefsSeed {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) return {};\n const input = raw as Record<string, unknown>;\n const out: Record<string, string> = {};\n for (const key of DISPLAY_PREF_KEYS) {\n if (!Object.hasOwn(input, key)) continue;\n const value = input[key];\n const allowed = (DISPLAY_PREF_VALUES[key] as readonly string[]).find((candidate) => candidate === value);\n if (allowed) out[key] = allowed;\n }\n return out as DisplayPrefsSeed;\n}\n\nexport interface DisplayPrefsSeedScriptProps {\n /**\n * Mặc định của tài khoản. Kiểu RỘNG (chuỗi bất kỳ) có chủ ý: component LỌC LẠI bên trong — xem \"Bề mặt\n * tấn công\" ở đầu file — nên app truyền thẳng được giá trị đọc từ cookie mà không phải ép kiểu.\n */\n seed: Readonly<Partial<Record<DisplayPrefKey, string | null>>> | null | undefined;\n /** Nonce của CSP (cùng giá trị truyền cho bốn provider). */\n nonce?: string;\n}\n\n/** Script gieo — xem chú thích đầu file. */\nexport function DisplayPrefsSeedScript({ seed, nonce }: DisplayPrefsSeedScriptProps) {\n const clean = parseDisplayPrefsSeed(seed);\n const entries: Record<string, string> = {};\n for (const key of DISPLAY_PREF_KEYS) {\n const value = clean[key];\n if (value) entries[DISPLAY_PREF_STORAGE_KEYS[key]] = value;\n }\n if (Object.keys(entries).length === 0) return null;\n\n /*\n * `JSON.stringify` chỉ để dựng cú pháp object — cả khoá lẫn giá trị đã là hằng của gói. `try/catch` bọc\n * TẤT CẢ: `localStorage` NÉM ở chế độ riêng tư / khi trang bị chặn dữ liệu, và một ngoại lệ ở script\n * đồng bộ đầu `<body>` chặn mọi script sau nó — kể cả bốn script chống nháy.\n */\n const script =\n `(function(){try{var s=${JSON.stringify(entries)},k,c,m;` +\n `for(k in s){m=k+\"-seeded\";c=localStorage.getItem(k);` +\n `if(c===null||c===localStorage.getItem(m)){if(c!==s[k])localStorage.setItem(k,s[k]);}` +\n `localStorage.setItem(m,s[k]);}` +\n `}catch(e){}})();`;\n\n return (\n <script\n suppressHydrationWarning\n nonce={nonce}\n // biome-ignore lint/security/noDangerouslySetInnerHtml: script chống nháy phải nội tuyến + đồng bộ; nội dung chỉ gồm hằng của gói (đã lọc qua tập đóng).\n dangerouslySetInnerHTML={{ __html: script }}\n />\n );\n}\n"],"mappings":"AA+GI;AA/GJ,SAAS,gBAAgB,4BAA4B;AACrD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAiCA,MAAM,sBAAsB;AAAA,EACjC,OAAO,CAAC,SAAS,QAAQ,QAAQ;AAAA,EACjC,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AACZ;AAQO,MAAM,4BAA4D;AAAA,EACvE,OAAO;AAAA,EACP,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AACZ;AAEA,MAAM,oBAAoB,OAAO,KAAK,mBAAmB;AAMlD,SAAS,sBAAsB,KAAgC;AACpE,MAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,MAAM,QAAQ,GAAG,EAAG,QAAO,CAAC;AAC3E,QAAM,QAAQ;AACd,QAAM,MAA8B,CAAC;AACrC,aAAW,OAAO,mBAAmB;AACnC,QAAI,CAAC,OAAO,OAAO,OAAO,GAAG,EAAG;AAChC,UAAM,QAAQ,MAAM,GAAG;AACvB,UAAM,UAAW,oBAAoB,GAAG,EAAwB,KAAK,CAAC,cAAc,cAAc,KAAK;AACvG,QAAI,QAAS,KAAI,GAAG,IAAI;AAAA,EAC1B;AACA,SAAO;AACT;AAaO,SAAS,uBAAuB,EAAE,MAAM,MAAM,GAAgC;AACnF,QAAM,QAAQ,sBAAsB,IAAI;AACxC,QAAM,UAAkC,CAAC;AACzC,aAAW,OAAO,mBAAmB;AACnC,UAAM,QAAQ,MAAM,GAAG;AACvB,QAAI,MAAO,SAAQ,0BAA0B,GAAG,CAAC,IAAI;AAAA,EACvD;AACA,MAAI,OAAO,KAAK,OAAO,EAAE,WAAW,EAAG,QAAO;AAO9C,QAAM,SACJ,yBAAyB,KAAK,UAAU,OAAO,CAAC;AAMlD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,0BAAwB;AAAA,MACxB;AAAA,MAEA,yBAAyB,EAAE,QAAQ,OAAO;AAAA;AAAA,EAC5C;AAEJ;","names":[]}
|
package/dist/shell/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export { ContrastToggle, ContrastToggleProps } from './contrast-toggle.js';
|
|
|
10
10
|
export { DEFAULT_DENSITY, DEFAULT_FONT_SIZE, DENSITY_ATTRIBUTE, DENSITY_MODES, DENSITY_STORAGE_KEY, DensityMode, FONT_SIZE_ATTRIBUTE, FONT_SIZE_MODES, FONT_SIZE_STORAGE_KEY, FontSizeMode, isDensityMode, isFontSizeMode } from './display-axis-constants.js';
|
|
11
11
|
export { DensityToggle, DensityToggleProps, FontSizeControl, FontSizeControlProps } from './display-axis-controls.js';
|
|
12
12
|
export { DensityProvider, DensityScript, DisplayAxisValue, FontSizeProvider, FontSizeScript, useDensity, useFontSize } from './display-axis-provider.js';
|
|
13
|
+
export { DISPLAY_PREF_STORAGE_KEYS, DISPLAY_PREF_VALUES, DisplayPrefKey, DisplayPrefsSeed, DisplayPrefsSeedScript, DisplayPrefsSeedScriptProps, parseDisplayPrefsSeed } from './display-prefs-seed.js';
|
|
13
14
|
export { MobileMenu, MobileMenuProps } from './mobile-menu.js';
|
|
14
15
|
export { NotificationsButton, NotificationsButtonProps } from './notifications-button.js';
|
|
15
16
|
export { ShellContextValue, ShellProvider, ShellProviderProps, useShell } from './shell-context.js';
|
package/dist/shell/index.js
CHANGED
|
@@ -10,6 +10,7 @@ export * from "./contrast-toggle.js";
|
|
|
10
10
|
export * from "./display-axis-constants.js";
|
|
11
11
|
export * from "./display-axis-controls.js";
|
|
12
12
|
export * from "./display-axis-provider.js";
|
|
13
|
+
export * from "./display-prefs-seed.js";
|
|
13
14
|
export * from "./mobile-menu.js";
|
|
14
15
|
export * from "./notifications-button.js";
|
|
15
16
|
export * from "./shell-context.js";
|
package/dist/shell/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/shell/index.ts"],"sourcesContent":["/**\n * Entry \"@comitor/ui/shell\" — Tier 3: khung ứng dụng (AppShell, Sidebar, AppHeader,\n * WorkspaceSwitcher, AppLauncher, UserMenu, ThemeProvider…).\n *\n * Tách khỏi entry chính vì tầng này kéo theo `next/navigation` và `next-themes` — hai\n * peer OPTIONAL. App không chạy trên Next thì đừng import entry này (hoặc tự cấp\n * `ShellLinkComponent` riêng qua `ShellProvider`).\n *\n * Toàn bộ file ở đây là client component: có state, có routing, có phím tắt.\n */\n\n/**\n * Toaster bám theo next-themes — về tier thì nó là primitive (`components/ui/sonner.tsx`),\n * nhưng đặt cửa ra ở entry shell vì nó gọi `useTheme()`, mà `next-themes` chỉ là peer\n * OPTIONAL: để ở entry chính là ép mọi app phải cài next-themes.\n * Dùng chung với `ThemeProvider` ở trên. Nếu app KHÔNG dùng next-themes thì lấy composite\n * `Toaster` ở \"@comitor/ui\" và tự truyền prop `theme`.\n */\nexport { SonnerToaster, type SonnerToasterProps } from \"../components/ui/sonner.js\";\nexport * from \"./app-header.js\";\nexport * from \"./app-launcher.js\";\nexport * from \"./app-shell.js\";\nexport * from \"./comitor-lockup.js\";\nexport * from \"./comitor-logo.js\";\n/**\n * Hằng của trục tương phản xuất THẲNG từ module thuần — root layout là Server Component và nó\n * đọc CONTRAST_STORAGE_KEY. Đi vòng qua contrast-provider.tsx (\"use client\") là hằng thành proxy\n * và ra `undefined` mà không có lỗi nào.\n */\nexport * from \"./contrast-constants.js\";\nexport * from \"./contrast-provider.js\";\nexport * from \"./contrast-toggle.js\";\n/* Cùng lý do như trên — hằng của trục MẬT ĐỘ và CỠ CHỮ xuất thẳng từ module thuần, TRƯỚC provider. */\nexport * from \"./display-axis-constants.js\";\nexport * from \"./display-axis-controls.js\";\nexport * from \"./display-axis-provider.js\";\nexport * from \"./mobile-menu.js\";\nexport * from \"./notifications-button.js\";\nexport * from \"./shell-context.js\";\nexport * from \"./shell-link.js\";\nexport * from \"./sidebar.js\";\nexport * from \"./sidebar-group.js\";\nexport * from \"./sidebar-menu-item.js\";\nexport * from \"./theme-provider.js\";\nexport * from \"./theme-toggle.js\";\nexport * from \"./types.js\";\nexport * from \"./user-menu.js\";\nexport * from \"./utils.js\";\nexport * from \"./workspace-switcher.js\";\n"],"mappings":"AAkBA,SAAS,qBAA8C;AACvD,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAMd,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;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/shell/index.ts"],"sourcesContent":["/**\n * Entry \"@comitor/ui/shell\" — Tier 3: khung ứng dụng (AppShell, Sidebar, AppHeader,\n * WorkspaceSwitcher, AppLauncher, UserMenu, ThemeProvider…).\n *\n * Tách khỏi entry chính vì tầng này kéo theo `next/navigation` và `next-themes` — hai\n * peer OPTIONAL. App không chạy trên Next thì đừng import entry này (hoặc tự cấp\n * `ShellLinkComponent` riêng qua `ShellProvider`).\n *\n * Toàn bộ file ở đây là client component: có state, có routing, có phím tắt.\n */\n\n/**\n * Toaster bám theo next-themes — về tier thì nó là primitive (`components/ui/sonner.tsx`),\n * nhưng đặt cửa ra ở entry shell vì nó gọi `useTheme()`, mà `next-themes` chỉ là peer\n * OPTIONAL: để ở entry chính là ép mọi app phải cài next-themes.\n * Dùng chung với `ThemeProvider` ở trên. Nếu app KHÔNG dùng next-themes thì lấy composite\n * `Toaster` ở \"@comitor/ui\" và tự truyền prop `theme`.\n */\nexport { SonnerToaster, type SonnerToasterProps } from \"../components/ui/sonner.js\";\nexport * from \"./app-header.js\";\nexport * from \"./app-launcher.js\";\nexport * from \"./app-shell.js\";\nexport * from \"./comitor-lockup.js\";\nexport * from \"./comitor-logo.js\";\n/**\n * Hằng của trục tương phản xuất THẲNG từ module thuần — root layout là Server Component và nó\n * đọc CONTRAST_STORAGE_KEY. Đi vòng qua contrast-provider.tsx (\"use client\") là hằng thành proxy\n * và ra `undefined` mà không có lỗi nào.\n */\nexport * from \"./contrast-constants.js\";\nexport * from \"./contrast-provider.js\";\nexport * from \"./contrast-toggle.js\";\n/* Cùng lý do như trên — hằng của trục MẬT ĐỘ và CỠ CHỮ xuất thẳng từ module thuần, TRƯỚC provider. */\nexport * from \"./display-axis-constants.js\";\nexport * from \"./display-axis-controls.js\";\nexport * from \"./display-axis-provider.js\";\nexport * from \"./display-prefs-seed.js\";\nexport * from \"./mobile-menu.js\";\nexport * from \"./notifications-button.js\";\nexport * from \"./shell-context.js\";\nexport * from \"./shell-link.js\";\nexport * from \"./sidebar.js\";\nexport * from \"./sidebar-group.js\";\nexport * from \"./sidebar-menu-item.js\";\nexport * from \"./theme-provider.js\";\nexport * from \"./theme-toggle.js\";\nexport * from \"./types.js\";\nexport * from \"./user-menu.js\";\nexport * from \"./utils.js\";\nexport * from \"./workspace-switcher.js\";\n"],"mappings":"AAkBA,SAAS,qBAA8C;AACvD,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAMd,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;","names":[]}
|