@comitor/ui 2.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -24
- package/dist/chart/chart.d.ts +6 -1
- package/dist/chart/chart.js +3 -1
- package/dist/chart/chart.js.map +1 -1
- package/dist/chart/comitor-chart.d.ts +4 -1
- package/dist/chart/comitor-chart.js +3 -1
- package/dist/chart/comitor-chart.js.map +1 -1
- package/dist/components/composite/avatar-group.d.ts +9 -6
- package/dist/components/composite/avatar-group.js +6 -2
- package/dist/components/composite/avatar-group.js.map +1 -1
- package/dist/components/composite/combobox.d.ts +11 -11
- package/dist/components/composite/combobox.js +25 -11
- package/dist/components/composite/combobox.js.map +1 -1
- package/dist/components/composite/command-palette-constants.d.ts +15 -5
- package/dist/components/composite/command-palette-constants.js +3 -2
- package/dist/components/composite/command-palette-constants.js.map +1 -1
- package/dist/components/composite/command-palette.d.ts +2 -2
- package/dist/components/composite/command-palette.js +8 -5
- package/dist/components/composite/command-palette.js.map +1 -1
- package/dist/components/composite/confirm-dialog.d.ts +8 -8
- package/dist/components/composite/confirm-dialog.js +8 -3
- package/dist/components/composite/confirm-dialog.js.map +1 -1
- package/dist/components/composite/copy-button.d.ts +7 -3
- package/dist/components/composite/copy-button.js +7 -3
- package/dist/components/composite/copy-button.js.map +1 -1
- package/dist/components/composite/data-table-constants.d.ts +7 -3
- package/dist/components/composite/data-table-constants.js +2 -9
- package/dist/components/composite/data-table-constants.js.map +1 -1
- package/dist/components/composite/data-table.js +3 -3
- package/dist/components/composite/data-table.js.map +1 -1
- package/dist/components/composite/date-picker-constants.d.ts +32 -9
- package/dist/components/composite/date-picker-constants.js +16 -11
- package/dist/components/composite/date-picker-constants.js.map +1 -1
- package/dist/components/composite/date-picker.d.ts +19 -10
- package/dist/components/composite/date-picker.js +33 -9
- package/dist/components/composite/date-picker.js.map +1 -1
- package/dist/components/composite/filter-chips.d.ts +4 -3
- package/dist/components/composite/filter-chips.js +6 -2
- package/dist/components/composite/filter-chips.js.map +1 -1
- package/dist/components/composite/inline-edit.d.ts +14 -3
- package/dist/components/composite/inline-edit.js +8 -4
- package/dist/components/composite/inline-edit.js.map +1 -1
- package/dist/components/composite/relative-time.d.ts +4 -4
- package/dist/components/composite/relative-time.js +4 -2
- package/dist/components/composite/relative-time.js.map +1 -1
- package/dist/components/composite/route-tabs-nav.d.ts +9 -0
- package/dist/components/composite/route-tabs-nav.js +11 -0
- package/dist/components/composite/route-tabs-nav.js.map +1 -0
- package/dist/components/composite/route-tabs.d.ts +4 -1
- package/dist/components/composite/route-tabs.js +3 -2
- package/dist/components/composite/route-tabs.js.map +1 -1
- package/dist/components/composite/search-filter-bar-constants.d.ts +18 -8
- package/dist/components/composite/search-filter-bar-constants.js +2 -14
- package/dist/components/composite/search-filter-bar-constants.js.map +1 -1
- package/dist/components/composite/search-filter-bar.d.ts +5 -2
- package/dist/components/composite/search-filter-bar.js +2 -2
- package/dist/components/composite/search-filter-bar.js.map +1 -1
- package/dist/components/composite/stat-card.d.ts +1 -1
- package/dist/components/composite/table-pagination-constants.d.ts +16 -11
- package/dist/components/composite/table-pagination-constants.js +2 -12
- package/dist/components/composite/table-pagination-constants.js.map +1 -1
- package/dist/components/composite/table-pagination.d.ts +6 -3
- package/dist/components/composite/table-pagination.js +3 -5
- package/dist/components/composite/table-pagination.js.map +1 -1
- package/dist/components/composite/toast.d.ts +4 -2
- package/dist/components/composite/toast.js +9 -1
- package/dist/components/composite/toast.js.map +1 -1
- package/dist/components/ui/action-bar-constants.d.ts +8 -4
- package/dist/components/ui/action-bar-constants.js +2 -5
- package/dist/components/ui/action-bar-constants.js.map +1 -1
- package/dist/components/ui/action-bar.d.ts +5 -4
- package/dist/components/ui/action-bar.js +2 -2
- package/dist/components/ui/action-bar.js.map +1 -1
- package/dist/components/ui/alert.d.ts +1 -1
- package/dist/components/ui/badge-overflow.d.ts +2 -2
- package/dist/components/ui/badge-overflow.js +4 -2
- package/dist/components/ui/badge-overflow.js.map +1 -1
- package/dist/components/ui/badge.d.ts +1 -1
- package/dist/components/ui/banner.d.ts +6 -5
- package/dist/components/ui/banner.js +3 -1
- package/dist/components/ui/banner.js.map +1 -1
- package/dist/components/ui/breadcrumb.d.ts +11 -4
- package/dist/components/ui/breadcrumb.js +7 -2
- package/dist/components/ui/breadcrumb.js.map +1 -1
- package/dist/components/ui/button.d.ts +2 -2
- package/dist/components/ui/calendar.d.ts +12 -5
- package/dist/components/ui/calendar.js +38 -3
- package/dist/components/ui/calendar.js.map +1 -1
- package/dist/components/ui/carousel.d.ts +4 -3
- package/dist/components/ui/carousel.js +11 -4
- package/dist/components/ui/carousel.js.map +1 -1
- package/dist/components/ui/circular-progress.js.map +1 -1
- package/dist/components/ui/command.d.ts +5 -4
- package/dist/components/ui/command.js +6 -2
- package/dist/components/ui/command.js.map +1 -1
- package/dist/components/ui/cropper-constants.d.ts +8 -3
- package/dist/components/ui/cropper-constants.js +2 -6
- package/dist/components/ui/cropper-constants.js.map +1 -1
- package/dist/components/ui/cropper.d.ts +2 -1
- package/dist/components/ui/cropper.js +2 -2
- package/dist/components/ui/cropper.js.map +1 -1
- package/dist/components/ui/dialog.d.ts +2 -2
- package/dist/components/ui/dialog.js +4 -1
- package/dist/components/ui/dialog.js.map +1 -1
- package/dist/components/ui/item.d.ts +2 -2
- package/dist/components/ui/kanban-constants.d.ts +7 -1
- package/dist/components/ui/kanban-constants.js +2 -17
- package/dist/components/ui/kanban-constants.js.map +1 -1
- package/dist/components/ui/kanban.d.ts +2 -2
- package/dist/components/ui/kanban.js +2 -2
- package/dist/components/ui/kanban.js.map +1 -1
- package/dist/components/ui/key-value-constants.d.ts +7 -3
- package/dist/components/ui/key-value-constants.js +2 -7
- package/dist/components/ui/key-value-constants.js.map +1 -1
- package/dist/components/ui/key-value.d.ts +5 -5
- package/dist/components/ui/key-value.js +2 -2
- package/dist/components/ui/key-value.js.map +1 -1
- package/dist/components/ui/mask-input-constants.d.ts +2 -3
- package/dist/components/ui/mask-input-constants.js +5 -6
- package/dist/components/ui/mask-input-constants.js.map +1 -1
- package/dist/components/ui/mask-input.d.ts +7 -4
- package/dist/components/ui/mask-input.js +4 -2
- package/dist/components/ui/mask-input.js.map +1 -1
- package/dist/components/ui/mention.d.ts +3 -2
- package/dist/components/ui/mention.js +4 -6
- package/dist/components/ui/mention.js.map +1 -1
- package/dist/components/ui/pagination.d.ts +13 -9
- package/dist/components/ui/pagination.js +15 -6
- package/dist/components/ui/pagination.js.map +1 -1
- package/dist/components/ui/phone-input-constants.d.ts +17 -6
- package/dist/components/ui/phone-input-constants.js +2 -5
- package/dist/components/ui/phone-input-constants.js.map +1 -1
- package/dist/components/ui/phone-input.d.ts +18 -11
- package/dist/components/ui/phone-input.js +9 -10
- package/dist/components/ui/phone-input.js.map +1 -1
- package/dist/components/ui/progress.d.ts +2 -2
- package/dist/components/ui/rating.d.ts +2 -1
- package/dist/components/ui/rating.js +4 -2
- package/dist/components/ui/rating.js.map +1 -1
- package/dist/components/ui/scroll-spy.js +3 -1
- package/dist/components/ui/scroll-spy.js.map +1 -1
- package/dist/components/ui/sheet.d.ts +2 -2
- package/dist/components/ui/sheet.js +10 -1
- package/dist/components/ui/sheet.js.map +1 -1
- package/dist/components/ui/spinner.js +4 -1
- package/dist/components/ui/spinner.js.map +1 -1
- package/dist/components/ui/stepper-constants.d.ts +7 -2
- package/dist/components/ui/stepper-constants.js +2 -5
- package/dist/components/ui/stepper-constants.js.map +1 -1
- package/dist/components/ui/stepper.d.ts +2 -1
- package/dist/components/ui/stepper.js +2 -2
- package/dist/components/ui/stepper.js.map +1 -1
- package/dist/components/ui/tags-input.d.ts +3 -2
- package/dist/components/ui/tags-input.js +4 -2
- package/dist/components/ui/tags-input.js.map +1 -1
- package/dist/components/ui/time-picker-constants.d.ts +12 -9
- package/dist/components/ui/time-picker-constants.js +2 -10
- package/dist/components/ui/time-picker-constants.js.map +1 -1
- package/dist/components/ui/time-picker.d.ts +11 -6
- package/dist/components/ui/time-picker.js +5 -7
- package/dist/components/ui/time-picker.js.map +1 -1
- package/dist/components/ui/toggle.d.ts +1 -1
- package/dist/components/ui/tour-constants.d.ts +7 -2
- package/dist/components/ui/tour-constants.js +2 -8
- package/dist/components/ui/tour-constants.js.map +1 -1
- package/dist/components/ui/tour.d.ts +3 -2
- package/dist/components/ui/tour.js +2 -2
- package/dist/components/ui/tour.js.map +1 -1
- package/dist/data-grid/data-grid-cell-variants.js +4 -4
- package/dist/data-grid/data-grid-cell-variants.js.map +1 -1
- package/dist/data-grid/data-grid-column-header.js +1 -1
- package/dist/data-grid/data-grid-column-header.js.map +1 -1
- package/dist/data-grid/data-grid-filter-menu.d.ts +5 -4
- package/dist/data-grid/data-grid-filter-menu.js +13 -8
- package/dist/data-grid/data-grid-filter-menu.js.map +1 -1
- package/dist/data-grid/data-grid-keyboard-shortcuts.d.ts +4 -4
- package/dist/data-grid/data-grid-keyboard-shortcuts.js.map +1 -1
- package/dist/data-grid/data-grid-locale.d.ts +58 -6
- package/dist/data-grid/data-grid-locale.js +41 -9
- package/dist/data-grid/data-grid-locale.js.map +1 -1
- package/dist/data-grid/data-grid-row-height-menu.d.ts +4 -3
- package/dist/data-grid/data-grid-row-height-menu.js.map +1 -1
- package/dist/data-grid/data-grid-sort-menu.d.ts +4 -4
- package/dist/data-grid/data-grid-sort-menu.js +1 -1
- package/dist/data-grid/data-grid-sort-menu.js.map +1 -1
- package/dist/data-grid/data-grid-view-menu.d.ts +4 -4
- package/dist/data-grid/data-grid-view-menu.js.map +1 -1
- package/dist/data-grid/data-grid.d.ts +4 -3
- package/dist/data-grid/data-grid.js +2 -3
- package/dist/data-grid/data-grid.js.map +1 -1
- package/dist/data-grid/index.d.ts +1 -0
- package/dist/data-grid/index.js.map +1 -1
- package/dist/data-grid/messages-en.d.ts +23 -4
- package/dist/data-grid/messages-en.js +20 -0
- package/dist/data-grid/messages-en.js.map +1 -1
- package/dist/data-grid/messages-vi.d.ts +3 -1
- package/dist/data-grid/messages-vi.js +14 -0
- package/dist/data-grid/messages-vi.js.map +1 -1
- package/dist/data-grid/messages.d.ts +29 -3
- package/dist/data-grid/messages.js.map +1 -1
- package/dist/data-grid/sortable.js +16 -19
- package/dist/data-grid/sortable.js.map +1 -1
- package/dist/data-grid/types.d.ts +1 -1
- package/dist/data-grid/use-data-grid-undo-redo.d.ts +5 -4
- package/dist/data-grid/use-data-grid-undo-redo.js +2 -2
- package/dist/data-grid/use-data-grid-undo-redo.js.map +1 -1
- package/dist/data-grid/use-data-grid.d.ts +21 -6
- package/dist/data-grid/use-data-grid.js +8 -6
- package/dist/data-grid/use-data-grid.js.map +1 -1
- package/dist/data-grid/utils.d.ts +24 -4
- package/dist/data-grid/utils.js +15 -5
- package/dist/data-grid/utils.js.map +1 -1
- package/dist/i18n/locale-provider.d.ts +109 -0
- package/dist/i18n/locale-provider.js +47 -0
- package/dist/i18n/locale-provider.js.map +1 -0
- package/dist/i18n/locale.d.ts +27 -0
- package/dist/i18n/locale.js +10 -0
- package/dist/i18n/locale.js.map +1 -0
- package/dist/i18n/messages.d.ts +116 -0
- package/dist/i18n/messages.js +149 -0
- package/dist/i18n/messages.js.map +1 -0
- package/dist/i18n/namespaces/action-bar.d.ts +7 -0
- package/dist/i18n/namespaces/action-bar.js +15 -0
- package/dist/i18n/namespaces/action-bar.js.map +1 -0
- package/dist/i18n/namespaces/avatar-group.d.ts +14 -0
- package/dist/i18n/namespaces/avatar-group.js +13 -0
- package/dist/i18n/namespaces/avatar-group.js.map +1 -0
- package/dist/i18n/namespaces/badge-overflow.d.ts +12 -0
- package/dist/i18n/namespaces/badge-overflow.js +11 -0
- package/dist/i18n/namespaces/badge-overflow.js.map +1 -0
- package/dist/i18n/namespaces/banner.d.ts +9 -0
- package/dist/i18n/namespaces/banner.js +7 -0
- package/dist/i18n/namespaces/banner.js.map +1 -0
- package/dist/i18n/namespaces/breadcrumb.d.ts +11 -0
- package/dist/i18n/namespaces/breadcrumb.js +13 -0
- package/dist/i18n/namespaces/breadcrumb.js.map +1 -0
- package/dist/i18n/namespaces/calendar.d.ts +40 -0
- package/dist/i18n/namespaces/calendar.js +25 -0
- package/dist/i18n/namespaces/calendar.js.map +1 -0
- package/dist/i18n/namespaces/carousel.d.ts +15 -0
- package/dist/i18n/namespaces/carousel.js +17 -0
- package/dist/i18n/namespaces/carousel.js.map +1 -0
- package/dist/i18n/namespaces/combobox.d.ts +21 -0
- package/dist/i18n/namespaces/combobox.js +23 -0
- package/dist/i18n/namespaces/combobox.js.map +1 -0
- package/dist/i18n/namespaces/command-palette.d.ts +20 -0
- package/dist/i18n/namespaces/command-palette.js +19 -0
- package/dist/i18n/namespaces/command-palette.js.map +1 -0
- package/dist/i18n/namespaces/command.d.ts +11 -0
- package/dist/i18n/namespaces/command.js +13 -0
- package/dist/i18n/namespaces/command.js.map +1 -0
- package/dist/i18n/namespaces/confirm-dialog.d.ts +13 -0
- package/dist/i18n/namespaces/confirm-dialog.js +15 -0
- package/dist/i18n/namespaces/confirm-dialog.js.map +1 -0
- package/dist/i18n/namespaces/contrast.d.ts +7 -0
- package/dist/i18n/namespaces/contrast.js +13 -0
- package/dist/i18n/namespaces/contrast.js.map +1 -0
- package/dist/i18n/namespaces/copy-button.d.ts +11 -0
- package/dist/i18n/namespaces/copy-button.js +13 -0
- package/dist/i18n/namespaces/copy-button.js.map +1 -0
- package/dist/i18n/namespaces/cropper.d.ts +7 -0
- package/dist/i18n/namespaces/cropper.js +17 -0
- package/dist/i18n/namespaces/cropper.js.map +1 -0
- package/dist/i18n/namespaces/data-table.d.ts +7 -0
- package/dist/i18n/namespaces/data-table.js +23 -0
- package/dist/i18n/namespaces/data-table.js.map +1 -0
- package/dist/i18n/namespaces/date-picker.d.ts +42 -0
- package/dist/i18n/namespaces/date-picker.js +35 -0
- package/dist/i18n/namespaces/date-picker.js.map +1 -0
- package/dist/i18n/namespaces/dialog.d.ts +9 -0
- package/dist/i18n/namespaces/dialog.js +7 -0
- package/dist/i18n/namespaces/dialog.js.map +1 -0
- package/dist/i18n/namespaces/display-axis.d.ts +25 -0
- package/dist/i18n/namespaces/display-axis.js +21 -0
- package/dist/i18n/namespaces/display-axis.js.map +1 -0
- package/dist/i18n/namespaces/file-upload.d.ts +11 -0
- package/dist/i18n/namespaces/file-upload.js +19 -0
- package/dist/i18n/namespaces/file-upload.js.map +1 -0
- package/dist/i18n/namespaces/filter-chips.d.ts +11 -0
- package/dist/i18n/namespaces/filter-chips.js +13 -0
- package/dist/i18n/namespaces/filter-chips.js.map +1 -0
- package/dist/i18n/namespaces/image-upload-field.d.ts +12 -0
- package/dist/i18n/namespaces/image-upload-field.js +23 -0
- package/dist/i18n/namespaces/image-upload-field.js.map +1 -0
- package/dist/i18n/namespaces/inline-edit.d.ts +15 -0
- package/dist/i18n/namespaces/inline-edit.js +17 -0
- package/dist/i18n/namespaces/inline-edit.js.map +1 -0
- package/dist/i18n/namespaces/kanban.d.ts +11 -0
- package/dist/i18n/namespaces/kanban.js +39 -0
- package/dist/i18n/namespaces/kanban.js.map +1 -0
- package/dist/i18n/namespaces/key-value.d.ts +10 -0
- package/dist/i18n/namespaces/key-value.js +19 -0
- package/dist/i18n/namespaces/key-value.js.map +1 -0
- package/dist/i18n/namespaces/mention.d.ts +9 -0
- package/dist/i18n/namespaces/mention.js +7 -0
- package/dist/i18n/namespaces/mention.js.map +1 -0
- package/dist/i18n/namespaces/pagination.d.ts +19 -0
- package/dist/i18n/namespaces/pagination.js +21 -0
- package/dist/i18n/namespaces/pagination.js.map +1 -0
- package/dist/i18n/namespaces/phone-input.d.ts +10 -0
- package/dist/i18n/namespaces/phone-input.js +17 -0
- package/dist/i18n/namespaces/phone-input.js.map +1 -0
- package/dist/i18n/namespaces/rating.d.ts +12 -0
- package/dist/i18n/namespaces/rating.js +11 -0
- package/dist/i18n/namespaces/rating.js.map +1 -0
- package/dist/i18n/namespaces/route-tabs.d.ts +9 -0
- package/dist/i18n/namespaces/route-tabs.js +7 -0
- package/dist/i18n/namespaces/route-tabs.js.map +1 -0
- package/dist/i18n/namespaces/scroll-spy.d.ts +9 -0
- package/dist/i18n/namespaces/scroll-spy.js +7 -0
- package/dist/i18n/namespaces/scroll-spy.js.map +1 -0
- package/dist/i18n/namespaces/search-filter-bar.d.ts +15 -0
- package/dist/i18n/namespaces/search-filter-bar.js +32 -0
- package/dist/i18n/namespaces/search-filter-bar.js.map +1 -0
- package/dist/i18n/namespaces/sheet.d.ts +9 -0
- package/dist/i18n/namespaces/sheet.js +7 -0
- package/dist/i18n/namespaces/sheet.js.map +1 -0
- package/dist/i18n/namespaces/shell.d.ts +17 -0
- package/dist/i18n/namespaces/shell.js +75 -0
- package/dist/i18n/namespaces/shell.js.map +1 -0
- package/dist/i18n/namespaces/spinner.d.ts +9 -0
- package/dist/i18n/namespaces/spinner.js +7 -0
- package/dist/i18n/namespaces/spinner.js.map +1 -0
- package/dist/i18n/namespaces/stepper.d.ts +7 -0
- package/dist/i18n/namespaces/stepper.js +15 -0
- package/dist/i18n/namespaces/stepper.js.map +1 -0
- package/dist/i18n/namespaces/table-pagination.d.ts +7 -0
- package/dist/i18n/namespaces/table-pagination.js +29 -0
- package/dist/i18n/namespaces/table-pagination.js.map +1 -0
- package/dist/i18n/namespaces/tags-input.d.ts +12 -0
- package/dist/i18n/namespaces/tags-input.js +11 -0
- package/dist/i18n/namespaces/tags-input.js.map +1 -0
- package/dist/i18n/namespaces/time-picker.d.ts +15 -0
- package/dist/i18n/namespaces/time-picker.js +25 -0
- package/dist/i18n/namespaces/time-picker.js.map +1 -0
- package/dist/i18n/namespaces/toast.d.ts +15 -0
- package/dist/i18n/namespaces/toast.js +7 -0
- package/dist/i18n/namespaces/toast.js.map +1 -0
- package/dist/i18n/namespaces/tour.d.ts +7 -0
- package/dist/i18n/namespaces/tour.js +21 -0
- package/dist/i18n/namespaces/tour.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +24 -1
- package/dist/index.js.map +1 -1
- package/dist/shell/app-header.js.map +1 -1
- package/dist/shell/app-shell.d.ts +20 -2
- package/dist/shell/app-shell.js +4 -1
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/contrast-constants.d.ts +9 -1
- package/dist/shell/contrast-constants.js +2 -4
- package/dist/shell/contrast-constants.js.map +1 -1
- package/dist/shell/contrast-toggle.d.ts +4 -1
- package/dist/shell/contrast-toggle.js +2 -2
- package/dist/shell/contrast-toggle.js.map +1 -1
- package/dist/shell/display-axis-constants.d.ts +2 -1
- package/dist/shell/display-axis-constants.js.map +1 -1
- package/dist/shell/display-axis-controls.d.ts +15 -6
- package/dist/shell/display-axis-controls.js +11 -9
- package/dist/shell/display-axis-controls.js.map +1 -1
- package/dist/shell/mobile-menu.js.map +1 -1
- package/dist/shell/notifications-button.d.ts +1 -1
- package/dist/shell/notifications-button.js +3 -2
- package/dist/shell/notifications-button.js.map +1 -1
- package/dist/shell/shell-context.d.ts +4 -1
- package/dist/shell/shell-context.js +2 -4
- package/dist/shell/shell-context.js.map +1 -1
- package/dist/shell/sidebar.d.ts +1 -1
- package/dist/shell/sidebar.js.map +1 -1
- package/dist/shell/theme-toggle.d.ts +6 -3
- package/dist/shell/theme-toggle.js +2 -2
- package/dist/shell/theme-toggle.js.map +1 -1
- package/dist/shell/types.d.ts +14 -8
- package/dist/shell/types.js +2 -35
- package/dist/shell/types.js.map +1 -1
- package/dist/shell/user-menu.d.ts +6 -6
- package/dist/shell/user-menu.js.map +1 -1
- package/dist/shell/utils.d.ts +1 -1
- package/dist/shell/utils.js.map +1 -1
- package/dist/shell/workspace-switcher.js +1 -1
- package/dist/shell/workspace-switcher.js.map +1 -1
- package/dist/uploader/file-upload-constants.d.ts +13 -0
- package/dist/uploader/file-upload-constants.js +4 -16
- package/dist/uploader/file-upload-constants.js.map +1 -1
- package/dist/uploader/file-upload.d.ts +4 -1
- package/dist/uploader/file-upload.js +2 -2
- package/dist/uploader/file-upload.js.map +1 -1
- package/dist/uploader/image-upload-field.d.ts +5 -1
- package/dist/uploader/image-upload-field.js +2 -2
- package/dist/uploader/image-upload-field.js.map +1 -1
- package/dist/uploader/use-file-upload.d.ts +4 -0
- package/dist/uploader/use-file-upload.js +6 -2
- package/dist/uploader/use-file-upload.js.map +1 -1
- package/package.json +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/stepper.tsx"],"sourcesContent":["\"use client\";\n\n/*\n * Port từ Dice UI (https://diceui.com/docs/components/stepper) — 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 { useDirection } from \"@radix-ui/react-direction\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { Check } from \"lucide-react\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\nimport { useComposedRefs } from \"../../lib/compose-refs.js\";\nimport { useAsRef } from \"../../lib/use-as-ref.js\";\nimport { useIsomorphicLayoutEffect } from \"../../lib/use-isomorphic-layout-effect.js\";\nimport { useLazyRef } from \"../../lib/use-lazy-ref.js\";\nimport { DEFAULT_STEPPER_LABELS, type StepperLabels } from \"./stepper-constants.js\";\n\nconst ROOT_NAME = \"Stepper\";\nconst LIST_NAME = \"StepperList\";\nconst ITEM_NAME = \"StepperItem\";\nconst TRIGGER_NAME = \"StepperTrigger\";\nconst INDICATOR_NAME = \"StepperIndicator\";\nconst SEPARATOR_NAME = \"StepperSeparator\";\nconst TITLE_NAME = \"StepperTitle\";\nconst DESCRIPTION_NAME = \"StepperDescription\";\nconst CONTENT_NAME = \"StepperContent\";\nconst PREV_NAME = \"StepperPrev\";\nconst NEXT_NAME = \"StepperNext\";\n\nconst ENTRY_FOCUS = \"stepperFocusGroup.onEntryFocus\";\nconst EVENT_OPTIONS = { bubbles: false, cancelable: true };\nconst ARROW_KEYS = [\"ArrowUp\", \"ArrowDown\", \"ArrowLeft\", \"ArrowRight\"];\n\ntype Direction = \"ltr\" | \"rtl\";\ntype Orientation = \"horizontal\" | \"vertical\";\ntype NavigationDirection = \"next\" | \"prev\";\ntype ActivationMode = \"automatic\" | \"manual\";\ntype DataState = \"inactive\" | \"active\" | \"completed\";\n\ninterface DivProps extends React.ComponentProps<\"div\"> {\n asChild?: boolean;\n}\ninterface ButtonProps extends React.ComponentProps<\"button\"> {\n asChild?: boolean;\n}\n\ntype ListElement = React.ComponentRef<typeof StepperList>;\ntype TriggerElement = React.ComponentRef<typeof StepperTrigger>;\n\nfunction getId(id: string, variant: \"trigger\" | \"content\" | \"title\" | \"description\", value: string) {\n return `${id}-${variant}-${value}`;\n}\n\ntype FocusIntent = \"first\" | \"last\" | \"prev\" | \"next\";\n\nconst MAP_KEY_TO_FOCUS_INTENT: Record<string, FocusIntent> = {\n ArrowLeft: \"prev\",\n ArrowUp: \"prev\",\n ArrowRight: \"next\",\n ArrowDown: \"next\",\n PageUp: \"first\",\n Home: \"first\",\n PageDown: \"last\",\n End: \"last\"\n};\n\nfunction getDirectionAwareKey(key: string, dir?: Direction) {\n if (dir !== \"rtl\") return key;\n return key === \"ArrowLeft\" ? \"ArrowRight\" : key === \"ArrowRight\" ? \"ArrowLeft\" : key;\n}\n\nfunction getFocusIntent(event: React.KeyboardEvent<TriggerElement>, dir?: Direction, orientation?: Orientation) {\n const key = getDirectionAwareKey(event.key, dir);\n if (orientation === \"horizontal\" && [\"ArrowUp\", \"ArrowDown\"].includes(key)) return undefined;\n if (orientation === \"vertical\" && [\"ArrowLeft\", \"ArrowRight\"].includes(key)) return undefined;\n return MAP_KEY_TO_FOCUS_INTENT[key];\n}\n\nfunction focusFirst(candidates: React.RefObject<TriggerElement | null>[], preventScroll = false) {\n const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;\n for (const candidateRef of candidates) {\n const candidate = candidateRef.current;\n if (!candidate) continue;\n if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;\n candidate.focus({ preventScroll });\n if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;\n }\n}\n\nfunction wrapArray<T>(array: T[], startIndex: number) {\n return array.map<T>((_, index) => array[(startIndex + index) % array.length] as T);\n}\n\nfunction getDataState(\n value: string | undefined,\n itemValue: string,\n stepState: StepState | undefined,\n steps: Map<string, StepState>,\n variant: \"item\" | \"separator\" = \"item\"\n): DataState {\n const stepKeys = Array.from(steps.keys());\n const currentIndex = stepKeys.indexOf(itemValue);\n\n if (stepState?.completed) return \"completed\";\n\n if (value === itemValue) {\n return variant === \"separator\" ? \"inactive\" : \"active\";\n }\n\n if (value) {\n const activeIndex = stepKeys.indexOf(value);\n\n if (activeIndex > currentIndex) return \"completed\";\n }\n\n return \"inactive\";\n}\n\ninterface StepState {\n value: string;\n completed: boolean;\n disabled: boolean;\n}\n\ninterface StoreState {\n steps: Map<string, StepState>;\n value: string;\n}\n\ninterface Store {\n subscribe: (callback: () => void) => () => void;\n getState: () => StoreState;\n setState: <K extends keyof StoreState>(key: K, value: StoreState[K]) => void;\n setStateWithValidation: (value: string, direction: NavigationDirection) => Promise<boolean>;\n hasValidation: () => boolean;\n notify: () => void;\n addStep: (value: string, completed: boolean, disabled: boolean) => void;\n removeStep: (value: string) => void;\n setStep: (value: string, completed: boolean, disabled: boolean) => void;\n}\n\nconst StoreContext = React.createContext<Store | null>(null);\n\nfunction useStoreContext(consumerName: string) {\n const context = React.useContext(StoreContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ROOT_NAME}\\``);\n }\n return context;\n}\n\nfunction useStore<T>(selector: (state: StoreState) => T): T {\n const store = useStoreContext(\"useStepper\");\n\n const getSnapshot = React.useCallback(() => selector(store.getState()), [store, selector]);\n\n return React.useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);\n}\n\ninterface ItemData {\n id: string;\n ref: React.RefObject<TriggerElement | null>;\n value: string;\n active: boolean;\n disabled: boolean;\n}\n\ninterface StepperContextValue {\n rootId: string;\n dir: Direction;\n orientation: Orientation;\n activationMode: ActivationMode;\n disabled: boolean;\n nonInteractive: boolean;\n loop: boolean;\n labels: StepperLabels;\n}\n\nconst StepperContext = React.createContext<StepperContextValue | null>(null);\n\nfunction useStepperContext(consumerName: string) {\n const context = React.useContext(StepperContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ROOT_NAME}\\``);\n }\n return context;\n}\n\ninterface StepperProps extends DivProps {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n onValueComplete?: (value: string, completed: boolean) => void;\n onValueAdd?: (value: string) => void;\n onValueRemove?: (value: string) => void;\n onValidate?: (value: string, direction: NavigationDirection) => boolean | Promise<boolean>;\n activationMode?: ActivationMode;\n dir?: Direction;\n orientation?: Orientation;\n disabled?: boolean;\n loop?: boolean;\n nonInteractive?: boolean;\n /**\n * Chuỗi hiển thị/a11y — ghi đè từng khoá của `DEFAULT_STEPPER_LABELS` (tiếng Việt).\n *\n * ⚠ Thêm so với thượng nguồn: bản gốc không có chuỗi nào, và chính vì thế có hai chỗ ra nút\n * KHÔNG TÊN (ô chỉ báo bước đã xong, `StepperPrev`/`StepperNext` thiếu `children`).\n */\n labels?: Partial<StepperLabels>;\n}\n\nfunction Stepper(props: StepperProps) {\n const {\n value,\n defaultValue,\n onValueChange,\n onValueComplete,\n onValueAdd,\n onValueRemove,\n onValidate,\n dir: dirProp,\n orientation = \"horizontal\",\n activationMode = \"automatic\",\n asChild,\n disabled = false,\n nonInteractive = false,\n loop = false,\n labels: labelsProp,\n className,\n id,\n ...rootProps\n } = props;\n\n const listenersRef = useLazyRef(() => new Set<() => void>());\n const stateRef = useLazyRef<StoreState>(() => ({\n steps: new Map(),\n value: value ?? defaultValue ?? \"\"\n }));\n\n const propsRef = useAsRef({\n onValueChange,\n onValueComplete,\n onValueAdd,\n onValueRemove,\n onValidate\n });\n\n const store = React.useMemo<Store>(() => {\n return {\n subscribe: (cb) => {\n listenersRef.current.add(cb);\n return () => listenersRef.current.delete(cb);\n },\n getState: () => stateRef.current,\n setState: (key, value) => {\n if (Object.is(stateRef.current[key], value)) return;\n\n if (key === \"value\" && typeof value === \"string\") {\n stateRef.current.value = value;\n propsRef.current.onValueChange?.(value);\n } else {\n stateRef.current[key] = value;\n }\n\n store.notify();\n },\n setStateWithValidation: async (value, direction) => {\n if (!propsRef.current.onValidate) {\n store.setState(\"value\", value);\n return true;\n }\n\n try {\n const isValid = await propsRef.current.onValidate(value, direction);\n if (isValid) {\n store.setState(\"value\", value);\n }\n return isValid;\n } catch {\n return false;\n }\n },\n hasValidation: () => !!propsRef.current.onValidate,\n /*\n * ⚠ Khác thượng nguồn: mỗi lần thêm/bớt/sửa bước đều thay `steps` bằng một `Map` MỚI. Bản gốc\n * sửa tại chỗ nên `useStore((s) => s.steps)` không bao giờ thấy tham chiếu mới — phần tử chỉ\n * đọc `steps` (`StepperPrev`/`StepperNext`) không render lại sau khi các bước đăng ký, và\n * nằm `disabled` cho tới lần đổi bước đầu tiên.\n */\n addStep: (value, completed, disabled) => {\n const newStep: StepState = { value, completed, disabled };\n const steps = new Map(stateRef.current.steps);\n steps.set(value, newStep);\n stateRef.current.steps = steps;\n propsRef.current.onValueAdd?.(value);\n store.notify();\n },\n removeStep: (value) => {\n const steps = new Map(stateRef.current.steps);\n steps.delete(value);\n stateRef.current.steps = steps;\n propsRef.current.onValueRemove?.(value);\n store.notify();\n },\n setStep: (value, completed, disabled) => {\n const step = stateRef.current.steps.get(value);\n if (step) {\n const updatedStep: StepState = { ...step, completed, disabled };\n const steps = new Map(stateRef.current.steps);\n steps.set(value, updatedStep);\n stateRef.current.steps = steps;\n\n if (completed !== step.completed) {\n propsRef.current.onValueComplete?.(value, completed);\n }\n\n store.notify();\n }\n },\n notify: () => {\n for (const cb of listenersRef.current) {\n cb();\n }\n }\n };\n }, [listenersRef, stateRef, propsRef]);\n\n useIsomorphicLayoutEffect(() => {\n if (value !== undefined) {\n store.setState(\"value\", value);\n }\n }, [value]);\n\n const dir = useDirection(dirProp);\n\n const instanceId = React.useId();\n const rootId = id ?? instanceId;\n\n const labels = React.useMemo<StepperLabels>(() => ({ ...DEFAULT_STEPPER_LABELS, ...labelsProp }), [labelsProp]);\n\n const contextValue = React.useMemo<StepperContextValue>(\n () => ({\n rootId,\n dir,\n orientation,\n activationMode,\n disabled,\n nonInteractive,\n loop,\n labels\n }),\n [rootId, dir, orientation, activationMode, disabled, nonInteractive, loop, labels]\n );\n\n const RootPrimitive = asChild ? Slot : \"div\";\n\n return (\n <StoreContext.Provider value={store}>\n <StepperContext.Provider value={contextValue}>\n <RootPrimitive\n id={rootId}\n data-disabled={disabled ? \"\" : undefined}\n data-orientation={orientation}\n data-slot=\"stepper\"\n dir={dir}\n {...rootProps}\n className={cn(\"flex gap-6\", orientation === \"horizontal\" ? \"w-full flex-col\" : \"flex-row\", className)}\n />\n </StepperContext.Provider>\n </StoreContext.Provider>\n );\n}\n\ninterface FocusContextValue {\n tabStopId: string | null;\n onItemFocus: (tabStopId: string) => void;\n onItemShiftTab: () => void;\n onFocusableItemAdd: () => void;\n onFocusableItemRemove: () => void;\n onItemRegister: (item: ItemData) => void;\n onItemUnregister: (id: string) => void;\n getItems: () => ItemData[];\n}\n\nconst FocusContext = React.createContext<FocusContextValue | null>(null);\n\nfunction useFocusContext(consumerName: string) {\n const context = React.useContext(FocusContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${LIST_NAME}\\``);\n }\n return context;\n}\n\nfunction StepperList(props: DivProps) {\n const {\n asChild,\n onBlur: onBlurProp,\n onFocus: onFocusProp,\n onMouseDown: onMouseDownProp,\n className,\n children,\n ref,\n ...listProps\n } = props;\n\n const context = useStepperContext(LIST_NAME);\n const orientation = context.orientation;\n const currentValue = useStore((state) => state.value);\n\n const propsRef = useAsRef({\n onBlur: onBlurProp,\n onFocus: onFocusProp,\n onMouseDown: onMouseDownProp\n });\n\n const [tabStopId, setTabStopId] = React.useState<string | null>(null);\n const [isTabbingBackOut, setIsTabbingBackOut] = React.useState(false);\n const [focusableItemCount, setFocusableItemCount] = React.useState(0);\n const isClickFocusRef = React.useRef(false);\n const itemsRef = React.useRef<Map<string, ItemData>>(new Map());\n const listRef = React.useRef<ListElement>(null);\n const composedRef = useComposedRefs(ref, listRef);\n\n const onItemFocus = React.useCallback((tabStopId: string) => {\n setTabStopId(tabStopId);\n }, []);\n\n const onItemShiftTab = React.useCallback(() => {\n setIsTabbingBackOut(true);\n }, []);\n\n const onFocusableItemAdd = React.useCallback(() => {\n setFocusableItemCount((prevCount) => prevCount + 1);\n }, []);\n\n const onFocusableItemRemove = React.useCallback(() => {\n setFocusableItemCount((prevCount) => prevCount - 1);\n }, []);\n\n const onItemRegister = React.useCallback((item: ItemData) => {\n itemsRef.current.set(item.id, item);\n }, []);\n\n const onItemUnregister = React.useCallback((id: string) => {\n itemsRef.current.delete(id);\n }, []);\n\n const getItems = React.useCallback(() => {\n return Array.from(itemsRef.current.values())\n .filter((item) => item.ref.current)\n .sort((a, b) => {\n const elementA = a.ref.current;\n const elementB = b.ref.current;\n if (!elementA || !elementB) return 0;\n const position = elementA.compareDocumentPosition(elementB);\n if (position & Node.DOCUMENT_POSITION_FOLLOWING) {\n return -1;\n }\n if (position & Node.DOCUMENT_POSITION_PRECEDING) {\n return 1;\n }\n return 0;\n });\n }, []);\n\n const onBlur = React.useCallback(\n (event: React.FocusEvent<ListElement>) => {\n propsRef.current.onBlur?.(event);\n if (event.defaultPrevented) return;\n\n setIsTabbingBackOut(false);\n },\n [propsRef]\n );\n\n const onFocus = React.useCallback(\n (event: React.FocusEvent<ListElement>) => {\n propsRef.current.onFocus?.(event);\n if (event.defaultPrevented) return;\n\n const isKeyboardFocus = !isClickFocusRef.current;\n if (event.target === event.currentTarget && isKeyboardFocus && !isTabbingBackOut) {\n const entryFocusEvent = new CustomEvent(ENTRY_FOCUS, EVENT_OPTIONS);\n event.currentTarget.dispatchEvent(entryFocusEvent);\n\n if (!entryFocusEvent.defaultPrevented) {\n const items = Array.from(itemsRef.current.values()).filter((item) => !item.disabled);\n const selectedItem = currentValue ? items.find((item) => item.value === currentValue) : undefined;\n const activeItem = items.find((item) => item.active);\n const currentItem = items.find((item) => item.id === tabStopId);\n\n const candidateItems = [selectedItem, activeItem, currentItem, ...items].filter(Boolean) as ItemData[];\n const candidateRefs = candidateItems.map((item) => item.ref);\n focusFirst(candidateRefs, false);\n }\n }\n isClickFocusRef.current = false;\n },\n [propsRef, isTabbingBackOut, currentValue, tabStopId]\n );\n\n const onMouseDown = React.useCallback(\n (event: React.MouseEvent<ListElement>) => {\n propsRef.current.onMouseDown?.(event);\n\n if (event.defaultPrevented) return;\n\n isClickFocusRef.current = true;\n },\n [propsRef]\n );\n\n const focusContextValue = React.useMemo<FocusContextValue>(\n () => ({\n tabStopId,\n onItemFocus,\n onItemShiftTab,\n onFocusableItemAdd,\n onFocusableItemRemove,\n onItemRegister,\n onItemUnregister,\n getItems\n }),\n [\n tabStopId,\n onItemFocus,\n onItemShiftTab,\n onFocusableItemAdd,\n onFocusableItemRemove,\n onItemRegister,\n onItemUnregister,\n getItems\n ]\n );\n\n const ListPrimitive = asChild ? Slot : \"div\";\n\n return (\n <FocusContext.Provider value={focusContextValue}>\n <ListPrimitive\n role=\"tablist\"\n aria-orientation={orientation}\n data-orientation={orientation}\n data-slot=\"stepper-list\"\n dir={context.dir}\n tabIndex={isTabbingBackOut || focusableItemCount === 0 ? -1 : 0}\n {...listProps}\n ref={composedRef}\n className={cn(\n \"flex outline-none\",\n orientation === \"horizontal\" ? \"flex-row items-center\" : \"flex-col items-start\",\n className\n )}\n onBlur={onBlur}\n onFocus={onFocus}\n onMouseDown={onMouseDown}\n >\n {children}\n </ListPrimitive>\n </FocusContext.Provider>\n );\n}\n\ninterface StepperItemContextValue {\n value: string;\n stepState: StepState | undefined;\n}\n\nconst StepperItemContext = React.createContext<StepperItemContextValue | null>(null);\n\nfunction useStepperItemContext(consumerName: string) {\n const context = React.useContext(StepperItemContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ITEM_NAME}\\``);\n }\n return context;\n}\n\ninterface StepperItemProps extends DivProps {\n value: string;\n completed?: boolean;\n disabled?: boolean;\n}\n\nfunction StepperItem(props: StepperItemProps) {\n const {\n value: itemValue,\n completed = false,\n disabled = false,\n asChild,\n className,\n children,\n ref,\n ...itemProps\n } = props;\n\n const context = useStepperContext(ITEM_NAME);\n const store = useStoreContext(ITEM_NAME);\n const orientation = context.orientation;\n const value = useStore((state) => state.value);\n\n /*\n * ⚠ Khác thượng nguồn: đăng ký/huỷ đăng ký chỉ phụ thuộc `itemValue`. Bản gốc phụ thuộc cả\n * `completed`/`disabled`, nên đánh dấu một bước là xong thì bước đó bị XOÁ rồi THÊM LẠI vào cuối\n * `Map` — thứ tự bước đảo (bước 1 thành \"Bước 3\"), `StepperPrev`/`StepperNext` tính sai vị trí,\n * và `onValueRemove`/`onValueAdd` bắn oan. Hai cờ đó đã có effect `setStep` ngay dưới đồng bộ.\n */\n useIsomorphicLayoutEffect(() => {\n store.addStep(itemValue, completed, disabled);\n\n return () => {\n store.removeStep(itemValue);\n };\n }, [itemValue]);\n\n useIsomorphicLayoutEffect(() => {\n store.setStep(itemValue, completed, disabled);\n }, [itemValue, completed, disabled]);\n\n const stepState = useStore((state) => state.steps.get(itemValue));\n const steps = useStore((state) => state.steps);\n const dataState = getDataState(value, itemValue, stepState, steps);\n\n const itemContextValue = React.useMemo<StepperItemContextValue>(\n () => ({\n value: itemValue,\n stepState\n }),\n [itemValue, stepState]\n );\n\n const ItemPrimitive = asChild ? Slot : \"div\";\n\n return (\n <StepperItemContext.Provider value={itemContextValue}>\n <ItemPrimitive\n data-disabled={stepState?.disabled ? \"\" : undefined}\n data-orientation={orientation}\n data-state={dataState}\n data-slot=\"stepper-item\"\n dir={context.dir}\n {...itemProps}\n ref={ref}\n className={cn(\n \"relative flex items-center not-last:flex-1\",\n orientation === \"horizontal\" ? \"flex-row\" : \"flex-col\",\n className\n )}\n >\n {children}\n </ItemPrimitive>\n </StepperItemContext.Provider>\n );\n}\n\nfunction StepperTrigger(props: ButtonProps) {\n const {\n asChild,\n onClick: onClickProp,\n onFocus: onFocusProp,\n onKeyDown: onKeyDownProp,\n onMouseDown: onMouseDownProp,\n disabled,\n className,\n ref,\n ...triggerProps\n } = props;\n\n const context = useStepperContext(TRIGGER_NAME);\n const itemContext = useStepperItemContext(TRIGGER_NAME);\n const itemValue = itemContext.value;\n\n const store = useStoreContext(TRIGGER_NAME);\n const focusContext = useFocusContext(TRIGGER_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n const stepState = useStore((state) => state.steps.get(itemValue));\n\n const propsRef = useAsRef({\n onClick: onClickProp,\n onFocus: onFocusProp,\n onKeyDown: onKeyDownProp,\n onMouseDown: onMouseDownProp\n });\n\n const activationMode = context.activationMode;\n const orientation = context.orientation;\n const loop = context.loop;\n\n const stepIndex = Array.from(steps.keys()).indexOf(itemValue);\n\n const stepPosition = stepIndex + 1;\n const stepCount = steps.size;\n\n const triggerId = getId(context.rootId, \"trigger\", itemValue);\n const contentId = getId(context.rootId, \"content\", itemValue);\n const titleId = getId(context.rootId, \"title\", itemValue);\n const descriptionId = getId(context.rootId, \"description\", itemValue);\n\n const isDisabled = disabled || stepState?.disabled || context.disabled;\n const isActive = value === itemValue;\n const isTabStop = focusContext.tabStopId === triggerId;\n const dataState = getDataState(value, itemValue, stepState, steps);\n\n const triggerRef = React.useRef<TriggerElement>(null);\n const composedRef = useComposedRefs(ref, triggerRef);\n const isArrowKeyPressedRef = React.useRef(false);\n const isMouseClickRef = React.useRef(false);\n\n React.useEffect(() => {\n function onKeyDown(event: KeyboardEvent) {\n if (ARROW_KEYS.includes(event.key)) {\n isArrowKeyPressedRef.current = true;\n }\n }\n function onKeyUp() {\n isArrowKeyPressedRef.current = false;\n }\n document.addEventListener(\"keydown\", onKeyDown);\n document.addEventListener(\"keyup\", onKeyUp);\n return () => {\n document.removeEventListener(\"keydown\", onKeyDown);\n document.removeEventListener(\"keyup\", onKeyUp);\n };\n }, []);\n\n useIsomorphicLayoutEffect(() => {\n focusContext.onItemRegister({\n id: triggerId,\n ref: triggerRef,\n value: itemValue,\n active: isTabStop,\n disabled: !!isDisabled\n });\n\n if (!isDisabled) {\n focusContext.onFocusableItemAdd();\n }\n\n return () => {\n focusContext.onItemUnregister(triggerId);\n if (!isDisabled) {\n focusContext.onFocusableItemRemove();\n }\n };\n }, [focusContext, triggerId, itemValue, isTabStop, isDisabled]);\n\n const onClick = React.useCallback(\n async (event: React.MouseEvent<TriggerElement>) => {\n propsRef.current.onClick?.(event);\n if (event.defaultPrevented) return;\n\n if (!isDisabled && !context.nonInteractive) {\n const currentStepIndex = Array.from(steps.keys()).indexOf(value ?? \"\");\n const targetStepIndex = Array.from(steps.keys()).indexOf(itemValue);\n const direction = targetStepIndex > currentStepIndex ? \"next\" : \"prev\";\n\n await store.setStateWithValidation(itemValue, direction);\n }\n },\n [isDisabled, context.nonInteractive, store, itemValue, value, steps, propsRef]\n );\n\n const onFocus = React.useCallback(\n async (event: React.FocusEvent<TriggerElement>) => {\n propsRef.current.onFocus?.(event);\n if (event.defaultPrevented) return;\n\n focusContext.onItemFocus(triggerId);\n\n const isKeyboardFocus = !isMouseClickRef.current;\n\n if (!isActive && !isDisabled && activationMode !== \"manual\" && !context.nonInteractive && isKeyboardFocus) {\n const currentStepIndex = Array.from(steps.keys()).indexOf(value || \"\");\n const targetStepIndex = Array.from(steps.keys()).indexOf(itemValue);\n const direction = targetStepIndex > currentStepIndex ? \"next\" : \"prev\";\n\n await store.setStateWithValidation(itemValue, direction);\n }\n\n isMouseClickRef.current = false;\n },\n [\n focusContext,\n triggerId,\n activationMode,\n isActive,\n isDisabled,\n context.nonInteractive,\n store,\n itemValue,\n value,\n steps,\n propsRef\n ]\n );\n\n const onKeyDown = React.useCallback(\n async (event: React.KeyboardEvent<TriggerElement>) => {\n propsRef.current.onKeyDown?.(event);\n if (event.defaultPrevented) return;\n\n if (event.key === \"Enter\" && context.nonInteractive) {\n event.preventDefault();\n return;\n }\n\n if ((event.key === \"Enter\" || event.key === \" \") && activationMode === \"manual\" && !context.nonInteractive) {\n event.preventDefault();\n if (!isDisabled && triggerRef.current) {\n triggerRef.current.click();\n }\n return;\n }\n\n if (event.key === \"Tab\" && event.shiftKey) {\n focusContext.onItemShiftTab();\n return;\n }\n\n if (event.target !== event.currentTarget) return;\n\n const focusIntent = getFocusIntent(event, context.dir, orientation);\n\n if (focusIntent !== undefined) {\n if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return;\n event.preventDefault();\n\n const items = focusContext.getItems().filter((item) => !item.disabled);\n let candidateRefs = items.map((item) => item.ref);\n\n if (focusIntent === \"last\") {\n candidateRefs.reverse();\n } else if (focusIntent === \"prev\" || focusIntent === \"next\") {\n if (focusIntent === \"prev\") candidateRefs.reverse();\n const currentIndex = candidateRefs.findIndex((ref) => ref.current === event.currentTarget);\n candidateRefs = loop ? wrapArray(candidateRefs, currentIndex + 1) : candidateRefs.slice(currentIndex + 1);\n }\n\n if (store.hasValidation() && candidateRefs.length > 0) {\n const nextRef = candidateRefs[0];\n const nextElement = nextRef?.current;\n const nextItem = items.find((item) => item.ref.current === nextElement);\n\n if (nextItem && nextItem.value !== itemValue) {\n const currentStepIndex = Array.from(steps.keys()).indexOf(value || \"\");\n const targetStepIndex = Array.from(steps.keys()).indexOf(nextItem.value);\n const direction: NavigationDirection = targetStepIndex > currentStepIndex ? \"next\" : \"prev\";\n\n if (direction === \"next\") {\n const isValid = await store.setStateWithValidation(nextItem.value, direction);\n if (!isValid) return;\n } else {\n store.setState(\"value\", nextItem.value);\n }\n\n queueMicrotask(() => nextElement?.focus());\n return;\n }\n }\n\n queueMicrotask(() => focusFirst(candidateRefs));\n }\n },\n [\n focusContext,\n context.nonInteractive,\n context.dir,\n activationMode,\n orientation,\n loop,\n isDisabled,\n store,\n propsRef,\n itemValue,\n value,\n steps\n ]\n );\n\n const onMouseDown = React.useCallback(\n (event: React.MouseEvent<TriggerElement>) => {\n propsRef.current.onMouseDown?.(event);\n if (event.defaultPrevented) return;\n\n isMouseClickRef.current = true;\n\n if (isDisabled) {\n event.preventDefault();\n } else {\n focusContext.onItemFocus(triggerId);\n }\n },\n [focusContext, triggerId, isDisabled, propsRef]\n );\n\n const TriggerPrimitive = asChild ? Slot : \"button\";\n\n return (\n <TriggerPrimitive\n id={triggerId}\n role=\"tab\"\n type=\"button\"\n aria-controls={contentId}\n aria-current={isActive ? \"step\" : undefined}\n aria-describedby={`${titleId} ${descriptionId}`}\n aria-posinset={stepPosition}\n aria-selected={isActive}\n aria-setsize={stepCount}\n data-disabled={isDisabled ? \"\" : undefined}\n data-state={dataState}\n data-slot=\"stepper-trigger\"\n disabled={isDisabled}\n tabIndex={isTabStop ? 0 : -1}\n {...triggerProps}\n ref={composedRef}\n className={cn(\n /*\n * ⚠ Khác thượng nguồn:\n * - Vòng focus theo khuôn `Checkbox`/`RadioGroup` của gói, thay cho `ring-[3px]` của bản gốc.\n * - Lỗi (`aria-invalid`) viền bằng `--destructive-ink` — VAI TRÒ viền trên nền trang (hợp\n * đồng §1 của docs/hop-dong-mau.md); bản gốc dùng `border-destructive` là token TÔ NỀN.\n */\n \"inline-flex items-center justify-center gap-3 rounded-md text-left transition-all outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive-ink aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n \"not-has-data-[slot=description]:rounded-full not-has-data-[slot=title]:rounded-full\",\n className\n )}\n onClick={onClick}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onMouseDown={onMouseDown}\n />\n );\n}\n\ninterface StepperIndicatorProps extends Omit<DivProps, \"children\"> {\n children?: React.ReactNode | ((dataState: DataState) => React.ReactNode);\n}\n\nfunction StepperIndicator(props: StepperIndicatorProps) {\n const { className, children, asChild, ref, ...indicatorProps } = props;\n\n const context = useStepperContext(INDICATOR_NAME);\n const itemContext = useStepperItemContext(INDICATOR_NAME);\n\n const value = useStore((state) => state.value);\n const itemValue = itemContext.value;\n const stepState = useStore((state) => state.steps.get(itemValue));\n const steps = useStore((state) => state.steps);\n\n const stepPosition = Array.from(steps.keys()).indexOf(itemValue) + 1;\n\n const dataState = getDataState(value, itemValue, stepState, steps);\n\n const IndicatorPrimitive = asChild ? Slot : \"div\";\n\n return (\n <IndicatorPrimitive\n data-state={dataState}\n data-slot=\"stepper-indicator\"\n dir={context.dir}\n {...indicatorProps}\n ref={ref}\n className={cn(\n /*\n * ⚠ Khác thượng nguồn — màu đi qua token VAI TRÒ (docs/hop-dong-mau.md §1, §3):\n * - Lúc nghỉ: viền `--control-edge` thay `border-muted`. Ô chỉ báo là HÌNH của chính nút\n * bước, nên viền của nó là viền control; `--muted` là token bề mặt, đem làm viền thì bảng\n * tương phản cao không kéo lên được. Ở bảng mặc định `--control-edge` nhạt đúng như bản gốc.\n * - Đang làm/đã xong: nền ĐẶC `bg-primary` + chữ/tick `text-primary-foreground` (giữ nguyên),\n * nhưng viền là `--primary-ink` chứ không `border-primary`: nền vàng đặc chỉ ~1,86:1 với\n * nền trang, nên chính VIỀN mới là dấu hiệu trạng thái đạt 3:1 (6,51:1 ở bảng tương phản cao).\n * - Chữ lúc nghỉ viết `data-[state=inactive]:text-muted-foreground` thay cho lớp trần: CSS y\n * hệt (ba trạng thái loại trừ nhau), nhưng cổng `lint:a11y` không ghép nhầm chữ xám với nền\n * vàng của trạng thái đang làm — cặp đó không bao giờ cùng xuất hiện.\n */\n \"flex size-7 shrink-0 items-center justify-center rounded-full border-2 border-control-edge bg-background text-sm font-medium data-[state=inactive]:text-muted-foreground transition-colors data-[state=active]:border-primary-ink data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=completed]:border-primary-ink data-[state=completed]:bg-primary data-[state=completed]:text-primary-foreground\",\n className\n )}\n >\n {typeof children === \"function\" ? (\n children(dataState)\n ) : children ? (\n children\n ) : dataState === \"completed\" ? (\n /*\n * ⚠ Khác thượng nguồn: bản gốc chỉ vẽ dấu tick. Trigger chỉ chứa ô chỉ báo (demo mặc định\n * của Dice UI) thì bước đã xong thành một nút KHÔNG TÊN — con số vốn là tên nút đã bị dấu\n * tick thay mất. Thêm chữ `sr-only` giữ lại con số và nói luôn trạng thái.\n */\n <>\n <Check aria-hidden=\"true\" className=\"size-4\" />\n <span className=\"sr-only\">{context.labels.completedStep(stepPosition)}</span>\n </>\n ) : (\n stepPosition\n )}\n </IndicatorPrimitive>\n );\n}\n\ninterface StepperSeparatorProps extends DivProps {\n forceMount?: boolean;\n}\n\nfunction StepperSeparator(props: StepperSeparatorProps) {\n const { className, asChild, forceMount = false, ref, ...separatorProps } = props;\n\n const context = useStepperContext(SEPARATOR_NAME);\n const itemContext = useStepperItemContext(SEPARATOR_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n\n const orientation = context.orientation;\n\n const stepIndex = Array.from(steps.keys()).indexOf(itemContext.value);\n\n const isLastStep = stepIndex === steps.size - 1;\n\n if (isLastStep && !forceMount) return null;\n\n const dataState = getDataState(value, itemContext.value, itemContext.stepState, steps, \"separator\");\n\n const SeparatorPrimitive = asChild ? Slot : \"div\";\n\n /*\n * ⚠ Khác thượng nguồn: bỏ `role=\"separator\"` + `aria-orientation`. Thẻ đã `aria-hidden` nên hai\n * thuộc tính đó không bao giờ tới trình đọc màn hình — cùng khuôn `TimelineConnector` của chính\n * Dice UI. Để lại thì cổng `lint:a11y` đọc `role=` là dấu hiệu CONTROL (thanh chia `Resizable`\n * focus được) và bắt sợi tóc trang trí ở đoạn CHƯA tới phải đạt 3:1 như một control.\n */\n return (\n <SeparatorPrimitive\n aria-hidden=\"true\"\n data-orientation={orientation}\n data-state={dataState}\n data-slot=\"stepper-separator\"\n dir={context.dir}\n {...separatorProps}\n ref={ref}\n className={cn(\n /*\n * ⚠ Khác thượng nguồn: đoạn nối ĐÃ XONG mang nghĩa tiến độ (phi văn bản, 3:1) → `--primary-ink`\n * thay `bg-primary` (token tô nền, ~1,86:1 với nền trang). Đoạn CHƯA tới giữ `bg-border`:\n * sợi tóc 1px, thuần trang trí.\n */\n \"bg-border transition-colors data-[state=active]:bg-primary-ink data-[state=completed]:bg-primary-ink\",\n orientation === \"horizontal\" ? \"h-px flex-1\" : \"h-10 w-px\",\n className\n )}\n />\n );\n}\n\ninterface StepperTitleProps extends React.ComponentProps<\"span\"> {\n asChild?: boolean;\n}\n\nfunction StepperTitle(props: StepperTitleProps) {\n const { className, asChild, ref, ...titleProps } = props;\n\n const context = useStepperContext(TITLE_NAME);\n const itemContext = useStepperItemContext(TITLE_NAME);\n\n const titleId = getId(context.rootId, \"title\", itemContext.value);\n\n const TitlePrimitive = asChild ? Slot : \"span\";\n\n return (\n <TitlePrimitive\n id={titleId}\n data-slot=\"title\"\n dir={context.dir}\n {...titleProps}\n ref={ref}\n className={cn(\"text-sm font-medium\", className)}\n />\n );\n}\n\ninterface StepperDescriptionProps extends React.ComponentProps<\"span\"> {\n asChild?: boolean;\n}\n\nfunction StepperDescription(props: StepperDescriptionProps) {\n const { className, asChild, ref, ...descriptionProps } = props;\n\n const context = useStepperContext(DESCRIPTION_NAME);\n const itemContext = useStepperItemContext(DESCRIPTION_NAME);\n\n const descriptionId = getId(context.rootId, \"description\", itemContext.value);\n\n const DescriptionPrimitive = asChild ? Slot : \"span\";\n\n return (\n <DescriptionPrimitive\n id={descriptionId}\n data-slot=\"description\"\n dir={context.dir}\n {...descriptionProps}\n ref={ref}\n className={cn(\"text-xs text-muted-foreground\", className)}\n />\n );\n}\n\ninterface StepperContentProps extends DivProps {\n value: string;\n forceMount?: boolean;\n}\n\nfunction StepperContent(props: StepperContentProps) {\n const { value: valueProp, asChild, forceMount = false, ref, className, ...contentProps } = props;\n\n const context = useStepperContext(CONTENT_NAME);\n const value = useStore((state) => state.value);\n\n const contentId = getId(context.rootId, \"content\", valueProp);\n const triggerId = getId(context.rootId, \"trigger\", valueProp);\n\n if (valueProp !== value && !forceMount) return null;\n\n const ContentPrimitive = asChild ? Slot : \"div\";\n\n return (\n <ContentPrimitive\n id={contentId}\n role=\"tabpanel\"\n aria-labelledby={triggerId}\n data-slot=\"stepper-content\"\n dir={context.dir}\n {...contentProps}\n ref={ref}\n className={cn(\"flex-1 outline-none\", className)}\n />\n );\n}\n\nfunction StepperPrev(props: ButtonProps) {\n const { asChild, onClick: onClickProp, disabled, children, ...prevProps } = props;\n\n const context = useStepperContext(PREV_NAME);\n const store = useStoreContext(PREV_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n\n const propsRef = useAsRef({\n onClick: onClickProp\n });\n\n const stepKeys = Array.from(steps.keys());\n const currentIndex = value ? stepKeys.indexOf(value) : -1;\n const isDisabled = disabled || currentIndex <= 0;\n\n const onClick = React.useCallback(\n async (event: React.MouseEvent<HTMLButtonElement>) => {\n propsRef.current.onClick?.(event);\n if (event.defaultPrevented || isDisabled) return;\n\n const prevIndex = Math.max(currentIndex - 1, 0);\n const prevStepValue = stepKeys[prevIndex];\n\n if (prevStepValue) {\n store.setState(\"value\", prevStepValue);\n }\n },\n [propsRef, isDisabled, currentIndex, stepKeys, store]\n );\n\n const PrevPrimitive = asChild ? Slot : \"button\";\n\n return (\n <PrevPrimitive type=\"button\" data-slot=\"stepper-prev\" disabled={isDisabled} {...prevProps} onClick={onClick}>\n {/* ⚠ Khác thượng nguồn: thiếu `children` thì bản gốc ra nút rỗng, không tên. */}\n {asChild ? children : (children ?? context.labels.prev)}\n </PrevPrimitive>\n );\n}\n\nfunction StepperNext(props: ButtonProps) {\n const { asChild, onClick: onClickProp, disabled, children, ...nextProps } = props;\n\n const context = useStepperContext(NEXT_NAME);\n const store = useStoreContext(NEXT_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n\n const propsRef = useAsRef({\n onClick: onClickProp\n });\n\n const stepKeys = Array.from(steps.keys());\n const currentIndex = value ? stepKeys.indexOf(value) : -1;\n const isDisabled = disabled || currentIndex >= stepKeys.length - 1;\n\n const onClick = React.useCallback(\n async (event: React.MouseEvent<HTMLButtonElement>) => {\n propsRef.current.onClick?.(event);\n if (event.defaultPrevented || isDisabled) return;\n\n const nextIndex = Math.min(currentIndex + 1, stepKeys.length - 1);\n const nextStepValue = stepKeys[nextIndex];\n\n if (nextStepValue) {\n await store.setStateWithValidation(nextStepValue, \"next\");\n }\n },\n [propsRef, isDisabled, currentIndex, stepKeys, store]\n );\n\n const NextPrimitive = asChild ? Slot : \"button\";\n\n return (\n <NextPrimitive type=\"button\" data-slot=\"stepper-next\" disabled={isDisabled} {...nextProps} onClick={onClick}>\n {/* ⚠ Khác thượng nguồn: thiếu `children` thì bản gốc ra nút rỗng, không tên. */}\n {asChild ? children : (children ?? context.labels.next)}\n </NextPrimitive>\n );\n}\n\nexport {\n Stepper,\n StepperContent,\n type StepperContentProps,\n StepperDescription,\n type StepperDescriptionProps,\n StepperIndicator,\n type StepperIndicatorProps,\n StepperItem,\n type StepperItemProps,\n StepperList,\n StepperNext,\n StepperPrev,\n type StepperProps,\n StepperSeparator,\n type StepperSeparatorProps,\n StepperTitle,\n type StepperTitleProps,\n StepperTrigger,\n useStore as useStepper\n};\n"],"mappings":"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","names":["value","disabled","tabStopId","onKeyDown","ref"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/stepper.tsx"],"sourcesContent":["\"use client\";\n\n/*\n * Port từ Dice UI (https://diceui.com/docs/components/stepper) — 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 { useDirection } from \"@radix-ui/react-direction\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { Check } from \"lucide-react\";\nimport * as React from \"react\";\nimport { useComitorLabels } from \"../../i18n/locale-provider.js\";\nimport { cn } from \"../../lib/cn.js\";\nimport { useComposedRefs } from \"../../lib/compose-refs.js\";\nimport { useAsRef } from \"../../lib/use-as-ref.js\";\nimport { useIsomorphicLayoutEffect } from \"../../lib/use-isomorphic-layout-effect.js\";\nimport { useLazyRef } from \"../../lib/use-lazy-ref.js\";\nimport type { StepperLabels } from \"./stepper-constants.js\";\n\nconst ROOT_NAME = \"Stepper\";\nconst LIST_NAME = \"StepperList\";\nconst ITEM_NAME = \"StepperItem\";\nconst TRIGGER_NAME = \"StepperTrigger\";\nconst INDICATOR_NAME = \"StepperIndicator\";\nconst SEPARATOR_NAME = \"StepperSeparator\";\nconst TITLE_NAME = \"StepperTitle\";\nconst DESCRIPTION_NAME = \"StepperDescription\";\nconst CONTENT_NAME = \"StepperContent\";\nconst PREV_NAME = \"StepperPrev\";\nconst NEXT_NAME = \"StepperNext\";\n\nconst ENTRY_FOCUS = \"stepperFocusGroup.onEntryFocus\";\nconst EVENT_OPTIONS = { bubbles: false, cancelable: true };\nconst ARROW_KEYS = [\"ArrowUp\", \"ArrowDown\", \"ArrowLeft\", \"ArrowRight\"];\n\ntype Direction = \"ltr\" | \"rtl\";\ntype Orientation = \"horizontal\" | \"vertical\";\ntype NavigationDirection = \"next\" | \"prev\";\ntype ActivationMode = \"automatic\" | \"manual\";\ntype DataState = \"inactive\" | \"active\" | \"completed\";\n\ninterface DivProps extends React.ComponentProps<\"div\"> {\n asChild?: boolean;\n}\ninterface ButtonProps extends React.ComponentProps<\"button\"> {\n asChild?: boolean;\n}\n\ntype ListElement = React.ComponentRef<typeof StepperList>;\ntype TriggerElement = React.ComponentRef<typeof StepperTrigger>;\n\nfunction getId(id: string, variant: \"trigger\" | \"content\" | \"title\" | \"description\", value: string) {\n return `${id}-${variant}-${value}`;\n}\n\ntype FocusIntent = \"first\" | \"last\" | \"prev\" | \"next\";\n\nconst MAP_KEY_TO_FOCUS_INTENT: Record<string, FocusIntent> = {\n ArrowLeft: \"prev\",\n ArrowUp: \"prev\",\n ArrowRight: \"next\",\n ArrowDown: \"next\",\n PageUp: \"first\",\n Home: \"first\",\n PageDown: \"last\",\n End: \"last\"\n};\n\nfunction getDirectionAwareKey(key: string, dir?: Direction) {\n if (dir !== \"rtl\") return key;\n return key === \"ArrowLeft\" ? \"ArrowRight\" : key === \"ArrowRight\" ? \"ArrowLeft\" : key;\n}\n\nfunction getFocusIntent(event: React.KeyboardEvent<TriggerElement>, dir?: Direction, orientation?: Orientation) {\n const key = getDirectionAwareKey(event.key, dir);\n if (orientation === \"horizontal\" && [\"ArrowUp\", \"ArrowDown\"].includes(key)) return undefined;\n if (orientation === \"vertical\" && [\"ArrowLeft\", \"ArrowRight\"].includes(key)) return undefined;\n return MAP_KEY_TO_FOCUS_INTENT[key];\n}\n\nfunction focusFirst(candidates: React.RefObject<TriggerElement | null>[], preventScroll = false) {\n const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;\n for (const candidateRef of candidates) {\n const candidate = candidateRef.current;\n if (!candidate) continue;\n if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;\n candidate.focus({ preventScroll });\n if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;\n }\n}\n\nfunction wrapArray<T>(array: T[], startIndex: number) {\n return array.map<T>((_, index) => array[(startIndex + index) % array.length] as T);\n}\n\nfunction getDataState(\n value: string | undefined,\n itemValue: string,\n stepState: StepState | undefined,\n steps: Map<string, StepState>,\n variant: \"item\" | \"separator\" = \"item\"\n): DataState {\n const stepKeys = Array.from(steps.keys());\n const currentIndex = stepKeys.indexOf(itemValue);\n\n if (stepState?.completed) return \"completed\";\n\n if (value === itemValue) {\n return variant === \"separator\" ? \"inactive\" : \"active\";\n }\n\n if (value) {\n const activeIndex = stepKeys.indexOf(value);\n\n if (activeIndex > currentIndex) return \"completed\";\n }\n\n return \"inactive\";\n}\n\ninterface StepState {\n value: string;\n completed: boolean;\n disabled: boolean;\n}\n\ninterface StoreState {\n steps: Map<string, StepState>;\n value: string;\n}\n\ninterface Store {\n subscribe: (callback: () => void) => () => void;\n getState: () => StoreState;\n setState: <K extends keyof StoreState>(key: K, value: StoreState[K]) => void;\n setStateWithValidation: (value: string, direction: NavigationDirection) => Promise<boolean>;\n hasValidation: () => boolean;\n notify: () => void;\n addStep: (value: string, completed: boolean, disabled: boolean) => void;\n removeStep: (value: string) => void;\n setStep: (value: string, completed: boolean, disabled: boolean) => void;\n}\n\nconst StoreContext = React.createContext<Store | null>(null);\n\nfunction useStoreContext(consumerName: string) {\n const context = React.useContext(StoreContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ROOT_NAME}\\``);\n }\n return context;\n}\n\nfunction useStore<T>(selector: (state: StoreState) => T): T {\n const store = useStoreContext(\"useStepper\");\n\n const getSnapshot = React.useCallback(() => selector(store.getState()), [store, selector]);\n\n return React.useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);\n}\n\ninterface ItemData {\n id: string;\n ref: React.RefObject<TriggerElement | null>;\n value: string;\n active: boolean;\n disabled: boolean;\n}\n\ninterface StepperContextValue {\n rootId: string;\n dir: Direction;\n orientation: Orientation;\n activationMode: ActivationMode;\n disabled: boolean;\n nonInteractive: boolean;\n loop: boolean;\n labels: StepperLabels;\n}\n\nconst StepperContext = React.createContext<StepperContextValue | null>(null);\n\nfunction useStepperContext(consumerName: string) {\n const context = React.useContext(StepperContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ROOT_NAME}\\``);\n }\n return context;\n}\n\ninterface StepperProps extends DivProps {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n onValueComplete?: (value: string, completed: boolean) => void;\n onValueAdd?: (value: string) => void;\n onValueRemove?: (value: string) => void;\n onValidate?: (value: string, direction: NavigationDirection) => boolean | Promise<boolean>;\n activationMode?: ActivationMode;\n dir?: Direction;\n orientation?: Orientation;\n disabled?: boolean;\n loop?: boolean;\n nonInteractive?: boolean;\n /**\n * Chuỗi hiển thị/a11y — ghi đè từng khoá. Không truyền thì theo namespace `stepper` của\n * `ComitorLocaleProvider` (mặc định tiếng Anh).\n *\n * ⚠ Thêm so với thượng nguồn: bản gốc không có chuỗi nào, và chính vì thế có hai chỗ ra nút\n * KHÔNG TÊN (ô chỉ báo bước đã xong, `StepperPrev`/`StepperNext` thiếu `children`).\n */\n labels?: Partial<StepperLabels>;\n}\n\nfunction Stepper(props: StepperProps) {\n const {\n value,\n defaultValue,\n onValueChange,\n onValueComplete,\n onValueAdd,\n onValueRemove,\n onValidate,\n dir: dirProp,\n orientation = \"horizontal\",\n activationMode = \"automatic\",\n asChild,\n disabled = false,\n nonInteractive = false,\n loop = false,\n labels: labelsProp,\n className,\n id,\n ...rootProps\n } = props;\n\n const listenersRef = useLazyRef(() => new Set<() => void>());\n const stateRef = useLazyRef<StoreState>(() => ({\n steps: new Map(),\n value: value ?? defaultValue ?? \"\"\n }));\n\n const propsRef = useAsRef({\n onValueChange,\n onValueComplete,\n onValueAdd,\n onValueRemove,\n onValidate\n });\n\n const store = React.useMemo<Store>(() => {\n return {\n subscribe: (cb) => {\n listenersRef.current.add(cb);\n return () => listenersRef.current.delete(cb);\n },\n getState: () => stateRef.current,\n setState: (key, value) => {\n if (Object.is(stateRef.current[key], value)) return;\n\n if (key === \"value\" && typeof value === \"string\") {\n stateRef.current.value = value;\n propsRef.current.onValueChange?.(value);\n } else {\n stateRef.current[key] = value;\n }\n\n store.notify();\n },\n setStateWithValidation: async (value, direction) => {\n if (!propsRef.current.onValidate) {\n store.setState(\"value\", value);\n return true;\n }\n\n try {\n const isValid = await propsRef.current.onValidate(value, direction);\n if (isValid) {\n store.setState(\"value\", value);\n }\n return isValid;\n } catch {\n return false;\n }\n },\n hasValidation: () => !!propsRef.current.onValidate,\n /*\n * ⚠ Khác thượng nguồn: mỗi lần thêm/bớt/sửa bước đều thay `steps` bằng một `Map` MỚI. Bản gốc\n * sửa tại chỗ nên `useStore((s) => s.steps)` không bao giờ thấy tham chiếu mới — phần tử chỉ\n * đọc `steps` (`StepperPrev`/`StepperNext`) không render lại sau khi các bước đăng ký, và\n * nằm `disabled` cho tới lần đổi bước đầu tiên.\n */\n addStep: (value, completed, disabled) => {\n const newStep: StepState = { value, completed, disabled };\n const steps = new Map(stateRef.current.steps);\n steps.set(value, newStep);\n stateRef.current.steps = steps;\n propsRef.current.onValueAdd?.(value);\n store.notify();\n },\n removeStep: (value) => {\n const steps = new Map(stateRef.current.steps);\n steps.delete(value);\n stateRef.current.steps = steps;\n propsRef.current.onValueRemove?.(value);\n store.notify();\n },\n setStep: (value, completed, disabled) => {\n const step = stateRef.current.steps.get(value);\n if (step) {\n const updatedStep: StepState = { ...step, completed, disabled };\n const steps = new Map(stateRef.current.steps);\n steps.set(value, updatedStep);\n stateRef.current.steps = steps;\n\n if (completed !== step.completed) {\n propsRef.current.onValueComplete?.(value, completed);\n }\n\n store.notify();\n }\n },\n notify: () => {\n for (const cb of listenersRef.current) {\n cb();\n }\n }\n };\n }, [listenersRef, stateRef, propsRef]);\n\n useIsomorphicLayoutEffect(() => {\n if (value !== undefined) {\n store.setState(\"value\", value);\n }\n }, [value]);\n\n const dir = useDirection(dirProp);\n\n const instanceId = React.useId();\n const rootId = id ?? instanceId;\n\n const labels = useComitorLabels(\"stepper\", labelsProp);\n\n const contextValue = React.useMemo<StepperContextValue>(\n () => ({\n rootId,\n dir,\n orientation,\n activationMode,\n disabled,\n nonInteractive,\n loop,\n labels\n }),\n [rootId, dir, orientation, activationMode, disabled, nonInteractive, loop, labels]\n );\n\n const RootPrimitive = asChild ? Slot : \"div\";\n\n return (\n <StoreContext.Provider value={store}>\n <StepperContext.Provider value={contextValue}>\n <RootPrimitive\n id={rootId}\n data-disabled={disabled ? \"\" : undefined}\n data-orientation={orientation}\n data-slot=\"stepper\"\n dir={dir}\n {...rootProps}\n className={cn(\"flex gap-6\", orientation === \"horizontal\" ? \"w-full flex-col\" : \"flex-row\", className)}\n />\n </StepperContext.Provider>\n </StoreContext.Provider>\n );\n}\n\ninterface FocusContextValue {\n tabStopId: string | null;\n onItemFocus: (tabStopId: string) => void;\n onItemShiftTab: () => void;\n onFocusableItemAdd: () => void;\n onFocusableItemRemove: () => void;\n onItemRegister: (item: ItemData) => void;\n onItemUnregister: (id: string) => void;\n getItems: () => ItemData[];\n}\n\nconst FocusContext = React.createContext<FocusContextValue | null>(null);\n\nfunction useFocusContext(consumerName: string) {\n const context = React.useContext(FocusContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${LIST_NAME}\\``);\n }\n return context;\n}\n\nfunction StepperList(props: DivProps) {\n const {\n asChild,\n onBlur: onBlurProp,\n onFocus: onFocusProp,\n onMouseDown: onMouseDownProp,\n className,\n children,\n ref,\n ...listProps\n } = props;\n\n const context = useStepperContext(LIST_NAME);\n const orientation = context.orientation;\n const currentValue = useStore((state) => state.value);\n\n const propsRef = useAsRef({\n onBlur: onBlurProp,\n onFocus: onFocusProp,\n onMouseDown: onMouseDownProp\n });\n\n const [tabStopId, setTabStopId] = React.useState<string | null>(null);\n const [isTabbingBackOut, setIsTabbingBackOut] = React.useState(false);\n const [focusableItemCount, setFocusableItemCount] = React.useState(0);\n const isClickFocusRef = React.useRef(false);\n const itemsRef = React.useRef<Map<string, ItemData>>(new Map());\n const listRef = React.useRef<ListElement>(null);\n const composedRef = useComposedRefs(ref, listRef);\n\n const onItemFocus = React.useCallback((tabStopId: string) => {\n setTabStopId(tabStopId);\n }, []);\n\n const onItemShiftTab = React.useCallback(() => {\n setIsTabbingBackOut(true);\n }, []);\n\n const onFocusableItemAdd = React.useCallback(() => {\n setFocusableItemCount((prevCount) => prevCount + 1);\n }, []);\n\n const onFocusableItemRemove = React.useCallback(() => {\n setFocusableItemCount((prevCount) => prevCount - 1);\n }, []);\n\n const onItemRegister = React.useCallback((item: ItemData) => {\n itemsRef.current.set(item.id, item);\n }, []);\n\n const onItemUnregister = React.useCallback((id: string) => {\n itemsRef.current.delete(id);\n }, []);\n\n const getItems = React.useCallback(() => {\n return Array.from(itemsRef.current.values())\n .filter((item) => item.ref.current)\n .sort((a, b) => {\n const elementA = a.ref.current;\n const elementB = b.ref.current;\n if (!elementA || !elementB) return 0;\n const position = elementA.compareDocumentPosition(elementB);\n if (position & Node.DOCUMENT_POSITION_FOLLOWING) {\n return -1;\n }\n if (position & Node.DOCUMENT_POSITION_PRECEDING) {\n return 1;\n }\n return 0;\n });\n }, []);\n\n const onBlur = React.useCallback(\n (event: React.FocusEvent<ListElement>) => {\n propsRef.current.onBlur?.(event);\n if (event.defaultPrevented) return;\n\n setIsTabbingBackOut(false);\n },\n [propsRef]\n );\n\n const onFocus = React.useCallback(\n (event: React.FocusEvent<ListElement>) => {\n propsRef.current.onFocus?.(event);\n if (event.defaultPrevented) return;\n\n const isKeyboardFocus = !isClickFocusRef.current;\n if (event.target === event.currentTarget && isKeyboardFocus && !isTabbingBackOut) {\n const entryFocusEvent = new CustomEvent(ENTRY_FOCUS, EVENT_OPTIONS);\n event.currentTarget.dispatchEvent(entryFocusEvent);\n\n if (!entryFocusEvent.defaultPrevented) {\n const items = Array.from(itemsRef.current.values()).filter((item) => !item.disabled);\n const selectedItem = currentValue ? items.find((item) => item.value === currentValue) : undefined;\n const activeItem = items.find((item) => item.active);\n const currentItem = items.find((item) => item.id === tabStopId);\n\n const candidateItems = [selectedItem, activeItem, currentItem, ...items].filter(Boolean) as ItemData[];\n const candidateRefs = candidateItems.map((item) => item.ref);\n focusFirst(candidateRefs, false);\n }\n }\n isClickFocusRef.current = false;\n },\n [propsRef, isTabbingBackOut, currentValue, tabStopId]\n );\n\n const onMouseDown = React.useCallback(\n (event: React.MouseEvent<ListElement>) => {\n propsRef.current.onMouseDown?.(event);\n\n if (event.defaultPrevented) return;\n\n isClickFocusRef.current = true;\n },\n [propsRef]\n );\n\n const focusContextValue = React.useMemo<FocusContextValue>(\n () => ({\n tabStopId,\n onItemFocus,\n onItemShiftTab,\n onFocusableItemAdd,\n onFocusableItemRemove,\n onItemRegister,\n onItemUnregister,\n getItems\n }),\n [\n tabStopId,\n onItemFocus,\n onItemShiftTab,\n onFocusableItemAdd,\n onFocusableItemRemove,\n onItemRegister,\n onItemUnregister,\n getItems\n ]\n );\n\n const ListPrimitive = asChild ? Slot : \"div\";\n\n return (\n <FocusContext.Provider value={focusContextValue}>\n <ListPrimitive\n role=\"tablist\"\n aria-orientation={orientation}\n data-orientation={orientation}\n data-slot=\"stepper-list\"\n dir={context.dir}\n tabIndex={isTabbingBackOut || focusableItemCount === 0 ? -1 : 0}\n {...listProps}\n ref={composedRef}\n className={cn(\n \"flex outline-none\",\n orientation === \"horizontal\" ? \"flex-row items-center\" : \"flex-col items-start\",\n className\n )}\n onBlur={onBlur}\n onFocus={onFocus}\n onMouseDown={onMouseDown}\n >\n {children}\n </ListPrimitive>\n </FocusContext.Provider>\n );\n}\n\ninterface StepperItemContextValue {\n value: string;\n stepState: StepState | undefined;\n}\n\nconst StepperItemContext = React.createContext<StepperItemContextValue | null>(null);\n\nfunction useStepperItemContext(consumerName: string) {\n const context = React.useContext(StepperItemContext);\n if (!context) {\n throw new Error(`\\`${consumerName}\\` phải nằm bên trong \\`${ITEM_NAME}\\``);\n }\n return context;\n}\n\ninterface StepperItemProps extends DivProps {\n value: string;\n completed?: boolean;\n disabled?: boolean;\n}\n\nfunction StepperItem(props: StepperItemProps) {\n const {\n value: itemValue,\n completed = false,\n disabled = false,\n asChild,\n className,\n children,\n ref,\n ...itemProps\n } = props;\n\n const context = useStepperContext(ITEM_NAME);\n const store = useStoreContext(ITEM_NAME);\n const orientation = context.orientation;\n const value = useStore((state) => state.value);\n\n /*\n * ⚠ Khác thượng nguồn: đăng ký/huỷ đăng ký chỉ phụ thuộc `itemValue`. Bản gốc phụ thuộc cả\n * `completed`/`disabled`, nên đánh dấu một bước là xong thì bước đó bị XOÁ rồi THÊM LẠI vào cuối\n * `Map` — thứ tự bước đảo (bước 1 thành \"Bước 3\"), `StepperPrev`/`StepperNext` tính sai vị trí,\n * và `onValueRemove`/`onValueAdd` bắn oan. Hai cờ đó đã có effect `setStep` ngay dưới đồng bộ.\n */\n useIsomorphicLayoutEffect(() => {\n store.addStep(itemValue, completed, disabled);\n\n return () => {\n store.removeStep(itemValue);\n };\n }, [itemValue]);\n\n useIsomorphicLayoutEffect(() => {\n store.setStep(itemValue, completed, disabled);\n }, [itemValue, completed, disabled]);\n\n const stepState = useStore((state) => state.steps.get(itemValue));\n const steps = useStore((state) => state.steps);\n const dataState = getDataState(value, itemValue, stepState, steps);\n\n const itemContextValue = React.useMemo<StepperItemContextValue>(\n () => ({\n value: itemValue,\n stepState\n }),\n [itemValue, stepState]\n );\n\n const ItemPrimitive = asChild ? Slot : \"div\";\n\n return (\n <StepperItemContext.Provider value={itemContextValue}>\n <ItemPrimitive\n data-disabled={stepState?.disabled ? \"\" : undefined}\n data-orientation={orientation}\n data-state={dataState}\n data-slot=\"stepper-item\"\n dir={context.dir}\n {...itemProps}\n ref={ref}\n className={cn(\n \"relative flex items-center not-last:flex-1\",\n orientation === \"horizontal\" ? \"flex-row\" : \"flex-col\",\n className\n )}\n >\n {children}\n </ItemPrimitive>\n </StepperItemContext.Provider>\n );\n}\n\nfunction StepperTrigger(props: ButtonProps) {\n const {\n asChild,\n onClick: onClickProp,\n onFocus: onFocusProp,\n onKeyDown: onKeyDownProp,\n onMouseDown: onMouseDownProp,\n disabled,\n className,\n ref,\n ...triggerProps\n } = props;\n\n const context = useStepperContext(TRIGGER_NAME);\n const itemContext = useStepperItemContext(TRIGGER_NAME);\n const itemValue = itemContext.value;\n\n const store = useStoreContext(TRIGGER_NAME);\n const focusContext = useFocusContext(TRIGGER_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n const stepState = useStore((state) => state.steps.get(itemValue));\n\n const propsRef = useAsRef({\n onClick: onClickProp,\n onFocus: onFocusProp,\n onKeyDown: onKeyDownProp,\n onMouseDown: onMouseDownProp\n });\n\n const activationMode = context.activationMode;\n const orientation = context.orientation;\n const loop = context.loop;\n\n const stepIndex = Array.from(steps.keys()).indexOf(itemValue);\n\n const stepPosition = stepIndex + 1;\n const stepCount = steps.size;\n\n const triggerId = getId(context.rootId, \"trigger\", itemValue);\n const contentId = getId(context.rootId, \"content\", itemValue);\n const titleId = getId(context.rootId, \"title\", itemValue);\n const descriptionId = getId(context.rootId, \"description\", itemValue);\n\n const isDisabled = disabled || stepState?.disabled || context.disabled;\n const isActive = value === itemValue;\n const isTabStop = focusContext.tabStopId === triggerId;\n const dataState = getDataState(value, itemValue, stepState, steps);\n\n const triggerRef = React.useRef<TriggerElement>(null);\n const composedRef = useComposedRefs(ref, triggerRef);\n const isArrowKeyPressedRef = React.useRef(false);\n const isMouseClickRef = React.useRef(false);\n\n React.useEffect(() => {\n function onKeyDown(event: KeyboardEvent) {\n if (ARROW_KEYS.includes(event.key)) {\n isArrowKeyPressedRef.current = true;\n }\n }\n function onKeyUp() {\n isArrowKeyPressedRef.current = false;\n }\n document.addEventListener(\"keydown\", onKeyDown);\n document.addEventListener(\"keyup\", onKeyUp);\n return () => {\n document.removeEventListener(\"keydown\", onKeyDown);\n document.removeEventListener(\"keyup\", onKeyUp);\n };\n }, []);\n\n useIsomorphicLayoutEffect(() => {\n focusContext.onItemRegister({\n id: triggerId,\n ref: triggerRef,\n value: itemValue,\n active: isTabStop,\n disabled: !!isDisabled\n });\n\n if (!isDisabled) {\n focusContext.onFocusableItemAdd();\n }\n\n return () => {\n focusContext.onItemUnregister(triggerId);\n if (!isDisabled) {\n focusContext.onFocusableItemRemove();\n }\n };\n }, [focusContext, triggerId, itemValue, isTabStop, isDisabled]);\n\n const onClick = React.useCallback(\n async (event: React.MouseEvent<TriggerElement>) => {\n propsRef.current.onClick?.(event);\n if (event.defaultPrevented) return;\n\n if (!isDisabled && !context.nonInteractive) {\n const currentStepIndex = Array.from(steps.keys()).indexOf(value ?? \"\");\n const targetStepIndex = Array.from(steps.keys()).indexOf(itemValue);\n const direction = targetStepIndex > currentStepIndex ? \"next\" : \"prev\";\n\n await store.setStateWithValidation(itemValue, direction);\n }\n },\n [isDisabled, context.nonInteractive, store, itemValue, value, steps, propsRef]\n );\n\n const onFocus = React.useCallback(\n async (event: React.FocusEvent<TriggerElement>) => {\n propsRef.current.onFocus?.(event);\n if (event.defaultPrevented) return;\n\n focusContext.onItemFocus(triggerId);\n\n const isKeyboardFocus = !isMouseClickRef.current;\n\n if (!isActive && !isDisabled && activationMode !== \"manual\" && !context.nonInteractive && isKeyboardFocus) {\n const currentStepIndex = Array.from(steps.keys()).indexOf(value || \"\");\n const targetStepIndex = Array.from(steps.keys()).indexOf(itemValue);\n const direction = targetStepIndex > currentStepIndex ? \"next\" : \"prev\";\n\n await store.setStateWithValidation(itemValue, direction);\n }\n\n isMouseClickRef.current = false;\n },\n [\n focusContext,\n triggerId,\n activationMode,\n isActive,\n isDisabled,\n context.nonInteractive,\n store,\n itemValue,\n value,\n steps,\n propsRef\n ]\n );\n\n const onKeyDown = React.useCallback(\n async (event: React.KeyboardEvent<TriggerElement>) => {\n propsRef.current.onKeyDown?.(event);\n if (event.defaultPrevented) return;\n\n if (event.key === \"Enter\" && context.nonInteractive) {\n event.preventDefault();\n return;\n }\n\n if ((event.key === \"Enter\" || event.key === \" \") && activationMode === \"manual\" && !context.nonInteractive) {\n event.preventDefault();\n if (!isDisabled && triggerRef.current) {\n triggerRef.current.click();\n }\n return;\n }\n\n if (event.key === \"Tab\" && event.shiftKey) {\n focusContext.onItemShiftTab();\n return;\n }\n\n if (event.target !== event.currentTarget) return;\n\n const focusIntent = getFocusIntent(event, context.dir, orientation);\n\n if (focusIntent !== undefined) {\n if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return;\n event.preventDefault();\n\n const items = focusContext.getItems().filter((item) => !item.disabled);\n let candidateRefs = items.map((item) => item.ref);\n\n if (focusIntent === \"last\") {\n candidateRefs.reverse();\n } else if (focusIntent === \"prev\" || focusIntent === \"next\") {\n if (focusIntent === \"prev\") candidateRefs.reverse();\n const currentIndex = candidateRefs.findIndex((ref) => ref.current === event.currentTarget);\n candidateRefs = loop ? wrapArray(candidateRefs, currentIndex + 1) : candidateRefs.slice(currentIndex + 1);\n }\n\n if (store.hasValidation() && candidateRefs.length > 0) {\n const nextRef = candidateRefs[0];\n const nextElement = nextRef?.current;\n const nextItem = items.find((item) => item.ref.current === nextElement);\n\n if (nextItem && nextItem.value !== itemValue) {\n const currentStepIndex = Array.from(steps.keys()).indexOf(value || \"\");\n const targetStepIndex = Array.from(steps.keys()).indexOf(nextItem.value);\n const direction: NavigationDirection = targetStepIndex > currentStepIndex ? \"next\" : \"prev\";\n\n if (direction === \"next\") {\n const isValid = await store.setStateWithValidation(nextItem.value, direction);\n if (!isValid) return;\n } else {\n store.setState(\"value\", nextItem.value);\n }\n\n queueMicrotask(() => nextElement?.focus());\n return;\n }\n }\n\n queueMicrotask(() => focusFirst(candidateRefs));\n }\n },\n [\n focusContext,\n context.nonInteractive,\n context.dir,\n activationMode,\n orientation,\n loop,\n isDisabled,\n store,\n propsRef,\n itemValue,\n value,\n steps\n ]\n );\n\n const onMouseDown = React.useCallback(\n (event: React.MouseEvent<TriggerElement>) => {\n propsRef.current.onMouseDown?.(event);\n if (event.defaultPrevented) return;\n\n isMouseClickRef.current = true;\n\n if (isDisabled) {\n event.preventDefault();\n } else {\n focusContext.onItemFocus(triggerId);\n }\n },\n [focusContext, triggerId, isDisabled, propsRef]\n );\n\n const TriggerPrimitive = asChild ? Slot : \"button\";\n\n return (\n <TriggerPrimitive\n id={triggerId}\n role=\"tab\"\n type=\"button\"\n aria-controls={contentId}\n aria-current={isActive ? \"step\" : undefined}\n aria-describedby={`${titleId} ${descriptionId}`}\n aria-posinset={stepPosition}\n aria-selected={isActive}\n aria-setsize={stepCount}\n data-disabled={isDisabled ? \"\" : undefined}\n data-state={dataState}\n data-slot=\"stepper-trigger\"\n disabled={isDisabled}\n tabIndex={isTabStop ? 0 : -1}\n {...triggerProps}\n ref={composedRef}\n className={cn(\n /*\n * ⚠ Khác thượng nguồn:\n * - Vòng focus theo khuôn `Checkbox`/`RadioGroup` của gói, thay cho `ring-[3px]` của bản gốc.\n * - Lỗi (`aria-invalid`) viền bằng `--destructive-ink` — VAI TRÒ viền trên nền trang (hợp\n * đồng §1 của docs/hop-dong-mau.md); bản gốc dùng `border-destructive` là token TÔ NỀN.\n */\n \"inline-flex items-center justify-center gap-3 rounded-md text-left transition-all outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive-ink aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n \"not-has-data-[slot=description]:rounded-full not-has-data-[slot=title]:rounded-full\",\n className\n )}\n onClick={onClick}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n onMouseDown={onMouseDown}\n />\n );\n}\n\ninterface StepperIndicatorProps extends Omit<DivProps, \"children\"> {\n children?: React.ReactNode | ((dataState: DataState) => React.ReactNode);\n}\n\nfunction StepperIndicator(props: StepperIndicatorProps) {\n const { className, children, asChild, ref, ...indicatorProps } = props;\n\n const context = useStepperContext(INDICATOR_NAME);\n const itemContext = useStepperItemContext(INDICATOR_NAME);\n\n const value = useStore((state) => state.value);\n const itemValue = itemContext.value;\n const stepState = useStore((state) => state.steps.get(itemValue));\n const steps = useStore((state) => state.steps);\n\n const stepPosition = Array.from(steps.keys()).indexOf(itemValue) + 1;\n\n const dataState = getDataState(value, itemValue, stepState, steps);\n\n const IndicatorPrimitive = asChild ? Slot : \"div\";\n\n return (\n <IndicatorPrimitive\n data-state={dataState}\n data-slot=\"stepper-indicator\"\n dir={context.dir}\n {...indicatorProps}\n ref={ref}\n className={cn(\n /*\n * ⚠ Khác thượng nguồn — màu đi qua token VAI TRÒ (docs/hop-dong-mau.md §1, §3):\n * - Lúc nghỉ: viền `--control-edge` thay `border-muted`. Ô chỉ báo là HÌNH của chính nút\n * bước, nên viền của nó là viền control; `--muted` là token bề mặt, đem làm viền thì bảng\n * tương phản cao không kéo lên được. Ở bảng mặc định `--control-edge` nhạt đúng như bản gốc.\n * - Đang làm/đã xong: nền ĐẶC `bg-primary` + chữ/tick `text-primary-foreground` (giữ nguyên),\n * nhưng viền là `--primary-ink` chứ không `border-primary`: nền vàng đặc chỉ ~1,86:1 với\n * nền trang, nên chính VIỀN mới là dấu hiệu trạng thái đạt 3:1 (6,51:1 ở bảng tương phản cao).\n * - Chữ lúc nghỉ viết `data-[state=inactive]:text-muted-foreground` thay cho lớp trần: CSS y\n * hệt (ba trạng thái loại trừ nhau), nhưng cổng `lint:a11y` không ghép nhầm chữ xám với nền\n * vàng của trạng thái đang làm — cặp đó không bao giờ cùng xuất hiện.\n */\n \"flex size-7 shrink-0 items-center justify-center rounded-full border-2 border-control-edge bg-background text-sm font-medium data-[state=inactive]:text-muted-foreground transition-colors data-[state=active]:border-primary-ink data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=completed]:border-primary-ink data-[state=completed]:bg-primary data-[state=completed]:text-primary-foreground\",\n className\n )}\n >\n {typeof children === \"function\" ? (\n children(dataState)\n ) : children ? (\n children\n ) : dataState === \"completed\" ? (\n /*\n * ⚠ Khác thượng nguồn: bản gốc chỉ vẽ dấu tick. Trigger chỉ chứa ô chỉ báo (demo mặc định\n * của Dice UI) thì bước đã xong thành một nút KHÔNG TÊN — con số vốn là tên nút đã bị dấu\n * tick thay mất. Thêm chữ `sr-only` giữ lại con số và nói luôn trạng thái.\n */\n <>\n <Check aria-hidden=\"true\" className=\"size-4\" />\n <span className=\"sr-only\">{context.labels.completedStep(stepPosition)}</span>\n </>\n ) : (\n stepPosition\n )}\n </IndicatorPrimitive>\n );\n}\n\ninterface StepperSeparatorProps extends DivProps {\n forceMount?: boolean;\n}\n\nfunction StepperSeparator(props: StepperSeparatorProps) {\n const { className, asChild, forceMount = false, ref, ...separatorProps } = props;\n\n const context = useStepperContext(SEPARATOR_NAME);\n const itemContext = useStepperItemContext(SEPARATOR_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n\n const orientation = context.orientation;\n\n const stepIndex = Array.from(steps.keys()).indexOf(itemContext.value);\n\n const isLastStep = stepIndex === steps.size - 1;\n\n if (isLastStep && !forceMount) return null;\n\n const dataState = getDataState(value, itemContext.value, itemContext.stepState, steps, \"separator\");\n\n const SeparatorPrimitive = asChild ? Slot : \"div\";\n\n /*\n * ⚠ Khác thượng nguồn: bỏ `role=\"separator\"` + `aria-orientation`. Thẻ đã `aria-hidden` nên hai\n * thuộc tính đó không bao giờ tới trình đọc màn hình — cùng khuôn `TimelineConnector` của chính\n * Dice UI. Để lại thì cổng `lint:a11y` đọc `role=` là dấu hiệu CONTROL (thanh chia `Resizable`\n * focus được) và bắt sợi tóc trang trí ở đoạn CHƯA tới phải đạt 3:1 như một control.\n */\n return (\n <SeparatorPrimitive\n aria-hidden=\"true\"\n data-orientation={orientation}\n data-state={dataState}\n data-slot=\"stepper-separator\"\n dir={context.dir}\n {...separatorProps}\n ref={ref}\n className={cn(\n /*\n * ⚠ Khác thượng nguồn: đoạn nối ĐÃ XONG mang nghĩa tiến độ (phi văn bản, 3:1) → `--primary-ink`\n * thay `bg-primary` (token tô nền, ~1,86:1 với nền trang). Đoạn CHƯA tới giữ `bg-border`:\n * sợi tóc 1px, thuần trang trí.\n */\n \"bg-border transition-colors data-[state=active]:bg-primary-ink data-[state=completed]:bg-primary-ink\",\n orientation === \"horizontal\" ? \"h-px flex-1\" : \"h-10 w-px\",\n className\n )}\n />\n );\n}\n\ninterface StepperTitleProps extends React.ComponentProps<\"span\"> {\n asChild?: boolean;\n}\n\nfunction StepperTitle(props: StepperTitleProps) {\n const { className, asChild, ref, ...titleProps } = props;\n\n const context = useStepperContext(TITLE_NAME);\n const itemContext = useStepperItemContext(TITLE_NAME);\n\n const titleId = getId(context.rootId, \"title\", itemContext.value);\n\n const TitlePrimitive = asChild ? Slot : \"span\";\n\n return (\n <TitlePrimitive\n id={titleId}\n data-slot=\"title\"\n dir={context.dir}\n {...titleProps}\n ref={ref}\n className={cn(\"text-sm font-medium\", className)}\n />\n );\n}\n\ninterface StepperDescriptionProps extends React.ComponentProps<\"span\"> {\n asChild?: boolean;\n}\n\nfunction StepperDescription(props: StepperDescriptionProps) {\n const { className, asChild, ref, ...descriptionProps } = props;\n\n const context = useStepperContext(DESCRIPTION_NAME);\n const itemContext = useStepperItemContext(DESCRIPTION_NAME);\n\n const descriptionId = getId(context.rootId, \"description\", itemContext.value);\n\n const DescriptionPrimitive = asChild ? Slot : \"span\";\n\n return (\n <DescriptionPrimitive\n id={descriptionId}\n data-slot=\"description\"\n dir={context.dir}\n {...descriptionProps}\n ref={ref}\n className={cn(\"text-xs text-muted-foreground\", className)}\n />\n );\n}\n\ninterface StepperContentProps extends DivProps {\n value: string;\n forceMount?: boolean;\n}\n\nfunction StepperContent(props: StepperContentProps) {\n const { value: valueProp, asChild, forceMount = false, ref, className, ...contentProps } = props;\n\n const context = useStepperContext(CONTENT_NAME);\n const value = useStore((state) => state.value);\n\n const contentId = getId(context.rootId, \"content\", valueProp);\n const triggerId = getId(context.rootId, \"trigger\", valueProp);\n\n if (valueProp !== value && !forceMount) return null;\n\n const ContentPrimitive = asChild ? Slot : \"div\";\n\n return (\n <ContentPrimitive\n id={contentId}\n role=\"tabpanel\"\n aria-labelledby={triggerId}\n data-slot=\"stepper-content\"\n dir={context.dir}\n {...contentProps}\n ref={ref}\n className={cn(\"flex-1 outline-none\", className)}\n />\n );\n}\n\nfunction StepperPrev(props: ButtonProps) {\n const { asChild, onClick: onClickProp, disabled, children, ...prevProps } = props;\n\n const context = useStepperContext(PREV_NAME);\n const store = useStoreContext(PREV_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n\n const propsRef = useAsRef({\n onClick: onClickProp\n });\n\n const stepKeys = Array.from(steps.keys());\n const currentIndex = value ? stepKeys.indexOf(value) : -1;\n const isDisabled = disabled || currentIndex <= 0;\n\n const onClick = React.useCallback(\n async (event: React.MouseEvent<HTMLButtonElement>) => {\n propsRef.current.onClick?.(event);\n if (event.defaultPrevented || isDisabled) return;\n\n const prevIndex = Math.max(currentIndex - 1, 0);\n const prevStepValue = stepKeys[prevIndex];\n\n if (prevStepValue) {\n store.setState(\"value\", prevStepValue);\n }\n },\n [propsRef, isDisabled, currentIndex, stepKeys, store]\n );\n\n const PrevPrimitive = asChild ? Slot : \"button\";\n\n return (\n <PrevPrimitive type=\"button\" data-slot=\"stepper-prev\" disabled={isDisabled} {...prevProps} onClick={onClick}>\n {/* ⚠ Khác thượng nguồn: thiếu `children` thì bản gốc ra nút rỗng, không tên. */}\n {asChild ? children : (children ?? context.labels.prev)}\n </PrevPrimitive>\n );\n}\n\nfunction StepperNext(props: ButtonProps) {\n const { asChild, onClick: onClickProp, disabled, children, ...nextProps } = props;\n\n const context = useStepperContext(NEXT_NAME);\n const store = useStoreContext(NEXT_NAME);\n const value = useStore((state) => state.value);\n const steps = useStore((state) => state.steps);\n\n const propsRef = useAsRef({\n onClick: onClickProp\n });\n\n const stepKeys = Array.from(steps.keys());\n const currentIndex = value ? stepKeys.indexOf(value) : -1;\n const isDisabled = disabled || currentIndex >= stepKeys.length - 1;\n\n const onClick = React.useCallback(\n async (event: React.MouseEvent<HTMLButtonElement>) => {\n propsRef.current.onClick?.(event);\n if (event.defaultPrevented || isDisabled) return;\n\n const nextIndex = Math.min(currentIndex + 1, stepKeys.length - 1);\n const nextStepValue = stepKeys[nextIndex];\n\n if (nextStepValue) {\n await store.setStateWithValidation(nextStepValue, \"next\");\n }\n },\n [propsRef, isDisabled, currentIndex, stepKeys, store]\n );\n\n const NextPrimitive = asChild ? Slot : \"button\";\n\n return (\n <NextPrimitive type=\"button\" data-slot=\"stepper-next\" disabled={isDisabled} {...nextProps} onClick={onClick}>\n {/* ⚠ Khác thượng nguồn: thiếu `children` thì bản gốc ra nút rỗng, không tên. */}\n {asChild ? children : (children ?? context.labels.next)}\n </NextPrimitive>\n );\n}\n\nexport {\n Stepper,\n StepperContent,\n type StepperContentProps,\n StepperDescription,\n type StepperDescriptionProps,\n StepperIndicator,\n type StepperIndicatorProps,\n StepperItem,\n type StepperItemProps,\n StepperList,\n StepperNext,\n StepperPrev,\n type StepperProps,\n StepperSeparator,\n type StepperSeparatorProps,\n StepperTitle,\n type StepperTitleProps,\n StepperTrigger,\n useStore as useStepper\n};\n"],"mappings":"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","names":["value","disabled","tabStopId","onKeyDown","ref"]}
|
|
@@ -22,7 +22,8 @@ type TagsInputInputProps = React.ComponentProps<typeof TagsInputPrimitive.Input>
|
|
|
22
22
|
declare function TagsInputInput({ className, ...props }: TagsInputInputProps): React.JSX.Element;
|
|
23
23
|
interface TagsInputItemProps extends React.ComponentProps<typeof TagsInputPrimitive.Item> {
|
|
24
24
|
/**
|
|
25
|
-
* Tên cho trình đọc màn hình của nút xoá thẻ — mặc định `
|
|
25
|
+
* Tên cho trình đọc màn hình của nút xoá thẻ — mặc định khoá `deleteLabel` của namespace
|
|
26
|
+
* `tagsInput` (`ComitorLocaleProvider`).
|
|
26
27
|
*
|
|
27
28
|
* ⚠ Thêm so với thượng nguồn. Nút xoá chỉ có một icon ✕; gói headless đặt cho nó
|
|
28
29
|
* `aria-labelledby` trỏ vào CHỮ của thẻ, nên trình đọc màn hình đọc "react, nút" — nghe như
|
|
@@ -30,7 +31,7 @@ interface TagsInputItemProps extends React.ComponentProps<typeof TagsInputPrimit
|
|
|
30
31
|
*/
|
|
31
32
|
deleteLabel?: (value: string) => string;
|
|
32
33
|
}
|
|
33
|
-
declare function TagsInputItem({ className, children, deleteLabel, ...props }: TagsInputItemProps): React.JSX.Element;
|
|
34
|
+
declare function TagsInputItem({ className, children, deleteLabel: deleteLabelProp, ...props }: TagsInputItemProps): React.JSX.Element;
|
|
34
35
|
type TagsInputClearProps = React.ComponentProps<typeof TagsInputPrimitive.Clear>;
|
|
35
36
|
/**
|
|
36
37
|
* Nút xoá hết thẻ. Không có nội dung mặc định (đúng thượng nguồn) — app tự đặt chữ/icon bên
|
|
@@ -3,6 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as TagsInputPrimitive from "@diceui/tags-input";
|
|
4
4
|
import { useDirection } from "@radix-ui/react-direction";
|
|
5
5
|
import { X } from "lucide-react";
|
|
6
|
+
import { useComitorMessages } from "../../i18n/locale-provider.js";
|
|
6
7
|
import { cn } from "../../lib/cn.js";
|
|
7
8
|
function TagsInput({ className, dir: dirProp, ...props }) {
|
|
8
9
|
const dir = useDirection(dirProp);
|
|
@@ -78,8 +79,9 @@ function TagsInputInput({ className, ...props }) {
|
|
|
78
79
|
}
|
|
79
80
|
);
|
|
80
81
|
}
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
function TagsInputItem({ className, children, deleteLabel: deleteLabelProp, ...props }) {
|
|
83
|
+
const t = useComitorMessages("tagsInput");
|
|
84
|
+
const deleteLabel = deleteLabelProp ?? t.deleteLabel;
|
|
83
85
|
return /* @__PURE__ */ jsxs(
|
|
84
86
|
TagsInputPrimitive.Item,
|
|
85
87
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/tags-input.tsx"],"sourcesContent":["\"use client\";\n\n/*\n * Port từ Dice UI (https://diceui.com/docs/components/tags-input) — 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 * as TagsInputPrimitive from \"@diceui/tags-input\";\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport { X } from \"lucide-react\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * TagsInput — ô nhập THẺ TỰ DO: gõ chữ rồi Enter (hoặc gõ dấu phân cách) để thành một thẻ.\n * Dùng cho nhãn tự đặt trên task / bản ghi CRM, danh sách người nhận email.\n *\n * ⚠ KHÁC `MultiCombobox`: `MultiCombobox` chọn nhiều giá trị từ một danh sách CỐ ĐỊNH; TagsInput\n * nhận giá trị người dùng TỰ GÕ, không có danh sách gợi ý. Đừng gộp hai thứ — giá trị hợp lệ\n * của chúng khác nhau về bản chất (có trong tập ⇄ bất kỳ chuỗi nào qua được `onValidate`).\n *\n * Phần lõi (bàn phím, dán, sửa tại chỗ, input ẩn cho form) là gói headless `@diceui/tags-input`;\n * file này chỉ phủ style theo token của Comitor.\n */\ntype TagsInputProps = React.ComponentProps<typeof TagsInputPrimitive.Root>;\n\nfunction TagsInput({ className, dir: dirProp, ...props }: TagsInputProps) {\n /*\n * ⚠ Khác thượng nguồn: `@diceui/shared` có `useDirection` RIÊNG, đọc một `DirectionContext` mà\n * gói không xuất ra — nên `DirectionProvider` của Radix (nguồn hướng chữ của mọi component khác\n * trong gói, vd `Rating`) không tới được nó, và app RTL thấy ô thẻ vẫn chạy LTR. Đọc hướng từ\n * Radix rồi truyền xuống bằng prop `dir` (prop của app vẫn thắng).\n */\n const dir = useDirection(dirProp);\n\n return (\n <TagsInputPrimitive.Root\n data-slot=\"tags-input\"\n dir={dir}\n // ⚠ Khác thượng nguồn: bản gốc ghim `w-[380px]` (kích thước của trang demo). Primitive của\n // gói luôn `w-full` như `Input` — bề rộng là việc của bố cục bên ngoài.\n className={cn(\"flex w-full flex-col gap-2\", className)}\n {...props}\n />\n );\n}\n\ntype TagsInputLabelProps = React.ComponentProps<typeof TagsInputPrimitive.Label>;\n\nfunction TagsInputLabel({ className, ...props }: TagsInputLabelProps) {\n return (\n <TagsInputPrimitive.Label\n data-slot=\"tags-input-label\"\n className={cn(\n /*\n * ⚠ Khác thượng nguồn: `peer-disabled:` của bản gốc không bao giờ khớp — nhãn đứng TRƯỚC ô\n * nhập, mà `peer-*` chỉ nhìn anh em đứng trước. Trạng thái vô hiệu nằm ở `data-disabled` của\n * gốc `TagsInput`, nên đọc bằng `in-data-disabled:`. Mức mờ theo `Label` của gói (50).\n */\n \"text-sm leading-none font-medium in-data-disabled:cursor-not-allowed in-data-disabled:opacity-50\",\n className\n )}\n {...props}\n />\n );\n}\n\ntype TagsInputListProps = React.ComponentProps<\"div\">;\n\nfunction TagsInputList({ className, ...props }: TagsInputListProps) {\n return (\n <div\n data-slot=\"tags-input-list\"\n className={cn(\n /*\n * Khung này là \"ô nhập\" mà người dùng nhìn thấy (thẻ + ô gõ nằm chung), nên nó mặc đúng bộ\n * viền của `Input`: `border-input` lúc nghỉ, đậm lên `--control-edge-strong` khi rê chuột,\n * `--primary-ink` + vòng `ring/50` khi có focus BÊN TRONG. Số đo ở chú thích đầu `input.tsx`.\n *\n * ⚠ Khác thượng nguồn:\n * · `focus-within:ring-1 ring-ring` → khuôn focus của `Input` (ring-2 ring/50 + viền ink).\n * · rê chuột lúc đang focus KHÔNG được đè viền focus: `focus-within` xếp TRƯỚC `hover`\n * trong thứ tự biến thể của Tailwind v4, nên hover phải kèm `not-focus-within`.\n * · `disabled:` trên một `<div>` không bao giờ khớp → `has-[input:disabled]:` (gốc vô\n * hiệu thì gói đặt `disabled` THẬT lên ô gõ bên trong). Chọn `:disabled` gốc của HTML\n * chứ không `data-disabled` vì đó là trạng thái mà WCAG 1.4.3/1.4.11 miễn trừ — và là\n * trạng thái duy nhất cổng màu nhận ra là \"vô hiệu\".\n * · `min-h-10 py-2` → `min-h-9 py-1.5`: cao đúng `h-9` của `Input` khi chưa có thẻ, để\n * đứng cạnh các ô khác trong cùng một form không lệch dòng.\n */\n \"flex min-h-9 w-full flex-wrap items-center gap-1.5 rounded-md border border-input bg-background px-3 py-1.5 text-sm text-foreground transition-colors duration-150 ease-out hover:not-focus-within:border-control-edge-strong focus-within:border-primary-ink focus-within:ring-2 focus-within:ring-ring/50 has-[input:disabled]:cursor-not-allowed has-[input:disabled]:bg-muted has-[input:disabled]:opacity-50\",\n className\n )}\n {...props}\n />\n );\n}\n\ntype TagsInputInputProps = React.ComponentProps<typeof TagsInputPrimitive.Input>;\n\nfunction TagsInputInput({ className, ...props }: TagsInputInputProps) {\n return (\n <TagsInputPrimitive.Input\n data-slot=\"tags-input-input\"\n className={cn(\n // `min-w-0` (thêm): ô gõ là mục flex co giãn — thiếu nó thì chiều rộng tối thiểu nội tại\n // của `<input>` đẩy hàng thẻ xuống dòng sớm.\n \"min-w-0 flex-1 bg-transparent outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n />\n );\n}\n\ninterface TagsInputItemProps extends React.ComponentProps<typeof TagsInputPrimitive.Item> {\n /**\n * Tên cho trình đọc màn hình của nút xoá thẻ — mặc định `(value) => \"Xoá thẻ \" + value`.\n *\n * ⚠ Thêm so với thượng nguồn. Nút xoá chỉ có một icon ✕; gói headless đặt cho nó\n * `aria-labelledby` trỏ vào CHỮ của thẻ, nên trình đọc màn hình đọc \"react, nút\" — nghe như\n * một nút mang tên thẻ chứ không phải nút xoá thẻ. Là HÀM vì giá trị thẻ chèn vào giữa câu.\n */\n deleteLabel?: (value: string) => string;\n}\n\nconst defaultDeleteLabel = (value: string) => `Xoá thẻ ${value}`;\n\nfunction TagsInputItem({ className, children, deleteLabel = defaultDeleteLabel, ...props }: TagsInputItemProps) {\n return (\n <TagsInputPrimitive.Item\n data-slot=\"tags-input-item\"\n /*\n * ⚠ Khác thượng nguồn (a11y): gói đặt `aria-labelledby` lên thẻ — một `<div>` KHÔNG có role,\n * mà ARIA 1.2 CẤM đặt tên cho vai trò `generic` (axe: `aria-prohibited-attr`). Chữ của thẻ đã\n * nằm ngay bên trong nên gỡ đi không mất gì.\n */\n aria-labelledby={undefined}\n className={cn(\n /*\n * Viền thẻ là viền TRANG TRÍ (`--border`, mặc định của `@layer base`): thẻ không phải một\n * control — control là nút ✕ bên trong. Thẻ đang được chọn bằng bàn phím tô\n * `bg-accent`/`text-accent-foreground`, cùng cặp với mục đang sáng của `CommandItem`.\n * ⚠ Khác thượng nguồn: `ring-1 ring-ring` lúc sửa tại chỗ → khuôn `ring-2 ring-ring/50`\n * của gói; `px-2.5 py-1` → `px-2 py-0.5` để thẻ lọt khung cao `h-9`.\n */\n \"inline-flex max-w-[calc(100%-8px)] items-center gap-1.5 rounded border bg-transparent px-2 py-0.5 text-sm focus:outline-hidden data-disabled:cursor-not-allowed data-disabled:opacity-50 data-editable:select-none data-editing:bg-transparent data-editing:ring-2 data-editing:ring-ring/50 [&:not([data-editing])]:pr-1 [&[data-highlighted]:not([data-editing])]:bg-accent [&[data-highlighted]:not([data-editing])]:text-accent-foreground\",\n className\n )}\n {...props}\n >\n <TagsInputPrimitive.ItemText className=\"truncate\">{children}</TagsInputPrimitive.ItemText>\n <TagsInputPrimitive.ItemDelete\n /*\n * ⚠ Khác thượng nguồn (a11y):\n * · Tên nút: gói đặt `aria-labelledby` = chữ của thẻ (xem `deleteLabel`). `aria-labelledby`\n * THẮNG `aria-label` trong phép tính tên, nên phải gỡ nó ra (props của ta được trải SAU\n * props của gói, nên `undefined` ở đây xoá được thuộc tính).\n * · `tabIndex`: gói đặt `disabled ? undefined : -1` — tức ngược: nút ĐANG dùng được thì\n * ra khỏi thứ tự Tab (đúng thiết kế: bàn phím xoá thẻ bằng ←/Backspace/Delete từ ô gõ),\n * còn nút VÔ HIỆU thì lại lọt VÀO thứ tự Tab, nhận focus mà bấm không làm gì. Ghim -1\n * cho cả hai trạng thái; trình đọc màn hình ở chế độ duyệt vẫn bấm được nút.\n */\n aria-labelledby={undefined}\n aria-label={deleteLabel(props.value)}\n tabIndex={-1}\n className=\"size-4 shrink-0 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100\"\n >\n <X aria-hidden=\"true\" className=\"size-3.5\" />\n </TagsInputPrimitive.ItemDelete>\n </TagsInputPrimitive.Item>\n );\n}\n\ntype TagsInputClearProps = React.ComponentProps<typeof TagsInputPrimitive.Clear>;\n\n/**\n * Nút xoá hết thẻ. Không có nội dung mặc định (đúng thượng nguồn) — app tự đặt chữ/icon bên\n * trong; nếu chỉ đặt icon thì PHẢI kèm `aria-label` (vd \"Xoá tất cả thẻ\").\n */\nfunction TagsInputClear({ ...props }: TagsInputClearProps) {\n return <TagsInputPrimitive.Clear data-slot=\"tags-input-clear\" {...props} />;\n}\n\nexport {\n TagsInput,\n TagsInputClear,\n type TagsInputClearProps,\n TagsInputInput,\n type TagsInputInputProps,\n TagsInputItem,\n type TagsInputItemProps,\n TagsInputLabel,\n type TagsInputLabelProps,\n TagsInputList,\n type TagsInputListProps,\n type TagsInputProps\n};\n"],"mappings":";AAoCI,cA8FA,YA9FA;AA7BJ,YAAY,wBAAwB;AACpC,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAElB,SAAS,UAAU;AAenB,SAAS,UAAU,EAAE,WAAW,KAAK,SAAS,GAAG,MAAM,GAAmB;AAOxE,QAAM,MAAM,aAAa,OAAO;AAEhC,SACE;AAAA,IAAC,mBAAmB;AAAA,IAAnB;AAAA,MACC,aAAU;AAAA,MACV;AAAA,MAGA,WAAW,GAAG,8BAA8B,SAAS;AAAA,MACpD,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,eAAe,EAAE,WAAW,GAAG,MAAM,GAAwB;AACpE,SACE;AAAA,IAAC,mBAAmB;AAAA,IAAnB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,cAAc,EAAE,WAAW,GAAG,MAAM,GAAuB;AAClE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAiBT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,eAAe,EAAE,WAAW,GAAG,MAAM,GAAwB;AACpE,SACE;AAAA,IAAC,mBAAmB;AAAA,IAAnB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA;AAAA;AAAA,QAGT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAaA,MAAM,qBAAqB,CAAC,UAAkB,mBAAW,KAAK;AAE9D,SAAS,cAAc,EAAE,WAAW,UAAU,cAAc,oBAAoB,GAAG,MAAM,GAAuB;AAC9G,SACE;AAAA,IAAC,mBAAmB;AAAA,IAAnB;AAAA,MACC,aAAU;AAAA,MAMV,mBAAiB;AAAA,MACjB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,4BAAC,mBAAmB,UAAnB,EAA4B,WAAU,YAAY,UAAS;AAAA,QAC5D;AAAA,UAAC,mBAAmB;AAAA,UAAnB;AAAA,YAWC,mBAAiB;AAAA,YACjB,cAAY,YAAY,MAAM,KAAK;AAAA,YACnC,UAAU;AAAA,YACV,WAAU;AAAA,YAEV,8BAAC,KAAE,eAAY,QAAO,WAAU,YAAW;AAAA;AAAA,QAC7C;AAAA;AAAA;AAAA,EACF;AAEJ;AAQA,SAAS,eAAe,EAAE,GAAG,MAAM,GAAwB;AACzD,SAAO,oBAAC,mBAAmB,OAAnB,EAAyB,aAAU,oBAAoB,GAAG,OAAO;AAC3E;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/tags-input.tsx"],"sourcesContent":["\"use client\";\n\n/*\n * Port từ Dice UI (https://diceui.com/docs/components/tags-input) — 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 * as TagsInputPrimitive from \"@diceui/tags-input\";\nimport { useDirection } from \"@radix-ui/react-direction\";\nimport { X } from \"lucide-react\";\nimport type * as React from \"react\";\nimport { useComitorMessages } from \"../../i18n/locale-provider.js\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * TagsInput — ô nhập THẺ TỰ DO: gõ chữ rồi Enter (hoặc gõ dấu phân cách) để thành một thẻ.\n * Dùng cho nhãn tự đặt trên task / bản ghi CRM, danh sách người nhận email.\n *\n * ⚠ KHÁC `MultiCombobox`: `MultiCombobox` chọn nhiều giá trị từ một danh sách CỐ ĐỊNH; TagsInput\n * nhận giá trị người dùng TỰ GÕ, không có danh sách gợi ý. Đừng gộp hai thứ — giá trị hợp lệ\n * của chúng khác nhau về bản chất (có trong tập ⇄ bất kỳ chuỗi nào qua được `onValidate`).\n *\n * Phần lõi (bàn phím, dán, sửa tại chỗ, input ẩn cho form) là gói headless `@diceui/tags-input`;\n * file này chỉ phủ style theo token của Comitor.\n */\ntype TagsInputProps = React.ComponentProps<typeof TagsInputPrimitive.Root>;\n\nfunction TagsInput({ className, dir: dirProp, ...props }: TagsInputProps) {\n /*\n * ⚠ Khác thượng nguồn: `@diceui/shared` có `useDirection` RIÊNG, đọc một `DirectionContext` mà\n * gói không xuất ra — nên `DirectionProvider` của Radix (nguồn hướng chữ của mọi component khác\n * trong gói, vd `Rating`) không tới được nó, và app RTL thấy ô thẻ vẫn chạy LTR. Đọc hướng từ\n * Radix rồi truyền xuống bằng prop `dir` (prop của app vẫn thắng).\n */\n const dir = useDirection(dirProp);\n\n return (\n <TagsInputPrimitive.Root\n data-slot=\"tags-input\"\n dir={dir}\n // ⚠ Khác thượng nguồn: bản gốc ghim `w-[380px]` (kích thước của trang demo). Primitive của\n // gói luôn `w-full` như `Input` — bề rộng là việc của bố cục bên ngoài.\n className={cn(\"flex w-full flex-col gap-2\", className)}\n {...props}\n />\n );\n}\n\ntype TagsInputLabelProps = React.ComponentProps<typeof TagsInputPrimitive.Label>;\n\nfunction TagsInputLabel({ className, ...props }: TagsInputLabelProps) {\n return (\n <TagsInputPrimitive.Label\n data-slot=\"tags-input-label\"\n className={cn(\n /*\n * ⚠ Khác thượng nguồn: `peer-disabled:` của bản gốc không bao giờ khớp — nhãn đứng TRƯỚC ô\n * nhập, mà `peer-*` chỉ nhìn anh em đứng trước. Trạng thái vô hiệu nằm ở `data-disabled` của\n * gốc `TagsInput`, nên đọc bằng `in-data-disabled:`. Mức mờ theo `Label` của gói (50).\n */\n \"text-sm leading-none font-medium in-data-disabled:cursor-not-allowed in-data-disabled:opacity-50\",\n className\n )}\n {...props}\n />\n );\n}\n\ntype TagsInputListProps = React.ComponentProps<\"div\">;\n\nfunction TagsInputList({ className, ...props }: TagsInputListProps) {\n return (\n <div\n data-slot=\"tags-input-list\"\n className={cn(\n /*\n * Khung này là \"ô nhập\" mà người dùng nhìn thấy (thẻ + ô gõ nằm chung), nên nó mặc đúng bộ\n * viền của `Input`: `border-input` lúc nghỉ, đậm lên `--control-edge-strong` khi rê chuột,\n * `--primary-ink` + vòng `ring/50` khi có focus BÊN TRONG. Số đo ở chú thích đầu `input.tsx`.\n *\n * ⚠ Khác thượng nguồn:\n * · `focus-within:ring-1 ring-ring` → khuôn focus của `Input` (ring-2 ring/50 + viền ink).\n * · rê chuột lúc đang focus KHÔNG được đè viền focus: `focus-within` xếp TRƯỚC `hover`\n * trong thứ tự biến thể của Tailwind v4, nên hover phải kèm `not-focus-within`.\n * · `disabled:` trên một `<div>` không bao giờ khớp → `has-[input:disabled]:` (gốc vô\n * hiệu thì gói đặt `disabled` THẬT lên ô gõ bên trong). Chọn `:disabled` gốc của HTML\n * chứ không `data-disabled` vì đó là trạng thái mà WCAG 1.4.3/1.4.11 miễn trừ — và là\n * trạng thái duy nhất cổng màu nhận ra là \"vô hiệu\".\n * · `min-h-10 py-2` → `min-h-9 py-1.5`: cao đúng `h-9` của `Input` khi chưa có thẻ, để\n * đứng cạnh các ô khác trong cùng một form không lệch dòng.\n */\n \"flex min-h-9 w-full flex-wrap items-center gap-1.5 rounded-md border border-input bg-background px-3 py-1.5 text-sm text-foreground transition-colors duration-150 ease-out hover:not-focus-within:border-control-edge-strong focus-within:border-primary-ink focus-within:ring-2 focus-within:ring-ring/50 has-[input:disabled]:cursor-not-allowed has-[input:disabled]:bg-muted has-[input:disabled]:opacity-50\",\n className\n )}\n {...props}\n />\n );\n}\n\ntype TagsInputInputProps = React.ComponentProps<typeof TagsInputPrimitive.Input>;\n\nfunction TagsInputInput({ className, ...props }: TagsInputInputProps) {\n return (\n <TagsInputPrimitive.Input\n data-slot=\"tags-input-input\"\n className={cn(\n // `min-w-0` (thêm): ô gõ là mục flex co giãn — thiếu nó thì chiều rộng tối thiểu nội tại\n // của `<input>` đẩy hàng thẻ xuống dòng sớm.\n \"min-w-0 flex-1 bg-transparent outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n />\n );\n}\n\ninterface TagsInputItemProps extends React.ComponentProps<typeof TagsInputPrimitive.Item> {\n /**\n * Tên cho trình đọc màn hình của nút xoá thẻ — mặc định khoá `deleteLabel` của namespace\n * `tagsInput` (`ComitorLocaleProvider`).\n *\n * ⚠ Thêm so với thượng nguồn. Nút xoá chỉ có một icon ✕; gói headless đặt cho nó\n * `aria-labelledby` trỏ vào CHỮ của thẻ, nên trình đọc màn hình đọc \"react, nút\" — nghe như\n * một nút mang tên thẻ chứ không phải nút xoá thẻ. Là HÀM vì giá trị thẻ chèn vào giữa câu.\n */\n deleteLabel?: (value: string) => string;\n}\n\nfunction TagsInputItem({ className, children, deleteLabel: deleteLabelProp, ...props }: TagsInputItemProps) {\n const t = useComitorMessages(\"tagsInput\");\n const deleteLabel = deleteLabelProp ?? t.deleteLabel;\n return (\n <TagsInputPrimitive.Item\n data-slot=\"tags-input-item\"\n /*\n * ⚠ Khác thượng nguồn (a11y): gói đặt `aria-labelledby` lên thẻ — một `<div>` KHÔNG có role,\n * mà ARIA 1.2 CẤM đặt tên cho vai trò `generic` (axe: `aria-prohibited-attr`). Chữ của thẻ đã\n * nằm ngay bên trong nên gỡ đi không mất gì.\n */\n aria-labelledby={undefined}\n className={cn(\n /*\n * Viền thẻ là viền TRANG TRÍ (`--border`, mặc định của `@layer base`): thẻ không phải một\n * control — control là nút ✕ bên trong. Thẻ đang được chọn bằng bàn phím tô\n * `bg-accent`/`text-accent-foreground`, cùng cặp với mục đang sáng của `CommandItem`.\n * ⚠ Khác thượng nguồn: `ring-1 ring-ring` lúc sửa tại chỗ → khuôn `ring-2 ring-ring/50`\n * của gói; `px-2.5 py-1` → `px-2 py-0.5` để thẻ lọt khung cao `h-9`.\n */\n \"inline-flex max-w-[calc(100%-8px)] items-center gap-1.5 rounded border bg-transparent px-2 py-0.5 text-sm focus:outline-hidden data-disabled:cursor-not-allowed data-disabled:opacity-50 data-editable:select-none data-editing:bg-transparent data-editing:ring-2 data-editing:ring-ring/50 [&:not([data-editing])]:pr-1 [&[data-highlighted]:not([data-editing])]:bg-accent [&[data-highlighted]:not([data-editing])]:text-accent-foreground\",\n className\n )}\n {...props}\n >\n <TagsInputPrimitive.ItemText className=\"truncate\">{children}</TagsInputPrimitive.ItemText>\n <TagsInputPrimitive.ItemDelete\n /*\n * ⚠ Khác thượng nguồn (a11y):\n * · Tên nút: gói đặt `aria-labelledby` = chữ của thẻ (xem `deleteLabel`). `aria-labelledby`\n * THẮNG `aria-label` trong phép tính tên, nên phải gỡ nó ra (props của ta được trải SAU\n * props của gói, nên `undefined` ở đây xoá được thuộc tính).\n * · `tabIndex`: gói đặt `disabled ? undefined : -1` — tức ngược: nút ĐANG dùng được thì\n * ra khỏi thứ tự Tab (đúng thiết kế: bàn phím xoá thẻ bằng ←/Backspace/Delete từ ô gõ),\n * còn nút VÔ HIỆU thì lại lọt VÀO thứ tự Tab, nhận focus mà bấm không làm gì. Ghim -1\n * cho cả hai trạng thái; trình đọc màn hình ở chế độ duyệt vẫn bấm được nút.\n */\n aria-labelledby={undefined}\n aria-label={deleteLabel(props.value)}\n tabIndex={-1}\n className=\"size-4 shrink-0 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100\"\n >\n <X aria-hidden=\"true\" className=\"size-3.5\" />\n </TagsInputPrimitive.ItemDelete>\n </TagsInputPrimitive.Item>\n );\n}\n\ntype TagsInputClearProps = React.ComponentProps<typeof TagsInputPrimitive.Clear>;\n\n/**\n * Nút xoá hết thẻ. Không có nội dung mặc định (đúng thượng nguồn) — app tự đặt chữ/icon bên\n * trong; nếu chỉ đặt icon thì PHẢI kèm `aria-label` (vd \"Xoá tất cả thẻ\").\n */\nfunction TagsInputClear({ ...props }: TagsInputClearProps) {\n return <TagsInputPrimitive.Clear data-slot=\"tags-input-clear\" {...props} />;\n}\n\nexport {\n TagsInput,\n TagsInputClear,\n type TagsInputClearProps,\n TagsInputInput,\n type TagsInputInputProps,\n TagsInputItem,\n type TagsInputItemProps,\n TagsInputLabel,\n type TagsInputLabelProps,\n TagsInputList,\n type TagsInputListProps,\n type TagsInputProps\n};\n"],"mappings":";AAqCI,cA+FA,YA/FA;AA9BJ,YAAY,wBAAwB;AACpC,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAElB,SAAS,0BAA0B;AACnC,SAAS,UAAU;AAenB,SAAS,UAAU,EAAE,WAAW,KAAK,SAAS,GAAG,MAAM,GAAmB;AAOxE,QAAM,MAAM,aAAa,OAAO;AAEhC,SACE;AAAA,IAAC,mBAAmB;AAAA,IAAnB;AAAA,MACC,aAAU;AAAA,MACV;AAAA,MAGA,WAAW,GAAG,8BAA8B,SAAS;AAAA,MACpD,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,eAAe,EAAE,WAAW,GAAG,MAAM,GAAwB;AACpE,SACE;AAAA,IAAC,mBAAmB;AAAA,IAAnB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,cAAc,EAAE,WAAW,GAAG,MAAM,GAAuB;AAClE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAiBT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,eAAe,EAAE,WAAW,GAAG,MAAM,GAAwB;AACpE,SACE;AAAA,IAAC,mBAAmB;AAAA,IAAnB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA;AAAA;AAAA,QAGT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAcA,SAAS,cAAc,EAAE,WAAW,UAAU,aAAa,iBAAiB,GAAG,MAAM,GAAuB;AAC1G,QAAM,IAAI,mBAAmB,WAAW;AACxC,QAAM,cAAc,mBAAmB,EAAE;AACzC,SACE;AAAA,IAAC,mBAAmB;AAAA,IAAnB;AAAA,MACC,aAAU;AAAA,MAMV,mBAAiB;AAAA,MACjB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEJ;AAAA,4BAAC,mBAAmB,UAAnB,EAA4B,WAAU,YAAY,UAAS;AAAA,QAC5D;AAAA,UAAC,mBAAmB;AAAA,UAAnB;AAAA,YAWC,mBAAiB;AAAA,YACjB,cAAY,YAAY,MAAM,KAAK;AAAA,YACnC,UAAU;AAAA,YACV,WAAU;AAAA,YAEV,8BAAC,KAAE,eAAY,QAAO,WAAU,YAAW;AAAA;AAAA,QAC7C;AAAA;AAAA;AAAA,EACF;AAEJ;AAQA,SAAS,eAAe,EAAE,GAAG,MAAM,GAAwB;AACzD,SAAO,oBAAC,mBAAmB,OAAnB,EAAyB,aAAU,oBAAoB,GAAG,OAAO;AAC3E;","names":[]}
|
|
@@ -11,12 +11,14 @@
|
|
|
11
11
|
* KHÔNG được `export` lại (re-export qua file client là vô hiệu, và đụng tên với `export *`).
|
|
12
12
|
*/
|
|
13
13
|
/**
|
|
14
|
-
* Toàn bộ chuỗi hiển thị (kể cả chuỗi chỉ dành cho trình đọc màn hình) của `TimePicker
|
|
15
|
-
*
|
|
14
|
+
* Toàn bộ chuỗi hiển thị (kể cả chuỗi chỉ dành cho trình đọc màn hình) của `TimePicker`. Theo
|
|
15
|
+
* `ComitorLocaleProvider` (mặc định tiếng Anh, bảng tiếng Việt dựng sẵn); đè từng khoá qua prop
|
|
16
|
+
* `labels` của `TimePicker`.
|
|
16
17
|
*
|
|
17
|
-
* ⚠
|
|
18
|
-
*
|
|
19
|
-
*
|
|
18
|
+
* ⚠ Hai trục tách nhau: NHÃN theo ngôn ngữ của provider, còn đồng hồ 12 hay 24 giờ theo `locale`
|
|
19
|
+
* (prop `locale` của `TimePicker`, không truyền thì `locale` của provider). Không provider →
|
|
20
|
+
* 12 giờ, "AM"/"PM"; provider `vi` → 24 giờ (ô buổi ẩn). App ép `locale="en-US"` dưới provider
|
|
21
|
+
* `vi` sẽ được đồng hồ 12 giờ với nhãn "SA"/"CH" — đúng cách viết tiếng Việt.
|
|
20
22
|
*/
|
|
21
23
|
interface TimePickerLabels {
|
|
22
24
|
/** Tên ô giờ (`TimePickerInput segment="hour"`) VÀ tên cột giờ trong bảng chọn — trình đọc màn hình */
|
|
@@ -29,10 +31,10 @@ interface TimePickerLabels {
|
|
|
29
31
|
period: string;
|
|
30
32
|
/**
|
|
31
33
|
* Chữ HIỆN của buổi sáng (giá trị lưu vẫn là giờ 24h, không phụ thuộc nhãn này). Ký tự đầu của
|
|
32
|
-
* nó cũng là phím tắt khi ô buổi đang focus — "S" cho "SA" — bên cạnh `A`/`1` của thượng nguồn.
|
|
34
|
+
* nó cũng là phím tắt khi ô buổi đang focus — vd "S" cho "SA" — bên cạnh `A`/`1` của thượng nguồn.
|
|
33
35
|
*/
|
|
34
36
|
am: string;
|
|
35
|
-
/** Chữ HIỆN của buổi chiều — ký tự đầu là phím tắt ("C" cho "CH"), bên cạnh `P`/`2`. */
|
|
37
|
+
/** Chữ HIỆN của buổi chiều — ký tự đầu là phím tắt (vd "C" cho "CH"), bên cạnh `P`/`2`. */
|
|
36
38
|
pm: string;
|
|
37
39
|
/** Tên nút mở bảng chọn (`TimePickerTrigger` mặc định chỉ có icon đồng hồ) — `sr-only` */
|
|
38
40
|
openPicker: string;
|
|
@@ -40,8 +42,9 @@ interface TimePickerLabels {
|
|
|
40
42
|
clear: string;
|
|
41
43
|
}
|
|
42
44
|
/**
|
|
43
|
-
*
|
|
44
|
-
* `
|
|
45
|
+
* 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:
|
|
46
|
+
* `comitorMessagesVi.timePicker`. Component không đọc thẳng hằng này — nó đọc bảng của
|
|
47
|
+
* `ComitorLocaleProvider`; hằng ở đây để app trải ra khi tự dựng nhãn.
|
|
45
48
|
*/
|
|
46
49
|
declare const DEFAULT_TIME_PICKER_LABELS: TimePickerLabels;
|
|
47
50
|
|
|
@@ -1,13 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
minute: "Ph\xFAt",
|
|
4
|
-
second: "Gi\xE2y",
|
|
5
|
-
period: "Bu\u1ED5i",
|
|
6
|
-
am: "SA",
|
|
7
|
-
pm: "CH",
|
|
8
|
-
openPicker: "M\u1EDF b\u1EA3ng ch\u1ECDn gi\u1EDD",
|
|
9
|
-
clear: "X\xF3a"
|
|
10
|
-
};
|
|
1
|
+
import { timePickerEn } from "../../i18n/namespaces/time-picker.js";
|
|
2
|
+
const DEFAULT_TIME_PICKER_LABELS = { ...timePickerEn };
|
|
11
3
|
export {
|
|
12
4
|
DEFAULT_TIME_PICKER_LABELS
|
|
13
5
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/time-picker-constants.ts"],"sourcesContent":["/**\n * Nhãn mặc định của `TimePicker`.\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\n * client-reference proxy, đọc ra `undefined` mà KHÔNG throw, KHÔNG warning. Hằng dữ liệu thuần\n * (nhãn mặc định) là thứ trang server hay đọc nhất — spread để override một khoá — nên phải\n * sống ngoài ranh giới client.\n *\n * ⚠ Barrel `src/index.ts` xuất module này TRỰC TIẾP. `time-picker.tsx` chỉ được `import`,\n * KHÔNG được `export` lại (re-export qua file client là vô hiệu, và đụng tên với `export *`).\n */\n\n/**\n * Toàn bộ chuỗi hiển thị (kể cả chuỗi chỉ dành cho trình đọc màn hình) của `TimePicker
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/time-picker-constants.ts"],"sourcesContent":["/**\n * Nhãn mặc định của `TimePicker`.\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\n * client-reference proxy, đọc ra `undefined` mà KHÔNG throw, KHÔNG warning. Hằng dữ liệu thuần\n * (nhãn mặc định) là thứ trang server hay đọc nhất — spread để override một khoá — nên phải\n * sống ngoài ranh giới client.\n *\n * ⚠ Barrel `src/index.ts` xuất module này TRỰC TIẾP. `time-picker.tsx` chỉ được `import`,\n * KHÔNG được `export` lại (re-export qua file client là vô hiệu, và đụng tên với `export *`).\n */\n\nimport { timePickerEn } from \"../../i18n/namespaces/time-picker.js\";\n\n/**\n * Toàn bộ chuỗi hiển thị (kể cả chuỗi chỉ dành cho trình đọc màn hình) của `TimePicker`. Theo\n * `ComitorLocaleProvider` (mặc định tiếng Anh, bảng tiếng Việt dựng sẵn); đè từng khoá qua prop\n * `labels` của `TimePicker`.\n *\n * ⚠ Hai trục tách nhau: NHÃN theo ngôn ngữ của provider, còn đồng hồ 12 hay 24 giờ theo `locale`\n * (prop `locale` của `TimePicker`, không truyền thì `locale` của provider). Không provider →\n * 12 giờ, \"AM\"/\"PM\"; provider `vi` → 24 giờ (ô buổi ẩn). App ép `locale=\"en-US\"` dưới provider\n * `vi` sẽ được đồng hồ 12 giờ với nhãn \"SA\"/\"CH\" — đúng cách viết tiếng Việt.\n */\nexport interface TimePickerLabels {\n /** Tên ô giờ (`TimePickerInput segment=\"hour\"`) VÀ tên cột giờ trong bảng chọn — trình đọc màn hình */\n hour: string;\n /** Tên ô phút và cột phút — trình đọc màn hình */\n minute: string;\n /** Tên ô giây và cột giây — trình đọc màn hình */\n second: string;\n /** Tên ô buổi và cột buổi (chỉ có ở đồng hồ 12 giờ) — trình đọc màn hình */\n period: string;\n /**\n * Chữ HIỆN của buổi sáng (giá trị lưu vẫn là giờ 24h, không phụ thuộc nhãn này). Ký tự đầu của\n * nó cũng là phím tắt khi ô buổi đang focus — vd \"S\" cho \"SA\" — bên cạnh `A`/`1` của thượng nguồn.\n */\n am: string;\n /** Chữ HIỆN của buổi chiều — ký tự đầu là phím tắt (vd \"C\" cho \"CH\"), bên cạnh `P`/`2`. */\n pm: string;\n /** Tên nút mở bảng chọn (`TimePickerTrigger` mặc định chỉ có icon đồng hồ) — `sr-only` */\n openPicker: string;\n /** Chữ mặc định của nút `TimePickerClear` */\n clear: 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.timePicker`. 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_TIME_PICKER_LABELS: TimePickerLabels = { ...timePickerEn };\n"],"mappings":"AAaA,SAAS,oBAAoB;AAuCtB,MAAM,6BAA+C,EAAE,GAAG,aAAa;","names":[]}
|
|
@@ -56,16 +56,21 @@ interface TimePickerProps extends DivProps {
|
|
|
56
56
|
/** Chữ giữ chỗ của ô trống — một chuỗi cho mọi ô, hoặc từng ô. Mặc định `"--"`. */
|
|
57
57
|
segmentPlaceholder?: SegmentPlaceholder;
|
|
58
58
|
/**
|
|
59
|
-
* Locale BCP 47 quyết định đồng hồ 12 hay 24 giờ — CHỈ vậy, không dịch nhãn (
|
|
59
|
+
* Locale BCP 47 quyết định đồng hồ 12 hay 24 giờ — CHỈ vậy, không dịch nhãn (nhãn theo
|
|
60
|
+
* `ComitorLocaleProvider`, xem `labels`).
|
|
60
61
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
62
|
+
* Không truyền thì lấy `locale` của `ComitorLocaleProvider`: không có provider → `"en"` → 12 giờ
|
|
63
|
+
* ("AM"/"PM"); `"vi"` → 24 giờ; `"en-GB"` → 24 giờ. Trước `3.0.0` mặc định cứng là `"vi-VN"`.
|
|
64
|
+
*
|
|
65
|
+
* ⚠ Khác thượng nguồn: bản gốc để `undefined`, tức theo locale của MÔI TRƯỜNG CHẠY — xem chú
|
|
66
|
+
* thích ở chỗ đọc prop này trong `TimePicker`. Muốn theo trình duyệt: truyền `navigator.language`
|
|
67
|
+
* — nhưng chỉ sau khi hydrate, vì server không biết giá trị đó.
|
|
64
68
|
*/
|
|
65
69
|
locale?: string;
|
|
66
70
|
/**
|
|
67
|
-
* Chuỗi hiển thị và nhãn trình đọc màn hình (tên từng ô,
|
|
68
|
-
*
|
|
71
|
+
* Chuỗi hiển thị và nhãn trình đọc màn hình (tên từng ô, nhãn buổi, tên nút mở, nút xoá). Không
|
|
72
|
+
* truyền thì theo namespace `timePicker` của `ComitorLocaleProvider` (mặc định tiếng Anh). Thêm
|
|
73
|
+
* so với thượng nguồn.
|
|
69
74
|
*/
|
|
70
75
|
labels?: Partial<TimePickerLabels>;
|
|
71
76
|
name?: string;
|
|
@@ -3,6 +3,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { Slot } from "@radix-ui/react-slot";
|
|
4
4
|
import { Clock } from "lucide-react";
|
|
5
5
|
import * as React from "react";
|
|
6
|
+
import { useComitorLabels, useComitorLocale } from "../../i18n/locale-provider.js";
|
|
6
7
|
import { cn } from "../../lib/cn.js";
|
|
7
8
|
import { useComposedRefs } from "../../lib/compose-refs.js";
|
|
8
9
|
import { useAsRef } from "../../lib/use-as-ref.js";
|
|
@@ -10,7 +11,6 @@ import { useIsomorphicLayoutEffect } from "../../lib/use-isomorphic-layout-effec
|
|
|
10
11
|
import { useLazyRef } from "../../lib/use-lazy-ref.js";
|
|
11
12
|
import { VisuallyHiddenInput } from "../../lib/visually-hidden-input.js";
|
|
12
13
|
import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from "./popover.js";
|
|
13
|
-
import { DEFAULT_TIME_PICKER_LABELS } from "./time-picker-constants.js";
|
|
14
14
|
const ROOT_NAME = "TimePicker";
|
|
15
15
|
const LABEL_NAME = "TimePickerLabel";
|
|
16
16
|
const INPUT_GROUP_NAME = "TimePickerInputGroup";
|
|
@@ -26,7 +26,6 @@ const PERIOD_NAME = "TimePickerPeriod";
|
|
|
26
26
|
const CLEAR_NAME = "TimePickerClear";
|
|
27
27
|
const DEFAULT_STEP = 1;
|
|
28
28
|
const DEFAULT_SEGMENT_PLACEHOLDER = "--";
|
|
29
|
-
const DEFAULT_LOCALE = "vi-VN";
|
|
30
29
|
const SEGMENTS = ["hour", "minute", "second", "period"];
|
|
31
30
|
const PERIODS = ["AM", "PM"];
|
|
32
31
|
function focusFirst(candidates, preventScroll = false) {
|
|
@@ -167,7 +166,7 @@ function TimePicker(props) {
|
|
|
167
166
|
minuteStep = DEFAULT_STEP,
|
|
168
167
|
secondStep = DEFAULT_STEP,
|
|
169
168
|
segmentPlaceholder = DEFAULT_SEGMENT_PLACEHOLDER,
|
|
170
|
-
locale
|
|
169
|
+
locale: localeProp,
|
|
171
170
|
labels: labelsProp,
|
|
172
171
|
name,
|
|
173
172
|
asChild,
|
|
@@ -181,6 +180,8 @@ function TimePicker(props) {
|
|
|
181
180
|
id,
|
|
182
181
|
...rootProps
|
|
183
182
|
} = props;
|
|
183
|
+
const { locale: providerLocale } = useComitorLocale();
|
|
184
|
+
const locale = localeProp ?? providerLocale;
|
|
184
185
|
const instanceId = React.useId();
|
|
185
186
|
const rootId = id ?? instanceId;
|
|
186
187
|
const inputGroupId = React.useId();
|
|
@@ -257,10 +258,7 @@ function TimePicker(props) {
|
|
|
257
258
|
period: segmentPlaceholder.period ?? DEFAULT_SEGMENT_PLACEHOLDER
|
|
258
259
|
};
|
|
259
260
|
}, [segmentPlaceholder]);
|
|
260
|
-
const labels =
|
|
261
|
-
() => ({ ...DEFAULT_TIME_PICKER_LABELS, ...labelsProp }),
|
|
262
|
-
[labelsProp]
|
|
263
|
-
);
|
|
261
|
+
const labels = useComitorLabels("timePicker", labelsProp);
|
|
264
262
|
const rootContext = React.useMemo(
|
|
265
263
|
() => ({
|
|
266
264
|
id: rootId,
|