@afurgeri/crud-vue 0.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.
Files changed (95) hide show
  1. package/package.json +46 -0
  2. package/src/__test__/CrudCards.test.ts +118 -0
  3. package/src/__test__/CrudEmptyState.test.ts +82 -0
  4. package/src/__test__/CrudForm.test.ts +101 -0
  5. package/src/__test__/CrudShow.test.ts +135 -0
  6. package/src/__test__/CrudTable.test.ts +111 -0
  7. package/src/__test__/CrudToolbar.test.ts +102 -0
  8. package/src/__test__/setup.ts +43 -0
  9. package/src/__test__/useCrud.test.ts +349 -0
  10. package/src/components/CrudCards.vue +105 -0
  11. package/src/components/CrudDeleteDialog.vue +80 -0
  12. package/src/components/CrudEmptyState.vue +58 -0
  13. package/src/components/CrudFilters.vue +194 -0
  14. package/src/components/CrudForm.vue +232 -0
  15. package/src/components/CrudPage.vue +206 -0
  16. package/src/components/CrudPagination.vue +130 -0
  17. package/src/components/CrudSearch.vue +42 -0
  18. package/src/components/CrudShow.vue +216 -0
  19. package/src/components/CrudTable.vue +146 -0
  20. package/src/components/CrudToolbar.vue +86 -0
  21. package/src/components/InputError.vue +13 -0
  22. package/src/components/ui/button/Button.vue +27 -0
  23. package/src/components/ui/button/index.ts +36 -0
  24. package/src/components/ui/card/Card.vue +22 -0
  25. package/src/components/ui/card/CardAction.vue +17 -0
  26. package/src/components/ui/card/CardContent.vue +17 -0
  27. package/src/components/ui/card/CardDescription.vue +17 -0
  28. package/src/components/ui/card/CardFooter.vue +17 -0
  29. package/src/components/ui/card/CardHeader.vue +17 -0
  30. package/src/components/ui/card/CardTitle.vue +17 -0
  31. package/src/components/ui/card/index.ts +7 -0
  32. package/src/components/ui/checkbox/Checkbox.vue +37 -0
  33. package/src/components/ui/checkbox/index.ts +1 -0
  34. package/src/components/ui/combobox/ComboboxInput.vue +83 -0
  35. package/src/components/ui/combobox/index.ts +1 -0
  36. package/src/components/ui/dialog/Dialog.vue +17 -0
  37. package/src/components/ui/dialog/DialogClose.vue +14 -0
  38. package/src/components/ui/dialog/DialogContent.vue +49 -0
  39. package/src/components/ui/dialog/DialogDescription.vue +25 -0
  40. package/src/components/ui/dialog/DialogFooter.vue +15 -0
  41. package/src/components/ui/dialog/DialogHeader.vue +17 -0
  42. package/src/components/ui/dialog/DialogOverlay.vue +23 -0
  43. package/src/components/ui/dialog/DialogScrollContent.vue +59 -0
  44. package/src/components/ui/dialog/DialogTitle.vue +25 -0
  45. package/src/components/ui/dialog/DialogTrigger.vue +14 -0
  46. package/src/components/ui/dialog/index.ts +10 -0
  47. package/src/components/ui/dropdown-menu/DropdownMenu.vue +17 -0
  48. package/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +41 -0
  49. package/src/components/ui/dropdown-menu/DropdownMenuContent.vue +39 -0
  50. package/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +14 -0
  51. package/src/components/ui/dropdown-menu/DropdownMenuItem.vue +30 -0
  52. package/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +22 -0
  53. package/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +22 -0
  54. package/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +42 -0
  55. package/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +26 -0
  56. package/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +17 -0
  57. package/src/components/ui/dropdown-menu/DropdownMenuSub.vue +19 -0
  58. package/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +31 -0
  59. package/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +30 -0
  60. package/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +16 -0
  61. package/src/components/ui/dropdown-menu/index.ts +16 -0
  62. package/src/components/ui/input/Input.vue +33 -0
  63. package/src/components/ui/input/index.ts +1 -0
  64. package/src/components/ui/label/Label.vue +28 -0
  65. package/src/components/ui/label/index.ts +1 -0
  66. package/src/components/ui/select/Select.vue +15 -0
  67. package/src/components/ui/select/SelectContent.vue +49 -0
  68. package/src/components/ui/select/SelectGroup.vue +17 -0
  69. package/src/components/ui/select/SelectItem.vue +41 -0
  70. package/src/components/ui/select/SelectItemText.vue +12 -0
  71. package/src/components/ui/select/SelectLabel.vue +14 -0
  72. package/src/components/ui/select/SelectScrollDownButton.vue +22 -0
  73. package/src/components/ui/select/SelectScrollUpButton.vue +22 -0
  74. package/src/components/ui/select/SelectSeparator.vue +15 -0
  75. package/src/components/ui/select/SelectTrigger.vue +29 -0
  76. package/src/components/ui/select/SelectValue.vue +12 -0
  77. package/src/components/ui/select/index.ts +11 -0
  78. package/src/components/ui/separator/Separator.vue +28 -0
  79. package/src/components/ui/separator/index.ts +1 -0
  80. package/src/components/ui/spinner/Spinner.vue +17 -0
  81. package/src/components/ui/spinner/index.ts +1 -0
  82. package/src/components/ui/table/Table.vue +16 -0
  83. package/src/components/ui/table/TableBody.vue +14 -0
  84. package/src/components/ui/table/TableCaption.vue +14 -0
  85. package/src/components/ui/table/TableCell.vue +21 -0
  86. package/src/components/ui/table/TableEmpty.vue +34 -0
  87. package/src/components/ui/table/TableFooter.vue +14 -0
  88. package/src/components/ui/table/TableHead.vue +14 -0
  89. package/src/components/ui/table/TableHeader.vue +14 -0
  90. package/src/components/ui/table/TableRow.vue +14 -0
  91. package/src/components/ui/table/index.ts +9 -0
  92. package/src/composables/useCrud.ts +328 -0
  93. package/src/index.ts +33 -0
  94. package/src/lib/utils.ts +18 -0
  95. package/src/types/crud.ts +133 -0
