@rovula/ui 0.0.9 → 0.0.10

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 (97) hide show
  1. package/dist/cjs/bundle.css +429 -3
  2. package/dist/cjs/bundle.js +1 -1
  3. package/dist/cjs/bundle.js.map +1 -1
  4. package/dist/cjs/types/components/AlertDialog/Alert.stories.d.ts +20 -0
  5. package/dist/cjs/types/components/AlertDialog/AlertDialog.d.ts +20 -0
  6. package/dist/cjs/types/components/Button/Button.styles.d.ts +1 -1
  7. package/dist/cjs/types/components/Checkbox/Checkbox.d.ts +4 -0
  8. package/dist/cjs/types/components/Checkbox/Checkbox.stories.d.ts +308 -0
  9. package/dist/cjs/types/components/Dialog/Dialog.d.ts +19 -0
  10. package/dist/cjs/types/components/Dialog/Dialog.stories.d.ts +25 -0
  11. package/dist/cjs/types/components/Input/Input.d.ts +5 -0
  12. package/dist/cjs/types/components/Input/Input.stories.d.ts +314 -0
  13. package/dist/cjs/types/components/Label/Label.d.ts +5 -0
  14. package/dist/cjs/types/components/Label/Label.stories.d.ts +286 -0
  15. package/dist/cjs/types/components/RadioGroup/RadioGroup.d.ts +5 -0
  16. package/dist/cjs/types/components/RadioGroup/RadioGroup.stories.d.ts +299 -0
  17. package/dist/cjs/types/components/Table/Datagrid.d.ts +11 -0
  18. package/dist/cjs/types/components/Table/Table.d.ts +10 -11
  19. package/dist/cjs/types/components/Table/Table.stories.d.ts +283 -0
  20. package/dist/cjs/types/components/Tabs/Tabs.d.ts +7 -5
  21. package/dist/cjs/types/components/Tabs/Tabs.stories.d.ts +49 -0
  22. package/dist/cjs/types/index.d.ts +7 -1
  23. package/dist/cjs/types/utils/cn.d.ts +2 -0
  24. package/dist/components/AlertDialog/Alert.stories.js +39 -0
  25. package/dist/components/AlertDialog/AlertDialog.js +73 -0
  26. package/dist/components/Button/Button.js +3 -3
  27. package/dist/components/Button/Button.styles.js +1 -1
  28. package/dist/components/Checkbox/Checkbox.js +37 -0
  29. package/dist/components/Checkbox/Checkbox.stories.js +49 -0
  30. package/dist/components/Dialog/Dialog.js +63 -0
  31. package/dist/components/Dialog/Dialog.stories.js +52 -0
  32. package/dist/components/Input/Input.js +31 -0
  33. package/dist/components/Input/Input.stories.js +37 -0
  34. package/dist/components/Label/Label.js +35 -0
  35. package/dist/components/Label/Label.stories.js +38 -0
  36. package/dist/components/RadioGroup/RadioGroup.js +41 -0
  37. package/dist/components/RadioGroup/RadioGroup.stories.js +44 -0
  38. package/dist/components/Table/Datagrid.js +6 -0
  39. package/dist/components/Table/Table.js +65 -5
  40. package/dist/components/Table/Table.stories.js +32 -0
  41. package/dist/components/Tabs/Tabs.js +10 -4
  42. package/dist/components/Tabs/Tabs.stories.js +60 -0
  43. package/dist/esm/bundle.css +429 -3
  44. package/dist/esm/bundle.js +1 -1
  45. package/dist/esm/bundle.js.map +1 -1
  46. package/dist/esm/types/components/AlertDialog/Alert.stories.d.ts +20 -0
  47. package/dist/esm/types/components/AlertDialog/AlertDialog.d.ts +20 -0
  48. package/dist/esm/types/components/Button/Button.styles.d.ts +1 -1
  49. package/dist/esm/types/components/Checkbox/Checkbox.d.ts +4 -0
  50. package/dist/esm/types/components/Checkbox/Checkbox.stories.d.ts +308 -0
  51. package/dist/esm/types/components/Dialog/Dialog.d.ts +19 -0
  52. package/dist/esm/types/components/Dialog/Dialog.stories.d.ts +25 -0
  53. package/dist/esm/types/components/Input/Input.d.ts +5 -0
  54. package/dist/esm/types/components/Input/Input.stories.d.ts +314 -0
  55. package/dist/esm/types/components/Label/Label.d.ts +5 -0
  56. package/dist/esm/types/components/Label/Label.stories.d.ts +286 -0
  57. package/dist/esm/types/components/RadioGroup/RadioGroup.d.ts +5 -0
  58. package/dist/esm/types/components/RadioGroup/RadioGroup.stories.d.ts +299 -0
  59. package/dist/esm/types/components/Table/Datagrid.d.ts +11 -0
  60. package/dist/esm/types/components/Table/Table.d.ts +10 -11
  61. package/dist/esm/types/components/Table/Table.stories.d.ts +283 -0
  62. package/dist/esm/types/components/Tabs/Tabs.d.ts +7 -5
  63. package/dist/esm/types/components/Tabs/Tabs.stories.d.ts +49 -0
  64. package/dist/esm/types/index.d.ts +7 -1
  65. package/dist/esm/types/utils/cn.d.ts +2 -0
  66. package/dist/index.d.ts +82 -28
  67. package/dist/index.js +7 -1
  68. package/dist/src/theme/global.css +511 -3
  69. package/dist/theme/global.css +57 -0
  70. package/dist/theme/main-preset.js +29 -1
  71. package/dist/theme/presets/colors.js +19 -0
  72. package/dist/utils/cn.js +9 -0
  73. package/package.json +9 -1
  74. package/src/components/AlertDialog/Alert.stories.tsx +67 -0
  75. package/src/components/AlertDialog/AlertDialog.tsx +142 -0
  76. package/src/components/Button/Button.styles.ts +1 -1
  77. package/src/components/Button/Button.tsx +4 -4
  78. package/src/components/Checkbox/Checkbox.stories.tsx +91 -0
  79. package/src/components/Checkbox/Checkbox.tsx +36 -0
  80. package/src/components/Dialog/Dialog.stories.tsx +118 -0
  81. package/src/components/Dialog/Dialog.tsx +119 -0
  82. package/src/components/Input/Input.stories.tsx +40 -0
  83. package/src/components/Input/Input.tsx +25 -0
  84. package/src/components/Label/Label.stories.tsx +45 -0
  85. package/src/components/Label/Label.tsx +26 -0
  86. package/src/components/RadioGroup/RadioGroup.stories.tsx +71 -0
  87. package/src/components/RadioGroup/RadioGroup.tsx +59 -0
  88. package/src/components/Table/Datagrid.tsx +36 -0
  89. package/src/components/Table/Table.stories.tsx +79 -0
  90. package/src/components/Table/Table.tsx +116 -35
  91. package/src/components/Tabs/Tabs.stories.tsx +75 -0
  92. package/src/components/Tabs/Tabs.tsx +39 -10
  93. package/src/index.ts +8 -1
  94. package/src/theme/global.css +57 -0
  95. package/src/theme/main-preset.js +29 -1
  96. package/src/theme/presets/colors.js +19 -0
  97. package/src/utils/cn.ts +6 -0
