@comitor/ui 2.1.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -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 +5 -2
- package/dist/components/composite/toast.js +3 -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 +47 -3
- 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 +10 -2
- 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 +11 -5
- 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 +72 -78
- 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 +36 -77
- 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 +22 -22
- 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 +14 -12
- 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 +8 -4
- 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/slider.d.ts +1 -1
- package/dist/components/ui/slider.js +15 -1
- package/dist/components/ui/slider.js.map +1 -1
- package/dist/components/ui/sonner.js +2 -0
- package/dist/components/ui/sonner.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-group.js +12 -1
- package/dist/components/ui/toggle-group.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 +5 -4
- 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 +23 -8
- 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 +127 -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 +12 -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 +21 -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 +16 -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/lib/toast-language.d.ts +8 -0
- package/dist/lib/toast-language.js +19 -0
- package/dist/lib/toast-language.js.map +1 -0
- 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/display-axis-provider.d.ts +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
|
@@ -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) {
|
|
@@ -467,7 +467,6 @@ function KanbanBoard(props) {
|
|
|
467
467
|
children: /* @__PURE__ */ jsx(
|
|
468
468
|
BoardPrimitive,
|
|
469
469
|
{
|
|
470
|
-
"aria-orientation": context.orientation,
|
|
471
470
|
"data-orientation": context.orientation,
|
|
472
471
|
"data-slot": "kanban-board",
|
|
473
472
|
...boardProps,
|
|
@@ -611,7 +610,8 @@ function KanbanColumnHandle(props) {
|
|
|
611
610
|
...isDisabled ? {} : columnContext.listeners,
|
|
612
611
|
ref: composedRef,
|
|
613
612
|
className: cn(
|
|
614
|
-
|
|
613
|
+
// `touch-none`: xem `KanbanItemHandle`.
|
|
614
|
+
"touch-none select-none disabled:pointer-events-none disabled:opacity-50",
|
|
615
615
|
context.flatCursor ? "cursor-default" : "cursor-grab data-dragging:cursor-grabbing",
|
|
616
616
|
className
|
|
617
617
|
),
|
|
@@ -732,7 +732,13 @@ function KanbanItemHandle(props) {
|
|
|
732
732
|
...isDisabled ? {} : itemContext.listeners,
|
|
733
733
|
ref: composedRef,
|
|
734
734
|
className: cn(
|
|
735
|
-
|
|
735
|
+
/*
|
|
736
|
+
* ⚠ Khác thượng nguồn (3.0.1): `touch-none` trên tay cầm. `KanbanItem asHandle` (cả thẻ là tay
|
|
737
|
+
* cầm) đã có nó, tay cầm RỜI thì không — trên màn cảm ứng, vuốt bắt đầu từ tay cầm bị trình
|
|
738
|
+
* duyệt nhận làm cuộn trang, cảm biến chạm của dnd-kit mất sự kiện và thẻ không nhấc lên.
|
|
739
|
+
* Trang Patterns của comitor-ds từng phải tự thêm lớp này cho từng tay cầm.
|
|
740
|
+
*/
|
|
741
|
+
"touch-none select-none disabled:pointer-events-none disabled:opacity-50",
|
|
736
742
|
context.flatCursor ? "cursor-default" : "cursor-grab data-dragging:cursor-grabbing",
|
|
737
743
|
className
|
|
738
744
|
),
|
|
@@ -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 {/*\n * ⚠ Khác thượng nguồn (3.0.1): bỏ `aria-orientation`. Thuộc tính đó chỉ hợp lệ trên vài vai trò\n * (listbox, tablist, toolbar, scrollbar…), còn bảng là một `<div>` KHÔNG vai trò — axe báo\n * \"ARIA attribute is not allowed\", và trình đọc màn hình bỏ qua nó. `2.1.0` đã gỡ đúng lỗi\n * này khỏi `Timeline`, sót ở đây. Hướng vẫn có ở `data-orientation` cho CSS.\n */}\n <BoardPrimitive\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 // `touch-none`: xem `KanbanItemHandle`.\n \"touch-none 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 /*\n * ⚠ Khác thượng nguồn (3.0.1): `touch-none` trên tay cầm. `KanbanItem asHandle` (cả thẻ là tay\n * cầm) đã có nó, tay cầm RỜI thì không — trên màn cảm ứng, vuốt bắt đầu từ tay cầm bị trình\n * duyệt nhận làm cuộn trang, cảm biến chạm của dnd-kit mất sự kiện và thẻ không nhấc lên.\n * Trang Patterns của comitor-ds từng phải tự thêm lớp này cho từng tay cầm.\n */\n \"touch-none 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;
|