@comitor/ui 2.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -24
- package/dist/chart/chart.d.ts +6 -1
- package/dist/chart/chart.js +3 -1
- package/dist/chart/chart.js.map +1 -1
- package/dist/chart/comitor-chart.d.ts +4 -1
- package/dist/chart/comitor-chart.js +3 -1
- package/dist/chart/comitor-chart.js.map +1 -1
- package/dist/components/composite/avatar-group.d.ts +9 -6
- package/dist/components/composite/avatar-group.js +6 -2
- package/dist/components/composite/avatar-group.js.map +1 -1
- package/dist/components/composite/combobox.d.ts +11 -11
- package/dist/components/composite/combobox.js +25 -11
- package/dist/components/composite/combobox.js.map +1 -1
- package/dist/components/composite/command-palette-constants.d.ts +15 -5
- package/dist/components/composite/command-palette-constants.js +3 -2
- package/dist/components/composite/command-palette-constants.js.map +1 -1
- package/dist/components/composite/command-palette.d.ts +2 -2
- package/dist/components/composite/command-palette.js +8 -5
- package/dist/components/composite/command-palette.js.map +1 -1
- package/dist/components/composite/confirm-dialog.d.ts +8 -8
- package/dist/components/composite/confirm-dialog.js +8 -3
- package/dist/components/composite/confirm-dialog.js.map +1 -1
- package/dist/components/composite/copy-button.d.ts +7 -3
- package/dist/components/composite/copy-button.js +7 -3
- package/dist/components/composite/copy-button.js.map +1 -1
- package/dist/components/composite/data-table-constants.d.ts +7 -3
- package/dist/components/composite/data-table-constants.js +2 -9
- package/dist/components/composite/data-table-constants.js.map +1 -1
- package/dist/components/composite/data-table.js +3 -3
- package/dist/components/composite/data-table.js.map +1 -1
- package/dist/components/composite/date-picker-constants.d.ts +32 -9
- package/dist/components/composite/date-picker-constants.js +16 -11
- package/dist/components/composite/date-picker-constants.js.map +1 -1
- package/dist/components/composite/date-picker.d.ts +19 -10
- package/dist/components/composite/date-picker.js +33 -9
- package/dist/components/composite/date-picker.js.map +1 -1
- package/dist/components/composite/filter-chips.d.ts +4 -3
- package/dist/components/composite/filter-chips.js +6 -2
- package/dist/components/composite/filter-chips.js.map +1 -1
- package/dist/components/composite/inline-edit.d.ts +14 -3
- package/dist/components/composite/inline-edit.js +8 -4
- package/dist/components/composite/inline-edit.js.map +1 -1
- package/dist/components/composite/relative-time.d.ts +4 -4
- package/dist/components/composite/relative-time.js +4 -2
- package/dist/components/composite/relative-time.js.map +1 -1
- package/dist/components/composite/route-tabs-nav.d.ts +9 -0
- package/dist/components/composite/route-tabs-nav.js +11 -0
- package/dist/components/composite/route-tabs-nav.js.map +1 -0
- package/dist/components/composite/route-tabs.d.ts +4 -1
- package/dist/components/composite/route-tabs.js +3 -2
- package/dist/components/composite/route-tabs.js.map +1 -1
- package/dist/components/composite/search-filter-bar-constants.d.ts +18 -8
- package/dist/components/composite/search-filter-bar-constants.js +2 -14
- package/dist/components/composite/search-filter-bar-constants.js.map +1 -1
- package/dist/components/composite/search-filter-bar.d.ts +5 -2
- package/dist/components/composite/search-filter-bar.js +2 -2
- package/dist/components/composite/search-filter-bar.js.map +1 -1
- package/dist/components/composite/stat-card.d.ts +1 -1
- package/dist/components/composite/table-pagination-constants.d.ts +16 -11
- package/dist/components/composite/table-pagination-constants.js +2 -12
- package/dist/components/composite/table-pagination-constants.js.map +1 -1
- package/dist/components/composite/table-pagination.d.ts +6 -3
- package/dist/components/composite/table-pagination.js +3 -5
- package/dist/components/composite/table-pagination.js.map +1 -1
- package/dist/components/composite/toast.d.ts +4 -2
- package/dist/components/composite/toast.js +9 -1
- package/dist/components/composite/toast.js.map +1 -1
- package/dist/components/ui/action-bar-constants.d.ts +8 -4
- package/dist/components/ui/action-bar-constants.js +2 -5
- package/dist/components/ui/action-bar-constants.js.map +1 -1
- package/dist/components/ui/action-bar.d.ts +5 -4
- package/dist/components/ui/action-bar.js +2 -2
- package/dist/components/ui/action-bar.js.map +1 -1
- package/dist/components/ui/alert.d.ts +1 -1
- package/dist/components/ui/badge-overflow.d.ts +2 -2
- package/dist/components/ui/badge-overflow.js +4 -2
- package/dist/components/ui/badge-overflow.js.map +1 -1
- package/dist/components/ui/badge.d.ts +1 -1
- package/dist/components/ui/banner.d.ts +6 -5
- package/dist/components/ui/banner.js +3 -1
- package/dist/components/ui/banner.js.map +1 -1
- package/dist/components/ui/breadcrumb.d.ts +11 -4
- package/dist/components/ui/breadcrumb.js +7 -2
- package/dist/components/ui/breadcrumb.js.map +1 -1
- package/dist/components/ui/button.d.ts +2 -2
- package/dist/components/ui/calendar.d.ts +12 -5
- package/dist/components/ui/calendar.js +38 -3
- package/dist/components/ui/calendar.js.map +1 -1
- package/dist/components/ui/carousel.d.ts +4 -3
- package/dist/components/ui/carousel.js +11 -4
- package/dist/components/ui/carousel.js.map +1 -1
- package/dist/components/ui/circular-progress.js.map +1 -1
- package/dist/components/ui/command.d.ts +5 -4
- package/dist/components/ui/command.js +6 -2
- package/dist/components/ui/command.js.map +1 -1
- package/dist/components/ui/cropper-constants.d.ts +8 -3
- package/dist/components/ui/cropper-constants.js +2 -6
- package/dist/components/ui/cropper-constants.js.map +1 -1
- package/dist/components/ui/cropper.d.ts +2 -1
- package/dist/components/ui/cropper.js +2 -2
- package/dist/components/ui/cropper.js.map +1 -1
- package/dist/components/ui/dialog.d.ts +2 -2
- package/dist/components/ui/dialog.js +4 -1
- package/dist/components/ui/dialog.js.map +1 -1
- package/dist/components/ui/item.d.ts +2 -2
- package/dist/components/ui/kanban-constants.d.ts +7 -1
- package/dist/components/ui/kanban-constants.js +2 -17
- package/dist/components/ui/kanban-constants.js.map +1 -1
- package/dist/components/ui/kanban.d.ts +2 -2
- package/dist/components/ui/kanban.js +2 -2
- package/dist/components/ui/kanban.js.map +1 -1
- package/dist/components/ui/key-value-constants.d.ts +7 -3
- package/dist/components/ui/key-value-constants.js +2 -7
- package/dist/components/ui/key-value-constants.js.map +1 -1
- package/dist/components/ui/key-value.d.ts +5 -5
- package/dist/components/ui/key-value.js +2 -2
- package/dist/components/ui/key-value.js.map +1 -1
- package/dist/components/ui/mask-input-constants.d.ts +2 -3
- package/dist/components/ui/mask-input-constants.js +5 -6
- package/dist/components/ui/mask-input-constants.js.map +1 -1
- package/dist/components/ui/mask-input.d.ts +7 -4
- package/dist/components/ui/mask-input.js +4 -2
- package/dist/components/ui/mask-input.js.map +1 -1
- package/dist/components/ui/mention.d.ts +3 -2
- package/dist/components/ui/mention.js +4 -6
- package/dist/components/ui/mention.js.map +1 -1
- package/dist/components/ui/pagination.d.ts +13 -9
- package/dist/components/ui/pagination.js +15 -6
- package/dist/components/ui/pagination.js.map +1 -1
- package/dist/components/ui/phone-input-constants.d.ts +17 -6
- package/dist/components/ui/phone-input-constants.js +2 -5
- package/dist/components/ui/phone-input-constants.js.map +1 -1
- package/dist/components/ui/phone-input.d.ts +18 -11
- package/dist/components/ui/phone-input.js +9 -10
- package/dist/components/ui/phone-input.js.map +1 -1
- package/dist/components/ui/progress.d.ts +2 -2
- package/dist/components/ui/rating.d.ts +2 -1
- package/dist/components/ui/rating.js +4 -2
- package/dist/components/ui/rating.js.map +1 -1
- package/dist/components/ui/scroll-spy.js +3 -1
- package/dist/components/ui/scroll-spy.js.map +1 -1
- package/dist/components/ui/sheet.d.ts +2 -2
- package/dist/components/ui/sheet.js +10 -1
- package/dist/components/ui/sheet.js.map +1 -1
- package/dist/components/ui/spinner.js +4 -1
- package/dist/components/ui/spinner.js.map +1 -1
- package/dist/components/ui/stepper-constants.d.ts +7 -2
- package/dist/components/ui/stepper-constants.js +2 -5
- package/dist/components/ui/stepper-constants.js.map +1 -1
- package/dist/components/ui/stepper.d.ts +2 -1
- package/dist/components/ui/stepper.js +2 -2
- package/dist/components/ui/stepper.js.map +1 -1
- package/dist/components/ui/tags-input.d.ts +3 -2
- package/dist/components/ui/tags-input.js +4 -2
- package/dist/components/ui/tags-input.js.map +1 -1
- package/dist/components/ui/time-picker-constants.d.ts +12 -9
- package/dist/components/ui/time-picker-constants.js +2 -10
- package/dist/components/ui/time-picker-constants.js.map +1 -1
- package/dist/components/ui/time-picker.d.ts +11 -6
- package/dist/components/ui/time-picker.js +5 -7
- package/dist/components/ui/time-picker.js.map +1 -1
- package/dist/components/ui/toggle.d.ts +1 -1
- package/dist/components/ui/tour-constants.d.ts +7 -2
- package/dist/components/ui/tour-constants.js +2 -8
- package/dist/components/ui/tour-constants.js.map +1 -1
- package/dist/components/ui/tour.d.ts +3 -2
- package/dist/components/ui/tour.js +2 -2
- package/dist/components/ui/tour.js.map +1 -1
- package/dist/data-grid/data-grid-cell-variants.js +4 -4
- package/dist/data-grid/data-grid-cell-variants.js.map +1 -1
- package/dist/data-grid/data-grid-column-header.js +1 -1
- package/dist/data-grid/data-grid-column-header.js.map +1 -1
- package/dist/data-grid/data-grid-filter-menu.d.ts +5 -4
- package/dist/data-grid/data-grid-filter-menu.js +13 -8
- package/dist/data-grid/data-grid-filter-menu.js.map +1 -1
- package/dist/data-grid/data-grid-keyboard-shortcuts.d.ts +4 -4
- package/dist/data-grid/data-grid-keyboard-shortcuts.js.map +1 -1
- package/dist/data-grid/data-grid-locale.d.ts +58 -6
- package/dist/data-grid/data-grid-locale.js +41 -9
- package/dist/data-grid/data-grid-locale.js.map +1 -1
- package/dist/data-grid/data-grid-row-height-menu.d.ts +4 -3
- package/dist/data-grid/data-grid-row-height-menu.js.map +1 -1
- package/dist/data-grid/data-grid-sort-menu.d.ts +4 -4
- package/dist/data-grid/data-grid-sort-menu.js +1 -1
- package/dist/data-grid/data-grid-sort-menu.js.map +1 -1
- package/dist/data-grid/data-grid-view-menu.d.ts +4 -4
- package/dist/data-grid/data-grid-view-menu.js.map +1 -1
- package/dist/data-grid/data-grid.d.ts +4 -3
- package/dist/data-grid/data-grid.js +2 -3
- package/dist/data-grid/data-grid.js.map +1 -1
- package/dist/data-grid/index.d.ts +1 -0
- package/dist/data-grid/index.js.map +1 -1
- package/dist/data-grid/messages-en.d.ts +23 -4
- package/dist/data-grid/messages-en.js +20 -0
- package/dist/data-grid/messages-en.js.map +1 -1
- package/dist/data-grid/messages-vi.d.ts +3 -1
- package/dist/data-grid/messages-vi.js +14 -0
- package/dist/data-grid/messages-vi.js.map +1 -1
- package/dist/data-grid/messages.d.ts +29 -3
- package/dist/data-grid/messages.js.map +1 -1
- package/dist/data-grid/sortable.js +16 -19
- package/dist/data-grid/sortable.js.map +1 -1
- package/dist/data-grid/types.d.ts +1 -1
- package/dist/data-grid/use-data-grid-undo-redo.d.ts +5 -4
- package/dist/data-grid/use-data-grid-undo-redo.js +2 -2
- package/dist/data-grid/use-data-grid-undo-redo.js.map +1 -1
- package/dist/data-grid/use-data-grid.d.ts +21 -6
- package/dist/data-grid/use-data-grid.js +8 -6
- package/dist/data-grid/use-data-grid.js.map +1 -1
- package/dist/data-grid/utils.d.ts +24 -4
- package/dist/data-grid/utils.js +15 -5
- package/dist/data-grid/utils.js.map +1 -1
- package/dist/i18n/locale-provider.d.ts +109 -0
- package/dist/i18n/locale-provider.js +47 -0
- package/dist/i18n/locale-provider.js.map +1 -0
- package/dist/i18n/locale.d.ts +27 -0
- package/dist/i18n/locale.js +10 -0
- package/dist/i18n/locale.js.map +1 -0
- package/dist/i18n/messages.d.ts +116 -0
- package/dist/i18n/messages.js +149 -0
- package/dist/i18n/messages.js.map +1 -0
- package/dist/i18n/namespaces/action-bar.d.ts +7 -0
- package/dist/i18n/namespaces/action-bar.js +15 -0
- package/dist/i18n/namespaces/action-bar.js.map +1 -0
- package/dist/i18n/namespaces/avatar-group.d.ts +14 -0
- package/dist/i18n/namespaces/avatar-group.js +13 -0
- package/dist/i18n/namespaces/avatar-group.js.map +1 -0
- package/dist/i18n/namespaces/badge-overflow.d.ts +12 -0
- package/dist/i18n/namespaces/badge-overflow.js +11 -0
- package/dist/i18n/namespaces/badge-overflow.js.map +1 -0
- package/dist/i18n/namespaces/banner.d.ts +9 -0
- package/dist/i18n/namespaces/banner.js +7 -0
- package/dist/i18n/namespaces/banner.js.map +1 -0
- package/dist/i18n/namespaces/breadcrumb.d.ts +11 -0
- package/dist/i18n/namespaces/breadcrumb.js +13 -0
- package/dist/i18n/namespaces/breadcrumb.js.map +1 -0
- package/dist/i18n/namespaces/calendar.d.ts +40 -0
- package/dist/i18n/namespaces/calendar.js +25 -0
- package/dist/i18n/namespaces/calendar.js.map +1 -0
- package/dist/i18n/namespaces/carousel.d.ts +15 -0
- package/dist/i18n/namespaces/carousel.js +17 -0
- package/dist/i18n/namespaces/carousel.js.map +1 -0
- package/dist/i18n/namespaces/combobox.d.ts +21 -0
- package/dist/i18n/namespaces/combobox.js +23 -0
- package/dist/i18n/namespaces/combobox.js.map +1 -0
- package/dist/i18n/namespaces/command-palette.d.ts +20 -0
- package/dist/i18n/namespaces/command-palette.js +19 -0
- package/dist/i18n/namespaces/command-palette.js.map +1 -0
- package/dist/i18n/namespaces/command.d.ts +11 -0
- package/dist/i18n/namespaces/command.js +13 -0
- package/dist/i18n/namespaces/command.js.map +1 -0
- package/dist/i18n/namespaces/confirm-dialog.d.ts +13 -0
- package/dist/i18n/namespaces/confirm-dialog.js +15 -0
- package/dist/i18n/namespaces/confirm-dialog.js.map +1 -0
- package/dist/i18n/namespaces/contrast.d.ts +7 -0
- package/dist/i18n/namespaces/contrast.js +13 -0
- package/dist/i18n/namespaces/contrast.js.map +1 -0
- package/dist/i18n/namespaces/copy-button.d.ts +11 -0
- package/dist/i18n/namespaces/copy-button.js +13 -0
- package/dist/i18n/namespaces/copy-button.js.map +1 -0
- package/dist/i18n/namespaces/cropper.d.ts +7 -0
- package/dist/i18n/namespaces/cropper.js +17 -0
- package/dist/i18n/namespaces/cropper.js.map +1 -0
- package/dist/i18n/namespaces/data-table.d.ts +7 -0
- package/dist/i18n/namespaces/data-table.js +23 -0
- package/dist/i18n/namespaces/data-table.js.map +1 -0
- package/dist/i18n/namespaces/date-picker.d.ts +42 -0
- package/dist/i18n/namespaces/date-picker.js +35 -0
- package/dist/i18n/namespaces/date-picker.js.map +1 -0
- package/dist/i18n/namespaces/dialog.d.ts +9 -0
- package/dist/i18n/namespaces/dialog.js +7 -0
- package/dist/i18n/namespaces/dialog.js.map +1 -0
- package/dist/i18n/namespaces/display-axis.d.ts +25 -0
- package/dist/i18n/namespaces/display-axis.js +21 -0
- package/dist/i18n/namespaces/display-axis.js.map +1 -0
- package/dist/i18n/namespaces/file-upload.d.ts +11 -0
- package/dist/i18n/namespaces/file-upload.js +19 -0
- package/dist/i18n/namespaces/file-upload.js.map +1 -0
- package/dist/i18n/namespaces/filter-chips.d.ts +11 -0
- package/dist/i18n/namespaces/filter-chips.js +13 -0
- package/dist/i18n/namespaces/filter-chips.js.map +1 -0
- package/dist/i18n/namespaces/image-upload-field.d.ts +12 -0
- package/dist/i18n/namespaces/image-upload-field.js +23 -0
- package/dist/i18n/namespaces/image-upload-field.js.map +1 -0
- package/dist/i18n/namespaces/inline-edit.d.ts +15 -0
- package/dist/i18n/namespaces/inline-edit.js +17 -0
- package/dist/i18n/namespaces/inline-edit.js.map +1 -0
- package/dist/i18n/namespaces/kanban.d.ts +11 -0
- package/dist/i18n/namespaces/kanban.js +39 -0
- package/dist/i18n/namespaces/kanban.js.map +1 -0
- package/dist/i18n/namespaces/key-value.d.ts +10 -0
- package/dist/i18n/namespaces/key-value.js +19 -0
- package/dist/i18n/namespaces/key-value.js.map +1 -0
- package/dist/i18n/namespaces/mention.d.ts +9 -0
- package/dist/i18n/namespaces/mention.js +7 -0
- package/dist/i18n/namespaces/mention.js.map +1 -0
- package/dist/i18n/namespaces/pagination.d.ts +19 -0
- package/dist/i18n/namespaces/pagination.js +21 -0
- package/dist/i18n/namespaces/pagination.js.map +1 -0
- package/dist/i18n/namespaces/phone-input.d.ts +10 -0
- package/dist/i18n/namespaces/phone-input.js +17 -0
- package/dist/i18n/namespaces/phone-input.js.map +1 -0
- package/dist/i18n/namespaces/rating.d.ts +12 -0
- package/dist/i18n/namespaces/rating.js +11 -0
- package/dist/i18n/namespaces/rating.js.map +1 -0
- package/dist/i18n/namespaces/route-tabs.d.ts +9 -0
- package/dist/i18n/namespaces/route-tabs.js +7 -0
- package/dist/i18n/namespaces/route-tabs.js.map +1 -0
- package/dist/i18n/namespaces/scroll-spy.d.ts +9 -0
- package/dist/i18n/namespaces/scroll-spy.js +7 -0
- package/dist/i18n/namespaces/scroll-spy.js.map +1 -0
- package/dist/i18n/namespaces/search-filter-bar.d.ts +15 -0
- package/dist/i18n/namespaces/search-filter-bar.js +32 -0
- package/dist/i18n/namespaces/search-filter-bar.js.map +1 -0
- package/dist/i18n/namespaces/sheet.d.ts +9 -0
- package/dist/i18n/namespaces/sheet.js +7 -0
- package/dist/i18n/namespaces/sheet.js.map +1 -0
- package/dist/i18n/namespaces/shell.d.ts +17 -0
- package/dist/i18n/namespaces/shell.js +75 -0
- package/dist/i18n/namespaces/shell.js.map +1 -0
- package/dist/i18n/namespaces/spinner.d.ts +9 -0
- package/dist/i18n/namespaces/spinner.js +7 -0
- package/dist/i18n/namespaces/spinner.js.map +1 -0
- package/dist/i18n/namespaces/stepper.d.ts +7 -0
- package/dist/i18n/namespaces/stepper.js +15 -0
- package/dist/i18n/namespaces/stepper.js.map +1 -0
- package/dist/i18n/namespaces/table-pagination.d.ts +7 -0
- package/dist/i18n/namespaces/table-pagination.js +29 -0
- package/dist/i18n/namespaces/table-pagination.js.map +1 -0
- package/dist/i18n/namespaces/tags-input.d.ts +12 -0
- package/dist/i18n/namespaces/tags-input.js +11 -0
- package/dist/i18n/namespaces/tags-input.js.map +1 -0
- package/dist/i18n/namespaces/time-picker.d.ts +15 -0
- package/dist/i18n/namespaces/time-picker.js +25 -0
- package/dist/i18n/namespaces/time-picker.js.map +1 -0
- package/dist/i18n/namespaces/toast.d.ts +15 -0
- package/dist/i18n/namespaces/toast.js +7 -0
- package/dist/i18n/namespaces/toast.js.map +1 -0
- package/dist/i18n/namespaces/tour.d.ts +7 -0
- package/dist/i18n/namespaces/tour.js +21 -0
- package/dist/i18n/namespaces/tour.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +24 -1
- package/dist/index.js.map +1 -1
- package/dist/shell/app-header.js.map +1 -1
- package/dist/shell/app-shell.d.ts +20 -2
- package/dist/shell/app-shell.js +4 -1
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/contrast-constants.d.ts +9 -1
- package/dist/shell/contrast-constants.js +2 -4
- package/dist/shell/contrast-constants.js.map +1 -1
- package/dist/shell/contrast-toggle.d.ts +4 -1
- package/dist/shell/contrast-toggle.js +2 -2
- package/dist/shell/contrast-toggle.js.map +1 -1
- package/dist/shell/display-axis-constants.d.ts +2 -1
- package/dist/shell/display-axis-constants.js.map +1 -1
- package/dist/shell/display-axis-controls.d.ts +15 -6
- package/dist/shell/display-axis-controls.js +11 -9
- package/dist/shell/display-axis-controls.js.map +1 -1
- package/dist/shell/mobile-menu.js.map +1 -1
- package/dist/shell/notifications-button.d.ts +1 -1
- package/dist/shell/notifications-button.js +3 -2
- package/dist/shell/notifications-button.js.map +1 -1
- package/dist/shell/shell-context.d.ts +4 -1
- package/dist/shell/shell-context.js +2 -4
- package/dist/shell/shell-context.js.map +1 -1
- package/dist/shell/sidebar.d.ts +1 -1
- package/dist/shell/sidebar.js.map +1 -1
- package/dist/shell/theme-toggle.d.ts +6 -3
- package/dist/shell/theme-toggle.js +2 -2
- package/dist/shell/theme-toggle.js.map +1 -1
- package/dist/shell/types.d.ts +14 -8
- package/dist/shell/types.js +2 -35
- package/dist/shell/types.js.map +1 -1
- package/dist/shell/user-menu.d.ts +6 -6
- package/dist/shell/user-menu.js.map +1 -1
- package/dist/shell/utils.d.ts +1 -1
- package/dist/shell/utils.js.map +1 -1
- package/dist/shell/workspace-switcher.js +1 -1
- package/dist/shell/workspace-switcher.js.map +1 -1
- package/dist/uploader/file-upload-constants.d.ts +13 -0
- package/dist/uploader/file-upload-constants.js +4 -16
- package/dist/uploader/file-upload-constants.js.map +1 -1
- package/dist/uploader/file-upload.d.ts +4 -1
- package/dist/uploader/file-upload.js +2 -2
- package/dist/uploader/file-upload.js.map +1 -1
- package/dist/uploader/image-upload-field.d.ts +5 -1
- package/dist/uploader/image-upload-field.js +2 -2
- package/dist/uploader/image-upload-field.js.map +1 -1
- package/dist/uploader/use-file-upload.d.ts +4 -0
- package/dist/uploader/use-file-upload.js +6 -2
- package/dist/uploader/use-file-upload.js.map +1 -1
- package/package.json +4 -3
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
4
4
|
import { XIcon } from "lucide-react";
|
|
5
|
+
import { useComitorMessages } from "../../i18n/locale-provider.js";
|
|
5
6
|
import { cn } from "../../lib/cn.js";
|
|
6
7
|
function Dialog({ ...props }) {
|
|
7
8
|
return /* @__PURE__ */ jsx(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
@@ -39,9 +40,11 @@ function DialogContent({
|
|
|
39
40
|
children,
|
|
40
41
|
showCloseButton = true,
|
|
41
42
|
size = "md",
|
|
42
|
-
closeLabel
|
|
43
|
+
closeLabel: closeLabelProp,
|
|
43
44
|
...props
|
|
44
45
|
}) {
|
|
46
|
+
const t = useComitorMessages("dialog");
|
|
47
|
+
const closeLabel = closeLabelProp ?? t.closeLabel;
|
|
45
48
|
return /* @__PURE__ */ jsxs(DialogPortal, { "data-slot": "dialog-portal", children: [
|
|
46
49
|
/* @__PURE__ */ jsx(DialogOverlay, {}),
|
|
47
50
|
/* @__PURE__ */ jsxs(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { XIcon } from \"lucide-react\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * Dialog — hộp thoại modal (Radix Dialog), style new-york + token Comitor.\n *\n * Khác bản shadcn gốc: có prop `size` (sm/md/lg/xl) và `DialogBody` để tách vùng\n * nội dung cuộn khỏi header/footer.\n */\n\nexport type DialogProps = React.ComponentProps<typeof DialogPrimitive.Root>;\n\nfunction Dialog({ ...props }: DialogProps) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nexport type DialogTriggerProps = React.ComponentProps<typeof DialogPrimitive.Trigger>;\n\nfunction DialogTrigger({ ...props }: DialogTriggerProps) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nexport type DialogPortalProps = React.ComponentProps<typeof DialogPrimitive.Portal>;\n\nfunction DialogPortal({ ...props }: DialogPortalProps) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\nexport type DialogCloseProps = React.ComponentProps<typeof DialogPrimitive.Close>;\n\nfunction DialogClose({ ...props }: DialogCloseProps) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nexport type DialogOverlayProps = React.ComponentProps<typeof DialogPrimitive.Overlay>;\n\nfunction DialogOverlay({ className, ...props }: DialogOverlayProps) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-ink/60 dark:bg-ink/80 backdrop-blur-sm\",\n className\n )}\n {...props}\n />\n );\n}\n\n/** Bề ngang tối đa theo cỡ — khai tĩnh để Tailwind quét được (không sinh class động). */\nconst dialogSizeStyles = {\n sm: \"sm:max-w-sm\",\n md: \"sm:max-w-md\",\n lg: \"sm:max-w-lg\",\n xl: \"sm:max-w-xl\"\n} as const;\n\nexport type DialogSize = keyof typeof dialogSizeStyles;\n\nexport type DialogContentProps = React.ComponentProps<typeof DialogPrimitive.Content> & {\n /** Hiện nút đóng ở góc phải trên. Mặc định true. */\n showCloseButton?: boolean;\n /** Cỡ hộp thoại theo breakpoint sm trở lên. Mặc định \"md\". */\n size?: DialogSize;\n /** Nhãn cho trình đọc màn hình của nút đóng. Mặc định \"Đóng\". */\n closeLabel?: string;\n};\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n size = \"md\",\n closeLabel = \"Đóng\",\n ...props\n}: DialogContentProps) {\n return (\n <DialogPortal data-slot=\"dialog-portal\">\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n /*\n * ⚠ `max-h` + `overflow-y-auto` là BẮT BUỘC, không phải trang trí.\n *\n * Hộp thoại là `position: fixed` căn giữa bằng `translate-y-[-50%]`. Không có trần\n * chiều cao thì một biểu mẫu dài tràn ra CẢ HAI phía màn hình — và vì nó `fixed` nên\n * trang không cuộn nó được: phần đầu và phần cuối (kể cả nút Gửi) trở nên KHÔNG THỂ\n * chạm tới. Đo được ở hộp \"Mời thành viên\": nội dung 812px trong khung nhìn 613px.\n *\n * ⚠ `flex flex-col` chứ KHÔNG phải `grid`. Với `grid`, mọi hàng là `auto` nên không\n * hàng nào chịu co lại — muốn `DialogBody` cuộn thì phải khai `grid-template-rows`,\n * mà làm vậy là ghim thứ tự con (header phải là con thứ nhất). Flex cho `DialogBody`\n * co lại theo `min-h-0` bất kể nó nằm ở đâu.\n *\n * `overflow-y-auto` ở đây là LƯỚI AN TOÀN cho hộp thoại KHÔNG dùng `DialogBody`:\n * có `DialogBody` thì chính nó cuộn và thanh cuộn ngoài này không bao giờ xuất hiện.\n */\n \"bg-card data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 flex max-h-[calc(100dvh-2rem)] w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] flex-col gap-4 overflow-y-auto rounded-xl border border-border p-6 shadow-overlay duration-200\",\n dialogSizeStyles[size],\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n className=\"absolute top-4 right-4 rounded-md p-1 text-muted-foreground transition-colors duration-150 ease-out hover:text-foreground hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\"\n >\n <XIcon />\n <span className=\"sr-only\">{closeLabel}</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPortal>\n );\n}\n\nexport type DialogBodyProps = React.ComponentProps<\"div\">;\n\n/**\n * Vùng nội dung CUỘN của hộp thoại, giữa header và footer.\n *\n * ⚠ Trước 1.3.2 component này render `<div className={cn(className)} />` — tức KHÔNG LÀM GÌ CẢ,\n * trong khi chính tài liệu của nó (và của `Dialog`) nói nó \"tách vùng nội dung cuộn khỏi\n * header/footer\". Một component không làm điều nó tự nhận là loại lỗi tệ nhất trong một gói dùng\n * chung: chỗ gọi đã làm ĐÚNG rồi mà vẫn hỏng, nên người ta đi tìm nguyên nhân ở app.\n *\n * ⚠ `flex-auto` chứ không `flex-1`: `flex-1` là `flex: 1 1 0%`, tức lấy 0 làm cỡ cơ sở. `flex-auto`\n * (`1 1 auto`) lấy cỡ NỘI DUNG làm cơ sở, nên hộp thoại ngắn vẫn ôm sát nội dung thay vì bị kéo\n * giãn. `min-h-0` là mảnh bắt buộc còn lại — thiếu nó, `min-height: auto` mặc định của flex item\n * giữ nguyên chiều cao nội dung và không gì cuộn được.\n */\nfunction DialogBody({ className, ...props }: DialogBodyProps) {\n return (\n <div\n data-slot=\"dialog-body\"\n /*\n * ⚠ `-m-1 p-1` KHÔNG phải để cho thoáng — nó là chỗ cho FOCUS RING thở.\n *\n * CSS không cho một trục `auto` còn trục kia `visible`: đặt `overflow-y: auto` thì\n * `overflow-x` **tự thành `auto`**, và hộp cắt xuất hiện ở CẢ HAI chiều. Con của vùng này\n * là `Input` `w-full`, tức mép nó trùng khít mép hộp cắt (đo được: chỗ trống hai bên đúng\n * 0px) — nên `focus:ring-2` nằm 2px bên ngoài bị cắt sạch. Ô đang focus trông như không\n * focus, và đó là dấu hiệu DUY NHẤT cho người dùng bàn phím.\n *\n * `p-1` cho 4,5px chỗ trống (rem gốc 18px); `-m-1` kéo hộp lại đúng bấy nhiêu nên vị trí\n * NỘI DUNG không đổi một pixel — khoảng cách tới header/footer vẫn là `gap-4`.\n *\n * ⚠ Đừng bê khuôn này sang `SheetContent`/`DrawerContent`: chúng `position: fixed` kèm\n * `inset-x-0`/`right-0`, nên margin ÂM làm chúng rộng ra 9px và tràn khỏi khung nhìn.\n * Ở đó, con phải tự mang padding — `SheetHeader`/`SheetFooter` đã có `p-4`.\n */\n className={cn(\"-m-1 min-h-0 flex-auto overflow-y-auto p-1\", className)}\n {...props}\n />\n );\n}\n\nexport type DialogHeaderProps = React.ComponentProps<\"div\">;\n\nfunction DialogHeader({ className, ...props }: DialogHeaderProps) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n );\n}\n\nexport type DialogFooterProps = React.ComponentProps<\"div\">;\n\nfunction DialogFooter({ className, ...props }: DialogFooterProps) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\", className)}\n {...props}\n />\n );\n}\n\nexport type DialogTitleProps = React.ComponentProps<typeof DialogPrimitive.Title>;\n\nfunction DialogTitle({ className, ...props }: DialogTitleProps) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-lg font-semibold text-foreground\", className)}\n {...props}\n />\n );\n}\n\nexport type DialogDescriptionProps = React.ComponentProps<typeof DialogPrimitive.Description>;\n\nfunction DialogDescription({ className, ...props }: DialogDescriptionProps) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Dialog,\n DialogBody,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger\n};\n"],"mappings":";AAiBS,cA6FC,YA7FD;AAfT,YAAY,qBAAqB;AACjC,SAAS,aAAa;AAEtB,SAAS,UAAU;AAWnB,SAAS,OAAO,EAAE,GAAG,MAAM,GAAgB;AACzC,SAAO,oBAAC,gBAAgB,MAAhB,EAAqB,aAAU,UAAU,GAAG,OAAO;AAC7D;AAIA,SAAS,cAAc,EAAE,GAAG,MAAM,GAAuB;AACvD,SAAO,oBAAC,gBAAgB,SAAhB,EAAwB,aAAU,kBAAkB,GAAG,OAAO;AACxE;AAIA,SAAS,aAAa,EAAE,GAAG,MAAM,GAAsB;AACrD,SAAO,oBAAC,gBAAgB,QAAhB,EAAuB,aAAU,iBAAiB,GAAG,OAAO;AACtE;AAIA,SAAS,YAAY,EAAE,GAAG,MAAM,GAAqB;AACnD,SAAO,oBAAC,gBAAgB,OAAhB,EAAsB,aAAU,gBAAgB,GAAG,OAAO;AACpE;AAIA,SAAS,cAAc,EAAE,WAAW,GAAG,MAAM,GAAuB;AAClE,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAGA,MAAM,mBAAmB;AAAA,EACvB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAaA,SAAS,cAAc;AAAA,EACrB;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB,OAAO;AAAA,EACP,aAAa;AAAA,EACb,GAAG;AACL,GAAuB;AACrB,SACE,qBAAC,gBAAa,aAAU,iBACtB;AAAA,wBAAC,iBAAc;AAAA,IACf;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC,aAAU;AAAA,QACV,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAiBT;AAAA,UACA,iBAAiB,IAAI;AAAA,UACrB;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEH;AAAA;AAAA,UACA,mBACC;AAAA,YAAC,gBAAgB;AAAA,YAAhB;AAAA,cACC,aAAU;AAAA,cACV,WAAU;AAAA,cAEV;AAAA,oCAAC,SAAM;AAAA,gBACP,oBAAC,UAAK,WAAU,WAAW,sBAAW;AAAA;AAAA;AAAA,UACxC;AAAA;AAAA;AAAA,IAEJ;AAAA,KACF;AAEJ;AAiBA,SAAS,WAAW,EAAE,WAAW,GAAG,MAAM,GAAoB;AAC5D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MAiBV,WAAW,GAAG,8CAA8C,SAAS;AAAA,MACpE,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,gDAAgD,SAAS;AAAA,MACtE,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,0DAA0D,SAAS;AAAA,MAChF,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,yCAAyC,SAAS;AAAA,MAC/D,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,kBAAkB,EAAE,WAAW,GAAG,MAAM,GAA2B;AAC1E,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,iCAAiC,SAAS;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { XIcon } from \"lucide-react\";\nimport type * as React from \"react\";\nimport { useComitorMessages } from \"../../i18n/locale-provider.js\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * Dialog — hộp thoại modal (Radix Dialog), style new-york + token Comitor.\n *\n * Khác bản shadcn gốc: có prop `size` (sm/md/lg/xl) và `DialogBody` để tách vùng\n * nội dung cuộn khỏi header/footer.\n */\n\nexport type DialogProps = React.ComponentProps<typeof DialogPrimitive.Root>;\n\nfunction Dialog({ ...props }: DialogProps) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nexport type DialogTriggerProps = React.ComponentProps<typeof DialogPrimitive.Trigger>;\n\nfunction DialogTrigger({ ...props }: DialogTriggerProps) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nexport type DialogPortalProps = React.ComponentProps<typeof DialogPrimitive.Portal>;\n\nfunction DialogPortal({ ...props }: DialogPortalProps) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\nexport type DialogCloseProps = React.ComponentProps<typeof DialogPrimitive.Close>;\n\nfunction DialogClose({ ...props }: DialogCloseProps) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nexport type DialogOverlayProps = React.ComponentProps<typeof DialogPrimitive.Overlay>;\n\nfunction DialogOverlay({ className, ...props }: DialogOverlayProps) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-ink/60 dark:bg-ink/80 backdrop-blur-sm\",\n className\n )}\n {...props}\n />\n );\n}\n\n/** Bề ngang tối đa theo cỡ — khai tĩnh để Tailwind quét được (không sinh class động). */\nconst dialogSizeStyles = {\n sm: \"sm:max-w-sm\",\n md: \"sm:max-w-md\",\n lg: \"sm:max-w-lg\",\n xl: \"sm:max-w-xl\"\n} as const;\n\nexport type DialogSize = keyof typeof dialogSizeStyles;\n\nexport type DialogContentProps = React.ComponentProps<typeof DialogPrimitive.Content> & {\n /** Hiện nút đóng ở góc phải trên. Mặc định true. */\n showCloseButton?: boolean;\n /** Cỡ hộp thoại theo breakpoint sm trở lên. Mặc định \"md\". */\n size?: DialogSize;\n /** Nhãn cho trình đọc màn hình của nút đóng. Mặc định: khoá `closeLabel` của namespace `dialog`. */\n closeLabel?: string;\n};\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n size = \"md\",\n closeLabel: closeLabelProp,\n ...props\n}: DialogContentProps) {\n const t = useComitorMessages(\"dialog\");\n const closeLabel = closeLabelProp ?? t.closeLabel;\n return (\n <DialogPortal data-slot=\"dialog-portal\">\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n /*\n * ⚠ `max-h` + `overflow-y-auto` là BẮT BUỘC, không phải trang trí.\n *\n * Hộp thoại là `position: fixed` căn giữa bằng `translate-y-[-50%]`. Không có trần\n * chiều cao thì một biểu mẫu dài tràn ra CẢ HAI phía màn hình — và vì nó `fixed` nên\n * trang không cuộn nó được: phần đầu và phần cuối (kể cả nút Gửi) trở nên KHÔNG THỂ\n * chạm tới. Đo được ở hộp \"Mời thành viên\": nội dung 812px trong khung nhìn 613px.\n *\n * ⚠ `flex flex-col` chứ KHÔNG phải `grid`. Với `grid`, mọi hàng là `auto` nên không\n * hàng nào chịu co lại — muốn `DialogBody` cuộn thì phải khai `grid-template-rows`,\n * mà làm vậy là ghim thứ tự con (header phải là con thứ nhất). Flex cho `DialogBody`\n * co lại theo `min-h-0` bất kể nó nằm ở đâu.\n *\n * `overflow-y-auto` ở đây là LƯỚI AN TOÀN cho hộp thoại KHÔNG dùng `DialogBody`:\n * có `DialogBody` thì chính nó cuộn và thanh cuộn ngoài này không bao giờ xuất hiện.\n */\n \"bg-card data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 flex max-h-[calc(100dvh-2rem)] w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] flex-col gap-4 overflow-y-auto rounded-xl border border-border p-6 shadow-overlay duration-200\",\n dialogSizeStyles[size],\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n className=\"absolute top-4 right-4 rounded-md p-1 text-muted-foreground transition-colors duration-150 ease-out hover:text-foreground hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\"\n >\n <XIcon />\n <span className=\"sr-only\">{closeLabel}</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPortal>\n );\n}\n\nexport type DialogBodyProps = React.ComponentProps<\"div\">;\n\n/**\n * Vùng nội dung CUỘN của hộp thoại, giữa header và footer.\n *\n * ⚠ Trước 1.3.2 component này render `<div className={cn(className)} />` — tức KHÔNG LÀM GÌ CẢ,\n * trong khi chính tài liệu của nó (và của `Dialog`) nói nó \"tách vùng nội dung cuộn khỏi\n * header/footer\". Một component không làm điều nó tự nhận là loại lỗi tệ nhất trong một gói dùng\n * chung: chỗ gọi đã làm ĐÚNG rồi mà vẫn hỏng, nên người ta đi tìm nguyên nhân ở app.\n *\n * ⚠ `flex-auto` chứ không `flex-1`: `flex-1` là `flex: 1 1 0%`, tức lấy 0 làm cỡ cơ sở. `flex-auto`\n * (`1 1 auto`) lấy cỡ NỘI DUNG làm cơ sở, nên hộp thoại ngắn vẫn ôm sát nội dung thay vì bị kéo\n * giãn. `min-h-0` là mảnh bắt buộc còn lại — thiếu nó, `min-height: auto` mặc định của flex item\n * giữ nguyên chiều cao nội dung và không gì cuộn được.\n */\nfunction DialogBody({ className, ...props }: DialogBodyProps) {\n return (\n <div\n data-slot=\"dialog-body\"\n /*\n * ⚠ `-m-1 p-1` KHÔNG phải để cho thoáng — nó là chỗ cho FOCUS RING thở.\n *\n * CSS không cho một trục `auto` còn trục kia `visible`: đặt `overflow-y: auto` thì\n * `overflow-x` **tự thành `auto`**, và hộp cắt xuất hiện ở CẢ HAI chiều. Con của vùng này\n * là `Input` `w-full`, tức mép nó trùng khít mép hộp cắt (đo được: chỗ trống hai bên đúng\n * 0px) — nên `focus:ring-2` nằm 2px bên ngoài bị cắt sạch. Ô đang focus trông như không\n * focus, và đó là dấu hiệu DUY NHẤT cho người dùng bàn phím.\n *\n * `p-1` cho 4,5px chỗ trống (rem gốc 18px); `-m-1` kéo hộp lại đúng bấy nhiêu nên vị trí\n * NỘI DUNG không đổi một pixel — khoảng cách tới header/footer vẫn là `gap-4`.\n *\n * ⚠ Đừng bê khuôn này sang `SheetContent`/`DrawerContent`: chúng `position: fixed` kèm\n * `inset-x-0`/`right-0`, nên margin ÂM làm chúng rộng ra 9px và tràn khỏi khung nhìn.\n * Ở đó, con phải tự mang padding — `SheetHeader`/`SheetFooter` đã có `p-4`.\n */\n className={cn(\"-m-1 min-h-0 flex-auto overflow-y-auto p-1\", className)}\n {...props}\n />\n );\n}\n\nexport type DialogHeaderProps = React.ComponentProps<\"div\">;\n\nfunction DialogHeader({ className, ...props }: DialogHeaderProps) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n );\n}\n\nexport type DialogFooterProps = React.ComponentProps<\"div\">;\n\nfunction DialogFooter({ className, ...props }: DialogFooterProps) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\", className)}\n {...props}\n />\n );\n}\n\nexport type DialogTitleProps = React.ComponentProps<typeof DialogPrimitive.Title>;\n\nfunction DialogTitle({ className, ...props }: DialogTitleProps) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-lg font-semibold text-foreground\", className)}\n {...props}\n />\n );\n}\n\nexport type DialogDescriptionProps = React.ComponentProps<typeof DialogPrimitive.Description>;\n\nfunction DialogDescription({ className, ...props }: DialogDescriptionProps) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Dialog,\n DialogBody,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger\n};\n"],"mappings":"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","names":[]}
|
|
@@ -10,7 +10,7 @@ declare function ItemGroup({ className, ...props }: ItemGroupProps): React.JSX.E
|
|
|
10
10
|
declare function ItemSeparator({ className, ...props }: ItemSeparatorProps): React.JSX.Element;
|
|
11
11
|
declare const itemVariants: (props?: ({
|
|
12
12
|
variant?: "default" | "outline" | "muted" | null | undefined;
|
|
13
|
-
size?: "
|
|
13
|
+
size?: "default" | "sm" | null | undefined;
|
|
14
14
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
15
15
|
interface ItemProps extends React.ComponentProps<"div">, VariantProps<typeof itemVariants> {
|
|
16
16
|
/** Render ra chính phần tử con (Radix Slot) — dùng khi cần <a> hoặc <button>. */
|
|
@@ -18,7 +18,7 @@ interface ItemProps extends React.ComponentProps<"div">, VariantProps<typeof ite
|
|
|
18
18
|
}
|
|
19
19
|
declare function Item({ className, variant, size, asChild, ...props }: ItemProps): React.JSX.Element;
|
|
20
20
|
declare const itemMediaVariants: (props?: ({
|
|
21
|
-
variant?: "
|
|
21
|
+
variant?: "default" | "image" | "icon" | null | undefined;
|
|
22
22
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
23
23
|
interface ItemMediaProps extends React.ComponentProps<"div">, VariantProps<typeof itemMediaVariants> {
|
|
24
24
|
}
|
|
@@ -31,6 +31,8 @@ interface KanbanAnnouncementInfo {
|
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
33
|
* Mọi chuỗi mà `Kanban` tự đọc/tự gắn. Chuỗi có số chèn vào là HÀM, không phải chuỗi mẫu.
|
|
34
|
+
* Theo `ComitorLocaleProvider` (mặc định tiếng Anh, bảng tiếng Việt dựng sẵn); đè từng khoá qua
|
|
35
|
+
* prop `labels` của `Kanban`.
|
|
34
36
|
*
|
|
35
37
|
* Bốn hàm đầu đi vào `accessibility.announcements` của dnd-kit (vùng `aria-live`). App vẫn có thể
|
|
36
38
|
* truyền thẳng `accessibility.announcements` như thượng nguồn — khi đó nó thắng hoàn toàn.
|
|
@@ -55,7 +57,11 @@ interface KanbanLabels {
|
|
|
55
57
|
/** Tên mặc định của `KanbanItemHandle` — tay cầm thường chỉ có một icon. */
|
|
56
58
|
itemHandleLabel: string;
|
|
57
59
|
}
|
|
58
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* Nhãn TIẾNG ANH mặc định (từ `3.0.0`; trước đó là tiếng Việt). Bảng tiếng Việt:
|
|
62
|
+
* `comitorMessagesVi.kanban`. Component không đọc thẳng hằng này — nó đọc bảng của
|
|
63
|
+
* `ComitorLocaleProvider`; hằng ở đây để app trải ra khi tự dựng nhãn.
|
|
64
|
+
*/
|
|
59
65
|
declare const DEFAULT_KANBAN_LABELS: KanbanLabels;
|
|
60
66
|
|
|
61
67
|
export { DEFAULT_KANBAN_LABELS, type KanbanAnnouncementInfo, type KanbanLabels };
|
|
@@ -1,20 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
}
|
|
4
|
-
function capitalizedNoun(variant) {
|
|
5
|
-
return variant === "column" ? "C\u1ED9t" : "Th\u1EBB";
|
|
6
|
-
}
|
|
7
|
-
const DEFAULT_KANBAN_LABELS = {
|
|
8
|
-
pickedUp: ({ variant, position, total }) => `\u0110\xE3 nh\u1EA5c ${noun(variant)} \u1EDF v\u1ECB tr\xED ${position} tr\xEAn ${total}.`,
|
|
9
|
-
moved: ({ variant, position, total, column }) => column === void 0 ? `${capitalizedNoun(variant)} \u0111ang \u1EDF v\u1ECB tr\xED ${position} tr\xEAn ${total}.` : `${capitalizedNoun(variant)} \u0111ang \u1EDF v\u1ECB tr\xED ${position} tr\xEAn ${total} trong c\u1ED9t ${column}.`,
|
|
10
|
-
dropped: ({ variant, position, total, column }) => column === void 0 ? `\u0110\xE3 th\u1EA3 ${noun(variant)} \u1EDF v\u1ECB tr\xED ${position} tr\xEAn ${total}.` : `\u0110\xE3 th\u1EA3 ${noun(variant)} \u1EDF v\u1ECB tr\xED ${position} tr\xEAn ${total} trong c\u1ED9t ${column}.`,
|
|
11
|
-
cancelled: ({ variant }) => `\u0110\xE3 hu\u1EF7 k\xE9o. ${capitalizedNoun(variant)} tr\u1EDF v\u1EC1 v\u1ECB tr\xED ban \u0111\u1EA7u.`,
|
|
12
|
-
instructions: "\u0110\u1EC3 nh\u1EA5c m\u1ED9t th\u1EBB ho\u1EB7c m\u1ED9t c\u1ED9t, nh\u1EA5n Space ho\u1EB7c Enter. Trong l\xFAc k\xE9o, d\xF9ng c\xE1c ph\xEDm m\u0169i t\xEAn \u0111\u1EC3 di chuy\u1EC3n. Nh\u1EA5n Space ho\u1EB7c Enter l\u1EA7n n\u1EEFa \u0111\u1EC3 th\u1EA3 v\xE0o v\u1ECB tr\xED m\u1EDBi, ho\u1EB7c nh\u1EA5n Escape \u0111\u1EC3 hu\u1EF7.",
|
|
13
|
-
columnRoleDescription: "c\u1ED9t k\xE9o th\u1EA3 \u0111\u01B0\u1EE3c",
|
|
14
|
-
itemRoleDescription: "th\u1EBB k\xE9o th\u1EA3 \u0111\u01B0\u1EE3c",
|
|
15
|
-
columnHandleLabel: "K\xE9o \u0111\u1EC3 di chuy\u1EC3n c\u1ED9t",
|
|
16
|
-
itemHandleLabel: "K\xE9o \u0111\u1EC3 di chuy\u1EC3n th\u1EBB"
|
|
17
|
-
};
|
|
1
|
+
import { kanbanEn } from "../../i18n/namespaces/kanban.js";
|
|
2
|
+
const DEFAULT_KANBAN_LABELS = { ...kanbanEn };
|
|
18
3
|
export {
|
|
19
4
|
DEFAULT_KANBAN_LABELS
|
|
20
5
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/kanban-constants.ts"],"sourcesContent":["/**\n * Nhãn mặc định của `Kanban` — lời xướng cho trình đọc màn hình và tên của tay cầm kéo.\n *\n * Module **CỐ Ý không có `\"use client\"`** — xem `src/chart/chart-colors.ts` để biết lý do đầy đủ:\n * mọi export của một file `\"use client\"` đến tay Server Component dưới dạng client-reference\n * proxy, đọc ra `undefined` mà KHÔNG throw, KHÔNG warning. `DEFAULT_KANBAN_LABELS` là một object\n * literal (dù phần lớn giá trị là HÀM) nên phải sống ngoài ranh giới client.\n *\n * ⚠ Barrel `src/index.ts` xuất module này TRỰC TIẾP. `kanban.tsx` chỉ được `import`, KHÔNG được\n * `export` lại (re-export qua file client là vô hiệu, và đụng tên với `export *`).\n */\n\nimport type { UniqueIdentifier } from \"@dnd-kit/core\";\n\n/** Dữ liệu dnd-kit đã tính sẵn, đưa vào các hàm xướng của `KanbanLabels`. */\nexport interface KanbanAnnouncementInfo {\n /** `\"column\"` khi đang kéo cả CỘT, `\"item\"` khi đang kéo một THẺ. */\n variant: \"column\" | \"item\";\n /** `value` của cột/thẻ đang kéo — dùng để tra ra TÊN hiển thị khi tự viết nhãn. */\n value: UniqueIdentifier;\n /** Vị trí hiện tại, đếm từ 1. */\n position: number;\n /** Tổng số cột (khi kéo cột) hoặc tổng số thẻ trong cột đang đứng (khi kéo thẻ). */\n total: number;\n /**\n * `value` của cột ĐÍCH — chỉ có khi thẻ vừa sang một cột KHÁC; `undefined` khi thẻ còn trong\n * cột cũ, và luôn `undefined` khi kéo cột. Là khoá máy (`\"inProgress\"`), không phải tên hiển\n * thị: app có tên cột thì tự viết hàm xướng và tra tên từ khoá này.\n */\n column?: UniqueIdentifier;\n}\n\n/**\n * Mọi chuỗi mà `Kanban` tự đọc/tự gắn. Chuỗi có số chèn vào là HÀM, không phải chuỗi mẫu.\n *\n * Bốn hàm đầu đi vào `accessibility.announcements` của dnd-kit (vùng `aria-live`). App vẫn có thể\n * truyền thẳng `accessibility.announcements` như thượng nguồn — khi đó nó thắng hoàn toàn.\n */\nexport interface KanbanLabels {\n /** Xướng lúc nhấc một cột/thẻ lên. */\n pickedUp: (info: KanbanAnnouncementInfo) => string;\n /** Xướng mỗi lần cột/thẻ đang kéo đổi chỗ. */\n moved: (info: KanbanAnnouncementInfo) => string;\n /** Xướng lúc thả. */\n dropped: (info: KanbanAnnouncementInfo) => string;\n /** Xướng lúc huỷ kéo (Escape) — cột/thẻ trở về chỗ cũ. */\n cancelled: (info: Pick<KanbanAnnouncementInfo, \"variant\" | \"value\">) => string;\n /** Hướng dẫn thao tác bàn phím, gắn vào mọi phần tử kéo được qua `aria-describedby`. */\n instructions: string;\n /** `aria-roledescription` của cột kéo được (và tay cầm của nó) — dnd-kit mặc định là \"sortable\". */\n columnRoleDescription: string;\n /** `aria-roledescription` của thẻ kéo được (và tay cầm của nó) — dnd-kit mặc định là \"sortable\". */\n itemRoleDescription: string;\n /** Tên mặc định của `KanbanColumnHandle` — tay cầm thường chỉ có một icon. */\n columnHandleLabel: string;\n /** Tên mặc định của `KanbanItemHandle` — tay cầm thường chỉ có một icon. */\n itemHandleLabel: string;\n}\n\
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/kanban-constants.ts"],"sourcesContent":["/**\n * Nhãn mặc định của `Kanban` — lời xướng cho trình đọc màn hình và tên của tay cầm kéo.\n *\n * Module **CỐ Ý không có `\"use client\"`** — xem `src/chart/chart-colors.ts` để biết lý do đầy đủ:\n * mọi export của một file `\"use client\"` đến tay Server Component dưới dạng client-reference\n * proxy, đọc ra `undefined` mà KHÔNG throw, KHÔNG warning. `DEFAULT_KANBAN_LABELS` là một object\n * literal (dù phần lớn giá trị là HÀM) nên phải sống ngoài ranh giới client.\n *\n * ⚠ Barrel `src/index.ts` xuất module này TRỰC TIẾP. `kanban.tsx` chỉ được `import`, KHÔNG được\n * `export` lại (re-export qua file client là vô hiệu, và đụng tên với `export *`).\n */\n\nimport type { UniqueIdentifier } from \"@dnd-kit/core\";\nimport { kanbanEn } from \"../../i18n/namespaces/kanban.js\";\n\n/** Dữ liệu dnd-kit đã tính sẵn, đưa vào các hàm xướng của `KanbanLabels`. */\nexport interface KanbanAnnouncementInfo {\n /** `\"column\"` khi đang kéo cả CỘT, `\"item\"` khi đang kéo một THẺ. */\n variant: \"column\" | \"item\";\n /** `value` của cột/thẻ đang kéo — dùng để tra ra TÊN hiển thị khi tự viết nhãn. */\n value: UniqueIdentifier;\n /** Vị trí hiện tại, đếm từ 1. */\n position: number;\n /** Tổng số cột (khi kéo cột) hoặc tổng số thẻ trong cột đang đứng (khi kéo thẻ). */\n total: number;\n /**\n * `value` của cột ĐÍCH — chỉ có khi thẻ vừa sang một cột KHÁC; `undefined` khi thẻ còn trong\n * cột cũ, và luôn `undefined` khi kéo cột. Là khoá máy (`\"inProgress\"`), không phải tên hiển\n * thị: app có tên cột thì tự viết hàm xướng và tra tên từ khoá này.\n */\n column?: UniqueIdentifier;\n}\n\n/**\n * Mọi chuỗi mà `Kanban` tự đọc/tự gắn. Chuỗi có số chèn vào là HÀM, không phải chuỗi mẫu.\n * Theo `ComitorLocaleProvider` (mặc định tiếng Anh, bảng tiếng Việt dựng sẵn); đè từng khoá qua\n * prop `labels` của `Kanban`.\n *\n * Bốn hàm đầu đi vào `accessibility.announcements` của dnd-kit (vùng `aria-live`). App vẫn có thể\n * truyền thẳng `accessibility.announcements` như thượng nguồn — khi đó nó thắng hoàn toàn.\n */\nexport interface KanbanLabels {\n /** Xướng lúc nhấc một cột/thẻ lên. */\n pickedUp: (info: KanbanAnnouncementInfo) => string;\n /** Xướng mỗi lần cột/thẻ đang kéo đổi chỗ. */\n moved: (info: KanbanAnnouncementInfo) => string;\n /** Xướng lúc thả. */\n dropped: (info: KanbanAnnouncementInfo) => string;\n /** Xướng lúc huỷ kéo (Escape) — cột/thẻ trở về chỗ cũ. */\n cancelled: (info: Pick<KanbanAnnouncementInfo, \"variant\" | \"value\">) => string;\n /** Hướng dẫn thao tác bàn phím, gắn vào mọi phần tử kéo được qua `aria-describedby`. */\n instructions: string;\n /** `aria-roledescription` của cột kéo được (và tay cầm của nó) — dnd-kit mặc định là \"sortable\". */\n columnRoleDescription: string;\n /** `aria-roledescription` của thẻ kéo được (và tay cầm của nó) — dnd-kit mặc định là \"sortable\". */\n itemRoleDescription: string;\n /** Tên mặc định của `KanbanColumnHandle` — tay cầm thường chỉ có một icon. */\n columnHandleLabel: string;\n /** Tên mặc định của `KanbanItemHandle` — tay cầm thường chỉ có một icon. */\n itemHandleLabel: string;\n}\n\n/**\n * Nhãn TIẾNG ANH mặc định (từ `3.0.0`; trước đó là tiếng Việt). Bảng tiếng Việt:\n * `comitorMessagesVi.kanban`. Component không đọc thẳng hằng này — nó đọc bảng của\n * `ComitorLocaleProvider`; hằng ở đây để app trải ra khi tự dựng nhãn.\n */\nexport const DEFAULT_KANBAN_LABELS: KanbanLabels = { ...kanbanEn };\n"],"mappings":"AAaA,SAAS,gBAAgB;AAsDlB,MAAM,wBAAsC,EAAE,GAAG,SAAS;","names":[]}
|
|
@@ -21,8 +21,8 @@ type KanbanProps<T> = Omit<DndContextProps, "collisionDetection"> & (T extends o
|
|
|
21
21
|
orientation?: "horizontal" | "vertical";
|
|
22
22
|
flatCursor?: boolean;
|
|
23
23
|
/**
|
|
24
|
-
* Lời xướng cho trình đọc màn hình, hướng dẫn bàn phím và tên tay cầm kéo —
|
|
25
|
-
*
|
|
24
|
+
* Lời xướng cho trình đọc màn hình, hướng dẫn bàn phím và tên tay cầm kéo — ghi đè TỪNG khoá.
|
|
25
|
+
* Không truyền thì theo namespace `kanban` của `ComitorLocaleProvider` (mặc định tiếng Anh).
|
|
26
26
|
*
|
|
27
27
|
* ⚠ Thêm so với thượng nguồn: bản gốc chôn cứng câu tiếng Anh ("Picked up item at position
|
|
28
28
|
* 2 of 5") trong component; chỉ đổi được bằng cách viết lại cả `accessibility.announcements`,
|
|
@@ -29,10 +29,10 @@ import { CSS, isKeyboardEvent } from "@dnd-kit/utilities";
|
|
|
29
29
|
import { Slot } from "@radix-ui/react-slot";
|
|
30
30
|
import * as React from "react";
|
|
31
31
|
import * as ReactDOM from "react-dom";
|
|
32
|
+
import { useComitorLabels } from "../../i18n/locale-provider.js";
|
|
32
33
|
import { cn } from "../../lib/cn.js";
|
|
33
34
|
import { useComposedRefs } from "../../lib/compose-refs.js";
|
|
34
35
|
import { useIsomorphicLayoutEffect } from "../../lib/use-isomorphic-layout-effect.js";
|
|
35
|
-
import { DEFAULT_KANBAN_LABELS } from "./kanban-constants.js";
|
|
36
36
|
const directions = /* @__PURE__ */ new Set([KeyboardCode.Down, KeyboardCode.Right, KeyboardCode.Up, KeyboardCode.Left]);
|
|
37
37
|
function getIsDirectionCode(code) {
|
|
38
38
|
return directions.has(code);
|
|
@@ -157,7 +157,7 @@ function Kanban(props) {
|
|
|
157
157
|
coordinateGetter
|
|
158
158
|
})
|
|
159
159
|
);
|
|
160
|
-
const labels =
|
|
160
|
+
const labels = useComitorLabels("kanban", labelsProp);
|
|
161
161
|
const getItemValue = React.useCallback(
|
|
162
162
|
(item) => {
|
|
163
163
|
if (typeof item === "object" && !getItemValueProp) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/kanban.tsx"],"sourcesContent":["\"use client\";\n\n/*\n * Port từ Dice UI (https://diceui.com/docs/components/kanban) — MIT, © 2024 Sadman Sakib.\n * Giữ nguyên cấu trúc thượng nguồn để còn đối chiếu ngược được; mọi chỗ đổi đều có chú thích.\n */\n\nimport {\n type Announcements,\n type CollisionDetection,\n closestCenter,\n closestCorners,\n DndContext,\n type DndContextProps,\n type DragCancelEvent,\n type DragEndEvent,\n type DraggableAttributes,\n type DraggableSyntheticListeners,\n type DragOverEvent,\n DragOverlay,\n type DragStartEvent,\n type DropAnimation,\n type DroppableContainer,\n defaultDropAnimationSideEffects,\n getFirstCollision,\n KeyboardCode,\n type KeyboardCoordinateGetter,\n KeyboardSensor,\n MeasuringStrategy,\n MouseSensor,\n pointerWithin,\n rectIntersection,\n TouchSensor,\n type UniqueIdentifier,\n useSensor,\n useSensors\n} from \"@dnd-kit/core\";\nimport {\n type AnimateLayoutChanges,\n arrayMove,\n defaultAnimateLayoutChanges,\n horizontalListSortingStrategy,\n SortableContext,\n type SortableContextProps,\n useSortable,\n verticalListSortingStrategy\n} from \"@dnd-kit/sortable\";\nimport { CSS, isKeyboardEvent } from \"@dnd-kit/utilities\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport * as ReactDOM from \"react-dom\";\nimport { cn } from \"../../lib/cn.js\";\nimport { useComposedRefs } from \"../../lib/compose-refs.js\";\nimport { useIsomorphicLayoutEffect } from \"../../lib/use-isomorphic-layout-effect.js\";\nimport { DEFAULT_KANBAN_LABELS, type KanbanLabels } from \"./kanban-constants.js\";\n\nconst directions = new Set<string>([KeyboardCode.Down, KeyboardCode.Right, KeyboardCode.Up, KeyboardCode.Left]);\n\nfunction getIsDirectionCode(code: string): code is KeyboardCode {\n return directions.has(code);\n}\n\nconst coordinateGetter: KeyboardCoordinateGetter = (event, { context }) => {\n const { active, droppableRects, droppableContainers, collisionRect } = context;\n\n if (getIsDirectionCode(event.code)) {\n event.preventDefault();\n\n if (!active || !collisionRect) return;\n\n const filteredContainers: DroppableContainer[] = [];\n\n /*\n * ⚠ Khác thượng nguồn: `continue` chứ không `return`. Vòng lặp này chép từ ví dụ \"multiple\n * containers\" của dnd-kit, nơi nó là `forEach` — ở đó `return` nghĩa là BỎ QUA MỘT mục. Bản\n * gốc đổi sang `for…of` nhưng giữ `return`, nên chỉ cần MỘT vùng thả chưa đo được rect là\n * cả hàm trả `undefined` và phím mũi tên không di chuyển được gì nữa.\n */\n for (const entry of droppableContainers.getEnabled()) {\n if (!entry || entry?.disabled) continue;\n\n const rect = droppableRects.get(entry.id);\n\n if (!rect) continue;\n\n const data = entry.data.current;\n\n if (data) {\n const { type, children } = data;\n\n if (type === \"container\" && children?.length > 0) {\n if (active.data.current?.type !== \"container\") {\n continue;\n }\n }\n }\n\n switch (event.code) {\n case KeyboardCode.Down:\n if (collisionRect.top < rect.top) {\n filteredContainers.push(entry);\n }\n break;\n case KeyboardCode.Up:\n if (collisionRect.top > rect.top) {\n filteredContainers.push(entry);\n }\n break;\n case KeyboardCode.Left:\n if (collisionRect.left >= rect.left + rect.width) {\n filteredContainers.push(entry);\n }\n break;\n case KeyboardCode.Right:\n if (collisionRect.left + collisionRect.width <= rect.left) {\n filteredContainers.push(entry);\n }\n break;\n }\n }\n\n const collisions = closestCorners({\n active,\n collisionRect: collisionRect,\n droppableRects,\n droppableContainers: filteredContainers,\n pointerCoordinates: null\n });\n const closestId = getFirstCollision(collisions, \"id\");\n\n if (closestId != null) {\n const newDroppable = droppableContainers.get(closestId);\n const newNode = newDroppable?.node.current;\n const newRect = newDroppable?.rect.current;\n\n if (newNode && newRect) {\n if (newDroppable.id === \"placeholder\") {\n return {\n x: newRect.left + (newRect.width - collisionRect.width) / 2,\n y: newRect.top + (newRect.height - collisionRect.height) / 2\n };\n }\n\n if (newDroppable.data.current?.type === \"container\") {\n return {\n x: newRect.left + 20,\n y: newRect.top + 74\n };\n }\n\n return {\n x: newRect.left,\n y: newRect.top\n };\n }\n }\n }\n\n return undefined;\n};\n\n/*\n * ⚠ Khác thượng nguồn: bản gốc bỏ qua MỌI thao tác khi `event.activatorEvent.defaultPrevented`\n * — một lối để app huỷ kéo bằng cách gọi `preventDefault()` trong `onDragStart` của mình. Nhưng\n * `KeyboardSensor` của dnd-kit TỰ gọi `preventDefault()` lên chính phím Space/Enter kích hoạt\n * (để trang không cuộn), và `activatorEvent` là đúng event đó. Hệ quả ở bản gốc: kéo bằng bàn\n * phím nhấc được thẻ nhưng `activeId` không bao giờ được gán, `onDragOver`/`onDragEnd` đều\n * thoát sớm — thả xong thẻ vẫn nằm nguyên chỗ cũ. Đã đo trên trình duyệt thật với phím thật:\n * Space → ArrowRight → Space, vùng `aria-live` đọc \"item was dropped at position 1 of 2 in\n * doing\" trong khi `onValueChange` KHÔNG được gọi lần nào — trình đọc màn hình báo đã thả, dữ\n * liệu không đổi. Lối huỷ bằng `preventDefault()` vì thế chỉ còn hiệu lực với chuột/cảm ứng;\n * với bàn phím, dùng `cancelDrop` của dnd-kit.\n */\nfunction isDragPrevented(event: { activatorEvent: Event }) {\n return event.activatorEvent.defaultPrevented && !isKeyboardEvent(event.activatorEvent);\n}\n\nconst ROOT_NAME = \"Kanban\";\nconst BOARD_NAME = \"KanbanBoard\";\nconst COLUMN_NAME = \"KanbanColumn\";\nconst COLUMN_HANDLE_NAME = \"KanbanColumnHandle\";\nconst ITEM_NAME = \"KanbanItem\";\nconst ITEM_HANDLE_NAME = \"KanbanItemHandle\";\nconst OVERLAY_NAME = \"KanbanOverlay\";\n\ninterface KanbanContextValue<T> {\n id: string;\n items: Record<UniqueIdentifier, T[]>;\n modifiers: DndContextProps[\"modifiers\"];\n strategy: SortableContextProps[\"strategy\"];\n orientation: \"horizontal\" | \"vertical\";\n activeId: UniqueIdentifier | null;\n setActiveId: (id: UniqueIdentifier | null) => void;\n getItemValue: (item: T) => UniqueIdentifier;\n flatCursor: boolean;\n labels: KanbanLabels;\n}\n\nconst KanbanContext = React.createContext<KanbanContextValue<unknown> | null>(null);\n\nfunction useKanbanContext(consumerName: string) {\n const context = React.useContext(KanbanContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ROOT_NAME}\\``);\n }\n return context;\n}\n\ninterface GetItemValue<T> {\n /**\n * Trả về định danh duy nhất của mỗi thẻ. BẮT BUỘC khi thẻ là object.\n * @example getItemValue={(item) => item.id}\n */\n getItemValue: (item: T) => UniqueIdentifier;\n}\n\ntype KanbanProps<T> = Omit<DndContextProps, \"collisionDetection\"> &\n (T extends object ? GetItemValue<T> : Partial<GetItemValue<T>>) & {\n value: Record<UniqueIdentifier, T[]>;\n onValueChange?: (columns: Record<UniqueIdentifier, T[]>) => void;\n onMove?: (event: DragEndEvent & { activeIndex: number; overIndex: number }) => void;\n strategy?: SortableContextProps[\"strategy\"];\n orientation?: \"horizontal\" | \"vertical\";\n flatCursor?: boolean;\n /**\n * Lời xướng cho trình đọc màn hình, hướng dẫn bàn phím và tên tay cầm kéo — mặc định tiếng\n * Việt (`DEFAULT_KANBAN_LABELS`), ghi đè TỪNG khoá.\n *\n * ⚠ Thêm so với thượng nguồn: bản gốc chôn cứng câu tiếng Anh (\"Picked up item at position\n * 2 of 5\") trong component; chỉ đổi được bằng cách viết lại cả `accessibility.announcements`,\n * tức tự tính lại vị trí/tổng số. Ở đây các hàm nhận sẵn `{ variant, value, position, total,\n * column }`. `accessibility` truyền thẳng vẫn được tôn trọng và THẮNG `labels`.\n */\n labels?: Partial<KanbanLabels>;\n };\n\nfunction Kanban<T>(props: KanbanProps<T>) {\n const {\n value,\n onValueChange,\n modifiers,\n strategy = verticalListSortingStrategy,\n orientation = \"horizontal\",\n onMove,\n getItemValue: getItemValueProp,\n accessibility,\n flatCursor = false,\n labels: labelsProp,\n ...kanbanProps\n } = props;\n\n const id = React.useId();\n const [activeId, setActiveId] = React.useState<UniqueIdentifier | null>(null);\n const lastOverIdRef = React.useRef<UniqueIdentifier | null>(null);\n const hasMovedRef = React.useRef(false);\n /*\n * ⚠ Khác thượng nguồn: `onDragOver` ghi thẳng mỗi lần đổi chỗ ra `onValueChange` (kéo tới\n * đâu, dữ liệu đổi tới đó), nên bản gốc huỷ bằng Escape KHÔNG trả thẻ về chỗ cũ — trái với\n * chính hướng dẫn bàn phím nó đọc cho người dùng (\"press escape to cancel\"). Chụp giá trị lúc\n * nhấc để `onDragCancel` trả lại, đúng như ví dụ \"multiple containers\" gốc của dnd-kit.\n */\n const valueAtDragStartRef = React.useRef<Record<UniqueIdentifier, T[]> | null>(null);\n const sensors = useSensors(\n useSensor(MouseSensor),\n useSensor(TouchSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter\n })\n );\n\n const labels = React.useMemo<KanbanLabels>(() => ({ ...DEFAULT_KANBAN_LABELS, ...labelsProp }), [labelsProp]);\n\n const getItemValue = React.useCallback(\n (item: T): UniqueIdentifier => {\n if (typeof item === \"object\" && !getItemValueProp) {\n throw new Error(\"`getItemValue` là bắt buộc khi thẻ là object\");\n }\n return getItemValueProp ? getItemValueProp(item) : (item as UniqueIdentifier);\n },\n [getItemValueProp]\n );\n\n const getColumn = React.useCallback(\n (targetId: UniqueIdentifier) => {\n if (targetId in value) return targetId;\n\n for (const [columnId, columnItems] of Object.entries(value)) {\n if (columnItems.some((item) => getItemValue(item) === targetId)) {\n return columnId;\n }\n }\n\n return null;\n },\n [value, getItemValue]\n );\n\n const collisionDetection: CollisionDetection = React.useCallback(\n (args) => {\n if (activeId && activeId in value) {\n return closestCenter({\n ...args,\n droppableContainers: args.droppableContainers.filter((container) => container.id in value)\n });\n }\n\n const pointerIntersections = pointerWithin(args);\n const intersections = pointerIntersections.length > 0 ? pointerIntersections : rectIntersection(args);\n let overId = getFirstCollision(intersections, \"id\");\n\n if (!overId) {\n if (hasMovedRef.current) {\n lastOverIdRef.current = activeId;\n }\n return lastOverIdRef.current ? [{ id: lastOverIdRef.current }] : [];\n }\n\n if (overId in value) {\n const containerItems = value[overId];\n if (containerItems && containerItems.length > 0) {\n const closestItem = closestCenter({\n ...args,\n droppableContainers: args.droppableContainers.filter(\n (container) =>\n container.id !== overId && containerItems.some((item) => getItemValue(item) === container.id)\n )\n });\n\n if (closestItem.length > 0) {\n overId = closestItem[0]?.id ?? overId;\n }\n }\n }\n\n lastOverIdRef.current = overId;\n return [{ id: overId }];\n },\n [activeId, value, getItemValue]\n );\n\n const onDragStart = React.useCallback(\n (event: DragStartEvent) => {\n kanbanProps.onDragStart?.(event);\n\n if (isDragPrevented(event)) return;\n setActiveId(event.active.id);\n valueAtDragStartRef.current = value;\n },\n [value, kanbanProps.onDragStart]\n );\n\n const onDragOver = React.useCallback(\n (event: DragOverEvent) => {\n kanbanProps.onDragOver?.(event);\n\n if (isDragPrevented(event)) return;\n\n const { active, over } = event;\n if (!over) return;\n\n const activeColumn = getColumn(active.id);\n const overColumn = getColumn(over.id);\n\n if (!activeColumn || !overColumn) return;\n\n if (activeColumn === overColumn) {\n const items = value[activeColumn];\n if (!items) return;\n\n const activeIndex = items.findIndex((item) => getItemValue(item) === active.id);\n const overIndex = items.findIndex((item) => getItemValue(item) === over.id);\n\n if (activeIndex !== overIndex) {\n const newColumns = { ...value };\n newColumns[activeColumn] = arrayMove(items, activeIndex, overIndex);\n onValueChange?.(newColumns);\n }\n } else {\n const activeItems = value[activeColumn];\n const overItems = value[overColumn];\n\n if (!activeItems || !overItems) return;\n\n const activeIndex = activeItems.findIndex((item) => getItemValue(item) === active.id);\n\n if (activeIndex === -1) return;\n\n const activeItem = activeItems[activeIndex];\n if (!activeItem) return;\n\n const updatedItems = {\n ...value,\n [activeColumn]: activeItems.filter((item) => getItemValue(item) !== active.id),\n [overColumn]: [...overItems, activeItem]\n };\n\n onValueChange?.(updatedItems);\n hasMovedRef.current = true;\n }\n },\n [value, getColumn, getItemValue, onValueChange, kanbanProps.onDragOver]\n );\n\n const onDragEnd = React.useCallback(\n (event: DragEndEvent) => {\n kanbanProps.onDragEnd?.(event);\n\n if (isDragPrevented(event)) return;\n\n valueAtDragStartRef.current = null;\n\n const { active, over } = event;\n\n if (!over) {\n setActiveId(null);\n return;\n }\n\n if (active.id in value && over.id in value) {\n const activeIndex = Object.keys(value).indexOf(active.id as string);\n const overIndex = Object.keys(value).indexOf(over.id as string);\n\n if (activeIndex !== overIndex) {\n const orderedColumns = Object.keys(value);\n const newOrder = arrayMove(orderedColumns, activeIndex, overIndex);\n\n const newColumns: Record<UniqueIdentifier, T[]> = {};\n for (const key of newOrder) {\n const items = value[key];\n if (items) {\n newColumns[key] = items;\n }\n }\n\n if (onMove) {\n onMove({ ...event, activeIndex, overIndex });\n } else {\n onValueChange?.(newColumns);\n }\n }\n } else {\n const activeColumn = getColumn(active.id);\n const overColumn = getColumn(over.id);\n\n if (!activeColumn || !overColumn) {\n setActiveId(null);\n return;\n }\n\n if (activeColumn === overColumn) {\n const items = value[activeColumn];\n if (!items) {\n setActiveId(null);\n return;\n }\n\n const activeIndex = items.findIndex((item) => getItemValue(item) === active.id);\n const overIndex = items.findIndex((item) => getItemValue(item) === over.id);\n\n if (activeIndex !== overIndex) {\n const newColumns = { ...value };\n newColumns[activeColumn] = arrayMove(items, activeIndex, overIndex);\n if (onMove) {\n onMove({\n ...event,\n activeIndex,\n overIndex\n });\n } else {\n onValueChange?.(newColumns);\n }\n }\n }\n }\n\n setActiveId(null);\n hasMovedRef.current = false;\n },\n [value, getColumn, getItemValue, onValueChange, onMove, kanbanProps.onDragEnd]\n );\n\n const onDragCancel = React.useCallback(\n (event: DragCancelEvent) => {\n kanbanProps.onDragCancel?.(event);\n\n if (isDragPrevented(event)) return;\n\n // Trả lại dữ liệu lúc nhấc — xem chú thích ở `valueAtDragStartRef`.\n const valueAtDragStart = valueAtDragStartRef.current;\n valueAtDragStartRef.current = null;\n if (valueAtDragStart && valueAtDragStart !== value) {\n onValueChange?.(valueAtDragStart);\n }\n\n setActiveId(null);\n hasMovedRef.current = false;\n },\n [value, onValueChange, kanbanProps.onDragCancel]\n );\n\n /*\n * ⚠ Khác thượng nguồn: câu chữ đi qua `labels` (tiếng Việt, ghi đè được); phần TÍNH vị trí và\n * tổng số giữ nguyên bản gốc.\n */\n const announcements: Announcements = React.useMemo(\n () => ({\n onDragStart({ active }) {\n const isColumn = active.id in value;\n const variant = isColumn ? \"column\" : \"item\";\n const position = isColumn\n ? Object.keys(value).indexOf(active.id as string) + 1\n : (() => {\n const column = getColumn(active.id);\n if (!column || !value[column]) return 1;\n return value[column].findIndex((item) => getItemValue(item) === active.id) + 1;\n })();\n const total = isColumn\n ? Object.keys(value).length\n : (() => {\n const column = getColumn(active.id);\n return column ? (value[column]?.length ?? 0) : 0;\n })();\n\n return labels.pickedUp({ variant, value: active.id, position, total });\n },\n onDragOver({ active, over }) {\n if (!over) return;\n\n const isColumn = active.id in value;\n const variant = isColumn ? \"column\" : \"item\";\n const position = isColumn\n ? Object.keys(value).indexOf(over.id as string) + 1\n : (() => {\n const column = getColumn(over.id);\n if (!column || !value[column]) return 1;\n return value[column].findIndex((item) => getItemValue(item) === over.id) + 1;\n })();\n const total = isColumn\n ? Object.keys(value).length\n : (() => {\n const column = getColumn(over.id);\n return column ? (value[column]?.length ?? 0) : 0;\n })();\n\n const overColumn = getColumn(over.id);\n const activeColumn = getColumn(active.id);\n\n if (isColumn) {\n return labels.moved({ variant, value: active.id, position, total });\n }\n\n if (activeColumn !== overColumn) {\n return labels.moved({ variant, value: active.id, position, total, column: overColumn ?? undefined });\n }\n\n return labels.moved({ variant, value: active.id, position, total });\n },\n onDragEnd({ active, over }) {\n if (!over) return;\n\n const isColumn = active.id in value;\n const variant = isColumn ? \"column\" : \"item\";\n const position = isColumn\n ? Object.keys(value).indexOf(over.id as string) + 1\n : (() => {\n const column = getColumn(over.id);\n if (!column || !value[column]) return 1;\n return value[column].findIndex((item) => getItemValue(item) === over.id) + 1;\n })();\n const total = isColumn\n ? Object.keys(value).length\n : (() => {\n const column = getColumn(over.id);\n return column ? (value[column]?.length ?? 0) : 0;\n })();\n\n const overColumn = getColumn(over.id);\n const activeColumn = getColumn(active.id);\n\n if (isColumn) {\n return labels.dropped({ variant, value: active.id, position, total });\n }\n\n if (activeColumn !== overColumn) {\n return labels.dropped({ variant, value: active.id, position, total, column: overColumn ?? undefined });\n }\n\n return labels.dropped({ variant, value: active.id, position, total });\n },\n onDragCancel({ active }) {\n const isColumn = active.id in value;\n return labels.cancelled({ variant: isColumn ? \"column\" : \"item\", value: active.id });\n }\n }),\n [value, getColumn, getItemValue, labels]\n );\n\n const contextValue = React.useMemo<KanbanContextValue<T>>(\n () => ({\n id,\n items: value,\n modifiers,\n strategy,\n orientation,\n activeId,\n setActiveId,\n getItemValue,\n flatCursor,\n labels\n }),\n [id, value, activeId, modifiers, strategy, orientation, getItemValue, flatCursor, labels]\n );\n\n return (\n <KanbanContext.Provider value={contextValue as KanbanContextValue<unknown>}>\n <DndContext\n collisionDetection={collisionDetection}\n modifiers={modifiers}\n sensors={sensors}\n {...kanbanProps}\n id={id}\n measuring={{\n droppable: {\n strategy: MeasuringStrategy.Always\n }\n }}\n onDragStart={onDragStart}\n onDragOver={onDragOver}\n onDragEnd={onDragEnd}\n onDragCancel={onDragCancel}\n accessibility={{\n announcements,\n screenReaderInstructions: {\n draggable: labels.instructions\n },\n ...accessibility\n }}\n />\n </KanbanContext.Provider>\n );\n}\n\nconst KanbanBoardContext = React.createContext<boolean>(false);\n\ninterface KanbanBoardProps extends React.ComponentProps<\"div\"> {\n children: React.ReactNode;\n asChild?: boolean;\n}\n\nfunction KanbanBoard(props: KanbanBoardProps) {\n const { asChild, className, ref, ...boardProps } = props;\n\n const context = useKanbanContext(BOARD_NAME);\n\n const columns = React.useMemo(() => {\n return Object.keys(context.items);\n }, [context.items]);\n\n const BoardPrimitive = asChild ? Slot : \"div\";\n\n return (\n <KanbanBoardContext.Provider value={true}>\n <SortableContext\n items={columns}\n strategy={context.orientation === \"horizontal\" ? horizontalListSortingStrategy : verticalListSortingStrategy}\n >\n <BoardPrimitive\n aria-orientation={context.orientation}\n data-orientation={context.orientation}\n data-slot=\"kanban-board\"\n {...boardProps}\n ref={ref}\n className={cn(\n \"flex size-full gap-4\",\n context.orientation === \"horizontal\" ? \"flex-row\" : \"flex-col\",\n className\n )}\n />\n </SortableContext>\n </KanbanBoardContext.Provider>\n );\n}\n\ninterface KanbanColumnContextValue {\n id: string;\n attributes: DraggableAttributes;\n listeners: DraggableSyntheticListeners | undefined;\n setActivatorNodeRef: (node: HTMLElement | null) => void;\n isDragging?: boolean;\n disabled?: boolean;\n}\n\nconst KanbanColumnContext = React.createContext<KanbanColumnContextValue | null>(null);\n\nfunction useKanbanColumnContext(consumerName: string) {\n const context = React.useContext(KanbanColumnContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${COLUMN_NAME}\\``);\n }\n return context;\n}\n\nconst animateLayoutChanges: AnimateLayoutChanges = (args) =>\n defaultAnimateLayoutChanges({ ...args, wasDragging: true });\n\ninterface KanbanColumnProps extends React.ComponentProps<\"div\"> {\n value: UniqueIdentifier;\n children: React.ReactNode;\n asChild?: boolean;\n asHandle?: boolean;\n disabled?: boolean;\n}\n\nfunction KanbanColumn(props: KanbanColumnProps) {\n const { value, asChild, asHandle, disabled, className, style, ref, ...columnProps } = props;\n\n const id = React.useId();\n const context = useKanbanContext(COLUMN_NAME);\n const inBoard = React.useContext(KanbanBoardContext);\n const inOverlay = React.useContext(KanbanOverlayContext);\n\n if (!inBoard && !inOverlay) {\n throw new Error(`\\`${COLUMN_NAME}\\` phải nằm bên trong \\`${BOARD_NAME}\\` hoặc \\`${OVERLAY_NAME}\\``);\n }\n\n if (value === \"\") {\n throw new Error(`\\`value\\` của \\`${COLUMN_NAME}\\` không được là chuỗi rỗng`);\n }\n\n const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({\n id: value,\n disabled,\n animateLayoutChanges,\n // ⚠ Khác thượng nguồn: dnd-kit mặc định đọc vai trò là \"sortable\" (tiếng Anh).\n attributes: { roleDescription: context.labels.columnRoleDescription }\n });\n\n const onNodeRefChange = React.useCallback(\n (node: HTMLElement | null) => {\n if (disabled) return;\n setNodeRef(node);\n },\n [disabled, setNodeRef]\n );\n\n const composedRef = useComposedRefs(ref, onNodeRefChange);\n\n const composedStyle = React.useMemo<React.CSSProperties>(() => {\n return {\n transform: CSS.Transform.toString(transform),\n transition,\n ...style\n };\n }, [transform, transition, style]);\n\n const items = React.useMemo(() => {\n const columnItems = context.items[value] ?? [];\n return columnItems.map((item) => context.getItemValue(item));\n }, [context.items, value, context.getItemValue]);\n\n const columnContext = React.useMemo<KanbanColumnContextValue>(\n () => ({\n id,\n attributes,\n listeners,\n setActivatorNodeRef,\n isDragging,\n disabled\n }),\n [id, attributes, listeners, setActivatorNodeRef, isDragging, disabled]\n );\n\n const ColumnPrimitive = asChild ? Slot : \"div\";\n\n return (\n <KanbanColumnContext.Provider value={columnContext}>\n <SortableContext\n items={items}\n strategy={context.orientation === \"horizontal\" ? horizontalListSortingStrategy : verticalListSortingStrategy}\n >\n <ColumnPrimitive\n id={id}\n // ⚠ Khác thượng nguồn: `disabled={false}` từng ra `data-disabled=\"false\"` — thuộc tính\n // VẪN CÓ MẶT, nên mọi selector `[data-disabled]` khớp nhầm cột đang bật.\n data-disabled={disabled ? \"\" : undefined}\n data-dragging={isDragging ? \"\" : undefined}\n data-slot=\"kanban-column\"\n {...columnProps}\n {...(asHandle && !disabled ? attributes : {})}\n {...(asHandle && !disabled ? listeners : {})}\n ref={composedRef}\n style={composedStyle}\n className={cn(\n /*\n * ⚠ Khác thượng nguồn: `bg-zinc-100 dark:bg-zinc-900` là thang mặc định của Tailwind\n * (cổng màu chặn) → `bg-muted`, tự lật theo theme. Khung cột là viền TRANG TRÍ (không\n * bấm được, không mang trạng thái) nên `border-border` là đúng vai trò.\n */\n \"flex size-full flex-col gap-2 rounded-lg border border-border bg-muted p-2.5 aria-disabled:pointer-events-none aria-disabled:opacity-50\",\n {\n \"touch-none select-none\": asHandle,\n \"cursor-default\": context.flatCursor,\n \"data-dragging:cursor-grabbing\": !context.flatCursor,\n \"cursor-grab\": !isDragging && asHandle && !context.flatCursor,\n \"opacity-50\": isDragging,\n \"pointer-events-none opacity-50\": disabled,\n // ⚠ Khác thượng nguồn: bản sao trong `KanbanOverlay` được nâng lên bằng bóng nổi.\n \"shadow-overlay\": inOverlay\n },\n className\n )}\n />\n </SortableContext>\n </KanbanColumnContext.Provider>\n );\n}\n\ninterface KanbanColumnHandleProps extends React.ComponentProps<\"button\"> {\n asChild?: boolean;\n}\n\nfunction KanbanColumnHandle(props: KanbanColumnHandleProps) {\n const { asChild, disabled, className, ref, ...columnHandleProps } = props;\n\n const context = useKanbanContext(COLUMN_HANDLE_NAME);\n const columnContext = useKanbanColumnContext(COLUMN_HANDLE_NAME);\n\n const isDisabled = disabled ?? columnContext.disabled;\n\n const { setActivatorNodeRef } = columnContext;\n\n const onActivatorNodeRef = React.useCallback(\n (node: HTMLElement | null) => {\n if (isDisabled) return;\n setActivatorNodeRef(node);\n },\n [isDisabled, setActivatorNodeRef]\n );\n\n const composedRef = useComposedRefs(ref, onActivatorNodeRef);\n\n const HandlePrimitive = asChild ? Slot : \"button\";\n\n return (\n <HandlePrimitive\n type=\"button\"\n /*\n * ⚠ Khác thượng nguồn: tay cầm gần như luôn chỉ chứa một icon (GripVertical) → nút KHÔNG\n * TÊN. Tên mặc định đứng TRƯỚC `{...columnHandleProps}` nên `aria-label` của app (hoặc của\n * phần tử con khi `asChild`) vẫn thắng.\n */\n aria-label={context.labels.columnHandleLabel}\n aria-controls={columnContext.id}\n data-disabled={isDisabled ? \"\" : undefined}\n data-dragging={columnContext.isDragging ? \"\" : undefined}\n data-slot=\"kanban-column-handle\"\n {...columnHandleProps}\n {...(isDisabled ? {} : columnContext.attributes)}\n {...(isDisabled ? {} : columnContext.listeners)}\n ref={composedRef}\n className={cn(\n \"select-none disabled:pointer-events-none disabled:opacity-50\",\n context.flatCursor ? \"cursor-default\" : \"cursor-grab data-dragging:cursor-grabbing\",\n className\n )}\n disabled={isDisabled}\n />\n );\n}\n\ninterface KanbanItemContextValue {\n id: string;\n attributes: DraggableAttributes;\n listeners: DraggableSyntheticListeners | undefined;\n setActivatorNodeRef: (node: HTMLElement | null) => void;\n isDragging?: boolean;\n disabled?: boolean;\n}\n\nconst KanbanItemContext = React.createContext<KanbanItemContextValue | null>(null);\n\nfunction useKanbanItemContext(consumerName: string) {\n const context = React.useContext(KanbanItemContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ITEM_NAME}\\``);\n }\n return context;\n}\n\ninterface KanbanItemProps extends React.ComponentProps<\"div\"> {\n value: UniqueIdentifier;\n asHandle?: boolean;\n asChild?: boolean;\n disabled?: boolean;\n}\n\nfunction KanbanItem(props: KanbanItemProps) {\n const { value, style, asHandle, asChild, disabled, className, ref, ...itemProps } = props;\n\n const id = React.useId();\n const context = useKanbanContext(ITEM_NAME);\n const inBoard = React.useContext(KanbanBoardContext);\n const inOverlay = React.useContext(KanbanOverlayContext);\n\n if (!inBoard && !inOverlay) {\n throw new Error(`\\`${ITEM_NAME}\\` phải nằm bên trong \\`${BOARD_NAME}\\``);\n }\n\n const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({\n id: value,\n disabled,\n // ⚠ Khác thượng nguồn: dnd-kit mặc định đọc vai trò là \"sortable\" (tiếng Anh).\n attributes: { roleDescription: context.labels.itemRoleDescription }\n });\n\n if (value === \"\") {\n throw new Error(`\\`value\\` của \\`${ITEM_NAME}\\` không được là chuỗi rỗng`);\n }\n\n // Giữ ổn định để React không gỡ rồi gắn lại ref node của dnd-kit mỗi lượt render — việc đó\n // kích hoạt đo lại vùng thả ngay giữa lúc kéo.\n const onNodeRef = React.useCallback(\n (node: HTMLElement | null) => {\n if (disabled) return;\n setNodeRef(node);\n },\n [disabled, setNodeRef]\n );\n\n const composedRef = useComposedRefs(ref, onNodeRef);\n\n const composedStyle = React.useMemo<React.CSSProperties>(() => {\n return {\n transform: CSS.Transform.toString(transform),\n transition,\n ...style\n };\n }, [transform, transition, style]);\n\n const itemContext = React.useMemo<KanbanItemContextValue>(\n () => ({\n id,\n attributes,\n listeners,\n setActivatorNodeRef,\n isDragging,\n disabled\n }),\n [id, attributes, listeners, setActivatorNodeRef, isDragging, disabled]\n );\n\n const ItemPrimitive = asChild ? Slot : \"div\";\n\n return (\n <KanbanItemContext.Provider value={itemContext}>\n <ItemPrimitive\n id={id}\n // ⚠ Khác thượng nguồn: xem chú thích `data-disabled` ở `KanbanColumn`.\n data-disabled={disabled ? \"\" : undefined}\n data-dragging={isDragging ? \"\" : undefined}\n data-slot=\"kanban-item\"\n {...itemProps}\n {...(asHandle && !disabled ? attributes : {})}\n {...(asHandle && !disabled ? listeners : {})}\n ref={composedRef}\n style={composedStyle}\n className={cn(\n // Viền focus cùng khuôn với `Checkbox`/`RadioGroup` của gói.\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n {\n \"touch-none select-none\": asHandle,\n \"cursor-default\": context.flatCursor,\n \"data-dragging:cursor-grabbing\": !context.flatCursor,\n \"cursor-grab\": !isDragging && asHandle && !context.flatCursor,\n \"opacity-50\": isDragging,\n \"pointer-events-none opacity-50\": disabled,\n // ⚠ Khác thượng nguồn: bản sao trong `KanbanOverlay` được nâng lên bằng bóng nổi.\n // Bóng theo bo góc của CHÍNH phần tử — dùng `asChild` lên thẻ để bóng ôm đúng góc.\n \"shadow-overlay\": inOverlay\n },\n className\n )}\n />\n </KanbanItemContext.Provider>\n );\n}\n\ninterface KanbanItemHandleProps extends React.ComponentProps<\"button\"> {\n asChild?: boolean;\n}\n\nfunction KanbanItemHandle(props: KanbanItemHandleProps) {\n const { asChild, disabled, className, ref, ...itemHandleProps } = props;\n\n const context = useKanbanContext(ITEM_HANDLE_NAME);\n const itemContext = useKanbanItemContext(ITEM_HANDLE_NAME);\n\n const isDisabled = disabled ?? itemContext.disabled;\n\n const { setActivatorNodeRef } = itemContext;\n\n const onActivatorNodeRef = React.useCallback(\n (node: HTMLElement | null) => {\n if (isDisabled) return;\n setActivatorNodeRef(node);\n },\n [isDisabled, setActivatorNodeRef]\n );\n\n const composedRef = useComposedRefs(ref, onActivatorNodeRef);\n\n const HandlePrimitive = asChild ? Slot : \"button\";\n\n return (\n <HandlePrimitive\n type=\"button\"\n // ⚠ Khác thượng nguồn: tên mặc định cho tay cầm chỉ có icon — xem `KanbanColumnHandle`.\n aria-label={context.labels.itemHandleLabel}\n aria-controls={itemContext.id}\n data-disabled={isDisabled ? \"\" : undefined}\n data-dragging={itemContext.isDragging ? \"\" : undefined}\n data-slot=\"kanban-item-handle\"\n {...itemHandleProps}\n {...(isDisabled ? {} : itemContext.attributes)}\n {...(isDisabled ? {} : itemContext.listeners)}\n ref={composedRef}\n className={cn(\n \"select-none disabled:pointer-events-none disabled:opacity-50\",\n context.flatCursor ? \"cursor-default\" : \"cursor-grab data-dragging:cursor-grabbing\",\n className\n )}\n disabled={isDisabled}\n />\n );\n}\n\nconst KanbanOverlayContext = React.createContext(false);\n\nconst dropAnimation: DropAnimation = {\n sideEffects: defaultDropAnimationSideEffects({\n styles: {\n active: {\n opacity: \"0.4\"\n }\n }\n })\n};\n\ninterface KanbanOverlayProps extends Omit<React.ComponentProps<typeof DragOverlay>, \"children\"> {\n container?: Element | DocumentFragment | null;\n children?: React.ReactNode | ((params: { value: UniqueIdentifier; variant: \"column\" | \"item\" }) => React.ReactNode);\n}\n\nfunction KanbanOverlay(props: KanbanOverlayProps) {\n const { container: containerProp, children, ...overlayProps } = props;\n\n const context = useKanbanContext(OVERLAY_NAME);\n\n const [mounted, setMounted] = React.useState(false);\n\n // ⚠ Khác thượng nguồn: `useIsomorphicLayoutEffect` thay `React.useLayoutEffect` — an toàn khi SSR.\n useIsomorphicLayoutEffect(() => setMounted(true), []);\n\n const container = containerProp ?? (mounted ? globalThis.document?.body : null);\n\n if (!container) return null;\n\n const variant = context.activeId && context.activeId in context.items ? \"column\" : \"item\";\n\n return ReactDOM.createPortal(\n <DragOverlay\n dropAnimation={dropAnimation}\n modifiers={context.modifiers}\n className={cn(!context.flatCursor && \"cursor-grabbing\")}\n {...overlayProps}\n >\n <KanbanOverlayContext.Provider value={true}>\n {context.activeId && children\n ? typeof children === \"function\"\n ? children({\n value: context.activeId,\n variant\n })\n : children\n : null}\n </KanbanOverlayContext.Provider>\n </DragOverlay>,\n container\n );\n}\n\nexport {\n Kanban,\n KanbanBoard,\n type KanbanBoardProps,\n KanbanColumn,\n KanbanColumnHandle,\n type KanbanColumnHandleProps,\n type KanbanColumnProps,\n KanbanItem,\n KanbanItemHandle,\n type KanbanItemHandleProps,\n type KanbanItemProps,\n KanbanOverlay,\n type KanbanOverlayProps,\n type KanbanProps\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/kanban.tsx"],"sourcesContent":["\"use client\";\n\n/*\n * Port từ Dice UI (https://diceui.com/docs/components/kanban) — MIT, © 2024 Sadman Sakib.\n * Giữ nguyên cấu trúc thượng nguồn để còn đối chiếu ngược được; mọi chỗ đổi đều có chú thích.\n */\n\nimport {\n type Announcements,\n type CollisionDetection,\n closestCenter,\n closestCorners,\n DndContext,\n type DndContextProps,\n type DragCancelEvent,\n type DragEndEvent,\n type DraggableAttributes,\n type DraggableSyntheticListeners,\n type DragOverEvent,\n DragOverlay,\n type DragStartEvent,\n type DropAnimation,\n type DroppableContainer,\n defaultDropAnimationSideEffects,\n getFirstCollision,\n KeyboardCode,\n type KeyboardCoordinateGetter,\n KeyboardSensor,\n MeasuringStrategy,\n MouseSensor,\n pointerWithin,\n rectIntersection,\n TouchSensor,\n type UniqueIdentifier,\n useSensor,\n useSensors\n} from \"@dnd-kit/core\";\nimport {\n type AnimateLayoutChanges,\n arrayMove,\n defaultAnimateLayoutChanges,\n horizontalListSortingStrategy,\n SortableContext,\n type SortableContextProps,\n useSortable,\n verticalListSortingStrategy\n} from \"@dnd-kit/sortable\";\nimport { CSS, isKeyboardEvent } from \"@dnd-kit/utilities\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport * as ReactDOM from \"react-dom\";\nimport { useComitorLabels } from \"../../i18n/locale-provider.js\";\nimport { cn } from \"../../lib/cn.js\";\nimport { useComposedRefs } from \"../../lib/compose-refs.js\";\nimport { useIsomorphicLayoutEffect } from \"../../lib/use-isomorphic-layout-effect.js\";\nimport type { KanbanLabels } from \"./kanban-constants.js\";\n\nconst directions = new Set<string>([KeyboardCode.Down, KeyboardCode.Right, KeyboardCode.Up, KeyboardCode.Left]);\n\nfunction getIsDirectionCode(code: string): code is KeyboardCode {\n return directions.has(code);\n}\n\nconst coordinateGetter: KeyboardCoordinateGetter = (event, { context }) => {\n const { active, droppableRects, droppableContainers, collisionRect } = context;\n\n if (getIsDirectionCode(event.code)) {\n event.preventDefault();\n\n if (!active || !collisionRect) return;\n\n const filteredContainers: DroppableContainer[] = [];\n\n /*\n * ⚠ Khác thượng nguồn: `continue` chứ không `return`. Vòng lặp này chép từ ví dụ \"multiple\n * containers\" của dnd-kit, nơi nó là `forEach` — ở đó `return` nghĩa là BỎ QUA MỘT mục. Bản\n * gốc đổi sang `for…of` nhưng giữ `return`, nên chỉ cần MỘT vùng thả chưa đo được rect là\n * cả hàm trả `undefined` và phím mũi tên không di chuyển được gì nữa.\n */\n for (const entry of droppableContainers.getEnabled()) {\n if (!entry || entry?.disabled) continue;\n\n const rect = droppableRects.get(entry.id);\n\n if (!rect) continue;\n\n const data = entry.data.current;\n\n if (data) {\n const { type, children } = data;\n\n if (type === \"container\" && children?.length > 0) {\n if (active.data.current?.type !== \"container\") {\n continue;\n }\n }\n }\n\n switch (event.code) {\n case KeyboardCode.Down:\n if (collisionRect.top < rect.top) {\n filteredContainers.push(entry);\n }\n break;\n case KeyboardCode.Up:\n if (collisionRect.top > rect.top) {\n filteredContainers.push(entry);\n }\n break;\n case KeyboardCode.Left:\n if (collisionRect.left >= rect.left + rect.width) {\n filteredContainers.push(entry);\n }\n break;\n case KeyboardCode.Right:\n if (collisionRect.left + collisionRect.width <= rect.left) {\n filteredContainers.push(entry);\n }\n break;\n }\n }\n\n const collisions = closestCorners({\n active,\n collisionRect: collisionRect,\n droppableRects,\n droppableContainers: filteredContainers,\n pointerCoordinates: null\n });\n const closestId = getFirstCollision(collisions, \"id\");\n\n if (closestId != null) {\n const newDroppable = droppableContainers.get(closestId);\n const newNode = newDroppable?.node.current;\n const newRect = newDroppable?.rect.current;\n\n if (newNode && newRect) {\n if (newDroppable.id === \"placeholder\") {\n return {\n x: newRect.left + (newRect.width - collisionRect.width) / 2,\n y: newRect.top + (newRect.height - collisionRect.height) / 2\n };\n }\n\n if (newDroppable.data.current?.type === \"container\") {\n return {\n x: newRect.left + 20,\n y: newRect.top + 74\n };\n }\n\n return {\n x: newRect.left,\n y: newRect.top\n };\n }\n }\n }\n\n return undefined;\n};\n\n/*\n * ⚠ Khác thượng nguồn: bản gốc bỏ qua MỌI thao tác khi `event.activatorEvent.defaultPrevented`\n * — một lối để app huỷ kéo bằng cách gọi `preventDefault()` trong `onDragStart` của mình. Nhưng\n * `KeyboardSensor` của dnd-kit TỰ gọi `preventDefault()` lên chính phím Space/Enter kích hoạt\n * (để trang không cuộn), và `activatorEvent` là đúng event đó. Hệ quả ở bản gốc: kéo bằng bàn\n * phím nhấc được thẻ nhưng `activeId` không bao giờ được gán, `onDragOver`/`onDragEnd` đều\n * thoát sớm — thả xong thẻ vẫn nằm nguyên chỗ cũ. Đã đo trên trình duyệt thật với phím thật:\n * Space → ArrowRight → Space, vùng `aria-live` đọc \"item was dropped at position 1 of 2 in\n * doing\" trong khi `onValueChange` KHÔNG được gọi lần nào — trình đọc màn hình báo đã thả, dữ\n * liệu không đổi. Lối huỷ bằng `preventDefault()` vì thế chỉ còn hiệu lực với chuột/cảm ứng;\n * với bàn phím, dùng `cancelDrop` của dnd-kit.\n */\nfunction isDragPrevented(event: { activatorEvent: Event }) {\n return event.activatorEvent.defaultPrevented && !isKeyboardEvent(event.activatorEvent);\n}\n\nconst ROOT_NAME = \"Kanban\";\nconst BOARD_NAME = \"KanbanBoard\";\nconst COLUMN_NAME = \"KanbanColumn\";\nconst COLUMN_HANDLE_NAME = \"KanbanColumnHandle\";\nconst ITEM_NAME = \"KanbanItem\";\nconst ITEM_HANDLE_NAME = \"KanbanItemHandle\";\nconst OVERLAY_NAME = \"KanbanOverlay\";\n\ninterface KanbanContextValue<T> {\n id: string;\n items: Record<UniqueIdentifier, T[]>;\n modifiers: DndContextProps[\"modifiers\"];\n strategy: SortableContextProps[\"strategy\"];\n orientation: \"horizontal\" | \"vertical\";\n activeId: UniqueIdentifier | null;\n setActiveId: (id: UniqueIdentifier | null) => void;\n getItemValue: (item: T) => UniqueIdentifier;\n flatCursor: boolean;\n labels: KanbanLabels;\n}\n\nconst KanbanContext = React.createContext<KanbanContextValue<unknown> | null>(null);\n\nfunction useKanbanContext(consumerName: string) {\n const context = React.useContext(KanbanContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ROOT_NAME}\\``);\n }\n return context;\n}\n\ninterface GetItemValue<T> {\n /**\n * Trả về định danh duy nhất của mỗi thẻ. BẮT BUỘC khi thẻ là object.\n * @example getItemValue={(item) => item.id}\n */\n getItemValue: (item: T) => UniqueIdentifier;\n}\n\ntype KanbanProps<T> = Omit<DndContextProps, \"collisionDetection\"> &\n (T extends object ? GetItemValue<T> : Partial<GetItemValue<T>>) & {\n value: Record<UniqueIdentifier, T[]>;\n onValueChange?: (columns: Record<UniqueIdentifier, T[]>) => void;\n onMove?: (event: DragEndEvent & { activeIndex: number; overIndex: number }) => void;\n strategy?: SortableContextProps[\"strategy\"];\n orientation?: \"horizontal\" | \"vertical\";\n flatCursor?: boolean;\n /**\n * Lời xướng cho trình đọc màn hình, hướng dẫn bàn phím và tên tay cầm kéo — ghi đè TỪNG khoá.\n * Không truyền thì theo namespace `kanban` của `ComitorLocaleProvider` (mặc định tiếng Anh).\n *\n * ⚠ Thêm so với thượng nguồn: bản gốc chôn cứng câu tiếng Anh (\"Picked up item at position\n * 2 of 5\") trong component; chỉ đổi được bằng cách viết lại cả `accessibility.announcements`,\n * tức tự tính lại vị trí/tổng số. Ở đây các hàm nhận sẵn `{ variant, value, position, total,\n * column }`. `accessibility` truyền thẳng vẫn được tôn trọng và THẮNG `labels`.\n */\n labels?: Partial<KanbanLabels>;\n };\n\nfunction Kanban<T>(props: KanbanProps<T>) {\n const {\n value,\n onValueChange,\n modifiers,\n strategy = verticalListSortingStrategy,\n orientation = \"horizontal\",\n onMove,\n getItemValue: getItemValueProp,\n accessibility,\n flatCursor = false,\n labels: labelsProp,\n ...kanbanProps\n } = props;\n\n const id = React.useId();\n const [activeId, setActiveId] = React.useState<UniqueIdentifier | null>(null);\n const lastOverIdRef = React.useRef<UniqueIdentifier | null>(null);\n const hasMovedRef = React.useRef(false);\n /*\n * ⚠ Khác thượng nguồn: `onDragOver` ghi thẳng mỗi lần đổi chỗ ra `onValueChange` (kéo tới\n * đâu, dữ liệu đổi tới đó), nên bản gốc huỷ bằng Escape KHÔNG trả thẻ về chỗ cũ — trái với\n * chính hướng dẫn bàn phím nó đọc cho người dùng (\"press escape to cancel\"). Chụp giá trị lúc\n * nhấc để `onDragCancel` trả lại, đúng như ví dụ \"multiple containers\" gốc của dnd-kit.\n */\n const valueAtDragStartRef = React.useRef<Record<UniqueIdentifier, T[]> | null>(null);\n const sensors = useSensors(\n useSensor(MouseSensor),\n useSensor(TouchSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter\n })\n );\n\n const labels = useComitorLabels(\"kanban\", labelsProp);\n\n const getItemValue = React.useCallback(\n (item: T): UniqueIdentifier => {\n if (typeof item === \"object\" && !getItemValueProp) {\n throw new Error(\"`getItemValue` là bắt buộc khi thẻ là object\");\n }\n return getItemValueProp ? getItemValueProp(item) : (item as UniqueIdentifier);\n },\n [getItemValueProp]\n );\n\n const getColumn = React.useCallback(\n (targetId: UniqueIdentifier) => {\n if (targetId in value) return targetId;\n\n for (const [columnId, columnItems] of Object.entries(value)) {\n if (columnItems.some((item) => getItemValue(item) === targetId)) {\n return columnId;\n }\n }\n\n return null;\n },\n [value, getItemValue]\n );\n\n const collisionDetection: CollisionDetection = React.useCallback(\n (args) => {\n if (activeId && activeId in value) {\n return closestCenter({\n ...args,\n droppableContainers: args.droppableContainers.filter((container) => container.id in value)\n });\n }\n\n const pointerIntersections = pointerWithin(args);\n const intersections = pointerIntersections.length > 0 ? pointerIntersections : rectIntersection(args);\n let overId = getFirstCollision(intersections, \"id\");\n\n if (!overId) {\n if (hasMovedRef.current) {\n lastOverIdRef.current = activeId;\n }\n return lastOverIdRef.current ? [{ id: lastOverIdRef.current }] : [];\n }\n\n if (overId in value) {\n const containerItems = value[overId];\n if (containerItems && containerItems.length > 0) {\n const closestItem = closestCenter({\n ...args,\n droppableContainers: args.droppableContainers.filter(\n (container) =>\n container.id !== overId && containerItems.some((item) => getItemValue(item) === container.id)\n )\n });\n\n if (closestItem.length > 0) {\n overId = closestItem[0]?.id ?? overId;\n }\n }\n }\n\n lastOverIdRef.current = overId;\n return [{ id: overId }];\n },\n [activeId, value, getItemValue]\n );\n\n const onDragStart = React.useCallback(\n (event: DragStartEvent) => {\n kanbanProps.onDragStart?.(event);\n\n if (isDragPrevented(event)) return;\n setActiveId(event.active.id);\n valueAtDragStartRef.current = value;\n },\n [value, kanbanProps.onDragStart]\n );\n\n const onDragOver = React.useCallback(\n (event: DragOverEvent) => {\n kanbanProps.onDragOver?.(event);\n\n if (isDragPrevented(event)) return;\n\n const { active, over } = event;\n if (!over) return;\n\n const activeColumn = getColumn(active.id);\n const overColumn = getColumn(over.id);\n\n if (!activeColumn || !overColumn) return;\n\n if (activeColumn === overColumn) {\n const items = value[activeColumn];\n if (!items) return;\n\n const activeIndex = items.findIndex((item) => getItemValue(item) === active.id);\n const overIndex = items.findIndex((item) => getItemValue(item) === over.id);\n\n if (activeIndex !== overIndex) {\n const newColumns = { ...value };\n newColumns[activeColumn] = arrayMove(items, activeIndex, overIndex);\n onValueChange?.(newColumns);\n }\n } else {\n const activeItems = value[activeColumn];\n const overItems = value[overColumn];\n\n if (!activeItems || !overItems) return;\n\n const activeIndex = activeItems.findIndex((item) => getItemValue(item) === active.id);\n\n if (activeIndex === -1) return;\n\n const activeItem = activeItems[activeIndex];\n if (!activeItem) return;\n\n const updatedItems = {\n ...value,\n [activeColumn]: activeItems.filter((item) => getItemValue(item) !== active.id),\n [overColumn]: [...overItems, activeItem]\n };\n\n onValueChange?.(updatedItems);\n hasMovedRef.current = true;\n }\n },\n [value, getColumn, getItemValue, onValueChange, kanbanProps.onDragOver]\n );\n\n const onDragEnd = React.useCallback(\n (event: DragEndEvent) => {\n kanbanProps.onDragEnd?.(event);\n\n if (isDragPrevented(event)) return;\n\n valueAtDragStartRef.current = null;\n\n const { active, over } = event;\n\n if (!over) {\n setActiveId(null);\n return;\n }\n\n if (active.id in value && over.id in value) {\n const activeIndex = Object.keys(value).indexOf(active.id as string);\n const overIndex = Object.keys(value).indexOf(over.id as string);\n\n if (activeIndex !== overIndex) {\n const orderedColumns = Object.keys(value);\n const newOrder = arrayMove(orderedColumns, activeIndex, overIndex);\n\n const newColumns: Record<UniqueIdentifier, T[]> = {};\n for (const key of newOrder) {\n const items = value[key];\n if (items) {\n newColumns[key] = items;\n }\n }\n\n if (onMove) {\n onMove({ ...event, activeIndex, overIndex });\n } else {\n onValueChange?.(newColumns);\n }\n }\n } else {\n const activeColumn = getColumn(active.id);\n const overColumn = getColumn(over.id);\n\n if (!activeColumn || !overColumn) {\n setActiveId(null);\n return;\n }\n\n if (activeColumn === overColumn) {\n const items = value[activeColumn];\n if (!items) {\n setActiveId(null);\n return;\n }\n\n const activeIndex = items.findIndex((item) => getItemValue(item) === active.id);\n const overIndex = items.findIndex((item) => getItemValue(item) === over.id);\n\n if (activeIndex !== overIndex) {\n const newColumns = { ...value };\n newColumns[activeColumn] = arrayMove(items, activeIndex, overIndex);\n if (onMove) {\n onMove({\n ...event,\n activeIndex,\n overIndex\n });\n } else {\n onValueChange?.(newColumns);\n }\n }\n }\n }\n\n setActiveId(null);\n hasMovedRef.current = false;\n },\n [value, getColumn, getItemValue, onValueChange, onMove, kanbanProps.onDragEnd]\n );\n\n const onDragCancel = React.useCallback(\n (event: DragCancelEvent) => {\n kanbanProps.onDragCancel?.(event);\n\n if (isDragPrevented(event)) return;\n\n // Trả lại dữ liệu lúc nhấc — xem chú thích ở `valueAtDragStartRef`.\n const valueAtDragStart = valueAtDragStartRef.current;\n valueAtDragStartRef.current = null;\n if (valueAtDragStart && valueAtDragStart !== value) {\n onValueChange?.(valueAtDragStart);\n }\n\n setActiveId(null);\n hasMovedRef.current = false;\n },\n [value, onValueChange, kanbanProps.onDragCancel]\n );\n\n /*\n * ⚠ Khác thượng nguồn: câu chữ đi qua `labels` (theo ngôn ngữ, ghi đè được); phần TÍNH vị trí và\n * tổng số giữ nguyên bản gốc.\n */\n const announcements: Announcements = React.useMemo(\n () => ({\n onDragStart({ active }) {\n const isColumn = active.id in value;\n const variant = isColumn ? \"column\" : \"item\";\n const position = isColumn\n ? Object.keys(value).indexOf(active.id as string) + 1\n : (() => {\n const column = getColumn(active.id);\n if (!column || !value[column]) return 1;\n return value[column].findIndex((item) => getItemValue(item) === active.id) + 1;\n })();\n const total = isColumn\n ? Object.keys(value).length\n : (() => {\n const column = getColumn(active.id);\n return column ? (value[column]?.length ?? 0) : 0;\n })();\n\n return labels.pickedUp({ variant, value: active.id, position, total });\n },\n onDragOver({ active, over }) {\n if (!over) return;\n\n const isColumn = active.id in value;\n const variant = isColumn ? \"column\" : \"item\";\n const position = isColumn\n ? Object.keys(value).indexOf(over.id as string) + 1\n : (() => {\n const column = getColumn(over.id);\n if (!column || !value[column]) return 1;\n return value[column].findIndex((item) => getItemValue(item) === over.id) + 1;\n })();\n const total = isColumn\n ? Object.keys(value).length\n : (() => {\n const column = getColumn(over.id);\n return column ? (value[column]?.length ?? 0) : 0;\n })();\n\n const overColumn = getColumn(over.id);\n const activeColumn = getColumn(active.id);\n\n if (isColumn) {\n return labels.moved({ variant, value: active.id, position, total });\n }\n\n if (activeColumn !== overColumn) {\n return labels.moved({ variant, value: active.id, position, total, column: overColumn ?? undefined });\n }\n\n return labels.moved({ variant, value: active.id, position, total });\n },\n onDragEnd({ active, over }) {\n if (!over) return;\n\n const isColumn = active.id in value;\n const variant = isColumn ? \"column\" : \"item\";\n const position = isColumn\n ? Object.keys(value).indexOf(over.id as string) + 1\n : (() => {\n const column = getColumn(over.id);\n if (!column || !value[column]) return 1;\n return value[column].findIndex((item) => getItemValue(item) === over.id) + 1;\n })();\n const total = isColumn\n ? Object.keys(value).length\n : (() => {\n const column = getColumn(over.id);\n return column ? (value[column]?.length ?? 0) : 0;\n })();\n\n const overColumn = getColumn(over.id);\n const activeColumn = getColumn(active.id);\n\n if (isColumn) {\n return labels.dropped({ variant, value: active.id, position, total });\n }\n\n if (activeColumn !== overColumn) {\n return labels.dropped({ variant, value: active.id, position, total, column: overColumn ?? undefined });\n }\n\n return labels.dropped({ variant, value: active.id, position, total });\n },\n onDragCancel({ active }) {\n const isColumn = active.id in value;\n return labels.cancelled({ variant: isColumn ? \"column\" : \"item\", value: active.id });\n }\n }),\n [value, getColumn, getItemValue, labels]\n );\n\n const contextValue = React.useMemo<KanbanContextValue<T>>(\n () => ({\n id,\n items: value,\n modifiers,\n strategy,\n orientation,\n activeId,\n setActiveId,\n getItemValue,\n flatCursor,\n labels\n }),\n [id, value, activeId, modifiers, strategy, orientation, getItemValue, flatCursor, labels]\n );\n\n return (\n <KanbanContext.Provider value={contextValue as KanbanContextValue<unknown>}>\n <DndContext\n collisionDetection={collisionDetection}\n modifiers={modifiers}\n sensors={sensors}\n {...kanbanProps}\n id={id}\n measuring={{\n droppable: {\n strategy: MeasuringStrategy.Always\n }\n }}\n onDragStart={onDragStart}\n onDragOver={onDragOver}\n onDragEnd={onDragEnd}\n onDragCancel={onDragCancel}\n accessibility={{\n announcements,\n screenReaderInstructions: {\n draggable: labels.instructions\n },\n ...accessibility\n }}\n />\n </KanbanContext.Provider>\n );\n}\n\nconst KanbanBoardContext = React.createContext<boolean>(false);\n\ninterface KanbanBoardProps extends React.ComponentProps<\"div\"> {\n children: React.ReactNode;\n asChild?: boolean;\n}\n\nfunction KanbanBoard(props: KanbanBoardProps) {\n const { asChild, className, ref, ...boardProps } = props;\n\n const context = useKanbanContext(BOARD_NAME);\n\n const columns = React.useMemo(() => {\n return Object.keys(context.items);\n }, [context.items]);\n\n const BoardPrimitive = asChild ? Slot : \"div\";\n\n return (\n <KanbanBoardContext.Provider value={true}>\n <SortableContext\n items={columns}\n strategy={context.orientation === \"horizontal\" ? horizontalListSortingStrategy : verticalListSortingStrategy}\n >\n <BoardPrimitive\n aria-orientation={context.orientation}\n data-orientation={context.orientation}\n data-slot=\"kanban-board\"\n {...boardProps}\n ref={ref}\n className={cn(\n \"flex size-full gap-4\",\n context.orientation === \"horizontal\" ? \"flex-row\" : \"flex-col\",\n className\n )}\n />\n </SortableContext>\n </KanbanBoardContext.Provider>\n );\n}\n\ninterface KanbanColumnContextValue {\n id: string;\n attributes: DraggableAttributes;\n listeners: DraggableSyntheticListeners | undefined;\n setActivatorNodeRef: (node: HTMLElement | null) => void;\n isDragging?: boolean;\n disabled?: boolean;\n}\n\nconst KanbanColumnContext = React.createContext<KanbanColumnContextValue | null>(null);\n\nfunction useKanbanColumnContext(consumerName: string) {\n const context = React.useContext(KanbanColumnContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${COLUMN_NAME}\\``);\n }\n return context;\n}\n\nconst animateLayoutChanges: AnimateLayoutChanges = (args) =>\n defaultAnimateLayoutChanges({ ...args, wasDragging: true });\n\ninterface KanbanColumnProps extends React.ComponentProps<\"div\"> {\n value: UniqueIdentifier;\n children: React.ReactNode;\n asChild?: boolean;\n asHandle?: boolean;\n disabled?: boolean;\n}\n\nfunction KanbanColumn(props: KanbanColumnProps) {\n const { value, asChild, asHandle, disabled, className, style, ref, ...columnProps } = props;\n\n const id = React.useId();\n const context = useKanbanContext(COLUMN_NAME);\n const inBoard = React.useContext(KanbanBoardContext);\n const inOverlay = React.useContext(KanbanOverlayContext);\n\n if (!inBoard && !inOverlay) {\n throw new Error(`\\`${COLUMN_NAME}\\` phải nằm bên trong \\`${BOARD_NAME}\\` hoặc \\`${OVERLAY_NAME}\\``);\n }\n\n if (value === \"\") {\n throw new Error(`\\`value\\` của \\`${COLUMN_NAME}\\` không được là chuỗi rỗng`);\n }\n\n const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({\n id: value,\n disabled,\n animateLayoutChanges,\n // ⚠ Khác thượng nguồn: dnd-kit mặc định đọc vai trò là \"sortable\" (tiếng Anh).\n attributes: { roleDescription: context.labels.columnRoleDescription }\n });\n\n const onNodeRefChange = React.useCallback(\n (node: HTMLElement | null) => {\n if (disabled) return;\n setNodeRef(node);\n },\n [disabled, setNodeRef]\n );\n\n const composedRef = useComposedRefs(ref, onNodeRefChange);\n\n const composedStyle = React.useMemo<React.CSSProperties>(() => {\n return {\n transform: CSS.Transform.toString(transform),\n transition,\n ...style\n };\n }, [transform, transition, style]);\n\n const items = React.useMemo(() => {\n const columnItems = context.items[value] ?? [];\n return columnItems.map((item) => context.getItemValue(item));\n }, [context.items, value, context.getItemValue]);\n\n const columnContext = React.useMemo<KanbanColumnContextValue>(\n () => ({\n id,\n attributes,\n listeners,\n setActivatorNodeRef,\n isDragging,\n disabled\n }),\n [id, attributes, listeners, setActivatorNodeRef, isDragging, disabled]\n );\n\n const ColumnPrimitive = asChild ? Slot : \"div\";\n\n return (\n <KanbanColumnContext.Provider value={columnContext}>\n <SortableContext\n items={items}\n strategy={context.orientation === \"horizontal\" ? horizontalListSortingStrategy : verticalListSortingStrategy}\n >\n <ColumnPrimitive\n id={id}\n // ⚠ Khác thượng nguồn: `disabled={false}` từng ra `data-disabled=\"false\"` — thuộc tính\n // VẪN CÓ MẶT, nên mọi selector `[data-disabled]` khớp nhầm cột đang bật.\n data-disabled={disabled ? \"\" : undefined}\n data-dragging={isDragging ? \"\" : undefined}\n data-slot=\"kanban-column\"\n {...columnProps}\n {...(asHandle && !disabled ? attributes : {})}\n {...(asHandle && !disabled ? listeners : {})}\n ref={composedRef}\n style={composedStyle}\n className={cn(\n /*\n * ⚠ Khác thượng nguồn: `bg-zinc-100 dark:bg-zinc-900` là thang mặc định của Tailwind\n * (cổng màu chặn) → `bg-muted`, tự lật theo theme. Khung cột là viền TRANG TRÍ (không\n * bấm được, không mang trạng thái) nên `border-border` là đúng vai trò.\n */\n \"flex size-full flex-col gap-2 rounded-lg border border-border bg-muted p-2.5 aria-disabled:pointer-events-none aria-disabled:opacity-50\",\n {\n \"touch-none select-none\": asHandle,\n \"cursor-default\": context.flatCursor,\n \"data-dragging:cursor-grabbing\": !context.flatCursor,\n \"cursor-grab\": !isDragging && asHandle && !context.flatCursor,\n \"opacity-50\": isDragging,\n \"pointer-events-none opacity-50\": disabled,\n // ⚠ Khác thượng nguồn: bản sao trong `KanbanOverlay` được nâng lên bằng bóng nổi.\n \"shadow-overlay\": inOverlay\n },\n className\n )}\n />\n </SortableContext>\n </KanbanColumnContext.Provider>\n );\n}\n\ninterface KanbanColumnHandleProps extends React.ComponentProps<\"button\"> {\n asChild?: boolean;\n}\n\nfunction KanbanColumnHandle(props: KanbanColumnHandleProps) {\n const { asChild, disabled, className, ref, ...columnHandleProps } = props;\n\n const context = useKanbanContext(COLUMN_HANDLE_NAME);\n const columnContext = useKanbanColumnContext(COLUMN_HANDLE_NAME);\n\n const isDisabled = disabled ?? columnContext.disabled;\n\n const { setActivatorNodeRef } = columnContext;\n\n const onActivatorNodeRef = React.useCallback(\n (node: HTMLElement | null) => {\n if (isDisabled) return;\n setActivatorNodeRef(node);\n },\n [isDisabled, setActivatorNodeRef]\n );\n\n const composedRef = useComposedRefs(ref, onActivatorNodeRef);\n\n const HandlePrimitive = asChild ? Slot : \"button\";\n\n return (\n <HandlePrimitive\n type=\"button\"\n /*\n * ⚠ Khác thượng nguồn: tay cầm gần như luôn chỉ chứa một icon (GripVertical) → nút KHÔNG\n * TÊN. Tên mặc định đứng TRƯỚC `{...columnHandleProps}` nên `aria-label` của app (hoặc của\n * phần tử con khi `asChild`) vẫn thắng.\n */\n aria-label={context.labels.columnHandleLabel}\n aria-controls={columnContext.id}\n data-disabled={isDisabled ? \"\" : undefined}\n data-dragging={columnContext.isDragging ? \"\" : undefined}\n data-slot=\"kanban-column-handle\"\n {...columnHandleProps}\n {...(isDisabled ? {} : columnContext.attributes)}\n {...(isDisabled ? {} : columnContext.listeners)}\n ref={composedRef}\n className={cn(\n \"select-none disabled:pointer-events-none disabled:opacity-50\",\n context.flatCursor ? \"cursor-default\" : \"cursor-grab data-dragging:cursor-grabbing\",\n className\n )}\n disabled={isDisabled}\n />\n );\n}\n\ninterface KanbanItemContextValue {\n id: string;\n attributes: DraggableAttributes;\n listeners: DraggableSyntheticListeners | undefined;\n setActivatorNodeRef: (node: HTMLElement | null) => void;\n isDragging?: boolean;\n disabled?: boolean;\n}\n\nconst KanbanItemContext = React.createContext<KanbanItemContextValue | null>(null);\n\nfunction useKanbanItemContext(consumerName: string) {\n const context = React.useContext(KanbanItemContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ITEM_NAME}\\``);\n }\n return context;\n}\n\ninterface KanbanItemProps extends React.ComponentProps<\"div\"> {\n value: UniqueIdentifier;\n asHandle?: boolean;\n asChild?: boolean;\n disabled?: boolean;\n}\n\nfunction KanbanItem(props: KanbanItemProps) {\n const { value, style, asHandle, asChild, disabled, className, ref, ...itemProps } = props;\n\n const id = React.useId();\n const context = useKanbanContext(ITEM_NAME);\n const inBoard = React.useContext(KanbanBoardContext);\n const inOverlay = React.useContext(KanbanOverlayContext);\n\n if (!inBoard && !inOverlay) {\n throw new Error(`\\`${ITEM_NAME}\\` phải nằm bên trong \\`${BOARD_NAME}\\``);\n }\n\n const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({\n id: value,\n disabled,\n // ⚠ Khác thượng nguồn: dnd-kit mặc định đọc vai trò là \"sortable\" (tiếng Anh).\n attributes: { roleDescription: context.labels.itemRoleDescription }\n });\n\n if (value === \"\") {\n throw new Error(`\\`value\\` của \\`${ITEM_NAME}\\` không được là chuỗi rỗng`);\n }\n\n // Giữ ổn định để React không gỡ rồi gắn lại ref node của dnd-kit mỗi lượt render — việc đó\n // kích hoạt đo lại vùng thả ngay giữa lúc kéo.\n const onNodeRef = React.useCallback(\n (node: HTMLElement | null) => {\n if (disabled) return;\n setNodeRef(node);\n },\n [disabled, setNodeRef]\n );\n\n const composedRef = useComposedRefs(ref, onNodeRef);\n\n const composedStyle = React.useMemo<React.CSSProperties>(() => {\n return {\n transform: CSS.Transform.toString(transform),\n transition,\n ...style\n };\n }, [transform, transition, style]);\n\n const itemContext = React.useMemo<KanbanItemContextValue>(\n () => ({\n id,\n attributes,\n listeners,\n setActivatorNodeRef,\n isDragging,\n disabled\n }),\n [id, attributes, listeners, setActivatorNodeRef, isDragging, disabled]\n );\n\n const ItemPrimitive = asChild ? Slot : \"div\";\n\n return (\n <KanbanItemContext.Provider value={itemContext}>\n <ItemPrimitive\n id={id}\n // ⚠ Khác thượng nguồn: xem chú thích `data-disabled` ở `KanbanColumn`.\n data-disabled={disabled ? \"\" : undefined}\n data-dragging={isDragging ? \"\" : undefined}\n data-slot=\"kanban-item\"\n {...itemProps}\n {...(asHandle && !disabled ? attributes : {})}\n {...(asHandle && !disabled ? listeners : {})}\n ref={composedRef}\n style={composedStyle}\n className={cn(\n // Viền focus cùng khuôn với `Checkbox`/`RadioGroup` của gói.\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n {\n \"touch-none select-none\": asHandle,\n \"cursor-default\": context.flatCursor,\n \"data-dragging:cursor-grabbing\": !context.flatCursor,\n \"cursor-grab\": !isDragging && asHandle && !context.flatCursor,\n \"opacity-50\": isDragging,\n \"pointer-events-none opacity-50\": disabled,\n // ⚠ Khác thượng nguồn: bản sao trong `KanbanOverlay` được nâng lên bằng bóng nổi.\n // Bóng theo bo góc của CHÍNH phần tử — dùng `asChild` lên thẻ để bóng ôm đúng góc.\n \"shadow-overlay\": inOverlay\n },\n className\n )}\n />\n </KanbanItemContext.Provider>\n );\n}\n\ninterface KanbanItemHandleProps extends React.ComponentProps<\"button\"> {\n asChild?: boolean;\n}\n\nfunction KanbanItemHandle(props: KanbanItemHandleProps) {\n const { asChild, disabled, className, ref, ...itemHandleProps } = props;\n\n const context = useKanbanContext(ITEM_HANDLE_NAME);\n const itemContext = useKanbanItemContext(ITEM_HANDLE_NAME);\n\n const isDisabled = disabled ?? itemContext.disabled;\n\n const { setActivatorNodeRef } = itemContext;\n\n const onActivatorNodeRef = React.useCallback(\n (node: HTMLElement | null) => {\n if (isDisabled) return;\n setActivatorNodeRef(node);\n },\n [isDisabled, setActivatorNodeRef]\n );\n\n const composedRef = useComposedRefs(ref, onActivatorNodeRef);\n\n const HandlePrimitive = asChild ? Slot : \"button\";\n\n return (\n <HandlePrimitive\n type=\"button\"\n // ⚠ Khác thượng nguồn: tên mặc định cho tay cầm chỉ có icon — xem `KanbanColumnHandle`.\n aria-label={context.labels.itemHandleLabel}\n aria-controls={itemContext.id}\n data-disabled={isDisabled ? \"\" : undefined}\n data-dragging={itemContext.isDragging ? \"\" : undefined}\n data-slot=\"kanban-item-handle\"\n {...itemHandleProps}\n {...(isDisabled ? {} : itemContext.attributes)}\n {...(isDisabled ? {} : itemContext.listeners)}\n ref={composedRef}\n className={cn(\n \"select-none disabled:pointer-events-none disabled:opacity-50\",\n context.flatCursor ? \"cursor-default\" : \"cursor-grab data-dragging:cursor-grabbing\",\n className\n )}\n disabled={isDisabled}\n />\n );\n}\n\nconst KanbanOverlayContext = React.createContext(false);\n\nconst dropAnimation: DropAnimation = {\n sideEffects: defaultDropAnimationSideEffects({\n styles: {\n active: {\n opacity: \"0.4\"\n }\n }\n })\n};\n\ninterface KanbanOverlayProps extends Omit<React.ComponentProps<typeof DragOverlay>, \"children\"> {\n container?: Element | DocumentFragment | null;\n children?: React.ReactNode | ((params: { value: UniqueIdentifier; variant: \"column\" | \"item\" }) => React.ReactNode);\n}\n\nfunction KanbanOverlay(props: KanbanOverlayProps) {\n const { container: containerProp, children, ...overlayProps } = props;\n\n const context = useKanbanContext(OVERLAY_NAME);\n\n const [mounted, setMounted] = React.useState(false);\n\n // ⚠ Khác thượng nguồn: `useIsomorphicLayoutEffect` thay `React.useLayoutEffect` — an toàn khi SSR.\n useIsomorphicLayoutEffect(() => setMounted(true), []);\n\n const container = containerProp ?? (mounted ? globalThis.document?.body : null);\n\n if (!container) return null;\n\n const variant = context.activeId && context.activeId in context.items ? \"column\" : \"item\";\n\n return ReactDOM.createPortal(\n <DragOverlay\n dropAnimation={dropAnimation}\n modifiers={context.modifiers}\n className={cn(!context.flatCursor && \"cursor-grabbing\")}\n {...overlayProps}\n >\n <KanbanOverlayContext.Provider value={true}>\n {context.activeId && children\n ? typeof children === \"function\"\n ? children({\n value: context.activeId,\n variant\n })\n : children\n : null}\n </KanbanOverlayContext.Provider>\n </DragOverlay>,\n container\n );\n}\n\nexport {\n Kanban,\n KanbanBoard,\n type KanbanBoardProps,\n KanbanColumn,\n KanbanColumnHandle,\n type KanbanColumnHandleProps,\n type KanbanColumnProps,\n KanbanItem,\n KanbanItemHandle,\n type KanbanItemHandleProps,\n type KanbanItemProps,\n KanbanOverlay,\n type KanbanOverlayProps,\n type KanbanProps\n};\n"],"mappings":"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","names":[]}
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* `export` lại (re-export qua file client là vô hiệu, và đụng tên với `export *`).
|
|
10
10
|
*/
|
|
11
11
|
/**
|
|
12
|
-
* Mọi chuỗi hiển thị (và chuỗi cho trình đọc màn hình) của `KeyValue`.
|
|
13
|
-
*
|
|
12
|
+
* Mọi chuỗi hiển thị (và chuỗi cho trình đọc màn hình) của `KeyValue`. Theo `ComitorLocaleProvider`
|
|
13
|
+
* (mặc định tiếng Anh, bảng tiếng Việt dựng sẵn); truyền một phần qua prop `labels` để đè.
|
|
14
14
|
*/
|
|
15
15
|
interface KeyValueLabels {
|
|
16
16
|
/** Placeholder của ô KHOÁ. Prop `keyPlaceholder` của `KeyValue` (tên của thượng nguồn) thắng nếu có. */
|
|
@@ -27,7 +27,11 @@ interface KeyValueLabels {
|
|
|
27
27
|
/** Lỗi hiện ở `KeyValueError field="key"` khi hai dòng trùng khoá (lúc `allowDuplicateKeys = false`). */
|
|
28
28
|
duplicateKey: string;
|
|
29
29
|
}
|
|
30
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Nhãn TIẾNG ANH mặc định (từ `3.0.0`; trước đó là tiếng Việt). Bảng tiếng Việt:
|
|
32
|
+
* `comitorMessagesVi.keyValue`. Component không đọc thẳng hằng này — nó đọc bảng của
|
|
33
|
+
* `ComitorLocaleProvider`; hằng ở đây để app trải ra khi tự dựng nhãn.
|
|
34
|
+
*/
|
|
31
35
|
declare const DEFAULT_KEY_VALUE_LABELS: KeyValueLabels;
|
|
32
36
|
|
|
33
37
|
export { DEFAULT_KEY_VALUE_LABELS, type KeyValueLabels };
|
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
valuePlaceholder: "Gi\xE1 tr\u1ECB",
|
|
4
|
-
add: "Th\xEAm",
|
|
5
|
-
remove: (key, index) => key ? `Xo\xE1 ${key}` : `Xo\xE1 d\xF2ng ${index}`,
|
|
6
|
-
duplicateKey: "Kho\xE1 b\u1ECB tr\xF9ng"
|
|
7
|
-
};
|
|
1
|
+
import { keyValueEn } from "../../i18n/namespaces/key-value.js";
|
|
2
|
+
const DEFAULT_KEY_VALUE_LABELS = { ...keyValueEn };
|
|
8
3
|
export {
|
|
9
4
|
DEFAULT_KEY_VALUE_LABELS
|
|
10
5
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/key-value-constants.ts"],"sourcesContent":["/**\n * Nhãn mặc định của `KeyValue` (src/components/ui/key-value.tsx).\n *\n * Module **CỐ Ý không có `\"use client\"`** — xem `src/chart/chart-colors.ts` để biết lý do đầy đủ:\n * mọi export của một file `\"use client\"` tới tay Server Component là client-reference proxy, đọc\n * ra `undefined` mà KHÔNG throw, KHÔNG warning.\n *\n * ⚠ Barrel `src/index.ts` xuất module này TRỰC TIẾP. `key-value.tsx` chỉ được `import`, KHÔNG được\n * `export` lại (re-export qua file client là vô hiệu, và đụng tên với `export *`).\n */\n\n/**\n * Mọi chuỗi hiển thị (và chuỗi cho trình đọc màn hình) của `KeyValue`.
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/key-value-constants.ts"],"sourcesContent":["/**\n * Nhãn mặc định của `KeyValue` (src/components/ui/key-value.tsx).\n *\n * Module **CỐ Ý không có `\"use client\"`** — xem `src/chart/chart-colors.ts` để biết lý do đầy đủ:\n * mọi export của một file `\"use client\"` tới tay Server Component là client-reference proxy, đọc\n * ra `undefined` mà KHÔNG throw, KHÔNG warning.\n *\n * ⚠ Barrel `src/index.ts` xuất module này TRỰC TIẾP. `key-value.tsx` chỉ được `import`, KHÔNG được\n * `export` lại (re-export qua file client là vô hiệu, và đụng tên với `export *`).\n */\n\nimport { keyValueEn } from \"../../i18n/namespaces/key-value.js\";\n\n/**\n * Mọi chuỗi hiển thị (và chuỗi cho trình đọc màn hình) của `KeyValue`. Theo `ComitorLocaleProvider`\n * (mặc định tiếng Anh, bảng tiếng Việt dựng sẵn); truyền một phần qua prop `labels` để đè.\n */\nexport interface KeyValueLabels {\n /** Placeholder của ô KHOÁ. Prop `keyPlaceholder` của `KeyValue` (tên của thượng nguồn) thắng nếu có. */\n keyPlaceholder: string;\n /** Placeholder của ô GIÁ TRỊ. Prop `valuePlaceholder` của `KeyValue` thắng nếu có. */\n valuePlaceholder: string;\n /** Chữ của nút thêm dòng (`KeyValueAdd` khi không có `children`). */\n add: string;\n /**\n * Tên cho trình đọc màn hình của nút xoá dòng — nút chỉ có icon ✕. Nhận khoá của dòng (có thể\n * rỗng) và SỐ THỨ TỰ dòng, tính từ 1.\n */\n remove: (key: string, index: number) => string;\n /** Lỗi hiện ở `KeyValueError field=\"key\"` khi hai dòng trùng khoá (lúc `allowDuplicateKeys = false`). */\n duplicateKey: string;\n}\n\n/**\n * Nhãn TIẾNG ANH mặc định (từ `3.0.0`; trước đó là tiếng Việt). Bảng tiếng Việt:\n * `comitorMessagesVi.keyValue`. Component không đọc thẳng hằng này — nó đọc bảng của\n * `ComitorLocaleProvider`; hằng ở đây để app trải ra khi tự dựng nhãn.\n */\nexport const DEFAULT_KEY_VALUE_LABELS: KeyValueLabels = { ...keyValueEn };\n"],"mappings":"AAWA,SAAS,kBAAkB;AA2BpB,MAAM,2BAA2C,EAAE,GAAG,WAAW;","names":[]}
|
|
@@ -36,14 +36,14 @@ interface KeyValueProps extends Omit<DivProps, "onPaste" | "defaultValue"> {
|
|
|
36
36
|
onValueChange?: (value: ItemData[]) => void;
|
|
37
37
|
maxItems?: number;
|
|
38
38
|
minItems?: number;
|
|
39
|
-
/** Placeholder của ô khoá —
|
|
39
|
+
/** Placeholder của ô khoá — thắng `labels.keyPlaceholder` (mặc định "Key"). */
|
|
40
40
|
keyPlaceholder?: string;
|
|
41
|
-
/** Placeholder của ô giá trị —
|
|
41
|
+
/** Placeholder của ô giá trị — thắng `labels.valuePlaceholder` (mặc định "Value"). */
|
|
42
42
|
valuePlaceholder?: string;
|
|
43
43
|
/**
|
|
44
|
-
* Chuỗi hiển thị và chuỗi cho trình đọc màn hình — truyền MỘT PHẦN là đủ, phần còn lại
|
|
45
|
-
* `
|
|
46
|
-
* "Add" / "Duplicate key" và để nút xoá không có tên).
|
|
44
|
+
* Chuỗi hiển thị và chuỗi cho trình đọc màn hình — truyền MỘT PHẦN là đủ, phần còn lại theo
|
|
45
|
+
* namespace `keyValue` của `ComitorLocaleProvider` (mặc định tiếng Anh). ⚠ Thêm so với thượng
|
|
46
|
+
* nguồn (bản gốc chôn cứng "Add" / "Duplicate key" và để nút xoá không có tên).
|
|
47
47
|
*/
|
|
48
48
|
labels?: Partial<KeyValueLabels>;
|
|
49
49
|
name?: string;
|
|
@@ -3,6 +3,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { Slot } from "@radix-ui/react-slot";
|
|
4
4
|
import { Plus, X } from "lucide-react";
|
|
5
5
|
import * as React from "react";
|
|
6
|
+
import { useComitorLabels } from "../../i18n/locale-provider.js";
|
|
6
7
|
import { cn } from "../../lib/cn.js";
|
|
7
8
|
import { useComposedRefs } from "../../lib/compose-refs.js";
|
|
8
9
|
import { useAsRef } from "../../lib/use-as-ref.js";
|
|
@@ -11,7 +12,6 @@ import { useLazyRef } from "../../lib/use-lazy-ref.js";
|
|
|
11
12
|
import { VisuallyHiddenInput } from "../../lib/visually-hidden-input.js";
|
|
12
13
|
import { Button } from "./button.js";
|
|
13
14
|
import { Input } from "./input.js";
|
|
14
|
-
import { DEFAULT_KEY_VALUE_LABELS } from "./key-value-constants.js";
|
|
15
15
|
import { Textarea } from "./textarea.js";
|
|
16
16
|
const ROOT_NAME = "KeyValue";
|
|
17
17
|
const LIST_NAME = "KeyValueList";
|
|
@@ -96,7 +96,7 @@ function KeyValue(props) {
|
|
|
96
96
|
} = props;
|
|
97
97
|
const instanceId = React.useId();
|
|
98
98
|
const rootId = id ?? instanceId;
|
|
99
|
-
const labels =
|
|
99
|
+
const labels = useComitorLabels("keyValue", labelsProp);
|
|
100
100
|
const keyPlaceholder = keyPlaceholderProp ?? labels.keyPlaceholder;
|
|
101
101
|
const valuePlaceholder = valuePlaceholderProp ?? labels.valuePlaceholder;
|
|
102
102
|
const [formTrigger, setFormTrigger] = React.useState(null);
|