@@ -0,0 +1,119 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
5
+
6
+ import { XMarkIcon } from "@heroicons/react/16/solid";
7
+ import { cn } from "@/utils/cn";
8
+
9
+ const Dialog = DialogPrimitive.Root;
10
+
11
+ const DialogTrigger = DialogPrimitive.Trigger;
12
+
13
+ const DialogPortal = DialogPrimitive.Portal;
14
+
15
+ const DialogClose = DialogPrimitive.Close;
16
+
17
+ const DialogOverlay = React.forwardRef<
18
+ React.ElementRef<typeof DialogPrimitive.Overlay>,
19
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
20
+ >(({ className, ...props }, ref) => (
21
+ <DialogPrimitive.Overlay
22
+ ref={ref}
23
+ className={cn(
24
+ "fixed inset-0 z-50 bg-popup-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
25
+ className
26
+ )}
27
+ {...props}
28
+ />
29
+ ));
30
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
31
+
32
+ const DialogContent = React.forwardRef<
33
+ React.ElementRef<typeof DialogPrimitive.Content>,
34
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
35
+ >(({ className, children, ...props }, ref) => (
36
+ <DialogPortal>
37
+ <DialogOverlay />
38
+ <DialogPrimitive.Content
39
+ ref={ref}
40
+ className={cn(
41
+ "fixed text-textcolor-grey-dark left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-[var(--popup-rounded)]",
42
+ className
43
+ )}
44
+ {...props}
45
+ >
46
+ {children}
47
+ <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
48
+ <XMarkIcon className="h-4 w-4" />
49
+ <span className="sr-only">Close</span>
50
+ </DialogPrimitive.Close>
51
+ </DialogPrimitive.Content>
52
+ </DialogPortal>
53
+ ));
54
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
55
+
56
+ const DialogHeader = ({
57
+ className,
58
+ ...props
59
+ }: React.HTMLAttributes<HTMLDivElement>) => (
60
+ <div
61
+ className={cn(
62
+ "flex flex-col space-y-2 text-center sm:text-left",
63
+ className
64
+ )}
65
+ {...props}
66
+ />
67
+ );
68
+ DialogHeader.displayName = "DialogHeader";
69
+
70
+ const DialogFooter = ({
71
+ className,
72
+ ...props
73
+ }: React.HTMLAttributes<HTMLDivElement>) => (
74
+ <div
75
+ className={cn(
76
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
77
+ className
78
+ )}
79
+ {...props}
80
+ />
81
+ );
82
+ DialogFooter.displayName = "DialogFooter";
83
+
84
+ const DialogTitle = React.forwardRef<
85
+ React.ElementRef<typeof DialogPrimitive.Title>,
86
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
87
+ >(({ className, ...props }, ref) => (
88
+ <DialogPrimitive.Title
89
+ ref={ref}
90
+ className={cn("typography-h5 tracking-tight", className)}
91
+ {...props}
92
+ />
93
+ ));
94
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
95
+
96
+ const DialogDescription = React.forwardRef<
97
+ React.ElementRef<typeof DialogPrimitive.Description>,
98
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
99
+ >(({ className, ...props }, ref) => (
100
+ <DialogPrimitive.Description
101
+ ref={ref}
102
+ className={cn("text-sm", className)}
103
+ {...props}
104
+ />
105
+ ));
106
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
107
+
108
+ export {
109
+ Dialog,
110
+ DialogPortal,
111
+ DialogOverlay,
112
+ DialogClose,
113
+ DialogTrigger,
114
+ DialogContent,
115
+ DialogHeader,
116
+ DialogFooter,
117
+ DialogTitle,
118
+ DialogDescription,
119
+ };
@@ -0,0 +1,40 @@
1
+ import React from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+ import { Input } from "./Input";
4
+
5
+ const meta = {
6
+ title: "Components/Input",
7
+ component: Input,
8
+ tags: ["autodocs"],
9
+ parameters: {
10
+ layout: "fullscreen",
11
+ },
12
+ decorators: [
13
+ (Story) => (
14
+ <div className="p-5 flex w-full">
15
+ <Story />
16
+ </div>
17
+ ),
18
+ ],
19
+ } satisfies Meta<typeof Input>;
20
+
21
+ export default meta;
22
+
23
+ export const Default = {
24
+ args: {
25
+ // label: "Lorem Ipsum",
26
+ // value: "Lorem Ipsum",
27
+ // fullwidth: true,
28
+ },
29
+ render: (args) => {
30
+ console.log("args ", args);
31
+ const props: typeof args = {
32
+ ...args,
33
+ };
34
+ return (
35
+ <div className="flex flex-row gap-4 w-full">
36
+ <Input type="email" placeholder="Email" />
37
+ </div>
38
+ );
39
+ },
40
+ } satisfies StoryObj;
@@ -0,0 +1,25 @@
1
+ import * as React from "react";
2
+
3
+ import { cn } from "@/utils/cn";
4
+
5
+ export interface InputProps
6
+ extends React.InputHTMLAttributes<HTMLInputElement> {}
7
+
8
+ const Input = React.forwardRef<HTMLInputElement, InputProps>(
9
+ ({ className, type, ...props }, ref) => {
10
+ return (
11
+ <input
12
+ type={type}
13
+ className={cn(
14
+ "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
15
+ className
16
+ )}
17
+ ref={ref}
18
+ {...props}
19
+ />
20
+ );
21
+ }
22
+ );
23
+ Input.displayName = "Input";
24
+
25
+ export { Input };
@@ -0,0 +1,45 @@
1
+ import React from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+
4
+ import { Checkbox } from "../Checkbox/Checkbox";
5
+ import { Label } from "./Label";
6
+
7
+ const meta = {
8
+ title: "Components/Label",
9
+ component: Label,
10
+ tags: ["autodocs"],
11
+ parameters: {
12
+ layout: "fullscreen",
13
+ },
14
+ decorators: [
15
+ (Story) => (
16
+ <div className="p-5 flex w-full">
17
+ <Story />
18
+ </div>
19
+ ),
20
+ ],
21
+ } satisfies Meta<typeof Label>;
22
+
23
+ export default meta;
24
+
25
+ export const Default = {
26
+ args: {
27
+ // label: "Lorem Ipsum",
28
+ // value: "Lorem Ipsum",
29
+ // fullwidth: true,
30
+ },
31
+ render: (args) => {
32
+ console.log("args ", args);
33
+ const props: typeof args = {
34
+ ...args,
35
+ };
36
+ return (
37
+ <div className="flex flex-row gap-4 w-full">
38
+ <div className="flex items-center space-x-2">
39
+ <Checkbox id="terms" />
40
+ <Label htmlFor="terms">Accept terms and conditions</Label>
41
+ </div>
42
+ </div>
43
+ );
44
+ },
45
+ } satisfies StoryObj;
@@ -0,0 +1,26 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as LabelPrimitive from "@radix-ui/react-label";
5
+ import { cva, type VariantProps } from "class-variance-authority";
6
+
7
+ import { cn } from "@/utils/cn";
8
+
9
+ const labelVariants = cva(
10
+ "typography-label1 peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
11
+ );
12
+
13
+ const Label = React.forwardRef<
14
+ React.ElementRef<typeof LabelPrimitive.Root>,
15
+ React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
16
+ VariantProps<typeof labelVariants>
17
+ >(({ className, ...props }, ref) => (
18
+ <LabelPrimitive.Root
19
+ ref={ref}
20
+ className={cn(labelVariants(), className)}
21
+ {...props}
22
+ />
23
+ ));
24
+ Label.displayName = LabelPrimitive.Root.displayName;
25
+
26
+ export { Label };
@@ -0,0 +1,71 @@
1
+ import React from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+ import { RadioGroup, RadioGroupItem } from "./RadioGroup";
4
+ import { Label } from "../Label/Label";
5
+ const meta = {
6
+ title: "Components/RadioGroup",
7
+ component: RadioGroup,
8
+ tags: ["autodocs"],
9
+ parameters: {
10
+ layout: "fullscreen",
11
+ },
12
+ decorators: [
13
+ (Story) => (
14
+ <div className="p-5 flex w-full">
15
+ <Story />
16
+ </div>
17
+ ),
18
+ ],
19
+ } satisfies Meta<typeof RadioGroup>;
20
+
21
+ export default meta;
22
+
23
+ export const Default = {
24
+ args: {
25
+ disabled: false,
26
+ },
27
+ render: (args) => {
28
+ const props: typeof args = {
29
+ ...args,
30
+ };
31
+ return (
32
+ <div className="flex flex-row gap-4 w-full">
33
+ <RadioGroup defaultValue="option-one" {...props}>
34
+ <div className="flex items-center space-x-2">
35
+ <RadioGroupItem value="option-one" id="option-one" />
36
+ <Label htmlFor="option-one">Option One</Label>
37
+ </div>
38
+ <div className="flex items-center space-x-2">
39
+ <RadioGroupItem value="option-two" id="option-two" />
40
+ <Label htmlFor="option-two">Option Two</Label>
41
+ </div>
42
+ </RadioGroup>
43
+ </div>
44
+ );
45
+ },
46
+ } satisfies StoryObj;
47
+
48
+ export const Diabled = {
49
+ args: {
50
+ disabled: true,
51
+ },
52
+ render: (args) => {
53
+ const props: typeof args = {
54
+ ...args,
55
+ };
56
+ return (
57
+ <div className="flex items-center space-x-2">
58
+ <RadioGroup defaultValue="option-one" disabled>
59
+ <div className="flex items-center space-x-2">
60
+ <RadioGroupItem value="option-one" id="option-one" />
61
+ <Label htmlFor="option-one">Option One</Label>
62
+ </div>
63
+ <div className="flex items-center space-x-2">
64
+ <RadioGroupItem value="option-two" id="option-two" />
65
+ <Label htmlFor="option-two">Option Two</Label>
66
+ </div>
67
+ </RadioGroup>
68
+ </div>
69
+ );
70
+ },
71
+ } satisfies StoryObj;
@@ -0,0 +1,59 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
5
+
6
+ import { cn } from "@/utils/cn";
7
+
8
+ const RadioGroup = React.forwardRef<
9
+ React.ElementRef<typeof RadioGroupPrimitive.Root>,
10
+ React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
11
+ >(({ className, ...props }, ref) => {
12
+ return (
13
+ <RadioGroupPrimitive.Root
14
+ className={cn("grid gap-2", className)}
15
+ {...props}
16
+ ref={ref}
17
+ />
18
+ );
19
+ });
20
+ RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
21
+
22
+ const RadioGroupItem = React.forwardRef<
23
+ React.ElementRef<typeof RadioGroupPrimitive.Item>,
24
+ React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
25
+ >(({ className, ...props }, ref) => {
26
+ return (
27
+ <RadioGroupPrimitive.Item
28
+ ref={ref}
29
+ className={cn(
30
+ "aspect-square h-4 w-4 rounded-full border text-primary disabled:fill-secondary-110 ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:border-secondary-110",
31
+ {
32
+ "border-primary-30 data-[state=checked]:border-primary":
33
+ !props.disabled,
34
+ "border-secondary-110 data-disabled:border-secondary-110 text-secondary-110 fill-secondary-110":
35
+ props.disabled,
36
+ },
37
+ className
38
+ )}
39
+ {...props}
40
+ >
41
+ <RadioGroupPrimitive.Indicator className="flex items-center justify-center">
42
+ {/* <div className="bg-primary size-2.5 rounded-full" /> */}
43
+ <svg
44
+ width="10"
45
+ height="10"
46
+ viewBox="0 0 10 10"
47
+ fill="none"
48
+ xmlns="http://www.w3.org/2000/svg"
49
+ className="fill-current text-current"
50
+ >
51
+ <circle cx="5" cy="5" r="5" fill="current" />
52
+ </svg>
53
+ </RadioGroupPrimitive.Indicator>
54
+ </RadioGroupPrimitive.Item>
55
+ );
56
+ });
57
+ RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
58
+
59
+ export { RadioGroup, RadioGroupItem };
@@ -0,0 +1,36 @@
1
+ import React from "react";
2
+
3
+ interface Column {
4
+ header: string;
5
+ accessor: string;
6
+ }
7
+
8
+ interface TableProps {
9
+ columns: Column[];
10
+ data: Record<string, any>[];
11
+ }
12
+
13
+ const Table: React.FC<TableProps> = ({ columns, data }) => {
14
+ return (
15
+ <table className="table">
16
+ <thead>
17
+ <tr>
18
+ {columns.map((column, index) => (
19
+ <th key={index}>{column.header}</th>
20
+ ))}
21
+ </tr>
22
+ </thead>
23
+ <tbody>
24
+ {data.map((row, rowIndex) => (
25
+ <tr key={rowIndex}>
26
+ {columns.map((column, colIndex) => (
27
+ <td key={colIndex}>{row[column.accessor]}</td>
28
+ ))}
29
+ </tr>
30
+ ))}
31
+ </tbody>
32
+ </table>
33
+ );
34
+ };
35
+
36
+ export default Table;
@@ -0,0 +1,79 @@
1
+ import React from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+ import {
4
+ Table,
5
+ TableBody,
6
+ TableCaption,
7
+ TableCell,
8
+ TableHead,
9
+ TableHeader,
10
+ TableRow,
11
+ } from "./Table";
12
+
13
+ const meta = {
14
+ title: "Components/Table",
15
+ component: Table,
16
+ tags: ["autodocs"],
17
+ parameters: {
18
+ layout: "fullscreen",
19
+ },
20
+ decorators: [
21
+ (Story) => (
22
+ <div className="p-5 flex w-full">
23
+ <Story />
24
+ </div>
25
+ ),
26
+ ],
27
+ } satisfies Meta<typeof Table>;
28
+
29
+ export default meta;
30
+
31
+ export const Default = {
32
+ args: {},
33
+ render: (args) => {
34
+ const props: typeof args = {
35
+ ...args,
36
+ };
37
+ return (
38
+ <div className="flex flex-row gap-4 w-full">
39
+ <Table>
40
+ <TableCaption>A list of your recent invoices.</TableCaption>
41
+ <TableHeader>
42
+ <TableRow>
43
+ <TableHead className="w-[100px]">Invoice</TableHead>
44
+ <TableHead>Status</TableHead>
45
+ <TableHead>Method</TableHead>
46
+ <TableHead className="text-right">Amount</TableHead>
47
+ </TableRow>
48
+ </TableHeader>
49
+ <TableBody>
50
+ <TableRow>
51
+ <TableCell className="font-medium">INV001</TableCell>
52
+ <TableCell>Paid</TableCell>
53
+ <TableCell>Credit Card</TableCell>
54
+ <TableCell className="text-right">$250.00</TableCell>
55
+ </TableRow>
56
+ <TableRow>
57
+ <TableCell className="font-medium">INV001</TableCell>
58
+ <TableCell>Paid</TableCell>
59
+ <TableCell>Credit Card</TableCell>
60
+ <TableCell className="text-right">$250.00</TableCell>
61
+ </TableRow>
62
+ <TableRow>
63
+ <TableCell className="font-medium">INV001</TableCell>
64
+ <TableCell>Paid</TableCell>
65
+ <TableCell>Credit Card</TableCell>
66
+ <TableCell className="text-right">$250.00</TableCell>
67
+ </TableRow>
68
+ <TableRow>
69
+ <TableCell className="font-medium">INV001</TableCell>
70
+ <TableCell>Paid</TableCell>
71
+ <TableCell>Credit Card</TableCell>
72
+ <TableCell className="text-right">$250.00</TableCell>
73
+ </TableRow>
74
+ </TableBody>
75
+ </Table>
76
+ </div>
77
+ );
78
+ },
79
+ } satisfies StoryObj;
@@ -1,36 +1,117 @@
1
- import React from "react";
2
-
3
- interface Column {
4
- header: string;
5
- accessor: string;
6
- }
7
-
8
- interface TableProps {
9
- columns: Column[];
10
- data: Record<string, any>[];
11
- }
12
-
13
- const Table: React.FC<TableProps> = ({ columns, data }) => {
14
- return (
15
- <table className="table">
16
- <thead>
17
- <tr>
18
- {columns.map((column, index) => (
19
- <th key={index}>{column.header}</th>
20
- ))}
21
- </tr>
22
- </thead>
23
- <tbody>
24
- {data.map((row, rowIndex) => (
25
- <tr key={rowIndex}>
26
- {columns.map((column, colIndex) => (
27
- <td key={colIndex}>{row[column.accessor]}</td>
28
- ))}
29
- </tr>
30
- ))}
31
- </tbody>
32
- </table>
33
- );
34
- };
1
+ import * as React from "react";
2
+
3
+ import { cn } from "@/utils/cn";
4
+
5
+ const Table = React.forwardRef<
6
+ HTMLTableElement,
7
+ React.HTMLAttributes<HTMLTableElement>
8
+ >(({ className, ...props }, ref) => (
9
+ <div className="relative w-full overflow-auto">
10
+ <table
11
+ ref={ref}
12
+ className={cn("w-full caption-bottom text-sm", className)}
13
+ {...props}
14
+ />
15
+ </div>
16
+ ));
17
+ Table.displayName = "Table";
18
+
19
+ const TableHeader = React.forwardRef<
20
+ HTMLTableSectionElement,
21
+ React.HTMLAttributes<HTMLTableSectionElement>
22
+ >(({ className, ...props }, ref) => (
23
+ <thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
24
+ ));
25
+ TableHeader.displayName = "TableHeader";
26
+
27
+ const TableBody = React.forwardRef<
28
+ HTMLTableSectionElement,
29
+ React.HTMLAttributes<HTMLTableSectionElement>
30
+ >(({ className, ...props }, ref) => (
31
+ <tbody
32
+ ref={ref}
33
+ className={cn("[&_tr:last-child]:border-0", className)}
34
+ {...props}
35
+ />
36
+ ));
37
+ TableBody.displayName = "TableBody";
38
+
39
+ const TableFooter = React.forwardRef<
40
+ HTMLTableSectionElement,
41
+ React.HTMLAttributes<HTMLTableSectionElement>
42
+ >(({ className, ...props }, ref) => (
43
+ <tfoot
44
+ ref={ref}
45
+ className={cn(
46
+ "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
47
+ className
48
+ )}
49
+ {...props}
50
+ />
51
+ ));
52
+ TableFooter.displayName = "TableFooter";
35
53
 
