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
|
@@ -53,7 +53,8 @@ export type CalendarProps = React.ComponentProps<"div"> & {
|
|
|
53
53
|
max?: string
|
|
54
54
|
disabledDates?: string[]
|
|
55
55
|
locale?: string
|
|
56
|
-
weekStartsOn?: 0 | 1
|
|
56
|
+
weekStartsOn?: 0 | 1
|
|
57
|
+
months?: number
|
|
57
58
|
numberOfMonths?: number
|
|
58
59
|
showMonthHeaders?: boolean
|
|
59
60
|
showOutsideDays?: boolean
|
|
@@ -127,8 +128,9 @@ function Calendar({
|
|
|
127
128
|
min,
|
|
128
129
|
max,
|
|
129
130
|
disabledDates,
|
|
130
|
-
locale = "en-US",
|
|
131
|
+
locale = "en-US",
|
|
131
132
|
weekStartsOn = 1,
|
|
133
|
+
months,
|
|
132
134
|
numberOfMonths = 1,
|
|
133
135
|
showMonthHeaders,
|
|
134
136
|
showOutsideDays = true,
|
|
@@ -148,7 +150,7 @@ function Calendar({
|
|
|
148
150
|
const currentValue = isControlledSingle ? value : internalValue
|
|
149
151
|
const currentRange = isControlledRange ? range : internalRange
|
|
150
152
|
const currentMonth = month ?? internalMonth
|
|
151
|
-
const resolvedNumberOfMonths = Math.max(numberOfMonths, 1)
|
|
153
|
+
const resolvedNumberOfMonths = Math.max(months ?? numberOfMonths, 1)
|
|
152
154
|
const shouldShowMonthHeaders = showMonthHeaders ?? resolvedNumberOfMonths > 1
|
|
153
155
|
const navigationStep = pagedNavigation ? resolvedNumberOfMonths : 1
|
|
154
156
|
const todayKey = toDateKey(new Date())
|
|
@@ -227,16 +229,16 @@ function Calendar({
|
|
|
227
229
|
onMonthChange?.(next)
|
|
228
230
|
}
|
|
229
231
|
|
|
230
|
-
const moveFocus = (date: Date) => {
|
|
231
|
-
let nextDate = date
|
|
232
|
-
let nextKey = toDateKey(nextDate)
|
|
233
|
-
let guard = 0
|
|
234
|
-
|
|
235
|
-
while (isDateDisabled(nextKey) && guard < 370) {
|
|
236
|
-
nextDate = addDays(nextDate,
|
|
237
|
-
nextKey = toDateKey(nextDate)
|
|
238
|
-
guard += 1
|
|
239
|
-
}
|
|
232
|
+
const moveFocus = (date: Date, step = 1) => {
|
|
233
|
+
let nextDate = date
|
|
234
|
+
let nextKey = toDateKey(nextDate)
|
|
235
|
+
let guard = 0
|
|
236
|
+
|
|
237
|
+
while (isDateDisabled(nextKey) && guard < 370) {
|
|
238
|
+
nextDate = addDays(nextDate, step)
|
|
239
|
+
nextKey = toDateKey(nextDate)
|
|
240
|
+
guard += 1
|
|
241
|
+
}
|
|
240
242
|
|
|
241
243
|
setFocusedDateKey(nextKey)
|
|
242
244
|
|
|
@@ -341,38 +343,38 @@ function Calendar({
|
|
|
341
343
|
((visibleMonthEntry?.days.findIndex((item) => toDateKey(item) === toDateKey(date)) ?? 0) + 7) % 7
|
|
342
344
|
|
|
343
345
|
switch (event.key) {
|
|
344
|
-
case "ArrowRight":
|
|
345
|
-
event.preventDefault()
|
|
346
|
-
moveFocus(addDays(date, 1))
|
|
347
|
-
break
|
|
348
|
-
case "ArrowLeft":
|
|
349
|
-
event.preventDefault()
|
|
350
|
-
moveFocus(addDays(date, -1))
|
|
351
|
-
break
|
|
352
|
-
case "ArrowDown":
|
|
353
|
-
event.preventDefault()
|
|
354
|
-
moveFocus(addDays(date, 7))
|
|
355
|
-
break
|
|
356
|
-
case "ArrowUp":
|
|
357
|
-
event.preventDefault()
|
|
358
|
-
moveFocus(addDays(date, -7))
|
|
359
|
-
break
|
|
360
|
-
case "Home":
|
|
361
|
-
event.preventDefault()
|
|
362
|
-
moveFocus(addDays(date, -columnIndex))
|
|
363
|
-
break
|
|
364
|
-
case "End":
|
|
365
|
-
event.preventDefault()
|
|
366
|
-
moveFocus(addDays(date, 6 - columnIndex))
|
|
367
|
-
break
|
|
368
|
-
case "PageUp":
|
|
369
|
-
event.preventDefault()
|
|
370
|
-
moveFocus(getDateAtSameDayInMonth(date, addMonths(date, -1)))
|
|
371
|
-
break
|
|
372
|
-
case "PageDown":
|
|
373
|
-
event.preventDefault()
|
|
374
|
-
moveFocus(getDateAtSameDayInMonth(date, addMonths(date, 1)))
|
|
375
|
-
break
|
|
346
|
+
case "ArrowRight":
|
|
347
|
+
event.preventDefault()
|
|
348
|
+
moveFocus(addDays(date, 1), 1)
|
|
349
|
+
break
|
|
350
|
+
case "ArrowLeft":
|
|
351
|
+
event.preventDefault()
|
|
352
|
+
moveFocus(addDays(date, -1), -1)
|
|
353
|
+
break
|
|
354
|
+
case "ArrowDown":
|
|
355
|
+
event.preventDefault()
|
|
356
|
+
moveFocus(addDays(date, 7), 7)
|
|
357
|
+
break
|
|
358
|
+
case "ArrowUp":
|
|
359
|
+
event.preventDefault()
|
|
360
|
+
moveFocus(addDays(date, -7), -7)
|
|
361
|
+
break
|
|
362
|
+
case "Home":
|
|
363
|
+
event.preventDefault()
|
|
364
|
+
moveFocus(addDays(date, -columnIndex), -1)
|
|
365
|
+
break
|
|
366
|
+
case "End":
|
|
367
|
+
event.preventDefault()
|
|
368
|
+
moveFocus(addDays(date, 6 - columnIndex), 1)
|
|
369
|
+
break
|
|
370
|
+
case "PageUp":
|
|
371
|
+
event.preventDefault()
|
|
372
|
+
moveFocus(getDateAtSameDayInMonth(date, addMonths(date, -1)), -1)
|
|
373
|
+
break
|
|
374
|
+
case "PageDown":
|
|
375
|
+
event.preventDefault()
|
|
376
|
+
moveFocus(getDateAtSameDayInMonth(date, addMonths(date, 1)), 1)
|
|
377
|
+
break
|
|
376
378
|
}
|
|
377
379
|
}
|
|
378
380
|
|
|
@@ -444,6 +446,9 @@ function Calendar({
|
|
|
444
446
|
const selected = mode === "single" ? currentValue === dateKey : dateKey === currentRange?.from || dateKey === currentRange?.to
|
|
445
447
|
const inRange = mode === "range" && isWithinRange(dateKey, currentRange?.from, currentRange?.to)
|
|
446
448
|
const inPreviewRange = !inRange && mode === "range" && isWithinRange(dateKey, previewRange?.from, previewRange?.to)
|
|
449
|
+
const rangeStart = mode === "range" && dateKey === currentRange?.from
|
|
450
|
+
const rangeEnd = mode === "range" && dateKey === currentRange?.to
|
|
451
|
+
const rangeMiddle = inRange && !rangeStart && !rangeEnd
|
|
447
452
|
const disabledReason = getDisabledReason(dateKey)
|
|
448
453
|
const disabled = Boolean(disabledReason)
|
|
449
454
|
const disabledLabel = disabledReason ? labels?.disabledDate?.(dateKey, disabledReason) : undefined
|
|
@@ -457,11 +462,15 @@ function Calendar({
|
|
|
457
462
|
}}
|
|
458
463
|
type="button"
|
|
459
464
|
disabled={disabled}
|
|
460
|
-
aria-label={disabledLabel ?? labels?.selectDate?.(dateKey) ?? dateKey}
|
|
461
|
-
aria-current={dateKey === todayKey ? "date" : undefined}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
+
aria-label={disabledLabel ?? labels?.selectDate?.(dateKey) ?? dateKey}
|
|
466
|
+
aria-current={dateKey === todayKey ? "date" : undefined}
|
|
467
|
+
aria-selected={selected || inRange || inPreviewRange || undefined}
|
|
468
|
+
tabIndex={dateKey === tabbableDateKey ? 0 : -1}
|
|
469
|
+
title={disabledLabel}
|
|
470
|
+
data-selected={selected || undefined}
|
|
471
|
+
data-range-start={rangeStart || undefined}
|
|
472
|
+
data-range-end={rangeEnd || undefined}
|
|
473
|
+
data-range-middle={rangeMiddle || undefined}
|
|
465
474
|
data-today={dateKey === todayKey || undefined}
|
|
466
475
|
data-outside={outside || undefined}
|
|
467
476
|
data-in-range={inRange || undefined}
|
|
@@ -39,6 +39,7 @@ export type DateRangePickerProps = Omit<
|
|
|
39
39
|
presets?: DateRangePickerPreset[]
|
|
40
40
|
triggerClassName?: string
|
|
41
41
|
contentClassName?: string
|
|
42
|
+
months?: number
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
function defaultFormatValue(value: string) {
|
|
@@ -65,8 +66,9 @@ function DateRangePicker({
|
|
|
65
66
|
showFooter = true,
|
|
66
67
|
presets,
|
|
67
68
|
triggerClassName,
|
|
68
|
-
contentClassName,
|
|
69
|
-
|
|
69
|
+
contentClassName,
|
|
70
|
+
months,
|
|
71
|
+
numberOfMonths = 2,
|
|
70
72
|
pagedNavigation = true,
|
|
71
73
|
...calendarProps
|
|
72
74
|
}: DateRangePickerProps) {
|
|
@@ -78,7 +80,8 @@ function DateRangePicker({
|
|
|
78
80
|
const activeValue = showFooter ? draftValue : value
|
|
79
81
|
const activeFrom = activeValue?.from ?? ""
|
|
80
82
|
const activeTo = activeValue?.to ?? ""
|
|
81
|
-
const hasDraftValue = Boolean(activeFrom || activeTo)
|
|
83
|
+
const hasDraftValue = Boolean(activeFrom || activeTo)
|
|
84
|
+
const resolvedNumberOfMonths = months ?? numberOfMonths
|
|
82
85
|
|
|
83
86
|
const label = from && to
|
|
84
87
|
? `${formatValue(from)} - ${formatValue(to)}`
|
|
@@ -244,7 +247,7 @@ function DateRangePicker({
|
|
|
244
247
|
if (fromValue) return `${fromValue} -> ...`
|
|
245
248
|
return "No range selected"
|
|
246
249
|
}}
|
|
247
|
-
numberOfMonths={
|
|
250
|
+
numberOfMonths={resolvedNumberOfMonths}
|
|
248
251
|
pagedNavigation={pagedNavigation}
|
|
249
252
|
showClearShortcut={!showFooter && clearable}
|
|
250
253
|
showSelectionSummary
|
|
@@ -3,12 +3,12 @@ import * as React from "react"
|
|
|
3
3
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
|
4
4
|
import { cn } from "@/lib/utils"
|
|
5
5
|
|
|
6
|
-
export type ChartDatum = {
|
|
7
|
-
label: React.ReactNode
|
|
8
|
-
value: number
|
|
9
|
-
description?: React.ReactNode
|
|
10
|
-
color?: string
|
|
11
|
-
}
|
|
6
|
+
export type ChartDatum = {
|
|
7
|
+
label: React.ReactNode
|
|
8
|
+
value: number
|
|
9
|
+
description?: React.ReactNode
|
|
10
|
+
color?: string
|
|
11
|
+
}
|
|
12
12
|
|
|
13
13
|
export type ChartSeries = {
|
|
14
14
|
key: string
|
|
@@ -19,7 +19,8 @@ export type ChartSeries = {
|
|
|
19
19
|
|
|
20
20
|
export type ChartAxisLabel = string | number | React.ReactNode
|
|
21
21
|
|
|
22
|
-
export type ChartSize = "sm" | "md" | "lg"
|
|
22
|
+
export type ChartSize = "sm" | "md" | "lg"
|
|
23
|
+
export type ChartState = "ready" | "loading" | "empty"
|
|
23
24
|
|
|
24
25
|
const chartHeightBySize: Record<ChartSize, number> = {
|
|
25
26
|
sm: 120,
|
|
@@ -31,10 +32,14 @@ function safeMax(values: number[], fallback = 1) {
|
|
|
31
32
|
return Math.max(...values, fallback)
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
function normalizeValue(value: number, max: number) {
|
|
35
|
-
if (!Number.isFinite(value) || max <= 0) return 0
|
|
36
|
-
return Math.max(0, Math.min(value / max, 1))
|
|
37
|
-
}
|
|
35
|
+
function normalizeValue(value: number, max: number) {
|
|
36
|
+
if (!Number.isFinite(value) || max <= 0) return 0
|
|
37
|
+
return Math.max(0, Math.min(value / max, 1))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function getChartColor(index: number, custom?: string) {
|
|
41
|
+
return custom ?? `var(--color-chart-${(index % 5) + 1}, var(--primary))`
|
|
42
|
+
}
|
|
38
43
|
|
|
39
44
|
function polarToCartesian(cx: number, cy: number, radius: number, angle: number) {
|
|
40
45
|
const radians = ((angle - 90) * Math.PI) / 180
|
|
@@ -79,13 +84,15 @@ function buildAreaPath(values: number[], width: number, height: number, padding
|
|
|
79
84
|
return `${line} L ${lastX} ${baseline} L ${firstX} ${baseline} Z`
|
|
80
85
|
}
|
|
81
86
|
|
|
82
|
-
export type ChartFrameProps = React.ComponentProps<typeof Card> & {
|
|
83
|
-
title?: React.ReactNode
|
|
84
|
-
description?: React.ReactNode
|
|
85
|
-
action?: React.ReactNode
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
export type ChartFrameProps = React.ComponentProps<typeof Card> & {
|
|
88
|
+
title?: React.ReactNode
|
|
89
|
+
description?: React.ReactNode
|
|
90
|
+
action?: React.ReactNode
|
|
91
|
+
state?: ChartState
|
|
92
|
+
emptyLabel?: React.ReactNode
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function ChartFrame({ title, description, action, state = "ready", emptyLabel = "No data available.", className, children, ...props }: ChartFrameProps) {
|
|
89
96
|
return (
|
|
90
97
|
<Card
|
|
91
98
|
data-slot="chart-frame"
|
|
@@ -101,39 +108,55 @@ function ChartFrame({ title, description, action, className, children, ...props
|
|
|
101
108
|
{action}
|
|
102
109
|
</CardHeader>
|
|
103
110
|
)}
|
|
104
|
-
<CardContent>
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
111
|
+
<CardContent>
|
|
112
|
+
{state === "loading" ? <div className="grid gap-3"><div className="h-4 w-24 animate-pulse rounded bg-muted" /><div className="h-36 animate-pulse rounded-[min(var(--radius-xl),16px)] bg-muted/70" /></div> : null}
|
|
113
|
+
{state === "empty" ? <div className="rounded-[min(var(--radius-xl),16px)] border border-dashed border-border/70 px-4 py-10 text-center text-sm text-muted-foreground">{emptyLabel}</div> : null}
|
|
114
|
+
{state === "ready" ? children : null}
|
|
115
|
+
</CardContent>
|
|
116
|
+
</Card>
|
|
117
|
+
)
|
|
118
|
+
}
|
|
108
119
|
|
|
109
120
|
export type BarChartProps = React.ComponentProps<"div"> & {
|
|
110
121
|
data: ChartDatum[]
|
|
111
|
-
size?: ChartSize
|
|
112
|
-
max?: number
|
|
113
|
-
showLabels?: boolean
|
|
114
|
-
showValues?: boolean
|
|
115
|
-
barClassName?: string
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
+
size?: ChartSize
|
|
123
|
+
max?: number
|
|
124
|
+
showLabels?: boolean
|
|
125
|
+
showValues?: boolean
|
|
126
|
+
barClassName?: string
|
|
127
|
+
state?: ChartState
|
|
128
|
+
emptyLabel?: React.ReactNode
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function BarChart({ data, size = "md", max, showLabels = true, showValues = true, state = "ready", emptyLabel = "No chart data.", className, barClassName, ...props }: BarChartProps) {
|
|
132
|
+
const values = data.map((item) => item.value)
|
|
133
|
+
const absoluteMax = max ?? safeMax(values.map((value) => Math.abs(value)))
|
|
134
|
+
const height = chartHeightBySize[size]
|
|
135
|
+
|
|
136
|
+
if (state === "loading") {
|
|
137
|
+
return <div data-slot="bar-chart" className={cn("grid gap-3", className)} {...props}><div className="h-40 animate-pulse rounded-[min(var(--radius-xl),16px)] bg-muted/70" /></div>
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (state === "empty" || data.length === 0) {
|
|
141
|
+
return <div data-slot="bar-chart" className={cn("rounded-[min(var(--radius-xl),16px)] border border-dashed border-border/70 px-4 py-10 text-center text-sm text-muted-foreground", className)} {...props}>{emptyLabel}</div>
|
|
142
|
+
}
|
|
143
|
+
|
|
122
144
|
return (
|
|
123
145
|
<div data-slot="bar-chart" className={cn("grid gap-3", className)} {...props}>
|
|
124
146
|
<div className="flex items-end gap-2" style={{ height }}>
|
|
125
|
-
{data.map((item, index) => {
|
|
126
|
-
const ratio = normalizeValue(item.value,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
147
|
+
{data.map((item, index) => {
|
|
148
|
+
const ratio = normalizeValue(Math.abs(item.value), absoluteMax)
|
|
149
|
+
const negative = item.value < 0
|
|
150
|
+
return (
|
|
151
|
+
<div key={index} className="flex min-w-0 flex-1 flex-col items-center gap-2">
|
|
152
|
+
{showValues && <div className="text-xs text-muted-foreground">{item.value}</div>}
|
|
130
153
|
<div className="flex w-full flex-1 items-end rounded-[min(var(--radius-xl),16px)] border border-border/60 bg-muted/38 p-1">
|
|
131
154
|
<div
|
|
132
155
|
className={cn("w-full rounded-[min(var(--radius-lg),12px)] bg-primary transition-all", barClassName)}
|
|
133
|
-
style={{ height: `${Math.max(ratio * 100, item.value > 0 ? 3 : 0)}%`, background: item.color }}
|
|
156
|
+
style={{ height: `${Math.max(ratio * 100, Math.abs(item.value) > 0 ? 3 : 0)}%`, background: getChartColor(index, item.color), opacity: negative ? 0.72 : 1 }}
|
|
134
157
|
/>
|
|
135
158
|
</div>
|
|
136
|
-
{showLabels && <div className="max-w-full truncate text-xs text-muted-foreground">{item.label}</div>}
|
|
159
|
+
{showLabels && <div className="max-w-full truncate text-xs text-muted-foreground">{item.label}</div>}
|
|
137
160
|
</div>
|
|
138
161
|
)
|
|
139
162
|
})}
|
|
@@ -147,15 +170,25 @@ export type LineChartProps = Omit<React.ComponentProps<"svg">, "values"> & {
|
|
|
147
170
|
size?: ChartSize
|
|
148
171
|
width?: number
|
|
149
172
|
showArea?: boolean
|
|
150
|
-
stroke?: string
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
173
|
+
stroke?: string
|
|
174
|
+
state?: ChartState
|
|
175
|
+
emptyLabel?: React.ReactNode
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function LineChart({ values, size = "md", width = 560, showArea = false, stroke = "var(--primary)", state = "ready", emptyLabel = "No line data.", className, ...props }: LineChartProps) {
|
|
179
|
+
const height = chartHeightBySize[size]
|
|
180
|
+
const linePath = buildLinePath(values, width, height)
|
|
181
|
+
const areaPath = buildAreaPath(values, width, height)
|
|
182
|
+
|
|
183
|
+
if (state === "loading") {
|
|
184
|
+
return <div className={cn("h-36 animate-pulse rounded-[min(var(--radius-xl),16px)] bg-muted/70", className)} />
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (state === "empty" || values.length === 0) {
|
|
188
|
+
return <div className={cn("rounded-[min(var(--radius-xl),16px)] border border-dashed border-border/70 px-4 py-10 text-center text-sm text-muted-foreground", className)}>{emptyLabel}</div>
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return (
|
|
159
192
|
<svg data-slot="line-chart" viewBox={`0 0 ${width} ${height}`} className={cn("h-auto w-full overflow-visible", className)} role="img" {...props}>
|
|
160
193
|
{showArea && <path d={areaPath} fill="var(--primary)" opacity="0.12" />}
|
|
161
194
|
<path d={linePath} fill="none" stroke={stroke} strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" />
|
|
@@ -191,12 +224,14 @@ function Sparkline({ values, positive = true, stroke, className, ...props }: Spa
|
|
|
191
224
|
export type DonutChartProps = React.ComponentProps<"svg"> & {
|
|
192
225
|
data: ChartDatum[]
|
|
193
226
|
size?: number
|
|
194
|
-
strokeWidth?: number
|
|
195
|
-
centerLabel?: React.ReactNode
|
|
196
|
-
centerValue?: React.ReactNode
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
227
|
+
strokeWidth?: number
|
|
228
|
+
centerLabel?: React.ReactNode
|
|
229
|
+
centerValue?: React.ReactNode
|
|
230
|
+
state?: ChartState
|
|
231
|
+
emptyLabel?: React.ReactNode
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function DonutChart({ data, size = 180, strokeWidth = 18, centerLabel, centerValue, state = "ready", emptyLabel = "No distribution data.", className, ...props }: DonutChartProps) {
|
|
200
235
|
const total = data.reduce((sum, item) => sum + Math.max(item.value, 0), 0)
|
|
201
236
|
const radius = size / 2 - strokeWidth
|
|
202
237
|
const segments = data.map((item, index) => {
|
|
@@ -207,6 +242,14 @@ function DonutChart({ data, size = 180, strokeWidth = 18, centerLabel, centerVal
|
|
|
207
242
|
return { item, start, end }
|
|
208
243
|
})
|
|
209
244
|
|
|
245
|
+
if (state === "loading") {
|
|
246
|
+
return <div className={cn("h-44 w-full max-w-48 animate-pulse rounded-full bg-muted/70", className)} />
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (state === "empty" || data.length === 0 || total <= 0) {
|
|
250
|
+
return <div className={cn("flex h-44 w-full max-w-48 items-center justify-center rounded-full border border-dashed border-border/70 px-4 text-center text-sm text-muted-foreground", className)}>{emptyLabel}</div>
|
|
251
|
+
}
|
|
252
|
+
|
|
210
253
|
return (
|
|
211
254
|
<svg data-slot="donut-chart" viewBox={`0 0 ${size} ${size}`} className={cn("h-auto w-full max-w-48", className)} role="img" {...props}>
|
|
212
255
|
<circle cx={size / 2} cy={size / 2} r={radius} fill="none" stroke="var(--muted)" strokeWidth={strokeWidth} />
|
|
@@ -215,11 +258,11 @@ function DonutChart({ data, size = 180, strokeWidth = 18, centerLabel, centerVal
|
|
|
215
258
|
<path
|
|
216
259
|
key={index}
|
|
217
260
|
d={describeArc(size / 2, size / 2, radius, start, end)}
|
|
218
|
-
fill="none"
|
|
219
|
-
stroke={item.color
|
|
220
|
-
strokeWidth={strokeWidth}
|
|
221
|
-
strokeLinecap="round"
|
|
222
|
-
/>
|
|
261
|
+
fill="none"
|
|
262
|
+
stroke={getChartColor(index, item.color)}
|
|
263
|
+
strokeWidth={strokeWidth}
|
|
264
|
+
strokeLinecap="round"
|
|
265
|
+
/>
|
|
223
266
|
)
|
|
224
267
|
})}
|
|
225
268
|
{(centerValue || centerLabel) && (
|
|
@@ -240,11 +283,11 @@ function ChartLegend({ data, className, ...props }: ChartLegendProps) {
|
|
|
240
283
|
return (
|
|
241
284
|
<div data-slot="chart-legend" className={cn("flex flex-wrap gap-3 text-xs text-muted-foreground", className)} {...props}>
|
|
242
285
|
{data.map((item, index) => (
|
|
243
|
-
<div key={index} className="inline-flex items-center gap-1.5">
|
|
244
|
-
<span className="size-2 rounded-full bg-primary" style={{ background: item.color }} />
|
|
245
|
-
<span>{item.label}</span>
|
|
246
|
-
</div>
|
|
247
|
-
))}
|
|
286
|
+
<div key={index} className="inline-flex items-center gap-1.5">
|
|
287
|
+
<span className="size-2 rounded-full bg-primary" style={{ background: getChartColor(index, item.color) }} />
|
|
288
|
+
<span>{item.label}</span>
|
|
289
|
+
</div>
|
|
290
|
+
))}
|
|
248
291
|
</div>
|
|
249
292
|
)
|
|
250
293
|
}
|
|
@@ -283,4 +326,4 @@ function MetricTrend({ label, value, change, positive = true, values, className,
|
|
|
283
326
|
)
|
|
284
327
|
}
|
|
285
328
|
|
|
286
|
-
export { BarChart, ChartFrame, ChartLegend, DonutChart, LineChart, MetricTrend, Sparkline }
|
|
329
|
+
export { BarChart, ChartFrame, ChartLegend, DonutChart, LineChart, MetricTrend, Sparkline }
|
|
@@ -2,36 +2,47 @@ import * as React from "react"
|
|
|
2
2
|
|
|
3
3
|
import { cn } from "@/lib/utils"
|
|
4
4
|
|
|
5
|
-
export type ProgressRingProps = React.ComponentProps<"svg"> & {
|
|
6
|
-
value: number
|
|
7
|
-
max?: number
|
|
8
|
-
size?: number
|
|
9
|
-
strokeWidth?: number
|
|
10
|
-
label?: React.ReactNode
|
|
11
|
-
description?: React.ReactNode
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
5
|
+
export type ProgressRingProps = React.ComponentProps<"svg"> & {
|
|
6
|
+
value: number
|
|
7
|
+
max?: number
|
|
8
|
+
size?: number
|
|
9
|
+
strokeWidth?: number
|
|
10
|
+
label?: React.ReactNode
|
|
11
|
+
description?: React.ReactNode
|
|
12
|
+
tone?: "default" | "success" | "warning" | "danger"
|
|
13
|
+
loading?: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function ProgressRing({ value, max = 100, size = 120, strokeWidth = 10, label, description, tone = "default", loading = false, className, ...props }: ProgressRingProps) {
|
|
17
|
+
const radius = (size - strokeWidth) / 2
|
|
18
|
+
const circumference = 2 * Math.PI * radius
|
|
19
|
+
const ratio = max > 0 ? Math.min(Math.max(value / max, 0), 1) : 0
|
|
20
|
+
const offset = circumference - ratio * circumference
|
|
21
|
+
const stroke =
|
|
22
|
+
tone === "success"
|
|
23
|
+
? "var(--color-chart-3, var(--primary))"
|
|
24
|
+
: tone === "warning"
|
|
25
|
+
? "var(--color-chart-4, var(--primary))"
|
|
26
|
+
: tone === "danger"
|
|
27
|
+
? "var(--destructive)"
|
|
28
|
+
: "var(--primary)"
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<svg data-slot="progress-ring" viewBox={`0 0 ${size} ${size}`} className={cn("h-auto w-full max-w-32", className)} role="img" {...props}>
|
|
32
|
+
<circle cx={size / 2} cy={size / 2} r={radius} fill="none" stroke="var(--muted)" strokeWidth={strokeWidth} />
|
|
33
|
+
<circle
|
|
24
34
|
cx={size / 2}
|
|
25
35
|
cy={size / 2}
|
|
26
36
|
r={radius}
|
|
27
37
|
fill="none"
|
|
28
|
-
stroke=
|
|
29
|
-
strokeWidth={strokeWidth}
|
|
30
|
-
strokeLinecap="round"
|
|
31
|
-
strokeDasharray={circumference}
|
|
32
|
-
strokeDashoffset={offset}
|
|
33
|
-
transform={`rotate(-90 ${size / 2} ${size / 2})`}
|
|
34
|
-
|
|
38
|
+
stroke={stroke}
|
|
39
|
+
strokeWidth={strokeWidth}
|
|
40
|
+
strokeLinecap="round"
|
|
41
|
+
strokeDasharray={circumference}
|
|
42
|
+
strokeDashoffset={loading ? circumference * 0.45 : offset}
|
|
43
|
+
transform={`rotate(-90 ${size / 2} ${size / 2})`}
|
|
44
|
+
className={loading ? "animate-pulse" : undefined}
|
|
45
|
+
/>
|
|
35
46
|
{(label || description) && (
|
|
36
47
|
<text x="50%" y="50%" textAnchor="middle" dominantBaseline="middle" fill="var(--foreground)">
|
|
37
48
|
{label && <tspan x="50%" dy={description ? "-0.15em" : "0"} className="text-base font-semibold">{label}</tspan>}
|
|
@@ -19,10 +19,13 @@ export type DataTableColumnVisibilityMenuProps<TData> = {
|
|
|
19
19
|
triggerLabel?: React.ReactNode
|
|
20
20
|
align?: "start" | "center" | "end"
|
|
21
21
|
side?: "top" | "right" | "bottom" | "left"
|
|
22
|
-
triggerClassName?: string
|
|
23
|
-
contentClassName?: string
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
triggerClassName?: string
|
|
23
|
+
contentClassName?: string
|
|
24
|
+
emptyLabel?: React.ReactNode
|
|
25
|
+
showCount?: boolean
|
|
26
|
+
triggerAriaLabel?: string
|
|
27
|
+
getColumnLabel?: (columnId: string) => React.ReactNode
|
|
28
|
+
}
|
|
26
29
|
|
|
27
30
|
function defaultColumnLabel(columnId: string) {
|
|
28
31
|
return columnId
|
|
@@ -36,16 +39,20 @@ function DataTableColumnVisibilityMenu<TData>({
|
|
|
36
39
|
label = "Columns",
|
|
37
40
|
triggerLabel,
|
|
38
41
|
align = "end",
|
|
39
|
-
side = "bottom",
|
|
40
|
-
triggerClassName,
|
|
41
|
-
contentClassName,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
side = "bottom",
|
|
43
|
+
triggerClassName,
|
|
44
|
+
contentClassName,
|
|
45
|
+
emptyLabel = "No hideable columns",
|
|
46
|
+
showCount = true,
|
|
47
|
+
triggerAriaLabel,
|
|
48
|
+
getColumnLabel = defaultColumnLabel,
|
|
49
|
+
}: DataTableColumnVisibilityMenuProps<TData>) {
|
|
50
|
+
const columns = table
|
|
51
|
+
.getAllLeafColumns()
|
|
52
|
+
.filter((column) => column.getCanHide())
|
|
53
|
+
const visibleCount = columns.filter((column) => column.getIsVisible()).length
|
|
54
|
+
|
|
55
|
+
return (
|
|
49
56
|
<DropdownMenu>
|
|
50
57
|
<DropdownMenuTrigger
|
|
51
58
|
render={
|
|
@@ -53,27 +60,39 @@ function DataTableColumnVisibilityMenu<TData>({
|
|
|
53
60
|
type="button"
|
|
54
61
|
variant="outline"
|
|
55
62
|
size="sm"
|
|
63
|
+
aria-label={triggerAriaLabel ?? "Choose visible columns"}
|
|
56
64
|
className={cn(
|
|
57
|
-
"border-border/80 bg-background/94 shadow-[0_1px_0_rgba(255,255,255,0.06)]",
|
|
65
|
+
"min-w-0 border-border/80 bg-background/94 px-2.5 shadow-[0_1px_0_rgba(255,255,255,0.06)] hover:border-border hover:bg-accent/70",
|
|
58
66
|
triggerClassName
|
|
59
67
|
)}
|
|
60
68
|
/>
|
|
61
69
|
}
|
|
62
70
|
>
|
|
63
|
-
<Columns3Icon data-icon="inline-start" />
|
|
64
|
-
{triggerLabel ?? label}
|
|
65
|
-
|
|
71
|
+
<Columns3Icon data-icon="inline-start" className="size-4 shrink-0" />
|
|
72
|
+
<span className="truncate">{triggerLabel ?? label}</span>
|
|
73
|
+
{showCount && columns.length > 0 ? (
|
|
74
|
+
<span className="ml-0.5 rounded-[var(--radius-sm)] bg-muted px-1.5 py-0.5 text-[11px] font-medium text-muted-foreground">
|
|
75
|
+
{visibleCount}/{columns.length}
|
|
76
|
+
</span>
|
|
77
|
+
) : null}
|
|
78
|
+
</DropdownMenuTrigger>
|
|
66
79
|
<DropdownMenuContent
|
|
67
80
|
align={align}
|
|
68
81
|
side={side}
|
|
69
82
|
className={cn(
|
|
70
|
-
"min-w-
|
|
83
|
+
"max-h-[min(24rem,var(--radix-dropdown-menu-content-available-height,24rem))] min-w-56 overflow-y-auto rounded-[var(--radius-lg)] border-border/80 bg-popover/98 p-1 shadow-[0_24px_80px_rgba(15,23,42,0.18)] backdrop-blur",
|
|
71
84
|
contentClassName
|
|
72
85
|
)}
|
|
73
86
|
>
|
|
74
|
-
<DropdownMenuLabel>
|
|
75
|
-
|
|
76
|
-
|
|
87
|
+
<DropdownMenuLabel className="flex items-center justify-between gap-3">
|
|
88
|
+
<span>{label}</span>
|
|
89
|
+
{showCount ? <span className="text-xs font-normal text-muted-foreground">{visibleCount} visible</span> : null}
|
|
90
|
+
</DropdownMenuLabel>
|
|
91
|
+
<DropdownMenuSeparator />
|
|
92
|
+
{columns.length === 0 ? (
|
|
93
|
+
<DropdownMenuLabel className="py-3 text-sm font-normal text-muted-foreground">{emptyLabel}</DropdownMenuLabel>
|
|
94
|
+
) : null}
|
|
95
|
+
{columns.map((column) => (
|
|
77
96
|
<DropdownMenuCheckboxItem
|
|
78
97
|
key={column.id}
|
|
79
98
|
checked={column.getIsVisible()}
|