azamat-ui-kit-cli 0.2.2

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.
Files changed (213) hide show
  1. package/README.md +8 -0
  2. package/dist/index.js +432 -0
  3. package/package.json +34 -0
  4. package/vendor/package.json +4 -0
  5. package/vendor/src/components/actions/action-bar.tsx +35 -0
  6. package/vendor/src/components/actions/action-menu.tsx +120 -0
  7. package/vendor/src/components/actions/button-group.tsx +47 -0
  8. package/vendor/src/components/actions/copy-button.tsx +91 -0
  9. package/vendor/src/components/actions/copy-field.tsx +31 -0
  10. package/vendor/src/components/actions/floating-action-button.tsx +33 -0
  11. package/vendor/src/components/actions/index.ts +7 -0
  12. package/vendor/src/components/actions/public.ts +5 -0
  13. package/vendor/src/components/actions/quick-action-grid.tsx +162 -0
  14. package/vendor/src/components/calendar/calendar.tsx +328 -0
  15. package/vendor/src/components/calendar/date-picker.tsx +78 -0
  16. package/vendor/src/components/calendar/date-range-picker.tsx +96 -0
  17. package/vendor/src/components/calendar/date-utils.ts +89 -0
  18. package/vendor/src/components/calendar/index.ts +4 -0
  19. package/vendor/src/components/charts/charts.tsx +275 -0
  20. package/vendor/src/components/charts/horizontal-bar-chart.tsx +46 -0
  21. package/vendor/src/components/charts/index.ts +4 -0
  22. package/vendor/src/components/charts/kpi.tsx +68 -0
  23. package/vendor/src/components/charts/progress-ring.tsx +45 -0
  24. package/vendor/src/components/charts/public.ts +1 -0
  25. package/vendor/src/components/command/command-palette.tsx +375 -0
  26. package/vendor/src/components/command/index.ts +1 -0
  27. package/vendor/src/components/data-table/data-table-actions-column.tsx +58 -0
  28. package/vendor/src/components/data-table/data-table-bulk-actions.tsx +84 -0
  29. package/vendor/src/components/data-table/data-table-column-visibility-menu.tsx +79 -0
  30. package/vendor/src/components/data-table/data-table-pagination.tsx +91 -0
  31. package/vendor/src/components/data-table/data-table-row-actions.tsx +48 -0
  32. package/vendor/src/components/data-table/data-table-select-column.tsx +59 -0
  33. package/vendor/src/components/data-table/data-table-sortable-header.tsx +45 -0
  34. package/vendor/src/components/data-table/data-table-toolbar.tsx +76 -0
  35. package/vendor/src/components/data-table/data-table-view-presets.tsx +128 -0
  36. package/vendor/src/components/data-table/data-table.tsx +507 -0
  37. package/vendor/src/components/data-table/index.ts +12 -0
  38. package/vendor/src/components/data-table/public.ts +10 -0
  39. package/vendor/src/components/data-table/table-export-menu.tsx +56 -0
  40. package/vendor/src/components/data-table/table-import-button.tsx +43 -0
  41. package/vendor/src/components/display/activity-feed.tsx +97 -0
  42. package/vendor/src/components/display/avatar.tsx +131 -0
  43. package/vendor/src/components/display/code-block.tsx +33 -0
  44. package/vendor/src/components/display/data-state.tsx +63 -0
  45. package/vendor/src/components/display/description-list.tsx +119 -0
  46. package/vendor/src/components/display/descriptions.tsx +83 -0
  47. package/vendor/src/components/display/entity-card.tsx +53 -0
  48. package/vendor/src/components/display/file-card.tsx +54 -0
  49. package/vendor/src/components/display/index.ts +30 -0
  50. package/vendor/src/components/display/kanban.tsx +104 -0
  51. package/vendor/src/components/display/keyboard-shortcut.tsx +31 -0
  52. package/vendor/src/components/display/list.tsx +100 -0
  53. package/vendor/src/components/display/metric-grid.tsx +86 -0
  54. package/vendor/src/components/display/progress.tsx +162 -0
  55. package/vendor/src/components/display/property-grid.tsx +54 -0
  56. package/vendor/src/components/display/result.tsx +90 -0
  57. package/vendor/src/components/display/smart-card.tsx +168 -0
  58. package/vendor/src/components/display/statistic.tsx +107 -0
  59. package/vendor/src/components/display/status-legend.tsx +108 -0
  60. package/vendor/src/components/display/tag-list.tsx +52 -0
  61. package/vendor/src/components/display/timeline.tsx +132 -0
  62. package/vendor/src/components/display/tree-view.tsx +116 -0
  63. package/vendor/src/components/feedback/alert.tsx +69 -0
  64. package/vendor/src/components/feedback/empty-state.tsx +56 -0
  65. package/vendor/src/components/feedback/index.ts +5 -0
  66. package/vendor/src/components/feedback/loading-state.tsx +39 -0
  67. package/vendor/src/components/feedback/page-state.tsx +69 -0
  68. package/vendor/src/components/feedback/status-badge.tsx +62 -0
  69. package/vendor/src/components/filters/filter-bar.tsx +89 -0
  70. package/vendor/src/components/filters/filter-chips.tsx +69 -0
  71. package/vendor/src/components/filters/index.ts +2 -0
  72. package/vendor/src/components/form/form-actions.tsx +53 -0
  73. package/vendor/src/components/form/form-async-select.tsx +26 -0
  74. package/vendor/src/components/form/form-date-input.tsx +19 -0
  75. package/vendor/src/components/form/form-date-picker.tsx +54 -0
  76. package/vendor/src/components/form/form-date-range-input.tsx +79 -0
  77. package/vendor/src/components/form/form-date-range-picker.tsx +57 -0
  78. package/vendor/src/components/form/form-field-shell.tsx +191 -0
  79. package/vendor/src/components/form/form-input.tsx +480 -0
  80. package/vendor/src/components/form/form-number-input.tsx +19 -0
  81. package/vendor/src/components/form/form-password-input.tsx +19 -0
  82. package/vendor/src/components/form/form-phone-input.tsx +22 -0
  83. package/vendor/src/components/form/form-search-input.tsx +19 -0
  84. package/vendor/src/components/form/form-section.tsx +29 -0
  85. package/vendor/src/components/form/form-select.tsx +194 -0
  86. package/vendor/src/components/form/form-switch.tsx +145 -0
  87. package/vendor/src/components/form/form-textarea.tsx +103 -0
  88. package/vendor/src/components/form/index.ts +17 -0
  89. package/vendor/src/components/form/public.ts +14 -0
  90. package/vendor/src/components/form/smart-form-shell.tsx +59 -0
  91. package/vendor/src/components/inputs/async-select.tsx +1143 -0
  92. package/vendor/src/components/inputs/clearable-input.tsx +78 -0
  93. package/vendor/src/components/inputs/color-input.tsx +47 -0
  94. package/vendor/src/components/inputs/combobox.tsx +89 -0
  95. package/vendor/src/components/inputs/date-input.tsx +32 -0
  96. package/vendor/src/components/inputs/date-range-input.tsx +67 -0
  97. package/vendor/src/components/inputs/index.ts +19 -0
  98. package/vendor/src/components/inputs/input-chrome.tsx +37 -0
  99. package/vendor/src/components/inputs/input-decorator.tsx +64 -0
  100. package/vendor/src/components/inputs/input-value.ts +42 -0
  101. package/vendor/src/components/inputs/masked-input.tsx +51 -0
  102. package/vendor/src/components/inputs/money-input.tsx +73 -0
  103. package/vendor/src/components/inputs/number-input.tsx +87 -0
  104. package/vendor/src/components/inputs/numeric-value.ts +39 -0
  105. package/vendor/src/components/inputs/otp-input.tsx +102 -0
  106. package/vendor/src/components/inputs/password-input.tsx +85 -0
  107. package/vendor/src/components/inputs/phone-input.tsx +46 -0
  108. package/vendor/src/components/inputs/quantity-input.tsx +116 -0
  109. package/vendor/src/components/inputs/quantity-stepper.tsx +49 -0
  110. package/vendor/src/components/inputs/rating.tsx +98 -0
  111. package/vendor/src/components/inputs/search-input.tsx +26 -0
  112. package/vendor/src/components/inputs/simple-select.tsx +72 -0
  113. package/vendor/src/components/inputs/slider.tsx +149 -0
  114. package/vendor/src/components/inputs/tag-input.tsx +104 -0
  115. package/vendor/src/components/layout/app-header.tsx +46 -0
  116. package/vendor/src/components/layout/app-shell.tsx +243 -0
  117. package/vendor/src/components/layout/app-sidebar.tsx +179 -0
  118. package/vendor/src/components/layout/breadcrumbs.tsx +72 -0
  119. package/vendor/src/components/layout/index.ts +11 -0
  120. package/vendor/src/components/layout/page-container.tsx +30 -0
  121. package/vendor/src/components/layout/page-header.tsx +60 -0
  122. package/vendor/src/components/layout/public.ts +10 -0
  123. package/vendor/src/components/layout/section.tsx +76 -0
  124. package/vendor/src/components/layout/sidebar-nav.tsx +147 -0
  125. package/vendor/src/components/layout/stat-card.tsx +88 -0
  126. package/vendor/src/components/layout/sticky-footer-bar.tsx +23 -0
  127. package/vendor/src/components/layout/workspace-shell.tsx +50 -0
  128. package/vendor/src/components/navigation/anchor-nav.tsx +44 -0
  129. package/vendor/src/components/navigation/index.ts +4 -0
  130. package/vendor/src/components/navigation/page-tabs.tsx +67 -0
  131. package/vendor/src/components/navigation/pagination.tsx +179 -0
  132. package/vendor/src/components/navigation/stepper-tabs.tsx +67 -0
  133. package/vendor/src/components/notifications/index.ts +1 -0
  134. package/vendor/src/components/notifications/toast.tsx +259 -0
  135. package/vendor/src/components/overlay/confirm-dialog.tsx +66 -0
  136. package/vendor/src/components/overlay/dialog-actions.tsx +68 -0
  137. package/vendor/src/components/overlay/index.ts +4 -0
  138. package/vendor/src/components/overlay/modal-shell.tsx +93 -0
  139. package/vendor/src/components/overlay/sheet-shell.tsx +212 -0
  140. package/vendor/src/components/patterns/action-system.tsx +116 -0
  141. package/vendor/src/components/patterns/crud-system.tsx +53 -0
  142. package/vendor/src/components/patterns/data-view.tsx +84 -0
  143. package/vendor/src/components/patterns/entity-details.tsx +66 -0
  144. package/vendor/src/components/patterns/filter-builder.tsx +113 -0
  145. package/vendor/src/components/patterns/form-builder-presets.ts +131 -0
  146. package/vendor/src/components/patterns/form-builder.tsx +334 -0
  147. package/vendor/src/components/patterns/index.ts +12 -0
  148. package/vendor/src/components/patterns/public.ts +4 -0
  149. package/vendor/src/components/patterns/resource-detail-page.tsx +160 -0
  150. package/vendor/src/components/patterns/resource-page.tsx +159 -0
  151. package/vendor/src/components/patterns/resource-system.tsx +61 -0
  152. package/vendor/src/components/patterns/settings-section.tsx +46 -0
  153. package/vendor/src/components/patterns/status-system.tsx +89 -0
  154. package/vendor/src/components/theme-provider.tsx +51 -0
  155. package/vendor/src/components/ui/badge.tsx +52 -0
  156. package/vendor/src/components/ui/button.tsx +61 -0
  157. package/vendor/src/components/ui/card.tsx +103 -0
  158. package/vendor/src/components/ui/checkbox.tsx +82 -0
  159. package/vendor/src/components/ui/collapse.tsx +126 -0
  160. package/vendor/src/components/ui/command.tsx +194 -0
  161. package/vendor/src/components/ui/dialog.tsx +160 -0
  162. package/vendor/src/components/ui/divider.tsx +46 -0
  163. package/vendor/src/components/ui/dropdown-menu.tsx +266 -0
  164. package/vendor/src/components/ui/input-group.tsx +158 -0
  165. package/vendor/src/components/ui/input.tsx +20 -0
  166. package/vendor/src/components/ui/popover.tsx +90 -0
  167. package/vendor/src/components/ui/segmented-control.tsx +78 -0
  168. package/vendor/src/components/ui/select.tsx +201 -0
  169. package/vendor/src/components/ui/skeleton.tsx +75 -0
  170. package/vendor/src/components/ui/spinner.tsx +50 -0
  171. package/vendor/src/components/ui/switch.tsx +71 -0
  172. package/vendor/src/components/ui/table.tsx +114 -0
  173. package/vendor/src/components/ui/tabs.tsx +55 -0
  174. package/vendor/src/components/ui/textarea.tsx +18 -0
  175. package/vendor/src/components/ui/tooltip.tsx +38 -0
  176. package/vendor/src/components/upload/file-upload.tsx +483 -0
  177. package/vendor/src/components/upload/image-upload.tsx +118 -0
  178. package/vendor/src/components/upload/index.ts +2 -0
  179. package/vendor/src/components/wizard/index.ts +2 -0
  180. package/vendor/src/components/wizard/stepper.tsx +53 -0
  181. package/vendor/src/components/wizard/wizard.tsx +60 -0
  182. package/vendor/src/families/card-family.ts +28 -0
  183. package/vendor/src/families/catalog.ts +96 -0
  184. package/vendor/src/families/data-table-family.ts +31 -0
  185. package/vendor/src/families/docs-adoption.ts +103 -0
  186. package/vendor/src/families/docs-groups.ts +209 -0
  187. package/vendor/src/families/docs-queries.ts +84 -0
  188. package/vendor/src/families/docs-routing.ts +89 -0
  189. package/vendor/src/families/form-family.ts +45 -0
  190. package/vendor/src/families/index.ts +17 -0
  191. package/vendor/src/families/input-family.ts +61 -0
  192. package/vendor/src/families/member-metadata.ts +466 -0
  193. package/vendor/src/families/member-queries.ts +28 -0
  194. package/vendor/src/families/member-snippet-queries.ts +54 -0
  195. package/vendor/src/families/member-snippets.ts +673 -0
  196. package/vendor/src/families/migration-map.ts +79 -0
  197. package/vendor/src/families/queries.ts +63 -0
  198. package/vendor/src/families/select-family.ts +33 -0
  199. package/vendor/src/families/views.ts +81 -0
  200. package/vendor/src/hooks/index.ts +6 -0
  201. package/vendor/src/hooks/use-before-unload-when-dirty.ts +21 -0
  202. package/vendor/src/hooks/use-data-table-view-state.ts +122 -0
  203. package/vendor/src/hooks/use-debounce.ts +52 -0
  204. package/vendor/src/hooks/use-disclosure.ts +38 -0
  205. package/vendor/src/hooks/use-is-mobile.ts +28 -0
  206. package/vendor/src/hooks/use-session-storage-state.ts +85 -0
  207. package/vendor/src/index.ts +38 -0
  208. package/vendor/src/lib/utils.ts +6 -0
  209. package/vendor/templates/components/button.tsx +0 -0
  210. package/vendor/templates/components/data-table.tsx +0 -0
  211. package/vendor/templates/components/input.tsx +0 -0
  212. package/vendor/templates/lib/utils.ts +0 -0
  213. package/vendor/templates/styles/globals.css +0 -0
