tembro 2.0.6 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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/status-legend.cjs +1 -1
- package/dist/components/display/status-legend.js +6 -2
- 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/status-legend.tsx +11 -8
- 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
|
@@ -10,6 +10,8 @@ export type FormFieldShellProps = React.ComponentProps<"div"> & {
|
|
|
10
10
|
label?: React.ReactNode
|
|
11
11
|
description?: React.ReactNode
|
|
12
12
|
error?: React.ReactNode
|
|
13
|
+
success?: React.ReactNode
|
|
14
|
+
loading?: boolean
|
|
13
15
|
required?: boolean
|
|
14
16
|
htmlFor?: string
|
|
15
17
|
labelId?: string
|
|
@@ -34,6 +36,8 @@ export type FormFieldShellControlProps = Pick<
|
|
|
34
36
|
FormFieldShellProps,
|
|
35
37
|
| "label"
|
|
36
38
|
| "description"
|
|
39
|
+
| "success"
|
|
40
|
+
| "loading"
|
|
37
41
|
| "required"
|
|
38
42
|
| "className"
|
|
39
43
|
| "htmlFor"
|
|
@@ -89,6 +93,8 @@ function FormFieldShell({
|
|
|
89
93
|
label,
|
|
90
94
|
description,
|
|
91
95
|
error,
|
|
96
|
+
success,
|
|
97
|
+
loading = false,
|
|
92
98
|
required = false,
|
|
93
99
|
htmlFor,
|
|
94
100
|
labelId,
|
|
@@ -181,13 +187,30 @@ function FormFieldShell({
|
|
|
181
187
|
{showErrorIcon && <span className="mt-1 shrink-0">{resolvedErrorIcon}</span>}
|
|
182
188
|
<span className="min-w-0">{error}</span>
|
|
183
189
|
</p>
|
|
184
|
-
) : null
|
|
185
|
-
|
|
186
|
-
|
|
190
|
+
) : null
|
|
191
|
+
|
|
192
|
+
const successNode = success && !error ? (
|
|
193
|
+
<p
|
|
194
|
+
data-slot="form-field-success"
|
|
195
|
+
className="rounded-[min(var(--radius-xl),16px)] border border-emerald-500/18 bg-emerald-500/8 px-3 py-2 text-sm font-medium leading-6 text-emerald-700 dark:text-emerald-300"
|
|
196
|
+
>
|
|
197
|
+
{success}
|
|
198
|
+
</p>
|
|
199
|
+
) : null
|
|
200
|
+
|
|
201
|
+
const loadingNode = loading ? (
|
|
202
|
+
<p data-slot="form-field-loading" className="text-sm leading-6 text-muted-foreground">
|
|
203
|
+
Loading...
|
|
204
|
+
</p>
|
|
205
|
+
) : null
|
|
206
|
+
|
|
207
|
+
return (
|
|
187
208
|
<div
|
|
188
209
|
data-slot="form-field-shell"
|
|
189
210
|
data-layout={layout}
|
|
190
211
|
data-invalid={Boolean(error) || undefined}
|
|
212
|
+
data-success={Boolean(success && !error) || undefined}
|
|
213
|
+
data-loading={loading || undefined}
|
|
191
214
|
data-disabled={disabled || undefined}
|
|
192
215
|
data-readonly={readOnly || undefined}
|
|
193
216
|
aria-disabled={disabled || undefined}
|
|
@@ -202,7 +225,9 @@ function FormFieldShell({
|
|
|
202
225
|
</div>
|
|
203
226
|
<div className="grid min-w-0 gap-2">
|
|
204
227
|
{content}
|
|
228
|
+
{loadingNode}
|
|
205
229
|
{hasDescriptionBottom && descriptionNode}
|
|
230
|
+
{successNode}
|
|
206
231
|
{errorNode}
|
|
207
232
|
</div>
|
|
208
233
|
</>
|
|
@@ -212,17 +237,21 @@ function FormFieldShell({
|
|
|
212
237
|
<div className="grid min-w-0 flex-1 gap-2">
|
|
213
238
|
{hasDescriptionTop && descriptionNode}
|
|
214
239
|
{content}
|
|
240
|
+
{loadingNode}
|
|
215
241
|
{hasDescriptionBottom && descriptionNode}
|
|
216
|
-
{
|
|
242
|
+
{successNode}
|
|
243
|
+
{errorNode}
|
|
217
244
|
</div>
|
|
218
245
|
</>
|
|
219
246
|
) : (
|
|
220
247
|
<>
|
|
221
248
|
{header}
|
|
222
|
-
{hasDescriptionTop && descriptionNode}
|
|
223
|
-
{content}
|
|
224
|
-
{
|
|
225
|
-
{
|
|
249
|
+
{hasDescriptionTop && descriptionNode}
|
|
250
|
+
{content}
|
|
251
|
+
{loadingNode}
|
|
252
|
+
{hasDescriptionBottom && descriptionNode}
|
|
253
|
+
{successNode}
|
|
254
|
+
{errorNode}
|
|
226
255
|
</>
|
|
227
256
|
)}
|
|
228
257
|
</div>
|
|
@@ -192,6 +192,8 @@ function buildShellProps<
|
|
|
192
192
|
return {
|
|
193
193
|
label: props.label,
|
|
194
194
|
description: props.description,
|
|
195
|
+
success: props.success,
|
|
196
|
+
loading: props.loading,
|
|
195
197
|
required: props.required,
|
|
196
198
|
className: props.className,
|
|
197
199
|
htmlFor: props.id ?? props.name,
|
|
@@ -29,9 +29,11 @@ function FormSwitch<
|
|
|
29
29
|
>({
|
|
30
30
|
control,
|
|
31
31
|
name,
|
|
32
|
-
label,
|
|
33
|
-
description,
|
|
34
|
-
|
|
32
|
+
label,
|
|
33
|
+
description,
|
|
34
|
+
success,
|
|
35
|
+
loading,
|
|
36
|
+
required,
|
|
35
37
|
className,
|
|
36
38
|
layout,
|
|
37
39
|
descriptionPosition,
|
|
@@ -96,6 +98,8 @@ function FormSwitch<
|
|
|
96
98
|
<FormFieldShell
|
|
97
99
|
label={label}
|
|
98
100
|
description={description}
|
|
101
|
+
success={success}
|
|
102
|
+
loading={loading}
|
|
99
103
|
required={required}
|
|
100
104
|
error={error}
|
|
101
105
|
htmlFor={switchId}
|
|
@@ -122,6 +126,8 @@ function FormSwitch<
|
|
|
122
126
|
) : (
|
|
123
127
|
<FormFieldShell
|
|
124
128
|
error={error}
|
|
129
|
+
success={success}
|
|
130
|
+
loading={loading}
|
|
125
131
|
className={className}
|
|
126
132
|
descriptionId={resolvedIds.descriptionId}
|
|
127
133
|
errorId={resolvedIds.errorId}
|
|
@@ -29,8 +29,10 @@ function FormTextarea<
|
|
|
29
29
|
name,
|
|
30
30
|
rules,
|
|
31
31
|
label,
|
|
32
|
-
description,
|
|
33
|
-
|
|
32
|
+
description,
|
|
33
|
+
success,
|
|
34
|
+
loading,
|
|
35
|
+
required,
|
|
34
36
|
className,
|
|
35
37
|
layout,
|
|
36
38
|
descriptionPosition,
|
|
@@ -68,6 +70,8 @@ function FormTextarea<
|
|
|
68
70
|
<FormFieldShell
|
|
69
71
|
label={label}
|
|
70
72
|
description={description}
|
|
73
|
+
success={success}
|
|
74
|
+
loading={loading}
|
|
71
75
|
required={required}
|
|
72
76
|
error={error}
|
|
73
77
|
htmlFor={textareaId}
|
|
@@ -59,6 +59,7 @@ export type AppSidebarProps = React.ComponentProps<"aside"> & {
|
|
|
59
59
|
mobileToggleClassName?: string
|
|
60
60
|
mobilePanelClassName?: string
|
|
61
61
|
mobileOverlayClassName?: string
|
|
62
|
+
footerClassName?: string
|
|
62
63
|
renderMobileToggle?: (state: { open: boolean; setOpen: (open: boolean) => void }) => React.ReactNode
|
|
63
64
|
onItemSelect?: (item: AppSidebarNavItem) => void
|
|
64
65
|
renderItem?: (item: AppSidebarNavItem, state: { collapsed: boolean }) => React.ReactNode
|
|
@@ -433,6 +434,7 @@ function SidebarSurface({
|
|
|
433
434
|
footerAccount,
|
|
434
435
|
secondaryActions = [],
|
|
435
436
|
footerSecondary,
|
|
437
|
+
footerClassName,
|
|
436
438
|
tooltipOnCollapsed,
|
|
437
439
|
onItemSelect,
|
|
438
440
|
renderItem,
|
|
@@ -531,7 +533,7 @@ function SidebarSurface({
|
|
|
531
533
|
</nav>
|
|
532
534
|
|
|
533
535
|
{(footerAccount || footerSecondary || footer || visibleSecondaryActions.length > 0 || (collapsed && (collapsedRail || visibleRailItems.length > 0))) && (
|
|
534
|
-
<div data-slot="app-sidebar-footer" className="shrink-0 border-t p-3">
|
|
536
|
+
<div data-slot="app-sidebar-footer" className={cn("shrink-0 border-t p-3", footerClassName)}>
|
|
535
537
|
{collapsed ? (
|
|
536
538
|
<>
|
|
537
539
|
{visibleRailItems.length > 0 ? (
|
|
@@ -19,6 +19,7 @@ export type BreadcrumbsProps = React.ComponentProps<"nav"> & {
|
|
|
19
19
|
collapseLabel?: React.ReactNode
|
|
20
20
|
separator?: React.ReactNode
|
|
21
21
|
wrap?: boolean
|
|
22
|
+
currentItemLabel?: React.AriaAttributes["aria-current"]
|
|
22
23
|
renderLink?: (props: React.ComponentProps<"a"> & { item: BreadcrumbItem; [key: `data-${string}`]: string | boolean | undefined }) => React.ReactNode
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -46,6 +47,7 @@ function Breadcrumbs({
|
|
|
46
47
|
collapseLabel = "…",
|
|
47
48
|
separator = <ChevronRightIcon className="size-3.5" />,
|
|
48
49
|
wrap = false,
|
|
50
|
+
currentItemLabel,
|
|
49
51
|
renderLink,
|
|
50
52
|
...props
|
|
51
53
|
}: BreadcrumbsProps) {
|
|
@@ -106,7 +108,7 @@ function Breadcrumbs({
|
|
|
106
108
|
) : (
|
|
107
109
|
<span
|
|
108
110
|
data-slot="breadcrumbs-current"
|
|
109
|
-
aria-current={isCurrent ? (item.currentLabel ?? "page") : undefined}
|
|
111
|
+
aria-current={isCurrent ? ((item.currentLabel ?? currentItemLabel ?? "page") as React.AriaAttributes["aria-current"]) : undefined}
|
|
110
112
|
className={cn(
|
|
111
113
|
"inline-flex min-w-0 items-center gap-1.5 truncate rounded-[var(--radius-sm)] px-1 py-0.5",
|
|
112
114
|
isCurrent && "bg-accent/45 font-medium text-foreground"
|
|
@@ -2,18 +2,22 @@ import * as React from "react"
|
|
|
2
2
|
|
|
3
3
|
import { cn } from "@/lib/utils"
|
|
4
4
|
|
|
5
|
-
export type CalendarSchedulerEvent = {
|
|
6
|
-
id: string
|
|
7
|
-
title: React.ReactNode
|
|
8
|
-
date: string
|
|
9
|
-
time?: string
|
|
10
|
-
tone?: "default" | "success" | "warning" | "danger"
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
export type CalendarSchedulerEvent = {
|
|
6
|
+
id: string
|
|
7
|
+
title: React.ReactNode
|
|
8
|
+
date: string
|
|
9
|
+
time?: string
|
|
10
|
+
tone?: "default" | "success" | "warning" | "danger"
|
|
11
|
+
durationMinutes?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
13
14
|
export type CalendarSchedulerProps = React.ComponentProps<"div"> & {
|
|
14
15
|
events: CalendarSchedulerEvent[]
|
|
15
16
|
days?: string[]
|
|
17
|
+
view?: "day" | "week" | "month"
|
|
16
18
|
empty?: React.ReactNode
|
|
19
|
+
onCreateEvent?: (date: string) => void
|
|
20
|
+
onEventClick?: (event: CalendarSchedulerEvent) => void
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
const toneClassName = {
|
|
@@ -23,11 +27,11 @@ const toneClassName = {
|
|
|
23
27
|
danger: "border-red-200 bg-red-50 text-red-700 dark:border-red-900 dark:bg-red-950 dark:text-red-300",
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
function CalendarScheduler({ events, days, empty = "No events scheduled.", className, ...props }: CalendarSchedulerProps) {
|
|
30
|
+
function CalendarScheduler({ events, days, view = "week", empty = "No events scheduled.", onCreateEvent, onEventClick, className, ...props }: CalendarSchedulerProps) {
|
|
27
31
|
const visibleDays = days ?? Array.from(new Set(events.map((event) => event.date)))
|
|
28
32
|
|
|
29
33
|
return (
|
|
30
|
-
<div data-slot="calendar-scheduler" className={cn("grid gap-3", className)} {...props}>
|
|
34
|
+
<div data-slot="calendar-scheduler" data-view={view} className={cn("grid gap-3", view === "month" && "md:grid-cols-2 xl:grid-cols-3", className)} {...props}>
|
|
31
35
|
{visibleDays.map((day) => (
|
|
32
36
|
<section key={day} className="rounded-[var(--aui-card-radius,var(--radius-xl))] border border-[color:var(--aui-card-border,var(--border))] bg-card p-4 shadow-[var(--aui-card-shadow,var(--aui-control-shadow,none))]">
|
|
33
37
|
<div className="mb-3 flex items-center justify-between gap-3">
|
|
@@ -41,16 +45,27 @@ function CalendarScheduler({ events, days, empty = "No events scheduled.", class
|
|
|
41
45
|
</div>
|
|
42
46
|
) : (
|
|
43
47
|
events.filter((event) => event.date === day).map((event) => (
|
|
44
|
-
<
|
|
48
|
+
<button
|
|
49
|
+
key={event.id}
|
|
50
|
+
type="button"
|
|
51
|
+
className={cn("rounded-[var(--radius-md)] border px-3 py-2.5 text-left text-sm shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40", toneClassName[event.tone ?? "default"])}
|
|
52
|
+
onClick={() => onEventClick?.(event)}
|
|
53
|
+
>
|
|
45
54
|
<div className="font-medium">{event.title}</div>
|
|
46
55
|
{event.time && <div className="mt-1 text-xs opacity-70">{event.time}</div>}
|
|
47
|
-
|
|
56
|
+
{event.durationMinutes && <div className="mt-1 text-xs opacity-70">{event.durationMinutes} min</div>}
|
|
57
|
+
</button>
|
|
48
58
|
))
|
|
49
59
|
)}
|
|
50
60
|
</div>
|
|
61
|
+
{onCreateEvent && (
|
|
62
|
+
<button type="button" className="mt-3 w-full rounded-md border border-dashed px-3 py-2 text-sm text-muted-foreground hover:bg-muted/50" onClick={() => onCreateEvent(day)}>
|
|
63
|
+
Create event
|
|
64
|
+
</button>
|
|
65
|
+
)}
|
|
51
66
|
</section>
|
|
52
67
|
))}
|
|
53
|
-
</div>
|
|
68
|
+
</div>
|
|
54
69
|
)
|
|
55
70
|
}
|
|
56
71
|
|
|
@@ -8,44 +8,112 @@ export type DualListItem = {
|
|
|
8
8
|
disabled?: boolean
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export type DualListPickerProps = React.ComponentProps<"div"> & {
|
|
12
|
-
items: DualListItem[]
|
|
13
|
-
picked?: string[]
|
|
14
|
-
onPickedChange?: (value: string[]) => void
|
|
15
|
-
availableTitle?: React.ReactNode
|
|
16
|
-
pickedTitle?: React.ReactNode
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
11
|
+
export type DualListPickerProps = React.ComponentProps<"div"> & {
|
|
12
|
+
items: DualListItem[]
|
|
13
|
+
picked?: string[]
|
|
14
|
+
onPickedChange?: (value: string[]) => void
|
|
15
|
+
availableTitle?: React.ReactNode
|
|
16
|
+
pickedTitle?: React.ReactNode
|
|
17
|
+
searchPlaceholder?: string
|
|
18
|
+
emptyMessage?: React.ReactNode
|
|
19
|
+
maxPicked?: number
|
|
20
|
+
transferAll?: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function DualListPicker({
|
|
24
|
+
items,
|
|
25
|
+
picked = [],
|
|
26
|
+
onPickedChange,
|
|
27
|
+
availableTitle = "Available",
|
|
28
|
+
pickedTitle = "Selected",
|
|
29
|
+
searchPlaceholder = "Search items...",
|
|
30
|
+
emptyMessage = "No items.",
|
|
31
|
+
maxPicked,
|
|
32
|
+
transferAll = true,
|
|
33
|
+
className,
|
|
34
|
+
...props
|
|
35
|
+
}: DualListPickerProps) {
|
|
36
|
+
const [query, setQuery] = React.useState("")
|
|
37
|
+
const pickedSet = new Set(picked)
|
|
38
|
+
const normalizedQuery = query.trim().toLowerCase()
|
|
39
|
+
const matchesQuery = (item: DualListItem) => {
|
|
40
|
+
if (!normalizedQuery) return true
|
|
41
|
+
return String(item.label).toLowerCase().includes(normalizedQuery) || item.value.toLowerCase().includes(normalizedQuery)
|
|
42
|
+
}
|
|
43
|
+
const availableItems = items.filter((item) => !pickedSet.has(item.value) && matchesQuery(item))
|
|
44
|
+
const pickedItems = items.filter((item) => pickedSet.has(item.value) && matchesQuery(item))
|
|
45
|
+
const maxReached = maxPicked !== undefined && picked.length >= maxPicked
|
|
46
|
+
|
|
47
|
+
function toggle(value: string) {
|
|
48
|
+
const isPicked = pickedSet.has(value)
|
|
49
|
+
if (!isPicked && maxReached) return
|
|
50
|
+
const next = isPicked ? picked.filter((item) => item !== value) : [...picked, value]
|
|
51
|
+
onPickedChange?.(next)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function addAll() {
|
|
55
|
+
const next = [...picked]
|
|
56
|
+
for (const item of items) {
|
|
57
|
+
if (item.disabled || pickedSet.has(item.value)) continue
|
|
58
|
+
if (maxPicked !== undefined && next.length >= maxPicked) break
|
|
59
|
+
next.push(item.value)
|
|
60
|
+
}
|
|
61
|
+
onPickedChange?.(next)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function removeAll() {
|
|
65
|
+
onPickedChange?.([])
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const renderColumn = (title: React.ReactNode, columnItems: DualListItem[], mode: "available" | "picked") => (
|
|
69
|
+
<div className="min-h-48 rounded-lg border bg-card">
|
|
70
|
+
<div className="flex items-center justify-between gap-2 border-b px-3 py-2 text-sm font-medium">
|
|
71
|
+
<span>{title}</span>
|
|
72
|
+
<span className="text-xs font-normal text-muted-foreground">{columnItems.length}</span>
|
|
73
|
+
</div>
|
|
74
|
+
<div className="grid gap-1 p-2">
|
|
75
|
+
{columnItems.length === 0 ? (
|
|
76
|
+
<div className="rounded-md border border-dashed px-3 py-6 text-center text-sm text-muted-foreground">{emptyMessage}</div>
|
|
77
|
+
) : columnItems.map((item) => (
|
|
78
|
+
<button
|
|
79
|
+
key={item.value}
|
|
80
|
+
type="button"
|
|
81
|
+
disabled={item.disabled || (mode === "available" && maxReached)}
|
|
82
|
+
className="flex items-center justify-between rounded-md px-2 py-1.5 text-left text-sm hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/40 disabled:opacity-50"
|
|
83
|
+
aria-pressed={pickedSet.has(item.value)}
|
|
84
|
+
onClick={() => toggle(item.value)}
|
|
85
|
+
>
|
|
86
|
+
<span>{item.label}</span>
|
|
87
|
+
<span className="text-muted-foreground">{pickedSet.has(item.value) ? "−" : "+"}</span>
|
|
88
|
+
</button>
|
|
38
89
|
))}
|
|
39
90
|
</div>
|
|
40
91
|
</div>
|
|
41
92
|
)
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<div data-slot="dual-list-picker" className={cn("grid gap-3
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<div data-slot="dual-list-picker" className={cn("grid gap-3", className)} {...props}>
|
|
96
|
+
<div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
|
|
97
|
+
<input
|
|
98
|
+
value={query}
|
|
99
|
+
placeholder={searchPlaceholder}
|
|
100
|
+
className="h-9 min-w-0 rounded-md border bg-background px-3 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring/40 sm:max-w-xs"
|
|
101
|
+
onChange={(event) => setQuery(event.currentTarget.value)}
|
|
102
|
+
/>
|
|
103
|
+
{transferAll && (
|
|
104
|
+
<div className="flex gap-2">
|
|
105
|
+
<button type="button" className="rounded-md border px-3 py-1.5 text-sm disabled:opacity-50" disabled={maxReached} onClick={addAll}>Add all</button>
|
|
106
|
+
<button type="button" className="rounded-md border px-3 py-1.5 text-sm disabled:opacity-50" disabled={picked.length === 0} onClick={removeAll}>Remove all</button>
|
|
107
|
+
</div>
|
|
108
|
+
)}
|
|
109
|
+
</div>
|
|
110
|
+
<div className="grid gap-3 md:grid-cols-2">
|
|
111
|
+
{renderColumn(availableTitle, availableItems, "available")}
|
|
112
|
+
{renderColumn(pickedTitle, pickedItems, "picked")}
|
|
113
|
+
</div>
|
|
114
|
+
{maxPicked !== undefined && <div className="text-xs text-muted-foreground">{picked.length} / {maxPicked} selected</div>}
|
|
115
|
+
</div>
|
|
116
|
+
)
|
|
117
|
+
}
|
|
50
118
|
|
|
51
119
|
export { DualListPicker }
|
|
@@ -2,14 +2,16 @@ import * as React from "react"
|
|
|
2
2
|
|
|
3
3
|
import { cn } from "@/lib/utils"
|
|
4
4
|
|
|
5
|
-
export type RichTextEditorProps = Omit<React.ComponentProps<"div">, "onChange"> & {
|
|
6
|
-
value?: string
|
|
7
|
-
onValueChange?: (value: string) => void
|
|
8
|
-
placeholder?: string
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
export type RichTextEditorProps = Omit<React.ComponentProps<"div">, "onChange"> & {
|
|
6
|
+
value?: string
|
|
7
|
+
onValueChange?: (value: string) => void
|
|
8
|
+
placeholder?: string
|
|
9
|
+
output?: "html" | "text"
|
|
10
|
+
disabled?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function RichTextEditor({ value, onValueChange, placeholder = "Write something...", output = "html", disabled = false, className, ...props }: RichTextEditorProps) {
|
|
14
|
+
const ref = React.useRef<HTMLDivElement | null>(null)
|
|
13
15
|
|
|
14
16
|
React.useEffect(() => {
|
|
15
17
|
if (ref.current && value !== undefined && ref.current.innerHTML !== value) {
|
|
@@ -18,27 +20,28 @@ function RichTextEditor({ value, onValueChange, placeholder = "Write something..
|
|
|
18
20
|
}, [value])
|
|
19
21
|
|
|
20
22
|
return (
|
|
21
|
-
<div data-slot="rich-text-editor" className={cn("grid gap-2 rounded-lg border bg-background p-2", className)} {...props}>
|
|
22
|
-
<div className="flex flex-wrap gap-1 border-b pb-2">
|
|
23
|
+
<div data-slot="rich-text-editor" data-disabled={disabled || undefined} className={cn("grid gap-2 rounded-lg border bg-background p-2", disabled && "opacity-60", className)} {...props}>
|
|
24
|
+
<div className="flex flex-wrap gap-1 border-b pb-2">
|
|
23
25
|
{[
|
|
24
26
|
["bold", "B"],
|
|
25
27
|
["italic", "I"],
|
|
26
28
|
["underline", "U"],
|
|
27
29
|
].map(([command, label]) => (
|
|
28
|
-
<button key={command} type="button" className="rounded border px-2 py-1 text-xs font-medium" onClick={() => document.execCommand(command)}>
|
|
29
|
-
{label}
|
|
30
|
-
</button>
|
|
30
|
+
<button key={command} type="button" disabled={disabled} className="rounded border px-2 py-1 text-xs font-medium disabled:opacity-50" onClick={() => document.execCommand(command)}>
|
|
31
|
+
{label}
|
|
32
|
+
</button>
|
|
31
33
|
))}
|
|
32
34
|
</div>
|
|
33
35
|
<div
|
|
34
|
-
ref={ref}
|
|
35
|
-
contentEditable
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
ref={ref}
|
|
37
|
+
contentEditable={!disabled}
|
|
38
|
+
aria-disabled={disabled || undefined}
|
|
39
|
+
data-placeholder={placeholder}
|
|
40
|
+
className="min-h-32 rounded-md p-2 text-sm outline-none empty:before:text-muted-foreground empty:before:content-[attr(data-placeholder)]"
|
|
41
|
+
onInput={(event) => onValueChange?.(output === "text" ? event.currentTarget.textContent ?? "" : event.currentTarget.innerHTML)}
|
|
42
|
+
/>
|
|
43
|
+
</div>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
43
46
|
|
|
44
47
|
export { RichTextEditor }
|
|
@@ -2,38 +2,56 @@ import * as React from "react"
|
|
|
2
2
|
|
|
3
3
|
import { cn } from "@/lib/utils"
|
|
4
4
|
|
|
5
|
-
export type TourStep = {
|
|
6
|
-
title: React.ReactNode
|
|
7
|
-
description?: React.ReactNode
|
|
8
|
-
|
|
5
|
+
export type TourStep = {
|
|
6
|
+
title: React.ReactNode
|
|
7
|
+
description?: React.ReactNode
|
|
8
|
+
target?: string
|
|
9
|
+
}
|
|
9
10
|
|
|
10
11
|
export type TourProps = React.ComponentProps<"div"> & {
|
|
11
12
|
steps: TourStep[]
|
|
12
|
-
index?: number
|
|
13
|
-
onIndexChange?: (index: number) => void
|
|
14
|
-
onClose?: () => void
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
13
|
+
index?: number
|
|
14
|
+
onIndexChange?: (index: number) => void
|
|
15
|
+
onClose?: () => void
|
|
16
|
+
onSkip?: () => void
|
|
17
|
+
onFinish?: () => void
|
|
18
|
+
placement?: "top" | "right" | "bottom" | "left"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function Tour({ steps, index = 0, onIndexChange, onClose, onSkip, onFinish, placement = "bottom", className, ...props }: TourProps) {
|
|
22
|
+
const step = steps[index]
|
|
23
|
+
const containerRef = React.useRef<HTMLDivElement | null>(null)
|
|
24
|
+
React.useEffect(() => {
|
|
25
|
+
containerRef.current?.focus()
|
|
26
|
+
}, [index])
|
|
27
|
+
|
|
28
|
+
if (!step) return null
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div
|
|
32
|
+
ref={containerRef}
|
|
33
|
+
data-slot="tour"
|
|
34
|
+
data-placement={placement}
|
|
35
|
+
tabIndex={-1}
|
|
36
|
+
className={cn("rounded-xl border bg-popover p-4 text-popover-foreground shadow-lg outline-none focus-visible:ring-2 focus-visible:ring-ring/40", className)}
|
|
37
|
+
{...props}
|
|
38
|
+
>
|
|
39
|
+
<div className="grid gap-2">
|
|
40
|
+
<div className="font-semibold">{step.title}</div>
|
|
41
|
+
{step.description && <div className="text-sm text-muted-foreground">{step.description}</div>}
|
|
42
|
+
{step.target && <div className="text-xs text-muted-foreground">{step.target}</div>}
|
|
43
|
+
<div className="flex items-center justify-between gap-3 pt-2">
|
|
44
|
+
<span className="text-xs text-muted-foreground">{index + 1} / {steps.length}</span>
|
|
45
|
+
<div className="flex gap-2">
|
|
46
|
+
<button type="button" className="rounded-md border px-2.5 py-1 text-sm" onClick={() => { onSkip?.(); onClose?.() }}>Skip</button>
|
|
47
|
+
<button type="button" className="rounded-md border px-2.5 py-1 text-sm" disabled={index === 0} onClick={() => onIndexChange?.(index - 1)}>Back</button>
|
|
48
|
+
{index < steps.length - 1 ? (
|
|
49
|
+
<button type="button" className="rounded-md bg-primary px-2.5 py-1 text-sm text-primary-foreground" onClick={() => onIndexChange?.(index + 1)}>Next</button>
|
|
50
|
+
) : (
|
|
51
|
+
<button type="button" className="rounded-md bg-primary px-2.5 py-1 text-sm text-primary-foreground" onClick={() => { onFinish?.(); onClose?.() }}>Done</button>
|
|
52
|
+
)}
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
37
55
|
</div>
|
|
38
56
|
</div>
|
|
39
57
|
)
|
|
@@ -5,11 +5,15 @@ export type CommandBarProps = React.ComponentProps<"div"> & {
|
|
|
5
5
|
open?: boolean
|
|
6
6
|
onOpenChange?: (open: boolean) => void
|
|
7
7
|
position?: "bottom" | "top"
|
|
8
|
+
grouped?: boolean
|
|
9
|
+
label?: React.ReactNode
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
function CommandBar({
|
|
11
13
|
open = true,
|
|
12
14
|
position = "bottom",
|
|
15
|
+
grouped = false,
|
|
16
|
+
label,
|
|
13
17
|
children,
|
|
14
18
|
className,
|
|
15
19
|
...props
|
|
@@ -22,10 +26,12 @@ function CommandBar({
|
|
|
22
26
|
className={cn(
|
|
23
27
|
"fixed left-1/2 z-50 flex -translate-x-1/2 items-center gap-2 rounded-full border bg-background/95 px-4 py-2 shadow-lg backdrop-blur supports-[backdrop-filter]:bg-background/60",
|
|
24
28
|
position === "bottom" ? "bottom-6" : "top-6",
|
|
29
|
+
grouped && "gap-3 rounded-[28px] px-3 py-2.5",
|
|
25
30
|
className
|
|
26
31
|
)}
|
|
27
32
|
{...props}
|
|
28
33
|
>
|
|
34
|
+
{label ? <span className="text-xs font-semibold uppercase tracking-[0.18em] text-muted-foreground">{label}</span> : null}
|
|
29
35
|
{children}
|
|
30
36
|
</div>
|
|
31
37
|
)
|
|
@@ -3,7 +3,6 @@ import { component, createShowcaseDemoRegistry } from "@/showcase/create-demo"
|
|
|
3
3
|
export const navigationShowcaseDemoRegistry = createShowcaseDemoRegistry([
|
|
4
4
|
component("pagination", "Pagination", "navigation", "Controlled page navigation with edge buttons and active state."),
|
|
5
5
|
component("nav-tabs", "NavTabs", "navigation", "Navigation tabs for switching related document sections."),
|
|
6
|
-
component("anchor-nav", "AnchorNav", "navigation", "Section jump navigation for long detail pages."),
|
|
7
6
|
component("page-tabs", "PageTabs", "navigation", "Top-level page tab strip for route-sized sections."),
|
|
8
7
|
component("stepper-tabs", "StepperTabs", "navigation", "Step-like tabs for setup and onboarding progress."),
|
|
9
8
|
])
|