diff --git a/package.json b/package.json index 6f52fae..f051de4 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@radix-ui/react-dialog": "^1.1.2", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-popover": "^1.1.2", + "@radix-ui/react-select": "^2.1.2", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tooltip": "^1.1.3", "@types/escape-html": "^1.0.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 02341c4..8c2ea6d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ importers: '@radix-ui/react-popover': specifier: ^1.1.2 version: 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-select': + specifier: ^2.1.2 + version: 2.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slot': specifier: ^1.1.0 version: 1.1.0(@types/react@18.3.12)(react@18.3.1) @@ -456,6 +459,9 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} + '@radix-ui/number@1.1.0': + resolution: {integrity: sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==} + '@radix-ui/primitive@1.0.1': resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==} @@ -488,6 +494,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-collection@1.1.0': + resolution: {integrity: sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==} + 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 + '@radix-ui/react-compose-refs@1.0.1': resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} peerDependencies: @@ -559,6 +578,15 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-direction@1.1.0': + resolution: {integrity: sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-dismissable-layer@1.0.5': resolution: {integrity: sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==} peerDependencies: @@ -756,6 +784,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-select@2.1.2': + resolution: {integrity: sha512-rZJtWmorC7dFRi0owDmoijm6nSJH1tVw64QGiNIZ9PNLyBDtG+iAq+XGsya052At4BfarzY/Dhv9wrrUr6IMZA==} + 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 + '@radix-ui/react-slot@1.0.2': resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==} peerDependencies: @@ -2949,6 +2990,8 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true + '@radix-ui/number@1.1.0': {} + '@radix-ui/primitive@1.0.1': dependencies: '@babel/runtime': 7.25.9 @@ -2980,6 +3023,18 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 + '@radix-ui/react-collection@1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(@types/react@18.3.12)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + '@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.12)(react@18.3.1)': dependencies: '@babel/runtime': 7.25.9 @@ -3057,6 +3112,12 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 + '@radix-ui/react-direction@1.1.0(@types/react@18.3.12)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.12 + '@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.25.9 @@ -3240,6 +3301,35 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 + '@radix-ui/react-select@2.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/number': 1.1.0 + '@radix-ui/primitive': 1.1.0 + '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-direction': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + aria-hidden: 1.2.4 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-remove-scroll: 2.6.0(@types/react@18.3.12)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + '@radix-ui/react-slot@1.0.2(@types/react@18.3.12)(react@18.3.1)': dependencies: '@babel/runtime': 7.25.9 diff --git a/src/app/globals.css b/src/app/globals.css index 13878a8..ef2c814 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -115,3 +115,25 @@ body { --radius: 0.5rem; } } + +/* width */ +::-webkit-scrollbar { + width: 10px; +} + +/* Track */ +::-webkit-scrollbar-track { + background: #131313; + border-radius: 6px; +} + +/* Handle */ +::-webkit-scrollbar-thumb { + background: #525252; + border-radius: 6px; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: #303030; +} diff --git a/src/app/page.tsx b/src/app/page.tsx index 8903738..b6ed6e3 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,6 +4,7 @@ import { Dialog, DialogContent, DialogDescription, + DialogFooter, DialogHeader, DialogTitle, DialogTrigger, @@ -17,12 +18,32 @@ import useSWR from "swr"; import { getUserCount, isUserMonitored } from "@/utils/actions"; import { isSnowflake } from "@/utils/snowflake"; import Link from "next/link"; +import { parameterInfo } from "@/utils/parameter"; + +import * as Icon from "lucide-react"; +import { Checkbox } from "@/components/ui/checkbox"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { Input } from "@/components/ui/input"; +import { filterLetters } from "@/lib/utils"; +import { Button } from "@/components/ui/button"; export default function Home() { const [userId, setUserId] = useState(null); const [userError, setUserError] = useState(); const [userData, setUserData] = useState<{ userId: string } | null>(null); - const originUrl = useMemo(() => window.location.origin, []); + const originUrl = useMemo(() => window.location?.origin, []); const [copyState, setCopyState] = useState("Copy"); const [outputType, setOutputType] = useState<"markdown" | "html" | "url">( "markdown", @@ -30,6 +51,10 @@ export default function Home() { const [isLoading, setIsLoading] = useState(true); const [onImageLoaded, setOnImageLoaded] = useState(false); + const [option, setOption] = useState< + Array<{ name: string; value: string }> + >([]); + const userCount = useSWR("getUserCount", getUserCount); const countRef = useRef(null); useSmoothCount({ @@ -39,23 +64,26 @@ export default function Home() { curve: [0, 1, 0, 1], }); - const outputText = () => { + const url = `${originUrl || "https://lanyard.cnrad.dev"}/api/${userData?.userId}${option.length > 0 ? `?${option.map((o) => `${o.name}=${o.value}`).join("&")}` : ""}`; + + function outputText() { if (outputType === "html") { - return ``; + return ``; } else if (outputType === "url") { - return `${originUrl || "https://lanyard.cnrad.dev"}/api/${userData?.userId}`; + return `${url}`; } else { - return `[![Discord Presence](${originUrl || "https://lanyard.cnrad.dev"}/api/${userData?.userId})](https://discord.com/users/${userData?.userId})`; + return `[![Discord Presence](${url})](https://discord.com/users/${userData?.userId})`; } - }; - const copy = () => { + } + + function copy() { navigator.clipboard.writeText(outputText()); setCopyState("Copied!"); setTimeout(() => setCopyState("Copy"), 1500); - }; + } - const submitDiscordId = async () => { + async function submitDiscordId() { setIsLoading(true); setOnImageLoaded(false); setUserData(null); @@ -82,7 +110,115 @@ export default function Home() { setUserData({ userId }); setIsLoading(false); - }; + } + + function modifyOption( + data: + | { + type: "string"; + name: string; + data: string; + event: React.ChangeEvent; + } + | { + type: "list"; + name: string; + data: string; + } + | { + type: "boolean"; + name: string; + data: string | boolean; + }, + ) { + if (data.type === "string") { + const filteredValue = filterLetters( + data.data, + ( + parameterInfo.find( + (p) => p.type === "string" && p.parameter === data.name, + ) as any + ).options.omit, + ); + + setOption((prev) => { + if (data.data === "") { + return prev?.filter((o) => o.name !== data.name) || []; + } else { + if (prev?.find((o) => o.name === data.name)) { + return prev.map((o) => { + if (o.name === data.name) { + o.value = filteredValue; + } + return o; + }); + } else { + return prev + ? [ + ...prev, + { + name: data.name, + value: filteredValue, + }, + ] + : [ + { + name: data.name, + value: filteredValue, + }, + ]; + } + } + }); + } else if (data.type === "list") { + setOption((prev) => { + if (prev?.find((o) => o.name === data.name)) { + return prev.map((o) => { + if (o.name === data.name) { + o.value = data.data; + } + return o; + }); + } else { + return prev + ? [...prev, { name: data.name, value: data.data }] + : [{ name: data.name, value: data.data }]; + } + }); + } else if (data.type === "boolean") { + setOption((prev) => { + if (prev?.find((o) => o.name === data.name)) { + return prev + .map((opt) => { + const options = parameterInfo.find( + (p) => + p.type === "boolean" && + p.parameter === data.name, + )?.options as { defaultBool?: boolean }; + + if ( + data.data === (options?.defaultBool! || false) + ) { + return null; + } else { + if (opt.name === data.name) { + opt.value = data.data.toString(); + } + return opt; + } + }) + .filter((opt) => opt !== null); + } else { + return prev + ? [ + ...prev, + { name: data.name, value: data.data.toString() }, + ] + : [{ name: data.name, value: data.data.toString() }]; + } + }); + } + } return ( <> @@ -169,16 +305,165 @@ export default function Home() { - - Are you absolutely sure? - + Option - This action cannot be undone. This - will permanently delete your account - and remove your data from our - servers. + Select an option to enable/disable + features to your Lanyard Profile + +
+ {parameterInfo.map((item, idx) => { + return ( +
+
+

{item.title}

+ + + { + e.preventDefault(); + }} + > + + + +

+ { + item.description + } +

+
+
+
+
+ {item.type === "string" && ( + + modifyOption({ + type: "string", + name: item.parameter, + data: e + .target + .value, + event: e, + }) + } + value={ + option?.find( + (o) => + o.name === + item.parameter, + )?.value || "" + } + /> + )} + {item.type === + "boolean" && ( + + modifyOption({ + type: "boolean", + name: item.parameter, + data: bool, + }) + } + checked={ + option?.find( + (o) => + o.name === + item.parameter, + )?.value === + "true" + ? true + : option?.find( + ( + o, + ) => + o.name === + item.parameter, + ) + ?.value === + "false" + ? false + : item + .options + ?.defaultBool || + false + } + /> + )} + {item.type === "list" && ( + + )} +
+ ); + })} +
+ + +
@@ -192,7 +477,7 @@ export default function Home() { opacity: onImageLoaded ? 1 : 0, }} transition={{ duration: 0.5 }} - src={`/api/${userData?.userId}`} + src={url} height={280} width={500} alt="Your Lanyard Banner" diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 58ccdf3..cca3833 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -1,57 +1,57 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-stone-950 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 dark:focus-visible:ring-stone-300", - { - variants: { - variant: { - default: - "bg-stone-900 text-stone-50 shadow hover:bg-stone-900/90 dark:bg-stone-50 dark:text-stone-900 dark:hover:bg-stone-50/90", - destructive: - "bg-red-500 text-stone-50 shadow-sm hover:bg-red-500/90 dark:bg-red-900 dark:text-stone-50 dark:hover:bg-red-900/90", - outline: - "border border-stone-200 bg-white shadow-sm hover:bg-stone-100 hover:text-stone-900 dark:border-stone-800 dark:bg-stone-950 dark:hover:bg-stone-800 dark:hover:text-stone-50", - secondary: - "bg-stone-100 text-stone-900 shadow-sm hover:bg-stone-100/80 dark:bg-stone-800 dark:text-stone-50 dark:hover:bg-stone-800/80", - ghost: "hover:bg-stone-100 hover:text-stone-900 dark:hover:bg-stone-800 dark:hover:text-stone-50", - link: "text-stone-900 underline-offset-4 hover:underline dark:text-stone-50", - }, - size: { - default: "h-9 px-4 py-2", - sm: "h-8 rounded-md px-3 text-xs", - lg: "h-10 rounded-md px-8", - icon: "h-9 w-9", - }, + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 focus-visible:ring-stone-300", + { + variants: { + variant: { + default: + "shadow bg-stone-50 text-stone-900 hover:bg-stone-50/90", + destructive: + "shadow-sm bg-red-900 text-stone-50 hover:bg-red-900/90", + outline: + "border shadow-sm text-stone-900 border-stone-800 bg-stone-950 hover:bg-stone-800 hover:text-stone-50", + secondary: + "shadow-sm bg-stone-800 text-stone-50 hover:bg-stone-800/80", + ghost: "hover:bg-stone-800 hover:text-stone-50", + link: "underline-offset-4 hover:underline text-stone-50", + }, + size: { + default: "h-9 px-4 py-2", + sm: "h-8 rounded-md px-3 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, }, - defaultVariants: { - variant: "default", - size: "default", - }, - } -) +); export interface ButtonProps - extends React.ButtonHTMLAttributes, - VariantProps { - asChild?: boolean + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; } const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button" - return ( - - ) - } -) -Button.displayName = "Button" + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button"; + return ( + + ); + }, +); +Button.displayName = "Button"; -export { Button, buttonVariants } +export { Button, buttonVariants }; diff --git a/src/components/ui/checkbox.tsx b/src/components/ui/checkbox.tsx index 0056445..7d6baef 100644 --- a/src/components/ui/checkbox.tsx +++ b/src/components/ui/checkbox.tsx @@ -1,30 +1,30 @@ -"use client" +"use client"; -import * as React from "react" -import * as CheckboxPrimitive from "@radix-ui/react-checkbox" -import { CheckIcon } from "@radix-ui/react-icons" +import * as React from "react"; +import * as CheckboxPrimitive from "@radix-ui/react-checkbox"; +import { CheckIcon } from "@radix-ui/react-icons"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const Checkbox = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef + React.ElementRef, + React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( - - - - - -)) -Checkbox.displayName = CheckboxPrimitive.Root.displayName + + + + +)); +Checkbox.displayName = CheckboxPrimitive.Root.displayName; -export { Checkbox } +export { Checkbox }; diff --git a/src/components/ui/command.tsx b/src/components/ui/command.tsx deleted file mode 100644 index 33ed7a6..0000000 --- a/src/components/ui/command.tsx +++ /dev/null @@ -1,155 +0,0 @@ -"use client" - -import * as React from "react" -import { type DialogProps } from "@radix-ui/react-dialog" -import { MagnifyingGlassIcon } from "@radix-ui/react-icons" -import { Command as CommandPrimitive } from "cmdk" - -import { cn } from "@/lib/utils" -import { Dialog, DialogContent } from "@/components/ui/dialog" - -const Command = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -Command.displayName = CommandPrimitive.displayName - -interface CommandDialogProps extends DialogProps {} - -const CommandDialog = ({ children, ...props }: CommandDialogProps) => { - return ( - - - - {children} - - - - ) -} - -const CommandInput = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( -
- - -
-)) - -CommandInput.displayName = CommandPrimitive.Input.displayName - -const CommandList = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) - -CommandList.displayName = CommandPrimitive.List.displayName - -const CommandEmpty = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->((props, ref) => ( - -)) - -CommandEmpty.displayName = CommandPrimitive.Empty.displayName - -const CommandGroup = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) - -CommandGroup.displayName = CommandPrimitive.Group.displayName - -const CommandSeparator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -CommandSeparator.displayName = CommandPrimitive.Separator.displayName - -const CommandItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) - -CommandItem.displayName = CommandPrimitive.Item.displayName - -const CommandShortcut = ({ - className, - ...props -}: React.HTMLAttributes) => { - return ( - - ) -} -CommandShortcut.displayName = "CommandShortcut" - -export { - Command, - CommandDialog, - CommandInput, - CommandList, - CommandEmpty, - CommandGroup, - CommandItem, - CommandShortcut, - CommandSeparator, -} diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx index b66002b..95248db 100644 --- a/src/components/ui/dialog.tsx +++ b/src/components/ui/dialog.tsx @@ -21,7 +21,7 @@ const DialogOverlay = React.forwardRef< {children} - + Close diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx new file mode 100644 index 0000000..4bb5f30 --- /dev/null +++ b/src/components/ui/input.tsx @@ -0,0 +1,25 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +export interface InputProps + extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ); + }, +); +Input.displayName = "Input"; + +export { Input }; diff --git a/src/components/ui/popover.tsx b/src/components/ui/popover.tsx deleted file mode 100644 index b973d4e..0000000 --- a/src/components/ui/popover.tsx +++ /dev/null @@ -1,33 +0,0 @@ -"use client" - -import * as React from "react" -import * as PopoverPrimitive from "@radix-ui/react-popover" - -import { cn } from "@/lib/utils" - -const Popover = PopoverPrimitive.Root - -const PopoverTrigger = PopoverPrimitive.Trigger - -const PopoverAnchor = PopoverPrimitive.Anchor - -const PopoverContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( - - - -)) -PopoverContent.displayName = PopoverPrimitive.Content.displayName - -export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor } diff --git a/src/components/ui/select.tsx b/src/components/ui/select.tsx new file mode 100644 index 0000000..352bfcb --- /dev/null +++ b/src/components/ui/select.tsx @@ -0,0 +1,164 @@ +"use client"; + +import * as React from "react"; +import { + CaretSortIcon, + CheckIcon, + ChevronDownIcon, + ChevronUpIcon, +} from "@radix-ui/react-icons"; +import * as SelectPrimitive from "@radix-ui/react-select"; + +import { cn } from "@/lib/utils"; + +const Select = SelectPrimitive.Root; + +const SelectGroup = SelectPrimitive.Group; + +const SelectValue = SelectPrimitive.Value; + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + span]:line-clamp-1", + className, + )} + {...props} + > + {children} + + + + +)); +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; + +const SelectScrollUpButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; + +const SelectScrollDownButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollDownButton.displayName = + SelectPrimitive.ScrollDownButton.displayName; + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = "popper", ...props }, ref) => ( + + + + + {children} + + + + +)); +SelectContent.displayName = SelectPrimitive.Content.displayName; + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectLabel.displayName = SelectPrimitive.Label.displayName; + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)); +SelectItem.displayName = SelectPrimitive.Item.displayName; + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectSeparator.displayName = SelectPrimitive.Separator.displayName; + +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, + SelectScrollUpButton, + SelectScrollDownButton, +}; diff --git a/src/components/ui/tooltip.tsx b/src/components/ui/tooltip.tsx index 85ee50f..a1a4520 100644 --- a/src/components/ui/tooltip.tsx +++ b/src/components/ui/tooltip.tsx @@ -1,32 +1,32 @@ -"use client" +"use client"; -import * as React from "react" -import * as TooltipPrimitive from "@radix-ui/react-tooltip" +import * as React from "react"; +import * as TooltipPrimitive from "@radix-ui/react-tooltip"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -const TooltipProvider = TooltipPrimitive.Provider +const TooltipProvider = TooltipPrimitive.Provider; -const Tooltip = TooltipPrimitive.Root +const Tooltip = TooltipPrimitive.Root; -const TooltipTrigger = TooltipPrimitive.Trigger +const TooltipTrigger = TooltipPrimitive.Trigger; const TooltipContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef + React.ElementRef, + React.ComponentPropsWithoutRef >(({ className, sideOffset = 4, ...props }, ref) => ( - - - -)) -TooltipContent.displayName = TooltipPrimitive.Content.displayName + + + +)); +TooltipContent.displayName = TooltipPrimitive.Content.displayName; -export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; diff --git a/src/lib/utils.ts b/src/lib/utils.ts index bd0c391..27a0642 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,6 +1,13 @@ -import { clsx, type ClassValue } from "clsx" -import { twMerge } from "tailwind-merge" +import { clsx, type ClassValue } from "clsx"; +import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return twMerge(clsx(inputs)); +} + +export function filterLetters(str: string, lettersToRemove: string[] = []) { + lettersToRemove.forEach((letter) => { + str = str.replaceAll(letter, ""); + }); + return str; } diff --git a/src/utils/parameter.ts b/src/utils/parameter.ts index 701f803..e490824 100644 --- a/src/utils/parameter.ts +++ b/src/utils/parameter.ts @@ -19,7 +19,7 @@ export type Parameters = { idleMessage?: string; }; -export const ParameterInfo: Array< +export const parameterInfo: Array< | { parameter: string; type: "boolean"; @@ -35,8 +35,8 @@ export const ParameterInfo: Array< title: string; description?: string; options?: { - prefix?: string; - suffix?: string; + placeholder?: string; + omit?: string[]; }; } | { @@ -76,18 +76,20 @@ export const ParameterInfo: Array< type: "string", title: "Background Color", description: - "This will change the background color. Must be in hex format.", + "This will change the background color. Must be in hex format. Omit the # symbol.", options: { - prefix: "#", + placeholder: "1A1C1F", + omit: ["#"], }, }, { parameter: "borderRadius", type: "string", title: "Border Radius", - description: "This will change the border radius of the card.", + description: + "This will change the border radius of the card. Must have a size unit (px, rem, em, and more).", options: { - suffix: "px", + placeholder: "10px", }, }, { @@ -106,20 +108,16 @@ export const ParameterInfo: Array< title: "Idle Message", description: "If you don't want the default \"I'm not currently doing anything!\" as your idle message, this is the right option.", + options: { + placeholder: "I'm not currently doing anything!", + }, }, { parameter: "showDisplayName", type: "boolean", title: "Show Display Name", description: - "If you don't want to show your display name, this is the right option.", - }, - { - parameter: "hideDecoration", - type: "boolean", - title: "Hide Avatar Decoration", - description: - "If you don't want people seeing your Avatar Decoration, this is the right option.", + "If you'd like to show your global display name as well as your username, this is the right option.", }, { parameter: "animatedDecoration", @@ -131,6 +129,13 @@ export const ParameterInfo: Array< defaultBool: true, }, }, + { + parameter: "hideDecoration", + type: "boolean", + title: "Hide Avatar Decoration", + description: + "If you don't want people seeing your Avatar Decoration, this is the right option.", + }, { parameter: "hideStatus", type: "boolean", @@ -185,7 +190,10 @@ export const ParameterInfo: Array< type: "string", title: "Hide App by ID", description: - "If you don't want display a specific application, this is the right option. IDs separate by `,`.", + "If you don't want display a specific application, this is the right option. IDs separate by ','", + options: { + placeholder: "1302143410907648071, 1302132259368861759", + }, }, { parameter: "hideDiscrim",