36
- export default Table;
54
+ const TableRow = React.forwardRef<
55
+ HTMLTableRowElement,
56
+ React.HTMLAttributes<HTMLTableRowElement>
57
+ >(({ className, ...props }, ref) => (
58
+ <tr
59
+ ref={ref}
60
+ className={cn(
61
+ "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
62
+ className
63
+ )}
64
+ {...props}
65
+ />
66
+ ));
67
+ TableRow.displayName = "TableRow";
68
+
69
+ const TableHead = React.forwardRef<
70
+ HTMLTableCellElement,
71
+ React.ThHTMLAttributes<HTMLTableCellElement>
72
+ >(({ className, ...props }, ref) => (
73
+ <th
74
+ ref={ref}
75
+ className={cn(
76
+ "h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
77
+ className
78
+ )}
79
+ {...props}
80
+ />
81
+ ));
82
+ TableHead.displayName = "TableHead";
83
+
84
+ const TableCell = React.forwardRef<
85
+ HTMLTableCellElement,
86
+ React.TdHTMLAttributes<HTMLTableCellElement>
87
+ >(({ className, ...props }, ref) => (
88
+ <td
89
+ ref={ref}
90
+ className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
91
+ {...props}
92
+ />
93
+ ));
94
+ TableCell.displayName = "TableCell";
95
+
96
+ const TableCaption = React.forwardRef<
97
+ HTMLTableCaptionElement,
98
+ React.HTMLAttributes<HTMLTableCaptionElement>
99
+ >(({ className, ...props }, ref) => (
100
+ <caption
101
+ ref={ref}
102
+ className={cn("mt-4 text-sm text-muted-foreground", className)}
103
+ {...props}
104
+ />
105
+ ));
106
+ TableCaption.displayName = "TableCaption";
107
+
108
+ export {
109
+ Table,
110
+ TableHeader,
111
+ TableBody,
112
+ TableFooter,
113
+ TableHead,
114
+ TableRow,
115
+ TableCell,
116
+ TableCaption,
117
+ };