diff --git a/package-lock.json b/package-lock.json index 3955a1105f..5dcf44af85 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,7 +37,7 @@ "@radix-ui/react-avatar": "^1.1.0", "@radix-ui/react-checkbox": "^1.1.1", "@radix-ui/react-collapsible": "^1.1.0", - "@radix-ui/react-dialog": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.2", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-focus-scope": "^1.1.0", "@radix-ui/react-hover-card": "^1.1.1", @@ -112,6 +112,7 @@ "three": "^0.166.1", "usehooks-ts": "^3.1.0", "uuidv7": "^0.6.3", + "vaul": "^1.0.0", "viem": "^2.21.1", "wagmi": "^2.12.8", "zod": "^3.22.4" @@ -8229,6 +8230,65 @@ } } }, + "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-dialog": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz", + "integrity": "sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-dismissable-layer": "1.1.0", + "@radix-ui/react-focus-guards": "1.1.0", + "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-portal": "1.1.1", + "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.7" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-alert-dialog/node_modules/react-remove-scroll": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz", + "integrity": "sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.4", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-arrow": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", @@ -8395,25 +8455,24 @@ } }, "node_modules/@radix-ui/react-dialog": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz", - "integrity": "sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==", - "license": "MIT", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.2.tgz", + "integrity": "sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==", "dependencies": { "@radix-ui/primitive": "1.1.0", "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-dismissable-layer": "1.1.0", - "@radix-ui/react-focus-guards": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-focus-guards": "1.1.1", "@radix-ui/react-focus-scope": "1.1.0", "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-portal": "1.1.1", - "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-portal": "1.1.2", + "@radix-ui/react-presence": "1.1.1", "@radix-ui/react-primitive": "2.0.0", "@radix-ui/react-slot": "1.1.0", "@radix-ui/react-use-controllable-state": "1.1.0", "aria-hidden": "^1.1.1", - "react-remove-scroll": "2.5.7" + "react-remove-scroll": "2.6.0" }, "peerDependencies": { "@types/react": "*", @@ -8430,24 +8489,53 @@ } } }, - "node_modules/@radix-ui/react-dialog/node_modules/react-remove-scroll": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz", - "integrity": "sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==", - "license": "MIT", + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", + "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", "dependencies": { - "react-remove-scroll-bar": "^2.3.4", - "react-style-singleton": "^2.2.1", - "tslib": "^2.1.0", - "use-callback-ref": "^1.3.0", - "use-sidecar": "^1.1.2" + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", + "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", "peerDependencies": { - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "peerDependenciesMeta": { "@types/react": { @@ -8455,6 +8543,52 @@ } } }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz", + "integrity": "sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-presence": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz", + "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-direction": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", @@ -34015,6 +34149,18 @@ "node": ">= 0.8" } }, + "node_modules/vaul": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vaul/-/vaul-1.0.0.tgz", + "integrity": "sha512-TegfMkwy86RSvSiIVREG6OqgRL7agqRsKYyWYacyVUAdpcIi34QoCOED476Mbf8J5d06e1hygSdvJhehlxEBhQ==", + "dependencies": { + "@radix-ui/react-dialog": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", diff --git a/package.json b/package.json index 60c53cffd5..f1bc356c49 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@radix-ui/react-avatar": "^1.1.0", "@radix-ui/react-checkbox": "^1.1.1", "@radix-ui/react-collapsible": "^1.1.0", - "@radix-ui/react-dialog": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.2", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-focus-scope": "^1.1.0", "@radix-ui/react-hover-card": "^1.1.1", @@ -124,6 +124,7 @@ "three": "^0.166.1", "usehooks-ts": "^3.1.0", "uuidv7": "^0.6.3", + "vaul": "^1.0.0", "viem": "^2.21.1", "wagmi": "^2.12.8", "zod": "^3.22.4" diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 0744789635..9bec3c6c9c 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -19,6 +19,7 @@ import { WagmiProvider } from "wagmi" import { wagmiConfig } from "wagmiConfig" import "../app/globals.css" import { AccountModal } from "@/components/Account/components/AccountModal" +import { PurchaseHistoryDrawer } from "@/components/Account/components/PurchaseHistoryDrawer/PurchaseHistoryDrawer" import AppErrorBoundary from "@/components/AppErrorBoundary" import { IntercomProvider } from "@/components/Providers/IntercomProvider" import { Toaster } from "@/components/ui/Toaster" @@ -83,6 +84,7 @@ const App = ({ + diff --git a/src/v2/components/Account/components/AccountModal/components/Account.tsx b/src/v2/components/Account/components/AccountModal/components/Account.tsx index f47ae46619..aed493a630 100644 --- a/src/v2/components/Account/components/AccountModal/components/Account.tsx +++ b/src/v2/components/Account/components/AccountModal/components/Account.tsx @@ -1,5 +1,6 @@ import { CopyableAddress } from "@/components/CopyableAddress" import { GuildAvatar } from "@/components/GuildAvatar" +import { purchaseHistoryDrawerAtom } from "@/components/Providers/atoms" import useConnectorNameAndIcon from "@/components/Web3ConnectionManager/hooks/useConnectorNameAndIcon" import { useWeb3ConnectionManager } from "@/components/Web3ConnectionManager/hooks/useWeb3ConnectionManager" import { @@ -11,6 +12,7 @@ import { import { IconButton } from "@/components/ui/IconButton" import { DotsThreeVertical, File, SignOut } from "@phosphor-icons/react" import useResolveAddress from "hooks/useResolveAddress" +import { useSetAtom } from "jotai" import { useAccount } from "wagmi" import { NetworkIndicator } from "./NetworkIndicator" @@ -25,6 +27,8 @@ export const Account = ({ handleLogout }: AccountProps) => { const { address: evmAddress } = useAccount() const domain = useResolveAddress(evmAddress ?? "") + const setIsPurchaseHistoryOpen = useSetAtom(purchaseHistoryDrawerAtom) + if (!address) return null return ( @@ -59,7 +63,10 @@ export const Account = ({ handleLogout }: AccountProps) => { /> - + setIsPurchaseHistoryOpen(true)} + > Purchase history diff --git a/src/v2/components/Account/components/AccountModal/components/AccountGuildProfile.tsx b/src/v2/components/Account/components/AccountModal/components/AccountGuildProfile.tsx index 6a803eb8f4..de7e3cb4fc 100644 --- a/src/v2/components/Account/components/AccountModal/components/AccountGuildProfile.tsx +++ b/src/v2/components/Account/components/AccountModal/components/AccountGuildProfile.tsx @@ -19,9 +19,11 @@ import { LevelBadge } from "@app/(marketing)/profile/_components/LevelBadge" import { ArrowRight, DotsThreeVertical } from "@phosphor-icons/react" import { File, SignOut } from "@phosphor-icons/react/dist/ssr" +import { purchaseHistoryDrawerAtom } from "@/components/Providers/atoms" import useConnectorNameAndIcon from "@/components/Web3ConnectionManager/hooks/useConnectorNameAndIcon" import { useExperienceProgression } from "@app/(marketing)/profile/_hooks/useExperienceProgression" import useUser from "components/[guild]/hooks/useUser" +import { useSetAtom } from "jotai" import { NetworkIndicator } from "../components/NetworkIndicator" type AccountGuildProfileProps = { @@ -36,6 +38,7 @@ export const AccountGuildProfile = ({ const { guildProfile } = useUser() const xp = useExperienceProgression(true) const { connectorName } = useConnectorNameAndIcon() + const setIsPurchaseHistoryOpen = useSetAtom(purchaseHistoryDrawerAtom) if (!guildProfile) return null @@ -108,7 +111,10 @@ export const AccountGuildProfile = ({ /> - + setIsPurchaseHistoryOpen(true)} + > Purchase history diff --git a/src/v2/components/Account/components/PurchaseHistoryDrawer/PurchaseHistoryDrawer.tsx b/src/v2/components/Account/components/PurchaseHistoryDrawer/PurchaseHistoryDrawer.tsx new file mode 100644 index 0000000000..769f08ac77 --- /dev/null +++ b/src/v2/components/Account/components/PurchaseHistoryDrawer/PurchaseHistoryDrawer.tsx @@ -0,0 +1,60 @@ +import { purchaseHistoryDrawerAtom } from "@/components/Providers/atoms" +import { + Drawer, + DrawerContent, + DrawerHeader, + DrawerTitle, +} from "@/components/ui/Drawer" +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/Table" +import { DownloadSimple } from "@phosphor-icons/react" +import { useAtom } from "jotai" +import Link from "next/link" +import shortenHex from "utils/shortenHex" + +export const PurchaseHistoryDrawer = () => { + const [isOpen, setIsOpen] = useAtom(purchaseHistoryDrawerAtom) + + return ( + setIsOpen(false)}> + + + Purchase History + + + + + Receipt + Name + Amount + Date + Payment Address + + + + + + + INV001 + + + Guild Pin + $250.00 + {new Date().toLocaleDateString()} + {shortenHex()} + + +
+
+
+ ) +} diff --git a/src/v2/components/Providers/Providers.tsx b/src/v2/components/Providers/Providers.tsx index 8295007a83..1714fca011 100644 --- a/src/v2/components/Providers/Providers.tsx +++ b/src/v2/components/Providers/Providers.tsx @@ -14,6 +14,7 @@ import { shouldUseReCAPTCHAAtom } from "utils/recaptcha" import { WagmiProvider } from "wagmi" import { wagmiConfig } from "wagmiConfig" import { AccountModal } from "../Account/components/AccountModal" +import { PurchaseHistoryDrawer } from "../Account/components/PurchaseHistoryDrawer/PurchaseHistoryDrawer" import { Web3ConnectionManager } from "../Web3ConnectionManager" import { Toaster } from "../ui/Toaster" import { TooltipProvider } from "../ui/Tooltip" @@ -45,6 +46,7 @@ export function Providers({ children }: { children: ReactNode }) { {children} + diff --git a/src/v2/components/Providers/atoms.ts b/src/v2/components/Providers/atoms.ts index ca9e07bb0d..f7adf9cfcb 100644 --- a/src/v2/components/Providers/atoms.ts +++ b/src/v2/components/Providers/atoms.ts @@ -12,3 +12,4 @@ export const walletLinkHelperModalAtom = atom(false) export const platformMergeAlertAtom = atom< false | { addressOrDomain: string; platformName: PlatformName } >(false) +export const purchaseHistoryDrawerAtom = atom(false) diff --git a/src/v2/components/ui/Drawer.stories.tsx b/src/v2/components/ui/Drawer.stories.tsx new file mode 100644 index 0000000000..2c557cc41c --- /dev/null +++ b/src/v2/components/ui/Drawer.stories.tsx @@ -0,0 +1,41 @@ +import type { Meta, StoryObj } from "@storybook/react" +import { Button } from "./Button" +import { + Drawer, + DrawerClose, + DrawerContent, + DrawerDescription, + DrawerFooter, + DrawerHeader, + DrawerTitle, + DrawerTrigger, +} from "./Drawer" + +const DrawerExample = () => ( + + Open + + + Are you absolutely sure? + This action cannot be undone. + + + + + + + + + +) + +const meta: Meta = { + title: "Design system/Drawer", + component: DrawerExample, +} + +export default meta + +type Story = StoryObj + +export const Default: Story = {} diff --git a/src/v2/components/ui/Drawer.tsx b/src/v2/components/ui/Drawer.tsx new file mode 100755 index 0000000000..ff9ca4f076 --- /dev/null +++ b/src/v2/components/ui/Drawer.tsx @@ -0,0 +1,109 @@ +"use client" + +import * as React from "react" +import { Drawer as DrawerPrimitive } from "vaul" + +import { cn } from "@/lib/utils" + +const Drawer = ({ + shouldScaleBackground = true, + ...props +}: React.ComponentProps) => ( + +) +Drawer.displayName = "Drawer" + +const DrawerTrigger = DrawerPrimitive.Trigger + +const DrawerPortal = DrawerPrimitive.Portal + +const DrawerClose = DrawerPrimitive.Close + +const DrawerOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName + +const DrawerContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + +
+ {children} + + +)) +DrawerContent.displayName = "DrawerContent" + +const DrawerHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DrawerHeader.displayName = "DrawerHeader" + +const DrawerFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DrawerFooter.displayName = "DrawerFooter" + +const DrawerTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DrawerTitle.displayName = DrawerPrimitive.Title.displayName + +const DrawerDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DrawerDescription.displayName = DrawerPrimitive.Description.displayName + +export { + Drawer, + DrawerPortal, + DrawerOverlay, + DrawerTrigger, + DrawerClose, + DrawerContent, + DrawerHeader, + DrawerFooter, + DrawerTitle, + DrawerDescription, +} diff --git a/src/v2/components/ui/Table.stories.tsx b/src/v2/components/ui/Table.stories.tsx new file mode 100644 index 0000000000..4f6b93a86e --- /dev/null +++ b/src/v2/components/ui/Table.stories.tsx @@ -0,0 +1,53 @@ +import type { Meta, StoryObj } from "@storybook/react" +import Link from "next/link" +import shortenHex from "utils/shortenHex" +import { + Table, + TableBody, + TableCaption, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "./Table" + +const TableExample = () => ( + + A list of your recent purchases. + + + ID + Name + Payment Address + Date + Amount (USD) + Receipt + + + + + INV001 + Guild Pin + {shortenHex()} + {new Date().toLocaleDateString()} + $250.00 + + + View + + + + +
+) + +const meta: Meta = { + title: "Design system/Table", + component: TableExample, +} + +export default meta + +type Story = StoryObj + +export const Default: Story = {} diff --git a/src/v2/components/ui/Table.tsx b/src/v2/components/ui/Table.tsx new file mode 100755 index 0000000000..690236151f --- /dev/null +++ b/src/v2/components/ui/Table.tsx @@ -0,0 +1,117 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Table = React.forwardRef< + HTMLTableElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+ + +)) +Table.displayName = "Table" + +const TableHeader = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableHeader.displayName = "TableHeader" + +const TableBody = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableBody.displayName = "TableBody" + +const TableFooter = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + tr]:last:border-b-0", + className + )} + {...props} + /> +)) +TableFooter.displayName = "TableFooter" + +const TableRow = React.forwardRef< + HTMLTableRowElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableRow.displayName = "TableRow" + +const TableHead = React.forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +TableHead.displayName = "TableHead" + +const TableCell = React.forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableCell.displayName = "TableCell" + +const TableCaption = React.forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +TableCaption.displayName = "TableCaption" + +export { + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption, +}