@@ -0,0 +1 @@
1
+ export { default as Label } from './Label.vue'
@@ -0,0 +1,15 @@
1
+ <script setup lang="ts">
2
+ import type { SelectRootEmits, SelectRootProps } from "reka-ui"
3
+ import { SelectRoot, useForwardPropsEmits } from "reka-ui"
4
+
5
+ const props = defineProps<SelectRootProps>()
6
+ const emits = defineEmits<SelectRootEmits>()
7
+
8
+ const forwarded = useForwardPropsEmits(props, emits)
9
+ </script>
10
+
11
+ <template>
12
+ <SelectRoot v-bind="forwarded">
13
+ <slot />
14
+ </SelectRoot>
15
+ </template>
@@ -0,0 +1,49 @@
1
+ <script setup lang="ts">
2
+ import type { SelectContentEmits, SelectContentProps } from "reka-ui"
3
+ import type { HTMLAttributes } from "vue"
4
+ import { reactiveOmit } from "@vueuse/core"
5
+ import {
6
+ SelectContent,
7
+ SelectPortal,
8
+ SelectViewport,
9
+ useForwardPropsEmits,
10
+ } from "reka-ui"
11
+ import { cn } from "../../../lib/utils"
12
+ import { SelectScrollDownButton, SelectScrollUpButton } from "."
13
+
14
+ defineOptions({
15
+ inheritAttrs: false,
16
+ })
17
+
18
+ const props = withDefaults(
19
+ defineProps<SelectContentProps & { class?: HTMLAttributes["class"] }>(),
20
+ {
21
+ position: "popper",
22
+ },
23
+ )
24
+ const emits = defineEmits<SelectContentEmits>()
25
+
26
+ const delegatedProps = reactiveOmit(props, "class")
27
+
28
+ const forwarded = useForwardPropsEmits(delegatedProps, emits)
29
+ </script>
30
+
31
+ <template>
32
+ <SelectPortal>
33
+ <SelectContent
34
+ v-bind="{ ...forwarded, ...$attrs }" :class="cn(
35
+ 'relative z-50 max-h-96 min-w-32 overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
36
+ position === 'popper'
37
+ && 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
38
+ props.class,
39
+ )
40
+ "
41
+ >
42
+ <SelectScrollUpButton />
43
+ <SelectViewport :class="cn('p-1', position === 'popper' && 'h-[--reka-select-trigger-height] w-full min-w-[--reka-select-trigger-width]')">
44
+ <slot />
45
+ </SelectViewport>
46
+ <SelectScrollDownButton />
47
+ </SelectContent>
48
+ </SelectPortal>
49
+ </template>
@@ -0,0 +1,17 @@
1
+ <script setup lang="ts">
2
+ import type { SelectGroupProps } from "reka-ui"
3
+ import type { HTMLAttributes } from "vue"
4
+ import { reactiveOmit } from "@vueuse/core"
5
+ import { SelectGroup } from "reka-ui"
6
+ import { cn } from "../../../lib/utils"
7
+
8
+ const props = defineProps<SelectGroupProps & { class?: HTMLAttributes["class"] }>()
9
+
10
+ const delegatedProps = reactiveOmit(props, "class")
11
+ </script>
12
+
13
+ <template>
14
+ <SelectGroup :class="cn('p-1 w-full', props.class)" v-bind="delegatedProps">
15
+ <slot />
16
+ </SelectGroup>
17
+ </template>
@@ -0,0 +1,41 @@
1
+ <script setup lang="ts">
2
+ import type { SelectItemProps } from "reka-ui"
3
+ import type { HTMLAttributes } from "vue"
4
+ import { reactiveOmit } from "@vueuse/core"
5
+ import { Check } from "lucide-vue-next"
6
+ import {
7
+ SelectItem,
8
+ SelectItemIndicator,
9
+ SelectItemText,
10
+ useForwardProps,
11
+ } from "reka-ui"
12
+ import { cn } from "../../../lib/utils"
13
+
14
+ const props = defineProps<SelectItemProps & { class?: HTMLAttributes["class"] }>()
15
+
16
+ const delegatedProps = reactiveOmit(props, "class")
17
+
18
+ const forwardedProps = useForwardProps(delegatedProps)
19
+ </script>
20
+
21
+ <template>
22
+ <SelectItem
23
+ v-bind="forwardedProps"
24
+ :class="
25
+ cn(
26
+ 'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
27
+ props.class,
28
+ )
29
+ "
30
+ >
31
+ <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
32
+ <SelectItemIndicator>
33
+ <Check class="h-4 w-4" />
34
+ </SelectItemIndicator>
35
+ </span>
36
+
37
+ <SelectItemText>
38
+ <slot />
39
+ </SelectItemText>
40
+ </SelectItem>
41
+ </template>
@@ -0,0 +1,12 @@
1
+ <script setup lang="ts">
2
+ import type { SelectItemTextProps } from "reka-ui"
3
+ import { SelectItemText } from "reka-ui"
4
+
5
+ const props = defineProps<SelectItemTextProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <SelectItemText v-bind="props">
10
+ <slot />
11
+ </SelectItemText>
12
+ </template>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ import type { SelectLabelProps } from "reka-ui"
3
+ import type { HTMLAttributes } from "vue"
4
+ import { SelectLabel } from "reka-ui"
5
+ import { cn } from "../../../lib/utils"
6
+
7
+ const props = defineProps<SelectLabelProps & { class?: HTMLAttributes["class"] }>()
8
+ </script>
9
+
10
+ <template>
11
+ <SelectLabel :class="cn('py-1.5 pl-8 pr-2 text-sm font-semibold', props.class)">
12
+ <slot />
13
+ </SelectLabel>
14
+ </template>
@@ -0,0 +1,22 @@
1
+ <script setup lang="ts">
2
+ import type { SelectScrollDownButtonProps } from "reka-ui"
3
+ import type { HTMLAttributes } from "vue"
4
+ import { reactiveOmit } from "@vueuse/core"
5
+ import { ChevronDown } from "lucide-vue-next"
6
+ import { SelectScrollDownButton, useForwardProps } from "reka-ui"
7
+ import { cn } from "../../../lib/utils"
8
+
9
+ const props = defineProps<SelectScrollDownButtonProps & { class?: HTMLAttributes["class"] }>()
10
+
11
+ const delegatedProps = reactiveOmit(props, "class")
12
+
13
+ const forwardedProps = useForwardProps(delegatedProps)
14
+ </script>
15
+
16
+ <template>
17
+ <SelectScrollDownButton v-bind="forwardedProps" :class="cn('flex cursor-default items-center justify-center py-1', props.class)">
18
+ <slot>
19
+ <ChevronDown class="h-4 w-4" />
20
+ </slot>
21
+ </SelectScrollDownButton>
22
+ </template>
@@ -0,0 +1,22 @@
1
+ <script setup lang="ts">
2
+ import type { SelectScrollUpButtonProps } from "reka-ui"
3
+ import type { HTMLAttributes } from "vue"
4
+ import { reactiveOmit } from "@vueuse/core"
5
+ import { ChevronUp } from "lucide-vue-next"
6
+ import { SelectScrollUpButton, useForwardProps } from "reka-ui"
7
+ import { cn } from "../../../lib/utils"
8
+
9
+ const props = defineProps<SelectScrollUpButtonProps & { class?: HTMLAttributes["class"] }>()
10
+
11
+ const delegatedProps = reactiveOmit(props, "class")
12
+
13
+ const forwardedProps = useForwardProps(delegatedProps)
14
+ </script>
15
+
16
+ <template>
17
+ <SelectScrollUpButton v-bind="forwardedProps" :class="cn('flex cursor-default items-center justify-center py-1', props.class)">
18
+ <slot>
19
+ <ChevronUp class="h-4 w-4" />
20
+ </slot>
21
+ </SelectScrollUpButton>
22
+ </template>
@@ -0,0 +1,15 @@
1
+ <script setup lang="ts">
2
+ import type { SelectSeparatorProps } from "reka-ui"
3
+ import type { HTMLAttributes } from "vue"
4
+ import { reactiveOmit } from "@vueuse/core"
5
+ import { SelectSeparator } from "reka-ui"
6
+ import { cn } from "../../../lib/utils"
7
+
8
+ const props = defineProps<SelectSeparatorProps & { class?: HTMLAttributes["class"] }>()
9
+
10
+ const delegatedProps = reactiveOmit(props, "class")
11
+ </script>
12
+
13
+ <template>
14
+ <SelectSeparator v-bind="delegatedProps" :class="cn('-mx-1 my-1 h-px bg-muted', props.class)" />
15
+ </template>
@@ -0,0 +1,29 @@
1
+ <script setup lang="ts">
2
+ import type { SelectTriggerProps } from "reka-ui"
3
+ import type { HTMLAttributes } from "vue"
4
+ import { reactiveOmit } from "@vueuse/core"
5
+ import { ChevronDown } from "lucide-vue-next"
6
+ import { SelectIcon, SelectTrigger, useForwardProps } from "reka-ui"
7
+ import { cn } from "../../../lib/utils"
8
+
9
+ const props = defineProps<SelectTriggerProps & { class?: HTMLAttributes["class"] }>()
10
+
11
+ const delegatedProps = reactiveOmit(props, "class")
12
+
13
+ const forwardedProps = useForwardProps(delegatedProps)
14
+ </script>
15
+
16
+ <template>
17
+ <SelectTrigger
18
+ v-bind="forwardedProps"
19
+ :class="cn(
20
+ 'flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:truncate text-start',
21
+ props.class,
22
+ )"
23
+ >
24
+ <slot />
25
+ <SelectIcon as-child>
26
+ <ChevronDown class="w-4 h-4 opacity-50 shrink-0" />
27
+ </SelectIcon>
28
+ </SelectTrigger>
29
+ </template>
@@ -0,0 +1,12 @@
1
+ <script setup lang="ts">
2
+ import type { SelectValueProps } from "reka-ui"
3
+ import { SelectValue } from "reka-ui"
4
+
5
+ const props = defineProps<SelectValueProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <SelectValue v-bind="props">
10
+ <slot />
11
+ </SelectValue>
12
+ </template>
@@ -0,0 +1,11 @@
1
+ export { default as Select } from "./Select.vue"
2
+ export { default as SelectContent } from "./SelectContent.vue"
3
+ export { default as SelectGroup } from "./SelectGroup.vue"
4
+ export { default as SelectItem } from "./SelectItem.vue"
5
+ export { default as SelectItemText } from "./SelectItemText.vue"
6
+ export { default as SelectLabel } from "./SelectLabel.vue"
7
+ export { default as SelectScrollDownButton } from "./SelectScrollDownButton.vue"
8
+ export { default as SelectScrollUpButton } from "./SelectScrollUpButton.vue"
9
+ export { default as SelectSeparator } from "./SelectSeparator.vue"
10
+ export { default as SelectTrigger } from "./SelectTrigger.vue"
11
+ export { default as SelectValue } from "./SelectValue.vue"
@@ -0,0 +1,28 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from 'vue'
3
+ import { cn } from '../../../lib/utils'
4
+ import { reactiveOmit } from '@vueuse/core'
5
+ import { Separator, type SeparatorProps } from 'reka-ui'
6
+
7
+ const props = withDefaults(defineProps<
8
+ SeparatorProps & { class?: HTMLAttributes['class'] }
9
+ >(), {
10
+ orientation: 'horizontal',
11
+ decorative: true,
12
+ })
13
+
14
+ const delegatedProps = reactiveOmit(props, 'class')
15
+ </script>
16
+
17
+ <template>
18
+ <Separator
19
+ data-slot="separator-root"
20
+ v-bind="delegatedProps"
21
+ :class="
22
+ cn(
23
+ `bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px`,
24
+ props.class,
25
+ )
26
+ "
27
+ />
28
+ </template>
@@ -0,0 +1 @@
1
+ export { default as Separator } from './Separator.vue'
@@ -0,0 +1,17 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from "vue"
3
+ import { Loader2Icon } from "lucide-vue-next"
4
+ import { cn } from "../../../lib/utils"
5
+
6
+ const props = defineProps<{
7
+ class?: HTMLAttributes["class"]
8
+ }>()
9
+ </script>
10
+
11
+ <template>
12
+ <Loader2Icon
13
+ role="status"
14
+ aria-label="Loading"
15
+ :class="cn('size-4 animate-spin', props.class)"
16
+ />
17
+ </template>
@@ -0,0 +1 @@
1
+ export { default as Spinner } from "./Spinner.vue"
@@ -0,0 +1,16 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from "vue"
3
+ import { cn } from "../../../lib/utils"
4
+
5
+ const props = defineProps<{
6
+ class?: HTMLAttributes["class"]
7
+ }>()
8
+ </script>
9
+
10
+ <template>
11
+ <div class="relative w-full overflow-auto">
12
+ <table :class="cn('w-full caption-bottom text-sm', props.class)">
13
+ <slot />
14
+ </table>
15
+ </div>
16
+ </template>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from "vue"
3
+ import { cn } from "../../../lib/utils"
4
+
5
+ const props = defineProps<{
6
+ class?: HTMLAttributes["class"]
7
+ }>()
8
+ </script>
9
+
10
+ <template>
11
+ <tbody :class="cn('[&_tr:last-child]:border-0', props.class)">
12
+ <slot />
13
+ </tbody>
14
+ </template>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from "vue"
3
+ import { cn } from "../../../lib/utils"
4
+
5
+ const props = defineProps<{
6
+ class?: HTMLAttributes["class"]
7
+ }>()
8
+ </script>
9
+
10
+ <template>
11
+ <caption :class="cn('mt-4 text-sm text-muted-foreground', props.class)">
12
+ <slot />
13
+ </caption>
14
+ </template>
@@ -0,0 +1,21 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from "vue"
3
+ import { cn } from "../../../lib/utils"
4
+
5
+ const props = defineProps<{
6
+ class?: HTMLAttributes["class"]
7
+ }>()
8
+ </script>
9
+
10
+ <template>
11
+ <td
12
+ :class="
13
+ cn(
14
+ 'p-4 align-middle [&:has([role=checkbox])]:pr-0',
15
+ props.class,
16
+ )
17
+ "
18
+ >
19
+ <slot />
20
+ </td>
21
+ </template>
@@ -0,0 +1,34 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from "vue"
3
+ import { reactiveOmit } from "@vueuse/core"
4
+ import { cn } from "../../../lib/utils"
5
+ import TableCell from "./TableCell.vue"
6
+ import TableRow from "./TableRow.vue"
7
+
8
+ const props = withDefaults(defineProps<{
9
+ class?: HTMLAttributes["class"]
10
+ colspan?: number
11
+ }>(), {
12
+ colspan: 1,
13
+ })
14
+
15
+ const delegatedProps = reactiveOmit(props, "class")
16
+ </script>
17
+
18
+ <template>
19
+ <TableRow>
20
+ <TableCell
21
+ :class="
22
+ cn(
23
+ 'p-4 whitespace-nowrap align-middle text-sm text-foreground',
24
+ props.class,
25
+ )
26
+ "
27
+ v-bind="delegatedProps"
28
+ >
29
+ <div class="flex items-center justify-center py-10">
30
+ <slot />
31
+ </div>
32
+ </TableCell>
33
+ </TableRow>
34
+ </template>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from "vue"
3
+ import { cn } from "../../../lib/utils"
4
+
5
+ const props = defineProps<{
6
+ class?: HTMLAttributes["class"]
7
+ }>()
8
+ </script>
9
+
10
+ <template>
11
+ <tfoot :class="cn('border-t bg-muted/50 font-medium [&>tr]:last:border-b-0', props.class)">
12
+ <slot />
13
+ </tfoot>
14
+ </template>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from "vue"
3
+ import { cn } from "../../../lib/utils"
4
+
5
+ const props = defineProps<{
6
+ class?: HTMLAttributes["class"]
7
+ }>()
8
+ </script>
9
+
10
+ <template>
11
+ <th :class="cn('h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0', props.class)">
12
+ <slot />
13
+ </th>
14
+ </template>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from "vue"
3
+ import { cn } from "../../../lib/utils"
4
+
5
+ const props = defineProps<{
6
+ class?: HTMLAttributes["class"]
7
+ }>()
8
+ </script>
9
+
10
+ <template>
11
+ <thead :class="cn('[&_tr]:border-b', props.class)">
12
+ <slot />
13
+ </thead>
14
+ </template>
@@ -0,0 +1,14 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from "vue"
3
+ import { cn } from "../../../lib/utils"
4
+
5
+ const props = defineProps<{
6
+ class?: HTMLAttributes["class"]
7
+ }>()
8
+ </script>
9
+
10
+ <template>
11
+ <tr :class="cn('border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted', props.class)">
12
+ <slot />
13
+ </tr>
14
+ </template>
@@ -0,0 +1,9 @@
1
+ export { default as Table } from "./Table.vue"
2
+ export { default as TableBody } from "./TableBody.vue"
3
+ export { default as TableCaption } from "./TableCaption.vue"
4
+ export { default as TableCell } from "./TableCell.vue"
5
+ export { default as TableEmpty } from "./TableEmpty.vue"
6
+ export { default as TableFooter } from "./TableFooter.vue"
7
+ export { default as TableHead } from "./TableHead.vue"
8
+ export { default as TableHeader } from "./TableHeader.vue"
9
+ export { default as TableRow } from "./TableRow.vue"