tembro 2.0.6 → 2.1.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/dist/components/calendar/calendar.cjs +1 -1
- package/dist/components/calendar/calendar.d.ts +2 -1
- package/dist/components/calendar/calendar.js +126 -122
- package/dist/components/calendar/date-range-picker.cjs +1 -1
- package/dist/components/calendar/date-range-picker.d.ts +2 -1
- package/dist/components/calendar/date-range-picker.js +39 -39
- package/dist/components/charts/charts.cjs +1 -1
- package/dist/components/charts/charts.d.ts +13 -4
- package/dist/components/charts/charts.js +76 -46
- package/dist/components/charts/progress-ring.cjs +1 -1
- package/dist/components/charts/progress-ring.d.ts +3 -1
- package/dist/components/charts/progress-ring.js +11 -10
- package/dist/components/data-table/data-table-column-visibility-menu.cjs +1 -1
- package/dist/components/data-table/data-table-column-visibility-menu.d.ts +4 -1
- package/dist/components/data-table/data-table-column-visibility-menu.js +36 -8
- package/dist/components/data-table/data-table-toolbar.cjs +1 -1
- package/dist/components/data-table/data-table-toolbar.js +12 -13
- package/dist/components/display/carousel.cjs +1 -1
- package/dist/components/display/carousel.d.ts +9 -1
- package/dist/components/display/carousel.js +123 -81
- package/dist/components/display/code-block.cjs +2 -2
- package/dist/components/display/code-block.d.ts +2 -1
- package/dist/components/display/code-block.js +17 -12
- package/dist/components/display/delta-badge.cjs +1 -1
- package/dist/components/display/delta-badge.d.ts +2 -1
- package/dist/components/display/delta-badge.js +11 -7
- package/dist/components/display/kanban.cjs +1 -1
- package/dist/components/display/kanban.d.ts +4 -1
- package/dist/components/display/kanban.js +60 -33
- package/dist/components/display/metric-grid.cjs +1 -1
- package/dist/components/display/metric-grid.d.ts +1 -0
- package/dist/components/display/metric-grid.js +1 -1
- package/dist/components/display/qr-code.cjs +1 -1
- package/dist/components/display/qr-code.d.ts +2 -1
- package/dist/components/display/qr-code.js +19 -16
- package/dist/components/display/tag.cjs +1 -1
- package/dist/components/display/tag.d.ts +2 -1
- package/dist/components/display/tag.js +28 -22
- package/dist/components/display/tree-view.cjs +1 -1
- package/dist/components/display/tree-view.d.ts +9 -1
- package/dist/components/display/tree-view.js +104 -40
- package/dist/components/display/trend-card.cjs +1 -1
- package/dist/components/display/trend-card.js +27 -41
- package/dist/components/feedback/alert.cjs +1 -1
- package/dist/components/feedback/alert.d.ts +2 -1
- package/dist/components/feedback/alert.js +6 -6
- package/dist/components/feedback/loading-state.cjs +1 -1
- package/dist/components/feedback/loading-state.d.ts +3 -1
- package/dist/components/feedback/loading-state.js +23 -10
- package/dist/components/feedback/page-state.cjs +1 -1
- package/dist/components/feedback/page-state.d.ts +2 -1
- package/dist/components/feedback/page-state.js +7 -4
- package/dist/components/form/form-field-shell.cjs +1 -1
- package/dist/components/form/form-field-shell.d.ts +4 -2
- package/dist/components/form/form-field-shell.js +57 -41
- package/dist/components/form/form-input.cjs +1 -1
- package/dist/components/form/form-input.js +2 -0
- package/dist/components/form/form-select.cjs +1 -1
- package/dist/components/form/form-select.js +2 -0
- package/dist/components/form/form-switch.cjs +1 -1
- package/dist/components/form/form-switch.d.ts +1 -1
- package/dist/components/form/form-switch.js +58 -54
- package/dist/components/form/form-textarea.cjs +1 -1
- package/dist/components/form/form-textarea.d.ts +1 -1
- package/dist/components/form/form-textarea.js +29 -27
- package/dist/components/layout/app-sidebar.cjs +1 -1
- package/dist/components/layout/app-sidebar.d.ts +1 -0
- package/dist/components/layout/app-sidebar.js +36 -36
- package/dist/components/layout/breadcrumbs.cjs +1 -1
- package/dist/components/layout/breadcrumbs.d.ts +2 -1
- package/dist/components/layout/breadcrumbs.js +7 -7
- package/dist/components/modern/calendar-scheduler.cjs +1 -1
- package/dist/components/modern/calendar-scheduler.d.ts +5 -1
- package/dist/components/modern/calendar-scheduler.js +47 -28
- package/dist/components/modern/dual-list-picker.cjs +1 -1
- package/dist/components/modern/dual-list-picker.d.ts +5 -1
- package/dist/components/modern/dual-list-picker.js +81 -23
- package/dist/components/modern/rich-text-editor.cjs +1 -1
- package/dist/components/modern/rich-text-editor.d.ts +3 -1
- package/dist/components/modern/rich-text-editor.js +12 -9
- package/dist/components/modern/tour.cjs +1 -1
- package/dist/components/modern/tour.d.ts +5 -1
- package/dist/components/modern/tour.js +57 -35
- package/dist/components/navigation/command-bar.cjs +1 -1
- package/dist/components/navigation/command-bar.d.ts +3 -1
- package/dist/components/navigation/command-bar.js +10 -7
- package/dist/components/navigation/demo.cjs +1 -1
- package/dist/components/navigation/demo.js +0 -1
- package/dist/components/navigation/nav-tabs.cjs +1 -1
- package/dist/components/navigation/nav-tabs.js +39 -27
- package/dist/components/navigation/page-tabs.cjs +1 -1
- package/dist/components/navigation/page-tabs.js +41 -30
- package/dist/components/navigation/pagination.cjs +1 -1
- package/dist/components/navigation/pagination.d.ts +7 -1
- package/dist/components/navigation/pagination.js +48 -25
- package/dist/components/notifications/notification-center.cjs +1 -1
- package/dist/components/notifications/notification-center.d.ts +3 -1
- package/dist/components/notifications/notification-center.js +56 -38
- package/dist/components/notifications/toast.cjs +1 -1
- package/dist/components/notifications/toast.d.ts +1 -0
- package/dist/components/notifications/toast.js +4 -0
- package/dist/components/overlay/alert-dialog.cjs +1 -1
- package/dist/components/overlay/alert-dialog.js +1 -1
- package/dist/components/overlay/confirm-dialog.cjs +1 -1
- package/dist/components/overlay/confirm-dialog.d.ts +4 -2
- package/dist/components/overlay/confirm-dialog.js +31 -22
- package/dist/components/overlay/drawer.cjs +1 -1
- package/dist/components/overlay/drawer.d.ts +3 -1
- package/dist/components/overlay/drawer.js +24 -16
- package/dist/components/ui/accordion/index.d.ts +4 -0
- package/dist/components/ui/badge/index.cjs +1 -1
- package/dist/components/ui/badge/index.d.ts +1 -1
- package/dist/components/ui/badge/index.js +2 -1
- package/dist/components/ui/button/index.cjs +1 -1
- package/dist/components/ui/button/index.d.ts +2 -1
- package/dist/components/ui/button/index.js +13 -10
- package/dist/components/ui/dialog/index.cjs +1 -1
- package/dist/components/ui/dialog/index.js +2 -1
- package/dist/components/ui/hover-card.cjs +1 -1
- package/dist/components/ui/hover-card.d.ts +11 -3
- package/dist/components/ui/hover-card.js +29 -24
- package/dist/components/ui/input/index.d.ts +1 -1
- package/dist/components/ui/popover/index.cjs +1 -1
- package/dist/components/ui/popover/index.d.ts +2 -2
- package/dist/components/ui/popover/index.js +6 -5
- package/dist/components/ui/radio-group/index.cjs +1 -1
- package/dist/components/ui/radio-group/index.d.ts +5 -1
- package/dist/components/ui/radio-group/index.js +50 -16
- package/dist/components/ui/right-click-menu/index.cjs +1 -1
- package/dist/components/ui/right-click-menu/index.d.ts +5 -1
- package/dist/components/ui/right-click-menu/index.js +77 -23
- package/dist/components/ui/segmented-control/index.cjs +1 -1
- package/dist/components/ui/segmented-control/index.d.ts +2 -1
- package/dist/components/ui/segmented-control/index.js +23 -11
- package/dist/components/ui/select/index.cjs +1 -1
- package/dist/components/ui/select/index.d.ts +8 -1
- package/dist/components/ui/select/index.js +40 -35
- package/dist/components/ui/switch/index.cjs +1 -1
- package/dist/components/ui/switch/index.d.ts +18 -0
- package/dist/components/ui/switch/index.js +47 -17
- package/dist/components/ui/tabs/index.cjs +1 -1
- package/dist/components/ui/tabs/index.d.ts +14 -4
- package/dist/components/ui/tabs/index.js +11 -8
- package/dist/components/ui/textarea/index.cjs +1 -1
- package/dist/components/ui/textarea/index.d.ts +10 -2
- package/dist/components/ui/textarea/index.js +37 -8
- package/dist/components/ui/textarea.cjs +1 -0
- package/dist/components/ui/textarea.d.ts +1 -0
- package/dist/components/ui/textarea.js +2 -0
- package/dist/components/ui/tooltip/index.cjs +1 -1
- package/dist/components/ui/tooltip/index.d.ts +11 -3
- package/dist/components/ui/tooltip/index.js +41 -20
- package/dist/components/upload/file-upload.cjs +1 -1
- package/dist/components/upload/file-upload.d.ts +8 -1
- package/dist/components/upload/file-upload.js +132 -100
- package/dist/components/upload/image-upload.cjs +1 -1
- package/dist/components/upload/image-upload.d.ts +5 -1
- package/dist/components/upload/image-upload.js +34 -9
- package/dist/index.cjs +1 -1
- package/dist/index.js +31 -31
- package/dist/public-component-surface.cjs +1 -1
- package/dist/public-component-surface.js +15 -0
- package/dist/showcase/component-api-schema.cjs +1 -1
- package/dist/showcase/component-api-schema.js +187 -10
- package/dist/showcase/fallback.cjs +3 -3
- package/dist/showcase/fallback.js +221 -243
- package/dist/showcase/premium/alert/showcase.cjs +1 -1
- package/dist/showcase/premium/alert/showcase.js +1 -0
- package/dist/showcase/premium/app-sidebar/showcase.cjs +1 -1
- package/dist/showcase/premium/app-sidebar/showcase.js +1 -0
- package/dist/showcase/premium/badge/showcase.cjs +1 -1
- package/dist/showcase/premium/badge/showcase.js +7 -0
- package/dist/showcase/premium/badge/types.d.ts +1 -1
- package/dist/showcase/premium/breadcrumbs/showcase.cjs +1 -1
- package/dist/showcase/premium/breadcrumbs/showcase.js +12 -1
- package/dist/showcase/premium/button/mock.cjs +1 -4
- package/dist/showcase/premium/button/mock.js +1 -1
- package/dist/showcase/premium/button/showcase.cjs +1 -1
- package/dist/showcase/premium/button/showcase.js +2 -2
- package/dist/showcase/premium/card/showcase.cjs +1 -1
- package/dist/showcase/premium/card/showcase.js +96 -47
- package/dist/showcase/premium/carousel/showcase.cjs +1 -1
- package/dist/showcase/premium/carousel/showcase.js +76 -49
- package/dist/showcase/premium/command-bar/showcase.cjs +1 -1
- package/dist/showcase/premium/command-bar/showcase.js +2 -0
- package/dist/showcase/premium/data-table/mock.cjs +12 -11
- package/dist/showcase/premium/data-table/mock.js +1 -1
- package/dist/showcase/premium/file-upload/showcase.cjs +1 -1
- package/dist/showcase/premium/file-upload/showcase.js +25 -4
- package/dist/showcase/premium/image-upload/showcase.cjs +1 -1
- package/dist/showcase/premium/image-upload/showcase.js +4 -1
- package/dist/showcase/premium/index.cjs +1 -1
- package/dist/showcase/premium/index.js +396 -402
- package/dist/showcase/premium/loading-state/showcase.cjs +1 -1
- package/dist/showcase/premium/loading-state/showcase.js +3 -1
- package/dist/showcase/premium/metric-grid/showcase.cjs +1 -1
- package/dist/showcase/premium/metric-grid/showcase.js +96 -28
- package/dist/showcase/premium/notification-center/showcase.cjs +1 -1
- package/dist/showcase/premium/notification-center/showcase.js +7 -3
- package/dist/showcase/premium/page-state/showcase.cjs +1 -1
- package/dist/showcase/premium/page-state/showcase.js +5 -1
- package/dist/showcase/premium/pagination/showcase.cjs +1 -1
- package/dist/showcase/premium/pagination/showcase.js +15 -2
- package/dist/showcase/premium/popover/showcase.cjs +1 -1
- package/dist/showcase/premium/popover/showcase.js +85 -50
- package/dist/showcase/premium/radio-group/showcase.cjs +1 -1
- package/dist/showcase/premium/radio-group/showcase.js +27 -4
- package/dist/showcase/premium/right-click-menu/showcase.cjs +1 -1
- package/dist/showcase/premium/right-click-menu/showcase.js +56 -43
- package/dist/showcase/premium/segmented-control/showcase.cjs +1 -1
- package/dist/showcase/premium/segmented-control/showcase.js +1 -0
- package/dist/showcase/premium/select/data.cjs +1 -1
- package/dist/showcase/premium/select/data.js +69 -34
- package/dist/showcase/premium/select/mock.cjs +19 -6
- package/dist/showcase/premium/select/mock.js +3 -2
- package/dist/showcase/premium/select/showcase.cjs +1 -1
- package/dist/showcase/premium/select/showcase.js +43 -18
- package/dist/showcase/premium/select/types.d.ts +3 -0
- package/dist/showcase/premium/statistic/showcase.cjs +1 -1
- package/dist/showcase/premium/statistic/showcase.js +57 -25
- package/dist/showcase/premium/switch/showcase.cjs +1 -1
- package/dist/showcase/premium/switch/showcase.js +25 -14
- package/dist/showcase/premium/tabs/showcase.cjs +1 -1
- package/dist/showcase/premium/tabs/showcase.js +171 -48
- package/dist/showcase/premium/textarea/mock.cjs +12 -4
- package/dist/showcase/premium/textarea/mock.js +1 -1
- package/dist/showcase/premium/textarea/showcase.cjs +1 -1
- package/dist/showcase/premium/textarea/showcase.js +8 -3
- package/dist/showcase/premium/toast/showcase.cjs +1 -1
- package/dist/showcase/premium/toast/showcase.js +32 -6
- package/dist/showcase/premium/types.d.ts +1 -1
- package/dist/showcase/registry-quality.cjs +1 -1
- package/dist/showcase/registry-quality.js +1 -0
- package/dist/showcase/render-registry-preview.cjs +1 -1
- package/dist/showcase/render-registry-preview.js +57 -79
- package/dist/showcase/site-data.cjs +1 -1
- package/dist/showcase/site-data.js +60 -21
- package/dist/showcase/tembro-registry.json.cjs +1 -1
- package/dist/showcase/tembro-registry.json.js +34 -20
- package/dist/showcase/types.d.ts +1 -1
- package/package.json +1 -1
- package/packages/cli/dist/index.cjs +31 -31
- package/packages/cli/vendor/src/components/calendar/calendar.tsx +59 -50
- package/packages/cli/vendor/src/components/calendar/date-range-picker.tsx +7 -4
- package/packages/cli/vendor/src/components/charts/charts.tsx +109 -66
- package/packages/cli/vendor/src/components/charts/progress-ring.tsx +37 -26
- package/packages/cli/vendor/src/components/data-table/data-table-column-visibility-menu.tsx +41 -22
- package/packages/cli/vendor/src/components/data-table/data-table-toolbar.tsx +8 -6
- package/packages/cli/vendor/src/components/display/carousel.tsx +84 -3
- package/packages/cli/vendor/src/components/display/code-block.tsx +22 -2
- package/packages/cli/vendor/src/components/display/delta-badge.tsx +11 -11
- package/packages/cli/vendor/src/components/display/kanban.tsx +103 -57
- package/packages/cli/vendor/src/components/display/metric-grid.tsx +16 -13
- package/packages/cli/vendor/src/components/display/qr-code.tsx +17 -15
- package/packages/cli/vendor/src/components/display/tag.tsx +39 -21
- package/packages/cli/vendor/src/components/display/tree-view.tsx +221 -84
- package/packages/cli/vendor/src/components/display/trend-card.tsx +6 -40
- package/packages/cli/vendor/src/components/feedback/alert.tsx +3 -1
- package/packages/cli/vendor/src/components/feedback/loading-state.tsx +33 -17
- package/packages/cli/vendor/src/components/feedback/page-state.tsx +8 -7
- package/packages/cli/vendor/src/components/form/form-field-shell.tsx +37 -8
- package/packages/cli/vendor/src/components/form/form-input.tsx +2 -0
- package/packages/cli/vendor/src/components/form/form-select.tsx +2 -0
- package/packages/cli/vendor/src/components/form/form-switch.tsx +9 -3
- package/packages/cli/vendor/src/components/form/form-textarea.tsx +6 -2
- package/packages/cli/vendor/src/components/layout/app-sidebar.tsx +3 -1
- package/packages/cli/vendor/src/components/layout/breadcrumbs.tsx +3 -1
- package/packages/cli/vendor/src/components/modern/calendar-scheduler.tsx +28 -13
- package/packages/cli/vendor/src/components/modern/dual-list-picker.tsx +103 -35
- package/packages/cli/vendor/src/components/modern/rich-text-editor.tsx +25 -22
- package/packages/cli/vendor/src/components/modern/tour.tsx +47 -29
- package/packages/cli/vendor/src/components/navigation/command-bar.tsx +6 -0
- package/packages/cli/vendor/src/components/navigation/demo.tsx +0 -1
- package/packages/cli/vendor/src/components/navigation/nav-tabs.tsx +38 -29
- package/packages/cli/vendor/src/components/navigation/page-tabs.tsx +35 -23
- package/packages/cli/vendor/src/components/navigation/pagination.tsx +65 -31
- package/packages/cli/vendor/src/components/notifications/notification-center.tsx +64 -39
- package/packages/cli/vendor/src/components/notifications/toast.tsx +23 -21
- package/packages/cli/vendor/src/components/overlay/alert-dialog.tsx +1 -1
- package/packages/cli/vendor/src/components/overlay/confirm-dialog.tsx +45 -22
- package/packages/cli/vendor/src/components/overlay/drawer.tsx +18 -5
- package/packages/cli/vendor/src/components/ui/accordion/index.tsx +4 -0
- package/packages/cli/vendor/src/components/ui/badge/index.tsx +2 -1
- package/packages/cli/vendor/src/components/ui/button/index.tsx +11 -5
- package/packages/cli/vendor/src/components/ui/dialog/index.tsx +2 -1
- package/packages/cli/vendor/src/components/ui/hover-card.tsx +54 -28
- package/packages/cli/vendor/src/components/ui/popover/index.tsx +10 -8
- package/packages/cli/vendor/src/components/ui/radio-group/index.tsx +55 -6
- package/packages/cli/vendor/src/components/ui/right-click-menu/index.tsx +120 -9
- package/packages/cli/vendor/src/components/ui/segmented-control/index.tsx +29 -3
- package/packages/cli/vendor/src/components/ui/select/index.tsx +64 -31
- package/packages/cli/vendor/src/components/ui/switch/index.tsx +71 -6
- package/packages/cli/vendor/src/components/ui/tabs/index.tsx +22 -6
- package/packages/cli/vendor/src/components/ui/textarea/index.tsx +105 -15
- package/packages/cli/vendor/src/components/ui/textarea.tsx +2 -0
- package/packages/cli/vendor/src/components/ui/tooltip/index.tsx +67 -22
- package/packages/cli/vendor/src/components/upload/file-upload.tsx +120 -57
- package/packages/cli/vendor/src/components/upload/image-upload.tsx +71 -24
- package/packages/cli/vendor/src/public-component-surface.ts +3 -0
- package/packages/cli/vendor/src/showcase/component-api-schema.ts +79 -41
- package/packages/cli/vendor/src/showcase/fallback.tsx +4 -19
- package/packages/cli/vendor/src/showcase/premium/alert/showcase.tsx +1 -0
- package/packages/cli/vendor/src/showcase/premium/app-sidebar/showcase.tsx +1 -0
- package/packages/cli/vendor/src/showcase/premium/badge/showcase.tsx +4 -2
- package/packages/cli/vendor/src/showcase/premium/badge/types.ts +1 -1
- package/packages/cli/vendor/src/showcase/premium/breadcrumbs/showcase.tsx +3 -1
- package/packages/cli/vendor/src/showcase/premium/button/mock.ts +2 -5
- package/packages/cli/vendor/src/showcase/premium/button/showcase.tsx +2 -2
- package/packages/cli/vendor/src/showcase/premium/card/showcase.tsx +26 -1
- package/packages/cli/vendor/src/showcase/premium/carousel/showcase.tsx +19 -3
- package/packages/cli/vendor/src/showcase/premium/command-bar/showcase.tsx +1 -1
- package/packages/cli/vendor/src/showcase/premium/data-table/mock.ts +26 -25
- package/packages/cli/vendor/src/showcase/premium/file-upload/showcase.tsx +21 -1
- package/packages/cli/vendor/src/showcase/premium/image-upload/showcase.tsx +4 -1
- package/packages/cli/vendor/src/showcase/premium/index.ts +0 -2
- package/packages/cli/vendor/src/showcase/premium/loading-state/showcase.tsx +1 -1
- package/packages/cli/vendor/src/showcase/premium/metric-grid/showcase.tsx +36 -4
- package/packages/cli/vendor/src/showcase/premium/notification-center/showcase.tsx +4 -3
- package/packages/cli/vendor/src/showcase/premium/page-state/showcase.tsx +1 -0
- package/packages/cli/vendor/src/showcase/premium/pagination/showcase.tsx +13 -1
- package/packages/cli/vendor/src/showcase/premium/popover/showcase.tsx +27 -11
- package/packages/cli/vendor/src/showcase/premium/radio-group/showcase.tsx +13 -1
- package/packages/cli/vendor/src/showcase/premium/right-click-menu/showcase.tsx +8 -5
- package/packages/cli/vendor/src/showcase/premium/segmented-control/showcase.tsx +1 -0
- package/packages/cli/vendor/src/showcase/premium/select/data.ts +12 -3
- package/packages/cli/vendor/src/showcase/premium/select/mock.ts +4 -4
- package/packages/cli/vendor/src/showcase/premium/select/showcase.tsx +22 -1
- package/packages/cli/vendor/src/showcase/premium/select/types.ts +3 -0
- package/packages/cli/vendor/src/showcase/premium/statistic/showcase.tsx +10 -1
- package/packages/cli/vendor/src/showcase/premium/switch/showcase.tsx +15 -6
- package/packages/cli/vendor/src/showcase/premium/tabs/showcase.tsx +48 -1
- package/packages/cli/vendor/src/showcase/premium/textarea/mock.ts +12 -4
- package/packages/cli/vendor/src/showcase/premium/textarea/showcase.tsx +5 -0
- package/packages/cli/vendor/src/showcase/premium/toast/showcase.tsx +17 -1
- package/packages/cli/vendor/src/showcase/premium/types.ts +1 -1
- package/packages/cli/vendor/src/showcase/registry-quality.ts +3 -2
- package/packages/cli/vendor/src/showcase/render-registry-preview.tsx +0 -15
- package/packages/cli/vendor/src/showcase/site-data.tsx +21 -15
- package/packages/cli/vendor/src/showcase/tembro-registry.json +42 -20
- package/packages/cli/vendor/src/showcase/types.ts +1 -1
- package/registry.json +18 -6
|
@@ -11,25 +11,32 @@ type ConfirmDialogProps = Omit<ModalShellProps, "footer"> & {
|
|
|
11
11
|
confirmVariant?: ConfirmVariant
|
|
12
12
|
confirmDisabled?: boolean
|
|
13
13
|
cancelDisabled?: boolean
|
|
14
|
-
isLoading?: boolean
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
isLoading?: boolean
|
|
15
|
+
closeOnConfirm?: boolean
|
|
16
|
+
onConfirmError?: (error: unknown) => void
|
|
17
|
+
onCancel?: () => void
|
|
18
|
+
onConfirm?: () => void | Promise<void>
|
|
19
|
+
}
|
|
18
20
|
|
|
19
21
|
function ConfirmDialog({
|
|
20
22
|
cancelText = "Cancel",
|
|
21
23
|
confirmText = "Confirm",
|
|
22
24
|
confirmVariant = "default",
|
|
23
25
|
confirmDisabled = false,
|
|
24
|
-
cancelDisabled = false,
|
|
25
|
-
isLoading = false,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
cancelDisabled = false,
|
|
27
|
+
isLoading = false,
|
|
28
|
+
closeOnConfirm = true,
|
|
29
|
+
onConfirmError,
|
|
30
|
+
onCancel,
|
|
31
|
+
onConfirm,
|
|
32
|
+
onOpenChange,
|
|
33
|
+
...props
|
|
30
34
|
}: ConfirmDialogProps) {
|
|
35
|
+
const [pending, setPending] = React.useState(false)
|
|
36
|
+
const resolvedLoading = isLoading || pending
|
|
37
|
+
|
|
31
38
|
const handleOpenChange = (open: boolean) => {
|
|
32
|
-
if (
|
|
39
|
+
if (resolvedLoading && open === false) {
|
|
33
40
|
return
|
|
34
41
|
}
|
|
35
42
|
|
|
@@ -38,31 +45,47 @@ function ConfirmDialog({
|
|
|
38
45
|
|
|
39
46
|
const handleCancel = () => {
|
|
40
47
|
onCancel?.()
|
|
41
|
-
if (!
|
|
48
|
+
if (!resolvedLoading) {
|
|
42
49
|
onOpenChange?.(false)
|
|
43
50
|
}
|
|
44
51
|
}
|
|
45
52
|
|
|
53
|
+
const handleConfirm = async () => {
|
|
54
|
+
if (confirmDisabled || resolvedLoading) return
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
setPending(true)
|
|
58
|
+
await onConfirm?.()
|
|
59
|
+
if (closeOnConfirm) {
|
|
60
|
+
onOpenChange?.(false)
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
onConfirmError?.(error)
|
|
64
|
+
} finally {
|
|
65
|
+
setPending(false)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
46
69
|
return (
|
|
47
70
|
<ModalShell
|
|
48
|
-
showCloseButton={!
|
|
71
|
+
showCloseButton={!resolvedLoading}
|
|
49
72
|
onOpenChange={handleOpenChange}
|
|
50
73
|
footer={
|
|
51
74
|
<DialogActions>
|
|
52
75
|
<DialogActionButton
|
|
53
|
-
type="button"
|
|
54
|
-
variant="outline"
|
|
55
|
-
disabled={cancelDisabled ||
|
|
56
|
-
onClick={handleCancel}
|
|
57
|
-
>
|
|
58
|
-
{cancelText}
|
|
76
|
+
type="button"
|
|
77
|
+
variant="outline"
|
|
78
|
+
disabled={cancelDisabled || resolvedLoading}
|
|
79
|
+
onClick={handleCancel}
|
|
80
|
+
>
|
|
81
|
+
{cancelText}
|
|
59
82
|
</DialogActionButton>
|
|
60
83
|
<DialogActionButton
|
|
61
84
|
type="button"
|
|
62
85
|
variant={confirmVariant}
|
|
63
|
-
disabled={confirmDisabled ||
|
|
64
|
-
isLoading={
|
|
65
|
-
onClick={
|
|
86
|
+
disabled={confirmDisabled || resolvedLoading}
|
|
87
|
+
isLoading={resolvedLoading}
|
|
88
|
+
onClick={() => void handleConfirm()}
|
|
66
89
|
>
|
|
67
90
|
{confirmText}
|
|
68
91
|
</DialogActionButton>
|
|
@@ -12,13 +12,15 @@ import {
|
|
|
12
12
|
} from "@/components/ui/dialog"
|
|
13
13
|
import { cn } from "@/lib/utils"
|
|
14
14
|
|
|
15
|
-
export type DrawerSide = "left" | "right" | "top" | "bottom"
|
|
15
|
+
export type DrawerSide = "left" | "right" | "top" | "bottom"
|
|
16
|
+
export type DrawerWidth = "sm" | "md" | "lg" | "xl" | "full"
|
|
16
17
|
|
|
17
18
|
export type DrawerProps = Omit<React.ComponentProps<typeof Dialog>, "children"> & {
|
|
18
19
|
trigger?: React.ReactNode
|
|
19
20
|
title?: React.ReactNode
|
|
20
21
|
description?: React.ReactNode
|
|
21
22
|
side?: DrawerSide
|
|
23
|
+
width?: DrawerWidth
|
|
22
24
|
footer?: React.ReactNode
|
|
23
25
|
headerClassName?: string
|
|
24
26
|
bodyClassName?: string
|
|
@@ -29,17 +31,26 @@ export type DrawerProps = Omit<React.ComponentProps<typeof Dialog>, "children">
|
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
const sideClassName: Record<DrawerSide, string> = {
|
|
32
|
-
right: "left-auto right-0 top-0 h-dvh max-h-dvh w-full
|
|
33
|
-
left: "left-0 top-0 h-dvh max-h-dvh w-full
|
|
34
|
+
right: "left-auto right-0 top-0 h-dvh max-h-dvh w-full translate-x-0 translate-y-0 rounded-none rounded-l-[var(--radius-3xl)] data-open:slide-in-from-right data-closed:slide-out-to-right",
|
|
35
|
+
left: "left-0 top-0 h-dvh max-h-dvh w-full translate-x-0 translate-y-0 rounded-none rounded-r-[var(--radius-3xl)] data-open:slide-in-from-left data-closed:slide-out-to-left",
|
|
34
36
|
top: "left-0 top-0 h-auto max-h-[85dvh] w-full max-w-none translate-x-0 translate-y-0 rounded-none rounded-b-[var(--radius-3xl)] data-open:slide-in-from-top data-closed:slide-out-to-top",
|
|
35
37
|
bottom: "bottom-0 left-0 top-auto h-auto max-h-[85dvh] w-full max-w-none translate-x-0 translate-y-0 rounded-none rounded-t-[var(--radius-3xl)] data-open:slide-in-from-bottom data-closed:slide-out-to-bottom",
|
|
36
38
|
}
|
|
39
|
+
|
|
40
|
+
const widthClassName: Record<DrawerWidth, string> = {
|
|
41
|
+
sm: "sm:max-w-sm",
|
|
42
|
+
md: "sm:max-w-md",
|
|
43
|
+
lg: "sm:max-w-lg",
|
|
44
|
+
xl: "sm:max-w-2xl",
|
|
45
|
+
full: "max-w-none sm:max-w-[min(100vw,72rem)]",
|
|
46
|
+
}
|
|
37
47
|
|
|
38
48
|
function Drawer({
|
|
39
49
|
trigger,
|
|
40
|
-
title,
|
|
50
|
+
title,
|
|
41
51
|
description,
|
|
42
52
|
side = "right",
|
|
53
|
+
width = "lg",
|
|
43
54
|
footer,
|
|
44
55
|
headerClassName,
|
|
45
56
|
bodyClassName,
|
|
@@ -55,7 +66,9 @@ function Drawer({
|
|
|
55
66
|
<DialogContent
|
|
56
67
|
size="full"
|
|
57
68
|
showCloseButton={showCloseButton}
|
|
58
|
-
|
|
69
|
+
data-side={side}
|
|
70
|
+
data-width={width}
|
|
71
|
+
className={cn("fixed grid grid-rows-[auto_minmax(0,1fr)_auto] gap-0 overscroll-contain p-0", sideClassName[side], (side === "left" || side === "right") && widthClassName[width], contentClassName)}
|
|
59
72
|
>
|
|
60
73
|
{(title || description) && (
|
|
61
74
|
<DialogHeader className={cn("border-b border-border/70 p-6", headerClassName)}>
|
|
@@ -17,6 +17,10 @@ export type AccordionRootProps = CollapseProps
|
|
|
17
17
|
export type AccordionTriggerProps = CollapseTriggerProps
|
|
18
18
|
export type AccordionContentProps = React.ComponentProps<"div">
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Accordion is the grouped disclosure API. Use CollapseRoot/CollapseTrigger/CollapseContent
|
|
22
|
+
* for a single standalone disclosure.
|
|
23
|
+
*/
|
|
20
24
|
function Accordion(props: AccordionProps) {
|
|
21
25
|
return <CollapseGroup data-slot="accordion" {...props} />
|
|
22
26
|
}
|
|
@@ -17,6 +17,7 @@ const badgeVariants = cva(
|
|
|
17
17
|
"border-[color:color-mix(in_oklch,var(--border),var(--foreground)_10%)] bg-[color:color-mix(in_oklch,var(--muted),var(--background)_8%)] text-foreground",
|
|
18
18
|
destructive:
|
|
19
19
|
"border-[color:color-mix(in_oklch,var(--destructive),transparent_52%)] bg-[color:color-mix(in_oklch,var(--destructive),transparent_82%)] text-[color:color-mix(in_oklch,var(--destructive),black_16%)] dark:text-[color:color-mix(in_oklch,var(--destructive),white_38%)]",
|
|
20
|
+
soft: "border-transparent bg-[color:color-mix(in_oklch,var(--muted),transparent_38%)] text-foreground shadow-none",
|
|
20
21
|
outline: "bg-[color:color-mix(in_oklch,var(--background),var(--muted)_6%)] text-foreground shadow-none",
|
|
21
22
|
ghost: "border-transparent bg-[color:color-mix(in_oklch,var(--muted),transparent_76%)] text-muted-foreground shadow-none",
|
|
22
23
|
link: "border-transparent bg-transparent p-0 text-primary shadow-none underline-offset-4",
|
|
@@ -115,7 +116,7 @@ function Badge({
|
|
|
115
116
|
event.stopPropagation()
|
|
116
117
|
onRemove?.()
|
|
117
118
|
}}
|
|
118
|
-
className="inline-flex size-4 shrink-0 items-center justify-center rounded-full bg-[color:color-mix(in_oklch,currentColor,transparent_90%)] opacity-80 transition hover:opacity-100"
|
|
119
|
+
className="inline-flex size-4 shrink-0 items-center justify-center rounded-full bg-[color:color-mix(in_oklch,currentColor,transparent_90%)] opacity-80 transition hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-current/35"
|
|
119
120
|
>
|
|
120
121
|
<XIcon className="size-3" />
|
|
121
122
|
</button>
|
|
@@ -46,6 +46,7 @@ export type ButtonProps = ButtonPrimitive.Props &
|
|
|
46
46
|
loadingLabel?: string
|
|
47
47
|
leftIcon?: React.ReactNode
|
|
48
48
|
rightIcon?: React.ReactNode
|
|
49
|
+
iconOnly?: boolean
|
|
49
50
|
fullWidth?: boolean
|
|
50
51
|
pressed?: boolean
|
|
51
52
|
}
|
|
@@ -59,25 +60,30 @@ function Button({
|
|
|
59
60
|
loadingLabel = "Loading",
|
|
60
61
|
leftIcon,
|
|
61
62
|
rightIcon,
|
|
63
|
+
iconOnly = false,
|
|
62
64
|
fullWidth = false,
|
|
63
65
|
pressed = false,
|
|
64
66
|
children,
|
|
67
|
+
"aria-label": ariaLabel,
|
|
65
68
|
...props
|
|
66
69
|
}: ButtonProps) {
|
|
67
|
-
const isDisabled = disabled || loading
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
const isDisabled = disabled || loading
|
|
71
|
+
const resolvedSize = iconOnly && (size === "default" || size === "md") ? "icon" : size
|
|
72
|
+
|
|
73
|
+
return (
|
|
70
74
|
<ButtonPrimitive
|
|
71
75
|
data-slot="button"
|
|
72
76
|
data-variant={variant ?? "default"}
|
|
73
|
-
data-size={
|
|
77
|
+
data-size={resolvedSize ?? "default"}
|
|
78
|
+
data-icon-only={iconOnly || undefined}
|
|
74
79
|
data-loading={loading || undefined}
|
|
75
80
|
data-pressed={pressed || undefined}
|
|
76
81
|
disabled={isDisabled}
|
|
77
82
|
aria-busy={loading || undefined}
|
|
78
83
|
aria-pressed={pressed || undefined}
|
|
84
|
+
aria-label={ariaLabel}
|
|
79
85
|
className={cn(
|
|
80
|
-
buttonVariants({ variant, size, className }),
|
|
86
|
+
buttonVariants({ variant, size: resolvedSize, className }),
|
|
81
87
|
fullWidth && "w-full",
|
|
82
88
|
pressed && "shadow-[var(--aui-control-shadow,0_1px_2px_rgba(15,23,42,0.04)),0_0_0_1px_var(--aui-focus-ring,var(--ring))]"
|
|
83
89
|
)}
|
|
@@ -70,8 +70,9 @@ function DialogContent({
|
|
|
70
70
|
data-size={size}
|
|
71
71
|
data-surface={surface}
|
|
72
72
|
role="dialog"
|
|
73
|
+
aria-modal="true"
|
|
73
74
|
className={cn(
|
|
74
|
-
"fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-5 overflow-
|
|
75
|
+
"fixed top-1/2 left-1/2 z-50 grid max-h-[min(92vh,calc(100dvh-2rem))] w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-5 overflow-y-auto overscroll-contain rounded-[var(--radius-3xl)] border border-[color:var(--aui-card-border,var(--border))] bg-[color:var(--aui-overlay-surface,var(--popover))] p-6 text-sm text-popover-foreground shadow-[var(--aui-control-panel-shadow,0_24px_70px_rgba(15,23,42,0.22))] backdrop-blur duration-100 outline-none data-[surface=plain]:overflow-visible data-[surface=plain]:border-transparent data-[surface=plain]:bg-transparent data-[surface=plain]:p-0 data-[surface=plain]:shadow-none data-[size=xs]:sm:max-w-sm data-[size=sm]:sm:max-w-md data-[size=md]:sm:max-w-lg data-[size=lg]:sm:max-w-2xl data-[size=xl]:sm:max-w-4xl data-[size=full]:h-[min(92vh,56rem)] data-[size=full]:max-w-[min(96vw,84rem)] data-[size=full]:grid-rows-[auto_minmax(0,1fr)] data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
75
76
|
className
|
|
76
77
|
)}
|
|
77
78
|
{...props}
|
|
@@ -1,51 +1,77 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
|
+
import { PreviewCard as PreviewCardPrimitive } from "@base-ui/react/preview-card"
|
|
2
3
|
|
|
3
4
|
import { cn } from "@/lib/utils"
|
|
4
5
|
|
|
5
|
-
export type HoverCardProps = Omit<
|
|
6
|
+
export type HoverCardProps = Omit<PreviewCardPrimitive.Root.Props, "children"> &
|
|
7
|
+
Omit<React.ComponentProps<"span">, "content" | "children"> & {
|
|
6
8
|
trigger: React.ReactNode
|
|
7
9
|
content: React.ReactNode
|
|
8
|
-
side?: "
|
|
10
|
+
side?: PreviewCardPrimitive.Positioner.Props["side"]
|
|
11
|
+
align?: PreviewCardPrimitive.Positioner.Props["align"]
|
|
12
|
+
sideOffset?: PreviewCardPrimitive.Positioner.Props["sideOffset"]
|
|
13
|
+
alignOffset?: PreviewCardPrimitive.Positioner.Props["alignOffset"]
|
|
14
|
+
collisionPadding?: PreviewCardPrimitive.Positioner.Props["collisionPadding"]
|
|
15
|
+
delay?: PreviewCardPrimitive.Trigger.Props["delay"]
|
|
16
|
+
closeDelay?: PreviewCardPrimitive.Trigger.Props["closeDelay"]
|
|
17
|
+
disabled?: boolean
|
|
9
18
|
contentClassName?: string
|
|
10
19
|
}
|
|
11
20
|
|
|
12
|
-
const sideClassName = {
|
|
13
|
-
top: "bottom-full left-1/2 mb-2.5 -translate-x-1/2",
|
|
14
|
-
right: "left-full top-1/2 ml-2.5 -translate-y-1/2",
|
|
15
|
-
bottom: "left-1/2 top-full mt-2.5 -translate-x-1/2",
|
|
16
|
-
left: "right-full top-1/2 mr-2.5 -translate-y-1/2",
|
|
17
|
-
} as const
|
|
18
|
-
|
|
19
21
|
function HoverCard({
|
|
20
22
|
trigger,
|
|
21
23
|
content,
|
|
22
24
|
side = "bottom",
|
|
25
|
+
align = "center",
|
|
26
|
+
sideOffset = 10,
|
|
27
|
+
alignOffset = 0,
|
|
28
|
+
collisionPadding = 12,
|
|
29
|
+
delay = 450,
|
|
30
|
+
closeDelay = 180,
|
|
31
|
+
disabled = false,
|
|
23
32
|
contentClassName,
|
|
24
33
|
className,
|
|
25
|
-
children,
|
|
26
34
|
...props
|
|
27
35
|
}: HoverCardProps) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
data-slot="hover-card"
|
|
31
|
-
className={cn("group/hover-card relative inline-flex", className)}
|
|
32
|
-
{...props}
|
|
33
|
-
>
|
|
34
|
-
<span data-slot="hover-card-trigger" className="inline-flex">
|
|
36
|
+
if (disabled) {
|
|
37
|
+
return (
|
|
38
|
+
<span data-slot="hover-card" className={cn("inline-flex", className)} {...props}>
|
|
35
39
|
{trigger}
|
|
36
40
|
</span>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<PreviewCardPrimitive.Root>
|
|
46
|
+
<PreviewCardPrimitive.Trigger
|
|
47
|
+
data-slot="hover-card-trigger"
|
|
48
|
+
delay={delay}
|
|
49
|
+
closeDelay={closeDelay}
|
|
50
|
+
render={<span data-slot="hover-card" className={cn("inline-flex", className)} {...props} />}
|
|
44
51
|
>
|
|
45
|
-
{
|
|
46
|
-
</
|
|
47
|
-
|
|
48
|
-
|
|
52
|
+
{trigger}
|
|
53
|
+
</PreviewCardPrimitive.Trigger>
|
|
54
|
+
<PreviewCardPrimitive.Portal>
|
|
55
|
+
<PreviewCardPrimitive.Positioner
|
|
56
|
+
className="isolate z-50"
|
|
57
|
+
side={side}
|
|
58
|
+
align={align}
|
|
59
|
+
sideOffset={sideOffset}
|
|
60
|
+
alignOffset={alignOffset}
|
|
61
|
+
collisionPadding={collisionPadding}
|
|
62
|
+
>
|
|
63
|
+
<PreviewCardPrimitive.Popup
|
|
64
|
+
data-slot="hover-card-content"
|
|
65
|
+
className={cn(
|
|
66
|
+
"z-50 min-w-60 max-w-[min(24rem,calc(100vw-1rem))] origin-(--transform-origin) rounded-[var(--aui-card-radius,var(--radius-xl))] border border-border/80 bg-popover/98 p-4 text-sm text-popover-foreground shadow-[0_18px_42px_color-mix(in_oklch,var(--foreground),transparent_86%)] ring-1 ring-foreground/8 outline-hidden backdrop-blur duration-150 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
67
|
+
contentClassName
|
|
68
|
+
)}
|
|
69
|
+
>
|
|
70
|
+
{content}
|
|
71
|
+
</PreviewCardPrimitive.Popup>
|
|
72
|
+
</PreviewCardPrimitive.Positioner>
|
|
73
|
+
</PreviewCardPrimitive.Portal>
|
|
74
|
+
</PreviewCardPrimitive.Root>
|
|
49
75
|
)
|
|
50
76
|
}
|
|
51
77
|
|
|
@@ -10,7 +10,7 @@ export type PopoverTriggerProps = PopoverPrimitive.Trigger.Props
|
|
|
10
10
|
export type PopoverContentProps = PopoverPrimitive.Popup.Props &
|
|
11
11
|
Pick<
|
|
12
12
|
PopoverPrimitive.Positioner.Props,
|
|
13
|
-
"align" | "alignOffset" | "side" | "sideOffset"
|
|
13
|
+
"align" | "alignOffset" | "collisionBoundary" | "collisionPadding" | "side" | "sideOffset"
|
|
14
14
|
>
|
|
15
15
|
export type PopoverHeaderProps = React.ComponentProps<"div">
|
|
16
16
|
export type PopoverTitleProps = PopoverPrimitive.Title.Props
|
|
@@ -28,6 +28,7 @@ function PopoverContent({
|
|
|
28
28
|
className,
|
|
29
29
|
align = "center",
|
|
30
30
|
alignOffset = 0,
|
|
31
|
+
collisionPadding = 12,
|
|
31
32
|
side = "bottom",
|
|
32
33
|
sideOffset = 4,
|
|
33
34
|
...props
|
|
@@ -35,16 +36,17 @@ function PopoverContent({
|
|
|
35
36
|
return (
|
|
36
37
|
<PopoverPrimitive.Portal>
|
|
37
38
|
<PopoverPrimitive.Positioner
|
|
38
|
-
align={align}
|
|
39
|
-
alignOffset={alignOffset}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
align={align}
|
|
40
|
+
alignOffset={alignOffset}
|
|
41
|
+
collisionPadding={collisionPadding}
|
|
42
|
+
side={side}
|
|
43
|
+
sideOffset={sideOffset}
|
|
44
|
+
className="isolate z-50"
|
|
45
|
+
>
|
|
44
46
|
<PopoverPrimitive.Popup
|
|
45
47
|
data-slot="popover-content"
|
|
46
48
|
className={cn(
|
|
47
|
-
"z-50 flex w-
|
|
49
|
+
"z-50 flex max-h-[min(var(--available-height),calc(100dvh-1rem))] w-[min(var(--anchor-width),20rem)] min-w-60 max-w-[calc(100vw-1rem)] origin-(--transform-origin) flex-col gap-3 overflow-y-auto rounded-[var(--aui-card-radius,var(--radius-xl))] border border-[color:var(--aui-card-border,var(--border))] bg-[color:var(--aui-overlay-surface,var(--popover))] p-4 text-sm text-popover-foreground shadow-[var(--aui-popover-shadow,0_18px_42px_rgba(15,23,42,0.16))] outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
48
50
|
className
|
|
49
51
|
)}
|
|
50
52
|
{...props}
|
|
@@ -17,7 +17,11 @@ export type RadioGroupProps = Omit<React.ComponentProps<"div">, "onChange"> & {
|
|
|
17
17
|
options: RadioGroupOption[]
|
|
18
18
|
orientation?: "vertical" | "horizontal"
|
|
19
19
|
size?: "sm" | "default" | "lg"
|
|
20
|
+
invalid?: boolean
|
|
21
|
+
disabled?: boolean
|
|
20
22
|
itemClassName?: string
|
|
23
|
+
itemLabelClassName?: string
|
|
24
|
+
itemDescriptionClassName?: string
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
const sizeClassName = {
|
|
@@ -34,8 +38,12 @@ function RadioGroup({
|
|
|
34
38
|
options,
|
|
35
39
|
orientation = "vertical",
|
|
36
40
|
size = "default",
|
|
41
|
+
invalid = false,
|
|
42
|
+
disabled = false,
|
|
37
43
|
className,
|
|
38
44
|
itemClassName,
|
|
45
|
+
itemLabelClassName,
|
|
46
|
+
itemDescriptionClassName,
|
|
39
47
|
...props
|
|
40
48
|
}: RadioGroupProps) {
|
|
41
49
|
const generatedName = React.useId()
|
|
@@ -43,39 +51,80 @@ function RadioGroup({
|
|
|
43
51
|
const [internalValue, setInternalValue] = React.useState(defaultValue ?? "")
|
|
44
52
|
const isControlled = value !== undefined
|
|
45
53
|
const currentValue = isControlled ? value : internalValue
|
|
54
|
+
const itemRefs = React.useRef<Array<HTMLInputElement | null>>([])
|
|
55
|
+
const enabledOptions = options.filter((option) => !option.disabled && !disabled)
|
|
46
56
|
|
|
47
57
|
const setValue = (nextValue: string) => {
|
|
48
58
|
if (!isControlled) setInternalValue(nextValue)
|
|
49
59
|
onValueChange?.(nextValue)
|
|
50
60
|
}
|
|
51
61
|
|
|
62
|
+
const focusOption = (nextIndex: number) => {
|
|
63
|
+
const option = enabledOptions[nextIndex]
|
|
64
|
+
if (!option) return
|
|
65
|
+
const optionIndex = options.findIndex((item) => item.value === option.value)
|
|
66
|
+
itemRefs.current[optionIndex]?.focus()
|
|
67
|
+
setValue(option.value)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const handleKeyDown: React.KeyboardEventHandler<HTMLDivElement> = (event) => {
|
|
71
|
+
if (!["ArrowDown", "ArrowRight", "ArrowUp", "ArrowLeft", "Home", "End"].includes(event.key)) return
|
|
72
|
+
if (enabledOptions.length === 0) return
|
|
73
|
+
|
|
74
|
+
event.preventDefault()
|
|
75
|
+
const currentEnabledIndex = Math.max(
|
|
76
|
+
0,
|
|
77
|
+
enabledOptions.findIndex((option) => option.value === currentValue)
|
|
78
|
+
)
|
|
79
|
+
if (event.key === "Home") {
|
|
80
|
+
focusOption(0)
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
if (event.key === "End") {
|
|
84
|
+
focusOption(enabledOptions.length - 1)
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
const direction = event.key === "ArrowDown" || event.key === "ArrowRight" ? 1 : -1
|
|
88
|
+
focusOption((currentEnabledIndex + direction + enabledOptions.length) % enabledOptions.length)
|
|
89
|
+
}
|
|
90
|
+
|
|
52
91
|
return (
|
|
53
92
|
<div
|
|
54
93
|
role="radiogroup"
|
|
94
|
+
aria-invalid={invalid || undefined}
|
|
95
|
+
aria-disabled={disabled || undefined}
|
|
55
96
|
data-slot="radio-group"
|
|
56
97
|
data-orientation={orientation}
|
|
98
|
+
data-invalid={invalid || undefined}
|
|
57
99
|
className={cn("grid gap-2", orientation === "horizontal" && "sm:flex sm:flex-wrap sm:items-center", className)}
|
|
100
|
+
onKeyDown={handleKeyDown}
|
|
58
101
|
{...props}
|
|
59
102
|
>
|
|
60
|
-
{options.map((option) => {
|
|
103
|
+
{options.map((option, index) => {
|
|
61
104
|
const checked = option.value === currentValue
|
|
105
|
+
const optionDisabled = disabled || option.disabled
|
|
62
106
|
return (
|
|
63
107
|
<label
|
|
64
108
|
key={option.value}
|
|
65
109
|
data-slot="radio-group-item"
|
|
66
110
|
data-checked={checked || undefined}
|
|
67
|
-
data-disabled={
|
|
111
|
+
data-disabled={optionDisabled || undefined}
|
|
112
|
+
data-invalid={invalid || undefined}
|
|
68
113
|
className={cn(
|
|
69
|
-
"group flex cursor-pointer items-start gap-3 rounded-[min(var(--radius-xl),16px)] border border-border/80 bg-background/88 px-3 py-2.5 text-sm transition hover:border-ring/35 hover:bg-accent/60 data-[checked=true]:border-primary/35 data-[checked=true]:bg-primary/8 data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-55",
|
|
114
|
+
"group flex cursor-pointer items-start gap-3 rounded-[min(var(--radius-xl),16px)] border border-border/80 bg-background/88 px-3 py-2.5 text-sm transition hover:border-ring/35 hover:bg-accent/60 focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/30 data-[checked=true]:border-primary/35 data-[checked=true]:bg-primary/8 data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-55 data-[invalid=true]:border-destructive/70 data-[invalid=true]:ring-3 data-[invalid=true]:ring-destructive/15",
|
|
70
115
|
itemClassName
|
|
71
116
|
)}
|
|
72
117
|
>
|
|
73
118
|
<input
|
|
119
|
+
ref={(node) => {
|
|
120
|
+
itemRefs.current[index] = node
|
|
121
|
+
}}
|
|
74
122
|
type="radio"
|
|
75
123
|
name={resolvedName}
|
|
76
124
|
value={option.value}
|
|
77
125
|
checked={checked}
|
|
78
|
-
disabled={
|
|
126
|
+
disabled={optionDisabled}
|
|
127
|
+
aria-invalid={invalid || undefined}
|
|
79
128
|
className="sr-only"
|
|
80
129
|
onChange={() => setValue(option.value)}
|
|
81
130
|
/>
|
|
@@ -89,8 +138,8 @@ function RadioGroup({
|
|
|
89
138
|
<span className="size-1.5 rounded-full bg-primary-foreground opacity-0 transition group-data-[checked=true]:opacity-100" />
|
|
90
139
|
</span>
|
|
91
140
|
<span className="min-w-0">
|
|
92
|
-
<span className="block font-medium text-foreground">{option.label}</span>
|
|
93
|
-
{option.description ? <span className="mt-1 block text-sm leading-6 text-muted-foreground">{option.description}</span> : null}
|
|
141
|
+
<span className={cn("block font-medium text-foreground", itemLabelClassName)}>{option.label}</span>
|
|
142
|
+
{option.description ? <span className={cn("mt-1 block text-sm leading-6 text-muted-foreground", itemDescriptionClassName)}>{option.description}</span> : null}
|
|
94
143
|
</span>
|
|
95
144
|
</label>
|
|
96
145
|
)
|