@@ -0,0 +1,48 @@
1
+ import type { Row } from "@tanstack/react-table"
2
+
3
+ import {
4
+ ActionMenu,
5
+ type ActionMenuItem,
6
+ type ActionMenuProps,
7
+ } from "@/components/actions/action-menu"
8
+
9
+ export type DataTableRowAction<TData> = Omit<ActionMenuItem, "onSelect"> & {
10
+ onSelect?: (row: Row<TData>, original: TData) => void | Promise<void>
11
+ }
12
+
13
+ export type DataTableRowActionsProps<TData> = Omit<ActionMenuProps, "actions"> & {
14
+ row: Row<TData>
15
+ actions?: DataTableRowAction<TData>[]
16
+ getActions?: (row: Row<TData>, original: TData) => DataTableRowAction<TData>[]
17
+ }
18
+
19
+ function resolveRowActions<TData>(
20
+ row: Row<TData>,
21
+ actions?: DataTableRowAction<TData>[],
22
+ getActions?: (row: Row<TData>, original: TData) => DataTableRowAction<TData>[]
23
+ ): ActionMenuItem[] {
24
+ const resolvedActions = getActions?.(row, row.original) ?? actions ?? []
25
+
26
+ return resolvedActions.map((action) => ({
27
+ ...action,
28
+ onSelect: action.onSelect
29
+ ? () => action.onSelect?.(row, row.original)
30
+ : undefined,
31
+ }))
32
+ }
33
+
34
+ function DataTableRowActions<TData>({
35
+ row,
36
+ actions,
37
+ getActions,
38
+ ...props
39
+ }: DataTableRowActionsProps<TData>) {
40
+ return (
41
+ <ActionMenu
42
+ actions={resolveRowActions(row, actions, getActions)}
43
+ {...props}
44
+ />
45
+ )
46
+ }
47
+
48
+ export { DataTableRowActions, resolveRowActions }
@@ -0,0 +1,59 @@
1
+ import type { ColumnDef } from "@tanstack/react-table"
2
+
3
+ import { Checkbox } from "@/components/ui/checkbox"
4
+ import { cn } from "@/lib/utils"
5
+
6
+ export type DataTableSelectColumnOptions<TData> = {
7
+ id?: string
8
+ size?: number
9
+ headerClassName?: string
10
+ cellClassName?: string
11
+ ariaLabel?: {
12
+ selectAll?: string
13
+ selectRow?: (row: TData) => string
14
+ }
15
+ }
16
+
17
+ function createDataTableSelectColumn<TData>({
18
+ id = "select",
19
+ size = 40,
20
+ headerClassName,
21
+ cellClassName,
22
+ ariaLabel,
23
+ }: DataTableSelectColumnOptions<TData> = {}): ColumnDef<TData> {
24
+ return {
25
+ id,
26
+ size,
27
+ enableSorting: false,
28
+ enableHiding: false,
29
+ header: ({ table }) => (
30
+ <div className={cn("flex items-center justify-center", headerClassName)}>
31
+ <Checkbox
32
+ checked={
33
+ table.getIsAllPageRowsSelected()
34
+ ? true
35
+ : table.getIsSomePageRowsSelected()
36
+ ? "indeterminate"
37
+ : false
38
+ }
39
+ aria-label={ariaLabel?.selectAll ?? "Select all rows"}
40
+ onClick={(event) => event.stopPropagation()}
41
+ onCheckedChange={(checked) => table.toggleAllPageRowsSelected(checked)}
42
+ />
43
+ </div>
44
+ ),
45
+ cell: ({ row }) => (
46
+ <div className={cn("flex items-center justify-center", cellClassName)}>
47
+ <Checkbox
48
+ checked={row.getIsSelected()}
49
+ disabled={!row.getCanSelect()}
50
+ aria-label={ariaLabel?.selectRow?.(row.original) ?? "Select row"}
51
+ onClick={(event) => event.stopPropagation()}
52
+ onCheckedChange={(checked) => row.toggleSelected(checked)}
53
+ />
54
+ </div>
55
+ ),
56
+ }
57
+ }
58
+
59
+ export { createDataTableSelectColumn }
@@ -0,0 +1,45 @@
1
+ import * as React from "react"
2
+ import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon } from "lucide-react"
3
+ import type { Column } from "@tanstack/react-table"
4
+
5
+ import { Button } from "@/components/ui/button"
6
+ import { cn } from "@/lib/utils"
7
+
8
+ export type DataTableSortableHeaderProps<TData, TValue> = React.ComponentProps<"div"> & {
9
+ column: Column<TData, TValue>
10
+ children?: React.ReactNode
11
+ label?: React.ReactNode
12
+ disabled?: boolean
13
+ buttonClassName?: string
14
+ }
15
+
16
+ function DataTableSortableHeader<TData, TValue>({
17
+ className,
18
+ column,
19
+ children,
20
+ label,
21
+ disabled,
22
+ buttonClassName,
23
+ ...props
24
+ }: DataTableSortableHeaderProps<TData, TValue>) {
25
+ const sorted = column.getIsSorted()
26
+ const Icon = sorted === "asc" ? ArrowUpIcon : sorted === "desc" ? ArrowDownIcon : ArrowUpDownIcon
27
+
28
+ return (
29
+ <div className={cn("flex items-center", className)} {...props}>
30
+ <Button
31
+ type="button"
32
+ variant="ghost"
33
+ size="sm"
34
+ className={cn("-ml-2 h-8 px-2 font-medium", buttonClassName)}
35
+ disabled={disabled || !column.getCanSort()}
36
+ onClick={() => column.toggleSorting(sorted === "asc")}
37
+ >
38
+ <span>{children ?? label}</span>
39
+ <Icon className="ml-1 size-3.5" />
40
+ </Button>
41
+ </div>
42
+ )
43
+ }
44
+
45
+ export { DataTableSortableHeader }
@@ -0,0 +1,76 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ export type DataTableToolbarProps = React.ComponentProps<"div"> & {
6
+ title?: React.ReactNode
7
+ description?: React.ReactNode
8
+ search?: React.ReactNode
9
+ filters?: React.ReactNode
10
+ actions?: React.ReactNode
11
+ selectionActions?: React.ReactNode
12
+ selectedCount?: number
13
+ totalCount?: number
14
+ selectedLabel?: (selectedCount: number, totalCount?: number) => React.ReactNode
15
+ }
16
+
17
+ function DataTableToolbar({
18
+ className,
19
+ title,
20
+ description,
21
+ search,
22
+ filters,
23
+ actions,
24
+ selectionActions,
25
+ selectedCount = 0,
26
+ totalCount,
27
+ selectedLabel = (selected, total) =>
28
+ total === undefined ? `${selected} selected` : `${selected} of ${total} selected`,
29
+ children,
30
+ ...props
31
+ }: DataTableToolbarProps) {
32
+ const hasHeading = Boolean(title || description)
33
+ const hasSelection = selectedCount > 0 && Boolean(selectionActions)
34
+
35
+ return (
36
+ <div
37
+ data-slot="data-table-toolbar"
38
+ className={cn("flex flex-col gap-4 rounded-[var(--radius-2xl)] p-4 md:p-5", className)}
39
+ {...props}
40
+ >
41
+ {(hasHeading || actions) && (
42
+ <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
43
+ {hasHeading && (
44
+ <div className="grid gap-1">
45
+ {title && <h2 className="text-lg font-semibold tracking-tight text-foreground">{title}</h2>}
46
+ {description && <p className="text-sm leading-6 text-muted-foreground">{description}</p>}
47
+ </div>
48
+ )}
49
+
50
+ {actions && <div className="flex shrink-0 flex-wrap items-center gap-2">{actions}</div>}
51
+ </div>
52
+ )}
53
+
54
+ {(search || filters || hasSelection || children) && (
55
+ <div className="flex flex-col gap-2 lg:flex-row lg:items-center lg:justify-between">
56
+ <div className="flex min-w-0 flex-1 flex-col gap-2 sm:flex-row sm:items-center">
57
+ {search}
58
+ {filters}
59
+ {children}
60
+ </div>
61
+
62
+ {hasSelection && (
63
+ <div className="flex shrink-0 items-center gap-2 rounded-full border border-border/70 bg-background/88 px-2.5 py-1.5 text-sm shadow-sm backdrop-blur">
64
+ <span className="text-muted-foreground">
65
+ {selectedLabel(selectedCount, totalCount)}
66
+ </span>
67
+ {selectionActions}
68
+ </div>
69
+ )}
70
+ </div>
71
+ )}
72
+ </div>
73
+ )
74
+ }
75
+
76
+ export { DataTableToolbar }
@@ -0,0 +1,128 @@
1
+ import * as React from "react"
2
+
3
+ import { Button } from "@/components/ui/button"
4
+ import { Badge } from "@/components/ui/badge"
5
+ import { cn } from "@/lib/utils"
6
+
7
+ export type DataTableViewPreset<TValue extends string = string> = {
8
+ value: TValue
9
+ label: React.ReactNode
10
+ description?: React.ReactNode
11
+ icon?: React.ReactNode
12
+ count?: React.ReactNode
13
+ disabled?: boolean
14
+ hidden?: boolean
15
+ }
16
+
17
+ export type DataTableViewPresetsProps<TValue extends string = string> = Omit<React.ComponentProps<"div">, "onChange"> & {
18
+ value?: TValue
19
+ presets: DataTableViewPreset<TValue>[]
20
+ onValueChange?: (value: TValue | undefined, preset?: DataTableViewPreset<TValue>) => void
21
+ clearable?: boolean
22
+ clearLabel?: React.ReactNode
23
+ emptyLabel?: React.ReactNode
24
+ size?: "xs" | "sm" | "default"
25
+ variant?: "tabs" | "buttons" | "pills"
26
+ renderPreset?: (preset: DataTableViewPreset<TValue>, state: { active: boolean }) => React.ReactNode
27
+ presetClassName?: string
28
+ activePresetClassName?: string
29
+ }
30
+
31
+ const sizeClassName: Record<NonNullable<DataTableViewPresetsProps["size"]>, string> = {
32
+ xs: "h-7 px-2 text-xs",
33
+ sm: "h-8 px-3 text-sm",
34
+ default: "h-9 px-3 text-sm",
35
+ }
36
+
37
+ function DataTableViewPresets<TValue extends string = string>({
38
+ className,
39
+ value,
40
+ presets,
41
+ onValueChange,
42
+ clearable = true,
43
+ clearLabel = "Clear",
44
+ emptyLabel = "No views",
45
+ size = "sm",
46
+ variant = "pills",
47
+ renderPreset,
48
+ presetClassName,
49
+ activePresetClassName,
50
+ ...props
51
+ }: DataTableViewPresetsProps<TValue>) {
52
+ const visiblePresets = presets.filter((preset) => !preset.hidden)
53
+ const activePreset = visiblePresets.find((preset) => preset.value === value)
54
+ const canClear = clearable && Boolean(value)
55
+
56
+ if (visiblePresets.length === 0) {
57
+ return (
58
+ <div data-slot="data-table-view-presets-empty" className={cn("text-sm text-muted-foreground", className)} {...props}>
59
+ {emptyLabel}
60
+ </div>
61
+ )
62
+ }
63
+
64
+ return (
65
+ <div
66
+ data-slot="data-table-view-presets"
67
+ data-variant={variant}
68
+ className={cn(
69
+ "flex min-w-0 flex-wrap items-center gap-2 rounded-[var(--radius-xl)] border border-border/70 bg-background/88 p-2 shadow-sm backdrop-blur",
70
+ className
71
+ )}
72
+ {...props}
73
+ >
74
+ {visiblePresets.map((preset) => {
75
+ const active = preset.value === value
76
+
77
+ return (
78
+ <Button
79
+ key={preset.value}
80
+ type="button"
81
+ variant={active ? "default" : variant === "tabs" ? "ghost" : "outline"}
82
+ size={size === "default" ? "sm" : size}
83
+ disabled={preset.disabled}
84
+ data-active={active || undefined}
85
+ className={cn(
86
+ "min-w-0 gap-1.5 rounded-full shadow-none",
87
+ sizeClassName[size],
88
+ variant === "tabs" && "rounded-[var(--radius-lg)] border border-transparent bg-transparent data-[active=true]:border-border data-[active=true]:bg-background",
89
+ variant === "buttons" && "rounded-[var(--radius-lg)]",
90
+ !active && "border-border/70 bg-transparent hover:border-border hover:bg-accent/60",
91
+ presetClassName,
92
+ active && "shadow-sm",
93
+ active && activePresetClassName
94
+ )}
95
+ title={typeof preset.description === "string" ? preset.description : undefined}
96
+ onClick={() => onValueChange?.(preset.value, preset)}
97
+ >
98
+ {renderPreset?.(preset, { active }) ?? (
99
+ <>
100
+ {preset.icon && <span className="shrink-0 [&_svg]:size-3.5">{preset.icon}</span>}
101
+ <span className="truncate">{preset.label}</span>
102
+ {preset.count !== undefined && (
103
+ <Badge variant={active ? "secondary" : "outline"} className="h-5 px-1.5 text-[10px]">
104
+ {preset.count}
105
+ </Badge>
106
+ )}
107
+ </>
108
+ )}
109
+ </Button>
110
+ )
111
+ })}
112
+
113
+ {canClear && (
114
+ <Button
115
+ type="button"
116
+ variant="ghost"
117
+ size={size === "default" ? "sm" : size}
118
+ className="rounded-full"
119
+ onClick={() => onValueChange?.(undefined, activePreset)}
120
+ >
121
+ {clearLabel}
122
+ </Button>
123
+ )}
124
+ </div>
125
+ )
126
+ }
127
+
128
+ export { DataTableViewPresets }