diff --git a/apps/next/src/components/landing/cta.tsx b/apps/next/src/components/landing/cta.tsx index f5d4d79..936eedd 100644 --- a/apps/next/src/components/landing/cta.tsx +++ b/apps/next/src/components/landing/cta.tsx @@ -2,7 +2,7 @@ export function CTA() { return (
-
+

Ready to Build Something Amazing?

diff --git a/apps/next/src/components/landing/features.tsx b/apps/next/src/components/landing/features.tsx index f1f89c5..da44afe 100644 --- a/apps/next/src/components/landing/features.tsx +++ b/apps/next/src/components/landing/features.tsx @@ -1,4 +1,4 @@ -import { Card, CardContent, CardHeader, CardTitle } from '@gib/ui/card'; +import { Card, CardContent, CardHeader, CardTitle } from '@gib/ui'; const features = [ { diff --git a/apps/next/src/components/landing/hero.tsx b/apps/next/src/components/landing/hero.tsx index c285e22..5ccbbc2 100644 --- a/apps/next/src/components/landing/hero.tsx +++ b/apps/next/src/components/landing/hero.tsx @@ -2,7 +2,7 @@ import { Kanit } from 'next/font/google'; import Image from 'next/image'; import Link from 'next/link'; -import { Button } from '@gib/ui/button'; +import { Button } from '@gib/ui'; const kanitSans = Kanit({ subsets: ['latin'], diff --git a/apps/next/src/components/layout/auth/profile/header.tsx b/apps/next/src/components/layout/auth/profile/header.tsx index 663becf..f7e8803 100644 --- a/apps/next/src/components/layout/auth/profile/header.tsx +++ b/apps/next/src/components/layout/auth/profile/header.tsx @@ -1,17 +1,7 @@ 'use client'; - -import type { Preloaded } from 'convex/react'; -import { usePreloadedQuery } from 'convex/react'; - -import type { api } from '@gib/backend/convex/_generated/api.js'; import { CardDescription, CardHeader, CardTitle } from '@gib/ui'; -interface ProfileCardProps { - preloadedUser: Preloaded; -} - -const ProfileHeader = ({ preloadedUser }: ProfileCardProps) => { - const user = usePreloadedQuery(preloadedUser); +const ProfileHeader = () => { return ( Account Settings diff --git a/packages/ui/package.json b/packages/ui/package.json index 6fedc33..3ebfbc0 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -4,68 +4,8 @@ "type": "module", "exports": { ".": "./src/index.tsx", - "./accordion": "./src/accordion.tsx", - "./alert": "./src/alert.tsx", - "./alert-dialog": "./src/alert-dialog.tsx", - "./aspect-ratio": "./src/aspect-ratio.tsx", - "./avatar": "./src/avatar.tsx", - "./badge": "./src/badge.tsx", - "./based-avatar": "./src/based-avatar.tsx", - "./based-progress": "./src/based-progress.tsx", - "./breadcrumb": "./src/breadcrumb.tsx", - "./button": "./src/button.tsx", - "./button-group": "./src/button-group.tsx", - "./calendar": "./src/calendar.tsx", - "./card": "./src/card.tsx", - "./carousel": "./src/carousel.tsx", - "./chart": "./src/chart.tsx", - "./checkbox": "./src/checkbox.tsx", - "./collapsible": "./src/collapsible.tsx", - "./combobox": "./src/combobox.tsx", - "./command": "./src/command.tsx", - "./context-menu": "./src/context-menu.tsx", - "./dialog": "./src/dialog.tsx", - "./drawer": "./src/drawer.tsx", - "./dropdown-menu": "./src/dropdown-menu.tsx", - "./empty": "./src/empty.tsx", - "./field": "./src/field.tsx", - "./form": "./src/form.tsx", - "./hover-card": "./src/hover-card.tsx", - "./image-crop": "./src/image-crop.tsx", - "./input": "./src/input.tsx", - "./input-group": "./src/input-group.tsx", - "./input-otp": "./src/input-otp.tsx", - "./item": "./src/item.tsx", - "./kbd": "./src/kbd.tsx", - "./label": "./src/label.tsx", - "./menubar": "./src/menubar.tsx", - "./native-select": "./src/native-select.tsx", - "./navigation-menu": "./src/navigation-menu.tsx", - "./pagination": "./src/pagination.tsx", - "./popover": "./src/popover.tsx", - "./progress": "./src/progress.tsx", - "./radio-group": "./src/radio-group.tsx", - "./resizeable": "./src/resizeable.tsx", - "./scroll-area": "./src/scroll-area.tsx", - "./select": "./src/select.tsx", - "./separator": "./src/separator.tsx", - "./sheet": "./src/sheet.tsx", - "./sidebar": "./src/sidebar.tsx", - "./skeleton": "./src/skeleton.tsx", - "./slider": "./src/slider.tsx", - "./sonner": "./src/sonner.tsx", - "./spinner": "./src/spinner.tsx", - "./status-message": "./src/status-message.tsx", - "./submit-button": "./src/submit-button.tsx", - "./switch": "./src/switch.tsx", - "./table": "./src/table.tsx", - "./tabs": "./src/tabs.tsx", - "./textarea": "./src/textarea.tsx", - "./theme": "./src/theme.tsx", - "./toast": "./src/toast.tsx", - "./toggle": "./src/toggle.tsx", - "./toggle-group": "./src/toggle-group.tsx", - "./tooltip": "./src/tooltip.tsx" + "./hooks": "./src/index.tsx", + "./hooks/*": "./src/hooks/*" }, "license": "MIT", "scripts": { diff --git a/packages/ui/src/hooks/index.tsx b/packages/ui/src/hooks/index.tsx new file mode 100644 index 0000000..29bc5ad --- /dev/null +++ b/packages/ui/src/hooks/index.tsx @@ -0,0 +1,2 @@ +export { useIsMobile } from './use-mobile'; +export { useOnClickOutside } from './use-on-click-outside'; diff --git a/packages/ui/src/hooks/use-on-click-outside.tsx b/packages/ui/src/hooks/use-on-click-outside.tsx new file mode 100644 index 0000000..1c051dc --- /dev/null +++ b/packages/ui/src/hooks/use-on-click-outside.tsx @@ -0,0 +1,60 @@ +import * as React from 'react'; +import { MousePointerClick, X } from 'lucide-react'; + +type EventType = + | 'mousedown' + | 'mouseup' + | 'touchstart' + | 'touchend' + | 'focusin' + | 'focusout'; + +export function useOnClickOutside( + ref: React.RefObject | React.RefObject[], + handler: (event: MouseEvent | TouchEvent | FocusEvent) => void, + eventType: EventType = 'mousedown', + eventListenerOptions: AddEventListenerOptions = {}, +): void { + const savedHandler = React.useRef(handler); + + React.useLayoutEffect(() => { + savedHandler.current = handler; + }, [handler]); + + React.useEffect(() => { + const listener = (event: MouseEvent | TouchEvent | FocusEvent) => { + const target = event.target as Node; + + // Do nothing if the target is not connected element with document + if (!target.isConnected) { + return; + } + + const isOutside = Array.isArray(ref) + ? ref + .filter((r) => Boolean(r.current)) + .every((r) => r.current && !r.current.contains(target)) + : ref.current && !ref.current.contains(target); + + if (isOutside) { + savedHandler.current(event); + } + }; + + document.addEventListener( + eventType, + listener as EventListener, + eventListenerOptions, + ); + + return () => { + document.removeEventListener( + eventType, + listener as EventListener, + eventListenerOptions, + ); + }; + }, [ref, eventType, eventListenerOptions]); +} + +export type { EventType }; diff --git a/packages/ui/src/index.tsx b/packages/ui/src/index.tsx index fe7445a..0821f40 100644 --- a/packages/ui/src/index.tsx +++ b/packages/ui/src/index.tsx @@ -381,4 +381,4 @@ export { TooltipContent, TooltipProvider, } from './tooltip'; -export { useIsMobile } from './hooks/use-mobile'; +export { useIsMobile, useOnClickOutside } from './hooks';