diff --git a/apps/admin/package.json b/apps/admin/package.json index 477b018..f8ffd48 100755 --- a/apps/admin/package.json +++ b/apps/admin/package.json @@ -10,6 +10,8 @@ "preview": "vite preview" }, "dependencies": { + "@emoji-mart/data": "^1.2.1", + "@emoji-mart/react": "^1.1.1", "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.0.6", diff --git a/apps/admin/src/components/ui/emoji-picker.tsx b/apps/admin/src/components/ui/emoji-picker.tsx new file mode 100644 index 0000000..b3d7982 --- /dev/null +++ b/apps/admin/src/components/ui/emoji-picker.tsx @@ -0,0 +1,59 @@ +import { useState, useRef, useEffect } from 'react'; +import data from '@emoji-mart/data'; +import Picker from '@emoji-mart/react'; +import { Button } from './button'; + +interface EmojiPickerProps { + value: string; + onChange: (emoji: string) => void; +} + +export function EmojiPicker({ value, onChange }: EmojiPickerProps) { + const [open, setOpen] = useState(false); + const containerRef = useRef(null); + + useEffect(() => { + function handleClickOutside(event: MouseEvent) { + if (containerRef.current && !containerRef.current.contains(event.target as Node)) { + setOpen(false); + } + } + + if (open) { + document.addEventListener('mousedown', handleClickOutside); + } + + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, [open]); + + const handleEmojiSelect = (emoji: any) => { + onChange(emoji.native); + setOpen(false); + }; + + return ( +
+ + {open && ( +
+ +
+ )} +
+ ); +} diff --git a/apps/admin/src/pages/content/CategoriesPage.tsx b/apps/admin/src/pages/content/CategoriesPage.tsx index 64865bd..6c2aa5a 100644 --- a/apps/admin/src/pages/content/CategoriesPage.tsx +++ b/apps/admin/src/pages/content/CategoriesPage.tsx @@ -7,6 +7,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; +import { EmojiPicker } from '@/components/ui/emoji-picker'; import { Skeleton } from '@/components/ui/skeleton'; import { Dialog, @@ -225,13 +226,10 @@ export function CategoriesPage() {
- - Icon + setFormData(d => ({ ...d, icon: e.target.value }))} - placeholder="📚" - className="w-20 text-center text-2xl" + onChange={(emoji) => setFormData(d => ({ ...d, icon: emoji }))} />
diff --git a/apps/admin/src/pages/content/PacksPage.tsx b/apps/admin/src/pages/content/PacksPage.tsx index 95d2c4a..71f7aad 100644 --- a/apps/admin/src/pages/content/PacksPage.tsx +++ b/apps/admin/src/pages/content/PacksPage.tsx @@ -8,6 +8,7 @@ import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { Switch } from '@/components/ui/switch'; +import { EmojiPicker } from '@/components/ui/emoji-picker'; import { Badge } from '@/components/ui/badge'; import { Skeleton } from '@/components/ui/skeleton'; import { @@ -286,13 +287,10 @@ export function PacksPage() {
- - Icon + setFormData(d => ({ ...d, icon: e.target.value }))} - placeholder="💕" - className="w-20 text-center text-2xl" + onChange={(emoji) => setFormData(d => ({ ...d, icon: emoji }))} />
diff --git a/package-lock.json b/package-lock.json index 3865427..3092a23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,8 @@ "name": "@sauci/admin", "version": "1.0.0", "dependencies": { + "@emoji-mart/data": "^1.2.1", + "@emoji-mart/react": "^1.1.1", "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.0.6", @@ -57,6 +59,16 @@ "vite": "^5.0.0" } }, + "apps/admin/node_modules/@emoji-mart/react": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@emoji-mart/react/-/react-1.1.1.tgz", + "integrity": "sha512-NMlFNeWgv1//uPsvLxvGQoIerPuVdXwK/EUek8OOkJ6wVOWPUizRBJU0hDqWZCOROVpfBgCemaC3m6jDOXi03g==", + "license": "MIT", + "peerDependencies": { + "emoji-mart": "^5.2", + "react": "^16.8 || ^17 || ^18" + } + }, "apps/admin/node_modules/@types/react": { "version": "18.3.27", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz", @@ -486,6 +498,12 @@ "node": ">=6.9.0" } }, + "node_modules/@emoji-mart/data": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emoji-mart/data/-/data-1.2.1.tgz", + "integrity": "sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw==", + "license": "MIT" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", @@ -3864,6 +3882,13 @@ "dev": true, "license": "ISC" }, + "node_modules/emoji-mart": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-5.6.0.tgz", + "integrity": "sha512-eJp3QRe79pjwa+duv+n7+5YsNhRcMl812EcFVwrnRvYKoNPoQb5qxU8DG6Bgwji0akHdp6D4Ln6tYLG58MFSow==", + "license": "MIT", + "peer": true + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",